Home | History | Annotate | Download | only in ap
      1 /*
      2  * hostapd / VLAN ioctl API
      3  * Copyright 2003, Instant802 Networks, Inc.
      4  * Copyright 2005-2006, Devicescape Software, Inc.
      5  * Copyright (c) 2009, Jouni Malinen <j (at) w1.fi>
      6  *
      7  * This software may be distributed under the terms of the BSD license.
      8  * See README for more details.
      9  */
     10 
     11 #include "utils/includes.h"
     12 #include <sys/ioctl.h>
     13 
     14 #include "utils/common.h"
     15 #include "common/linux_vlan.h"
     16 #include "vlan_util.h"
     17 
     18 
     19 int vlan_rem(const char *if_name)
     20 {
     21 	int fd;
     22 	struct vlan_ioctl_args if_request;
     23 
     24 	wpa_printf(MSG_DEBUG, "VLAN: vlan_rem(%s)", if_name);
     25 	if ((os_strlen(if_name) + 1) > sizeof(if_request.device1)) {
     26 		wpa_printf(MSG_ERROR, "VLAN: Interface name too long: '%s'",
     27 			   if_name);
     28 		return -1;
     29 	}
     30 
     31 	if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
     32 		wpa_printf(MSG_ERROR, "VLAN: %s: socket(AF_INET,SOCK_STREAM) "
     33 			   "failed: %s", __func__, strerror(errno));
     34 		return -1;
     35 	}
     36 
     37 	os_memset(&if_request, 0, sizeof(if_request));
     38 
     39 	os_strlcpy(if_request.device1, if_name, sizeof(if_request.device1));
     40 	if_request.cmd = DEL_VLAN_CMD;
     41 
     42 	if (ioctl(fd, SIOCSIFVLAN, &if_request) < 0) {
     43 		wpa_printf(MSG_ERROR, "VLAN: %s: DEL_VLAN_CMD failed for %s: "
     44 			   "%s", __func__, if_name, strerror(errno));
     45 		close(fd);
     46 		return -1;
     47 	}
     48 
     49 	close(fd);
     50 	return 0;
     51 }
     52 
     53 
     54 /*
     55 	Add a vlan interface with VLAN ID 'vid' and tagged interface
     56 	'if_name'.
     57 
     58 	returns -1 on error
     59 	returns 1 if the interface already exists
     60 	returns 0 otherwise
     61 */
     62 int vlan_add(const char *if_name, int vid, const char *vlan_if_name)
     63 {
     64 	int fd;
     65 	struct vlan_ioctl_args if_request;
     66 
     67 	wpa_printf(MSG_DEBUG, "VLAN: vlan_add(if_name=%s, vid=%d)",
     68 		   if_name, vid);
     69 	ifconfig_up(if_name);
     70 
     71 	if ((os_strlen(if_name) + 1) > sizeof(if_request.device1)) {
     72 		wpa_printf(MSG_ERROR, "VLAN: Interface name too long: '%s'",
     73 			   if_name);
     74 		return -1;
     75 	}
     76 
     77 	if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
     78 		wpa_printf(MSG_ERROR, "VLAN: %s: socket(AF_INET,SOCK_STREAM) "
     79 			   "failed: %s", __func__, strerror(errno));
     80 		return -1;
     81 	}
     82 
     83 	os_memset(&if_request, 0, sizeof(if_request));
     84 
     85 	/* Determine if a suitable vlan device already exists. */
     86 
     87 	os_snprintf(if_request.device1, sizeof(if_request.device1), "vlan%d",
     88 		    vid);
     89 
     90 	if_request.cmd = GET_VLAN_VID_CMD;
     91 
     92 	if (ioctl(fd, SIOCSIFVLAN, &if_request) == 0 &&
     93 	    if_request.u.VID == vid) {
     94 		if_request.cmd = GET_VLAN_REALDEV_NAME_CMD;
     95 
     96 		if (ioctl(fd, SIOCSIFVLAN, &if_request) == 0 &&
     97 		    os_strncmp(if_request.u.device2, if_name,
     98 			       sizeof(if_request.u.device2)) == 0) {
     99 			close(fd);
    100 			wpa_printf(MSG_DEBUG,
    101 				   "VLAN: vlan_add: if_name %s exists already",
    102 				   if_request.device1);
    103 			return 1;
    104 		}
    105 	}
    106 
    107 	/* A suitable vlan device does not already exist, add one. */
    108 
    109 	os_memset(&if_request, 0, sizeof(if_request));
    110 	os_strlcpy(if_request.device1, if_name, sizeof(if_request.device1));
    111 	if_request.u.VID = vid;
    112 	if_request.cmd = ADD_VLAN_CMD;
    113 
    114 	if (ioctl(fd, SIOCSIFVLAN, &if_request) < 0) {
    115 		wpa_printf(MSG_ERROR,
    116 			   "VLAN: %s: ADD_VLAN_CMD failed for %s: %s",
    117 			   __func__, if_request.device1, strerror(errno));
    118 		close(fd);
    119 		return -1;
    120 	}
    121 
    122 	close(fd);
    123 	return 0;
    124 }
    125 
    126 
    127 int vlan_set_name_type(unsigned int name_type)
    128 {
    129 	int fd;
    130 	struct vlan_ioctl_args if_request;
    131 
    132 	wpa_printf(MSG_DEBUG, "VLAN: vlan_set_name_type(name_type=%u)",
    133 		   name_type);
    134 	if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
    135 		wpa_printf(MSG_ERROR,
    136 			   "VLAN: %s: socket(AF_INET,SOCK_STREAM) failed: %s",
    137 			   __func__, strerror(errno));
    138 		return -1;
    139 	}
    140 
    141 	os_memset(&if_request, 0, sizeof(if_request));
    142 
    143 	if_request.u.name_type = name_type;
    144 	if_request.cmd = SET_VLAN_NAME_TYPE_CMD;
    145 	if (ioctl(fd, SIOCSIFVLAN, &if_request) < 0) {
    146 		wpa_printf(MSG_ERROR,
    147 			   "VLAN: %s: SET_VLAN_NAME_TYPE_CMD name_type=%u failed: %s",
    148 			   __func__, name_type, strerror(errno));
    149 		close(fd);
    150 		return -1;
    151 	}
    152 
    153 	close(fd);
    154 	return 0;
    155 }
    156