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