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(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 } 248
This page was automatically generated by LXR 0.3.1. • OpenWrt