Subject: bin/9422: Bug fix diffs for wiconfig
To: None <gnats-bugs@gnats.netbsd.org>
From: None <mragan@uk.tivoli.com>
List: netbsd-bugs
Date: 02/14/2000 18:52:37
>Number:         9422
>Category:       bin
>Synopsis:       wiconfig does not accept multiple options; core dumps if interface is not set
>Confidential:   no
>Severity:       serious
>Priority:       high
>Responsible:    bin-bug-people (Utility Bug People)
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Mon Feb 14 18:48:00 2000
>Last-Modified:
>Originator:     Matt Ragan
>Organization:
Tivoli Systems UK
>Release:        <NetBSD-current source date> 1.4S Feb 14 2000
>Environment:
	
System: NetBSD rizzo.uk.tivoli.com 1.4S NetBSD 1.4S (RIZZO) #5: Fri Feb 11 20:39:43 GMT 2000 mragan@rizzo.uk.tivoli.com:/home/NetBSD/current/src/sys/arch/i386/compile/RIZZO.nocardbus i386


>Description:
wiconfig does not accept multiple options, even though the documentation
suggests that it does.  After the first option is accepted, the command
quietly exits, in most cases.

Also, if the interface is accidentally left off of the command line, wiconfig
core dumps, due to it trying to configure a null pointer

>How-To-Repeat:
	
Run wiconfig with no interface specified, but with options (core dump)
Run wiconfig with multiple options (first option set, others ignored)

>Fix:

Attached is a shar file with three patch files.

wiconfig.c.patch1 contains the diffs to fix most of the issues associated
wih this PR (see below commentary for the remaining issue and patch).  Apply 
the diff to the current version of usr.sbin/wiconfig/wiconfig.c.  Note that 
the undocumented '-i' option, which allowed an alternate form of interface 
specification, has been removed to simplify argument checking (i.e. it can 
now determine whether an interface was specified, to avoid core dumps).

A more minor problem still exists in that only one encryption key can
be specified per invocation of wiconfig.  wiconfig.c.patch2 remedies this
problem by changing the way to specify an encryption key to have an alternate 
prefix to specify the key to be set, and eliminates the '-v' option 
altogether.  As before, if the option is eliminated, they key defaults
to the first key.  To set multiple keys, you can specify multiple -k options on
the command line (e.g. 'wiconfig wi0 -k 'test1' -k '2:test2' -k '3:test3').
As this changes a documented interface, this fix is contained in a separate
patch (wiconfig.c.patch2), which should be applied on top of a wiconfig.c
that has had the first patch applied to it.

Also included is a patch to the current wiconfig.8 man page, documenting
the interface change.


# This is a shell archive.  Save it in a file, remove anything before
# this line, and then unpack it by entering "sh file".  Note, it may
# create directories; files and directories will be owned by you and
# have default permissions.
#
# This archive contains:
#
#	wiconfig.c.patch1
#	wiconfig.c.patch2
#	wiconfig.8.patch
#
echo x - wiconfig.c.patch1
sed 's/^X//' >wiconfig.c.patch1 << 'END-of-wiconfig.c.patch1'
X*** usr.sbin/wiconfig/wiconfig.c	2000/02/15 00:23:02
X***************
X*** 636,704 ****
X  		memcpy(&argv[1], &argv[2], argc * sizeof(char *));
X  		argc--;
X  	}
X  
X  	while((ch = getopt(argc, argv,
X! 	    "hoc:d:f:p:r:q:t:n:s:i:m:P:S:T:e:k:v:")) != -1) {
X  		switch(ch) {
X  		case 'o':
X  			wi_dumpstats(iface);
X- 			exit(0);
X- 			break;
X- 			if (iface == NULL)
X- 				iface = optarg;
X  			break;
X  		case 'c':
X  			wi_setword(iface, WI_RID_CREATE_IBSS, atoi(optarg));
X- 			exit(0);
X  			break;
X  		case 'd':
X  			wi_setword(iface, WI_RID_MAX_DATALEN, atoi(optarg));
X- 			exit(0);
X  			break;
X  		case 'f':
X  			wi_setword(iface, WI_RID_OWN_CHNL, atoi(optarg));
X- 			exit(0);
X  			break;
X  		case 'p':
X  			wi_setword(iface, WI_RID_PORTTYPE, atoi(optarg));
X- 			exit(0);
X  			break;
X  		case 'r':
X  			wi_setword(iface, WI_RID_RTS_THRESH, atoi(optarg));
X- 			exit(0);
X  			break;
X  		case 't':
X  			wi_setword(iface, WI_RID_TX_RATE, atoi(optarg));
X- 			exit(0);
X  			break;
X  		case 'n':
X  			wi_setstr(iface, WI_RID_DESIRED_SSID, optarg);
X- 			exit(0);
X  			break;
X  		case 's':
X  			wi_setstr(iface, WI_RID_NODENAME, optarg);
X- 			exit(0);
X  			break;
X  		case 'm':
X  			wi_sethex(iface, WI_RID_MAC_NODE, optarg);
X- 			exit(0);
X  			break;
X  		case 'q':
X  			wi_setstr(iface, WI_RID_OWN_SSID, optarg);
X- 			exit(0);
X  			break;
X  		case 'S':
X  			wi_setword(iface, WI_RID_MAX_SLEEP, atoi(optarg));
X- 			exit(0);
X  			break;
X  		case 'P':
X  			wi_setword(iface, WI_RID_PM_ENABLED, atoi(optarg));
X- 			exit(0);
X  			break;
X  		case 'T':
X  			wi_setword(iface, WI_RID_TX_CRYPT_KEY,
X  				   atoi(optarg) - 1);
X- 			exit(0);
X  			break;
X  		case 'k':
X--- 636,694 ----
X  		memcpy(&argv[1], &argv[2], argc * sizeof(char *));
X  		argc--;
X+ 	} else {
X+ 		usage(p);
X+ 		exit(1);
X+ 	}
X+ 
X+ 	if (argc == 1) {
X+ 		wi_dumpinfo(iface);
X+ 		exit(0);
X  	}
X  
X  	while((ch = getopt(argc, argv,
X! 	    "hoc:d:f:p:r:q:t:n:s:m:P:S:T:e:k:v:")) != -1) {
X  		switch(ch) {
X  		case 'o':
X  			wi_dumpstats(iface);
X  			break;
X  		case 'c':
X  			wi_setword(iface, WI_RID_CREATE_IBSS, atoi(optarg));
X  			break;
X  		case 'd':
X  			wi_setword(iface, WI_RID_MAX_DATALEN, atoi(optarg));
X  			break;
X  		case 'f':
X  			wi_setword(iface, WI_RID_OWN_CHNL, atoi(optarg));
X  			break;
X  		case 'p':
X  			wi_setword(iface, WI_RID_PORTTYPE, atoi(optarg));
X  			break;
X  		case 'r':
X  			wi_setword(iface, WI_RID_RTS_THRESH, atoi(optarg));
X  			break;
X  		case 't':
X  			wi_setword(iface, WI_RID_TX_RATE, atoi(optarg));
X  			break;
X  		case 'n':
X  			wi_setstr(iface, WI_RID_DESIRED_SSID, optarg);
X  			break;
X  		case 's':
X  			wi_setstr(iface, WI_RID_NODENAME, optarg);
X  			break;
X  		case 'm':
X  			wi_sethex(iface, WI_RID_MAC_NODE, optarg);
X  			break;
X  		case 'q':
X  			wi_setstr(iface, WI_RID_OWN_SSID, optarg);
X  			break;
X  		case 'S':
X  			wi_setword(iface, WI_RID_MAX_SLEEP, atoi(optarg));
X  			break;
X  		case 'P':
X  			wi_setword(iface, WI_RID_PM_ENABLED, atoi(optarg));
X  			break;
X  		case 'T':
X  			wi_setword(iface, WI_RID_TX_CRYPT_KEY,
X  				   atoi(optarg) - 1);
X  			break;
X  		case 'k':
X***************
X*** 707,711 ****
X  		case 'e':
X  		        wi_setword(iface, WI_RID_ENCRYPTION, atoi(optarg));
X- 			exit(0);
X  			break;
X  		case 'v':
X--- 697,700 ----
X***************
X*** 723,730 ****
X  		usage(p);
X  
X! 	if (key != NULL)
X! 	        wi_setkeys(iface, key, modifier);
X  
X! 	wi_dumpinfo(iface);
X  
X  	exit(0);
X--- 712,730 ----
X  		usage(p);
X  
X! 	/*
X! 	   Unfortunately, due to the way that we process the command line
X! 	   arguments, only one key can be set at a time, since we don't
X! 	   know which key to set until we do or don't see the -v option,
X! 	   which means that wiconfig must be called multiple times if
X! 	   multiple keys are being set.
X! 
X! 	   Perhaps a better way to do this is to embed the key parameter
X! 	   with the key value?  ('-k 1:0xaabbccdd..', where the hex value
X! 	   would have to be used if a ':' existed in the key)
X! 	*/
X  
X! 	if (key != NULL) {
X! 		wi_setkeys(iface, key, modifier);
X! 	}
X  
X  	exit(0);
END-of-wiconfig.c.patch1
echo x - wiconfig.c.patch2
sed 's/^X//' >wiconfig.c.patch2 << 'END-of-wiconfig.c.patch2'
X*** usr.sbin/wiconfig/wiconfig.c	2000/02/15 01:04:23
X***************
X*** 82,86 ****
X  static void wi_printhex		__P((struct wi_req *));
X  static void wi_dumpinfo		__P((char *));
X! static void wi_setkeys		__P((char *, char *, int));
X  static void wi_printkeys	__P((struct wi_req *));
X  static void wi_dumpstats	__P((char *));
X--- 82,86 ----
X  static void wi_printhex		__P((struct wi_req *));
X  static void wi_dumpinfo		__P((char *));
X! static void wi_setkeys		__P((char *, char *));
X  static void wi_printkeys	__P((struct wi_req *));
X  static void wi_dumpstats	__P((char *));
X***************
X*** 296,307 ****
X  }
X  
X! static void wi_setkeys(iface, key, idx)
X          char                    *iface;
X          char                    *key;
X-         int                     idx;
X  {
X          struct wi_req           wreq;
X          struct wi_ltv_keys      *keys;
X          struct wi_key           *k;
X  
X  	if (iface == NULL)
X--- 296,307 ----
X  }
X  
X! static void wi_setkeys(iface, key)
X          char                    *iface;
X          char                    *key;
X  {
X          struct wi_req           wreq;
X          struct wi_ltv_keys      *keys;
X          struct wi_key           *k;
X+         int                     idx = 0;
X  
X  	if (iface == NULL)
X***************
X*** 323,326 ****
X--- 323,334 ----
X          keys = (struct wi_ltv_keys *)&wreq;
X  
X+ 	if (key[1] == ':') {
X+ 		idx = key[0] - '1';
X+ 		if ((idx < 0) || (idx > 3)) {
X+ 			err(1, "key format: [1|2|3|4:]key");
X+ 		}
X+ 		key += 2;
X+ 	}
X+ 		
X          if (key[0] == '0' && (key[1] == 'x' || key[1] == 'X')) {
X  	        if (strlen(key) > 30)
X***************
X*** 615,619 ****
X  	    "usage: wiconfig interface "
X  	    "[-o] [-t tx rate] [-n network name] [-s station name]\n"
X! 	    "       [-e 0|1] [-k key [-v 1|2|3|4]] [-T 1|2|3|4]\n"
X  	    "       [-c 0|1] [-q SSID] [-p port type] [-a access point density]\n"
X  	    "       [-m MAC address] [-d max data length] [-r RTS threshold]\n"
X--- 623,627 ----
X  	    "usage: wiconfig interface "
X  	    "[-o] [-t tx rate] [-n network name] [-s station name]\n"
X! 	    "       [-e 0|1] [-k [1|2|3|4:]key [-T 1|2|3|4]\n"
X  	    "       [-c 0|1] [-q SSID] [-p port type] [-a access point density]\n"
X  	    "       [-m MAC address] [-d max data length] [-r RTS threshold]\n"
X***************
X*** 629,634 ****
X  	char			*iface = NULL;
X  	char			*p = argv[0];
X- 	char                    *key = NULL;
X- 	int                     modifier = 0;
X  
X  	if (argc > 1 && argv[1][0] != '-') {
X--- 637,640 ----
X***************
X*** 647,651 ****
X  
X  	while((ch = getopt(argc, argv,
X! 	    "hoc:d:f:p:r:q:t:n:s:m:P:S:T:e:k:v:")) != -1) {
X  		switch(ch) {
X  		case 'o':
X--- 653,657 ----
X  
X  	while((ch = getopt(argc, argv,
X! 	    "hoc:d:f:p:r:q:t:n:s:m:P:S:T:e:k:")) != -1) {
X  		switch(ch) {
X  		case 'o':
X***************
X*** 693,705 ****
X  			break;
X  		case 'k':
X! 		        key = optarg;
X  			break;
X  		case 'e':
X  		        wi_setword(iface, WI_RID_ENCRYPTION, atoi(optarg));
X  			break;
X- 		        modifier = atoi(optarg);
X- 			modifier--;
X- 			break;
X  		case 'h':
X  		default:
X--- 699,707 ----
X  			break;
X  		case 'k':
X! 			wi_setkeys(iface, optarg);
X  			break;
X  		case 'e':
X  		        wi_setword(iface, WI_RID_ENCRYPTION, atoi(optarg));
X  			break;
X  		case 'h':
X  		default:
X***************
X*** 711,720 ****
X  	if (iface == NULL)
X  		usage(p);
X- 
X- 	/* Why do we do this here, rather than above? */
X- 
X- 	if (key != NULL) {
X- 		wi_setkeys(iface, key, modifier);
X- 	}
X  
X  	exit(0);
X--- 713,716 ----
END-of-wiconfig.c.patch2
echo x - wiconfig.8.patch
sed 's/^X//' >wiconfig.8.patch << 'END-of-wiconfig.8.patch'
X*** wiconfig.8	2000/02/15 02:03:29
X***************
X*** 44,48 ****
X  .Op Fl o
X  .Op Fl e Ar 0|1
X! .Op Fl k Ar key "[ -v 1|2|3|4 ]"
X  .Op Fl t Ar tx rate
X  .Op Fl n Ar network name
X--- 44,48 ----
X  .Op Fl o
X  .Op Fl e Ar 0|1
X! .Op Fl k Ar [1|2|3|4:]key
X  .Op Fl t Ar tx rate
X  .Op Fl n Ar network name
X***************
X*** 100,112 ****
X  .Ar 1
X  (encryption enabled). Encryption is off by default.
X! .It Fl k Ar key "[ -v 1|2|3|4 ]"
X  Set WEP encryption keys. There are four default encryption keys that can be
X! programmed. A specific key can be set using the
X! .Fl v
X! flag. If the
X! .Fl v
X! flag is not specified, the first key will be set. Encryption keys can either
X! be normal text (i.e., "hello") or a series of hexadecimal digits
X! (i.e., "0x1234512345"). For WaveLAN Silver cards, the key is
X  restricted to 40 bits, hence the key can be either a 5-character text string
X  or 10 hexadecimal digits. For WaveLAN Gold cards, the key can be up to
X--- 100,113 ----
X  .Ar 1
X  (encryption enabled). Encryption is off by default.
X! .It Fl k Ar [1|2|3|4:]key
X  Set WEP encryption keys. There are four default encryption keys that can be
X! programmed. A specific key can be set by prefixing the key with a numeric
X! value and a colon.  If this prefix is omitted, the first key will be set.
X! Encryption keys can either
X! be normal text (e.g., "hello") or a series of hexadecimal digits
X! (e.g., "0x1234512345").  Note that due to syntactical issues, if a key
X! has a colon as its second character, it must either be prefixed with the
X! key value and a colon (e.g. "1:a:key"), or be specified in hex format.
X! (For WaveLAN Silver cards, the key is
X  restricted to 40 bits, hence the key can be either a 5-character text string
X  or 10 hexadecimal digits. For WaveLAN Gold cards, the key can be up to
END-of-wiconfig.8.patch
exit

>Audit-Trail:
>Unformatted: