summaryrefslogtreecommitdiffhomepage
path: root/bridge.c
diff options
context:
space:
mode:
authorFelix Fietkau <nbd@openwrt.org>2012-03-04 01:14:26 +0100
committerFelix Fietkau <nbd@openwrt.org>2012-03-04 01:14:26 +0100
commite8ae4f0fb1470af28fe10fb6dbcd27ce97ea7f03 (patch)
tree54c9e96d08f39f734977dd9ed1f37deca270ecd2 /bridge.c
parent84ff4cd5f8f4bca062e2c9fa8690433c492567a8 (diff)
bridge: fix member list handling
Diffstat (limited to 'bridge.c')
-rw-r--r--bridge.c27
1 files changed, 19 insertions, 8 deletions
diff --git a/bridge.c b/bridge.c
index 1ffc6b1..f2c73b0 100644
--- a/bridge.c
+++ b/bridge.c
@@ -76,6 +76,7 @@ struct bridge_member {
struct bridge_state *bst;
struct device_user dev;
bool present;
+ char name[];
};
static int
@@ -232,17 +233,14 @@ static struct bridge_member *
bridge_create_member(struct bridge_state *bst, struct device *dev, bool hotplug)
{
struct bridge_member *bm;
- char *name;
bm = calloc(1, sizeof(*bm) + strlen(dev->ifname) + 1);
bm->bst = bst;
bm->dev.cb = bridge_member_cb;
bm->dev.hotplug = hotplug;
- name = (char *) (bm + 1);
- strcpy(name, dev->ifname);
- vlist_add(&bst->members, &bm->node, name);
-
- device_add_user(&bm->dev, dev);
+ strcpy(bm->name, dev->ifname);
+ bm->dev.dev = dev;
+ vlist_add(&bst->members, &bm->node, bm->name);
return bm;
}
@@ -252,9 +250,21 @@ bridge_member_update(struct vlist_tree *tree, struct vlist_node *node_new,
struct vlist_node *node_old)
{
struct bridge_member *bm;
+ struct device *dev;
+
+ if (node_new) {
+ bm = container_of(node_new, struct bridge_member, node);
+
+ if (node_old) {
+ free(bm);
+ return;
+ }
+
+ dev = bm->dev.dev;
+ bm->dev.dev = NULL;
+ device_add_user(&bm->dev, dev);
+ }
- if (node_new && node_old)
- return;
if (node_old) {
bm = container_of(node_old, struct bridge_member, node);
@@ -431,6 +441,7 @@ bridge_create(const char *name, struct blob_attr *attr)
dev->hotplug_ops = &bridge_ops;
vlist_init(&bst->members, avl_strcmp, bridge_member_update);
+ bst->members.keep_old = true;
return dev;
}