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