aboutsummaryrefslogtreecommitdiffstats
path: root/src/drivers/linux_ioctl.c
diff options
context:
space:
mode:
authorJouni Malinen <j@w1.fi>2010-01-16 13:19:58 (GMT)
committerJouni Malinen <j@w1.fi>2010-01-16 13:19:58 (GMT)
commit94627f6cc8be8693b6c6a7a6407fcf94ba0a7edb (patch)
treea17034718c8d9d941a1cf7c39270ec5f42dea1f1 /src/drivers/linux_ioctl.c
parentd455d0806ed30cd471937d445f4d840017f25758 (diff)
downloadhostap-94627f6cc8be8693b6c6a7a6407fcf94ba0a7edb.zip
hostap-94627f6cc8be8693b6c6a7a6407fcf94ba0a7edb.tar.gz
hostap-94627f6cc8be8693b6c6a7a6407fcf94ba0a7edb.tar.bz2
hostapd: Detect bridge interface automatically
This makes the bridge parameter unnecessary for cases where the interface is already in a bridge and sysfs is mounted to /sys so that the detection code works. For nl80211, the bridge parameter can be used to request the AP interface to be added to the bridge automatically (brctl may refuse to do this before hostapd has been started to change the interface mode). If needed, the bridge interface is also created.
Diffstat (limited to 'src/drivers/linux_ioctl.c')
-rw-r--r--src/drivers/linux_ioctl.c98
1 files changed, 98 insertions, 0 deletions
diff --git a/src/drivers/linux_ioctl.c b/src/drivers/linux_ioctl.c
index 549ebb4..f806167 100644
--- a/src/drivers/linux_ioctl.c
+++ b/src/drivers/linux_ioctl.c
@@ -97,3 +97,101 @@ int linux_set_ifhwaddr(int sock, const char *ifname, const u8 *addr)
return 0;
}
+
+
+#ifndef SIOCBRADDBR
+#define SIOCBRADDBR 0x89a0
+#endif
+#ifndef SIOCBRDELBR
+#define SIOCBRDELBR 0x89a1
+#endif
+#ifndef SIOCBRADDIF
+#define SIOCBRADDIF 0x89a2
+#endif
+#ifndef SIOCBRDELIF
+#define SIOCBRDELIF 0x89a3
+#endif
+
+
+int linux_br_add(int sock, const char *brname)
+{
+ if (ioctl(sock, SIOCBRADDBR, brname) < 0) {
+ wpa_printf(MSG_DEBUG, "Could not add bridge %s: %s",
+ brname, strerror(errno));
+ return -1;
+ }
+
+ return 0;
+}
+
+
+int linux_br_del(int sock, const char *brname)
+{
+ if (ioctl(sock, SIOCBRDELBR, brname) < 0) {
+ wpa_printf(MSG_DEBUG, "Could not remove bridge %s: %s",
+ brname, strerror(errno));
+ return -1;
+ }
+
+ return 0;
+}
+
+
+int linux_br_add_if(int sock, const char *brname, const char *ifname)
+{
+ struct ifreq ifr;
+ int ifindex;
+
+ ifindex = if_nametoindex(ifname);
+ if (ifindex == 0)
+ return -1;
+
+ os_memset(&ifr, 0, sizeof(ifr));
+ os_strlcpy(ifr.ifr_name, brname, IFNAMSIZ);
+ ifr.ifr_ifindex = ifindex;
+ if (ioctl(sock, SIOCBRADDIF, &ifr) < 0) {
+ wpa_printf(MSG_DEBUG, "Could not add interface %s into bridge "
+ "%s: %s", ifname, brname, strerror(errno));
+ return -1;
+ }
+
+ return 0;
+}
+
+
+int linux_br_del_if(int sock, const char *brname, const char *ifname)
+{
+ struct ifreq ifr;
+ int ifindex;
+
+ ifindex = if_nametoindex(ifname);
+ if (ifindex == 0)
+ return -1;
+
+ os_memset(&ifr, 0, sizeof(ifr));
+ os_strlcpy(ifr.ifr_name, brname, IFNAMSIZ);
+ ifr.ifr_ifindex = ifindex;
+ if (ioctl(sock, SIOCBRDELIF, &ifr) < 0) {
+ wpa_printf(MSG_DEBUG, "Could not remove interface %s from "
+ "bridge %s: %s", ifname, brname, strerror(errno));
+ return -1;
+ }
+
+ return 0;
+}
+
+
+int linux_br_get(char *brname, const char *ifname)
+{
+ char path[128], brlink[128], *pos;
+ os_snprintf(path, sizeof(path), "/sys/class/net/%s/brport/bridge",
+ ifname);
+ if (readlink(path, brlink, sizeof(brlink)) < 0)
+ return -1;
+ pos = os_strrchr(brlink, '/');
+ if (pos == NULL)
+ return -1;
+ pos++;
+ os_strlcpy(brname, pos, IFNAMSIZ);
+ return 0;
+}