Add ifmedia support so that dhcp happy. Also, add nwid support.

This commit is contained in:
enami 2000-03-02 05:00:47 +00:00
parent a5921b902e
commit 027db8bf87
2 changed files with 210 additions and 40 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: if_wi.c,v 1.8 2000/02/27 23:10:51 enami Exp $ */
/* $NetBSD: if_wi.c,v 1.9 2000/03/02 05:00:47 enami Exp $ */
/*
* Copyright (c) 1997, 1998, 1999
@ -31,7 +31,7 @@
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*
* $Id: if_wi.c,v 1.8 2000/02/27 23:10:51 enami Exp $
* $Id: if_wi.c,v 1.9 2000/03/02 05:00:47 enami Exp $
*/
/*
@ -90,6 +90,7 @@
#include <net/if_dl.h>
#include <net/if_media.h>
#include <net/if_ether.h>
#include <net/if_ieee80211.h>
#ifdef INET
#include <netinet/in.h>
@ -115,7 +116,7 @@
#if !defined(lint)
static const char rcsid[] =
"$Id: if_wi.c,v 1.8 2000/02/27 23:10:51 enami Exp $";
"$Id: if_wi.c,v 1.9 2000/03/02 05:00:47 enami Exp $";
#endif
#ifdef foo
@ -157,6 +158,13 @@ static void wi_shutdown __P((void *));
static int wi_enable __P((struct wi_softc *));
static void wi_disable __P((struct wi_softc *));
static int wi_media_change __P((struct ifnet *));
static void wi_media_status __P((struct ifnet *, struct ifmediareq *));
static int wi_set_ssid __P((struct wi_ssid *, u_int8_t *, int));
static void wi_request_fill_ssid __P((struct wi_req *, struct wi_ssid *));
static int wi_write_ssid __P((struct wi_softc *, int, struct wi_req *,
struct wi_ssid *));
struct cfattach wi_ca = {
sizeof(struct wi_softc), wi_match, wi_attach, wi_detach, wi_activate
@ -292,16 +300,11 @@ wi_attach(parent, self, aux)
ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
ifp->if_baudrate = 2000000;
bzero(sc->wi_node_name, sizeof(sc->wi_node_name));
bcopy(WI_DEFAULT_NODENAME, sc->wi_node_name,
(void)wi_set_ssid(&sc->wi_nodeid, WI_DEFAULT_NODENAME,
sizeof(WI_DEFAULT_NODENAME) - 1);
bzero(sc->wi_net_name, sizeof(sc->wi_net_name));
bcopy(WI_DEFAULT_NETNAME, sc->wi_net_name,
(void)wi_set_ssid(&sc->wi_netid, WI_DEFAULT_NETNAME,
sizeof(WI_DEFAULT_NETNAME) - 1);
bzero(sc->wi_ibss_name, sizeof(sc->wi_ibss_name));
bcopy(WI_DEFAULT_IBSS, sc->wi_ibss_name,
(void)wi_set_ssid(&sc->wi_ibssid, WI_DEFAULT_IBSS,
sizeof(WI_DEFAULT_IBSS) - 1);
sc->wi_portnum = WI_DEFAULT_PORT;
@ -335,6 +338,24 @@ wi_attach(parent, self, aux)
wi_read_record(sc, &gen);
sc->wi_has_wep = gen.wi_val;
ifmedia_init(&sc->sc_media, 0, wi_media_change, wi_media_status);
#define IFM_AUTOADHOC \
IFM_MAKEWORD(IFM_IEEE80211, IFM_AUTO, IFM_IEEE80211_ADHOC, 0)
#define ADD(m, c) ifmedia_add(&sc->sc_media, (m), (c), NULL)
ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_AUTO, 0, 0), 0);
ADD(IFM_AUTOADHOC, 0);
ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS1, 0, 0), 0);
ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS1,
IFM_IEEE80211_ADHOC, 0), 0);
ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS2, 0, 0), 0);
ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS2,
IFM_IEEE80211_ADHOC, 0), 0);
ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS11, 0, 0), 0);
ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS11,
IFM_IEEE80211_ADHOC, 0), 0);
#undef ADD
ifmedia_set(&sc->sc_media, IFM_AUTOADHOC);
/*
* Call MI attach routines.
*/
@ -962,16 +983,16 @@ wi_setdef(sc, wreq)
sc->wi_channel = wreq->wi_val[0];
break;
case WI_RID_NODENAME:
bzero(sc->wi_node_name, sizeof(sc->wi_node_name));
bcopy((char *)&wreq->wi_val[1], sc->wi_node_name, 30);
error = wi_set_ssid(&sc->wi_nodeid,
(u_int8_t *)&wreq->wi_val[1], wreq->wi_val[0]);
break;
case WI_RID_DESIRED_SSID:
bzero(sc->wi_net_name, sizeof(sc->wi_net_name));
bcopy((char *)&wreq->wi_val[1], sc->wi_net_name, 30);
error = wi_set_ssid(&sc->wi_netid,
(u_int8_t *)&wreq->wi_val[1], wreq->wi_val[0]);
break;
case WI_RID_OWN_SSID:
bzero(sc->wi_ibss_name, sizeof(sc->wi_ibss_name));
bcopy((char *)&wreq->wi_val[1], sc->wi_ibss_name, 30);
error = wi_set_ssid(&sc->wi_ibssid,
(u_int8_t *)&wreq->wi_val[1], wreq->wi_val[0]);
break;
case WI_RID_PM_ENABLED:
sc->wi_pm_enabled = wreq->wi_val[0];
@ -1038,22 +1059,13 @@ wi_getdef(sc, wreq)
wreq->wi_val[0] = sc->wi_channel;
break;
case WI_RID_NODENAME:
bzero(&wreq->wi_val[0], sizeof(wreq->wi_val));
wreq->wi_val[0] = strlen(sc->wi_node_name);
wreq->wi_len += roundup(wreq->wi_val[0], 2) / 2 - 1;
bcopy(sc->wi_node_name, &wreq->wi_val[1], 30);
wi_request_fill_ssid(wreq, &sc->wi_nodeid);
break;
case WI_RID_DESIRED_SSID:
bzero(&wreq->wi_val[0], sizeof(wreq->wi_val));
wreq->wi_val[0] = strlen(sc->wi_net_name);
wreq->wi_len += roundup(wreq->wi_val[0], 2) / 2 - 1;
bcopy(sc->wi_net_name, &wreq->wi_val[1], 30);
wi_request_fill_ssid(wreq, &sc->wi_netid);
break;
case WI_RID_OWN_SSID:
bzero(&wreq->wi_val[0], sizeof(wreq->wi_val));
wreq->wi_val[0] = strlen(sc->wi_ibss_name);
wreq->wi_len += roundup(wreq->wi_val[0], 2) / 2 - 1;
bcopy(sc->wi_ibss_name, &wreq->wi_val[1], 30);
wi_request_fill_ssid(wreq, &sc->wi_ibssid);
break;
case WI_RID_PM_ENABLED:
wreq->wi_val[0] = sc->wi_pm_enabled;
@ -1091,12 +1103,13 @@ static int wi_ioctl(ifp, command, data)
u_long command;
caddr_t data;
{
int s, error = 0;
int s, len, error = 0;
struct wi_softc *sc = ifp->if_softc;
struct wi_req wreq;
struct ifreq *ifr;
struct proc *p = curproc;
struct ifaddr *ifa = (struct ifaddr *)data;
u_int8_t nwid[IEEE80211_NWID_LEN + 1];
if ((sc->sc_dev.dv_flags & DVF_ACTIVE) == 0)
return (ENXIO);
@ -1178,6 +1191,12 @@ static int wi_ioctl(ifp, command, data)
error = 0;
}
break;
case SIOCSIFMEDIA:
case SIOCGIFMEDIA:
error = ifmedia_ioctl(ifp, ifr, &sc->sc_media, command);
break;
case SIOCGWAVELAN:
error = copyin(ifr->ifr_data, &wreq, sizeof(wreq));
if (error)
@ -1227,6 +1246,48 @@ static int wi_ioctl(ifp, command, data)
wi_init(sc);
}
break;
case SIOCG80211NWID:
/*
* Actually, the ESS-ID is a variable length octet string
* up to 32 bytes, and we should have a way to pass length
* separately. But for now, we treat as if it is terminated
* by NUL. XXX.
*/
if (sc->sc_enabled == 0)
/* Return the desried ID */
error = copyout(&sc->wi_netid.ws_id, ifr->ifr_data,
IEEE80211_NWID_LEN); /* XXX */
else {
wreq.wi_type = WI_RID_CURRENT_SSID;
wreq.wi_len = WI_MAX_DATALEN;
if (wi_read_record(sc, (struct wi_ltv_gen *)&wreq) ||
wreq.wi_val[0] > IEEE80211_NWID_LEN)
error = EINVAL;
else
error = copyout(&wreq.wi_val[1], ifr->ifr_data,
IEEE80211_NWID_LEN); /* XXX */
}
break;
case SIOCS80211NWID:
memset(nwid, 0, sizeof(nwid));
error = copyin(ifr->ifr_data, nwid, IEEE80211_NWID_LEN);
if (error != 0)
break;
len = strlen(nwid); /* XXX */
if (sc->wi_netid.ws_len == len &&
memcmp(sc->wi_netid.ws_id, nwid, len) == 0)
break;
wi_set_ssid(&sc->wi_netid, nwid, len);
if (sc->sc_enabled != 0) {
error = wi_write_ssid(sc, WI_RID_DESIRED_SSID, &wreq,
&sc->wi_netid);
if (error == 0 &&
(ifp->if_flags & IFF_RUNNING) != 0) {
untimeout(wi_inquire, sc);
wi_inquire(sc);
}
}
break;
default:
error = EINVAL;
break;
@ -1242,6 +1303,7 @@ wi_init(sc)
struct wi_softc *sc;
{
struct ifnet *ifp = &sc->sc_ethercom.ec_if;
struct wi_req wreq;
struct wi_ltv_macaddr mac;
int s, id = 0;
@ -1275,16 +1337,16 @@ wi_init(sc)
WI_SETVAL(WI_RID_MAX_SLEEP, sc->wi_max_sleep);
/* Specify the IBSS name */
WI_SETSTR(WI_RID_OWN_SSID, sc->wi_ibss_name);
wi_write_ssid(sc, WI_RID_OWN_SSID, &wreq, &sc->wi_ibssid);
/* Specify the network name */
WI_SETSTR(WI_RID_DESIRED_SSID, sc->wi_net_name);
wi_write_ssid(sc, WI_RID_DESIRED_SSID, &wreq, &sc->wi_netid);
/* Specify the frequency to use */
WI_SETVAL(WI_RID_OWN_CHNL, sc->wi_channel);
/* Program the nodename. */
WI_SETSTR(WI_RID_NODENAME, sc->wi_node_name);
wi_write_ssid(sc, WI_RID_NODENAME, &wreq, &sc->wi_nodeid);
/* Set our MAC address. */
mac.wi_len = 4;
@ -1534,6 +1596,9 @@ wi_detach(self, flags)
shutdownhook_disestablish(sc->sc_sdhook);
wi_disable(sc);
/* Delete all remaining media. */
ifmedia_delete_instance(&sc->sc_media, IFM_INST_ANY);
if (sc->wi_resource & WI_RES_NET) {
#if NBPFILTER > 0
bpfdetach(ifp);
@ -1550,3 +1615,98 @@ wi_detach(self, flags)
return (0);
}
static int
wi_set_ssid(ws, id, len)
struct wi_ssid *ws;
u_int8_t *id;
int len;
{
if (len > IEEE80211_NWID_LEN)
return (EINVAL);
ws->ws_len = len;
memcpy(ws->ws_id, id, len);
if (len < IEEE80211_NWID_LEN) /* XXX */
ws->ws_id[len] = 0; /* XXX */
return (0);
}
static void
wi_request_fill_ssid(wreq, ws)
struct wi_req *wreq;
struct wi_ssid *ws;
{
memset(&wreq->wi_val[0], 0, sizeof(wreq->wi_val));
wreq->wi_val[0] = ws->ws_len;
wreq->wi_len = roundup(wreq->wi_val[0], 2) / 2 + 1;
memcpy(&wreq->wi_val[1], ws->ws_id, wreq->wi_val[0]);
}
static int
wi_write_ssid(sc, type, wreq, ws)
struct wi_softc *sc;
int type;
struct wi_req *wreq;
struct wi_ssid *ws;
{
wreq->wi_type = type;
wi_request_fill_ssid(wreq, ws);
return (wi_write_record(sc, (struct wi_ltv_gen *)wreq));
}
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->sc_media.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->sc_media.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_AUTO:
sc->wi_tx_rate = 3;
break;
case IFM_IEEE80211_DS11:
sc->wi_tx_rate = 11;
break;
}
if (sc->sc_enabled != 0) {
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_softc *sc = ifp->if_softc;
if (sc->sc_enabled == 0) {
imr->ifm_active = IFM_IEEE80211|IFM_NONE;
imr->ifm_status = 0;
return;
}
imr->ifm_active = sc->sc_media.ifm_cur->ifm_media;
imr->ifm_status = IFM_AVALID|IFM_ACTIVE;
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: if_wivar.h,v 1.5 2000/02/27 23:10:51 enami Exp $ */
/* $NetBSD: if_wivar.h,v 1.6 2000/03/02 05:00:47 enami Exp $ */
/*
* Copyright (c) 1997, 1998, 1999
@ -31,7 +31,7 @@
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*
* $Id: if_wivar.h,v 1.5 2000/02/27 23:10:51 enami Exp $
* $Id: if_wivar.h,v 1.6 2000/03/02 05:00:47 enami Exp $
*/
@ -40,6 +40,14 @@
* Oslo IETF plenary meeting.
*/
/*
* Service set identifier.
*/
struct wi_ssid {
int ws_len;
u_int8_t ws_id[IEEE80211_NWID_LEN];
};
struct wi_softc {
struct device sc_dev;
struct ethercom sc_ethercom;
@ -54,9 +62,9 @@ struct wi_softc {
void *sc_sdhook; /* saved shutdown hook for card */
void *sc_ih;
u_int8_t sc_macaddr[6];
u_int8_t sc_macaddr[ETHER_ADDR_LEN];
struct ifmedia ifmedia;
struct ifmedia sc_media;
int wi_tx_data_id;
int wi_tx_mgmt_id;
int wi_if_flags;
@ -70,9 +78,11 @@ struct wi_softc {
u_int16_t wi_channel;
u_int16_t wi_pm_enabled;
u_int16_t wi_max_sleep;
char wi_node_name[32];
char wi_net_name[32];
char wi_ibss_name[32];
struct wi_ssid wi_nodeid;
struct wi_ssid wi_netid;
struct wi_ssid wi_ibssid;
u_int8_t wi_txbuf[1596];
int wi_has_wep;
int wi_use_wep;