1 /*
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing,
13 * software distributed under the License is distributed on an
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 * KIND, either express or implied. See the License for the
16 * specific language governing permissions and limitations
17 * under the License.
18 */
19
20 #include <string.h>
21
22 #include "tinycbor/cbor.h"
23 #include "mgmt/endian.h"
24 #include "mgmt/mgmt.h"
25
26 static mgmt_on_evt_cb *evt_cb;
27 static struct mgmt_group *mgmt_group_list;
28 static struct mgmt_group *mgmt_group_list_end;
29
30 void *
mgmt_streamer_alloc_rsp(struct mgmt_streamer * streamer,const void * req)31 mgmt_streamer_alloc_rsp(struct mgmt_streamer *streamer, const void *req)
32 {
33 return streamer->cfg->alloc_rsp(req, streamer->cb_arg);
34 }
35
36 void
mgmt_streamer_trim_front(struct mgmt_streamer * streamer,void * buf,size_t len)37 mgmt_streamer_trim_front(struct mgmt_streamer *streamer, void *buf, size_t len)
38 {
39 streamer->cfg->trim_front(buf, len, streamer->cb_arg);
40 }
41
42 void
mgmt_streamer_reset_buf(struct mgmt_streamer * streamer,void * buf)43 mgmt_streamer_reset_buf(struct mgmt_streamer *streamer, void *buf)
44 {
45 streamer->cfg->reset_buf(buf, streamer->cb_arg);
46 }
47
48 int
mgmt_streamer_write_at(struct mgmt_streamer * streamer,size_t offset,const void * data,int len)49 mgmt_streamer_write_at(struct mgmt_streamer *streamer, size_t offset,
50 const void *data, int len)
51 {
52 return streamer->cfg->write_at(streamer->writer, offset, data, len,
53 streamer->cb_arg);
54 }
55
56 int
mgmt_streamer_init_reader(struct mgmt_streamer * streamer,void * buf)57 mgmt_streamer_init_reader(struct mgmt_streamer *streamer, void *buf)
58 {
59 return streamer->cfg->init_reader(streamer->reader, buf, streamer->cb_arg);
60 }
61
62 int
mgmt_streamer_init_writer(struct mgmt_streamer * streamer,void * buf)63 mgmt_streamer_init_writer(struct mgmt_streamer *streamer, void *buf)
64 {
65 return streamer->cfg->init_writer(streamer->writer, buf, streamer->cb_arg);
66 }
67
68 void
mgmt_streamer_free_buf(struct mgmt_streamer * streamer,void * buf)69 mgmt_streamer_free_buf(struct mgmt_streamer *streamer, void *buf)
70 {
71 streamer->cfg->free_buf(buf, streamer->cb_arg);
72 }
73
74 void
mgmt_unregister_group(struct mgmt_group * group)75 mgmt_unregister_group(struct mgmt_group *group)
76 {
77 struct mgmt_group *curr = mgmt_group_list, *prev = NULL;
78
79 if (!group) {
80 return;
81 }
82
83 if (curr == group) {
84 mgmt_group_list = curr->mg_next;
85 return;
86 }
87
88 while (curr && curr != group) {
89 prev = curr;
90 curr = curr->mg_next;
91 }
92
93 if (!prev || !curr) {
94 return;
95 }
96
97 prev->mg_next = curr->mg_next;
98 if (curr->mg_next == NULL) {
99 mgmt_group_list_end = curr;
100 }
101 }
102
103 static struct mgmt_group *
mgmt_find_group(uint16_t group_id,uint16_t command_id)104 mgmt_find_group(uint16_t group_id, uint16_t command_id)
105 {
106 struct mgmt_group *group;
107
108 /*
109 * Find the group with the specified group id, if one exists
110 * check the handler for the command id and make sure
111 * that is not NULL. If that is not set, look for the group
112 * with a command id that is set
113 */
114 for (group = mgmt_group_list; group != NULL; group = group->mg_next) {
115 if (group->mg_group_id == group_id) {
116 if (command_id >= group->mg_handlers_count) {
117 return NULL;
118 }
119
120 if (!group->mg_handlers[command_id].mh_read &&
121 !group->mg_handlers[command_id].mh_write) {
122 continue;
123 }
124
125 break;
126 }
127 }
128
129 return group;
130 }
131
132 void
mgmt_register_group(struct mgmt_group * group)133 mgmt_register_group(struct mgmt_group *group)
134 {
135 if (mgmt_group_list_end == NULL) {
136 mgmt_group_list = group;
137 } else {
138 mgmt_group_list_end->mg_next = group;
139 }
140 mgmt_group_list_end = group;
141 }
142
143 const struct mgmt_handler *
mgmt_find_handler(uint16_t group_id,uint16_t command_id)144 mgmt_find_handler(uint16_t group_id, uint16_t command_id)
145 {
146 const struct mgmt_group *group;
147
148 group = mgmt_find_group(group_id, command_id);
149 if (!group) {
150 return NULL;
151 }
152
153 return &group->mg_handlers[command_id];
154 }
155
156 int
mgmt_write_rsp_status(struct mgmt_ctxt * ctxt,int errcode)157 mgmt_write_rsp_status(struct mgmt_ctxt *ctxt, int errcode)
158 {
159 int rc;
160
161 rc = cbor_encode_text_stringz(&ctxt->encoder, "rc");
162 if (rc != 0) {
163 return rc;
164 }
165
166 rc = cbor_encode_int(&ctxt->encoder, errcode);
167 if (rc != 0) {
168 return rc;
169 }
170
171 return 0;
172 }
173
174 int
mgmt_err_from_cbor(int cbor_status)175 mgmt_err_from_cbor(int cbor_status)
176 {
177 switch (cbor_status) {
178 case CborNoError: return MGMT_ERR_EOK;
179 case CborErrorOutOfMemory: return MGMT_ERR_ENOMEM;
180 default: return MGMT_ERR_EUNKNOWN;
181 }
182 }
183
184 int
mgmt_ctxt_init(struct mgmt_ctxt * ctxt,struct mgmt_streamer * streamer)185 mgmt_ctxt_init(struct mgmt_ctxt *ctxt, struct mgmt_streamer *streamer)
186 {
187 int rc;
188
189 rc = cbor_parser_init(streamer->reader, 0, &ctxt->parser, &ctxt->it);
190 if (rc != CborNoError) {
191 return mgmt_err_from_cbor(rc);
192 }
193
194 cbor_encoder_init(&ctxt->encoder, streamer->writer, 0);
195
196 return 0;
197 }
198
199 void
mgmt_ntoh_hdr(struct mgmt_hdr * hdr)200 mgmt_ntoh_hdr(struct mgmt_hdr *hdr)
201 {
202 hdr->nh_len = ntohs(hdr->nh_len);
203 hdr->nh_group = ntohs(hdr->nh_group);
204 }
205
206 void
mgmt_hton_hdr(struct mgmt_hdr * hdr)207 mgmt_hton_hdr(struct mgmt_hdr *hdr)
208 {
209 hdr->nh_len = htons(hdr->nh_len);
210 hdr->nh_group = htons(hdr->nh_group);
211 }
212
213 void
mgmt_register_evt_cb(mgmt_on_evt_cb * cb)214 mgmt_register_evt_cb(mgmt_on_evt_cb *cb)
215 {
216 evt_cb = cb;
217 }
218
219 void
mgmt_evt(uint8_t opcode,uint16_t group,uint8_t id,void * arg)220 mgmt_evt(uint8_t opcode, uint16_t group, uint8_t id, void *arg)
221 {
222 if (evt_cb) {
223 evt_cb(opcode, group, id, arg);
224 }
225 }
226