📄 if_an.c
字号:
case AN_RID_SSIDLIST: ssid = (struct an_ltv_ssidlist *)areq; bcopy((char *)ssid, (char *)&sc->an_ssidlist, sizeof(struct an_ltv_ssidlist)); break; case AN_RID_APLIST: ap = (struct an_ltv_aplist *)areq; bcopy((char *)ap, (char *)&sc->an_aplist, sizeof(struct an_ltv_aplist)); break; case AN_RID_TX_SPEED: sp = (struct an_ltv_gen *)areq; sc->an_tx_rate = sp->an_val; break; case AN_RID_WEP_TEMP: case AN_RID_WEP_PERM: /* Disable the MAC. */ /* an_cmd(sc, AN_CMD_DISABLE, 0); */ /* Write the key */ an_write_record(sc, (struct an_ltv_gen *)areq); /* Turn the MAC back on. */ /* an_cmd(sc, AN_CMD_ENABLE, 0); */ return; break; case AN_RID_MONITOR_MODE: cfg = (struct an_ltv_genconfig *)areq; bpfdetach(ifp); if (ng_ether_detach_p != NULL) (*ng_ether_detach_p) (ifp); sc->an_monitor = cfg->an_len; if (sc->an_monitor & AN_MONITOR) { if (sc->an_monitor & AN_MONITOR_AIRONET_HEADER) { bpfattach(ifp, DLT_AIRONET_HEADER, sizeof(struct ether_header)); } else { bpfattach(ifp, DLT_IEEE802_11, sizeof(struct ether_header)); } } else { bpfattach(ifp, DLT_EN10MB, sizeof(struct ether_header)); if (ng_ether_attach_p != NULL) (*ng_ether_attach_p) (ifp); } break; default: printf("an%d: unknown RID: %x\n", sc->an_unit, areq->an_type); return; break; } /* Reinitialize the card. */ if (ifp->if_flags) an_init(sc); return;}/* * Derived from Linux driver to enable promiscious mode. */static voidan_promisc(sc, promisc) struct an_softc *sc; int promisc;{ if (sc->an_was_monitor) an_reset(sc); if (sc->an_monitor || sc->an_was_monitor) an_init(sc); sc->an_was_monitor = sc->an_monitor; an_cmd(sc, AN_CMD_SET_MODE, promisc ? 0xffff : 0); return;}static intan_ioctl(ifp, command, data) struct ifnet *ifp; u_long command; caddr_t data;{ int s, error = 0; int len; int i; struct an_softc *sc; struct an_req areq; struct ifreq *ifr; struct proc *p = curproc; struct ieee80211req *ireq; u_int8_t tmpstr[IEEE80211_NWID_LEN*2]; u_int8_t *tmpptr; struct an_ltv_genconfig *config; struct an_ltv_key *key; struct an_ltv_status *status; struct an_ltv_ssidlist *ssids; s = splimp(); sc = ifp->if_softc; ifr = (struct ifreq *)data; ireq = (struct ieee80211req *)data; config = (struct an_ltv_genconfig *)&areq; key = (struct an_ltv_key *)&areq; status = (struct an_ltv_status *)&areq; ssids = (struct an_ltv_ssidlist *)&areq; if (sc->an_gone) { error = ENODEV; goto out; } switch (command) { case SIOCSIFADDR: case SIOCGIFADDR: case SIOCSIFMTU: error = ether_ioctl(ifp, command, data); break; case SIOCSIFFLAGS: if (ifp->if_flags & IFF_UP) { if (ifp->if_flags & IFF_RUNNING && ifp->if_flags & IFF_PROMISC && !(sc->an_if_flags & IFF_PROMISC)) { an_promisc(sc, 1); } else if (ifp->if_flags & IFF_RUNNING && !(ifp->if_flags & IFF_PROMISC) && sc->an_if_flags & IFF_PROMISC) { an_promisc(sc, 0); } else an_init(sc); } else { if (ifp->if_flags & IFF_RUNNING) an_stop(sc); } sc->an_if_flags = ifp->if_flags; error = 0; break; case SIOCSIFMEDIA: case SIOCGIFMEDIA: error = ifmedia_ioctl(ifp, ifr, &sc->an_ifmedia, command); break; case SIOCADDMULTI: case SIOCDELMULTI: /* The Aironet has no multicast filter. */ error = 0; break; case SIOCGAIRONET: error = copyin(ifr->ifr_data, &areq, sizeof(areq)); if (error != 0) break;#ifdef ANCACHE if (areq.an_type == AN_RID_ZERO_CACHE) { sc->an_sigitems = sc->an_nextitem = 0; break; } else if (areq.an_type == AN_RID_READ_CACHE) { char *pt = (char *)&areq.an_val; bcopy((char *)&sc->an_sigitems, (char *)pt, sizeof(int)); pt += sizeof(int); areq.an_len = sizeof(int) / 2; bcopy((char *)&sc->an_sigcache, (char *)pt, sizeof(struct an_sigcache) * sc->an_sigitems); areq.an_len += ((sizeof(struct an_sigcache) * sc->an_sigitems) / 2) + 1; } else#endif if (an_read_record(sc, (struct an_ltv_gen *)&areq)) { error = EINVAL; break; } error = copyout(&areq, ifr->ifr_data, sizeof(areq)); break; case SIOCSAIRONET: if ((error = suser(p))) goto out; error = copyin(ifr->ifr_data, &areq, sizeof(areq)); if (error != 0) break; an_setdef(sc, &areq); break; case SIOCG80211: areq.an_len = sizeof(areq); switch (ireq->i_type) { case IEEE80211_IOC_SSID: if (ireq->i_val == -1) { areq.an_type = AN_RID_STATUS; if (an_read_record(sc, (struct an_ltv_gen *)&areq)) { error = EINVAL; break; } len = status->an_ssidlen; tmpptr = status->an_ssid; } else if (ireq->i_val >= 0) { areq.an_type = AN_RID_SSIDLIST; if (an_read_record(sc, (struct an_ltv_gen *)&areq)) { error = EINVAL; break; } if (ireq->i_val == 0) { len = ssids->an_ssid1_len; tmpptr = ssids->an_ssid1; } else if (ireq->i_val == 1) { len = ssids->an_ssid2_len; tmpptr = ssids->an_ssid3; } else if (ireq->i_val == 1) { len = ssids->an_ssid3_len; tmpptr = ssids->an_ssid3; } else { error = EINVAL; break; } } else { error = EINVAL; break; } if (len > IEEE80211_NWID_LEN) { error = EINVAL; break; } ireq->i_len = len; bzero(tmpstr, IEEE80211_NWID_LEN); bcopy(tmpptr, tmpstr, len); error = copyout(tmpstr, ireq->i_data, IEEE80211_NWID_LEN); break; case IEEE80211_IOC_NUMSSIDS: ireq->i_val = 3; break; case IEEE80211_IOC_WEP: areq.an_type = AN_RID_ACTUALCFG; if (an_read_record(sc, (struct an_ltv_gen *)&areq)) { error = EINVAL; break; } if (config->an_authtype & AN_AUTHTYPE_PRIVACY_IN_USE) { if (config->an_authtype & AN_AUTHTYPE_ALLOW_UNENCRYPTED) ireq->i_val = IEEE80211_WEP_MIXED; else ireq->i_val = IEEE80211_WEP_ON; } else { ireq->i_val = IEEE80211_WEP_OFF; } break; case IEEE80211_IOC_WEPKEY: /* * XXX: I'm not entierly convinced this is * correct, but it's what is implemented in * ancontrol so it will have to do until we get * access to actual Cisco code. */ if (ireq->i_val < 0 || ireq->i_val > 7) { error = EINVAL; break; } len = 0; if (ireq->i_val < 4) { areq.an_type = AN_RID_WEP_TEMP; for (i = 0; i < 5; i++) { if (an_read_record(sc, (struct an_ltv_gen *)&areq)) { error = EINVAL; break; } if (key->kindex == 0xffff) break; if (key->kindex == ireq->i_val) len = key->klen; /* Required to get next entry */ areq.an_type = AN_RID_WEP_PERM; } if (error != 0) break; } /* We aren't allowed to read the value of the * key from the card so we just output zeros * like we would if we could read the card, but * denied the user access. */ bzero(tmpstr, len); ireq->i_len = len; error = copyout(tmpstr, ireq->i_data, len); break; case IEEE80211_IOC_NUMWEPKEYS: ireq->i_val = 8; break; case IEEE80211_IOC_WEPTXKEY: /* * For some strange reason, you have to read all * keys before you can read the txkey. */ areq.an_type = AN_RID_WEP_TEMP; for (i = 0; i < 5; i++) { if (an_read_record(sc, (struct an_ltv_gen *)&areq)) { error = EINVAL; break; } if (key->kindex == 0xffff) break; /* Required to get next entry */ areq.an_type = AN_RID_WEP_PERM; } if (error != 0) break; areq.an_type = AN_RID_WEP_PERM; key->kindex = 0xffff; if (an_read_record(sc, (struct an_ltv_gen *)&areq)) { error = EINVAL; break; } ireq->i_val = key->mac[0]; break; case IEEE80211_IOC_AUTHMODE: areq.an_type = AN_RID_ACTUALCFG; if (an_read_record(sc, (struct an_ltv_gen *)&areq)) { error = EINVAL; break; } if ((config->an_authtype & AN_AUTHTYPE_MASK) == AN_AUTHTYPE_NONE) { ireq->i_val = IEEE80211_AUTH_NONE; } else if ((config->an_authtype & AN_AUTHTYPE_MASK) == AN_AUTHTYPE_OPEN) { ireq->i_val = IEEE80211_AUTH_OPEN; } else if ((config->an_authtype & AN_AUTHTYPE_MASK) == AN_AUTHTYPE_SHAREDKEY) { ireq->i_val = IEEE80211_AUTH_SHARED; } else error = EINVAL; break; case IEEE80211_IOC_STATIONNAME: areq.an_type = AN_RID_ACTUALCFG; if (an_read_record(sc, (struct an_ltv_gen *)&areq)) { error = EINVAL; break; } ireq->i_len = sizeof(config->an_nodename); tmpptr = config->an_nodename; bzero(tmpstr, IEEE80211_NWID_LEN); bcopy(tmpptr, tmpstr, ireq->i_len); error = copyout(tmpstr, ireq->i_data, IEEE80211_NWID_LEN); break; case IEEE80211_IOC_CHANNEL: areq.an_type = AN_RID_STATUS; if (an_read_record(sc, (struct an_ltv_gen *)&areq)) { error = EINVAL; break; } ireq->i_val = status->an_cur_channel; break; case IEEE80211_IOC_POWERSAVE: areq.an_type = AN_RID_ACTUALCFG; if (an_read_record(sc, (struct an_ltv_gen *)&areq)) { error = EINVAL; break; } if (config->an_psave_mode == AN_PSAVE_NONE) { ireq->i_val = IEEE80211_POWERSAVE_OFF; } else if (config->an_psave_mode == AN_PSAVE_CAM) { ireq->i_val = IEEE80211_POWERSAVE_CAM; } else if (config->an_psave_mode == AN_PSAVE_PSP) { ireq->i_val = IEEE80211_POWERSAVE_PSP; } else if (config->an_psave_mode == AN_PSAVE_PSP_CAM) { ireq->i_val = IEEE80211_POWERSAVE_PSP_CAM; } else error = EINVAL; break; case IEEE80211_IOC_POWERSAVESLEEP: areq.an_type = AN_RID_ACTUALCFG; if (an_read_record(sc, (struct an_ltv_gen *)&areq)) { error = EINVAL; break; } ireq->i_val = config->an_listen_interval; break; } break; case SIOCS80211: if ((error = suser(p))) goto out; areq.an_len = sizeof(areq); /* * We need a config structure for everything but the WEP * key management and SSIDs so we get it now so avoid * duplicating this code every time. */ if (ireq->i_type != IEEE80211_IOC_SSID && ireq->i_type != IEEE80211_IOC_WEPKEY && ireq->i_type != IEEE80211_IOC_WEPTXKEY) { areq.an_type = AN_RID_GENCONFIG; if (an_read_record(sc, (struct an_ltv_gen *)&areq)) { error = EINVAL; break; } } switch (ireq->i_type) { case IEEE80211_IOC_SSID: areq.an_type = AN_RID_SSIDLIST; if (an_read_record(sc, (struct an_ltv_gen *)&areq)) { error = EINVAL; break; } if (ireq->i_len > IEEE80211_NWID_LEN) { error = EINVAL; break; } switch (ireq->i_val) { case 0: error = copyin(ireq->i_data, ssids->an_ssid1, ireq->i_len); ssids->an_ssid1_len = ireq->i_len; break; case 1: error = copyin(ireq->i_data, ssids->an_ssid2, ireq->i_len); ssids->an_ssid2_len = ireq->i_len; break; case 2: error = copyin(ireq->i_data, ssids->an_ssid3, ireq->i_len); ssids->an_ssid3_len = ireq->i_len; break; default: error = EINVAL; break; } break; case IEEE80211_IOC_WEP: switch (ireq->i_val) { case IEEE80211_WEP_OFF: config->an_authtype &= ~(AN_AUTHTYPE_PRIVACY_IN_USE | AN_AUTHTYPE_ALLOW_UNENCRYPTED); break; case IEEE80211_WEP_ON: config->an_authtype |= AN_AUTHTYPE_PRIVACY_IN_USE; config->an_authtype &= ~AN_AUTHTYPE_ALLOW_UNENCRYPTED; break; case IEEE80211_WEP_MIXED: config->an_authtype |= AN_AUTHTYPE_PRIVACY_IN_USE | AN_AUTHTYPE_ALLOW_UNENCRYPTED; break; default: error = EINVAL; break; } break; case IEEE80211_IOC_WEPKEY: if (ireq->i_val < 0 || ireq->i_val > 7 || ireq->i_len > 13) { error = EINVAL; break; } error = copyin(ireq->i_data, tmpstr, 13); if (error != 0) break; bzero(&areq, sizeof(struct an_ltv_key)); areq.an_len = sizeof(struct an_ltv_key); key->mac[0] = 1; /* The others are 0. */ key->kindex = ireq->i_val % 4; if (ireq->i_val < 4) areq.an_type = AN_RID_WEP_TEMP; else areq.an_type = AN_RID_WEP_PERM; key->klen = ireq->i_len; bcopy(tmpstr, key->key, key->klen); break; case IEEE80211_IOC_WEPTXKEY: if (ireq->i_val < 0 || ireq->i_val > 3) { error = EINVAL; break; } bzero(&areq, sizeof(struct an_ltv_key)); areq.an_len = sizeof(struct an_ltv_key); areq.an_type = AN_RID_WEP_PERM; key->kindex = 0xffff; key->mac[0] = ireq->i_val; break; case IEEE80211_IOC_AUTHMODE: switch (ireq->i_val) { case IEEE80211_AUTH_NONE: config->an_authtype = AN_AUTHTYPE_NONE | (config->an_authtype & ~AN_AUTHTYPE_MASK); break; case IEEE80211_AUTH_OPEN: config->an_authtype = AN_AUTHTYPE_OPEN | (config->an_authtype & ~AN_AUTHTYPE_MASK); break; case IEEE80211_AUTH_SHARED: config->an_authtype = AN_AUTHTYPE_SHAREDKEY | (config->an_authtype & ~AN_AUTHTYPE_MASK); break; default: error = EINVAL; } break; case IEEE80211_IOC_STATIONNAME: if (ireq->i_len > 16) { error = EINVAL; break; } bzero(config->an_nodename, 16); error = copyin(ireq->i_data, config->an_nodename, ireq->i_len); break; case IEEE80211_IOC_CHANNEL: /* * The actual range is 1-14, but if you set it * to 0 you get the default so we let that work * too. */ if (ireq->i_val < 0 || ireq->i_val >14) { error = EINVAL; break; } config->an_ds_channel = ireq->i_val; break; case IEEE80211_IOC_POWERSAVE: switch (ireq->i_val) { case IEEE80211_POWERSAVE_OFF: config->an_psave_mode = AN_PSAVE_NONE; break; case IEEE80211_POWERSAVE_CAM: config->an_psave_mode = AN_PSAVE_CAM; break; case IEEE80211_POWERSAVE_PSP: config->an_psave_mode = AN_PSAVE_PSP; break; case IEEE80211_POWERSAVE_PSP_CAM: config->an_psave_mode = AN_PSAVE_PSP_CAM; break; default: error = EINVAL; break; } break; case IEEE80211_IOC_POWERSAVESLEEP: config->an_listen_interval = ireq->i_val; break; } if (!error) an_setdef(sc, &areq); break; default: error = EINVAL; break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -