Plan 9 from Bell Labs’s /usr/web/sources/contrib/steve/misc/guard.c

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


#include <u.h>
#include <libc.h>
#include <auth.h>
#include <bio.h>
#include <ndb.h>
#include <ctype.h>

int nosnmp = 0;
int nonames = 0;
int nobootp = 0;
int nodomain = 0;
int nonetbios = 0;
int norip = 0;
char *netroot = "/net";

#define BGET16(p)	((p)[0]<<8 | (p)[1])
#define BPUT16(p, x)	((p)[1] = (x), (p)[0] = ((x)>>8))

enum {
	NBstat		= 0x21,
	NBin		= 1,
};

static void
ding(void *u, char *msg)
{
	USED(u);

	if(strstr(msg, "alarm"))
		noted(NCONT);
	noted(NDFLT);
}

static int
nbname(char *rv, char *name, char pad)
{
	char *p, c;
	int i;
	int done=0;

	p = rv;
	*p++ = 0x20;
	for(i=0; i<16; i++) {
		c = pad;
		if(!done && name[i] == '\0')
			done = 1;
		if(!done)
			c = toupper(name[i]);
		*p++ = (c >> 4) + 'A';
		*p++ = (c & 0xf) + 'A';
	}
	*p++ = 0x0;
	return (p-rv);
}

char *
strlwr(char *str)
{
	char *p = str;
	for (; *p; p++)
		if (isupper(*p))
			*p = tolower(*p);
	return str;
}

char *
nbhost(char *host)
{
	int num, n, i, fd, trn;
	char *addr, buf[520], *p;
	static char name[20];
	char *wildcard = " CKAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA";

	trn = (getpid() ^ time(0)) & 0xffff;

	if ((addr = netmkaddr(host, "udp", "netbios-ns")) == nil)
		sysfatal("%s can't make address - %r", host);

	if((fd = dial(addr, "netbios-ns", 0, 0)) < 0)
		sysfatal("%s can't dial - %r", addr);
	n = 0;
	p = buf;
	memset(buf, 0, sizeof(buf));

	BPUT16(p+n, trn);	n+= 2;	// TRNid
	BPUT16(p+n, 0);		n+= 2;	// flags/type
	BPUT16(p+n, 0);		n+= 2;	// # questions
	BPUT16(p+n, 0);		n+= 2;	// # answers
	BPUT16(p+n, 0);		n+= 2;	// # authority RRs
	BPUT16(p+n, 0);		n+= 2;	// # Aditional RRs
	strcpy(p+n, wildcard);	n+= strlen(wildcard) +1;
	BPUT16(p+n, NBstat);	n+= 2;
	BPUT16(p+n, NBin);	n+= 2;

	if (write(fd, buf, n) != n)
		return nil;

	notify(ding);

	memset(buf, 0, sizeof(buf));

	for (i = 0; i < 3; i++){
		alarm(300);
		n = read(fd, buf, sizeof(buf));
		alarm(0);
		if (BGET16(p) == trn)
			break;
	}
	close(fd);
	if (n < 64)
		return "?";

	p = buf +56;
	num = *p++;			// number of names

	memset(name, 0, sizeof(name));
	for (i = 0; i < num; i++){
		memcpy(name, p, 16);
		p += 18;
		if (name[15] == 0){
			name[15] = 0;
			return strlwr(name);
		}
	}

	return "?";
}

void
usage(void)
{
	fprint(2, "usage: %s [-b] [-d] [-n] [-r] [-N] [-s] [-x mntpoint]\n", argv0);
	fprint(2, "  -N     don't resolve DNS names\n");
	fprint(2, "  -d     ignore DNS packets\n");
	fprint(2, "  -b     ignore BootP packets\n");
	fprint(2, "  -n     ignore NetBios packets\n");
	fprint(2, "  -r     ignore RIP packets\n");
	fprint(2, "  -s     ignore snmp packets\n");
	fprint(2, "  -x xx  alternative network mountpoint\n");
	exits("usage");
}

char*
remoteaddr(char *dir)
{
	static char buf[128];
	char *p;
	int n, fd;

	snprint(buf, sizeof buf, "%s/remote", dir);
	fd = open(buf, OREAD);
	if(fd < 0)
		return "";
	n = read(fd, buf, sizeof(buf));
	close(fd);
	if(n > 0){
		buf[n] = 0;
		if ((p = strchr(buf, '\n')) != nil)
			*p = 0;
		return buf;
	}
	return "";
}

char*
localport(char *dir)
{
	static char buf[128];
	char *p;
	int n, fd;

	snprint(buf, sizeof buf, "%s/local", dir);
	fd = open(buf, OREAD);
	if(fd < 0)
		return "";
	n = read(fd, buf, sizeof(buf));
	close(fd);
	if(n > 0){
		buf[n] = 0;
		if ((p = strchr(buf, '\n')) != nil)
			*p = 0;
		if ((p = strchr(buf, '!')) != nil)
			return p+1;
		return buf;
	}
	return "";
}

int skip(char c, int l, int r)
{
	if (nobootp && c == 'u' && l == 68 && r == 67)
		return 1;
	if (nobootp && c == 'u' && l == 67 && r == 68)
		return 1;
	if (nodomain && c == 'u' && r == 53)
		return 1;
	if (norip && c == 'u' && l == 520 && r == 520)
		return 1;
	if (nonetbios && c == 'u' && l == 137 && r == 137)
		return 1;
	if (nonetbios && c == 'u' && l == 138 && r == 138)
		return 1;
	if (nosnmp && c == 'u' && l == 161)
		return 1;
	return 0;
}


void
guard(char *proto)
{
	long when;
	int ctl, nctl;
	char *p, *ip, *tstr, *lprt, *rprt, *sys, *rem, *loc;
	char addr[16], dir[40], ndir[40];

	snprint(addr, sizeof(addr), "%s!*!*", proto);
	if ((ctl = announce(addr, dir)) < 0)
		sysfatal("announce %s: %r", addr);

	while(1){
		sys = lprt = rprt = "?";
		if((nctl = listen(dir, ndir)) < 0)
			sysfatal("listen %s: %r", addr);
		when = time(0);
		ip = remoteaddr(ndir);
		loc = localport(ndir);
		reject(ctl, ndir, "unexpected");
		close(nctl);

		if ((rem = strchr(ip, '!')) != nil)
			*rem++ = 0;

		if (skip(*proto, atoi(loc), atoi(rem)))
			continue;

		tstr = ctime(when);
		tstr[strlen(tstr) -1] = 0;

		print("%s %4s %-16s %-4s -> %-4s", tstr +4, proto, ip, rem, loc);

		if (! nonames){
			if ((p = csgetvalue(netroot, "ip", ip, "dom", nil)) != nil)
				sys = p;
			else
				switch(atoi(loc)){
				case 137:
				case 138:
				case 139:
					sys = nbhost(ip);
					break;
				default:
					break;
				}

			if ((p = csgetvalue(netroot, "port", loc, proto, nil)) != nil)
				lprt = p;
			if ((p = csgetvalue(netroot, "port", rem, proto, nil)) != nil)
				rprt = p;
			print("   %s %s -> %s", sys, rprt, lprt);
		}
		print("\n");
	}
}

void
main(int argc, char *argv[])
{
	int pid;

	ARGBEGIN{
	case 's':
		nosnmp++;
	case 'r':
		norip++;
		break;
	case 'n':
		nonetbios++;
		break;
	case 'N':
		nonames++;
		break;
	case 'x':
		netroot = EARGF(usage());
		break;
	case 'b':
		nobootp++;
		break;
	case 'd':
		nodomain++;
		break;
	default:
		usage();
		break;
	}ARGEND;

	if (argc)
		usage();

	if ((pid = fork()) == -1)
		sysfatal("fork failed: %r");
	if (pid)
		guard("tcp");
	else
		guard("udp");
	exits(nil);
}

Bell Labs OSI certified Powered by Plan 9

(Return to Plan 9 Home Page)

Copyright © 2021 Plan 9 Foundation. All Rights Reserved.
Comments to [email protected].