~kris/9p

9hist

9542dc66231c8212f79e5ff609418eb15d40f3ea — David du Colombier 24 years ago c127923
Plan 9 from Bell Labs 2001-11-17
M alphapc/devfloppy.c => alphapc/devfloppy.c +1 -1
@@ 911,7 911,7 @@ floppyformat(FDrive *dp, char *params)
	/*
	 *  set the type
	 */
	if(getfields(params, f, 3, 1, " ") > 1){
	if(tokenize(params, f, 3) > 1){
		for(t = floppytype; t < &floppytype[nelem(floppytype)]; t++){
			if(strcmp(f[1], t->name)==0 && t->dt==dp->dt){
				dp->t = t;

M alphapc/devvga.c => alphapc/devvga.c +1 -1
@@ 173,7 173,7 @@ vgactl(char* a)
	extern VGAcur *vgacur[];
	Rectangle r;

	n = getfields(a, field, nelem(field), 1, " ");
	n = tokenize(a, field, nelem(field));
	if(n < 1)
		error(Ebadarg);


M bitsy/devpenmouse.c => bitsy/devpenmouse.c +1 -1
@@ 341,7 341,7 @@ penmousewrite(Chan *c, void *va, long n, vlong)
			buf[n-1] = 0;
		else
			buf[n] = 0;
		nf = getfields(buf, field, 5, 1, " ");
		nf = tokenize(buf, field, 5);
		if(strcmp(field[0], "swap") == 0){
			if(mouseswap)
				setbuttonmap("123");

M bitsy/devuda1341.c => bitsy/devuda1341.c +1 -1
@@ 1270,7 1270,7 @@ audiowrite(Chan *c, void *vp, long n, vlong)
		memmove(buf, p, n);
		buf[n] = '\0';

		nf = getfields(buf, field, Ncmd, 1, " \t\n");
		nf = tokenize(buf, field, Ncmd);
		for(i = 0; i < nf; i++){
			/*
			 * a number is volume

M boot/boot.c => boot/boot.c +1 -1
@@ 232,7 232,7 @@ rootserver(char *arg)
		outin(prompt, reply, sizeof(reply));
		mp = findmethod(reply);
		if(mp){
			bargc = getfields(reply, bargv, Nbarg-1, 1, " ");
			bargc = tokenize(reply, bargv, Nbarg-1);
			cp = strchr(reply, '!');
			if(cp)
				strcpy(sys, cp+1);

M boot/bootcache.c => boot/bootcache.c +1 -1
@@ 17,7 17,7 @@ cache(int fd)

	readfile("#e/cfs", buf, sizeof(buf));
	if(*buf){
		argc = getfields(buf, argv, 4, 1, " ");
		argc = tokenize(buf, argv, 4);
		for(i = 0; i < argc; i++){
			if(strcmp(argv[i], "off") == 0)
				return fd;

M ip/arp.c => ip/arp.c +1 -1
@@ 271,7 271,7 @@ arpwrite(Fs *fs, char *s, int len)
	if(len > 0 && buf[len-1] == '\n')
		buf[len-1] = 0;

	n = getfields(buf, f, 4, 1, " ");
	n = tokenize(buf, f, 4);
	if(strcmp(f[0], "flush") == 0){
		qlock(arp);
		for(a = arp->cache; a < &arp->cache[NCACHE]; a++){

M ip/icmp.c => ip/icmp.c +25 -3
@@ 28,6 28,7 @@ typedef struct Icmp {

enum {			/* Packet Types */
	EchoReply	= 0,
	UnreachableV6	= 1,
	Unreachable	= 3,
	SrcQuench	= 4,
	Redirect	= 5,


@@ 51,6 52,7 @@ enum

char *icmpnames[Maxtype+1] =
{
[UnreachableV6]		"UnreachableV6",
[EchoReply]		"EchoReply",
[Unreachable]		"Unreachable",
[SrcQuench]		"SrcQuench",


@@ 293,7 295,7 @@ static char *unreachcode[] =
[1]	"host unreachable",
[2]	"protocol unreachable",
[3]	"port unreachable",
[4]	"fragmentation needed and DF set",
[4]	"unfragmentable",
[5]	"source route failed",
};



@@ 307,6 309,9 @@ icmpiput(Proto *icmp, Ipifc*, Block *bp)
	char	*msg;
	char	m2[128];
	Icmppriv *ipriv;
	int	code;
	ushort	x;
	uchar	dst[IPaddrlen];

	ipriv = icmp->priv;
	


@@ 344,10 349,23 @@ icmpiput(Proto *icmp, Ipifc*, Block *bp)
		ipoput(icmp->f, r, 0, MAXTTL, DFLTTOS);
		break;
	case Unreachable:
		if(p->code > 5 || p->code < 0)
		code = p->code;
		switch(code){
		default:
			msg = unreachcode[1];
		else
			break;
		case 5:
			x = nhgets(p->seq);
			msg = unreachcode[p->code];
			break;
		case 0:
		case 1:
		case 2:
		case 3:
		case 4:
			msg = unreachcode[p->code];
			break;
		}

		bp->rp += ICMP_IPSIZE+ICMP_HDRSIZE;
		if(blocklen(bp) < MinAdvise){


@@ 355,6 373,10 @@ icmpiput(Proto *icmp, Ipifc*, Block *bp)
			goto raise;
		}
		p = (Icmp *)bp->rp;
		if(code == 5){
			v4tov6(dst, p->dst);
			update_mtucache(dst, x);
		}
		pr = Fsrcvpcolx(icmp->f, p->proto);
		if(pr != nil && pr->advise != nil) {
			(*pr->advise)(pr, bp, msg);

M ip/ip.c => ip/ip.c +83 -2
@@ 432,6 432,20 @@ ipiput(Fs *f, Ipifc *ifc, Block *bp)
			freeblist(bp);
			return;
		}
		
		/* reassemble if the interface expects it */
		if(r->ifc->reassemble){
			frag = nhgets(h->frag);
			if(frag) {
				h->tos = 0;
				if(frag & IP_MF)
					h->tos = 1;
				bp = ipreassemble(ip, frag, bp, h);
				if(bp == nil)
					return;
				h = (Iphdr *)(bp->rp);
			}
		}

		ip->stats[ForwDatagrams]++;
		ipoput(f, bp, 1, h->ttl - 1, h->tos);


@@ 439,8 453,7 @@ ipiput(Fs *f, Ipifc *ifc, Block *bp)
		return;
	}



	/* reassemble */
	frag = nhgets(h->frag);
	if(frag) {
		h->tos = 0;


@@ 716,3 729,71 @@ ipcsum(uchar *addr)

	return (sum^0xffff);
}

enum
{
	Nmtucache=	128,
};

typedef struct MTUcache MTUcache;

struct MTUcache
{
	uchar	ip[IPaddrlen];
	ulong	mtu;
	ulong	ms;
};

static struct {
	Lock;
	MTUcache c[Nmtucache];
} mc;

void
update_mtucache(uchar *ip, ulong mtu)
{
	MTUcache *oldest, *p;

	if(mtu < 512)
		return;

	lock(&mc);
	oldest = mc.c;
	for(p = mc.c; p < &mc.c[Nmtucache]; p++){
		if(ipcmp(ip, p->ip) == 0){
			p->mtu = mtu;
			p->ms = msec;
			break;
		}
		if(p->ms < oldest->ms)
			oldest = p;
	}
	if(p == &mc.c[Nmtucache]){
		ipmove(oldest->ip, ip);
		oldest->mtu = mtu;
		oldest->ms = msec;
	}
	unlock(&mc);
}

ulong
restrict_mtu(uchar *ip, ulong mtu)
{
	MTUcache *p;

	lock(&mc);
	for(p = mc.c; p < &mc.c[Nmtucache]; p++){
		if(p->ms + 1000*10*60 < msec){
			memset(p->ip, 0, sizeof(p->ip));
			p->ms = 0;
		}
		if(ipcmp(ip, p->ip) == 0){
			if(p->mtu < mtu)
				mtu = p->mtu;
			break;
		}
	}
	unlock(&mc);

	return mtu;
}

M ip/ip.h => ip/ip.h +3 -0
@@ 174,6 174,7 @@ struct Ipifc
	int	maxmtu;		/* Maximum transfer unit */
	int	minmtu;		/* Minumum tranfer unit */
	void	*arg;		/* medium specific */
	int	reassemble;	/* reassemble IP packets before forwarding */

	/* these are used so that we can unbind on the fly */
	Lock	idlock;


@@ 543,6 544,8 @@ extern int	ipstats(Fs*, char*, int);
extern ushort	ptclbsum(uchar*, int);
extern ushort	ptclcsum(Block*, int, int);
extern void	ip_init(Fs*);
extern void	update_mtucache(uchar*, ulong);
extern ulong	restrict_mtu(uchar*, ulong);

/*
 * bootp.c

M ip/ipifc.c => ip/ipifc.c +6 -1
@@ 173,6 173,7 @@ ipifcunbind(Ipifc *ifc)
		(*ifc->m->unbind)(ifc);
	memset(ifc->dev, 0, sizeof(ifc->dev));
	ifc->arg = nil;
	ifc->reassemble = 0;

	/* hangup queues to stop queuing of packets */
	qhangup(ifc->conv->rq, "unbind");


@@ 288,6 289,7 @@ ipifccreate(Conv *c)
	ifc->conv = c;
	ifc->unbinding = 0;
	ifc->m = nil;
	ifc->reassemble = 0;
}

/* 


@@ 636,7 638,10 @@ ipifcctl(Conv* c, char**argv, int argc)
		return ipifcleavemulti(ifc, argv, argc);
	else if(strcmp(argv[0], "mtu") == 0)
		return ipifcsetmtu(ifc, argv, argc);
	else if(strcmp(argv[0], "iprouting") == 0){
	else if(strcmp(argv[0], "reassemble") == 0){
		ifc->reassemble = 1;
		return nil;
	} else if(strcmp(argv[0], "iprouting") == 0){
		i = 1;
		if(argc > 1)
			i = atoi(argv[1]);

M ip/netlog.c => ip/netlog.c +1 -1
@@ 167,7 167,7 @@ netlogctl(Fs *f, char* s, int len)
	if(len > 0 && buf[len-1] == '\n')
		buf[len-1] = 0;

	n = getfields(buf, fields, 10, 1, " ");
	n = tokenize(buf, fields, 10);
	if(n < 2)
		return Ebadnetctl;


M ip/tcp.c => ip/tcp.c +39 -18
@@ 649,7 649,7 @@ tcpmtu(Conv *s)
		mtu = ifc->maxmtu - ifc->m->hsize - (TCP_PKT + TCP_HDRSIZE);
	if(mtu < 4)
		mtu = DEF_MSS;
	return mtu;
	return restrict_mtu(s->raddr, mtu);
}

void


@@ 2183,24 2183,45 @@ tcpadvise(Proto *tcp, Block *bp, char *msg)

	/* Look for a connection */
	qlock(tcp);
	for(p = tcp->conv; *p; p++) {
		s = *p;
		tcb = (Tcpctl*)s->ptcl;
		if(s->rport == pdest)
		if(s->lport == psource)
		if(tcb->state != Closed)
		if(ipcmp(s->raddr, dest) == 0)
		if(ipcmp(s->laddr, source) == 0){
			qlock(s);
			qunlock(tcp);
			switch(tcb->state){
			case Syn_sent:
				localclose(s, msg);
				break;
	if(strcmp(msg, "unfragmentable") == 0){
		for(p = tcp->conv; *p; p++) {
			s = *p;
			tcb = (Tcpctl*)s->ptcl;
			if(tcb->state != Closed)
			if(ipcmp(s->raddr, dest) == 0)
			if(ipcmp(s->laddr, source) == 0){
				qlock(s);
				qunlock(tcp);
				switch(tcb->state){
				case Syn_sent:
					localclose(s, msg);
					break;
				}
				qunlock(s);
				freeblist(bp);
				return;
			}
		}
	} else {
		for(p = tcp->conv; *p; p++) {
			s = *p;
			tcb = (Tcpctl*)s->ptcl;
			if(s->rport == pdest)
			if(s->lport == psource)
			if(tcb->state != Closed)
			if(ipcmp(s->raddr, dest) == 0)
			if(ipcmp(s->laddr, source) == 0){
				qlock(s);
				qunlock(tcp);
				switch(tcb->state){
				case Syn_sent:
					localclose(s, msg);
					break;
				}
				qunlock(s);
				freeblist(bp);
				return;
			}
			qunlock(s);
			freeblist(bp);
			return;
		}
	}
	qunlock(tcp);

M pc/devfloppy.c => pc/devfloppy.c +1 -1
@@ 904,7 904,7 @@ floppyformat(FDrive *dp, char *params)
	/*
	 *  set the type
	 */
	if(getfields(params, f, 3, 1, " ") > 1){
	if(tokenize(params, f, 3) > 1){
		for(t = floppytype; t < &floppytype[nelem(floppytype)]; t++){
			if(strcmp(f[1], t->name)==0 && t->dt==dp->dt){
				dp->t = t;

M pc/devpccard.c => pc/devpccard.c +1 -1
@@ 1326,7 1326,7 @@ pccardwrite(Chan *c, void *v, long n, vlong)
		memmove(buf, v, n);
		buf[n] = '\0';

		nf = getfields(buf, field, Ncmd, 1, " \t\n");
		nf = tokenize(buf, field, Ncmd);
		for (i = 0; i != nf; i++) {
			if (!strcmp(field[i], "down")) {


M pc/devusb.c => pc/devusb.c +2 -2
@@ 2014,7 2014,7 @@ usbwrite(Chan *c, void *a, long n, vlong offset)
			n = sizeof(cmd)-1;
		memmove(cmd, a, n);
		cmd[n] = 0;
		nf = getfields(cmd, fields, nelem(fields), 0, " \t\n");
		nf = tokenize(cmd, fields, nelem(fields));
		if(nf < 2)
			error(Ebadarg);
		id = strtol(fields[1], nil, 0);


@@ 2038,7 2038,7 @@ usbwrite(Chan *c, void *a, long n, vlong offset)
			n = sizeof(cmd)-1;
		memmove(cmd, a, n);
		cmd[n] = 0;
		nf = getfields(cmd, fields, nelem(fields), 0, " \t\n");
		nf = tokenize(cmd, fields, nelem(fields));
		if(nf > 1 && strcmp(fields[0], "speed") == 0){
			d->ls = strtoul(fields[1], nil, 0) == 0;
		} else if(nf > 3 && strcmp(fields[0], "class") == 0){

M pc/devvga.c => pc/devvga.c +1 -1
@@ 184,7 184,7 @@ vgactl(char* a)
	extern VGAdev *vgadev[];
	extern VGAcur *vgacur[];

	n = getfields(a, field, nelem(field), 1, " \t\n");
	n = tokenize(a, field, nelem(field));
	if(n < 1)
		error(Ebadarg);


M pc/vgamach64xx.c => pc/vgamach64xx.c +1 -1
@@ 1174,7 1174,7 @@ mach64xxovlctl(VGAscr *scr, Chan *c, void *a, int)
	if (!mach64type->m64_vtgt) 
		error(Enodev);

	nfields = getfields(a, field, nelem(field), 1, "\t\n\r ");
	nfields = tokenize(a, field, nelem(field));
	if (nfields < 1) 
		error(Ebadarg);


M port/devaudio.c => port/devaudio.c +1 -1
@@ 1090,7 1090,7 @@ audiowrite(Chan *c, void *vp, long n, vlong)
		memmove(buf, a, n);
		buf[n] = '\0';

		nf = getfields(buf, field, Ncmd, 1, " \t\n");
		nf = tokenize(buf, field, Ncmd);
		for(i = 0; i < nf; i++){
			/*
			 * a number is volume

M port/devdraw.c => port/devdraw.c +1 -1
@@ 1159,7 1159,7 @@ drawwrite(Chan *c, void *a, long n, vlong)
			a = (char*)a + i;
			m -= i;
			*q = 0;
			if(getfields(buf, fields, nelem(fields), 1, " ") != 4)
			if(tokenize(buf, fields, nelem(fields)) != 4)
				error(Ebadarg);
			i = strtoul(fields[0], 0, 0);
			red = strtoul(fields[1], 0, 0);

M port/devmouse.c => port/devmouse.c +1 -1
@@ 343,7 343,7 @@ mousewrite(Chan *c, void *va, long n, vlong)
			buf[n-1] = 0;
		else
			buf[n] = 0;
		nf = getfields(buf, field, 3, 1, " ");
		nf = tokenize(buf, field, 3);
		if(strcmp(field[0], "swap") == 0){
			if(mouseswap)
				setbuttonmap("123");

M port/devproc.c => port/devproc.c +9 -6
@@ 240,11 240,14 @@ procopen(Chan *c, int omode)
			error(Eperm);
		break;

	case Qmem:
		if(p->privatemem)
			error(Eperm);
		/* fall through */
	case Qargs:
	case Qctl:
	case Qnote:
	case Qnoteid:
	case Qmem:
	case Qstatus:
	case Qwait:
	case Qregs:


@@ 507,17 510,14 @@ procread(Chan *c, void *va, long n, vlong off)
		|| (offset >= USTKTOP-USTKSIZE && offset < USTKTOP))
			return procctlmemio(p, offset, n, va, 1);

		/* Protect crypt key memory */
		if(offset+n >= palloc.cmembase && offset < palloc.cmemtop)
			error(Eperm);

		/* validate physical kernel addresses */
		/* validate kernel addresses */
		if(offset < (ulong)end) {
			if(offset+n > (ulong)end)
				n = (ulong)end - offset;
			memmove(a, (char*)offset, n);
			return n;
		}
		/* conf.base* and conf.npage* are set by xinit to refer to kernel allocation, not user pages */
		if(offset >= conf.base0 && offset < conf.npage0){
			if(offset+n > conf.npage0)
				n = conf.npage0 - offset;


@@ 1070,6 1070,9 @@ procctlreq(Proc *p, char *va, int n)
			error(Ebadctl);
		procctlclosefiles(p, 0, atoi(buf+6));
	}else
	if(strncmp(buf, "private", 7) == 0)
		p->privatemem = 1;
	else
	if(strncmp(buf, "pri", 3) == 0) {
		if(n < 4)
			error(Ebadctl);

M port/devsd.c => port/devsd.c +2 -2
@@ 205,7 205,7 @@ sdinitpart(SDunit* unit)
		for(p = getconf(buf); p != nil; p = q){
			if(q = strchr(p, '/'))
				*q++ = '\0';
			nf = getfields(p, f, nelem(f), 1, " \t\r");
			nf = tokenize(p, f, nelem(f));
			if(nf < 3)
				continue;
		


@@ 1100,7 1100,7 @@ sdwrite(Chan *c, void *a, long n, vlong off)
		cd.o_spec = '\0';
		memset(&cd.o_cf, 0, sizeof(DevConf));

		nf = getfields(buf, field, Ncmd, 1, " \t\n");
		nf = tokenize(buf, field, Ncmd);
		for (i = 0; i < nf; i++) {
			char *opt = field[i++];
			if (i >= nf)

M port/devuart.c => port/devuart.c +1 -1
@@ 318,7 318,7 @@ uartctl(Uart *p, char *cmd)
	char *f[16];
	int i, n, nf;

	nf = getfields(cmd, f, nelem(f), 1, " \t\n");
	nf = tokenize(cmd, f, nelem(f));
	for(i = 0; i < nf; i++){
		if(strncmp(f[i], "break", 5) == 0){
			(*p->phys->dobreak)(p, 0);

M port/parse.c => port/parse.c +34 -7
@@ 6,6 6,31 @@
#include	"../port/error.h"

/*
 * Generous estimate of number of fields, including terminal nil pointer
 */
static int
ncmdfield(char *p, int n)
{
	int white, nwhite;
	char *ep;
	int nf;

	if(p == nil)
		return 1;

	nf = 0;
	ep = p+n;
	white = 1;	/* first text will start field */
	while(p < ep){
		nwhite = (strchr(" \t\r\n", *p++ & 0xFF) != 0);	/* UTF is irrelevant */
		if(white && !nwhite)	/* beginning of field */
			nf++;
		white = nwhite;
	}
	return nf+1;	/* +1 for nil */
}

/*
 *  parse a command written to a device
 */
Cmdbuf*


@@ 15,13 40,13 @@ parsecmd(char *p, int n)
	int nf;
	char *sp;

	/* count fields and allocate a big enough cmdbuf */
	for(nf = 1, sp = p; sp != nil && *sp; nf++, sp = strchr(sp+1, ' '))
		;
	sp = smalloc(sizeof(*cb) + n + 1 + nf*sizeof(char*));
	nf = ncmdfield(p, n);

	/* allocate Cmdbuf plus string pointers plus copy of string including \0 */
	sp = smalloc(sizeof(*cb) + nf * sizeof(char*) + n + 1);
	cb = (Cmdbuf*)sp;
	cb->buf = sp+sizeof(*cb);
	cb->f = (char**)(cb->buf + n + 1);
	cb->f = (char**)(&cb[1]);
	cb->buf = (char*)(&cb->f[nf]);

	if(up!=nil && waserror()){
		free(cb);


@@ 36,7 61,9 @@ parsecmd(char *p, int n)
		n--;
	cb->buf[n] = '\0';

	cb->nf = getfields(cb->buf, cb->f, nf, 1, " ");
	cb->nf = tokenize(cb->buf, cb->f, nf-1);
	cb->f[cb->nf] = nil;

	return cb;
}


M port/portdat.h => port/portdat.h +6 -2
@@ 470,8 470,6 @@ struct Palloc
	Lock	hashlock;
	Rendez	r;			/* Sleep for free mem */
	QLock	pwait;			/* Queue of procs waiting for memory */
	ulong	cmembase;		/* Key memory */
	ulong	cmemtop;
};

struct Waitq


@@ 582,6 580,7 @@ struct Proc
	QLock	debug;		/* to access debugging elements of User */
	Proc	*pdbg;		/* the debugging process */
	ulong	procmode;	/* proc device file mode */
	ulong	privatemem;	/* proc does not let anyone read mem */
	int	hang;		/* hang at next exec for debug */
	int	procctl;	/* Control for /proc debugging */
	ulong	pc;		/* DEBUG only */


@@ 710,6 709,11 @@ struct Logflag {
	int	mask;
};

enum
{
	NCMDFIELD = 128
};

struct Cmdbuf
{
	char	*buf;

M port/proc.c => port/proc.c +1 -0
@@ 338,6 338,7 @@ newproc(void)
	p->movetime = 0;
	p->wired = 0;
	p->ureg = 0;
	p->privatemem = 0;
	p->errstr = p->errbuf0;
	p->syserrstr = p->errbuf1;
	p->errbuf0[0] = '\0';

M port/sysproc.c => port/sysproc.c +1 -0
@@ 471,6 471,7 @@ sysexec(ulong *arg)
	up->nnote = 0;
	up->notify = 0;
	up->notified = 0;
	up->privatemem = 0;
	procsetup(up);
	qunlock(&up->debug);
	if(up->hang)