tcpdump  4.99.1
About: tcpdump is a tool for network monitoring and data acquisition.
  Fossies Dox: tcpdump-4.99.1.tar.gz  ("unofficial" and yet experimental doxygen-generated source code documentation)  

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