PageRenderTime 64ms CodeModel.GetById 33ms RepoModel.GetById 1ms app.codeStats 0ms

/iptraf-ng-1.1.3.1/src/itrafmon.c

#
C | 1325 lines | 1007 code | 197 blank | 121 comment | 267 complexity | 3a0d962948e75631a2b46ea7cdb29b5f MD5 | raw file
Possible License(s): GPL-2.0
  1. /* For terms of usage/redistribution/modification see the LICENSE file */
  2. /* For authors and contributors see the AUTHORS file */
  3. /***
  4. itrafmon.c - the IP traffic monitor module
  5. ***/
  6. #include "iptraf-ng-compat.h"
  7. #include "tui/labels.h"
  8. #include "tui/winops.h"
  9. #include "options.h"
  10. #include "tcptable.h"
  11. #include "othptab.h"
  12. #include "fltdefs.h"
  13. #include "fltselect.h"
  14. #include "isdntab.h"
  15. #include "packet.h"
  16. #include "ifaces.h"
  17. #include "promisc.h"
  18. #include "deskman.h"
  19. #include "error.h"
  20. #include "attrs.h"
  21. #include "log.h"
  22. #include "revname.h"
  23. #include "rvnamed.h"
  24. #include "dirs.h"
  25. #include "timer.h"
  26. #include "ipfrag.h"
  27. #include "instances.h"
  28. #include "logvars.h"
  29. #include "bar.h"
  30. #include "itrafmon.h"
  31. #define SCROLLUP 0
  32. #define SCROLLDOWN 1
  33. extern int exitloop;
  34. extern int daemonized;
  35. static void rotate_ipmon_log(int s __unused)
  36. {
  37. rotate_flag = 1;
  38. strcpy(target_logname, current_logfile);
  39. signal(SIGUSR1, rotate_ipmon_log);
  40. }
  41. /* Hot key indicators for the bottom line */
  42. static void ipmonhelp(void)
  43. {
  44. move(LINES - 1, 1);
  45. tx_printkeyhelp("Up/Dn/PgUp/PgDn", "-scroll ", stdscr, HIGHATTR,
  46. STATUSBARATTR);
  47. move(LINES - 1, 43);
  48. tx_printkeyhelp("W", "-chg actv win ", stdscr, HIGHATTR,
  49. STATUSBARATTR);
  50. tx_printkeyhelp("S", "-sort TCP ", stdscr, HIGHATTR, STATUSBARATTR);
  51. stdexitkeyhelp();
  52. }
  53. static void uniq_help(int what)
  54. {
  55. move(LINES - 1, 25);
  56. if (!what)
  57. tx_printkeyhelp("M", "-more TCP info ", stdscr, HIGHATTR,
  58. STATUSBARATTR);
  59. else
  60. tx_printkeyhelp("Lft/Rt", "-vtcl scrl ", stdscr, HIGHATTR,
  61. STATUSBARATTR);
  62. }
  63. /* Mark general packet count indicators */
  64. static void prepare_statwin(WINDOW * win)
  65. {
  66. wattrset(win, IPSTATLABELATTR);
  67. wmove(win, 0, 1);
  68. wprintw(win, "Packets captured:");
  69. mvwaddch(win, 0, 45 * COLS / 80, ACS_VLINE);
  70. }
  71. static void markactive(int curwin, WINDOW * tw, WINDOW * ow)
  72. {
  73. WINDOW *win1;
  74. WINDOW *win2;
  75. int x1 __unused, y1, x2 __unused, y2;
  76. if (!curwin) {
  77. win1 = tw;
  78. win2 = ow;
  79. } else {
  80. win1 = ow;
  81. win2 = tw;
  82. }
  83. getmaxyx(win1, y1, x1);
  84. getmaxyx(win2, y2, x2);
  85. wmove(win1, --y1, COLS - 10);
  86. wattrset(win1, ACTIVEATTR);
  87. wprintw(win1, " Active ");
  88. wattrset(win1, BOXATTR);
  89. wmove(win2, --y2, COLS - 10);
  90. whline(win2, ACS_HLINE, 8);
  91. }
  92. static void show_stats(WINDOW * win, unsigned long long total)
  93. {
  94. wattrset(win, IPSTATATTR);
  95. wmove(win, 0, 35 * COLS / 80);
  96. printlargenum(total, win);
  97. }
  98. /*
  99. * Scrolling and paging routines for the upper (TCP) window
  100. */
  101. static void scrollupperwin(struct tcptable *table, int direction,
  102. unsigned long *idx, int mode)
  103. {
  104. char sp_buf[10];
  105. sprintf(sp_buf, "%%%dc", COLS - 2);
  106. wattrset(table->tcpscreen, STDATTR);
  107. if (direction == SCROLLUP) {
  108. if (table->lastvisible != table->tail) {
  109. wscrl(table->tcpscreen, 1);
  110. table->lastvisible = table->lastvisible->next_entry;
  111. table->firstvisible = table->firstvisible->next_entry;
  112. (*idx)++;
  113. wmove(table->tcpscreen, table->imaxy - 1, 0);
  114. scrollok(table->tcpscreen, 0);
  115. wprintw(table->tcpscreen, sp_buf, ' ');
  116. scrollok(table->tcpscreen, 1);
  117. printentry(table, table->lastvisible, *idx, mode);
  118. }
  119. } else {
  120. if (table->firstvisible != table->head) {
  121. wscrl(table->tcpscreen, -1);
  122. table->firstvisible = table->firstvisible->prev_entry;
  123. table->lastvisible = table->lastvisible->prev_entry;
  124. (*idx)--;
  125. wmove(table->tcpscreen, 0, 0);
  126. wprintw(table->tcpscreen, sp_buf, ' ');
  127. printentry(table, table->firstvisible, *idx, mode);
  128. }
  129. }
  130. }
  131. static void pageupperwin(struct tcptable *table, int direction,
  132. unsigned long *idx)
  133. {
  134. unsigned int i = 1;
  135. wattrset(table->tcpscreen, STDATTR);
  136. if (direction == SCROLLUP) {
  137. while ((i <= table->imaxy - 3)
  138. && (table->lastvisible != table->tail)) {
  139. i++;
  140. table->firstvisible = table->firstvisible->next_entry;
  141. table->lastvisible = table->lastvisible->next_entry;
  142. (*idx)++;
  143. }
  144. } else {
  145. while ((i <= table->imaxy - 3)
  146. && (table->firstvisible != table->head)) {
  147. i++;
  148. table->firstvisible = table->firstvisible->prev_entry;
  149. table->lastvisible = table->lastvisible->prev_entry;
  150. (*idx)--;
  151. }
  152. }
  153. }
  154. /*
  155. * Scrolling and paging routines for the lower (non-TCP) window.
  156. */
  157. static void scrolllowerwin(struct othptable *table, int direction)
  158. {
  159. if (direction == SCROLLUP) {
  160. if (table->lastvisible != table->tail) {
  161. wscrl(table->othpwin, 1);
  162. table->lastvisible = table->lastvisible->next_entry;
  163. table->firstvisible = table->firstvisible->next_entry;
  164. if (table->htstat == HIND) { /* Head indicator on? */
  165. wmove(table->borderwin, table->obmaxy - 1, 1);
  166. whline(table->borderwin, ACS_HLINE, 8);
  167. table->htstat = NOHTIND;
  168. }
  169. printothpentry(table, table->lastvisible,
  170. table->oimaxy - 1, 0, NULL);
  171. }
  172. } else {
  173. if (table->firstvisible != table->head) {
  174. wscrl(table->othpwin, -1);
  175. table->firstvisible = table->firstvisible->prev_entry;
  176. table->lastvisible = table->lastvisible->prev_entry;
  177. if (table->htstat == TIND) { /* Tail indicator on? */
  178. wmove(table->borderwin, table->obmaxy - 1, 1);
  179. whline(table->borderwin, ACS_HLINE, 8);
  180. table->htstat = NOHTIND;
  181. }
  182. printothpentry(table, table->firstvisible, 0, 0, NULL);
  183. }
  184. }
  185. }
  186. static void pagelowerwin(struct othptable *table, int direction)
  187. {
  188. unsigned int i = 1;
  189. if (direction == SCROLLUP) {
  190. while ((i <= table->oimaxy - 2)
  191. && (table->lastvisible != table->tail)) {
  192. i++;
  193. table->firstvisible = table->firstvisible->next_entry;
  194. table->lastvisible = table->lastvisible->next_entry;
  195. if (table->htstat == HIND) { /* Head indicator on? */
  196. wmove(table->borderwin, table->obmaxy - 1, 1);
  197. whline(table->borderwin, ACS_HLINE, 8);
  198. table->htstat = NOHTIND;
  199. }
  200. }
  201. } else {
  202. while ((i <= table->oimaxy - 2)
  203. && (table->firstvisible != table->head)) {
  204. i++;
  205. table->firstvisible = table->firstvisible->prev_entry;
  206. table->lastvisible = table->lastvisible->prev_entry;
  207. if (table->htstat == TIND) { /* Tail indicator on? */
  208. wmove(table->borderwin, table->obmaxy - 1, 1);
  209. whline(table->borderwin, ACS_HLINE, 8);
  210. table->htstat = NOHTIND;
  211. }
  212. }
  213. }
  214. }
  215. /*
  216. * Pop up sorting key window
  217. */
  218. static void show_tcpsort_win(WINDOW ** win, PANEL ** panel)
  219. {
  220. *win = newwin(9, 35, (LINES - 8) / 2, COLS - 40);
  221. *panel = new_panel(*win);
  222. wattrset(*win, DLGBOXATTR);
  223. tx_colorwin(*win);
  224. tx_box(*win, ACS_VLINE, ACS_HLINE);
  225. wattrset(*win, DLGTEXTATTR);
  226. mvwprintw(*win, 2, 2, "Select sort criterion");
  227. wmove(*win, 4, 2);
  228. tx_printkeyhelp("P", " - sort by packet count", *win, DLGHIGHATTR,
  229. DLGTEXTATTR);
  230. wmove(*win, 5, 2);
  231. tx_printkeyhelp("B", " - sort by byte count", *win, DLGHIGHATTR,
  232. DLGTEXTATTR);
  233. wmove(*win, 6, 2);
  234. tx_printkeyhelp("Any other key", " - cancel sort", *win, DLGHIGHATTR,
  235. DLGTEXTATTR);
  236. update_panels();
  237. doupdate();
  238. }
  239. /*
  240. * Routine to swap two TCP entries. p1 and p2 are pointers to TCP entries,
  241. * but p1 must be ahead of p2. It's a linked list thing.
  242. */
  243. static void swap_tcp_entries(struct tcptable *table, struct tcptableent *p1,
  244. struct tcptableent *p2)
  245. {
  246. struct tcptableent *p2nextsaved;
  247. struct tcptableent *p1prevsaved;
  248. unsigned int tmp;
  249. if (p1 == p2)
  250. return;
  251. tmp = p1->index;
  252. p1->index = p2->index;
  253. p2->index = tmp;
  254. p1->next_entry->index = p1->index + 1;
  255. p2->next_entry->index = p2->index + 1;
  256. if (p1->prev_entry != NULL)
  257. p1->prev_entry->next_entry = p2;
  258. else
  259. table->head = p2;
  260. if (p2->next_entry->next_entry != NULL)
  261. p2->next_entry->next_entry->prev_entry = p1->next_entry;
  262. else
  263. table->tail = p1->next_entry;
  264. p2nextsaved = p2->next_entry->next_entry;
  265. p1prevsaved = p1->prev_entry;
  266. if (p1->next_entry->next_entry == p2) { /* swapping adjacent entries */
  267. p2->next_entry->next_entry = p1;
  268. p1->prev_entry = p2->next_entry;
  269. } else {
  270. p2->next_entry->next_entry = p1->next_entry->next_entry;
  271. p1->prev_entry = p2->prev_entry;
  272. p2->prev_entry->next_entry = p1;
  273. p1->next_entry->next_entry->prev_entry = p2->next_entry;
  274. }
  275. p2->prev_entry = p1prevsaved;
  276. p1->next_entry->next_entry = p2nextsaved;
  277. }
  278. static unsigned long long qt_getkey(struct tcptableent *entry, int ch)
  279. {
  280. if (ch == 'B')
  281. return (max(entry->bcount, entry->oth_connection->bcount));
  282. return (max(entry->pcount, entry->oth_connection->pcount));
  283. }
  284. static struct tcptableent *qt_partition(struct tcptable *table,
  285. struct tcptableent **low,
  286. struct tcptableent **high, int ch,
  287. struct OPTIONS *opts, int logging,
  288. FILE * logfile)
  289. {
  290. struct tcptableent *pivot = *low;
  291. struct tcptableent *left = *low;
  292. struct tcptableent *right = *high;
  293. struct tcptableent *ptmp;
  294. unsigned long long pivot_value;
  295. time_t now;
  296. pivot_value = qt_getkey(pivot, ch);
  297. now = time(NULL);
  298. while (left->index < right->index) {
  299. while ((qt_getkey(left, ch) >= pivot_value)
  300. && (left->next_entry->next_entry != NULL)) {
  301. /*
  302. * Might as well check out timed out entries here too.
  303. */
  304. if ((opts->timeout > 0)
  305. && ((now - left->lastupdate) / 60 > opts->timeout)
  306. && (!(left->inclosed))) {
  307. left->timedout =
  308. left->oth_connection->timedout = 1;
  309. addtoclosedlist(table, left);
  310. if (logging)
  311. write_timeout_log(logging, logfile,
  312. left, opts);
  313. }
  314. left = left->next_entry->next_entry;
  315. }
  316. while (qt_getkey(right, ch) < pivot_value) {
  317. /*
  318. * Might as well check out timed out entries here too.
  319. */
  320. if ((opts->timeout > 0)
  321. && ((now - right->lastupdate) / 60 > opts->timeout)
  322. && (!(right->inclosed))) {
  323. right->timedout =
  324. right->oth_connection->timedout = 1;
  325. addtoclosedlist(table, right);
  326. if (logging)
  327. write_timeout_log(logging, logfile,
  328. right, opts);
  329. }
  330. right = right->prev_entry->prev_entry;
  331. }
  332. if (left->index < right->index) {
  333. swap_tcp_entries(table, left, right);
  334. if (*low == left)
  335. *low = right;
  336. if (*high == right)
  337. *high = left;
  338. ptmp = left;
  339. left = right;
  340. right = ptmp;
  341. }
  342. }
  343. swap_tcp_entries(table, pivot, right);
  344. if (*low == pivot)
  345. *low = right;
  346. if (*high == right)
  347. *high = pivot;
  348. return pivot;
  349. }
  350. /*
  351. * Quicksort the TCP entries.
  352. */
  353. static void quicksort_tcp_entries(struct tcptable *table,
  354. struct tcptableent *low,
  355. struct tcptableent *high, int ch,
  356. struct OPTIONS *opts, int logging,
  357. FILE *logfile)
  358. {
  359. struct tcptableent *pivot;
  360. if ((high == NULL) || (low == NULL))
  361. return;
  362. if (high->index > low->index) {
  363. pivot =
  364. qt_partition(table, &low, &high, ch, opts, logging, logfile);
  365. if (pivot->prev_entry != NULL)
  366. quicksort_tcp_entries(table, low,
  367. pivot->prev_entry->prev_entry, ch,
  368. opts, logging, logfile);
  369. quicksort_tcp_entries(table, pivot->next_entry->next_entry,
  370. high, ch, opts, logging, logfile);
  371. }
  372. }
  373. /*
  374. * This function sorts the TCP window. The old exchange sort has been
  375. * replaced with a Quicksort algorithm.
  376. */
  377. static void sortipents(struct tcptable *table, unsigned long *idx, int ch,
  378. int logging, FILE * logfile,
  379. struct OPTIONS *opts)
  380. {
  381. struct tcptableent *tcptmp1;
  382. unsigned int idxtmp;
  383. if ((table->head == NULL)
  384. || (table->head->next_entry->next_entry == NULL))
  385. return;
  386. ch = toupper(ch);
  387. if ((ch != 'P') && (ch != 'B'))
  388. return;
  389. quicksort_tcp_entries(table, table->head, table->tail->prev_entry, ch,
  390. opts, logging, logfile);
  391. update_panels();
  392. doupdate();
  393. tx_colorwin(table->tcpscreen);
  394. tcptmp1 = table->firstvisible = table->head;
  395. *idx = 1;
  396. idxtmp = 0;
  397. while ((tcptmp1 != NULL) && (idxtmp <= table->imaxy - 1)) {
  398. if (idxtmp++ <= table->imaxy - 1)
  399. table->lastvisible = tcptmp1;
  400. tcptmp1 = tcptmp1->next_entry;
  401. }
  402. }
  403. /*
  404. * Attempt to communicate with rvnamed, and if it doesn't respond, try
  405. * to start it.
  406. */
  407. static int checkrvnamed(void)
  408. {
  409. pid_t cpid = 0;
  410. int cstat;
  411. extern int errno;
  412. indicate("Trying to communicate with reverse lookup server");
  413. if (!rvnamedactive()) {
  414. indicate("Starting reverse lookup server");
  415. if ((cpid = fork()) == 0) {
  416. char *args[] = {
  417. "rvnamed-ng",
  418. NULL
  419. };
  420. execvp("rvnamed-ng", args);
  421. /*
  422. * execvp() never returns, so if we reach this point, we have
  423. * a problem.
  424. */
  425. die("unable execvp() rvnamed-ng");
  426. } else if (cpid == -1) {
  427. write_error("Can't spawn new process; lookups will block");
  428. return 0;
  429. } else {
  430. while (waitpid(cpid, &cstat, 0) < 0)
  431. if (errno != EINTR)
  432. break;
  433. if (WEXITSTATUS(cstat) == 1) {
  434. write_error("Can't start rvnamed; lookups will block");
  435. return 0;
  436. } else {
  437. sleep(1);
  438. return 1;
  439. }
  440. }
  441. }
  442. return 1;
  443. }
  444. static void update_flowrate(WINDOW * win, struct tcptableent *entry, time_t now,
  445. int *cleared, int mode)
  446. {
  447. float rate = 0;
  448. wattrset(win, IPSTATLABELATTR);
  449. mvwprintw(win, 0, COLS * 47 / 80, "TCP flow rate: ");
  450. wattrset(win, IPSTATATTR);
  451. if (mode == KBITS) {
  452. rate =
  453. (float) (entry->spanbr * 8 / 1000) / (float) (now -
  454. entry->
  455. starttime);
  456. } else {
  457. rate =
  458. (float) (entry->spanbr / 1024) / (float) (now -
  459. entry->starttime);
  460. }
  461. mvwprintw(win, 0, COLS * 53 / 80 + 13, "%8.2f %s", rate, dispmode(mode));
  462. entry->spanbr = 0;
  463. *cleared = 0;
  464. }
  465. /*
  466. * The IP Traffic Monitor
  467. */
  468. void ipmon(struct OPTIONS *options, struct filterstate *ofilter,
  469. time_t facilitytime, char *ifptr)
  470. {
  471. int logging = options->logging;
  472. struct iphdr *ippacket;
  473. struct ip6_hdr *ip6packet;
  474. unsigned int protocol;
  475. unsigned int frag_off;
  476. struct tcphdr *transpacket; /* IP-encapsulated packet */
  477. unsigned int sport = 0, dport = 0; /* TCP/UDP port values */
  478. char sp_buf[10];
  479. unsigned long screen_idx = 1;
  480. struct timeval tv;
  481. time_t starttime = 0;
  482. time_t now = 0;
  483. time_t timeint = 0;
  484. time_t updtime = 0;
  485. unsigned long long updtime_usec = 0;
  486. unsigned long long unow = 0;
  487. time_t closedint = 0;
  488. WINDOW *statwin;
  489. PANEL *statpanel;
  490. WINDOW *sortwin;
  491. PANEL *sortpanel;
  492. FILE *logfile = NULL;
  493. int curwin = 0;
  494. char *ifname = ifptr;
  495. unsigned long long total_pkts = 0;
  496. unsigned int br; /* bytes read. Differs from readlen */
  497. /* only when packets fragmented */
  498. unsigned int iphlen;
  499. struct tcptable table;
  500. struct tcptableent *tcpentry;
  501. struct tcptableent *tmptcp;
  502. int mode = 0;
  503. struct othptable othptbl;
  504. int p_sstat = 0, p_dstat = 0; /* Reverse lookup statuses prior to */
  505. /* reattempt in updateentry() */
  506. int pkt_result = 0; /* Non-IP filter ok */
  507. int fragment = 0; /* Set to 1 if not first fragment */
  508. int fd;
  509. int ch;
  510. int keymode = 0;
  511. char msgstring[80];
  512. struct promisc_states *promisc_list;
  513. int rvnfd = 0;
  514. int instance_id;
  515. int revlook = options->revlook;
  516. int statcleared = 0;
  517. int wasempty = 1;
  518. const int statx = COLS * 47 / 80;
  519. /*
  520. * Mark this instance of the traffic monitor
  521. */
  522. if (!facility_active(IPMONIDFILE, ifptr))
  523. mark_facility(IPMONIDFILE, "IP traffic monitor", ifptr);
  524. else {
  525. write_error("IP Traffic Monitor already listening on %s", gen_iface_msg(ifptr));
  526. return;
  527. }
  528. if (ifptr != NULL) {
  529. if (!dev_up(ifptr)) {
  530. err_iface_down();
  531. unmark_facility(IPMONIDFILE, ifptr);
  532. return;
  533. }
  534. }
  535. if (options->promisc) {
  536. if (first_active_facility()) {
  537. init_promisc_list(&promisc_list);
  538. save_promisc_list(promisc_list);
  539. srpromisc(1, promisc_list);
  540. }
  541. }
  542. /*
  543. * Adjust instance counters
  544. */
  545. adjust_instance_count(PROCCOUNTFILE, 1);
  546. instance_id = adjust_instance_count(ITRAFMONCOUNTFILE, 1);
  547. init_tcp_table(&table);
  548. init_othp_table(&othptbl, options->mac);
  549. statwin = newwin(1, COLS, LINES - 2, 0);
  550. statpanel = new_panel(statwin);
  551. wattrset(statwin, IPSTATLABELATTR);
  552. wmove(statwin, 0, 0);
  553. sprintf(sp_buf, "%%%dc", COLS);
  554. wprintw(statwin, sp_buf, ' ');
  555. prepare_statwin(statwin);
  556. show_stats(statwin, 0);
  557. markactive(curwin, table.borderwin, othptbl.borderwin);
  558. update_panels();
  559. doupdate();
  560. if (revlook) {
  561. if (checkrvnamed())
  562. open_rvn_socket(&rvnfd);
  563. } else
  564. rvnfd = 0;
  565. ipmonhelp();
  566. uniq_help(0);
  567. update_panels();
  568. doupdate();
  569. if (options->servnames)
  570. setservent(1);
  571. /*
  572. * Try to open log file if logging activated. Turn off logging
  573. * (for this session only) if an error was discovered in opening
  574. * the log file. Configuration setting is kept. Who knows, the
  575. * situation may be corrected later.
  576. */
  577. if (logging) {
  578. if (strcmp(current_logfile, "") == 0) {
  579. strncpy(current_logfile,
  580. gen_instance_logname(IPMONLOG, instance_id),
  581. 80);
  582. if (!daemonized)
  583. input_logfile(current_logfile, &logging);
  584. }
  585. }
  586. if (logging) {
  587. opentlog(&logfile, current_logfile);
  588. if (logfile == NULL)
  589. logging = 0;
  590. }
  591. if (logging) {
  592. signal(SIGUSR1, rotate_ipmon_log);
  593. rotate_flag = 0;
  594. writelog(logging, logfile,
  595. "******** IP traffic monitor started ********");
  596. }
  597. setprotoent(1);
  598. fd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
  599. if(fd == -1) {
  600. write_error("Unable to obtain monitoring socket");
  601. goto err;
  602. }
  603. if(ifptr && dev_bind_ifname(fd, ifptr) == -1) {
  604. write_error("Unable to bind interface on the socket");
  605. goto err_close;
  606. }
  607. //isdnfd = -1;
  608. exitloop = 0;
  609. gettimeofday(&tv, NULL);
  610. starttime = timeint = closedint = tv.tv_sec;
  611. PACKET_INIT(pkt);
  612. while (!exitloop) {
  613. char ifnamebuf[IFNAMSIZ];
  614. gettimeofday(&tv, NULL);
  615. now = tv.tv_sec;
  616. unow = tv.tv_sec * 1e+06 + tv.tv_usec;
  617. /*
  618. * Print timer at bottom of screen
  619. */
  620. if (now - timeint >= 5) {
  621. printelapsedtime(starttime, now, othptbl.obmaxy - 1, 15,
  622. othptbl.borderwin);
  623. timeint = now;
  624. }
  625. /*
  626. * Automatically clear closed/timed out entries
  627. */
  628. if ((options->closedint != 0)
  629. && ((now - closedint) / 60 >= options->closedint)) {
  630. flushclosedentries(&table, &screen_idx, logging,
  631. logfile, options);
  632. refreshtcpwin(&table, screen_idx, mode);
  633. closedint = now;
  634. }
  635. /*
  636. * Update screen at configured intervals.
  637. */
  638. if (((options->updrate != 0)
  639. && (now - updtime >= options->updrate))
  640. || ((options->updrate == 0)
  641. && (unow - updtime_usec >= DEFAULT_UPDATE_DELAY))) {
  642. update_panels();
  643. doupdate();
  644. updtime = now;
  645. updtime_usec = unow;
  646. }
  647. /*
  648. * If highlight bar is on some entry, update the flow rate
  649. * indicator after five seconds.
  650. */
  651. if (table.barptr != NULL) {
  652. if ((now - table.barptr->starttime) >= 5) {
  653. update_flowrate(statwin, table.barptr, now,
  654. &statcleared, options->actmode);
  655. table.barptr->starttime = now;
  656. }
  657. } else {
  658. wattrset(statwin, IPSTATATTR);
  659. mvwprintw(statwin, 0, statx,
  660. "No TCP entries ");
  661. }
  662. /*
  663. * Terminate facility should a lifetime be specified at the
  664. * command line
  665. */
  666. if ((facilitytime != 0)
  667. && (((now - starttime) / 60) >= facilitytime))
  668. exitloop = 1;
  669. /*
  670. * Close and rotate log file if signal was received
  671. */
  672. if (logging && (rotate_flag == 1)) {
  673. announce_rotate_prepare(logfile);
  674. write_tcp_unclosed(logging, logfile, &table);
  675. rotate_logfile(&logfile, target_logname);
  676. announce_rotate_complete(logfile);
  677. rotate_flag = 0;
  678. }
  679. if (packet_get(fd, &pkt, &ch, table.tcpscreen) == -1) {
  680. write_error("Packet receive failed");
  681. exitloop = 1;
  682. break;
  683. }
  684. if (ch == ERR)
  685. goto no_key_ready;
  686. if (keymode == 0) {
  687. switch (ch) {
  688. case KEY_UP:
  689. if (curwin) {
  690. scrolllowerwin(&othptbl, SCROLLDOWN);
  691. break;
  692. }
  693. if (!table.barptr
  694. || !table.barptr->prev_entry)
  695. break;
  696. tmptcp = table.barptr;
  697. set_barptr((void *) &(table.barptr),
  698. table.barptr->prev_entry,
  699. &(table.barptr->prev_entry->starttime),
  700. &(table.barptr->prev_entry->spanbr),
  701. sizeof(unsigned long),
  702. statwin, &statcleared, statx);
  703. printentry(&table, tmptcp, screen_idx, mode);
  704. if (table.baridx == 1)
  705. scrollupperwin(&table, SCROLLDOWN,
  706. &screen_idx, mode);
  707. else
  708. (table.baridx)--;
  709. printentry(&table, table.barptr, screen_idx,
  710. mode);
  711. break;
  712. case KEY_DOWN:
  713. if (curwin) {
  714. scrolllowerwin(&othptbl, SCROLLUP);
  715. break;
  716. }
  717. if (!table.barptr
  718. || !table.barptr->next_entry)
  719. break;
  720. tmptcp = table.barptr;
  721. set_barptr((void*) &(table.barptr),
  722. table.barptr->next_entry,
  723. &(table.barptr->next_entry->starttime),
  724. &(table.barptr->next_entry->spanbr),
  725. sizeof(unsigned long),
  726. statwin, &statcleared, statx);
  727. printentry(&table, tmptcp, screen_idx,mode);
  728. if (table.baridx == table.imaxy)
  729. scrollupperwin(&table, SCROLLUP,
  730. &screen_idx, mode);
  731. else
  732. (table.baridx)++;
  733. printentry(&table,table.barptr, screen_idx,
  734. mode);
  735. break;
  736. case KEY_RIGHT:
  737. if (!curwin)
  738. break;
  739. if (othptbl.strindex != VSCRL_OFFSET)
  740. othptbl.strindex = VSCRL_OFFSET;
  741. refresh_othwindow(&othptbl);
  742. break;
  743. case KEY_LEFT:
  744. if (!curwin)
  745. break;
  746. if (othptbl.strindex != 0)
  747. othptbl.strindex = 0;
  748. refresh_othwindow(&othptbl);
  749. break;
  750. case KEY_PPAGE:
  751. case '-':
  752. if (curwin) {
  753. pagelowerwin(&othptbl, SCROLLDOWN);
  754. refresh_othwindow(&othptbl);
  755. break;
  756. }
  757. if (!table.barptr)
  758. break;
  759. pageupperwin(&table, SCROLLDOWN, &screen_idx);
  760. set_barptr((void *) &(table.barptr),
  761. table.lastvisible,
  762. &(table.lastvisible->starttime),
  763. &(table.lastvisible->spanbr),
  764. sizeof(unsigned long),
  765. statwin,&statcleared, statx);
  766. table.baridx =
  767. table.lastvisible->index - screen_idx + 1;
  768. refreshtcpwin(&table, screen_idx, mode);
  769. break;
  770. case KEY_NPAGE:
  771. case ' ':
  772. if (curwin) {
  773. pagelowerwin(&othptbl, SCROLLUP);
  774. refresh_othwindow(&othptbl);
  775. break;
  776. }
  777. if (!table.barptr)
  778. break;
  779. pageupperwin(&table, SCROLLUP, &screen_idx);
  780. set_barptr((void *) &(table.barptr),
  781. table.firstvisible,
  782. &(table.firstvisible->starttime),
  783. &(table.firstvisible->spanbr),
  784. sizeof(unsigned long),
  785. statwin, &statcleared, statx);
  786. table.baridx = 1;
  787. refreshtcpwin(&table, screen_idx, mode);
  788. break;
  789. case KEY_F(6):
  790. case 'w':
  791. case 'W':
  792. case 9:
  793. curwin = !curwin;
  794. markactive(curwin, table.borderwin,
  795. othptbl.borderwin);
  796. uniq_help(curwin);
  797. break;
  798. case 'm':
  799. case 'M':
  800. if (curwin)
  801. break;
  802. mode = (mode + 1) % 3;
  803. if ((mode == 1) && (!options->mac))
  804. mode = 2;
  805. refreshtcpwin(&table, screen_idx, mode);
  806. break;
  807. case 12:
  808. case 'l':
  809. case 'L':
  810. tx_refresh_screen();
  811. break;
  812. case 'F':
  813. case 'f':
  814. case 'c':
  815. case 'C':
  816. flushclosedentries(&table, &screen_idx, logging,
  817. logfile, options);
  818. refreshtcpwin(&table, screen_idx, mode);
  819. break;
  820. case 's':
  821. case 'S':
  822. keymode = 1;
  823. show_tcpsort_win(&sortwin, &sortpanel);
  824. break;
  825. case 'Q':
  826. case 'q':
  827. case 'X':
  828. case 'x':
  829. case 24:
  830. case 27:
  831. exitloop = 1;
  832. break;
  833. }
  834. } else if (keymode == 1) {
  835. keymode = 0;
  836. del_panel(sortpanel);
  837. delwin(sortwin);
  838. show_sort_statwin(&sortwin, &sortpanel);
  839. update_panels();
  840. doupdate();
  841. sortipents(&table, &screen_idx, ch, logging,
  842. logfile, options);
  843. if (table.barptr != NULL) {
  844. set_barptr((void *) &(table.barptr),
  845. table.firstvisible,
  846. &(table.firstvisible->starttime),
  847. &(table.firstvisible->spanbr),
  848. sizeof(unsigned long),
  849. statwin, &statcleared, statx);
  850. table.baridx = 1;
  851. }
  852. refreshtcpwin(&table, screen_idx, mode);
  853. del_panel(sortpanel);
  854. delwin(sortwin);
  855. update_panels();
  856. doupdate();
  857. }
  858. no_key_ready:
  859. if (pkt.pkt_len <= 0)
  860. continue;
  861. total_pkts++;
  862. show_stats(statwin, total_pkts);
  863. pkt_result =
  864. packet_process(&pkt, &br, &sport, &dport,
  865. ofilter, MATCH_OPPOSITE_ALWAYS,
  866. options->v6inv4asv6);
  867. if (pkt_result != PACKET_OK)
  868. continue;
  869. if (!ifptr) {
  870. /* we're capturing on "All interfaces", */
  871. /* so get the name of the interface */
  872. /* of this packet */
  873. int r = dev_get_ifname(pkt.pkt_ifindex, ifnamebuf);
  874. if (r != 0) {
  875. write_error("Unable to get interface name");
  876. break; /* error getting interface name, get out! */
  877. }
  878. ifname = ifnamebuf;
  879. }
  880. switch(pkt.pkt_protocol) {
  881. case ETH_P_IP:
  882. ippacket = (struct iphdr *) pkt.pkt_payload;
  883. iphlen = ippacket->ihl * 4;
  884. ip6packet = NULL;
  885. protocol = ippacket->protocol;
  886. frag_off = ippacket->frag_off;
  887. break;
  888. case ETH_P_IPV6:
  889. ip6packet = (struct ip6_hdr *) pkt.pkt_payload;
  890. iphlen = 40;
  891. ippacket = NULL;
  892. protocol = ip6packet->ip6_nxt;
  893. frag_off = 0;
  894. break;
  895. default:
  896. add_othp_entry(&othptbl, &pkt, 0, 0, NULL,
  897. NULL, NOT_IP,
  898. pkt.pkt_protocol,
  899. pkt.pkt_payload, ifname, 0,
  900. 0, logging, logfile,
  901. options->servnames, 0);
  902. continue;
  903. }
  904. transpacket = (struct tcphdr *) (pkt.pkt_payload + iphlen);
  905. if (protocol == IPPROTO_TCP) {
  906. if (ippacket != NULL) {
  907. tcpentry =
  908. in_table(&table,
  909. ippacket->saddr,
  910. ippacket->daddr,
  911. NULL, NULL,
  912. ntohs(sport),
  913. ntohs(dport),
  914. ifname, logging,
  915. logfile, options);
  916. } else {
  917. tcpentry =
  918. in_table(&table, 0, 0,
  919. (uint8_t *) (&ip6packet->
  920. ip6_src.
  921. s6_addr),
  922. (uint8_t *) (&ip6packet->
  923. ip6_dst.
  924. s6_addr),
  925. ntohs(sport), ntohs(dport),
  926. ifname, logging, logfile, options);
  927. }
  928. /*
  929. * Add a new entry if it doesn't exist, and,
  930. * to reduce the chances of stales, not a FIN.
  931. */
  932. if (((ntohs(frag_off) & 0x3fff) == 0) /* first frag only */
  933. && (tcpentry == NULL)
  934. && (!(transpacket->fin))) {
  935. /*
  936. * Ok, so we have a packet. Add it if this connection
  937. * is not yet closed, or if it is a SYN packet.
  938. */
  939. wasempty = (table.head == NULL);
  940. if (ippacket != NULL)
  941. tcpentry =
  942. addentry(&table,
  943. (unsigned long) ippacket->saddr,
  944. (unsigned long) ippacket->daddr,
  945. NULL, NULL, sport, dport,
  946. ippacket->protocol,
  947. ifname, &revlook, rvnfd,
  948. options->servnames);
  949. else
  950. tcpentry =
  951. addentry(&table, 0, 0,
  952. (uint8_t *) (&ip6packet->ip6_src.s6_addr),
  953. (uint8_t *) (&ip6packet->ip6_dst.s6_addr),
  954. sport, dport, ip6packet->ip6_nxt,
  955. ifname, &revlook, rvnfd,
  956. options->servnames);
  957. if (tcpentry != NULL) {
  958. printentry(&table, tcpentry->oth_connection, screen_idx,
  959. mode);
  960. if (wasempty) {
  961. set_barptr((void *) &(table.barptr),
  962. table.firstvisible,
  963. &(table.firstvisible->starttime),
  964. &(table.firstvisible->spanbr),
  965. sizeof(unsigned long),
  966. statwin, &statcleared, statx);
  967. table.baridx = 1;
  968. }
  969. if ((table.barptr == tcpentry)
  970. || (table.barptr == tcpentry->oth_connection))
  971. set_barptr((void *) &(table.barptr),
  972. table.barptr,
  973. &(table.barptr->starttime),
  974. &(table.barptr->spanbr),
  975. sizeof(unsigned long), statwin,
  976. &statcleared, statx);
  977. }
  978. }
  979. /*
  980. * If we had an addentry() success, we should have no
  981. * problem here. Same thing if we had a table lookup
  982. * success.
  983. */
  984. if ((tcpentry != NULL)
  985. && !(tcpentry->stat & FLAG_RST)) {
  986. /*
  987. * Don't bother updating the entry if the connection
  988. * has been previously reset. (Does this really
  989. * happen in practice?)
  990. */
  991. if (revlook) {
  992. p_sstat = tcpentry->s_fstat;
  993. p_dstat = tcpentry->d_fstat;
  994. }
  995. if (ippacket != NULL)
  996. updateentry(&table, tcpentry, transpacket,
  997. pkt.pkt_buf, pkt.pkt_hatype,
  998. pkt.pkt_len, br, ippacket->frag_off,
  999. logging, &revlook, rvnfd, options,
  1000. logfile);
  1001. else
  1002. updateentry(&table, tcpentry, transpacket,
  1003. pkt.pkt_buf, pkt.pkt_hatype,
  1004. pkt.pkt_len, pkt.pkt_len, 0, logging,
  1005. &revlook, rvnfd, options,
  1006. logfile);
  1007. /*
  1008. * Log first packet of a TCP connection except if
  1009. * it's a RST, which was already logged earlier in
  1010. * updateentry()
  1011. */
  1012. if (logging
  1013. && (tcpentry->pcount == 1)
  1014. && (!(tcpentry->stat & FLAG_RST))) {
  1015. strcpy(msgstring, "first packet");
  1016. if (transpacket->syn)
  1017. strcat(msgstring, " (SYN)");
  1018. writetcplog(logging, logfile, tcpentry,
  1019. pkt.pkt_len, options->mac,
  1020. msgstring);
  1021. }
  1022. if ((revlook)
  1023. && (((p_sstat != RESOLVED)
  1024. && (tcpentry->s_fstat == RESOLVED))
  1025. || ((p_dstat != RESOLVED)
  1026. && (tcpentry->d_fstat == RESOLVED)))) {
  1027. clearaddr(&table, tcpentry, screen_idx);
  1028. clearaddr(&table, tcpentry->oth_connection,
  1029. screen_idx);
  1030. }
  1031. printentry(&table, tcpentry, screen_idx, mode);
  1032. /*
  1033. * Special cases: Update other direction if it's
  1034. * an ACK in response to a FIN.
  1035. *
  1036. * -- or --
  1037. *
  1038. * Addresses were just resolved for the other
  1039. * direction, so we should also do so here.
  1040. */
  1041. if (((tcpentry->oth_connection->finsent == 2)
  1042. && /* FINed and ACKed */
  1043. (ntohl(transpacket->seq) == tcpentry->oth_connection->finack))
  1044. || ((revlook)
  1045. && (((p_sstat != RESOLVED)
  1046. && (tcpentry->s_fstat == RESOLVED))
  1047. || ((p_dstat != RESOLVED)
  1048. && (tcpentry->d_fstat == RESOLVED)))))
  1049. printentry(&table, tcpentry->oth_connection,
  1050. screen_idx, mode);
  1051. }
  1052. } else if (ippacket != NULL) {
  1053. fragment = ((ntohs(ippacket->frag_off) & 0x1fff) != 0);
  1054. if (ippacket->protocol == IPPROTO_ICMP) {
  1055. /*
  1056. * Cancel the corresponding TCP entry if an ICMP
  1057. * Destination Unreachable or TTL Exceeded message
  1058. * is received.
  1059. */
  1060. if (((struct icmphdr *) transpacket)->type == ICMP_DEST_UNREACH)
  1061. process_dest_unreach(&table, (char *) transpacket,
  1062. ifname);
  1063. }
  1064. add_othp_entry(&othptbl, &pkt, ippacket->saddr,
  1065. ippacket->daddr, NULL, NULL, IS_IP,
  1066. ippacket->protocol,
  1067. (char *) transpacket,
  1068. ifname, &revlook, rvnfd,
  1069. logging, logfile,
  1070. options->servnames, fragment);
  1071. } else {
  1072. if (ip6packet->ip6_nxt == IPPROTO_ICMPV6
  1073. && (((struct icmp6_hdr *) transpacket)->icmp6_type == ICMP6_DST_UNREACH))
  1074. process_dest_unreach(&table, (char *) transpacket,
  1075. ifname);
  1076. add_othp_entry(&othptbl, &pkt, 0, 0,
  1077. &ip6packet->ip6_src, &ip6packet->ip6_dst,
  1078. IS_IP, ip6packet->ip6_nxt,
  1079. (char *) transpacket, ifname,
  1080. &revlook, rvnfd,
  1081. logging, logfile, options->servnames,
  1082. fragment);
  1083. }
  1084. }
  1085. err_close:
  1086. close(fd);
  1087. err:
  1088. if (get_instance_count(ITRAFMONCOUNTFILE) <= 1)
  1089. killrvnamed();
  1090. if (options->servnames)
  1091. endservent();
  1092. endprotoent();
  1093. close_rvn_socket(rvnfd);
  1094. if ((options->promisc) && (is_last_instance())) {
  1095. load_promisc_list(&promisc_list);
  1096. srpromisc(0, promisc_list);
  1097. destroy_promisc_list(&promisc_list);
  1098. }
  1099. attrset(STDATTR);
  1100. mvprintw(0, COLS - 20, " ");
  1101. del_panel(table.tcppanel);
  1102. del_panel(table.borderpanel);
  1103. del_panel(othptbl.othppanel);
  1104. del_panel(othptbl.borderpanel);
  1105. del_panel(statpanel);
  1106. update_panels();
  1107. doupdate();
  1108. delwin(table.tcpscreen);
  1109. delwin(table.borderwin);
  1110. delwin(othptbl.othpwin);
  1111. delwin(othptbl.borderwin);
  1112. delwin(statwin);
  1113. destroytcptable(&table);
  1114. destroyothptable(&othptbl);
  1115. pkt_cleanup();
  1116. if (logging) {
  1117. signal(SIGUSR1, SIG_DFL);
  1118. writelog(logging, logfile,
  1119. "******** IP traffic monitor stopped ********\n");
  1120. fclose(logfile);
  1121. strcpy(current_logfile, "");
  1122. }
  1123. adjust_instance_count(PROCCOUNTFILE, -1);
  1124. adjust_instance_count(ITRAFMONCOUNTFILE, -1);
  1125. unmark_facility(IPMONIDFILE, ifptr);
  1126. }