"SfR Fresh" - the SfR Freeware/Shareware Archive

Member "trafshow-3.1/display.c" of archive trafshow-3.1.tgz:


As a special service "SfR Fresh" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting with prefixed line numbers. Alternatively you can here view or download the uninterpreted source code file. That can be also achieved for any archive member file by clicking within an archive contents listing on the first character of the file(path) respectively on the according byte size field.
    1 /*
    2  *	Copyright (c) 1993-1997 JSC Rinet, Novosibirsk, Russia
    3  *
    4  * Redistribution and use in source forms, with and without modification,
    5  * are permitted provided that this entire comment appears intact.
    6  * Redistribution in binary form may occur without any restrictions.
    7  *
    8  * THIS SOFTWARE IS PROVIDED ``AS IS'' WITHOUT ANY WARRANTIES OF ANY KIND.
    9  */
   10 
   11 /* display.c -- collect and display network traffic */
   12 
   13 char copyright[] = "Copyright (c) 1993-1997 JSC Rinet, Novosibirsk, Russia";
   14 
   15 #ifdef	HAVE_CONFIG_H
   16 #include <config.h>
   17 #endif
   18 
   19 #ifdef	HAVE_SLCURSES
   20 #include <slcurses.h>
   21 #endif
   22 #ifdef	HAVE_NCURSES
   23 #include <ncurses.h>
   24 #endif
   25 #ifdef	HAVE_CURSES
   26 #include <curses.h>
   27 #endif
   28 
   29 #include <sys/types.h>
   30 #include <sys/time.h>
   31 #include <netinet/in.h>
   32 #include <netinet/in_systm.h>
   33 #include <netinet/ip.h>
   34 #include <netinet/ip_icmp.h>
   35 #include <netinet/udp.h>
   36 #include <netinet/tcp.h>
   37 #include <stdlib.h>
   38 #include <signal.h>
   39 #include <string.h>
   40 #include <unistd.h>
   41 #ifdef	TIME_WITH_SYS_TIME
   42 #include <time.h>
   43 #endif
   44 
   45 #include "trafshow.h"
   46 
   47 typedef struct t_entry *p_entry;
   48 struct t_entry *entries;
   49 int n_entry = 0;
   50 u_long bytes_total = 0;
   51 u_long packets_total = 0;
   52 int page = 0;
   53 int page_size;
   54 static int l_nflag, l_eflag;
   55 static int n_entries;
   56 static int err_pos;
   57 
   58 void
   59 init_display(reinit)
   60 	int reinit;
   61 {
   62 	if (!reinit) {
   63 		n_entries = LINES * MAX_PAGES;
   64 		entries = (struct t_entry *)calloc(n_entries, sizeof(struct t_entry));
   65 		if (!entries) error(1, "init_display: calloc");
   66 		l_nflag = nflag;
   67 		l_eflag = eflag;
   68 		alarm(scr_interval);
   69 	} else {
   70 		int i = LINES * MAX_PAGES;
   71 		if (i > n_entries) {
   72 			n_entries = i;
   73 			entries = (struct t_entry *)realloc(entries, i * sizeof(struct t_entry));
   74 			if (!entries) error(1, "init_display: realloc");
   75 		}
   76 		page = 0;
   77 	}
   78 	err_pos = strlen(device_name) + count_size + 15;
   79 }
   80 
   81 void
   82 header_line()
   83 {
   84 	int i;
   85 
   86 	mvprintw(0, 0, "%-*.*s %-*.*s %-*.*s %*.*s %-*.*s",
   87 		 addr_size, addr_size, "From Address",
   88 		 addr_size, addr_size, "To Address",
   89 		 proto_size, proto_size, "Proto",
   90 		 bytes_size, bytes_size, "Bytes",
   91 		 cps_size, cps_size, "CPS");
   92 	for (i = 0; i < COLS; i++) mvaddch(1, i, '=');
   93 }
   94 
   95 void
   96 status_line(reinit)
   97 	int reinit;
   98 {
   99 	static time_t tp = 0;
  100 	static u_long bytes_prev = 0, packets_prev = 0;
  101 
  102 	if (reinit) {
  103 		time_t tn = time(NULL);
  104 		register sec = tn - tp;
  105 		if (sec < 1) sec = 1;
  106 		mvprintw(LINES-1, 0, "(%.5s) %*ld kb/total %*d pkts/sec %*d bytes/sec",
  107 			 device_name, count_size, bytes_total/1024,
  108 			 count_size, (packets_total-packets_prev)/sec,
  109 			 count_size, (bytes_total-bytes_prev)/sec);
  110 		packets_prev = packets_total;
  111 		bytes_prev = bytes_total;
  112 		tp = tn;
  113 	} else	mvprintw(LINES-1, 0, "(%.5s) %*ld kb/total",
  114 			 device_name, count_size, bytes_total/1024);
  115 	mvprintw(LINES-1, COLS-13, " Page %2d/%-2d", page+1, n_entry/page_size+1);
  116 	clrtoeol();
  117 }
  118 
  119 /*
  120  * Pretty print an Internet address (net address + port).
  121  */
  122 static char *
  123 inet_print(in, port, proto)
  124 	struct in_addr in;
  125 	u_short port, proto;
  126 {
  127 	register char *cp;
  128 	char pline[20];
  129 	int alen, plen;
  130 	static char aline[1024];
  131 	static char *icmp_type[ICMP_MAXTYPE+1] = {
  132 		"echoreply", "unknown", "unknown", "dstunreach", "srcquench",
  133 		"redirect", "unknown", "unknown", "echoreqst", "rtradvert",
  134 		"rtrsolicit", "timeexceed", "paramprobl", "stampreqst",
  135 		"stampreply", "inforeqst", "inforeply", "maskreqst",
  136 		"maskreply" };
  137 
  138 	if (l_nflag) cp = intoa(in.s_addr);
  139 	else cp = ipaddr_string(&in);
  140 	(void) sprintf(aline, "%-*.*s", addr_size, addr_size, cp);
  141 
  142 	if (port) {
  143 		if (proto == IPPROTO_TCP)
  144 			cp = tcpport_string(port);
  145 		else if (proto == IPPROTO_UDP)
  146 			cp = udpport_string(port);
  147 		else if (proto == IPPROTO_ICMP && port <= ICMP_MAXTYPE)
  148 			cp = icmp_type[port];
  149 		else cp = "unknown";
  150 
  151 		plen = sprintf(pline, "..%.10s", cp);
  152 
  153 		if ((cp = strchr(aline, ' ')) != NULL)
  154 			alen = cp - aline;
  155 		else	alen = addr_size;
  156 		if ((alen + plen) >= addr_size)
  157 			memcpy(&aline[addr_size - plen], pline, plen);
  158 		else	memcpy(&aline[alen], pline, plen);
  159 	}
  160 	return aline;
  161 }
  162 
  163 static void
  164 main_print(line, i)
  165 	int line;
  166 	register i;
  167 {
  168 	char *proto;
  169 	int normal = TRUE;
  170 
  171 	move(SCR_OFFS+line, 0);
  172 #ifdef	HAVE_HAS_COLORS
  173 	if (use_colors) normal = !color_on(&entries[i]);
  174 #endif
  175 	if (l_eflag) {
  176 		printw("%-*.*s", addr_size, addr_size,
  177 		       l_nflag ? entoa(entries[i].eh.ether_shost) :
  178 		       etheraddr_string(entries[i].eh.ether_shost));
  179 		addch(' ');
  180 		printw("%-*.*s", addr_size, addr_size,
  181 		       l_nflag ? entoa(entries[i].eh.ether_dhost) :
  182 		       etheraddr_string(entries[i].eh.ether_dhost));
  183 
  184 		proto = etherproto_string(entries[i].eh.ether_type);
  185 	} else {
  186 		addstr(inet_print(entries[i].src, entries[i].sport, entries[i].proto));
  187 		addch(' ');
  188 		addstr(inet_print(entries[i].dst, entries[i].dport, entries[i].proto));
  189 
  190 		proto = getprotoname(entries[i].proto);
  191 		if (proto == NULL) proto = "unknown";
  192 	}
  193 
  194 	printw(" %-*.*s", proto_size, proto_size, proto);
  195 #ifdef	HAVE_HAS_COLORS
  196 	if (!normal) attrset(A_NORMAL);
  197 #endif
  198 	printw(" %*ld", bytes_size, entries[i].bytes);
  199 	if (entries[i].cps) printw(" %-*d", cps_size, entries[i].cps);
  200 	clrtoeol();
  201 }
  202 
  203 static int
  204 sortbybytes(e1, e2)
  205 	register p_entry e1, e2;
  206 {
  207 	if (e1->bytes > e2->bytes) return -1;
  208 	if (e1->bytes < e2->bytes) return 1;
  209 	return 0;
  210 }
  211 
  212 /*
  213  * If scr_interval time any entry wasn't changed then purge it
  214  * and redraw whole screen.
  215  */
  216 void
  217 scr_redraw(del_old)
  218 	int del_old;
  219 {
  220 	register i, j;
  221 
  222 	if (del_old) {
  223 		alarm(0);
  224 		for (i = j = 0; i < n_entry; i++) {
  225 			if (entries[i].bytes != entries[i].obytes)
  226 				entries[i].cps = (entries[i].bytes - entries[i].obytes)/scr_interval;
  227 			else	entries[i].bytes = 0, j++;
  228 			entries[i].obytes = entries[i].bytes;
  229 		}
  230 		qsort(entries, n_entry, sizeof(struct t_entry), sortbybytes);
  231 		n_entry -= j;
  232 	}
  233 	j = n_entry/page_size;
  234 	if (page > j) page = j;
  235 
  236 	move(SCR_OFFS, 0);
  237 	if (n_entry) {
  238 		for (i = 0, j = page * page_size;
  239 		     i < page_size && j < n_entry; i++, j++)
  240 			main_print(i, j);
  241 	} else {
  242 		clrtoeol();
  243 		switch (alarm_flag) {
  244 		case 1:
  245 			addstr("Where is the tcp or udp packets contained data? It is exactly what I want! Now!");
  246 			break;
  247 		case 2:
  248 			addstr("Nothing to show, this interface sleeping or broken. blah-blah-gluk-gluk-wait...");
  249 			break;
  250 		default:
  251 			i = COLS/2 - strlen(copyright)/2;
  252 			if (i < 0) i = 0;
  253 			mvaddstr(SCR_OFFS, i, copyright);
  254 			alarm_flag = 1;
  255 		}
  256 	}
  257 	clrtobot();
  258 	status_line(del_old);
  259 	if (del_old) alarm(scr_interval);
  260 }
  261 
  262 void
  263 scr_update()
  264 {
  265 #ifdef	HAVE_HAS_COLORS
  266 	move(LINES-1, COLS-1);
  267 #else
  268 	move(0, COLS-1);
  269 #endif
  270 	refresh();
  271 }
  272 
  273 /*
  274  * Add new entry or add bytes to existed record.
  275  */
  276 static void
  277 collect(e)
  278 	register p_entry e;
  279 {
  280 	register i, j;
  281 
  282 	packets_total++;
  283 	bytes_total += e->bytes;
  284 	j = page * page_size;
  285 	for (i = 0; i < n_entry; i++) {
  286 		if (memcmp(&e->eh, &entries[i].eh, sizeof(e->eh)) == 0 &&
  287 		    e->src.s_addr == entries[i].src.s_addr &&
  288 		    e->sport == entries[i].sport &&
  289 		    e->dst.s_addr == entries[i].dst.s_addr &&
  290 		    e->dport == entries[i].dport &&
  291 		    e->proto == entries[i].proto) {
  292 			entries[i].bytes += e->bytes;
  293 			if (i >= j && i < j + page_size)
  294 				mvprintw(i-j+SCR_OFFS, addr_size*2+proto_size+3,
  295 					 "%*ld", bytes_size, entries[i].bytes);
  296 			return;
  297 		}
  298 	}
  299 	if (i >= LINES * MAX_PAGES) {
  300 		mvaddstr(LINES-1, COLS-13, " Overflow");
  301 		clrtoeol();
  302 		return;
  303 	}
  304 	/* add new entry */
  305 	entries[i] = *e;
  306 	entries[i].obytes = entries[i].cps = 0;
  307 	if (i >= j && i < j + page_size) main_print(i-j, i);
  308 	n_entry++;
  309 	status_line(0);
  310 }
  311 
  312 void
  313 display(eh, ip, length)
  314 	struct ether_header *eh;
  315 	register struct ip *ip;
  316 	int length;
  317 {
  318 	register iplen;
  319 	int hlen, not_ip = 0;
  320 	register u_char *cp;
  321 	struct t_entry te;
  322 
  323 	if ((u_char *)(ip + 1) > snapend) {
  324 		if (!eflag) return; /* not ip proto? discard silently */
  325 		not_ip++;
  326 	} else if (length < sizeof(*ip)) {
  327 		if (!eflag) {
  328 			mvprintw(LINES-1, err_pos, "\
  329 truncated-ip: discard %d bytes", length);
  330 			clrtoeol();
  331 			goto refresh_screen;
  332 		}
  333 		not_ip++;
  334 	} else if (ip->ip_v != IPVERSION) {
  335 		if (!eflag) {
  336 			mvprintw(LINES-1, err_pos, "\
  337 ip ver != %d: discard %d bytes", IPVERSION, length);
  338 			clrtoeol();
  339 			goto refresh_screen;
  340 		}
  341 		not_ip++;
  342 	} else if ((iplen = ntohs(ip->ip_len)) < 1) {
  343 		if (!eflag) return; /* empty ip packet? discard silently */
  344 		not_ip++;
  345 	} else if (length < iplen) {
  346 		if (!eflag) {
  347 			mvprintw(LINES-1, err_pos, "\
  348 truncated-ip: %d bytes missing", iplen - length);
  349 			clrtoeol();
  350 			goto refresh_screen;
  351 		}
  352 		not_ip++;
  353 	}
  354 
  355 	if (eh)	te.eh = *eh;
  356 	else memset(&te.eh, 0, sizeof(te.eh));
  357 
  358 	te.sport = te.dport = 0;
  359 
  360 	if (!not_ip) {	/* parse ip packet */
  361 
  362 		/*
  363 		* If this is fragment zero, hand it to the next higher level
  364 		* protocol to fetch ports or icmp type else it is fragmented
  365 		* ip datagram.
  366 		*/
  367 		if ((ntohs(ip->ip_off) & 0x1fff) == 0) {
  368 			/* advance to high level protocol header */
  369 			hlen = ip->ip_hl * 4;
  370 			cp = (u_char *)ip + hlen;
  371 			if (ip->ip_p == IPPROTO_TCP) {
  372 				if (cp + sizeof(struct tcphdr) > snapend ||
  373 				    iplen - hlen < sizeof(struct tcphdr)) {
  374 					mvprintw(LINES-1, err_pos, "\
  375 truncated-tcp: wrong ip hdrlen");
  376 					clrtoeol();
  377 					goto refresh_screen;
  378 				}
  379 				te.sport = ntohs(((struct tcphdr *)cp)->th_sport);
  380 				te.dport = ntohs(((struct tcphdr *)cp)->th_dport);
  381 			} else if (ip->ip_p == IPPROTO_UDP) {
  382 				if (cp + sizeof(struct udphdr) > snapend ||
  383 				    iplen - hlen < sizeof(struct udphdr)) {
  384 					mvprintw(LINES-1, err_pos, "\
  385 truncated-udp: wrong ip hdrlen");
  386 					clrtoeol();
  387 					goto refresh_screen;
  388 				}
  389 				te.sport = ntohs(((struct udphdr *)cp)->uh_sport);
  390 				te.dport = ntohs(((struct udphdr *)cp)->uh_dport);
  391 			} else if (ip->ip_p == IPPROTO_ICMP) {
  392 				if (cp + sizeof(struct icmp) > snapend ||
  393 				    iplen - hlen < sizeof(struct icmp)) {
  394 					mvprintw(LINES-1, err_pos, "\
  395 truncated-icmp: wrong ip hdrlen");
  396 					clrtoeol();
  397 					goto refresh_screen;
  398 				}
  399 				te.sport = ((struct icmp *)cp)->icmp_type;
  400 			}
  401 		}
  402 		te.src.s_addr = ip->ip_src.s_addr;
  403 		te.dst.s_addr = ip->ip_dst.s_addr;
  404 		te.proto = ip->ip_p;
  405 		te.bytes = iplen;
  406 	} else {	/* other than ip protocol packets */
  407 		te.src.s_addr = te.dst.s_addr = 0;
  408 		te.proto = 0;
  409 		te.bytes = length;
  410 	}
  411 
  412 	collect(&te);
  413 
  414 	if (alarm_flag) {
  415 		alarm_flag = 0;
  416 		if (resize_flag) {
  417 			resize_flag = 0;
  418 			init_term(TRUE);
  419 		}
  420 		scr_redraw(TRUE);
  421 	}
  422 
  423 refresh_screen:
  424 	if (kflag && kbhit(0) && get_keyb()) scr_redraw(FALSE);
  425 
  426 	scr_update();
  427 	return;
  428 }
  429 
  430 int
  431 inputchar()
  432 {
  433 	return getch();
  434 }
  435 
  436 int
  437 get_keyb()
  438 {
  439 	int ch;
  440 
  441 	if ((ch = getch()) == ERR) error(1, "get_keyb: getch");
  442 	switch(ch) {
  443 	case ESC:
  444 		switch(get_arrowkey(inputchar)) {
  445 		case KEYMAP_UP:
  446 		case KEYMAP_PAGE_UP:
  447 			goto page_up;
  448 		case KEYMAP_DOWN:
  449 		case KEYMAP_PAGE_DOWN:
  450 			goto page_down;
  451 		case KEYMAP_LEFT:
  452 		case KEYMAP_HOME:
  453 			goto home_list;
  454 		case KEYMAP_RIGHT:
  455 		case KEYMAP_END:
  456 			goto end_list;
  457 		default:
  458 			mvaddstr(LINES-1, COLS-13, " Bad command");
  459 			return 0;
  460 		}
  461 		break;
  462 
  463 	case 'k':		/* line up */
  464 	case ctrl('P'):
  465 	case '\b':		/* page up */
  466 	case 'b':
  467 	case ctrl('U'):
  468 	case ctrl('B'):
  469 page_up:
  470 		if (page > 0) page--;
  471 		break;
  472 
  473 	case 'j':
  474 	case ctrl('N'):		/* line down */
  475 	case ' ':		/* page down */
  476 	case ctrl('D'):
  477 	case ctrl('F'):
  478 page_down:
  479 		if (page < n_entry/page_size) page++;
  480 		break;
  481 
  482 	case ctrl('A'):		/* home */
  483 home_list:
  484 		page = 0;
  485 		break;
  486 
  487 	case ctrl('E'):		/* end */
  488 end_list:
  489 		page = n_entry/page_size;
  490 		break;
  491 
  492 	case '\r':		/* enter */
  493 	case '\n':
  494 		l_eflag ^= 1;
  495 		break;
  496 
  497 	case '\t':		/* tab */
  498 		l_nflag ^= 1;
  499 		break;
  500 
  501 	case 'q':		/* quit */
  502 		cleanup(SIGINT);
  503 
  504 	case ctrl('L'):		/* refresh screen */
  505 		clear();
  506 		header_line();
  507 		scr_redraw(FALSE);
  508 		scr_update();
  509 		break;
  510 
  511 	default:
  512 		mvaddstr(LINES-1, COLS-13, " Bad command");
  513 		return 0;
  514 	}
  515 	return 1;
  516 }