Plan 9 from Bell Labs’s /usr/web/sources/contrib/quanstro/root/sys/src/cmd/ip/cidr.c

Copyright © 2021 Plan 9 Foundation.
Distributed under the MIT License.
Download the Plan 9 distribution.


#include <u.h>
#include <libc.h>
#include <ip.h>
#include <bio.h>

char	flag[127];
char	*fil;
uint	lin;

int
parsecidr(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
 */
int
cidrmatch(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;
}

void
prmatch(char *s)
{
	if(flag['s'] == 0){
		if(flag['n'])
			print("%s:%ud: %s\n", fil, lin, s);
		else
			print("%s\n", s);
	}
}

void
usage(void)
{
	fprint(2, "cidr [-clLnrsv] ip [-f ipfile] file ...\n");
	exits("usage");
}

void
main(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");
}

Bell Labs OSI certified Powered by Plan 9

(Return to Plan 9 Home Page)

Copyright © 2021 Plan 9 Foundation. All Rights Reserved.
Comments to webmaster@9p.io.