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.
21 static struct avl_tree aliases
;
26 struct device_user dep
;
31 static const struct device_type alias_device_type
;
34 alias_device_set_state(struct device
*dev
, bool state
)
36 struct alias_device
*alias
;
38 alias
= container_of(dev
, struct alias_device
, dev
);
43 return device_claim(&alias
->dep
);
45 device_release(&alias
->dep
);
47 device_remove_user(&alias
->dep
);
51 static struct device
*
52 alias_device_create(const char *name
, struct blob_attr
*attr
)
54 struct alias_device
*alias
;
56 alias
= calloc(1, sizeof(*alias
) + strlen(name
) + 1);
57 strcpy(alias
->name
, name
);
58 alias
->dev
.set_state
= alias_device_set_state
;
59 alias
->dev
.hidden
= true;
60 device_init_virtual(&alias
->dev
, &alias_device_type
, NULL
);
61 alias
->avl
.key
= alias
->name
;
62 avl_insert(&aliases
, &alias
->avl
);
67 static void alias_device_free(struct device
*dev
)
69 struct alias_device
*alias
;
71 alias
= container_of(dev
, struct alias_device
, dev
);
72 avl_delete(&aliases
, &alias
->avl
);
76 static const struct device_type alias_device_type
= {
77 .name
= "Network alias",
78 .create
= alias_device_create
,
79 .free
= alias_device_free
,
83 alias_notify_device(const char *name
, struct device
*dev
)
85 struct alias_device
*alias
;
89 alias
= avl_find_element(&aliases
, name
, alias
, avl
);
93 alias
->cleanup
= !dev
;
95 if (dev
!= alias
->dep
.dev
) {
96 device_remove_user(&alias
->dep
);
97 strcpy(alias
->dev
.ifname
, dev
->ifname
);
98 device_add_user(&alias
->dep
, dev
);
99 alias
->dev
.hidden
= false;
100 device_broadcast_event(&alias
->dev
, DEV_EVENT_UPDATE_IFNAME
);
104 device_set_present(&alias
->dev
, !!dev
);
106 if (!dev
&& alias
->dep
.dev
&& !alias
->dep
.dev
->active
) {
107 device_remove_user(&alias
->dep
);
108 alias
->dev
.hidden
= true;
109 alias
->dev
.ifname
[0] = 0;
110 device_broadcast_event(&alias
->dev
, DEV_EVENT_UPDATE_IFNAME
);
117 device_alias_get(const char *name
)
119 struct alias_device
*alias
;
121 alias
= avl_find_element(&aliases
, name
, alias
, avl
);
125 return alias_device_create(name
, NULL
);
128 static void __init
alias_init(void)
130 avl_init(&aliases
, avl_strcmp
, false, NULL
);