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@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
fn_print(netdissect_options * ndo,register const u_char * s,register const u_char * ep)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
fn_printn(netdissect_options * ndo,register const u_char * s,register u_int n,register const u_char * ep)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
fn_printzp(netdissect_options * ndo,register const u_char * s,register u_int n,register const u_char * ep)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 *
ts_format(netdissect_options * ndo _U_,int sec,int usec)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
ts_print(netdissect_options * ndo,register const struct timeval * tvp)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
relts_print(netdissect_options * ndo,int secs)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
print_unknown_data(netdissect_options * ndo,const u_char * cp,const char * ident,int len)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 *
tok2strbuf(register const struct tok * lp,register const char * fmt,register u_int v,char * buf,size_t bufsize)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 *
tok2str(register const struct tok * lp,register const char * fmt,register u_int v)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 *
bittok2str_internal(register const struct tok * lp,register const char * fmt,register u_int v,const char * sep)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 *
bittok2str_nosep(register const struct tok * lp,register const char * fmt,register u_int v)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 *
bittok2str(register const struct tok * lp,register const char * fmt,register u_int v)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 *
tok2strary_internal(register const char ** lp,int n,register const char * fmt,register int v)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
mask2plen(uint32_t mask)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
mask62plen(const u_char * mask)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
fetch_token(netdissect_options * ndo,const u_char * pptr,u_int idx,u_int len,u_char * tbuf,size_t tbuflen)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
print_txt_line(netdissect_options * ndo,const char * protoname,const char * prefix,const u_char * pptr,u_int idx,u_int len)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
txtproto_print(netdissect_options * ndo,const u_char * pptr,u_int len,const char * protoname,const char ** cmds,u_int flags)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
error(const char * fmt,...)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
warning(const char * fmt,...)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 *
copy_argv(register char ** argv)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 *
read_infile(char * fname)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
safeputs(netdissect_options * ndo,const u_char * s,const u_int maxlen)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
safeputchar(netdissect_options * ndo,const u_char c)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
unaligned_memcpy(void * p,const void * q,size_t l)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
unaligned_memcmp(const void * p,const void * q,size_t l)886 unaligned_memcmp(const void *p, const void *q, size_t l)
887 {
888 return (memcmp(p, q, l));
889 }
890 #endif
891