1252190Srpaulo/* 2252190Srpaulo * hostapd / VLAN netlink api 3252190Srpaulo * Copyright (c) 2012, Michael Braun <michael-dev@fami-braun.de> 4252190Srpaulo * 5252190Srpaulo * This software may be distributed under the terms of the BSD license. 6252190Srpaulo * See README for more details. 7252190Srpaulo */ 8252190Srpaulo 9252190Srpaulo#include "utils/includes.h" 10252190Srpaulo#include <netlink/route/link.h> 11252190Srpaulo#include <netlink/route/link/vlan.h> 12252190Srpaulo 13252190Srpaulo#include "utils/common.h" 14252190Srpaulo#include "vlan_util.h" 15252190Srpaulo 16252190Srpaulo/* 17252190Srpaulo * Add a vlan interface with name 'vlan_if_name', VLAN ID 'vid' and 18252190Srpaulo * tagged interface 'if_name'. 19252190Srpaulo * 20252190Srpaulo * returns -1 on error 21252190Srpaulo * returns 1 if the interface already exists 22252190Srpaulo * returns 0 otherwise 23252190Srpaulo*/ 24252190Srpauloint vlan_add(const char *if_name, int vid, const char *vlan_if_name) 25252190Srpaulo{ 26289549Srpaulo int err, ret = -1; 27252190Srpaulo struct nl_sock *handle = NULL; 28252190Srpaulo struct rtnl_link *rlink = NULL; 29252190Srpaulo int if_idx = 0; 30252190Srpaulo 31252190Srpaulo wpa_printf(MSG_DEBUG, "VLAN: vlan_add(if_name=%s, vid=%d, " 32252190Srpaulo "vlan_if_name=%s)", if_name, vid, vlan_if_name); 33252190Srpaulo 34252190Srpaulo if ((os_strlen(if_name) + 1) > IFNAMSIZ) { 35252190Srpaulo wpa_printf(MSG_ERROR, "VLAN: Interface name too long: '%s'", 36252190Srpaulo if_name); 37252190Srpaulo return -1; 38252190Srpaulo } 39252190Srpaulo 40252190Srpaulo if ((os_strlen(vlan_if_name) + 1) > IFNAMSIZ) { 41252190Srpaulo wpa_printf(MSG_ERROR, "VLAN: Interface name too long: '%s'", 42252190Srpaulo vlan_if_name); 43252190Srpaulo return -1; 44252190Srpaulo } 45252190Srpaulo 46252190Srpaulo handle = nl_socket_alloc(); 47252190Srpaulo if (!handle) { 48252190Srpaulo wpa_printf(MSG_ERROR, "VLAN: failed to open netlink socket"); 49252190Srpaulo goto vlan_add_error; 50252190Srpaulo } 51252190Srpaulo 52289549Srpaulo err = nl_connect(handle, NETLINK_ROUTE); 53289549Srpaulo if (err < 0) { 54289549Srpaulo wpa_printf(MSG_ERROR, "VLAN: failed to connect to netlink: %s", 55289549Srpaulo nl_geterror(err)); 56252190Srpaulo goto vlan_add_error; 57252190Srpaulo } 58252190Srpaulo 59337817Scy err = rtnl_link_get_kernel(handle, 0, if_name, &rlink); 60289549Srpaulo if (err < 0) { 61252190Srpaulo /* link does not exist */ 62252190Srpaulo wpa_printf(MSG_ERROR, "VLAN: interface %s does not exist", 63252190Srpaulo if_name); 64252190Srpaulo goto vlan_add_error; 65252190Srpaulo } 66337817Scy if_idx = rtnl_link_get_ifindex(rlink); 67337817Scy rtnl_link_put(rlink); 68337817Scy rlink = NULL; 69252190Srpaulo 70337817Scy err = rtnl_link_get_kernel(handle, 0, vlan_if_name, &rlink); 71337817Scy if (err >= 0) { 72252190Srpaulo /* link does exist */ 73252190Srpaulo rtnl_link_put(rlink); 74252190Srpaulo rlink = NULL; 75252190Srpaulo wpa_printf(MSG_ERROR, "VLAN: interface %s already exists", 76252190Srpaulo vlan_if_name); 77252190Srpaulo ret = 1; 78252190Srpaulo goto vlan_add_error; 79252190Srpaulo } 80252190Srpaulo 81252190Srpaulo rlink = rtnl_link_alloc(); 82252190Srpaulo if (!rlink) { 83252190Srpaulo wpa_printf(MSG_ERROR, "VLAN: failed to allocate new link"); 84252190Srpaulo goto vlan_add_error; 85252190Srpaulo } 86252190Srpaulo 87289549Srpaulo err = rtnl_link_set_type(rlink, "vlan"); 88289549Srpaulo if (err < 0) { 89289549Srpaulo wpa_printf(MSG_ERROR, "VLAN: failed to set link type: %s", 90289549Srpaulo nl_geterror(err)); 91252190Srpaulo goto vlan_add_error; 92252190Srpaulo } 93252190Srpaulo 94252190Srpaulo rtnl_link_set_link(rlink, if_idx); 95252190Srpaulo rtnl_link_set_name(rlink, vlan_if_name); 96252190Srpaulo 97289549Srpaulo err = rtnl_link_vlan_set_id(rlink, vid); 98289549Srpaulo if (err < 0) { 99289549Srpaulo wpa_printf(MSG_ERROR, "VLAN: failed to set link vlan id: %s", 100289549Srpaulo nl_geterror(err)); 101252190Srpaulo goto vlan_add_error; 102252190Srpaulo } 103252190Srpaulo 104289549Srpaulo err = rtnl_link_add(handle, rlink, NLM_F_CREATE); 105289549Srpaulo if (err < 0) { 106252190Srpaulo wpa_printf(MSG_ERROR, "VLAN: failed to create link %s for " 107289549Srpaulo "vlan %d on %s (%d): %s", 108289549Srpaulo vlan_if_name, vid, if_name, if_idx, 109289549Srpaulo nl_geterror(err)); 110252190Srpaulo goto vlan_add_error; 111252190Srpaulo } 112252190Srpaulo 113252190Srpaulo ret = 0; 114252190Srpaulo 115252190Srpaulovlan_add_error: 116252190Srpaulo if (rlink) 117252190Srpaulo rtnl_link_put(rlink); 118252190Srpaulo if (handle) 119252190Srpaulo nl_socket_free(handle); 120252190Srpaulo return ret; 121252190Srpaulo} 122252190Srpaulo 123252190Srpaulo 124252190Srpauloint vlan_rem(const char *if_name) 125252190Srpaulo{ 126289549Srpaulo int err, ret = -1; 127252190Srpaulo struct nl_sock *handle = NULL; 128252190Srpaulo struct rtnl_link *rlink = NULL; 129252190Srpaulo 130252190Srpaulo wpa_printf(MSG_DEBUG, "VLAN: vlan_rem(if_name=%s)", if_name); 131252190Srpaulo 132252190Srpaulo handle = nl_socket_alloc(); 133252190Srpaulo if (!handle) { 134252190Srpaulo wpa_printf(MSG_ERROR, "VLAN: failed to open netlink socket"); 135252190Srpaulo goto vlan_rem_error; 136252190Srpaulo } 137252190Srpaulo 138289549Srpaulo err = nl_connect(handle, NETLINK_ROUTE); 139289549Srpaulo if (err < 0) { 140289549Srpaulo wpa_printf(MSG_ERROR, "VLAN: failed to connect to netlink: %s", 141289549Srpaulo nl_geterror(err)); 142252190Srpaulo goto vlan_rem_error; 143252190Srpaulo } 144252190Srpaulo 145337817Scy err = rtnl_link_get_kernel(handle, 0, if_name, &rlink); 146289549Srpaulo if (err < 0) { 147252190Srpaulo /* link does not exist */ 148252190Srpaulo wpa_printf(MSG_ERROR, "VLAN: interface %s does not exists", 149252190Srpaulo if_name); 150252190Srpaulo goto vlan_rem_error; 151252190Srpaulo } 152252190Srpaulo 153289549Srpaulo err = rtnl_link_delete(handle, rlink); 154289549Srpaulo if (err < 0) { 155289549Srpaulo wpa_printf(MSG_ERROR, "VLAN: failed to remove link %s: %s", 156289549Srpaulo if_name, nl_geterror(err)); 157252190Srpaulo goto vlan_rem_error; 158252190Srpaulo } 159252190Srpaulo 160252190Srpaulo ret = 0; 161252190Srpaulo 162252190Srpaulovlan_rem_error: 163252190Srpaulo if (rlink) 164252190Srpaulo rtnl_link_put(rlink); 165252190Srpaulo if (handle) 166252190Srpaulo nl_socket_free(handle); 167252190Srpaulo return ret; 168252190Srpaulo} 169337817Scy 170337817Scy 171337817Scyint vlan_set_name_type(unsigned int name_type) 172337817Scy{ 173337817Scy return 0; 174337817Scy} 175