ngrep.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884
  1. /*
  2. * $Id$
  3. *
  4. * Copyright (c) 2001 Jordan Ritter <[email protected]>
  5. *
  6. * Please refer to the COPYRIGHT file for more information.
  7. *
  8. */
  9. #if defined(BSD) || defined(SOLARIS) || defined(MACOSX)
  10. #include <unistd.h>
  11. #include <ctype.h>
  12. #include <sys/types.h>
  13. #include <sys/socket.h>
  14. #include <netinet/in.h>
  15. #include <netinet/in_systm.h>
  16. #include <net/if.h>
  17. #include <sys/tty.h>
  18. #endif
  19. #if defined(OSF1)
  20. #include <sys/types.h>
  21. #include <sys/socket.h>
  22. #include <netinet/in.h>
  23. #include <netinet/in_systm.h>
  24. #include <net/route.h>
  25. #include <sys/mbuf.h>
  26. #endif
  27. #if defined(LINUX)
  28. #include <getopt.h>
  29. #include <arpa/inet.h>
  30. #include <ctype.h>
  31. #include <time.h>
  32. #endif
  33. #if defined(AIX)
  34. #include <sys/machine.h>
  35. #include <sys/types.h>
  36. #include <netinet/in.h>
  37. #include <time.h>
  38. #endif
  39. #include <netinet/ip.h>
  40. #include <netinet/tcp.h>
  41. #include <netinet/udp.h>
  42. #include <netinet/ip_icmp.h>
  43. #include <pcap.h>
  44. #include <net/bpf.h>
  45. #include <stdlib.h>
  46. #include <string.h>
  47. #include <signal.h>
  48. #include <sys/ioctl.h>
  49. #include <locale.h>
  50. #ifdef USE_PCRE
  51. #include "pcre-3.4/pcre.h"
  52. #else
  53. #include "regex-0.12/regex.h"
  54. #endif
  55. #include "ngrep.h"
  56. #define dump(_a,_b) ( show_eol ? \
  57. dump_line_by_line((_a),(_b)) : _dump((_a),(_b)) )
  58. static char rcsver[] = "$Revision$";
  59. int snaplen = 65535, promisc = 1, to = 1000;
  60. int show_empty = 0, show_hex = 0, quiet = 0;
  61. int match_after = 0, keep_matching = 0;
  62. int invert_match = 0, bin_match = 0;
  63. int matches = 0, max_matches = 0;
  64. int live_read = 1, want_delay = 0;
  65. int show_eol=0;
  66. char pc_err[PCAP_ERRBUF_SIZE];
  67. #ifdef USE_PCRE
  68. int err_offset;
  69. char *re_err = NULL;
  70. #else
  71. const char *re_err = NULL;
  72. #endif
  73. int re_match_word = 0, re_ignore_case = 0;
  74. #ifdef USE_PCRE
  75. pcre *pattern = NULL;
  76. pcre_extra *pattern_extra = NULL;
  77. #else
  78. struct re_pattern_buffer pattern;
  79. #endif
  80. char *match_data = NULL, *bin_data = NULL, *filter = NULL;
  81. int (*match_func)() = &blank_match_func;
  82. int match_len = 0;
  83. struct bpf_program pcapfilter;
  84. struct in_addr net, mask;
  85. pcap_t *pd = NULL;
  86. char *dev = NULL;
  87. int link_offset;
  88. char *read_file = NULL, *dump_file = NULL;
  89. pcap_dumper_t *pd_dump = NULL;
  90. struct timeval prev_ts = {0, 0}, prev_delay_ts = {0,0};
  91. void (*print_time)() = NULL, (*dump_delay)() = dump_delay_proc_init;
  92. unsigned ws_row, ws_col;
  93. int main(int argc, char **argv) {
  94. int c;
  95. signal(SIGINT, clean_exit);
  96. signal(SIGQUIT, clean_exit);
  97. signal(SIGABRT, clean_exit);
  98. signal(SIGPIPE, clean_exit);
  99. signal(SIGWINCH, update_windowsize);
  100. setlocale(LC_ALL, "");
  101. while ((c = getopt(argc, argv, "LhXViwqpevxlDtTs:n:d:A:I:O:")) != EOF) {
  102. switch (c) {
  103. case 'L':
  104. show_eol=1;
  105. break;
  106. case 'I':
  107. read_file = optarg;
  108. break;
  109. case 'O':
  110. dump_file = optarg;
  111. break;
  112. case 'A':
  113. match_after = atoi(optarg) + 1;
  114. break;
  115. case 'd':
  116. dev = optarg;
  117. break;
  118. case 'n':
  119. max_matches = atoi(optarg);
  120. break;
  121. case 's':
  122. snaplen = atoi(optarg);
  123. break;
  124. case 'T':
  125. print_time = &print_time_diff_init;
  126. break;
  127. case 't':
  128. print_time = &print_time_absolute;
  129. break;
  130. case 'D':
  131. want_delay = 1;
  132. break;
  133. case 'l':
  134. setvbuf(stdout, NULL, _IOLBF, 0);
  135. break;
  136. case 'x':
  137. show_hex++;
  138. break;
  139. case 'v':
  140. invert_match++;
  141. break;
  142. case 'e':
  143. show_empty++;
  144. break;
  145. case 'p':
  146. promisc = 0;
  147. break;
  148. case 'q':
  149. quiet++;
  150. break;
  151. case 'w':
  152. re_match_word++;
  153. break;
  154. case 'i':
  155. re_ignore_case++;
  156. break;
  157. case 'V':
  158. version();
  159. case 'X':
  160. bin_match++;
  161. break;
  162. case 'h':
  163. usage(0);
  164. default:
  165. usage(-1);
  166. }
  167. }
  168. if (argv[optind])
  169. match_data = argv[optind++];
  170. if (read_file) {
  171. if (!(pd = pcap_open_offline(read_file, pc_err))) {
  172. perror(pc_err);
  173. clean_exit(-1);
  174. }
  175. live_read = 0;
  176. printf("input: %s\n", read_file);
  177. } else {
  178. if (!dev)
  179. if (!(dev = pcap_lookupdev(pc_err))) {
  180. perror(pc_err);
  181. clean_exit(-1);
  182. }
  183. if ((pd = pcap_open_live(dev, snaplen, promisc, to, pc_err)) == NULL) {
  184. perror(pc_err);
  185. clean_exit(-1);
  186. }
  187. if (pcap_lookupnet(dev, &net.s_addr, &mask.s_addr, pc_err) == -1) {
  188. perror(pc_err);
  189. memset(&net, 0, sizeof(net));
  190. memset(&mask, 0, sizeof(mask));
  191. }
  192. if (!quiet) {
  193. printf("interface: %s", dev);
  194. if (net.s_addr && mask.s_addr) {
  195. printf(" (%s/", inet_ntoa(net));
  196. printf("%s)", inet_ntoa(mask));
  197. }
  198. printf("\n");
  199. }
  200. }
  201. if (argv[optind]) {
  202. filter = get_filter(&argv[optind]);
  203. if (pcap_compile(pd, &pcapfilter, filter, 0, mask.s_addr)) {
  204. free(filter);
  205. filter = get_filter(&argv[optind-1]);
  206. #ifdef NEED_RESTART
  207. PCAP_RESTART();
  208. #endif
  209. if (pcap_compile(pd, &pcapfilter, filter, 0, mask.s_addr)) {
  210. pcap_perror(pd, "pcap compile");
  211. clean_exit(-1);
  212. } else match_data = NULL;
  213. }
  214. if (!quiet) printf("filter: %s\n", filter);
  215. if (pcap_setfilter(pd, &pcapfilter)) {
  216. pcap_perror(pd, "pcap set");
  217. clean_exit(-1);
  218. }
  219. }
  220. if (match_data) {
  221. if (bin_match) {
  222. int i = 0, n;
  223. char *s, *d;
  224. int len;
  225. if (re_match_word || re_ignore_case) {
  226. fprintf(stderr, "fatal: regex switches are incompatible with binary matching\n");
  227. clean_exit(-1);
  228. }
  229. len = strlen(match_data);
  230. if (len % 2 != 0 || !strishex(match_data)) {
  231. fprintf(stderr, "fatal: invalid hex string specified\n");
  232. clean_exit(-1);
  233. }
  234. bin_data = malloc(len / 2);
  235. memset(bin_data, 0, len / 2);
  236. d = bin_data;
  237. if ((s = strchr(match_data, 'x')))
  238. len -= ++s - match_data - 1;
  239. else s = match_data;
  240. while (i <= len) {
  241. sscanf(s+i, "%2x", &n);
  242. *d++ = n;
  243. i += 2;
  244. }
  245. match_len = len / 2;
  246. match_func = &bin_match_func;
  247. } else {
  248. #ifdef USE_PCRE
  249. int pcre_options = PCRE_UNGREEDY;
  250. if (re_ignore_case)
  251. pcre_options |= PCRE_CASELESS;
  252. re_err = malloc(512);
  253. #else
  254. re_syntax_options = RE_SYNTAX_EGREP;
  255. if (re_ignore_case) {
  256. char *s;
  257. int i;
  258. pattern.translate = (char*)malloc(256);
  259. s = pattern.translate;
  260. for (i = 0; i < 256; i++)
  261. s[i] = i;
  262. for (i = 'A'; i <= 'Z'; i++)
  263. s[i] = i + 32;
  264. s = match_data;
  265. while (*s)
  266. *s++ = tolower(*s);
  267. } else pattern.translate = NULL;
  268. #endif
  269. if (re_match_word) {
  270. char *word_regex = malloc(strlen(match_data) * 3 + strlen(WORD_REGEX));
  271. sprintf(word_regex, WORD_REGEX, match_data, match_data, match_data);
  272. match_data = word_regex;
  273. }
  274. #ifdef USE_PCRE
  275. pattern = pcre_compile(match_data, pcre_options, (const char **)&re_err, &err_offset, 0);
  276. if (!pattern) {
  277. fprintf(stderr, "compile failed: %s\n", re_err);
  278. clean_exit(-1);
  279. }
  280. pattern_extra = pcre_study(pattern, 0, (const char **)&re_err);
  281. free(re_err);
  282. re_err = NULL;
  283. #else
  284. re_err = re_compile_pattern(match_data, strlen(match_data), &pattern);
  285. if (re_err) {
  286. fprintf(stderr, "regex compile: %s\n", re_err);
  287. clean_exit(-1);
  288. }
  289. pattern.fastmap = (char*)malloc(256);
  290. if (re_compile_fastmap(&pattern)) {
  291. perror("fastmap compile failed");
  292. clean_exit(-1);
  293. }
  294. #endif
  295. match_func = &re_match_func;
  296. }
  297. if (!quiet && match_data && strlen(match_data))
  298. printf("%smatch: %s%s\n", invert_match?"don't ":"",
  299. (bin_data && !strchr(match_data, 'x'))?"0x":"", match_data);
  300. }
  301. if (filter) free(filter);
  302. if (re_match_word) free(match_data);
  303. switch(pcap_datalink(pd)) {
  304. case DLT_EN10MB:
  305. link_offset = ETHHDR_SIZE;
  306. break;
  307. case DLT_IEEE802:
  308. link_offset = TOKENRING_SIZE;
  309. break;
  310. case DLT_FDDI:
  311. link_offset = FDDIHDR_SIZE;
  312. break;
  313. case DLT_SLIP:
  314. link_offset = SLIPHDR_SIZE;
  315. break;
  316. case DLT_PPP:
  317. link_offset = PPPHDR_SIZE;
  318. break;
  319. case DLT_RAW:
  320. link_offset = RAWHDR_SIZE;
  321. break;
  322. case DLT_LOOP:
  323. case DLT_NULL:
  324. link_offset = LOOPHDR_SIZE;
  325. break;
  326. case DLT_LINUX_SLL:
  327. link_offset = ISDNHDR_SIZE;
  328. break;
  329. default:
  330. fprintf(stderr, "fatal: unsupported interface type %d\n", pcap_datalink(pd));
  331. clean_exit(-1);
  332. }
  333. if (dump_file) {
  334. if (!(pd_dump = pcap_dump_open(pd, dump_file))) {
  335. fprintf(stderr, "fatal: %s\n", pcap_geterr(pd));
  336. clean_exit(-1);
  337. } else printf("output: %s\n", dump_file);
  338. }
  339. update_windowsize(0);
  340. while (pcap_loop(pd, 0, (pcap_handler)process, 0));
  341. clean_exit(0);
  342. }
  343. void process(u_char *data1, struct pcap_pkthdr* h, u_char *p) {
  344. struct ip* ip_packet = (struct ip *)(p + link_offset);
  345. #if defined(AIX)
  346. #undef ip_hl
  347. unsigned ip_hl = ip_packet->ip_ff.ip_fhl*4;
  348. #else
  349. unsigned ip_hl = ip_packet->ip_hl*4;
  350. #endif
  351. unsigned ip_off = ntohs(ip_packet->ip_off);
  352. unsigned fragmented = ip_off & (IP_MF | IP_OFFMASK);
  353. unsigned frag_offset = fragmented?(ip_off & IP_OFFMASK) * 8:0;
  354. char *data;
  355. int len;
  356. switch (ip_packet->ip_p) {
  357. case IPPROTO_TCP: {
  358. struct tcphdr* tcp = (struct tcphdr *)(((char *)ip_packet) + ip_hl);
  359. unsigned tcphdr_offset = fragmented?0:(tcp->th_off * 4);
  360. if (!quiet) {
  361. printf("#");
  362. fflush(stdout);
  363. }
  364. data = ((char*)tcp) + tcphdr_offset;
  365. if ((len = ntohs(ip_packet->ip_len)) < h->caplen)
  366. len -= ip_hl + tcphdr_offset;
  367. else len = h->caplen - link_offset - ip_hl - tcphdr_offset;
  368. if (((len || show_empty) && (((int)(*match_func)(data, len)) != invert_match))
  369. || keep_matching) {
  370. if (!live_read && want_delay)
  371. dump_delay(h);
  372. printf("\nT ");
  373. if (print_time)
  374. print_time(h);
  375. if (tcphdr_offset || !frag_offset) {
  376. printf("%s:%d -", inet_ntoa(ip_packet->ip_src), ntohs(tcp->th_sport));
  377. printf("> %s:%d", inet_ntoa(ip_packet->ip_dst), ntohs(tcp->th_dport));
  378. printf(" [%s%s%s%s%s%s]",
  379. (tcp->th_flags & TH_ACK)?"A":"",
  380. (tcp->th_flags & TH_SYN)?"S":"",
  381. (tcp->th_flags & TH_RST)?"R":"",
  382. (tcp->th_flags & TH_FIN)?"F":"",
  383. (tcp->th_flags & TH_URG)?"U":"",
  384. (tcp->th_flags & TH_PUSH)?"P":"");
  385. } else {
  386. printf("%s -", inet_ntoa(ip_packet->ip_src));
  387. printf("> %s", inet_ntoa(ip_packet->ip_dst));
  388. }
  389. if (fragmented)
  390. printf(" %s%d@%d:%d\n", frag_offset?"+":"", ntohs(ip_packet->ip_id),
  391. frag_offset, len);
  392. else printf("\n");
  393. if (pd_dump) {
  394. pcap_dump((u_char*)pd_dump, h, p);
  395. if (!quiet) dump(data, len);
  396. } else dump(data, len);
  397. }
  398. }
  399. break;
  400. case IPPROTO_UDP: {
  401. struct udphdr* udp = (struct udphdr *)(((char *)ip_packet) + ip_hl);
  402. unsigned udphdr_offset = (fragmented)?0:sizeof(struct udphdr);
  403. if (!quiet) {
  404. printf("#");
  405. fflush(stdout);
  406. }
  407. data = ((char*)udp) + udphdr_offset;
  408. if ((len = ntohs(ip_packet->ip_len)) < h->caplen)
  409. len -= ip_hl + udphdr_offset;
  410. else len = h->caplen - link_offset - ip_hl - udphdr_offset;
  411. if (((len || show_empty) && (((int)(*match_func)(data, len)) != invert_match))
  412. || keep_matching) {
  413. if (!live_read && want_delay)
  414. dump_delay(h);
  415. printf("\nU ");
  416. if (print_time)
  417. print_time(h);
  418. if (udphdr_offset || !frag_offset) {
  419. #ifdef HAVE_DUMB_UDPHDR
  420. printf("%s:%d -", inet_ntoa(ip_packet->ip_src), ntohs(udp->source));
  421. printf("> %s:%d", inet_ntoa(ip_packet->ip_dst), ntohs(udp->dest));
  422. #else
  423. printf("%s:%d -", inet_ntoa(ip_packet->ip_src), ntohs(udp->uh_sport));
  424. printf("> %s:%d", inet_ntoa(ip_packet->ip_dst), ntohs(udp->uh_dport));
  425. #endif
  426. } else {
  427. printf("%s -", inet_ntoa(ip_packet->ip_src));
  428. printf("> %s", inet_ntoa(ip_packet->ip_dst));
  429. }
  430. if (fragmented)
  431. printf(" %s%d@%d:%d\n", frag_offset?"+":"", ntohs(ip_packet->ip_id),
  432. frag_offset, len);
  433. else printf("\n");
  434. if (pd_dump) {
  435. pcap_dump((u_char*)pd_dump, h, p);
  436. if (!quiet) dump(data, len);
  437. } else dump(data, len);
  438. }
  439. }
  440. break;
  441. case IPPROTO_ICMP: {
  442. struct icmp* ic = (struct icmp *)(((char *)ip_packet) + ip_hl);
  443. unsigned icmphdr_offset = fragmented?0:4;
  444. if (!quiet) {
  445. printf("#");
  446. fflush(stdout);
  447. }
  448. data = ((char*)ic) + icmphdr_offset;
  449. if ((len = ntohs(ip_packet->ip_len)) < h->caplen)
  450. len -= ip_hl + icmphdr_offset;
  451. else len = h->caplen - link_offset - ip_hl - icmphdr_offset;
  452. if (((len || show_empty) && (((int)(*match_func)(data, len)) != invert_match))
  453. || keep_matching) {
  454. if (!live_read && want_delay)
  455. dump_delay(h);
  456. printf("\nI ");
  457. if (print_time)
  458. print_time(h);
  459. printf("%s -", inet_ntoa(ip_packet->ip_src));
  460. printf("> %s", inet_ntoa(ip_packet->ip_dst));
  461. if (icmphdr_offset || !frag_offset)
  462. printf(" %d:%d", ic->icmp_type, ic->icmp_code);
  463. if (fragmented)
  464. printf(" %s%d@%d:%d\n", frag_offset?"+":"", ntohs(ip_packet->ip_id),
  465. frag_offset, len);
  466. else printf("\n");
  467. if (pd_dump) {
  468. pcap_dump((u_char*)pd_dump, h, p);
  469. if (!quiet) dump(data, len);
  470. } else dump(data, len);
  471. }
  472. }
  473. break;
  474. }
  475. if (match_after && keep_matching)
  476. keep_matching--;
  477. }
  478. int re_match_func(char *data, int len) {
  479. #ifdef USE_PCRE
  480. switch(pcre_exec(pattern, 0, data, len, 0, 0, 0, 0)) {
  481. case PCRE_ERROR_NULL:
  482. case PCRE_ERROR_BADOPTION:
  483. case PCRE_ERROR_BADMAGIC:
  484. case PCRE_ERROR_UNKNOWN_NODE:
  485. case PCRE_ERROR_NOMEMORY:
  486. perror("she's dead, jim\n");
  487. clean_exit(-2);
  488. case PCRE_ERROR_NOMATCH:
  489. return 0;
  490. }
  491. #else
  492. switch (re_search(&pattern, data, len, 0, len, 0)) {
  493. case -2:
  494. perror("she's dead, jim\n");
  495. clean_exit(-2);
  496. case -1:
  497. return 0;
  498. }
  499. #endif
  500. if (max_matches && ++matches > max_matches)
  501. clean_exit(0);
  502. if (match_after && keep_matching != match_after)
  503. keep_matching = match_after;
  504. return 1;
  505. }
  506. int bin_match_func(char *data, int len) {
  507. int stop = len - match_len;
  508. int i = 0;
  509. if (stop < 0)
  510. return 0;
  511. while (i <= stop)
  512. if (!memcmp(data+(i++), bin_data, match_len)) {
  513. if (max_matches && ++matches > max_matches)
  514. clean_exit(0);
  515. if (match_after && keep_matching != match_after)
  516. keep_matching = match_after;
  517. return 1;
  518. }
  519. return 0;
  520. }
  521. int blank_match_func(char *data, int len) {
  522. if (max_matches && ++matches > max_matches)
  523. clean_exit(0);
  524. return 1;
  525. }
  526. void dump_line_by_line( char *data, int len )
  527. {
  528. unsigned width;
  529. char *c;
  530. c=data;
  531. while( c< data + len) {
  532. if (*c=='\n') {
  533. puts("");
  534. } else {
  535. putchar(isprint(*c)?*c:'.');
  536. }
  537. c++;
  538. }
  539. puts("");
  540. }
  541. void _dump(char *data, int len) {
  542. if (len > 0) {
  543. unsigned width = show_hex?16:(ws_col-5);
  544. char *str = data;
  545. int j, i = 0;
  546. while (i < len) {
  547. printf(" ");
  548. if (show_hex)
  549. for (j = 0; j < width; j++) {
  550. if (i+j < len)
  551. printf("%02x ", (unsigned char)str[j]);
  552. else printf(" ");
  553. if ((j+1) % (width/2) == 0)
  554. printf(" ");
  555. }
  556. for (j = 0; j < width; j++)
  557. if (i+j < len)
  558. printf("%c", isprint(str[j])?str[j]:'.');
  559. else printf(" ");
  560. str += width;
  561. i += j;
  562. printf("\n");
  563. }
  564. }
  565. }
  566. char *get_filter(char **argv) {
  567. char **arg = argv, *theirs, *mine;
  568. char *from, *to;
  569. int len = 0;
  570. if (!*arg)
  571. return NULL;
  572. while (*arg)
  573. len += strlen(*arg++) + 1;
  574. if (!(theirs = (char*)malloc(len + 1)) ||
  575. !(mine = (char*)malloc(len + sizeof(IP_ONLY))))
  576. return NULL;
  577. memset(theirs, 0, len + 1);
  578. memset(mine, 0, len + sizeof(IP_ONLY));
  579. arg = argv;
  580. to = theirs;
  581. while ((from = *arg++)) {
  582. while ((*to++ = *from++));
  583. *(to-1) = ' ';
  584. }
  585. sprintf(mine, IP_ONLY, theirs);
  586. free(theirs);
  587. return mine;
  588. }
  589. int strishex(char *str) {
  590. char *s;
  591. if ((s = strchr(str, 'x')))
  592. s++;
  593. else s = str;
  594. while (*s)
  595. if (!isxdigit(*s++))
  596. return 0;
  597. return 1;
  598. }
  599. void print_time_absolute(struct pcap_pkthdr *h) {
  600. #ifdef MACOSX
  601. struct tm *t = localtime((const time_t *)&h->ts.tv_sec);
  602. #else
  603. struct tm *t = localtime(&h->ts.tv_sec);
  604. #endif
  605. printf("%02d/%02d/%02d %02d:%02d:%02d.%06d ",
  606. t->tm_year+1900, t->tm_mon+1, t->tm_mday, t->tm_hour,
  607. t->tm_min, t->tm_sec, h->ts.tv_usec);
  608. }
  609. void print_time_diff_init(struct pcap_pkthdr *h) {
  610. print_time = &print_time_diff;
  611. prev_ts.tv_sec = h->ts.tv_sec;
  612. prev_ts.tv_usec = h->ts.tv_usec;
  613. print_time(h);
  614. }
  615. void print_time_diff(struct pcap_pkthdr *h) {
  616. unsigned secs, usecs;
  617. secs = h->ts.tv_sec - prev_ts.tv_sec;
  618. if (h->ts.tv_usec >= prev_ts.tv_usec)
  619. usecs = h->ts.tv_usec - prev_ts.tv_usec;
  620. else {
  621. secs--;
  622. usecs = 1000000 - (prev_ts.tv_usec - h->ts.tv_usec);
  623. }
  624. printf("+%d.%06d ", secs, usecs);
  625. prev_ts.tv_sec = h->ts.tv_sec;
  626. prev_ts.tv_usec = h->ts.tv_usec;
  627. }
  628. void dump_delay_proc_init(struct pcap_pkthdr *h) {
  629. dump_delay = &dump_delay_proc;
  630. prev_delay_ts.tv_sec = h->ts.tv_sec;
  631. prev_delay_ts.tv_usec = h->ts.tv_usec;
  632. dump_delay(h);
  633. }
  634. void dump_delay_proc(struct pcap_pkthdr *h) {
  635. unsigned secs, usecs;
  636. secs = h->ts.tv_sec - prev_delay_ts.tv_sec;
  637. if (h->ts.tv_usec >= prev_delay_ts.tv_usec)
  638. usecs = h->ts.tv_usec - prev_delay_ts.tv_usec;
  639. else {
  640. secs--;
  641. usecs = 1000000 - (prev_delay_ts.tv_usec - h->ts.tv_usec);
  642. }
  643. sleep(secs);
  644. usleep(usecs);
  645. prev_delay_ts.tv_sec = h->ts.tv_sec;
  646. prev_delay_ts.tv_usec = h->ts.tv_usec;
  647. }
  648. void update_windowsize(int e) {
  649. const struct winsize ws;
  650. if (!ioctl(0, TIOCGWINSZ, &ws)) {
  651. ws_row = ws.ws_row;
  652. ws_col = ws.ws_col;
  653. } else {
  654. ws_row = 24;
  655. ws_col = 80;
  656. }
  657. }
  658. void usage(int e) {
  659. printf("usage: ngrep <-hLXViwqpevxlDtT> <-IO pcap_dump> <-n num> <-d dev> <-A num>\n"
  660. " <-s snaplen> <match expression> <bpf filter>\n");
  661. exit(e);
  662. }
  663. void version(void) {
  664. printf("ngrep: V%s, %s\n", VERSION, rcsver);
  665. exit(0);
  666. }
  667. void clean_exit(int sig) {
  668. struct pcap_stat s;
  669. if (!quiet && sig >= 0) printf("exit\n");
  670. #ifdef USE_PCRE
  671. if (re_err) free(re_err);
  672. if (pattern) pcre_free(pattern);
  673. if (pattern_extra) pcre_free(pattern_extra);
  674. #else
  675. if (pattern.translate) free(pattern.translate);
  676. if (pattern.fastmap) free(pattern.fastmap);
  677. #endif
  678. if (bin_data) free(bin_data);
  679. if (!quiet && sig >= 0 && !read_file &&
  680. pd && !pcap_stats(pd, &s))
  681. printf("%d received, %d dropped\n", s.ps_recv, s.ps_drop);
  682. if (pd) pcap_close(pd);
  683. if (pd_dump) pcap_dump_close(pd_dump);
  684. exit(sig);
  685. }