Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 24 May 2001 23:19:35 -0400
From:      Peter Radcliffe <pir@pir.net>
To:        freebsd-mobile@FreeBSD.ORG
Subject:   Re: if_wi.c with encryption for 3.4-RELEASE/PAO?
Message-ID:  <20010524231934.I24699@pir.net>
In-Reply-To: <20010524205128.A25731@chaos.obstruction.com>; from guy@obstruction.com on Thu, May 24, 2001 at 08:51:28PM -0400
References:  <20010524205128.A25731@chaos.obstruction.com>

next in thread | previous in thread | raw e-mail | index | archive | help

--AhhlLboLdkugWU4S
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline

Guy Middleton <guy@obstruction.com> probably said:
> I have a Lucent Orinico/Wavelan card working fine with 3.4-RELEASE+PAO,
> but I would like to be able to turn on encryption, which the driver I am
> using does not support.

Greg backported those changes a while back. Patch attatched.

-- 
pir                  pir@pir.net                    pir@net.tufts.edu


--AhhlLboLdkugWU4S
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="wep.diffs.patch"

--- if_wavelan_ieee.h	Mon Apr 10 11:13:49 2000
+++ /usr/src/sys/i386/include/if_wavelan_ieee.h	Mon Apr 10 10:45:53 2000
@@ -185,6 +185,8 @@
 #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
@@ -216,7 +218,20 @@
 #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
--- if_wi.c	Mon Apr 10 11:13:55 2000
+++ /usr/src/sys/i386/isa/if_wi.c	Mon Apr 10 10:48:36 2000
@@ -344,6 +344,14 @@
 	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);
@@ -975,6 +983,16 @@
 	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;
 	}
@@ -1042,6 +1060,9 @@
 			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));
 		} else {
 			if (wi_read_record(sc, (struct wi_ltv_gen *)&wreq)) {
 				error = EINVAL;
@@ -1137,6 +1158,15 @@
 	bcopy((char *)&sc->arpcom.ac_enaddr,
 	   (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) {
--- if_wireg.h	Mon Apr 10 11:14:01 2000
+++ /usr/src/sys/i386/isa/if_wireg.h	Mon Apr 10 10:49:27 2000
@@ -56,6 +56,27 @@
 	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;
@@ -79,7 +100,11 @@
 	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];
+	int			wi_has_wep;
+	int			wi_use_wep;
+	int			wi_tx_key;
+	struct wi_ltv_keys	wi_keys;
 	struct wi_counters	wi_stats;
 	struct callout_handle	wi_stat_ch;
 };
--- wicontrol.8	Mon Apr 10 11:14:09 2000
+++ /usr/src/usr.sbin/wicontrol/wicontrol.8	Mon Apr 10 10:50:28 2000
@@ -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
@@ -202,6 +209,34 @@
 .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
--- wicontrol.c	Mon Apr 10 11:14:13 2000
+++ /usr/src/usr.sbin/wicontrol/wicontrol.c	Mon Apr 10 10:52:51 2000
@@ -70,6 +70,8 @@
 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 @@
 	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 @@
 #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 @@
 	{ 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 @@
 	{ 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++) {
@@ -345,10 +469,45 @@
 			break;
 		default:
 			break;
		}	
 		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;
 }
 
@@ -426,11 +585,14 @@
 	fprintf(stderr, "\t%s -i iface -p port type\n", 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 -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 -d max data length\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);
 
 	exit(1);
 }
@@ -442,9 +604,11 @@
 	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:")) != -1) {
+	    "hoc:d:e:f:i:k:p:r:q:t:n:s:m:v:P:S:T:")) != -1) {
 		switch(ch) {
 		case 'o':
 			wi_dumpstats(iface);
@@ -461,10 +625,17 @@
 			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);
@@ -497,10 +668,19 @@
 			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);
@@ -510,6 +690,11 @@
 
 	if (iface == NULL)
 		usage(p);
+
+	if (key != NULL) {
+		wi_setkeys(iface, key, modifier);
+		exit(0);
+	}
 
 	wi_dumpinfo(iface);
 


--AhhlLboLdkugWU4S--

To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-mobile" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20010524231934.I24699>