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 if (mvdev->parent.dev) 143 blobmsg_add_string(b, "parent", mvdev->parent.dev->ifname); 144 system_if_dump_info(dev, b); 145 } 146 147 static void 148 macvlan_config_init(struct device *dev) 149 { 150 struct macvlan_device *mvdev; 151 struct device *basedev = NULL; 152 153 mvdev = container_of(dev, struct macvlan_device, dev); 154 if (mvdev->ifname) 155 basedev = device_get(blobmsg_data(mvdev->ifname), true); 156 157 device_add_user(&mvdev->parent, basedev); 158 } 159 160 static void 161 macvlan_apply_settings(struct macvlan_device *mvdev, struct blob_attr **tb) 162 { 163 struct macvlan_config *cfg = &mvdev->config; 164 struct blob_attr *cur; 165 struct ether_addr *ea; 166 167 cfg->flags = 0; 168 cfg->mode = NULL; 169 170 if ((cur = tb[MACVLAN_ATTR_MACADDR])) { 171 ea = ether_aton(blobmsg_data(cur)); 172 if (ea) { 173 memcpy(cfg->macaddr, ea, 6); 174 cfg->flags |= MACVLAN_OPT_MACADDR; 175 } 176 } 177 178 if ((cur = tb[MACVLAN_ATTR_MODE])) 179 cfg->mode = blobmsg_data(cur); 180 } 181 182 static enum dev_change_type 183 macvlan_reload(struct device *dev, struct blob_attr *attr, 184 struct blob_attr **tb_dev) 185 { 186 struct blob_attr *tb_mv[__MACVLAN_ATTR_MAX]; 187 enum dev_change_type ret = DEV_CONFIG_APPLIED; 188 struct macvlan_device *mvdev; 189 190 mvdev = container_of(dev, struct macvlan_device, dev); 191 attr = blob_memdup(attr); 192 193 blobmsg_parse_attr(macvlan_attrs, __MACVLAN_ATTR_MAX, tb_mv, attr); 194 195 macvlan_apply_settings(mvdev, tb_mv); 196 mvdev->ifname = tb_mv[MACVLAN_ATTR_IFNAME]; 197 198 if (mvdev->config_data) { 199 struct blob_attr *otb_mv[__MACVLAN_ATTR_MAX]; 200 201 blobmsg_parse_attr(macvlan_attrs, __MACVLAN_ATTR_MAX, otb_mv, 202 mvdev->config_data); 203 204 if (uci_blob_diff(tb_mv, otb_mv, &macvlan_attr_list, NULL)) 205 ret = DEV_CONFIG_RESTART; 206 207 macvlan_config_init(dev); 208 } 209 210 free(mvdev->config_data); 211 mvdev->config_data = attr; 212 return ret; 213 } 214 215 static struct device * 216 macvlan_create(const char *name, struct device_type *devtype, 217 struct blob_attr *attr) 218 { 219 struct macvlan_device *mvdev; 220 struct device *dev = NULL; 221 222 mvdev = calloc(1, sizeof(*mvdev)); 223 if (!mvdev) 224 return NULL; 225 226 dev = &mvdev->dev; 227 if (device_init(dev, devtype, name) < 0) { 228 device_cleanup(dev); 229 free(mvdev); 230 return NULL; 231 } 232 233 dev->config_pending = true; 234 235 mvdev->set_state = dev->set_state; 236 dev->set_state = macvlan_set_state; 237 238 dev->hotplug_ops = NULL; 239 mvdev->parent.cb = macvlan_base_cb; 240 241 device_init_config(dev, attr); 242 243 return dev; 244 } 245 246 static struct device_type macvlan_device_type = { 247 .name = "macvlan", 248 .config_params = &macvlan_attr_list, 249 .create = macvlan_create, 250 .config_init = macvlan_config_init, 251 .reload = macvlan_reload, 252 .free = macvlan_free, 253 .dump_info = macvlan_dump_info, 254 }; 255 256 static void __init macvlan_device_type_init(void) 257 { 258 device_type_add(&macvlan_device_type); 259 } 260
This page was automatically generated by LXR 0.3.1. • OpenWrt