Charles.Forsyth20060303a828770d19 years agoHistory
656 lines · 13.8 KB · Brainfuck
RawDownload
implement IP; ## Copyright © 2003,2004 Vita Nuova Holdings Limited.  All rights reserved.# include "sys.m";	sys: Sys; include "ip.m"; init(){	sys = load Sys Sys->PATH;	v4prefix = array[] of {		byte 0, byte 0, byte 0, byte 0,		byte 0, byte 0, byte 0, byte 0,		byte 0, byte 0, byte 16rFF, byte 16rFF,	}; 	v4bcast = IPaddr(array[] of {		byte 0, byte 0, byte 0, byte 0,		byte 0, byte 0, byte 0, byte 0,		byte 0, byte 0, byte 16rFF, byte 16rFF,		byte 16rFF, byte 16rFF, byte 16rFF, byte 16rFF,	}); 	v4allsys = IPaddr(array[] of {		byte 0, byte 0, byte 0, byte 0,		byte 0, byte 0, byte 0, byte 0,		byte 0, byte 0, byte 16rFF, byte 16rFF,		byte 16rE0, byte 0, byte 0, byte 16r01,	}); 	v4allrouter = IPaddr(array[] of {		byte 0, byte 0, byte 0, byte 0,		byte 0, byte 0, byte 0, byte 0,		byte 0, byte 0, byte 16rFF, byte 16rFF,		byte 16rE0, byte 0, byte 0, byte 16r02,	}); 	v4noaddr = IPaddr(array[] of {		byte 0, byte 0, byte 0, byte 0,		byte 0, byte 0, byte 0, byte 0,		byte 0, byte 0, byte 16rFF, byte 16rFF,		byte 0, byte 0, byte 0, byte 0,	}); 	selfv6 = IPaddr(array[] of {		byte 0, byte 0, byte 0, byte 0,		byte 0, byte 0, byte 0, byte 0,		byte 0, byte 0, byte 0, byte 0,		byte 0, byte 0, byte 0, byte 1,	}); 	selfv4 = IPaddr(array[] of {		byte 0, byte 0, byte 0, byte 0,		byte 0, byte 0, byte 0, byte 0,		byte 0, byte 0, byte 16rFF, byte 16rFF,		byte 127, byte 0, byte 0, byte 1,	}); 	noaddr = IPaddr(array[] of {0 to IPaddrlen-1 => byte 0});	allbits = IPaddr(array[] of {0 to IPaddrlen-1 => byte 16rFF});} IPaddr.newv6(a: array of byte): IPaddr{	b := array[len a] of byte;	b[0:] = a[0:IPaddrlen];	return IPaddr(b);} IPaddr.newv4(a: array of byte): IPaddr{	b := array[IPaddrlen] of byte;	b[0:] = v4prefix;	b[IPv4off:] = a[0:IPv4addrlen];	return IPaddr(b);} IPaddr.copy(ip: self IPaddr): IPaddr{	if(ip.a == nil)		return noaddr.copy();	a := array[len ip.a] of byte;	a[0:] = ip.a;	return IPaddr(a);} IPaddr.eq(ip: self IPaddr, v: IPaddr): int{	a := ip.a;	if(a == nil)		a = noaddr.a;	b := v.a;	if(b == nil)		b = noaddr.a;	for(i := 0; i < IPaddrlen; i++)		if(a[i] != b[i])			return 0;	return 1;} IPaddr.mask(a1: self IPaddr, a2: IPaddr): IPaddr{	c := array[IPaddrlen] of byte;	for(i := 0; i < IPaddrlen; i++)		c[i] = a1.a[i] & a2.a[i];	return IPaddr(c);} IPaddr.maskn(a1: self IPaddr, a2: IPaddr): IPaddr{	c := array[IPaddrlen] of byte;	for(i := 0; i < IPaddrlen; i++)		c[i] = a1.a[i] & ~a2.a[i];	return IPaddr(c);} IPaddr.isv4(ip: self IPaddr): int{	for(i := 0; i < IPv4off; i++)		if(ip.a[i] != v4prefix[i])			return 0;	return 1;} IPaddr.ismulticast(ip: self IPaddr): int{	if(ip.isv4()){		v := int ip.a[IPv4off];		return v >= 16rE0 && v < 16rF0 || ip.eq(v4bcast);	# rfc1112	}	return ip.a[0] == byte 16rFF;} IPaddr.isvalid(ip: self IPaddr): int{	return !ip.eq(noaddr) && !ip.eq(v4noaddr);} IPaddr.v4(ip: self IPaddr): array of byte{	if(!ip.isv4() && !ip.eq(noaddr))		return nil;	a := array[4] of byte;	for(i := 0; i < 4; i++)		a[i] = ip.a[IPv4off+i];	return a;} IPaddr.v6(ip: self IPaddr): array of byte{	a := array[IPaddrlen] of byte;	a[0:] = ip.a;	return a;} IPaddr.class(ip: self IPaddr): int{	if(!ip.isv4())		return 6;	return int ip.a[IPv4off]>>6;} IPaddr.classmask(ip: self IPaddr): IPaddr{	m := allbits.copy();	if(!ip.isv4())		return m;	if((n := ip.class()) == 0)		n = 1;	for(i := IPaddrlen-4+n; i < IPaddrlen; i++)		m.a[i] = byte 0;	return m;} ## rfc2373# IPaddr.parse(s: string): (int, IPaddr){	a := noaddr.copy();	col := 0;	gap := 0;	for(i:=0; i<IPaddrlen && s != ""; i+=2){		c := 'x';		v := 0;		for(m := 0; m < len s && (c = s[m]) != '.' && c != ':'; m++){			d := 0;			if(c >= '0' && c <= '9')				d = c-'0';			else if(c >= 'a' && c <= 'f')				d = c-'a'+10;			else if(c >= 'A' && c <= 'F')				d = c-'A'+10;			else				return (-1, a);			v = (v<<4) | d;		}		if(c == '.'){			if(parseipv4(a.a[i:], s) < 0)				return (-1, noaddr.copy());			i += IPv4addrlen;			break;		}		if(v > 16rFFFF)			return (-1, a);		a.a[i] = byte (v>>8);		a.a[i+1] = byte v;		if(c == ':'){			col = 1;			if(++m < len s && s[m] == ':'){				if(gap > 0)					return (-1, a);				gap = i+2;				m++;			}		}		s = s[m:];	}	if(i < IPaddrlen){	# mind the gap		ns := i-gap;		for(j := 1; j <= ns; j++){			a.a[IPaddrlen-j] = a.a[i-j];			a.a[i-j] = byte 0;		}	}	if(!col)		a.a[0:] = v4prefix;	return (0, IPaddr(a));} IPaddr.parsemask(s: string): (int, IPaddr){	return parsemask(s, 128);} IPaddr.parsecidr(s: string): (int, IPaddr, IPaddr){	for(i := 0; i < len s && s[i] != '/'; i++)		;	(ok, a) := IPaddr.parse(s[0:i]);	if(i < len s){		(ok2, m) := IPaddr.parsemask(s[i:]);		if(ok < 0 || ok2 < 0)			return (-1, a, m);		return (0, a, m);	}	return (ok, a, allbits.copy());} parseipv4(b: array of byte, s: string): int{	a := array[4] of {* => 0};	o := 0;	for(i := 0; i < 4 && o < len s; i++){		for(m := o; m < len s && (c := s[m]) != '.'; m++)			if(!(c >= '0' && c <= '9'))				return -1;		if(m == o)			return -1;		a[i] = int big s[o:m];		b[i] = byte a[i];		if(m < len s && s[m] == '.')			m++;		o = m;	}	case i {	1 =>		# 32 bit		b[0] = byte (a[0] >> 24);		b[1] = byte (a[0] >> 16);		b[2] = byte (a[0] >> 8);		b[3] = byte a[0];	2 =>		if(a[0] < 256){	# 8/24			b[0] = byte a[0];			b[1] = byte (a[1]>>16);			b[2] = byte (a[1]>>8);		}else if(a[0] < 65536){	# 16/16			b[0] = byte (a[0]>>8);			b[1] = byte a[0];			b[2] = byte (a[1]>>16);		}else{	# 24/8			b[0] = byte (a[0]>>16);			b[1] = byte (a[0]>>8);			b[2] = byte a[0];		}		b[3] = byte a[1];	3 =>		# 8/8/16		b[0] = byte a[0];		b[1] = byte a[1];		b[2] = byte (a[2]>>16);		b[3] = byte a[2];	}	return 0;} parsemask(s: string, abits: int): (int, IPaddr){	m := allbits.copy();	if(s == nil)		return (0, m);	if(s[0] != '/'){		(ok, a) := IPaddr.parse(s);		if(ok < 0)			return (0, m);		if(a.isv4())			a.a[0:] = m.a[0:IPv4off];		return (0, a);	}	if(len s == 1)		return (0, m);	nbit := int s[1:];	if(nbit < 0)		return (-1, m);	if(nbit > abits)		return (0, m);	nbit = abits-nbit;	i := IPaddrlen;	for(; nbit >= 8; nbit -= 8)		m.a[--i] = byte 0;	if(nbit > 0)		m.a[i-1] &= byte (~0<<nbit);	return (0, m);} IPaddr.text(a: self IPaddr): string{	b := a.a;	if(b == nil)		return "::";	if(a.isv4())		return sys->sprint("%d.%d.%d.%d", int b[IPv4off], int b[IPv4off+1], int b[IPv4off+2], int b[IPv4off+3]);	cs := -1;	nc := 0;	for(i:=0; i<IPaddrlen; i+=2)		if(int b[i] == 0 && int b[i+1] == 0){			for(j:=i+2; j<IPaddrlen; j+=2)				if(int b[j] != 0 || int b[j+1] != 0)					break;			if(j-i > nc){				nc = j-i;				cs = i;			}		}	if(nc <= 2)		cs = -1;	s := "";	for(i=0; i<IPaddrlen; ){		if(i == cs){			s += "::";			i += nc;		}else{			if(s != "" && s[len s-1]!=':')				s[len s] = ':';			v := (int a.a[i] << 8) | int a.a[i+1];			s += sys->sprint("%ux", v);			i += 2;		}	}	return s;} IPaddr.masktext(a: self IPaddr): string{	b := a.a;	if(b == nil)		return "/0";	for(i:=0; i<IPaddrlen; i++)		if(i == IPv4off)			return sys->sprint("%d.%d.%d.%d", int b[IPv4off], int b[IPv4off+1], int b[IPv4off+2], int b[IPv4off+3]);		else if(b[i] != byte 16rFF)			break;	for(j:=i+1; j<IPaddrlen; j++)		if(b[j] != byte 0)			return a.text();	nbit := 8*i;	if(i < IPaddrlen){		v := int b[i];		for(m := 16r80; m != 0; m >>= 1){			if((v & m) == 0)				break;			v &= ~m;			nbit++;		}		if(v != 0)			return a.text();	}	return sys->sprint("/%d", nbit);} addressesof(ifcs: list of ref Ipifc, all: int): list of IPaddr{	ra: list of IPaddr;	runi: list of IPaddr;	for(; ifcs != nil; ifcs = tl ifcs){		for(ifcas :=(hd ifcs).addrs; ifcs != nil; ifcs = tl ifcs){			a := (hd ifcas).ip;			if(all || !(a.eq(noaddr) || a.eq(v4noaddr))){	# ignore unspecified and loopback				if(a.ismulticast() || a.eq(selfv4) || a.eq(selfv6))					ra = a :: ra;				else					runi = a :: runi;			}		}	}	# unicast first, then others, both sets in order as found	# for ipv6, might want to give priority to unicast other than link- and site-local	al: list of IPaddr;	for(; ra != nil; ra = tl ra)		al = hd ra :: al;	for(; runi != nil; runi = tl runi)		al = hd runi :: al;	return al;} interfaceof(l: list of ref Ipifc, ip: IPaddr): (ref Ipifc, ref Ifcaddr){	for(; l != nil; l = tl l){		ifc := hd l;		for(addrs := ifc.addrs; addrs != nil; addrs = tl addrs){			a := hd addrs;			if(ip.mask(a.mask).eq(a.net))				return (ifc, a);		}	}	return (nil, nil);} ownerof(l: list of ref Ipifc, ip: IPaddr): (ref Ipifc, ref Ifcaddr){	for(; l != nil; l = tl l){		ifc := hd l;		for(addrs := ifc.addrs; addrs != nil; addrs = tl addrs){			a := hd addrs;			if(ip.eq(a.ip))				return (ifc, a);		}	}	return (nil, nil);} readipifc(net: string, index: int): (list of ref Ipifc, string){	if(net == nil)		net = "/net";	if(index < 0){		ifcs: list of ref Ipifc;		dirfd := sys->open(net+"/ipifc", Sys->OREAD);		if(dirfd == nil)			return (nil, sys->sprint("%r"));		err: string;		for(;;){			(nd, dirs) := sys->dirread(dirfd);			if(nd <= 0){				if(nd < 0)					err = sys->sprint("%r");				break;			}			for(i:=0; i<nd; i++)				if((dn := dirs[i].name) != nil && dn[0]>='0' && dn[0]<='9'){					index = int dn;					ifc := readstatus(net+"/ipifc/"+dn+"/status", index);					if(ifc != nil)						ifcs = ifc :: ifcs;				}		}		l := ifcs;		for(ifcs = nil; l != nil; l = tl l)			ifcs = hd l :: ifcs;		return (ifcs, err);	}	ifc := readstatus(net+"/ipifc/"+string index+"/status", index);	if(ifc == nil)		return (nil, sys->sprint("%r"));	return (ifc :: nil, nil);} ## return data structure containing values read from status file:## device /net/ether0 maxtu 1514 sendra 0 recvra 0 mflag 0 oflag 0 maxraint 600000 minraint 200000 linkmtu 0 reachtime 0 rxmitra 0 ttl 255 routerlt 1800000 pktin 47609 pktout 42322 errin 0 errout 0#	144.32.112.83 /119 144.32.112.0 4294967295   4294967295#		...# readstatus(file: string, index: int): ref Ipifc{	fd := sys->open(file, Sys->OREAD);	if(fd == nil)		return nil;	contents := slurp(fd);	fd = nil;	(nline, lines) := sys->tokenize(contents, "\n");	if(nline <= 0){		sys->werrstr("unexpected ipifc status file format");		return nil;

Lines 1–500 of 656.