- ifr.ifr_flags &= ~IFF_UP;
-
- if (ioctl(fd, SIOCSIFFLAGS, &ifr) != 0) {
- wpa_printf(MSG_ERROR, "VLAN: %s: ioctl(SIOCSIFFLAGS) failed "
- "for interface %s (up=%d): %s",
- __func__, if_name, up, strerror(errno));
- close(fd);
- return -1;
- }
-
- close(fd);
- return 0;
-}
-
-
-static int ifconfig_up(const char *if_name)
-{
- wpa_printf(MSG_DEBUG, "VLAN: Set interface %s up", if_name);
- return ifconfig_helper(if_name, 1);
-}
-
-
-static int ifconfig_down(const char *if_name)
-{
- wpa_printf(MSG_DEBUG, "VLAN: Set interface %s down", if_name);
- return ifconfig_helper(if_name, 0);
-}
-
-
-/*
- * These are only available in recent linux headers (without the leading
- * underscore).
- */
-#define _GET_VLAN_REALDEV_NAME_CMD 8
-#define _GET_VLAN_VID_CMD 9
-
-/* This value should be 256 ONLY. If it is something else, then hostapd
- * might crash!, as this value has been hard-coded in 2.4.x kernel
- * bridging code.
- */
-#define MAX_BR_PORTS 256
-
-static int br_delif(const char *br_name, const char *if_name)
-{
- int fd;
- struct ifreq ifr;
- unsigned long args[2];
- int if_index;
-
- wpa_printf(MSG_DEBUG, "VLAN: br_delif(%s, %s)", br_name, if_name);
- if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
- wpa_printf(MSG_ERROR, "VLAN: %s: socket(AF_INET,SOCK_STREAM) "
- "failed: %s", __func__, strerror(errno));
- return -1;
- }
-
- if_index = if_nametoindex(if_name);
-
- if (if_index == 0) {
- wpa_printf(MSG_ERROR, "VLAN: %s: Failure determining "
- "interface index for '%s'",
- __func__, if_name);
- close(fd);
- return -1;
- }
-
- args[0] = BRCTL_DEL_IF;
- args[1] = if_index;
-
- os_strlcpy(ifr.ifr_name, br_name, sizeof(ifr.ifr_name));
- ifr.ifr_data = (__caddr_t) args;
-
- if (ioctl(fd, SIOCDEVPRIVATE, &ifr) < 0 && errno != EINVAL) {
- /* No error if interface already removed. */
- wpa_printf(MSG_ERROR, "VLAN: %s: ioctl[SIOCDEVPRIVATE,"
- "BRCTL_DEL_IF] failed for br_name=%s if_name=%s: "
- "%s", __func__, br_name, if_name, strerror(errno));
- close(fd);
- return -1;
- }
-
- close(fd);
- return 0;
-}
-
-
-/*
- Add interface 'if_name' to the bridge 'br_name'
-
- returns -1 on error
- returns 1 if the interface is already part of the bridge
- returns 0 otherwise
-*/
-static int br_addif(const char *br_name, const char *if_name)
-{
- int fd;
- struct ifreq ifr;
- unsigned long args[2];
- int if_index;
-
- wpa_printf(MSG_DEBUG, "VLAN: br_addif(%s, %s)", br_name, if_name);
- if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
- wpa_printf(MSG_ERROR, "VLAN: %s: socket(AF_INET,SOCK_STREAM) "
- "failed: %s", __func__, strerror(errno));
- return -1;
- }
-
- if_index = if_nametoindex(if_name);
-
- if (if_index == 0) {
- wpa_printf(MSG_ERROR, "VLAN: %s: Failure determining "
- "interface index for '%s'",
- __func__, if_name);
- close(fd);
- return -1;
- }
-
- args[0] = BRCTL_ADD_IF;
- args[1] = if_index;
-
- os_strlcpy(ifr.ifr_name, br_name, sizeof(ifr.ifr_name));
- ifr.ifr_data = (__caddr_t) args;
-
- if (ioctl(fd, SIOCDEVPRIVATE, &ifr) < 0) {
- if (errno == EBUSY) {
- /* The interface is already added. */
- close(fd);
- return 1;
- }
-
- wpa_printf(MSG_ERROR, "VLAN: %s: ioctl[SIOCDEVPRIVATE,"
- "BRCTL_ADD_IF] failed for br_name=%s if_name=%s: "
- "%s", __func__, br_name, if_name, strerror(errno));
- close(fd);
- return -1;
- }
-
- close(fd);
- return 0;
-}
-
-
-static int br_delbr(const char *br_name)
-{
- int fd;
- unsigned long arg[2];
-
- wpa_printf(MSG_DEBUG, "VLAN: br_delbr(%s)", br_name);
- if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
- wpa_printf(MSG_ERROR, "VLAN: %s: socket(AF_INET,SOCK_STREAM) "
- "failed: %s", __func__, strerror(errno));
- return -1;
- }
-
- arg[0] = BRCTL_DEL_BRIDGE;
- arg[1] = (unsigned long) br_name;
-
- if (ioctl(fd, SIOCGIFBR, arg) < 0 && errno != ENXIO) {
- /* No error if bridge already removed. */
- wpa_printf(MSG_ERROR, "VLAN: %s: BRCTL_DEL_BRIDGE failed for "
- "%s: %s", __func__, br_name, strerror(errno));
- close(fd);
- return -1;
- }
-
- close(fd);
- return 0;
-}
-
-
-/*
- Add a bridge with the name 'br_name'.
-
- returns -1 on error
- returns 1 if the bridge already exists
- returns 0 otherwise
-*/
-static int br_addbr(const char *br_name)
-{
- int fd;
- unsigned long arg[4];
- struct ifreq ifr;
-
- wpa_printf(MSG_DEBUG, "VLAN: br_addbr(%s)", br_name);
- if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
- wpa_printf(MSG_ERROR, "VLAN: %s: socket(AF_INET,SOCK_STREAM) "
- "failed: %s", __func__, strerror(errno));
- return -1;
- }
-
- arg[0] = BRCTL_ADD_BRIDGE;
- arg[1] = (unsigned long) br_name;
-
- if (ioctl(fd, SIOCGIFBR, arg) < 0) {
- if (errno == EEXIST) {
- /* The bridge is already added. */
- close(fd);
- return 1;
- } else {
- wpa_printf(MSG_ERROR, "VLAN: %s: BRCTL_ADD_BRIDGE "
- "failed for %s: %s",
- __func__, br_name, strerror(errno));
- close(fd);
- return -1;
- }
- }
-
- /* Decrease forwarding delay to avoid EAPOL timeouts. */
- os_memset(&ifr, 0, sizeof(ifr));
- os_strlcpy(ifr.ifr_name, br_name, IFNAMSIZ);
- arg[0] = BRCTL_SET_BRIDGE_FORWARD_DELAY;
- arg[1] = 1;
- arg[2] = 0;
- arg[3] = 0;
- ifr.ifr_data = (char *) &arg;
- if (ioctl(fd, SIOCDEVPRIVATE, &ifr) < 0) {
- wpa_printf(MSG_ERROR, "VLAN: %s: "
- "BRCTL_SET_BRIDGE_FORWARD_DELAY (1 sec) failed for "
- "%s: %s", __func__, br_name, strerror(errno));
- /* Continue anyway */
- }
-
- close(fd);
- return 0;
-}
-
-
-static int br_getnumports(const char *br_name)
-{
- int fd;
- int i;
- int port_cnt = 0;
- unsigned long arg[4];
- int ifindices[MAX_BR_PORTS];
- struct ifreq ifr;
-
- if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
- wpa_printf(MSG_ERROR, "VLAN: %s: socket(AF_INET,SOCK_STREAM) "
- "failed: %s", __func__, strerror(errno));
- return -1;
- }
-
- arg[0] = BRCTL_GET_PORT_LIST;
- arg[1] = (unsigned long) ifindices;
- arg[2] = MAX_BR_PORTS;
- arg[3] = 0;
-
- os_memset(ifindices, 0, sizeof(ifindices));
- os_strlcpy(ifr.ifr_name, br_name, sizeof(ifr.ifr_name));
- ifr.ifr_data = (__caddr_t) arg;
-
- if (ioctl(fd, SIOCDEVPRIVATE, &ifr) < 0) {
- wpa_printf(MSG_ERROR, "VLAN: %s: BRCTL_GET_PORT_LIST "
- "failed for %s: %s",
- __func__, br_name, strerror(errno));
- close(fd);
- return -1;
- }
-
- for (i = 1; i < MAX_BR_PORTS; i++) {
- if (ifindices[i] > 0) {
- port_cnt++;
- }
- }
-
- close(fd);
- return port_cnt;
-}
-
-
-static int vlan_rem(const char *if_name)
-{
- int fd;
- struct vlan_ioctl_args if_request;
-
- wpa_printf(MSG_DEBUG, "VLAN: vlan_rem(%s)", if_name);
- if ((os_strlen(if_name) + 1) > sizeof(if_request.device1)) {
- wpa_printf(MSG_ERROR, "VLAN: Interface name too long: '%s'",
- if_name);
- return -1;
- }
-
- if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
- wpa_printf(MSG_ERROR, "VLAN: %s: socket(AF_INET,SOCK_STREAM) "
- "failed: %s", __func__, strerror(errno));
- return -1;
- }
-
- os_memset(&if_request, 0, sizeof(if_request));
-
- os_strlcpy(if_request.device1, if_name, sizeof(if_request.device1));
- if_request.cmd = DEL_VLAN_CMD;
-
- if (ioctl(fd, SIOCSIFVLAN, &if_request) < 0) {
- wpa_printf(MSG_ERROR, "VLAN: %s: DEL_VLAN_CMD failed for %s: "
- "%s", __func__, if_name, strerror(errno));
- close(fd);
- return -1;
- }
-
- close(fd);
- return 0;
-}
-
-
-/*
- Add a vlan interface with VLAN ID 'vid' and tagged interface
- 'if_name'.
-
- returns -1 on error
- returns 1 if the interface already exists
- returns 0 otherwise
-*/
-static int vlan_add(const char *if_name, int vid)
-{
- int fd;
- struct vlan_ioctl_args if_request;
-
- wpa_printf(MSG_DEBUG, "VLAN: vlan_add(if_name=%s, vid=%d)",
- if_name, vid);
- ifconfig_up(if_name);
-
- if ((os_strlen(if_name) + 1) > sizeof(if_request.device1)) {
- wpa_printf(MSG_ERROR, "VLAN: Interface name too long: '%s'",
- if_name);
- return -1;
- }
-
- if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
- wpa_printf(MSG_ERROR, "VLAN: %s: socket(AF_INET,SOCK_STREAM) "
- "failed: %s", __func__, strerror(errno));
- return -1;
- }
-
- os_memset(&if_request, 0, sizeof(if_request));
-
- /* Determine if a suitable vlan device already exists. */