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 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License version 2 8 * as published by the Free Software Foundation 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 */ 15 #include <string.h> 16 #include <stdlib.h> 17 #include <stdio.h> 18 #include <assert.h> 19 #include <errno.h> 20 21 #include "netifd.h" 22 #include "device.h" 23 #include "interface.h" 24 #include "system.h" 25 26 enum { 27 MACVLAN_ATTR_IFNAME, 28 MACVLAN_ATTR_MACADDR, 29 MACVLAN_ATTR_MODE, 30 __MACVLAN_ATTR_MAX 31 }; 32 33 static const struct blobmsg_policy macvlan_attrs[__MACVLAN_ATTR_MAX] = { 34 [MACVLAN_ATTR_IFNAME] = { "ifname", BLOBMSG_TYPE_STRING }, 35 [MACVLAN_ATTR_MACADDR] = { "macaddr", BLOBMSG_TYPE_STRING }, 36 [MACVLAN_ATTR_MODE] = { "mode", BLOBMSG_TYPE_STRING }, 37 }; 38 39 static const struct uci_blob_param_list macvlan_attr_list = { 40 .n_params = __MACVLAN_ATTR_MAX, 41 .params = macvlan_attrs, 42 43 .n_next = 1, 44 .next = { &device_attr_list }, 45 }; 46 47 struct macvlan_device { 48 struct device dev; 49 struct device_user parent; 50 51 device_state_cb set_state; 52 53 struct blob_attr *config_data; 54 struct blob_attr *ifname; 55 struct macvlan_config config; 56 }; 57 58 static void 59 macvlan_base_cb(struct device_user *dev, enum device_event ev) 60 { 61 struct macvlan_device *mvdev = container_of(dev, struct macvlan_device, parent); 62 63 switch (ev) { 64 case DEV_EVENT_ADD: 65 device_set_present(&mvdev->dev, true); 66 break; 67 case DEV_EVENT_REMOVE: 68 device_set_present(&mvdev->dev, false); 69 break; 70 default: 71 return; 72 } 73 } 74 75 static int 76 macvlan_set_down(struct macvlan_device *mvdev) 77 { 78 mvdev->set_state(&mvdev->dev, false); 79 system_macvlan_del(&mvdev->dev); 80 device_release(&mvdev->parent); 81 82 return 0; 83 } 84 85 static int 86 macvlan_set_up(struct macvlan_device *mvdev) 87 { 88 int ret; 89 90 ret = device_claim(&mvdev->parent); 91 if (ret < 0) 92 return ret; 93 94 ret = system_macvlan_add(&mvdev->dev, mvdev->parent.dev, &mvdev->config); 95 if (ret < 0) 96 goto release; 97 98 ret = mvdev->set_state(&mvdev->dev, true); 99 if (ret) 100 goto delete; 101 102 return 0; 103 104 delete: 105 system_macvlan_del(&mvdev->dev); 106 release: 107 device_release(&mvdev->parent); 108 return ret; 109 } 110 111 static int 112 macvlan_set_state(struct device *dev, bool up) 113 { 114 struct macvlan_device *mvdev; 115 116 D(SYSTEM, "macvlan_set_state(%s, %u)", dev->ifname, up); 117 118 mvdev = container_of(dev, struct macvlan_device, dev); 119 if (up) 120 return macvlan_set_up(mvdev); 121 else 122 return macvlan_set_down(mvdev); 123 } 124 125 static void 126 macvlan_free(struct device *dev) 127 { 128 struct macvlan_device *mvdev; 129 130 mvdev = container_of(dev, struct macvlan_device, dev); 131 device_remove_user(&mvdev->parent); 132 free(mvdev->config_data); 133 free(mvdev); 134 } 135 136 static void 137 macvlan_dump_info(struct device *dev, struct blob_buf *b) 138 { 139 struct macvlan_device *mvdev; 140 141 mvdev = container_of(dev, struct macvlan_device, dev); 142 blobmsg_add_string(b, "parent", mvdev->parent.dev->ifname); 143 system_if_dump_info(dev, b); 144 } 145 146 static void 147 macvlan_config_init(struct device *dev) 148 { 149 struct macvlan_device *mvdev; 150 struct device *basedev = NULL; 151 152 mvdev = container_of(dev, struct macvlan_device, dev); 153 if (mvdev->ifname) 154 basedev = device_get(blobmsg_data(mvdev->ifname), true); 155 156 device_add_user(&mvdev->parent, basedev); 157 } 158 159 static void 160 macvlan_apply_settings(struct macvlan_device *mvdev, struct blob_attr **tb) 161 { 162 struct macvlan_config *cfg = &mvdev->config; 163 struct blob_attr *cur; 164 struct ether_addr *ea; 165 166 cfg->flags = 0; 167 cfg->mode = NULL; 168 169 if ((cur = tb[MACVLAN_ATTR_MACADDR])) { 170 ea = ether_aton(blobmsg_data(cur)); 171 if (ea) { 172 memcpy(cfg->macaddr, ea, 6); 173 cfg->flags |= MACVLAN_OPT_MACADDR; 174 } 175 } 176 177 if ((cur = tb[MACVLAN_ATTR_MODE])) 178 cfg->mode = blobmsg_data(cur); 179 } 180 181 static enum dev_change_type 182 macvlan_reload(struct device *dev, struct blob_attr *attr) 183 { 184 struct blob_attr *tb_dev[__DEV_ATTR_MAX]; 185 struct blob_attr *tb_mv[__MACVLAN_ATTR_MAX]; 186 enum dev_change_type ret = DEV_CONFIG_APPLIED; 187 struct macvlan_device *mvdev; 188 189 mvdev = container_of(dev, struct macvlan_device, dev); 190 attr = blob_memdup(attr); 191 192 blobmsg_parse(device_attr_list.params, __DEV_ATTR_MAX, tb_dev, 193 blob_data(attr), blob_len(attr)); 194 blobmsg_parse(macvlan_attrs, __MACVLAN_ATTR_MAX, tb_mv, 195 blob_data(attr), blob_len(attr)); 196 197 device_init_settings(dev, tb_dev); 198 macvlan_apply_settings(mvdev, tb_mv); 199 mvdev->ifname = tb_mv[MACVLAN_ATTR_IFNAME]; 200 201 if (mvdev->config_data) { 202 struct blob_attr *otb_dev[__DEV_ATTR_MAX]; 203 struct blob_attr *otb_mv[__MACVLAN_ATTR_MAX]; 204 205 blobmsg_parse(device_attr_list.params, __DEV_ATTR_MAX, otb_dev, 206 blob_data(mvdev->config_data), blob_len(mvdev->config_data)); 207 208 if (uci_blob_diff(tb_dev, otb_dev, &device_attr_list, NULL)) 209 ret = DEV_CONFIG_RESTART; 210 211 blobmsg_parse(macvlan_attrs, __MACVLAN_ATTR_MAX, otb_mv, 212 blob_data(mvdev->config_data), blob_len(mvdev->config_data)); 213 214 if (uci_blob_diff(tb_mv, otb_mv, &macvlan_attr_list, NULL)) 215 ret = DEV_CONFIG_RESTART; 216 217 macvlan_config_init(dev); 218 } 219 220 free(mvdev->config_data); 221 mvdev->config_data = attr; 222 return ret; 223 } 224 225 static struct device * 226 macvlan_create(const char *name, struct device_type *devtype, 227 struct blob_attr *attr) 228 { 229 struct macvlan_device *mvdev; 230 struct device *dev = NULL; 231 232 mvdev = calloc(1, sizeof(*mvdev)); 233 if (!mvdev) 234 return NULL; 235 236 dev = &mvdev->dev; 237 if (device_init(dev, devtype, name) < 0) { 238 device_cleanup(dev); 239 free(mvdev); 240 return NULL; 241 } 242 243 dev->config_pending = true; 244 245 mvdev->set_state = dev->set_state; 246 dev->set_state = macvlan_set_state; 247 248 dev->hotplug_ops = NULL; 249 mvdev->parent.cb = macvlan_base_cb; 250 251 macvlan_reload(dev, attr); 252 253 return dev; 254 } 255 256 static struct device_type macvlan_device_type = { 257 .name = "macvlan", 258 .config_params = &macvlan_attr_list, 259 .create = macvlan_create, 260 .config_init = macvlan_config_init, 261 .reload = macvlan_reload, 262 .free = macvlan_free, 263 .dump_info = macvlan_dump_info, 264 }; 265 266 static void __init macvlan_device_type_init(void) 267 { 268 device_type_add(&macvlan_device_type); 269 } 270
This page was automatically generated by LXR 0.3.1. • OpenWrt