summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--etc/mtree/BSD.include.dist2
-rw-r--r--include/Makefile2
-rw-r--r--sbin/ifconfig/ifieee80211.c17
-rw-r--r--sys/dev/an/if_aironet_ieee.h118
-rw-r--r--sys/dev/an/if_an.c617
-rw-r--r--sys/dev/an/if_anreg.h29
-rw-r--r--usr.sbin/ancontrol/Makefile1
-rw-r--r--usr.sbin/ancontrol/ancontrol.833
-rw-r--r--usr.sbin/ancontrol/ancontrol.c150
9 files changed, 915 insertions, 54 deletions
diff --git a/etc/mtree/BSD.include.dist b/etc/mtree/BSD.include.dist
index 95e12c1..a90d7ff 100644
--- a/etc/mtree/BSD.include.dist
+++ b/etc/mtree/BSD.include.dist
@@ -12,6 +12,8 @@
..
..
dev
+ an
+ ..
ic
..
ppbus
diff --git a/include/Makefile b/include/Makefile
index f991f3f..3df3f2a 100644
--- a/include/Makefile
+++ b/include/Makefile
@@ -45,7 +45,7 @@ LDIRS= cam net netatalk netatm netgraph netinet netinet6 \
LNOHEADERDIRS= fs isofs ufs dev
-LSUBDIRS= cam/scsi dev/ic dev/ppbus dev/usb dev/wi fs/devfs \
+LSUBDIRS= cam/scsi dev/ic dev/ppbus dev/usb dev/wi dev/an fs/devfs \
fs/fdescfs fs/fifofs fs/msdosfs fs/ntfs fs/nullfs fs/nwfs fs/portalfs \
fs/procfs fs/smbfs fs/umapfs fs/unionfs isofs/cd9660 \
ufs/ffs ufs/ufs
diff --git a/sbin/ifconfig/ifieee80211.c b/sbin/ifconfig/ifieee80211.c
index ac8c871..33b2d83 100644
--- a/sbin/ifconfig/ifieee80211.c
+++ b/sbin/ifconfig/ifieee80211.c
@@ -99,6 +99,11 @@ set80211ssid(const char *val, int d, int s, const struct afswtch *rafp)
u_int8_t data[33];
ssid = 0;
+ len = sizeof(val);
+ if (len > 2 && isdigit(val[0]) && val[1] == ':') {
+ ssid = atoi(val)-1;
+ val += 2;
+ }
bzero(data, sizeof(data));
len = sizeof(data);
@@ -296,6 +301,18 @@ ieee80211_status (s, info)
}
printf("\tssid ");
print_string(data, ireq.i_len);
+ num = 0;
+ ireq.i_type = IEEE80211_IOC_NUMSSIDS;
+ if (ioctl(s, SIOCG80211, &ireq) >= 0) {
+ num = ireq.i_val;
+ }
+ ireq.i_type = IEEE80211_IOC_SSID;
+ for (ireq.i_val = 0; ireq.i_val < num; ireq.i_val++) {
+ if (ioctl(s, SIOCG80211, &ireq) >= 0 && ireq.i_len > 0) {
+ printf(" %d:", ireq.i_val + 1);
+ print_string(data, ireq.i_len);
+ }
+ }
printf("\n");
ireq.i_type = IEEE80211_IOC_STATIONNAME;
diff --git a/sys/dev/an/if_aironet_ieee.h b/sys/dev/an/if_aironet_ieee.h
index 2534312..2e110f2 100644
--- a/sys/dev/an/if_aironet_ieee.h
+++ b/sys/dev/an/if_aironet_ieee.h
@@ -355,6 +355,7 @@ struct an_ltv_genconfig {
#define AN_AUTHTYPE_ENABLE 0x0100
#define AN_AUTHTYPE_PRIVACY_IN_USE 0x0100
#define AN_AUTHTYPE_ALLOW_UNENCRYPTED 0x0200
+#define AN_AUTHTYPE_LEAP 0x1000
#define AN_PSAVE_NONE 0x0000
#define AN_PSAVE_CAM 0x0001
@@ -480,6 +481,7 @@ struct an_ltv_caps {
u_int16_t an_softcaps; /* 0x7C */
u_int16_t an_bootblockrev; /* 0x7E */
u_int16_t an_req_hw_support; /* 0x80 */
+ u_int16_t an_unknown; /* 0x82 */
};
/*
@@ -553,6 +555,7 @@ struct an_ltv_status {
#define AN_STATUS_OPMODE_RX_ENABLED 0x0004
#define AN_STATUS_OPMODE_IN_SYNC 0x0010
#define AN_STATUS_OPMODE_ASSOCIATED 0x0020
+#define AN_STATUS_OPMODE_LEAP 0x0040
#define AN_STATUS_OPMODE_ERROR 0x8000
/*
@@ -568,6 +571,55 @@ struct an_ltv_wepkey {
};
/*
+ * Receive frame structure.
+ */
+struct an_rxframe {
+ u_int32_t an_rx_time; /* 0x00 */
+ u_int16_t an_rx_status; /* 0x04 */
+ u_int16_t an_rx_payload_len; /* 0x06 */
+ u_int8_t an_rsvd0; /* 0x08 */
+ u_int8_t an_rx_signal_strength; /* 0x09 */
+ u_int8_t an_rx_rate; /* 0x0A */
+ u_int8_t an_rx_chan; /* 0x0B */
+ u_int8_t an_rx_assoc_cnt; /* 0x0C */
+ u_int8_t an_rsvd1[3]; /* 0x0D */
+ u_int8_t an_plcp_hdr[4]; /* 0x10 */
+ u_int16_t an_frame_ctl; /* 0x14 */
+ u_int16_t an_duration; /* 0x16 */
+ u_int8_t an_addr1[6]; /* 0x18 */
+ u_int8_t an_addr2[6]; /* 0x1E */
+ u_int8_t an_addr3[6]; /* 0x24 */
+ u_int16_t an_seq_ctl; /* 0x2A */
+ u_int8_t an_addr4[6]; /* 0x2C */
+ u_int8_t an_gaplen; /* 0x32 */
+} __attribute__((packed));
+
+
+/* Do not modify this unless you are modifying LEAP itself */
+#define LEAP_USERNAME_MAX 32
+#define LEAP_PASSWORD_MAX 32
+
+/*
+ * LEAP Username
+ */
+struct an_ltv_leap_username {
+ u_int16_t an_len; /* 0x00 */
+ u_int16_t an_type; /* 0xXX */
+ u_int16_t an_username_len; /* 0x02 */
+ u_int8_t an_username[LEAP_USERNAME_MAX]; /* 0x04 */
+};
+
+/*
+ * LEAP Password
+ */
+struct an_ltv_leap_password {
+ u_int16_t an_len; /* 0x00 */
+ u_int16_t an_type; /* 0xXX */
+ u_int16_t an_password_len; /* 0x02 */
+ u_int8_t an_password[LEAP_PASSWORD_MAX]; /* 0x04 */
+};
+
+/*
* These are all the LTV record types that we can read or write
* from the Aironet. Not all of them are temendously useful, but I
* list as many as I know about here for completeness.
@@ -624,12 +676,76 @@ struct an_ltv_wepkey {
/*
* FreeBSD fake RID
*/
+
#define AN_RID_MONITOR_MODE 0x0001 /* Set monitor mode for driver */
#define AN_MONITOR 1
#define AN_MONITOR_ANY_BSS 2
#define AN_MONITOR_INCLUDE_BEACON 4
#define AN_MONITOR_AIRONET_HEADER 8
-#define DLT_AIRONET_HEADER 120 /* Just something for now */
+#define DLT_AIRONET_HEADER 120 /* Has been allocated at tcpdump.org */
+
+/*
+ * from the Linux driver from Cisco ... no copyright header.
+ * Removed duplicated information that already existed in the FreeBSD driver
+ * provides emulation of the Cisco extensions to the Linux Aironet driver.
+ */
+
+/*
+ * Ioctl constants to be used in airo_ioctl.command
+ */
+
+#define AIROGCAP 0 /* Capability rid */
+#define AIROGCFG 1 /* USED A LOT */
+#define AIROGSLIST 2 /* System ID list */
+#define AIROGVLIST 3 /* List of specified AP's */
+#define AIROGDRVNAM 4 /* NOTUSED */
+#define AIROGEHTENC 5 /* NOTUSED */
+#define AIROGWEPKTMP 6
+#define AIROGWEPKNV 7
+#define AIROGSTAT 8
+#define AIROGSTATSC32 9
+#define AIROGSTATSD32 10
+
+/*
+ * Leave gap of 40 commands after AIROGSTATSD32
+ */
+
+#define AIROPCAP AIROGSTATSD32 + 40
+#define AIROPVLIST AIROPCAP + 1
+#define AIROPSLIST AIROPVLIST + 1
+#define AIROPCFG AIROPSLIST + 1
+#define AIROPSIDS AIROPCFG + 1
+#define AIROPAPLIST AIROPSIDS + 1
+#define AIROPMACON AIROPAPLIST + 1 /* Enable mac */
+#define AIROPMACOFF AIROPMACON + 1 /* Disable mac */
+#define AIROPSTCLR AIROPMACOFF + 1
+#define AIROPWEPKEY AIROPSTCLR + 1
+#define AIROPWEPKEYNV AIROPWEPKEY + 1
+#define AIROPLEAPPWD AIROPWEPKEYNV + 1
+#define AIROPLEAPUSR AIROPLEAPPWD + 1
+
+/*
+ * Another gap of 40 commands before flash codes
+ */
+
+#define AIROFLSHRST AIROPWEPKEYNV + 40
+#define AIROFLSHGCHR AIROFLSHRST + 1
+#define AIROFLSHSTFL AIROFLSHGCHR + 1
+#define AIROFLSHPCHR AIROFLSHSTFL + 1
+#define AIROFLPUTBUF AIROFLSHPCHR + 1
+#define AIRORESTART AIROFLPUTBUF + 1
+
+/*
+ * Struct to enable up to 65535 ioctl's
+ */
+
+#define AIROMAGIC 0xa55a
+
+typedef struct aironet_ioctl {
+ unsigned short command; /* What to do */
+ unsigned short len; /* Len of data */
+ unsigned char *data; /* d-data */
+} airo_ioctl;
#endif
diff --git a/sys/dev/an/if_an.c b/sys/dev/an/if_an.c
index ce8d224..f97aaad 100644
--- a/sys/dev/an/if_an.c
+++ b/sys/dev/an/if_an.c
@@ -162,6 +162,23 @@ static void an_cache_store __P((struct an_softc *, struct ether_header *,
struct mbuf *, unsigned short));
#endif
+/* function definitions for use with the Cisco's Linux configuration
+ utilities
+*/
+
+static int readrids __P((struct ifnet*, struct aironet_ioctl*));
+static int writerids __P((struct ifnet*, struct aironet_ioctl*));
+static int flashcard __P((struct ifnet*, struct aironet_ioctl*));
+
+static int cmdreset __P((struct ifnet *));
+static int setflashmode __P((struct ifnet *));
+static int flashgchar __P((struct ifnet *,int,int));
+static int flashpchar __P((struct ifnet *,int,int));
+static int flashputbuf __P((struct ifnet *));
+static int flashrestart __P((struct ifnet *));
+static int WaitBusy __P((struct ifnet *, int));
+static int unstickbusy __P((struct ifnet *));
+
static void an_dump_record __P((struct an_softc *,struct an_ltv_gen *,
char *));
@@ -169,6 +186,7 @@ static int an_media_change __P((struct ifnet *));
static void an_media_status __P((struct ifnet *, struct ifmediareq *));
static int an_dump = 0;
+
static char an_conf[256];
/* sysctl vars */
@@ -592,7 +610,7 @@ an_rxeof(sc)
return;
}
m->m_pkthdr.rcvif = ifp;
- /* Read Ethenet encapsulated packet */
+ /* Read Ethernet encapsulated packet */
#ifdef ANCACHE
/* Read NIC frame header */
@@ -1171,6 +1189,8 @@ an_setdef(sc, areq)
break;
case AN_RID_WEP_TEMP:
case AN_RID_WEP_PERM:
+ case AN_RID_LEAPUSERNAME:
+ case AN_RID_LEAPPASSWORD:
/* Disable the MAC. */
an_cmd(sc, AN_CMD_DISABLE, 0);
@@ -1257,6 +1277,8 @@ an_ioctl(ifp, command, data)
struct an_ltv_key *key;
struct an_ltv_status *status;
struct an_ltv_ssidlist *ssids;
+ int mode;
+ struct aironet_ioctl l_ioctl;
sc = ifp->if_softc;
AN_LOCK(sc);
@@ -1341,8 +1363,34 @@ an_ioctl(ifp, command, data)
break;
an_setdef(sc, &areq);
break;
+ case SIOCGPRIVATE_0: /* used by Cisco client utility */
+ copyin(ifr->ifr_data, &l_ioctl, sizeof(l_ioctl));
+ mode = l_ioctl.command;
+
+ if (mode >= AIROGCAP && mode <= AIROGSTATSD32) {
+ error = readrids(ifp, &l_ioctl);
+ }else if (mode >= AIROPCAP && mode <= AIROPLEAPUSR) {
+ error = writerids(ifp, &l_ioctl);
+ }else if (mode >= AIROFLSHRST && mode <= AIRORESTART) {
+ error = flashcard(ifp, &l_ioctl);
+ }else{
+ error =-1;
+ }
+
+ /* copy out the updated command info */
+ copyout(&l_ioctl, ifr->ifr_data, sizeof(l_ioctl));
+
+ break;
+ case SIOCGPRIVATE_1: /* used by Cisco client utility */
+ copyin(ifr->ifr_data, &l_ioctl, sizeof(l_ioctl));
+ l_ioctl.command = 0;
+ error = AIROMAGIC;
+ copyout(&error, l_ioctl.data, sizeof(error));
+ error = 0;
+ break;
case SIOCG80211:
areq.an_len = sizeof(areq);
+ /* was that a good idea DJA we are doing a short-cut */
switch (ireq->i_type) {
case IEEE80211_IOC_SSID:
if (ireq->i_val == -1) {
@@ -1366,8 +1414,8 @@ an_ioctl(ifp, command, data)
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) {
+ tmpptr = ssids->an_ssid2;
+ } else if (ireq->i_val == 2) {
len = ssids->an_ssid3_len;
tmpptr = ssids->an_ssid3;
} else {
@@ -1415,12 +1463,12 @@ an_ioctl(ifp, command, data)
* ancontrol so it will have to do until we get
* access to actual Cisco code.
*/
- if (ireq->i_val < 0 || ireq->i_val > 7) {
+ if (ireq->i_val < 0 || ireq->i_val > 8) {
error = EINVAL;
break;
}
len = 0;
- if (ireq->i_val < 4) {
+ if (ireq->i_val < 5) {
areq.an_type = AN_RID_WEP_TEMP;
for (i = 0; i < 5; i++) {
if (an_read_record(sc,
@@ -1448,7 +1496,7 @@ an_ioctl(ifp, command, data)
error = copyout(tmpstr, ireq->i_data, len);
break;
case IEEE80211_IOC_NUMWEPKEYS:
- ireq->i_val = 8;
+ ireq->i_val = 9; /* include home key */
break;
case IEEE80211_IOC_WEPTXKEY:
/*
@@ -1458,7 +1506,7 @@ an_ioctl(ifp, command, data)
areq.an_type = AN_RID_WEP_TEMP;
for (i = 0; i < 5; i++) {
if (an_read_record(sc,
- (struct an_ltv_gen *)&areq)) {
+ (struct an_ltv_gen *) &areq)) {
error = EINVAL;
break;
}
@@ -1478,6 +1526,20 @@ an_ioctl(ifp, command, data)
break;
}
ireq->i_val = key->mac[0];
+ /*
+ * Check for home mode. Map home mode into
+ * 5th key since that is how it is stored on
+ * the card
+ */
+ areq.an_len = sizeof(struct an_ltv_genconfig);
+ areq.an_type = AN_RID_GENCONFIG;
+ if (an_read_record(sc,
+ (struct an_ltv_gen *)&areq)) {
+ error = EINVAL;
+ break;
+ }
+ if (config->an_home_product & AN_HOME_NETWORK)
+ ireq->i_val = 4;
break;
case IEEE80211_IOC_AUTHMODE:
areq.an_type = AN_RID_ACTUALCFG;
@@ -1646,10 +1708,33 @@ an_ioctl(ifp, command, data)
bcopy(tmpstr, key->key, key->klen);
break;
case IEEE80211_IOC_WEPTXKEY:
- if (ireq->i_val < 0 || ireq->i_val > 3) {
+ /*
+ * Map the 5th key into the home mode
+ * since that is how it is stored on
+ * the card
+ */
+ if (ireq->i_val < 0 || ireq->i_val > 4) {
error = EINVAL;
break;
}
+ areq.an_len = sizeof(struct an_ltv_genconfig);
+ areq.an_type = AN_RID_ACTUALCFG;
+ if (an_read_record(sc,
+ (struct an_ltv_gen *)&areq)) {
+ error = EINVAL;
+ break;
+ }
+ if (ireq->i_val == 4) {
+ config->an_home_product |= AN_HOME_NETWORK;
+ ireq->i_val = 0;
+ } else {
+ config->an_home_product &= ~AN_HOME_NETWORK;
+ }
+
+ sc->an_config.an_home_product
+ = config->an_home_product;
+ an_write_record(sc, (struct an_ltv_gen *)&areq);
+
bzero(&areq, sizeof(struct an_ltv_key));
areq.an_len = sizeof(struct an_ltv_key);
areq.an_type = AN_RID_WEP_PERM;
@@ -2034,7 +2119,7 @@ an_shutdown(dev)
* a small fixed cache. The cache wraps if > MAX slots
* used. The cache may be zeroed out to start over.
* Two simple filters exist to reduce computation:
- * 1. ip only (literally 0x800) which may be used
+ * 1. ip only (literally 0x800, ETHERTYPE_IP) which may be used
* to ignore some packets. It defaults to ip only.
* it could be used to focus on broadcast, non-IP 802.11 beacons.
* 2. multicast/broadcast only. This may be used to
@@ -2099,7 +2184,7 @@ an_cache_store (sc, eh, m, rx_quality)
int i;
static int cache_slot = 0; /* use this cache entry */
static int wrapindex = 0; /* next "free" cache entry */
- int saanp = 0;
+ int type_ipv4 = 0;
/* filters:
* 1. ip only
@@ -2107,13 +2192,13 @@ an_cache_store (sc, eh, m, rx_quality)
* keep multicast only.
*/
- if ((ntohs(eh->ether_type) == 0x800)) {
- saanp = 1;
+ if ((ntohs(eh->ether_type) == ETHERTYPE_IP)) {
+ type_ipv4 = 1;
}
/* filter for ip packets only
*/
- if ( an_cache_iponly && !saanp) {
+ if ( an_cache_iponly && !type_ipv4) {
return;
}
@@ -2131,7 +2216,7 @@ an_cache_store (sc, eh, m, rx_quality)
/* find the ip header. we want to store the ip_src
* address.
*/
- if (saanp) {
+ if (type_ipv4) {
ip = mtod(m, struct ip *);
}
@@ -2197,7 +2282,7 @@ an_cache_store (sc, eh, m, rx_quality)
* .mac src
* .signal, etc.
*/
- if (saanp) {
+ if (type_ipv4) {
sc->an_sigcache[cache_slot].ipsrc = ip->ip_src.s_addr;
}
bcopy( eh->ether_shost, sc->an_sigcache[cache_slot].macsrc, 6);
@@ -2290,3 +2375,505 @@ an_media_status(ifp, imr)
else if (status.an_opmode & AN_STATUS_OPMODE_ASSOCIATED)
imr->ifm_status |= IFM_ACTIVE;
}
+
+/********************** Cisco utility support routines *************/
+
+/*
+ * ReadRids & WriteRids derived from Cisco driver additions to Ben Reed's
+ * Linux driver
+ */
+
+static int
+readrids(ifp, l_ioctl)
+ struct ifnet *ifp;
+ struct aironet_ioctl *l_ioctl;
+{
+ unsigned short rid;
+ struct an_softc *sc;
+ struct an_req areq;
+
+ switch (l_ioctl->command) {
+ case AIROGCAP:
+ rid = AN_RID_CAPABILITIES;
+ break;
+ case AIROGCFG:
+ rid = AN_RID_GENCONFIG;
+ break;
+ case AIROGSLIST:
+ rid = AN_RID_SSIDLIST;
+ break;
+ case AIROGVLIST:
+ rid = AN_RID_APLIST;
+ break;
+ case AIROGDRVNAM:
+ rid = AN_RID_DRVNAME;
+ break;
+ case AIROGEHTENC:
+ rid = AN_RID_ENCAPPROTO;
+ break;
+ case AIROGWEPKTMP:
+ rid = AN_RID_WEP_TEMP;
+ break;
+ case AIROGWEPKNV:
+ rid = AN_RID_WEP_PERM;
+ break;
+ case AIROGSTAT:
+ rid = AN_RID_STATUS;
+ break;
+ case AIROGSTATSD32:
+ rid = AN_RID_32BITS_DELTA;
+ break;
+ case AIROGSTATSC32:
+ rid = AN_RID_32BITS_CUM;
+ break;
+ default:
+ rid = 999;
+ break;
+ }
+
+ if (rid == 999) /* Is bad command */
+ return -EINVAL;
+
+ sc = ifp->if_softc;
+ areq.an_len = AN_MAX_DATALEN;
+ areq.an_type = rid;
+
+ an_read_record(sc, (struct an_ltv_gen *)&areq);
+
+ l_ioctl->len = areq.an_len - 4; /* just data */
+
+ /* the data contains the length at first */
+ if (copyout(&(areq.an_len), l_ioctl->data,
+ sizeof(areq.an_len))) {
+ return -EFAULT;
+ }
+ /* Just copy the data back */
+ if (copyout(&(areq.an_val), l_ioctl->data + 2,
+ l_ioctl->len)) {
+ return -EFAULT;
+ }
+ return 0;
+}
+
+static int
+writerids(ifp, l_ioctl)
+ struct ifnet *ifp;
+ struct aironet_ioctl *l_ioctl;
+{
+ struct an_softc *sc;
+ struct an_req areq;
+ int rid, command;
+
+ sc = ifp->if_softc;
+ rid = 0;
+ command = l_ioctl->command;
+
+ switch (command) {
+ case AIROPSIDS:
+ rid = AN_RID_SSIDLIST;
+ break;
+ case AIROPCAP:
+ rid = AN_RID_CAPABILITIES;
+ break;
+ case AIROPAPLIST:
+ rid = AN_RID_APLIST;
+ break;
+ case AIROPCFG:
+ rid = AN_RID_GENCONFIG;
+ break;
+ case AIROPMACON:
+ an_cmd(sc, AN_CMD_ENABLE, 0);
+ return 0;
+ break;
+ case AIROPMACOFF:
+ an_cmd(sc, AN_CMD_DISABLE, 0);
+ return 0;
+ break;
+ case AIROPSTCLR:
+ /*
+ * This command merely clears the counts does not actually
+ * store any data only reads rid. But as it changes the cards
+ * state, I put it in the writerid routines.
+ */
+
+ rid = AN_RID_32BITS_DELTACLR;
+ sc = ifp->if_softc;
+ areq.an_len = AN_MAX_DATALEN;
+ areq.an_type = rid;
+
+ an_read_record(sc, (struct an_ltv_gen *)&areq);
+ l_ioctl->len = areq.an_len - 4; /* just data */
+
+ /* the data contains the length at first */
+ if (copyout(&(areq.an_len), l_ioctl->data,
+ sizeof(areq.an_len))) {
+ return -EFAULT;
+ }
+ /* Just copy the data */
+ if (copyout(&(areq.an_val), l_ioctl->data + 2,
+ l_ioctl->len)) {
+ return -EFAULT;
+ }
+ return 0;
+ break;
+ case AIROPWEPKEY:
+ rid = AN_RID_WEP_TEMP;
+ break;
+ case AIROPWEPKEYNV:
+ rid = AN_RID_WEP_PERM;
+ break;
+ case AIROPLEAPUSR:
+ rid = AN_RID_LEAPUSERNAME;
+ break;
+ case AIROPLEAPPWD:
+ rid = AN_RID_LEAPPASSWORD;
+ break;
+ default:
+ return -EOPNOTSUPP;
+ }
+
+ if (rid) {
+ if (l_ioctl->len > sizeof(areq.an_val) + 4)
+ return -EINVAL;
+ areq.an_len = l_ioctl->len + 4; /* add type & length */
+ areq.an_type = rid;
+
+ /* Just copy the data back */
+ copyin((l_ioctl->data) + 2, &areq.an_val,
+ l_ioctl->len);
+
+ an_cmd(sc, AN_CMD_DISABLE, 0);
+ an_write_record(sc, (struct an_ltv_gen *)&areq);
+ an_cmd(sc, AN_CMD_ENABLE, 0);
+ return 0;
+ }
+ return -EOPNOTSUPP;
+}
+
+/*
+ * General Flash utilities derived from Cisco driver additions to Ben Reed's
+ * Linux driver
+ */
+
+#define FLASH_DELAY(x) tsleep(ifp, PZERO, "flash", ((x) / hz) + 1);
+
+static int
+unstickbusy(ifp)
+ struct ifnet *ifp;
+{
+ struct an_softc *sc = ifp->if_softc;
+
+ if (CSR_READ_2(sc, AN_COMMAND) & AN_CMD_BUSY) {
+ CSR_WRITE_2(sc, AN_EVENT_ACK, AN_EV_CLR_STUCK_BUSY);
+ return 1;
+ }
+ return 0;
+}
+
+/*
+ * Wait for busy completion from card wait for delay uSec's Return true for
+ * success meaning command reg is clear
+ */
+
+static int
+WaitBusy(ifp, uSec)
+ struct ifnet *ifp;
+ int uSec;
+{
+ int statword = 0xffff;
+ int delay = 0;
+ struct an_softc *sc = ifp->if_softc;
+
+ while ((statword & AN_CMD_BUSY) && delay <= (1000 * 100)) {
+ FLASH_DELAY(10);
+ delay += 10;
+ statword = CSR_READ_2(sc, AN_COMMAND);
+
+ if ((AN_CMD_BUSY & statword) && (delay % 200)) {
+ unstickbusy(ifp);
+ }
+ }
+
+ return 0 == (AN_CMD_BUSY & statword);
+}
+
+/*
+ * STEP 1) Disable MAC and do soft reset on card.
+ */
+
+static int
+cmdreset(ifp)
+ struct ifnet *ifp;
+{
+ int status;
+ struct an_softc *sc = ifp->if_softc;
+
+ an_stop(sc);
+
+ an_cmd(sc, AN_CMD_DISABLE, 0);
+
+ if (!(status = WaitBusy(ifp, 600))) {
+ printf("an%d: Waitbusy hang b4 RESET =%d\n",
+ sc->an_unit, status);
+ return -EBUSY;
+ }
+ CSR_WRITE_2(sc, AN_COMMAND, AN_CMD_FW_RESTART);
+
+ FLASH_DELAY(1000); /* WAS 600 12/7/00 */
+
+
+ if (!(status = WaitBusy(ifp, 100))) {
+ printf("an%d: Waitbusy hang AFTER RESET =%d\n",
+ sc->an_unit, status);
+ return -EBUSY;
+ }
+ return 0;
+}
+
+/*
+ * STEP 2) Put the card in legendary flash mode
+ */
+#define FLASH_COMMAND 0x7e7e
+
+static int
+setflashmode(ifp)
+ struct ifnet *ifp;
+{
+ int status;
+ struct an_softc *sc = ifp->if_softc;
+
+ CSR_WRITE_2(sc, AN_SW0, FLASH_COMMAND);
+ CSR_WRITE_2(sc, AN_SW1, FLASH_COMMAND);
+ CSR_WRITE_2(sc, AN_SW0, FLASH_COMMAND);
+ CSR_WRITE_2(sc, AN_COMMAND, FLASH_COMMAND);
+
+ /*
+ * mdelay(500); // 500ms delay
+ */
+
+ FLASH_DELAY(500);
+
+ if (!(status = WaitBusy(ifp, 600))) {
+ printf("Waitbusy hang after setflash mode\n");
+ return -EIO;
+ }
+ return 0;
+}
+
+/*
+ * Get a character from the card matching matchbyte Step 3)
+ */
+
+static int
+flashgchar(ifp, matchbyte, dwelltime)
+ struct ifnet *ifp;
+ int matchbyte;
+ int dwelltime;
+{
+ int rchar;
+ unsigned char rbyte = 0;
+ int success = -1;
+ struct an_softc *sc = ifp->if_softc;
+
+
+ do {
+ rchar = CSR_READ_2(sc, AN_SW1);
+
+ if (dwelltime && !(0x8000 & rchar)) {
+ dwelltime -= 10;
+ FLASH_DELAY(10);
+ continue;
+ }
+ rbyte = 0xff & rchar;
+
+ if ((rbyte == matchbyte) && (0x8000 & rchar)) {
+ CSR_WRITE_2(sc, AN_SW1, 0);
+ success = 1;
+ break;
+ }
+ if (rbyte == 0x81 || rbyte == 0x82 || rbyte == 0x83 || rbyte == 0x1a || 0xffff == rchar)
+ break;
+ CSR_WRITE_2(sc, AN_SW1, 0);
+
+ } while (dwelltime > 0);
+ return success;
+}
+
+/*
+ * Put character to SWS0 wait for dwelltime x 50us for echo .
+ */
+
+static int
+flashpchar(ifp, byte, dwelltime)
+ struct ifnet *ifp;
+ int byte;
+ int dwelltime;
+{
+ int echo;
+ int pollbusy, waittime;
+ struct an_softc *sc = ifp->if_softc;
+
+ byte |= 0x8000;
+
+ if (dwelltime == 0)
+ dwelltime = 200;
+
+ waittime = dwelltime;
+
+ /*
+ * Wait for busy bit d15 to go false indicating buffer empty
+ */
+ do {
+ pollbusy = CSR_READ_2(sc, AN_SW0);
+
+ if (pollbusy & 0x8000) {
+ FLASH_DELAY(50);
+ waittime -= 50;
+ continue;
+ } else
+ break;
+ }
+ while (waittime >= 0);
+
+ /* timeout for busy clear wait */
+
+ if (waittime <= 0) {
+ printf("an%d: flash putchar busywait timeout! \n",
+ sc->an_unit);
+ return -1;
+ }
+ /*
+ * Port is clear now write byte and wait for it to echo back
+ */
+ do {
+ CSR_WRITE_2(sc, AN_SW0, byte);
+ FLASH_DELAY(50);
+ dwelltime -= 50;
+ echo = CSR_READ_2(sc, AN_SW1);
+ } while (dwelltime >= 0 && echo != byte);
+
+
+ CSR_WRITE_2(sc, AN_SW1, 0);
+
+ return echo == byte;
+}
+
+/*
+ * Transfer 32k of firmware data from user buffer to our buffer and send to
+ * the card
+ */
+
+char flashbuffer[1024 * 38]; /* RAW Buffer for flash will be
+ * dynamic next */
+
+static int
+flashputbuf(ifp)
+ struct ifnet *ifp;
+{
+ unsigned short *bufp;
+ int nwords;
+ struct an_softc *sc = ifp->if_softc;
+
+ /* Write stuff */
+
+ bufp = (unsigned short *)flashbuffer;
+
+ CSR_WRITE_2(sc, AN_AUX_PAGE, 0x100);
+ CSR_WRITE_2(sc, AN_AUX_OFFSET, 0);
+
+ for (nwords = 0; nwords != 16384; nwords++) {
+ CSR_WRITE_2(sc, AN_AUX_DATA, bufp[nwords] & 0xffff);
+ }
+
+ CSR_WRITE_2(sc, AN_SW0, 0x8000);
+
+ return 0;
+}
+
+/*
+ * After flashing restart the card.
+ */
+
+static int
+flashrestart(ifp)
+ struct ifnet *ifp;
+{
+ int status = 0;
+ struct an_softc *sc = ifp->if_softc;
+
+ FLASH_DELAY(1024); /* Added 12/7/00 */
+
+ an_init(sc);
+
+ FLASH_DELAY(1024); /* Added 12/7/00 */
+ return status;
+}
+
+/*
+ * Entry point for flash ioclt.
+ */
+
+static int
+flashcard(ifp, l_ioctl)
+ struct ifnet *ifp;
+ struct aironet_ioctl *l_ioctl;
+{
+ struct an_softc *sc;
+ struct an_req areq;
+ int z = 0, status;
+
+ sc = ifp->if_softc;
+ status = l_ioctl->command;
+
+ switch (l_ioctl->command) {
+ case AIROFLSHRST:
+ return cmdreset(ifp);
+ break;
+ case AIROFLSHSTFL:
+ return setflashmode(ifp);
+ break;
+ case AIROFLSHGCHR: /* Get char from aux */
+ copyin(l_ioctl->data, &areq, l_ioctl->len);
+ z = *(int *)&areq;
+ if ((status = flashgchar(ifp, z, 8000)) == 1)
+ return 0;
+ else
+ return -1;
+ break;
+ case AIROFLSHPCHR: /* Send char to card. */
+ copyin(l_ioctl->data, &areq, l_ioctl->len);
+ z = *(int *)&areq;
+ if ((status = flashpchar(ifp, z, 8000)) == -1)
+ return -EIO;
+ else
+ return 0;
+ break;
+ case AIROFLPUTBUF: /* Send 32k to card */
+ if (l_ioctl->len > sizeof(flashbuffer)) {
+ printf("an%d: Buffer to big, %x %x\n", sc->an_unit,
+ l_ioctl->len, sizeof(flashbuffer));
+ return -EINVAL;
+ }
+ copyin(l_ioctl->data, &flashbuffer, l_ioctl->len);
+
+ if ((status = flashputbuf(ifp)) != 0)
+ return -EIO;
+ else
+ return 0;
+ break;
+ case AIRORESTART:
+ if ((status = flashrestart(ifp)) != 0) {
+ printf("an%d: FLASHRESTART returned %d\n",
+ sc->an_unit, status);
+ return -EIO;
+ } else
+ return 0;
+
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return -EINVAL;
+}
+
diff --git a/sys/dev/an/if_anreg.h b/sys/dev/an/if_anreg.h
index 0113d93..9d56314 100644
--- a/sys/dev/an/if_anreg.h
+++ b/sys/dev/an/if_anreg.h
@@ -217,30 +217,6 @@ struct an_ltv_gen {
#define AN_DEF_SSID_LEN 7
#define AN_DEF_SSID "tsunami"
-/*
- * Receive frame structure.
- */
-struct an_rxframe {
- u_int32_t an_rx_time; /* 0x00 */
- u_int16_t an_rx_status; /* 0x04 */
- u_int16_t an_rx_payload_len; /* 0x06 */
- u_int8_t an_rsvd0; /* 0x08 */
- u_int8_t an_rx_signal_strength; /* 0x09 */
- u_int8_t an_rx_rate; /* 0x0A */
- u_int8_t an_rx_chan; /* 0x0B */
- u_int8_t an_rx_assoc_cnt; /* 0x0C */
- u_int8_t an_rsvd1[3]; /* 0x0D */
- u_int8_t an_plcp_hdr[4]; /* 0x10 */
- u_int16_t an_frame_ctl; /* 0x14 */
- u_int16_t an_duration; /* 0x16 */
- u_int8_t an_addr1[6]; /* 0x18 */
- u_int8_t an_addr2[6]; /* 0x1E */
- u_int8_t an_addr3[6]; /* 0x24 */
- u_int16_t an_seq_ctl; /* 0x2A */
- u_int8_t an_addr4[6]; /* 0x2C */
- u_int16_t an_gaplen; /* 0x32 */
-};
-
#define AN_RXGAP_MAX 8
/*
@@ -265,8 +241,8 @@ struct an_txframe {
u_int8_t an_addr3[6]; /* 0x24 */
u_int16_t an_seq_ctl; /* 0x2A */
u_int8_t an_addr4[6]; /* 0x2C */
- u_int16_t an_gaplen; /* 0x32 */
-};
+ u_int8_t an_gaplen; /* 0x32 */
+} __attribute__((packed));
struct an_rxframe_802_3 {
u_int16_t an_rx_802_3_status; /* 0x34 */
@@ -386,6 +362,7 @@ struct an_softc {
int an_monitor;
int an_was_monitor;
u_char buf_802_11[MCLBYTES];
+ struct an_req areq;
};
#define AN_LOCK(_sc) mtx_lock(&(_sc)->an_mtx)
diff --git a/usr.sbin/ancontrol/Makefile b/usr.sbin/ancontrol/Makefile
index fe33ae1..696af71 100644
--- a/usr.sbin/ancontrol/Makefile
+++ b/usr.sbin/ancontrol/Makefile
@@ -4,6 +4,7 @@ PROG= ancontrol
MAN= ancontrol.8
CFLAGS+= -I${.CURDIR}/../../sys -DANCACHE
+LDADD+= -lmd
WARNS?= 2
diff --git a/usr.sbin/ancontrol/ancontrol.8 b/usr.sbin/ancontrol/ancontrol.8
index 0b5f21d..90d8730 100644
--- a/usr.sbin/ancontrol/ancontrol.8
+++ b/usr.sbin/ancontrol/ancontrol.8
@@ -82,10 +82,14 @@
.Nm
.Fl i Ar iface Fl m Ar mac_address
.Nm
+.Fl i Ar iface Fl m Ar mac address
+.Nm
.Fl i Ar iface
.Op Fl v Cm 1 | 2 | 3
.Fl n Ar SSID
.Nm
+.Fl i Ar iface Fl o Ar 0|1
+.Nm
.Fl i Ar iface Fl o Cm 0 | 1
.Nm
.Fl i Ar iface Fl p Ar tx_power
@@ -259,7 +263,7 @@ option: selection
sets the receive diversity and
.Cm 1
sets the transmit diversity.
-.It Fl i Ar iface Fl e Cm 0 | 1 | 2 | 3
+.It Fl i Ar iface Fl e Cm 0 | 1 | 2 | 3 | 4
Set the transmit WEP key to use.
Note that until this command is issued, the device will use the
last key programmed.
@@ -267,8 +271,9 @@ The transmit key is stored in NVRAM.
Currently
set transmit key can be checked via
.Fl C
-option.
-.It Fl i Ar iface Oo Fl v Cm 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 Oc Fl k Ar key
+option. The 4th key sets the card in "Home Network Mode" and uses the
+home key.
+.It Fl i Ar iface Oo Fl v Cm 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 Oc Fl k Ar key
Set a WEP key.
For 40 bit prefix 10 hex character with 0x.
For 128 bit prefix 26 hex character with 0x.
@@ -289,7 +294,8 @@ Note that the device will use the most recently-programmed key by default.
Currently set keys can be checked via
.Fl C
option, only the sizes of the
-keys are returned.
+keys are returned. The 8th key is for the home key. Note that
+the value for the home key can be read back from firmware.
.It Fl i Ar iface Fl K Cm 0 | 1 | 2
Set authorization type.
Use
@@ -310,6 +316,9 @@ for no WEP,
to enable full WEP,
.Cm 2
for mixed cell.
+.It Fl i Ar iface Fl L Ar user_name
+Enable LEAP and query for password. It will check to see if it
+has authenticated for up to 60s. To disable LEAP set WEP mode.
.It Fl i Ar iface Fl j Ar netjoin_timeout
Set the ad-hoc network join timeout.
When a station is first activated
@@ -423,6 +432,22 @@ need to be retransmitted instead of the whole packet.
The fragmentation
threshold can be anything from 64 to 2312 bytes.
The default is 2312.
+.It Fl i Ar iface Fl M Ar 0-15
+Set monitor mode via bit mask, meaning:
+.Bl -tag -offset indent -compact -width 0x000000
+.Em "Bit Mask Meaning"
+.It 0
+to not dump 802.11 packet.
+.It 1
+to enable 802.11 monitor.
+.It 2
+to monitor any SSID.
+.It 4
+to not skip beacons, monitor beacons produces a high system load.
+.It 8
+to enable full Aironet header returned via BPF.
+Note it appears that a SSID must be set.
+.El
.It Fl i Ar iface Fl r Ar RTS_threshold
Set the RTS/CTS threshold for a given interface.
This controls the
diff --git a/usr.sbin/ancontrol/ancontrol.c b/usr.sbin/ancontrol/ancontrol.c
index 0a89c4f..eadc5e3 100644
--- a/usr.sbin/ancontrol/ancontrol.c
+++ b/usr.sbin/ancontrol/ancontrol.c
@@ -56,6 +56,7 @@ static const char rcsid[] =
#include <unistd.h>
#include <errno.h>
#include <err.h>
+#include <md4.h>
static void an_getval __P((const char *, struct an_req *));
static void an_setval __P((const char *, struct an_req *));
@@ -83,6 +84,7 @@ static int an_hex2int __P((char));
static void an_str2key __P((char *, struct an_ltv_key *));
static void an_setkeys __P((const char *, char *, int));
static void an_enable_tx_key __P((const char *, char *));
+static void an_enable_leap_mode __P((const char *, char *));
static void usage __P((char *));
int main __P((int, char **));
@@ -126,6 +128,7 @@ int main __P((int, char **));
#define ACT_SET_KEYS 35
#define ACT_ENABLE_TX_KEY 36
#define ACT_SET_MONITOR_MODE 37
+#define ACT_SET_LEAP_MODE 38
static void an_getval(iface, areq)
const char *iface;
@@ -277,6 +280,8 @@ static void an_dumpstatus(iface)
printf("synced ");
if (sts->an_opmode & AN_STATUS_OPMODE_ASSOCIATED)
printf("associated ");
+ if (sts->an_opmode & AN_STATUS_OPMODE_LEAP)
+ printf("LEAP ");
if (sts->an_opmode & AN_STATUS_OPMODE_ERROR)
printf("error ");
printf("]\n");
@@ -285,6 +290,7 @@ static void an_dumpstatus(iface)
printf("\nSignal quality:\t\t");
an_printhex((char *)&sts->an_cur_signal_quality, 1);
printf("\nSignal strength:\t[ %d%% ]",sts->an_normalized_rssi);
+ printf("\nMax Noise:\t\t[ %d%% ]",sts->an_avg_noise_prev_min);
/*
* XXX: This uses the old definition of the rate field (units of
* 500kbps). Technically the new definition is that this field
@@ -707,7 +713,9 @@ static void an_dumpconfig(iface)
printf("\nWEP enabled:\t\t\t\t[ ");
if (cfg->an_authtype & AN_AUTHTYPE_PRIVACY_IN_USE)
{
- if (cfg->an_authtype & AN_AUTHTYPE_ALLOW_UNENCRYPTED)
+ if (cfg->an_authtype & AN_AUTHTYPE_LEAP)
+ printf("LEAP");
+ else if (cfg->an_authtype & AN_AUTHTYPE_ALLOW_UNENCRYPTED)
printf("mixed cell");
else
printf("full");
@@ -805,6 +813,12 @@ static void an_dumpconfig(iface)
an_printwords(&cfg->an_arl_decay, 1);
printf("\nARL delay:\t\t\t\t");
an_printwords(&cfg->an_arl_delay, 1);
+ printf("\nConfiguration:\t\t\t\t[ ");
+ if (cfg->an_home_product & AN_HOME_NETWORK)
+ printf("Home Configuration");
+ else
+ printf("Enterprise Configuration");
+ printf(" ]");
printf("\n");
printf("\n");
@@ -842,6 +856,7 @@ static void usage(p)
fprintf(stderr, "\t%s -i iface -f val (set frag threshold)\n", p);
fprintf(stderr, "\t%s -i iface -r val (set RTS threshold)\n", p);
fprintf(stderr, "\t%s -i iface -M 0-15 (set monitor mode)\n", p);
+ fprintf(stderr, "\t%s -i iface -L user (enter LEAP authentication mode)\n", p);
#ifdef ANCACHE
fprintf(stderr, "\t%s -i iface -Q print signal quality cache\n", p);
fprintf(stderr, "\t%s -i iface -Z zero out signal cache\n", p);
@@ -962,12 +977,14 @@ static void an_setconfig(iface, act, arg)
case 0:
/* no WEP */
cfg->an_authtype &= ~(AN_AUTHTYPE_PRIVACY_IN_USE
- | AN_AUTHTYPE_ALLOW_UNENCRYPTED);
+ | AN_AUTHTYPE_ALLOW_UNENCRYPTED
+ | AN_AUTHTYPE_LEAP);
break;
case 1:
/* full WEP */
cfg->an_authtype |= AN_AUTHTYPE_PRIVACY_IN_USE;
cfg->an_authtype &= ~AN_AUTHTYPE_ALLOW_UNENCRYPTED;
+ cfg->an_authtype &= ~AN_AUTHTYPE_LEAP;
break;
case 2:
/* mixed cell */
@@ -1261,7 +1278,7 @@ static void an_setkeys(iface, key, keytype)
k->mac[4]=0;
k->mac[5]=0;
- switch(keytype & 1){
+ switch(keytype & 1) {
case 0:
areq.an_len = sizeof(struct an_ltv_key);
areq.an_type = AN_RID_WEP_PERM;
@@ -1289,12 +1306,12 @@ static void an_readkeyinfo(iface)
printf("WEP Key status:\n");
areq.an_type = AN_RID_WEP_TEMP; /* read first key */
- for(i=0; i<5; i++){
+ for(i=0; i<5; i++) {
areq.an_len = sizeof(struct an_ltv_key);
an_getval(iface, &areq);
- if(k->kindex == 0xffff)
+ if (k->kindex == 0xffff)
break;
- switch (k->klen){
+ switch (k->klen) {
case 0:
printf("\tKey %d is unset\n",k->kindex);
break;
@@ -1325,8 +1342,24 @@ static void an_enable_tx_key(iface, arg)
{
struct an_req areq;
struct an_ltv_key *k;
+ struct an_ltv_genconfig *config;
bzero((char *)&areq, sizeof(areq));
+
+ /* set home or not home mode */
+ areq.an_len = sizeof(struct an_ltv_genconfig);
+ areq.an_type = AN_RID_GENCONFIG;
+ an_getval(iface, &areq);
+ config = (struct an_ltv_genconfig *)&areq;
+ if (atoi(arg) == 4) {
+ config->an_home_product |= AN_HOME_NETWORK;
+ }else{
+ config->an_home_product &= ~AN_HOME_NETWORK;
+ }
+ an_setval(iface, &areq);
+
+ bzero((char *)&areq, sizeof(areq));
+
k = (struct an_ltv_key *)&areq;
/* From a Cisco engineer write the transmit key to use in the
@@ -1348,6 +1381,102 @@ static void an_enable_tx_key(iface, arg)
return;
}
+static void an_enable_leap_mode(iface, username)
+ const char *iface;
+ char *username;
+{
+ struct an_req areq;
+ struct an_ltv_status *sts;
+ struct an_ltv_genconfig *cfg;
+ struct an_ltv_caps *caps;
+ struct an_ltv_leap_username an_username;
+ struct an_ltv_leap_password an_password;
+ char *password;
+ MD4_CTX context;
+ int len;
+ int i;
+ char unicode_password[LEAP_PASSWORD_MAX * 2];
+
+ areq.an_len = sizeof(areq);
+ areq.an_type = AN_RID_CAPABILITIES;
+
+ an_getval(iface, &areq);
+
+ caps = (struct an_ltv_caps *)&areq;
+
+ if (!caps->an_softcaps & AN_AUTHTYPE_LEAP) {
+ fprintf(stderr, "Firmware does not support LEAP\n");
+ exit(1);
+ }
+
+ bzero(&an_username, sizeof(an_username));
+ bzero(&an_password, sizeof(an_password));
+
+ len = strlen(username);
+ if (len > LEAP_USERNAME_MAX) {
+ printf("Username too long (max %d)\n", LEAP_USERNAME_MAX);
+ exit(1);
+ }
+ strncpy(an_username.an_username, username, len);
+ an_username.an_username_len = len;
+ an_username.an_len = sizeof(an_username);
+ an_username.an_type = AN_RID_LEAPUSERNAME;
+
+ password = getpass("Enter LEAP password:");
+
+ len = strlen(password);
+ if (len > LEAP_PASSWORD_MAX) {
+ printf("Password too long (max %d)\n", LEAP_PASSWORD_MAX);
+ exit(1);
+ }
+
+ bzero(&unicode_password, sizeof(unicode_password));
+ for(i = 0; i < len; i++) {
+ unicode_password[i * 2] = *password++;
+ }
+
+ /* First half */
+ MD4Init(&context);
+ MD4Update(&context, unicode_password, len * 2);
+ MD4Final(&an_password.an_password[0], &context);
+
+ /* Second half */
+ MD4Init (&context);
+ MD4Update (&context, &an_password.an_password[0], 16);
+ MD4Final (&an_password.an_password[16], &context);
+
+ an_password.an_password_len = 32;
+ an_password.an_len = sizeof(an_password);
+ an_password.an_type = AN_RID_LEAPPASSWORD;
+
+ an_setval(iface, (struct an_req *)&an_username);
+ an_setval(iface, (struct an_req *)&an_password);
+
+ areq.an_len = sizeof(areq);
+ areq.an_type = AN_RID_GENCONFIG;
+ an_getval(iface, &areq);
+ cfg = (struct an_ltv_genconfig *)&areq;
+ cfg->an_authtype = (AN_AUTHTYPE_PRIVACY_IN_USE | AN_AUTHTYPE_LEAP);
+ an_setval(iface, &areq);
+
+ sts = (struct an_ltv_status *)&areq;
+ areq.an_type = AN_RID_STATUS;
+
+ for (i = 60; i > 0; i--) {
+ an_getval(iface, &areq);
+ if (sts->an_opmode & AN_STATUS_OPMODE_LEAP) {
+ printf("Authenticated\n");
+ break;
+ }
+ sleep(1);
+ }
+
+ if (i == 0) {
+ fprintf(stderr, "Failed LEAP authentication\n");
+ exit(1);
+ }
+}
+
int main(argc, argv)
int argc;
char *argv[];
@@ -1378,7 +1507,7 @@ int main(argc, argv)
opterr = 1;
while ((ch = getopt(argc, argv,
- "ANISCTht:a:e:o:s:n:v:d:j:b:c:r:p:w:m:l:k:K:W:QZM:")) != -1) {
+ "ANISCTht:a:e:o:s:n:v:d:j:b:c:r:p:w:m:l:k:K:W:QZM:L:")) != -1) {
switch(ch) {
case 'Z':
#ifdef ANCACHE
@@ -1545,6 +1674,10 @@ int main(argc, argv)
act = ACT_SET_MONITOR_MODE;
arg = optarg;
break;
+ case 'L':
+ act = ACT_SET_LEAP_MODE;
+ arg = optarg;
+ break;
case 'h':
default:
usage(p);
@@ -1602,6 +1735,9 @@ int main(argc, argv)
case ACT_ENABLE_TX_KEY:
an_enable_tx_key(iface, arg);
break;
+ case ACT_SET_LEAP_MODE:
+ an_enable_leap_mode(iface, arg);
+ break;
default:
an_setconfig(iface, act, arg);
break;
OpenPOWER on IntegriCloud