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