Currently, each wireless networking driver has it's own control program

despite the fact that most people want to set exactly the same settings
regardless of which card they have.  It has been repeatidly suggested
that this configuration should be done via ifconfig.  This patch
implements the required functionality in ifconfig and add support to the
wi and an drivers.  It also provides partial, untested support for the
awi driver.

PR:		25577
Submitted by:	Brooks Davis <brooks@one-eyed-alien.net>
This commit is contained in:
Poul-Henning Kamp 2001-05-26 09:27:08 +00:00
parent 3344c5a17e
commit 419d8080a4
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=77217
18 changed files with 1351 additions and 12 deletions

View File

@ -15,6 +15,10 @@ SRCS+= ifvlan.c
CFLAGS+=-DUSE_VLANS
.endif
#comment out to exclude SIOC[GS]IEEE80211 support
SRCS+= ifieee80211.c
CFLAGS+=-DUSE_IEEE80211
MAN= ifconfig.8
DPADD= ${LIBIPX}
LDADD= -lipx

View File

@ -413,6 +413,111 @@ This may be used to enable an interface after an
It happens automatically when setting the first address on an interface.
If the interface was reset when previously marked down,
the hardware will be re-initialized.
.It Cm ssid Ar ssid
For IEEE 802.11 wireless interfaces, set the desired Service Set
Identifier (aka network name.) The SSID is a string up to 32 characters
in length and may be specified as either a normal string or in
hexadecimal when proceeded by
.Sq 0x .
Additionally, the SSID may be cleared by setting it to
.Sq - .
.It Cm nwid Ar ssid
Another name for the
.Dq ssid
parameter. Included for NetBSD compatibility.
.It Cm stationname Ar name
For IEEE 802.11 wireless interfaces, set the name of this station.
It appears that the station name is not really part of the IEEE 802.11
protocol though all interfaces seem to support it. As such it only
seems to be meaningful to identical or virtually identical equipment.
Setting the station name is identical in syntax to setting the SSID.
.It Cm station Ar name
Another name for the
.Dq stationname
parameter. Included for BSD/OS compatibility.
.It Cm channel Ar number
For IEEE 802.11 wireless interfaces, set the desired channel.
Channels range from 1 to 14, but the exact selection available
depends on the region your adaptor was manufactured for. Setting
the channel to 0 will give you the default for your adaptor. Many
adaptors ignore this setting unless you are in ad-hoc mode.
.It Cm authmode Ar mode
For IEEE 802.11 wireless interfaces, set the desired authentication mode
in infrastructure mode. Not all adaptors support all modes. The set of
valid modes is
.Dq none ,
.Dq open ,
and
.Dq shared .
Modes are case insensitive.
.It Cm powersave
For IEEE 802.11 wireless interfaces, enable powersave mode.
.It Cm -powersave
For IEEE 802.11 wireless interfaces, disable powersave mode.
.It Cm powersavesleep Ar sleep
For IEEE 802.11 wireless interfaces, set the desired max powersave sleep
time in milliseconds.
.It Cm wepmode Ar mode
For IEEE 802.11 wireless interfaces, set the desired WEP mode. Not all
adaptors support all modes. The set of valid modes is
.Dq off ,
.Dq on ,
and
.Dq mixed .
.Dq Mixed
mode explicitly tells the adaptor to allow association with access
points which allow both encrypted and unencrypted traffic. On these
adaptors,
.Dq on
means that the access point must only allow encrypted connections. On
other adaptors,
.Dq on
is generally another name for
.Dq mixed .
Modes are case insensitive.
.It Cm weptxkey Ar index
For IEEE 802.11 wireless interfaces, set the WEP key to be used for
transmission.
.It Cm wepkey Ar key|index:key
For IEEE 802.11 wireless interfaces, set the selected WEP key. If
an
.Ar index
is not given, key 1 is set. A WEP key will be either 5 or 13
characters (40 or 104 bits) depending of the local network and the
capabilities of the adaptor. It may be specified either as a plain
string or as a string of hexadecimal digits proceeded by
.Sq 0x .
A key may be cleared by setting it to
.Sq - .
If WEP is supported then there are at least four keys. Some adaptors
support more then four keys. If that is the case, then the first four keys
(1-4) will be the standard temporary keys and any others will be adaptor
specific keys such as permanent keys stored in NVRAM.
.It Cm wep
Another way of saying
.Dq wepmode on .
Included for BSD/OS compatibility.
.It Cm -wep
Another way of saying
.Dq wepmode off .
Included for BSD/OS compatibility.
.It Cm nwkey key
Another way of saying:
.Pp
``wepmode on weptxkey 1 wepkey 1:key wepkey 2:- wepkey 3:- wepkey 4:-''.
.Pp
Included for NetBSD compatibility.
.It Cm nwkey n:k1,k2,k3,k4
Another way of saying
.Pp
``wepmode on weptxkey n wepkey 1:k1 wepkey 2:k2 wepkey 3:k3 wepkey 4:k4''.
.Pp
Included for NetBSD compatibility.
.It Cm -nwkey
Another way of saying
.Dq wepmode off .
.Pp
Included for NetBSD compatibility.
.El
.Pp
.Nm Ifconfig

View File

@ -222,6 +222,25 @@ struct cmd {
{ "vlan", NEXTARG, setvlantag },
{ "vlandev", NEXTARG, setvlandev },
{ "-vlandev", NEXTARG, unsetvlandev },
#endif
#ifdef USE_IEEE80211
{ "ssid", NEXTARG, set80211ssid },
{ "nwid", NEXTARG, set80211ssid },
{ "stationname", NEXTARG, set80211stationname },
{ "station", NEXTARG, set80211stationname }, /* BSD/OS */
{ "channel", NEXTARG, set80211channel },
{ "authmode", NEXTARG, set80211authmode },
{ "powersavemode", NEXTARG, set80211powersavemode },
{ "powersave", 1, set80211powersave },
{ "-powersave", 0, set80211powersave },
{ "powersavesleep", NEXTARG, set80211powersavesleep },
{ "wepmode", NEXTARG, set80211wepmode },
{ "wep", 1, set80211wep },
{ "-wep", 0, set80211wep },
{ "weptxkey", NEXTARG, set80211weptxkey },
{ "wepkey", NEXTARG, set80211wepkey },
{ "nwkey", NEXTARG, set80211nwkey }, /* NetBSD */
{ "-nwkey", 0, set80211wep }, /* NetBSD */
#endif
{ "normal", -IFF_LINK0, setifflags },
{ "compress", IFF_LINK0, setifflags },
@ -291,6 +310,9 @@ struct afswtch {
#ifdef USE_VLANS
{ "vlan", AF_UNSPEC, vlan_status, NULL, NULL, }, /* XXX not real!! */
#endif
#ifdef USE_IEEE80211
{ "ieee80211", AF_UNSPEC, ieee80211_status, NULL, NULL, }, /* XXX not real!! */
#endif
#endif
{ 0, 0, 0, 0 }
};
@ -969,6 +991,10 @@ status(afp, addrcount, sdl, ifm, ifam)
#ifdef USE_VLANS
if (allfamilies || afp->af_status == vlan_status)
vlan_status(s, NULL);
#endif
#ifdef USE_IEEE80211
if (allfamilies || afp->af_status == ieee80211_status)
ieee80211_status(s, NULL);
#endif
strncpy(ifs.ifs_name, name, sizeof ifs.ifs_name);
if (ioctl(s, SIOCGIFSTATUS, &ifs) == 0)

View File

@ -49,3 +49,17 @@ extern void setvlantag(const char *, int, int, const struct afswtch *rafp);
extern void setvlandev(const char *, int, int, const struct afswtch *rafp);
extern void unsetvlandev(const char *, int, int, const struct afswtch *rafp);
extern void vlan_status(int s, struct rt_addrinfo *);
extern void set80211ssid(const char *, int, int, const struct afswtch *rafp);
extern void set80211stationname(const char *, int, int, const struct afswtch *rafp);
extern void set80211channel(const char *, int, int, const struct afswtch *rafp);
extern void set80211authmode(const char *, int, int, const struct afswtch *rafp);
extern void set80211powersave(const char *, int, int, const struct afswtch *rafp);
extern void set80211powersavemode(const char *, int, int, const struct afswtch *rafp);
extern void set80211powersavesleep(const char *, int, int, const struct afswtch *rafp);
extern void set80211wepmode(const char *, int, int, const struct afswtch *rafp);
extern void set80211wep(const char *, int, int, const struct afswtch *rafp);
extern void set80211weptxkey(const char *, int, int, const struct afswtch *rafp);
extern void set80211wepkey(const char *, int, int, const struct afswtch *rafp);
extern void set80211nwkey(const char *, int, int, const struct afswtch *rafp);
extern void ieee80211_status(int s, struct rt_addrinfo *);

View File

@ -152,6 +152,13 @@ media_status(s, info)
else
printf("no ring");
break;
case IFM_IEEE80211:
/* XXX: Different value for adhoc? */
if (ifmr.ifm_status & IFM_ACTIVE)
printf("associated");
else
printf("no carrier");
break;
}
}
@ -318,6 +325,15 @@ static struct ifmedia_description ifm_subtype_fddi_aliases[] =
static struct ifmedia_description ifm_subtype_fddi_option_descriptions[] =
IFM_SUBTYPE_FDDI_OPTION_DESCRIPTIONS;
static struct ifmedia_description ifm_subtype_ieee80211_descriptions[] =
IFM_SUBTYPE_IEEE80211_DESCRIPTIONS;
static struct ifmedia_description ifm_subtype_ieee80211_aliases[] =
IFM_SUBTYPE_IEEE80211_ALIASES;
static struct ifmedia_description ifm_subtype_ieee80211_option_descriptions[] =
IFM_SUBTYPE_IEEE80211_OPTION_DESCRIPTIONS;
static struct ifmedia_description ifm_subtype_shared_descriptions[] =
IFM_SUBTYPE_SHARED_DESCRIPTIONS;
@ -350,7 +366,7 @@ static struct ifmedia_type_to_subtype ifmedia_types_to_subtypes[] = {
},
{
{ &ifm_shared_option_descriptions[0], 0 },
{ &ifm_subtype_ethernet_option_descriptions[0], 1 },
{ &ifm_subtype_ethernet_option_descriptions[0], 0 },
{ NULL, 0 },
},
},
@ -364,7 +380,7 @@ static struct ifmedia_type_to_subtype ifmedia_types_to_subtypes[] = {
},
{
{ &ifm_shared_option_descriptions[0], 0 },
{ &ifm_subtype_tokenring_option_descriptions[0], 1 },
{ &ifm_subtype_tokenring_option_descriptions[0], 0 },
{ NULL, 0 },
},
},
@ -378,7 +394,21 @@ static struct ifmedia_type_to_subtype ifmedia_types_to_subtypes[] = {
},
{
{ &ifm_shared_option_descriptions[0], 0 },
{ &ifm_subtype_fddi_option_descriptions[0], 1 },
{ &ifm_subtype_fddi_option_descriptions[0], 0 },
{ NULL, 0 },
},
},
{
{
{ &ifm_subtype_shared_descriptions[0], 0 },
{ &ifm_subtype_shared_aliases[0], 1 },
{ &ifm_subtype_ieee80211_descriptions[0], 0 },
{ &ifm_subtype_ieee80211_aliases[0], 1 },
{ NULL, 0 },
},
{
{ &ifm_shared_option_descriptions[0], 0 },
{ &ifm_subtype_ieee80211_option_descriptions[0], 0 },
{ NULL, 0 },
},
},

View File

@ -43,6 +43,7 @@ MAN= aac.4 \
ichsmb.4 \
icmp.4 \
icmp6.4 \
ieee80211.4 \
ifmib.4 \
iic.4 \
iicbb.4 \

View File

@ -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;

View File

@ -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;
}

View File

@ -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);

View File

@ -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;

View File

@ -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);

View File

@ -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)

View File

@ -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;

View File

@ -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

View File

@ -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);
@ -1397,6 +1437,203 @@ static int wi_ioctl(ifp, command, data)
if (!error)
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;
@ -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;
}
}

View File

@ -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_ */

View File

@ -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]
},
};
/*

View File

@ -166,6 +166,19 @@ int ifmedia_ioctl __P((struct ifnet *ifp, struct ifreq *ifr,
#define IFM_FDDI_UTP 5 /* CDDI / UTP */
#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
*/
@ -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" }, \