File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / trafshow / colormask.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Tue Feb 21 16:55:18 2012 UTC (12 years, 4 months ago) by misho
Branches: trafshow, MAIN
CVS tags: v5_2_3p0, v5_2_3, HEAD
trafshow

    1: /*
    2:  *	Copyright (c) 1993-1997,2004 Rinet Corp., 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: #ifdef	HAVE_CONFIG_H
   12: #include <config.h>
   13: #endif
   14: 
   15: #ifdef	HAVE_HAS_COLORS
   16: 
   17: #ifdef	HAVE_SLCURSES
   18: #include <slcurses.h>
   19: #elif	HAVE_NCURSES
   20: #include <ncurses.h>
   21: #else
   22: #include <curses.h>
   23: #endif
   24: #include <sys/param.h>
   25: #include <sys/types.h>
   26: #include <sys/socket.h>
   27: #include <netinet/in.h>
   28: #include <arpa/inet.h>
   29: #include <stdio.h>
   30: #include <stdlib.h>
   31: #include <string.h>
   32: #include <unistd.h>
   33: #include <ctype.h>
   34: #include <netdb.h>
   35: #include <errno.h>
   36: 
   37: #include "colormask.h"
   38: #include "trafshow.h"
   39: #include "netstat.h"
   40: #ifdef	DEBUG
   41: #include "show_stat.h" /* just for hdr2str() */
   42: #endif
   43: 
   44: /* mask entry */
   45: struct cm_entry {
   46: 	struct internet_header in_hdr;
   47: 	int src_mask;		/* source ip address mask */
   48: 	int dst_mask;		/* destination ip address mask */
   49: 
   50: 	short   pair;		/* color-pair */
   51: 	int     attr;		/* video attributes; bold, blink, etc */
   52: };
   53: 
   54: static struct cm_entry *color_mask = NULL;
   55: static int n_masks = 0;
   56: static int n_pairs = 0;
   57: static const char *rc_file = 0;
   58: static int rc_line;
   59: 
   60: /* SLcurses can't handle attributes as well; so hack it */
   61: #ifdef	HAVE_SLCURSES
   62: static void
   63: slang_init_pair(short pair, short fc, short bc, int at)
   64: {
   65: 	SLtt_set_color_object(pair, ((fc | (bc << 8)) << 8) | at);
   66: }
   67: 
   68: static int
   69: slang_pair_content(short pair, short *fc, short *bc)
   70: {
   71: 	int attr;
   72: 	SLtt_Char_Type at;
   73: 
   74: 	at = SLtt_get_color_object(pair);
   75: 	attr = at & (A_BOLD | A_BLINK);
   76: 	at &= ~(A_BOLD | A_BLINK);
   77: 	at >>= 8;
   78: 	*fc = at & 0xff;
   79: 	*bc = (at >> 8) & 0xff;
   80: 
   81: 	return attr;
   82: }
   83: #endif	/* HAVE_SLCURSES */
   84: 
   85: static short
   86: findpair(short f, short b, int a)
   87: {
   88: 	int i;
   89: 	short f1 = -1, b1 = -1;
   90: 	struct cm_entry *cm;
   91: 
   92: 	for (cm = color_mask, i = 0; cm != NULL && i < n_masks-1; cm++, i++) {
   93: #ifdef	HAVE_SLCURSES
   94: 		int a1 = slang_pair_content(cm->pair, &f1, &b1);
   95: 		if (f1 >= COLORS) f1 = -1;
   96: 		if (b1 >= COLORS) b1 = -1;
   97: 		if (f == f1 && b == b1 && a == a1) return cm->pair;
   98: #else
   99: 		pair_content(cm->pair, &f1, &b1);
  100: 		if (f1 >= COLORS) f1 = -1;
  101: 		if (b1 >= COLORS) b1 = -1;
  102: 		if (f == f1 && b == b1) return cm->pair;
  103: #endif
  104: 	}
  105: 	return 0;
  106: }
  107: 
  108: static int
  109: add_colormask(const char *s, struct cm_entry *m)
  110: {
  111: 	int i, attr = 0;
  112: 	short fc, bc;
  113: 	char f[100], *b;
  114: 	static char *ctab[8] = { "black", "red", "green", "yellow",
  115: 				"blue",	"magenta", "cyan", "white" };
  116: #ifdef	HAVE_USE_DEFAULT_COLORS
  117: 	static short fc_def = -1, bc_def = -1;
  118: #else
  119: 	static short fc_def = COLOR_WHITE, bc_def = COLOR_BLACK;
  120: #endif
  121: 
  122: 	if ((b = strchr(strcpy(f, s), ':')) != NULL) *b++ = '\0';
  123: 
  124: 	if (*f) {
  125: 		for (i = 0; i < 8; i++)
  126: 			if (!strcasecmp(ctab[i], f)) break;
  127: 		if (i < 8) fc = i;
  128: 		else {
  129: 			fc = atoi(f);
  130: 			if (fc < 1 || fc > COLORS) {
  131: 				fprintf(stderr, "%s: line %d: Unknown color `%s'\n",
  132: 					rc_file, rc_line, f);
  133: 				return -1;
  134: 			}
  135: 		}
  136: 		if (isupper((int)*f)) attr |= A_BOLD;
  137: 	} else fc = fc_def;
  138: 
  139: 	if (b && *b) {
  140: 		for (i = 0; i < 8; i++)
  141: 			if (!strcasecmp(ctab[i], b)) break;
  142: 		if (i < 8) bc = i;
  143: 		else {
  144: 			bc = atoi(b);
  145: 			if (bc < 1 || bc > COLORS) {
  146: 				fprintf(stderr, "%s: line %d: Unknown color `%s'\n",
  147: 					rc_file, rc_line, b);
  148: 				return -1;
  149: 			}
  150: 		}
  151: 		if (isupper((int)*b)) attr |= A_BLINK;
  152: 	} else bc = bc_def;
  153: 
  154: 	if (m != NULL) {
  155: 		if ((color_mask = realloc(color_mask, ++n_masks * sizeof(struct cm_entry))) == NULL) {
  156: 			fprintf(stderr, "add_colormask: realloc: Out of memory?\n");
  157: 			return -1;
  158: 		}
  159: 		if ((m->pair = findpair(fc, bc, attr)) == 0) {
  160: 			if (++n_pairs < COLOR_PAIRS-1) {
  161: #ifdef	HAVE_SLCURSES
  162: 				slang_init_pair(n_pairs, fc, bc, attr);
  163: #else
  164: 				init_pair(n_pairs, fc, bc);
  165: #endif
  166: 			} else {
  167: 				fprintf(stderr, "%s: line %d: Max %d color-pairs can be used\n",
  168: 					rc_file, rc_line, COLOR_PAIRS-1);
  169: 				return -1;
  170: 			}
  171: 			m->pair = n_pairs;
  172: 		}
  173: 		m->attr = attr;
  174: 		memcpy(color_mask + (n_masks-1), m, sizeof(struct cm_entry));
  175: 	} else {	/* default colors */
  176: #ifdef	HAVE_SLCURSES
  177: 		slang_init_pair(0, fc, bc, attr);
  178: #else
  179: #ifdef	HAVE_BKGD
  180: 		init_pair(COLOR_PAIRS-1, fc, bc);
  181: 		bkgd(COLOR_PAIR(COLOR_PAIRS-1) | attr);
  182: #elif	HAVE_WBKGD
  183: 		init_pair(COLOR_PAIRS-1, fc, bc);
  184: 		wbkgd(stdscr, COLOR_PAIR(COLOR_PAIRS-1) | attr);
  185: #else /* assume the color-pair 0 is background for whole screen */
  186: 		init_pair(0, fc, bc);
  187: #endif
  188: #endif
  189: 		fc_def = fc;
  190: 		bc_def = bc;
  191: 	}
  192: 	return 0;
  193: }
  194: 
  195: static int
  196: is_any(const char *s)
  197: {
  198: 	if (!s || !*s) return 0;
  199: 	return (!strcmp(s, "*") || !strcasecmp(s, "any") || !strcasecmp(s, "all"));
  200: }
  201: 
  202: static int
  203: is_number(const char *s)
  204: {
  205: 	if (!s || !*s) return 0;
  206: 	for (; *s; s++) {
  207: 		if (!isdigit((int)*s)) return 0;
  208: 	}
  209: 	return 1;
  210: }
  211: 
  212: static char *
  213: str2proto(const char *str, int *proto)
  214: {
  215: 	int num;
  216: 	struct protoent *pe;
  217: 
  218: 	if (is_any(str)) {
  219: 		*proto = 0;
  220: 		return "";
  221: 	}
  222: 	if (is_number(str)) {
  223: 		num = atoi(str);
  224: 		if (num > 0 && num <= 0xff) {
  225: 			if ((pe = getprotobynumber(num)) != 0) {
  226: 				*proto = pe->p_proto;
  227: 				return pe->p_name;
  228: 			}
  229: 			*proto = num;
  230: 			return "";
  231: 		}
  232: 	}
  233: 	if ((pe = getprotobyname(str)) != 0) {
  234: 		*proto = pe->p_proto;
  235: 		return pe->p_name;
  236: 	}
  237: 	fprintf(stderr, "%s: line %d: Unknown protocol `%s'\n",
  238: 		rc_file, rc_line, str);
  239: 	return 0;
  240: }
  241: 
  242: static int
  243: str2port(const char *str, const char *proto)
  244: {
  245: 	int num;
  246: 	struct servent *se;
  247: 
  248: 	if (is_any(str))
  249: 		return 0;
  250: 
  251: 	num = atoi(str);
  252: 	if (num > 0 && num <= 0xffff)
  253: 		return htons((u_int16_t)num);
  254: 
  255: 	if ((se = getservbyname(str, (proto && *proto) ? proto : 0)) != 0)
  256: 		return se->s_port;
  257: 
  258: 	if (proto && *proto) {
  259: 		fprintf(stderr, "%s: line %d: Unknown port `%s' at protocol `%s'\n",
  260: 			rc_file, rc_line, str, proto);
  261: 	} else {
  262: 		fprintf(stderr, "%s: line %d: Unknown port `%s'\n",
  263: 			rc_file, rc_line, str);
  264: 	}
  265: 	return -1;
  266: }
  267: 
  268: static int
  269: str2addr(const char *str, const char *proto, struct ip_address *addr, int *mask)
  270: {
  271: 	int op, ver = 0;
  272: 	char buf[256], *cp, *mp, *pp;
  273: 
  274: 	if (proto && !strcasecmp(proto, "IPv6")) {
  275: #ifdef INET6
  276: 		ver = 6;
  277: #else
  278: 		fprintf(stderr, "%s: line %d: IPv6 is unsupported at this system\n",
  279: 			rc_file, rc_line);
  280: 		return -1;
  281: #endif
  282: 	}
  283: 	cp = strcpy(buf, str);
  284: 	if ((mp = strchr(cp, '/')) != 0) {
  285: 		*mp++ = '\0';
  286: 		cp = mp;
  287: 	}
  288: 	if ((pp = strchr(cp, ',')) != 0) {
  289: 		*pp++ = '\0';
  290: 	}
  291: 	if (mp && !is_number(mp)) {
  292: 		fprintf(stderr, "%s: line %d: %s: Mask must be number of bits\n",
  293: 			rc_file, rc_line, mp);
  294: 		return -1;
  295: 	}
  296: 	if (!is_any(buf)) {
  297: 		op = 0;
  298: #ifdef INET6
  299: 		if (ver == 6 || strchr(buf, ':')) {
  300: 			ver = 6;
  301: 			op = inet_pton(AF_INET6, buf, &addr->ip6_addr);
  302: 			if (op < 0) {
  303: 				fprintf(stderr, "%s: line %d: %s: %s\n",
  304: 					rc_file, rc_line, buf, strerror(errno));
  305: 				return -1;
  306: 			}
  307: 		}
  308: #endif
  309: 		if (!op) {
  310: 			ver = 4;
  311: 			op = inet_pton(AF_INET, buf, &addr->ip_addr);
  312: 			if (op < 0) {
  313: 				fprintf(stderr, "%s: line %d: %s: %s\n",
  314: 					rc_file, rc_line, buf, strerror(errno));
  315: 				return -1;
  316: 			}
  317: 		}
  318: 		if (!op) {
  319: 			struct hostent *he;
  320: 			if ((he = gethostbyname(buf)) == 0) {
  321: 				fprintf(stderr, "%s: line %d: %s: Unknown host\n",
  322: 					rc_file, rc_line, buf);
  323: 				return -1;
  324: 			}
  325: 			if (he->h_addrtype == AF_INET) {
  326: 				ver = 4;
  327: 				memcpy(&addr->ip_addr, he->h_addr,
  328: 				       MIN(sizeof(addr->ip_addr), he->h_length));
  329: 			}
  330: #ifdef INET6
  331: 			else if (he->h_addrtype == AF_INET6) {
  332: 				ver = 6;
  333: 				memcpy(&addr->ip6_addr, he->h_addr,
  334: 				       MIN(sizeof(addr->ip6_addr), he->h_length));
  335: 			}
  336: #endif
  337: 			else {
  338: 				fprintf(stderr, "%s: line %d: %s: Unknown address family\n",
  339: 					rc_file, rc_line, buf);
  340: 				return -1;
  341: 			}
  342: 		}
  343: 	}
  344: 	if (pp) {
  345: 		if ((op = str2port(pp, proto)) == -1)
  346: 			return -1;
  347: 		addr->ip_port = op;
  348: 	}
  349: 	if (mask) {
  350: 		if (mp) {
  351: 			op = atoi(mp);
  352: 			if (op < 8 || op > 128) {
  353: 				fprintf(stderr, "%s: line %d: %d: Wrong mask\n",
  354: 					rc_file, rc_line, op);
  355: 				return -1;
  356: 			}
  357: 			*mask = op;
  358: 		} else	*mask = 0;
  359: 	}
  360: 	return ver;
  361: }
  362: 
  363: int
  364: init_colormask()
  365: {
  366: 	FILE *fp;
  367: 	int num;
  368: 	struct cm_entry me, *cm;
  369: 	char *cp, buf[1024];
  370: 	char s1[256], s2[256], s3[256], s4[256];
  371: 
  372: 	if (rc_file) {
  373: 		free((char *)rc_file);
  374: 		rc_file = 0;
  375: 	}
  376: 	if (!color_conf) {
  377: 		if ((cp = getenv("HOME")) != 0) {
  378: 			(void)strcpy(buf, cp);
  379: 			(void)strcat(buf, "/");
  380: 		} else	buf[0] = '\0';
  381: 		(void)strcat(buf, ".");
  382: 		(void)strcat(buf, progname);
  383: 		if ((fp = fopen(buf, "r")) == NULL) {
  384: 			(void)strcpy(buf, "/etc/");
  385: 			(void)strcat(buf, progname);
  386: 			if ((fp = fopen(buf, "r")) == NULL) return 0;
  387: 		}
  388: 		rc_file = strdup(buf);
  389: 	} else {
  390: 		if ((fp = fopen(color_conf, "r")) == NULL) {
  391: 			fprintf(stderr, "%s: %s\n", color_conf, strerror(errno));
  392: 			return -1;
  393: 		}
  394: 		rc_file = strdup(color_conf);
  395: 	}
  396: 	if (!rc_file) {
  397: 		fprintf(stderr, "init_colormask: strdup: Out of memory?\n");
  398: 		(void)fclose(fp);
  399: 		return -1;
  400: 	}
  401: 	rc_line = 0;
  402: 	cm = &me;
  403: 
  404: #ifdef	HAVE_USE_DEFAULT_COLORS
  405: 	use_default_colors();
  406: #endif
  407: 	while (fgets(buf, sizeof(buf), fp) != NULL) {
  408: 		rc_line++;
  409: 		if (buf[0] == '\n' || buf[0] == '#') continue;
  410: 		if ((cp = strchr(buf, '#')) != NULL) {
  411: 			*cp++ = '\n';
  412: 			*cp = '\0';
  413: 		}
  414: 		memset(cm, 0, sizeof(struct cm_entry));
  415: 		num = sscanf(buf, "%s %s %s %s\n", s1, s2, s3, s4);
  416: 		if (num == 2) {
  417: 			if (strcasecmp(s1, "default")) {
  418: 				if ((cp = strchr(s1, '/')) != 0) {
  419: 					*cp++ = '\0';
  420: 					if ((cp = str2proto(cp, &num)) == 0) {
  421: 						(void)fclose(fp);
  422: 						return -1;
  423: 					}
  424: 					cm->in_hdr.proto = num;
  425: 				}
  426: 				if ((num = str2port(s1, cp)) == -1) {
  427: 					(void)fclose(fp);
  428: 					return -1;
  429: 				}
  430: 				cm->in_hdr.src.ip_port = num;
  431: 				cm->in_hdr.dst.ip_port = 0;
  432: 				if (add_colormask(s2, cm) < 0) {
  433: 					(void)fclose(fp);
  434: 					return -1;
  435: 				}
  436: 				cm->in_hdr.src.ip_port = 0;
  437: 				cm->in_hdr.dst.ip_port = num;
  438: 				if (add_colormask(s2, cm) < 0) {
  439: 					(void)fclose(fp);
  440: 					return -1;
  441: 				}
  442: 			} else if (add_colormask(s2, 0) < 0) {
  443: 				(void)fclose(fp);
  444: 				return -1;
  445: 			}
  446: 		} else if (num == 3) {
  447: 			num = str2addr(s1, 0, &cm->in_hdr.src, &cm->src_mask);
  448: 			if (num == -1) {
  449: 				(void)fclose(fp);
  450: 				return -1;
  451: 			}
  452: 			cm->in_hdr.ver = num;
  453: 			num = str2addr(s2, 0, &cm->in_hdr.dst, &cm->dst_mask);
  454: 			if (num == -1) {
  455: 				(void)fclose(fp);
  456: 				return -1;
  457: 			}
  458: 			if (!cm->in_hdr.ver) {
  459: 				cm->in_hdr.ver = num;
  460: 			} else if (num && num != cm->in_hdr.ver) {
  461: 				fprintf(stderr, "%s: line %d: Addresses family mismatch\n",
  462: 					rc_file, rc_line);
  463: 				(void)fclose(fp);
  464: 				return -1;
  465: 			}
  466: 			if (add_colormask(s3, cm) < 0) {
  467: 				(void)fclose(fp);
  468: 				return -1;
  469: 			}
  470: 		} else if (num == 4) {
  471: 			if ((cp = str2proto(s1, &num)) == 0) {
  472: 				(void)fclose(fp);
  473: 				return -1;
  474: 			}
  475: 			cm->in_hdr.proto = num;
  476: 			num = str2addr(s2, cp, &cm->in_hdr.src, &cm->src_mask);
  477: 			if (num == -1) {
  478: 				(void)fclose(fp);
  479: 				return -1;
  480: 			}
  481: 			cm->in_hdr.ver = num;
  482: 			num = str2addr(s3, cp, &cm->in_hdr.dst, &cm->dst_mask);
  483: 			if (num == -1) {
  484: 				(void)fclose(fp);
  485: 				return -1;
  486: 			}
  487: 			if (!cm->in_hdr.ver) {
  488: 				cm->in_hdr.ver = num;
  489: 			} else if (num && num != cm->in_hdr.ver) {
  490: 				fprintf(stderr, "%s: line %d: Addresses family mismatch\n",
  491: 					rc_file, rc_line);
  492: 				(void)fclose(fp);
  493: 				return -1;
  494: 			}
  495: 			if (add_colormask(s4, cm) < 0) {
  496: 				(void)fclose(fp);
  497: 				return -1;
  498: 			}
  499: 		} else {
  500: 			fprintf(stderr, "%s: line %d: Bad format\n",
  501: 				rc_file, rc_line);
  502: 			(void)fclose(fp);
  503: 			return -1;
  504: 		}
  505: 	}
  506: 	(void)fclose(fp);
  507: #ifdef	DEBUG
  508: 	for (cm = color_mask, num = 0; cm && num < n_masks; cm++, num++) {
  509: 		struct netstat_header nh;
  510: 		memset(&nh, 0, sizeof(nh));
  511: 		nh.in_hdr = cm->in_hdr;
  512: 		hdr2str(&nh, s1, sizeof(s1), s2, sizeof(s2), s3, sizeof(s3));
  513: 		fprintf(stderr, "%d:", num+1);
  514: 		fprintf(stderr, " proto=%s", s3);
  515: 		fprintf(stderr, " src=%s", s1);
  516: 		fprintf(stderr, " src_mask=%d", cm->src_mask);
  517: 		fprintf(stderr, " dst=%s", s2);
  518: 		fprintf(stderr, " dst_mask=%d", cm->dst_mask);
  519: 		fprintf(stderr, " color_pair=%d\r\n", (int)cm->pair);
  520: 	}
  521: 	fflush(stderr);
  522: 	pause();
  523: #endif
  524: 	return n_masks;
  525: }
  526: 
  527: static u_int32_t
  528: netmask(int bits)
  529: {
  530: 	register u_int32_t mask = 0;
  531: 	int i;
  532: 	for (i = 0; i < bits; i++) {
  533: 		mask >>= 1;
  534: 		mask |= 0x80000000L;
  535: 	}
  536: 	return (u_int32_t)htonl(mask);
  537: }
  538: 
  539: int
  540: colormask(nh)
  541: 	const struct netstat_header *nh;
  542: {
  543: 	/* sanity check */
  544: 	if (!nh) return A_NORMAL;
  545: 
  546: 	if (nh->in_hdr.ver) {
  547: 		register const struct cm_entry *cm;
  548: 		int i;
  549: 		for (cm = color_mask, i = 0; cm && i < n_masks; cm++, i++) {
  550: 			/* IP version */
  551: 			if (cm->in_hdr.ver) {
  552: 				if (nh->in_hdr.ver != cm->in_hdr.ver)
  553: 					continue;
  554: 			}
  555: 			/* IP protocol */
  556: 			if (cm->in_hdr.proto) {
  557: 				if (nh->in_hdr.proto != cm->in_hdr.proto)
  558: 					continue;
  559: 			}
  560: 			/* IP source address */
  561: 			if (cm->in_hdr.src.ip_addr.s_addr) {
  562: 				if (cm->src_mask) {
  563: 					u_int32_t mask = netmask(cm->src_mask);
  564: 					if ((nh->in_hdr.src.ip_addr.s_addr & mask) ^
  565: 					    (cm->in_hdr.src.ip_addr.s_addr & mask))
  566: 						continue;
  567: 				} else if (nh->in_hdr.src.ip_addr.s_addr !=
  568: 					   cm->in_hdr.src.ip_addr.s_addr)
  569: 					continue;
  570: 			}
  571: 			/* IP source port */
  572: 			if (cm->in_hdr.src.ip_port) {
  573: 				if (nh->in_hdr.src.ip_port != cm->in_hdr.src.ip_port)
  574: 					continue;
  575: 			}
  576: 			/* IP destination address */
  577: 			if (cm->in_hdr.dst.ip_addr.s_addr) {
  578: 				if (cm->dst_mask) {
  579: 					u_int32_t mask = netmask(cm->dst_mask);
  580: 					if ((nh->in_hdr.dst.ip_addr.s_addr & mask) ^
  581: 					    (cm->in_hdr.dst.ip_addr.s_addr & mask))
  582: 						continue;
  583: 				} else if (nh->in_hdr.dst.ip_addr.s_addr !=
  584: 					   cm->in_hdr.dst.ip_addr.s_addr)
  585: 					continue;
  586: 			}
  587: 			/* IP destination port */
  588: 			if (cm->in_hdr.dst.ip_port) {
  589: 				if (nh->in_hdr.dst.ip_port != cm->in_hdr.dst.ip_port)
  590: 					continue;
  591: 			}
  592: #ifdef	HAVE_SLCURSES
  593: 			return (COLOR_PAIR(cm->pair));
  594: #else
  595: 			return (COLOR_PAIR(cm->pair) | cm->attr);
  596: #endif
  597: 		}
  598: 	}
  599: 
  600: 	return A_NORMAL;
  601: }
  602: 
  603: #endif	/* HAVE_HAS_COLORS */

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>