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_attr(device_attr_list.params, __DEV_ATTR_MAX, tb_dev, attr); 193 blobmsg_parse_attr(macvlan_attrs, __MACVLAN_ATTR_MAX, tb_mv, attr); 194 195 device_init_settings(dev, tb_dev); 196 macvlan_apply_settings(mvdev, tb_mv); 197 mvdev->ifname = tb_mv[MACVLAN_ATTR_IFNAME]; 198 199 if (mvdev->config_data) { 200 struct blob_attr *otb_dev[__DEV_ATTR_MAX]; 201 struct blob_attr *otb_mv[__MACVLAN_ATTR_MAX]; 202 203 blobmsg_parse_attr(device_attr_list.params, __DEV_ATTR_MAX, otb_dev, 204 mvdev->config_data); 205 206 if (uci_blob_diff(tb_dev, otb_dev, &device_attr_list, NULL)) 207 ret = DEV_CONFIG_RESTART; 208 209 blobmsg_parse_attr(macvlan_attrs, __MACVLAN_ATTR_MAX, otb_mv, 210 mvdev->config_data); 211 212 if (uci_blob_diff(tb_mv, otb_mv, &macvlan_attr_list, NULL)) 213 ret = DEV_CONFIG_RESTART; 214 215 macvlan_config_init(dev); 216 } 217 218 free(mvdev->config_data); 219 mvdev->config_data = attr; 220 return ret; 221 } 222 223 static struct device * 224 macvlan_create(const char *name, struct device_type *devtype, 225 struct blob_attr *attr) 226 { 227 struct macvlan_device *mvdev; 228 struct device *dev = NULL; 229 230 mvdev = calloc(1, sizeof(*mvdev)); 231 if (!mvdev) 232 return NULL; 233 234 dev = &mvdev->dev; 235 if (device_init(dev, devtype, name) < 0) { 236 device_cleanup(dev); 237 free(mvdev); 238 return NULL; 239 } 240 241 dev->config_pending = true; 242 243 mvdev->set_state = dev->set_state; 244 dev->set_state = macvlan_set_state; 245 246 dev->hotplug_ops = NULL; 247 mvdev->parent.cb = macvlan_base_cb; 248 249 macvlan_reload(dev, attr); 250 251 return dev; 252 } 253 254 static struct device_type macvlan_device_type = { 255 .name = "macvlan", 256 .config_params = &macvlan_attr_list, 257 .create = macvlan_create, 258 .config_init = macvlan_config_init, 259 .reload = macvlan_reload, 260 .free = macvlan_free, 261 .dump_info = macvlan_dump_info, 262 }; 263 264 static void __init macvlan_device_type_init(void) 265 { 266 device_type_add(&macvlan_device_type); 267 } 268
This page was automatically generated by LXR 0.3.1. • OpenWrt