Home | History | Annotate | Download | only in ap
      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