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 #define /* glibc 2.19 and earlier */ _BSD_SOURCE || \
33 	/* Since glibc 2.20 */_DEFAULT_SOURCE || \
34 	_XOPEN_SOURCE >= 500 || \
35 	_XOPEN_SOURCE && _XOPEN_SOURCE_EXTENDED || \
36 	/* Since glibc 2.10: */ _POSIX_C_SOURCE >= 200112L \
37 
38 #include <sys/types.h>
39 #include <sys/stat.h>
40 #include <sys/ioctl.h>  /* For TIOCNOTTY */
41 
42 #include <stdlib.h>
43 #include <stdint.h>
44 #include <stdio.h>
45 #include <inttypes.h>
46 #include <signal.h>
47 #include <string.h>
48 #include <strings.h>
49 #include <unistd.h>
50 #include <fcntl.h>
51 #include <errno.h>
52 #include <assert.h>
53 #include <ctype.h>
54 
55 #if HAVE_CONFIG_H
56 # include <config.h>
57 #endif
58 
59 #ifdef HAVE_PATHS_H
60 # include <paths.h>
61 #else
62 # define _PATH_VARRUN "/var/run/"
63 #endif
64 
65 #include <ipmitool/ipmi.h>
66 #include <ipmitool/ipmi_intf.h>
67 #include <ipmitool/helper.h>
68 #include <ipmitool/log.h>
69 
70 extern int verbose;
71 
buf2long(uint8_t * buf)72 uint32_t buf2long(uint8_t * buf)
73 {
74 	return (uint32_t)(buf[3] << 24 | buf[2] << 16 | buf[1] << 8 | buf[0]);
75 }
76 
buf2short(uint8_t * buf)77 uint16_t buf2short(uint8_t * buf)
78 {
79 	return (uint16_t)(buf[1] << 8 | buf[0]);
80 }
81 
82 /* buf2str_extended - convert sequence of bytes to hexadecimal string with
83  * optional separator
84  *
85  * @param buf - data to convert
86  * @param len - size of data
87  * @param sep - optional separator (can be NULL)
88  *
89  * @returns     buf representation in hex, possibly truncated to fit
90  *              allocated static memory
91  */
92 const char *
buf2str_extended(const uint8_t * buf,int len,const char * sep)93 buf2str_extended(const uint8_t *buf, int len, const char *sep)
94 {
95 	static char str[BUF2STR_MAXIMUM_OUTPUT_SIZE];
96 	char *cur;
97 	int i;
98 	int sz;
99 	int left;
100 	int sep_len;
101 
102 	if (buf == NULL) {
103 		snprintf(str, sizeof(str), "<NULL>");
104 		return (const char *)str;
105 	}
106 	cur = str;
107 	left = sizeof(str);
108 	if (sep) {
109 		sep_len = strlen(sep);
110 	} else {
111 		sep_len = 0;
112 	}
113 	for (i = 0; i < len; i++) {
114 		/* may return more than 2, depending on locale */
115 		sz = snprintf(cur, left, "%2.2x", buf[i]);
116 		if (sz >= left) {
117 			/* buffer overflow, truncate */
118 			break;
119 		}
120 		cur += sz;
121 		left -= sz;
122 		/* do not write separator after last byte */
123 		if (sep && i != (len - 1)) {
124 			if (sep_len >= left) {
125 				break;
126 			}
127 			strncpy(cur, sep, left - sz);
128 			cur += sep_len;
129 			left -= sep_len;
130 		}
131 	}
132 	*cur = '\0';
133 
134 	return (const char *)str;
135 }
136 
137 const char *
buf2str(const uint8_t * buf,int len)138 buf2str(const uint8_t *buf, int len)
139 {
140 	return buf2str_extended(buf, len, NULL);
141 }
142 
143 /* ipmi_parse_hex - convert hexadecimal numbers to ascii string
144  *                  Input string must be composed of two-characer
145  *                  hexadecimal numbers.
146  *                  There is no separator between the numbers. Each number
147  *                  results in one byte of the converted string.
148  *
149  *                  Example: ipmi_parse_hex("50415353574F5244")
150  *                  returns 'PASSWORD'
151  *
152  * @param str:  input string. It must contain only even number
153  *              of '0'-'9','a'-'f' and 'A-F' characters.
154  * @param out: pointer to output data
155  * @param size: size of the output buffer
156  * @returns 0 for empty input string
157  *         -1 for string with odd length
158  *         -2 if out is NULL
159  *         -3 if there is non-hexadecimal char in string
160  *         >0 length of resulting binary data even if it is > size
161  */
162 int
ipmi_parse_hex(const char * str,uint8_t * out,int size)163 ipmi_parse_hex(const char *str, uint8_t *out, int size)
164 {
165 	const char *p;
166 	uint8_t *q;
167 	uint8_t d = 0;
168 	uint8_t b = 0;
169 	int shift = 4;
170 	int len;
171 
172 	len = strlen(str);
173 	if (len == 0) {
174 		return 0;
175 	}
176 
177 	if (len % 2 != 0) {
178 		return -1;
179 	}
180 
181 	len /= 2; /* out bytes */
182 	if (out == NULL) {
183 		return -2;
184 	}
185 
186 	for (p = str, q = out; *p; p++) {
187 		if (!isxdigit(*p)) {
188 			return -3;
189 		}
190 
191 		if (*p < 'A') {
192 			/* it must be 0-9 */
193 			d = *p - '0';
194 		} else {
195 			/* it's A-F or a-f */
196 			/* convert to lowercase and to 10-15 */
197 			d = (*p | 0x20) - 'a' + 10;
198 		}
199 
200 		if (q < (out + size)) {
201 			/* there is space, store */
202 			b += d << shift;
203 			if (shift) {
204 				shift = 0;
205 			} else {
206 				shift = 4;
207 				*q = b;
208 				b = 0;
209 				q++;
210 			}
211 		}
212 	}
213 
214 	return len;
215 }
216 
printbuf(const uint8_t * buf,int len,const char * desc)217 void printbuf(const uint8_t * buf, int len, const char * desc)
218 {
219 	int i;
220 
221 	if (len <= 0)
222 		return;
223 
224 	if (verbose < 1)
225 		return;
226 
227 	fprintf(stderr, "%s (%d bytes)\n", desc, len);
228 	for (i=0; i<len; i++) {
229 		if (((i%16) == 0) && (i != 0))
230 			fprintf(stderr, "\n");
231 		fprintf(stderr, " %2.2x", buf[i]);
232 	}
233 	fprintf(stderr, "\n");
234 }
235 
236 /* str2mac - parse-out MAC address from given string and store it
237  * into buffer.
238  *
239  * @arg: string to be parsed.
240  * @buf: buffer of 6 to hold parsed MAC address.
241  *
242  * returns zero on success, (-1) on error and error message is printed-out.
243  */
244 int
str2mac(const char * arg,uint8_t * buf)245 str2mac(const char *arg, uint8_t *buf)
246 {
247 	unsigned int m1 = 0;
248 	unsigned int m2 = 0;
249 	unsigned int m3 = 0;
250 	unsigned int m4 = 0;
251 	unsigned int m5 = 0;
252 	unsigned int m6 = 0;
253 	if (sscanf(arg, "%02x:%02x:%02x:%02x:%02x:%02x",
254 		   &m1, &m2, &m3, &m4, &m5, &m6) != 6) {
255 		lprintf(LOG_ERR, "Invalid MAC address: %s", arg);
256 		return -1;
257 	}
258 	if (m1 > UINT8_MAX || m2 > UINT8_MAX
259 			|| m3 > UINT8_MAX || m4 > UINT8_MAX
260 			|| m5 > UINT8_MAX || m6 > UINT8_MAX) {
261 		lprintf(LOG_ERR, "Invalid MAC address: %s", arg);
262 		return -1;
263 	}
264 	buf[0] = (uint8_t)m1;
265 	buf[1] = (uint8_t)m2;
266 	buf[2] = (uint8_t)m3;
267 	buf[3] = (uint8_t)m4;
268 	buf[4] = (uint8_t)m5;
269 	buf[5] = (uint8_t)m6;
270 	return 0;
271 }
272 
273 /* mac2str   -- return MAC address as a string
274  *
275  * @buf: buffer of 6 to hold parsed MAC address.
276  */
277 const char *
mac2str(const uint8_t * buf)278 mac2str(const uint8_t *buf)
279 {
280 	return buf2str_extended(buf, 6, ":");
281 }
282 
val2str(uint16_t val,const struct valstr * vs)283 const char * val2str(uint16_t val, const struct valstr *vs)
284 {
285 	static char un_str[32];
286 	int i;
287 
288 	for (i = 0; vs[i].str != NULL; i++) {
289 		if (vs[i].val == val)
290 			return vs[i].str;
291 	}
292 
293 	memset(un_str, 0, 32);
294 	snprintf(un_str, 32, "Unknown (0x%02X)", val);
295 
296 	return un_str;
297 }
298 
oemval2str(uint32_t oem,uint16_t val,const struct oemvalstr * vs)299 const char * oemval2str(uint32_t oem, uint16_t val,
300                                              const struct oemvalstr *vs)
301 {
302 	static char un_str[32];
303 	int i;
304 
305 	for (i = 0; vs[i].oem != 0xffffff &&  vs[i].str != NULL; i++) {
306 		/* FIXME: for now on we assume PICMG capability on all IANAs */
307 		if ( (vs[i].oem == oem || vs[i].oem == IPMI_OEM_PICMG) &&
308 				vs[i].val == val ) {
309 			return vs[i].str;
310 		}
311 	}
312 
313 	memset(un_str, 0, 32);
314 	snprintf(un_str, 32, "Unknown (0x%X)", val);
315 
316 	return un_str;
317 }
318 
319 /* str2double - safely convert string to double
320  *
321  * @str: source string to convert from
322  * @double_ptr: pointer where to store result
323  *
324  * returns zero on success
325  * returns (-1) if one of args is NULL, (-2) invalid input, (-3) for *flow
326  */
str2double(const char * str,double * double_ptr)327 int str2double(const char * str, double * double_ptr)
328 {
329 	char * end_ptr = 0;
330 	if (!str || !double_ptr)
331 		return (-1);
332 
333 	*double_ptr = 0;
334 	errno = 0;
335 	*double_ptr = strtod(str, &end_ptr);
336 
337 	if (*end_ptr != '\0')
338 		return (-2);
339 
340 	if (errno != 0)
341 		return (-3);
342 
343 	return 0;
344 } /* str2double(...) */
345 
346 /* str2long - safely convert string to int64_t
347  *
348  * @str: source string to convert from
349  * @lng_ptr: pointer where to store result
350  *
351  * returns zero on success
352  * returns (-1) if one of args is NULL, (-2) invalid input, (-3) for *flow
353  */
str2long(const char * str,int64_t * lng_ptr)354 int str2long(const char * str, int64_t * lng_ptr)
355 {
356 	char * end_ptr = 0;
357 	if (!str || !lng_ptr)
358 		return (-1);
359 
360 	*lng_ptr = 0;
361 	errno = 0;
362 	*lng_ptr = strtol(str, &end_ptr, 0);
363 
364 	if (*end_ptr != '\0')
365 		return (-2);
366 
367 	if (errno != 0)
368 		return (-3);
369 
370 	return 0;
371 } /* str2long(...) */
372 
373 /* str2ulong - safely convert string to uint64_t
374  *
375  * @str: source string to convert from
376  * @ulng_ptr: pointer where to store result
377  *
378  * returns zero on success
379  * returns (-1) if one of args is NULL, (-2) invalid input, (-3) for *flow
380  */
str2ulong(const char * str,uint64_t * ulng_ptr)381 int str2ulong(const char * str, uint64_t * ulng_ptr)
382 {
383 	char * end_ptr = 0;
384 	if (!str || !ulng_ptr)
385 		return (-1);
386 
387 	*ulng_ptr = 0;
388 	errno = 0;
389 	*ulng_ptr = strtoul(str, &end_ptr, 0);
390 
391 	if (*end_ptr != '\0')
392 		return (-2);
393 
394 	if (errno != 0)
395 		return (-3);
396 
397 	return 0;
398 } /* str2ulong(...) */
399 
400 /* str2int - safely convert string to int32_t
401  *
402  * @str: source string to convert from
403  * @int_ptr: pointer where to store result
404  *
405  * returns zero on success
406  * returns (-1) if one of args is NULL, (-2) invalid input, (-3) for *flow
407  */
str2int(const char * str,int32_t * int_ptr)408 int str2int(const char * str, int32_t * int_ptr)
409 {
410 	int rc = 0;
411 	int64_t arg_long = 0;
412 	if (!str || !int_ptr)
413 		return (-1);
414 
415 	if ( (rc = str2long(str, &arg_long)) != 0 ) {
416 		*int_ptr = 0;
417 		return rc;
418 	}
419 
420 	if (arg_long < INT32_MIN || arg_long > INT32_MAX)
421 		return (-3);
422 
423 	*int_ptr = (int32_t)arg_long;
424 	return 0;
425 } /* str2int(...) */
426 
427 /* str2uint - safely convert string to uint32_t
428  *
429  * @str: source string to convert from
430  * @uint_ptr: pointer where to store result
431  *
432  * returns zero on success
433  * returns (-1) if one of args is NULL, (-2) invalid input, (-3) for *flow
434  */
str2uint(const char * str,uint32_t * uint_ptr)435 int str2uint(const char * str, uint32_t * uint_ptr)
436 {
437 	int rc = 0;
438 	uint64_t arg_ulong = 0;
439 	if (!str || !uint_ptr)
440 		return (-1);
441 
442 	if ( (rc = str2ulong(str, &arg_ulong)) != 0) {
443 		*uint_ptr = 0;
444 		return rc;
445 	}
446 
447 	if (arg_ulong > UINT32_MAX)
448 		return (-3);
449 
450 	*uint_ptr = (uint32_t)arg_ulong;
451 	return 0;
452 } /* str2uint(...) */
453 
454 /* str2short - safely convert string to int16_t
455  *
456  * @str: source string to convert from
457  * @shrt_ptr: pointer where to store result
458  *
459  * returns zero on success
460  * returns (-1) if one of args is NULL, (-2) invalid input, (-3) for *flow
461  */
str2short(const char * str,int16_t * shrt_ptr)462 int str2short(const char * str, int16_t * shrt_ptr)
463 {
464 	int rc = (-3);
465 	int64_t arg_long = 0;
466 	if (!str || !shrt_ptr)
467 		return (-1);
468 
469 	if ( (rc = str2long(str, &arg_long)) != 0 ) {
470 		*shrt_ptr = 0;
471 		return rc;
472 	}
473 
474 	if (arg_long < INT16_MIN || arg_long > INT16_MAX)
475 		return (-3);
476 
477 	*shrt_ptr = (int16_t)arg_long;
478 	return 0;
479 } /* str2short(...) */
480 
481 /* str2ushort - safely convert string to uint16_t
482  *
483  * @str: source string to convert from
484  * @ushrt_ptr: pointer where to store result
485  *
486  * returns zero on success
487  * returns (-1) if one of args is NULL, (-2) invalid input, (-3) for *flow
488  */
str2ushort(const char * str,uint16_t * ushrt_ptr)489 int str2ushort(const char * str, uint16_t * ushrt_ptr)
490 {
491 	int rc = (-3);
492 	uint64_t arg_ulong = 0;
493 	if (!str || !ushrt_ptr)
494 		return (-1);
495 
496 	if ( (rc = str2ulong(str, &arg_ulong)) != 0 ) {
497 		*ushrt_ptr = 0;
498 		return rc;
499 	}
500 
501 	if (arg_ulong > UINT16_MAX)
502 		return (-3);
503 
504 	*ushrt_ptr = (uint16_t)arg_ulong;
505 	return 0;
506 } /* str2ushort(...) */
507 
508 /* str2char - safely convert string to int8
509  *
510  * @str: source string to convert from
511  * @chr_ptr: pointer where to store result
512  *
513  * returns zero on success
514  * returns (-1) if one of args is NULL, (-2) or (-3) if conversion fails
515  */
str2char(const char * str,int8_t * chr_ptr)516 int str2char(const char *str, int8_t * chr_ptr)
517 {
518 	int rc = (-3);
519 	int64_t arg_long = 0;
520 	if (!str || !chr_ptr) {
521 		return (-1);
522 	}
523 	if ((rc = str2long(str, &arg_long)) != 0) {
524 		*chr_ptr = 0;
525 		return rc;
526 	}
527 	if (arg_long < INT8_MIN || arg_long > INT8_MAX) {
528 		return (-3);
529 	}
530 	*chr_ptr = (uint8_t)arg_long;
531 	return 0;
532 } /* str2char(...) */
533 
534 /* str2uchar - safely convert string to uint8
535  *
536  * @str: source string to convert from
537  * @uchr_ptr: pointer where to store result
538  *
539  * returns zero on success
540  * returns (-1) if one of args is NULL, (-2) or (-3) if conversion fails
541  */
str2uchar(const char * str,uint8_t * uchr_ptr)542 int str2uchar(const char * str, uint8_t * uchr_ptr)
543 {
544 	int rc = (-3);
545 	uint64_t arg_ulong = 0;
546 	if (!str || !uchr_ptr)
547 		return (-1);
548 
549 	if ( (rc = str2ulong(str, &arg_ulong)) != 0 ) {
550 		*uchr_ptr = 0;
551 		return rc;
552 	}
553 
554 	if (arg_ulong > UINT8_MAX)
555 		return (-3);
556 
557 	*uchr_ptr = (uint8_t)arg_ulong;
558 	return 0;
559 } /* str2uchar(...) */
560 
str2val(const char * str,const struct valstr * vs)561 uint16_t str2val(const char *str, const struct valstr *vs)
562 {
563 	int i;
564 
565 	for (i = 0; vs[i].str != NULL; i++) {
566 		if (strncasecmp(vs[i].str, str, __maxlen(str, vs[i].str)) == 0)
567 			return vs[i].val;
568 	}
569 
570 	return vs[i].val;
571 }
572 
573 /* print_valstr  -  print value string list to log or stdout
574  *
575  * @vs:		value string list to print
576  * @title:	name of this value string list
577  * @loglevel:	what log level to print, -1 for stdout
578  */
579 void
print_valstr(const struct valstr * vs,const char * title,int loglevel)580 print_valstr(const struct valstr * vs, const char * title, int loglevel)
581 {
582 	int i;
583 
584 	if (vs == NULL)
585 		return;
586 
587 	if (title != NULL) {
588 		if (loglevel < 0)
589 			printf("\n%s:\n\n", title);
590 		else
591 			lprintf(loglevel, "\n%s:\n", title);
592 	}
593 
594 	if (loglevel < 0) {
595 		printf("  VALUE\tHEX\tSTRING\n");
596 		printf("==============================================\n");
597 	} else {
598 		lprintf(loglevel, "  VAL\tHEX\tSTRING");
599 		lprintf(loglevel, "==============================================");
600 	}
601 
602 	for (i = 0; vs[i].str != NULL; i++) {
603 		if (loglevel < 0) {
604 			if (vs[i].val < 256)
605 				printf("  %d\t0x%02x\t%s\n", vs[i].val, vs[i].val, vs[i].str);
606 			else
607 				printf("  %d\t0x%04x\t%s\n", vs[i].val, vs[i].val, vs[i].str);
608 		} else {
609 			if (vs[i].val < 256)
610 				lprintf(loglevel, "  %d\t0x%02x\t%s", vs[i].val, vs[i].val, vs[i].str);
611 			else
612 				lprintf(loglevel, "  %d\t0x%04x\t%s", vs[i].val, vs[i].val, vs[i].str);
613 		}
614 	}
615 
616 	if (loglevel < 0)
617 		printf("\n");
618 	else
619 		lprintf(loglevel, "");
620 }
621 
622 /* print_valstr_2col  -  print value string list in two columns to log or stdout
623  *
624  * @vs:		value string list to print
625  * @title:	name of this value string list
626  * @loglevel:	what log level to print, -1 for stdout
627  */
628 void
print_valstr_2col(const struct valstr * vs,const char * title,int loglevel)629 print_valstr_2col(const struct valstr * vs, const char * title, int loglevel)
630 {
631 	int i;
632 
633 	if (vs == NULL)
634 		return;
635 
636 	if (title != NULL) {
637 		if (loglevel < 0)
638 			printf("\n%s:\n\n", title);
639 		else
640 			lprintf(loglevel, "\n%s:\n", title);
641 	}
642 
643 	for (i = 0; vs[i].str != NULL; i++) {
644 		if (vs[i+1].str == NULL) {
645 			/* last one */
646 			if (loglevel < 0) {
647 				printf("  %4d  %-32s\n", vs[i].val, vs[i].str);
648 			} else {
649 				lprintf(loglevel, "  %4d  %-32s\n", vs[i].val, vs[i].str);
650 			}
651 		}
652 		else {
653 			if (loglevel < 0) {
654 				printf("  %4d  %-32s    %4d  %-32s\n",
655 				       vs[i].val, vs[i].str, vs[i+1].val, vs[i+1].str);
656 			} else {
657 				lprintf(loglevel, "  %4d  %-32s    %4d  %-32s\n",
658 					vs[i].val, vs[i].str, vs[i+1].val, vs[i+1].str);
659 			}
660 			i++;
661 		}
662 	}
663 
664 	if (loglevel < 0)
665 		printf("\n");
666 	else
667 		lprintf(loglevel, "");
668 }
669 
670 /* ipmi_csum  -  calculate an ipmi checksum
671  *
672  * @d:		buffer to check
673  * @s:		position in buffer to start checksum from
674  */
675 uint8_t
ipmi_csum(uint8_t * d,int s)676 ipmi_csum(uint8_t * d, int s)
677 {
678 	uint8_t c = 0;
679 	for (; s > 0; s--, d++)
680 		c += *d;
681 	return -c;
682 }
683 
684 /* ipmi_open_file  -  safely open a file for reading or writing
685  *
686  * @file:	filename
687  * @rw:		read-write flag, 1=write
688  *
689  * returns pointer to file handler on success
690  * returns NULL on error
691  */
692 FILE *
ipmi_open_file(const char * file,int rw)693 ipmi_open_file(const char * file, int rw)
694 {
695 	struct stat st1, st2;
696 	FILE * fp;
697 
698 	/* verify existance */
699 	if (lstat(file, &st1) < 0) {
700 		if (rw) {
701 			/* does not exist, ok to create */
702 			fp = fopen(file, "w");
703 			if (fp == NULL) {
704 				lperror(LOG_ERR, "Unable to open file %s "
705 					"for write", file);
706 				return NULL;
707 			}
708 			/* created ok, now return the descriptor */
709 			return fp;
710 		} else {
711 			lprintf(LOG_ERR, "File %s does not exist", file);
712 			return NULL;
713 		}
714 	}
715 
716 #ifndef ENABLE_FILE_SECURITY
717 	if (!rw) {
718 		/* on read skip the extra checks */
719 		fp = fopen(file, "r");
720 		if (fp == NULL) {
721 			lperror(LOG_ERR, "Unable to open file %s", file);
722 			return NULL;
723 		}
724 		return fp;
725 	}
726 #endif
727 
728 	/* it exists - only regular files, not links */
729 	if (S_ISREG(st1.st_mode) == 0) {
730 		lprintf(LOG_ERR, "File %s has invalid mode: %d",
731 			file, st1.st_mode);
732 		return NULL;
733 	}
734 
735 	/* allow only files with 1 link (itself) */
736 	if (st1.st_nlink != 1) {
737 		lprintf(LOG_ERR, "File %s has invalid link count: %d != 1",
738 		       file, (int)st1.st_nlink);
739 		return NULL;
740 	}
741 
742 	fp = fopen(file, rw ? "w+" : "r");
743 	if (fp == NULL) {
744 		lperror(LOG_ERR, "Unable to open file %s", file);
745 		return NULL;
746 	}
747 
748 	/* stat again */
749 	if (fstat(fileno(fp), &st2) < 0) {
750 		lperror(LOG_ERR, "Unable to stat file %s", file);
751 		fclose(fp);
752 		return NULL;
753 	}
754 
755 	/* verify inode */
756 	if (st1.st_ino != st2.st_ino) {
757 		lprintf(LOG_ERR, "File %s has invalid inode: %d != %d",
758 			file, st1.st_ino, st2.st_ino);
759 		fclose(fp);
760 		return NULL;
761 	}
762 
763 	/* verify owner */
764 	if (st1.st_uid != st2.st_uid) {
765 		lprintf(LOG_ERR, "File %s has invalid user id: %d != %d",
766 			file, st1.st_uid, st2.st_uid);
767 		fclose(fp);
768 		return NULL;
769 	}
770 
771 	/* verify inode */
772 	if (st2.st_nlink != 1) {
773 		lprintf(LOG_ERR, "File %s has invalid link count: %d != 1",
774 			file, st2.st_nlink);
775 		fclose(fp);
776 		return NULL;
777 	}
778 
779 	return fp;
780 }
781 
782 void
ipmi_start_daemon(struct ipmi_intf * intf)783 ipmi_start_daemon(struct ipmi_intf *intf)
784 {
785 	pid_t pid;
786 	int fd;
787 #ifdef SIGHUP
788 	sigset_t sighup;
789 #endif
790 
791 #ifdef SIGHUP
792 	sigemptyset(&sighup);
793 	sigaddset(&sighup, SIGHUP);
794 	if (sigprocmask(SIG_UNBLOCK, &sighup, NULL) < 0)
795 		fprintf(stderr, "ERROR: could not unblock SIGHUP signal\n");
796 	signal(SIGHUP, SIG_IGN);
797 #endif
798 #ifdef SIGTTOU
799 	signal(SIGTTOU, SIG_IGN);
800 #endif
801 #ifdef SIGTTIN
802 	signal(SIGTTIN, SIG_IGN);
803 #endif
804 #ifdef SIGQUIT
805 	signal(SIGQUIT, SIG_IGN);
806 #endif
807 #ifdef SIGTSTP
808 	signal(SIGTSTP, SIG_IGN);
809 #endif
810 
811 	pid = (pid_t) fork();
812 	if (pid < 0 || pid > 0)
813 		exit(0);
814 
815 #if defined(SIGTSTP) && defined(TIOCNOTTY)
816 	if (setpgid(0, getpid()) == -1)
817 		exit(1);
818 	if ((fd = open(_PATH_TTY, O_RDWR)) >= 0) {
819 		ioctl(fd, TIOCNOTTY, NULL);
820 		close(fd);
821 	}
822 #else
823 	if (setpgid(0, 0) == -1)
824 		exit(1);
825 	pid = (pid_t) fork();
826 	if (pid < 0 || pid > 0)
827 		exit(0);
828 #endif
829 
830 	chdir("/");
831 	umask(0);
832 
833 	for (fd=0; fd<64; fd++) {
834 		if (fd != intf->fd)
835 			close(fd);
836 	}
837 
838 	fd = open("/dev/null", O_RDWR);
839 	assert(0 == fd);
840 	dup(fd);
841 	dup(fd);
842 }
843 
844 /* eval_ccode - evaluate return value of _ipmi_* functions and print error error
845  * message, if conditions are met.
846  *
847  * @ccode - return value of _ipmi_* function.
848  *
849  * returns - 0 if ccode is 0, otherwise (-1) and error might get printed-out.
850  */
851 int
eval_ccode(const int ccode)852 eval_ccode(const int ccode)
853 {
854 	if (ccode == 0) {
855 		return 0;
856 	} else if (ccode < 0) {
857 		switch (ccode) {
858 			case (-1):
859 				lprintf(LOG_ERR, "IPMI response is NULL.");
860 				break;
861 			case (-2):
862 				lprintf(LOG_ERR, "Unexpected data length received.");
863 				break;
864 			case (-3):
865 				lprintf(LOG_ERR, "Invalid function parameter.");
866 				break;
867 			case (-4):
868 				lprintf(LOG_ERR, "ipmitool: malloc failure.");
869 				break;
870 			default:
871 				break;
872 		}
873 		return (-1);
874 	} else {
875 		lprintf(LOG_ERR, "IPMI command failed: %s",
876 				val2str(ccode, completion_code_vals));
877 		return (-1);
878 	}
879 }
880 
881 /* is_fru_id - wrapper for str-2-int FRU ID conversion. Message is printed
882  * on error.
883  * FRU ID range: <0..255>
884  *
885  * @argv_ptr: source string to convert from; usually argv
886  * @fru_id_ptr: pointer where to store result
887  *
888  * returns zero on success
889  * returns (-1) on error and message is printed on STDERR
890  */
891 int
is_fru_id(const char * argv_ptr,uint8_t * fru_id_ptr)892 is_fru_id(const char *argv_ptr, uint8_t *fru_id_ptr)
893 {
894 	if (!argv_ptr || !fru_id_ptr) {
895 		lprintf(LOG_ERR, "is_fru_id(): invalid argument(s).");
896 		return (-1);
897 	}
898 
899 	if (str2uchar(argv_ptr, fru_id_ptr) == 0) {
900 		return 0;
901 	}
902 	lprintf(LOG_ERR, "FRU ID '%s' is either invalid or out of range.",
903 			argv_ptr);
904 	return (-1);
905 } /* is_fru_id(...) */
906 
907 /* is_ipmi_channel_num - wrapper for str-2-int Channel conversion. Message is
908  * printed on error.
909  *
910  * 6.3 Channel Numbers, p. 49, IPMIv2 spec. rev1.1
911  * Valid channel numbers are: <0x0..0xB>, <0xE-0xF>
912  * Reserved channel numbers: <0xC-0xD>
913  *
914  * @argv_ptr: source string to convert from; usually argv
915  * @channel_ptr: pointer where to store result
916  *
917  * returns zero on success
918  * returns (-1) on error and message is printed on STDERR
919  */
920 int
is_ipmi_channel_num(const char * argv_ptr,uint8_t * channel_ptr)921 is_ipmi_channel_num(const char *argv_ptr, uint8_t *channel_ptr)
922 {
923 	if (!argv_ptr || !channel_ptr) {
924 		lprintf(LOG_ERR,
925 				"is_ipmi_channel_num(): invalid argument(s).");
926 		return (-1);
927 	}
928 	if ((str2uchar(argv_ptr, channel_ptr) == 0)
929 			&& (*channel_ptr <= 0xB
930 				|| (*channel_ptr >= 0xE && *channel_ptr <= 0xF))) {
931 		return 0;
932 	}
933 	lprintf(LOG_ERR,
934 			"Given Channel number '%s' is either invalid or out of range.",
935 			argv_ptr);
936 	lprintf(LOG_ERR, "Channel number must be from ranges: <0x0..0xB>, <0xE..0xF>");
937 	return (-1);
938 }
939 
940 /* is_ipmi_user_id() - wrapper for str-2-uint IPMI UID conversion. Message is
941  * printed on error.
942  *
943  * @argv_ptr: source string to convert from; usually argv
944  * @ipmi_uid_ptr: pointer where to store result
945  *
946  * returns zero on success
947  * returns (-1) on error and message is printed on STDERR
948  */
949 int
is_ipmi_user_id(const char * argv_ptr,uint8_t * ipmi_uid_ptr)950 is_ipmi_user_id(const char *argv_ptr, uint8_t *ipmi_uid_ptr)
951 {
952 	if (!argv_ptr || !ipmi_uid_ptr) {
953 		lprintf(LOG_ERR,
954 				"is_ipmi_user_id(): invalid argument(s).");
955 		return (-1);
956 	}
957 	if ((str2uchar(argv_ptr, ipmi_uid_ptr) == 0)
958 			&& *ipmi_uid_ptr >= IPMI_UID_MIN
959 			&& *ipmi_uid_ptr <= IPMI_UID_MAX) {
960 		return 0;
961 	}
962 	lprintf(LOG_ERR,
963 			"Given User ID '%s' is either invalid or out of range.",
964 			argv_ptr);
965 	lprintf(LOG_ERR, "User ID is limited to range <%i..%i>.",
966 			IPMI_UID_MIN, IPMI_UID_MAX);
967 	return (-1);
968 }
969 
970 /* is_ipmi_user_priv_limit - check whether given value is valid User Privilege
971  * Limit, eg. IPMI v2 spec, 22.27 Get User Access Command.
972  *
973  * @priv_limit: User Privilege Limit
974  *
975  * returns 0 if Priv Limit is valid
976  * returns (-1) when Priv Limit is invalid
977  */
978 int
is_ipmi_user_priv_limit(const char * argv_ptr,uint8_t * ipmi_priv_limit_ptr)979 is_ipmi_user_priv_limit(const char *argv_ptr, uint8_t *ipmi_priv_limit_ptr)
980 {
981 	if (!argv_ptr || !ipmi_priv_limit_ptr) {
982 		lprintf(LOG_ERR,
983 				"is_ipmi_user_priv_limit(): invalid argument(s).");
984 		return (-1);
985 	}
986 	if ((str2uchar(argv_ptr, ipmi_priv_limit_ptr) != 0)
987 			|| ((*ipmi_priv_limit_ptr < 0x01
988 				|| *ipmi_priv_limit_ptr > 0x05)
989 				&& *ipmi_priv_limit_ptr != 0x0F)) {
990 		lprintf(LOG_ERR,
991 				"Given Privilege Limit '%s' is invalid.",
992 				argv_ptr);
993 		lprintf(LOG_ERR,
994 				"Privilege Limit is limited to <0x1..0x5> and <0xF>.");
995 		return (-1);
996 	}
997 	return 0;
998 }
999 
1000 uint16_t
ipmi_get_oem_id(struct ipmi_intf * intf)1001 ipmi_get_oem_id(struct ipmi_intf *intf)
1002 {
1003 	/* Execute a Get Board ID command to determine the board */
1004 	struct ipmi_rs *rsp;
1005 	struct ipmi_rq req;
1006 	uint16_t oem_id;
1007 
1008 	memset(&req, 0, sizeof(req));
1009 	req.msg.netfn = IPMI_NETFN_TSOL;
1010 	req.msg.cmd   = 0x21;
1011 	req.msg.data_len = 0;
1012 
1013 	rsp = intf->sendrecv(intf, &req);
1014 	if (rsp == NULL) {
1015 		lprintf(LOG_ERR, "Get Board ID command failed");
1016 		return 0;
1017 	}
1018 	if (rsp->ccode > 0) {
1019 		lprintf(LOG_ERR, "Get Board ID command failed: %#x %s",
1020 			rsp->ccode, val2str(rsp->ccode, completion_code_vals));
1021 		return 0;
1022 	}
1023 	oem_id = rsp->data[0] | (rsp->data[1] << 8);
1024 	lprintf(LOG_DEBUG,"Board ID: %x", oem_id);
1025 
1026 	return oem_id;
1027 }
1028