mod_print.c 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326
  1. /*
  2. * mod_print.c
  3. *
  4. * Copyright (c) 2001 Dug Song <dugsong@monkey.org>
  5. *
  6. * $Id: mod_print.c 2000 2008-04-27 06:17:35Z aturner $
  7. */
  8. #include "config.h"
  9. #include <stdio.h>
  10. #include <stdlib.h>
  11. #include <string.h>
  12. #include "mod.h"
  13. #include "pkt.h"
  14. #define EXTRACT_16BITS(p) ((uint16_t)ntohs(*(uint16_t *)(p)))
  15. #define EXTRACT_32BITS(p) ((uint32_t)ntohl(*(uint32_t *)(p)))
  16. /* XXX - _print_* routines adapted from tcpdump */
  17. static void
  18. _print_icmp(u_char *p, int length)
  19. {
  20. struct ip_hdr *ip;
  21. struct icmp_hdr *icmp;
  22. ip = (struct ip_hdr *)p;
  23. icmp = (struct icmp_hdr *)(p + (ip->ip_hl * 4));
  24. /* XXX - truncation? */
  25. printf("%s > %s:", ip_ntoa(&ip->ip_src), ip_ntoa(&ip->ip_dst));
  26. printf(" icmp: type %d code %d", icmp->icmp_type, icmp->icmp_code);
  27. }
  28. void
  29. _print_tcp(unsigned char *p, int length)
  30. {
  31. struct ip_hdr *ip;
  32. struct tcp_hdr *tcp;
  33. u_short sport, dport, win, urp;
  34. u_long seq, ack;
  35. int len, tcp_hl;
  36. register char ch;
  37. ip = (struct ip_hdr *)p;
  38. tcp = (struct tcp_hdr *)(p + (ip->ip_hl * 4));
  39. len = length - (ip->ip_hl * 4);
  40. if (len < TCP_HDR_LEN) {
  41. printf("truncated-tcp %d", len);
  42. return;
  43. }
  44. sport = ntohs(tcp->th_sport);
  45. dport = ntohs(tcp->th_dport);
  46. seq = ntohl(tcp->th_seq);
  47. ack = ntohl(tcp->th_ack);
  48. win = ntohs(tcp->th_win);
  49. urp = ntohs(tcp->th_urp);
  50. tcp_hl = tcp->th_off * 4;
  51. printf("%s.%d > %s.%d: ", ip_ntoa(&ip->ip_src), sport,
  52. ip_ntoa(&ip->ip_dst), dport);
  53. if (tcp->th_flags & (TH_SYN|TH_FIN|TH_RST|TH_PUSH)) {
  54. if (tcp->th_flags & TH_SYN) putchar('S');
  55. if (tcp->th_flags & TH_FIN) putchar('F');
  56. if (tcp->th_flags & TH_RST) putchar('R');
  57. if (tcp->th_flags & TH_PUSH) putchar('P');
  58. } else
  59. putchar('.');
  60. if (tcp_hl > len) {
  61. printf(" [bad hdr length]");
  62. return;
  63. }
  64. len -= tcp_hl;
  65. if (len > 0 || tcp->th_flags & (TH_SYN | TH_FIN | TH_RST))
  66. printf(" %lu:%lu(%d)", seq, seq + len, len);
  67. if (tcp->th_flags & TH_ACK)
  68. printf(" ack %lu", ack);
  69. printf(" win %d", win);
  70. if (tcp->th_flags & TH_URG)
  71. printf(" urg %d", urp);
  72. /* Handle options. */
  73. if ((tcp_hl -= TCP_HDR_LEN) > 0) {
  74. register const u_char *cp;
  75. register int i, opt, len, datalen;
  76. cp = (const u_char *)tcp + TCP_HDR_LEN;
  77. putchar(' ');
  78. ch = '<';
  79. while (tcp_hl > 0) {
  80. putchar(ch);
  81. opt = *cp++;
  82. if (TCP_OPT_TYPEONLY(opt)) {
  83. len = 1;
  84. } else {
  85. len = *cp++; /* total including type, len */
  86. if (len < 2 || len > tcp_hl)
  87. goto bad;
  88. --tcp_hl; /* account for length byte */
  89. }
  90. --tcp_hl; /* account for type byte */
  91. datalen = 0;
  92. /* Bail if "l" bytes of data are not left or were not captured */
  93. #define LENCHECK(l) { if ((l) > tcp_hl) goto bad; }
  94. switch (opt) {
  95. case TCP_OPT_MSS:
  96. printf("mss");
  97. datalen = 2;
  98. LENCHECK(datalen);
  99. printf(" %u", EXTRACT_16BITS(cp));
  100. break;
  101. case TCP_OPT_EOL:
  102. printf("eol");
  103. break;
  104. case TCP_OPT_NOP:
  105. printf("nop");
  106. break;
  107. case TCP_OPT_WSCALE:
  108. printf("wscale");
  109. datalen = 1;
  110. LENCHECK(datalen);
  111. printf(" %u", *cp);
  112. break;
  113. case TCP_OPT_SACKOK:
  114. printf("sackOK");
  115. if (len != 2)
  116. printf("[len %d]", len);
  117. break;
  118. case TCP_OPT_SACK:
  119. datalen = len - 2;
  120. if ((datalen % 8) != 0 ||
  121. !(tcp->th_flags & TH_ACK)) {
  122. printf("malformed sack ");
  123. printf("[len %d] ", datalen);
  124. break;
  125. }
  126. printf("sack %d ", datalen / 8);
  127. break;
  128. case TCP_OPT_ECHO:
  129. printf("echo");
  130. datalen = 4;
  131. LENCHECK(datalen);
  132. printf(" %u", EXTRACT_32BITS(cp));
  133. break;
  134. case TCP_OPT_ECHOREPLY:
  135. printf("echoreply");
  136. datalen = 4;
  137. LENCHECK(datalen);
  138. printf(" %u", EXTRACT_32BITS(cp));
  139. break;
  140. case TCP_OPT_TIMESTAMP:
  141. printf("timestamp");
  142. datalen = 8;
  143. LENCHECK(4);
  144. printf(" %u", EXTRACT_32BITS(cp));
  145. LENCHECK(datalen);
  146. printf(" %u", EXTRACT_32BITS(cp + 4));
  147. break;
  148. case TCP_OPT_CC:
  149. printf("cc");
  150. datalen = 4;
  151. LENCHECK(datalen);
  152. printf(" %u", EXTRACT_32BITS(cp));
  153. break;
  154. case TCP_OPT_CCNEW:
  155. printf("ccnew");
  156. datalen = 4;
  157. LENCHECK(datalen);
  158. printf(" %u", EXTRACT_32BITS(cp));
  159. break;
  160. case TCP_OPT_CCECHO:
  161. printf("ccecho");
  162. datalen = 4;
  163. LENCHECK(datalen);
  164. printf(" %u", EXTRACT_32BITS(cp));
  165. break;
  166. default:
  167. printf("opt-%d:", opt);
  168. datalen = len - 2;
  169. for (i = 0; i < datalen; ++i) {
  170. LENCHECK(i);
  171. printf("%02x", cp[i]);
  172. }
  173. break;
  174. }
  175. /* Account for data printed */
  176. cp += datalen;
  177. tcp_hl -= datalen;
  178. /* Check specification against observed length */
  179. ++datalen; /* option octet */
  180. if (!TCP_OPT_TYPEONLY(opt))
  181. ++datalen; /* size octet */
  182. if (datalen != len)
  183. printf("[len %d]", len);
  184. ch = ',';
  185. if (opt == TCP_OPT_EOL)
  186. break;
  187. }
  188. putchar('>');
  189. }
  190. return;
  191. bad:
  192. fputs("[bad opt]", stdout);
  193. if (ch != '\0')
  194. putchar('>');
  195. return;
  196. }
  197. static void
  198. _print_udp(u_char *p, int length)
  199. {
  200. struct ip_hdr *ip;
  201. struct udp_hdr *udp;
  202. ip = (struct ip_hdr *)p;
  203. udp = (struct udp_hdr *)(p + (ip->ip_hl * 4));
  204. /* XXX - truncation? */
  205. printf("%s.%d > %s.%d:", ip_ntoa(&ip->ip_src), ntohs(udp->uh_sport),
  206. ip_ntoa(&ip->ip_dst), ntohs(udp->uh_dport));
  207. printf(" udp %d", ntohs(udp->uh_ulen) - UDP_HDR_LEN);
  208. }
  209. static void
  210. _print_ip(u_char *p, int length)
  211. {
  212. struct ip_hdr *ip;
  213. u_int ip_off, ip_hl, ip_len;
  214. ip = (struct ip_hdr *)p;
  215. if (length < IP_HDR_LEN) {
  216. printf("truncated-ip %d", length);
  217. return;
  218. }
  219. ip_hl = ip->ip_hl * 4;
  220. ip_len = ntohs(ip->ip_len);
  221. if (length < ip_len) {
  222. printf("truncated-ip - %d bytes missing!", ip_len - length);
  223. return;
  224. }
  225. ip_off = ntohs(ip->ip_off);
  226. /* Handle first fragment. */
  227. if ((ip_off & IP_OFFMASK) == 0) {
  228. switch (ip->ip_p) {
  229. case IP_PROTO_TCP:
  230. _print_tcp(p, ip_len);
  231. break;
  232. case IP_PROTO_UDP:
  233. _print_udp(p, ip_len);
  234. break;
  235. case IP_PROTO_ICMP:
  236. _print_icmp(p, ip_len);
  237. break;
  238. default:
  239. printf("%s > %s:", ip_ntoa(&ip->ip_src),
  240. ip_ntoa(&ip->ip_dst));
  241. printf(" ip-proto-%d %d", ip->ip_p, ip_len);
  242. break;
  243. }
  244. }
  245. /* Handle more frags. */
  246. if (ip_off & (IP_MF|IP_OFFMASK)) {
  247. if (ip_off & IP_OFFMASK)
  248. printf("%s > %s:", ip_ntoa(&ip->ip_src),
  249. ip_ntoa(&ip->ip_dst));
  250. printf(" (frag %d:%d@%d%s)", ntohs(ip->ip_id), ip_len - ip_hl,
  251. (ip_off & IP_OFFMASK) << 3, (ip_off & IP_MF) ? "+" : "");
  252. } else if (ip_off & IP_DF)
  253. printf(" (DF)");
  254. if (ip->ip_tos)
  255. printf(" [tos 0x%x]", ip->ip_tos);
  256. if (ip->ip_ttl <= 1)
  257. printf(" [ttl %d]", ip->ip_ttl);
  258. }
  259. static char *
  260. timerntoa(struct timeval *tv)
  261. {
  262. static char buf[128];
  263. uint64_t usec;
  264. usec = (tv->tv_sec * 1000000) + tv->tv_usec;
  265. snprintf(buf, sizeof(buf), "%d.%03d ms",
  266. (int)(usec / 1000), (int)(usec % 1000));
  267. return (buf);
  268. }
  269. int
  270. print_apply(void *d, struct pktq *pktq)
  271. {
  272. struct pkt *pkt;
  273. TAILQ_FOREACH(pkt, pktq, pkt_next) {
  274. _print_ip(pkt->pkt_eth_data, pkt->pkt_end - pkt->pkt_eth_data);
  275. if (timerisset(&pkt->pkt_ts))
  276. printf(" [delay %s]", timerntoa(&pkt->pkt_ts));
  277. printf("\n");
  278. }
  279. return (0);
  280. }
  281. struct mod mod_print = {
  282. "print", /* name */
  283. "print", /* usage */
  284. NULL, /* init */
  285. print_apply, /* apply */
  286. NULL /* close */
  287. };