Browse Source

Plan 9 from Bell Labs 2009-07-10

David du Colombier 15 years ago
parent
commit
580fc51282

+ 8 - 12
rc/bin/usps

@@ -9,16 +9,12 @@ if(! ~ $#* 1) {
 
 rfork e
 
-hget -p 'tracknbr='^$1 http://www.framed.usps.com/cgi-bin/cttgate/ontrack.cgi |
-	tr -d '
' |
-	sed 's/<[^>]*>//g' | 
-	sed 's/\&quot;/"/g;s/\&lt;/</g;s/\&gt;/>/g;s/\&amp;/\&/g' |
-	sed 's/\&(copy|nbsp);//' |
-	grep -v Copyright |
-	grep -v 'You can track' |
-	grep -v 'Enter the number' |
-	grep -v 'Item Number:' |
-	sed 's/[ 	]*$//' |
-	uniq |
-	fmt
+hget -p 'origTrackNum='^$1 http://trkcnfrm1.smi.usps.com/PTSInternetWeb/InterLabelInquiry.do |
+	htmlfmt > /tmp/usps.$pid
 
+sam -d /tmp/usps.$pid >[2] /dev/null <<'!'
+0,/Label/-1d
+/^Enter Label/,$d
+,p
+!
+rm /tmp/usps.$pid

+ 11 - 2
sys/include/libsec.h

@@ -23,17 +23,26 @@ struct AESstate
 	ulong	setup;
 	int	rounds;
 	int	keybytes;
-//	uint	ctrsz;
+	uint	ctrsz;
 	uchar	key[AESmaxkey];			/* unexpanded key */
 	ulong	ekey[4*(AESmaxrounds + 1)];	/* encryption key */
 	ulong	dkey[4*(AESmaxrounds + 1)];	/* decryption key */
 	uchar	ivec[AESbsize];			/* initialization vector */
-//	uchar	mackey[3 * AESbsize];		/* 3 XCBC mac 96 keys */
+	uchar	mackey[3 * AESbsize];		/* 3 XCBC mac 96 keys */
 };
 
+/* block ciphers */
+void	aes_encrypt(ulong rk[], int Nr, uchar pt[16], uchar ct[16]);
+void	aes_decrypt(ulong rk[], int Nr, uchar ct[16], uchar pt[16]);
+
 void	setupAESstate(AESstate *s, uchar key[], int keybytes, uchar *ivec);
 void	aesCBCencrypt(uchar *p, int len, AESstate *s);
 void	aesCBCdecrypt(uchar *p, int len, AESstate *s);
+void	aesCTRdecrypt(uchar *p, int len, AESstate *s);
+void	aesCTRencrypt(uchar *p, int len, AESstate *s);
+
+void	setupAESXCBCstate(AESstate *s);
+uchar*	aesXCBCmac(uchar *p, int len, AESstate *s);
 
 /*
  * Blowfish Definitions

+ 47 - 4
sys/man/2/aes

@@ -1,6 +1,6 @@
 .TH AES 2
 .SH NAME
-setupAESstate, aesCBCencrypt, aesCBCdecrypt - advanced encryption standard (rijndael)
+setupAESstate, aesCBCencrypt, aesCBCdecrypt, aesCTRencrypt, aesCTRdecrypt, setupAESXCBCstate, aesXCBCmac - advanced encryption standard (rijndael)
 .SH SYNOPSIS
 .B #include <u.h>
 .br
@@ -13,6 +13,12 @@ setupAESstate, aesCBCencrypt, aesCBCdecrypt - advanced encryption standard (rijn
 .in +0.5i
 .ti -0.5i
 .B
+void	aes_encrypt(ulong rk[], int Nr, uchar pt[16], uchar ct[16]);
+.PP
+.B
+void	aes_decrypt(ulong rk[], int Nr, uchar ct[16], uchar pt[16]);
+.PP
+.B
 void	setupAESstate(AESstate *s, uchar key[], int keybytes, uchar *ivec)
 .PP
 .B
@@ -20,14 +26,41 @@ void	aesCBCencrypt(uchar *p, int len, AESstate *s)
 .PP
 .B
 void	aesCBCdecrypt(uchar *p, int len, AESstate *s)
+.PP
+.B
+void	aesCTRencrypt(uchar *p, int len, AESstate *s)
+.PP
+.B
+void	aesCTRdecrypt(uchar *p, int len, AESstate *s)
+.PP
+.B
+void	setupAESXCBCstate(AESstate *s)
+.PP
+.B
+void	aesXCBCmac(uchar *p, int len, AESstate *s)
 .SH DESCRIPTION
-DES is being replaced by Rijndael, also known as AES, as the preferred
+AES (a.k.a. Rijndael) has replaced DES as the preferred
 block cipher.
+.I Aes_encrypt
+and
+.I aes_decrypt
+are the block ciphers, corresponding to
+.IR des (2)'s
+.IR block_cipher .
 .IR SetupAESstate ,
 .IR aesCBCencrypt ,
 and
 .I aesCBCdecrypt
-implement cipher block chaining encryption.
+implement cipher-block-chaining encryption.
+.I AesCTRencrypt
+and
+.I aesCTRdecrypt
+implement counter mode, per RFC 3686;
+they are identical operations.
+.I setupAESXCBCstate
+and
+.I aesXCBCmac
+implement AES XCBC message authentication, per RFC 3566.
 All ciphering is performed in place.
 .I Keybytes
 should be 16, 24, or 32.
@@ -55,4 +88,14 @@ in
 .IR prime (2),
 .IR rand (2)
 .br
-.B http://csrc.nist.gov/encryption/aes/rijndael
+.B http://csrc.nist.gov/publications/fips/fips197/fips-197.pdf
+.SH BUGS
+The functions
+.IR aes_encrypt ,
+.IR aes_decrypt ,
+.IR aesCTRencrypt ,
+.IR aesCTRdecrypt ,
+.IR setupAESXCBCstate ,
+and
+.IR aesXCBCmac
+have not yet been verified by running test vectors through them.

+ 2 - 2
sys/man/3/arch

@@ -126,7 +126,7 @@ The following code reads from an x86 byte I/O port.
 .IP
 .EX
 uchar
-inportb(long port)
+inportb(unsigned port)
 {
     uchar data;
 
@@ -135,7 +135,7 @@ inportb(long port)
 
     seek(iobfd, port, 0);
     if(read(iobfd, &data, sizeof(data)) != sizeof(data))
-        sysfatal("inportb(0x%4.4x): %r", port);
+        sysfatal("inportb(0x%4.4ux): %r", port);
     return data;
 }
 .EE

+ 20 - 1
sys/man/8/auth

@@ -1,6 +1,6 @@
 .TH AUTH 8
 .SH NAME
-changeuser, convkeys, convkeys2, printnetkey, status, enable, disable, authsrv, guard.srv, wrkey, login, newns, none \- maintain or query authentication databases
+changeuser, convkeys, convkeys2, printnetkey, status, enable, disable, authsrv, guard.srv, wrkey, login, newns, none, as \- maintain or query authentication databases
 .SH SYNOPSIS
 .B auth/changeuser
 .RB [ -np ]
@@ -54,6 +54,10 @@ changeuser, convkeys, convkeys2, printnetkey, status, enable, disable, authsrv,
 .I command
 .I arg
 \&...
+.PP
+.B auth/as
+.I user
+.I command
 .SH DESCRIPTION
 These administrative commands run only on the authentication server.
 .IR Changeuser
@@ -235,6 +239,21 @@ If there are no arguments, it
 .BR /bin/rc .
 It's an easy way to run a command as
 .IR none .
+.PP
+.I As
+executes
+.I command
+as
+.IR user .
+.I Command
+is a single argument to
+.IR rc ,
+containing an arbitrary
+.I rc
+command.
+This only works for the hostowner and only if
+.L #¤/caphash
+still exists.
 .SH FILES
 .TF /sys/lib/httppasswords
 .TP

File diff suppressed because it is too large
+ 458 - 182
sys/src/9/ip/esp.c


+ 44 - 36
sys/src/9/ip/icmp6.c

@@ -67,39 +67,47 @@ enum {
 	Maxtype6	= 137,
 };
 
-typedef struct ICMPpkt ICMPpkt;
+/* on-the-wire packet formats */
 typedef struct IPICMP IPICMP;
 typedef struct Ndpkt Ndpkt;
 typedef struct NdiscC NdiscC;
 
-struct ICMPpkt {
-	uchar	type;
-	uchar	code;
-	uchar	cksum[2];
-	uchar	icmpid[2];
-	uchar	seq[2];
-};
+/* we do this to avoid possible struct padding  */
+#define ICMPHDR \
+	IPV6HDR; \
+	uchar	type; \
+	uchar	code; \
+	uchar	cksum[2]; \
+	uchar	icmpid[2]; \
+	uchar	seq[2]
 
 struct IPICMP {
-	Ip6hdr;
-	ICMPpkt;
+	ICMPHDR;
+	uchar	payload[];
 };
 
-struct NdiscC
-{
-	IPICMP;
+#define IPICMPSZ offsetof(IPICMP, payload[0])
+
+struct NdiscC {
+	ICMPHDR;
 	uchar	target[IPaddrlen];
+	uchar	payload[];
 };
 
-struct Ndpkt
-{
-	NdiscC;
+#define NDISCSZ offsetof(NdiscC, payload[0])
+
+struct Ndpkt {
+	ICMPHDR;
+	uchar	target[IPaddrlen];
 	uchar	otype;
 	uchar	olen;		/* length in units of 8 octets(incl type, code),
 				 * 1 for IEEE 802 addresses */
 	uchar	lnaddr[6];	/* link-layer address */
+	uchar	payload[];
 };
 
+#define NDPKTSZ offsetof(Ndpkt, payload[0])
+
 typedef struct Icmppriv6
 {
 	ulong	stats[Nstats6];
@@ -246,10 +254,10 @@ icmpkick6(void *x, Block *bp)
 		bp->rp += IPaddrlen;
 		ipmove(raddr, bp->rp);
 		bp->rp += IPaddrlen;
-		bp = padblock(bp, sizeof(Ip6hdr));
+		bp = padblock(bp, IP6HDR);
 	}
 
-	if(blocklen(bp) < sizeof(IPICMP)){
+	if(blocklen(bp) < IPICMPSZ){
 		freeblist(bp);
 		return;
 	}
@@ -343,7 +351,7 @@ icmpns(Fs *f, uchar* src, int suni, uchar* targ, int tuni, uchar* mac)
 	Proto *icmp = f->t2p[ICMPv6];
 	Icmppriv6 *ipriv = icmp->priv;
 
-	nbp = newIPICMP(sizeof(Ndpkt));
+	nbp = newIPICMP(NDPKTSZ);
 	np = (Ndpkt*) nbp->rp;
 
 	if(suni == SRC_UNSPEC)
@@ -364,7 +372,7 @@ icmpns(Fs *f, uchar* src, int suni, uchar* targ, int tuni, uchar* mac)
 		np->olen = 1;		/* 1+1+6 = 8 = 1 8-octet */
 		memmove(np->lnaddr, mac, sizeof(np->lnaddr));
 	} else
-		nbp->wp -= sizeof(Ndpkt) - sizeof(NdiscC);
+		nbp->wp -= NDPKTSZ - NDISCSZ;
 
 	set_cksum(nbp);
 	np = (Ndpkt*)nbp->rp;
@@ -386,7 +394,7 @@ icmpna(Fs *f, uchar* src, uchar* dst, uchar* targ, uchar* mac, uchar flags)
 	Proto *icmp = f->t2p[ICMPv6];
 	Icmppriv6 *ipriv = icmp->priv;
 
-	nbp = newIPICMP(sizeof(Ndpkt));
+	nbp = newIPICMP(NDPKTSZ);
 	np = (Ndpkt*)nbp->rp;
 
 	memmove(np->src, src, IPaddrlen);
@@ -414,7 +422,7 @@ extern void
 icmphostunr(Fs *f, Ipifc *ifc, Block *bp, int code, int free)
 {
 	int osz = BLEN(bp);
-	int sz = MIN(sizeof(IPICMP) + osz, v6MINTU);
+	int sz = MIN(IPICMPSZ + osz, v6MINTU);
 	Block *nbp;
 	IPICMP *np;
 	Ip6hdr *p;
@@ -446,7 +454,7 @@ icmphostunr(Fs *f, Ipifc *ifc, Block *bp, int code, int free)
 	memmove(np->dst, p->src, IPaddrlen);
 	np->type = UnreachableV6;
 	np->code = code;
-	memmove(nbp->rp + sizeof(IPICMP), bp->rp, sz - sizeof(IPICMP));
+	memmove(nbp->rp + IPICMPSZ, bp->rp, sz - IPICMPSZ);
 	set_cksum(nbp);
 	np->ttl = HOP_LIMIT;
 	np->vcf[0] = 0x06 << 4;
@@ -468,7 +476,7 @@ extern void
 icmpttlexceeded6(Fs *f, Ipifc *ifc, Block *bp)
 {
 	int osz = BLEN(bp);
-	int sz = MIN(sizeof(IPICMP) + osz, v6MINTU);
+	int sz = MIN(IPICMPSZ + osz, v6MINTU);
 	Block *nbp;
 	IPICMP *np;
 	Ip6hdr *p;
@@ -495,7 +503,7 @@ icmpttlexceeded6(Fs *f, Ipifc *ifc, Block *bp)
 	memmove(np->dst, p->src, IPaddrlen);
 	np->type = TimeExceedV6;
 	np->code = 0;
-	memmove(nbp->rp + sizeof(IPICMP), bp->rp, sz - sizeof(IPICMP));
+	memmove(nbp->rp + IPICMPSZ, bp->rp, sz - IPICMPSZ);
 	set_cksum(nbp);
 	np->ttl = HOP_LIMIT;
 	np->vcf[0] = 0x06 << 4;
@@ -507,7 +515,7 @@ extern void
 icmppkttoobig6(Fs *f, Ipifc *ifc, Block *bp)
 {
 	int osz = BLEN(bp);
-	int sz = MIN(sizeof(IPICMP) + osz, v6MINTU);
+	int sz = MIN(IPICMPSZ + osz, v6MINTU);
 	Block *nbp;
 	IPICMP *np;
 	Ip6hdr *p;
@@ -535,7 +543,7 @@ icmppkttoobig6(Fs *f, Ipifc *ifc, Block *bp)
 	np->type = PacketTooBigV6;
 	np->code = 0;
 	hnputl(np->icmpid, ifc->maxtu - ifc->m->hsize);
-	memmove(nbp->rp + sizeof(IPICMP), bp->rp, sz - sizeof(IPICMP));
+	memmove(nbp->rp + IPICMPSZ, bp->rp, sz - IPICMPSZ);
 	set_cksum(nbp);
 	np->ttl = HOP_LIMIT;
 	np->vcf[0] = 0x06 << 4;
@@ -557,7 +565,7 @@ valid(Proto *icmp, Ipifc *ifc, Block *bp, Icmppriv6 *ipriv)
 
 	USED(ifc);
 	n = blocklen(bp);
-	if(n < sizeof(IPICMP)) {
+	if(n < IPICMPSZ) {
 		ipriv->stats[HlenErrs6]++;
 		netlog(icmp->f, Logicmp, "icmp hlen %d\n", n);
 		goto err;
@@ -630,7 +638,7 @@ valid(Proto *icmp, Ipifc *ifc, Block *bp, Icmppriv6 *ipriv)
 			break;
 
 		case RouterAdvert:
-			if(pktsz - sizeof(Ip6hdr) < 16) {
+			if(pktsz - IP6HDR < 16) {
 				ipriv->stats[HlenErrs6]++;
 				goto err;
 			}
@@ -638,7 +646,7 @@ valid(Proto *icmp, Ipifc *ifc, Block *bp, Icmppriv6 *ipriv)
 				ipriv->stats[RouterAddrErrs6]++;
 				goto err;
 			}
-			sz = sizeof(IPICMP) + 8;
+			sz = IPICMPSZ + 8;
 			while (sz+1 < pktsz) {
 				osz = packet[sz+1];
 				if(osz <= 0) {
@@ -650,12 +658,12 @@ valid(Proto *icmp, Ipifc *ifc, Block *bp, Icmppriv6 *ipriv)
 			break;
 
 		case RouterSolicit:
-			if(pktsz - sizeof(Ip6hdr) < 8) {
+			if(pktsz - IP6HDR < 8) {
 				ipriv->stats[HlenErrs6]++;
 				goto err;
 			}
 			unsp = (ipcmp(p->src, v6Unspecified) == 0);
-			sz = sizeof(IPICMP) + 8;
+			sz = IPICMPSZ + 8;
 			while (sz+1 < pktsz) {
 				osz = packet[sz+1];
 				if(osz <= 0 ||
@@ -739,7 +747,7 @@ icmpiput6(Proto *icmp, Ipifc *ipifc, Block *bp)
 		else
 			msg = unreachcode[p->code];
 
-		bp->rp += sizeof(IPICMP);
+		bp->rp += IPICMPSZ;
 		if(blocklen(bp) < 8){
 			ipriv->stats[LenErrs6]++;
 			goto raise;
@@ -751,7 +759,7 @@ icmpiput6(Proto *icmp, Ipifc *ipifc, Block *bp)
 			return;
 		}
 
-		bp->rp -= sizeof(IPICMP);
+		bp->rp -= IPICMPSZ;
 		goticmpkt6(icmp, bp, 0);
 		break;
 
@@ -759,7 +767,7 @@ icmpiput6(Proto *icmp, Ipifc *ipifc, Block *bp)
 		if(p->code == 0){
 			sprint(m2, "ttl exceeded at %I", p->src);
 
-			bp->rp += sizeof(IPICMP);
+			bp->rp += IPICMPSZ;
 			if(blocklen(bp) < 8){
 				ipriv->stats[LenErrs6]++;
 				goto raise;
@@ -770,7 +778,7 @@ icmpiput6(Proto *icmp, Ipifc *ipifc, Block *bp)
 				(*pr->advise)(pr, bp, m2);
 				return;
 			}
-			bp->rp -= sizeof(IPICMP);
+			bp->rp -= IPICMPSZ;
 		}
 
 		goticmpkt6(icmp, bp, 0);

+ 10 - 6
sys/src/9/ip/ipv6.h

@@ -117,13 +117,17 @@ typedef struct Opthdr	Opthdr;
 typedef struct Routinghdr Routinghdr;
 typedef struct Fraghdr6	Fraghdr6;
 
+/* we do this in case there's padding at the end of Ip6hdr */
+#define IPV6HDR \
+	uchar	vcf[4];		/* version:4, traffic class:8, flow label:20 */\
+	uchar	ploadlen[2];	/* payload length: packet length - 40 */ \
+	uchar	proto;		/* next header type */ \
+	uchar	ttl;		/* hop limit */ \
+	uchar	src[IPaddrlen]; \
+	uchar	dst[IPaddrlen]
+
 struct	Ip6hdr {
-	uchar	vcf[4];		/* version:4, traffic class:8, flow label:20 */
-	uchar	ploadlen[2];	/* payload length: packet length - 40 */
-	uchar	proto;		/* next header type */
-	uchar	ttl;		/* hop limit */
-	uchar	src[IPaddrlen];
-	uchar	dst[IPaddrlen];
+	IPV6HDR;
 	uchar	payload[];
 };
 

+ 0 - 27
sys/src/9/pc/devether.c

@@ -467,39 +467,12 @@ etherprobe(int cardno, int ctlrno)
 	return ether;
 }
 
-static void
-fakeintrs(void)
-{
-	int ctlrno;
-	Ether *ether;
-
-	for(ctlrno = 0; ctlrno < MaxEther; ctlrno++) {
-		ether = etherxx[ctlrno];
-		if (ether && ether->interrupt)
-			ether->interrupt(nil, ether);
-	}
-}
-
-/* terrible temporary hack for 82575 */
-static void
-startfakeintrs(void)
-{
-	static int first = 1;
-
-	if (first) {
-		addclock0link(fakeintrs, 1);
-		first = 0;
-	}
-}
-
 static void
 etherreset(void)
 {
 	Ether *ether;
 	int cardno, ctlrno;
 
-	if (getconf("*fakeintrs") != nil)
-		startfakeintrs();
 	for(ctlrno = 0; ctlrno < MaxEther; ctlrno++){
 		if((ether = etherprobe(-1, ctlrno)) == nil)
 			continue;

+ 15 - 2
sys/src/9/port/xalloc.c

@@ -6,7 +6,6 @@
 
 enum
 {
-	Chunk		= 64*1024,
 	Nhole		= 128,
 	Magichole	= 0x484F4C45,			/* HOLE */
 };
@@ -120,6 +119,7 @@ xallocz(ulong size, int zero)
 	Xhdr *p;
 	Hole *h, **l;
 
+	/* add room for magix & size overhead, round up to nearest vlong */
 	size += BY2V + offsetof(Xhdr, data[0]);
 	size &= ~(BY2V-1);
 
@@ -137,7 +137,7 @@ xallocz(ulong size, int zero)
 			}
 			iunlock(&xlists);
 			if(zero)
-				memset(p->data, 0, size);
+				memset(p, 0, size);
 			p->magix = Magichole;
 			p->size = size;
 			return p->data;
@@ -175,7 +175,20 @@ xmerge(void *vp, void *vq)
 	p = (Xhdr*)(((ulong)vp - offsetof(Xhdr, data[0])));
 	q = (Xhdr*)(((ulong)vq - offsetof(Xhdr, data[0])));
 	if(p->magix != Magichole || q->magix != Magichole) {
+		int i;
+		ulong *wd;
+		void *badp;
+
 		xsummary();
+		badp = (p->magix != Magichole? p: q);
+		wd = (ulong *)badp - 12;
+		for (i = 24; i-- > 0; ) {
+			print("%#p: %lux", wd, *wd);
+			if (wd == badp)
+				print(" <-");
+			print("\n");
+			wd++;
+		}
 		panic("xmerge(%#p, %#p) bad magic %#lux, %#lux\n",
 			vp, vq, p->magix, q->magix);
 	}

+ 3 - 2
sys/src/boot/pc/alarm.c

@@ -4,7 +4,9 @@
 #include	"dat.h"
 #include	"fns.h"
 #include	"io.h"
-#define	MAXALARM	10
+
+#define NA	10		/* max. alarms per clock tick */
+#define	MAXALARM (3 * NA)
 
 Alarm	alarmtab[MAXALARM];
 
@@ -92,7 +94,6 @@ alarminit(void)
 {
 }
 
-#define NA 10		/* alarms per clock tick */
 void
 checkalarms(void)
 {

+ 65 - 3
sys/src/boot/pc/bootp.c

@@ -6,8 +6,8 @@
 #include "io.h"
 
 #include "ip.h"
+#include "aoe.h"
 
-extern int debugload;
 extern char *persist;
 
 uchar broadcast[Eaddrlen] = {
@@ -202,7 +202,8 @@ if(debug) {
 	 */
 	if (len < ETHERMINTU)
 		len = ETHERMINTU;
-	ethertxpkt(ctlrno, &pkt, len, Timeout);
+	if (ethertxpkt(ctlrno, &pkt, len, Timeout) == 0)
+		print("xmit failure\n");
 }
 
 static void
@@ -373,7 +374,12 @@ tftpopen(int ctlrno, Netaddr *a, char *name, Tftp *tftp)
 		}
 	}
 
-	print("tftpopen: failed to connect to server\n");
+	print("tftpopen: failed to connect to server (%ld.%ld.%ld.%ld!%d)\n",
+		(a->ip >> 24) & 0xff,
+		(a->ip >> 16) & 0xff,
+		(a->ip >> 8) & 0xff,
+		a->ip & 0xff,
+		oport);
 	return -1;
 }
 
@@ -392,6 +398,7 @@ tftpread(int ctlrno, Netaddr *a, Tftp *tftp, int dlen)
 		buf[3] = tftpblockno;
 
 		udpsend(ctlrno, a, buf, sizeof(buf));
+
 		len = udprecv(ctlrno, a, tftp, dlen);
 		if(len <= sizeof(tftp->header)){
 			if(debug)
@@ -648,3 +655,58 @@ pxegetfspart(int ctlrno, char* part, int)
 
 	return &pxether[ctlrno].fs;
 }
+
+/*
+ * hack to avoid queueing packets we don't care about.
+ * needs to admit udp and aoe packets.
+ */
+int
+interesting(Block *bp)
+{
+	ulong addr;
+	Netaddr *a = &server;
+	Udphdr *h;
+
+	h = (Udphdr*)bp->rp;
+	if(debug)
+		print("inpkt %E to %E...\n", h->s, h->d);
+
+	switch(nhgets(h->type)){
+	case Aoetype:
+		return 1;
+	case ET_IP:
+		break;
+	default:
+		if(debug)
+			print("not ipv4...");
+		return 0;
+	}
+
+	if(h->vihl != (IP_VER|IP_HLEN)) {
+		print("ip bad vers/hlen\n");
+		return 0;
+	}
+	if(h->udpproto != IP_UDPPROTO) {
+		if(debug)
+			print("not udp (%d)...", h->udpproto);
+		return 0;
+	}
+
+	if(debug)
+		print("okay udp...");
+
+	if(a->port != 0 && nhgets(h->udpsport) != a->port) {
+		if(debug)
+			print("udpport %ux not %ux\n",
+				nhgets(h->udpsport), a->port);
+		return 0;
+	}
+
+	addr = nhgetl(h->udpsrc);
+	if(a->ip != Bcastip && a->ip != addr) {
+		if(debug)
+			print("bad ip %lux not %lux\n", addr, a->ip);
+		return 0;
+	}
+	return 1;
+}

+ 16 - 0
sys/src/boot/pc/conf.c

@@ -318,6 +318,22 @@ addconf(char *fmt, ...)
 	va_end(arg);
 }
 
+void
+dumpbootargs(void)
+{
+	char *p, *nl;
+
+	/* in the boot, we can only print PRINTSIZE (256) bytes at a time. */
+	print("boot args: ");
+	for (p = (char *)BOOTARGS; *p != '\0'; p = nl) {
+		nl = strchr(p, '\n');
+		if (nl != nil) {
+			++nl;
+			print("%.*s", (int)(nl - p), p);
+		}
+	}
+}
+
 void
 changeconf(char *fmt, ...)
 {

+ 2 - 2
sys/src/boot/pc/ether82563.c

@@ -638,7 +638,7 @@ toringbuf(Ether *ether, Block *bp)
 			ether->ctlrno, ether->ri);
 }
 
-//int	interesting(Block *bp);
+int	interesting(Block *bp);
 
 static void
 i82563interrupt(Ureg*, void* arg)
@@ -674,7 +674,7 @@ i82563interrupt(Ureg*, void* arg)
 						bp->rp+6, rdesc->length);
 				ctlr->rb[rdh] = nil;
 				bp->wp += rdesc->length;
-//				if (interesting(bp))
+				if (interesting(bp))
 					toringbuf(edev, bp);
 				freeb(bp);
 			} else if (rdesc->status & Reop && rdesc->errors)

+ 5 - 2
sys/src/boot/pc/mem.h

@@ -18,7 +18,9 @@
 /*
  * Time
  */
-#define	HZ		(100)				/* clock frequency */
+// #define	HZ		100				/* clock frequency */
+/* 1000Hz for *9loadfakeintrs */
+#define	HZ		1000				/* clock frequency */
 #define	MS2HZ		(1000/HZ)			/* millisec per clock tick */
 #define	TK2SEC(t)	((t)/HZ)			/* ticks to seconds */
 #define	TK2MS(x)	((x)*(1000/HZ))
@@ -27,12 +29,13 @@
 /*
  * Fundamental addresses
  */
+/* edd 4 draft says BDA is at 40:00 = 0x400 */
 #define IDTADDR		0x80000800		/* idt */
 #define APBOOTSTRAP	0x80001000		/* AP bootstrap code */
 #define CONFADDR	0x80001200		/* info passed from boot loader */
 #define CPU0PDB		0x80002000		/* bootstrap processor PDB */
 #define CPU0PTE		0x80003000		/* bootstrap processor PTE's for 0-4MB */
-#define MACHADDR	0x80004000		/* as seen by current processor */
+#define MACHADDR	0x80004000 /* as seen by current processor (unused by boot) */
 #define CPU0MACH	0x80005000		/* Mach for bootstrap processor */
 #define BIOSXCHG	0x80006000		/* To exchange data with the BIOS */
 #define	MACHSIZE	(BY2PG*8)		/* stack size */

+ 181 - 0
sys/src/cmd/auth/as.c

@@ -0,0 +1,181 @@
+/*
+ * as user cmd [arg...] - run cmd with args as user on this cpu server.
+ *	must be hostowner for this to work.
+ *	needs #¤/caphash and #¤/capuse.
+ */
+#include <u.h>
+#include <libc.h>
+#include <bio.h>
+#include <libsec.h>
+#include <auth.h>
+#include "authcmdlib.h"
+
+int	debug;
+
+int	becomeuser(char*);
+void	createuser(void);
+void	*emalloc(ulong);
+void	*erealloc(void*, ulong);
+void	initcap(void);
+int	mkcmd(char*, char*, int);
+int	myauth(int, char*);
+int	qidcmp(Qid, Qid);
+void	runas(char *, char *);
+void	usage(void);
+
+#pragma varargck	argpos clog 1
+#pragma varargck	argpos fatal 1
+
+static void
+fatal(char *fmt, ...)
+{
+	char msg[256];
+	va_list arg;
+
+	va_start(arg, fmt);
+	vseprint(msg, msg + sizeof msg, fmt, arg);
+	va_end(arg);
+	error("%s", msg);
+}
+
+void
+main(int argc, char *argv[])
+{
+	debug = 0;
+	ARGBEGIN{
+	case 'd':
+		debug = 1;
+		break;
+	default:
+		usage();
+	}ARGEND
+
+	initcap();
+	srand(getpid()*time(0));
+	runas(argv[0], argv[1]);
+}
+
+void
+runas(char *user, char *cmd)
+{
+	if(becomeuser(user) < 0)
+		sysfatal("can't change uid for %s: %r", user);
+	putenv("service", "rx");
+	execl("/bin/rc", "rc", "-lc", cmd, nil);
+	sysfatal("exec /bin/rc: %r");
+}
+
+void *
+emalloc(ulong n)
+{
+	void *p;
+
+	if(p = mallocz(n, 1))
+		return p;
+	fatal("out of memory");
+	return 0;
+}
+
+void *
+erealloc(void *p, ulong n)
+{
+	if(p = realloc(p, n))
+		return p;
+	fatal("out of memory");
+	return 0;
+}
+
+void
+usage(void)
+{
+	fprint(2, "usage: %s [-c]\n", argv0);
+	exits("usage");
+}
+
+void
+memrandom(void *p, int n)
+{
+	uchar *cp;
+
+	for(cp = (uchar*)p; n > 0; n--)
+		*cp++ = fastrand();
+}
+
+/*
+ *  keep caphash fd open since opens of it could be disabled
+ */
+static int caphashfd;
+
+void
+initcap(void)
+{
+	caphashfd = open("#¤/caphash", OCEXEC|OWRITE);
+	if(caphashfd < 0)
+		fprint(2, "%s: opening #¤/caphash: %r\n", argv0);
+}
+
+/*
+ *  create a change uid capability 
+ */
+char*
+mkcap(char *from, char *to)
+{
+	uchar rand[20];
+	char *cap;
+	char *key;
+	int nfrom, nto;
+	uchar hash[SHA1dlen];
+
+	if(caphashfd < 0)
+		return nil;
+
+	/* create the capability */
+	nto = strlen(to);
+	nfrom = strlen(from);
+	cap = emalloc(nfrom+1+nto+1+sizeof(rand)*3+1);
+	sprint(cap, "%s@%s", from, to);
+	memrandom(rand, sizeof(rand));
+	key = cap+nfrom+1+nto+1;
+	enc64(key, sizeof(rand)*3, rand, sizeof(rand));
+
+	/* hash the capability */
+	hmac_sha1((uchar*)cap, strlen(cap), (uchar*)key, strlen(key), hash, nil);
+
+	/* give the kernel the hash */
+	key[-1] = '@';
+	if(write(caphashfd, hash, SHA1dlen) < 0){
+		free(cap);
+		return nil;
+	}
+
+	return cap;
+}
+
+int
+usecap(char *cap)
+{
+	int fd, rv;
+
+	fd = open("#¤/capuse", OWRITE);
+	if(fd < 0)
+		return -1;
+	rv = write(fd, cap, strlen(cap));
+	close(fd);
+	return rv;
+}
+
+int
+becomeuser(char *new)
+{
+	char *cap;
+	int rv;
+
+	cap = mkcap(getuser(), new);
+	if(cap == nil)
+		return -1;
+	rv = usecap(cap);
+	free(cap);
+
+	newns(new, nil);
+	return rv;
+}

+ 2 - 1
sys/src/cmd/ndb/dblookup.c

@@ -16,7 +16,7 @@ enum {
 	 * confused by a zero ttl, and instead of using the data and then
 	 * discarding the RR, they conclude that they don't have valid data.
 	 */
-	Ptrttl = 300,
+	Ptrttl = 120,
 };
 
 static Ndb *db;
@@ -602,6 +602,7 @@ dbpair2cache(DN *dp, Ndbtuple *entry, Ndbtuple *pair)
 		return;
 
 	rp->owner = dp;
+	dnagenever(dp, 1);
 	rp->db = 1;
 	rp->ttl = intval(entry, pair, "ttl", rp->ttl);
 	rrattach(rp, Notauthoritative);

+ 72 - 17
sys/src/cmd/ndb/dn.c

@@ -11,10 +11,10 @@
  *  about 1780 names.
  *
  * aging seems to corrupt the cache, so raise the trigger from 4000 until we
- * figure it out.  trying again with 4000...
+ * figure it out.
  */
 enum {
-	Deftarget = 4000,
+	Deftarget = 8000,
 };
 enum {
 	Minage		= 10*60,
@@ -377,29 +377,82 @@ dnage(DN *dp)
 
 #define MARK(dp)	{ if (dp) (dp)->keep = 1; }
 
+/* mark a domain name and those in its RRs as never to be aged */
+void
+dnagenever(DN *dp, int dolock)
+{
+	RR *rp;
+
+	if (dolock)
+		lock(&dnlock);
+
+	/* mark all referenced domain names */
+	MARK(dp);
+	for(rp = dp->rr; rp; rp = rp->next){
+		MARK(rp->owner);
+		if(rp->negative){
+			MARK(rp->negsoaowner);
+			continue;
+		}
+		switch(rp->type){
+		case Thinfo:
+			MARK(rp->cpu);
+			MARK(rp->os);
+			break;
+		case Ttxt:
+			break;
+		case Tcname:
+		case Tmb:
+		case Tmd:
+		case Tmf:
+		case Tns:
+		case Tmx:
+		case Tsrv:
+			MARK(rp->host);
+			break;
+		case Tmg:
+		case Tmr:
+			MARK(rp->mb);
+			break;
+		case Tminfo:
+			MARK(rp->rmb);
+			MARK(rp->mb);
+			break;
+		case Trp:
+			MARK(rp->rmb);
+			MARK(rp->rp);
+			break;
+		case Ta:
+		case Taaaa:
+			MARK(rp->ip);
+			break;
+		case Tptr:
+			MARK(rp->ptr);
+			break;
+		case Tsoa:
+			MARK(rp->host);
+			MARK(rp->rmb);
+			break;
+		}
+	}
+
+	if (dolock)
+		unlock(&dnlock);
+}
+
 /* mark all current domain names as never to be aged */
 void
-dnagenever(void)
+dnageallnever(void)
 {
 	int i;
 	DN *dp;
-	RR *rp;
 
 	lock(&dnlock);
 
-	/* mark referenced domain names in NS RRs */
+	/* mark all referenced domain names */
 	for(i = 0; i < HTLEN; i++)
-		for(dp = ht[i]; dp; dp = dp->next) {
-//			MARK(dp);
-			for(rp = dp->rr; rp; rp = rp->next){
-				MARK(rp->owner);
-				switch(rp->type){
-				case Tns:
-					MARK(rp->host);
-					break;
-				}
-			}
-		}
+		for(dp = ht[i]; dp; dp = dp->next)
+			dnagenever(dp, 0);
 
 	unlock(&dnlock);
 
@@ -539,10 +592,12 @@ dnagedb(void)
 
 	/* time out all database entries */
 	for(i = 0; i < HTLEN; i++)
-		for(dp = ht[i]; dp; dp = dp->next)
+		for(dp = ht[i]; dp; dp = dp->next) {
+			dp->keep = 0;
 			for(rp = dp->rr; rp; rp = rp->next)
 				if(rp->db)
 					rp->expire = 0;
+		}
 
 	unlock(&dnlock);
 }

+ 11 - 8
sys/src/cmd/ndb/dnresolve.c

@@ -507,7 +507,7 @@ udpport(char *mtpt)
 	}
 
 	/* turn on header style interface */
-	if(write(ctl, hmsg, strlen(hmsg)) , 0){
+	if(write(ctl, hmsg, strlen(hmsg)) != strlen(hmsg)){
 		close(ctl);
 		warning(hmsg);
 		return -1;
@@ -1459,7 +1459,7 @@ udpquery(Query *qp, char *mntpt, int depth, int patient, int inns)
 static int
 netquery(Query *qp, int depth)
 {
-	int lock, rv, triedin, inname, cnt;
+	int lock, rv, triedin, inname;
 //	char buf[32];
 	RR *rp;
 	DN *dp;
@@ -1495,12 +1495,9 @@ netquery(Query *qp, int depth)
 		 * causing us to query other nameservers.
 		 */
 		qlp = &dp->querylck[qtype2lck(qp->type)];
-		incref(qlp);
 		qlock(qlp);
-		cnt = qlp->Ref.ref;
-		qunlock(qlp);
-		if (cnt > 10) {
-			decref(qlp);
+		if (qlp->Ref.ref > 10) {
+			qunlock(qlp);
 			if (!whined) {
 				whined = 1;
 				dnslog("too many outstanding queries for %s;"
@@ -1509,6 +1506,8 @@ netquery(Query *qp, int depth)
 			}
 			return 0;
 		}
+		++qlp->Ref.ref;
+		qunlock(qlp);
 	}
 	procsetname("netquery: %s", dp->name);
 
@@ -1549,8 +1548,12 @@ netquery(Query *qp, int depth)
 //	if (rv == 0)		/* could ask /net.alt/dns directly */
 //		askoutdns(dp, qp->type);
 
-	if(lock && qlp)
+	if(lock && qlp) {
+		qlock(qlp);
+		assert(qlp->Ref.ref > 0);
+		qunlock(qlp);
 		decref(qlp);
+	}
 	return rv;
 }
 

+ 9 - 5
sys/src/cmd/ndb/dns.c

@@ -29,6 +29,7 @@ int vers;		/* incremented each clone/attach */
 
 static volatile int stop;
 
+/* holds data to be returned via read of /net/dns, perhaps multiple reads */
 struct Mfile
 {
 	Mfile		*next;		/* next free mfile */
@@ -105,10 +106,12 @@ void
 usage(void)
 {
 	fprint(2, "usage: %s [-FnorRst] [-a maxage] [-f ndb-file] [-N target] "
-		"[-x netmtpt] [-z refreshprog]\n", argv0);
+		"[-T forwip] [-x netmtpt] [-z refreshprog]\n", argv0);
 	exits("usage");
 }
 
+int addforwtarg(char *);
+
 void
 main(int argc, char *argv[])
 {
@@ -158,6 +161,9 @@ main(int argc, char *argv[])
 	case 't':
 		testing = 1;
 		break;
+	case 'T':
+		addforwtarg(EARGF(usage()));
+		break;
 	case 'x':
 		setnetmtpt(mntpt, sizeof mntpt, EARGF(usage()));
 		setext(ext, sizeof ext, mntpt);
@@ -206,7 +212,7 @@ main(int argc, char *argv[])
 
 	srand(now*getpid());
 	db2cache(1);
-	dnagenever();
+//	dnageallnever();
 
 	if (cfg.straddle && !seerootns())
 		dnslog("straddle server misconfigured; can't see root name servers");
@@ -314,8 +320,6 @@ newfid(int fid, int needunused)
 			return mf;
 		}
 	mf = emalloc(sizeof(*mf));
-	if(mf == nil)
-		sysfatal("out of memory");
 	mf->fid = fid;
 	mf->next = mfalloc.inuse;
 	mf->user = estrdup("dummy");
@@ -719,7 +723,7 @@ rwrite(Job *job, Mfile *mf, Request *req)
 	/*
 	 *  special commands
 	 */
-	dnslog("rwrite got: %s", job->request.data);
+//	dnslog("rwrite got: %s", job->request.data);
 	if(strcmp(job->request.data, "debug")==0){
 		debug ^= 1;
 		goto send;

+ 3 - 2
sys/src/cmd/ndb/dns.h

@@ -148,7 +148,7 @@ enum
 	Maxactive=	250,
 
 	/* tune; was 60; keep it short */
-	Maxreqtm=	10,	/* max. seconds to process a request */
+	Maxreqtm=	30,	/* max. seconds to process a request */
 
 	Notauthoritative = 0,
 	Authoritative,
@@ -455,7 +455,8 @@ void	db2cache(int);
 void	dnage(DN*);
 void	dnageall(int);
 void	dnagedb(void);
-void	dnagenever(void);
+void	dnageallnever(void);
+void	dnagenever(DN *, int);
 void	dnauthdb(void);
 void	dncheck(void*, int);
 void	dndump(char*);

+ 69 - 3
sys/src/cmd/ndb/dnudpserver.c

@@ -21,6 +21,18 @@ struct Inprogress
 };
 Inprogress inprog[Maxactive+2];
 
+typedef struct Forwtarg Forwtarg;
+struct Forwtarg {
+	char	*host;
+	uchar	addr[IPaddrlen];
+	int	fd;
+	ulong	lastdial;
+};
+Forwtarg forwtarg[10];
+int currtarg;
+
+static char *hmsg = "headers";
+
 /*
  *  record client id and ignore retransmissions.
  *  we're still single thread at this point.
@@ -58,6 +70,59 @@ clientrxmit(DNSmsg *req, uchar *buf)
 	return empty;
 }
 
+int
+addforwtarg(char *host)
+{
+	Forwtarg *tp;
+
+	if (currtarg >= nelem(forwtarg)) {
+		dnslog("too many forwarding targets");
+		return -1;
+	}
+	tp = forwtarg + currtarg;
+	if (parseip(tp->addr, host) < 0) {
+		dnslog("can't parse ip %s", host);
+		return -1;
+	}
+	tp->lastdial = time(nil);
+	tp->fd = udpport(mntpt);
+	if (tp->fd < 0)
+		return -1;
+
+	free(tp->host);
+	tp->host = estrdup(host);
+	currtarg++;
+	return 0;
+}
+
+/*
+ * fast forwarding of incoming queries to other dns servers.
+ * intended primarily for debugging.
+ */
+static void
+redistrib(uchar *buf, int len)
+{
+	Forwtarg *tp;
+	Udphdr *uh;
+	static uchar outpkt[1500];
+
+	assert(len <= sizeof outpkt);
+	memmove(outpkt, buf, len);
+	uh = (Udphdr *)outpkt;
+	for (tp = forwtarg; tp < forwtarg + currtarg; tp++)
+		if (tp->fd > 0) {
+			memmove(outpkt, tp->addr, sizeof tp->addr);
+			hnputs(uh->rport, 53);		/* dns port */
+			if (write(tp->fd, outpkt, len) != len) {
+				close(tp->fd);
+				tp->fd = -1;
+			}
+		} else if (tp->host && time(nil) - tp->lastdial > 60) {
+			tp->lastdial = time(nil);
+			tp->fd = udpport(mntpt);
+		}
+}
+
 /*
  *  a process to act as a dns server for outside reqeusts
  */
@@ -114,6 +179,9 @@ restart:
 		alarm(0);
 		if(len <= Udphdrsize)
 			goto restart;
+
+		redistrib(buf, len);
+
 		uh = (Udphdr*)buf;
 		len -= Udphdrsize;
 
@@ -203,8 +271,6 @@ freereq:
 /*
  *  announce on well-known dns udp port and set message style interface
  */
-static char *hmsg = "headers";
-
 static int
 udpannounce(char *mntpt)
 {
@@ -223,7 +289,7 @@ udpannounce(char *mntpt)
 	snprint(datafile, sizeof(datafile), "%s/data", dir);
 
 	/* turn on header style interface */
-	if(write(ctl, hmsg, strlen(hmsg)) , 0)
+	if(write(ctl, hmsg, strlen(hmsg)) != strlen(hmsg))
 		abort();			/* hmsg */
 	data = open(datafile, ORDWR);
 	if(data < 0){

+ 15 - 3
sys/src/libhttpd/fail.c

@@ -50,16 +50,28 @@ int
 hfail(HConnect *c, int reason, ...)
 {
 	Hio *hout;
-	char makeup[HBufSize];
+	char makeup[HBufSize], err[ERRMAX];
 	va_list arg;
 	int n;
 
+	rerrstr(err, sizeof err);
 	hout = &c->hout;
 	va_start(arg, reason);
 	vseprint(makeup, makeup+HBufSize, errormsg[reason].verbose, arg);
 	va_end(arg);
-	n = snprint(c->xferbuf, HBufSize, "<head><title>%s</title></head>\n<body><h1>%s</h1>\n%s</body>\n",
-		errormsg[reason].concise, errormsg[reason].concise, makeup);
+	/*
+	 * this additional information has proved useful when debugging
+	 * complex http configuration problems.
+	 */
+	n = snprint(c->xferbuf, HBufSize, "<head><title>%s</title></head>\n"
+		"<body><h1>%s</h1>\n%s<p>\n"
+		"errstr: %s<br>\n"
+		"uri host: %s<br>\n"
+		"header host: %s<br>\nactual host: %s\n</body>\n",
+		errormsg[reason].concise, errormsg[reason].concise, makeup,
+		err,
+		(c->req.urihost? c->req.urihost: ""),
+		c->head.host, hmydomain);
 
 	hprint(hout, "%s %s\r\n", hversion, errormsg[reason].num);
 	hprint(hout, "Date: %D\r\n", time(nil));

+ 301 - 31
sys/src/libsec/port/aes.c

@@ -30,6 +30,7 @@
  */
 #include <u.h>
 #include <libc.h>
+#include <mp.h>
 #include <libsec.h>
 
 typedef uchar	u8;
@@ -43,12 +44,30 @@ static const u32 Td1[256];
 static const u32 Td2[256];
 static const u32 Td3[256];
 static const u8  Te4[256];
+static uchar basekey[3][16] = {
+	{
+	0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+	0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+	},
+	{
+	0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+	0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+	},
+	{
+	0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
+	0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
+	},
+};
+
+int aes_setupEnc(ulong rk[/*4*(Nr + 1)*/], const uchar cipherKey[],
+		int keyBits);
+static int aes_setupDec(ulong rk[/*4*(Nr + 1)*/], const uchar cipherKey[],
+		int keyBits);
+static int aes_setup(ulong erk[/*4*(Nr + 1)*/], ulong drk[/*4*(Nr + 1)*/],
+		const uchar cipherKey[], int keyBits);
 
-static int rijndaelKeySetupEnc(u32 rk[/*4*(Nr + 1)*/], const u8 cipherKey[], int keyBits);
-static int rijndaelKeySetupDec(u32 rk[/*4*(Nr + 1)*/], const u8 cipherKey[], int keyBits);
-static int rijndaelKeySetup(u32 erk[/*4*(Nr + 1)*/], u32 drk[/*4*(Nr + 1)*/], const u8 cipherKey[], int keyBits);
-static void	rijndaelEncrypt(const u32 rk[], int Nr, const uchar pt[16], uchar ct[16]);
-static void	rijndaelDecrypt(const u32 rk[], int Nr, const uchar ct[16], uchar pt[16]);
+void	aes_encrypt(const ulong rk[], int Nr, const uchar pt[16], uchar ct[16]);
+void	aes_decrypt(const ulong rk[], int Nr, const uchar ct[16], uchar pt[16]);
 
 void
 setupAESstate(AESstate *s, uchar key[], int keybytes, uchar *ivec)
@@ -58,12 +77,89 @@ setupAESstate(AESstate *s, uchar key[], int keybytes, uchar *ivec)
 		keybytes = AESmaxkey;
 	memmove(s->key, key, keybytes);
 	s->keybytes = keybytes;
-	s->rounds = rijndaelKeySetup(s->ekey, s->dkey, s->key, keybytes * 8);
+	s->rounds = aes_setup(s->ekey, s->dkey, s->key, keybytes * 8);
 	if(ivec != nil)
 		memmove(s->ivec, ivec, AESbsize);
 	if(keybytes==16 || keybytes==24 || keybytes==32)
 		s->setup = 0xcafebabe;
-	/* else rijndaelKeySetup was invalid */
+	/* else aes_setup was invalid */
+}
+
+/*
+ * AES-XCBC-MAC-96 message authentication, per rfc3566.
+ */
+
+void
+setupAESXCBCstate(AESstate *s)		/* was setupmac96 */
+{
+	int i, j;
+	uint q[16 / sizeof(uint)];
+	uchar *p;
+
+	assert(s->keybytes == 16);
+	for(i = 0; i < 3; i++)
+		aes_encrypt(s->ekey, s->rounds, basekey[i],
+			s->mackey + AESbsize*i);
+
+	p = s->mackey;
+	memset(q, 0, AESbsize);
+
+	/*
+	 * put the in the right endian.  once figured, probably better
+	 * to use some fcall macros.
+	 * keys for encryption in local endianness for the algorithm...
+	 * only key1 is used for encryption;
+	 * BUG!!: I think this is what I got wrong.
+	 */
+	for(i = 0; i < 16 / sizeof(uint); i ++){
+		for(j = 0; j < sizeof(uint); j++)
+			q[i] |= p[sizeof(uint)-j-1] << 8*j;
+		p += sizeof(uint);
+	}
+	memmove(s->mackey, q, 16);
+}
+
+/*
+ * Not dealing with > 128-bit keys, not dealing with strange corner cases like
+ * empty message.  Should be fine for AES-XCBC-MAC-96.
+ */
+uchar*
+aesXCBCmac(uchar *p, int len, AESstate *s)
+{
+	uchar *p2, *ip, *eip, *mackey;
+	uchar q[AESbsize];
+
+	assert(s->keybytes == 16);	/* more complicated for bigger */
+	memset(s->ivec, 0, AESbsize);	/* E[0] is 0+ */
+
+	for(; len > AESbsize; len -= AESbsize){
+		memmove(q, p, AESbsize);
+		p2 = q;
+		ip = s->ivec;
+		for(eip = ip + AESbsize; ip < eip; )
+			*p2++ ^= *ip++;
+		aes_encrypt((ulong *)s->mackey, s->rounds, q, s->ivec);
+		p += AESbsize;
+	}
+	/* the last one */
+
+	memmove(q, p, len);
+	p2 = q+len;
+	if(len == AESbsize)
+		mackey = s->mackey + AESbsize;	/* k2 */
+	else{
+		mackey = s->mackey+2*AESbsize;	/* k3 */
+		*p2++ = 1 << 7;			/* padding */
+		len = AESbsize - len - 1;
+		memset(p2, 0, len);
+	}
+
+	ip = s->ivec;
+	p2 = q;
+	for(eip = ip + AESbsize; ip < eip; )
+		*p2++ ^= *ip++ ^ *mackey++;
+	aes_encrypt((ulong *)s->mackey, s->rounds, q, s->ivec);
+	return s->ivec;			/* only the 12 bytes leftmost */
 }
 
 /*
@@ -82,7 +178,7 @@ aesCBCencrypt(uchar *p, int len, AESstate *s)
 		ip = s->ivec;
 		for(eip = ip+AESbsize; ip < eip; )
 			*p2++ ^= *ip++;
-		rijndaelEncrypt(s->ekey, s->rounds, p, q);
+		aes_encrypt(s->ekey, s->rounds, p, q);
 		memmove(s->ivec, q, AESbsize);
 		memmove(p, q, AESbsize);
 		p += AESbsize;
@@ -90,7 +186,7 @@ aesCBCencrypt(uchar *p, int len, AESstate *s)
 
 	if(len > 0){
 		ip = s->ivec;
-		rijndaelEncrypt(s->ekey, s->rounds, ip, q);
+		aes_encrypt(s->ekey, s->rounds, ip, q);
 		memmove(s->ivec, q, AESbsize);
 		for(eip = ip+len; ip < eip; )
 			*p++ ^= *ip++;
@@ -105,7 +201,7 @@ aesCBCdecrypt(uchar *p, int len, AESstate *s)
 
 	for(; len >= AESbsize; len -= AESbsize){
 		memmove(tmp, p, AESbsize);
-		rijndaelDecrypt(s->dkey, s->rounds, p, q);
+		aes_decrypt(s->dkey, s->rounds, p, q);
 		memmove(p, q, AESbsize);
 		tp = tmp;
 		ip = s->ivec;
@@ -117,18 +213,191 @@ aesCBCdecrypt(uchar *p, int len, AESstate *s)
 
 	if(len > 0){
 		ip = s->ivec;
-		rijndaelEncrypt(s->ekey, s->rounds, ip, q);
+		aes_encrypt(s->ekey, s->rounds, ip, q);
 		memmove(s->ivec, q, AESbsize);
 		for(eip = ip+len; ip < eip; )
 			*p++ ^= *ip++;
 	}
 }
 
+/*
+ * AES-CTR mode, per rfc3686.
+ * CTRs could be precalculated for efficiency
+ * and there would also be less back and forth mp
+ */
+
+static void
+incrementCTR(uchar *p, uint ctrsz)
+{
+	int len;
+	uchar *ctr;
+	mpint *mpctr, *mpctrsz;
+
+	ctr = p + AESbsize - ctrsz;
+	mpctr = betomp(ctr, ctrsz, nil);
+	mpctrsz = itomp(1 << (ctrsz*8), nil);
+	mpadd(mpctr, mpone, mpctr);
+	mpmod(mpctr, mpctrsz, mpctr);
+	len = mptobe(mpctr, ctr, ctrsz, nil);
+	assert(len == ctrsz);
+	mpfree(mpctrsz);
+	mpfree(mpctr);
+}
+
+void
+aesCTRencrypt(uchar *p, int len, AESstate *s)
+{
+	uchar q[AESbsize];
+	uchar *ip, *eip, *ctr;
+
+	ctr = s->ivec;
+	for(; len >= AESbsize; len -= AESbsize){
+		ip = q;
+		aes_encrypt(s->ekey, s->rounds, ctr, q);
+		for(eip = p + AESbsize; p < eip; )
+			*p++ ^= *ip++;
+		incrementCTR(ctr, s->ctrsz);
+	}
+
+	if(len > 0){
+		ip = q;
+		aes_encrypt(s->ekey, s->rounds, ctr, q);
+		for(eip = p + len; p < eip; )
+			*p++ ^= *ip++;
+		incrementCTR(ctr, s->ctrsz);
+	}
+}
+
+void
+aesCTRdecrypt(uchar *p, int len, AESstate *s)
+{
+	aesCTRencrypt(p, len, s);
+}
+
+
+/* taken from sha1; TODO: verify suitability (esp. byte order) for aes */
+/*
+ *	encodes input (ulong) into output (uchar). Assumes len is
+ *	a multiple of 4.
+ */
+static void
+encode(uchar *output, ulong *input, ulong len)
+{
+	ulong x;
+	uchar *e;
+
+	for(e = output + len; output < e;) {
+		x = *input++;
+		*output++ = x >> 24;
+		*output++ = x >> 16;
+		*output++ = x >> 8;
+		*output++ = x;
+	}
+}
+
+/* TODO: verify use of aes_encrypt here */
 AEShstate*
 aes(uchar *p, ulong len, uchar *digest, AEShstate *s)
 {
-	USED(p, len, digest, s);
-	return nil;		/* TODO: compute aes hash for ipsec */
+	uchar buf[128];
+	ulong x[16];
+	int i;
+	uchar *e;
+
+	if(s == nil){
+		s = malloc(sizeof(*s));
+		if(s == nil)
+			return nil;
+		memset(s, 0, sizeof(*s));
+		s->malloced = 1;
+	}
+
+	if(s->seeded == 0){
+		/* seed the state, these constants would look nicer big-endian */
+		s->state[0] = 0x67452301;
+		s->state[1] = 0xefcdab89;
+		s->state[2] = 0x98badcfe;
+		s->state[3] = 0x10325476;
+		/* in sha1 (20-byte digest), but not md5 (16 bytes)*/
+		s->state[4] = 0xc3d2e1f0;
+		s->seeded = 1;
+	}
+
+	/* fill out the partial 64 byte block from previous calls */
+	if(s->blen){
+		i = 64 - s->blen;
+		if(len < i)
+			i = len;
+		memmove(s->buf + s->blen, p, i);
+		len -= i;
+		s->blen += i;
+		p += i;
+		if(s->blen == 64){
+			/* encrypt s->buf into s->state */
+			// _sha1block(s->buf, s->blen, s->state);
+			aes_encrypt((ulong *)s->buf, 1, s->buf, (uchar *)s->state);
+			s->len += s->blen;
+			s->blen = 0;
+		}
+	}
+
+	/* do 64 byte blocks */
+	i = len & ~0x3f;
+	if(i){
+		/* encrypt p into s->state */
+		// _sha1block(p, i, s->state);
+		aes_encrypt((ulong *)s->buf, 1, p, (uchar *)s->state);
+		s->len += i;
+		len -= i;
+		p += i;
+	}
+
+	/* save the left overs if not last call */
+	if(digest == 0){
+		if(len){
+			memmove(s->buf, p, len);
+			s->blen += len;
+		}
+		return s;
+	}
+
+	/*
+	 *  this is the last time through, pad what's left with 0x80,
+	 *  0's, and the input count to create a multiple of 64 bytes
+	 */
+	if(s->blen){
+		p = s->buf;
+		len = s->blen;
+	} else {
+		memmove(buf, p, len);
+		p = buf;
+	}
+	s->len += len;
+	e = p + len;
+	if(len < 56)
+		i = 56 - len;
+	else
+		i = 120 - len;
+	memset(e, 0, i);
+	*e = 0x80;
+	len += i;
+
+	/* append the count */
+	x[0] = s->len>>29;		/* byte-order dependent */
+	x[1] = s->len<<3;
+	encode(p+len, x, 8);
+
+	/* digest the last part */
+	/* encrypt p into s->state */
+	// _sha1block(p, len+8, s->state);
+	aes_encrypt((ulong *)s->buf, 1, p, (uchar *)s->state);
+	s->len += len+8;		/* sha1: +8 */
+
+	/* return result and free state */
+	encode((uchar *)digest, (ulong *)s->state, AESdlen);
+	if(s->malloced == 1)
+		free(s);
+	return nil;
 }
 
 DigestState*
@@ -147,13 +416,13 @@ hmac_aes(uchar *p, ulong len, uchar *key, ulong klen, uchar *digest,
  * @return	the number of rounds for the given cipher key size.
  */
 static int
-rijndaelKeySetup(u32 erk[/* 4*(Nr + 1) */], u32 drk[/* 4*(Nr + 1) */],
-	const u8 cipherKey[], int keyBits)
+aes_setup(ulong erk[/* 4*(Nr + 1) */], ulong drk[/* 4*(Nr + 1) */],
+	const uchar cipherKey[], int keyBits)
 {
 	int Nr, i;
 
 	/* expand the cipher key: */
-	Nr = rijndaelKeySetupEnc(erk, cipherKey, keyBits);
+	Nr = aes_setupEnc(erk, cipherKey, keyBits);
 
 	/*
 	 * invert the order of the round keys and apply the inverse MixColumn
@@ -889,8 +1158,8 @@ static const u32 rcon[] = {
  *
  * @return	the number of rounds for the given cipher key size.
  */
-static int
-rijndaelKeySetupEnc(u32 rk[/*4*(Nr + 1)*/], const u8 cipherKey[], int keyBits)
+int
+aes_setupEnc(ulong rk[/*4*(Nr + 1)*/], const uchar cipherKey[], int keyBits)
 {
 	int i = 0;
 	u32 temp;
@@ -977,13 +1246,13 @@ rijndaelKeySetupEnc(u32 rk[/*4*(Nr + 1)*/], const u8 cipherKey[], int keyBits)
  * @return	the number of rounds for the given cipher key size.
  */
 static int
-rijndaelKeySetupDec(u32 rk[/* 4*(Nr + 1) */], const u8 cipherKey[], int keyBits)
+aes_setupDec(ulong rk[/* 4*(Nr + 1) */], const uchar cipherKey[], int keyBits)
 {
 	int Nr, i, j;
-	u32 temp;
+	ulong temp;
 
 	/* expand the cipher key: */
-	Nr = rijndaelKeySetupEnc(rk, cipherKey, keyBits);
+	Nr = aes_setupEnc(rk, cipherKey, keyBits);
 	/* invert the order of the round keys: */
 	for (i = 0, j = 4*Nr; i < j; i += 4, j -= 4) {
 		temp = rk[i    ]; rk[i    ] = rk[j    ]; rk[j    ] = temp;
@@ -1021,11 +1290,12 @@ rijndaelKeySetupDec(u32 rk[/* 4*(Nr + 1) */], const u8 cipherKey[], int keyBits)
 	return Nr;
 }
 
-static void
-rijndaelEncrypt(const u32 rk[/* 4*(Nr + 1) */], int Nr, const u8 pt[16],
-	u8 ct[16])
+/* using round keys in rk, perform Nr rounds of encrypting pt into ct */
+void
+aes_encrypt(const ulong rk[/* 4*(Nr + 1) */], int Nr, const uchar pt[16],
+	uchar ct[16])
 {
-	u32 s0, s1, s2, s3, t0, t1, t2, t3;
+	ulong s0, s1, s2, s3, t0, t1, t2, t3;
 #ifndef FULL_UNROLL
 	int r;
 #endif /* ?FULL_UNROLL */
@@ -1204,11 +1474,11 @@ rijndaelEncrypt(const u32 rk[/* 4*(Nr + 1) */], int Nr, const u8 pt[16],
 	PUTU32(ct + 12, s3);
 }
 
-static void
-rijndaelDecrypt(const u32 rk[/* 4*(Nr + 1) */], int Nr, const u8 ct[16],
-	u8 pt[16])
+void
+aes_decrypt(const ulong rk[/* 4*(Nr + 1) */], int Nr, const uchar ct[16],
+	uchar pt[16])
 {
-	u32 s0, s1, s2, s3, t0, t1, t2, t3;
+	ulong s0, s1, s2, s3, t0, t1, t2, t3;
 #ifndef FULL_UNROLL
 	int r;
 #endif		/* ?FULL_UNROLL */
@@ -1390,7 +1660,7 @@ rijndaelDecrypt(const u32 rk[/* 4*(Nr + 1) */], int Nr, const u8 ct[16],
 #ifdef INTERMEDIATE_VALUE_KAT
 
 static void
-rijndaelEncryptRound(const u32 rk[/* 4*(Nr + 1) */], int Nr, u8 block[16],
+aes_encryptRound(const u32 rk[/* 4*(Nr + 1) */], int Nr, u8 block[16],
 	int rounds)
 {
 	int r;
@@ -1483,7 +1753,7 @@ rijndaelEncryptRound(const u32 rk[/* 4*(Nr + 1) */], int Nr, u8 block[16],
 }
 
 static void
-rijndaelDecryptRound(const u32 rk[/* 4*(Nr + 1) */], int Nr, u8 block[16],
+aes_decryptRound(const u32 rk[/* 4*(Nr + 1) */], int Nr, u8 block[16],
 	int rounds)
 {
 	int r;

Some files were not shown because too many files changed in this diff