remote: close file on usteer_init_local_id fread fail
[project/usteer.git] / parse.c
1 /*
2 * This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License as published by
4 * the Free Software Foundation; either version 2 of the License.
5 *
6 * This program is distributed in the hope that it will be useful,
7 * but WITHOUT ANY WARRANTY; without even the implied warranty of
8 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9 * GNU General Public License for more details.
10 *
11 * You should have received a copy of the GNU General Public License
12 * along with this program; if not, write to the Free Software
13 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
14 *
15 * Copyright (C) 2020 embedd.ch
16 * Copyright (C) 2020 Felix Fietkau <nbd@nbd.name>
17 * Copyright (C) 2020 John Crispin <john@phrozen.org>
18 */
19
20 #include "usteer.h"
21 #include "remote.h"
22
23 bool parse_apmsg(struct apmsg *msg, struct blob_attr *data)
24 {
25 static const struct blob_attr_info policy[__APMSG_MAX] = {
26 [APMSG_ID] = { .type = BLOB_ATTR_INT32 },
27 [APMSG_SEQ] = { .type = BLOB_ATTR_INT32 },
28 [APMSG_NODES] = { .type = BLOB_ATTR_NESTED },
29 [APMSG_HOST_INFO] = { .type = BLOB_ATTR_NESTED },
30 };
31 struct blob_attr *tb[__APMSG_MAX];
32
33 blob_parse(data, tb, policy, __APMSG_MAX);
34 if (!tb[APMSG_ID] || !tb[APMSG_SEQ] || !tb[APMSG_NODES])
35 return false;
36
37 msg->id = blob_get_int32(tb[APMSG_ID]);
38 msg->seq = blob_get_int32(tb[APMSG_SEQ]);
39 msg->nodes = tb[APMSG_NODES];
40 msg->host_info = tb[APMSG_HOST_INFO];
41
42 return true;
43 }
44
45 static int
46 get_int32(struct blob_attr *attr)
47 {
48 if (!attr)
49 return 0;
50
51 return blob_get_int32(attr);
52 }
53
54 bool parse_apmsg_node(struct apmsg_node *msg, struct blob_attr *data)
55 {
56 static const struct blob_attr_info policy[__APMSG_NODE_MAX] = {
57 [APMSG_NODE_NAME] = { .type = BLOB_ATTR_STRING },
58 [APMSG_NODE_BSSID] = { .type = BLOB_ATTR_BINARY },
59 [APMSG_NODE_FREQ] = { .type = BLOB_ATTR_INT32 },
60 [APMSG_NODE_N_ASSOC] = { .type = BLOB_ATTR_INT32 },
61 [APMSG_NODE_MAX_ASSOC] = { .type = BLOB_ATTR_INT32 },
62 [APMSG_NODE_STATIONS] = { .type = BLOB_ATTR_NESTED },
63 [APMSG_NODE_NOISE] = { .type = BLOB_ATTR_INT32 },
64 [APMSG_NODE_LOAD] = { .type = BLOB_ATTR_INT32 },
65 [APMSG_NODE_RRM_NR] = { .type = BLOB_ATTR_NESTED },
66 [APMSG_NODE_NODE_INFO] = { .type = BLOB_ATTR_NESTED },
67 [APMSG_NODE_CHANNEL] = { .type = BLOB_ATTR_INT32 },
68 [APMSG_NODE_OP_CLASS] = { .type = BLOB_ATTR_INT32 },
69 };
70 struct blob_attr *tb[__APMSG_NODE_MAX];
71 struct blob_attr *cur;
72
73 blob_parse(data, tb, policy, __APMSG_NODE_MAX);
74 if (!tb[APMSG_NODE_NAME] ||
75 !tb[APMSG_NODE_BSSID] ||
76 blob_len(tb[APMSG_NODE_BSSID]) != 6 ||
77 !tb[APMSG_NODE_FREQ] ||
78 !tb[APMSG_NODE_N_ASSOC] ||
79 !tb[APMSG_NODE_STATIONS] ||
80 !tb[APMSG_NODE_SSID])
81 return false;
82
83 msg->name = blob_data(tb[APMSG_NODE_NAME]);
84 msg->n_assoc = blob_get_int32(tb[APMSG_NODE_N_ASSOC]);
85 msg->freq = blob_get_int32(tb[APMSG_NODE_FREQ]);
86 msg->stations = tb[APMSG_NODE_STATIONS];
87 msg->ssid = blob_data(tb[APMSG_NODE_SSID]);
88 msg->bssid = blob_data(tb[APMSG_NODE_BSSID]);
89
90 msg->noise = get_int32(tb[APMSG_NODE_NOISE]);
91 msg->load = get_int32(tb[APMSG_NODE_LOAD]);
92 msg->max_assoc = get_int32(tb[APMSG_NODE_MAX_ASSOC]);
93 msg->rrm_nr = NULL;
94
95 if (tb[APMSG_NODE_CHANNEL] && tb[APMSG_NODE_OP_CLASS]) {
96 msg->channel = blob_get_int32(tb[APMSG_NODE_CHANNEL]);
97 msg->op_class = blob_get_int32(tb[APMSG_NODE_OP_CLASS]);
98 }
99
100 cur = tb[APMSG_NODE_RRM_NR];
101 if (cur && blob_len(cur) >= sizeof(struct blob_attr) &&
102 blob_len(cur) >= blob_pad_len(blob_data(cur))) {
103 int rem;
104
105 msg->rrm_nr = blob_data(cur);
106
107 blobmsg_for_each_attr(cur, msg->rrm_nr, rem) {
108 if (blobmsg_check_attr(cur, false))
109 continue;
110 if (blobmsg_type(cur) == BLOBMSG_TYPE_STRING)
111 continue;
112 msg->rrm_nr = NULL;
113 break;
114 }
115
116 if (msg->rrm_nr &&
117 blobmsg_type(msg->rrm_nr) != BLOBMSG_TYPE_ARRAY)
118 msg->rrm_nr = NULL;
119 }
120
121 msg->node_info = tb[APMSG_NODE_NODE_INFO];
122
123 return true;
124 }
125
126 bool parse_apmsg_sta(struct apmsg_sta *msg, struct blob_attr *data)
127 {
128 static const struct blob_attr_info policy[__APMSG_STA_MAX] = {
129 [APMSG_STA_ADDR] = { .type = BLOB_ATTR_BINARY },
130 [APMSG_STA_SIGNAL] = { .type = BLOB_ATTR_INT32 },
131 [APMSG_STA_SEEN] = { .type = BLOB_ATTR_INT32 },
132 [APMSG_STA_TIMEOUT] = { .type = BLOB_ATTR_INT32 },
133 [APMSG_STA_CONNECTED] = { .type = BLOB_ATTR_INT8 },
134 [APMSG_STA_LAST_CONNECTED] = { .type = BLOB_ATTR_INT32 },
135 };
136 struct blob_attr *tb[__APMSG_STA_MAX];
137
138 blob_parse(data, tb, policy, __APMSG_STA_MAX);
139 if (!tb[APMSG_STA_ADDR] ||
140 !tb[APMSG_STA_SIGNAL] ||
141 !tb[APMSG_STA_SEEN] ||
142 !tb[APMSG_STA_TIMEOUT] ||
143 !tb[APMSG_STA_CONNECTED] ||
144 !tb[APMSG_STA_LAST_CONNECTED])
145 return false;
146
147 if (blob_len(tb[APMSG_STA_ADDR]) != sizeof(msg->addr))
148 return false;
149
150 memcpy(msg->addr, blob_data(tb[APMSG_STA_ADDR]), sizeof(msg->addr));
151 msg->signal = blob_get_int32(tb[APMSG_STA_SIGNAL]);
152 msg->seen = blob_get_int32(tb[APMSG_STA_SEEN]);
153 msg->timeout = blob_get_int32(tb[APMSG_STA_TIMEOUT]);
154 msg->connected = blob_get_int8(tb[APMSG_STA_CONNECTED]);
155 msg->last_connected = blob_get_int32(tb[APMSG_STA_LAST_CONNECTED]);
156
157 return true;
158 }