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