Browse Source

Plan 9 from Bell Labs 2009-11-20

David du Colombier 14 years ago
parent
commit
c52f39b718

+ 4 - 2
sys/man/8/smtp

@@ -55,7 +55,7 @@ sends the mail message from standard input
 to the users
 .I rcpt-list
 on the host at network address
-.I address 
+.I address
 using the Simple Mail Transfer Protocol.
 The options are:
 .TF -
@@ -151,7 +151,9 @@ specifies a certificate to use for TLS.  Without this
 option, the capability to start TLS will not be advertised.
 .TP
 .B -d
-turns on debugging output to standard error.
+turns on debugging output,
+with each connection's output going to a uniquely-named file in
+.BR /sys/log/smtpdb .
 .TP
 .B -D
 sleeps for 15 seconds usually at the start of the SMTP dialogue;

+ 7 - 0
sys/src/9/boot/boot.c

@@ -35,6 +35,13 @@ boot(int argc, char *argv[])
 
 	fmtinstall('r', errfmt);
 
+	/*
+	 * we should inherit the standard fds all referring to /dev/cons,
+	 * but we're being paranoid.
+	 */
+	close(0);
+	close(1);
+	close(2);
 	bind("#c", "/dev", MBEFORE);
 	open("/dev/cons", OREAD);
 	open("/dev/cons", OWRITE);

+ 1 - 1
sys/src/9/boot/bootauth.c

@@ -38,7 +38,7 @@ authentication(int cpuflag)
 	av[ac] = 0;
 	switch(fork()){
 	case -1:
-		fatal("starting factotum");
+		fatal("starting factotum: %r");
 	case 0:
 		exec("/boot/factotum", av);
 		fatal("execing /boot/factotum");

+ 17 - 0
sys/src/9/ip/devip.c

@@ -818,6 +818,12 @@ setlport(Conv* c)
 		}
 	}
 	qunlock(p);
+	/*
+	 * debugging: let's see if we ever get this.
+	 * if we do (and we're a cpu server), we might as well restart
+	 * since we're now unable to service new connections.
+	 */
+	panic("setlport: out of ports");
 	return "no ports available";
 
 chosen:
@@ -1313,8 +1319,12 @@ retry:
 		}
 	}
 	if(pp >= ep) {
+		if(p->gc)
+			print("Fsprotoclone: garbage collecting Convs\n");
 		if(p->gc != nil && (*p->gc)(p))
 			goto retry;
+		/* debugging: do we ever get here? */
+		panic("Fsprotoclone: all conversations in use");
 		return nil;
 	}
 
@@ -1390,7 +1400,14 @@ Fsnewcall(Conv *c, uchar *raddr, ushort rport, uchar *laddr, ushort lport, uchar
 	for(l = &c->incall; *l; l = &(*l)->next)
 		i++;
 	if(i >= Maxincall) {
+		static int beenhere;
+
 		qunlock(c);
+		if (!beenhere) {
+			beenhere = 1;
+			print("Fsnewcall: incall queue full (%d) on port %d\n",
+				i, c->lport);
+		}
 		return nil;
 	}
 

+ 3 - 1
sys/src/9/ip/icmp.c

@@ -336,7 +336,9 @@ icmpiput(Proto *icmp, Ipifc*, Block *bp)
 	ipriv->stats[InMsgs]++;
 
 	p = (Icmp *)bp->rp;
-	netlog(icmp->f, Logicmp, "icmpiput %d %d\n", p->type, p->code);
+	netlog(icmp->f, Logicmp, "icmpiput %s (%d) %d\n",
+		(p->type < nelem(icmpnames)? icmpnames[p->type]: ""),
+		p->type, p->code);
 	n = blocklen(bp);
 	if(n < ICMP_IPSIZE+ICMP_HDRSIZE){
 		ipriv->stats[InErrors]++;

+ 0 - 13
sys/src/9/ip/inferno.c

@@ -4,7 +4,6 @@
 #include	"dat.h"
 #include	"fns.h"
 #include	"../port/error.h"
-#include	"ip.h"
 
 /*
  *  some hacks for commonality twixt inferno and plan9
@@ -16,24 +15,12 @@ commonuser(void)
 	return up->user;
 }
 
-Chan*
-commonfdtochan(int fd, int mode, int a, int b)
-{
-	return fdtochan(fd, mode, a, b);
-}
-
 char*
 commonerror(void)
 {
 	return up->errstr;
 }
 
-char*
-bootp(Ipifc*)
-{
-	return "unimplmented";
-}
-
 int
 bootpread(char*, ulong, int)
 {

+ 0 - 2
sys/src/9/ip/ip.h

@@ -648,13 +648,11 @@ extern ulong	restrict_mtu(uchar*, ulong);
 /*
  * bootp.c
  */
-extern char*	bootp(Ipifc*);
 extern int	bootpread(char*, ulong, int);
 
 /*
  *  resolving inferno/plan9 differences
  */
-Chan*		commonfdtochan(int, int, int, int);
 char*		commonuser(void);
 char*		commonerror(void);
 

+ 1 - 1
sys/src/9/ip/netlog.c

@@ -225,7 +225,7 @@ netlogctl(Fs *f, char* s, int n)
 void
 netlog(Fs *f, int mask, char *fmt, ...)
 {
-	char buf[128], *t, *fp;
+	char buf[256], *t, *fp;
 	int i, n;
 	va_list arg;
 

+ 2 - 2
sys/src/9/kw/archkw.c

@@ -162,9 +162,9 @@ archkwlink(void)
 }
 
 int
-archether(int ctlno, Ether *ether)
+archether(unsigned ctlno, Ether *ether)
 {
-	if(ctlno != 0)
+	if(ctlno >= 2)
 		return -1;
 	ether->type = "kirkwood";
 	ether->port = ctlno;

+ 1 - 1
sys/src/9/kw/devether.c

@@ -12,7 +12,7 @@
 #define devno	dev
 #define iq	in
 
-extern int archether(int ctlno, Ether *ether);
+extern int archether(unsigned ctlno, Ether *ether);
 
 static Ether *etherxx[MaxEther];
 

+ 3 - 2
sys/src/9/kw/etherif.h

@@ -9,13 +9,11 @@ struct Ether {
 	RWlock;				/* TO DO */
 	ISAConf;			/* hardware info */
 	int	ctlrno;
-//	int	tbdf;			/* type+busno+devno+funcno */
 	int	minmtu;
 	int	maxmtu;
 	uchar	ea[Eaddrlen];
 	void	*address;
 	int	tbusy;
-	int	encry;
 
 	void	(*attach)(Ether*);	/* filled in by reset routine */
 	void	(*closed)(Ether*);
@@ -29,6 +27,9 @@ struct Ether {
 	void	*ctlr;
 	int	pcmslot;		/* PCMCIA */
 	int	fullduplex;		/* non-zero if full duplex */
+	int	linkchg;		/* link status changed? */
+	int	mcaston;		/* multicast ever enabled? */
+	uvlong	starttime;		/* last activity time */
 
 	Queue*	oq;
 

+ 66 - 79
sys/src/9/kw/etherkw.c

@@ -1,11 +1,7 @@
 /*
  * marvell kirkwood ethernet (88e1116) driver
- * (as found in the sheevaplug).
+ * (as found in the sheevaplug & openrd).
  * from /public/doc/marvell/sheeva/88f61xx.kirkwood.pdf
- *
- * features that could be implemented:
- * - ip4, tcp, udp checksum offloading
- * - multicast filtering
  */
 
 #include "u.h"
@@ -23,14 +19,11 @@
 
 #define MASK(v)	((1UL<<(v)) - 1)
 
-// #undef	assert
-// #define assert(expr)
-
 #define	MIIDBG	if(0)iprint
-#define diprint	if(0)iprint
 
 enum {
-	Gberegs		= Regbase + 0x72000,
+	Gbe0regs	= Regbase + 0x72000,
+	Gbe1regs	= Regbase + 0x76000,
 
 	Nrx		= 512,
 	Ntx		= 512,
@@ -43,6 +36,8 @@ enum {
 	Descralign	= 16,
 	Bufalign	= 8,
 
+	Pass		= 1,		/* accept packets */
+
 	Qno		= 0,		/* do everything on queue zero */
 };
 
@@ -166,7 +161,7 @@ enum {
 #define SDCipgintrx(v)	((((v)>>15) & 1)<<25) | (((v) & MASK(15))<<7)
 
 	/* portcfg */
-	PCFGupromisc		= 1<<0,
+	PCFGupromisc		= 1<<0,	/* unicast promiscuous mode */
 #define Rxqdefault(q)	((q)<<1)
 #define Rxqarp(q)	((q)<<4)
 	PCFGbcrejectnoiparp	= 1<<7,
@@ -223,7 +218,7 @@ enum {
 	/* port serial control 1, psc1 */
 	PSC1loopback	= 1<<1,
 	PSC1mii		= 0<<2,
-	PSC1rgmii	= 1<<3,
+	PSC1rgmii	= 1<<3,			/* enable RGMII */
 	PSC1portreset	= 1<<4,
 	PSC1clockbypass	= 1<<5,
 	PSC1iban	= 1<<6,
@@ -461,17 +456,13 @@ struct Gbereg {
 	Mibstats;
 	ulong	_pad23[PAD(0x1400, 0x107c)];
 
-	/* multicast filtering */
+	/* multicast filtering; each byte: Qno<<1 | Pass */
 	ulong	dfsmt[64];	/* dest addr filter special m'cast table */
 	ulong	dfomt[64];	/* dest addr filter other m'cast table */
-
 	/* unicast filtering */
 	ulong	dfut[4];		/* dest addr filter unicast table */
 };
 
-vlong etherstart;
-
-
 static void getmibstats(Ctlr *);
 
 static void
@@ -571,16 +562,16 @@ dump(uchar *bp, long max)
 }
 
 static void
-etheractive(void)
+etheractive(Ether *ether)
 {
-	etherstart = TK2MS(MACHP(0)->ticks)/1000;
+	ether->starttime = TK2MS(MACHP(0)->ticks)/1000;
 }
 
 static void
-ethercheck(void)
+ethercheck(Ether *ether)
 {
-	if (etherstart != 0 &&
-	    TK2MS(MACHP(0)->ticks)/1000 - etherstart > Etherstuck)
+	if (ether->starttime != 0 &&
+	    TK2MS(MACHP(0)->ticks)/1000 - ether->starttime > Etherstuck)
 		iprint("ethernet stuck\n");
 }
 
@@ -593,7 +584,7 @@ receive(Ether *ether)
 	Ctlr *ctlr = ether->ctlr;
 	Rx *r;
 
-	ethercheck();
+	ethercheck(ether);
 	for (i = Nrx-2; i > 0; i--) {
 		r = &ctlr->rx[ctlr->rxhead];
 		assert(((uintptr)r & (Descralign - 1)) == 0);
@@ -629,7 +620,7 @@ receive(Ether *ether)
 		 */
 		b->rp += 2;
 		etheriq(ether, b, 1);
-		etheractive();
+		etheractive(ether);
 		if (i % (Nrx / 2) == 0)
 			rxreplenish(ctlr);
 	}
@@ -637,8 +628,11 @@ receive(Ether *ether)
 }
 
 static void
-txreplenish(Ctlr *ctlr)			/* free transmitted packets */
+txreplenish(Ether *ether)			/* free transmitted packets */
 {
+	Ctlr *ctlr;
+
+	ctlr = ether->ctlr;
 	while(ctlr->txtail != ctlr->txhead) {
 		cachedinvse(&ctlr->tx[ctlr->txtail].cs, BY2SE);
 		if(ctlr->tx[ctlr->txtail].cs & TCSdmaown)
@@ -648,7 +642,7 @@ txreplenish(Ctlr *ctlr)			/* free transmitted packets */
 		freeb(ctlr->txb[ctlr->txtail]);
 		ctlr->txb[ctlr->txtail] = nil;
 		ctlr->txtail = NEXT(ctlr->txtail, Ntx);
-		etheractive();
+		etheractive(ether);
 	}
 }
 
@@ -666,9 +660,9 @@ transmit(Ether *ether)
 	Gbereg *reg = ctlr->reg;
 	Tx *t;
 
-	ethercheck();
+	ethercheck(ether);
 	ilock(ctlr);
-	txreplenish(ctlr);			/* reap old packets */
+	txreplenish(ether);			/* reap old packets */
 
 	/* queue new packets; don't use more than half the tx descs. */
 	kick = 0;
@@ -759,14 +753,13 @@ interrupt(Ureg*, void *arg)
 	Ether *ether = arg;
 	Ctlr *ctlr = ether->ctlr;
 	Gbereg *reg = ctlr->reg;
-	static int linkchg = 0;
 
 	handled = 0;
 	irq = reg->irq;
 	irqe = reg->irqe;
 	reg->irq = 0;				/* extinguish intr causes */
 	reg->irqe = 0;				/* " " " */
-	ethercheck();
+	ethercheck(ether);
 
 	if(irq & Irxbufferq(Qno)) {
 		/*
@@ -795,7 +788,7 @@ interrupt(Ureg*, void *arg)
 		 */
 		if(irqe & IEphystschg) {
 			ether->link = (reg->ps0 & PS0linkup) != 0;
-			linkchg = 1;
+			ether->linkchg = 1;
 		}
 		if(irqe & IEtxerrq(Qno))
 			ether->oerrs++;
@@ -822,10 +815,10 @@ interrupt(Ureg*, void *arg)
 			handled++;
 	}
 
-	if(linkchg && (reg->ps1 & PS1an_done)) {
+	if(ether->linkchg && (reg->ps1 & PS1an_done)) {
 		handled++;
 		ether->link = (reg->ps0 & PS0linkup) != 0;
-		linkchg = 0;
+		ether->linkchg = 0;
 	}
 	ctlr->newintrs++;
 
@@ -842,8 +835,6 @@ interrupt(Ureg*, void *arg)
 	intrclear(Irqlo, IRQ0gbe0sum);
 }
 
-static int prom, mcast;
-
 void
 promiscuous(void *arg, int on)
 {
@@ -852,8 +843,8 @@ promiscuous(void *arg, int on)
 	Gbereg *reg = ctlr->reg;
 
 	ilock(ctlr);
-	ether->prom = prom = on;
-	if(prom || mcast)
+	ether->prom = on;
+	if(on)
 		reg->portcfg |= PCFGupromisc;
 	else
 		reg->portcfg &= ~PCFGupromisc;
@@ -861,20 +852,9 @@ promiscuous(void *arg, int on)
 }
 
 void
-multicast(void *arg, uchar *addr, int on)
+multicast(void *, uchar *, int)
 {
-	Ether *e = arg;
-	Ctlr *ctlr = e->ctlr;
-	Gbereg *reg = ctlr->reg;
-
-	mcast |= on;
-	USED(addr);
-	ilock(ctlr);
-	if(prom || mcast)
-		reg->portcfg |= PCFGupromisc;		/* overkill */
-	else
-		reg->portcfg &= ~PCFGupromisc;
-	iunlock(ctlr);
+	/* nothing to do; we always accept multicast */
 }
 
 static void quiesce(Gbereg *reg);
@@ -1047,10 +1027,17 @@ kirkwoodmii(Ether *ether)
 	ctlr->mii->mir = miird;
 	ctlr->mii->miw = miiwr;
 
+	phy = nil;
 	if(mii(ctlr->mii, ~0) == 0 || (phy = ctlr->mii->curphy) == nil){
+		iprint("#l%d: etherkw: init mii failure\n", ether->ctlrno);
+		if (phy)
+			iprint("#l%d: etherkw: mii(...,~0) failed\n",
+				ether->ctlrno);
+		else
+			iprint("#l%d: etherkw: nil ctlr->mii->curphy\n",
+				ether->ctlrno);
 		free(ctlr->mii);
 		ctlr->mii = nil;
-		iprint("etherkw: init mii failure\n");
 		return -1;
 	}
 
@@ -1092,30 +1079,25 @@ kirkwoodmii(Ether *ether)
 static int
 miiphyinit(Mii *mii)			/* magic numbers 'r' us */
 {
-	ulong reg, devadr;
+	ulong dev;
 
 	/* select mii phy */
-	devadr = miird(mii, 0xEE, 0xEE);
-//	print("devadr %lux\n", devadr);
-	if (devadr == -1) {
+	dev = miird(mii, 0xEE, 0xEE);		/* device address */
+//	print("dev %lux\n", dev);
+	if (dev == -1) {
 		print("etherkw: can't read PHY dev address\n");
 		return -1;
 	}
 
 	/* leds link & activity */
-	miiwr(mii, devadr, 22, 0x3);
-	reg = miird(mii, devadr, 10);
-	reg &= ~0xf;
-	reg |= 0x1;
-	miiwr(mii, devadr, 10, reg);
-	miiwr(mii, devadr, 22, 0);
+	miiwr(mii, dev, 22, 0x3);
+	miiwr(mii, dev, 10, (miird(mii, dev, 10) & ~0xf) | 1);	/* magic */
+	miiwr(mii, dev, 22, 0);
 
 	/* enable RGMII delay on Tx and Rx for CPU port */
-	miiwr(mii, devadr, 22, 2);
-	reg = miird(mii, devadr, 21);
-	reg |= (1<<5) | (1<<4);
-	miiwr(mii, devadr, 21, reg);
-	miiwr(mii, devadr, 22, 0);
+	miiwr(mii, dev, 22, 2);
+	miiwr(mii, dev, 21, miird(mii, dev, 21) | 1<<5 | 1<<4);	/* magic */
+	miiwr(mii, dev, 22, 0);
 	return 0;
 }
 
@@ -1167,16 +1149,12 @@ p32(uchar *p, ulong v)
 	*p   = v;
 }
 
-enum {
-	Pass = 1,
-};
-
 /*
  * set ether->ea from hw mac address,
  * configure unicast filtering to accept it.
  */
 void
-archetheraddr(Ether *ether, Gbereg *reg, int queue)
+archetheraddr(Ether *ether, Gbereg *reg, int rxqno)
 {
 	ulong nibble, ucreg, tbloff, regoff;
 
@@ -1191,8 +1169,12 @@ archetheraddr(Ether *ether, Gbereg *reg, int queue)
 	regoff *= 8;
 	ucreg = reg->dfut[tbloff];
 	ucreg &= 0xff << regoff;
-	ucreg |= (queue << 1 | Pass) << regoff;
+	ucreg |= (rxqno << 1 | Pass) << regoff;
 	reg->dfut[tbloff] = ucreg;
+
+	/* accept all multicast too.  set up special & other tables. */
+	memset(reg->dfsmt, Qno<<1 | Pass, sizeof reg->dfsmt);
+	memset(reg->dfomt, Qno<<1 | Pass, sizeof reg->dfomt);
 }
 
 static void
@@ -1269,7 +1251,7 @@ ctlrinit(Ether *ether)
 	reg->sdc = SDCrifb | SDCrxburst(Burst16) | SDCtxburst(Burst16) |
 		SDCrxnobyteswap | SDCtxnobyteswap |
 		SDCipgintrx(CLOCKFREQ/(Maxrxintrsec*64));
-	reg->pxtfut = 0;	// TFUTipginttx(CLOCKFREQ/(Maxrxintrsec*64));
+	reg->pxtfut = 0;	/* TFUTipginttx(CLOCKFREQ/(Maxrxintrsec*64)) */
 
 	/* allow just these interrupts */
 	reg->irqmask = Irxbufferq(Qno) | Irxerr | Itxendq(Qno);
@@ -1280,6 +1262,8 @@ ctlrinit(Ether *ether)
 	reg->euirqmask = 0;
 	reg->euirq = 0;
 
+//	archetheraddr(ether, ctlr->reg, Qno);	/* 2nd location */
+
 	reg->tcqdp[Qno]  = PADDR(&ctlr->tx[ctlr->txhead]);
 	for (i = 1; i < nelem(reg->tcqdp); i++)
 		reg->tcqdp[i] = 0;
@@ -1299,9 +1283,9 @@ ctlrinit(Ether *ether)
 
 	/* set ethernet MTU for leaky bucket mechanism to 0 (disabled) */
 	reg->pmtu = 0;
-	reg->rqc = Rxqon(Qno);
 
-	etheractive();
+	reg->rqc = Rxqon(Qno);
+	etheractive(ether);
 
 	snprint(name, sizeof name, "#l%drproc", ether->ctlrno);
 	kproc(name, rcvproc, ether);
@@ -1449,10 +1433,13 @@ reset(Ether *ether)
 	ether->ctlr = ctlr;
 	switch(ether->ctlrno) {
 	case 0:
-		ctlr->reg = (Gbereg*)Gberegs;
+		ctlr->reg = (Gbereg*)Gbe0regs;
+		break;
+	case 1:
+		ctlr->reg = (Gbereg*)Gbe1regs;
 		break;
 	default:
-		panic("etherkirdwood: bad ether ctlr #%d", ether->ctlrno);
+		panic("etherkw: bad ether ctlr #%d", ether->ctlrno);
 	}
 
 	/* io cfg 0: 1.8v gbe */
@@ -1471,8 +1458,8 @@ reset(Ether *ether)
 		ether->ctlr = nil;
 		return -1;
 	}
-	miiphyinit(ctlr->mii);
-	archetheraddr(ether, ctlr->reg, 0);	/* 0 is the rx queue */
+	miiphyinit(ctlr->mii);			/* commented-out in inferno */
+	archetheraddr(ether, ctlr->reg, Qno);	/* original location */
 
 	ether->attach = attach;
 	ether->transmit = transmit;

+ 1 - 1
sys/src/9/kw/mkfile

@@ -1,5 +1,5 @@
 CONF=plug
-CONFLIST=plug
+CONFLIST=plug openrd
 
 # allegedly u-boot uses the bottom 8MB (up to 0x800000)
 # so avoid that

+ 10 - 2
sys/src/9/port/initcode.c

@@ -1,6 +1,7 @@
 /*
  * IMPORTANT!  DO NOT ADD LIBRARY CALLS TO THIS FILE.
- * The entire text image must fit on one page.
+ * The entire text image must fit on one page
+ * (and there's no data segment, so any read/write data must be on the stack).
  */
 
 #include <u.h>
@@ -19,6 +20,9 @@ char env[] = "/env";
 void
 startboot(char *argv0, char **argv)
 {
+	char buf[200];	/* keep this fairly large to capture error details */
+
+	/* in case boot is a shell script */
 	open(cons, OREAD);
 	open(cons, OWRITE);
 	open(cons, OWRITE);
@@ -26,6 +30,10 @@ startboot(char *argv0, char **argv)
 	bind(ec, env, MAFTER);
 	bind(e, env, MCREATE|MAFTER);
 	bind(s, srv, MREPL|MCREATE);
+
 	exec(boot, argv);
-	for(;;);
+
+	rerrstr(buf, sizeof buf);
+	buf[sizeof buf - 1] = '\0';
+	_exits(buf);
 }

+ 1 - 1
sys/src/9/port/page.c

@@ -181,7 +181,7 @@ newpage(int clear, Segment **s, ulong va)
 
 	lock(p);
 	if(p->ref != 0)
-		panic("newpage");
+		panic("newpage: p->ref %d != 0", p->ref);
 
 	uncachepage(p);
 	p->ref++;

+ 19 - 10
sys/src/cmd/upas/pop3/pop3.c

@@ -63,7 +63,7 @@ static int passwordinclear;
 static int didtls;
 
 typedef struct Msg Msg;
-struct Msg 
+struct Msg
 {
 	int upasnum;
 	char digest[64];
@@ -85,7 +85,8 @@ static char tmpaddr[64];
 void
 usage(void)
 {
-	fprint(2, "usage: upas/pop3 [-a authmboxfile] [-d debugfile] [-p]\n");
+	fprint(2, "usage: upas/pop3 [-a authmboxfile] [-d debugfile] [-p] "
+		"[-r remote] [-t cert]\n");
 	exits("usage");
 }
 
@@ -113,6 +114,9 @@ main(int argc, char **argv)
 			close(fd);
 		}
 		break;
+	case 'p':
+		passwordinclear = 1;
+		break;
 	case 'r':
 		strecpy(tmpaddr, tmpaddr+sizeof tmpaddr, EARGF(usage()));
 		if(arg = strchr(tmpaddr, '!'))
@@ -126,9 +130,6 @@ main(int argc, char **argv)
 			exits(nil);
 		}
 		break;
-	case 'p':
-		passwordinclear = 1;
-		break;
 	}ARGEND
 
 	/* do before TLS */
@@ -575,7 +576,7 @@ stlscmd(char*)
 	Binit(&out, 1, OWRITE);
 	didtls = 1;
 	return 0;
-}		
+}
 
 static int
 topcmd(char *arg)
@@ -643,7 +644,7 @@ uidlcmd(char *arg)
 			return senderr("no such message");
 		sendok("%d %s", n+1, msg[n].digest);
 	}
-	return 0;	
+	return 0;
 }
 
 static char*
@@ -738,15 +739,23 @@ dologin(char *response)
 {
 	AuthInfo *ai;
 	static int tries;
+	static ulong delaysecs = 5;
 
 	chs->user = user;
 	chs->resp = response;
 	chs->nresp = strlen(response);
 	if((ai = auth_response(chs)) == nil){
-		if(tries++ >= 5){
+		if(tries >= 20){
 			senderr("authentication failed: %r; server exiting");
 			exits(nil);
-		}	
+		}
+		if(++tries == 3)
+			syslog(0, "pop3", "likely password guesser from %s",
+				peeraddr);
+		delaysecs *= 2;
+		if (delaysecs > 30*60)
+			delaysecs = 30*60;		/* half-hour max. */
+		sleep(delaysecs * 1000); /* prevent beating on our auth server */
 		return senderr("authentication failed");
 	}
 
@@ -784,7 +793,7 @@ passcmd(char *arg)
 	if((chs = auth_challenge("proto=apop role=server")) == nil)
 		return senderr("couldn't get apop challenge");
 
-	// hash challenge with secret and convert to ascii
+	/* hash challenge with secret and convert to ascii */
 	s = md5((uchar*)chs->chal, chs->nchal, 0, 0);
 	md5((uchar*)arg, strlen(arg), digest, s);
 	snprint(response, sizeof response, "%.*H", MD5dlen, digest);

+ 2 - 2
sys/src/cmd/upas/send/message.c

@@ -71,7 +71,7 @@ m_free(message *mp)
 	free((char *)mp);
 }
 
-/* read a message into a temp file , return an open fd to it */
+/* read a message into a temp file, return an open fd to it in mp->fd */
 static int
 m_read_to_file(Biobuf *fp, message *mp)
 {
@@ -82,7 +82,7 @@ m_read_to_file(Biobuf *fp, message *mp)
 
 	file = s_new();
 	/*
-	 *  create temp file to be remove on close
+	 *  create temp file to be removed on close
 	 */
 	abspath("mtXXXXXX", UPASTMP, file);
 	mktemp(s_to_c(file));

+ 5 - 5
sys/src/cmd/upas/send/rewrite.c

@@ -168,7 +168,7 @@ findrule(String *addrp, int authorized)
 			continue;
 		memset(rp->subexp, 0, sizeof(rp->subexp));
 		if(debug)
-			print("matching %s against %s\n", s_to_c(addrp),
+			fprint(2, "matching %s against %s\n", s_to_c(addrp),
 				rp->matchre->base);
 		if(regexec(rp->program, s_to_c(addrp), rp->subexp, NSUBEXP))
 		if(s_to_c(addrp) == rp->subexp[0].sp)
@@ -204,12 +204,12 @@ rewrite(dest *dp, message *mp)
 	dp->repl2 = substitute(rp->repl2, rp->subexp, mp);
 	dp->status = rp->type;
 	if(debug){
-		print("\t->");
+		fprint(2, "\t->");
 		if(dp->repl1)
-			print("%s", s_to_c(dp->repl1));
+			fprint(2, "%s", s_to_c(dp->repl1));
 		if(dp->repl2)
-			print("%s", s_to_c(dp->repl2));
-		print("\n");
+			fprint(2, "%s", s_to_c(dp->repl2));
+		fprint(2, "\n");
 	}
 	s_free(lower);
 	return 0;

+ 1 - 1
sys/src/cmd/upas/smtp/smtp.c

@@ -357,7 +357,7 @@ dotls(char *me)
 		h = malloc(2*sizeof hash + 1);
 		if (h != nil) {
 			enc16(h, 2*sizeof hash + 1, hash, sizeof hash);
-			// print("x509 sha1=%s", h);
+			// fprint(2, "x509 sha1=%s", h);
 			syslog(0, "smtp",
 		"remote cert. has bad thumbprint: x509 sha1=%s server=%q",
 				h, ddomain);

+ 65 - 11
sys/src/cmd/upas/smtp/smtpd.c

@@ -22,6 +22,8 @@ int	logged;
 int	rejectcount;
 int	hardreject;
 
+ulong	starttime;
+
 Biobuf	bin;
 
 int	debug;
@@ -69,9 +71,13 @@ catchalarm(void *a, char *msg)
 		rv = Atnoterecog;
 	} else
 		rv = Atnoteunknown;
+	if (debug) {
+		seek(2, 0, 2);
+		fprint(2, "caught note: %s\n", msg);
+	}
 
 	/* kill the children if there are any */
-	if(pp) {
+	if(pp && pp->pid > 0) {
 		syskillpg(pp->pid);
 		/* none can't syskillpg, so try a variant */
 		sleep(500);
@@ -114,6 +120,7 @@ main(int argc, char **argv)
 	netdir = nil;
 	quotefmtinstall();
 	fmtinstall('I', eipfmt);
+	starttime = time(0);
 	ARGBEGIN{
 	case 'a':
 		authenticate = 1;
@@ -172,9 +179,9 @@ main(int argc, char **argv)
 		mailer = mailerpath("send");
 
 	if(debug){
+		snprint(buf, sizeof buf, "%s/smtpdb/%ld", UPASLOG, time(0));
 		close(2);
-		snprint(buf, sizeof(buf), "%s/smtpd.db", UPASLOG);
-		if (open(buf, OWRITE) >= 0) {
+		if (create(buf, OWRITE | OEXCL, 0662) >= 0) {
 			seek(2, 0, 2);
 			fprint(2, "%d smtpd %s\n", getpid(), thedate());
 		} else
@@ -231,6 +238,15 @@ listadd(List *l, String *path)
 	l->last = lp;
 }
 
+void
+stamp(void)
+{
+	if(debug) {
+		seek(2, 0, 2);
+		fprint(2, "%3lud ", time(0) - starttime);
+	}
+}
+
 #define	SIZE	4096
 
 int
@@ -247,6 +263,7 @@ reply(char *fmt, ...)
 	n = out - buf;
 	if(debug) {
 		seek(2, 0, 2);
+		stamp();
 		write(2, buf, n);
 	}
 	write(1, buf, n);
@@ -675,6 +692,12 @@ void
 quit(void)
 {
 	reply("221 2.0.0 Successful termination\r\n");
+	if(debug){
+		seek(2, 0, 2);
+		stamp();
+		fprint(2, "# %d sent 221 reply to QUIT %s\n",
+			getpid(), thedate());
+	}
 	close(0);
 	exits(0);
 }
@@ -766,6 +789,7 @@ getcrnl(String *s, Biobuf *fp)
 				if(debug) {
 					seek(2, 0, 2);
 					fprint(2, "%c", c);
+					stamp();
 				}
 				s_putc(s, '\n');
 				goto out;
@@ -1008,7 +1032,8 @@ forgedheaderwarnings(void)
 	nbytes = 0;
 
 	/* warn about envelope sender */
-	if(strcmp(s_to_c(senders.last->p), "/dev/null") != 0 &&
+	if(senders.last != nil && senders.last->p != nil &&
+	    strcmp(s_to_c(senders.last->p), "/dev/null") != 0 &&
 	    masquerade(senders.last->p, nil))
 		nbytes += Bprint(pp->std[0]->fp,
 			"X-warning: suspect envelope domain\n");
@@ -1110,7 +1135,7 @@ pipemsg(int *byteswritten)
 	 *  add an orginator and/or destination if either is missing
 	 */
 	if(originator == 0){
-		if(senders.last == nil)
+		if(senders.last == nil || senders.last->p == nil)
 			nbytes += Bprint(pp->std[0]->fp, "From: /dev/null@%s\n",
 				him);
 		else
@@ -1190,10 +1215,12 @@ pipemsg(int *byteswritten)
 		/* message did not terminate normally */
 		snprint(pipbuf, sizeof pipbuf, "network eof: %r");
 		piperror = pipbuf;
-		syskillpg(pp->pid);
-		/* none can't syskillpg, so try a variant */
-		sleep(500);
-		syskill(pp->pid);
+		if (pp->pid > 0) {
+			syskillpg(pp->pid);
+			/* none can't syskillpg, so try a variant */
+			sleep(500);
+			syskill(pp->pid);
+		}
 		status = 1;
 	}
 
@@ -1201,6 +1228,11 @@ pipemsg(int *byteswritten)
 		piperror = "write error 4";
 		status = 1;
 	}
+	if (debug) {
+		stamp();
+		fprint(2, "at end of message; %s .\n",
+			(sawdot? "saw": "didn't see"));
+	}
 	stream_free(pp->std[0]);
 	pp->std[0] = 0;
 	*byteswritten = nbytes;
@@ -1338,6 +1370,12 @@ data(void)
 		return;
 
 	reply("354 Input message; end with <CRLF>.<CRLF>\r\n");
+	if(debug){
+		seek(2, 0, 2);
+		stamp();
+		fprint(2, "# sent 354; accepting DATA %s\n", thedate());
+	}
+
 
 	/*
 	 *  allow 145 more minutes to move the data
@@ -1350,18 +1388,28 @@ data(void)
 	 *  read any error messages
 	 */
 	err = s_new();
+	if (debug) {
+		stamp();
+		fprint(2, "waiting for upas/send to close stderr\n");
+	}
 	while(s_read_line(pp->std[2]->fp, err))
 		;
 
 	alarm(0);
 	atnotify(catchalarm, 0);
 
+	if (debug) {
+		stamp();
+		fprint(2, "waiting for upas/send to exit\n");
+	}
 	status |= proc_wait(pp);
 	if(debug){
 		seek(2, 0, 2);
-		fprint(2, "%d status %ux\n", getpid(), status);
+		stamp();
+		fprint(2, "# %d upas/send status %#ux at %s\n",
+			getpid(), status, thedate());
 		if(*s_to_c(err))
-			fprint(2, "%d error %s\n", getpid(), s_to_c(err));
+			fprint(2, "# %d error %s\n", getpid(), s_to_c(err));
 	}
 
 	/*
@@ -1414,6 +1462,12 @@ data(void)
 		else {
 			reply("250 2.5.0 sent\r\n");
 			logcall(nbytes);
+			if(debug){
+				seek(2, 0, 2);
+				stamp();
+				fprint(2, "# %d sent 250 reply %s\n",
+					getpid(), thedate());
+			}
 		}
 	}
 	proc_free(pp);

+ 1 - 1
sys/src/cmd/upas/smtp/smtpd.y

@@ -145,7 +145,7 @@ dotnum		: snum '.' snum '.' snum '.' snum ={ $$ = cat(&$1, &$2, &$3, &$4, &$5, &
 number		: d		={ $$ = cat(&$1, 0, 0, 0, 0 ,0, 0); }
 		| number d	={ $$ = cat(&$1, &$2, 0, 0, 0 ,0, 0); }
 		;
-snum		: number		={ if(atoi(s_to_c($1.s)) > 255) print("bad snum\n"); }
+snum		: number		={ if(atoi(s_to_c($1.s)) > 255) fprint(2, "bad snum\n"); }
 		;
 spaces		: SPACE		={ $$ = $1; }
 		| SPACE	spaces	={ $$ = $1; }

+ 7 - 4
sys/src/cmd/upas/smtp/spam.c

@@ -367,12 +367,13 @@ masquerade(String *path, char *him)
 	int rv = 0;
 
 	if(debug)
-		fprint(2, "masquerade(%s)\n", s_to_c(path));
+		fprint(2, "masquerade(%s) ", s_to_c(path));
 
-	if(trusted)
-		return 0;
-	if(path == nil)
+	if(trusted || path == nil) {
+		if(debug)
+			fprint(2, "0\n");
 		return 0;
+	}
 
 	lpath = s_copy(s_to_c(path));
 
@@ -395,6 +396,8 @@ masquerade(String *path, char *him)
 	}
 
 	s_free(lpath);
+	if (debug)
+		fprint(2, "%d\n", rv);
 	return rv;
 }