// insert header here // mbm. gpl. #include #include #include #include #include #include #include #define DEBUG static struct net_device *dev; static int wl_ioctl(struct net_device *dev, int cmd, void *buf, int len) { mm_segment_t old_fs = get_fs(); struct ifreq ifr; int ret; wl_ioctl_t ioc; ioc.cmd = cmd; ioc.buf = buf; ioc.len = len; strncpy(ifr.ifr_name, dev->name, IFNAMSIZ); ifr.ifr_data = (caddr_t) &ioc; set_fs(KERNEL_DS); ret = dev->do_ioctl(dev,&ifr,SIOCDEVPRIVATE); set_fs (old_fs); return ret; } static int wlcompat_ioctl(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra) { switch (info->cmd) { case SIOCGIWNAME: strcpy(wrqu->name, "IEEE 802.11-DS"); break; case SIOCGIWFREQ: { channel_info_t ci; wl_ioctl(dev,WLC_GET_CHANNEL, &ci, sizeof(ci)); wrqu->freq.m = ci.target_channel; wrqu->freq.e = 0; break; } case SIOCGIWAP: { wrqu->ap_addr.sa_family = ARPHRD_ETHER; wl_ioctl(dev,WLC_GET_BSSID,wrqu->ap_addr.sa_data,6); break; } case SIOCGIWESSID: { wlc_ssid_t ssid; wl_ioctl(dev,WLC_GET_SSID, &ssid, sizeof(wlc_ssid_t)); wrqu->essid.flags = wrqu->data.flags = 1; wrqu->essid.length = wrqu->data.length = ssid.SSID_len + 1; memcpy(extra,ssid.SSID,ssid.SSID_len + 1); break; } case SIOCGIWRTS: { wl_ioctl(dev,WLC_GET_RTS,&(wrqu->rts.value),sizeof(int)); break; } case SIOCGIWFRAG: { wl_ioctl(dev,WLC_GET_FRAG,&(wrqu->frag.value),sizeof(int)); break; } case SIOCGIWTXPOW: { wrqu->txpower.value = 0; wl_ioctl(dev,WLC_GET_TXPWR, &(wrqu->txpower.value), sizeof(int)); wrqu->txpower.fixed = 0; wrqu->txpower.disabled = 0; wrqu->txpower.flags = IW_TXPOW_MWATT; break; } case SIOCGIWENCODE: { wrqu->data.flags = IW_ENCODE_DISABLED; break; } } return 0; } static const iw_handler wlcompat_handler[] = { NULL, /* SIOCSIWNAME */ wlcompat_ioctl, /* SIOCGIWNAME */ NULL, /* SIOCSIWNWID */ NULL, /* SIOCGIWNWID */ NULL, /* SIOCSIWFREQ */ wlcompat_ioctl, /* SIOCGIWFREQ */ NULL, /* SIOCSIWMODE */ NULL, /* SIOCGIWMODE */ NULL, /* SIOCSIWSENS */ NULL, /* SIOCGIWSENS */ NULL, /* SIOCSIWRANGE */ NULL, /* SIOCGIWRANGE */ NULL, /* SIOCSIWPRIV */ NULL, /* SIOCGIWPRIV */ NULL, /* SIOCSIWSTATS */ NULL, /* SIOCGIWSTATS */ iw_handler_set_spy, /* SIOCSIWSPY */ iw_handler_get_spy, /* SIOCGIWSPY */ iw_handler_set_thrspy, /* SIOCSIWTHRSPY */ iw_handler_get_thrspy, /* SIOCGIWTHRSPY */ NULL, /* SIOCSIWAP */ wlcompat_ioctl, /* SIOCGIWAP */ NULL, /* -- hole -- */ NULL, /* SIOCGIWAPLIST */ NULL, /* -- hole -- */ NULL, /* -- hole -- */ NULL, /* SIOCSIWESSID */ wlcompat_ioctl, /* SIOCGIWESSID */ NULL, /* SIOCSIWNICKN */ NULL, /* SIOCGIWNICKN */ NULL, /* -- hole -- */ NULL, /* -- hole -- */ NULL, /* SIOCSIWRATE */ NULL, /* SIOCGIWRATE */ NULL, /* SIOCSIWRTS */ wlcompat_ioctl, /* SIOCGIWRTS */ NULL, /* SIOCSIWFRAG */ wlcompat_ioctl, /* SIOCGIWFRAG */ NULL, /* SIOCSIWTXPOW */ wlcompat_ioctl, /* SIOCGIWTXPOW */ NULL, /* SIOCSIWRETRY */ NULL, /* SIOCGIWRETRY */ NULL, /* SIOCSIWENCODE */ wlcompat_ioctl, /* SIOCGIWENCODE */ }; static const struct iw_handler_def wlcompat_handler_def = { .standard = (iw_handler *) wlcompat_handler, .num_standard = sizeof(wlcompat_handler)/sizeof(iw_handler), .private = NULL, .num_private = 0, .private_args = NULL, .num_private_args = 0, }; #ifdef DEBUG static int (*old_ioctl)(struct net_device *dev, struct ifreq *ifr, int cmd); static int new_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) { int ret = old_ioctl(dev,ifr,cmd); printk("dev: %s ioctl: 0x%04x\n",dev->name,cmd); if (cmd==SIOCDEVPRIVATE) { int x; wl_ioctl_t *ioc = (wl_ioctl_t *)ifr->ifr_data; unsigned char *buf = ioc->buf; printk(" cmd: %d buf: 0x%08x len: %d\n",ioc->cmd,&(ioc->buf),ioc->len); printk(" ->"); for (x=0;xlen && x<128 ;x++) { printk("%02X",buf[x]); } printk("\n"); } return ret; } #endif static int __init wlcompat_init() { dev = dev_get_by_name("eth1"); #ifdef DEBUG old_ioctl = dev->do_ioctl; dev->do_ioctl = new_ioctl; #endif dev->wireless_handlers = (struct iw_handler_def *)&wlcompat_handler_def; return 0; } static void __exit wlcompat_exit() { dev->wireless_handlers = NULL; #ifdef DEBUG dev->do_ioctl = old_ioctl; #endif return; } EXPORT_NO_SYMBOLS; MODULE_AUTHOR("openwrt.org"); MODULE_LICENSE("GPL"); module_init(wlcompat_init); module_exit(wlcompat_exit);