X-Git-Url: https://git.rohieb.name/openwrt.git/blobdiff_plain/102ad2157b31642e029c8c176de1cc5b22c96599..e2b0a0cc9aa0c95f9eef48c44ffba0ded73a2ea3:/package/nvram/src/wl.c diff --git a/package/nvram/src/wl.c b/package/nvram/src/wl.c index f09317ad0..c33610310 100644 --- a/package/nvram/src/wl.c +++ b/package/nvram/src/wl.c @@ -11,11 +11,68 @@ * * $Id$ */ +#include +#include #include +#include +#include +#include #include #include +int +wl_ioctl(char *name, int cmd, void *buf, int len) +{ + struct ifreq ifr; + wl_ioctl_t ioc; + int ret = 0; + int s; + + /* open socket to kernel */ + if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { + perror("socket"); + return errno; + } + + /* do it */ + ioc.cmd = cmd; + ioc.buf = buf; + ioc.len = len; + strncpy(ifr.ifr_name, name, IFNAMSIZ); + ifr.ifr_data = (caddr_t) &ioc; + if ((ret = ioctl(s, SIOCDEVPRIVATE, &ifr)) < 0) + if (cmd != WLC_GET_MAGIC) + perror(ifr.ifr_name); + + /* cleanup */ + close(s); + return ret; +} + +int +wl_hwaddr(char *name, unsigned char *hwaddr) +{ + struct ifreq ifr; + int ret = 0; + int s; + + /* open socket to kernel */ + if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { + perror("socket"); + return errno; + } + + /* do it */ + strncpy(ifr.ifr_name, name, IFNAMSIZ); + if ((ret = ioctl(s, SIOCGIFHWADDR, &ifr)) == 0) + memcpy(hwaddr, ifr.ifr_hwaddr.sa_data, ETHER_ADDR_LEN); + + /* cleanup */ + close(s); + return ret; +} + int wl_probe(char *name) { @@ -84,3 +141,216 @@ wl_get_int(char *name, char *var, int *val) return wl_get_val(name, var, val, sizeof(*val)); } +/************************************************************************** + * The following code is from Broadcom (wl.c) * + **************************************************************************/ + +int +wl_iovar_getbuf(char *ifname, char *iovar, void *param, + int paramlen, void *bufptr, int buflen) +{ + int err; + uint namelen; + uint iolen; + + namelen = strlen(iovar) + 1; /* length of iovar name plus null */ + iolen = namelen + paramlen; + + /* check for overflow */ + if (iolen > buflen) + return (-1); + + memcpy(bufptr, iovar, namelen); /* copy iovar name including null */ + memcpy((int8*)bufptr + namelen, param, paramlen); + + err = wl_ioctl(ifname, WLC_GET_VAR, bufptr, buflen); + + return (err); +} + +int +wl_iovar_setbuf(char *ifname, char *iovar, void *param, + int paramlen, void *bufptr, int buflen) +{ + uint namelen; + uint iolen; + + namelen = strlen(iovar) + 1; /* length of iovar name plus null */ + iolen = namelen + paramlen; + + /* check for overflow */ + if (iolen > buflen) + return (-1); + + memcpy(bufptr, iovar, namelen); /* copy iovar name including null */ + memcpy((int8*)bufptr + namelen, param, paramlen); + + return wl_ioctl(ifname, WLC_SET_VAR, bufptr, iolen); +} + +int +wl_iovar_set(char *ifname, char *iovar, void *param, int paramlen) +{ + char smbuf[WLC_IOCTL_SMLEN]; + + return wl_iovar_setbuf(ifname, iovar, param, paramlen, smbuf, sizeof(smbuf)); +} + +int +wl_iovar_get(char *ifname, char *iovar, void *bufptr, int buflen) +{ + char smbuf[WLC_IOCTL_SMLEN]; + int ret; + + /* use the return buffer if it is bigger than what we have on the stack */ + if (buflen > sizeof(smbuf)) { + ret = wl_iovar_getbuf(ifname, iovar, NULL, 0, bufptr, buflen); + } else { + ret = wl_iovar_getbuf(ifname, iovar, NULL, 0, smbuf, sizeof(smbuf)); + if (ret == 0) + memcpy(bufptr, smbuf, buflen); + } + + return ret; +} + +/* + * set named driver variable to int value + * calling example: wl_iovar_setint(ifname, "arate", rate) +*/ +int +wl_iovar_setint(char *ifname, char *iovar, int val) +{ + return wl_iovar_set(ifname, iovar, &val, sizeof(val)); +} + +/* + * get named driver variable to int value and return error indication + * calling example: wl_iovar_getint(ifname, "arate", &rate) + */ +int +wl_iovar_getint(char *ifname, char *iovar, int *val) +{ + return wl_iovar_get(ifname, iovar, val, sizeof(int)); +} + +/* + * format a bsscfg indexed iovar buffer + */ +static int +wl_bssiovar_mkbuf(char *iovar, int bssidx, void *param, + int paramlen, void *bufptr, int buflen, int *plen) +{ + char *prefix = "bsscfg:"; + int8* p; + uint prefixlen; + uint namelen; + uint iolen; + + prefixlen = strlen(prefix); /* length of bsscfg prefix */ + namelen = strlen(iovar) + 1; /* length of iovar name + null */ + iolen = prefixlen + namelen + sizeof(int) + paramlen; + + /* check for overflow */ + if (buflen < 0 || iolen > (uint)buflen) { + *plen = 0; + return -1; + } + + p = (int8*)bufptr; + + /* copy prefix, no null */ + memcpy(p, prefix, prefixlen); + p += prefixlen; + + /* copy iovar name including null */ + memcpy(p, iovar, namelen); + p += namelen; + + /* bss config index as first param */ + memcpy(p, &bssidx, sizeof(int32)); + p += sizeof(int32); + + /* parameter buffer follows */ + if (paramlen) + memcpy(p, param, paramlen); + + *plen = iolen; + return 0; +} + +/* + * set named & bss indexed driver variable to buffer value + */ +int +wl_bssiovar_setbuf(char *ifname, char *iovar, int bssidx, void *param, + int paramlen, void *bufptr, int buflen) +{ + int err; + uint iolen; + + err = wl_bssiovar_mkbuf(iovar, bssidx, param, paramlen, bufptr, buflen, &iolen); + if (err) + return err; + + return wl_ioctl(ifname, WLC_SET_VAR, bufptr, iolen); +} + +/* + * get named & bss indexed driver variable buffer value + */ +int +wl_bssiovar_getbuf(char *ifname, char *iovar, int bssidx, void *param, + int paramlen, void *bufptr, int buflen) +{ + int err; + uint iolen; + + err = wl_bssiovar_mkbuf(iovar, bssidx, param, paramlen, bufptr, buflen, &iolen); + if (err) + return err; + + return wl_ioctl(ifname, WLC_GET_VAR, bufptr, buflen); +} + +/* + * set named & bss indexed driver variable to buffer value + */ +int +wl_bssiovar_set(char *ifname, char *iovar, int bssidx, void *param, int paramlen) +{ + char smbuf[WLC_IOCTL_SMLEN]; + + return wl_bssiovar_setbuf(ifname, iovar, bssidx, param, paramlen, smbuf, sizeof(smbuf)); +} + +/* + * get named & bss indexed driver variable buffer value + */ +int +wl_bssiovar_get(char *ifname, char *iovar, int bssidx, void *outbuf, int len) +{ + char smbuf[WLC_IOCTL_SMLEN]; + int err; + + /* use the return buffer if it is bigger than what we have on the stack */ + if (len > (int)sizeof(smbuf)) { + err = wl_bssiovar_getbuf(ifname, iovar, bssidx, NULL, 0, outbuf, len); + } else { + memset(smbuf, 0, sizeof(smbuf)); + err = wl_bssiovar_getbuf(ifname, iovar, bssidx, NULL, 0, smbuf, sizeof(smbuf)); + if (err == 0) + memcpy(outbuf, smbuf, len); + } + + return err; +} + +/* + * set named & bss indexed driver variable to int value + */ +int +wl_bssiovar_setint(char *ifname, char *iovar, int bssidx, int val) +{ + return wl_bssiovar_set(ifname, iovar, bssidx, &val, sizeof(int)); +}