• source navigation  • diff markup  • identifier search  • freetext search  • 

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

This page was automatically generated by LXR 0.3.1.  •  OpenWrt