2 * netifd - network interface daemon
3 * Copyright (C) 2012 Felix Fietkau <nbd@openwrt.org>
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
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.
23 struct device_user dep
;
25 device_state_cb set_state
;
29 static void free_vlan_if(struct device
*iface
)
31 struct vlan_device
*vldev
;
33 vldev
= container_of(iface
, struct vlan_device
, dev
);
34 device_remove_user(&vldev
->dep
);
35 device_cleanup(&vldev
->dev
);
39 static int vlan_set_device_state(struct device
*dev
, bool up
)
41 struct vlan_device
*vldev
;
44 vldev
= container_of(dev
, struct vlan_device
, dev
);
46 vldev
->set_state(dev
, false);
48 device_release(&vldev
->dep
);
52 ret
= device_claim(&vldev
->dep
);
56 system_vlan_add(vldev
->dep
.dev
, vldev
->id
);
57 ret
= vldev
->set_state(dev
, true);
59 device_release(&vldev
->dep
);
64 static int vlan_dev_set_name(struct vlan_device
*vldev
, struct device
*dev
)
68 name
= alloca(strlen(dev
->ifname
) + sizeof(".2147483647\0"));
69 vldev
->dev
.hidden
= dev
->hidden
;
70 sprintf(name
, "%s.%d", dev
->ifname
, vldev
->id
);
72 return device_set_ifname(&vldev
->dev
, name
);
75 static void vlan_dev_cb(struct device_user
*dep
, enum device_event ev
)
77 struct vlan_device
*vldev
;
79 vldev
= container_of(dep
, struct vlan_device
, dep
);
82 device_set_present(&vldev
->dev
, true);
84 case DEV_EVENT_REMOVE
:
85 device_set_present(&vldev
->dev
, false);
87 case DEV_EVENT_UPDATE_IFNAME
:
88 if (vlan_dev_set_name(vldev
, dep
->dev
) < 0)
89 free_vlan_if(&vldev
->dev
);
91 case DEV_EVENT_TOPO_CHANGE
:
92 /* Propagate topo changes */
93 device_broadcast_event(&vldev
->dev
, DEV_EVENT_TOPO_CHANGE
);
100 static struct device
*get_vlan_device(struct device
*dev
, int id
, bool create
)
102 static struct device_type vlan_type
= {
104 .config_params
= &device_attr_list
,
105 .free
= free_vlan_if
,
107 struct vlan_device
*vldev
;
108 struct device_user
*dep
;
110 /* look for an existing interface before creating a new one */
111 list_for_each_entry(dep
, &dev
->users
.list
, list
.list
) {
112 if (dep
->cb
!= vlan_dev_cb
)
115 vldev
= container_of(dep
, struct vlan_device
, dep
);
125 D(DEVICE
, "Create vlan device '%s.%d'\n", dev
->ifname
, id
);
127 vldev
= calloc(1, sizeof(*vldev
));
133 if (device_init(&vldev
->dev
, &vlan_type
, NULL
) < 0)
136 if (vlan_dev_set_name(vldev
, dev
) < 0)
139 vldev
->dev
.default_config
= true;
141 vldev
->set_state
= vldev
->dev
.set_state
;
142 vldev
->dev
.set_state
= vlan_set_device_state
;
144 vldev
->dep
.cb
= vlan_dev_cb
;
145 device_add_user(&vldev
->dep
, dev
);
150 device_cleanup(&vldev
->dev
);
155 static char *split_vlan(char *s
)
168 struct device
*get_vlan_device_chain(const char *ifname
, bool create
)
170 struct device
*dev
= NULL
;
171 char *buf
, *s
, *next
, *err
= NULL
;
174 buf
= strdup(ifname
);
179 dev
= device_get(buf
, create
);
184 next
= split_vlan(s
);
185 id
= strtoul(s
, &err
, 10);
189 dev
= get_vlan_device(dev
, id
, create
);