interface-ip: mask out host bits in IPv4 route targets
[project/netifd.git] / device.c
1 /*
2 * netifd - network interface daemon
3 * Copyright (C) 2012 Felix Fietkau <nbd@openwrt.org>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2
7 * as published by the Free Software Foundation
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 */
14 #include <string.h>
15 #include <stdlib.h>
16 #include <stdio.h>
17 #include <assert.h>
18
19 #include <sys/types.h>
20 #include <sys/socket.h>
21
22 #include <libubox/list.h>
23
24 #include "netifd.h"
25 #include "system.h"
26 #include "config.h"
27 #include "wireless.h"
28 #include "ubus.h"
29
30 static struct list_head devtypes = LIST_HEAD_INIT(devtypes);
31 static struct avl_tree devices;
32 static struct blob_buf b;
33
34 static const struct blobmsg_policy dev_attrs[__DEV_ATTR_MAX] = {
35 [DEV_ATTR_TYPE] = { .name = "type", .type = BLOBMSG_TYPE_STRING },
36 [DEV_ATTR_MTU] = { .name = "mtu", .type = BLOBMSG_TYPE_INT32 },
37 [DEV_ATTR_MTU6] = { .name = "mtu6", .type = BLOBMSG_TYPE_INT32 },
38 [DEV_ATTR_MACADDR] = { .name = "macaddr", .type = BLOBMSG_TYPE_STRING },
39 [DEV_ATTR_TXQUEUELEN] = { .name = "txqueuelen", .type = BLOBMSG_TYPE_INT32 },
40 [DEV_ATTR_ENABLED] = { .name = "enabled", .type = BLOBMSG_TYPE_BOOL },
41 [DEV_ATTR_IPV6] = { .name = "ipv6", .type = BLOBMSG_TYPE_BOOL },
42 [DEV_ATTR_IP6SEGMENTROUTING] = { .name = "ip6segmentrouting", .type = BLOBMSG_TYPE_BOOL },
43 [DEV_ATTR_PROMISC] = { .name = "promisc", .type = BLOBMSG_TYPE_BOOL },
44 [DEV_ATTR_RPFILTER] = { .name = "rpfilter", .type = BLOBMSG_TYPE_STRING },
45 [DEV_ATTR_ACCEPTLOCAL] = { .name = "acceptlocal", .type = BLOBMSG_TYPE_BOOL },
46 [DEV_ATTR_IGMPVERSION] = { .name = "igmpversion", .type = BLOBMSG_TYPE_INT32 },
47 [DEV_ATTR_MLDVERSION] = { .name = "mldversion", .type = BLOBMSG_TYPE_INT32 },
48 [DEV_ATTR_NEIGHREACHABLETIME] = { .name = "neighreachabletime", .type = BLOBMSG_TYPE_INT32 },
49 [DEV_ATTR_NEIGHGCSTALETIME] = { .name = "neighgcstaletime", .type = BLOBMSG_TYPE_INT32 },
50 [DEV_ATTR_DADTRANSMITS] = { .name = "dadtransmits", .type = BLOBMSG_TYPE_INT32 },
51 [DEV_ATTR_MULTICAST_TO_UNICAST] = { .name = "multicast_to_unicast", .type = BLOBMSG_TYPE_BOOL },
52 [DEV_ATTR_MULTICAST_ROUTER] = { .name = "multicast_router", .type = BLOBMSG_TYPE_INT32 },
53 [DEV_ATTR_MULTICAST_FAST_LEAVE] = { .name = "multicast_fast_leave", . type = BLOBMSG_TYPE_BOOL },
54 [DEV_ATTR_MULTICAST] = { .name ="multicast", .type = BLOBMSG_TYPE_BOOL },
55 [DEV_ATTR_LEARNING] = { .name ="learning", .type = BLOBMSG_TYPE_BOOL },
56 [DEV_ATTR_UNICAST_FLOOD] = { .name ="unicast_flood", .type = BLOBMSG_TYPE_BOOL },
57 [DEV_ATTR_SENDREDIRECTS] = { .name = "sendredirects", .type = BLOBMSG_TYPE_BOOL },
58 [DEV_ATTR_NEIGHLOCKTIME] = { .name = "neighlocktime", .type = BLOBMSG_TYPE_INT32 },
59 [DEV_ATTR_ISOLATE] = { .name = "isolate", .type = BLOBMSG_TYPE_BOOL },
60 [DEV_ATTR_DROP_V4_UNICAST_IN_L2_MULTICAST] = { .name = "drop_v4_unicast_in_l2_multicast", .type = BLOBMSG_TYPE_BOOL },
61 [DEV_ATTR_DROP_V6_UNICAST_IN_L2_MULTICAST] = { .name = "drop_v6_unicast_in_l2_multicast", .type = BLOBMSG_TYPE_BOOL },
62 [DEV_ATTR_DROP_GRATUITOUS_ARP] = { .name = "drop_gratuitous_arp", .type = BLOBMSG_TYPE_BOOL },
63 [DEV_ATTR_DROP_UNSOLICITED_NA] = { .name = "drop_unsolicited_na", .type = BLOBMSG_TYPE_BOOL },
64 [DEV_ATTR_ARP_ACCEPT] = { .name = "arp_accept", .type = BLOBMSG_TYPE_BOOL },
65 [DEV_ATTR_AUTH] = { .name = "auth", .type = BLOBMSG_TYPE_BOOL },
66 [DEV_ATTR_AUTH_VLAN] = { .name = "auth_vlan", BLOBMSG_TYPE_ARRAY },
67 [DEV_ATTR_SPEED] = { .name = "speed", .type = BLOBMSG_TYPE_INT32 },
68 [DEV_ATTR_DUPLEX] = { .name = "duplex", .type = BLOBMSG_TYPE_BOOL },
69 [DEV_ATTR_VLAN] = { .name = "vlan", .type = BLOBMSG_TYPE_ARRAY },
70 [DEV_ATTR_PAUSE] = { .name = "pause", .type = BLOBMSG_TYPE_BOOL },
71 [DEV_ATTR_ASYM_PAUSE] = { .name = "asym_pause", .type = BLOBMSG_TYPE_BOOL },
72 [DEV_ATTR_RXPAUSE] = { .name = "rxpause", .type = BLOBMSG_TYPE_BOOL },
73 [DEV_ATTR_TXPAUSE] = { .name = "txpause", .type = BLOBMSG_TYPE_BOOL },
74 [DEV_ATTR_AUTONEG] = { .name = "autoneg", .type = BLOBMSG_TYPE_BOOL },
75 };
76
77 const struct uci_blob_param_list device_attr_list = {
78 .n_params = __DEV_ATTR_MAX,
79 .params = dev_attrs,
80 };
81
82 static int __devlock = 0;
83
84 int device_type_add(struct device_type *devtype)
85 {
86 if (device_type_get(devtype->name)) {
87 netifd_log_message(L_WARNING, "Device handler '%s' already exists\n",
88 devtype->name);
89 return 1;
90 }
91
92 netifd_log_message(L_NOTICE, "Added device handler type: %s\n",
93 devtype->name);
94
95 list_add(&devtype->list, &devtypes);
96 return 0;
97 }
98
99 struct device_type *
100 device_type_get(const char *tname)
101 {
102 struct device_type *cur;
103
104 list_for_each_entry(cur, &devtypes, list)
105 if (!strcmp(cur->name, tname))
106 return cur;
107
108 return NULL;
109 }
110
111 static int device_vlan_len(struct kvlist *kv, const void *data)
112 {
113 return sizeof(unsigned int);
114 }
115
116 void device_vlan_update(bool done)
117 {
118 struct device *dev;
119
120 avl_for_each_element(&devices, dev, avl) {
121 if (!dev->vlans.update)
122 continue;
123
124 if (!done) {
125 if (dev->vlan_aliases.get_len)
126 kvlist_free(&dev->vlan_aliases);
127 else
128 kvlist_init(&dev->vlan_aliases, device_vlan_len);
129 vlist_update(&dev->vlans);
130 } else {
131 vlist_flush(&dev->vlans);
132
133 if (dev->type->vlan_update)
134 dev->type->vlan_update(dev);
135 }
136 }
137 }
138
139 void device_stp_init(void)
140 {
141 struct device *dev;
142
143 avl_for_each_element(&devices, dev, avl) {
144 if (!dev->type->stp_init)
145 continue;
146
147 dev->type->stp_init(dev);
148 }
149 }
150
151 static int set_device_state(struct device *dev, bool state)
152 {
153 if (state) {
154 /* Get ifindex for all devices being enabled so a valid */
155 /* ifindex is in place avoiding possible race conditions */
156 device_set_ifindex(dev, system_if_resolve(dev));
157 if (!dev->ifindex)
158 return -1;
159
160 system_if_get_settings(dev, &dev->orig_settings);
161 /* Only keep orig settings based on what needs to be set */
162 dev->orig_settings.valid_flags = dev->orig_settings.flags;
163 dev->orig_settings.flags &= dev->settings.flags;
164 system_if_apply_settings(dev, &dev->settings, dev->settings.flags);
165
166 system_if_up(dev);
167 } else {
168 system_if_down(dev);
169 system_if_apply_settings(dev, &dev->orig_settings, dev->orig_settings.flags);
170 }
171
172 return 0;
173 }
174
175 static int
176 simple_device_set_state(struct device *dev, bool state)
177 {
178 struct device *pdev;
179 int ret = 0;
180
181 pdev = dev->parent.dev;
182 if (state && !pdev) {
183 pdev = system_if_get_parent(dev);
184 if (pdev)
185 device_add_user(&dev->parent, pdev);
186 }
187
188 if (pdev) {
189 if (state)
190 ret = device_claim(&dev->parent);
191 else
192 device_release(&dev->parent);
193
194 if (ret < 0)
195 return ret;
196 }
197 return set_device_state(dev, state);
198 }
199
200 static struct device *
201 simple_device_create(const char *name, struct device_type *devtype,
202 struct blob_attr *attr)
203 {
204 struct blob_attr *tb[__DEV_ATTR_MAX];
205 struct device *dev = NULL;
206
207 /* device type is unused for simple devices */
208 devtype = NULL;
209
210 blobmsg_parse(dev_attrs, __DEV_ATTR_MAX, tb, blob_data(attr), blob_len(attr));
211 dev = device_get(name, true);
212 if (!dev)
213 return NULL;
214
215 dev->set_state = simple_device_set_state;
216 device_init_settings(dev, tb);
217
218 return dev;
219 }
220
221 static void simple_device_free(struct device *dev)
222 {
223 if (dev->parent.dev)
224 device_remove_user(&dev->parent);
225 free(dev);
226 }
227
228 struct device_type simple_device_type = {
229 .name = "Network device",
230 .config_params = &device_attr_list,
231
232 .create = simple_device_create,
233 .check_state = system_if_check,
234 .free = simple_device_free,
235 };
236
237 void
238 device_merge_settings(struct device *dev, struct device_settings *n)
239 {
240 struct device_settings *os = &dev->orig_settings;
241 struct device_settings *s = &dev->settings;
242
243 memset(n, 0, sizeof(*n));
244 n->mtu = s->flags & DEV_OPT_MTU ? s->mtu : os->mtu;
245 n->mtu6 = s->flags & DEV_OPT_MTU6 ? s->mtu6 : os->mtu6;
246 n->txqueuelen = s->flags & DEV_OPT_TXQUEUELEN ?
247 s->txqueuelen : os->txqueuelen;
248 memcpy(n->macaddr,
249 (s->flags & (DEV_OPT_MACADDR|DEV_OPT_DEFAULT_MACADDR) ? s->macaddr : os->macaddr),
250 sizeof(n->macaddr));
251 n->ipv6 = s->flags & DEV_OPT_IPV6 ? s->ipv6 : os->ipv6;
252 n->ip6segmentrouting = s->flags & DEV_OPT_IP6SEGMENTROUTING ? s->ip6segmentrouting : os->ip6segmentrouting;
253 n->promisc = s->flags & DEV_OPT_PROMISC ? s->promisc : os->promisc;
254 n->rpfilter = s->flags & DEV_OPT_RPFILTER ? s->rpfilter : os->rpfilter;
255 n->acceptlocal = s->flags & DEV_OPT_ACCEPTLOCAL ? s->acceptlocal : os->acceptlocal;
256 n->igmpversion = s->flags & DEV_OPT_IGMPVERSION ? s->igmpversion : os->igmpversion;
257 n->mldversion = s->flags & DEV_OPT_MLDVERSION ? s->mldversion : os->mldversion;
258 n->neigh4reachabletime = s->flags & DEV_OPT_NEIGHREACHABLETIME ?
259 s->neigh4reachabletime : os->neigh4reachabletime;
260 n->neigh6reachabletime = s->flags & DEV_OPT_NEIGHREACHABLETIME ?
261 s->neigh6reachabletime : os->neigh6reachabletime;
262 n->neigh4gcstaletime = s->flags & DEV_OPT_NEIGHGCSTALETIME ?
263 s->neigh4gcstaletime : os->neigh4gcstaletime;
264 n->neigh6gcstaletime = s->flags & DEV_OPT_NEIGHGCSTALETIME ?
265 s->neigh6gcstaletime : os->neigh6gcstaletime;
266 n->neigh4locktime = s->flags & DEV_OPT_NEIGHLOCKTIME ?
267 s->neigh4locktime : os->neigh4locktime;
268 n->dadtransmits = s->flags & DEV_OPT_DADTRANSMITS ?
269 s->dadtransmits : os->dadtransmits;
270 n->multicast = s->flags & DEV_OPT_MULTICAST ?
271 s->multicast : os->multicast;
272 n->multicast_to_unicast = s->multicast_to_unicast;
273 n->multicast_router = s->multicast_router;
274 n->multicast_fast_leave = s->multicast_fast_leave;
275 n->learning = s->learning;
276 n->unicast_flood = s->unicast_flood;
277 n->sendredirects = s->flags & DEV_OPT_SENDREDIRECTS ?
278 s->sendredirects : os->sendredirects;
279 n->drop_v4_unicast_in_l2_multicast = s->flags & DEV_OPT_DROP_V4_UNICAST_IN_L2_MULTICAST ?
280 s->drop_v4_unicast_in_l2_multicast : os->drop_v4_unicast_in_l2_multicast;
281 n->drop_v6_unicast_in_l2_multicast = s->flags & DEV_OPT_DROP_V6_UNICAST_IN_L2_MULTICAST ?
282 s->drop_v6_unicast_in_l2_multicast : os->drop_v6_unicast_in_l2_multicast;
283 n->drop_gratuitous_arp = s->flags & DEV_OPT_DROP_GRATUITOUS_ARP ?
284 s->drop_gratuitous_arp : os->drop_gratuitous_arp;
285 n->drop_unsolicited_na = s->flags & DEV_OPT_DROP_UNSOLICITED_NA ?
286 s->drop_unsolicited_na : os->drop_unsolicited_na;
287 n->arp_accept = s->flags & DEV_OPT_ARP_ACCEPT ?
288 s->arp_accept : os->arp_accept;
289 n->auth = s->flags & DEV_OPT_AUTH ? s->auth : os->auth;
290 n->speed = s->flags & DEV_OPT_SPEED ? s->speed : os->speed;
291 n->duplex = s->flags & DEV_OPT_DUPLEX ? s->duplex : os->duplex;
292 n->pause = s->flags & DEV_OPT_PAUSE ? s->pause : os->pause;
293 n->asym_pause = s->flags & DEV_OPT_ASYM_PAUSE ? s->asym_pause : os->asym_pause;
294 n->rxpause = s->flags & DEV_OPT_RXPAUSE ? s->rxpause : os->rxpause;
295 n->txpause = s->flags & DEV_OPT_TXPAUSE ? s->txpause : os->txpause;
296 n->autoneg = s->flags & DEV_OPT_AUTONEG ? s->autoneg : os->autoneg;
297 n->flags = s->flags | os->flags | os->valid_flags;
298 }
299
300 static bool device_fill_vlan_range(struct device_vlan_range *r, const char *val)
301 {
302 unsigned long cur_start, cur_end;
303 char *sep;
304
305 cur_start = strtoul(val, &sep, 0);
306 cur_end = cur_start;
307
308 if (*sep == '-')
309 cur_end = strtoul(sep + 1, &sep, 0);
310 if (*sep || cur_end < cur_start)
311 return false;
312
313 r->start = cur_start;
314 r->end = cur_end;
315
316 return true;
317 }
318
319 static void
320 device_set_extra_vlans(struct device *dev, struct blob_attr *data)
321 {
322 struct blob_attr *cur;
323 int n_vlans;
324 size_t rem;
325
326 dev->n_extra_vlan = 0;
327 if (!data)
328 return;
329
330 n_vlans = blobmsg_check_array(data, BLOBMSG_TYPE_STRING);
331 if (n_vlans < 1)
332 return;
333
334 dev->extra_vlan = realloc(dev->extra_vlan, n_vlans * sizeof(*dev->extra_vlan));
335 blobmsg_for_each_attr(cur, data, rem)
336 if (device_fill_vlan_range(&dev->extra_vlan[dev->n_extra_vlan],
337 blobmsg_get_string(cur)))
338 dev->n_extra_vlan++;
339 }
340
341 void
342 device_init_settings(struct device *dev, struct blob_attr **tb)
343 {
344 struct device_settings *s = &dev->settings;
345 struct blob_attr *cur;
346 struct ether_addr *ea;
347 bool disabled = false;
348
349 s->flags = 0;
350 if ((cur = tb[DEV_ATTR_ENABLED]))
351 disabled = !blobmsg_get_bool(cur);
352
353 if ((cur = tb[DEV_ATTR_MTU]) && blobmsg_get_u32(cur) >= 68) {
354 s->mtu = blobmsg_get_u32(cur);
355 s->flags |= DEV_OPT_MTU;
356 }
357
358 if ((cur = tb[DEV_ATTR_MTU6]) && blobmsg_get_u32(cur) >= 1280) {
359 s->mtu6 = blobmsg_get_u32(cur);
360 s->flags |= DEV_OPT_MTU6;
361 }
362
363 if ((cur = tb[DEV_ATTR_TXQUEUELEN])) {
364 s->txqueuelen = blobmsg_get_u32(cur);
365 s->flags |= DEV_OPT_TXQUEUELEN;
366 }
367
368 if ((cur = tb[DEV_ATTR_MACADDR])) {
369 ea = ether_aton(blobmsg_data(cur));
370 if (ea) {
371 memcpy(s->macaddr, ea, 6);
372 s->flags |= DEV_OPT_MACADDR;
373 }
374 }
375
376 if ((cur = tb[DEV_ATTR_IPV6])) {
377 s->ipv6 = blobmsg_get_bool(cur);
378 s->flags |= DEV_OPT_IPV6;
379 }
380
381 if ((cur = tb[DEV_ATTR_IP6SEGMENTROUTING])) {
382 s->ip6segmentrouting = blobmsg_get_bool(cur);
383 s->flags |= DEV_OPT_IP6SEGMENTROUTING;
384 }
385
386 if ((cur = tb[DEV_ATTR_PROMISC])) {
387 s->promisc = blobmsg_get_bool(cur);
388 s->flags |= DEV_OPT_PROMISC;
389 }
390
391 if ((cur = tb[DEV_ATTR_RPFILTER])) {
392 if (system_resolve_rpfilter(blobmsg_data(cur), &s->rpfilter))
393 s->flags |= DEV_OPT_RPFILTER;
394 else
395 DPRINTF("Failed to resolve rpfilter: %s\n", (char *) blobmsg_data(cur));
396 }
397
398 if ((cur = tb[DEV_ATTR_ACCEPTLOCAL])) {
399 s->acceptlocal = blobmsg_get_bool(cur);
400 s->flags |= DEV_OPT_ACCEPTLOCAL;
401 }
402
403 if ((cur = tb[DEV_ATTR_IGMPVERSION])) {
404 s->igmpversion = blobmsg_get_u32(cur);
405 if (s->igmpversion >= 1 && s->igmpversion <= 3)
406 s->flags |= DEV_OPT_IGMPVERSION;
407 else
408 DPRINTF("Failed to resolve igmpversion: %d\n", blobmsg_get_u32(cur));
409 }
410
411 if ((cur = tb[DEV_ATTR_MLDVERSION])) {
412 s->mldversion = blobmsg_get_u32(cur);
413 if (s->mldversion >= 1 && s->mldversion <= 2)
414 s->flags |= DEV_OPT_MLDVERSION;
415 else
416 DPRINTF("Failed to resolve mldversion: %d\n", blobmsg_get_u32(cur));
417 }
418
419 if ((cur = tb[DEV_ATTR_NEIGHREACHABLETIME])) {
420 s->neigh6reachabletime = s->neigh4reachabletime = blobmsg_get_u32(cur);
421 s->flags |= DEV_OPT_NEIGHREACHABLETIME;
422 }
423
424 if ((cur = tb[DEV_ATTR_NEIGHGCSTALETIME])) {
425 s->neigh6gcstaletime = s->neigh4gcstaletime = blobmsg_get_u32(cur);
426 s->flags |= DEV_OPT_NEIGHGCSTALETIME;
427 }
428
429 if ((cur = tb[DEV_ATTR_NEIGHLOCKTIME])) {
430 s->neigh4locktime = blobmsg_get_u32(cur);
431 s->flags |= DEV_OPT_NEIGHLOCKTIME;
432 }
433
434 if ((cur = tb[DEV_ATTR_DADTRANSMITS])) {
435 s->dadtransmits = blobmsg_get_u32(cur);
436 s->flags |= DEV_OPT_DADTRANSMITS;
437 }
438
439 if ((cur = tb[DEV_ATTR_MULTICAST_TO_UNICAST])) {
440 s->multicast_to_unicast = blobmsg_get_bool(cur);
441 s->flags |= DEV_OPT_MULTICAST_TO_UNICAST;
442 }
443
444 if ((cur = tb[DEV_ATTR_MULTICAST_ROUTER])) {
445 s->multicast_router = blobmsg_get_u32(cur);
446 if (s->multicast_router <= 2)
447 s->flags |= DEV_OPT_MULTICAST_ROUTER;
448 else
449 DPRINTF("Invalid value: %d - (Use 0: never, 1: learn, 2: always)\n", blobmsg_get_u32(cur));
450 }
451
452 if ((cur = tb[DEV_ATTR_MULTICAST_FAST_LEAVE])) {
453 s->multicast_fast_leave = blobmsg_get_bool(cur);
454 s->flags |= DEV_OPT_MULTICAST_FAST_LEAVE;
455 }
456
457 if ((cur = tb[DEV_ATTR_MULTICAST])) {
458 s->multicast = blobmsg_get_bool(cur);
459 s->flags |= DEV_OPT_MULTICAST;
460 }
461
462 if ((cur = tb[DEV_ATTR_LEARNING])) {
463 s->learning = blobmsg_get_bool(cur);
464 s->flags |= DEV_OPT_LEARNING;
465 }
466
467 if ((cur = tb[DEV_ATTR_UNICAST_FLOOD])) {
468 s->unicast_flood = blobmsg_get_bool(cur);
469 s->flags |= DEV_OPT_UNICAST_FLOOD;
470 }
471
472 if ((cur = tb[DEV_ATTR_SENDREDIRECTS])) {
473 s->sendredirects = blobmsg_get_bool(cur);
474 s->flags |= DEV_OPT_SENDREDIRECTS;
475 }
476
477 if ((cur = tb[DEV_ATTR_ISOLATE])) {
478 s->isolate = blobmsg_get_bool(cur);
479 s->flags |= DEV_OPT_ISOLATE;
480 }
481
482 if ((cur = tb[DEV_ATTR_DROP_V4_UNICAST_IN_L2_MULTICAST])) {
483 s->drop_v4_unicast_in_l2_multicast = blobmsg_get_bool(cur);
484 s->flags |= DEV_OPT_DROP_V4_UNICAST_IN_L2_MULTICAST;
485 }
486
487 if ((cur = tb[DEV_ATTR_DROP_V6_UNICAST_IN_L2_MULTICAST])) {
488 s->drop_v6_unicast_in_l2_multicast = blobmsg_get_bool(cur);
489 s->flags |= DEV_OPT_DROP_V6_UNICAST_IN_L2_MULTICAST;
490 }
491
492 if ((cur = tb[DEV_ATTR_DROP_GRATUITOUS_ARP])) {
493 s->drop_gratuitous_arp = blobmsg_get_bool(cur);
494 s->flags |= DEV_OPT_DROP_GRATUITOUS_ARP;
495 }
496
497 if ((cur = tb[DEV_ATTR_DROP_UNSOLICITED_NA])) {
498 s->drop_unsolicited_na = blobmsg_get_bool(cur);
499 s->flags |= DEV_OPT_DROP_UNSOLICITED_NA;
500 }
501
502 if ((cur = tb[DEV_ATTR_ARP_ACCEPT])) {
503 s->arp_accept = blobmsg_get_bool(cur);
504 s->flags |= DEV_OPT_ARP_ACCEPT;
505 }
506
507 if ((cur = tb[DEV_ATTR_AUTH])) {
508 s->auth = blobmsg_get_bool(cur);
509 s->flags |= DEV_OPT_AUTH;
510 }
511
512 if ((cur = tb[DEV_ATTR_SPEED])) {
513 s->speed = blobmsg_get_u32(cur);
514 s->flags |= DEV_OPT_SPEED;
515 }
516
517 if ((cur = tb[DEV_ATTR_DUPLEX])) {
518 s->duplex = blobmsg_get_bool(cur);
519 s->flags |= DEV_OPT_DUPLEX;
520 }
521
522 if ((cur = tb[DEV_ATTR_PAUSE])) {
523 s->pause = blobmsg_get_bool(cur);
524 s->flags |= DEV_OPT_PAUSE;
525 }
526
527 if ((cur = tb[DEV_ATTR_ASYM_PAUSE])) {
528 s->asym_pause = blobmsg_get_bool(cur);
529 s->flags |= DEV_OPT_ASYM_PAUSE;
530 }
531
532 if ((cur = tb[DEV_ATTR_RXPAUSE])) {
533 s->rxpause = blobmsg_get_bool(cur);
534 s->flags |= DEV_OPT_RXPAUSE;
535 }
536
537 if ((cur = tb[DEV_ATTR_TXPAUSE])) {
538 s->txpause = blobmsg_get_bool(cur);
539 s->flags |= DEV_OPT_TXPAUSE;
540 }
541
542 if ((cur = tb[DEV_ATTR_AUTONEG])) {
543 s->autoneg = blobmsg_get_bool(cur);
544 s->flags |= DEV_OPT_AUTONEG;
545 }
546
547 cur = tb[DEV_ATTR_AUTH_VLAN];
548 free(dev->config_auth_vlans);
549 dev->config_auth_vlans = cur ? blob_memdup(cur) : NULL;
550
551 device_set_extra_vlans(dev, tb[DEV_ATTR_VLAN]);
552 device_set_disabled(dev, disabled);
553 }
554
555 static void __init dev_init(void)
556 {
557 avl_init(&devices, avl_strcmp, true, NULL);
558 }
559
560 static int device_release_cb(void *ctx, struct safe_list *list)
561 {
562 struct device_user *dep = container_of(list, struct device_user, list);
563
564 if (!dep->dev || !dep->claimed)
565 return 0;
566
567 device_release(dep);
568 return 0;
569 }
570
571 static int device_broadcast_cb(void *ctx, struct safe_list *list)
572 {
573 struct device_user *dep = container_of(list, struct device_user, list);
574 int *ev = ctx;
575
576 /* device might have been removed by an earlier callback */
577 if (!dep->dev)
578 return 0;
579
580 if (dep->cb)
581 dep->cb(dep, *ev);
582 return 0;
583 }
584
585 void device_broadcast_event(struct device *dev, enum device_event ev)
586 {
587 static const char * const event_names[] = {
588 [DEV_EVENT_ADD] = "add",
589 [DEV_EVENT_REMOVE] = "remove",
590 [DEV_EVENT_UP] = "up",
591 [DEV_EVENT_DOWN] = "down",
592 [DEV_EVENT_AUTH_UP] = "auth_up",
593 [DEV_EVENT_LINK_UP] = "link_up",
594 [DEV_EVENT_LINK_DOWN] = "link_down",
595 [DEV_EVENT_TOPO_CHANGE] = "topo_change",
596 };
597 int dev_ev = ev;
598
599 safe_list_for_each(&dev->aliases, device_broadcast_cb, &dev_ev);
600 safe_list_for_each(&dev->users, device_broadcast_cb, &dev_ev);
601
602 if (ev >= ARRAY_SIZE(event_names) || !event_names[ev] || !dev->ifname[0])
603 return;
604
605 blob_buf_init(&b, 0);
606 blobmsg_add_string(&b, "name", dev->ifname);
607 blobmsg_add_u8(&b, "auth_status", dev->auth_status);
608 blobmsg_add_u8(&b, "present", dev->present);
609 blobmsg_add_u8(&b, "active", dev->active);
610 blobmsg_add_u8(&b, "link_active", dev->link_active);
611 netifd_ubus_device_notify(event_names[ev], b.head, -1);
612 }
613
614 static void
615 device_fill_default_settings(struct device *dev)
616 {
617 struct device_settings *s = &dev->settings;
618 struct ether_addr *ea;
619
620 if (!(s->flags & DEV_OPT_MACADDR)) {
621 ea = config_get_default_macaddr(dev->ifname);
622 if (ea) {
623 memcpy(s->macaddr, ea, 6);
624 s->flags |= DEV_OPT_DEFAULT_MACADDR;
625 }
626 }
627 }
628
629 int device_claim(struct device_user *dep)
630 {
631 struct device *dev = dep->dev;
632 int ret = 0;
633
634 if (dep->claimed)
635 return 0;
636
637 if (!dev)
638 return -1;
639
640 dep->claimed = true;
641 D(DEVICE, "Claim %s %s, new active count: %d\n", dev->type->name, dev->ifname, dev->active + 1);
642 if (++dev->active != 1)
643 return 0;
644
645 device_broadcast_event(dev, DEV_EVENT_SETUP);
646 device_fill_default_settings(dev);
647 if (dev->external) {
648 /* Get ifindex for external claimed devices so a valid */
649 /* ifindex is in place avoiding possible race conditions */
650 device_set_ifindex(dev, system_if_resolve(dev));
651 if (!dev->ifindex)
652 ret = -1;
653
654 system_if_get_settings(dev, &dev->orig_settings);
655 } else
656 ret = dev->set_state(dev, true);
657
658 if (ret == 0)
659 device_broadcast_event(dev, DEV_EVENT_UP);
660 else {
661 D(DEVICE, "claim %s %s failed: %d\n", dev->type->name, dev->ifname, ret);
662 dev->active = 0;
663 dep->claimed = false;
664 }
665
666 return ret;
667 }
668
669 void device_release(struct device_user *dep)
670 {
671 struct device *dev = dep->dev;
672
673 if (!dep->claimed)
674 return;
675
676 dep->claimed = false;
677 dev->active--;
678 D(DEVICE, "Release %s %s, new active count: %d\n", dev->type->name, dev->ifname, dev->active);
679 assert(dev->active >= 0);
680
681 if (dev->active)
682 return;
683
684 device_broadcast_event(dev, DEV_EVENT_TEARDOWN);
685 if (!dev->external)
686 dev->set_state(dev, false);
687
688 if (dev->active)
689 return;
690
691 device_broadcast_event(dev, DEV_EVENT_DOWN);
692 }
693
694 int device_check_state(struct device *dev)
695 {
696 if (!dev->type->check_state)
697 return simple_device_type.check_state(dev);
698
699 return dev->type->check_state(dev);
700 }
701
702 int device_init_virtual(struct device *dev, struct device_type *type, const char *name)
703 {
704 assert(dev);
705 assert(type);
706
707 D(DEVICE, "Initialize device '%s'\n", name ? name : "");
708 INIT_SAFE_LIST(&dev->users);
709 INIT_SAFE_LIST(&dev->aliases);
710 dev->type = type;
711
712 if (name) {
713 int ret;
714
715 ret = device_set_ifname(dev, name);
716 if (ret < 0)
717 return ret;
718 }
719
720 if (!dev->set_state)
721 dev->set_state = set_device_state;
722
723 return 0;
724 }
725
726 int device_init(struct device *dev, struct device_type *type, const char *ifname)
727 {
728 int ret;
729
730 ret = device_init_virtual(dev, type, ifname);
731 if (ret < 0)
732 return ret;
733
734 dev->avl.key = dev->ifname;
735
736 ret = avl_insert(&devices, &dev->avl);
737 if (ret < 0)
738 return ret;
739
740 system_if_clear_state(dev);
741
742 return 0;
743 }
744
745 static struct device *
746 device_create_default(const char *name, bool external)
747 {
748 struct device *dev;
749
750 if (!external && system_if_force_external(name))
751 return NULL;
752
753 D(DEVICE, "Create simple device '%s'\n", name);
754 dev = calloc(1, sizeof(*dev));
755 if (!dev)
756 return NULL;
757
758 dev->external = external;
759 dev->set_state = simple_device_set_state;
760
761 if (device_init(dev, &simple_device_type, name) < 0) {
762 device_cleanup(dev);
763 free(dev);
764 return NULL;
765 }
766
767 dev->default_config = true;
768 if (external)
769 system_if_apply_settings(dev, &dev->settings, dev->settings.flags);
770
771 device_check_state(dev);
772
773 return dev;
774 }
775
776 struct device *
777 device_find(const char *name)
778 {
779 struct device *dev;
780
781 return avl_find_element(&devices, name, dev, avl);
782 }
783
784 struct device *
785 __device_get(const char *name, int create, bool check_vlan)
786 {
787 struct device *dev;
788
789 dev = avl_find_element(&devices, name, dev, avl);
790
791 if (!dev && check_vlan && strchr(name, '.'))
792 return get_vlan_device_chain(name, create);
793
794 if (name[0] == '@')
795 return device_alias_get(name + 1);
796
797 if (dev) {
798 if (create > 1 && !dev->external) {
799 system_if_apply_settings(dev, &dev->settings, dev->settings.flags);
800 dev->external = true;
801 device_set_present(dev, true);
802 }
803 return dev;
804 }
805
806 if (!create)
807 return NULL;
808
809 return device_create_default(name, create > 1);
810 }
811
812 static void
813 device_delete(struct device *dev)
814 {
815 if (!dev->avl.key)
816 return;
817
818 D(DEVICE, "Delete device '%s' from list\n", dev->ifname);
819 avl_delete(&devices, &dev->avl);
820 dev->avl.key = NULL;
821 }
822
823 static int device_cleanup_cb(void *ctx, struct safe_list *list)
824 {
825 struct device_user *dep = container_of(list, struct device_user, list);
826 if (dep->cb)
827 dep->cb(dep, DEV_EVENT_REMOVE);
828
829 device_release(dep);
830 return 0;
831 }
832
833 void device_cleanup(struct device *dev)
834 {
835 D(DEVICE, "Clean up device '%s'\n", dev->ifname);
836 safe_list_for_each(&dev->users, device_cleanup_cb, NULL);
837 safe_list_for_each(&dev->aliases, device_cleanup_cb, NULL);
838 device_delete(dev);
839 }
840
841 static void __device_set_present(struct device *dev, bool state)
842 {
843 if (dev->present == state)
844 return;
845
846 dev->present = state;
847 device_broadcast_event(dev, state ? DEV_EVENT_ADD : DEV_EVENT_REMOVE);
848 }
849
850 void
851 device_refresh_present(struct device *dev)
852 {
853 bool state = dev->sys_present;
854
855 if (dev->disabled || dev->deferred)
856 state = false;
857
858 __device_set_present(dev, state);
859 }
860
861 void
862 device_set_auth_status(struct device *dev, bool value, struct blob_attr *vlans)
863 {
864 if (!value)
865 vlans = NULL;
866 else if (!blob_attr_equal(vlans, dev->auth_vlans))
867 device_set_auth_status(dev, false, NULL);
868
869 free(dev->auth_vlans);
870 dev->auth_vlans = vlans ? blob_memdup(vlans) : NULL;
871
872 if (dev->auth_status == value)
873 return;
874
875 dev->auth_status = value;
876 if (!dev->present)
877 return;
878
879 if (dev->auth_status) {
880 device_broadcast_event(dev, DEV_EVENT_AUTH_UP);
881 return;
882 }
883
884 device_broadcast_event(dev, DEV_EVENT_LINK_DOWN);
885 if (!dev->link_active)
886 return;
887
888 device_broadcast_event(dev, DEV_EVENT_LINK_UP);
889 }
890
891 void device_set_present(struct device *dev, bool state)
892 {
893 if (dev->sys_present == state)
894 return;
895
896 D(DEVICE, "%s '%s' %s present\n", dev->type->name, dev->ifname, state ? "is now" : "is no longer" );
897 dev->sys_present = state;
898 device_refresh_present(dev);
899 if (!state)
900 safe_list_for_each(&dev->users, device_release_cb, NULL);
901 }
902
903 void device_set_link(struct device *dev, bool state)
904 {
905 if (dev->link_active == state)
906 return;
907
908 netifd_log_message(L_NOTICE, "%s '%s' link is %s\n", dev->type->name, dev->ifname, state ? "up" : "down" );
909
910 dev->link_active = state;
911 if (!state)
912 dev->auth_status = false;
913 device_broadcast_event(dev, state ? DEV_EVENT_LINK_UP : DEV_EVENT_LINK_DOWN);
914 }
915
916 void device_set_ifindex(struct device *dev, int ifindex)
917 {
918 if (dev->ifindex == ifindex)
919 return;
920
921 dev->ifindex = ifindex;
922 device_broadcast_event(dev, DEV_EVENT_UPDATE_IFINDEX);
923 }
924
925 int device_set_ifname(struct device *dev, const char *name)
926 {
927 int ret = 0;
928
929 if (!strcmp(dev->ifname, name))
930 return 0;
931
932 if (strlen(name) > sizeof(dev->ifname) - 1)
933 return -1;
934
935 if (dev->avl.key)
936 avl_delete(&devices, &dev->avl);
937
938 strcpy(dev->ifname, name);
939
940 if (dev->avl.key)
941 ret = avl_insert(&devices, &dev->avl);
942
943 if (ret == 0)
944 device_broadcast_event(dev, DEV_EVENT_UPDATE_IFNAME);
945
946 return ret;
947 }
948
949 static int device_refcount(struct device *dev)
950 {
951 struct list_head *list;
952 int count = 0;
953
954 list_for_each(list, &dev->users.list)
955 count++;
956
957 list_for_each(list, &dev->aliases.list)
958 count++;
959
960 return count;
961 }
962
963 static void
964 __device_add_user(struct device_user *dep, struct device *dev)
965 {
966 struct safe_list *head;
967
968 dep->dev = dev;
969
970 if (dep->alias)
971 head = &dev->aliases;
972 else
973 head = &dev->users;
974
975 safe_list_add(&dep->list, head);
976 D(DEVICE, "Add user for device '%s', refcount=%d\n", dev->ifname, device_refcount(dev));
977
978 if (dep->cb && dev->present) {
979 dep->cb(dep, DEV_EVENT_ADD);
980 if (dev->active)
981 dep->cb(dep, DEV_EVENT_UP);
982
983 if (dev->link_active)
984 dep->cb(dep, DEV_EVENT_LINK_UP);
985 }
986 }
987
988 void device_add_user(struct device_user *dep, struct device *dev)
989 {
990 if (dep->dev == dev)
991 return;
992
993 if (dep->dev)
994 device_remove_user(dep);
995
996 if (!dev)
997 return;
998
999 __device_add_user(dep, dev);
1000 }
1001
1002 static void
1003 device_free(struct device *dev)
1004 {
1005 __devlock++;
1006 free(dev->auth_vlans);
1007 free(dev->config);
1008 device_cleanup(dev);
1009 free(dev->config_auth_vlans);
1010 free(dev->extra_vlan);
1011 dev->type->free(dev);
1012 __devlock--;
1013 }
1014
1015 static void
1016 __device_free_unused(struct uloop_timeout *timeout)
1017 {
1018 struct device *dev, *tmp;
1019
1020 avl_for_each_element_safe(&devices, dev, avl, tmp) {
1021 if (!safe_list_empty(&dev->users) ||
1022 !safe_list_empty(&dev->aliases) ||
1023 dev->current_config)
1024 continue;
1025
1026 device_free(dev);
1027 }
1028 }
1029
1030 void device_free_unused(void)
1031 {
1032 static struct uloop_timeout free_timer = {
1033 .cb = __device_free_unused,
1034 };
1035
1036 uloop_timeout_set(&free_timer, 1);
1037 }
1038
1039 void device_remove_user(struct device_user *dep)
1040 {
1041 struct device *dev = dep->dev;
1042
1043 if (!dep->dev)
1044 return;
1045
1046 dep->hotplug = false;
1047 if (dep->claimed)
1048 device_release(dep);
1049
1050 safe_list_del(&dep->list);
1051 dep->dev = NULL;
1052 D(DEVICE, "Remove user for device '%s', refcount=%d\n", dev->ifname, device_refcount(dev));
1053 device_free_unused();
1054 }
1055
1056 void
1057 device_init_pending(void)
1058 {
1059 struct device *dev, *tmp;
1060
1061 avl_for_each_element_safe(&devices, dev, avl, tmp) {
1062 if (!dev->config_pending)
1063 continue;
1064
1065 dev->type->config_init(dev);
1066 dev->config_pending = false;
1067 device_check_state(dev);
1068 }
1069 }
1070
1071 bool
1072 device_check_ip6segmentrouting(void)
1073 {
1074 struct device *dev;
1075 bool ip6segmentrouting = false;
1076
1077 avl_for_each_element(&devices, dev, avl)
1078 ip6segmentrouting |= dev->settings.ip6segmentrouting;
1079
1080 return ip6segmentrouting;
1081 }
1082
1083 static enum dev_change_type
1084 device_set_config(struct device *dev, struct device_type *type,
1085 struct blob_attr *attr)
1086 {
1087 struct blob_attr *tb[__DEV_ATTR_MAX];
1088 const struct uci_blob_param_list *cfg = type->config_params;
1089
1090 if (type != dev->type)
1091 return DEV_CONFIG_RECREATE;
1092
1093 if (dev->type->reload)
1094 return dev->type->reload(dev, attr);
1095
1096 if (uci_blob_check_equal(dev->config, attr, cfg))
1097 return DEV_CONFIG_NO_CHANGE;
1098
1099 if (cfg == &device_attr_list) {
1100 memset(tb, 0, sizeof(tb));
1101
1102 if (attr)
1103 blobmsg_parse(dev_attrs, __DEV_ATTR_MAX, tb,
1104 blob_data(attr), blob_len(attr));
1105
1106 device_init_settings(dev, tb);
1107 return DEV_CONFIG_RESTART;
1108 } else
1109 return DEV_CONFIG_RECREATE;
1110 }
1111
1112 enum dev_change_type
1113 device_apply_config(struct device *dev, struct device_type *type,
1114 struct blob_attr *config)
1115 {
1116 enum dev_change_type change;
1117
1118 change = device_set_config(dev, type, config);
1119 if (dev->external) {
1120 system_if_apply_settings(dev, &dev->settings, dev->settings.flags);
1121 change = DEV_CONFIG_APPLIED;
1122 }
1123
1124 switch (change) {
1125 case DEV_CONFIG_RESTART:
1126 case DEV_CONFIG_APPLIED:
1127 D(DEVICE, "Device '%s': config applied\n", dev->ifname);
1128 config = blob_memdup(config);
1129 free(dev->config);
1130 dev->config = config;
1131 if (change == DEV_CONFIG_RESTART && dev->present) {
1132 int ret = 0;
1133
1134 device_set_present(dev, false);
1135 if (dev->active && !dev->external) {
1136 ret = dev->set_state(dev, false);
1137 if (!ret)
1138 ret = dev->set_state(dev, true);
1139 }
1140 if (!ret)
1141 device_set_present(dev, true);
1142 }
1143 break;
1144 case DEV_CONFIG_NO_CHANGE:
1145 D(DEVICE, "Device '%s': no configuration change\n", dev->ifname);
1146 break;
1147 case DEV_CONFIG_RECREATE:
1148 break;
1149 }
1150
1151 return change;
1152 }
1153
1154 static void
1155 device_replace(struct device *dev, struct device *odev)
1156 {
1157 struct device_user *dep;
1158
1159 __devlock++;
1160 if (odev->present)
1161 device_set_present(odev, false);
1162
1163 while (!list_empty(&odev->users.list)) {
1164 dep = list_first_entry(&odev->users.list, struct device_user, list.list);
1165 device_release(dep);
1166 if (!dep->dev)
1167 continue;
1168
1169 safe_list_del(&dep->list);
1170 __device_add_user(dep, dev);
1171 }
1172 __devlock--;
1173
1174 device_free(odev);
1175 }
1176
1177 void
1178 device_reset_config(void)
1179 {
1180 struct device *dev;
1181
1182 avl_for_each_element(&devices, dev, avl)
1183 dev->current_config = false;
1184 }
1185
1186 void
1187 device_reset_old(void)
1188 {
1189 struct device *dev, *tmp, *ndev;
1190
1191 avl_for_each_element_safe(&devices, dev, avl, tmp) {
1192 if (dev->current_config || dev->default_config)
1193 continue;
1194
1195 if (dev->type != &simple_device_type)
1196 continue;
1197
1198 ndev = device_create_default(dev->ifname, dev->external);
1199 if (!ndev)
1200 continue;
1201
1202 device_replace(ndev, dev);
1203 }
1204 }
1205
1206 struct device *
1207 device_create(const char *name, struct device_type *type,
1208 struct blob_attr *config)
1209 {
1210 struct device *odev = NULL, *dev;
1211 enum dev_change_type change;
1212
1213 odev = device_find(name);
1214 if (odev) {
1215 odev->current_config = true;
1216 change = device_apply_config(odev, type, config);
1217 switch (change) {
1218 case DEV_CONFIG_RECREATE:
1219 D(DEVICE, "Device '%s': recreate device\n", odev->ifname);
1220 device_delete(odev);
1221 break;
1222 default:
1223 return odev;
1224 }
1225 } else
1226 D(DEVICE, "Create new device '%s' (%s)\n", name, type->name);
1227
1228 config = blob_memdup(config);
1229 if (!config)
1230 return NULL;
1231
1232 dev = type->create(name, type, config);
1233 if (!dev)
1234 return NULL;
1235
1236 dev->current_config = true;
1237 dev->config = config;
1238 if (odev)
1239 device_replace(dev, odev);
1240
1241 if (!config_init && dev->config_pending) {
1242 type->config_init(dev);
1243 dev->config_pending = false;
1244 }
1245
1246 device_check_state(dev);
1247
1248 return dev;
1249 }
1250
1251 void
1252 device_dump_status(struct blob_buf *b, struct device *dev)
1253 {
1254 struct device_settings st;
1255 void *c, *s;
1256
1257 if (!dev) {
1258 avl_for_each_element(&devices, dev, avl) {
1259 if (!dev->present)
1260 continue;
1261 c = blobmsg_open_table(b, dev->ifname);
1262 device_dump_status(b, dev);
1263 blobmsg_close_table(b, c);
1264 }
1265
1266 return;
1267 }
1268
1269 blobmsg_add_u8(b, "external", dev->external);
1270 blobmsg_add_u8(b, "present", dev->present);
1271 blobmsg_add_string(b, "type", dev->type->name);
1272
1273 if (!dev->present)
1274 return;
1275
1276 blobmsg_add_u8(b, "up", !!dev->active);
1277 blobmsg_add_u8(b, "carrier", !!dev->link_active);
1278 blobmsg_add_u8(b, "auth_status", !!dev->auth_status);
1279
1280 if (dev->type->dump_info)
1281 dev->type->dump_info(dev, b);
1282 else
1283 system_if_dump_info(dev, b);
1284
1285 if (dev->active) {
1286 device_merge_settings(dev, &st);
1287 if (st.flags & DEV_OPT_MTU)
1288 blobmsg_add_u32(b, "mtu", st.mtu);
1289 if (st.flags & DEV_OPT_MTU6)
1290 blobmsg_add_u32(b, "mtu6", st.mtu6);
1291 if (st.flags & DEV_OPT_MACADDR)
1292 blobmsg_add_string(b, "macaddr", format_macaddr(st.macaddr));
1293 if (st.flags & DEV_OPT_TXQUEUELEN)
1294 blobmsg_add_u32(b, "txqueuelen", st.txqueuelen);
1295 if (st.flags & DEV_OPT_IPV6)
1296 blobmsg_add_u8(b, "ipv6", st.ipv6);
1297 if (st.flags & DEV_OPT_IP6SEGMENTROUTING)
1298 blobmsg_add_u8(b, "ip6segmentrouting", st.ip6segmentrouting);
1299 if (st.flags & DEV_OPT_PROMISC)
1300 blobmsg_add_u8(b, "promisc", st.promisc);
1301 if (st.flags & DEV_OPT_RPFILTER)
1302 blobmsg_add_u32(b, "rpfilter", st.rpfilter);
1303 if (st.flags & DEV_OPT_ACCEPTLOCAL)
1304 blobmsg_add_u8(b, "acceptlocal", st.acceptlocal);
1305 if (st.flags & DEV_OPT_IGMPVERSION)
1306 blobmsg_add_u32(b, "igmpversion", st.igmpversion);
1307 if (st.flags & DEV_OPT_MLDVERSION)
1308 blobmsg_add_u32(b, "mldversion", st.mldversion);
1309 if (st.flags & DEV_OPT_NEIGHREACHABLETIME) {
1310 blobmsg_add_u32(b, "neigh4reachabletime", st.neigh4reachabletime);
1311 blobmsg_add_u32(b, "neigh6reachabletime", st.neigh6reachabletime);
1312 }
1313 if (st.flags & DEV_OPT_NEIGHGCSTALETIME) {
1314 blobmsg_add_u32(b, "neigh4gcstaletime", st.neigh4gcstaletime);
1315 blobmsg_add_u32(b, "neigh6gcstaletime", st.neigh6gcstaletime);
1316 }
1317 if (st.flags & DEV_OPT_NEIGHLOCKTIME)
1318 blobmsg_add_u32(b, "neigh4locktime", st.neigh4locktime);
1319 if (st.flags & DEV_OPT_DADTRANSMITS)
1320 blobmsg_add_u32(b, "dadtransmits", st.dadtransmits);
1321 if (st.flags & DEV_OPT_MULTICAST_TO_UNICAST)
1322 blobmsg_add_u8(b, "multicast_to_unicast", st.multicast_to_unicast);
1323 if (st.flags & DEV_OPT_MULTICAST_ROUTER)
1324 blobmsg_add_u32(b, "multicast_router", st.multicast_router);
1325 if (st.flags & DEV_OPT_MULTICAST_FAST_LEAVE)
1326 blobmsg_add_u8(b, "multicast_fast_leave", st.multicast_fast_leave);
1327 if (st.flags & DEV_OPT_MULTICAST)
1328 blobmsg_add_u8(b, "multicast", st.multicast);
1329 if (st.flags & DEV_OPT_LEARNING)
1330 blobmsg_add_u8(b, "learning", st.learning);
1331 if (st.flags & DEV_OPT_UNICAST_FLOOD)
1332 blobmsg_add_u8(b, "unicast_flood", st.unicast_flood);
1333 if (st.flags & DEV_OPT_SENDREDIRECTS)
1334 blobmsg_add_u8(b, "sendredirects", st.sendredirects);
1335 if (st.flags & DEV_OPT_DROP_V4_UNICAST_IN_L2_MULTICAST)
1336 blobmsg_add_u8(b, "drop_v4_unicast_in_l2_multicast", st.drop_v4_unicast_in_l2_multicast);
1337 if (st.flags & DEV_OPT_DROP_V6_UNICAST_IN_L2_MULTICAST)
1338 blobmsg_add_u8(b, "drop_v6_unicast_in_l2_multicast", st.drop_v6_unicast_in_l2_multicast);
1339 if (st.flags & DEV_OPT_DROP_GRATUITOUS_ARP)
1340 blobmsg_add_u8(b, "drop_gratuitous_arp", st.drop_gratuitous_arp);
1341 if (st.flags & DEV_OPT_DROP_UNSOLICITED_NA)
1342 blobmsg_add_u8(b, "drop_unsolicited_na", st.drop_unsolicited_na);
1343 if (st.flags & DEV_OPT_ARP_ACCEPT)
1344 blobmsg_add_u8(b, "arp_accept", st.arp_accept);
1345 if (st.flags & DEV_OPT_AUTH)
1346 blobmsg_add_u8(b, "auth", st.auth);
1347 }
1348
1349 s = blobmsg_open_table(b, "statistics");
1350 if (dev->type->dump_stats)
1351 dev->type->dump_stats(dev, b);
1352 else
1353 system_if_dump_stats(dev, b);
1354 blobmsg_close_table(b, s);
1355 }
1356
1357 static void __init simple_device_type_init(void)
1358 {
1359 device_type_add(&simple_device_type);
1360 }
1361
1362 void device_hotplug_event(const char *name, bool add)
1363 {
1364 struct device *dev;
1365
1366 wireless_device_hotplug_event(name, add);
1367
1368 dev = device_find(name);
1369 if (!dev || dev->type != &simple_device_type)
1370 return;
1371
1372 device_set_present(dev, add);
1373 }