scripts/netifd-wireless.sh: add support for specifying the operating band
[project/netifd.git] / veth.c
1 /*
2 * netifd - network interface daemon
3 * Copyright (C) 2012 Felix Fietkau <nbd@openwrt.org>
4 * Copyright (C) 2013 Jo-Philipp Wich <jow@openwrt.org>
5 * Copyright (C) 2017 Matthias Schiffer <mschiffer@universe-factory.net>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2
9 * as published by the Free Software Foundation
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 */
16 #include <string.h>
17 #include <stdlib.h>
18 #include <stdio.h>
19 #include <assert.h>
20 #include <errno.h>
21
22 #include "netifd.h"
23 #include "device.h"
24 #include "interface.h"
25 #include "system.h"
26
27 enum {
28 VETH_ATTR_MACADDR,
29 VETH_ATTR_PEER_NAME,
30 VETH_ATTR_PEER_MACADDR,
31 __VETH_ATTR_MAX
32 };
33
34 static const struct blobmsg_policy veth_attrs[__VETH_ATTR_MAX] = {
35 [VETH_ATTR_MACADDR] = { "macaddr", BLOBMSG_TYPE_STRING },
36 [VETH_ATTR_PEER_NAME] = { "peer_name", BLOBMSG_TYPE_STRING },
37 [VETH_ATTR_PEER_MACADDR] = { "peer_macaddr", BLOBMSG_TYPE_STRING },
38 };
39
40 static const struct uci_blob_param_list veth_attr_list = {
41 .n_params = __VETH_ATTR_MAX,
42 .params = veth_attrs,
43
44 .n_next = 1,
45 .next = { &device_attr_list },
46 };
47
48 struct veth {
49 struct device dev;
50
51 device_state_cb set_state;
52
53 struct blob_attr *config_data;
54 struct veth_config config;
55 };
56
57 static int
58 veth_set_down(struct veth *veth)
59 {
60 veth->set_state(&veth->dev, false);
61 system_veth_del(&veth->dev);
62
63 return 0;
64 }
65
66 static int
67 veth_set_up(struct veth *veth)
68 {
69 int ret;
70
71 ret = system_veth_add(&veth->dev, &veth->config);
72 if (ret < 0)
73 return ret;
74
75 ret = veth->set_state(&veth->dev, true);
76 if (ret)
77 goto delete;
78
79 return 0;
80
81 delete:
82 system_veth_del(&veth->dev);
83 return ret;
84 }
85
86 static int
87 veth_set_state(struct device *dev, bool up)
88 {
89 struct veth *veth;
90
91 D(SYSTEM, "veth_set_state(%s, %u)\n", dev->ifname, up);
92
93 veth = container_of(dev, struct veth, dev);
94 if (up)
95 return veth_set_up(veth);
96 else
97 return veth_set_down(veth);
98 }
99
100 static void
101 veth_free(struct device *dev)
102 {
103 struct veth *veth;
104
105 veth = container_of(dev, struct veth, dev);
106 free(veth->config_data);
107 free(veth);
108 }
109
110 static void
111 veth_dump_info(struct device *dev, struct blob_buf *b)
112 {
113 struct veth *veth;
114
115 veth = container_of(dev, struct veth, dev);
116 if (veth->config.flags & VETH_OPT_PEER_NAME)
117 blobmsg_add_string(b, "peer", veth->config.peer_name);
118 system_if_dump_info(dev, b);
119 }
120
121 static void
122 veth_config_init(struct device *dev)
123 {
124 device_set_present(dev, true);
125 }
126
127 static void
128 veth_apply_settings(struct veth *veth, struct blob_attr **tb)
129 {
130 struct veth_config *cfg = &veth->config;
131 struct blob_attr *cur;
132 struct ether_addr *ea;
133
134 cfg->flags = 0;
135
136 if ((cur = tb[VETH_ATTR_MACADDR]))
137 {
138 ea = ether_aton(blobmsg_data(cur));
139 if (ea) {
140 memcpy(cfg->macaddr, ea, 6);
141 cfg->flags |= VETH_OPT_MACADDR;
142 }
143 }
144
145 if ((cur = tb[VETH_ATTR_PEER_NAME]))
146 {
147 strncpy(cfg->peer_name, blobmsg_get_string(cur), sizeof(cfg->peer_name)-1);
148 cfg->flags |= VETH_OPT_PEER_NAME;
149 }
150
151 if ((cur = tb[VETH_ATTR_PEER_MACADDR]))
152 {
153 ea = ether_aton(blobmsg_data(cur));
154 if (ea) {
155 memcpy(cfg->peer_macaddr, ea, 6);
156 cfg->flags |= VETH_OPT_PEER_MACADDR;
157 }
158 }
159 }
160
161 static enum dev_change_type
162 veth_reload(struct device *dev, struct blob_attr *attr)
163 {
164 struct blob_attr *tb_dev[__DEV_ATTR_MAX];
165 struct blob_attr *tb_mv[__VETH_ATTR_MAX];
166 enum dev_change_type ret = DEV_CONFIG_APPLIED;
167 struct veth *veth;
168
169 veth = container_of(dev, struct veth, dev);
170 attr = blob_memdup(attr);
171
172 blobmsg_parse(device_attr_list.params, __DEV_ATTR_MAX, tb_dev,
173 blob_data(attr), blob_len(attr));
174 blobmsg_parse(veth_attrs, __VETH_ATTR_MAX, tb_mv,
175 blob_data(attr), blob_len(attr));
176
177 device_init_settings(dev, tb_dev);
178 veth_apply_settings(veth, tb_mv);
179
180 if (veth->config_data) {
181 struct blob_attr *otb_dev[__DEV_ATTR_MAX];
182 struct blob_attr *otb_mv[__VETH_ATTR_MAX];
183
184 blobmsg_parse(device_attr_list.params, __DEV_ATTR_MAX, otb_dev,
185 blob_data(veth->config_data), blob_len(veth->config_data));
186
187 if (uci_blob_diff(tb_dev, otb_dev, &device_attr_list, NULL))
188 ret = DEV_CONFIG_RESTART;
189
190 blobmsg_parse(veth_attrs, __VETH_ATTR_MAX, otb_mv,
191 blob_data(veth->config_data), blob_len(veth->config_data));
192
193 if (uci_blob_diff(tb_mv, otb_mv, &veth_attr_list, NULL))
194 ret = DEV_CONFIG_RESTART;
195
196 veth_config_init(dev);
197 }
198
199 free(veth->config_data);
200 veth->config_data = attr;
201 return ret;
202 }
203
204 static struct device *
205 veth_create(const char *name, struct device_type *devtype,
206 struct blob_attr *attr)
207 {
208 struct veth *veth;
209 struct device *dev = NULL;
210
211 veth = calloc(1, sizeof(*veth));
212 if (!veth)
213 return NULL;
214
215 dev = &veth->dev;
216 if (device_init(dev, devtype, name) < 0) {
217 device_cleanup(dev);
218 free(veth);
219 return NULL;
220 }
221
222 dev->config_pending = true;
223
224 veth->set_state = dev->set_state;
225 dev->set_state = veth_set_state;
226
227 dev->hotplug_ops = NULL;
228
229 veth_reload(dev, attr);
230
231 return dev;
232 }
233
234 static struct device_type veth_device_type = {
235 .name = "veth",
236 .config_params = &veth_attr_list,
237 .create = veth_create,
238 .config_init = veth_config_init,
239 .reload = veth_reload,
240 .free = veth_free,
241 .dump_info = veth_dump_info,
242 };
243
244 static void __init veth_device_type_init(void)
245 {
246 device_type_add(&veth_device_type);
247 }