xref: /minix/external/bsd/tcpdump/dist/util.c (revision bb9622b5)
1 /*
2  * Copyright (c) 1990, 1991, 1993, 1994, 1995, 1996, 1997
3  *	The Regents of the University of California.  All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that: (1) source code distributions
7  * retain the above copyright notice and this paragraph in its entirety, (2)
8  * distributions including binary code include the above copyright notice and
9  * this paragraph in its entirety in the documentation or other materials
10  * provided with the distribution, and (3) all advertising materials mentioning
11  * features or use of this software display the following acknowledgement:
12  * ``This product includes software developed by the University of California,
13  * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
14  * the University nor the names of its contributors may be used to endorse
15  * or promote products derived from this software without specific prior
16  * written permission.
17  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
18  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
19  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
20  */
21 
22 #include <sys/cdefs.h>
23 #ifndef lint
24 __RCSID("$NetBSD: util.c,v 1.5 2015/03/31 21:59:35 christos Exp $");
25 #endif
26 
27 /*
28  * txtproto_print() derived from original code by Hannes Gredler
29  * (hannes@juniper.net):
30  *
31  * Redistribution and use in source and binary forms, with or without
32  * modification, are permitted provided that: (1) source code
33  * distributions retain the above copyright notice and this paragraph
34  * in its entirety, and (2) distributions including binary code include
35  * the above copyright notice and this paragraph in its entirety in
36  * the documentation or other materials provided with the distribution.
37  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND
38  * WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT
39  * LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
40  * FOR A PARTICULAR PURPOSE.
41  */
42 
43 #define NETDISSECT_REWORKED
44 #ifdef HAVE_CONFIG_H
45 #include "config.h"
46 #endif
47 
48 #include <tcpdump-stdinc.h>
49 
50 #include <sys/stat.h>
51 
52 #ifdef HAVE_FCNTL_H
53 #include <fcntl.h>
54 #endif
55 #include <stdio.h>
56 #include <stdarg.h>
57 #include <stdlib.h>
58 #include <string.h>
59 
60 #include "interface.h"
61 
62 /*
63  * Print out a null-terminated filename (or other ascii string).
64  * If ep is NULL, assume no truncation check is needed.
65  * Return true if truncated.
66  */
67 int
68 fn_print(netdissect_options *ndo,
69          register const u_char *s, register const u_char *ep)
70 {
71 	register int ret;
72 	register u_char c;
73 
74 	ret = 1;			/* assume truncated */
75 	while (ep == NULL || s < ep) {
76 		c = *s++;
77 		if (c == '\0') {
78 			ret = 0;
79 			break;
80 		}
81 		if (!ND_ISASCII(c)) {
82 			c = ND_TOASCII(c);
83 			ND_PRINT((ndo, "M-"));
84 		}
85 		if (!ND_ISPRINT(c)) {
86 			c ^= 0x40;	/* DEL to ?, others to alpha */
87 			ND_PRINT((ndo, "^"));
88 		}
89 		ND_PRINT((ndo, "%c", c));
90 	}
91 	return(ret);
92 }
93 
94 /*
95  * Print out a counted filename (or other ascii string).
96  * If ep is NULL, assume no truncation check is needed.
97  * Return true if truncated.
98  */
99 int
100 fn_printn(netdissect_options *ndo,
101           register const u_char *s, register u_int n, register const u_char *ep)
102 {
103 	register u_char c;
104 
105 	while (n > 0 && (ep == NULL || s < ep)) {
106 		n--;
107 		c = *s++;
108 		if (!ND_ISASCII(c)) {
109 			c = ND_TOASCII(c);
110 			ND_PRINT((ndo, "M-"));
111 		}
112 		if (!ND_ISPRINT(c)) {
113 			c ^= 0x40;	/* DEL to ?, others to alpha */
114 			ND_PRINT((ndo, "^"));
115 		}
116 		ND_PRINT((ndo, "%c", c));
117 	}
118 	return (n == 0) ? 0 : 1;
119 }
120 
121 /*
122  * Print out a null-padded filename (or other ascii string).
123  * If ep is NULL, assume no truncation check is needed.
124  * Return true if truncated.
125  */
126 int
127 fn_printzp(netdissect_options *ndo,
128            register const u_char *s, register u_int n,
129            register const u_char *ep)
130 {
131 	register int ret;
132 	register u_char c;
133 
134 	ret = 1;			/* assume truncated */
135 	while (n > 0 && (ep == NULL || s < ep)) {
136 		n--;
137 		c = *s++;
138 		if (c == '\0') {
139 			ret = 0;
140 			break;
141 		}
142 		if (!ND_ISASCII(c)) {
143 			c = ND_TOASCII(c);
144 			ND_PRINT((ndo, "M-"));
145 		}
146 		if (!ND_ISPRINT(c)) {
147 			c ^= 0x40;	/* DEL to ?, others to alpha */
148 			ND_PRINT((ndo, "^"));
149 		}
150 		ND_PRINT((ndo, "%c", c));
151 	}
152 	return (n == 0) ? 0 : ret;
153 }
154 
155 /*
156  * Format the timestamp
157  */
158 static char *
159 ts_format(netdissect_options *ndo
160 #ifndef HAVE_PCAP_SET_TSTAMP_PRECISION
161 _U_
162 #endif
163 , int sec, int usec)
164 {
165 	static char buf[sizeof("00:00:00.000000000")];
166 	const char *format;
167 
168 #ifdef HAVE_PCAP_SET_TSTAMP_PRECISION
169 	switch (ndo->ndo_tstamp_precision) {
170 
171 	case PCAP_TSTAMP_PRECISION_MICRO:
172 		format = "%02d:%02d:%02d.%06u";
173 		break;
174 
175 	case PCAP_TSTAMP_PRECISION_NANO:
176 		format = "%02d:%02d:%02d.%09u";
177 		break;
178 
179 	default:
180 		format = "%02d:%02d:%02d.{unknown precision}";
181 		break;
182 	}
183 #else
184 	format = "%02d:%02d:%02d.%06u";
185 #endif
186 
187 	snprintf(buf, sizeof(buf), format,
188                  sec / 3600, (sec % 3600) / 60, sec % 60, usec);
189 
190         return buf;
191 }
192 
193 /*
194  * Print the timestamp
195  */
196 void
197 ts_print(netdissect_options *ndo,
198          register const struct timeval *tvp)
199 {
200 	register int s;
201 	struct tm *tm;
202 	time_t Time;
203 	static unsigned b_sec;
204 	static unsigned b_usec;
205 	int d_usec;
206 	int d_sec;
207 
208 	switch (ndo->ndo_tflag) {
209 
210 	case 0: /* Default */
211 		s = (tvp->tv_sec + thiszone) % 86400;
212 		ND_PRINT((ndo, "%s ", ts_format(ndo, s, tvp->tv_usec)));
213 		break;
214 
215 	case 1: /* No time stamp */
216 		break;
217 
218 	case 2: /* Unix timeval style */
219 		ND_PRINT((ndo, "%u.%06u ",
220 			     (unsigned)tvp->tv_sec,
221 			     (unsigned)tvp->tv_usec));
222 		break;
223 
224 	case 3: /* Microseconds since previous packet */
225         case 5: /* Microseconds since first packet */
226 		if (b_sec == 0) {
227                         /* init timestamp for first packet */
228                         b_usec = tvp->tv_usec;
229                         b_sec = tvp->tv_sec;
230                 }
231 
232                 d_usec = tvp->tv_usec - b_usec;
233                 d_sec = tvp->tv_sec - b_sec;
234 
235                 while (d_usec < 0) {
236                     d_usec += 1000000;
237                     d_sec--;
238                 }
239 
240                 ND_PRINT((ndo, "%s ", ts_format(ndo, d_sec, d_usec)));
241 
242                 if (ndo->ndo_tflag == 3) { /* set timestamp for last packet */
243                     b_sec = tvp->tv_sec;
244                     b_usec = tvp->tv_usec;
245                 }
246 		break;
247 
248 	case 4: /* Default + Date*/
249 		s = (tvp->tv_sec + thiszone) % 86400;
250 		Time = (tvp->tv_sec + thiszone) - s;
251 		tm = gmtime (&Time);
252 		if (!tm)
253 			ND_PRINT((ndo, "Date fail  "));
254 		else
255 			ND_PRINT((ndo, "%04d-%02d-%02d %s ",
256                                tm->tm_year+1900, tm->tm_mon+1, tm->tm_mday,
257                                ts_format(ndo, s, tvp->tv_usec)));
258 		break;
259 	}
260 }
261 
262 /*
263  * Print a relative number of seconds (e.g. hold time, prune timer)
264  * in the form 5m1s.  This does no truncation, so 32230861 seconds
265  * is represented as 1y1w1d1h1m1s.
266  */
267 void
268 relts_print(netdissect_options *ndo,
269             int secs)
270 {
271 	static const char *lengths[] = {"y", "w", "d", "h", "m", "s"};
272 	static const int seconds[] = {31536000, 604800, 86400, 3600, 60, 1};
273 	const char **l = lengths;
274 	const int *s = seconds;
275 
276 	if (secs == 0) {
277 		ND_PRINT((ndo, "0s"));
278 		return;
279 	}
280 	if (secs < 0) {
281 		ND_PRINT((ndo, "-"));
282 		secs = -secs;
283 	}
284 	while (secs > 0) {
285 		if (secs >= *s) {
286 			ND_PRINT((ndo, "%d%s", secs / *s, *l));
287 			secs -= (secs / *s) * *s;
288 		}
289 		s++;
290 		l++;
291 	}
292 }
293 
294 /*
295  *  this is a generic routine for printing unknown data;
296  *  we pass on the linefeed plus indentation string to
297  *  get a proper output - returns 0 on error
298  */
299 
300 int
301 print_unknown_data(netdissect_options *ndo, const u_char *cp,const char *ident,int len)
302 {
303 	if (len < 0) {
304           ND_PRINT((ndo,"%sDissector error: print_unknown_data called with negative length",
305 		    ident));
306 		return(0);
307 	}
308 	if (ndo->ndo_snapend - cp < len)
309 		len = ndo->ndo_snapend - cp;
310 	if (len < 0) {
311           ND_PRINT((ndo,"%sDissector error: print_unknown_data called with pointer past end of packet",
312 		    ident));
313 		return(0);
314 	}
315         hex_print(ndo, ident,cp,len);
316 	return(1); /* everything is ok */
317 }
318 
319 /*
320  * Convert a token value to a string; use "fmt" if not found.
321  */
322 const char *
323 tok2strbuf(register const struct tok *lp, register const char *fmt,
324 	   register u_int v, char *buf, size_t bufsize)
325 {
326 	if (lp != NULL) {
327 		while (lp->s != NULL) {
328 			if (lp->v == v)
329 				return (lp->s);
330 			++lp;
331 		}
332 	}
333 	if (fmt == NULL)
334 		fmt = "#%d";
335 
336 	(void)snprintf(buf, bufsize, fmt, v);
337 	return (const char *)buf;
338 }
339 
340 /*
341  * Convert a token value to a string; use "fmt" if not found.
342  */
343 const char *
344 tok2str(register const struct tok *lp, register const char *fmt,
345 	register int v)
346 {
347 	static char buf[4][128];
348 	static int idx = 0;
349 	char *ret;
350 
351 	ret = buf[idx];
352 	idx = (idx+1) & 3;
353 	return tok2strbuf(lp, fmt, v, ret, sizeof(buf[0]));
354 }
355 
356 /*
357  * Convert a bit token value to a string; use "fmt" if not found.
358  * this is useful for parsing bitfields, the output strings are seperated
359  * if the s field is positive.
360  */
361 static char *
362 bittok2str_internal(register const struct tok *lp, register const char *fmt,
363 	   register int v, register int sep)
364 {
365         static char buf[256]; /* our stringbuffer */
366         int buflen=0;
367         register int rotbit; /* this is the bit we rotate through all bitpositions */
368         register int tokval;
369         const char * sepstr = "";
370 
371 	while (lp != NULL && lp->s != NULL) {
372             tokval=lp->v;   /* load our first value */
373             rotbit=1;
374             while (rotbit != 0) {
375                 /*
376                  * lets AND the rotating bit with our token value
377                  * and see if we have got a match
378                  */
379 		if (tokval == (v&rotbit)) {
380                     /* ok we have found something */
381                     buflen+=snprintf(buf+buflen, sizeof(buf)-buflen, "%s%s",
382                                      sepstr, lp->s);
383                     sepstr = sep ? ", " : "";
384                     break;
385                 }
386                 rotbit=rotbit<<1; /* no match - lets shift and try again */
387             }
388             lp++;
389 	}
390 
391         if (buflen == 0)
392             /* bummer - lets print the "unknown" message as advised in the fmt string if we got one */
393             (void)snprintf(buf, sizeof(buf), fmt == NULL ? "#%d" : fmt, v);
394         return (buf);
395 }
396 
397 /*
398  * Convert a bit token value to a string; use "fmt" if not found.
399  * this is useful for parsing bitfields, the output strings are not seperated.
400  */
401 char *
402 bittok2str_nosep(register const struct tok *lp, register const char *fmt,
403 	   register int v)
404 {
405     return (bittok2str_internal(lp, fmt, v, 0));
406 }
407 
408 /*
409  * Convert a bit token value to a string; use "fmt" if not found.
410  * this is useful for parsing bitfields, the output strings are comma seperated.
411  */
412 char *
413 bittok2str(register const struct tok *lp, register const char *fmt,
414 	   register int v)
415 {
416     return (bittok2str_internal(lp, fmt, v, 1));
417 }
418 
419 /*
420  * Convert a value to a string using an array; the macro
421  * tok2strary() in <interface.h> is the public interface to
422  * this function and ensures that the second argument is
423  * correct for bounds-checking.
424  */
425 const char *
426 tok2strary_internal(register const char **lp, int n, register const char *fmt,
427 	register int v)
428 {
429 	static char buf[128];
430 
431 	if (v >= 0 && v < n && lp[v] != NULL)
432 		return lp[v];
433 	if (fmt == NULL)
434 		fmt = "#%d";
435 	(void)snprintf(buf, sizeof(buf), fmt, v);
436 	return (buf);
437 }
438 
439 /*
440  * Convert a 32-bit netmask to prefixlen if possible
441  * the function returns the prefix-len; if plen == -1
442  * then conversion was not possible;
443  */
444 
445 int
446 mask2plen(uint32_t mask)
447 {
448 	uint32_t bitmasks[33] = {
449 		0x00000000,
450 		0x80000000, 0xc0000000, 0xe0000000, 0xf0000000,
451 		0xf8000000, 0xfc000000, 0xfe000000, 0xff000000,
452 		0xff800000, 0xffc00000, 0xffe00000, 0xfff00000,
453 		0xfff80000, 0xfffc0000, 0xfffe0000, 0xffff0000,
454 		0xffff8000, 0xffffc000, 0xffffe000, 0xfffff000,
455 		0xfffff800, 0xfffffc00, 0xfffffe00, 0xffffff00,
456 		0xffffff80, 0xffffffc0, 0xffffffe0, 0xfffffff0,
457 		0xfffffff8, 0xfffffffc, 0xfffffffe, 0xffffffff
458 	};
459 	int prefix_len = 32;
460 
461 	/* let's see if we can transform the mask into a prefixlen */
462 	while (prefix_len >= 0) {
463 		if (bitmasks[prefix_len] == mask)
464 			break;
465 		prefix_len--;
466 	}
467 	return (prefix_len);
468 }
469 
470 #ifdef INET6
471 int
472 mask62plen(const u_char *mask)
473 {
474 	u_char bitmasks[9] = {
475 		0x00,
476 		0x80, 0xc0, 0xe0, 0xf0,
477 		0xf8, 0xfc, 0xfe, 0xff
478 	};
479 	int byte;
480 	int cidr_len = 0;
481 
482 	for (byte = 0; byte < 16; byte++) {
483 		u_int bits;
484 
485 		for (bits = 0; bits < (sizeof (bitmasks) / sizeof (bitmasks[0])); bits++) {
486 			if (mask[byte] == bitmasks[bits]) {
487 				cidr_len += bits;
488 				break;
489 			}
490 		}
491 
492 		if (mask[byte] != 0xff)
493 			break;
494 	}
495 	return (cidr_len);
496 }
497 #endif /* INET6 */
498 
499 /*
500  * Routine to print out information for text-based protocols such as FTP,
501  * HTTP, SMTP, RTSP, SIP, ....
502  */
503 #define MAX_TOKEN	128
504 
505 /*
506  * Fetch a token from a packet, starting at the specified index,
507  * and return the length of the token.
508  *
509  * Returns 0 on error; yes, this is indistinguishable from an empty
510  * token, but an "empty token" isn't a valid token - it just means
511  * either a space character at the beginning of the line (this
512  * includes a blank line) or no more tokens remaining on the line.
513  */
514 static int
515 fetch_token(netdissect_options *ndo, const u_char *pptr, u_int idx, u_int len,
516     u_char *tbuf, size_t tbuflen)
517 {
518 	size_t toklen = 0;
519 
520 	for (; idx < len; idx++) {
521 		if (!ND_TTEST(*(pptr + idx))) {
522 			/* ran past end of captured data */
523 			return (0);
524 		}
525 		if (!isascii(*(pptr + idx))) {
526 			/* not an ASCII character */
527 			return (0);
528 		}
529 		if (isspace(*(pptr + idx))) {
530 			/* end of token */
531 			break;
532 		}
533 		if (!isprint(*(pptr + idx))) {
534 			/* not part of a command token or response code */
535 			return (0);
536 		}
537 		if (toklen + 2 > tbuflen) {
538 			/* no room for this character and terminating '\0' */
539 			return (0);
540 		}
541 		tbuf[toklen] = *(pptr + idx);
542 		toklen++;
543 	}
544 	if (toklen == 0) {
545 		/* no token */
546 		return (0);
547 	}
548 	tbuf[toklen] = '\0';
549 
550 	/*
551 	 * Skip past any white space after the token, until we see
552 	 * an end-of-line (CR or LF).
553 	 */
554 	for (; idx < len; idx++) {
555 		if (!ND_TTEST(*(pptr + idx))) {
556 			/* ran past end of captured data */
557 			break;
558 		}
559 		if (*(pptr + idx) == '\r' || *(pptr + idx) == '\n') {
560 			/* end of line */
561 			break;
562 		}
563 		if (!isascii(*(pptr + idx)) || !isprint(*(pptr + idx))) {
564 			/* not a printable ASCII character */
565 			break;
566 		}
567 		if (!isspace(*(pptr + idx))) {
568 			/* beginning of next token */
569 			break;
570 		}
571 	}
572 	return (idx);
573 }
574 
575 /*
576  * Scan a buffer looking for a line ending - LF or CR-LF.
577  * Return the index of the character after the line ending or 0 if
578  * we encounter a non-ASCII or non-printable character or don't find
579  * the line ending.
580  */
581 static u_int
582 print_txt_line(netdissect_options *ndo, const char *protoname,
583     const char *prefix, const u_char *pptr, u_int idx, u_int len)
584 {
585 	u_int startidx;
586 	u_int linelen;
587 
588 	startidx = idx;
589 	while (idx < len) {
590 		ND_TCHECK(*(pptr+idx));
591 		if (*(pptr+idx) == '\n') {
592 			/*
593 			 * LF without CR; end of line.
594 			 * Skip the LF and print the line, with the
595 			 * exception of the LF.
596 			 */
597 			linelen = idx - startidx;
598 			idx++;
599 			goto print;
600 		} else if (*(pptr+idx) == '\r') {
601 			/* CR - any LF? */
602 			if ((idx+1) >= len) {
603 				/* not in this packet */
604 				return (0);
605 			}
606 			ND_TCHECK(*(pptr+idx+1));
607 			if (*(pptr+idx+1) == '\n') {
608 				/*
609 				 * CR-LF; end of line.
610 				 * Skip the CR-LF and print the line, with
611 				 * the exception of the CR-LF.
612 				 */
613 				linelen = idx - startidx;
614 				idx += 2;
615 				goto print;
616 			}
617 
618 			/*
619 			 * CR followed by something else; treat this
620 			 * as if it were binary data, and don't print
621 			 * it.
622 			 */
623 			return (0);
624 		} else if (!isascii(*(pptr+idx)) ||
625 		    (!isprint(*(pptr+idx)) && *(pptr+idx) != '\t')) {
626 			/*
627 			 * Not a printable ASCII character and not a tab;
628 			 * treat this as if it were binary data, and
629 			 * don't print it.
630 			 */
631 			return (0);
632 		}
633 		idx++;
634 	}
635 
636 	/*
637 	 * All printable ASCII, but no line ending after that point
638 	 * in the buffer; treat this as if it were truncated.
639 	 */
640 trunc:
641 	linelen = idx - startidx;
642 	ND_PRINT((ndo, "%s%.*s[!%s]", prefix, (int)linelen, pptr + startidx,
643 	    protoname));
644 	return (0);
645 
646 print:
647 	ND_PRINT((ndo, "%s%.*s", prefix, (int)linelen, pptr + startidx));
648 	return (idx);
649 }
650 
651 void
652 txtproto_print(netdissect_options *ndo, const u_char *pptr, u_int len,
653     const char *protoname, const char **cmds, u_int flags)
654 {
655 	u_int idx, eol;
656 	u_char token[MAX_TOKEN+1];
657 	const char *cmd;
658 	int is_reqresp = 0;
659 	const char *pnp;
660 
661 	if (cmds != NULL) {
662 		/*
663 		 * This protocol has more than just request and
664 		 * response lines; see whether this looks like a
665 		 * request or response.
666 		 */
667 		idx = fetch_token(ndo, pptr, 0, len, token, sizeof(token));
668 		if (idx != 0) {
669 			/* Is this a valid request name? */
670 			while ((cmd = *cmds++) != NULL) {
671 				if (strcasecmp((const char *)token, cmd) == 0) {
672 					/* Yes. */
673 					is_reqresp = 1;
674 					break;
675 				}
676 			}
677 
678 			/*
679 			 * No - is this a valid response code (3 digits)?
680 			 *
681 			 * Is this token the response code, or is the next
682 			 * token the response code?
683 			 */
684 			if (flags & RESP_CODE_SECOND_TOKEN) {
685 				/*
686 				 * Next token - get it.
687 				 */
688 				idx = fetch_token(ndo, pptr, idx, len, token,
689 				    sizeof(token));
690 			}
691 			if (idx != 0) {
692 				if (isdigit(token[0]) && isdigit(token[1]) &&
693 				    isdigit(token[2]) && token[3] == '\0') {
694 					/* Yes. */
695 					is_reqresp = 1;
696 				}
697 			}
698 		}
699 	} else {
700 		/*
701 		 * This protocol has only request and response lines
702 		 * (e.g., FTP, where all the data goes over a
703 		 * different connection); assume the payload is
704 		 * a request or response.
705 		 */
706 		is_reqresp = 1;
707 	}
708 
709 	/* Capitalize the protocol name */
710 	for (pnp = protoname; *pnp != '\0'; pnp++)
711 		ND_PRINT((ndo, "%c", toupper((unsigned char)*pnp)));
712 
713 	if (is_reqresp) {
714 		/*
715 		 * In non-verbose mode, just print the protocol, followed
716 		 * by the first line as the request or response info.
717 		 *
718 		 * In verbose mode, print lines as text until we run out
719 		 * of characters or see something that's not a
720 		 * printable-ASCII line.
721 		 */
722 		if (ndo->ndo_vflag) {
723 			/*
724 			 * We're going to print all the text lines in the
725 			 * request or response; just print the length
726 			 * on the first line of the output.
727 			 */
728 			ND_PRINT((ndo, ", length: %u", len));
729 			for (idx = 0;
730 			    idx < len && (eol = print_txt_line(ndo, protoname, "\n\t", pptr, idx, len)) != 0;
731 			    idx = eol)
732 				;
733 		} else {
734 			/*
735 			 * Just print the first text line.
736 			 */
737 			print_txt_line(ndo, protoname, ": ", pptr, 0, len);
738 		}
739 	}
740 }
741 
742 /* VARARGS */
743 void
744 error(const char *fmt, ...)
745 {
746 	va_list ap;
747 
748 	(void)fprintf(stderr, "%s: ", program_name);
749 	va_start(ap, fmt);
750 	(void)vfprintf(stderr, fmt, ap);
751 	va_end(ap);
752 	if (*fmt) {
753 		fmt += strlen(fmt);
754 		if (fmt[-1] != '\n')
755 			(void)fputc('\n', stderr);
756 	}
757 	exit(1);
758 	/* NOTREACHED */
759 }
760 
761 /* VARARGS */
762 void
763 warning(const char *fmt, ...)
764 {
765 	va_list ap;
766 
767 	(void)fprintf(stderr, "%s: WARNING: ", program_name);
768 	va_start(ap, fmt);
769 	(void)vfprintf(stderr, fmt, ap);
770 	va_end(ap);
771 	if (*fmt) {
772 		fmt += strlen(fmt);
773 		if (fmt[-1] != '\n')
774 			(void)fputc('\n', stderr);
775 	}
776 }
777 
778 /*
779  * Copy arg vector into a new buffer, concatenating arguments with spaces.
780  */
781 char *
782 copy_argv(register char **argv)
783 {
784 	register char **p;
785 	register u_int len = 0;
786 	char *buf;
787 	char *src, *dst;
788 
789 	p = argv;
790 	if (*p == 0)
791 		return 0;
792 
793 	while (*p)
794 		len += strlen(*p++) + 1;
795 
796 	buf = (char *)malloc(len);
797 	if (buf == NULL)
798 		error("copy_argv: malloc");
799 
800 	p = argv;
801 	dst = buf;
802 	while ((src = *p++) != NULL) {
803 		while ((*dst++ = *src++) != '\0')
804 			;
805 		dst[-1] = ' ';
806 	}
807 	dst[-1] = '\0';
808 
809 	return buf;
810 }
811 
812 /*
813  * On Windows, we need to open the file in binary mode, so that
814  * we get all the bytes specified by the size we get from "fstat()".
815  * On UNIX, that's not necessary.  O_BINARY is defined on Windows;
816  * we define it as 0 if it's not defined, so it does nothing.
817  */
818 #ifndef O_BINARY
819 #define O_BINARY	0
820 #endif
821 
822 char *
823 read_infile(char *fname)
824 {
825 	register int i, fd, cc;
826 	register char *cp;
827 	struct stat buf;
828 
829 	fd = open(fname, O_RDONLY|O_BINARY);
830 	if (fd < 0)
831 		error("can't open %s: %s", fname, pcap_strerror(errno));
832 
833 	if (fstat(fd, &buf) < 0)
834 		error("can't stat %s: %s", fname, pcap_strerror(errno));
835 
836 	cp = malloc((u_int)buf.st_size + 1);
837 	if (cp == NULL)
838 		error("malloc(%d) for %s: %s", (u_int)buf.st_size + 1,
839 			fname, pcap_strerror(errno));
840 	cc = read(fd, cp, (u_int)buf.st_size);
841 	if (cc < 0)
842 		error("read %s: %s", fname, pcap_strerror(errno));
843 	if (cc != buf.st_size)
844 		error("short read %s (%d != %d)", fname, cc, (int)buf.st_size);
845 
846 	close(fd);
847 	/* replace "# comment" with spaces */
848 	for (i = 0; i < cc; i++) {
849 		if (cp[i] == '#')
850 			while (i < cc && cp[i] != '\n')
851 				cp[i++] = ' ';
852 	}
853 	cp[cc] = '\0';
854 	return (cp);
855 }
856 
857 void
858 safeputs(netdissect_options *ndo,
859          const u_char *s, const u_int maxlen)
860 {
861 	u_int idx = 0;
862 
863 	while (*s && idx < maxlen) {
864 		safeputchar(ndo, *s);
865 		idx++;
866 		s++;
867 	}
868 }
869 
870 void
871 safeputchar(netdissect_options *ndo,
872             const u_char c)
873 {
874 	ND_PRINT((ndo, (c < 0x80 && ND_ISPRINT(c)) ? "%c" : "\\0x%02x", c));
875 }
876 
877 #ifdef LBL_ALIGN
878 /*
879  * Some compilers try to optimize memcpy(), using the alignment constraint
880  * on the argument pointer type.  by using this function, we try to avoid the
881  * optimization.
882  */
883 void
884 unaligned_memcpy(void *p, const void *q, size_t l)
885 {
886 	memcpy(p, q, l);
887 }
888 
889 /* As with memcpy(), so with memcmp(). */
890 int
891 unaligned_memcmp(const void *p, const void *q, size_t l)
892 {
893 	return (memcmp(p, q, l));
894 }
895 #endif
896