util-print.c 23 KB

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