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