X-Git-Url: http://git.rohieb.name/openwrt.git/blobdiff_plain/f52d66ff00b24111f87c274d3d7085ef2e1d27b1..a989a4bdd97f2e2a5340bfb96494d84b93027573:/package/broadcom-wl/src/wlc/wlc.c diff --git a/package/broadcom-wl/src/wlc/wlc.c b/package/broadcom-wl/src/wlc/wlc.c index 09cbb8453..e0d016feb 100644 --- a/package/broadcom-wl/src/wlc/wlc.c +++ b/package/broadcom-wl/src/wlc/wlc.c @@ -56,7 +56,6 @@ static char wlbuf[8192]; static char interface[16] = "wl0"; -static unsigned long ptable[128]; static unsigned long kmem_offset = 0; static int vif = 0, debug = 1, fromstdin = 0; @@ -92,205 +91,10 @@ struct wlc_call { /* can't use the system include because of the stupid broadcom header files */ extern struct ether_addr *ether_aton(const char *asc); -extern char *ether_ntoa(const struct ether_addr *addr); - -/* - * find the starting point of wl.o in memory - * by reading /proc/ksyms - */ -static inline void wlc_get_mem_offset(void) -{ - FILE *f; - char s[64]; - - /* yes, i'm lazy ;) */ - f = popen("grep '\\[wl]' /proc/ksyms | sort", "r"); - if (fgets(s, 64, f) == 0) - return; - - pclose(f); - - s[8] = 0; - kmem_offset = strtoul(s, NULL, 16); - - /* sanity check */ - if (kmem_offset < 0xc0000000) - kmem_offset = 0; -} - - -static int ptable_init(void) -{ - glob_t globbuf; - struct stat statbuf; - int fd; - - if (ptable[0] == PTABLE_MAGIC) - return 0; - - glob("/lib/modules/2.4.*/wl.o.patch", 0, NULL, &globbuf); - - if (globbuf.gl_pathv[0] == NULL) - return -1; - - if ((fd = open(globbuf.gl_pathv[0], O_RDONLY)) < 0) - return -1; - - if (fstat(fd, &statbuf) < 0) - goto failed; - - if (statbuf.st_size < 512) - goto failed; - - if (read(fd, ptable, 512) < 512) - goto failed; - - if (ptable[0] != PTABLE_MAGIC) - goto failed; - - close(fd); - - wlc_get_mem_offset(); - if (kmem_offset == 0) - return -1; - - return 0; - -failed: - close(fd); - - return -1; -} - -static inline unsigned long wlc_kmem_read(unsigned long offset) +static inline int my_ether_ntoa(unsigned char *ea, char *buf) { - int fd; - unsigned long ret; - - if ((fd = open("/dev/kmem", O_RDONLY )) < 0) - return -1; - - lseek(fd, 0x70000000, SEEK_SET); - lseek(fd, (kmem_offset - 0x70000000) + offset, SEEK_CUR); - read(fd, &ret, 4); - close(fd); - - return ret; -} - -static inline void wlc_kmem_write(unsigned long offset, unsigned long value) -{ - int fd; - - if ((fd = open("/dev/kmem", O_WRONLY )) < 0) - return; - - lseek(fd, 0x70000000, SEEK_SET); - lseek(fd, (kmem_offset - 0x70000000) + offset, SEEK_CUR); - write(fd, &value, 4); - close(fd); -} - -static int wlc_patcher_getval(unsigned long key, unsigned long *val) -{ - unsigned long *pt = &ptable[1]; - unsigned long tmp; - - if (ptable_init() < 0) { - fprintf(stderr, "Could not load the ptable\n"); - return -1; - } - - while (*pt != PTABLE_END) { - if (*pt == key) { - tmp = wlc_kmem_read(pt[1]); - - if (tmp == pt[2]) - *val = 0xffffffff; - else - *val = tmp; - - return 0; - } - pt += 3; - } - - return -1; -} - -static int wlc_patcher_setval(unsigned long key, unsigned long val) -{ - unsigned long *pt = &ptable[1]; - - if (ptable_init() < 0) { - fprintf(stderr, "Could not load the ptable\n"); - return -1; - } - - if (val != 0xffffffff) - val = (pt[2] & ~(0xffff)) | (val & 0xffff); - - while (*pt != PTABLE_END) { - if (*pt == key) { - if (val == 0xffffffff) /* default */ - val = pt[2]; - - wlc_kmem_write(pt[1], val); - } - pt += 3; - } - - return 0; -} - -static int wlc_slottime(wlc_param param, void *data, void *value) -{ - int *val = (int *) value; - int ret = 0; - - if ((param & PARAM_MODE) == SET) { - wlc_patcher_setval(PTABLE_SLT1, *val); - wlc_patcher_setval(PTABLE_SLT2, ((*val == -1) ? *val : *val + 510)); - } else if ((param & PARAM_MODE) == GET) { - ret = wlc_patcher_getval(PTABLE_SLT1, (unsigned long *) val); - if (*val != 0xffffffff) - *val &= 0xffff; - } - - return ret; -} - -static int wlc_noack(wlc_param param, void *data, void *value) -{ - int *val = (int *) value; - int ret = 0; - - if ((param & PARAM_MODE) == SET) { - wlc_patcher_setval(PTABLE_ACKW, ((*val) ? 1 : 0)); - } else if ((param & PARAM_MODE) == GET) { - ret = wlc_patcher_getval(PTABLE_ACKW, (unsigned long *) val); - *val &= 0xffff; - *val = (*val ? 1 : 0); - } - - return ret; -} - -static int wlc_ibss_merge(wlc_param param, void *data, void *value) -{ - int *val = (int *) value; - int ret = 0; - - if ((param & PARAM_MODE) == SET) { - /* overwrite the instruction with 'lui v0,0x0' - fake a return - * status of 0 for wlc_bcn_tsf_later */ - wlc_patcher_setval(PTABLE_ACKW, ((*val) ? -1 : 0x3c020000)); - } else if ((param & PARAM_MODE) == GET) { - ret = wlc_patcher_getval(PTABLE_ACKW, (unsigned long *) val); - *val = ((*val == -1) ? 1 : 0); - } - - return ret; + return sprintf(buf, "%02x:%02x:%02x:%02x:%02x:%02x", + ea[0], ea[1], ea[2], ea[3], ea[4], ea[5]); } static int wlc_ioctl(wlc_param param, void *data, void *value) @@ -476,8 +280,10 @@ static int wlc_maclist(wlc_param param, void *data, void *value) ret = wl_ioctl(interface, (ioc >> 16) & 0xffff, wlbuf, sizeof(wlbuf)); if (!ret) - while (list->count) - str += sprintf(str, "%s%s", ((((char *) value) == str) ? "" : " "), ether_ntoa(&list->ea[list->count-- - 1])); + while (list->count) { + str += sprintf(str, "%s", ((((char *) value) == str) ? "" : " ")); + str += my_ether_ntoa((unsigned char *) &list->ea[list->count-- - 1], str); + } return ret; } else { @@ -644,6 +450,58 @@ static int wlc_wme_ac(wlc_param param, void *data, void *value) return ret; } +static int wlc_ifname(wlc_param param, void *data, void *value) +{ + char *val = (char *) value; + int ret = 0; + + if (param & SET) { + if (strlen(val) < 16) + strcpy(interface, val); + else ret = -1; + } + if (param & GET) { + strcpy(val, interface); + } + + return ret; +} + +static int wlc_wdsmac(wlc_param param, void *data, void *value) +{ + unsigned char mac[6]; + int ret = 0; + + ret = wl_ioctl(interface, WLC_WDS_GET_REMOTE_HWADDR, &mac, 6); + if (ret == 0) + my_ether_ntoa(mac, value); + + return ret; +} + +static int wlc_pmk(wlc_param param, void *data, void *value) +{ + int ret = -1; + char *str = (char *) value; + wsec_pmk_t pmk; + + /* driver doesn't support GET */ + + if ((param & PARAM_MODE) == SET) { + strncpy(pmk.key, value, WSEC_MAX_PSK_LEN); + pmk.key_len = strlen(value); + + if (pmk.key_len > WSEC_MAX_PSK_LEN) + pmk.key_len = WSEC_MAX_PSK_LEN; + + pmk.flags = WSEC_PASSPHRASE; + + ret = wl_ioctl(interface, WLC_SET_WSEC_PMK, &pmk, sizeof(pmk)); + } + + return ret; +} + static const struct wlc_call wlc_calls[] = { { .name = "version", @@ -666,6 +524,12 @@ static const struct wlc_call wlc_calls[] = { .data.ptr = &fromstdin, .desc = "Accept input from stdin" }, + { + .name = "ifname", + .param = STRING, + .handler = wlc_ifname, + .desc = "interface to send commands to" + }, { .name = "up", .param = NOARG, @@ -697,7 +561,7 @@ static const struct wlc_call wlc_calls[] = { .name = "mssid", .param = INT, .handler = wlc_iovar, - .data.str = "mssid", + .data.str = "mbss", .desc = "Multi-ssid mode" }, { @@ -823,6 +687,12 @@ static const struct wlc_call wlc_calls[] = { .data.str = "sup_wpa", .desc = "Built-in WPA supplicant" }, + { + .name = "passphrase", + .param = STRING, + .handler = wlc_pmk, + .desc = "Passphrase for built-in WPA supplicant", + }, { .name = "maxassoc", .param = INT, @@ -858,6 +728,20 @@ static const struct wlc_call wlc_calls[] = { .data.str = "wme_noack", .desc = "WME ACK disable request", }, + { + .name = "802.11d", + .param = INT, + .handler = wlc_ioctl, + .data.num = ((WLC_GET_REGULATORY << 16) | WLC_SET_REGULATORY), + .desc = "Enable/disable 802.11d regulatory management", + }, + { + .name = "802.11h", + .param = INT, + .handler = wlc_ioctl, + .data.num = ((WLC_GET_SPECT_MANAGMENT << 16) | WLC_SET_SPECT_MANAGMENT), + .desc = "Enable/disable 802.11h spectrum management", + }, { .name = "fragthresh", .param = INT, @@ -872,6 +756,13 @@ static const struct wlc_call wlc_calls[] = { .data.str = "rtsthresh", .desc = "RTS threshold" }, + { + .name = "slottime", + .param = INT, + .handler = wlc_iovar, + .data.str = "acktiming", + .desc = "Slot time" + }, { .name = "rxant", .param = INT, @@ -956,30 +847,18 @@ static const struct wlc_call wlc_calls[] = { .data.str = "wdstimeout", .desc = "WDS link detection timeout" }, + { + .name = "wdsmac", + .param = STRING|NOARG, + .handler = wlc_wdsmac, + .desc = "MAC of the remote WDS endpoint (only with wds0.* interfaces)" + }, { .name = "afterburner", .param = INT, .handler = wlc_afterburner, .desc = "Broadcom Afterburner" }, - { - .name = "slottime", - .param = INT, - .handler = wlc_slottime, - .desc = "Slot time (-1 = auto)" - }, - { - .name = "txack", - .param = INT, - .handler = wlc_noack, - .desc = "Tx ACK enabled flag" - }, - { - .name = "ibss_merge", - .param = INT, - .handler = wlc_ibss_merge, - .desc = "Allow IBSS merge in Ad-Hoc mode" - } }; #define wlc_calls_size (sizeof(wlc_calls) / sizeof(struct wlc_call))