xref: /openbmc/ipmitool/lib/ipmi_lanp.c (revision 6ca88cb6)
1 /*
2  * Copyright (c) 2003 Sun Microsystems, Inc.  All Rights Reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  *
8  * Redistribution of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  *
11  * Redistribution in binary form must reproduce the above copyright
12  * notice, this list of conditions and the following disclaimer in the
13  * documentation and/or other materials provided with the distribution.
14  *
15  * Neither the name of Sun Microsystems, Inc. or the names of
16  * contributors may be used to endorse or promote products derived
17  * from this software without specific prior written permission.
18  *
19  * This software is provided "AS IS," without a warranty of any kind.
20  * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
21  * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
22  * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
23  * SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE
24  * FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
25  * OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES.  IN NO EVENT WILL
26  * SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA,
27  * OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
28  * PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
29  * LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
30  * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
31  */
32 
33 #include <stdlib.h>
34 #include <stdio.h>
35 #include <string.h>
36 #include <strings.h>
37 #include <sys/types.h>
38 #include <sys/socket.h>
39 #include <netinet/in.h>
40 #include <arpa/inet.h>
41 #include <errno.h>
42 #include <unistd.h>
43 #include <signal.h>
44 #include <setjmp.h>
45 #include <netdb.h>
46 #include <limits.h>
47 
48 #include <ipmitool/ipmi.h>
49 #include <ipmitool/log.h>
50 #include <ipmitool/ipmi_intf.h>
51 #include <ipmitool/helper.h>
52 #include <ipmitool/ipmi_constants.h>
53 #include <ipmitool/ipmi_strings.h>
54 #include <ipmitool/ipmi_lanp.h>
55 #include <ipmitool/ipmi_channel.h>
56 
57 extern int verbose;
58 
59 /* is_lan_channel - Check if channel is LAN medium
60  *
61  * return 1 if channel is LAN
62  * return 0 if channel is not LAN
63  *
64  * @intf:    ipmi interface handle
65  * @chan:    channel number to check
66  */
67 static int
68 is_lan_channel(struct ipmi_intf * intf, uint8_t chan)
69 {
70 	uint8_t medium;
71 
72 	if (chan < 1 || chan > IPMI_CHANNEL_NUMBER_MAX)
73 		return 0;
74 
75 	medium = ipmi_get_channel_medium(intf, chan);
76 
77 	if (medium == IPMI_CHANNEL_MEDIUM_LAN ||
78 	    medium == IPMI_CHANNEL_MEDIUM_LAN_OTHER)
79 		return 1;
80 
81 	return 0;
82 }
83 
84 /* find_lan_channel - Find first channel that is LAN
85  *
86  * return channel number if successful
87  * return 0 if no lan channel found, which is not a valid LAN channel
88  *
89  * @intf:    ipmi interface handle
90  * @start:   channel number to start searching from
91  */
92 static uint8_t
93 find_lan_channel(struct ipmi_intf * intf, uint8_t start)
94 {
95 	uint8_t chan = 0;
96 
97 	for (chan = start; chan < IPMI_CHANNEL_NUMBER_MAX; chan++) {
98 		if (is_lan_channel(intf, chan)) {
99 			return chan;
100 		}
101 	}
102 	return 0;
103 }
104 
105 /* get_lan_param_select - Query BMC for LAN parameter data
106  *
107  * return pointer to lan_param if successful
108  * if parameter not supported then
109  *   return pointer to lan_param with
110  *   lan_param->data == NULL and lan_param->data_len == 0
111  * return NULL on error
112  *
113  * @intf:    ipmi interface handle
114  * @chan:    ipmi channel
115  * @param:   lan parameter id
116  * @select:  lan parameter set selector
117  */
118 static struct lan_param *
119 get_lan_param_select(struct ipmi_intf * intf, uint8_t chan, int param, int select)
120 {
121 	struct lan_param * p = NULL;
122 	struct ipmi_rs * rsp;
123 	struct ipmi_rq req;
124 	int i = 0;
125 	uint8_t msg_data[4];
126 
127 	for (i = 0; ipmi_lan_params[i].cmd != (-1); i++) {
128 		if (ipmi_lan_params[i].cmd == param) {
129 			p = &ipmi_lan_params[i];
130 			break;
131 		}
132 	}
133 
134 	if (p == NULL) {
135 		lprintf(LOG_INFO, "Get LAN Parameter failed: Unknown parameter.");
136 		return NULL;
137 	}
138 
139 	msg_data[0] = chan;
140 	msg_data[1] = p->cmd;
141 	msg_data[2] = select;
142 	msg_data[3] = 0;
143 
144 	memset(&req, 0, sizeof(req));
145 	req.msg.netfn    = IPMI_NETFN_TRANSPORT;
146 	req.msg.cmd      = IPMI_LAN_GET_CONFIG;
147 	req.msg.data     = msg_data;
148 	req.msg.data_len = 4;
149 
150 	rsp = intf->sendrecv(intf, &req);
151 	if (rsp == NULL) {
152 		lprintf(LOG_INFO, "Get LAN Parameter '%s' command failed", p->desc);
153 		return NULL;
154 	}
155 
156 	switch (rsp->ccode)
157 	{
158 	case 0x00: /* successful */
159 		break;
160 
161 	case 0x80: /* parameter not supported */
162 	case 0xc9: /* parameter out of range */
163 	case 0xcc: /* invalid data field in request */
164 
165 		/* these completion codes usually mean parameter not supported */
166 		lprintf(LOG_INFO, "Get LAN Parameter '%s' command failed: %s",
167 			p->desc, val2str(rsp->ccode, completion_code_vals));
168 		p->data = NULL;
169 		p->data_len = 0;
170 		return p;
171 
172 	default:
173 
174 		/* other completion codes are treated as error */
175 		lprintf(LOG_INFO, "Get LAN Parameter '%s' command failed: %s",
176 			p->desc, val2str(rsp->ccode, completion_code_vals));
177 		return NULL;
178 	}
179 
180 	p->data = rsp->data + 1;
181 	p->data_len = rsp->data_len - 1;
182 
183 	return p;
184 }
185 
186 /* get_lan_param - Query BMC for LAN parameter data
187  *
188  * return pointer to lan_param if successful
189  * if parameter not supported then
190  *   return pointer to lan_param with
191  *   lan_param->data == NULL and lan_param->data_len == 0
192  * return NULL on error
193  *
194  * @intf:    ipmi interface handle
195  * @chan:    ipmi channel
196  * @param:   lan parameter id
197  */
198 static struct lan_param *
199 get_lan_param(struct ipmi_intf * intf, uint8_t chan, int param)
200 {
201 	return get_lan_param_select(intf, chan, param, 0);
202 }
203 
204 /* set_lan_param_wait - Wait for Set LAN Parameter command to complete
205  *
206  * On some systems this can take unusually long so we wait for the write
207  * to take effect and verify that the data was written successfully
208  * before continuing or retrying.
209  *
210  * returns 0 on success
211  * returns -1 on error
212  *
213  * @intf:    ipmi interface handle
214  * @chan:    ipmi channel
215  * @param:   lan parameter id
216  * @data:    lan parameter data
217  * @len:     length of lan parameter data
218  */
219 static int
220 set_lan_param_wait(struct ipmi_intf * intf, uint8_t chan,
221 		   int param, uint8_t * data, int len)
222 {
223 	struct lan_param * p;
224 	int retry = 10;		/* 10 retries */
225 
226 	lprintf(LOG_DEBUG, "Waiting for Set LAN Parameter to complete...");
227 	if (verbose > 1)
228 		printbuf(data, len, "SET DATA");
229 
230 	for (;;) {
231 		p = get_lan_param(intf, chan, param);
232 		if (p == NULL) {
233 			sleep(IPMI_LANP_TIMEOUT);
234 			if (retry-- == 0)
235 				return -1;
236 			continue;
237 		}
238 		if (verbose > 1)
239 			printbuf(p->data, p->data_len, "READ DATA");
240 		if (p->data_len != len) {
241 			sleep(IPMI_LANP_TIMEOUT);
242 			if (retry-- == 0) {
243 				lprintf(LOG_WARNING, "Mismatched data lengths: %d != %d",
244 				       p->data_len, len);
245 				return -1;
246 			}
247 			continue;
248 		}
249 		if (memcmp(data, p->data, len) != 0) {
250 			sleep(IPMI_LANP_TIMEOUT);
251 			if (retry-- == 0) {
252 				lprintf(LOG_WARNING, "LAN Parameter Data does not match!  "
253 				       "Write may have failed.");
254 				return -1;
255 			}
256 			continue;
257 		}
258 		break;
259 	}
260 	return 0;
261 }
262 
263 /* __set_lan_param - Write LAN Parameter data to BMC
264  *
265  * This function does the actual work of writing the LAN parameter
266  * to the BMC and calls set_lan_param_wait() if requested.
267  *
268  * returns 0 on success
269  * returns -1 on error
270  *
271  * @intf:    ipmi interface handle
272  * @chan:    ipmi channel
273  * @param:   lan parameter id
274  * @data:    lan parameter data
275  * @len:     length of lan parameter data
276  * @wait:    whether to wait for write completion
277  */
278 static int
279 __set_lan_param(struct ipmi_intf * intf, uint8_t chan,
280 		int param, uint8_t * data, int len, int wait)
281 {
282 	struct ipmi_rs * rsp;
283 	struct ipmi_rq req;
284 	uint8_t msg_data[32];
285 
286 	if (param < 0)
287 		return -1;
288 
289 	msg_data[0] = chan;
290 	msg_data[1] = param;
291 
292 	memcpy(&msg_data[2], data, len);
293 	memset(&req, 0, sizeof(req));
294 	req.msg.netfn = IPMI_NETFN_TRANSPORT;
295 	req.msg.cmd = IPMI_LAN_SET_CONFIG;
296 	req.msg.data = msg_data;
297 	req.msg.data_len = len+2;
298 
299 	rsp = intf->sendrecv(intf, &req);
300 	if (rsp == NULL) {
301 		lprintf(LOG_ERR, "Set LAN Parameter failed");
302 		return -1;
303 	}
304 	if ((rsp->ccode > 0) && (wait != 0)) {
305 		lprintf(LOG_DEBUG, "Warning: Set LAN Parameter failed: %s",
306 			val2str(rsp->ccode, completion_code_vals));
307 		if (rsp->ccode == 0xcc) {
308 			/* retry hack for invalid data field ccode */
309 			int retry = 10;		/* 10 retries */
310 			lprintf(LOG_DEBUG, "Retrying...");
311 			for (;;) {
312 				if (retry-- == 0)
313 					break;
314 				sleep(IPMI_LANP_TIMEOUT);
315 				rsp = intf->sendrecv(intf, &req);
316 				if (rsp == NULL)
317 					continue;
318 				if (rsp->ccode > 0)
319 					continue;
320 				return set_lan_param_wait(intf, chan, param, data, len);
321 			}
322 		}
323 		else if (rsp->ccode != 0xff) {
324 			/* let 0xff ccode continue */
325 			return -1;
326 		}
327 	}
328 
329 	if (wait == 0)
330 		return 0;
331 	return set_lan_param_wait(intf, chan, param, data, len);
332 }
333 
334 /* ipmi_lanp_lock_state - Retrieve set-in-progress status
335  *
336  * returns one of:
337  *  IPMI_LANP_WRITE_UNLOCK
338  *  IPMI_LANP_WRITE_LOCK
339  *  IPMI_LANP_WRITE_COMMIT
340  *  -1 on error/if not supported
341  *
342  * @intf:    ipmi interface handle
343  * @chan:    ipmi channel
344  */
345 static int
346 ipmi_lanp_lock_state(struct ipmi_intf * intf, uint8_t chan)
347 {
348 	struct lan_param * p;
349 	p = get_lan_param(intf, chan, IPMI_LANP_SET_IN_PROGRESS);
350 	if (p == NULL)
351 		return -1;
352 	if (p->data == NULL)
353 		return -1;
354 	return (p->data[0] & 3);
355 }
356 
357 /* ipmi_lanp_lock - Lock set-in-progress bits for our use
358  *
359  * Write to the Set-In-Progress LAN parameter to indicate
360  * to other management software that we are modifying parameters.
361  *
362  * No meaningful return value because this is an optional
363  * requirement in IPMI spec and not found on many BMCs.
364  *
365  * @intf:    ipmi interface handle
366  * @chan:    ipmi channel
367  */
368 static void
369 ipmi_lanp_lock(struct ipmi_intf * intf, uint8_t chan)
370 {
371 	uint8_t val = IPMI_LANP_WRITE_LOCK;
372 	int retry = 3;
373 
374 	for (;;) {
375 		int state = ipmi_lanp_lock_state(intf, chan);
376 		if (state == -1)
377 			break;
378 		if (state == val)
379 			break;
380 		if (retry-- == 0)
381 			break;
382 		__set_lan_param(intf, chan, IPMI_LANP_SET_IN_PROGRESS,
383 				&val, 1, 0);
384 	}
385 }
386 
387 /* ipmi_lanp_unlock - Unlock set-in-progress bits
388  *
389  * Write to the Set-In-Progress LAN parameter, first with
390  * a "commit" instruction and then unlocking it.
391  *
392  * No meaningful return value because this is an optional
393  * requirement in IPMI spec and not found on many BMCs.
394  *
395  * @intf:    ipmi interface handle
396  * @chan:    ipmi channel
397  */
398 static void
399 ipmi_lanp_unlock(struct ipmi_intf * intf, uint8_t chan)
400 {
401 	uint8_t val = IPMI_LANP_WRITE_COMMIT;
402 	int rc;
403 
404 	rc = __set_lan_param(intf, chan, IPMI_LANP_SET_IN_PROGRESS, &val, 1, 0);
405 	if (rc < 0) {
406 		lprintf(LOG_DEBUG, "LAN Parameter Commit not supported");
407 	}
408 
409 	val = IPMI_LANP_WRITE_UNLOCK;
410 	__set_lan_param(intf, chan, IPMI_LANP_SET_IN_PROGRESS, &val, 1, 0);
411 }
412 
413 /* set_lan_param - Wrap LAN parameter write with set-in-progress lock
414  *
415  * Returns value from __set_lan_param()
416  *
417  * @intf:    ipmi interface handle
418  * @chan:    ipmi channel
419  * @param:   lan parameter id
420  * @data:    lan parameter data
421  * @len:     length of lan parameter data
422  */
423 static int
424 set_lan_param(struct ipmi_intf * intf, uint8_t chan,
425 	      int param, uint8_t * data, int len)
426 {
427 	int rc;
428 	ipmi_lanp_lock(intf, chan);
429 	rc = __set_lan_param(intf, chan, param, data, len, 1);
430 	ipmi_lanp_unlock(intf, chan);
431 	return rc;
432 }
433 
434 /* set_lan_param_nowait - Wrap LAN parameter write without set-in-progress lock
435  *
436  * Returns value from __set_lan_param()
437  *
438  * @intf:    ipmi interface handle
439  * @chan:    ipmi channel
440  * @param:   lan parameter id
441  * @data:    lan parameter data
442  * @len:     length of lan parameter data
443  */
444 static int
445 set_lan_param_nowait(struct ipmi_intf * intf, uint8_t chan,
446 		     int param, uint8_t * data, int len)
447 {
448 	int rc;
449 	ipmi_lanp_lock(intf, chan);
450 	rc = __set_lan_param(intf, chan, param, data, len, 0);
451 	ipmi_lanp_unlock(intf, chan);
452 	return rc;
453 }
454 
455 static int
456 lan_set_arp_interval(struct ipmi_intf * intf, uint8_t chan, uint8_t ival)
457 {
458 	struct lan_param *lp;
459 	uint8_t interval = 0;
460 	int rc = 0;
461 
462 	lp = get_lan_param(intf, chan, IPMI_LANP_GRAT_ARP);
463 	if (lp == NULL)
464 		return -1;
465 	if (lp->data == NULL)
466 		return -1;
467 
468 	if (ival != 0) {
469 		if (((UINT8_MAX - 1) / 2) < ival) {
470 			lprintf(LOG_ERR, "Given ARP interval '%u' is too big.", ival);
471 			return (-1);
472 		}
473 		interval = (ival * 2) - 1;
474 		rc = set_lan_param(intf, chan, IPMI_LANP_GRAT_ARP, &interval, 1);
475 	} else {
476 		interval = lp->data[0];
477 	}
478 
479 	printf("BMC-generated Gratuitous ARP interval:  %.1f seconds\n",
480 	       (float)((interval + 1) / 2));
481 
482 	return rc;
483 }
484 
485 static int
486 lan_set_arp_generate(struct ipmi_intf * intf,
487 		     uint8_t chan, uint8_t ctl)
488 {
489 	struct lan_param *lp;
490 	uint8_t data;
491 
492 	lp = get_lan_param(intf, chan, IPMI_LANP_BMC_ARP);
493 	if (lp == NULL)
494 		return -1;
495 	if (lp->data == NULL)
496 		return -1;
497 	data = lp->data[0];
498 
499 	/* set arp generate bitflag */
500 	if (ctl == 0)
501 		data &= ~0x1;
502 	else
503 		data |= 0x1;
504 
505 	printf("%sabling BMC-generated Gratuitous ARPs\n", ctl ? "En" : "Dis");
506 	return set_lan_param(intf, chan, IPMI_LANP_BMC_ARP, &data, 1);
507 }
508 
509 static int
510 lan_set_arp_respond(struct ipmi_intf * intf,
511 		    uint8_t chan, uint8_t ctl)
512 {
513 	struct lan_param *lp;
514 	uint8_t data;
515 
516 	lp = get_lan_param(intf, chan, IPMI_LANP_BMC_ARP);
517 	if (lp == NULL)
518 		return -1;
519 	if (lp->data == NULL)
520 		return -1;
521 	data = lp->data[0];
522 
523 	/* set arp response bitflag */
524 	if (ctl == 0)
525 		data &= ~0x2;
526 	else
527 		data |= 0x2;
528 
529 	printf("%sabling BMC-generated ARP responses\n", ctl ? "En" : "Dis");
530 	return set_lan_param(intf, chan, IPMI_LANP_BMC_ARP, &data, 1);
531 }
532 
533 
534 static char priv_level_to_char(unsigned char priv_level)
535 {
536 	char ret = 'X';
537 
538 	switch (priv_level)
539 	{
540 	case IPMI_SESSION_PRIV_CALLBACK:
541 		ret = 'c';
542 		break;
543 	case IPMI_SESSION_PRIV_USER:
544 		ret = 'u';
545 		break;
546 	case IPMI_SESSION_PRIV_OPERATOR:
547 		ret = 'o';
548 		break;
549 	case IPMI_SESSION_PRIV_ADMIN:
550 		ret = 'a';
551 		break;
552 	case IPMI_SESSION_PRIV_OEM:
553 		ret = 'O';
554 		break;
555 	}
556 
557  	return ret;
558 }
559 
560 
561 static int
562 ipmi_lan_print(struct ipmi_intf * intf, uint8_t chan)
563 {
564 	struct lan_param * p;
565 	int rc = 0;
566 
567 	if (chan < 1 || chan > IPMI_CHANNEL_NUMBER_MAX) {
568 		lprintf(LOG_ERR, "Invalid Channel %d", chan);
569 		return -1;
570 	}
571 
572 	/* find type of channel and only accept 802.3 LAN */
573 	if (!is_lan_channel(intf, chan)) {
574 		lprintf(LOG_ERR, "Channel %d is not a LAN channel", chan);
575 		return -1;
576 	}
577 
578 	p = get_lan_param(intf, chan, IPMI_LANP_SET_IN_PROGRESS);
579 	if (p == NULL)
580 		return -1;
581 	if (p->data != NULL) {
582 		printf("%-24s: ", p->desc);
583 		p->data[0] &= 3;
584 		switch (p->data[0]) {
585 		case 0:
586 			printf("Set Complete\n");
587 			break;
588 		case 1:
589 			printf("Set In Progress\n");
590 			break;
591 		case 2:
592 			printf("Commit Write\n");
593 			break;
594 		case 3:
595 			printf("Reserved\n");
596 			break;
597 		default:
598 			printf("Unknown\n");
599 		}
600 	}
601 
602 	p = get_lan_param(intf, chan, IPMI_LANP_AUTH_TYPE);
603 	if (p == NULL)
604 		return -1;
605 	if (p->data != NULL) {
606 		printf("%-24s: %s%s%s%s%s\n", p->desc,
607 		       (p->data[0] & 1<<IPMI_SESSION_AUTHTYPE_NONE) ? "NONE " : "",
608 		       (p->data[0] & 1<<IPMI_SESSION_AUTHTYPE_MD2) ? "MD2 " : "",
609 		       (p->data[0] & 1<<IPMI_SESSION_AUTHTYPE_MD5) ? "MD5 " : "",
610 		       (p->data[0] & 1<<IPMI_SESSION_AUTHTYPE_PASSWORD) ? "PASSWORD " : "",
611 		       (p->data[0] & 1<<IPMI_SESSION_AUTHTYPE_OEM) ? "OEM " : "");
612 	}
613 
614 	p = get_lan_param(intf, chan, IPMI_LANP_AUTH_TYPE_ENABLE);
615 	if (p == NULL)
616 		return -1;
617 	if (p->data != NULL) {
618 		printf("%-24s: Callback : %s%s%s%s%s\n", p->desc,
619 		       (p->data[0] & 1<<IPMI_SESSION_AUTHTYPE_NONE) ? "NONE " : "",
620 		       (p->data[0] & 1<<IPMI_SESSION_AUTHTYPE_MD2) ? "MD2 " : "",
621 		       (p->data[0] & 1<<IPMI_SESSION_AUTHTYPE_MD5) ? "MD5 " : "",
622 		       (p->data[0] & 1<<IPMI_SESSION_AUTHTYPE_PASSWORD) ? "PASSWORD " : "",
623 		       (p->data[0] & 1<<IPMI_SESSION_AUTHTYPE_OEM) ? "OEM " : "");
624 		printf("%-24s: User     : %s%s%s%s%s\n", "",
625 		       (p->data[1] & 1<<IPMI_SESSION_AUTHTYPE_NONE) ? "NONE " : "",
626 		       (p->data[1] & 1<<IPMI_SESSION_AUTHTYPE_MD2) ? "MD2 " : "",
627 		       (p->data[1] & 1<<IPMI_SESSION_AUTHTYPE_MD5) ? "MD5 " : "",
628 		       (p->data[1] & 1<<IPMI_SESSION_AUTHTYPE_PASSWORD) ? "PASSWORD " : "",
629 		       (p->data[1] & 1<<IPMI_SESSION_AUTHTYPE_OEM) ? "OEM " : "");
630 		printf("%-24s: Operator : %s%s%s%s%s\n", "",
631 		       (p->data[2] & 1<<IPMI_SESSION_AUTHTYPE_NONE) ? "NONE " : "",
632 		       (p->data[2] & 1<<IPMI_SESSION_AUTHTYPE_MD2) ? "MD2 " : "",
633 		       (p->data[2] & 1<<IPMI_SESSION_AUTHTYPE_MD5) ? "MD5 " : "",
634 		       (p->data[2] & 1<<IPMI_SESSION_AUTHTYPE_PASSWORD) ? "PASSWORD " : "",
635 		       (p->data[2] & 1<<IPMI_SESSION_AUTHTYPE_OEM) ? "OEM " : "");
636 		printf("%-24s: Admin    : %s%s%s%s%s\n", "",
637 		       (p->data[3] & 1<<IPMI_SESSION_AUTHTYPE_NONE) ? "NONE " : "",
638 		       (p->data[3] & 1<<IPMI_SESSION_AUTHTYPE_MD2) ? "MD2 " : "",
639 		       (p->data[3] & 1<<IPMI_SESSION_AUTHTYPE_MD5) ? "MD5 " : "",
640 		       (p->data[3] & 1<<IPMI_SESSION_AUTHTYPE_PASSWORD) ? "PASSWORD " : "",
641 		       (p->data[3] & 1<<IPMI_SESSION_AUTHTYPE_OEM) ? "OEM " : "");
642 		printf("%-24s: OEM      : %s%s%s%s%s\n", "",
643 		       (p->data[4] & 1<<IPMI_SESSION_AUTHTYPE_NONE) ? "NONE " : "",
644 		       (p->data[4] & 1<<IPMI_SESSION_AUTHTYPE_MD2) ? "MD2 " : "",
645 		       (p->data[4] & 1<<IPMI_SESSION_AUTHTYPE_MD5) ? "MD5 " : "",
646 		       (p->data[4] & 1<<IPMI_SESSION_AUTHTYPE_PASSWORD) ? "PASSWORD " : "",
647 		       (p->data[4] & 1<<IPMI_SESSION_AUTHTYPE_OEM) ? "OEM " : "");
648 	}
649 
650 	p = get_lan_param(intf, chan, IPMI_LANP_IP_ADDR_SRC);
651 	if (p == NULL)
652 		return -1;
653 	if (p->data != NULL) {
654 		printf("%-24s: ", p->desc);
655 		p->data[0] &= 0xf;
656 		switch (p->data[0]) {
657 		case 0:
658 			printf("Unspecified\n");
659 			break;
660 		case 1:
661 			printf("Static Address\n");
662 			break;
663 		case 2:
664 			printf("DHCP Address\n");
665 			break;
666 		case 3:
667 			printf("BIOS Assigned Address\n");
668 			break;
669 		default:
670 			printf("Other\n");
671 			break;
672 		}
673 	}
674 
675 	p = get_lan_param(intf, chan, IPMI_LANP_IP_ADDR);
676 	if (p == NULL)
677 		return -1;
678 	if (p->data != NULL)
679 		printf("%-24s: %d.%d.%d.%d\n", p->desc,
680 		       p->data[0], p->data[1], p->data[2], p->data[3]);
681 
682 	p = get_lan_param(intf, chan, IPMI_LANP_SUBNET_MASK);
683 	if (p == NULL)
684 		return -1;
685 	if (p->data != NULL)
686 		printf("%-24s: %d.%d.%d.%d\n", p->desc,
687 		       p->data[0], p->data[1], p->data[2], p->data[3]);
688 
689 	p = get_lan_param(intf, chan, IPMI_LANP_MAC_ADDR);
690 	if (p == NULL)
691 		return -1;
692 	if (p->data != NULL)
693 		printf("%-24s: %02x:%02x:%02x:%02x:%02x:%02x\n", p->desc,
694 		       p->data[0], p->data[1], p->data[2], p->data[3], p->data[4], p->data[5]);
695 
696 	p = get_lan_param(intf, chan, IPMI_LANP_SNMP_STRING);
697 	if (p == NULL)
698 		return -1;
699 	if (p->data != NULL)
700 		printf("%-24s: %s\n", p->desc, p->data);
701 
702 	p = get_lan_param(intf, chan, IPMI_LANP_IP_HEADER);
703 	if (p == NULL)
704 		return -1;
705 	if (p->data != NULL)
706 		printf("%-24s: TTL=0x%02x Flags=0x%02x Precedence=0x%02x TOS=0x%02x\n",
707 		       p->desc, p->data[0], p->data[1] & 0xe0, p->data[2] & 0xe0, p->data[2] & 0x1e);
708 
709 	p = get_lan_param(intf, chan, IPMI_LANP_BMC_ARP);
710 	if (p == NULL)
711 		return -1;
712 	if (p->data != NULL)
713 		printf("%-24s: ARP Responses %sabled, Gratuitous ARP %sabled\n", p->desc,
714 		       (p->data[0] & 2) ? "En" : "Dis", (p->data[0] & 1) ? "En" : "Dis");
715 
716 	p = get_lan_param(intf, chan, IPMI_LANP_GRAT_ARP);
717 	if (p == NULL)
718 		return -1;
719 	if (p->data != NULL)
720 		printf("%-24s: %.1f seconds\n", p->desc, (float)((p->data[0] + 1) / 2));
721 
722 	p = get_lan_param(intf, chan, IPMI_LANP_DEF_GATEWAY_IP);
723 	if (p == NULL)
724 		return -1;
725 	if (p->data != NULL)
726 		printf("%-24s: %d.%d.%d.%d\n", p->desc,
727 		       p->data[0], p->data[1], p->data[2], p->data[3]);
728 
729 	p = get_lan_param(intf, chan, IPMI_LANP_DEF_GATEWAY_MAC);
730 	if (p == NULL)
731 		return -1;
732 	if (p->data != NULL)
733 		printf("%-24s: %02x:%02x:%02x:%02x:%02x:%02x\n", p->desc,
734 		       p->data[0], p->data[1], p->data[2], p->data[3], p->data[4], p->data[5]);
735 
736 	p = get_lan_param(intf, chan, IPMI_LANP_BAK_GATEWAY_IP);
737 	if (p == NULL)
738 		return -1;
739 	if (p->data != NULL)
740 		printf("%-24s: %d.%d.%d.%d\n", p->desc,
741 		       p->data[0], p->data[1], p->data[2], p->data[3]);
742 
743 	p = get_lan_param(intf, chan, IPMI_LANP_BAK_GATEWAY_MAC);
744 	if (p == NULL)
745 		return -1;
746 	if (p->data != NULL)
747 		printf("%-24s: %02x:%02x:%02x:%02x:%02x:%02x\n", p->desc,
748 		       p->data[0], p->data[1], p->data[2], p->data[3], p->data[4], p->data[5]);
749 
750 	p = get_lan_param(intf, chan, IPMI_LANP_VLAN_ID);
751 	if (p != NULL && p->data != NULL) {
752 		int id = ((p->data[1] & 0x0f) << 8) + p->data[0];
753 		if (p->data[1] & 0x80)
754 			printf("%-24s: %d\n", p->desc, id);
755 		else
756 			printf("%-24s: Disabled\n", p->desc);
757 	}
758 
759 	p = get_lan_param(intf, chan, IPMI_LANP_VLAN_PRIORITY);
760 	if (p != NULL && p->data != NULL)
761 		printf("%-24s: %d\n", p->desc, p->data[0] & 0x07);
762 
763 	/* Determine supported Cipher Suites -- Requires two calls */
764 	p = get_lan_param(intf, chan, IPMI_LANP_RMCP_CIPHER_SUPPORT);
765 	if (p == NULL)
766 		return -1;
767 	else if (p->data != NULL)
768 	{
769 		unsigned char cipher_suite_count = p->data[0];
770 		p = get_lan_param(intf, chan, IPMI_LANP_RMCP_CIPHERS);
771 		if (p == NULL)
772 			return -1;
773 
774 		printf("%-24s: ", p->desc);
775 
776 		/* Now we're dangerous.  There are only 15 fixed cipher
777 		   suite IDs, but the spec allows for 16 in the return data.*/
778 		if ((p->data != NULL) && (p->data_len <= 17))
779 		{
780 			unsigned int i;
781 			for (i = 0; (i < 16) && (i < cipher_suite_count); ++i)
782 			{
783 				printf("%s%d",
784 				       (i > 0? ",": ""),
785 				       p->data[i + 1]);
786 			}
787 			printf("\n");
788 		}
789 		else
790 		{
791 			printf("None\n");
792 		}
793 	}
794 
795 	/* RMCP+ Messaging Cipher Suite Privilege Levels */
796 	/* These are the privilege levels for the 15 fixed cipher suites */
797 	p = get_lan_param(intf, chan, IPMI_LANP_RMCP_PRIV_LEVELS);
798 	if (p == NULL)
799 		return -1;
800 	if ((p->data != NULL) && (p->data_len == 9))
801 	{
802 		printf("%-24s: %c%c%c%c%c%c%c%c%c%c%c%c%c%c%c\n", p->desc,
803 		       priv_level_to_char(p->data[1] & 0x0F),
804 		       priv_level_to_char(p->data[1] >> 4),
805 		       priv_level_to_char(p->data[2] & 0x0F),
806 		       priv_level_to_char(p->data[2] >> 4),
807 		       priv_level_to_char(p->data[3] & 0x0F),
808 		       priv_level_to_char(p->data[3] >> 4),
809 		       priv_level_to_char(p->data[4] & 0x0F),
810 		       priv_level_to_char(p->data[4] >> 4),
811 		       priv_level_to_char(p->data[5] & 0x0F),
812 		       priv_level_to_char(p->data[5] >> 4),
813 		       priv_level_to_char(p->data[6] & 0x0F),
814 		       priv_level_to_char(p->data[6] >> 4),
815 		       priv_level_to_char(p->data[7] & 0x0F),
816 		       priv_level_to_char(p->data[7] >> 4),
817 		       priv_level_to_char(p->data[8] & 0x0F));
818 
819 		/* Now print a legend */
820 		printf("%-24s: %s\n", "", "    X=Cipher Suite Unused");
821 		printf("%-24s: %s\n", "", "    c=CALLBACK");
822 		printf("%-24s: %s\n", "", "    u=USER");
823 		printf("%-24s: %s\n", "", "    o=OPERATOR");
824 		printf("%-24s: %s\n", "", "    a=ADMIN");
825 		printf("%-24s: %s\n", "", "    O=OEM");
826 	}
827 	else
828 		printf("%-24s: Not Available\n", p->desc);
829 
830 	return rc;
831 }
832 
833 /* Configure Authentication Types */
834 static int
835 ipmi_lan_set_auth(struct ipmi_intf * intf, uint8_t chan, char * level, char * types)
836 {
837 	uint8_t data[5];
838 	uint8_t authtype = 0;
839 	char * p;
840 	struct lan_param * lp;
841 
842 	if (level == NULL || types == NULL)
843 		return -1;
844 
845 	lp = get_lan_param(intf, chan, IPMI_LANP_AUTH_TYPE_ENABLE);
846 	if (lp == NULL)
847 		return -1;
848 	if (lp->data == NULL)
849 		return -1;
850 
851 	lprintf(LOG_DEBUG, "%-24s: callback=0x%02x user=0x%02x operator=0x%02x admin=0x%02x oem=0x%02x",
852 		lp->desc, lp->data[0], lp->data[1], lp->data[2], lp->data[3], lp->data[4]);
853 
854 	memset(data, 0, 5);
855 	memcpy(data, lp->data, 5);
856 
857 	p = types;
858 	while (p) {
859 		if (strncasecmp(p, "none", 4) == 0)
860 			authtype |= 1 << IPMI_SESSION_AUTHTYPE_NONE;
861 		else if (strncasecmp(p, "md2", 3) == 0)
862 			authtype |= 1 << IPMI_SESSION_AUTHTYPE_MD2;
863 		else if (strncasecmp(p, "md5", 3) == 0)
864 			authtype |= 1 << IPMI_SESSION_AUTHTYPE_MD5;
865 		else if ((strncasecmp(p, "password", 8) == 0) ||
866 			 (strncasecmp(p, "key", 3) == 0))
867 			authtype |= 1 << IPMI_SESSION_AUTHTYPE_KEY;
868 		else if (strncasecmp(p, "oem", 3) == 0)
869 			authtype |= 1 << IPMI_SESSION_AUTHTYPE_OEM;
870 		else
871 			lprintf(LOG_WARNING, "Invalid authentication type: %s", p);
872 		p = strchr(p, ',');
873 		if (p)
874 			p++;
875 	}
876 
877 	p = level;
878 	while (p) {
879 		if (strncasecmp(p, "callback", 8) == 0)
880 			data[0] = authtype;
881 		else if (strncasecmp(p, "user", 4) == 0)
882 			data[1] = authtype;
883 		else if (strncasecmp(p, "operator", 8) == 0)
884 			data[2] = authtype;
885 		else if (strncasecmp(p, "admin", 5) == 0)
886 			data[3] = authtype;
887 		else
888 			lprintf(LOG_WARNING, "Invalid authentication level: %s", p);
889 		p = strchr(p, ',');
890 		if (p)
891 			p++;
892 	}
893 
894 	if (verbose > 1)
895 		printbuf(data, 5, "authtype data");
896 
897 	return set_lan_param(intf, chan, IPMI_LANP_AUTH_TYPE_ENABLE, data, 5);
898 }
899 
900 static int
901 ipmi_lan_set_password(struct ipmi_intf * intf,
902 	uint8_t userid, uint8_t * password)
903 {
904 	struct ipmi_rs * rsp;
905 	struct ipmi_rq req;
906 	uint8_t data[18];
907 
908 	memset(&data, 0, sizeof(data));
909 	data[0] = userid & 0x3f;/* user ID */
910 	data[1] = 0x02;		/* set password */
911 
912 	if (password != NULL)
913 		memcpy(data+2, password, __min(strlen((const char *)password), 16));
914 
915 	memset(&req, 0, sizeof(req));
916 	req.msg.netfn = IPMI_NETFN_APP;
917 	req.msg.cmd = 0x47;
918 	req.msg.data = data;
919 	req.msg.data_len = 18;
920 
921 	rsp = intf->sendrecv(intf, &req);
922 	if (rsp == NULL) {
923 		lprintf(LOG_ERR, "Unable to Set LAN Password for user %d", userid);
924 		return -1;
925 	}
926 	if (rsp->ccode > 0) {
927 		lprintf(LOG_ERR, "Set LAN Password for user %d failed: %s",
928 			userid, val2str(rsp->ccode, completion_code_vals));
929 		return -1;
930 	}
931 
932 	/* adjust our session password
933 	 * or we will no longer be able to communicate with BMC
934 	 */
935 	ipmi_intf_session_set_password(intf, (char *)password);
936 	printf("Password %s for user %d\n",
937 	       (password == NULL) ? "cleared" : "set", userid);
938 
939 	return 0;
940 }
941 
942 static int
943 ipmi_set_alert_enable(struct ipmi_intf * intf, uint8_t channel, uint8_t enable)
944 {
945 	struct ipmi_rs * rsp;
946 	struct ipmi_rq req;
947 	uint8_t rqdata[3];
948 
949 	memset(&req, 0, sizeof(req));
950 
951 	/* update non-volatile access */
952 	rqdata[0] = channel;
953 	rqdata[1] = 0x40;
954 
955 	req.msg.netfn = IPMI_NETFN_APP;
956 	req.msg.cmd = 0x41;
957 	req.msg.data = rqdata;
958 	req.msg.data_len = 2;
959 
960 	rsp = intf->sendrecv(intf, &req);
961 	if (rsp == NULL) {
962 		lprintf(LOG_ERR, "Unable to Get Channel Access for channel %d", channel);
963 		return -1;
964 	}
965 	if (rsp->ccode > 0) {
966 		lprintf(LOG_ERR, "Get Channel Access for channel %d failed: %s",
967 			channel, val2str(rsp->ccode, completion_code_vals));
968 		return -1;
969 	}
970 
971 	/* SAVE TO NVRAM */
972 	memset(rqdata, 0, 3);
973 	rqdata[0] = channel & 0xf;
974 	rqdata[1] = rsp->data[0];
975 	if (enable != 0)
976 		rqdata[1] &= ~0x20;
977 	else
978 		rqdata[1] |= 0x20;
979 	rqdata[1] |= 0x40;
980 	rqdata[2] = 0;
981 
982 	req.msg.cmd = 0x40;
983 	req.msg.data_len = 3;
984 
985 	rsp = intf->sendrecv(intf, &req);
986 	if (rsp == NULL) {
987 		lprintf(LOG_ERR, "Unable to Set Channel Access for channel %d", channel);
988 		return -1;
989 	}
990 	if (rsp->ccode > 0) {
991 		lprintf(LOG_ERR, "Set Channel Access for channel %d failed: %s",
992 			channel, val2str(rsp->ccode, completion_code_vals));
993 		return -1;
994 	}
995 
996 	/* SAVE TO CURRENT */
997 	rqdata[1] &= 0xc0;
998 	rqdata[1] |= 0x80;
999 
1000 	rsp = intf->sendrecv(intf, &req);
1001 	if (rsp == NULL) {
1002 		lprintf(LOG_ERR, "Unable to Set Channel Access for channel %d", channel);
1003 		return -1;
1004 	}
1005 	if (rsp->ccode > 0) {
1006 		lprintf(LOG_ERR, "Set Channel Access for channel %d failed: %s",
1007 			channel, val2str(rsp->ccode, completion_code_vals));
1008 		return -1;
1009 	}
1010 
1011 	return 0;
1012 }
1013 
1014 static int
1015 ipmi_set_channel_access(struct ipmi_intf * intf, uint8_t channel, uint8_t enable)
1016 {
1017 	struct ipmi_rs * rsp;
1018 	struct ipmi_rq req;
1019 	uint8_t rqdata[3];
1020 	uint8_t byteEnable;
1021 
1022 	memset(&req, 0, sizeof(req));
1023 
1024 	/* RETREIVE VALUE IN NVRAM */
1025 	req.msg.netfn = IPMI_NETFN_APP;
1026 	req.msg.cmd = 0x41;  /* Get Channel Access Command */
1027 	req.msg.data = rqdata;
1028 	req.msg.data_len = 2;
1029 
1030 	memset(rqdata, 0, 2);
1031 	rqdata[0] = channel & 0xf;
1032 	rqdata[1] = 0x40; /* retreive NV */
1033 
1034 	rsp = intf->sendrecv(intf, &req);
1035 	if (rsp == NULL) {
1036 		lprintf(LOG_ERR, "Unable to Get Channel Access for channel %d", channel);
1037 		return -1;
1038 	} else if (rsp->ccode > 0) {
1039 		lprintf(LOG_ERR, "Set Channel Access for channel %d failed: %s",
1040 			channel, val2str(rsp->ccode, completion_code_vals));
1041 		return -1;
1042 	} else {
1043 		byteEnable = *(rsp->data + 0);
1044 	}
1045 
1046 	/* SAVE TO NVRAM */
1047 	memset(&req, 0, sizeof(req));
1048 
1049 	req.msg.netfn = IPMI_NETFN_APP;
1050 	req.msg.cmd = 0x40;   /* Set Channel Access Command */
1051 	req.msg.data = rqdata;
1052 	req.msg.data_len = 3;
1053 
1054 	memset(rqdata, 0, 3);
1055 	rqdata[0] = channel & 0xf;
1056 	rqdata[1] = 0x40 | (byteEnable & 0x38);  /* use previously set values */
1057 	if (enable != 0)
1058 		rqdata[1] |= 0x2; /* set always available if enable is set */
1059 	rqdata[2] = 0x44; 	/* set channel privilege limit to ADMIN */
1060 
1061 	rsp = intf->sendrecv(intf, &req);
1062 	if (rsp == NULL) {
1063 		lprintf(LOG_ERR, "Unable to Set Channel Access for channel %d", channel);
1064 		return -1;
1065 	} else if (rsp->ccode > 0) {
1066 		lprintf(LOG_ERR, "Set Channel Access for channel %d failed: %s",
1067 			channel, val2str(rsp->ccode, completion_code_vals));
1068 		return -1;
1069 	}
1070 
1071 	/* RETREIVE VALUE IN NVRAM */
1072 	req.msg.netfn = IPMI_NETFN_APP;
1073 	req.msg.cmd = 0x41;  /* Get Channel Access Command */
1074 	req.msg.data = rqdata;
1075 	req.msg.data_len = 2;
1076 
1077 	memset(rqdata, 0, 2);
1078 	rqdata[0] = channel & 0xf;
1079 	rqdata[1] = 0x80; /* retreive NV */
1080 
1081 	rsp = intf->sendrecv(intf, &req);
1082 	if (rsp == NULL) {
1083 		lprintf(LOG_ERR, "Unable to Get Channel Access for channel %d", channel);
1084 		return -1;
1085 	} else if (rsp->ccode > 0) {
1086 		lprintf(LOG_ERR, "Set Channel Access for channel %d failed: %s",
1087 			channel, val2str(rsp->ccode, completion_code_vals));
1088 		return -1;
1089 	} else {
1090 		byteEnable = *(rsp->data + 0);
1091 	}
1092 
1093 	/* SAVE TO CURRENT */
1094 	memset(&req, 0, sizeof(req));
1095 
1096 	req.msg.netfn = IPMI_NETFN_APP;
1097 	req.msg.cmd = 0x40;   /* Set Channel Access Command */
1098 	req.msg.data = rqdata;
1099 	req.msg.data_len = 3;
1100 
1101 	memset(rqdata, 0, 3);
1102 	rqdata[0] = channel & 0xf;
1103 	rqdata[1] = 0x80 | (byteEnable & 0x38);  /* use previously set values */
1104 	if (enable != 0)
1105 		rqdata[1] |= 0x2; /* set always available if enable is set */
1106 	rqdata[2] = 0x84; 	/* set channel privilege limit to ADMIN */
1107 
1108 	rsp = intf->sendrecv(intf, &req);
1109 	if (rsp == NULL) {
1110 		lprintf(LOG_ERR, "Unable to Set Channel Access for channel %d", channel);
1111 		return -1;
1112 	} else if (rsp->ccode > 0) {
1113 		lprintf(LOG_ERR, "Set Channel Access for channel %d failed: %s",
1114 			channel, val2str(rsp->ccode, completion_code_vals));
1115 		return -1;
1116 	}
1117 
1118 	/* can't send close session if access off so abort instead */
1119 	if (enable == 0)
1120 		intf->abort = 1;
1121 
1122 	return 0;
1123 }
1124 
1125 static int
1126 ipmi_set_user_access(struct ipmi_intf * intf, uint8_t channel, uint8_t userid)
1127 {
1128 	struct ipmi_rs * rsp;
1129 	struct ipmi_rq req;
1130 	uint8_t rqdata[4];
1131 
1132 	memset(rqdata, 0, 4);
1133 	rqdata[0] = 0x90 | (channel & 0xf);
1134 	rqdata[1] = userid & 0x3f;
1135 	rqdata[2] = 0x4;
1136 	rqdata[3] = 0;
1137 
1138 	memset(&req, 0, sizeof(req));
1139 	req.msg.netfn = IPMI_NETFN_APP;
1140 	req.msg.cmd = 0x43;
1141 	req.msg.data = rqdata;
1142 	req.msg.data_len = 4;
1143 
1144 	rsp = intf->sendrecv(intf, &req);
1145 	if (rsp == NULL) {
1146 		lprintf(LOG_ERR, "Unable to Set User Access for channel %d", channel);
1147 		return -1;
1148 	}
1149 	if (rsp->ccode > 0) {
1150 		lprintf(LOG_ERR, "Set User Access for channel %d failed: %s",
1151 			channel, val2str(rsp->ccode, completion_code_vals));
1152 		return -1;
1153 	}
1154 
1155 	return 0;
1156 }
1157 
1158 static int
1159 get_cmdline_macaddr(char * arg, uint8_t * buf)
1160 {
1161 	uint32_t m1, m2, m3, m4, m5, m6;
1162 	if (sscanf(arg, "%02x:%02x:%02x:%02x:%02x:%02x",
1163 		   &m1, &m2, &m3, &m4, &m5, &m6) != 6) {
1164 		lprintf(LOG_ERR, "Invalid MAC address: %s", arg);
1165 		return -1;
1166 	}
1167 	buf[0] = (uint8_t)m1;
1168 	buf[1] = (uint8_t)m2;
1169 	buf[2] = (uint8_t)m3;
1170 	buf[3] = (uint8_t)m4;
1171 	buf[4] = (uint8_t)m5;
1172 	buf[5] = (uint8_t)m6;
1173 	return 0;
1174 }
1175 
1176 
1177 static int
1178 get_cmdline_cipher_suite_priv_data(char * arg, uint8_t * buf)
1179 {
1180 	int i, ret = 0;
1181 
1182 	if (strlen(arg) != 15)
1183 	{
1184 		lprintf(LOG_ERR, "Invalid privilege specification length: %d",
1185 			strlen(arg));
1186 		return -1;
1187 	}
1188 
1189 	/*
1190 	 * The first byte is reserved (0).  The rest of the buffer is setup
1191 	 * so that each nibble holds the maximum privilege level available for
1192 	 * that cipher suite number.  The number of nibbles (15) matches the number
1193 	 * of fixed cipher suite IDs.  This command documentation mentions 16 IDs
1194 	 * but table 22-19 shows that there are only 15 (0-14).
1195 	 *
1196 	 * data 1 - reserved
1197 	 * data 2 - maximum priv level for first (LSN) and second (MSN) ciphers
1198 	 * data 3 - maximum priv level for third (LSN) and fourth (MSN) ciphers
1199 	 * data 9 - maximum priv level for 15th (LSN) cipher.
1200 	 */
1201 	memset(buf, 0, 9);
1202 	for (i = 0; i < 15; ++i)
1203 	{
1204 		unsigned char priv_level = IPMI_SESSION_PRIV_ADMIN;
1205 
1206 		switch (arg[i])
1207 		{
1208 		case 'X':
1209 			priv_level = IPMI_SESSION_PRIV_UNSPECIFIED; /* 0 */
1210 			break;
1211 		case 'c':
1212 			priv_level = IPMI_SESSION_PRIV_CALLBACK;    /* 1 */
1213 			break;
1214 		case 'u':
1215 			priv_level = IPMI_SESSION_PRIV_USER;        /* 2 */
1216 			break;
1217 		case 'o':
1218 			priv_level = IPMI_SESSION_PRIV_OPERATOR;    /* 3 */
1219 			break;
1220 		case 'a':
1221 			priv_level = IPMI_SESSION_PRIV_ADMIN;       /* 4 */
1222 			break;
1223 		case 'O':
1224 			priv_level = IPMI_SESSION_PRIV_OEM;         /* 5 */
1225 			break;
1226 		default:
1227 			lprintf(LOG_ERR, "Invalid privilege specification char: %c",
1228 				arg[i]);
1229 			ret = -1;
1230 			break;
1231 		}
1232 
1233 		if (ret != 0)
1234 			break;
1235 		else
1236 		{
1237 			if ((i + 1) % 2)
1238 			{
1239 				// Odd number cipher suites will be in the LSN
1240 				buf[1 + (i / 2)] += priv_level;
1241 			}
1242 			else
1243 			{
1244 				// Even number cipher suites will be in the MSN
1245 				buf[1 + (i / 2)] += (priv_level << 4);
1246 			}
1247 		}
1248 	}
1249 
1250 	return ret;
1251 }
1252 
1253 
1254 static int
1255 get_cmdline_ipaddr(char * arg, uint8_t * buf)
1256 {
1257 	uint32_t ip1, ip2, ip3, ip4;
1258 	if (sscanf(arg, "%d.%d.%d.%d", &ip1, &ip2, &ip3, &ip4) != 4) {
1259 		lprintf(LOG_ERR, "Invalid IP address: %s", arg);
1260 		return -1;
1261 	}
1262 	buf[0] = (uint8_t)ip1;
1263 	buf[1] = (uint8_t)ip2;
1264 	buf[2] = (uint8_t)ip3;
1265 	buf[3] = (uint8_t)ip4;
1266 	return 0;
1267 }
1268 
1269 static void ipmi_lan_set_usage(void)
1270 {
1271 	lprintf(LOG_NOTICE, "\nusage: lan set <channel> <command> <parameter>\n");
1272 	lprintf(LOG_NOTICE, "LAN set command/parameter options:");
1273 	lprintf(LOG_NOTICE, "  ipaddr <x.x.x.x>               Set channel IP address");
1274 	lprintf(LOG_NOTICE, "  netmask <x.x.x.x>              Set channel IP netmask");
1275 	lprintf(LOG_NOTICE, "  macaddr <x:x:x:x:x:x>          Set channel MAC address");
1276 	lprintf(LOG_NOTICE, "  defgw ipaddr <x.x.x.x>         Set default gateway IP address");
1277 	lprintf(LOG_NOTICE, "  defgw macaddr <x:x:x:x:x:x>    Set default gateway MAC address");
1278 	lprintf(LOG_NOTICE, "  bakgw ipaddr <x.x.x.x>         Set backup gateway IP address");
1279 	lprintf(LOG_NOTICE, "  bakgw macaddr <x:x:x:x:x:x>    Set backup gateway MAC address");
1280 	lprintf(LOG_NOTICE, "  password <password>            Set session password for this channel");
1281 	lprintf(LOG_NOTICE, "  snmp <community string>        Set SNMP public community string");
1282 	lprintf(LOG_NOTICE, "  user                           Enable default user for this channel");
1283 	lprintf(LOG_NOTICE, "  access <on|off>                Enable or disable access to this channel");
1284 	lprintf(LOG_NOTICE, "  alert <on|off>                 Enable or disable PEF alerting for this channel");
1285 	lprintf(LOG_NOTICE, "  arp respond <on|off>           Enable or disable BMC ARP responding");
1286 	lprintf(LOG_NOTICE, "  arp generate <on|off>          Enable or disable BMC gratuitous ARP generation");
1287 	lprintf(LOG_NOTICE, "  arp interval <seconds>         Set gratuitous ARP generation interval");
1288 	lprintf(LOG_NOTICE, "  vlan id <off|<id>>             Disable or enable VLAN and set ID (1-4094)");
1289 	lprintf(LOG_NOTICE, "  vlan priority <priority>       Set vlan priority (0-7)");
1290 	lprintf(LOG_NOTICE, "  auth <level> <type,..>         Set channel authentication types");
1291 	lprintf(LOG_NOTICE, "    level  = CALLBACK, USER, OPERATOR, ADMIN");
1292 	lprintf(LOG_NOTICE, "    type   = NONE, MD2, MD5, PASSWORD, OEM");
1293 	lprintf(LOG_NOTICE, "  ipsrc <source>                 Set IP Address source");
1294 	lprintf(LOG_NOTICE, "    none   = unspecified source");
1295 	lprintf(LOG_NOTICE, "    static = address manually configured to be static");
1296 	lprintf(LOG_NOTICE, "    dhcp   = address obtained by BMC running DHCP");
1297 	lprintf(LOG_NOTICE, "    bios   = address loaded by BIOS or system software");
1298 	lprintf(LOG_NOTICE, "  cipher_privs XXXXXXXXXXXXXXX   Set RMCP+ cipher suite privilege levels");
1299 	lprintf(LOG_NOTICE, "    X = Cipher Suite Unused");
1300 	lprintf(LOG_NOTICE, "    c = CALLBACK");
1301 	lprintf(LOG_NOTICE, "    u = USER");
1302 	lprintf(LOG_NOTICE, "    o = OPERATOR");
1303 	lprintf(LOG_NOTICE, "    a = ADMIN");
1304 	lprintf(LOG_NOTICE, "    O = OEM\n");
1305 }
1306 
1307 static void
1308 ipmi_lan_set_vlan_usage(void)
1309 {
1310 	lprintf(LOG_NOTICE,
1311 		"lan set <channel> vlan id <id>\n"
1312 		"lan set <channel> vlan id off\n"
1313 		"lan set <channel> vlan priority <priority>\n");
1314 }
1315 
1316 static int
1317 ipmi_lan_set_vlan_id(struct ipmi_intf * intf,  uint8_t chan, char *string)
1318 {
1319 	uint8_t data[2];
1320 	int rc;
1321 
1322 	if (string == NULL) {
1323 		data[0] = 0;
1324 		data[1] = 0;
1325 	}
1326 	else {
1327 		int id = 0;
1328 		if (str2int(string, &id) != 0) {
1329 			lprintf(LOG_ERR, "Given VLAN ID '%s' is invalid.", string);
1330 			return (-1);
1331 		}
1332 
1333 		if (id < 1 || id > 4094) {
1334 			lprintf(LOG_NOTICE, "vlan id must be between 1 and 4094.");
1335 			return -1;
1336 		}
1337 		else {
1338 			data[0] = (uint8_t)id;
1339 			data[1] = (uint8_t)(id >> 8) | 0x80;
1340 		}
1341 	}
1342 	rc = set_lan_param(intf, chan, IPMI_LANP_VLAN_ID, data, 2);
1343 	return rc;
1344 }
1345 
1346 static int
1347 ipmi_lan_set_vlan_priority(struct ipmi_intf * intf,  uint8_t chan, char *string)
1348 {
1349 	uint8_t data;
1350 	int rc;
1351 	int priority = 0;
1352 	if (str2int(string, &priority) != 0) {
1353 		lprintf(LOG_ERR, "Given VLAN priority '%s' is invalid.", string);
1354 		return (-1);
1355 	}
1356 
1357 	if (priority < 0 || priority > 7) {
1358 		lprintf(LOG_NOTICE, "vlan priority must be between 0 and 7.");
1359 		return -1;
1360 	}
1361 	data = (uint8_t)priority;
1362 	rc = set_lan_param(intf, chan, IPMI_LANP_VLAN_PRIORITY, &data, 1);
1363 	return rc;
1364 }
1365 
1366 static int
1367 ipmi_lan_set(struct ipmi_intf * intf, int argc, char ** argv)
1368 {
1369 	uint8_t data[32];
1370 	uint8_t chan;
1371 	int rc = 0;
1372 
1373 	if (argc < 2) {
1374 		ipmi_lan_set_usage();
1375 		return (-1);
1376 	}
1377 
1378 	if (strncmp(argv[0], "help", 4) == 0 ||
1379 	    strncmp(argv[1], "help", 4) == 0) {
1380 		ipmi_lan_set_usage();
1381 		return 0;
1382 	}
1383 
1384 	if (str2uchar(argv[0], &chan) != 0) {
1385 		lprintf(LOG_ERR, "Invalid channel: %s", argv[0]);
1386 		return (-1);
1387 	}
1388 
1389 	/* find type of channel and only accept 802.3 LAN */
1390 	if (!is_lan_channel(intf, chan)) {
1391 		lprintf(LOG_ERR, "Channel %d is not a LAN channel!", chan);
1392 		ipmi_lan_set_usage();
1393 		return -1;
1394 	}
1395 
1396 	memset(&data, 0, sizeof(data));
1397 
1398 	/* set user access */
1399 	if (strncmp(argv[1], "user", 4) == 0) {
1400 		rc = ipmi_set_user_access(intf, chan, 1);
1401 	}
1402 	/* set channel access mode */
1403 	else if (strncmp(argv[1], "access", 6) == 0) {
1404 		if (argc < 3) {
1405 			lprintf(LOG_NOTICE, "lan set access <on|off>");
1406 			return (-1);
1407 		}
1408 		else if (strncmp(argv[2], "help", 4) == 0) {
1409 			lprintf(LOG_NOTICE, "lan set access <on|off>");
1410 			return 0;
1411 		}
1412 		else if (strncmp(argv[2], "on", 2) == 0) {
1413 			rc = ipmi_set_channel_access(intf, chan, 1);
1414 		}
1415 		else if (strncmp(argv[2], "off", 3) == 0) {
1416 			rc = ipmi_set_channel_access(intf, chan, 0);
1417 		}
1418 		else {
1419 			lprintf(LOG_NOTICE, "lan set access <on|off>");
1420 			return (-1);
1421 		}
1422 	}
1423 	/* set ARP control */
1424 	else if (strncmp(argv[1], "arp", 3) == 0) {
1425 		if (argc < 3) {
1426 			lprintf(LOG_NOTICE,
1427 				"lan set <channel> arp respond <on|off>\n"
1428 				"lan set <channel> arp generate <on|off>\n"
1429 				"lan set <channel> arp interval <seconds>\n\n"
1430 				"example: lan set 7 arp gratuitous off\n");
1431 			return (-1);
1432 		}
1433 		else if (strncmp(argv[2], "help", 4) == 0) {
1434 			lprintf(LOG_NOTICE,
1435 				"lan set <channel> arp respond <on|off>\n"
1436 				"lan set <channel> arp generate <on|off>\n"
1437 				"lan set <channel> arp interval <seconds>\n\n"
1438 				"example: lan set 7 arp gratuitous off\n");
1439 			return 0;
1440 		}
1441 		else if (strncmp(argv[2], "interval", 8) == 0) {
1442 			uint8_t interval = 0;
1443 			if (str2uchar(argv[3], &interval) != 0) {
1444 				lprintf(LOG_ERR, "Given ARP interval '%s' is invalid.", argv[3]);
1445 				return (-1);
1446 			}
1447 			rc = lan_set_arp_interval(intf, chan, interval);
1448 		}
1449 		else if (strncmp(argv[2], "generate", 8) == 0) {
1450 			if (argc < 4) {
1451 				lprintf(LOG_NOTICE, "lan set <channel> arp generate <on|off>");
1452 				return (-1);
1453 			}
1454 			else if (strncmp(argv[3], "on", 2) == 0)
1455 				rc = lan_set_arp_generate(intf, chan, 1);
1456 			else if (strncmp(argv[3], "off", 3) == 0)
1457 				rc = lan_set_arp_generate(intf, chan, 0);
1458 			else {
1459 				lprintf(LOG_NOTICE, "lan set <channel> arp generate <on|off>");
1460 				return (-1);
1461 			}
1462 		}
1463 		else if (strncmp(argv[2], "respond", 7) == 0) {
1464 			if (argc < 4) {
1465 				lprintf(LOG_NOTICE, "lan set <channel> arp respond <on|off>");
1466 				return (-1);
1467 			}
1468 			else if (strncmp(argv[3], "on", 2) == 0)
1469 				rc = lan_set_arp_respond(intf, chan, 1);
1470 			else if (strncmp(argv[3], "off", 3) == 0)
1471 				rc = lan_set_arp_respond(intf, chan, 0);
1472 			else {
1473 				lprintf(LOG_NOTICE, "lan set <channel> arp respond <on|off>");
1474 				return (-1);
1475 			}
1476 		}
1477 		else {
1478 			lprintf(LOG_NOTICE,
1479 				"lan set <channel> arp respond <on|off>\n"
1480 				"lan set <channel> arp generate <on|off>\n"
1481 				"lan set <channel> arp interval <seconds>\n");
1482 			return (-1);
1483 		}
1484 	}
1485 	/* set authentication types */
1486 	else if (strncmp(argv[1], "auth", 4) == 0) {
1487 		if (argc < 3) {
1488 			lprintf(LOG_NOTICE,
1489 				"lan set <channel> auth <level> <type,type,...>\n"
1490 				"  level = CALLBACK, USER, OPERATOR, ADMIN\n"
1491 				"  types = NONE, MD2, MD5, PASSWORD, OEM\n"
1492 				"example: lan set 7 auth ADMIN PASSWORD,MD5\n");
1493 			return (-1);
1494 		}
1495 		else if (strncmp(argv[2], "help", 4) == 0) {
1496 			lprintf(LOG_NOTICE,
1497 				"lan set <channel> auth <level> <type,type,...>\n"
1498 				"  level = CALLBACK, USER, OPERATOR, ADMIN\n"
1499 				"  types = NONE, MD2, MD5, PASSWORD, OEM\n"
1500 				"example: lan set 7 auth ADMIN PASSWORD,MD5\n");
1501 			return 0;
1502 		} else {
1503 			rc = ipmi_lan_set_auth(intf, chan, argv[2], argv[3]);
1504 		}
1505 	}
1506 	/* ip address source */
1507 	else if (strncmp(argv[1], "ipsrc", 5) == 0) {
1508 		if (argc < 3) {
1509 			lprintf(LOG_NOTICE,
1510 				"lan set <channel> ipsrc <source>\n"
1511 				"  none   = unspecified\n"
1512 				"  static = static address (manually configured)\n"
1513 				"  dhcp   = address obtained by BMC running DHCP\n"
1514 				"  bios   = address loaded by BIOS or system software\n");
1515 			return (-1);
1516 		}
1517 		else if (strncmp(argv[2], "help", 4) == 0) {
1518 			lprintf(LOG_NOTICE,
1519 				"lan set <channel> ipsrc <source>\n"
1520 				"  none   = unspecified\n"
1521 				"  static = static address (manually configured)\n"
1522 				"  dhcp   = address obtained by BMC running DHCP\n"
1523 				"  bios   = address loaded by BIOS or system software\n");
1524 			return 0;
1525 		}
1526 		else if (strncmp(argv[2], "none", 4) == 0)
1527 			data[0] = 0;
1528 		else if (strncmp(argv[2], "static", 5) == 0)
1529 			data[0] = 1;
1530 		else if (strncmp(argv[2], "dhcp", 4) == 0)
1531 			data[0] = 2;
1532 		else if (strncmp(argv[2], "bios", 4) == 0)
1533 			data[0] = 3;
1534 		else {
1535 			lprintf(LOG_NOTICE,
1536 				"lan set <channel> ipsrc <source>\n"
1537 				"  none   = unspecified\n"
1538 				"  static = static address (manually configured)\n"
1539 				"  dhcp   = address obtained by BMC running DHCP\n"
1540 				"  bios   = address loaded by BIOS or system software\n");
1541 			return -1;
1542 		}
1543 		rc = set_lan_param(intf, chan, IPMI_LANP_IP_ADDR_SRC, data, 1);
1544 	}
1545 	/* session password
1546 	 * not strictly a lan setting, but its used for lan connections */
1547 	else if (strncmp(argv[1], "password", 8) == 0) {
1548 		rc = ipmi_lan_set_password(intf, 1, (uint8_t *)argv[2]);
1549 	}
1550 	/* snmp community string */
1551 	else if (strncmp(argv[1], "snmp", 4) == 0) {
1552 		if (argc < 3) {
1553 			lprintf(LOG_NOTICE, "lan set <channel> snmp <community string>");
1554 			return (-1);
1555 		}
1556 		else if (strncmp(argv[2], "help", 4) == 0) {
1557 			lprintf(LOG_NOTICE, "lan set <channel> snmp <community string>");
1558 			return 0;
1559 		} else {
1560 			memcpy(data, argv[2], __min(strlen(argv[2]), 18));
1561 			printf("Setting LAN %s to %s\n",
1562 			       ipmi_lan_params[IPMI_LANP_SNMP_STRING].desc, data);
1563 			rc = set_lan_param(intf, chan, IPMI_LANP_SNMP_STRING, data, 18);
1564 		}
1565 	}
1566 	/* ip address */
1567 	else if (strncmp(argv[1], "ipaddr", 6) == 0) {
1568 		if(argc != 3)
1569 		{
1570 			ipmi_lan_set_usage();
1571 			return -1;
1572 		}
1573 		rc = get_cmdline_ipaddr(argv[2], data);
1574 		if (rc == 0) {
1575 			printf("Setting LAN %s to %d.%d.%d.%d\n",
1576 				ipmi_lan_params[IPMI_LANP_IP_ADDR].desc,
1577 				data[0], data[1], data[2], data[3]);
1578 			rc = set_lan_param(intf, chan, IPMI_LANP_IP_ADDR, data, 4);
1579 		}
1580 	}
1581 	/* network mask */
1582 	else if (strncmp(argv[1], "netmask", 7) == 0) {
1583 		if(argc != 3)
1584 		{
1585 			ipmi_lan_set_usage();
1586 			return -1;
1587 		}
1588 		rc = get_cmdline_ipaddr(argv[2], data);
1589 		if (rc == 0) {
1590 			printf("Setting LAN %s to %d.%d.%d.%d\n",
1591 		       		ipmi_lan_params[IPMI_LANP_SUBNET_MASK].desc,
1592 		       		data[0], data[1], data[2], data[3]);
1593 			rc = set_lan_param(intf, chan, IPMI_LANP_SUBNET_MASK, data, 4);
1594 		}
1595 	}
1596 	/* mac address */
1597 	else if (strncmp(argv[1], "macaddr", 7) == 0) {
1598 		if(argc != 3)
1599 		{
1600 			ipmi_lan_set_usage();
1601 			return -1;
1602 		}
1603 		rc = get_cmdline_macaddr(argv[2], data);
1604 		if (rc == 0) {
1605 			printf("Setting LAN %s to %02x:%02x:%02x:%02x:%02x:%02x\n",
1606 		       		ipmi_lan_params[IPMI_LANP_MAC_ADDR].desc,
1607 		       		data[0], data[1], data[2], data[3], data[4], data[5]);
1608 			rc = set_lan_param(intf, chan, IPMI_LANP_MAC_ADDR, data, 6);
1609 		}
1610 	}
1611 	/* default gateway settings */
1612 	else if (strncmp(argv[1], "defgw", 5) == 0) {
1613 		if (argc < 4) {
1614 			lprintf(LOG_NOTICE, "LAN set default gateway Commands: ipaddr, macaddr");
1615 			return (-1);
1616 		}
1617 		else if (strncmp(argv[2], "help", 4) == 0) {
1618 			lprintf(LOG_NOTICE, "LAN set default gateway Commands: ipaddr, macaddr");
1619 			return 0;
1620 		}
1621 		else if ((strncmp(argv[2], "ipaddr", 5) == 0) &&
1622 			 (get_cmdline_ipaddr(argv[3], data) == 0)) {
1623 			printf("Setting LAN %s to %d.%d.%d.%d\n",
1624 			       ipmi_lan_params[IPMI_LANP_DEF_GATEWAY_IP].desc,
1625 			       data[0], data[1], data[2], data[3]);
1626 			rc = set_lan_param(intf, chan, IPMI_LANP_DEF_GATEWAY_IP, data, 4);
1627 		}
1628 		else if ((strncmp(argv[2], "macaddr", 7) == 0) &&
1629 			 (get_cmdline_macaddr(argv[3], data) == 0)) {
1630 			printf("Setting LAN %s to %02x:%02x:%02x:%02x:%02x:%02x\n",
1631 			       ipmi_lan_params[IPMI_LANP_DEF_GATEWAY_MAC].desc,
1632 			       data[0], data[1], data[2], data[3], data[4], data[5]);
1633 			rc = set_lan_param(intf, chan, IPMI_LANP_DEF_GATEWAY_MAC, data, 6);
1634 		}
1635 		else {
1636 			ipmi_lan_set_usage();
1637 			return -1;
1638 		}
1639 	}
1640 	/* backup gateway settings */
1641 	else if (strncmp(argv[1], "bakgw", 5) == 0) {
1642 		if (argc < 4) {
1643 			lprintf(LOG_NOTICE, "LAN set backup gateway commands: ipaddr, macaddr");
1644 			return (-1);
1645 		}
1646 		else if (strncmp(argv[2], "help", 4) == 0) {
1647 			lprintf(LOG_NOTICE, "LAN set backup gateway commands: ipaddr, macaddr");
1648 			return 0;
1649 		}
1650 		else if ((strncmp(argv[2], "ipaddr", 5) == 0) &&
1651 			 (get_cmdline_ipaddr(argv[3], data) == 0)) {
1652 			printf("Setting LAN %s to %d.%d.%d.%d\n",
1653 			       ipmi_lan_params[IPMI_LANP_BAK_GATEWAY_IP].desc,
1654 			       data[0], data[1], data[2], data[3]);
1655 			rc = set_lan_param(intf, chan, IPMI_LANP_BAK_GATEWAY_IP, data, 4);
1656 		}
1657 		else if ((strncmp(argv[2], "macaddr", 7) == 0) &&
1658 			 (get_cmdline_macaddr(argv[3], data) == 0)) {
1659 			printf("Setting LAN %s to %02x:%02x:%02x:%02x:%02x:%02x\n",
1660 			       ipmi_lan_params[IPMI_LANP_BAK_GATEWAY_MAC].desc,
1661 			       data[0], data[1], data[2], data[3], data[4], data[5]);
1662 			rc = set_lan_param(intf, chan, IPMI_LANP_BAK_GATEWAY_MAC, data, 6);
1663 		}
1664 		else {
1665 			ipmi_lan_set_usage();
1666 			return -1;
1667 		}
1668 	}
1669 	else if (strncasecmp(argv[1], "vlan", 4) == 0) {
1670 		if (argc < 4) {
1671 			ipmi_lan_set_vlan_usage();
1672 			return (-1);
1673 		}
1674 		else if (strncmp(argv[2], "help", 4) == 0) {
1675 			ipmi_lan_set_vlan_usage();
1676 			return 0;
1677 		}
1678 		else if (strncasecmp(argv[2], "id", 2) == 0) {
1679 			if (strncasecmp(argv[3], "off", 3) == 0) {
1680 				ipmi_lan_set_vlan_id(intf, chan, NULL);
1681 			}
1682 			else {
1683 				ipmi_lan_set_vlan_id(intf, chan, argv[3]);
1684 			}
1685 		}
1686 		else if (strncasecmp(argv[2], "priority", 8) == 0) {
1687 			ipmi_lan_set_vlan_priority(intf, chan, argv[3]);
1688 		}
1689 		else {
1690 			ipmi_lan_set_vlan_usage();
1691 			return (-1);
1692 		}
1693 	}
1694 	/* set PEF alerting on or off */
1695 	else if (strncasecmp(argv[1], "alert", 5) == 0) {
1696 		if (argc < 3) {
1697 			lprintf(LOG_NOTICE, "LAN set alert must be 'on' or 'off'");
1698 			return (-1);
1699 		}
1700 		else if (strncasecmp(argv[2], "on", 2) == 0 ||
1701 			 strncasecmp(argv[2], "enable", 6) == 0) {
1702 			printf("Enabling PEF alerts for LAN channel %d\n", chan);
1703 			rc = ipmi_set_alert_enable(intf, chan, 1);
1704 		}
1705 		else if (strncasecmp(argv[2], "off", 3) == 0 ||
1706 			 strncasecmp(argv[2], "disable", 7) == 0) {
1707 			printf("Disabling PEF alerts for LAN channel %d\n", chan);
1708 			rc = ipmi_set_alert_enable(intf, chan, 0);
1709 		}
1710 		else {
1711 			lprintf(LOG_NOTICE, "LAN set alert must be 'on' or 'off'");
1712 			return 0;
1713 		}
1714 	}
1715 	/* RMCP+ cipher suite privilege levels */
1716 	else if (strncmp(argv[1], "cipher_privs", 12) == 0)
1717 	{
1718 		if (argc != 3) {
1719 			lprintf(LOG_NOTICE, "lan set <channel> cipher_privs XXXXXXXXXXXXXXX");
1720 			lprintf(LOG_NOTICE, "    X = Cipher Suite Unused");
1721 			lprintf(LOG_NOTICE, "    c = CALLBACK");
1722 			lprintf(LOG_NOTICE, "    u = USER");
1723 			lprintf(LOG_NOTICE, "    o = OPERATOR");
1724 			lprintf(LOG_NOTICE, "    a = ADMIN");
1725 			lprintf(LOG_NOTICE, "    O = OEM\n");
1726 			return (-1);
1727 		}
1728 		else if ((strncmp(argv[2], "help", 4) == 0) ||
1729 		    get_cmdline_cipher_suite_priv_data(argv[2], data))
1730 		{
1731 			lprintf(LOG_NOTICE, "lan set <channel> cipher_privs XXXXXXXXXXXXXXX");
1732 			lprintf(LOG_NOTICE, "    X = Cipher Suite Unused");
1733 			lprintf(LOG_NOTICE, "    c = CALLBACK");
1734 			lprintf(LOG_NOTICE, "    u = USER");
1735 			lprintf(LOG_NOTICE, "    o = OPERATOR");
1736 			lprintf(LOG_NOTICE, "    a = ADMIN");
1737 			lprintf(LOG_NOTICE, "    O = OEM\n");
1738 			return 0;
1739 		}
1740 		else
1741 		{
1742 			rc = set_lan_param(intf, chan, IPMI_LANP_RMCP_PRIV_LEVELS, data, 9);
1743 		}
1744 	}
1745 	else {
1746 		ipmi_lan_set_usage();
1747 		return (-1);
1748 	}
1749 
1750 	return rc;
1751 }
1752 
1753 
1754 static int
1755 is_alert_destination(struct ipmi_intf * intf, uint8_t channel, uint8_t alert)
1756 {
1757 	struct lan_param * p;
1758 
1759 	p = get_lan_param(intf, channel, IPMI_LANP_NUM_DEST);
1760 	if (p == NULL)
1761 		return 0;
1762 	if (p->data == NULL)
1763 		return 0;
1764 
1765 	if (alert <= (p->data[0] & 0xf))
1766 		return 1;
1767 	else
1768 		return 0;
1769 }
1770 
1771 static int
1772 ipmi_lan_alert_print(struct ipmi_intf * intf, uint8_t channel, uint8_t alert)
1773 {
1774 # define PTYPE_LEN	4
1775 # define PADDR_LEN	13
1776 	struct lan_param *lp_ptr = NULL;
1777 	int isack = 0;
1778 	uint8_t ptype[PTYPE_LEN];
1779 	uint8_t paddr[PADDR_LEN];
1780 
1781 	lp_ptr = get_lan_param_select(intf, channel, IPMI_LANP_DEST_TYPE, alert);
1782 	if (lp_ptr == NULL || lp_ptr->data == NULL
1783 			|| lp_ptr->data_len < PTYPE_LEN) {
1784 		return (-1);
1785 	}
1786 	memcpy(ptype, lp_ptr->data, PTYPE_LEN);
1787 
1788 	lp_ptr = get_lan_param_select(intf, channel, IPMI_LANP_DEST_ADDR, alert);
1789 	if (lp_ptr == NULL || lp_ptr->data == NULL
1790 			|| lp_ptr->data_len < PADDR_LEN) {
1791 		return (-1);
1792 	}
1793 	memcpy(paddr, lp_ptr->data, PADDR_LEN);
1794 
1795 	printf("%-24s: %d\n", "Alert Destination",
1796 			ptype[0]);
1797 
1798 	if (ptype[1] & 0x80) {
1799 		isack = 1;
1800 	}
1801 	printf("%-24s: %s\n", "Alert Acknowledge",
1802 			isack ? "Acknowledged" : "Unacknowledged");
1803 
1804 	printf("%-24s: ", "Destination Type");
1805 	switch (ptype[1] & 0x7) {
1806 	case 0:
1807 		printf("PET Trap\n");
1808 		break;
1809 	case 6:
1810 		printf("OEM 1\n");
1811 		break;
1812 	case 7:
1813 		printf("OEM 2\n");
1814 		break;
1815 	default:
1816 		printf("Unknown\n");
1817 		break;
1818 	}
1819 
1820 	printf("%-24s: %d\n",
1821 			isack ? "Acknowledge Timeout" : "Retry Interval",
1822 			ptype[2]);
1823 
1824 	printf("%-24s: %d\n", "Number of Retries",
1825 			ptype[3] & 0x7);
1826 
1827 	if ((paddr[1] & 0xf0) != 0) {
1828 		/* unknown address format */
1829 		printf("\n");
1830 		return 0;
1831 	}
1832 
1833 	printf("%-24s: %s\n", "Alert Gateway",
1834 			(paddr[2] & 1) ? "Backup" : "Default");
1835 
1836 	printf("%-24s: %d.%d.%d.%d\n", "Alert IP Address",
1837 			paddr[3], paddr[4], paddr[5], paddr[6]);
1838 
1839 	printf("%-24s: %02x:%02x:%02x:%02x:%02x:%02x\n", "Alert MAC Address",
1840 			paddr[7], paddr[8], paddr[9],
1841 			paddr[10], paddr[11], paddr[12]);
1842 
1843 	printf("\n");
1844 	return 0;
1845 }
1846 
1847 static int
1848 ipmi_lan_alert_print_all(struct ipmi_intf * intf, uint8_t channel)
1849 {
1850 	int j, ndest;
1851 	struct lan_param * p;
1852 
1853 	p = get_lan_param(intf, channel, IPMI_LANP_NUM_DEST);
1854 	if (p == NULL)
1855 		return -1;
1856 	if (p->data == NULL)
1857 		return -1;
1858 	ndest = p->data[0] & 0xf;
1859 
1860 	for (j=0; j<=ndest; j++) {
1861 		ipmi_lan_alert_print(intf, channel, j);
1862 	}
1863 
1864 	return 0;
1865 }
1866 
1867 static void
1868 ipmi_lan_alert_print_usage(void)
1869 {
1870 	lprintf(LOG_NOTICE, "\nusage: lan alert print [channel number] [alert destination]\n");
1871 	lprintf(LOG_NOTICE, "Default will print all alerts for the first found LAN channel");
1872 }
1873 
1874 static void
1875 ipmi_lan_alert_set_usage(void)
1876 {
1877 	lprintf(LOG_NOTICE, "\nusage: lan alert set <channel number> <alert destination> <command> <parameter>\n");
1878 	lprintf(LOG_NOTICE, "    Command/parameter options:\n");
1879 	lprintf(LOG_NOTICE, "    ipaddr <x.x.x.x>               Set alert IP address");
1880 	lprintf(LOG_NOTICE, "    macaddr <x:x:x:x:x:x>          Set alert MAC address");
1881 	lprintf(LOG_NOTICE, "    gateway <default|backup>       Set channel gateway to use for alerts");
1882 	lprintf(LOG_NOTICE, "    ack <on|off>                   Set Alert Acknowledge on or off");
1883 	lprintf(LOG_NOTICE, "    type <pet|oem1|oem2>           Set destination type as PET or OEM");
1884 	lprintf(LOG_NOTICE, "    time <seconds>                 Set ack timeout or unack retry interval");
1885 	lprintf(LOG_NOTICE, "    retry <number>                 Set number of alert retries");
1886 	lprintf(LOG_NOTICE, "");
1887 }
1888 
1889 static int
1890 ipmi_lan_alert_set(struct ipmi_intf * intf, uint8_t chan, uint8_t alert,
1891 		   int argc, char ** argv)
1892 {
1893 	struct lan_param * p;
1894 	uint8_t data[32], temp[32];
1895 	int rc = 0;
1896 
1897 	if (argc < 2) {
1898 		ipmi_lan_alert_set_usage();
1899 		return (-1);
1900 	}
1901 
1902 	if (strncmp(argv[0], "help", 4) == 0 ||
1903 	    strncmp(argv[1], "help", 4) == 0) {
1904 		ipmi_lan_alert_set_usage();
1905 		return 0;
1906 	}
1907 
1908 	memset(data, 0, sizeof(data));
1909 	memset(temp, 0, sizeof(temp));
1910 
1911 	/* alert destination ip address */
1912 	if (strncasecmp(argv[0], "ipaddr", 6) == 0 &&
1913 	    (get_cmdline_ipaddr(argv[1], temp) == 0)) {
1914 		/* get current parameter */
1915 		p = get_lan_param_select(intf, chan, IPMI_LANP_DEST_ADDR, alert);
1916 		if (p == NULL) {
1917 			return (-1);
1918 		}
1919 		memcpy(data, p->data, p->data_len);
1920 		/* set new ipaddr */
1921 		memcpy(data+3, temp, 4);
1922 		printf("Setting LAN Alert %d IP Address to %d.%d.%d.%d\n", alert,
1923 		       data[3], data[4], data[5], data[6]);
1924 		rc = set_lan_param_nowait(intf, chan, IPMI_LANP_DEST_ADDR, data, p->data_len);
1925 	}
1926 	/* alert destination mac address */
1927 	else if (strncasecmp(argv[0], "macaddr", 7) == 0 &&
1928 		 (get_cmdline_macaddr(argv[1], temp) == 0)) {
1929 		/* get current parameter */
1930 		p = get_lan_param_select(intf, chan, IPMI_LANP_DEST_ADDR, alert);
1931 		if (p == NULL) {
1932 			return (-1);
1933 		}
1934 		memcpy(data, p->data, p->data_len);
1935 		/* set new macaddr */
1936 		memcpy(data+7, temp, 6);
1937 		printf("Setting LAN Alert %d MAC Address to "
1938 		       "%02x:%02x:%02x:%02x:%02x:%02x\n", alert,
1939 		       data[7], data[8], data[9], data[10], data[11], data[12]);
1940 		rc = set_lan_param_nowait(intf, chan, IPMI_LANP_DEST_ADDR, data, p->data_len);
1941 	}
1942 	/* alert destination gateway selector */
1943 	else if (strncasecmp(argv[0], "gateway", 7) == 0) {
1944 		/* get current parameter */
1945 		p = get_lan_param_select(intf, chan, IPMI_LANP_DEST_ADDR, alert);
1946 		if (p == NULL) {
1947 			return (-1);
1948 		}
1949 		memcpy(data, p->data, p->data_len);
1950 
1951 		if (strncasecmp(argv[1], "def", 3) == 0 ||
1952 		    strncasecmp(argv[1], "default", 7) == 0) {
1953 			printf("Setting LAN Alert %d to use Default Gateway\n", alert);
1954 			data[2] = 0;
1955 		}
1956 		else if (strncasecmp(argv[1], "bak", 3) == 0 ||
1957 			 strncasecmp(argv[1], "backup", 6) == 0) {
1958 			printf("Setting LAN Alert %d to use Backup Gateway\n", alert);
1959 			data[2] = 1;
1960 		}
1961 		else {
1962 			ipmi_lan_alert_set_usage();
1963 			return -1;
1964 		}
1965 
1966 		rc = set_lan_param_nowait(intf, chan, IPMI_LANP_DEST_ADDR, data, p->data_len);
1967 	}
1968 	/* alert acknowledgement */
1969 	else if (strncasecmp(argv[0], "ack", 3) == 0) {
1970 		/* get current parameter */
1971 		p = get_lan_param_select(intf, chan, IPMI_LANP_DEST_TYPE, alert);
1972 		if (p == NULL) {
1973 			return (-1);
1974 		}
1975 		memcpy(data, p->data, p->data_len);
1976 
1977 		if (strncasecmp(argv[1], "on", 2) == 0 ||
1978 		    strncasecmp(argv[1], "yes", 3) == 0) {
1979 			printf("Setting LAN Alert %d to Acknowledged\n", alert);
1980 			data[1] |= 0x80;
1981 		}
1982 		else if (strncasecmp(argv[1], "off", 3) == 0 ||
1983 			 strncasecmp(argv[1], "no", 2) == 0) {
1984 			printf("Setting LAN Alert %d to Unacknowledged\n", alert);
1985 			data[1] &= ~0x80;
1986 		}
1987 		else {
1988 			ipmi_lan_alert_set_usage();
1989 			return -1;
1990 		}
1991 		rc = set_lan_param_nowait(intf, chan, IPMI_LANP_DEST_TYPE, data, p->data_len);
1992 	}
1993 	/* alert destination type */
1994 	else if (strncasecmp(argv[0], "type", 4) == 0) {
1995 		/* get current parameter */
1996 		p = get_lan_param_select(intf, chan, IPMI_LANP_DEST_TYPE, alert);
1997 		if (p == NULL) {
1998 			return (-1);
1999 		}
2000 		memcpy(data, p->data, p->data_len);
2001 
2002 		if (strncasecmp(argv[1], "pet", 3) == 0) {
2003 			printf("Setting LAN Alert %d destination to PET Trap\n", alert);
2004 			data[1] &= ~0x07;
2005 		}
2006 		else if (strncasecmp(argv[1], "oem1", 4) == 0) {
2007 			printf("Setting LAN Alert %d destination to OEM 1\n", alert);
2008 			data[1] &= ~0x07;
2009 			data[1] |= 0x06;
2010 		}
2011 		else if (strncasecmp(argv[1], "oem2", 4) == 0) {
2012 			printf("Setting LAN Alert %d destination to OEM 2\n", alert);
2013 			data[1] |= 0x07;
2014 		}
2015 		else {
2016 			ipmi_lan_alert_set_usage();
2017 			return -1;
2018 		}
2019 		rc = set_lan_param_nowait(intf, chan, IPMI_LANP_DEST_TYPE, data, p->data_len);
2020 	}
2021 	/* alert acknowledge timeout or retry interval */
2022 	else if (strncasecmp(argv[0], "time", 4) == 0) {
2023 		/* get current parameter */
2024 		p = get_lan_param_select(intf, chan, IPMI_LANP_DEST_TYPE, alert);
2025 		if (p == NULL) {
2026 			return (-1);
2027 		}
2028 		memcpy(data, p->data, p->data_len);
2029 
2030 		if (str2uchar(argv[1], &data[2]) != 0) {
2031 			lprintf(LOG_ERR, "Invalid time: %s", argv[1]);
2032 			return (-1);
2033 		}
2034 		printf("Setting LAN Alert %d timeout/retry to %d seconds\n", alert, data[2]);
2035 		rc = set_lan_param_nowait(intf, chan, IPMI_LANP_DEST_TYPE, data, p->data_len);
2036 	}
2037 	/* number of retries */
2038 	else if (strncasecmp(argv[0], "retry", 5) == 0) {
2039 		/* get current parameter */
2040 		p = get_lan_param_select(intf, chan, IPMI_LANP_DEST_TYPE, alert);
2041 		if (p == NULL) {
2042 			return (-1);
2043 		}
2044 		memcpy(data, p->data, p->data_len);
2045 
2046 		if (str2uchar(argv[1], &data[3]) != 0) {
2047 			lprintf(LOG_ERR, "Invalid retry: %s", argv[1]);
2048 			return (-1);
2049 		}
2050 		data[3] = data[3] & 0x7;
2051 		printf("Setting LAN Alert %d number of retries to %d\n", alert, data[3]);
2052 		rc = set_lan_param_nowait(intf, chan, IPMI_LANP_DEST_TYPE, data, p->data_len);
2053 	}
2054 	else {
2055 		ipmi_lan_alert_set_usage();
2056 		return -1;
2057 	}
2058 
2059 	return rc;
2060 }
2061 
2062 static int
2063 ipmi_lan_alert(struct ipmi_intf * intf, int argc, char ** argv)
2064 {
2065 	uint8_t alert;
2066 	uint8_t channel = 1;
2067 
2068 	if (argc < 1) {
2069 		ipmi_lan_alert_print_usage();
2070 		ipmi_lan_alert_set_usage();
2071 		return (-1);
2072 	}
2073 	else if (strncasecmp(argv[0], "help", 4) == 0) {
2074 		ipmi_lan_alert_print_usage();
2075 		ipmi_lan_alert_set_usage();
2076 		return 0;
2077 	}
2078 
2079 	/* alert print [channel] [alert] */
2080 	if (strncasecmp(argv[0], "print", 5) == 0) {
2081 		if (argc < 2) {
2082 			channel = find_lan_channel(intf, 1);
2083 			if (!is_lan_channel(intf, channel)) {
2084 				lprintf(LOG_ERR, "Channel %d is not a LAN channel", channel);
2085 				return -1;
2086 			}
2087 			return ipmi_lan_alert_print_all(intf, channel);
2088 		}
2089 
2090 		if (strncasecmp(argv[1], "help", 4) == 0) {
2091 			ipmi_lan_alert_print_usage();
2092 			return 0;
2093 		}
2094 
2095 		if (str2uchar(argv[1], &channel) != 0) {
2096 			lprintf(LOG_ERR, "Invalid channel: %s", argv[1]);
2097 			return (-1);
2098 		}
2099 		if (!is_lan_channel(intf, channel)) {
2100 			lprintf(LOG_ERR, "Channel %d is not a LAN channel", channel);
2101 			return -1;
2102 		}
2103 
2104 		if (argc < 3)
2105 			return ipmi_lan_alert_print_all(intf, channel);
2106 
2107 		if (str2uchar(argv[2], &alert) != 0) {
2108 			lprintf(LOG_ERR, "Invalid alert: %s", argv[2]);
2109 			return (-1);
2110 		}
2111 		if (is_alert_destination(intf, channel, alert) == 0) {
2112 			lprintf(LOG_ERR, "Alert %d is not a valid destination", alert);
2113 			return -1;
2114 		}
2115 		return ipmi_lan_alert_print(intf, channel, alert);
2116 	}
2117 
2118 	/* alert set <channel> <alert> [option] */
2119 	if (strncasecmp(argv[0], "set", 3) == 0) {
2120 		if (argc < 5) {
2121 			ipmi_lan_alert_set_usage();
2122 			return (-1);
2123 		}
2124 		else if (strncasecmp(argv[1], "help", 4) == 0) {
2125 			ipmi_lan_alert_set_usage();
2126 			return 0;
2127 		}
2128 
2129 		if (str2uchar(argv[1], &channel) != 0) {
2130 			lprintf(LOG_ERR, "Invalid channel: %s", argv[1]);
2131 			return (-1);
2132 		}
2133 		if (!is_lan_channel(intf, channel)) {
2134 			lprintf(LOG_ERR, "Channel %d is not a LAN channel", channel);
2135 			return -1;
2136 		}
2137 
2138 		if (str2uchar(argv[2], &alert) != 0) {
2139 			lprintf(LOG_ERR, "Invalid alert: %s", argv[2]);
2140 			return (-1);
2141 		}
2142 		if (is_alert_destination(intf, channel, alert) == 0) {
2143 			lprintf(LOG_ERR, "Alert %d is not a valid destination", alert);
2144 			return -1;
2145 		}
2146 
2147 		return ipmi_lan_alert_set(intf, channel, alert, argc-3, &(argv[3]));
2148 	}
2149 
2150 	return 0;
2151 }
2152 
2153 
2154 static int
2155 ipmi_lan_stats_get(struct ipmi_intf * intf, uint8_t chan)
2156 {
2157 	int rc = 0;
2158 	struct ipmi_rs * rsp;
2159 	struct ipmi_rq req;
2160 	uint8_t msg_data[2];
2161 	uint16_t statsTemp;
2162 
2163 	if (!is_lan_channel(intf, chan)) {
2164 		lprintf(LOG_ERR, "Channel %d is not a LAN channel", chan);
2165 		return -1;
2166 	}
2167 
2168 	/* From here, we are ready to get the stats */
2169 
2170 	msg_data[0] = chan;
2171 	msg_data[1] = 0;   /* Don't clear */
2172 
2173 	memset(&req, 0, sizeof(req));
2174 	req.msg.netfn    = IPMI_NETFN_TRANSPORT;
2175 	req.msg.cmd      = IPMI_LAN_GET_STAT;
2176 	req.msg.data     = msg_data;
2177 	req.msg.data_len = 2;
2178 
2179 	rsp = intf->sendrecv(intf, &req);
2180 	if (rsp == NULL) {
2181 		lprintf(LOG_ERR, "Get LAN Stats command failed");
2182 		return (-1);
2183 	}
2184 
2185 	if (rsp->ccode > 0) {
2186 		lprintf(LOG_ERR, "Get LAN Stats command failed: %s",
2187 			val2str(rsp->ccode, completion_code_vals));
2188 		return (-1);
2189 	}
2190 
2191 	if (verbose > 1) {
2192 		uint8_t counter;
2193 		printf("--- Rx Stats ---\n");
2194 		for (counter=0; counter<18; counter+=2) {
2195 			printf("%02X", *(rsp->data + counter));
2196 			printf(" %02X - ", *(rsp->data + counter+1));
2197 		}
2198 		printf("\n");
2199 	}
2200 
2201 	statsTemp = ((*(rsp->data + 0)) << 8) | (*(rsp->data + 1));
2202 	printf("IP Rx Packet              : %d\n", statsTemp);
2203 
2204 	statsTemp = ((*(rsp->data + 2)) << 8) | (*(rsp->data + 3));
2205 	printf("IP Rx Header Errors       : %u\n", statsTemp);
2206 
2207 	statsTemp = ((*(rsp->data + 4)) << 8) | (*(rsp->data + 5));
2208 	printf("IP Rx Address Errors      : %u\n", statsTemp);
2209 
2210 	statsTemp = ((*(rsp->data + 6)) << 8) | (*(rsp->data + 7));
2211 	printf("IP Rx Fragmented          : %u\n", statsTemp);
2212 
2213 	statsTemp = ((*(rsp->data + 8)) << 8) | (*(rsp->data + 9));
2214 	printf("IP Tx Packet              : %u\n", statsTemp);
2215 
2216 	statsTemp = ((*(rsp->data +10)) << 8) | (*(rsp->data +11));
2217 	printf("UDP Rx Packet             : %u\n", statsTemp);
2218 
2219 	statsTemp = ((*(rsp->data + 12)) << 8) | (*(rsp->data + 13));
2220 	printf("RMCP Rx Valid             : %u\n", statsTemp);
2221 
2222 	statsTemp = ((*(rsp->data + 14)) << 8) | (*(rsp->data + 15));
2223 	printf("UDP Proxy Packet Received : %u\n", statsTemp);
2224 
2225 	statsTemp = ((*(rsp->data + 16)) << 8) | (*(rsp->data + 17));
2226 	printf("UDP Proxy Packet Dropped  : %u\n", statsTemp);
2227 
2228 	return rc;
2229 }
2230 
2231 
2232 static int
2233 ipmi_lan_stats_clear(struct ipmi_intf * intf, uint8_t chan)
2234 {
2235 	int rc = 0;
2236 	struct ipmi_rs * rsp;
2237 	struct ipmi_rq req;
2238 	uint8_t msg_data[2];
2239 
2240 	if (!is_lan_channel(intf, chan)) {
2241 		lprintf(LOG_ERR, "Channel %d is not a LAN channel", chan);
2242 		return -1;
2243 	}
2244 
2245 	/* From here, we are ready to get the stats */
2246 	msg_data[0] = chan;
2247 	msg_data[1] = 1;   /* Clear */
2248 
2249 	memset(&req, 0, sizeof(req));
2250 	req.msg.netfn    = IPMI_NETFN_TRANSPORT;
2251 	req.msg.cmd      = IPMI_LAN_GET_STAT;
2252 	req.msg.data     = msg_data;
2253 	req.msg.data_len = 2;
2254 
2255 	rsp = intf->sendrecv(intf, &req);
2256 	if (rsp == NULL) {
2257 		lprintf(LOG_INFO, "Get LAN Stats command failed");
2258 		return (-1);
2259 	}
2260 
2261 	if (rsp->ccode > 0) {
2262 		lprintf(LOG_INFO, "Get LAN Stats command failed: %s",
2263 			val2str(rsp->ccode, completion_code_vals));
2264 		return (-1);
2265 	}
2266 
2267 	return rc;
2268 }
2269 
2270 
2271 /*
2272  * print_lan_usage
2273  */
2274 static void
2275 print_lan_usage(void)
2276 {
2277 	lprintf(LOG_NOTICE, "LAN Commands:");
2278 	lprintf(LOG_NOTICE, "		   print [<channel number>]");
2279 	lprintf(LOG_NOTICE, "		   set <channel number> <command> <parameter>");
2280 	lprintf(LOG_NOTICE, "		   alert print <channel number> <alert destination>");
2281 	lprintf(LOG_NOTICE, "		   alert set <channel number> <alert destination> <command> <parameter>");
2282 	lprintf(LOG_NOTICE, "		   stats get [<channel number>]");
2283 	lprintf(LOG_NOTICE, "		   stats clear [<channel number>]");
2284 }
2285 
2286 
2287 int
2288 ipmi_lanp_main(struct ipmi_intf * intf, int argc, char ** argv)
2289 {
2290 	int rc = 0;
2291 	uint8_t chan = 0;
2292 
2293 	if (argc == 0) {
2294 		print_lan_usage();
2295 		return (-1);
2296 	} else if (strncmp(argv[0], "help", 4) == 0) {
2297 		print_lan_usage();
2298 		return 0;
2299 	}
2300 
2301 	chan = find_lan_channel(intf, 1);
2302 
2303 	if (strncmp(argv[0], "printconf", 9) == 0 ||
2304 			strncmp(argv[0], "print", 5) == 0)
2305 	{
2306 		if (argc > 2) {
2307 			print_lan_usage();
2308 			return (-1);
2309 		} else if (argc == 2) {
2310 			if (str2uchar(argv[1], &chan) != 0) {
2311 				lprintf(LOG_ERR, "Invalid channel: %s", argv[1]);
2312 				return (-1);
2313 			}
2314 		}
2315 		if (!is_lan_channel(intf, chan)) {
2316 			lprintf(LOG_ERR, "Invalid channel: %d", chan);
2317 			return (-1);
2318 		}
2319 		rc = ipmi_lan_print(intf, chan);
2320 	} else if (strncmp(argv[0], "set", 3) == 0) {
2321 		rc = ipmi_lan_set(intf, argc-1, &(argv[1]));
2322 	} else if (strncmp(argv[0], "alert", 5) == 0) {
2323 		rc = ipmi_lan_alert(intf, argc-1, &(argv[1]));
2324 	} else if (strncmp(argv[0], "stats", 5) == 0) {
2325 		if (argc < 2) {
2326 			print_lan_usage();
2327 			return (-1);
2328 		} else if (argc == 3) {
2329 			if (str2uchar(argv[2], &chan) != 0) {
2330 				lprintf(LOG_ERR, "Invalid channel: %s", argv[2]);
2331 				return (-1);
2332 			}
2333 		}
2334 		if (!is_lan_channel(intf, chan)) {
2335 			lprintf(LOG_ERR, "Invalid channel: %d", chan);
2336 			return (-1);
2337 		}
2338 		if (strncmp(argv[1], "get", 3) == 0) {
2339 			rc = ipmi_lan_stats_get(intf, chan);
2340 		} else if (strncmp(argv[1], "clear", 5) == 0) {
2341 			rc = ipmi_lan_stats_clear(intf, chan);
2342 		} else {
2343 			print_lan_usage();
2344 			return (-1);
2345 		}
2346 	} else {
2347 		lprintf(LOG_NOTICE, "Invalid LAN command: %s", argv[0]);
2348 		return (-1);
2349 	}
2350 	return rc;
2351 }
2352