From 64cdecd0b12655ca32a635ed258f8b3179f11e06 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Sat, 25 Nov 2006 21:00:29 +0000 Subject: [PATCH] modify the watchdog for forcing adhoc or client mode connections to a specific bssid SVN-Revision: 5641 --- openwrt/package/wificonf/wificonf.c | 63 ++++++++++++++++++++++++++++- 1 file changed, 62 insertions(+), 1 deletion(-) diff --git a/openwrt/package/wificonf/wificonf.c b/openwrt/package/wificonf/wificonf.c index d045ad71f7..480bc6fb5d 100644 --- a/openwrt/package/wificonf/wificonf.c +++ b/openwrt/package/wificonf/wificonf.c @@ -224,6 +224,8 @@ void start_watchdog(int skfd, char *ifname) FILE *f; unsigned char buf[8192], wdslist[8192], wbuf[80], *v, *p, *next, *tmp; int i, j, wds = 0, c = 0, restart_wds = 0, wdstimeout = 0, infra; + int tsf_attack = 0; + unsigned int cur_tsf = 0; if (fork()) return; @@ -258,11 +260,70 @@ void start_watchdog(int skfd, char *ifname) else c = 0; - if (infra != 1) + /* + * In adhoc mode it can be desirable to use a specific BSSID to prevent + * accidental cell splitting caused by broken cards/drivers. + * When wl0_bssid is set, make sure the current BSSID matches the one + * set in nvram. If it doesn't change it and try to overpower the hostile + * AP by increasing the upper 32 bit of the TSF by one every time. + * + * In client mode simply use that variable to connect to a specific AP + */ + if ((infra < 1) || + nvram_match(wl_var("mode"), "sta") || + nvram_match(wl_var("mode"), "wet")) { + rw_reg_t reg; + + if (!(tmp = nvram_get(wl_var("bssid")))) + continue; + + if (!ether_atoe(tmp, wbuf)) + continue; + + if ((bcom_ioctl(skfd, ifname, WLC_GET_BSSID, buf, 6) < 0) || + (memcmp(buf, "\0\0\0\0\0\0", 6) == 0) || + (memcmp(buf, wbuf, 6) != 0)) { + + if (bcom_ioctl(skfd, ifname, (infra < 1 ? WLC_SET_BSSID : WLC_REASSOC), wbuf, 6) < 0) + continue; + + if (infra < 1) { + /* upper 32 bit of the TSF */ + memset(®, 0, sizeof(reg)); + reg.size = 4; + reg.byteoff = 0x184; + + bcom_ioctl(skfd, ifname, WLC_R_REG, ®, sizeof(reg)); + + if (reg.val > cur_tsf) + cur_tsf = reg.val; + + cur_tsf |= 1; + cur_tsf <<=1; + reg.val = (cur_tsf == ~0 ? cur_tsf : cur_tsf + 1); + bcom_ioctl(skfd, ifname, WLC_W_REG, ®, sizeof(reg)); + + /* set the lower 32 bit as well */ + reg.byteoff = 0x180; + bcom_ioctl(skfd, ifname, WLC_W_REG, ®, sizeof(reg)); + + /* set the bssid again, just in case.. */ + bcom_ioctl(skfd, ifname, WLC_SET_BSSID, wbuf, 6); + + /* reached the maximum, next time wrap around to (1 << 16) + * instead of 0 */ + if (cur_tsf == ~0) + cur_tsf = (1 << 16); + } + } + } + + if (infra < 1) continue; if (nvram_match(wl_var("mode"), "sta") || nvram_match(wl_var("mode"), "wet")) { + i = 0; if (bcom_ioctl(skfd, ifname, WLC_GET_BSSID, buf, 6) < 0) i = 1; -- 2.30.2