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)", 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_attr(device_attr_list.params, __DEV_ATTR_MAX, tb_dev, attr); 173 blobmsg_parse_attr(veth_attrs, __VETH_ATTR_MAX, tb_mv, attr); 174 175 device_init_settings(dev, tb_dev); 176 veth_apply_settings(veth, tb_mv); 177 178 if (veth->config_data) { 179 struct blob_attr *otb_dev[__DEV_ATTR_MAX]; 180 struct blob_attr *otb_mv[__VETH_ATTR_MAX]; 181 182 blobmsg_parse_attr(device_attr_list.params, __DEV_ATTR_MAX, otb_dev, 183 veth->config_data); 184 185 if (uci_blob_diff(tb_dev, otb_dev, &device_attr_list, NULL)) 186 ret = DEV_CONFIG_RESTART; 187 188 blobmsg_parse_attr(veth_attrs, __VETH_ATTR_MAX, otb_mv, 189 veth->config_data); 190 191 if (uci_blob_diff(tb_mv, otb_mv, &veth_attr_list, NULL)) 192 ret = DEV_CONFIG_RESTART; 193 194 veth_config_init(dev); 195 } 196 197 free(veth->config_data); 198 veth->config_data = attr; 199 return ret; 200 } 201 202 static struct device * 203 veth_create(const char *name, struct device_type *devtype, 204 struct blob_attr *attr) 205 { 206 struct veth *veth; 207 struct device *dev = NULL; 208 209 veth = calloc(1, sizeof(*veth)); 210 if (!veth) 211 return NULL; 212 213 dev = &veth->dev; 214 if (device_init(dev, devtype, name) < 0) { 215 device_cleanup(dev); 216 free(veth); 217 return NULL; 218 } 219 220 dev->config_pending = true; 221 222 veth->set_state = dev->set_state; 223 dev->set_state = veth_set_state; 224 225 dev->hotplug_ops = NULL; 226 227 veth_reload(dev, attr); 228 229 return dev; 230 } 231 232 static struct device_type veth_device_type = { 233 .name = "veth", 234 .config_params = &veth_attr_list, 235 .create = veth_create, 236 .config_init = veth_config_init, 237 .reload = veth_reload, 238 .free = veth_free, 239 .dump_info = veth_dump_info, 240 }; 241 242 static void __init veth_device_type_init(void) 243 { 244 device_type_add(&veth_device_type); 245 } 246
This page was automatically generated by LXR 0.3.1. • OpenWrt