diff options
| author | Poul-Henning Kamp <phk@FreeBSD.org> | 2001-05-26 09:27:08 +0000 |
|---|---|---|
| committer | Poul-Henning Kamp <phk@FreeBSD.org> | 2001-05-26 09:27:08 +0000 |
| commit | 419d8080a45c9baf85e2254f2f6f30edb11fb0bd (patch) | |
| tree | da27a0f86ea098d14264679df4a59a965ce9f57c /sys | |
| parent | 3344c5a17e9322ec55ad4e3026e2a1e547b89938 (diff) | |
Notes
Diffstat (limited to 'sys')
| -rw-r--r-- | sys/dev/an/if_aironet_ieee.h | 2 | ||||
| -rw-r--r-- | sys/dev/an/if_an.c | 500 | ||||
| -rw-r--r-- | sys/dev/an/if_an_isa.c | 2 | ||||
| -rw-r--r-- | sys/dev/an/if_an_pccard.c | 2 | ||||
| -rw-r--r-- | sys/dev/an/if_an_pci.c | 2 | ||||
| -rw-r--r-- | sys/dev/an/if_anreg.h | 5 | ||||
| -rw-r--r-- | sys/dev/awi/awi.c | 181 | ||||
| -rw-r--r-- | sys/dev/wi/if_wavelan_ieee.h | 4 | ||||
| -rw-r--r-- | sys/dev/wi/if_wi.c | 376 | ||||
| -rw-r--r-- | sys/net/if_ieee80211.h | 39 | ||||
| -rw-r--r-- | sys/net/if_media.c | 10 | ||||
| -rw-r--r-- | sys/net/if_media.h | 54 |
12 files changed, 1168 insertions, 9 deletions
diff --git a/sys/dev/an/if_aironet_ieee.h b/sys/dev/an/if_aironet_ieee.h index bcbd32f05e83..a1eeb2683991 100644 --- a/sys/dev/an/if_aironet_ieee.h +++ b/sys/dev/an/if_aironet_ieee.h @@ -336,6 +336,7 @@ struct an_ltv_genconfig { u_int8_t an_magic_packet_ctl; /* 0x99 */ u_int16_t an_rsvd9; }; +#endif #define AN_OPMODE_IBSS_ADHOC 0x0000 #define AN_OPMODE_INFRASTRUCTURE_STATION 0x0001 @@ -395,6 +396,7 @@ struct an_ltv_genconfig { #define AN_HOME_NETWORK 0x0001 #define AN_HOME_INSTALL_AP 0x0002 +#ifndef _KERNEL struct an_ltv_ssidlist { u_int16_t an_len; u_int16_t an_type; diff --git a/sys/dev/an/if_an.c b/sys/dev/an/if_an.c index 2b382842bebf..c7843e6b99ab 100644 --- a/sys/dev/an/if_an.c +++ b/sys/dev/an/if_an.c @@ -113,6 +113,8 @@ #include <net/ethernet.h> #include <net/if_dl.h> #include <net/if_types.h> +#include <net/if_ieee80211.h> +#include <net/if_media.h> #ifdef INET #include <netinet/in.h> @@ -160,6 +162,9 @@ static void an_cache_store __P((struct an_softc *, struct ether_header *, struct mbuf *, unsigned short)); #endif +static int an_media_change __P((struct ifnet *)); +static void an_media_status __P((struct ifnet *, struct ifmediareq *)); + /* * We probe for an Aironet 4500/4800 card by attempting to * read the default SSID list. On reset, the first entry in @@ -380,6 +385,31 @@ int an_attach(sc, unit, flags) sc->an_tx_rate = 0; bzero((char *)&sc->an_stats, sizeof(sc->an_stats)); + ifmedia_init(&sc->an_ifmedia, 0, an_media_change, an_media_status); +#define ADD(m, c) ifmedia_add(&sc->an_ifmedia, (m), (c), NULL) + ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS1, + IFM_IEEE80211_ADHOC, 0), 0); + ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS1, 0, 0), 0); + ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS2, + IFM_IEEE80211_ADHOC, 0), 0); + ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS2, 0, 0), 0); + if(sc->an_caps.an_rates[2] == AN_RATE_5_5MBPS) { + ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS5, + IFM_IEEE80211_ADHOC, 0), 0); + ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS5, 0, 0), 0); + } + if(sc->an_caps.an_rates[3] == AN_RATE_11MBPS) { + ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS11, + IFM_IEEE80211_ADHOC, 0), 0); + ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS11, 0, 0), 0); + } + ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_AUTO, + IFM_IEEE80211_ADHOC, 0), 0); + ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_AUTO, 0, 0), 0); +#undef ADD + ifmedia_set(&sc->an_ifmedia, IFM_MAKEWORD(IFM_IEEE80211, IFM_AUTO, + 0, 0)); + /* * Call MI attach routine. */ @@ -713,10 +743,10 @@ static int an_read_record(sc, ltv) * room to hold all of the returned data). */ len = CSR_READ_2(sc, AN_DATA1); - if (len > ltv->an_len) { + if (len > (ltv->an_len - 2)) { printf("an%d: record length mismatch -- expected %d, " - "got %d\n", sc->an_unit, ltv->an_len, len); - return(ENOSPC); + "got %d\n", sc->an_unit, (ltv->an_len - 2), len); + len = (ltv->an_len - 2); } ltv->an_len = len; @@ -981,14 +1011,29 @@ static int an_ioctl(ifp, command, data) caddr_t data; { int 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; sc = ifp->if_softc; AN_LOCK(sc); 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; @@ -1020,6 +1065,10 @@ static int an_ioctl(ifp, command, data) 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. */ @@ -1059,6 +1108,369 @@ static int an_ioctl(ifp, command, data) 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<4; i++) { + areq.an_len = sizeof(areq); + if (an_read_record(sc, + (struct an_ltv_gen *)&areq)) { + error = EINVAL; + break; + } + len = key->klen; + if(i == ireq->i_val) + break; + /* Required to get next entry */ + areq.an_type = AN_RID_WEP_PERM; + } + if(error) + 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: + 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) + 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; @@ -1416,6 +1828,7 @@ void an_cache_store (sc, eh, m, rx_quality) static int cache_slot = 0; /* use this cache entry */ static int wrapindex = 0; /* next "free" cache entry */ int saanp=0; + int sig, noise; /* filters: * 1. ip only @@ -1523,3 +1936,84 @@ void an_cache_store (sc, eh, m, rx_quality) return; } #endif + +static int an_media_change(ifp) + struct ifnet *ifp; +{ + struct an_softc *sc = ifp->if_softc; + int otype = sc->an_config.an_opmode; + int orate = sc->an_tx_rate; + + if ((sc->an_ifmedia.ifm_cur->ifm_media & IFM_IEEE80211_ADHOC) != 0) + sc->an_config.an_opmode = AN_OPMODE_IBSS_ADHOC; + else + sc->an_config.an_opmode = AN_OPMODE_INFRASTRUCTURE_STATION; + + switch (IFM_SUBTYPE(sc->an_ifmedia.ifm_cur->ifm_media)) { + case IFM_IEEE80211_DS1: + sc->an_tx_rate = AN_RATE_1MBPS; + break; + case IFM_IEEE80211_DS2: + sc->an_tx_rate = AN_RATE_2MBPS; + break; + case IFM_IEEE80211_DS5: + sc->an_tx_rate = AN_RATE_5_5MBPS; + break; + case IFM_IEEE80211_DS11: + sc->an_tx_rate = AN_RATE_11MBPS; + break; + case IFM_AUTO: + sc->an_tx_rate = 0; + break; + } + + if (otype != sc->an_config.an_opmode || + orate != sc->an_tx_rate) + an_init(sc); + + return(0); +} + +static void an_media_status(ifp, imr) + struct ifnet *ifp; + struct ifmediareq *imr; +{ + struct an_ltv_status status; + struct an_softc *sc = ifp->if_softc; + + status.an_len = sizeof(status); + status.an_type = AN_RID_STATUS; + if (an_read_record(sc, (struct an_ltv_gen *)&status)) { + /* If the status read fails, just lie. */ + imr->ifm_active = sc->an_ifmedia.ifm_cur->ifm_media; + imr->ifm_status = IFM_AVALID|IFM_ACTIVE; + } + + if(sc->an_tx_rate == 0) { + imr->ifm_active = IFM_IEEE80211|IFM_AUTO; + if (sc->an_config.an_opmode == AN_OPMODE_IBSS_ADHOC) + imr->ifm_active |= IFM_IEEE80211_ADHOC; + switch(status.an_current_tx_rate) { + case AN_RATE_1MBPS: + imr->ifm_active |= IFM_IEEE80211_DS1; + break; + case AN_RATE_2MBPS: + imr->ifm_active |= IFM_IEEE80211_DS2; + break; + case AN_RATE_5_5MBPS: + imr->ifm_active |= IFM_IEEE80211_DS5; + break; + case AN_RATE_11MBPS: + imr->ifm_active |= IFM_IEEE80211_DS11; + break; + } + } else { + imr->ifm_active = sc->an_ifmedia.ifm_cur->ifm_media; + } + + imr->ifm_status = IFM_AVALID; + if (sc->an_config.an_opmode == AN_OPMODE_IBSS_ADHOC) + imr->ifm_status |= IFM_ACTIVE; + else if (status.an_opmode & AN_STATUS_OPMODE_ASSOCIATED) + imr->ifm_status |= IFM_ACTIVE; +} diff --git a/sys/dev/an/if_an_isa.c b/sys/dev/an/if_an_isa.c index 29e6c2869580..8ece54de82dc 100644 --- a/sys/dev/an/if_an_isa.c +++ b/sys/dev/an/if_an_isa.c @@ -63,6 +63,7 @@ #include <net/ethernet.h> #include <net/if_dl.h> #include <net/if_types.h> +#include <net/if_media.h> #include <isa/isavar.h> #include <isa/pnpvar.h> @@ -137,6 +138,7 @@ an_detach_isa(device_t dev) struct ifnet *ifp = &sc->arpcom.ac_if; an_stop(sc); + ifmedia_removeall(&sc->an_ifmedia); ether_ifdetach(ifp, ETHER_BPF_SUPPORTED); bus_teardown_intr(dev, sc->irq_res, sc->irq_handle); an_release_resources(dev); diff --git a/sys/dev/an/if_an_pccard.c b/sys/dev/an/if_an_pccard.c index ebb78036271a..dc91b0fa5095 100644 --- a/sys/dev/an/if_an_pccard.c +++ b/sys/dev/an/if_an_pccard.c @@ -64,6 +64,7 @@ #include <net/ethernet.h> #include <net/if_dl.h> #include <net/if_types.h> +#include <net/if_media.h> #ifndef lint static const char rcsid[] = @@ -111,6 +112,7 @@ an_pccard_detach(device_t dev) return(0); } an_stop(sc); + ifmedia_removeall(&sc->an_ifmedia); ifp->if_flags &= ~IFF_RUNNING; ether_ifdetach(ifp, ETHER_BPF_SUPPORTED); sc->an_gone = 1; diff --git a/sys/dev/an/if_an_pci.c b/sys/dev/an/if_an_pci.c index bde0f3df9c5b..47099e82aeeb 100644 --- a/sys/dev/an/if_an_pci.c +++ b/sys/dev/an/if_an_pci.c @@ -76,6 +76,7 @@ #include <net/if_arp.h> #include <net/ethernet.h> #include <net/if_dl.h> +#include <net/if_media.h> #include <pci/pcireg.h> #include <pci/pcivar.h> @@ -195,6 +196,7 @@ an_detach_pci(device_t dev) struct ifnet *ifp = &sc->arpcom.ac_if; an_stop(sc); + ifmedia_removeall(&sc->an_ifmedia); ether_ifdetach(ifp, ETHER_BPF_SUPPORTED); bus_teardown_intr(dev, sc->irq_res, sc->irq_handle); an_release_resources(dev); diff --git a/sys/dev/an/if_anreg.h b/sys/dev/an/if_anreg.h index 844d4807a3ee..e86e354b74dd 100644 --- a/sys/dev/an/if_anreg.h +++ b/sys/dev/an/if_anreg.h @@ -34,8 +34,8 @@ #define AN_TIMEOUT 65536 -/* Default network name: ANY */ -#define AN_DEFAULT_NETNAME "ANY" +/* Default network name: <empty string> */ +#define AN_DEFAULT_NETNAME "" /* The nodename must be less than 16 bytes */ #define AN_DEFAULT_NODENAME "FreeBSD" @@ -846,6 +846,7 @@ struct an_softc { struct callout_handle an_stat_ch; struct mtx an_mtx; device_t an_dev; + struct ifmedia an_ifmedia; }; #define AN_LOCK(_sc) mtx_lock(&(_sc)->an_mtx) diff --git a/sys/dev/awi/awi.c b/sys/dev/awi/awi.c index 4dab87bbcc6d..fdfa82260182 100644 --- a/sys/dev/awi/awi.c +++ b/sys/dev/awi/awi.c @@ -455,9 +455,12 @@ awi_ioctl(ifp, cmd, data) struct awi_softc *sc = ifp->if_softc; struct ifreq *ifr = (struct ifreq *)data; struct ifaddr *ifa = (struct ifaddr *)data; + struct ieee80211req *ireq = (struct ieee80211req *)data; int s, error; struct ieee80211_nwid nwid; u_int8_t *p; + int len; + u_int8_t tmpstr[IEEE80211_NWID_LEN*2]; s = splnet(); @@ -566,6 +569,184 @@ awi_ioctl(ifp, cmd, data) error = ifmedia_ioctl(ifp, ifr, &sc->sc_media, cmd); break; #endif +#ifdef __FreeBSD__ + case SIOCG80211: + switch(ireq->i_type) { + case IEEE80211_IOC_SSID: + bzero(tmpstr, IEEE80211_NWID_LEN); + if(ireq->i_val == -1 && ifp->if_flags & IFF_RUNNING) { + if (sc->sc_mib_local.Network_Mode) { + p = sc->sc_bss.essid; + len = p[1]; + p += 2; + } else { + len = ETHER_ADDR_LEN; + p = sc->sc_bss.bssid; + } + } else if(ireq->i_val == 0) { + if (sc->sc_mib_local.Network_Mode) + p = sc->sc_mib_mac.aDesired_ESS_ID; + else + p = sc->sc_ownssid; + len = p[1]; + p += 2; + } else { + error = EINVAL; + break; + } + if(len > IEEE80211_NWID_LEN) { + error = EINVAL; + break; + } + bcopy(p, tmpstr, len); + error = copyout(tmpstr, ireq->i_data, + IEEE80211_NWID_LEN); + break; + case IEEE80211_IOC_NUMSSIDS: + ireq->i_val = 1; + break; + case IEEE80211_IOC_WEP: + /* XXX: I'm not sure this is entierly correct */ + ireq->i_val = awi_wep_getalgo(sc); + if(ireq->i_val != IEEE80211_WEP_OFF) + ireq->i_val = IEEE80211_WEP_ON; + break; + case IEEE80211_IOC_WEPKEY: + if(ireq->i_val < 0 || ireq->i_val > 3) { + error = EINVAL; + break; + } + len = sizeof(tmpstr); + error = awi_wep_getkey(sc, ireq->i_val, tmpstr, &len); + if(error) + break; + if(!suser(curproc)) + bzero(tmpstr, len); + ireq->i_val = len; + error = copyout(tmpstr, ireq->i_data, len); + break; + case IEEE80211_IOC_NUMWEPKEYS: + ireq->i_val = 4; + break; + case IEEE80211_IOC_WEPTXKEY: + ireq->i_val = sc->sc_wep_defkid; + break; + case IEEE80211_IOC_AUTHMODE: + /* XXX: Is this correct? */ + ireq->i_val = IEEE80211_AUTH_OPEN; + break; + case IEEE80211_IOC_STATIONNAME: + bzero(tmpstr, IEEE80211_NWID_LEN); + p = hostname; + len = strlen(hostname); + if(len > IEEE80211_NWID_LEN) { + error = EINVAL; + break; + } + bcopy(p, tmpstr, len); + error = copyout(tmpstr, ireq->i_data, + IEEE80211_NWID_LEN); + break; + case IEEE80211_IOC_CHANNEL: + /* XXX: Handle FH cards */ + ireq->i_val = sc->sc_bss.chanset; + break; + case IEEE80211_IOC_POWERSAVE: + /* + * There appears to be a mib for this in the + * softc, but since there's no way to enable + * powersaving reporting it's value isn't really + * meaningfull. + */ + ireq->i_val = IEEE80211_POWERSAVE_NOSUP; + break; + case IEEE80211_IOC_POWERSAVESLEEP: + error = EINVAL; + break; + default: + error = EINVAL; + break; + } + break; + case SIOCS80211: + error = suser(curproc); + if(error) + break; + switch(ireq->i_type) { + case IEEE80211_IOC_SSID: + if(ireq->i_val != 0) { + error = EINVAL; + break; + } + bzero(tmpstr, AWI_ESS_ID_SIZE); + tmpstr[0] = IEEE80211_ELEMID_SSID; + tmpstr[1] = ireq->i_val; + error = copyin(ireq->i_data, tmpstr+2, ireq->i_val); + if(error) + break; + bcopy(tmpstr, sc->sc_mib_mac.aDesired_ESS_ID, + AWI_ESS_ID_SIZE); + bcopy(tmpstr, sc->sc_ownssid, AWI_ESS_ID_SIZE); + break; + case IEEE80211_IOC_WEP: + if(ireq->i_val == IEEE80211_WEP_OFF) + error = awi_wep_setalgo(sc, 0); + else + error = awi_wep_setalgo(sc, 1); + break; + case IEEE80211_IOC_WEPKEY: + error = copyin(ireq->i_data, tmpstr, 14); + if(error) + break; + if(ireq->i_val < 0 || ireq->i_val > 3 || + tmpstr[0] > 13) { + error = EINVAL; + break; + } + error = awi_wep_setkey(sc, ireq->i_val, tmpstr+1, + tmpstr[0]); + break; + case IEEE80211_IOC_WEPTXKEY: + if(ireq->i_val < 0 || ireq->i_val > 3) { + error = EINVAL; + break; + } + sc->sc_wep_defkid = ireq->i_val; + break; + case IEEE80211_IOC_AUTHMODE: + error = EINVAL; + break; + case IEEE80211_IOC_STATIONNAME: + error = EPERM; + break; + case IEEE80211_IOC_CHANNEL: + if(ireq->i_val < sc->sc_scan_min || + ireq->i_val > sc->sc_scan_max) { + error = EINVAL; + break; + } + sc->sc_ownch = ireq->i_val; + break; + case IEEE80211_IOC_POWERSAVE: + if(ireq->i_val != 0) + error = EINVAL; + break; + case IEEE80211_IOC_POWERSAVESLEEP: + error = EINVAL; + break; + default: + error = EINVAL; + break; + } + /* Restart the card so the change takes effect */ + if(!error) { + if(sc->sc_enabled) { + awi_stop(sc); + error = awi_init(sc); + } + } + break; +#endif /* __FreeBSD__ */ default: error = awi_wicfg(ifp, cmd, data); break; diff --git a/sys/dev/wi/if_wavelan_ieee.h b/sys/dev/wi/if_wavelan_ieee.h index 5e1046a6c06f..0454898d7c2a 100644 --- a/sys/dev/wi/if_wavelan_ieee.h +++ b/sys/dev/wi/if_wavelan_ieee.h @@ -169,6 +169,7 @@ struct wi_counters { u_int32_t wi_rx_msg_in_msg_frags; u_int32_t wi_rx_msg_in_bad_msg_frags; }; +#endif /* * These are all the LTV record types that we can read or write @@ -247,6 +248,7 @@ struct wi_counters { #define WI_RID_TX_CRYPT_KEY 0xFCB1 #define WI_RID_TICK_TIME 0xFCE0 +#ifndef _KERNEL struct wi_key { u_int16_t wi_keylen; u_int8_t wi_keydat[14]; @@ -257,6 +259,7 @@ struct wi_ltv_keys { u_int16_t wi_type; struct wi_key wi_keys[4]; }; +#endif /* * NIC information @@ -315,7 +318,6 @@ struct wi_ltv_keys { #define WI_RID_CCA_TIME 0xFDC4 /* clear chan assess time */ #define WI_RID_MAC_PROC_DELAY 0xFDC5 /* MAC processing delay time */ #define WI_RID_DATA_RATES 0xFDC6 /* supported data rates */ -#endif #endif diff --git a/sys/dev/wi/if_wi.c b/sys/dev/wi/if_wi.c index 2ae8fd1a1ac2..40cdbc509385 100644 --- a/sys/dev/wi/if_wi.c +++ b/sys/dev/wi/if_wi.c @@ -92,6 +92,7 @@ #include <net/if_dl.h> #include <net/if_media.h> #include <net/if_types.h> +#include <net/if_ieee80211.h> #include <netinet/in.h> #include <netinet/in_systm.h> @@ -161,6 +162,10 @@ static void wi_shutdown __P((device_t)); static int wi_alloc __P((device_t, int)); static void wi_free __P((device_t)); +static int wi_get_cur_ssid __P((struct wi_softc *, char *, int *)); +static int wi_media_change __P((struct ifnet *)); +static void wi_media_status __P((struct ifnet *, struct ifmediareq *)); + static device_method_t wi_pccard_methods[] = { /* Device interface */ DEVMETHOD(device_probe, pccard_compat_probe), @@ -282,6 +287,9 @@ static int wi_pccard_detach(dev) wi_stop(sc); + /* Delete all remaining media. */ + ifmedia_removeall(&sc->ifmedia); + ether_ifdetach(ifp, ETHER_BPF_SUPPORTED); bus_teardown_intr(dev, sc->irq, sc->wi_intrhand); wi_free(dev); @@ -511,6 +519,29 @@ wi_generic_attach(device_t dev) wi_init(sc); wi_stop(sc); + ifmedia_init(&sc->ifmedia, 0, wi_media_change, wi_media_status); + /* XXX: Should read from card capabilities */ +#define ADD(m, c) ifmedia_add(&sc->ifmedia, (m), (c), NULL) + ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS1, + IFM_IEEE80211_ADHOC, 0), 0); + ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS1, 0, 0), 0); + ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS2, + IFM_IEEE80211_ADHOC, 0), 0); + ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS2, 0, 0), 0); + ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS5, + IFM_IEEE80211_ADHOC, 0), 0); + ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS5, 0, 0), 0); + ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS11, + IFM_IEEE80211_ADHOC, 0), 0); + ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS11, 0, 0), 0); + ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_AUTO, + IFM_IEEE80211_ADHOC, 0), 0); + ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_AUTO, 0, 0), 0); +#undef ADD + ifmedia_set(&sc->ifmedia, IFM_MAKEWORD(IFM_IEEE80211, IFM_AUTO, + 0, 0)); + + /* * Call MI attach routine. */ @@ -1297,14 +1328,19 @@ static int wi_ioctl(ifp, command, data) caddr_t data; { int error = 0; + int len; + u_int8_t tmpkey[14]; + char tmpssid[IEEE80211_NWID_LEN]; struct wi_softc *sc; struct wi_req wreq; struct ifreq *ifr; + struct ieee80211req *ireq; struct proc *p = curproc; sc = ifp->if_softc; WI_LOCK(sc); ifr = (struct ifreq *)data; + ireq = (struct ieee80211req *)data; if (sc->wi_gone) { error = ENODEV; @@ -1337,6 +1373,10 @@ static int wi_ioctl(ifp, command, data) sc->wi_if_flags = ifp->if_flags; error = 0; break; + case SIOCSIFMEDIA: + case SIOCGIFMEDIA: + error = ifmedia_ioctl(ifp, ifr, &sc->ifmedia, command); + break; case SIOCADDMULTI: case SIOCDELMULTI: wi_setmulti(sc); @@ -1398,6 +1438,203 @@ static int wi_ioctl(ifp, command, data) wi_setdef(sc, &wreq); } break; + case SIOCG80211: + switch(ireq->i_type) { + case IEEE80211_IOC_SSID: + if(ireq->i_val == -1) { + bzero(tmpssid, IEEE80211_NWID_LEN); + error = wi_get_cur_ssid(sc, tmpssid, &len); + if (error != 0) + break; + error = copyout(tmpssid, ireq->i_data, + IEEE80211_NWID_LEN); + ireq->i_len = len; + } else if (ireq->i_val == 0) { + error = copyout(sc->wi_net_name, + ireq->i_data, + IEEE80211_NWID_LEN); + ireq->i_len = IEEE80211_NWID_LEN; + } else + error = EINVAL; + break; + case IEEE80211_IOC_NUMSSIDS: + ireq->i_val = 1; + break; + case IEEE80211_IOC_WEP: + if(!sc->wi_has_wep) { + ireq->i_val = IEEE80211_WEP_NOSUP; + } else { + if(sc->wi_use_wep) { + ireq->i_val = + IEEE80211_WEP_MIXED; + } else { + ireq->i_val = + IEEE80211_WEP_OFF; + } + } + break; + case IEEE80211_IOC_WEPKEY: + if(!sc->wi_has_wep || + ireq->i_val < 0 || ireq->i_val > 3) { + error = EINVAL; + break; + } + len = sc->wi_keys.wi_keys[ireq->i_val].wi_keylen; + if (suser(p)) + bcopy(sc->wi_keys.wi_keys[ireq->i_val].wi_keydat, + tmpkey, len); + else + bzero(tmpkey, len); + + ireq->i_len = len; + error = copyout(tmpkey, ireq->i_data, len); + + break; + case IEEE80211_IOC_NUMWEPKEYS: + if(!sc->wi_has_wep) + error = EINVAL; + else + ireq->i_val = 4; + break; + case IEEE80211_IOC_WEPTXKEY: + if(!sc->wi_has_wep) + error = EINVAL; + else + ireq->i_val = sc->wi_tx_key; + break; + case IEEE80211_IOC_AUTHMODE: + ireq->i_val = IEEE80211_AUTH_NONE; + break; + case IEEE80211_IOC_STATIONNAME: + error = copyout(sc->wi_node_name, + ireq->i_data, IEEE80211_NWID_LEN); + ireq->i_len = IEEE80211_NWID_LEN; + break; + case IEEE80211_IOC_CHANNEL: + wreq.wi_type = WI_RID_CURRENT_CHAN; + wreq.wi_len = WI_MAX_DATALEN; + if (wi_read_record(sc, (struct wi_ltv_gen *)&wreq)) + error = EINVAL; + else { + ireq->i_val = wreq.wi_val[0]; + } + break; + case IEEE80211_IOC_POWERSAVE: + if(sc->wi_pm_enabled) + ireq->i_val = IEEE80211_POWERSAVE_ON; + else + ireq->i_val = IEEE80211_POWERSAVE_OFF; + break; + case IEEE80211_IOC_POWERSAVESLEEP: + ireq->i_val = sc->wi_max_sleep; + break; + default: + error = EINVAL; + } + break; + case SIOCS80211: + if ((error = suser(p))) + goto out; + switch(ireq->i_type) { + case IEEE80211_IOC_SSID: + if (ireq->i_val != 0 || + ireq->i_len > IEEE80211_NWID_LEN) { + error = EINVAL; + break; + } + /* We set both of them */ + bzero(sc->wi_net_name, IEEE80211_NWID_LEN); + error = copyin(ireq->i_data, + sc->wi_net_name, ireq->i_len); + bcopy(sc->wi_net_name, sc->wi_ibss_name, IEEE80211_NWID_LEN); + break; + case IEEE80211_IOC_WEP: + /* + * These cards only support one mode so + * we just turn wep on what ever is + * passed in if it's not OFF. + */ + if (ireq->i_val == IEEE80211_WEP_OFF) { + sc->wi_use_wep = 0; + } else { + sc->wi_use_wep = 1; + } + break; + case IEEE80211_IOC_WEPKEY: + if (ireq->i_val < 0 || ireq->i_val > 3 || + ireq->i_len > 13) { + error = EINVAL; + break; + } + bzero(sc->wi_keys.wi_keys[ireq->i_val].wi_keydat, 13); + error = copyin(ireq->i_data, + sc->wi_keys.wi_keys[ireq->i_val].wi_keydat, + ireq->i_len); + if(error) + break; + sc->wi_keys.wi_keys[ireq->i_val].wi_keylen = + ireq->i_len; + break; + case IEEE80211_IOC_WEPTXKEY: + if (ireq->i_val < 0 || ireq->i_val > 3) { + error = EINVAL; + break; + } + sc->wi_tx_key = ireq->i_val; + break; + case IEEE80211_IOC_AUTHMODE: + error = EINVAL; + break; + case IEEE80211_IOC_STATIONNAME: + if (ireq->i_len > 32) { + error = EINVAL; + break; + } + bzero(sc->wi_node_name, 32); + error = copyin(ireq->i_data, + sc->wi_node_name, 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; + } + sc->wi_channel = ireq->i_val; + break; + case IEEE80211_IOC_POWERSAVE: + switch (ireq->i_val) { + case IEEE80211_POWERSAVE_OFF: + sc->wi_pm_enabled = 0; + break; + case IEEE80211_POWERSAVE_ON: + sc->wi_pm_enabled = 1; + break; + default: + error = EINVAL; + break; + } + break; + case IEEE80211_IOC_POWERSAVESLEEP: + if (ireq->i_val < 0) { + error = EINVAL; + break; + } + sc->wi_max_sleep = ireq->i_val; + break; + default: + error = EINVAL; + break; + } + + /* Reinitialize WaveLAN. */ + wi_init(sc); + + break; default: error = EINVAL; break; @@ -1966,3 +2203,142 @@ void wi_cache_store (struct wi_softc *sc, struct ether_header *eh, return; } #endif + +static int wi_get_cur_ssid(sc, ssid, len) + struct wi_softc *sc; + char *ssid; + int *len; +{ + int error = 0; + struct wi_req wreq; + + wreq.wi_len = WI_MAX_DATALEN; + switch (sc->wi_ptype) { + case WI_PORTTYPE_ADHOC: + wreq.wi_type = WI_RID_CURRENT_SSID; + error = wi_read_record(sc, (struct wi_ltv_gen *)&wreq); + if (error != 0) + break; + if (wreq.wi_val[0] > IEEE80211_NWID_LEN) { + error = EINVAL; + break; + } + *len = wreq.wi_val[0]; + bcopy(&wreq.wi_val[1], ssid, IEEE80211_NWID_LEN); + break; + case WI_PORTTYPE_BSS: + wreq.wi_type = WI_RID_COMMQUAL; + error = wi_read_record(sc, (struct wi_ltv_gen *)&wreq); + if (error != 0) + break; + if (wreq.wi_val[0] != 0) /* associated */ { + wreq.wi_type = WI_RID_CURRENT_SSID; + wreq.wi_len = WI_MAX_DATALEN; + error = wi_read_record(sc, (struct wi_ltv_gen *)&wreq); + if (error != 0) + break; + if (wreq.wi_val[0] > IEEE80211_NWID_LEN) { + error = EINVAL; + break; + } + *len = wreq.wi_val[0]; + bcopy(&wreq.wi_val[1], ssid, IEEE80211_NWID_LEN); + } else { + *len = IEEE80211_NWID_LEN; + bcopy(sc->wi_net_name, ssid, IEEE80211_NWID_LEN); + } + break; + default: + error = EINVAL; + break; + } + + return error; +} + +static int wi_media_change(ifp) + struct ifnet *ifp; +{ + struct wi_softc *sc = ifp->if_softc; + int otype = sc->wi_ptype; + int orate = sc->wi_tx_rate; + + if ((sc->ifmedia.ifm_cur->ifm_media & IFM_IEEE80211_ADHOC) != 0) + sc->wi_ptype = WI_PORTTYPE_ADHOC; + else + sc->wi_ptype = WI_PORTTYPE_BSS; + + switch (IFM_SUBTYPE(sc->ifmedia.ifm_cur->ifm_media)) { + case IFM_IEEE80211_DS1: + sc->wi_tx_rate = 1; + break; + case IFM_IEEE80211_DS2: + sc->wi_tx_rate = 2; + break; + case IFM_IEEE80211_DS5: + sc->wi_tx_rate = 5; + break; + case IFM_IEEE80211_DS11: + sc->wi_tx_rate = 11; + break; + case IFM_AUTO: + sc->wi_tx_rate = 3; + break; + } + + if (otype != sc->wi_ptype || + orate != sc->wi_tx_rate) + wi_init(sc); + + return(0); +} + +static void wi_media_status(ifp, imr) + struct ifnet *ifp; + struct ifmediareq *imr; +{ + struct wi_req wreq; + struct wi_softc *sc = ifp->if_softc; + + if (sc->wi_tx_rate == 3) { + imr->ifm_active = IFM_IEEE80211|IFM_AUTO; + if (sc->wi_ptype == WI_PORTTYPE_ADHOC) + imr->ifm_active |= IFM_IEEE80211_ADHOC; + wreq.wi_type = WI_RID_CUR_TX_RATE; + wreq.wi_len = WI_MAX_DATALEN; + if (wi_read_record(sc, (struct wi_ltv_gen *)&wreq) == 0) { + switch(wreq.wi_val[0]) { + case 1: + imr->ifm_active |= IFM_IEEE80211_DS1; + break; + case 2: + imr->ifm_active |= IFM_IEEE80211_DS2; + break; + case 6: + imr->ifm_active |= IFM_IEEE80211_DS5; + break; + case 11: + imr->ifm_active |= IFM_IEEE80211_DS11; + break; + } + } + } else { + imr->ifm_active = sc->ifmedia.ifm_cur->ifm_media; + } + + imr->ifm_status = IFM_AVALID; + if (sc->wi_ptype == WI_PORTTYPE_ADHOC) + /* + * XXX: It would be nice if we could give some actually + * useful status like whether we joined another IBSS or + * created one ourselves. + */ + imr->ifm_status |= IFM_ACTIVE; + else { + wreq.wi_type = WI_RID_COMMQUAL; + wreq.wi_len = WI_MAX_DATALEN; + if (wi_read_record(sc, (struct wi_ltv_gen *)&wreq) == 0 && + wreq.wi_val[0] != 0) + imr->ifm_status |= IFM_ACTIVE; + } +} diff --git a/sys/net/if_ieee80211.h b/sys/net/if_ieee80211.h index a95498fb843d..a6e866e3bbe3 100644 --- a/sys/net/if_ieee80211.h +++ b/sys/net/if_ieee80211.h @@ -229,4 +229,43 @@ struct ieee80211_nwkey { #define SIOCS80211NWKEY _IOW('i', 232, struct ieee80211_nwkey) #define SIOCG80211NWKEY _IOWR('i', 233, struct ieee80211_nwkey) +#define IEEE80211_WEP_NOSUP -1 +#define IEEE80211_WEP_OFF 0 +#define IEEE80211_WEP_ON 1 +#define IEEE80211_WEP_MIXED 2 + +#define IEEE80211_AUTH_NONE 0 +#define IEEE80211_AUTH_OPEN 1 +#define IEEE80211_AUTH_SHARED 2 + +#define IEEE80211_POWERSAVE_NOSUP -1 +#define IEEE80211_POWERSAVE_OFF 0 +#define IEEE80211_POWERSAVE_CAM 1 +#define IEEE80211_POWERSAVE_PSP 2 +#define IEEE80211_POWERSAVE_PSP_CAM 3 +#define IEEE80211_POWERSAVE_ON IEEE80211_POWERSAVE_CAM + +/* the first member must be matched with struct ifreq */ +struct ieee80211req { + char i_name[IFNAMSIZ]; /* if_name, e.g. "wi0" */ + u_int16_t i_type; /* req type */ + int16_t i_val; /* Index or simple value */ + int16_t i_len; /* Index or simple value */ + void *i_data; /* Extra data */ +}; +#define SIOCS80211 _IOW('i', 234, struct ieee80211req) +#define SIOCG80211 _IOWR('i', 235, struct ieee80211req) + +#define IEEE80211_IOC_SSID 1 +#define IEEE80211_IOC_NUMSSIDS 2 +#define IEEE80211_IOC_WEP 3 +#define IEEE80211_IOC_WEPKEY 4 +#define IEEE80211_IOC_NUMWEPKEYS 5 +#define IEEE80211_IOC_WEPTXKEY 6 +#define IEEE80211_IOC_AUTHMODE 7 +#define IEEE80211_IOC_STATIONNAME 8 +#define IEEE80211_IOC_CHANNEL 9 +#define IEEE80211_IOC_POWERSAVE 10 +#define IEEE80211_IOC_POWERSAVESLEEP 11 + #endif /* !_NET_IF_IEEE80211_H_ */ diff --git a/sys/net/if_media.c b/sys/net/if_media.c index 691c8cdfad7c..fd372ca5e03b 100644 --- a/sys/net/if_media.c +++ b/sys/net/if_media.c @@ -401,6 +401,12 @@ struct ifmedia_description ifm_subtype_fddi_descriptions[] = struct ifmedia_description ifm_subtype_fddi_option_descriptions[] = IFM_SUBTYPE_FDDI_OPTION_DESCRIPTIONS; +struct ifmedia_description ifm_subtype_ieee80211_descriptions[] = + IFM_SUBTYPE_IEEE80211_DESCRIPTIONS; + +struct ifmedia_description ifm_subtype_ieee80211_option_descriptions[] = + IFM_SUBTYPE_IEEE80211_OPTION_DESCRIPTIONS; + struct ifmedia_description ifm_subtype_shared_descriptions[] = IFM_SUBTYPE_SHARED_DESCRIPTIONS; @@ -426,6 +432,10 @@ struct ifmedia_type_to_subtype ifmedia_types_to_subtypes[] = { &ifm_subtype_fddi_descriptions[0], &ifm_subtype_fddi_option_descriptions[0] }, + { + &ifm_subtype_ieee80211_descriptions[0], + &ifm_subtype_ieee80211_option_descriptions[0] + }, }; /* diff --git a/sys/net/if_media.h b/sys/net/if_media.h index 2ed5ed0171c7..52bbdbd3667b 100644 --- a/sys/net/if_media.h +++ b/sys/net/if_media.h @@ -167,6 +167,19 @@ int ifmedia_ioctl __P((struct ifnet *ifp, struct ifreq *ifr, #define IFM_FDDI_DA 0x00000100 /* Dual attach / single attach */ /* + * IEEE 802.11 Wireless + */ +#define IFM_IEEE80211 0x00000080 +#define IFM_IEEE80211_FH1 3 /* Frequency Hopping 1Mbps */ +#define IFM_IEEE80211_FH2 4 /* Frequency Hopping 2Mbps */ +#define IFM_IEEE80211_DS1 5 /* Direct Sequence 1Mbps */ +#define IFM_IEEE80211_DS2 6 /* Direct Sequence 2Mbps */ +#define IFM_IEEE80211_DS5 7 /* Direct Sequence 5.5Mbps */ +#define IFM_IEEE80211_DS11 8 /* Direct Sequence 11Mbps */ +#define IFM_IEEE80211_DS22 9 /* Direct Sequence 22Mbps */ +#define IFM_IEEE80211_ADHOC 0x00000100 /* Operate in Adhoc mode */ + +/* * Shared media sub-types */ #define IFM_AUTO 0 /* Autoselect best media */ @@ -229,9 +242,10 @@ struct ifmedia_description { }; #define IFM_TYPE_DESCRIPTIONS { \ - { IFM_ETHER, "Ethernet" }, \ - { IFM_TOKEN, "Token ring" }, \ - { IFM_FDDI, "FDDI" }, \ + { IFM_ETHER, "Ethernet" }, \ + { IFM_TOKEN, "Token ring" }, \ + { IFM_FDDI, "FDDI" }, \ + { IFM_IEEE80211, "IEEE 802.11 Wireless Ethernet" }, \ { 0, NULL }, \ } @@ -330,6 +344,40 @@ struct ifmedia_description { { 0, NULL }, \ } +#define IFM_SUBTYPE_IEEE80211_DESCRIPTIONS { \ + { IFM_IEEE80211_FH1, "FH/1Mbps" }, \ + { IFM_IEEE80211_FH2, "FH/2Mbps" }, \ + { IFM_IEEE80211_DS1, "DS/1Mbps" }, \ + { IFM_IEEE80211_DS2, "DS/2Mbps" }, \ + { IFM_IEEE80211_DS5, "DS/5.5Mbps" }, \ + { IFM_IEEE80211_DS11, "DS/11Mbps" }, \ + { IFM_IEEE80211_DS22, "DS/22Mbps" }, \ + { 0, NULL }, \ +} + +#define IFM_SUBTYPE_IEEE80211_ALIASES { \ + { IFM_IEEE80211_FH1, "FH1" }, \ + { IFM_IEEE80211_FH2, "FH2" }, \ + { IFM_IEEE80211_FH1, "FrequencyHopping/1Mbps" }, \ + { IFM_IEEE80211_FH2, "FrequencyHopping/2Mbps" }, \ + { IFM_IEEE80211_DS1, "DS1" }, \ + { IFM_IEEE80211_DS2, "DS2" }, \ + { IFM_IEEE80211_DS5, "DS5.5" }, \ + { IFM_IEEE80211_DS11, "DS11" }, \ + { IFM_IEEE80211_DS22, "DS22" }, \ + { IFM_IEEE80211_DS1, "DirectSequence/1Mbps" }, \ + { IFM_IEEE80211_DS2, "DirectSequence/2Mbps" }, \ + { IFM_IEEE80211_DS5, "DirectSequence/5.5Mbps" }, \ + { IFM_IEEE80211_DS11, "DirectSequence/11Mbps" }, \ + { IFM_IEEE80211_DS22, "DirectSequence/22Mbps" }, \ + { 0, NULL }, \ +} + +#define IFM_SUBTYPE_IEEE80211_OPTION_DESCRIPTIONS { \ + { IFM_IEEE80211_ADHOC, "adhoc" }, \ + { 0, NULL }, \ +} + #define IFM_SUBTYPE_SHARED_DESCRIPTIONS { \ { IFM_AUTO, "autoselect" }, \ { IFM_MANUAL, "manual" }, \ |
