xref: /openbmc/ipmitool/lib/ipmi_lanp.c (revision 4c5058cd)
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 /* TODO - probably move elsewhere */
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 /* TODO - probably some code duplication going on ??? */
835 static int
836 ipmi_lan_set_auth(struct ipmi_intf * intf, uint8_t chan, char * level, char * types)
837 {
838 	uint8_t data[5];
839 	uint8_t authtype = 0;
840 	char * p;
841 	struct lan_param * lp;
842 
843 	if (level == NULL || types == NULL)
844 		return -1;
845 
846 	lp = get_lan_param(intf, chan, IPMI_LANP_AUTH_TYPE_ENABLE);
847 	if (lp == NULL)
848 		return -1;
849 	if (lp->data == NULL)
850 		return -1;
851 
852 	lprintf(LOG_DEBUG, "%-24s: callback=0x%02x user=0x%02x operator=0x%02x admin=0x%02x oem=0x%02x",
853 		lp->desc, lp->data[0], lp->data[1], lp->data[2], lp->data[3], lp->data[4]);
854 
855 	memset(data, 0, 5);
856 	memcpy(data, lp->data, 5);
857 
858 	p = types;
859 	while (p) {
860 		if (strncasecmp(p, "none", 4) == 0)
861 			authtype |= 1 << IPMI_SESSION_AUTHTYPE_NONE;
862 		else if (strncasecmp(p, "md2", 3) == 0)
863 			authtype |= 1 << IPMI_SESSION_AUTHTYPE_MD2;
864 		else if (strncasecmp(p, "md5", 3) == 0)
865 			authtype |= 1 << IPMI_SESSION_AUTHTYPE_MD5;
866 		else if ((strncasecmp(p, "password", 8) == 0) ||
867 			 (strncasecmp(p, "key", 3) == 0))
868 			authtype |= 1 << IPMI_SESSION_AUTHTYPE_KEY;
869 		else if (strncasecmp(p, "oem", 3) == 0)
870 			authtype |= 1 << IPMI_SESSION_AUTHTYPE_OEM;
871 		else
872 			lprintf(LOG_WARNING, "Invalid authentication type: %s", p);
873 		p = strchr(p, ',');
874 		if (p)
875 			p++;
876 	}
877 
878 	p = level;
879 	while (p) {
880 		if (strncasecmp(p, "callback", 8) == 0)
881 			data[0] = authtype;
882 		else if (strncasecmp(p, "user", 4) == 0)
883 			data[1] = authtype;
884 		else if (strncasecmp(p, "operator", 8) == 0)
885 			data[2] = authtype;
886 		else if (strncasecmp(p, "admin", 5) == 0)
887 			data[3] = authtype;
888 		else
889 			lprintf(LOG_WARNING, "Invalid authentication level: %s", p);
890 		p = strchr(p, ',');
891 		if (p)
892 			p++;
893 	}
894 
895 	if (verbose > 1)
896 		printbuf(data, 5, "authtype data");
897 
898 	return set_lan_param(intf, chan, IPMI_LANP_AUTH_TYPE_ENABLE, data, 5);
899 }
900 
901 /* TODO - we already have set user password in ipmi_user! */
902 static int
903 ipmi_lan_set_password(struct ipmi_intf * intf,
904 	uint8_t userid, uint8_t * password)
905 {
906 	struct ipmi_rs * rsp;
907 	struct ipmi_rq req;
908 	uint8_t data[18];
909 
910 	memset(&data, 0, sizeof(data));
911 	data[0] = userid & 0x3f;/* user ID */
912 	data[1] = 0x02;		/* set password */
913 
914 	if (password != NULL)
915 		memcpy(data+2, password, __min(strlen((const char *)password), 16));
916 
917 	memset(&req, 0, sizeof(req));
918 	req.msg.netfn = IPMI_NETFN_APP;
919 	req.msg.cmd = 0x47;
920 	req.msg.data = data;
921 	req.msg.data_len = 18;
922 
923 	rsp = intf->sendrecv(intf, &req);
924 	if (rsp == NULL) {
925 		lprintf(LOG_ERR, "Unable to Set LAN Password for user %d", userid);
926 		return -1;
927 	}
928 	if (rsp->ccode > 0) {
929 		lprintf(LOG_ERR, "Set LAN Password for user %d failed: %s",
930 			userid, val2str(rsp->ccode, completion_code_vals));
931 		return -1;
932 	}
933 
934 	/* adjust our session password
935 	 * or we will no longer be able to communicate with BMC
936 	 */
937 	ipmi_intf_session_set_password(intf, (char *)password);
938 	printf("Password %s for user %d\n",
939 	       (password == NULL) ? "cleared" : "set", userid);
940 
941 	return 0;
942 }
943 
944 static int
945 ipmi_set_alert_enable(struct ipmi_intf * intf, uint8_t channel, uint8_t enable)
946 {
947 	struct ipmi_rs * rsp;
948 	struct ipmi_rq req;
949 	uint8_t rqdata[3];
950 
951 	memset(&req, 0, sizeof(req));
952 
953 	/* update non-volatile access */
954 	rqdata[0] = channel;
955 	rqdata[1] = 0x40;
956 
957 	req.msg.netfn = IPMI_NETFN_APP;
958 	req.msg.cmd = 0x41; /* Get Channel Access ??? */
959 	req.msg.data = rqdata;
960 	req.msg.data_len = 2;
961 
962 	rsp = intf->sendrecv(intf, &req);
963 	if (rsp == NULL) {
964 		lprintf(LOG_ERR, "Unable to Get Channel Access for channel %d", channel);
965 		return -1;
966 	}
967 	if (rsp->ccode > 0) {
968 		lprintf(LOG_ERR, "Get Channel Access for channel %d failed: %s",
969 			channel, val2str(rsp->ccode, completion_code_vals));
970 		return -1;
971 	}
972 
973 	/* SAVE TO NVRAM */
974 	memset(rqdata, 0, 3);
975 	rqdata[0] = channel & 0xf;
976 	rqdata[1] = rsp->data[0];
977 	if (enable != 0)
978 		rqdata[1] &= ~0x20;
979 	else
980 		rqdata[1] |= 0x20;
981 	rqdata[1] |= 0x40;
982 	rqdata[2] = 0;
983 
984 	req.msg.cmd = 0x40; /* Set Channel Access ??? */
985 	req.msg.data_len = 3;
986 
987 	rsp = intf->sendrecv(intf, &req);
988 	if (rsp == NULL) {
989 		lprintf(LOG_ERR, "Unable to Set Channel Access for channel %d", channel);
990 		return -1;
991 	}
992 	if (rsp->ccode > 0) {
993 		lprintf(LOG_ERR, "Set Channel Access for channel %d failed: %s",
994 			channel, val2str(rsp->ccode, completion_code_vals));
995 		return -1;
996 	}
997 
998 	/* SAVE TO CURRENT */
999 	rqdata[1] &= 0xc0;
1000 	rqdata[1] |= 0x80;
1001 
1002 	rsp = intf->sendrecv(intf, &req);
1003 	if (rsp == NULL) {
1004 		lprintf(LOG_ERR, "Unable to Set Channel Access for channel %d", channel);
1005 		return -1;
1006 	}
1007 	if (rsp->ccode > 0) {
1008 		lprintf(LOG_ERR, "Set Channel Access for channel %d failed: %s",
1009 			channel, val2str(rsp->ccode, completion_code_vals));
1010 		return -1;
1011 	}
1012 
1013 	return 0;
1014 }
1015 
1016 /* TODO - we already have functions for this elsewere!!! */
1017 static int
1018 ipmi_set_channel_access(struct ipmi_intf * intf, uint8_t channel, uint8_t enable)
1019 {
1020 	struct ipmi_rs * rsp;
1021 	struct ipmi_rq req;
1022 	uint8_t rqdata[3];
1023 	uint8_t byteEnable;
1024 
1025 	memset(&req, 0, sizeof(req));
1026 
1027 	/* RETREIVE VALUE IN NVRAM */
1028 	req.msg.netfn = IPMI_NETFN_APP;
1029 	req.msg.cmd = 0x41;  /* Get Channel Access Command */
1030 	req.msg.data = rqdata;
1031 	req.msg.data_len = 2;
1032 
1033 	memset(rqdata, 0, 2);
1034 	rqdata[0] = channel & 0xf;
1035 	rqdata[1] = 0x40; /* retreive NV */
1036 
1037 	rsp = intf->sendrecv(intf, &req);
1038 	if (rsp == NULL) {
1039 		lprintf(LOG_ERR, "Unable to Get Channel Access for channel %d", channel);
1040 		return -1;
1041 	} else if (rsp->ccode > 0) {
1042 		lprintf(LOG_ERR, "Set Channel Access for channel %d failed: %s",
1043 			channel, val2str(rsp->ccode, completion_code_vals));
1044 		return -1;
1045 	} else {
1046 		byteEnable = *(rsp->data + 0);
1047 	}
1048 
1049 	/* SAVE TO NVRAM */
1050 	memset(&req, 0, sizeof(req));
1051 
1052 	req.msg.netfn = IPMI_NETFN_APP;
1053 	req.msg.cmd = 0x40;   /* Set Channel Access Command */
1054 	req.msg.data = rqdata;
1055 	req.msg.data_len = 3;
1056 
1057 	memset(rqdata, 0, 3);
1058 	rqdata[0] = channel & 0xf;
1059 	rqdata[1] = 0x40 | (byteEnable & 0x38);  /* use previously set values */
1060 	if (enable != 0)
1061 		rqdata[1] |= 0x2; /* set always available if enable is set */
1062 	rqdata[2] = 0x44; 	/* set channel privilege limit to ADMIN */
1063 
1064 	rsp = intf->sendrecv(intf, &req);
1065 	if (rsp == NULL) {
1066 		lprintf(LOG_ERR, "Unable to Set Channel Access for channel %d", channel);
1067 		return -1;
1068 	} else if (rsp->ccode > 0) {
1069 		lprintf(LOG_ERR, "Set Channel Access for channel %d failed: %s",
1070 			channel, val2str(rsp->ccode, completion_code_vals));
1071 		return -1;
1072 	}
1073 
1074 	/* RETREIVE VALUE IN NVRAM */
1075 	req.msg.netfn = IPMI_NETFN_APP;
1076 	req.msg.cmd = 0x41;  /* Get Channel Access Command */
1077 	req.msg.data = rqdata;
1078 	req.msg.data_len = 2;
1079 
1080 	memset(rqdata, 0, 2);
1081 	rqdata[0] = channel & 0xf;
1082 	rqdata[1] = 0x80; /* retreive NV */
1083 
1084 	rsp = intf->sendrecv(intf, &req);
1085 	if (rsp == NULL) {
1086 		lprintf(LOG_ERR, "Unable to Get Channel Access for channel %d", channel);
1087 		return -1;
1088 	} else if (rsp->ccode > 0) {
1089 		lprintf(LOG_ERR, "Set Channel Access for channel %d failed: %s",
1090 			channel, val2str(rsp->ccode, completion_code_vals));
1091 		return -1;
1092 	} else {
1093 		byteEnable = *(rsp->data + 0);
1094 	}
1095 
1096 	/* SAVE TO CURRENT */
1097 	memset(&req, 0, sizeof(req));
1098 
1099 	req.msg.netfn = IPMI_NETFN_APP;
1100 	req.msg.cmd = 0x40;   /* Set Channel Access Command */
1101 	req.msg.data = rqdata;
1102 	req.msg.data_len = 3;
1103 
1104 	memset(rqdata, 0, 3);
1105 	rqdata[0] = channel & 0xf;
1106 	rqdata[1] = 0x80 | (byteEnable & 0x38);  /* use previously set values */
1107 	if (enable != 0)
1108 		rqdata[1] |= 0x2; /* set always available if enable is set */
1109 	rqdata[2] = 0x84; 	/* set channel privilege limit to ADMIN */
1110 
1111 	rsp = intf->sendrecv(intf, &req);
1112 	if (rsp == NULL) {
1113 		lprintf(LOG_ERR, "Unable to Set Channel Access for channel %d", channel);
1114 		return -1;
1115 	} else if (rsp->ccode > 0) {
1116 		lprintf(LOG_ERR, "Set Channel Access for channel %d failed: %s",
1117 			channel, val2str(rsp->ccode, completion_code_vals));
1118 		return -1;
1119 	}
1120 
1121 	/* can't send close session if access off so abort instead */
1122 	if (enable == 0)
1123 		intf->abort = 1;
1124 
1125 	return 0;
1126 }
1127 
1128 /* TODO - we already have functions for this elsewhere!!! */
1129 static int
1130 ipmi_set_user_access(struct ipmi_intf * intf, uint8_t channel, uint8_t userid)
1131 {
1132 	struct ipmi_rs * rsp;
1133 	struct ipmi_rq req;
1134 	uint8_t rqdata[4];
1135 
1136 	memset(rqdata, 0, 4);
1137 	rqdata[0] = 0x90 | (channel & 0xf);
1138 	rqdata[1] = userid & 0x3f;
1139 	rqdata[2] = 0x4;
1140 	rqdata[3] = 0;
1141 
1142 	memset(&req, 0, sizeof(req));
1143 	req.msg.netfn = IPMI_NETFN_APP;
1144 	req.msg.cmd = 0x43;
1145 	req.msg.data = rqdata;
1146 	req.msg.data_len = 4;
1147 
1148 	rsp = intf->sendrecv(intf, &req);
1149 	if (rsp == NULL) {
1150 		lprintf(LOG_ERR, "Unable to Set User Access for channel %d", channel);
1151 		return -1;
1152 	}
1153 	if (rsp->ccode > 0) {
1154 		lprintf(LOG_ERR, "Set User Access for channel %d failed: %s",
1155 			channel, val2str(rsp->ccode, completion_code_vals));
1156 		return -1;
1157 	}
1158 
1159 	return 0;
1160 }
1161 
1162 static int
1163 get_cmdline_macaddr(char * arg, uint8_t * buf)
1164 {
1165 	uint32_t m1, m2, m3, m4, m5, m6;
1166 	if (sscanf(arg, "%02x:%02x:%02x:%02x:%02x:%02x",
1167 		   &m1, &m2, &m3, &m4, &m5, &m6) != 6) {
1168 		lprintf(LOG_ERR, "Invalid MAC address: %s", arg);
1169 		return -1;
1170 	}
1171 	/* TODO - UINT8_MAX check */
1172 	buf[0] = (uint8_t)m1;
1173 	buf[1] = (uint8_t)m2;
1174 	buf[2] = (uint8_t)m3;
1175 	buf[3] = (uint8_t)m4;
1176 	buf[4] = (uint8_t)m5;
1177 	buf[5] = (uint8_t)m6;
1178 	return 0;
1179 }
1180 
1181 
1182 static int
1183 get_cmdline_cipher_suite_priv_data(char * arg, uint8_t * buf)
1184 {
1185 	int i, ret = 0;
1186 
1187 	if (strlen(arg) != 15)
1188 	{
1189 		lprintf(LOG_ERR, "Invalid privilege specification length: %d",
1190 			strlen(arg));
1191 		return -1;
1192 	}
1193 
1194 	/*
1195 	 * The first byte is reserved (0).  The rest of the buffer is setup
1196 	 * so that each nibble holds the maximum privilege level available for
1197 	 * that cipher suite number.  The number of nibbles (15) matches the number
1198 	 * of fixed cipher suite IDs.  This command documentation mentions 16 IDs
1199 	 * but table 22-19 shows that there are only 15 (0-14).
1200 	 *
1201 	 * data 1 - reserved
1202 	 * data 2 - maximum priv level for first (LSN) and second (MSN) ciphers
1203 	 * data 3 - maximum priv level for third (LSN) and fourth (MSN) ciphers
1204 	 * data 9 - maximum priv level for 15th (LSN) cipher.
1205 	 */
1206 	memset(buf, 0, 9);
1207 	for (i = 0; i < 15; ++i)
1208 	{
1209 		unsigned char priv_level = IPMI_SESSION_PRIV_ADMIN;
1210 
1211 		switch (arg[i])
1212 		{
1213 		case 'X':
1214 			priv_level = IPMI_SESSION_PRIV_UNSPECIFIED; /* 0 */
1215 			break;
1216 		case 'c':
1217 			priv_level = IPMI_SESSION_PRIV_CALLBACK;    /* 1 */
1218 			break;
1219 		case 'u':
1220 			priv_level = IPMI_SESSION_PRIV_USER;        /* 2 */
1221 			break;
1222 		case 'o':
1223 			priv_level = IPMI_SESSION_PRIV_OPERATOR;    /* 3 */
1224 			break;
1225 		case 'a':
1226 			priv_level = IPMI_SESSION_PRIV_ADMIN;       /* 4 */
1227 			break;
1228 		case 'O':
1229 			priv_level = IPMI_SESSION_PRIV_OEM;         /* 5 */
1230 			break;
1231 		default:
1232 			lprintf(LOG_ERR, "Invalid privilege specification char: %c",
1233 				arg[i]);
1234 			ret = -1;
1235 			break;
1236 		}
1237 
1238 		if (ret != 0)
1239 			break;
1240 		else
1241 		{
1242 			if ((i + 1) % 2)
1243 			{
1244 				// Odd number cipher suites will be in the LSN
1245 				buf[1 + (i / 2)] += priv_level;
1246 			}
1247 			else
1248 			{
1249 				// Even number cipher suites will be in the MSN
1250 				buf[1 + (i / 2)] += (priv_level << 4);
1251 			}
1252 		}
1253 	}
1254 
1255 	return ret;
1256 }
1257 
1258 
1259 static int
1260 get_cmdline_ipaddr(char * arg, uint8_t * buf)
1261 {
1262 	uint32_t ip1, ip2, ip3, ip4;
1263 	if (sscanf(arg,
1264 				"%" PRIu32 ".%" PRIu32 ".%" PRIu32 ".%" PRIu32,
1265 				&ip1, &ip2, &ip3, &ip4) != 4) {
1266 		lprintf(LOG_ERR, "Invalid IP address: %s", arg);
1267 		return (-1);
1268 	}
1269 	if (ip1 > UINT8_MAX || ip2 > UINT8_MAX
1270 			|| ip3 > UINT8_MAX || ip4 > UINT8_MAX) {
1271 		lprintf(LOG_ERR, "Invalid IP address: %s", arg);
1272 		return (-1);
1273 	}
1274 	buf[0] = (uint8_t)ip1;
1275 	buf[1] = (uint8_t)ip2;
1276 	buf[2] = (uint8_t)ip3;
1277 	buf[3] = (uint8_t)ip4;
1278 	return 0;
1279 }
1280 
1281 static void ipmi_lan_set_usage(void)
1282 {
1283 	lprintf(LOG_NOTICE, "\nusage: lan set <channel> <command> <parameter>\n");
1284 	lprintf(LOG_NOTICE, "LAN set command/parameter options:");
1285 	lprintf(LOG_NOTICE, "  ipaddr <x.x.x.x>               Set channel IP address");
1286 	lprintf(LOG_NOTICE, "  netmask <x.x.x.x>              Set channel IP netmask");
1287 	lprintf(LOG_NOTICE, "  macaddr <x:x:x:x:x:x>          Set channel MAC address");
1288 	lprintf(LOG_NOTICE, "  defgw ipaddr <x.x.x.x>         Set default gateway IP address");
1289 	lprintf(LOG_NOTICE, "  defgw macaddr <x:x:x:x:x:x>    Set default gateway MAC address");
1290 	lprintf(LOG_NOTICE, "  bakgw ipaddr <x.x.x.x>         Set backup gateway IP address");
1291 	lprintf(LOG_NOTICE, "  bakgw macaddr <x:x:x:x:x:x>    Set backup gateway MAC address");
1292 	lprintf(LOG_NOTICE, "  password <password>            Set session password for this channel");
1293 	lprintf(LOG_NOTICE, "  snmp <community string>        Set SNMP public community string");
1294 	lprintf(LOG_NOTICE, "  user                           Enable default user for this channel");
1295 	lprintf(LOG_NOTICE, "  access <on|off>                Enable or disable access to this channel");
1296 	lprintf(LOG_NOTICE, "  alert <on|off>                 Enable or disable PEF alerting for this channel");
1297 	lprintf(LOG_NOTICE, "  arp respond <on|off>           Enable or disable BMC ARP responding");
1298 	lprintf(LOG_NOTICE, "  arp generate <on|off>          Enable or disable BMC gratuitous ARP generation");
1299 	lprintf(LOG_NOTICE, "  arp interval <seconds>         Set gratuitous ARP generation interval");
1300 	lprintf(LOG_NOTICE, "  vlan id <off|<id>>             Disable or enable VLAN and set ID (1-4094)");
1301 	lprintf(LOG_NOTICE, "  vlan priority <priority>       Set vlan priority (0-7)");
1302 	lprintf(LOG_NOTICE, "  auth <level> <type,..>         Set channel authentication types");
1303 	lprintf(LOG_NOTICE, "    level  = CALLBACK, USER, OPERATOR, ADMIN");
1304 	lprintf(LOG_NOTICE, "    type   = NONE, MD2, MD5, PASSWORD, OEM");
1305 	lprintf(LOG_NOTICE, "  ipsrc <source>                 Set IP Address source");
1306 	lprintf(LOG_NOTICE, "    none   = unspecified source");
1307 	lprintf(LOG_NOTICE, "    static = address manually configured to be static");
1308 	lprintf(LOG_NOTICE, "    dhcp   = address obtained by BMC running DHCP");
1309 	lprintf(LOG_NOTICE, "    bios   = address loaded by BIOS or system software");
1310 	lprintf(LOG_NOTICE, "  cipher_privs XXXXXXXXXXXXXXX   Set RMCP+ cipher suite privilege levels");
1311 	lprintf(LOG_NOTICE, "    X = Cipher Suite Unused");
1312 	lprintf(LOG_NOTICE, "    c = CALLBACK");
1313 	lprintf(LOG_NOTICE, "    u = USER");
1314 	lprintf(LOG_NOTICE, "    o = OPERATOR");
1315 	lprintf(LOG_NOTICE, "    a = ADMIN");
1316 	lprintf(LOG_NOTICE, "    O = OEM\n");
1317 }
1318 
1319 static void
1320 ipmi_lan_set_vlan_usage(void)
1321 {
1322 	lprintf(LOG_NOTICE,
1323 		"lan set <channel> vlan id <id>\n"
1324 		"lan set <channel> vlan id off\n"
1325 		"lan set <channel> vlan priority <priority>\n");
1326 }
1327 
1328 /* TODO - formatting, vlan->VLAN */
1329 static int
1330 ipmi_lan_set_vlan_id(struct ipmi_intf * intf,  uint8_t chan, char *string)
1331 {
1332 	uint8_t data[2];
1333 	int rc;
1334 
1335 	if (string == NULL) {
1336 		data[0] = 0;
1337 		data[1] = 0;
1338 	}
1339 	else {
1340 		int id = 0;
1341 		if (str2int(string, &id) != 0) {
1342 			lprintf(LOG_ERR, "Given VLAN ID '%s' is invalid.", string);
1343 			return (-1);
1344 		}
1345 
1346 		if (id < 1 || id > 4094) {
1347 			lprintf(LOG_NOTICE, "vlan id must be between 1 and 4094.");
1348 			return -1;
1349 		}
1350 		else {
1351 			data[0] = (uint8_t)id;
1352 			data[1] = (uint8_t)(id >> 8) | 0x80;
1353 		}
1354 	}
1355 	rc = set_lan_param(intf, chan, IPMI_LANP_VLAN_ID, data, 2);
1356 	return rc;
1357 }
1358 
1359 /* TODO - formatting, vlan->VLAN */
1360 static int
1361 ipmi_lan_set_vlan_priority(struct ipmi_intf * intf,  uint8_t chan, char *string)
1362 {
1363 	uint8_t data;
1364 	int rc;
1365 	int priority = 0;
1366 	if (str2int(string, &priority) != 0) {
1367 		lprintf(LOG_ERR, "Given VLAN priority '%s' is invalid.", string);
1368 		return (-1);
1369 	}
1370 
1371 	if (priority < 0 || priority > 7) {
1372 		lprintf(LOG_NOTICE, "vlan priority must be between 0 and 7.");
1373 		return -1;
1374 	}
1375 	data = (uint8_t)priority;
1376 	rc = set_lan_param(intf, chan, IPMI_LANP_VLAN_PRIORITY, &data, 1);
1377 	return rc;
1378 }
1379 
1380 static int
1381 ipmi_lan_set(struct ipmi_intf * intf, int argc, char ** argv)
1382 {
1383 	uint8_t data[32];
1384 	uint8_t chan;
1385 	int rc = 0;
1386 
1387 	if (argc < 2) {
1388 		ipmi_lan_set_usage();
1389 		return (-1);
1390 	}
1391 
1392 	if (strncmp(argv[0], "help", 4) == 0 ||
1393 	    strncmp(argv[1], "help", 4) == 0) {
1394 		ipmi_lan_set_usage();
1395 		return 0;
1396 	}
1397 
1398 	if (str2uchar(argv[0], &chan) != 0) {
1399 		lprintf(LOG_ERR, "Invalid channel: %s", argv[0]);
1400 		return (-1);
1401 	}
1402 
1403 	/* find type of channel and only accept 802.3 LAN */
1404 	if (!is_lan_channel(intf, chan)) {
1405 		lprintf(LOG_ERR, "Channel %d is not a LAN channel!", chan);
1406 		ipmi_lan_set_usage();
1407 		return -1;
1408 	}
1409 
1410 	memset(&data, 0, sizeof(data));
1411 
1412 	/* set user access */
1413 	if (strncmp(argv[1], "user", 4) == 0) {
1414 		rc = ipmi_set_user_access(intf, chan, 1);
1415 	}
1416 	/* set channel access mode */
1417 	else if (strncmp(argv[1], "access", 6) == 0) {
1418 		if (argc < 3) {
1419 			lprintf(LOG_NOTICE, "lan set access <on|off>");
1420 			return (-1);
1421 		}
1422 		else if (strncmp(argv[2], "help", 4) == 0) {
1423 			lprintf(LOG_NOTICE, "lan set access <on|off>");
1424 			return 0;
1425 		}
1426 		else if (strncmp(argv[2], "on", 2) == 0) {
1427 			rc = ipmi_set_channel_access(intf, chan, 1);
1428 		}
1429 		else if (strncmp(argv[2], "off", 3) == 0) {
1430 			rc = ipmi_set_channel_access(intf, chan, 0);
1431 		}
1432 		else {
1433 			lprintf(LOG_NOTICE, "lan set access <on|off>");
1434 			return (-1);
1435 		}
1436 	}
1437 	/* set ARP control */
1438 	else if (strncmp(argv[1], "arp", 3) == 0) {
1439 		if (argc < 3) {
1440 			lprintf(LOG_NOTICE,
1441 				"lan set <channel> arp respond <on|off>\n"
1442 				"lan set <channel> arp generate <on|off>\n"
1443 				"lan set <channel> arp interval <seconds>\n\n"
1444 				"example: lan set 7 arp gratuitous off\n");
1445 			return (-1);
1446 		}
1447 		else if (strncmp(argv[2], "help", 4) == 0) {
1448 			lprintf(LOG_NOTICE,
1449 				"lan set <channel> arp respond <on|off>\n"
1450 				"lan set <channel> arp generate <on|off>\n"
1451 				"lan set <channel> arp interval <seconds>\n\n"
1452 				"example: lan set 7 arp gratuitous off\n");
1453 			return 0;
1454 		}
1455 		else if (strncmp(argv[2], "interval", 8) == 0) {
1456 			uint8_t interval = 0;
1457 			if (str2uchar(argv[3], &interval) != 0) {
1458 				lprintf(LOG_ERR, "Given ARP interval '%s' is invalid.", argv[3]);
1459 				return (-1);
1460 			}
1461 			rc = lan_set_arp_interval(intf, chan, interval);
1462 		}
1463 		else if (strncmp(argv[2], "generate", 8) == 0) {
1464 			if (argc < 4) {
1465 				lprintf(LOG_NOTICE, "lan set <channel> arp generate <on|off>");
1466 				return (-1);
1467 			}
1468 			else if (strncmp(argv[3], "on", 2) == 0)
1469 				rc = lan_set_arp_generate(intf, chan, 1);
1470 			else if (strncmp(argv[3], "off", 3) == 0)
1471 				rc = lan_set_arp_generate(intf, chan, 0);
1472 			else {
1473 				lprintf(LOG_NOTICE, "lan set <channel> arp generate <on|off>");
1474 				return (-1);
1475 			}
1476 		}
1477 		else if (strncmp(argv[2], "respond", 7) == 0) {
1478 			if (argc < 4) {
1479 				lprintf(LOG_NOTICE, "lan set <channel> arp respond <on|off>");
1480 				return (-1);
1481 			}
1482 			else if (strncmp(argv[3], "on", 2) == 0)
1483 				rc = lan_set_arp_respond(intf, chan, 1);
1484 			else if (strncmp(argv[3], "off", 3) == 0)
1485 				rc = lan_set_arp_respond(intf, chan, 0);
1486 			else {
1487 				lprintf(LOG_NOTICE, "lan set <channel> arp respond <on|off>");
1488 				return (-1);
1489 			}
1490 		}
1491 		else {
1492 			lprintf(LOG_NOTICE,
1493 				"lan set <channel> arp respond <on|off>\n"
1494 				"lan set <channel> arp generate <on|off>\n"
1495 				"lan set <channel> arp interval <seconds>\n");
1496 			return (-1);
1497 		}
1498 	}
1499 	/* set authentication types */
1500 	else if (strncmp(argv[1], "auth", 4) == 0) {
1501 		if (argc < 3) {
1502 			lprintf(LOG_NOTICE,
1503 				"lan set <channel> auth <level> <type,type,...>\n"
1504 				"  level = CALLBACK, USER, OPERATOR, ADMIN\n"
1505 				"  types = NONE, MD2, MD5, PASSWORD, OEM\n"
1506 				"example: lan set 7 auth ADMIN PASSWORD,MD5\n");
1507 			return (-1);
1508 		}
1509 		else if (strncmp(argv[2], "help", 4) == 0) {
1510 			lprintf(LOG_NOTICE,
1511 				"lan set <channel> auth <level> <type,type,...>\n"
1512 				"  level = CALLBACK, USER, OPERATOR, ADMIN\n"
1513 				"  types = NONE, MD2, MD5, PASSWORD, OEM\n"
1514 				"example: lan set 7 auth ADMIN PASSWORD,MD5\n");
1515 			return 0;
1516 		} else {
1517 			rc = ipmi_lan_set_auth(intf, chan, argv[2], argv[3]);
1518 		}
1519 	}
1520 	/* ip address source */
1521 	else if (strncmp(argv[1], "ipsrc", 5) == 0) {
1522 		if (argc < 3) {
1523 			lprintf(LOG_NOTICE,
1524 				"lan set <channel> ipsrc <source>\n"
1525 				"  none   = unspecified\n"
1526 				"  static = static address (manually configured)\n"
1527 				"  dhcp   = address obtained by BMC running DHCP\n"
1528 				"  bios   = address loaded by BIOS or system software\n");
1529 			return (-1);
1530 		}
1531 		else if (strncmp(argv[2], "help", 4) == 0) {
1532 			lprintf(LOG_NOTICE,
1533 				"lan set <channel> ipsrc <source>\n"
1534 				"  none   = unspecified\n"
1535 				"  static = static address (manually configured)\n"
1536 				"  dhcp   = address obtained by BMC running DHCP\n"
1537 				"  bios   = address loaded by BIOS or system software\n");
1538 			return 0;
1539 		}
1540 		else if (strncmp(argv[2], "none", 4) == 0)
1541 			data[0] = 0;
1542 		else if (strncmp(argv[2], "static", 5) == 0)
1543 			data[0] = 1;
1544 		else if (strncmp(argv[2], "dhcp", 4) == 0)
1545 			data[0] = 2;
1546 		else if (strncmp(argv[2], "bios", 4) == 0)
1547 			data[0] = 3;
1548 		else {
1549 			lprintf(LOG_NOTICE,
1550 				"lan set <channel> ipsrc <source>\n"
1551 				"  none   = unspecified\n"
1552 				"  static = static address (manually configured)\n"
1553 				"  dhcp   = address obtained by BMC running DHCP\n"
1554 				"  bios   = address loaded by BIOS or system software\n");
1555 			return -1;
1556 		}
1557 		rc = set_lan_param(intf, chan, IPMI_LANP_IP_ADDR_SRC, data, 1);
1558 	}
1559 	/* session password
1560 	 * not strictly a lan setting, but its used for lan connections */
1561 	else if (strncmp(argv[1], "password", 8) == 0) {
1562 		rc = ipmi_lan_set_password(intf, 1, (uint8_t *)argv[2]);
1563 	}
1564 	/* snmp community string */
1565 	else if (strncmp(argv[1], "snmp", 4) == 0) {
1566 		if (argc < 3) {
1567 			lprintf(LOG_NOTICE, "lan set <channel> snmp <community string>");
1568 			return (-1);
1569 		}
1570 		else if (strncmp(argv[2], "help", 4) == 0) {
1571 			lprintf(LOG_NOTICE, "lan set <channel> snmp <community string>");
1572 			return 0;
1573 		} else {
1574 			memcpy(data, argv[2], __min(strlen(argv[2]), 18));
1575 			printf("Setting LAN %s to %s\n",
1576 			       ipmi_lan_params[IPMI_LANP_SNMP_STRING].desc, data);
1577 			rc = set_lan_param(intf, chan, IPMI_LANP_SNMP_STRING, data, 18);
1578 		}
1579 	}
1580 	/* ip address */
1581 	else if (strncmp(argv[1], "ipaddr", 6) == 0) {
1582 		if(argc != 3)
1583 		{
1584 			ipmi_lan_set_usage();
1585 			return -1;
1586 		}
1587 		rc = get_cmdline_ipaddr(argv[2], data);
1588 		if (rc == 0) {
1589 			printf("Setting LAN %s to %d.%d.%d.%d\n",
1590 				ipmi_lan_params[IPMI_LANP_IP_ADDR].desc,
1591 				data[0], data[1], data[2], data[3]);
1592 			rc = set_lan_param(intf, chan, IPMI_LANP_IP_ADDR, data, 4);
1593 		}
1594 	}
1595 	/* network mask */
1596 	else if (strncmp(argv[1], "netmask", 7) == 0) {
1597 		if(argc != 3)
1598 		{
1599 			ipmi_lan_set_usage();
1600 			return -1;
1601 		}
1602 		rc = get_cmdline_ipaddr(argv[2], data);
1603 		if (rc == 0) {
1604 			printf("Setting LAN %s to %d.%d.%d.%d\n",
1605 		       		ipmi_lan_params[IPMI_LANP_SUBNET_MASK].desc,
1606 		       		data[0], data[1], data[2], data[3]);
1607 			rc = set_lan_param(intf, chan, IPMI_LANP_SUBNET_MASK, data, 4);
1608 		}
1609 	}
1610 	/* mac address */
1611 	else if (strncmp(argv[1], "macaddr", 7) == 0) {
1612 		if(argc != 3)
1613 		{
1614 			ipmi_lan_set_usage();
1615 			return -1;
1616 		}
1617 		rc = get_cmdline_macaddr(argv[2], data);
1618 		if (rc == 0) {
1619 			printf("Setting LAN %s to %02x:%02x:%02x:%02x:%02x:%02x\n",
1620 		       		ipmi_lan_params[IPMI_LANP_MAC_ADDR].desc,
1621 		       		data[0], data[1], data[2], data[3], data[4], data[5]);
1622 			rc = set_lan_param(intf, chan, IPMI_LANP_MAC_ADDR, data, 6);
1623 		}
1624 	}
1625 	/* default gateway settings */
1626 	else if (strncmp(argv[1], "defgw", 5) == 0) {
1627 		if (argc < 4) {
1628 			lprintf(LOG_NOTICE, "LAN set default gateway Commands: ipaddr, macaddr");
1629 			return (-1);
1630 		}
1631 		else if (strncmp(argv[2], "help", 4) == 0) {
1632 			lprintf(LOG_NOTICE, "LAN set default gateway Commands: ipaddr, macaddr");
1633 			return 0;
1634 		}
1635 		else if ((strncmp(argv[2], "ipaddr", 5) == 0) &&
1636 			 (get_cmdline_ipaddr(argv[3], data) == 0)) {
1637 			printf("Setting LAN %s to %d.%d.%d.%d\n",
1638 			       ipmi_lan_params[IPMI_LANP_DEF_GATEWAY_IP].desc,
1639 			       data[0], data[1], data[2], data[3]);
1640 			rc = set_lan_param(intf, chan, IPMI_LANP_DEF_GATEWAY_IP, data, 4);
1641 		}
1642 		else if ((strncmp(argv[2], "macaddr", 7) == 0) &&
1643 			 (get_cmdline_macaddr(argv[3], data) == 0)) {
1644 			printf("Setting LAN %s to %02x:%02x:%02x:%02x:%02x:%02x\n",
1645 			       ipmi_lan_params[IPMI_LANP_DEF_GATEWAY_MAC].desc,
1646 			       data[0], data[1], data[2], data[3], data[4], data[5]);
1647 			rc = set_lan_param(intf, chan, IPMI_LANP_DEF_GATEWAY_MAC, data, 6);
1648 		}
1649 		else {
1650 			ipmi_lan_set_usage();
1651 			return -1;
1652 		}
1653 	}
1654 	/* backup gateway settings */
1655 	else if (strncmp(argv[1], "bakgw", 5) == 0) {
1656 		if (argc < 4) {
1657 			lprintf(LOG_NOTICE, "LAN set backup gateway commands: ipaddr, macaddr");
1658 			return (-1);
1659 		}
1660 		else if (strncmp(argv[2], "help", 4) == 0) {
1661 			lprintf(LOG_NOTICE, "LAN set backup gateway commands: ipaddr, macaddr");
1662 			return 0;
1663 		}
1664 		else if ((strncmp(argv[2], "ipaddr", 5) == 0) &&
1665 			 (get_cmdline_ipaddr(argv[3], data) == 0)) {
1666 			printf("Setting LAN %s to %d.%d.%d.%d\n",
1667 			       ipmi_lan_params[IPMI_LANP_BAK_GATEWAY_IP].desc,
1668 			       data[0], data[1], data[2], data[3]);
1669 			rc = set_lan_param(intf, chan, IPMI_LANP_BAK_GATEWAY_IP, data, 4);
1670 		}
1671 		else if ((strncmp(argv[2], "macaddr", 7) == 0) &&
1672 			 (get_cmdline_macaddr(argv[3], data) == 0)) {
1673 			printf("Setting LAN %s to %02x:%02x:%02x:%02x:%02x:%02x\n",
1674 			       ipmi_lan_params[IPMI_LANP_BAK_GATEWAY_MAC].desc,
1675 			       data[0], data[1], data[2], data[3], data[4], data[5]);
1676 			rc = set_lan_param(intf, chan, IPMI_LANP_BAK_GATEWAY_MAC, data, 6);
1677 		}
1678 		else {
1679 			ipmi_lan_set_usage();
1680 			return -1;
1681 		}
1682 	}
1683 	else if (strncasecmp(argv[1], "vlan", 4) == 0) {
1684 		if (argc < 4) {
1685 			ipmi_lan_set_vlan_usage();
1686 			return (-1);
1687 		}
1688 		else if (strncmp(argv[2], "help", 4) == 0) {
1689 			ipmi_lan_set_vlan_usage();
1690 			return 0;
1691 		}
1692 		else if (strncasecmp(argv[2], "id", 2) == 0) {
1693 			if (strncasecmp(argv[3], "off", 3) == 0) {
1694 				ipmi_lan_set_vlan_id(intf, chan, NULL);
1695 			}
1696 			else {
1697 				ipmi_lan_set_vlan_id(intf, chan, argv[3]);
1698 			}
1699 		}
1700 		else if (strncasecmp(argv[2], "priority", 8) == 0) {
1701 			ipmi_lan_set_vlan_priority(intf, chan, argv[3]);
1702 		}
1703 		else {
1704 			ipmi_lan_set_vlan_usage();
1705 			return (-1);
1706 		}
1707 	}
1708 	/* set PEF alerting on or off */
1709 	else if (strncasecmp(argv[1], "alert", 5) == 0) {
1710 		if (argc < 3) {
1711 			lprintf(LOG_NOTICE, "LAN set alert must be 'on' or 'off'");
1712 			return (-1);
1713 		}
1714 		else if (strncasecmp(argv[2], "on", 2) == 0 ||
1715 			 strncasecmp(argv[2], "enable", 6) == 0) {
1716 			printf("Enabling PEF alerts for LAN channel %d\n", chan);
1717 			rc = ipmi_set_alert_enable(intf, chan, 1);
1718 		}
1719 		else if (strncasecmp(argv[2], "off", 3) == 0 ||
1720 			 strncasecmp(argv[2], "disable", 7) == 0) {
1721 			printf("Disabling PEF alerts for LAN channel %d\n", chan);
1722 			rc = ipmi_set_alert_enable(intf, chan, 0);
1723 		}
1724 		else {
1725 			lprintf(LOG_NOTICE, "LAN set alert must be 'on' or 'off'");
1726 			return 0;
1727 		}
1728 	}
1729 	/* RMCP+ cipher suite privilege levels */
1730 	else if (strncmp(argv[1], "cipher_privs", 12) == 0)
1731 	{
1732 		if (argc != 3) {
1733 			lprintf(LOG_NOTICE, "lan set <channel> cipher_privs XXXXXXXXXXXXXXX");
1734 			lprintf(LOG_NOTICE, "    X = Cipher Suite Unused");
1735 			lprintf(LOG_NOTICE, "    c = CALLBACK");
1736 			lprintf(LOG_NOTICE, "    u = USER");
1737 			lprintf(LOG_NOTICE, "    o = OPERATOR");
1738 			lprintf(LOG_NOTICE, "    a = ADMIN");
1739 			lprintf(LOG_NOTICE, "    O = OEM\n");
1740 			return (-1);
1741 		}
1742 		else if ((strncmp(argv[2], "help", 4) == 0) ||
1743 		    get_cmdline_cipher_suite_priv_data(argv[2], data))
1744 		{
1745 			lprintf(LOG_NOTICE, "lan set <channel> cipher_privs XXXXXXXXXXXXXXX");
1746 			lprintf(LOG_NOTICE, "    X = Cipher Suite Unused");
1747 			lprintf(LOG_NOTICE, "    c = CALLBACK");
1748 			lprintf(LOG_NOTICE, "    u = USER");
1749 			lprintf(LOG_NOTICE, "    o = OPERATOR");
1750 			lprintf(LOG_NOTICE, "    a = ADMIN");
1751 			lprintf(LOG_NOTICE, "    O = OEM\n");
1752 			return 0;
1753 		}
1754 		else
1755 		{
1756 			rc = set_lan_param(intf, chan, IPMI_LANP_RMCP_PRIV_LEVELS, data, 9);
1757 		}
1758 	}
1759 	else {
1760 		ipmi_lan_set_usage();
1761 		return (-1);
1762 	}
1763 
1764 	return rc;
1765 }
1766 
1767 
1768 static int
1769 is_alert_destination(struct ipmi_intf * intf, uint8_t channel, uint8_t alert)
1770 {
1771 	struct lan_param * p;
1772 
1773 	p = get_lan_param(intf, channel, IPMI_LANP_NUM_DEST);
1774 	if (p == NULL)
1775 		return 0;
1776 	if (p->data == NULL)
1777 		return 0;
1778 
1779 	if (alert <= (p->data[0] & 0xf))
1780 		return 1;
1781 	else
1782 		return 0;
1783 }
1784 
1785 static int
1786 ipmi_lan_alert_print(struct ipmi_intf * intf, uint8_t channel, uint8_t alert)
1787 {
1788 # define PTYPE_LEN	4
1789 # define PADDR_LEN	13
1790 	struct lan_param *lp_ptr = NULL;
1791 	int isack = 0;
1792 	uint8_t ptype[PTYPE_LEN];
1793 	uint8_t paddr[PADDR_LEN];
1794 
1795 	lp_ptr = get_lan_param_select(intf, channel, IPMI_LANP_DEST_TYPE, alert);
1796 	if (lp_ptr == NULL || lp_ptr->data == NULL
1797 			|| lp_ptr->data_len < PTYPE_LEN) {
1798 		return (-1);
1799 	}
1800 	memcpy(ptype, lp_ptr->data, PTYPE_LEN);
1801 
1802 	lp_ptr = get_lan_param_select(intf, channel, IPMI_LANP_DEST_ADDR, alert);
1803 	if (lp_ptr == NULL || lp_ptr->data == NULL
1804 			|| lp_ptr->data_len < PADDR_LEN) {
1805 		return (-1);
1806 	}
1807 	memcpy(paddr, lp_ptr->data, PADDR_LEN);
1808 
1809 	printf("%-24s: %d\n", "Alert Destination",
1810 			ptype[0]);
1811 
1812 	if (ptype[1] & 0x80) {
1813 		isack = 1;
1814 	}
1815 	printf("%-24s: %s\n", "Alert Acknowledge",
1816 			isack ? "Acknowledged" : "Unacknowledged");
1817 
1818 	printf("%-24s: ", "Destination Type");
1819 	switch (ptype[1] & 0x7) {
1820 	case 0:
1821 		printf("PET Trap\n");
1822 		break;
1823 	case 6:
1824 		printf("OEM 1\n");
1825 		break;
1826 	case 7:
1827 		printf("OEM 2\n");
1828 		break;
1829 	default:
1830 		printf("Unknown\n");
1831 		break;
1832 	}
1833 
1834 	printf("%-24s: %d\n",
1835 			isack ? "Acknowledge Timeout" : "Retry Interval",
1836 			ptype[2]);
1837 
1838 	printf("%-24s: %d\n", "Number of Retries",
1839 			ptype[3] & 0x7);
1840 
1841 	if ((paddr[1] & 0xf0) != 0) {
1842 		/* unknown address format */
1843 		printf("\n");
1844 		return 0;
1845 	}
1846 
1847 	printf("%-24s: %s\n", "Alert Gateway",
1848 			(paddr[2] & 1) ? "Backup" : "Default");
1849 
1850 	printf("%-24s: %d.%d.%d.%d\n", "Alert IP Address",
1851 			paddr[3], paddr[4], paddr[5], paddr[6]);
1852 
1853 	printf("%-24s: %02x:%02x:%02x:%02x:%02x:%02x\n", "Alert MAC Address",
1854 			paddr[7], paddr[8], paddr[9],
1855 			paddr[10], paddr[11], paddr[12]);
1856 
1857 	printf("\n");
1858 	return 0;
1859 }
1860 
1861 static int
1862 ipmi_lan_alert_print_all(struct ipmi_intf * intf, uint8_t channel)
1863 {
1864 	int j, ndest;
1865 	struct lan_param * p;
1866 
1867 	p = get_lan_param(intf, channel, IPMI_LANP_NUM_DEST);
1868 	if (p == NULL)
1869 		return -1;
1870 	if (p->data == NULL)
1871 		return -1;
1872 	ndest = p->data[0] & 0xf;
1873 
1874 	for (j=0; j<=ndest; j++) {
1875 		ipmi_lan_alert_print(intf, channel, j);
1876 	}
1877 
1878 	return 0;
1879 }
1880 
1881 static void
1882 ipmi_lan_alert_print_usage(void)
1883 {
1884 	lprintf(LOG_NOTICE, "\nusage: lan alert print [channel number] [alert destination]\n");
1885 	lprintf(LOG_NOTICE, "Default will print all alerts for the first found LAN channel");
1886 }
1887 
1888 static void
1889 ipmi_lan_alert_set_usage(void)
1890 {
1891 	lprintf(LOG_NOTICE, "\nusage: lan alert set <channel number> <alert destination> <command> <parameter>\n");
1892 	lprintf(LOG_NOTICE, "    Command/parameter options:\n");
1893 	lprintf(LOG_NOTICE, "    ipaddr <x.x.x.x>               Set alert IP address");
1894 	lprintf(LOG_NOTICE, "    macaddr <x:x:x:x:x:x>          Set alert MAC address");
1895 	lprintf(LOG_NOTICE, "    gateway <default|backup>       Set channel gateway to use for alerts");
1896 	lprintf(LOG_NOTICE, "    ack <on|off>                   Set Alert Acknowledge on or off");
1897 	lprintf(LOG_NOTICE, "    type <pet|oem1|oem2>           Set destination type as PET or OEM");
1898 	lprintf(LOG_NOTICE, "    time <seconds>                 Set ack timeout or unack retry interval");
1899 	lprintf(LOG_NOTICE, "    retry <number>                 Set number of alert retries");
1900 	lprintf(LOG_NOTICE, "");
1901 }
1902 
1903 static int
1904 ipmi_lan_alert_set(struct ipmi_intf * intf, uint8_t chan, uint8_t alert,
1905 		   int argc, char ** argv)
1906 {
1907 	struct lan_param * p;
1908 	uint8_t data[32], temp[32];
1909 	int rc = 0;
1910 
1911 	if (argc < 2) {
1912 		ipmi_lan_alert_set_usage();
1913 		return (-1);
1914 	}
1915 
1916 	if (strncmp(argv[0], "help", 4) == 0 ||
1917 	    strncmp(argv[1], "help", 4) == 0) {
1918 		ipmi_lan_alert_set_usage();
1919 		return 0;
1920 	}
1921 
1922 	memset(data, 0, sizeof(data));
1923 	memset(temp, 0, sizeof(temp));
1924 
1925 	/* alert destination ip address */
1926 	if (strncasecmp(argv[0], "ipaddr", 6) == 0 &&
1927 	    (get_cmdline_ipaddr(argv[1], temp) == 0)) {
1928 		/* get current parameter */
1929 		p = get_lan_param_select(intf, chan, IPMI_LANP_DEST_ADDR, alert);
1930 		if (p == NULL) {
1931 			return (-1);
1932 		}
1933 		memcpy(data, p->data, p->data_len);
1934 		/* set new ipaddr */
1935 		memcpy(data+3, temp, 4);
1936 		printf("Setting LAN Alert %d IP Address to %d.%d.%d.%d\n", alert,
1937 		       data[3], data[4], data[5], data[6]);
1938 		rc = set_lan_param_nowait(intf, chan, IPMI_LANP_DEST_ADDR, data, p->data_len);
1939 	}
1940 	/* alert destination mac address */
1941 	else if (strncasecmp(argv[0], "macaddr", 7) == 0 &&
1942 		 (get_cmdline_macaddr(argv[1], temp) == 0)) {
1943 		/* get current parameter */
1944 		p = get_lan_param_select(intf, chan, IPMI_LANP_DEST_ADDR, alert);
1945 		if (p == NULL) {
1946 			return (-1);
1947 		}
1948 		memcpy(data, p->data, p->data_len);
1949 		/* set new macaddr */
1950 		memcpy(data+7, temp, 6);
1951 		printf("Setting LAN Alert %d MAC Address to "
1952 		       "%02x:%02x:%02x:%02x:%02x:%02x\n", alert,
1953 		       data[7], data[8], data[9], data[10], data[11], data[12]);
1954 		rc = set_lan_param_nowait(intf, chan, IPMI_LANP_DEST_ADDR, data, p->data_len);
1955 	}
1956 	/* alert destination gateway selector */
1957 	else if (strncasecmp(argv[0], "gateway", 7) == 0) {
1958 		/* get current parameter */
1959 		p = get_lan_param_select(intf, chan, IPMI_LANP_DEST_ADDR, alert);
1960 		if (p == NULL) {
1961 			return (-1);
1962 		}
1963 		memcpy(data, p->data, p->data_len);
1964 
1965 		if (strncasecmp(argv[1], "def", 3) == 0 ||
1966 		    strncasecmp(argv[1], "default", 7) == 0) {
1967 			printf("Setting LAN Alert %d to use Default Gateway\n", alert);
1968 			data[2] = 0;
1969 		}
1970 		else if (strncasecmp(argv[1], "bak", 3) == 0 ||
1971 			 strncasecmp(argv[1], "backup", 6) == 0) {
1972 			printf("Setting LAN Alert %d to use Backup Gateway\n", alert);
1973 			data[2] = 1;
1974 		}
1975 		else {
1976 			ipmi_lan_alert_set_usage();
1977 			return -1;
1978 		}
1979 
1980 		rc = set_lan_param_nowait(intf, chan, IPMI_LANP_DEST_ADDR, data, p->data_len);
1981 	}
1982 	/* alert acknowledgement */
1983 	else if (strncasecmp(argv[0], "ack", 3) == 0) {
1984 		/* get current parameter */
1985 		p = get_lan_param_select(intf, chan, IPMI_LANP_DEST_TYPE, alert);
1986 		if (p == NULL) {
1987 			return (-1);
1988 		}
1989 		memcpy(data, p->data, p->data_len);
1990 
1991 		if (strncasecmp(argv[1], "on", 2) == 0 ||
1992 		    strncasecmp(argv[1], "yes", 3) == 0) {
1993 			printf("Setting LAN Alert %d to Acknowledged\n", alert);
1994 			data[1] |= 0x80;
1995 		}
1996 		else if (strncasecmp(argv[1], "off", 3) == 0 ||
1997 			 strncasecmp(argv[1], "no", 2) == 0) {
1998 			printf("Setting LAN Alert %d to Unacknowledged\n", alert);
1999 			data[1] &= ~0x80;
2000 		}
2001 		else {
2002 			ipmi_lan_alert_set_usage();
2003 			return -1;
2004 		}
2005 		rc = set_lan_param_nowait(intf, chan, IPMI_LANP_DEST_TYPE, data, p->data_len);
2006 	}
2007 	/* alert destination type */
2008 	else if (strncasecmp(argv[0], "type", 4) == 0) {
2009 		/* get current parameter */
2010 		p = get_lan_param_select(intf, chan, IPMI_LANP_DEST_TYPE, alert);
2011 		if (p == NULL) {
2012 			return (-1);
2013 		}
2014 		memcpy(data, p->data, p->data_len);
2015 
2016 		if (strncasecmp(argv[1], "pet", 3) == 0) {
2017 			printf("Setting LAN Alert %d destination to PET Trap\n", alert);
2018 			data[1] &= ~0x07;
2019 		}
2020 		else if (strncasecmp(argv[1], "oem1", 4) == 0) {
2021 			printf("Setting LAN Alert %d destination to OEM 1\n", alert);
2022 			data[1] &= ~0x07;
2023 			data[1] |= 0x06;
2024 		}
2025 		else if (strncasecmp(argv[1], "oem2", 4) == 0) {
2026 			printf("Setting LAN Alert %d destination to OEM 2\n", alert);
2027 			data[1] |= 0x07;
2028 		}
2029 		else {
2030 			ipmi_lan_alert_set_usage();
2031 			return -1;
2032 		}
2033 		rc = set_lan_param_nowait(intf, chan, IPMI_LANP_DEST_TYPE, data, p->data_len);
2034 	}
2035 	/* alert acknowledge timeout or retry interval */
2036 	else if (strncasecmp(argv[0], "time", 4) == 0) {
2037 		/* get current parameter */
2038 		p = get_lan_param_select(intf, chan, IPMI_LANP_DEST_TYPE, alert);
2039 		if (p == NULL) {
2040 			return (-1);
2041 		}
2042 		memcpy(data, p->data, p->data_len);
2043 
2044 		if (str2uchar(argv[1], &data[2]) != 0) {
2045 			lprintf(LOG_ERR, "Invalid time: %s", argv[1]);
2046 			return (-1);
2047 		}
2048 		printf("Setting LAN Alert %d timeout/retry to %d seconds\n", alert, data[2]);
2049 		rc = set_lan_param_nowait(intf, chan, IPMI_LANP_DEST_TYPE, data, p->data_len);
2050 	}
2051 	/* number of retries */
2052 	else if (strncasecmp(argv[0], "retry", 5) == 0) {
2053 		/* get current parameter */
2054 		p = get_lan_param_select(intf, chan, IPMI_LANP_DEST_TYPE, alert);
2055 		if (p == NULL) {
2056 			return (-1);
2057 		}
2058 		memcpy(data, p->data, p->data_len);
2059 
2060 		if (str2uchar(argv[1], &data[3]) != 0) {
2061 			lprintf(LOG_ERR, "Invalid retry: %s", argv[1]);
2062 			return (-1);
2063 		}
2064 		data[3] = data[3] & 0x7;
2065 		printf("Setting LAN Alert %d number of retries to %d\n", alert, data[3]);
2066 		rc = set_lan_param_nowait(intf, chan, IPMI_LANP_DEST_TYPE, data, p->data_len);
2067 	}
2068 	else {
2069 		ipmi_lan_alert_set_usage();
2070 		return -1;
2071 	}
2072 
2073 	return rc;
2074 }
2075 
2076 static int
2077 ipmi_lan_alert(struct ipmi_intf * intf, int argc, char ** argv)
2078 {
2079 	uint8_t alert;
2080 	uint8_t channel = 1;
2081 
2082 	if (argc < 1) {
2083 		ipmi_lan_alert_print_usage();
2084 		ipmi_lan_alert_set_usage();
2085 		return (-1);
2086 	}
2087 	else if (strncasecmp(argv[0], "help", 4) == 0) {
2088 		ipmi_lan_alert_print_usage();
2089 		ipmi_lan_alert_set_usage();
2090 		return 0;
2091 	}
2092 
2093 	/* alert print [channel] [alert] */
2094 	if (strncasecmp(argv[0], "print", 5) == 0) {
2095 		if (argc < 2) {
2096 			channel = find_lan_channel(intf, 1);
2097 			if (!is_lan_channel(intf, channel)) {
2098 				lprintf(LOG_ERR, "Channel %d is not a LAN channel", channel);
2099 				return -1;
2100 			}
2101 			return ipmi_lan_alert_print_all(intf, channel);
2102 		}
2103 
2104 		if (strncasecmp(argv[1], "help", 4) == 0) {
2105 			ipmi_lan_alert_print_usage();
2106 			return 0;
2107 		}
2108 
2109 		if (str2uchar(argv[1], &channel) != 0) {
2110 			lprintf(LOG_ERR, "Invalid channel: %s", argv[1]);
2111 			return (-1);
2112 		}
2113 		if (!is_lan_channel(intf, channel)) {
2114 			lprintf(LOG_ERR, "Channel %d is not a LAN channel", channel);
2115 			return -1;
2116 		}
2117 
2118 		if (argc < 3)
2119 			return ipmi_lan_alert_print_all(intf, channel);
2120 
2121 		if (str2uchar(argv[2], &alert) != 0) {
2122 			lprintf(LOG_ERR, "Invalid alert: %s", argv[2]);
2123 			return (-1);
2124 		}
2125 		if (is_alert_destination(intf, channel, alert) == 0) {
2126 			lprintf(LOG_ERR, "Alert %d is not a valid destination", alert);
2127 			return -1;
2128 		}
2129 		return ipmi_lan_alert_print(intf, channel, alert);
2130 	}
2131 
2132 	/* alert set <channel> <alert> [option] */
2133 	if (strncasecmp(argv[0], "set", 3) == 0) {
2134 		if (argc < 5) {
2135 			ipmi_lan_alert_set_usage();
2136 			return (-1);
2137 		}
2138 		else if (strncasecmp(argv[1], "help", 4) == 0) {
2139 			ipmi_lan_alert_set_usage();
2140 			return 0;
2141 		}
2142 
2143 		if (str2uchar(argv[1], &channel) != 0) {
2144 			lprintf(LOG_ERR, "Invalid channel: %s", argv[1]);
2145 			return (-1);
2146 		}
2147 		if (!is_lan_channel(intf, channel)) {
2148 			lprintf(LOG_ERR, "Channel %d is not a LAN channel", channel);
2149 			return -1;
2150 		}
2151 
2152 		if (str2uchar(argv[2], &alert) != 0) {
2153 			lprintf(LOG_ERR, "Invalid alert: %s", argv[2]);
2154 			return (-1);
2155 		}
2156 		if (is_alert_destination(intf, channel, alert) == 0) {
2157 			lprintf(LOG_ERR, "Alert %d is not a valid destination", alert);
2158 			return -1;
2159 		}
2160 
2161 		return ipmi_lan_alert_set(intf, channel, alert, argc-3, &(argv[3]));
2162 	}
2163 
2164 	return 0;
2165 }
2166 
2167 
2168 static int
2169 ipmi_lan_stats_get(struct ipmi_intf * intf, uint8_t chan)
2170 {
2171 	int rc = 0;
2172 	struct ipmi_rs * rsp;
2173 	struct ipmi_rq req;
2174 	uint8_t msg_data[2];
2175 	uint16_t statsTemp;
2176 
2177 	if (!is_lan_channel(intf, chan)) {
2178 		lprintf(LOG_ERR, "Channel %d is not a LAN channel", chan);
2179 		return -1;
2180 	}
2181 
2182 	/* From here, we are ready to get the stats */
2183 
2184 	msg_data[0] = chan;
2185 	msg_data[1] = 0;   /* Don't clear */
2186 
2187 	memset(&req, 0, sizeof(req));
2188 	req.msg.netfn    = IPMI_NETFN_TRANSPORT;
2189 	req.msg.cmd      = IPMI_LAN_GET_STAT;
2190 	req.msg.data     = msg_data;
2191 	req.msg.data_len = 2;
2192 
2193 	rsp = intf->sendrecv(intf, &req);
2194 	if (rsp == NULL) {
2195 		lprintf(LOG_ERR, "Get LAN Stats command failed");
2196 		return (-1);
2197 	}
2198 
2199 	if (rsp->ccode > 0) {
2200 		lprintf(LOG_ERR, "Get LAN Stats command failed: %s",
2201 			val2str(rsp->ccode, completion_code_vals));
2202 		return (-1);
2203 	}
2204 
2205 	if (verbose > 1) {
2206 		uint8_t counter;
2207 		printf("--- Rx Stats ---\n");
2208 		for (counter=0; counter<18; counter+=2) {
2209 			printf("%02X", *(rsp->data + counter));
2210 			printf(" %02X - ", *(rsp->data + counter+1));
2211 		}
2212 		printf("\n");
2213 	}
2214 
2215 	statsTemp = ((*(rsp->data + 0)) << 8) | (*(rsp->data + 1));
2216 	printf("IP Rx Packet              : %d\n", statsTemp);
2217 
2218 	statsTemp = ((*(rsp->data + 2)) << 8) | (*(rsp->data + 3));
2219 	printf("IP Rx Header Errors       : %u\n", statsTemp);
2220 
2221 	statsTemp = ((*(rsp->data + 4)) << 8) | (*(rsp->data + 5));
2222 	printf("IP Rx Address Errors      : %u\n", statsTemp);
2223 
2224 	statsTemp = ((*(rsp->data + 6)) << 8) | (*(rsp->data + 7));
2225 	printf("IP Rx Fragmented          : %u\n", statsTemp);
2226 
2227 	statsTemp = ((*(rsp->data + 8)) << 8) | (*(rsp->data + 9));
2228 	printf("IP Tx Packet              : %u\n", statsTemp);
2229 
2230 	statsTemp = ((*(rsp->data +10)) << 8) | (*(rsp->data +11));
2231 	printf("UDP Rx Packet             : %u\n", statsTemp);
2232 
2233 	statsTemp = ((*(rsp->data + 12)) << 8) | (*(rsp->data + 13));
2234 	printf("RMCP Rx Valid             : %u\n", statsTemp);
2235 
2236 	statsTemp = ((*(rsp->data + 14)) << 8) | (*(rsp->data + 15));
2237 	printf("UDP Proxy Packet Received : %u\n", statsTemp);
2238 
2239 	statsTemp = ((*(rsp->data + 16)) << 8) | (*(rsp->data + 17));
2240 	printf("UDP Proxy Packet Dropped  : %u\n", statsTemp);
2241 
2242 	return rc;
2243 }
2244 
2245 
2246 static int
2247 ipmi_lan_stats_clear(struct ipmi_intf * intf, uint8_t chan)
2248 {
2249 	int rc = 0;
2250 	struct ipmi_rs * rsp;
2251 	struct ipmi_rq req;
2252 	uint8_t msg_data[2];
2253 
2254 	if (!is_lan_channel(intf, chan)) {
2255 		lprintf(LOG_ERR, "Channel %d is not a LAN channel", chan);
2256 		return -1;
2257 	}
2258 
2259 	/* From here, we are ready to get the stats */
2260 	msg_data[0] = chan;
2261 	msg_data[1] = 1;   /* Clear */
2262 
2263 	memset(&req, 0, sizeof(req));
2264 	req.msg.netfn    = IPMI_NETFN_TRANSPORT;
2265 	req.msg.cmd      = IPMI_LAN_GET_STAT;
2266 	req.msg.data     = msg_data;
2267 	req.msg.data_len = 2;
2268 
2269 	rsp = intf->sendrecv(intf, &req);
2270 	if (rsp == NULL) {
2271 		lprintf(LOG_INFO, "Get LAN Stats command failed");
2272 		return (-1);
2273 	}
2274 
2275 	if (rsp->ccode > 0) {
2276 		lprintf(LOG_INFO, "Get LAN Stats command failed: %s",
2277 			val2str(rsp->ccode, completion_code_vals));
2278 		return (-1);
2279 	}
2280 
2281 	return rc;
2282 }
2283 
2284 
2285 /*
2286  * print_lan_usage
2287  */
2288 static void
2289 print_lan_usage(void)
2290 {
2291 	lprintf(LOG_NOTICE, "LAN Commands:");
2292 	lprintf(LOG_NOTICE, "		   print [<channel number>]");
2293 	lprintf(LOG_NOTICE, "		   set <channel number> <command> <parameter>");
2294 	lprintf(LOG_NOTICE, "		   alert print <channel number> <alert destination>");
2295 	lprintf(LOG_NOTICE, "		   alert set <channel number> <alert destination> <command> <parameter>");
2296 	lprintf(LOG_NOTICE, "		   stats get [<channel number>]");
2297 	lprintf(LOG_NOTICE, "		   stats clear [<channel number>]");
2298 }
2299 
2300 
2301 int
2302 ipmi_lanp_main(struct ipmi_intf * intf, int argc, char ** argv)
2303 {
2304 	int rc = 0;
2305 	uint8_t chan = 0;
2306 
2307 	if (argc == 0) {
2308 		print_lan_usage();
2309 		return (-1);
2310 	} else if (strncmp(argv[0], "help", 4) == 0) {
2311 		print_lan_usage();
2312 		return 0;
2313 	}
2314 
2315 	chan = find_lan_channel(intf, 1);
2316 
2317 	if (strncmp(argv[0], "printconf", 9) == 0 ||
2318 			strncmp(argv[0], "print", 5) == 0)
2319 	{
2320 		if (argc > 2) {
2321 			print_lan_usage();
2322 			return (-1);
2323 		} else if (argc == 2) {
2324 			if (str2uchar(argv[1], &chan) != 0) {
2325 				lprintf(LOG_ERR, "Invalid channel: %s", argv[1]);
2326 				return (-1);
2327 			}
2328 		}
2329 		if (!is_lan_channel(intf, chan)) {
2330 			lprintf(LOG_ERR, "Invalid channel: %d", chan);
2331 			return (-1);
2332 		}
2333 		rc = ipmi_lan_print(intf, chan);
2334 	} else if (strncmp(argv[0], "set", 3) == 0) {
2335 		rc = ipmi_lan_set(intf, argc-1, &(argv[1]));
2336 	} else if (strncmp(argv[0], "alert", 5) == 0) {
2337 		rc = ipmi_lan_alert(intf, argc-1, &(argv[1]));
2338 	} else if (strncmp(argv[0], "stats", 5) == 0) {
2339 		if (argc < 2) {
2340 			print_lan_usage();
2341 			return (-1);
2342 		} else if (argc == 3) {
2343 			if (str2uchar(argv[2], &chan) != 0) {
2344 				lprintf(LOG_ERR, "Invalid channel: %s", argv[2]);
2345 				return (-1);
2346 			}
2347 		}
2348 		if (!is_lan_channel(intf, chan)) {
2349 			lprintf(LOG_ERR, "Invalid channel: %d", chan);
2350 			return (-1);
2351 		}
2352 		if (strncmp(argv[1], "get", 3) == 0) {
2353 			rc = ipmi_lan_stats_get(intf, chan);
2354 		} else if (strncmp(argv[1], "clear", 5) == 0) {
2355 			rc = ipmi_lan_stats_clear(intf, chan);
2356 		} else {
2357 			print_lan_usage();
2358 			return (-1);
2359 		}
2360 	} else {
2361 		lprintf(LOG_NOTICE, "Invalid LAN command: %s", argv[0]);
2362 		return (-1);
2363 	}
2364 	return rc;
2365 }
2366