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