1/*******************************************************************************
2 * Agere Systems Inc.
3 * Wireless device driver for Linux (wlags49).
4 *
5 * Copyright (c) 1998-2003 Agere Systems Inc.
6 * All rights reserved.
7 *   http://www.agere.com
8 *
9 * Initially developed by TriplePoint, Inc.
10 *   http://www.triplepoint.com
11 *
12 *------------------------------------------------------------------------------
13 *
14 *   This file defines routines required to parse configuration parameters
15 *   listed in a config file, if that config file exists.
16 *
17 *------------------------------------------------------------------------------
18 *
19 * SOFTWARE LICENSE
20 *
21 * This software is provided subject to the following terms and conditions,
22 * which you should read carefully before using the software.  Using this
23 * software indicates your acceptance of these terms and conditions.  If you do
24 * not agree with these terms and conditions, do not use the software.
25 *
26 * Copyright © 2003 Agere Systems Inc.
27 * All rights reserved.
28 *
29 * Redistribution and use in source or binary forms, with or without
30 * modifications, are permitted provided that the following conditions are met:
31 *
32 * . Redistributions of source code must retain the above copyright notice, this
33 *    list of conditions and the following Disclaimer as comments in the code as
34 *    well as in the documentation and/or other materials provided with the
35 *    distribution.
36 *
37 * . Redistributions in binary form must reproduce the above copyright notice,
38 *    this list of conditions and the following Disclaimer in the documentation
39 *    and/or other materials provided with the distribution.
40 *
41 * . Neither the name of Agere Systems Inc. nor the names of the contributors
42 *    may be used to endorse or promote products derived from this software
43 *    without specific prior written permission.
44 *
45 * Disclaimer
46 *
47 * THIS SOFTWARE IS PROVIDED AS IS AND ANY EXPRESS OR IMPLIED WARRANTIES,
48 * INCLUDING, BUT NOT LIMITED TO, INFRINGEMENT AND THE IMPLIED WARRANTIES OF
49 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  ANY
50 * USE, MODIFICATION OR DISTRIBUTION OF THIS SOFTWARE IS SOLELY AT THE USERS OWN
51 * RISK. IN NO EVENT SHALL AGERE SYSTEMS INC. OR CONTRIBUTORS BE LIABLE FOR ANY
52 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
53 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
54 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
55 * ON ANY THEORY OF LIABILITY, INCLUDING, BUT NOT LIMITED TO, CONTRACT, STRICT
56 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
57 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
58 * DAMAGE.
59 *
60 ******************************************************************************/
61
62/* Only include this file if USE_PROFILE is defined */
63#ifdef USE_PROFILE
64
65
66
67
68/*******************************************************************************
69 *  constant definitions
70 ******************************************************************************/
71
72
73/* Allow support for calling system fcns to parse config file */
74#define __KERNEL_SYSCALLS__
75
76
77
78
79/*******************************************************************************
80 * include files
81 ******************************************************************************/
82#include <wl_version.h>
83
84#include <linux/netdevice.h>
85#include <linux/etherdevice.h>
86#include <linux/unistd.h>
87#include <asm/uaccess.h>
88#include <limits.h>
89
90#define BIN_DL 1
91
92#include <debug.h>
93#include <hcf.h>
94/* #include <hcfdef.h> */
95
96#include <wl_if.h>
97#include <wl_internal.h>
98#include <wl_util.h>
99#include <wl_enc.h>
100#include <wl_main.h>
101#include <wl_profile.h>
102
103
104/*******************************************************************************
105 * global variables
106 ******************************************************************************/
107
108/* Definition needed to prevent unresolved external in unistd.h */
109static int errno;
110
111#if DBG
112extern p_u32    DebugFlag;
113extern dbg_info_t *DbgInfo;
114#endif
115
116int parse_yes_no(char *value);
117
118
119int parse_yes_no(char *value)
120{
121int rc = 0;										/* default to NO for invalid parameters */
122
123	if (strlen(value) == 1) {
124		if ((value[0] | ('Y'^'y')) == 'y')
125			rc = 1;
126	/* } else { */
127		/* this should not be debug time info, it is an enduser data entry error ;? */
128		/* DBG_WARNING(DbgInfo, "%s invalid; will be ignored\n", PARM_NAME_MICROWAVE_ROBUSTNESS); */
129	}
130	return rc;
131} /* parse_yes_no */
132
133
134/*******************************************************************************
135 *	parse_config()
136 *******************************************************************************
137 *
138 *  DESCRIPTION:
139 *
140 *      This function opens the device's config file and parses the options from
141 *   it, so that it can properly configure itself. If no configuration file
142 *   or configuration is present, then continue to use the options already
143 *   parsed from config.opts or wireless.opts.
144 *
145 *  PARAMETERS:
146 *
147 *      dev - a pointer to the device's net_device structure
148 *
149 *  RETURNS:
150 *
151 *      N/A
152 *
153 ******************************************************************************/
154void parse_config(struct net_device *dev)
155{
156	int				    file_desc;
157#if 0 /* BIN_DL */
158	int				rc;
159	char				*cp = NULL;
160#endif /* BIN_DL */
161	char                buffer[MAX_LINE_SIZE];
162	char                filename[MAX_LINE_SIZE];
163	mm_segment_t	    fs;
164	struct wl_private   *wvlan_config = NULL;
165	ENCSTRCT            sEncryption;
166	/*------------------------------------------------------------------------*/
167
168	DBG_FUNC("parse_config");
169	DBG_ENTER(DbgInfo);
170
171	/* Get the wavelan specific info for this device */
172	wvlan_config = dev->priv;
173	if (wvlan_config == NULL) {
174		DBG_ERROR(DbgInfo, "Wavelan specific info struct not present?\n");
175		return;
176	}
177
178	/* setup the default encryption string */
179	strcpy(wvlan_config->szEncryption, DEF_CRYPT_STR);
180
181	/* Obtain a user-space process context, storing the original context */
182	fs = get_fs();
183	set_fs(get_ds());
184
185	/* Determine the filename for this device and attempt to open it */
186	sprintf(filename, "%s%s", ROOT_CONFIG_FILENAME, dev->name);
187	file_desc = open(filename, O_RDONLY, 0);
188	if (file_desc != -1) {
189		DBG_TRACE(DbgInfo, "Wireless config file found. Parsing options...\n");
190
191		/* Read out the options */
192		while (readline(file_desc, buffer))
193			translate_option(buffer, wvlan_config);
194		/* Close the file */
195		close(file_desc);	/* ;?even if file_desc == -1 ??? */
196	} else {
197		DBG_TRACE(DbgInfo, "No iwconfig file found for this device; "
198				   "config.opts or wireless.opts will be used\n");
199	}
200	/* Return to the original context */
201	set_fs(fs);
202
203	/* convert the WEP keys, if read in as key1, key2, type of data */
204	if (wvlan_config->EnableEncryption) {
205		memset(&sEncryption, 0, sizeof(sEncryption));
206
207		wl_wep_decode(CRYPT_CODE, &sEncryption,
208						   wvlan_config->szEncryption);
209
210		/* the Linux driver likes to use 1-4 for the key IDs, and then
211		   convert to 0-3 when sending to the card.  The Windows code
212		   base used 0-3 in the API DLL, which was ported to Linux.  For
213		   the sake of the user experience, we decided to keep 0-3 as the
214		   numbers used in the DLL; and will perform the +1 conversion here.
215		   We could have converted  the entire Linux driver, but this is
216		   less obtrusive.  This may be a "todo" to convert the whole driver */
217		sEncryption.wEnabled = wvlan_config->EnableEncryption;
218		sEncryption.wTxKeyID = wvlan_config->TransmitKeyID - 1;
219
220		memcpy(&sEncryption.EncStr, &wvlan_config->DefaultKeys,
221				sizeof(CFG_DEFAULT_KEYS_STRCT));
222
223		memset(wvlan_config->szEncryption, 0, sizeof(wvlan_config->szEncryption));
224
225		wl_wep_code(CRYPT_CODE, wvlan_config->szEncryption, &sEncryption,
226						 sizeof(sEncryption));
227	}
228
229	/* decode the encryption string for the call to wl_commit() */
230	wl_wep_decode(CRYPT_CODE, &sEncryption, wvlan_config->szEncryption);
231
232	wvlan_config->TransmitKeyID    = sEncryption.wTxKeyID + 1;
233	wvlan_config->EnableEncryption = sEncryption.wEnabled;
234
235	memcpy(&wvlan_config->DefaultKeys, &sEncryption.EncStr,
236			sizeof(CFG_DEFAULT_KEYS_STRCT));
237
238#if 0 /* BIN_DL */
239		/* Obtain a user-space process context, storing the original context */
240		fs = get_fs();
241		set_fs(get_ds());
242
243		/* ;?just to fake something */
244		strcpy(/*wvlan_config->fw_image_*/filename, "/etc/agere/fw.bin");
245		file_desc = open(/*wvlan_config->fw_image_*/filename, 0, 0);
246		if (file_desc == -1) {
247			DBG_ERROR(DbgInfo, "No image file found\n");
248		} else {
249			DBG_TRACE(DbgInfo, "F/W image file found\n");
250#define DHF_ALLOC_SIZE 96000			/* just below 96K, let's hope it suffices for now and for the future */
251			cp = vmalloc(DHF_ALLOC_SIZE);
252			if (cp == NULL) {
253				DBG_ERROR(DbgInfo, "error in vmalloc\n");
254			} else {
255				rc = read(file_desc, cp, DHF_ALLOC_SIZE);
256				if (rc == DHF_ALLOC_SIZE) {
257					DBG_ERROR(DbgInfo, "buffer too small, %d\n", DHF_ALLOC_SIZE);
258				} else if (rc > 0) {
259					DBG_TRACE(DbgInfo, "read O.K.: %d bytes  %.12s\n", rc, cp);
260					rc = read(file_desc, &cp[rc], 1);
261					if (rc == 0)
262						DBG_TRACE(DbgInfo, "no more to read\n");
263				}
264				if (rc != 0) {
265					DBG_ERROR(DbgInfo, "file not read in one swoop or other error"\
266										", give up, too complicated, rc = %0X\n", rc);
267				}
268				vfree(cp);
269			}
270			close(file_desc);
271		}
272		set_fs(fs);			/* Return to the original context */
273#endif /* BIN_DL */
274
275	DBG_LEAVE(DbgInfo);
276	return;
277} /* parse_config */
278
279/*******************************************************************************
280 *	readline()
281 *******************************************************************************
282 *
283 *  DESCRIPTION:
284 *
285 *      This function reads in data from a given file one line at a time,
286 *   converting the detected newline character '\n' to a null '\0'. Note that
287 *   the file descriptor must be valid before calling this function.
288 *
289 *  PARAMETERS:
290 *
291 *      filedesc    - the file descriptor for the open configuration file
292 *      buffer      - a buffer pointer, passed in by the caller, to which the
293 *                    line will be stored.
294 *
295 *  RETURNS:
296 *
297 *      the number of bytes read
298 *      -1 on error
299 *
300 ******************************************************************************/
301int readline(int filedesc, char *buffer)
302{
303	int result = -1;
304	int bytes_read = 0;
305	/*------------------------------------------------------------------------*/
306
307	/* Make sure the file descriptor is good */
308	if (filedesc != -1) {
309		/* Read in from the file byte by byte until a newline is reached */
310		while ((result = read(filedesc, &buffer[bytes_read], 1)) == 1) {
311			if (buffer[bytes_read] == '\n') {
312				buffer[bytes_read] = '\0';
313				bytes_read++;
314				break;
315			}
316			bytes_read++;
317		}
318	}
319
320	/* Return the number of bytes read */
321	if (result == -1)
322		return result;
323	else
324		return bytes_read;
325} /* readline */
326/*============================================================================*/
327
328/*******************************************************************************
329 *	translate_option()
330 *******************************************************************************
331 *
332 *  DESCRIPTION:
333 *
334 *      This function takes a line read in from the config file and parses out
335 *   the key/value pairs. It then determines which key has been parsed and sets
336 *   the card's configuration based on the value given.
337 *
338 *  PARAMETERS:
339 *
340 *      buffer - a buffer containing a line to translate
341 *      config - a pointer to the device's private adapter structure
342 *
343 *  RETURNS:
344 *
345 *      N/A
346 *
347 ******************************************************************************/
348void translate_option(char *buffer, struct wl_private *lp)
349{
350	unsigned int value_convert = 0;
351	int string_length = 0;
352	char *key = NULL;
353	char *value = NULL;
354	u_char mac_value[ETH_ALEN];
355	/*------------------------------------------------------------------------*/
356
357	DBG_FUNC("translate_option");
358
359	if (buffer == NULL || lp == NULL) {
360		DBG_ERROR(DbgInfo, "Config file buffer and/or wavelan buffer ptr NULL\n");
361		return;
362	}
363
364	ParseConfigLine(buffer, &key, &value);
365
366	if (key == NULL || value == NULL)
367		return;
368
369	/* Determine which key it is and perform the appropriate action */
370
371	/* Configuration parameters used in all scenarios */
372#if DBG
373	/* handle DebugFlag as early as possible so it starts its influence as early
374	 * as possible
375	 */
376	if (strcmp(key, PARM_NAME_DEBUG_FLAG) == 0) {
377		if (DebugFlag == ~0) {			/* if DebugFlag is not specified on the command line */
378			if (DbgInfo->DebugFlag == 0) {	/* if pc_debug did not set DebugFlag (i.e.pc_debug is
379											 * not specified or specified outside the 4-8 range
380											 */
381				DbgInfo->DebugFlag |= DBG_DEFAULTS;
382			}
383		} else {
384			DbgInfo->DebugFlag = simple_strtoul(value, NULL, 0); /* ;?DebugFlag; */
385		}
386		DbgInfo->DebugFlag = simple_strtoul(value, NULL, 0); /* ;?Delete ASAP */
387	}
388#endif /* DBG */
389	if (strcmp(key, PARM_NAME_AUTH_KEY_MGMT_SUITE) == 0) {
390		DBG_TRACE(DbgInfo, "%s, value: %s\n", PARM_NAME_AUTH_KEY_MGMT_SUITE, value);
391
392		value_convert = simple_strtoul(value, NULL, 0);
393		if ((value_convert >= PARM_MIN_AUTH_KEY_MGMT_SUITE) || (value_convert <= PARM_MAX_AUTH_KEY_MGMT_SUITE))
394			lp->AuthKeyMgmtSuite = value_convert;
395		else
396			DBG_WARNING(DbgInfo, "%s invalid; will be ignored\n", PARM_NAME_AUTH_KEY_MGMT_SUITE);
397	} else if (strcmp(key, PARM_NAME_BRSC_2GHZ) == 0) {
398		DBG_TRACE(DbgInfo, "%s, value: %s\n", PARM_NAME_BRSC_2GHZ, value);
399
400		value_convert = simple_strtoul(value, NULL, 0);
401		if ((value_convert >= PARM_MIN_BRSC) || (value_convert <= PARM_MAX_BRSC))
402			lp->brsc[0] = value_convert;
403		else
404			DBG_WARNING(DbgInfo, "%s invaid; will be ignored\n", PARM_NAME_BRSC_2GHZ);
405	} else if (strcmp(key, PARM_NAME_BRSC_5GHZ) == 0) {
406		DBG_TRACE(DbgInfo, "%s, value: %s\n", PARM_NAME_BRSC_5GHZ, value);
407
408		value_convert = simple_strtoul(value, NULL, 0);
409		if ((value_convert >= PARM_MIN_BRSC) || (value_convert <= PARM_MAX_BRSC))
410			lp->brsc[1] = value_convert;
411		else
412			DBG_WARNING(DbgInfo, "%s invaid; will be ignored\n", PARM_NAME_BRSC_5GHZ);
413	} else if ((strcmp(key, PARM_NAME_DESIRED_SSID) == 0) || (strcmp(key, PARM_NAME_OWN_SSID) == 0)) {
414		DBG_TRACE(DbgInfo, "SSID, value: %s\n", value);
415
416		memset(lp->NetworkName, 0, (PARM_MAX_NAME_LEN + 1));
417
418		/* Make sure the value isn't too long */
419		string_length = strlen(value);
420		if (string_length > PARM_MAX_NAME_LEN) {
421			DBG_WARNING(DbgInfo, "SSID too long; will be truncated\n");
422			string_length = PARM_MAX_NAME_LEN;
423		}
424
425		memcpy(lp->NetworkName, value, string_length);
426	}
427#if 0
428	else if (strcmp(key, PARM_NAME_DOWNLOAD_FIRMWARE) == 0) {
429		DBG_TRACE(DbgInfo, "DOWNLOAD_FIRMWARE, value: %s\n", value);
430		memset(lp->fw_image_filename, 0, (MAX_LINE_SIZE + 1));
431		/* Make sure the value isn't too long */
432		string_length = strlen(value);
433		if (string_length > MAX_LINE_SIZE)
434			DBG_WARNING(DbgInfo, "F/W image file name too long; will be ignored\n");
435		else
436			memcpy(lp->fw_image_filename, value, string_length);
437	}
438#endif
439	else if (strcmp(key, PARM_NAME_ENABLE_ENCRYPTION) == 0) {
440		DBG_TRACE(DbgInfo, "%s, value: %s\n", PARM_NAME_ENABLE_ENCRYPTION, value);
441
442		value_convert = simple_strtoul(value, NULL, 0);
443		if ((value_convert >= PARM_MIN_ENABLE_ENCRYPTION) && (value_convert <= PARM_MAX_ENABLE_ENCRYPTION))
444			lp->EnableEncryption = value_convert;
445		else
446			DBG_WARNING(DbgInfo, "%s invalid; will be ignored\n", PARM_NAME_ENABLE_ENCRYPTION);
447	} else if (strcmp(key, PARM_NAME_ENCRYPTION) == 0) {
448		DBG_TRACE(DbgInfo, "%s, value: %s\n", PARM_NAME_ENCRYPTION, value);
449
450		memset(lp->szEncryption, 0, sizeof(lp->szEncryption));
451
452		/* Make sure the value isn't too long */
453		string_length = strlen(value);
454		if (string_length > sizeof(lp->szEncryption)) {
455			DBG_WARNING(DbgInfo, "%s too long; will be truncated\n", PARM_NAME_ENCRYPTION);
456			string_length = sizeof(lp->szEncryption);
457		}
458
459		memcpy(lp->szEncryption, value, string_length);
460	} else if (strcmp(key, PARM_NAME_KEY1) == 0) {
461		DBG_TRACE(DbgInfo, "%s, value: %s\n", PARM_NAME_KEY1, value);
462
463		if (is_valid_key_string(value)) {
464			memset(lp->DefaultKeys.key[0].key, 0, MAX_KEY_SIZE);
465
466			key_string2key(value, &lp->DefaultKeys.key[0]);
467		} else {
468			 DBG_WARNING(DbgInfo, "%s invalid; will be ignored\n", PARM_NAME_KEY1);
469		}
470	} else if (strcmp(key, PARM_NAME_KEY2) == 0) {
471		DBG_TRACE(DbgInfo, "%s, value: %s\n", PARM_NAME_KEY2, value);
472
473		if (is_valid_key_string(value)) {
474			memset(lp->DefaultKeys.key[1].key, 0, MAX_KEY_SIZE);
475
476			key_string2key(value, &lp->DefaultKeys.key[1]);
477		} else {
478			 DBG_WARNING(DbgInfo, "%s invalid; will be ignored\n", PARM_NAME_KEY2);
479		}
480	} else if (strcmp(key, PARM_NAME_KEY3) == 0) {
481		DBG_TRACE(DbgInfo, "%s, value: %s\n", PARM_NAME_KEY3, value);
482
483		if (is_valid_key_string(value)) {
484			memset(lp->DefaultKeys.key[2].key, 0, MAX_KEY_SIZE);
485
486			key_string2key(value, &lp->DefaultKeys.key[2]);
487		} else {
488			 DBG_WARNING(DbgInfo, "%s invalid; will be ignored\n", PARM_NAME_KEY3);
489		}
490	} else if (strcmp(key, PARM_NAME_KEY4) == 0) {
491		DBG_TRACE(DbgInfo, "%s, value: %s\n", PARM_NAME_KEY4, value);
492
493		if (is_valid_key_string(value)) {
494			memset(lp->DefaultKeys.key[3].key, 0, MAX_KEY_SIZE);
495
496			key_string2key(value, &lp->DefaultKeys.key[3]);
497		} else {
498			 DBG_WARNING(DbgInfo, "%s invalid; will be ignored\n", PARM_NAME_KEY4);
499		}
500	}
501	/* New Parameters for WARP */
502	else if (strcmp(key, PARM_NAME_LOAD_BALANCING) == 0) {
503		DBG_TRACE(DbgInfo, "%s, value: %s\n", PARM_NAME_LOAD_BALANCING, value);
504		lp->loadBalancing = parse_yes_no(value);
505	} else if (strcmp(key, PARM_NAME_MEDIUM_DISTRIBUTION) == 0) {
506		DBG_TRACE(DbgInfo, "%s, value: %s\n", PARM_NAME_MEDIUM_DISTRIBUTION, value);
507		lp->mediumDistribution = parse_yes_no(value);
508	} else if (strcmp(key, PARM_NAME_MICROWAVE_ROBUSTNESS) == 0) {
509		DBG_TRACE(DbgInfo, "%s, value: %s\n", PARM_NAME_MICROWAVE_ROBUSTNESS, value);
510		lp->MicrowaveRobustness = parse_yes_no(value);
511	} else if (strcmp(key, PARM_NAME_MULTICAST_RATE) == 0) {
512		DBG_TRACE(DbgInfo, "%s, value: %s\n", PARM_NAME_MULTICAST_RATE, value);
513
514		value_convert = simple_strtoul(value, NULL, 0);
515
516		if ((value_convert >= PARM_MIN_MULTICAST_RATE) && (value_convert <= PARM_MAX_MULTICAST_RATE))
517			lp->MulticastRate[0] = value_convert;
518		else
519			DBG_WARNING(DbgInfo, "%s invalid; will be ignored\n", PARM_NAME_MULTICAST_RATE);
520	} else if (strcmp(key, PARM_NAME_OWN_CHANNEL) == 0) {
521		DBG_TRACE(DbgInfo, "%s, value: %s\n", PARM_NAME_OWN_CHANNEL, value);
522
523		value_convert = simple_strtoul(value, NULL, 0);
524		if (wl_is_a_valid_chan(value_convert)) {
525			if (value_convert > 14)
526				value_convert = value_convert | 0x100;
527			lp->Channel = value_convert;
528		} else {
529			DBG_WARNING(DbgInfo, "%s invalid; will be ignored\n", PARM_NAME_OWN_CHANNEL);
530		}
531	} else if (strcmp(key, PARM_NAME_OWN_NAME) == 0) {
532		DBG_TRACE(DbgInfo, "%s, value: %s\n", PARM_NAME_OWN_NAME, value);
533
534		memset(lp->StationName, 0, (PARM_MAX_NAME_LEN + 1));
535
536		/* Make sure the value isn't too long */
537		string_length = strlen(value);
538		if (string_length > PARM_MAX_NAME_LEN) {
539			DBG_WARNING(DbgInfo, "%s too long; will be truncated\n", PARM_NAME_OWN_NAME);
540			string_length = PARM_MAX_NAME_LEN;
541		}
542
543		memcpy(lp->StationName, value, string_length);
544	} else if (strcmp(key, PARM_NAME_RTS_THRESHOLD) == 0) {
545		DBG_TRACE(DbgInfo, "%s, value: %s\n", PARM_NAME_RTS_THRESHOLD, value);
546
547		value_convert = simple_strtoul(value, NULL, 0);
548		if ((value_convert >= PARM_MIN_RTS_THRESHOLD) && (value_convert <= PARM_MAX_RTS_THRESHOLD))
549			lp->RTSThreshold = value_convert;
550		else
551			DBG_WARNING(DbgInfo, "%s invalid; will be ignored\n", PARM_NAME_RTS_THRESHOLD);
552	} else if (strcmp(key, PARM_NAME_SRSC_2GHZ) == 0) {
553		DBG_TRACE(DbgInfo, "%s, value: %s\n", PARM_NAME_SRSC_2GHZ, value);
554
555		value_convert = simple_strtoul(value, NULL, 0);
556		if ((value_convert >= PARM_MIN_SRSC) || (value_convert <= PARM_MAX_SRSC))
557			lp->srsc[0] = value_convert;
558		else
559			DBG_WARNING(DbgInfo, "%s invaid; will be ignored\n", PARM_NAME_SRSC_2GHZ);
560	} else if (strcmp(key, PARM_NAME_SRSC_5GHZ) == 0) {
561		DBG_TRACE(DbgInfo, "%s, value: %s\n", PARM_NAME_SRSC_5GHZ, value);
562
563		value_convert = simple_strtoul(value, NULL, 0);
564		if ((value_convert >= PARM_MIN_SRSC) || (value_convert <= PARM_MAX_SRSC))
565			lp->srsc[1] = value_convert;
566		else
567			DBG_WARNING(DbgInfo, "%s invaid; will be ignored\n", PARM_NAME_SRSC_5GHZ);
568	} else if (strcmp(key, PARM_NAME_SYSTEM_SCALE) == 0) {
569		DBG_TRACE(DbgInfo, "%s, value: %s\n", PARM_NAME_SYSTEM_SCALE, value);
570
571		value_convert = simple_strtoul(value, NULL, 0);
572		if ((value_convert >= PARM_MIN_SYSTEM_SCALE) && (value_convert <= PARM_MAX_SYSTEM_SCALE))
573			lp->DistanceBetweenAPs = value_convert;
574		else
575			DBG_WARNING(DbgInfo, "%s invalid; will be ignored\n", PARM_NAME_SYSTEM_SCALE);
576	} else if (strcmp(key, PARM_NAME_TX_KEY) == 0) {
577		DBG_TRACE(DbgInfo, "%s, value: %s\n", PARM_NAME_TX_KEY, value);
578
579		value_convert = simple_strtoul(value, NULL, 0);
580		if ((value_convert >= PARM_MIN_TX_KEY) && (value_convert <= PARM_MAX_TX_KEY))
581			lp->TransmitKeyID = simple_strtoul(value, NULL, 0);
582		else
583			DBG_WARNING(DbgInfo, "%s invalid; will be ignored\n", PARM_NAME_TX_KEY);
584	} else if (strcmp(key, PARM_NAME_TX_RATE) == 0) {
585		DBG_TRACE(DbgInfo, "%s, value: %s\n", PARM_NAME_TX_RATE, value);
586
587		value_convert = simple_strtoul(value, NULL, 0);
588		if ((value_convert >= PARM_MIN_TX_RATE) && (value_convert <= PARM_MAX_TX_RATE))
589			lp->TxRateControl[0] = value_convert;
590		else
591			DBG_WARNING(DbgInfo, "%s invalid; will be ignored\n", PARM_NAME_TX_RATE);
592	} else if (strcmp(key, PARM_NAME_TX_POW_LEVEL) == 0) {
593		DBG_TRACE(DbgInfo, "%s, value: %s\n", PARM_NAME_TX_POW_LEVEL, value);
594
595		value_convert = simple_strtoul(value, NULL, 0);
596		if ((value_convert >= PARM_MIN_TX_POW_LEVEL) || (value_convert <= PARM_MAX_TX_POW_LEVEL))
597			lp->txPowLevel = value_convert;
598		else
599			DBG_WARNING(DbgInfo, "%s invalid; will be ignored\n", PARM_NAME_TX_POW_LEVEL);
600	}
601
602	/* Need to add? : Country code, Short/Long retry */
603
604	/* Configuration parameters specific to STA mode */
605#if 1 /* ;? (HCF_TYPE) & HCF_TYPE_STA */
606/* ;?seems reasonable that even an AP-only driver could afford this small additional footprint */
607	if (CNV_INT_TO_LITTLE(lp->hcfCtx.IFB_FWIdentity.comp_id) == COMP_ID_FW_STA) {
608					/* ;?should we return an error status in AP mode */
609		if (strcmp(key, PARM_NAME_PORT_TYPE) == 0) {
610			DBG_TRACE(DbgInfo, "%s, value: %s\n", PARM_NAME_PORT_TYPE, value);
611
612			value_convert = simple_strtoul(value, NULL, 0);
613			if ((value_convert == PARM_MIN_PORT_TYPE) || (value_convert == PARM_MAX_PORT_TYPE))
614				lp->PortType = value_convert;
615			else
616				DBG_WARNING(DbgInfo, "%s invalid; will be ignored\n", PARM_NAME_PORT_TYPE);
617		} else if (strcmp(key, PARM_NAME_PM_ENABLED) == 0) {
618			DBG_TRACE(DbgInfo, "%s, value: %s\n", PARM_NAME_PM_ENABLED, value);
619			value_convert = simple_strtoul(value, NULL, 0);
620	/* ;? how about wl_main.c containing
621	 * VALID_PARAM(PARM_PM_ENABLED <= WVLAN_PM_STATE_STANDARD ||
622	 *					 (PARM_PM_ENABLED & 0x7FFF) <= WVLAN_PM_STATE_STANDARD);
623	 */
624			if ((value_convert & 0x7FFF) <= PARM_MAX_PM_ENABLED) {
625				lp->PMEnabled = value_convert;
626			} else {
627				DBG_WARNING(DbgInfo, "%s invalid; will be ignored\n", PARM_NAME_PM_ENABLED);
628				/* ;?this is a data entry error, hence not a DBG_WARNING */
629			}
630		} else if (strcmp(key, PARM_NAME_CREATE_IBSS) == 0) {
631			DBG_TRACE(DbgInfo, "%s, value: %s\n", PARM_NAME_CREATE_IBSS, value);
632			lp->CreateIBSS = parse_yes_no(value);
633		} else if (strcmp(key, PARM_NAME_MULTICAST_RX) == 0) {
634			DBG_TRACE(DbgInfo, "%s, value: %s\n", PARM_NAME_MULTICAST_RX, value);
635			lp->MulticastReceive = parse_yes_no(value);
636		} else if (strcmp(key, PARM_NAME_MAX_SLEEP) == 0) {
637			DBG_TRACE(DbgInfo, "%s, value: %s\n", PARM_NAME_MAX_SLEEP, value);
638
639			value_convert = simple_strtoul(value, NULL, 0);
640			if ((value_convert >= 0) && (value_convert <= 65535))
641				lp->MaxSleepDuration = value_convert;
642			else
643				DBG_WARNING(DbgInfo, "%s invalid; will be ignored\n", PARM_NAME_MAX_SLEEP);
644		} else if (strcmp(key, PARM_NAME_NETWORK_ADDR) == 0) {
645			DBG_TRACE(DbgInfo, "%s, value: %s\n", PARM_NAME_NETWORK_ADDR, value);
646
647			if (parse_mac_address(value, mac_value) == ETH_ALEN)
648				memcpy(lp->MACAddress, mac_value, ETH_ALEN);
649			else
650				DBG_WARNING(DbgInfo, "%s invalid; will be ignored\n", PARM_NAME_NETWORK_ADDR);
651		} else if (strcmp(key, PARM_NAME_AUTHENTICATION) == 0) {
652			DBG_TRACE(DbgInfo, "%s, value: %s\n", PARM_NAME_AUTHENTICATION, value);
653
654			value_convert = simple_strtoul(value, NULL, 0);
655			if ((value_convert >= PARM_MIN_AUTHENTICATION) && (value_convert <= PARM_MAX_AUTHENTICATION))
656				lp->authentication = value_convert;
657			else
658				DBG_WARNING(DbgInfo, "%s invalid; will be ignored\n", PARM_NAME_AUTHENTICATION);
659		} else if (strcmp(key, PARM_NAME_OWN_ATIM_WINDOW) == 0) {
660			DBG_TRACE(DbgInfo, "%s, value: %s\n", PARM_NAME_OWN_ATIM_WINDOW, value);
661
662			value_convert = simple_strtoul(value, NULL, 0);
663			if ((value_convert >= PARM_MIN_OWN_ATIM_WINDOW) && (value_convert <= PARM_MAX_OWN_ATIM_WINDOW))
664				lp->atimWindow = value_convert;
665			else
666				DBG_WARNING(DbgInfo, "%s invalid; will be ignored\n", PARM_NAME_OWN_ATIM_WINDOW);
667		} else if (strcmp(key, PARM_NAME_PM_HOLDOVER_DURATION) == 0) {
668			DBG_TRACE(DbgInfo, "%s, value: %s\n", PARM_NAME_PM_HOLDOVER_DURATION, value);
669
670			value_convert = simple_strtoul(value, NULL, 0);
671			if ((value_convert >= PARM_MIN_PM_HOLDOVER_DURATION) && (value_convert <= PARM_MAX_PM_HOLDOVER_DURATION))
672				lp->holdoverDuration = value_convert;
673			else
674				DBG_WARNING(DbgInfo, "%s invalid; will be ignored\n", PARM_NAME_PM_HOLDOVER_DURATION);
675		} else if (strcmp(key, PARM_NAME_PROMISCUOUS_MODE) == 0) {
676			DBG_TRACE(DbgInfo, "%s, value: %s\n", PARM_NAME_PROMISCUOUS_MODE, value);
677			lp->promiscuousMode = parse_yes_no(value);
678		} else if (strcmp(key, PARM_NAME_CONNECTION_CONTROL) == 0) {
679			DBG_TRACE(DbgInfo, "%s, value: %s\n", PARM_NAME_CONNECTION_CONTROL, value);
680
681			value_convert = simple_strtoul(value, NULL, 0);
682			if ((value_convert >= PARM_MIN_CONNECTION_CONTROL) && (value_convert <= PARM_MAX_CONNECTION_CONTROL))
683				lp->connectionControl = value_convert;
684			else
685				DBG_WARNING(DbgInfo, "%s invalid; will be ignored\n", PARM_NAME_CONNECTION_CONTROL);
686		}
687
688		/* Need to add? : Probe Data Rate */
689	}
690#endif  /* (HCF_TYPE) & HCF_TYPE_STA */
691
692	/* Configuration parameters specific to AP mode */
693#if 1 /* ;? (HCF_TYPE) & HCF_TYPE_AP */
694		/* ;?should we restore this to allow smaller memory footprint */
695	if (CNV_INT_TO_LITTLE(lp->hcfCtx.IFB_FWIdentity.comp_id) == COMP_ID_FW_AP) {
696		if (strcmp(key, PARM_NAME_OWN_DTIM_PERIOD) == 0) {
697			DBG_TRACE(DbgInfo, "%s, value: %s\n", PARM_NAME_OWN_DTIM_PERIOD, value);
698
699			value_convert = simple_strtoul(value, NULL, 0);
700			if (value_convert >= PARM_MIN_OWN_DTIM_PERIOD)
701				lp->DTIMPeriod = value_convert;
702			else
703				DBG_WARNING(DbgInfo, "%s invalid; will be ignored\n", PARM_NAME_OWN_DTIM_PERIOD);
704		} else if (strcmp(key, PARM_NAME_REJECT_ANY) == 0) {
705			DBG_TRACE(DbgInfo, "%s, value: %s\n", PARM_NAME_REJECT_ANY, value);
706			lp->RejectAny = parse_yes_no(value);
707		} else if (strcmp(key, PARM_NAME_EXCLUDE_UNENCRYPTED) == 0) {
708			DBG_TRACE(DbgInfo, "%s, value: %s\n", PARM_NAME_EXCLUDE_UNENCRYPTED, value);
709			lp->ExcludeUnencrypted = parse_yes_no(value);
710		} else if (strcmp(key, PARM_NAME_MULTICAST_PM_BUFFERING) == 0) {
711			DBG_TRACE(DbgInfo, "%s, value: %s\n", PARM_NAME_MULTICAST_PM_BUFFERING, value);
712			lp->ExcludeUnencrypted = parse_yes_no(value);
713		} else if (strcmp(key, PARM_NAME_INTRA_BSS_RELAY) == 0) {
714			DBG_TRACE(DbgInfo, "%s, value: %s\n", PARM_NAME_INTRA_BSS_RELAY, value);
715			lp->ExcludeUnencrypted = parse_yes_no(value);
716		} else if (strcmp(key, PARM_NAME_OWN_BEACON_INTERVAL) == 0) {
717			DBG_TRACE(DbgInfo, "%s, value: %s\n", PARM_NAME_OWN_BEACON_INTERVAL, value);
718
719			value_convert = simple_strtoul(value, NULL, 0);
720			if (value_convert >= PARM_MIN_OWN_BEACON_INTERVAL)
721				lp->ownBeaconInterval = value_convert;
722			else
723				DBG_WARNING(DbgInfo, "%s invalid; will be ignored\n", PARM_NAME_OWN_BEACON_INTERVAL);
724		} else if (strcmp(key, PARM_NAME_COEXISTENCE) == 0) {
725			DBG_TRACE(DbgInfo, "%s, value: %s\n", PARM_NAME_COEXISTENCE, value);
726
727			value_convert = simple_strtoul(value, NULL, 0);
728			if (value_convert >= PARM_MIN_COEXISTENCE)
729				lp->coexistence = value_convert;
730			else
731				DBG_WARNING(DbgInfo, "%s invalid; will be ignored\n", PARM_NAME_COEXISTENCE);
732		}
733
734#ifdef USE_WDS
735		else if (strcmp(key, PARM_NAME_RTS_THRESHOLD1) == 0) {
736			DBG_TRACE(DbgInfo, "%s, value: %s\n", PARM_NAME_RTS_THRESHOLD1, value);
737
738			value_convert = simple_strtoul(value, NULL, 0);
739			if ((value_convert >= PARM_MIN_RTS_THRESHOLD) && (value_convert <= PARM_MAX_RTS_THRESHOLD))
740				lp->wds_port[0].rtsThreshold = value_convert;
741			else
742				DBG_WARNING(DbgInfo, "%s invalid; will be ignored\n", PARM_NAME_RTS_THRESHOLD1);
743		} else if (strcmp(key, PARM_NAME_RTS_THRESHOLD2) == 0) {
744			DBG_TRACE(DbgInfo, "%s, value: %s\n", PARM_NAME_RTS_THRESHOLD2, value);
745
746			value_convert = simple_strtoul(value, NULL, 0);
747			if ((value_convert >= PARM_MIN_RTS_THRESHOLD) && (value_convert <= PARM_MAX_RTS_THRESHOLD))
748				lp->wds_port[1].rtsThreshold = value_convert;
749			else
750				DBG_WARNING(DbgInfo, "%s invalid; will be ignored\n", PARM_NAME_RTS_THRESHOLD2);
751		} else if (strcmp(key, PARM_NAME_RTS_THRESHOLD3) == 0) {
752			DBG_TRACE(DbgInfo, "%s, value: %s\n", PARM_NAME_RTS_THRESHOLD3, value);
753
754			value_convert = simple_strtoul(value, NULL, 0);
755			if ((value_convert >= PARM_MIN_RTS_THRESHOLD) && (value_convert <= PARM_MAX_RTS_THRESHOLD))
756				lp->wds_port[2].rtsThreshold = value_convert;
757			else
758				DBG_WARNING(DbgInfo, "%s invalid; will be ignored\n", PARM_NAME_RTS_THRESHOLD3);
759		} else if (strcmp(key, PARM_NAME_RTS_THRESHOLD4) == 0) {
760			DBG_TRACE(DbgInfo, "%s, value: %s\n", PARM_NAME_RTS_THRESHOLD4, value);
761
762			value_convert = simple_strtoul(value, NULL, 0);
763			if ((value_convert >= PARM_MIN_RTS_THRESHOLD) && (value_convert <= PARM_MAX_RTS_THRESHOLD))
764				lp->wds_port[3].rtsThreshold = value_convert;
765			else
766				DBG_WARNING(DbgInfo, "%s invalid; will be ignored\n", PARM_NAME_RTS_THRESHOLD4);
767		} else if (strcmp(key, PARM_NAME_RTS_THRESHOLD5) == 0) {
768			DBG_TRACE(DbgInfo, "%s, value: %s\n", PARM_NAME_RTS_THRESHOLD5, value);
769
770			value_convert = simple_strtoul(value, NULL, 0);
771			if ((value_convert >= PARM_MIN_RTS_THRESHOLD) && (value_convert <= PARM_MAX_RTS_THRESHOLD))
772				lp->wds_port[4].rtsThreshold = value_convert;
773			else
774				DBG_WARNING(DbgInfo, "%s invalid; will be ignored\n", PARM_NAME_RTS_THRESHOLD5);
775		} else if (strcmp(key, PARM_NAME_RTS_THRESHOLD6) == 0) {
776			DBG_TRACE(DbgInfo, "%s, value: %s\n", PARM_NAME_RTS_THRESHOLD6, value);
777
778			value_convert = simple_strtoul(value, NULL, 0);
779			if ((value_convert >= PARM_MIN_RTS_THRESHOLD) && (value_convert <= PARM_MAX_RTS_THRESHOLD))
780				lp->wds_port[5].rtsThreshold = value_convert;
781			else
782				DBG_WARNING(DbgInfo, "%s invalid; will be ignored\n", PARM_NAME_RTS_THRESHOLD6);
783		} else if (strcmp(key, PARM_NAME_TX_RATE1) == 0) {
784			DBG_TRACE(DbgInfo, "%s, value: %s\n", PARM_NAME_TX_RATE1, value);
785
786			value_convert = simple_strtoul(value, NULL, 0);
787			if ((value_convert >= PARM_MIN_TX_RATE) && (value_convert <= PARM_MAX_TX_RATE))
788				lp->wds_port[0].txRateCntl = value_convert;
789			else
790				DBG_WARNING(DbgInfo, "%s invalid; will be ignored\n", PARM_NAME_TX_RATE1);
791		} else if (strcmp(key, PARM_NAME_TX_RATE2) == 0) {
792			DBG_TRACE(DbgInfo, "%s, value: %s\n", PARM_NAME_TX_RATE2, value);
793
794			value_convert = simple_strtoul(value, NULL, 0);
795			if ((value_convert >= PARM_MIN_TX_RATE) && (value_convert <= PARM_MAX_TX_RATE))
796				lp->wds_port[1].txRateCntl = value_convert;
797			else
798				DBG_WARNING(DbgInfo, "%s invalid; will be ignored\n", PARM_NAME_TX_RATE2);
799		} else if (strcmp(key, PARM_NAME_TX_RATE3) == 0) {
800			DBG_TRACE(DbgInfo, "%s, value: %s\n", PARM_NAME_TX_RATE3, value);
801
802			value_convert = simple_strtoul(value, NULL, 0);
803			if ((value_convert >= PARM_MIN_TX_RATE) && (value_convert <= PARM_MAX_TX_RATE))
804				lp->wds_port[2].txRateCntl = value_convert;
805			else
806				DBG_WARNING(DbgInfo, "%s invalid; will be ignored\n", PARM_NAME_TX_RATE3);
807		} else if (strcmp(key, PARM_NAME_TX_RATE4) == 0) {
808			DBG_TRACE(DbgInfo, "%s, value: %s\n", PARM_NAME_TX_RATE4, value);
809
810			value_convert = simple_strtoul(value, NULL, 0);
811			if ((value_convert >= PARM_MIN_TX_RATE) && (value_convert <= PARM_MAX_TX_RATE))
812				lp->wds_port[3].txRateCntl = value_convert;
813			else
814				DBG_WARNING(DbgInfo, "%s invalid; will be ignored\n", PARM_NAME_TX_RATE4);
815		} else if (strcmp(key, PARM_NAME_TX_RATE5) == 0) {
816			DBG_TRACE(DbgInfo, "%s, value: %s\n", PARM_NAME_TX_RATE5, value);
817
818			value_convert = simple_strtoul(value, NULL, 0);
819			if ((value_convert >= PARM_MIN_TX_RATE) && (value_convert <= PARM_MAX_TX_RATE))
820				lp->wds_port[4].txRateCntl = value_convert;
821			else
822				DBG_WARNING(DbgInfo, "%s invalid; will be ignored\n", PARM_NAME_TX_RATE5);
823		} else if (strcmp(key, PARM_NAME_TX_RATE6) == 0) {
824			DBG_TRACE(DbgInfo, "%s, value: %s\n", PARM_NAME_TX_RATE6, value);
825
826			value_convert = simple_strtoul(value, NULL, 0);
827			if ((value_convert >= PARM_MIN_TX_RATE) && (value_convert <= PARM_MAX_TX_RATE))
828				lp->wds_port[5].txRateCntl = value_convert;
829			else
830				DBG_WARNING(DbgInfo, "%s invalid; will be ignored\n", PARM_NAME_TX_RATE6);
831		} else if (strcmp(key, PARM_NAME_WDS_ADDRESS1) == 0) {
832			DBG_TRACE(DbgInfo, "%s, value: %s\n", PARM_NAME_WDS_ADDRESS1, value);
833
834			if (parse_mac_address(value, mac_value) == ETH_ALEN)
835				memcpy(lp->wds_port[0].wdsAddress, mac_value, ETH_ALEN);
836			else
837				DBG_WARNING(DbgInfo, "%s invalid; will be ignored\n", PARM_NAME_WDS_ADDRESS1);
838		} else if (strcmp(key, PARM_NAME_WDS_ADDRESS2) == 0) {
839			DBG_TRACE(DbgInfo, "%s, value: %s\n", PARM_NAME_WDS_ADDRESS2, value);
840
841			if (parse_mac_address(value, mac_value) == ETH_ALEN)
842				memcpy(lp->wds_port[1].wdsAddress, mac_value, ETH_ALEN);
843			else
844				DBG_WARNING(DbgInfo, "%s invalid; will be ignored\n", PARM_NAME_WDS_ADDRESS2);
845		} else if (strcmp(key, PARM_NAME_WDS_ADDRESS3) == 0) {
846			DBG_TRACE(DbgInfo, "%s, value: %s\n", PARM_NAME_WDS_ADDRESS3, value);
847
848			if (parse_mac_address(value, mac_value) == ETH_ALEN)
849				memcpy(lp->wds_port[2].wdsAddress, mac_value, ETH_ALEN);
850			else
851				DBG_WARNING(DbgInfo, "%s invalid; will be ignored\n", PARM_NAME_WDS_ADDRESS3);
852		} else if (strcmp(key, PARM_NAME_WDS_ADDRESS4) == 0) {
853			DBG_TRACE(DbgInfo, "%s, value: %s\n", PARM_NAME_WDS_ADDRESS4, value);
854
855			if (parse_mac_address(value, mac_value) == ETH_ALEN)
856				memcpy(lp->wds_port[3].wdsAddress, mac_value, ETH_ALEN);
857			else
858				DBG_WARNING(DbgInfo, "%s invalid; will be ignored\n", PARM_NAME_WDS_ADDRESS4);
859		} else if (strcmp(key, PARM_NAME_WDS_ADDRESS5) == 0) {
860			DBG_TRACE(DbgInfo, "%s, value: %s\n", PARM_NAME_WDS_ADDRESS5, value);
861
862			if (parse_mac_address(value, mac_value) == ETH_ALEN)
863				memcpy(lp->wds_port[4].wdsAddress, mac_value, ETH_ALEN);
864			else
865				DBG_WARNING(DbgInfo, "%s invalid; will be ignored\n", PARM_NAME_WDS_ADDRESS5);
866		} else if (strcmp(key, PARM_NAME_WDS_ADDRESS6) == 0) {
867			DBG_TRACE(DbgInfo, "%s, value: %s\n", PARM_NAME_WDS_ADDRESS6, value);
868
869			if (parse_mac_address(value, mac_value) == ETH_ALEN)
870				memcpy(lp->wds_port[5].wdsAddress, mac_value, ETH_ALEN);
871			else
872				DBG_WARNING(DbgInfo, "%s invalid; will be ignored\n", PARM_NAME_WDS_ADDRESS6);
873		}
874#endif  /* USE_WDS */
875	}
876#endif  /* (HCF_TYPE) & HCF_TYPE_AP */
877
878	return;
879} /* translate_option */
880/*============================================================================*/
881
882/*******************************************************************************
883 *	parse_mac_address()
884 *******************************************************************************
885 *
886 *  DESCRIPTION:
887 *
888 *      This function will parse a mac address string and convert it to a byte
889 *   array.
890 *
891 *  PARAMETERS:
892 *
893 *      value       - the MAC address, represented as a string
894 *      byte_array  - the MAC address, represented as a byte array of length
895 *                    ETH_ALEN
896 *
897 *  RETURNS:
898 *
899 *      The number of bytes in the final MAC address, should equal to ETH_ALEN.
900 *
901 ******************************************************************************/
902int parse_mac_address(char *value, u_char *byte_array)
903{
904	int     value_offset = 0;
905	int     array_offset = 0;
906	int     field_offset = 0;
907	char    byte_field[3];
908	/*------------------------------------------------------------------------*/
909
910	memset(byte_field, '\0', 3);
911
912	while (value[value_offset] != '\0') {
913		/* Skip over the colon chars seperating the bytes, if they exist */
914		if (value[value_offset] == ':') {
915			value_offset++;
916			continue;
917		}
918
919		byte_field[field_offset] = value[value_offset];
920		field_offset++;
921		value_offset++;
922
923		/* Once the byte_field is filled, convert it and store it */
924		if (field_offset == 2) {
925			byte_field[field_offset] = '\0';
926			byte_array[array_offset] = simple_strtoul(byte_field, NULL, 16);
927			field_offset = 0;
928			array_offset++;
929		}
930	}
931
932	/* Use the array_offset as a check; 6 bytes should be written to the
933	   byte_array */
934	return array_offset;
935} /* parse_mac_address */
936/*============================================================================*/
937
938/*******************************************************************************
939 *	ParseConfigLine()
940 *******************************************************************************
941 *
942 *  DESCRIPTION:
943 *
944 *      Parses a line from the configuration file into an L-val and an R-val,
945 *  representing a key/value pair.
946 *
947 *  PARAMETERS:
948 *
949 *      pszLine     - the line from the config file to parse
950 *      ppszLVal    - the resulting L-val (Key)
951 *      ppszRVal    - the resulting R-val (Value)
952 *
953 *  RETURNS:
954 *
955 *      N/A
956 *
957 ******************************************************************************/
958void ParseConfigLine(char *pszLine, char **ppszLVal, char **ppszRVal)
959{
960	int i;
961	int size;
962	/*------------------------------------------------------------------------*/
963
964	DBG_FUNC("ParseConfigLine");
965	DBG_ENTER(DbgInfo);
966
967	/* get a snapshot of our string size */
968	size      = strlen(pszLine);
969	*ppszLVal = NULL;
970	*ppszRVal = NULL;
971
972	if (pszLine[0] != '#' &&							/* skip the line if it is a comment */
973		 pszLine[0] != '\n' &&							/* if it's an empty UNIX line, do nothing */
974		 !(pszLine[0] == '\r' && pszLine[1] == '\n')	/* if it's an empty MS-DOS line, do nothing */
975	   ) {
976		/* advance past any whitespace, and assign the L-value */
977		for (i = 0; i < size; i++) {
978			if (pszLine[i] != ' ') {
979				*ppszLVal = &pszLine[i];
980				break;
981			}
982		}
983		/* advance to the end of the l-value*/
984		for (i++; i < size; i++) {
985			if (pszLine[i] == ' ' || pszLine[i] == '=') {
986				pszLine[i] = '\0';
987				break;
988			}
989		}
990		/* make any whitespace and the equal sign a NULL character, and
991		   advance to the R-Value */
992		for (i++; i < size; i++) {
993			if (pszLine[i] == ' ' || pszLine[i] == '=') {
994				pszLine[i] = '\0';
995				continue;
996			}
997			*ppszRVal = &pszLine[i];
998			break;
999		}
1000		/* make the line ending character(s) a NULL */
1001		for (i++; i < size; i++) {
1002			if (pszLine[i] == '\n')
1003				pszLine[i] = '\0';
1004			if ((pszLine[i] == '\r') && (pszLine[i+1] == '\n'))
1005				pszLine[i] = '\0';
1006		}
1007	}
1008	DBG_LEAVE(DbgInfo);
1009} /* ParseConfigLine */
1010/*============================================================================*/
1011
1012#endif  /* USE_PROFILE */
1013