add support for defining global host info
[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_FREQ] = { .type = BLOB_ATTR_INT32 },
59 [APMSG_NODE_N_ASSOC] = { .type = BLOB_ATTR_INT32 },
60 [APMSG_NODE_MAX_ASSOC] = { .type = BLOB_ATTR_INT32 },
61 [APMSG_NODE_STATIONS] = { .type = BLOB_ATTR_NESTED },
62 [APMSG_NODE_NOISE] = { .type = BLOB_ATTR_INT32 },
63 [APMSG_NODE_LOAD] = { .type = BLOB_ATTR_INT32 },
64 [APMSG_NODE_RRM_NR] = { .type = BLOB_ATTR_NESTED },
65 [APMSG_NODE_NODE_INFO] = { .type = BLOB_ATTR_NESTED },
66 };
67 struct blob_attr *tb[__APMSG_NODE_MAX];
68 struct blob_attr *cur;
69
70 blob_parse(data, tb, policy, __APMSG_NODE_MAX);
71 if (!tb[APMSG_NODE_NAME] ||
72 !tb[APMSG_NODE_FREQ] ||
73 !tb[APMSG_NODE_N_ASSOC] ||
74 !tb[APMSG_NODE_STATIONS] ||
75 !tb[APMSG_NODE_SSID])
76 return false;
77
78 msg->name = blob_data(tb[APMSG_NODE_NAME]);
79 msg->n_assoc = blob_get_int32(tb[APMSG_NODE_N_ASSOC]);
80 msg->freq = blob_get_int32(tb[APMSG_NODE_FREQ]);
81 msg->stations = tb[APMSG_NODE_STATIONS];
82 msg->ssid = blob_data(tb[APMSG_NODE_SSID]);
83
84 msg->noise = get_int32(tb[APMSG_NODE_NOISE]);
85 msg->load = get_int32(tb[APMSG_NODE_LOAD]);
86 msg->max_assoc = get_int32(tb[APMSG_NODE_MAX_ASSOC]);
87 msg->rrm_nr = NULL;
88
89 cur = tb[APMSG_NODE_RRM_NR];
90 if (cur && blob_len(cur) >= sizeof(struct blob_attr) &&
91 blob_len(cur) >= blob_pad_len(blob_data(cur))) {
92 int rem;
93
94 msg->rrm_nr = blob_data(cur);
95
96 blobmsg_for_each_attr(cur, msg->rrm_nr, rem) {
97 if (blobmsg_check_attr(cur, false))
98 continue;
99 if (blobmsg_type(cur) == BLOBMSG_TYPE_STRING)
100 continue;
101 msg->rrm_nr = NULL;
102 break;
103 }
104
105 if (msg->rrm_nr &&
106 blobmsg_type(msg->rrm_nr) != BLOBMSG_TYPE_ARRAY)
107 msg->rrm_nr = NULL;
108 }
109
110 msg->node_info = tb[APMSG_NODE_NODE_INFO];
111
112 return true;
113 }
114
115 bool parse_apmsg_sta(struct apmsg_sta *msg, struct blob_attr *data)
116 {
117 static const struct blob_attr_info policy[__APMSG_STA_MAX] = {
118 [APMSG_STA_ADDR] = { .type = BLOB_ATTR_BINARY },
119 [APMSG_STA_SIGNAL] = { .type = BLOB_ATTR_INT32 },
120 [APMSG_STA_SEEN] = { .type = BLOB_ATTR_INT32 },
121 [APMSG_STA_TIMEOUT] = { .type = BLOB_ATTR_INT32 },
122 [APMSG_STA_CONNECTED] = { .type = BLOB_ATTR_INT8 },
123 };
124 struct blob_attr *tb[__APMSG_STA_MAX];
125
126 blob_parse(data, tb, policy, __APMSG_STA_MAX);
127 if (!tb[APMSG_STA_ADDR] ||
128 !tb[APMSG_STA_SIGNAL] ||
129 !tb[APMSG_STA_SEEN] ||
130 !tb[APMSG_STA_TIMEOUT] ||
131 !tb[APMSG_STA_CONNECTED])
132 return false;
133
134 if (blob_len(tb[APMSG_STA_ADDR]) != sizeof(msg->addr))
135 return false;
136
137 memcpy(msg->addr, blob_data(tb[APMSG_STA_ADDR]), sizeof(msg->addr));
138 msg->signal = blob_get_int32(tb[APMSG_STA_SIGNAL]);
139 msg->seen = blob_get_int32(tb[APMSG_STA_SEEN]);
140 msg->timeout = blob_get_int32(tb[APMSG_STA_TIMEOUT]);
141 msg->connected = blob_get_int8(tb[APMSG_STA_CONNECTED]);
142
143 return true;
144 }