Add support for WEP (encryption) for silver and gold WaveLAN/IEEE turbo cards.

Also update wicontrol to enable/disable encryption, set WEP keys and set the
TX key index. Silver cards only have 40-bit keys. This is something of a quick
hack, but it works well enough for me to commit this from the LinuxWorld
exhibit floor.

The WEP support only shows up if you have a card that supports it.

Would have been approved by: jkh, if he hadn't wandered off somewhere
Approved in his place by: msmith, who's standing right here
This commit is contained in:
wpaul 2000-02-02 17:59:13 +00:00
parent 9ec448d8ca
commit 648f1c0043
8 changed files with 369 additions and 10 deletions

View File

@ -210,6 +210,8 @@ struct wi_counters {
#define WI_RID_WDS_ADDR5 0xFC15 /* port 1 MAC of WDS link node */
#define WI_RID_WDS_ADDR6 0xFC16 /* port 1 MAC of WDS link node */
#define WI_RID_MCAST_PM_BUF 0xFC17 /* PM buffering of mcast */
#define WI_RID_ENCRYPTION 0xFC20 /* enable/disable WEP */
#define WI_RID_AUTHTYPE 0xFC21 /* specify authentication type */
/*
* Network parameters, dynamic configuration entities
@ -241,8 +243,21 @@ struct wi_counters {
#define WI_RID_TX_RATE4 0xFCA2
#define WI_RID_TX_RATE5 0xFCA3
#define WI_RID_TX_RATE6 0xFCA4
#define WI_RID_DEFLT_CRYPT_KEYS 0xFCB0
#define WI_RID_TX_CRYPT_KEY 0xFCB1
#define WI_RID_TICK_TIME 0xFCE0
struct wi_key {
u_int16_t wi_keylen;
u_int8_t wi_keydat[14];
};
struct wi_ltv_keys {
u_int16_t wi_len;
u_int16_t wi_type;
struct wi_key wi_keys[4];
};
/*
* NIC information
*/

View File

@ -310,6 +310,14 @@ static int wi_pccard_attach(device_t dev)
wi_read_record(sc, &gen);
sc->wi_channel = gen.wi_val;
/*
* Find out if we support WEP on this card.
*/
gen.wi_type = WI_RID_WEP_AVAIL;
gen.wi_len = 2;
wi_read_record(sc, &gen);
sc->wi_has_wep = gen.wi_val;
bzero((char *)&sc->wi_stats, sizeof(sc->wi_stats));
wi_init(sc);
@ -932,6 +940,16 @@ static void wi_setdef(sc, wreq)
case WI_RID_MAX_SLEEP:
sc->wi_max_sleep = wreq->wi_val[0];
break;
case WI_RID_ENCRYPTION:
sc->wi_use_wep = wreq->wi_val[0];
break;
case WI_RID_TX_CRYPT_KEY:
sc->wi_tx_key = wreq->wi_val[0];
break;
case WI_RID_DEFLT_CRYPT_KEYS:
bcopy((char *)wreq, (char *)&sc->wi_keys,
sizeof(struct wi_ltv_keys));
break;
default:
break;
}
@ -999,6 +1017,9 @@ static int wi_ioctl(ifp, command, data)
bcopy((char *)&sc->wi_stats, (char *)&wreq.wi_val,
sizeof(sc->wi_stats));
wreq.wi_len = (sizeof(sc->wi_stats) / 2) + 1;
} else if (wreq.wi_type == WI_RID_DEFLT_CRYPT_KEYS) {
bcopy((char *)&sc->wi_keys, (char *)&wreq,
sizeof(struct wi_ltv_keys));
}
#ifdef WICACHE
else if (wreq.wi_type == WI_RID_ZERO_CACHE) {
@ -1111,6 +1132,15 @@ static void wi_init(xsc)
(char *)&mac.wi_mac_addr, ETHER_ADDR_LEN);
wi_write_record(sc, (struct wi_ltv_gen *)&mac);
/* Configure WEP. */
if (sc->wi_has_wep) {
WI_SETVAL(WI_RID_ENCRYPTION, sc->wi_use_wep);
WI_SETVAL(WI_RID_TX_CRYPT_KEY, sc->wi_tx_key);
sc->wi_keys.wi_len = (sizeof(struct wi_ltv_keys) / 2) + 1;
sc->wi_keys.wi_type = WI_RID_DEFLT_CRYPT_KEYS;
wi_write_record(sc, (struct wi_ltv_gen *)&sc->wi_keys);
}
/* Initialize promisc mode. */
if (ifp->if_flags & IFF_PROMISC) {
WI_SETVAL(WI_RID_PROMISC, 1);

View File

@ -56,6 +56,27 @@ struct wi_counters {
u_int32_t wi_rx_msg_in_bad_msg_frags;
};
/*
* Encryption controls. We can enable or disable encryption as
* well as specify up to 4 encryption keys. We can also specify
* which of the four keys will be used for transmit encryption.
*/
#define WI_RID_ENCRYPTION 0xFC20
#define WI_RID_AUTHTYPE 0xFC21
#define WI_RID_DEFLT_CRYPT_KEYS 0xFCB0
#define WI_RID_TX_CRYPT_KEY 0xFCB1
#define WI_RID_WEP_AVAIL 0xFD4F
struct wi_key {
u_int16_t wi_keylen;
u_int8_t wi_keydat[14];
};
struct wi_ltv_keys {
u_int16_t wi_len;
u_int16_t wi_type;
struct wi_key wi_keys[4];
};
struct wi_softc {
struct arpcom arpcom;
struct ifmedia ifmedia;
@ -84,8 +105,12 @@ struct wi_softc {
char wi_node_name[32];
char wi_net_name[32];
char wi_ibss_name[32];
u_int8_t wi_txbuf[1536];
u_int8_t wi_txbuf[1596];
struct wi_counters wi_stats;
int wi_has_wep;
int wi_use_wep;
int wi_tx_key;
struct wi_ltv_keys wi_keys;
#ifdef WICACHE
int wi_sigitems;
struct wi_sigcache wi_sigcache[MAXWICACHE];

View File

@ -210,6 +210,8 @@ struct wi_counters {
#define WI_RID_WDS_ADDR5 0xFC15 /* port 1 MAC of WDS link node */
#define WI_RID_WDS_ADDR6 0xFC16 /* port 1 MAC of WDS link node */
#define WI_RID_MCAST_PM_BUF 0xFC17 /* PM buffering of mcast */
#define WI_RID_ENCRYPTION 0xFC20 /* enable/disable WEP */
#define WI_RID_AUTHTYPE 0xFC21 /* specify authentication type */
/*
* Network parameters, dynamic configuration entities
@ -241,8 +243,21 @@ struct wi_counters {
#define WI_RID_TX_RATE4 0xFCA2
#define WI_RID_TX_RATE5 0xFCA3
#define WI_RID_TX_RATE6 0xFCA4
#define WI_RID_DEFLT_CRYPT_KEYS 0xFCB0
#define WI_RID_TX_CRYPT_KEY 0xFCB1
#define WI_RID_TICK_TIME 0xFCE0
struct wi_key {
u_int16_t wi_keylen;
u_int8_t wi_keydat[14];
};
struct wi_ltv_keys {
u_int16_t wi_len;
u_int16_t wi_type;
struct wi_key wi_keys[4];
};
/*
* NIC information
*/

View File

@ -310,6 +310,14 @@ static int wi_pccard_attach(device_t dev)
wi_read_record(sc, &gen);
sc->wi_channel = gen.wi_val;
/*
* Find out if we support WEP on this card.
*/
gen.wi_type = WI_RID_WEP_AVAIL;
gen.wi_len = 2;
wi_read_record(sc, &gen);
sc->wi_has_wep = gen.wi_val;
bzero((char *)&sc->wi_stats, sizeof(sc->wi_stats));
wi_init(sc);
@ -932,6 +940,16 @@ static void wi_setdef(sc, wreq)
case WI_RID_MAX_SLEEP:
sc->wi_max_sleep = wreq->wi_val[0];
break;
case WI_RID_ENCRYPTION:
sc->wi_use_wep = wreq->wi_val[0];
break;
case WI_RID_TX_CRYPT_KEY:
sc->wi_tx_key = wreq->wi_val[0];
break;
case WI_RID_DEFLT_CRYPT_KEYS:
bcopy((char *)wreq, (char *)&sc->wi_keys,
sizeof(struct wi_ltv_keys));
break;
default:
break;
}
@ -999,6 +1017,9 @@ static int wi_ioctl(ifp, command, data)
bcopy((char *)&sc->wi_stats, (char *)&wreq.wi_val,
sizeof(sc->wi_stats));
wreq.wi_len = (sizeof(sc->wi_stats) / 2) + 1;
} else if (wreq.wi_type == WI_RID_DEFLT_CRYPT_KEYS) {
bcopy((char *)&sc->wi_keys, (char *)&wreq,
sizeof(struct wi_ltv_keys));
}
#ifdef WICACHE
else if (wreq.wi_type == WI_RID_ZERO_CACHE) {
@ -1111,6 +1132,15 @@ static void wi_init(xsc)
(char *)&mac.wi_mac_addr, ETHER_ADDR_LEN);
wi_write_record(sc, (struct wi_ltv_gen *)&mac);
/* Configure WEP. */
if (sc->wi_has_wep) {
WI_SETVAL(WI_RID_ENCRYPTION, sc->wi_use_wep);
WI_SETVAL(WI_RID_TX_CRYPT_KEY, sc->wi_tx_key);
sc->wi_keys.wi_len = (sizeof(struct wi_ltv_keys) / 2) + 1;
sc->wi_keys.wi_type = WI_RID_DEFLT_CRYPT_KEYS;
wi_write_record(sc, (struct wi_ltv_gen *)&sc->wi_keys);
}
/* Initialize promisc mode. */
if (ifp->if_flags & IFF_PROMISC) {
WI_SETVAL(WI_RID_PROMISC, 1);

View File

@ -56,6 +56,27 @@ struct wi_counters {
u_int32_t wi_rx_msg_in_bad_msg_frags;
};
/*
* Encryption controls. We can enable or disable encryption as
* well as specify up to 4 encryption keys. We can also specify
* which of the four keys will be used for transmit encryption.
*/
#define WI_RID_ENCRYPTION 0xFC20
#define WI_RID_AUTHTYPE 0xFC21
#define WI_RID_DEFLT_CRYPT_KEYS 0xFCB0
#define WI_RID_TX_CRYPT_KEY 0xFCB1
#define WI_RID_WEP_AVAIL 0xFD4F
struct wi_key {
u_int16_t wi_keylen;
u_int8_t wi_keydat[14];
};
struct wi_ltv_keys {
u_int16_t wi_len;
u_int16_t wi_type;
struct wi_key wi_keys[4];
};
struct wi_softc {
struct arpcom arpcom;
struct ifmedia ifmedia;
@ -84,8 +105,12 @@ struct wi_softc {
char wi_node_name[32];
char wi_net_name[32];
char wi_ibss_name[32];
u_int8_t wi_txbuf[1536];
u_int8_t wi_txbuf[1596];
struct wi_counters wi_stats;
int wi_has_wep;
int wi_use_wep;
int wi_tx_key;
struct wi_ltv_keys wi_keys;
#ifdef WICACHE
int wi_sigitems;
struct wi_sigcache wi_sigcache[MAXWICACHE];

View File

@ -58,6 +58,13 @@
.Nm wicontrol
.Fl i Ar iface Fl d Ar max data length
.Nm wicontrol
.Fl i Ar iface Fl e Ar 0|1
.Nm wicontrol
.Fl i Ar iface Fl k Ar key
.Op Fl v Ar 1|2|3|4
.Nm wicontrol
.Fl i Ar iface Fl T Ar 1|2|3|4
.Nm wicontrol
.Fl i Ar iface Fl r Ar RTS threshold
.Nm wicontrol
.Fl i Ar iface Fl f Ar frequency
@ -66,9 +73,11 @@
.Nm wicontrol
.Fl i Ar iface Fl S Ar max_sleep_duration
.Nm wicontrol
.Fl i Ar iface Fl Z (zero signal cache)
.Fl i Ar iface Fl Z
(zero signal cache)
.Nm wicontrol
.Fl i Ar iface Fl C (display signal cache)
.Fl i Ar iface Fl C
(display signal cache)
.Sh DESCRIPTION
The
.Nm
@ -187,6 +196,34 @@ Set the maximum receive and transmit frame size for a specified interface.
The
.Ar max data length
can be any number from 350 to 2304. The default is 2304.
.It Fl i Ar iface Fl e Ar 0|1
Enable or disable WEP encryption. Permitted values are
.Ar 0
(encryption disabled) or
.Ar 1
(encryption enabled). Encryption is off by default.
.It Fl i Ar iface Fl k Ar key "[-v 1|2|3|4]"
Set WEP encryption keys. There are four default encryption keys
that can be programmed. A specific key can be set using
the
.Fl v
flag. If the
.Fl v
flag is not specified, the first key will be set. Encryption keys
can either be normal text (i.e. "hello") or a series of hexadecimal
digits (i.e. "0x1234512345"). For
WaveLAN Turbo Silver cards, the key is restricted to 40 bits, hence
the key can be either a 5 character text string or 10 hex digits.
For WaveLAN Turbo Gold cards, the key can be up to 128 bits,
which means the key can be specified as either a 16 character text
string or 32 hex digits.
.Pp
Note: currently, the field in the structure used to program the key
into the NIC is only 14 bytes long, not 16. I'm not sure how this is
supposed to allow 128 bits of key info for the gold cards.
.It Fl i Ar iface Fl T Ar 1|2|3|4
Specify which of the four WEP encryption keys will be used to
encrypt transmitted packets.
.It Fl i Ar iface Fl r Ar RTS threshold
Set the RTS/CTS threshold for a given interface. This controls the
number of bytes used for the RTS/CTS handshake boundary. The

View File

@ -70,6 +70,8 @@ static void wi_printwords __P((struct wi_req *));
static void wi_printbool __P((struct wi_req *));
static void wi_printhex __P((struct wi_req *));
static void wi_dumpinfo __P((char *));
static void wi_setkeys __P((char *, char *, int));
static void wi_printkeys __P((struct wi_req *));
static void usage __P((char *));
static void wi_getval(iface, wreq)
@ -236,6 +238,111 @@ void wi_sethex(iface, code, str)
return;
}
static int wi_hex2int(c)
char c;
{
if (c >= '0' && c <= '9')
return (c - '0');
if (c >= 'A' && c <= 'F')
return (c - 'A' + 10);
if (c >= 'a' && c <= 'f')
return (c - 'a' + 10);
return (0);
}
static void wi_str2key(s, k)
char *s;
struct wi_key *k;
{
int n, i;
char *p;
/* Is this a hex string? */
if (s[0] == '0' && (s[1] == 'x' || s[1] == 'X')) {
/* Yes, convert to int. */
n = 0;
p = (char *)&k->wi_keydat[0];
for (i = 2; i < strlen(s); i+= 2) {
*p++ = (wi_hex2int(s[i]) << 4) + wi_hex2int(s[i + 1]);
n++;
}
k->wi_keylen = n;
} else {
/* No, just copy it in. */
bcopy(s, k->wi_keydat, strlen(s));
k->wi_keylen = strlen(s);
}
return;
}
static void wi_setkeys(iface, key, idx)
char *iface;
char *key;
int idx;
{
struct wi_req wreq;
struct wi_ltv_keys *keys;
struct wi_key *k;
bzero((char *)&wreq, sizeof(wreq));
wreq.wi_len = WI_MAX_DATALEN;
wreq.wi_type = WI_RID_WEP_AVAIL;
wi_getval(iface, &wreq);
if (wreq.wi_val[0] == 0)
err(1, "no WEP option available on this card");
bzero((char *)&wreq, sizeof(wreq));
wreq.wi_len = WI_MAX_DATALEN;
wreq.wi_type = WI_RID_DEFLT_CRYPT_KEYS;
wi_getval(iface, &wreq);
keys = (struct wi_ltv_keys *)&wreq;
if (strlen(key) > 14) {
err(1, "encryption key must be no "
"more than 14 characters long");
}
if (idx > 3)
err(1, "only 4 encryption keys available");
k = &keys->wi_keys[idx];
wi_str2key(key, k);
wreq.wi_len = (sizeof(struct wi_ltv_keys) / 2) + 1;
wreq.wi_type = WI_RID_DEFLT_CRYPT_KEYS;
wi_setval(iface, &wreq);
return;
}
static void wi_printkeys(wreq)
struct wi_req *wreq;
{
int i, j;
struct wi_key *k;
struct wi_ltv_keys *keys;
char *ptr;
keys = (struct wi_ltv_keys *)wreq;
for (i = 0; i < 4; i++) {
k = &keys->wi_keys[i];
ptr = (char *)k->wi_keydat;
for (j = 0; j < k->wi_keylen; j++) {
if (ptr[i] == '\0')
ptr[i] = ' ';
}
ptr[j] = '\0';
printf("[ %s ]", ptr);
}
return;
};
void wi_printwords(wreq)
struct wi_req *wreq;
{
@ -283,6 +390,7 @@ void wi_printhex(wreq)
#define WI_BOOL 0x02
#define WI_WORDS 0x03
#define WI_HEXBYTES 0x04
#define WI_KEYSTRUCT 0x05
struct wi_table {
int wi_code;
@ -304,7 +412,8 @@ static struct wi_table wi_table[] = {
{ WI_RID_PROMISC, WI_BOOL, "Promiscuous mode:\t\t\t" },
{ WI_RID_PORTTYPE, WI_WORDS, "Port type (1=BSS, 3=ad-hoc):\t\t"},
{ WI_RID_MAC_NODE, WI_HEXBYTES, "MAC address:\t\t\t\t"},
{ WI_RID_TX_RATE, WI_WORDS, "TX rate:\t\t\t\t"},
{ WI_RID_TX_RATE, WI_WORDS, "TX rate (selection):\t\t\t"},
{ WI_RID_CUR_TX_RATE, WI_WORDS, "TX rate (actual speed):\t\t\t"},
{ WI_RID_RTS_THRESH, WI_WORDS, "RTS/CTS handshake threshold:\t\t"},
{ WI_RID_CREATE_IBSS, WI_BOOL, "Create IBSS:\t\t\t\t" },
{ WI_RID_SYSTEM_SCALE, WI_WORDS, "Access point density:\t\t\t" },
@ -313,13 +422,28 @@ static struct wi_table wi_table[] = {
{ 0, NULL }
};
static struct wi_table wi_crypt_table[] = {
{ WI_RID_ENCRYPTION, WI_BOOL, "WEP encryption:\t\t\t\t" },
{ WI_RID_TX_CRYPT_KEY, WI_WORDS, "TX encryption key:\t\t\t" },
{ WI_RID_DEFLT_CRYPT_KEYS, WI_KEYSTRUCT, "Encryption keys:\t\t\t" },
{ 0, NULL }
};
static void wi_dumpinfo(iface)
char *iface;
{
struct wi_req wreq;
int i;
int i, has_wep;
struct wi_table *w;
bzero((char *)&wreq, sizeof(wreq));
wreq.wi_len = WI_MAX_DATALEN;
wreq.wi_type = WI_RID_WEP_AVAIL;
wi_getval(iface, &wreq);
has_wep = wreq.wi_val[0];
w = wi_table;
for (i = 0; w[i].wi_type; i++) {
@ -349,6 +473,41 @@ static void wi_dumpinfo(iface)
printf("\n");
}
if (has_wep) {
w = wi_crypt_table;
for (i = 0; w[i].wi_type; i++) {
bzero((char *)&wreq, sizeof(wreq));
wreq.wi_len = WI_MAX_DATALEN;
wreq.wi_type = w[i].wi_code;
wi_getval(iface, &wreq);
printf("%s", w[i].wi_str);
switch(w[i].wi_type) {
case WI_STRING:
wi_printstr(&wreq);
break;
case WI_WORDS:
if (wreq.wi_type == WI_RID_TX_CRYPT_KEY)
wreq.wi_val[0]++;
wi_printwords(&wreq);
break;
case WI_BOOL:
wi_printbool(&wreq);
break;
case WI_HEXBYTES:
wi_printhex(&wreq);
break;
case WI_KEYSTRUCT:
wi_printkeys(&wreq);
break;
default:
break;
}
printf("\n");
}
}
return;
}
@ -427,10 +586,13 @@ static void usage(p)
fprintf(stderr, "\t%s -i iface -a access point density\n", p);
fprintf(stderr, "\t%s -i iface -m mac address\n", p);
fprintf(stderr, "\t%s -i iface -d max data length\n", p);
fprintf(stderr, "\t%s -i iface -e 0|1\n", p);
fprintf(stderr, "\t%s -i iface -k encryption key [-v 1|2|3|4]\n", p);
fprintf(stderr, "\t%s -i iface -r RTS threshold\n", p);
fprintf(stderr, "\t%s -i iface -f frequency\n", p);
fprintf(stderr, "\t%s -i iface -P 0|1t\n", p);
fprintf(stderr, "\t%s -i iface -S max sleep duration\n", p);
fprintf(stderr, "\t%s -i iface -T 1|2|3|4\n", p);
#ifdef WICACHE
fprintf(stderr, "\t%s -i iface -Z zero out signal cache\n", p);
fprintf(stderr, "\t%s -i iface -C print signal cache\n", p);
@ -509,9 +671,11 @@ int main(argc, argv)
int ch;
char *iface = NULL;
char *p = argv[0];
char *key = NULL;
int modifier = 0;
while((ch = getopt(argc, argv,
"hoc:d:f:i:p:r:q:t:n:s:m:P:S:ZC")) != -1) {
"hoc:d:e:f:i:k:p:r:q:t:n:s:m:v:P:S:T:ZC")) != -1) {
switch(ch) {
case 'Z':
#ifdef WICACHE
@ -544,10 +708,17 @@ int main(argc, argv)
wi_setword(iface, WI_RID_MAX_DATALEN, atoi(optarg));
exit(0);
break;
case 'e':
wi_setword(iface, WI_RID_ENCRYPTION, atoi(optarg));
exit(0);
break;
case 'f':
wi_setword(iface, WI_RID_OWN_CHNL, atoi(optarg));
exit(0);
break;
case 'k':
key = optarg;
break;
case 'p':
wi_setword(iface, WI_RID_PORTTYPE, atoi(optarg));
exit(0);
@ -580,10 +751,19 @@ int main(argc, argv)
wi_setword(iface, WI_RID_MAX_SLEEP, atoi(optarg));
exit(0);
break;
case 'T':
wi_setword(iface,
WI_RID_TX_CRYPT_KEY, atoi(optarg) - 1);
exit(0);
break;
case 'P':
wi_setword(iface, WI_RID_PM_ENABLED, atoi(optarg));
exit(0);
break;
case 'v':
modifier = atoi(optarg);
modifier--;
break;
case 'h':
default:
usage(p);
@ -594,10 +774,12 @@ int main(argc, argv)
if (iface == NULL)
usage(p);
if (key != NULL) {
wi_setkeys(iface, key, modifier);
exit(0);
}
wi_dumpinfo(iface);
exit(0);
}