Legacy ioctl's through SIOCDEVPRIVATE are deprecated. Follow the approach taken by bridge-utils and make use of new bridge ioctl's whenever possible. For example, using legacy ioctl's breaks dynamic VLAN mode on 32-bit Linux systems running 64-bit kernels. Signed-off-by: Sergey Matyukevich <sergey.matyukevich.os@xxxxxxxxxxxxx> --- src/ap/vlan_full.c | 110 +++++++++++++++++++++++++++++----------------- src/common/linux_bridge.h | 15 +++++++ 2 files changed, 85 insertions(+), 40 deletions(-) diff --git a/src/ap/vlan_full.c b/src/ap/vlan_full.c index aa42335b9..b797f4b60 100644 --- a/src/ap/vlan_full.c +++ b/src/ap/vlan_full.c @@ -135,6 +135,7 @@ static int br_delif(const char *br_name, const char *if_name) struct ifreq ifr; unsigned long args[2]; int if_index; + int ret; wpa_printf(MSG_DEBUG, "VLAN: br_delif(%s, %s)", br_name, if_name); if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { @@ -153,19 +154,23 @@ static int br_delif(const char *br_name, const char *if_name) 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 = (void *) 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; + ifr.ifr_ifindex = if_index; + ret = ioctl(fd, SIOCBRDELIF, &ifr); + if (ret < 0) { + args[0] = BRCTL_DEL_IF; + args[1] = if_index; + + ifr.ifr_data = (void *) 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); @@ -186,6 +191,7 @@ static int br_addif(const char *br_name, const char *if_name) struct ifreq ifr; unsigned long args[2]; int if_index; + int ret; wpa_printf(MSG_DEBUG, "VLAN: br_addif(%s, %s)", br_name, if_name); if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { @@ -204,24 +210,34 @@ static int br_addif(const char *br_name, const char *if_name) 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 = (void *) args; - if (ioctl(fd, SIOCDEVPRIVATE, &ifr) < 0) { + ifr.ifr_ifindex = if_index; + ret = ioctl(fd, SIOCBRADDIF, &ifr); + if (ret < 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; + args[0] = BRCTL_ADD_IF; + args[1] = if_index; + + ifr.ifr_data = (void *) 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); @@ -233,6 +249,7 @@ static int br_delbr(const char *br_name) { int fd; unsigned long arg[2]; + int ret; wpa_printf(MSG_DEBUG, "VLAN: br_delbr(%s)", br_name); if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { @@ -241,15 +258,18 @@ static int br_delbr(const char *br_name) return -1; } - arg[0] = BRCTL_DEL_BRIDGE; - arg[1] = (unsigned long) br_name; + ret = ioctl(fd, SIOCBRDELBR, br_name); + if (ret < 0) { + 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; + 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); @@ -269,6 +289,7 @@ static int br_addbr(const char *br_name) int fd; unsigned long arg[4]; struct ifreq ifr; + int ret; wpa_printf(MSG_DEBUG, "VLAN: br_addbr(%s)", br_name); if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { @@ -277,20 +298,29 @@ static int br_addbr(const char *br_name) return -1; } - arg[0] = BRCTL_ADD_BRIDGE; - arg[1] = (unsigned long) br_name; - - if (ioctl(fd, SIOCGIFBR, arg) < 0) { - if (errno == EEXIST) { + ret = ioctl(fd, SIOCBRADDBR, br_name); + if (ret < 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; + } + + 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; + } } } diff --git a/src/common/linux_bridge.h b/src/common/linux_bridge.h index 7b768464f..84386e60f 100644 --- a/src/common/linux_bridge.h +++ b/src/common/linux_bridge.h @@ -9,6 +9,21 @@ #ifndef LINUX_BRIDGE_H #define LINUX_BRIDGE_H +/* This ioctl is defined in linux/sockios.h */ + +#ifndef SIOCBRADDBR +#define SIOCBRADDBR 0x89a0 +#endif +#ifndef SIOCBRDELBR +#define SIOCBRDELBR 0x89a1 +#endif +#ifndef SIOCBRADDIF +#define SIOCBRADDIF 0x89a2 +#endif +#ifndef SIOCBRDELIF +#define SIOCBRDELIF 0x89a3 +#endif + /* This interface is defined in linux/if_bridge.h */ #define BRCTL_GET_VERSION 0 -- 2.11.0 _______________________________________________ Hostap mailing list Hostap@xxxxxxxxxxxxxxxxxxx http://lists.infradead.org/mailman/listinfo/hostap