1 /* 2 * hostapd / VLAN netlink api 3 * Copyright (c) 2012, Michael Braun <michael-dev (at) fami-braun.de> 4 * 5 * This software may be distributed under the terms of the BSD license. 6 * See README for more details. 7 */ 8 9 #include "utils/includes.h" 10 #include <netlink/route/link.h> 11 #include <netlink/route/link/vlan.h> 12 13 #include "utils/common.h" 14 #include "vlan_util.h" 15 16 /* 17 * Add a vlan interface with name 'vlan_if_name', VLAN ID 'vid' and 18 * tagged interface 'if_name'. 19 * 20 * returns -1 on error 21 * returns 1 if the interface already exists 22 * returns 0 otherwise 23 */ 24 int vlan_add(const char *if_name, int vid, const char *vlan_if_name) 25 { 26 int err, ret = -1; 27 struct nl_sock *handle = NULL; 28 struct rtnl_link *rlink = NULL; 29 int if_idx = 0; 30 31 wpa_printf(MSG_DEBUG, "VLAN: vlan_add(if_name=%s, vid=%d, " 32 "vlan_if_name=%s)", if_name, vid, vlan_if_name); 33 34 if ((os_strlen(if_name) + 1) > IFNAMSIZ) { 35 wpa_printf(MSG_ERROR, "VLAN: Interface name too long: '%s'", 36 if_name); 37 return -1; 38 } 39 40 if ((os_strlen(vlan_if_name) + 1) > IFNAMSIZ) { 41 wpa_printf(MSG_ERROR, "VLAN: Interface name too long: '%s'", 42 vlan_if_name); 43 return -1; 44 } 45 46 handle = nl_socket_alloc(); 47 if (!handle) { 48 wpa_printf(MSG_ERROR, "VLAN: failed to open netlink socket"); 49 goto vlan_add_error; 50 } 51 52 err = nl_connect(handle, NETLINK_ROUTE); 53 if (err < 0) { 54 wpa_printf(MSG_ERROR, "VLAN: failed to connect to netlink: %s", 55 nl_geterror(err)); 56 goto vlan_add_error; 57 } 58 59 err = rtnl_link_get_kernel(handle, 0, if_name, &rlink); 60 if (err < 0) { 61 /* link does not exist */ 62 wpa_printf(MSG_ERROR, "VLAN: interface %s does not exist", 63 if_name); 64 goto vlan_add_error; 65 } 66 if_idx = rtnl_link_get_ifindex(rlink); 67 rtnl_link_put(rlink); 68 rlink = NULL; 69 70 err = rtnl_link_get_kernel(handle, 0, vlan_if_name, &rlink); 71 if (err >= 0) { 72 /* link does exist */ 73 rtnl_link_put(rlink); 74 rlink = NULL; 75 wpa_printf(MSG_ERROR, "VLAN: interface %s already exists", 76 vlan_if_name); 77 ret = 1; 78 goto vlan_add_error; 79 } 80 81 rlink = rtnl_link_alloc(); 82 if (!rlink) { 83 wpa_printf(MSG_ERROR, "VLAN: failed to allocate new link"); 84 goto vlan_add_error; 85 } 86 87 err = rtnl_link_set_type(rlink, "vlan"); 88 if (err < 0) { 89 wpa_printf(MSG_ERROR, "VLAN: failed to set link type: %s", 90 nl_geterror(err)); 91 goto vlan_add_error; 92 } 93 94 rtnl_link_set_link(rlink, if_idx); 95 rtnl_link_set_name(rlink, vlan_if_name); 96 97 err = rtnl_link_vlan_set_id(rlink, vid); 98 if (err < 0) { 99 wpa_printf(MSG_ERROR, "VLAN: failed to set link vlan id: %s", 100 nl_geterror(err)); 101 goto vlan_add_error; 102 } 103 104 err = rtnl_link_add(handle, rlink, NLM_F_CREATE); 105 if (err < 0) { 106 wpa_printf(MSG_ERROR, "VLAN: failed to create link %s for " 107 "vlan %d on %s (%d): %s", 108 vlan_if_name, vid, if_name, if_idx, 109 nl_geterror(err)); 110 goto vlan_add_error; 111 } 112 113 ret = 0; 114 115 vlan_add_error: 116 if (rlink) 117 rtnl_link_put(rlink); 118 if (handle) 119 nl_socket_free(handle); 120 return ret; 121 } 122 123 124 int vlan_rem(const char *if_name) 125 { 126 int err, ret = -1; 127 struct nl_sock *handle = NULL; 128 struct rtnl_link *rlink = NULL; 129 130 wpa_printf(MSG_DEBUG, "VLAN: vlan_rem(if_name=%s)", if_name); 131 132 handle = nl_socket_alloc(); 133 if (!handle) { 134 wpa_printf(MSG_ERROR, "VLAN: failed to open netlink socket"); 135 goto vlan_rem_error; 136 } 137 138 err = nl_connect(handle, NETLINK_ROUTE); 139 if (err < 0) { 140 wpa_printf(MSG_ERROR, "VLAN: failed to connect to netlink: %s", 141 nl_geterror(err)); 142 goto vlan_rem_error; 143 } 144 145 err = rtnl_link_get_kernel(handle, 0, if_name, &rlink); 146 if (err < 0) { 147 /* link does not exist */ 148 wpa_printf(MSG_ERROR, "VLAN: interface %s does not exists", 149 if_name); 150 goto vlan_rem_error; 151 } 152 153 err = rtnl_link_delete(handle, rlink); 154 if (err < 0) { 155 wpa_printf(MSG_ERROR, "VLAN: failed to remove link %s: %s", 156 if_name, nl_geterror(err)); 157 goto vlan_rem_error; 158 } 159 160 ret = 0; 161 162 vlan_rem_error: 163 if (rlink) 164 rtnl_link_put(rlink); 165 if (handle) 166 nl_socket_free(handle); 167 return ret; 168 } 169 170 171 int vlan_set_name_type(unsigned int name_type) 172 { 173 return 0; 174 } 175