[RFC] vlan: use new bridge ioctl's
Sergey Matyukevich
sergey.matyukevich.os at quantenna.com
Tue Nov 21 12:14:45 PST 2017
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 at quantenna.com>
---
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
More information about the Hostap
mailing list