remote: close file on usteer_init_local_id fread fail
[project/usteer.git] / netifd.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 "node.h"
22
23 static struct blob_buf b;
24
25 static void
26 netifd_parse_interface_config(struct usteer_local_node *ln, struct blob_attr *msg)
27 {
28 static const struct blobmsg_policy policy = {
29 .name = "maxassoc",
30 .type = BLOBMSG_TYPE_INT32,
31 };
32 struct blob_attr *cur;
33 int val = 0;
34
35 blobmsg_parse(&policy, 1, &cur, blobmsg_data(msg), blobmsg_data_len(msg));
36 if (cur)
37 val = blobmsg_get_u32(cur);
38
39 ln->node.max_assoc = val;
40 ln->netifd.status_complete = true;
41 }
42
43 static void
44 netifd_parse_interface(struct usteer_local_node *ln, struct blob_attr *msg)
45 {
46 enum {
47 N_IF_CONFIG,
48 N_IF_NAME,
49 __N_IF_MAX
50 };
51 static const struct blobmsg_policy policy[__N_IF_MAX] = {
52 [N_IF_CONFIG] = { .name = "config", .type = BLOBMSG_TYPE_TABLE },
53 [N_IF_NAME] = { .name = "ifname", .type = BLOBMSG_TYPE_STRING },
54 };
55 struct blob_attr *tb[__N_IF_MAX];
56
57 if (blobmsg_type(msg) != BLOBMSG_TYPE_TABLE)
58 return;
59
60 blobmsg_parse(policy, __N_IF_MAX, tb, blobmsg_data(msg), blobmsg_data_len(msg));
61 if (!tb[N_IF_CONFIG] || !tb[N_IF_NAME])
62 return;
63
64 if (strcmp(blobmsg_get_string(tb[N_IF_NAME]), ln->iface) != 0)
65 return;
66
67 netifd_parse_interface_config(ln, tb[N_IF_CONFIG]);
68 }
69
70 static void
71 netifd_parse_radio(struct usteer_local_node *ln, struct blob_attr *msg)
72 {
73 static const struct blobmsg_policy policy = {
74 .name = "interfaces",
75 .type = BLOBMSG_TYPE_ARRAY,
76 };
77 struct blob_attr *cur, *iface;
78 int rem;
79
80 if (blobmsg_type(msg) != BLOBMSG_TYPE_TABLE)
81 return;
82
83 blobmsg_parse(&policy, 1, &iface, blobmsg_data(msg), blobmsg_data_len(msg));
84 if (!iface)
85 return;
86
87 blobmsg_for_each_attr(cur, iface, rem)
88 netifd_parse_interface(ln, cur);
89 }
90
91 static void
92 netifd_status_cb(struct ubus_request *req, int type, struct blob_attr *msg)
93 {
94 struct usteer_local_node *ln;
95 struct blob_attr *cur;
96 int rem;
97
98 ln = container_of(req, struct usteer_local_node, netifd.req);
99 ln->netifd.req_pending = false;
100
101 blobmsg_for_each_attr(cur, msg, rem)
102 netifd_parse_radio(ln, cur);
103 }
104
105 static void netifd_update_node(struct usteer_node *node)
106 {
107 struct usteer_local_node *ln;
108 uint32_t id;
109
110 ln = container_of(node, struct usteer_local_node, node);
111 if (ln->netifd.status_complete)
112 return;
113
114 if (ln->netifd.req_pending)
115 ubus_abort_request(ubus_ctx, &ln->netifd.req);
116
117 if (ubus_lookup_id(ubus_ctx, "network.wireless", &id))
118 return;
119
120 blob_buf_init(&b, 0);
121 ubus_invoke_async(ubus_ctx, id, "status", b.head, &ln->netifd.req);
122 ln->netifd.req.data_cb = netifd_status_cb;
123 ubus_complete_request_async(ubus_ctx, &ln->netifd.req);
124 ln->netifd.req_pending = true;
125 }
126
127 static void netifd_init_node(struct usteer_node *node)
128 {
129 struct usteer_local_node *ln;
130
131 ln = container_of(node, struct usteer_local_node, node);
132 ln->netifd.status_complete = false;
133 netifd_update_node(node);
134 }
135
136 static void netifd_free_node(struct usteer_node *node)
137 {
138 struct usteer_local_node *ln;
139
140 ln = container_of(node, struct usteer_local_node, node);
141 if (ln->netifd.req_pending)
142 ubus_abort_request(ubus_ctx, &ln->netifd.req);
143 }
144
145 static struct usteer_node_handler netifd_handler = {
146 .init_node = netifd_init_node,
147 .update_node = netifd_update_node,
148 .free_node = netifd_free_node,
149 };
150
151 static void __usteer_init usteer_netifd_init(void)
152 {
153 list_add(&netifd_handler.list, &node_handlers);
154 }