207 lines · 3.0 KB · C
RawDownload
#include <u.h>#include <libc.h>#include <ip.h>#include <bio.h> char	flag[127];char	*fil;uint	lin; intparsecidr(uchar *addr, uchar *mask, char *from){	char *p, buf[50];	int i, bits, z;	vlong v;	uchar *a; 	strecpy(buf, buf+sizeof buf, from);	if(p = strchr(buf, '/'))		*p = 0;	v = parseip(addr, buf);	if(v == -1)		return -1;	switch((ulong)v){	default:		bits = 32;		z = 96;		break;	case 6:		bits = 128;		z = 0;		break;	} 	if(p){		i = strtoul(p+1, &p, 0);		if(i > bits)			i = bits;		i += z;		memset(mask, 0, 128/8);		for(a = mask; i >= 8; i -= 8)			*a++ = 0xff;		if(i > 0)			*a = ~((1<<(8-i))-1);	}else		memset(mask, 0xff, IPaddrlen);	return 0;} /* * match x.y.z.w to ~?x1.y1.z1.w1/m */intcidrmatch(char *x, char *y){	uchar r, a[IPaddrlen], b[IPaddrlen], m[IPaddrlen]; 	r = *y == '~';	if(parseip(a, x) == -1)		return 0;	parsecidr(b, m, y+r);	maskip(a, m, a);	maskip(b, m, b);	if(!memcmp(a, b, IPaddrlen) ^ r)		return 1;	return 0;} Biobuf*patopen(char *s){	Biobuf *b; 	lin = 0;	b = Bopen(fil = s, OREAD);	if(b == nil)		sysfatal("open: %r");	return b;} char*nextpat(Biobuf *b){	char *q;	static char *s, *p; b1:	if(p == nil || *p == 0){		free(s);		p = s = Brdstr(b, '\n', 1);		lin++;	}	if(p == nil)		return nil;	p += strspn(p, " \t\r");	if(*p == '#' || *p == 0){		*p = 0;		goto b1;	}	q = p;	p += strcspn(p, " \t\r");	if(*p != 0)		*p++ = 0;	return q;} voidprmatch(char *s){	if(flag['s'] == 0){		if(flag['n'])			print("%s:%ud: %s\n", fil, lin, s);		else			print("%s\n", s);	}} voidusage(void){	fprint(2, "cidr [-clLnrsv] ip [-f ipfile] file ...\n");	exits("usage");} voidmain(int argc, char **argv){	char *pat, *file, **tab;	int i, j, c, c0, n, ntab;	Biobuf *b; 	file = nil;	ARGBEGIN{	case 'f':		file = EARGF(usage());	case 'c':	case 'l':	case 'L':	case 'n':	case 'r':	case 's':	case 'v':		flag[ARGC()] = 1;		break;	default:		usage();	}ARGEND 	if(flag['l'] || flag['L'] || flag['c'])		flag['s'] = 1; 	ntab = 1;	tab = malloc(1 * sizeof *tab);	if(tab == nil)		sysfatal("malloc: %r");	if(!flag['f']){		if(argc == 0)			usage();		tab[0] = strdup(*argv++);		argc--;	}else{		b = patopen(file);		for(i = 0; tab[i] = nextpat(b); i++){			if((tab[i] = strdup(tab[i])) == nil)				sysfatal("strdup: %r");			if(i + 1 == ntab){				ntab <<= 2;				tab = realloc(tab, ntab*sizeof *tab);				if(tab == nil)					sysfatal("realloc: %r");			}		}		Bterm(b);		ntab = i;	} 	if(argc == 0)		argv[argc++] = "/fd/0"; 	c = 0;	for(i = 0; i < argc; i++){		b = patopen(argv[i]);		c0 = c;		while((pat = nextpat(b)) != nil){			for(j = 0; j < ntab; j++){				if(flag['r'])					n = cidrmatch(tab[j], pat);				else					n = cidrmatch(pat, tab[j]);				if(n ^ flag['v']){					prmatch(pat);					c++;					break;				}			}		}		Bterm(b);		if(c0 == c && flag['L'] || c0 != c&& flag['l'])			print("%s\n", argv[i]);	}	for(i = 0; i < ntab; i++)		free(tab[i]);	free(tab);	if(flag['c'])		print("%d\n", c);	exits(c>0? nil: "no matches");}