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@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