]> The Tcpdump Group git mirrors - tcpdump/blob - util-print.c
Include <config.h> unconditionally
[tcpdump] / util-print.c
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@gredler.at):
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 #include <config.h>
39
40 #include "netdissect-stdinc.h"
41
42 #include <sys/stat.h>
43
44 #ifdef HAVE_FCNTL_H
45 #include <fcntl.h>
46 #endif
47 #include <stdio.h>
48 #include <stdarg.h>
49 #include <stdlib.h>
50 #include <string.h>
51
52 #include "netdissect-ctype.h"
53
54 #include "netdissect.h"
55 #include "extract.h"
56 #include "ascii_strcasecmp.h"
57 #include "timeval-operations.h"
58
59 #define TOKBUFSIZE 128
60
61 enum date_flag { WITHOUT_DATE = 0, WITH_DATE = 1 };
62 enum time_flag { UTC_TIME = 0, LOCAL_TIME = 1 };
63
64 /*
65 * Print out a character, filtering out the non-printable ones
66 */
67 void
68 fn_print_char(netdissect_options *ndo, u_char c)
69 {
70 if (!ND_ISASCII(c)) {
71 c = ND_TOASCII(c);
72 ND_PRINT("M-");
73 }
74 if (!ND_ASCII_ISPRINT(c)) {
75 c ^= 0x40; /* DEL to ?, others to alpha */
76 ND_PRINT("^");
77 }
78 ND_PRINT("%c", c);
79 }
80
81 /*
82 * Print a null-terminated string, filtering out non-printable characters.
83 * DON'T USE IT with a pointer on the packet buffer because there is no
84 * truncation check. For this use, see the nd_printX() functions below.
85 */
86 void
87 fn_print_str(netdissect_options *ndo, const u_char *s)
88 {
89 while (*s != '\0') {
90 fn_print_char(ndo, *s);
91 s++;
92 }
93 }
94
95 /*
96 * Print out a null-terminated filename (or other ASCII string) from
97 * a fixed-length field in the packet buffer, or from what remains of
98 * the packet.
99 *
100 * n is the length of the fixed-length field, or the number of bytes
101 * remaining in the packet based on its on-the-network length.
102 *
103 * If ep is non-null, it should point just past the last captured byte
104 * of the packet, e.g. ndo->ndo_snapend. If ep is NULL, we assume no
105 * truncation check, other than the checks of the field length/remaining
106 * packet data length, is needed.
107 *
108 * Return the number of bytes of string processed, including the
109 * terminating null, if not truncated; as the terminating null is
110 * included in the count, and as there must be a terminating null,
111 * this will always be non-zero. Return 0 if truncated.
112 */
113 u_int
114 nd_printztn(netdissect_options *ndo,
115 const u_char *s, u_int n, const u_char *ep)
116 {
117 u_int bytes;
118 u_char c;
119
120 bytes = 0;
121 for (;;) {
122 if (n == 0 || (ep != NULL && s >= ep)) {
123 /*
124 * Truncated. This includes "no null before we
125 * got to the end of the fixed-length buffer or
126 * the end of the packet".
127 *
128 * XXX - BOOTP says "null-terminated", which
129 * means the maximum length of the string, in
130 * bytes, is 1 less than the size of the buffer,
131 * as there must always be a terminating null.
132 */
133 bytes = 0;
134 break;
135 }
136
137 c = GET_U_1(s);
138 s++;
139 bytes++;
140 n--;
141 if (c == '\0') {
142 /* End of string */
143 break;
144 }
145 fn_print_char(ndo, c);
146 }
147 return(bytes);
148 }
149
150 /*
151 * Print out a counted filename (or other ASCII string), part of
152 * the packet buffer.
153 * If ep is NULL, assume no truncation check is needed.
154 * Return true if truncated.
155 * Stop at ep (if given) or after n bytes, whichever is first.
156 */
157 int
158 nd_printn(netdissect_options *ndo,
159 const u_char *s, u_int n, const u_char *ep)
160 {
161 u_char c;
162
163 while (n > 0 && (ep == NULL || s < ep)) {
164 n--;
165 c = GET_U_1(s);
166 s++;
167 fn_print_char(ndo, c);
168 }
169 return (n == 0) ? 0 : 1;
170 }
171
172 /*
173 * Print a counted filename (or other ASCII string), part of
174 * the packet buffer, filtering out non-printable characters.
175 * Stop if truncated (via GET_U_1/longjmp) or after n bytes,
176 * whichever is first.
177 * The suffix comes from: j:longJmp, n:after N bytes.
178 */
179 void
180 nd_printjn(netdissect_options *ndo, const u_char *s, u_int n)
181 {
182 while (n != 0) {
183 fn_print_char(ndo, GET_U_1(s));
184 n--;
185 s++;
186 }
187 }
188
189 /*
190 * Print a null-padded filename (or other ASCII string), part of
191 * the packet buffer, filtering out non-printable characters.
192 * Stop if truncated (via GET_U_1/longjmp) or after n bytes or before
193 * the null char, whichever occurs first.
194 * The suffix comes from: j:longJmp, n:after N bytes, p:null-Padded.
195 */
196 void
197 nd_printjnp(netdissect_options *ndo, const u_char *s, u_int n)
198 {
199 u_char c;
200
201 while (n != 0) {
202 c = GET_U_1(s);
203 if (c == '\0')
204 break;
205 fn_print_char(ndo, c);
206 n--;
207 s++;
208 }
209 }
210
211 /*
212 * Print the timestamp .FRAC part (Microseconds/nanoseconds)
213 */
214 static void
215 ts_frac_print(netdissect_options *ndo, const struct timeval *tv)
216 {
217 #ifdef HAVE_PCAP_SET_TSTAMP_PRECISION
218 switch (ndo->ndo_tstamp_precision) {
219
220 case PCAP_TSTAMP_PRECISION_MICRO:
221 ND_PRINT(".%06u", (unsigned)tv->tv_usec);
222 break;
223
224 case PCAP_TSTAMP_PRECISION_NANO:
225 ND_PRINT(".%09u", (unsigned)tv->tv_usec);
226 break;
227
228 default:
229 ND_PRINT(".{unknown}");
230 break;
231 }
232 #else
233 ND_PRINT(".%06u", (unsigned)tv->tv_usec);
234 #endif
235 }
236
237 /*
238 * Print the timestamp as [YY:MM:DD] HH:MM:SS.FRAC.
239 * if time_flag == LOCAL_TIME print local time else UTC/GMT time
240 * if date_flag == WITH_DATE print YY:MM:DD before HH:MM:SS.FRAC
241 */
242 static void
243 ts_date_hmsfrac_print(netdissect_options *ndo, const struct timeval *tv,
244 enum date_flag date_flag, enum time_flag time_flag)
245 {
246 struct tm *tm;
247 char timebuf[32];
248 const char *timestr;
249
250 if (tv->tv_sec < 0) {
251 ND_PRINT("[timestamp < 1970-01-01 00:00:00 UTC]");
252 return;
253 }
254
255 if (time_flag == LOCAL_TIME)
256 tm = localtime(&tv->tv_sec);
257 else
258 tm = gmtime(&tv->tv_sec);
259
260 if (date_flag == WITH_DATE) {
261 timestr = nd_format_time(timebuf, sizeof(timebuf),
262 "%Y-%m-%d %H:%M:%S", tm);
263 } else {
264 timestr = nd_format_time(timebuf, sizeof(timebuf),
265 "%H:%M:%S", tm);
266 }
267 ND_PRINT("%s", timestr);
268
269 ts_frac_print(ndo, tv);
270 }
271
272 /*
273 * Print the timestamp - Unix timeval style, as SECS.FRAC.
274 */
275 static void
276 ts_unix_print(netdissect_options *ndo, const struct timeval *tv)
277 {
278 if (tv->tv_sec < 0) {
279 ND_PRINT("[timestamp < 1970-01-01 00:00:00 UTC]");
280 return;
281 }
282
283 ND_PRINT("%u", (unsigned)tv->tv_sec);
284 ts_frac_print(ndo, tv);
285 }
286
287 /*
288 * Print the timestamp
289 */
290 void
291 ts_print(netdissect_options *ndo,
292 const struct timeval *tvp)
293 {
294 static struct timeval tv_ref;
295 struct timeval tv_result;
296 int negative_offset;
297 int nano_prec;
298
299 switch (ndo->ndo_tflag) {
300
301 case 0: /* Default */
302 ts_date_hmsfrac_print(ndo, tvp, WITHOUT_DATE, LOCAL_TIME);
303 ND_PRINT(" ");
304 break;
305
306 case 1: /* No time stamp */
307 break;
308
309 case 2: /* Unix timeval style */
310 ts_unix_print(ndo, tvp);
311 ND_PRINT(" ");
312 break;
313
314 case 3: /* Microseconds/nanoseconds since previous packet */
315 case 5: /* Microseconds/nanoseconds since first packet */
316 #ifdef HAVE_PCAP_SET_TSTAMP_PRECISION
317 switch (ndo->ndo_tstamp_precision) {
318 case PCAP_TSTAMP_PRECISION_MICRO:
319 nano_prec = 0;
320 break;
321 case PCAP_TSTAMP_PRECISION_NANO:
322 nano_prec = 1;
323 break;
324 default:
325 nano_prec = 0;
326 break;
327 }
328 #else
329 nano_prec = 0;
330 #endif
331 if (!(netdissect_timevalisset(&tv_ref)))
332 tv_ref = *tvp; /* set timestamp for first packet */
333
334 negative_offset = netdissect_timevalcmp(tvp, &tv_ref, <);
335 if (negative_offset)
336 netdissect_timevalsub(&tv_ref, tvp, &tv_result, nano_prec);
337 else
338 netdissect_timevalsub(tvp, &tv_ref, &tv_result, nano_prec);
339
340 ND_PRINT((negative_offset ? "-" : " "));
341 ts_date_hmsfrac_print(ndo, &tv_result, WITHOUT_DATE, UTC_TIME);
342 ND_PRINT(" ");
343
344 if (ndo->ndo_tflag == 3)
345 tv_ref = *tvp; /* set timestamp for previous packet */
346 break;
347
348 case 4: /* Date + Default */
349 ts_date_hmsfrac_print(ndo, tvp, WITH_DATE, LOCAL_TIME);
350 ND_PRINT(" ");
351 break;
352 }
353 }
354
355 /*
356 * Print an unsigned relative number of seconds (e.g. hold time, prune timer)
357 * in the form 5m1s. This does no truncation, so 32230861 seconds
358 * is represented as 1y1w1d1h1m1s.
359 */
360 void
361 unsigned_relts_print(netdissect_options *ndo,
362 uint32_t secs)
363 {
364 static const char *lengths[] = {"y", "w", "d", "h", "m", "s"};
365 static const u_int seconds[] = {31536000, 604800, 86400, 3600, 60, 1};
366 const char **l = lengths;
367 const u_int *s = seconds;
368
369 if (secs == 0) {
370 ND_PRINT("0s");
371 return;
372 }
373 while (secs != 0) {
374 if (secs >= *s) {
375 ND_PRINT("%u%s", secs / *s, *l);
376 secs -= (secs / *s) * *s;
377 }
378 s++;
379 l++;
380 }
381 }
382
383 /*
384 * Print a signed relative number of seconds (e.g. hold time, prune timer)
385 * in the form 5m1s. This does no truncation, so 32230861 seconds
386 * is represented as 1y1w1d1h1m1s.
387 */
388 void
389 signed_relts_print(netdissect_options *ndo,
390 int32_t secs)
391 {
392 if (secs < 0) {
393 ND_PRINT("-");
394 if (secs == INT32_MIN) {
395 /*
396 * -2^31; you can't fit its absolute value into
397 * a 32-bit signed integer.
398 *
399 * Just directly pass said absolute value to
400 * unsigned_relts_print() directly.
401 *
402 * (XXX - does ISO C guarantee that -(-2^n),
403 * when calculated and cast to an n-bit unsigned
404 * integer type, will have the value 2^n?)
405 */
406 unsigned_relts_print(ndo, 2147483648U);
407 } else {
408 /*
409 * We now know -secs will fit into an int32_t;
410 * negate it and pass that to unsigned_relts_print().
411 */
412 unsigned_relts_print(ndo, -secs);
413 }
414 return;
415 }
416 unsigned_relts_print(ndo, secs);
417 }
418
419 /*
420 * Format a struct tm with strftime().
421 * If the pointer to the struct tm is null, that means that the
422 * routine to convert a time_t to a struct tm failed; the localtime()
423 * and gmtime() in the Microsoft Visual Studio C library will fail,
424 * returning null, if the value is before the UNIX Epoch.
425 */
426 const char *
427 nd_format_time(char *buf, size_t bufsize, const char *format,
428 const struct tm *timeptr)
429 {
430 if (timeptr != NULL) {
431 if (strftime(buf, bufsize, format, timeptr) != 0)
432 return (buf);
433 else
434 return ("[nd_format_time() buffer is too small]");
435 } else
436 return ("[localtime() or gmtime() couldn't convert the date and time]");
437 }
438
439 /* Print the truncated string */
440 void nd_print_trunc(netdissect_options *ndo)
441 {
442 ND_PRINT(" [|%s]", ndo->ndo_protocol);
443 }
444
445 /* Print the protocol name */
446 void nd_print_protocol(netdissect_options *ndo)
447 {
448 ND_PRINT("%s", ndo->ndo_protocol);
449 }
450
451 /* Print the protocol name in caps (uppercases) */
452 void nd_print_protocol_caps(netdissect_options *ndo)
453 {
454 const char *p;
455 for (p = ndo->ndo_protocol; *p != '\0'; p++)
456 ND_PRINT("%c", ND_ASCII_TOUPPER(*p));
457 }
458
459 /* Print the invalid string */
460 void nd_print_invalid(netdissect_options *ndo)
461 {
462 ND_PRINT(" (invalid)");
463 }
464
465 /*
466 * this is a generic routine for printing unknown data;
467 * we pass on the linefeed plus indentation string to
468 * get a proper output - returns 0 on error
469 */
470
471 int
472 print_unknown_data(netdissect_options *ndo, const u_char *cp,
473 const char *indent, u_int len)
474 {
475 if (!ND_TTEST_LEN(cp, 0)) {
476 ND_PRINT("%sDissector error: %s() called with pointer past end of packet",
477 indent, __func__);
478 return(0);
479 }
480 hex_print(ndo, indent, cp, ND_MIN(len, ND_BYTES_AVAILABLE_AFTER(cp)));
481 return(1); /* everything is ok */
482 }
483
484 /*
485 * Convert a token value to a string; use "fmt" if not found.
486 */
487 static const char *
488 tok2strbuf(const struct tok *lp, const char *fmt,
489 const u_int v, char *buf, const size_t bufsize)
490 {
491 if (lp != NULL) {
492 while (lp->s != NULL) {
493 if (lp->v == v)
494 return (lp->s);
495 ++lp;
496 }
497 }
498 if (fmt == NULL)
499 fmt = "#%d";
500
501 (void)snprintf(buf, bufsize, fmt, v);
502 return (const char *)buf;
503 }
504
505 /*
506 * Convert a token value to a string; use "fmt" if not found.
507 * Uses tok2strbuf() on one of four local static buffers of size TOKBUFSIZE
508 * in round-robin fashion.
509 */
510 const char *
511 tok2str(const struct tok *lp, const char *fmt, const u_int v)
512 {
513 static char buf[4][TOKBUFSIZE];
514 static int idx = 0;
515 char *ret;
516
517 ret = buf[idx];
518 idx = (idx+1) & 3;
519 return tok2strbuf(lp, fmt, v, ret, sizeof(buf[0]));
520 }
521
522 /*
523 * Convert a bit token value to a string; use "fmt" if not found.
524 * this is useful for parsing bitfields, the output strings are separated
525 * if the s field is positive.
526 *
527 * A token matches iff it has one or more bits set and every bit that is set
528 * in the token is set in v. Consequently, a 0 token never matches.
529 */
530 static char *
531 bittok2str_internal(const struct tok *lp, const char *fmt,
532 const u_int v, const char *sep)
533 {
534 static char buf[1024+1]; /* our string buffer */
535 char *bufp = buf;
536 size_t space_left = sizeof(buf), string_size;
537 const char * sepstr = "";
538
539 while (lp != NULL && lp->s != NULL) {
540 if (lp->v && (v & lp->v) == lp->v) {
541 /* ok we have found something */
542 if (space_left <= 1)
543 return (buf); /* only enough room left for NUL, if that */
544 string_size = strlcpy(bufp, sepstr, space_left);
545 if (string_size >= space_left)
546 return (buf); /* we ran out of room */
547 bufp += string_size;
548 space_left -= string_size;
549 if (space_left <= 1)
550 return (buf); /* only enough room left for NUL, if that */
551 string_size = strlcpy(bufp, lp->s, space_left);
552 if (string_size >= space_left)
553 return (buf); /* we ran out of room */
554 bufp += string_size;
555 space_left -= string_size;
556 sepstr = sep;
557 }
558 lp++;
559 }
560
561 if (bufp == buf)
562 /* bummer - lets print the "unknown" message as advised in the fmt string if we got one */
563 (void)snprintf(buf, sizeof(buf), fmt == NULL ? "#%08x" : fmt, v);
564 return (buf);
565 }
566
567 /*
568 * Convert a bit token value to a string; use "fmt" if not found.
569 * this is useful for parsing bitfields, the output strings are not separated.
570 */
571 char *
572 bittok2str_nosep(const struct tok *lp, const char *fmt, const u_int v)
573 {
574 return (bittok2str_internal(lp, fmt, v, ""));
575 }
576
577 /*
578 * Convert a bit token value to a string; use "fmt" if not found.
579 * this is useful for parsing bitfields, the output strings are comma separated.
580 */
581 char *
582 bittok2str(const struct tok *lp, const char *fmt, const u_int v)
583 {
584 return (bittok2str_internal(lp, fmt, v, ", "));
585 }
586
587 /*
588 * Convert a value to a string using an array; the macro
589 * tok2strary() in <netdissect.h> is the public interface to
590 * this function and ensures that the second argument is
591 * correct for bounds-checking.
592 */
593 const char *
594 tok2strary_internal(const char **lp, int n, const char *fmt, const int v)
595 {
596 static char buf[TOKBUFSIZE];
597
598 if (v >= 0 && v < n && lp[v] != NULL)
599 return lp[v];
600 if (fmt == NULL)
601 fmt = "#%d";
602 (void)snprintf(buf, sizeof(buf), fmt, v);
603 return (buf);
604 }
605
606 const struct tok *
607 uint2tokary_internal(const struct uint_tokary dict[], const size_t size,
608 const u_int val)
609 {
610 size_t i;
611 /* Try a direct lookup before the full scan. */
612 if (val < size && dict[val].uintval == val)
613 return dict[val].tokary; /* OK if NULL */
614 for (i = 0; i < size; i++)
615 if (dict[i].uintval == val)
616 return dict[i].tokary; /* OK if NULL */
617 return NULL;
618 }
619
620 /*
621 * Convert a 32-bit netmask to prefixlen if possible
622 * the function returns the prefix-len; if plen == -1
623 * then conversion was not possible;
624 */
625
626 int
627 mask2plen(const uint32_t mask)
628 {
629 const uint32_t bitmasks[33] = {
630 0x00000000,
631 0x80000000, 0xc0000000, 0xe0000000, 0xf0000000,
632 0xf8000000, 0xfc000000, 0xfe000000, 0xff000000,
633 0xff800000, 0xffc00000, 0xffe00000, 0xfff00000,
634 0xfff80000, 0xfffc0000, 0xfffe0000, 0xffff0000,
635 0xffff8000, 0xffffc000, 0xffffe000, 0xfffff000,
636 0xfffff800, 0xfffffc00, 0xfffffe00, 0xffffff00,
637 0xffffff80, 0xffffffc0, 0xffffffe0, 0xfffffff0,
638 0xfffffff8, 0xfffffffc, 0xfffffffe, 0xffffffff
639 };
640 int prefix_len = 32;
641
642 /* let's see if we can transform the mask into a prefixlen */
643 while (prefix_len >= 0) {
644 if (bitmasks[prefix_len] == mask)
645 break;
646 prefix_len--;
647 }
648 return (prefix_len);
649 }
650
651 int
652 mask62plen(const u_char *mask)
653 {
654 u_char bitmasks[9] = {
655 0x00,
656 0x80, 0xc0, 0xe0, 0xf0,
657 0xf8, 0xfc, 0xfe, 0xff
658 };
659 int byte;
660 int cidr_len = 0;
661
662 for (byte = 0; byte < 16; byte++) {
663 u_int bits;
664
665 for (bits = 0; bits < (sizeof (bitmasks) / sizeof (bitmasks[0])); bits++) {
666 if (mask[byte] == bitmasks[bits]) {
667 cidr_len += bits;
668 break;
669 }
670 }
671
672 if (mask[byte] != 0xff)
673 break;
674 }
675 return (cidr_len);
676 }
677
678 /*
679 * Routine to print out information for text-based protocols such as FTP,
680 * HTTP, SMTP, RTSP, SIP, ....
681 */
682 #define MAX_TOKEN 128
683
684 /*
685 * Fetch a token from a packet, starting at the specified index,
686 * and return the length of the token.
687 *
688 * Returns 0 on error; yes, this is indistinguishable from an empty
689 * token, but an "empty token" isn't a valid token - it just means
690 * either a space character at the beginning of the line (this
691 * includes a blank line) or no more tokens remaining on the line.
692 */
693 static u_int
694 fetch_token(netdissect_options *ndo, const u_char *pptr, u_int idx, u_int len,
695 u_char *tbuf, size_t tbuflen)
696 {
697 size_t toklen = 0;
698 u_char c;
699
700 for (; idx < len; idx++) {
701 if (!ND_TTEST_1(pptr + idx)) {
702 /* ran past end of captured data */
703 return (0);
704 }
705 c = GET_U_1(pptr + idx);
706 if (!ND_ISASCII(c)) {
707 /* not an ASCII character */
708 return (0);
709 }
710 if (c == ' ' || c == '\t' || c == '\r' || c == '\n') {
711 /* end of token */
712 break;
713 }
714 if (!ND_ASCII_ISPRINT(c)) {
715 /* not part of a command token or response code */
716 return (0);
717 }
718 if (toklen + 2 > tbuflen) {
719 /* no room for this character and terminating '\0' */
720 return (0);
721 }
722 tbuf[toklen] = c;
723 toklen++;
724 }
725 if (toklen == 0) {
726 /* no token */
727 return (0);
728 }
729 tbuf[toklen] = '\0';
730
731 /*
732 * Skip past any white space after the token, until we see
733 * an end-of-line (CR or LF).
734 */
735 for (; idx < len; idx++) {
736 if (!ND_TTEST_1(pptr + idx)) {
737 /* ran past end of captured data */
738 break;
739 }
740 c = GET_U_1(pptr + idx);
741 if (c == '\r' || c == '\n') {
742 /* end of line */
743 break;
744 }
745 if (!ND_ASCII_ISPRINT(c)) {
746 /* not a printable ASCII character */
747 break;
748 }
749 if (c != ' ' && c != '\t' && c != '\r' && c != '\n') {
750 /* beginning of next token */
751 break;
752 }
753 }
754 return (idx);
755 }
756
757 /*
758 * Scan a buffer looking for a line ending - LF or CR-LF.
759 * Return the index of the character after the line ending or 0 if
760 * we encounter a non-ASCII or non-printable character or don't find
761 * the line ending.
762 */
763 static u_int
764 print_txt_line(netdissect_options *ndo, const char *prefix,
765 const u_char *pptr, u_int idx, u_int len)
766 {
767 u_int startidx;
768 u_int linelen;
769 u_char c;
770
771 startidx = idx;
772 while (idx < len) {
773 c = GET_U_1(pptr + idx);
774 if (c == '\n') {
775 /*
776 * LF without CR; end of line.
777 * Skip the LF and print the line, with the
778 * exception of the LF.
779 */
780 linelen = idx - startidx;
781 idx++;
782 goto print;
783 } else if (c == '\r') {
784 /* CR - any LF? */
785 if ((idx+1) >= len) {
786 /* not in this packet */
787 return (0);
788 }
789 if (GET_U_1(pptr + idx + 1) == '\n') {
790 /*
791 * CR-LF; end of line.
792 * Skip the CR-LF and print the line, with
793 * the exception of the CR-LF.
794 */
795 linelen = idx - startidx;
796 idx += 2;
797 goto print;
798 }
799
800 /*
801 * CR followed by something else; treat this
802 * as if it were binary data, and don't print
803 * it.
804 */
805 return (0);
806 } else if (!ND_ASCII_ISPRINT(c) && c != '\t') {
807 /*
808 * Not a printable ASCII character and not a tab;
809 * treat this as if it were binary data, and
810 * don't print it.
811 */
812 return (0);
813 }
814 idx++;
815 }
816
817 /*
818 * All printable ASCII, but no line ending after that point
819 * in the buffer.
820 */
821 linelen = idx - startidx;
822 ND_PRINT("%s%.*s", prefix, (int)linelen, pptr + startidx);
823 return (0);
824
825 print:
826 ND_PRINT("%s%.*s", prefix, (int)linelen, pptr + startidx);
827 return (idx);
828 }
829
830 /* Assign needed before calling txtproto_print(): ndo->ndo_protocol = "proto" */
831 void
832 txtproto_print(netdissect_options *ndo, const u_char *pptr, u_int len,
833 const char **cmds, u_int flags)
834 {
835 u_int idx, eol;
836 u_char token[MAX_TOKEN+1];
837 const char *cmd;
838 int print_this = 0;
839
840 if (cmds != NULL) {
841 /*
842 * This protocol has more than just request and
843 * response lines; see whether this looks like a
844 * request or response and, if so, print it and,
845 * in verbose mode, print everything after it.
846 *
847 * This is for HTTP-like protocols, where we
848 * want to print requests and responses, but
849 * don't want to print continuations of request
850 * or response bodies in packets that don't
851 * contain the request or response line.
852 */
853 idx = fetch_token(ndo, pptr, 0, len, token, sizeof(token));
854 if (idx != 0) {
855 /* Is this a valid request name? */
856 while ((cmd = *cmds++) != NULL) {
857 if (ascii_strcasecmp((const char *)token, cmd) == 0) {
858 /* Yes. */
859 print_this = 1;
860 break;
861 }
862 }
863
864 /*
865 * No - is this a valid response code (3 digits)?
866 *
867 * Is this token the response code, or is the next
868 * token the response code?
869 */
870 if (flags & RESP_CODE_SECOND_TOKEN) {
871 /*
872 * Next token - get it.
873 */
874 idx = fetch_token(ndo, pptr, idx, len, token,
875 sizeof(token));
876 }
877 if (idx != 0) {
878 if (ND_ASCII_ISDIGIT(token[0]) && ND_ASCII_ISDIGIT(token[1]) &&
879 ND_ASCII_ISDIGIT(token[2]) && token[3] == '\0') {
880 /* Yes. */
881 print_this = 1;
882 }
883 }
884 }
885 } else {
886 /*
887 * Either:
888 *
889 * 1) This protocol has only request and response lines
890 * (e.g., FTP, where all the data goes over a different
891 * connection); assume the payload is a request or
892 * response.
893 *
894 * or
895 *
896 * 2) This protocol is just text, so that we should
897 * always, at minimum, print the first line and,
898 * in verbose mode, print all lines.
899 */
900 print_this = 1;
901 }
902
903 nd_print_protocol_caps(ndo);
904
905 if (print_this) {
906 /*
907 * In non-verbose mode, just print the protocol, followed
908 * by the first line.
909 *
910 * In verbose mode, print lines as text until we run out
911 * of characters or see something that's not a
912 * printable-ASCII line.
913 */
914 if (ndo->ndo_vflag) {
915 /*
916 * We're going to print all the text lines in the
917 * request or response; just print the length
918 * on the first line of the output.
919 */
920 ND_PRINT(", length: %u", len);
921 for (idx = 0;
922 idx < len && (eol = print_txt_line(ndo, "\n\t", pptr, idx, len)) != 0;
923 idx = eol)
924 ;
925 } else {
926 /*
927 * Just print the first text line.
928 */
929 print_txt_line(ndo, ": ", pptr, 0, len);
930 }
931 }
932 }
933
934 #if (defined(__i386__) || defined(_M_IX86) || defined(__X86__) || defined(__x86_64__) || defined(_M_X64)) || \
935 (defined(__arm__) || defined(_M_ARM) || defined(__aarch64__)) || \
936 (defined(__m68k__) && (!defined(__mc68000__) && !defined(__mc68010__))) || \
937 (defined(__ppc__) || defined(__ppc64__) || defined(_M_PPC) || defined(_ARCH_PPC) || defined(_ARCH_PPC64)) || \
938 (defined(__s390__) || defined(__s390x__) || defined(__zarch__)) || \
939 defined(__vax__)
940 /*
941 * The processor natively handles unaligned loads, so just use memcpy()
942 * and memcmp(), to enable those optimizations.
943 *
944 * XXX - are those all the x86 tests we need?
945 * XXX - do we need to worry about ARMv1 through ARMv5, which didn't
946 * support unaligned loads, and, if so, do we need to worry about all
947 * of them, or just some of them, e.g. ARMv5?
948 * XXX - are those the only 68k tests we need not to generated
949 * unaligned accesses if the target is the 68000 or 68010?
950 * XXX - are there any tests we don't need, because some definitions are for
951 * compilers that also predefine the GCC symbols?
952 * XXX - do we need to test for both 32-bit and 64-bit versions of those
953 * architectures in all cases?
954 */
955 #else
956 /*
957 * The processor doesn't natively handle unaligned loads,
958 * and the compiler might "helpfully" optimize memcpy()
959 * and memcmp(), when handed pointers that would normally
960 * be properly aligned, into sequences that assume proper
961 * alignment.
962 *
963 * Do copies and compares of possibly-unaligned data by
964 * calling routines that wrap memcpy() and memcmp(), to
965 * prevent that optimization.
966 */
967 void
968 unaligned_memcpy(void *p, const void *q, size_t l)
969 {
970 memcpy(p, q, l);
971 }
972
973 /* As with memcpy(), so with memcmp(). */
974 int
975 unaligned_memcmp(const void *p, const void *q, size_t l)
976 {
977 return (memcmp(p, q, l));
978 }
979 #endif
980