~kris/9p

9hist

93e67d8b42f178491667ba7165427bc5ac2705f3 — David du Colombier 34 years ago a58e250
Plan 9 from Bell Labs 1992-03-18
M boot/aux.c => boot/aux.c +1 -0
@@ 107,6 107,7 @@ srvcreate(char *name, int fd)
{
	char *srvname;
	int f;
	char buf[2*NAMELEN];

	srvname = strrchr(name, '/');
	if(srvname)

M boot/boot.c => boot/boot.c +23 -179
@@ 1,22 1,11 @@
#include <u.h>
#include <libc.h>
#include <fcall.h>
#include "../port/bootp.h"
#include "../port/arp.h"
#include "../boot/boot.h"

#define DEFSYS "bootes"
typedef struct Net	Net;
typedef struct Flavor	Flavor;

enum
{
	Nterm	= 4,
	CtrlD	= 4,
	Cr	= 13,
	View	= 0x80,
};

Fcall	hdr;
int	printcol;

char	cputype[NAMELEN];


@@ 28,20 17,17 @@ int mflag;
int fflag;
int kflag;

void	nop(int);
void	session(int);
int	cache(int);
void	swapproc(void);
void	settime(int);
Method	*rootserver(char*);

void
main(int argc, char *argv)
main(int argc, char *argv[])
{
	int fd;
	Method *mp;
	char cmd[64];
	char flags[5];
	char flags[6];
	int islocal;

	sleep(1000);


@@ 71,14 57,14 @@ main(int argc, char *argv)
	/*
	 *  pick a method and initialize it
	 */
	mp = rootserver(*argv);
	islocal = strcmp(mp->name, "local") == 0;
	mp = rootserver(argc ? *argv : 0);
	(*mp->config)(mp);
	islocal = strcmp(mp->name, "local") == 0;

	/*
	 *  get/set key or password
	 */
	(*pword)(mp);
	(*pword)(islocal, mp);

	/*
	 *  connect to the root file system


@@ 89,7 75,8 @@ main(int argc, char *argv)
	if(!islocal){
		nop(fd);
		session(fd);
		fd = cache(fd);
		if(cfs)
			fd = (*cfs)(fd);
		srvcreate(sys, fd);
	}
	srvcreate("boot", fd);


@@ 104,17 91,19 @@ main(int argc, char *argv)
	close(fd);

	/*
	 *  start local fs if its not the root file server
	 *  if a local file server exists and it's not the
	 *  root file server, start it and mount it onto /n/kfs
	 */
	if(!islocal){
		for(mp = method; mp->name; mp++)
			if(strcmp(mp->name, "local")==0){
				local = (*mp->connect)(mp);
				if(local < 0)
				(*mp->config)(mp);
				fd = (*mp->connect)();
				if(fd < 0)
					break;
				if(mount(local, "/n/kfs", MAFTER|MCREATE, "", "") < 0)
				if(mount(fd, "/n/kfs", MAFTER|MCREATE, "", "") < 0)
					fatal("mount");
				close(local);
				close(fd);
				break;
			}
	}


@@ 124,13 113,13 @@ main(int argc, char *argv)

	sleep(1000);
	sprint(cmd, "/%s/init", cputype);
	sprint(flags, "-%s%s", cpuflag ? "c" : "t", mflag ? "m", "");
	sprint(flags, "-%s%s", cpuflag ? "c" : "t", mflag ? "m" : "");
	execl(cmd, "init", flags, 0);
	fatal(cmd);
}

/*
 *  ask user from whence comes the root file system
 *  ask user from whence cometh the root file system
 */
Method*
rootserver(char *arg)


@@ 142,18 131,18 @@ rootserver(char *arg)
	int n;

	mp = method;
	n = 0;
	sprint(prompt, "root is from (", mp->name);
	n = sprint(prompt, "root is from (%s", mp->name);
	for(mp++; mp->name; mp++)
		n += sprint(prompt+n, ", %s", mp->name);
	sprint(prompt+n, ")");

	for(;;){
	if(arg)
		strcpy(reply, arg);
	else
		strcpy(reply, method->name);
		if(arg == 0)
	for(;;){
		if(arg == 0 || mflag)
			outin(prompt, reply, sizeof(reply));
		else
			strcpy(reply, arg);
		arg = 0;
		for(mp = method; mp->name; mp++)
			if(*reply == *mp->name){


@@ 168,94 157,6 @@ rootserver(char *arg)
}

void
nop(int fd)
{
	long n;

	print("nop...");
	hdr.type = Tnop;
	hdr.tag = NOTAG;
	n = convS2M(&hdr, buf);
	if(write(fd, buf, n) != n)
		fatal("write nop");
	n = read(fd, buf, sizeof buf);
	if(n==2 && buf[0]=='O' && buf[1]=='K')
		n = read(fd, buf, sizeof buf);
	if(n <= 0)
		fatal("read nop");
	if(convM2S(buf, &hdr, n) == 0) {
		print("n = %d; buf = %#.2x %#.2x %#.2x %#.2x\n",
			n, buf[0], buf[1], buf[2], buf[3]);
		fatal("format nop");
	}
	if(hdr.type != Rnop)
		fatal("not Rnop");
}

void
session(int fd)
{
	long n;

	print("session...");
	hdr.type = Tsession;
	hdr.tag = NOTAG;
	n = convS2M(&hdr, buf);
	if(write(fd, buf, n) != n)
		fatal("write session");
	n = read(fd, buf, sizeof buf);
	if(n <= 0)
		fatal("read session");
	if(convM2S(buf, &hdr, n) == 0)
		fatal("format session");
	if(hdr.type == Rerror){
		print("error %s;", hdr.ename);
		fatal(hdr.ename);
	}
	if(hdr.type != Rsession)
		fatal("not Rsession");
}

int
cache(int fd)
{
	ulong i;
	int p[2];
	char d[DIRLEN];
	char partition[2*NAMELEN];

	if(stat("/cfs", d) < 0)
		return fd;
	sprint(partition, "%scache", bootdisk);
	if(stat(partition, d) < 0)
		return fd;
	print("cfs...");
	if(pipe(p)<0)
		fatal("pipe");
	switch(fork()){
	case -1:
		fatal("fork");
	case 0:
		close(p[1]);
		dup(fd, 0);
		close(fd);
		dup(p[0], 1);
		close(p[0]);
		if(format)
			execl("/cfs", "bootcfs", "-fs", "-p", partition, 0);
		else
			execl("/cfs", "bootcfs", "-s", "-p", partition, 0);
		break;
	default:
		close(p[0]);
		close(fd);
		fd = p[1];
		break;
	}
	return fd;
}

void
swapproc(void)
{
	int fd;


@@ 268,60 169,3 @@ swapproc(void)
	if(write(fd, "start", 5) <= 0)
		warning("starting swap kproc");
}

void
settime(int islocal)
{
	int n, f;
	int timeset;
	Dir dir;
	char dirbuf[DIRLEN];
	char *srvname;

	print("time...");
	timeset = 0;
	if(islocal){
		/*
		 *  set the time from the real time clock
		 */
		f = open("#r/rtc", ORDWR);
		if(f >= 0){
			if((n = read(f, dirbuf, sizeof(dirbuf)-1)) > 0){
				dirbuf[n] = 0;
				timeset = 1;
			}
			close(f);
		}
	}
	if(timeset == 0){
		/*
		 *  set the time from the access time of the root
		 */
		f = open("#s/boot", ORDWR);
		if(f < 0)
			return;
		if(mount(f, "/n/boot", MREPL, "", "") < 0){
			close(f);
			return;
		}
		close(f);
		if(stat("/n/boot", dirbuf) < 0)
			fatal("stat");
		convM2D(dirbuf, &dir);
		sprint(dirbuf, "%ld", dir.atime);
		unmount(0, "/n/boot");
		/*
		 *  set real time clock if there is one
		 */
		f = open("#r/rtc", ORDWR);
		if(f > 0){
			write(f, dirbuf, strlen(dirbuf));
			close(f);
		}
		close(f);
	}

	f = open("#c/time", OWRITE);
	write(f, dirbuf, strlen(dirbuf));
	close(f);
}

M boot/boot.h => boot/boot.h +44 -34
@@ 3,57 3,67 @@ struct Method
{
	char	*name;
	void	(*config)(Method*);
	void	(*auth)(Method*);
	void	(*connect)(Method*);
	int	(*auth)(void);
	int	(*connect)(void);
	char	*arg;
};

extern char	terminal[NAMELEN];
extern char	sys[2*NAMELEN];
extern char	password[NAMELEN];
extern char	username[NAMELEN];
extern char*	bootdisk;
extern int	(*cfs)(int);
extern int	cpuflag;
extern char	cputype[NAMELEN];
extern char	*bootdisk;
extern char	*initflag;
extern void	(*pword)(Method*);
extern int	fflag;
extern int	kflag;
extern Method	method[];
extern char	password[NAMELEN];
extern void	(*pword)(int, Method*);
extern char	sys[2*NAMELEN];
extern char	terminal[NAMELEN];
extern char	username[NAMELEN];

/* libc equivalent */
extern int	plumb(char*, char*, int*, char*);
extern int	outin(char*, char*, int);
extern int	sendmsg(int, char*);
extern void	warning(char*);
extern int	cache(int);
extern int	dkauth(void);
extern int	dkconnect(void);
extern void	fatal(char*);
extern void	getpasswd(char*, int);
extern void	key(int, Method*);
extern void	newkernel(void);
extern void	nop(int);
extern int	outin(char*, char*, int);
extern int	passtokey(char*, char*, int);
extern int	plumb(char*, char*, int*, char*);
extern int	readenv(char*, char*, int);
extern int	sendmsg(int, char*);
extern void	session(int);
extern void	setenv(char*, char*);
extern void	settime(int);
extern void	srvcreate(char*, int);
extern int	dkauth(void);
extern int	dkconnect(void);
extern void	userpasswd(int);
extern void	getpasswd(char*, int);
extern void	userpasswd(int, Method*);
extern void	warning(char*);

/* methods */
extern void	config9600(Method*);
extern int	auth9600(Method*);
extern int	connect9600(Method*);
extern void	config192000(Method*);
extern int	auth192000(Method*);
extern int	connect192000(Method*);
extern int	auth9600(void);
extern int	connect9600(void);
extern void	config19200(Method*);
extern int	auth19200(void);
extern int	connect19200(void);
extern void	confighs(Method*);
extern int	authhs(Method*);
extern int	connecths(Method*);
extern int	authhs(void);
extern int	connecths(void);
extern void	configincon(Method*);
extern int	authincon(Method*);
extern int	connectincon(Method*);
extern int	authincon(void);
extern int	connectincon(void);
extern void	configil(Method*);
extern int	authil(Method*);
extern int	connectil(Method*);
extern int	authil(void);
extern int	connectil(void);
extern void	configtcp(Method*);
extern int	authtcp(Method*);
extern int	connecttcp(Method*);
extern int	authtcp(void);
extern int	connecttcp(void);
extern void	configcyc(Method*);
extern int	authcyc(Method*);
extern int	connectcyc(Method*);
extern int	authcyc(void);
extern int	connectcyc(void);
extern void	configlocal(Method*);
extern int	authlocal(Method*);
extern int	connectlocal(Method*);
extern int	authlocal(void);
extern int	connectlocal(void);

M boot/getpasswd.c => boot/getpasswd.c +25 -0
@@ 2,6 2,31 @@
#include <libc.h>
#include <../boot/boot.h>

int
passtokey(char *key, char *p, int n)
{
	uchar t[10];
	int c;

	memset(t, ' ', sizeof t);
	if(n < 5)
		return 0;
	if(n > 10)
		n = 10;
	strncpy((char*)t, p, n);
	if(n >= 9){
		c = p[8] & 0xf;
		if(n == 10)
			c += p[9] << 4;
		for(n = 0; n < 8; n++)
			if(c & (1 << n))
				t[n] -= ' ';
	}
	for(n = 0; n < 7; n++)
		key[n] = (t[n] >> n) + (t[n+1] << (8 - (n+1)));
	return 1;
}

void
getpasswd(char *p, int len)
{

M boot/key.c => boot/key.c +4 -6
@@ 3,11 3,12 @@
#include <../boot/boot.h>

void
key(Method *mp)
key(int islocal, Method *mp)
{
	char password[20], key[7];
	int prompt, fd;

	USED(islocal);
	USED(mp);

	prompt = kflag;


@@ 18,16 19,13 @@ key(Method *mp)
	}
	if(prompt){
		do
			if(getpasswd(password, sizeof password) < 0){
				warning("can't read cons");
				return;
			}
			getpasswd(password, sizeof password);
		while(!passtokey(key, password, strlen(password)));
	}else if(seek(fd, 1024+900, 0) < 0 || read(fd, key, 7) != 7){
		close(fd);
		warning("can't read key from nvram");
	}
	if(kflag && seek(fd, 1024+900, 0) < 0 || write(fd, key, 7) != 7){
	if(kflag && (seek(fd, 1024+900, 0) < 0 || write(fd, key, 7) != 7)){
		close(fd);
		warning("can't write key to nvram");
	}

M boot/local.c => boot/local.c +1 -1
@@ 30,7 30,7 @@ connectlocal(void)

	if(stat("/kfs", d) < 0)
		return -1;
	sprint(partition, "%sfs", mp->arg ? mp->arg : bootdisk);
	sprint(partition, "%sfs", disk ? disk : bootdisk);
	if(stat(partition, d) < 0)
		return -1;


A boot/nopsession.c => boot/nopsession.c +56 -0
@@ 0,0 1,56 @@
#include <u.h>
#include <libc.h>
#include <fcall.h>
#include "../boot/boot.h"

static Fcall	hdr;
static char	buf[4*1024];

void
nop(int fd)
{
	long n;

	print("nop...");
	hdr.type = Tnop;
	hdr.tag = NOTAG;
	n = convS2M(&hdr, buf);
	if(write(fd, buf, n) != n)
		fatal("write nop");
	n = read(fd, buf, sizeof buf);
	if(n==2 && buf[0]=='O' && buf[1]=='K')
		n = read(fd, buf, sizeof buf);
	if(n <= 0)
		fatal("read nop");
	if(convM2S(buf, &hdr, n) == 0) {
		print("n = %d; buf = %#.2x %#.2x %#.2x %#.2x\n",
			n, buf[0], buf[1], buf[2], buf[3]);
		fatal("format nop");
	}
	if(hdr.type != Rnop)
		fatal("not Rnop");
}

void
session(int fd)
{
	long n;

	print("session...");
	hdr.type = Tsession;
	hdr.tag = NOTAG;
	n = convS2M(&hdr, buf);
	if(write(fd, buf, n) != n)
		fatal("write session");
	n = read(fd, buf, sizeof buf);
	if(n <= 0)
		fatal("read session");
	if(convM2S(buf, &hdr, n) == 0)
		fatal("format session");
	if(hdr.type == Rerror){
		print("error %s;", hdr.ename);
		fatal(hdr.ename);
	}
	if(hdr.type != Rsession)
		fatal("not Rsession");
}

A boot/settime.c => boot/settime.c +61 -0
@@ 0,0 1,61 @@
#include <u.h>
#include <libc.h>
#include <fcall.h>
#include "../boot/boot.h"

void
settime(int islocal)
{
	int n, f;
	int timeset;
	Dir dir;
	char dirbuf[DIRLEN];
	char *srvname;

	print("time...");
	timeset = 0;
	if(islocal){
		/*
		 *  set the time from the real time clock
		 */
		f = open("#r/rtc", ORDWR);
		if(f >= 0){
			if((n = read(f, dirbuf, sizeof(dirbuf)-1)) > 0){
				dirbuf[n] = 0;
				timeset = 1;
			}
			close(f);
		}
	}
	if(timeset == 0){
		/*
		 *  set the time from the access time of the root
		 */
		f = open("#s/boot", ORDWR);
		if(f < 0)
			return;
		if(mount(f, "/n/boot", MREPL, "", "") < 0){
			close(f);
			return;
		}
		close(f);
		if(stat("/n/boot", dirbuf) < 0)
			fatal("stat");
		convM2D(dirbuf, &dir);
		sprint(dirbuf, "%ld", dir.atime);
		unmount(0, "/n/boot");
		/*
		 *  set real time clock if there is one
		 */
		f = open("#r/rtc", ORDWR);
		if(f > 0){
			write(f, dirbuf, strlen(dirbuf));
			close(f);
		}
		close(f);
	}

	f = open("#c/time", OWRITE);
	write(f, dirbuf, strlen(dirbuf));
	close(f);
}

M boot/userpasswd.c => boot/userpasswd.c +2 -27
@@ 4,36 4,11 @@

char	password[NAMELEN];

static int
passtokey(char *key, char *p, int n)
{
	uchar t[10];
	int c;

	memset(t, ' ', sizeof t);
	if(n < 5)
		return 0;
	if(n > 10)
		n = 10;
	strncpy((char*)t, p, n);
	if(n >= 9){
		c = p[8] & 0xf;
		if(n == 10)
			c += p[9] << 4;
		for(n = 0; n < 8; n++)
			if(c & (1 << n))
				t[n] -= ' ';
	}
	for(n = 0; n < 7; n++)
		key[n] = (t[n] >> n) + (t[n+1] << (8 - (n+1)));
	return 1;
}

/*
 *  get/set user name and password.  verify password with auth server.
 */
void
userpasswd(Method *mp)
userpasswd(int islocal, Method *mp)
{
	char key[7];
	char buf[8 + NAMELEN];


@@ 44,7 19,7 @@ userpasswd(Method *mp)
		outin("user", username, sizeof(username));
	}
	crfd = fd = -1;
	while(strcmp(username, "none") != 0 && strcmp(mp->name, "local") != 0){
	while(strcmp(username, "none") != 0 && !islocal){
		getpasswd(password, sizeof password);
		if(!passtokey(key, password, strlen(password))){
			print("bad password; try again\n");

M gnot/fns.h => gnot/fns.h +2 -1
@@ 7,6 7,7 @@
#define	P_write(sel, addr, val, type)	P_oper(sel, *(type *)(PORT+addr) = val)

void	addportintr(int (*)(void));
void	bootargs(ulong);
void	clearmmucache(void);
void	duartclock(void);
void	duartinit(void);


@@ 58,7 59,7 @@ int	spl1(void);
void	spldone(void);
int	splduart(void);
int	tas(char*);
void	touser(void);
void	touser(void*);
#define	waserror()	(u->nerrlab++, setlabel(&u->errlab[u->nerrlab-1]))
#define	kmapperm(x)	kmap(x)
#define getcallerpc(x)	(*(ulong*)(x))

M gnot/l.s => gnot/l.s +4 -3
@@ 29,17 29,18 @@ dead:
	BRA	dead

/*
 * Take first processor into user mode.  Leave enough room on the stack
 * Take first processor into user mode.  Leave enough room on the kernel stack
 * for a full-sized Ureg (including long bus error format) to fit
 * 	- argument is stack pointer to user
 */

TEXT	touser(SB), $-4
TEXT	touser(SB), $0

	MOVL	usp+0(FP), A0
	MOVL	$(USERADDR+BY2PG-UREGVARSZ), A7
	MOVW	$0, -(A7)
	MOVL	$(UTZERO+32), -(A7)	/* header is in text */
	MOVW	$0, -(A7)
	MOVL	$(USTKTOP-6*BY2WD), A0	/* MAXSYSARG=6 */
	MOVL	A0, USP
	MOVW	$(SUPER|SPL(0)), SR
	MOVL	$8, R0

M gnot/main.c => gnot/main.c +76 -14
@@ 11,7 11,6 @@
#include	<gnot.h>

typedef struct Boot Boot;

struct Boot
{
	long station;


@@ 23,11 22,11 @@ struct Boot
};
#define BOOT ((Boot*)0)

char bootuser[NAMELEN];
char bootline[64];
char bootserver[64];
char bootdevice[2];
int bank[2];
char	bootuser[NAMELEN];
char	bootline[64];
char	bootserver[72];
int	bank[2];
uchar	*sp;

void unloadboot(void);



@@ 66,10 65,25 @@ main(void)
void
unloadboot(void)
{
	char s[64];

	strncpy(bootuser, BOOT->user, NAMELEN);
	memmove(bootline, BOOT->line, 64);
	memmove(bootserver, BOOT->server, 64);
	bootdevice[0] = BOOT->device;
	memmove(s, BOOT->server, 64);
	switch(BOOT->device){
	case 'a':
		sprint(bootserver, "19200!%s", s);
		break;
	case 'A':
		sprint(bootserver, "9600!%s", s);
		break;
	case 'i':
		sprint(bootserver, "incon!%s", s);
		break;
	default:
		sprint(bootserver, "scsi!%s", s);
		break;
	}
}

void


@@ 124,14 138,10 @@ init0(void)
	if(!waserror()){
		ksetterm("at&t %s");
		ksetenv("cputype", "68020");
		ksetenv("bootuser", bootuser);
		ksetenv("bootline", bootline);
		ksetenv("bootserver", bootserver);
		ksetenv("bootdevice", bootdevice);
		poperror();
	}

	touser();
	touser(sp);
}

FPsave	initfp;


@@ 143,6 153,7 @@ userinit(void)
	Segment *s;
	User *up;
	KMap *k;
	Page *pg;

	p = newproc();
	p->pgrp = newpgrp();


@@ 171,10 182,15 @@ userinit(void)
	kunmap(k);

	/*
	 * User Stack
	 * User Stack, copy in boot arguments
	 */
	s = newseg(SG_STACK, USTKTOP-BY2PG, 1);
	p->seg[SSEG] = s;
	pg = newpage(1, 0, USTKTOP-BY2PG);
	segpage(s, pg);
	k = kmap(pg);
	bootargs(VA(k));
	kunmap(k);

	/*
	 * Text


@@ 189,6 205,52 @@ userinit(void)
	ready(p);
}

uchar *
pusharg(char *p)
{
	int n;

	n = strlen(p)+1;
	sp -= n;
	memmove(sp, p, n);
	return sp;
}

void
bootargs(ulong base)
{
 	int i, ac;
	uchar *av[32];
	char *p, *pp;
	uchar **lsp;

	sp = (uchar*)base + BY2PG - MAXSYSARG*BY2WD;

	ac = 0;
	for(p = bootline; p && *p; p = pp){
		pp = strchr(p, ' ');
		if(pp)
			*pp++ = 0;
		av[ac++] = pusharg(p);
	}
	if(bootuser[0]){
		av[ac++] = pusharg("-u");
		av[ac++] = pusharg(bootuser);
	}
	av[ac++] = pusharg(bootserver);

	/* 4 byte word align stack */
	sp = (uchar*)((ulong)sp & ~3);

	/* build argc, argv on stack */
	sp -= (ac+1)*sizeof(sp);
	lsp = (uchar**)sp;
	for(i = 0; i < ac; i++)
		*lsp++ = av[i] + ((USTKTOP - BY2PG) - base);
	*lsp = 0;
	sp += (USTKTOP - BY2PG) - base - sizeof(sp);
}

void
exit(void)
{

M port/devcons.c => port/devcons.c +3 -3
@@ 379,7 379,7 @@ int
readnum(ulong off, char *buf, ulong n, ulong val, int size)
{
	char tmp[64];
	Op op = { tmp, tmp+sizeof(tmp), &val, size-1, 0, FUNSIGN|FLONG };
	Op op = (Op){ tmp, tmp+sizeof(tmp), &val, size-1, 0, FUNSIGN|FLONG };

	numbconv(&op, 10);
	tmp[size-1] = ' ';


@@ 597,12 597,12 @@ consread(Chan *c, void *buf, long n, ulong offset)
		if(offset != 0 || n != 8)
			error(Ebadarg);
		chal = u->p->pgrp->crypt->chal;
		chal[0] = 0;
		chal[0] = RXschal;
		for(i=1; i<8; i++)
			chal[i] = nrand(256);
		memmove(buf, chal, 8);
		encrypt(evekey, buf, 8);
		chal[0] = 1;
		chal[0] = RXstick;
		return n;

	case Quser:

M port/devip.c => port/devip.c +5 -7
@@ 11,8 11,8 @@

enum
{
	Nrprotocol	= 3,		/* Number of protocols supported by this driver */
	Nipsubdir	= 4,		/* Number of subdirectory entries per connection */
	Nrprotocol	= 3,	/* Number of protocols supported by this driver */
	Nipsubdir	= 4,	/* Number of subdirectory entries per connection */
};

int 	udpsum = 1;


@@ 38,7 38,7 @@ void	iloput(Queue *, Block *);
void	ilopen(Queue *, Stream *);
void	ilclose(Queue *);

Qinfo tcpinfo = { tcpstiput, tcpstoput, tcpstopen, tcpstclose, "tcp" };
Qinfo tcpinfo = { tcpstiput, tcpstoput, tcpstopen, tcpstclose, "tcp", 0, 1 };
Qinfo udpinfo = { udpstiput, udpstoput, udpstopen, udpstclose, "udp" };
Qinfo ilinfo  = { iliput,    iloput,    ilopen,    ilclose,    "il"  };



@@ 164,12 164,10 @@ ipincoming(Ipconv *base, Ipconv *from)
				qunlock(new);
				continue;
			}
			if(from)
				/* copy ownership from listening channel */
			if(from)	/* copy ownership from listening channel */
				netown(new->net, new->index,
				       new->net->prot[from->index].owner, 0);
			else
				/* current user becomes owner */
			else		/* current user becomes owner */
				netown(new->net, new->index, u->p->user, 0);

			new->ref = 1;

M port/devmnt.c => port/devmnt.c +59 -29
@@ 67,6 67,7 @@ void	mntdirfix(uchar*, Chan*);
void	mntgate(Mnt*);
void	mntrpcread(Mnt*, Mntrpc*);
void	mntdoclunk(Mnt *, Mntrpc *);
void	mntauth(Mnt *, Mntrpc *, char *, ushort);

enum
{


@@ 123,6 124,8 @@ Chan*
mntattach(char *muxattach)
{
	Mnt *m, *e;
	Stream *s;
	Qinfo *qi;
	struct bogus{
		Chan	*chan;
		char	*spec;


@@ 159,9 162,23 @@ mntattach(char *muxattach)
	m->c->flag |= CMSG;
	m->blocksize = MAXFDATA;

	/* If we have a stream based protocol (TCP/IP) we push fcall to block
	 * up P9 protocol messages into single deliminted blocks
	 */
	s = m->c->stream;
	qi = qinfofind("fcall");
	if(s)
	if(s->procq->next)
	if(s->procq->next->info->nodelim) {
		if(qi == 0)
			error(Ebadctl);
		pushq(s, qi);
	}

	switch(devchar[m->c->type]) {
	default:
		m->mux = 0;
		break;
	case 'H':			/* Cyclone */
		m->mux = 1;
		break;


@@ 177,8 194,6 @@ mattach(Mnt *m, char *spec, char *serv)
{
	Chan *c;
	Mntrpc *r;
	char chal[8];
	int i;

	r = mntralloc();
	c = devattach('M', spec);


@@ 193,31 208,10 @@ mattach(Mnt *m, char *spec, char *serv)
		nexterror();
	}

	if(*serv){
		r->request.type = Tauth;
		r->request.fid = c->fid;
		memmove(r->request.uname, u->p->user, NAMELEN);
		chal[0] = 1;
		for(i = 1; i < sizeof chal; i++)
			chal[i++] = nrand(256);
		memmove(r->request.chal, chal, 8);
		strncpy(r->request.chal+8, serv, NAMELEN);
		encrypt(u->p->pgrp->crypt->key, r->request.chal, 8+NAMELEN);
		if(waserror())
			memset(r->request.auth, 0, sizeof r->request.auth);
		else{
			mountrpc(m, r);
			poperror();
			decrypt(u->p->pgrp->crypt->key, r->reply.chal, 2*8+2*DESKEYLEN);
			chal[0] = 4;
			if(memcmp(chal, r->reply.chal, 8) != 0)
				error(Eperm);
			memmove(r->request.auth, r->reply.chal+8+DESKEYLEN, 8+DESKEYLEN);
		}
		r->done = 0;
		r->flushed = 0;
	}else
		memset(r->request.auth, 0, sizeof r->request.auth);
	memset(r->request.auth, 0, sizeof r->request.auth);
	if(*serv)
		mntauth(m, r, serv, c->fid);


	r->request.type = Tattach;
	r->request.fid = c->fid;


@@ 233,6 227,42 @@ mattach(Mnt *m, char *spec, char *serv)
	return c;
}

void
mntauth(Mnt *m, Mntrpc *f, char *serv, ushort fid)
{
	Mntrpc *r;
	uchar chal[CHLEN];
	int i;

	r = mntralloc();
	if(waserror()) {
		mntfree(r);
		return;
	}

	r->request.type = Tauth;
	r->request.fid = fid;
	memmove(r->request.uname, u->p->user, NAMELEN);
	chal[0] = FScchal;
	for(i = 1; i < CHLEN; i++)
		chal[i++] = nrand(256);

	memmove(r->request.chal, chal, CHLEN);
	strncpy(r->request.chal+CHLEN, serv, NAMELEN);
	encrypt(u->p->pgrp->crypt->key, r->request.chal, CHLEN+NAMELEN);

	mountrpc(m, r);
	decrypt(u->p->pgrp->crypt->key, r->reply.chal, 2*CHLEN+2*DESKEYLEN);
	chal[0] = FSctick;
	poperror();
	if(memcmp(chal, r->reply.chal, CHLEN) != 0) {
		mntfree(r);
		error(Eperm);
	}
	memmove(f->request.auth, r->reply.chal+CHLEN+DESKEYLEN, CHLEN+DESKEYLEN);
	mntfree(r);
}

Chan*
mntclone(Chan *c, Chan *nc)
{


@@ 790,8 820,8 @@ mntdump(void)
	for(m = mntalloc.mntarena; m < me; m++) {
		if(m->ref == 0)
			continue;
		print("mount %d: mux %d queue %lux rip 0x%lux %d %s\n", m->id, m->mux, m->queue,
			m->rip,
		print("mount %d: mux %d queue %lux rip 0x%lux %d %s\n", 
			m->id, m->mux, m->queue, m->rip,
			m->rip ? m->rip->pid : 0, m->rip ? m->rip->text : "no");
	}
	print("rpcfree 0x%lux\n", mntalloc.rpcfree);

M port/page.c => port/page.c +0 -1
@@ 195,7 195,6 @@ pageinit(void)
	ulong i, vmem, pmem, hw, hr;
	Page *p;

print("addr0 %lux addr1 %lux\n", palloc.addr0, palloc.addr1);
	/*
	 *  calculate an upper bound to the number of pages structures
	 *  we'll need (np).

M port/portdat.h => port/portdat.h +19 -5
@@ 156,8 156,8 @@ struct Chan
	Mount	*mnt;			/* mount point that derived Chan */
	ulong	mountid;
	int	fid;			/* for devmnt */
	Stream	*stream;		/* for stream channels */
	union {
		Stream	*stream;	/* for stream channels */
		void	*aux;
		Qid	pgrpid;		/* for #p/notepg */
		int	mntindex;	/* for devmnt */


@@ 579,6 579,7 @@ struct Qinfo
	void (*close)(Queue*);
	char *name;
	void (*reset)(void);		/* initialization */
	char nodelim;			/* True if stream does not preserve delimiters */
	Qinfo *next;
};



@@ 590,7 591,8 @@ struct Qinfo
#define QHIWAT	0x4			/* queue has gone past the high water mark */	
#define QDEBUG	0x8

struct Queue {
struct Queue
{
	Blist;
	int	flag;
	Qinfo	*info;			/* line discipline definition */


@@ 603,7 605,8 @@ struct Queue {
	void	*ptr;			/* private info for the queue */
};

struct Stream {
struct Stream
{
	QLock;				/* structure lock */
	short	inuse;			/* number of processes in stream */
	short	opens;			/* number of processes with stream open */


@@ 623,7 626,6 @@ struct Stream {
 */
#define	RD(q)		((q)->other < (q) ? (q->other) : q)
#define	WR(q)		((q)->other > (q) ? (q->other) : q)
#define GLOBAL(a)	(((ulong)(a)) & 0x80000000)
#define STREAMTYPE(x)	((x)&0x1f)
#define STREAMID(x)	(((x)&~CHDIR)>>5)
#define STREAMQID(i,t)	(((i)<<5)|(t))


@@ 684,7 686,7 @@ extern	FPsave	initfp;
extern	Conf	conf;
extern	ulong	initcode[];
extern	Dev	devtab[];
extern	char	devchar[];
extern	char	*devchar;
extern	char	*conffile;
extern	char	*statename[];
extern	Palloc 	palloc;


@@ 696,3 698,15 @@ extern	int	nrdy;
#define	CHDIR		0x80000000L
#define	CHAPPEND 	0x40000000L
#define	CHEXCL		0x20000000L

/*
 * auth messages
 */
#define CHLEN		8
enum{
	FScchal	= 1,
	FSctick,

	RXschal	= 0,
	RXstick	= 1,
};

M port/portfns.h => port/portfns.h +2 -0
@@ 143,6 143,7 @@ Segment*	newseg(int, ulong, ulong);
Waitq*	newwaitq(void);
char*	nextelem(char*, char*);
void	nexterror(void);
int	nodelims(Stream*);
int	notify(Ureg*);
int	nrand(int);
void	nullput(Queue*, Block*);


@@ 182,6 183,7 @@ void	putstr(char*);
void	putstrn(char*, long);
void	putswap(Page*);
ulong	pwait(Waitmsg*);
Qinfo*	qinfofind(char*);
void	qlock(QLock*);
void	qunlock(QLock*);
int	readnum(ulong, char*, ulong, ulong, int);

M port/stfcall.c => port/stfcall.c +106 -167
@@ 7,91 7,74 @@

#include	"fcall.h"

#define DPRINT 	if(fcalldebug)kprint

int fcalldebug = 0;

typedef struct Fcalld	Fcalld;

struct Fcalld{
	int	dev;		/* ref. for debug output */
	int	state;
	int	type;		/* of current message */
	int	need;		/* bytes remaining in current message */
	int	nhdr;		/* bytes of header treasured up in hdr */
	uchar	hdr[16];
};

enum {
	Startup, Startup1, Begin, Header, Data
enum
{
	Twritehdr	= 15,	/* Min bytes for Twrite */
	Rreadhdr	= 8,	/* Min bytes for Rread */
	Twritecnt	= 13,	/* Offset in byte stream of write count */
	Rreadcnt	= 5,	/* Offset for Readcnt */
};

/*
 *  fcall stream module definition
 */
static void fcalliput(Queue*, Block*);
static void fcalloput(Queue*, Block*);
static void fcallopen(Queue*, Stream*);
static void fcallclose(Queue*);
static void fcallreset(void);
Qinfo fcallinfo =
Qinfo fcallinfo = { fcalliput, fcalloput, fcallopen, fcallclose, "fcall", fcallreset };

static uchar msglen[256] =
{
	fcalliput,
	fcalloput,
	fcallopen,
	fcallclose,
	"fcall",
	fcallreset
	[Tnop]		3,
	[Rnop]		3,
	[Tsession]	3,
	[Rsession]	3,
	[Terror]	0,
	[Rerror]	67,
	[Tflush]	5,
	[Rflush]	3,
	[Tattach]	89,
	[Rattach]	13,
	[Tclone]	7,
	[Rclone]	5,
	[Twalk]		33,
	[Rwalk]		13,
	[Topen]		6,
	[Ropen]		13,
	[Tcreate]	38,
	[Rcreate]	13,
	[Tread]		15,
	[Rread]		8,
	[Twrite]	16,
	[Rwrite]	7,
	[Tclunk]	5,
	[Rclunk]	5,
	[Tremove]	5,
	[Rremove]	5,
	[Tstat]		5,
	[Rstat]		121,
	[Twstat]	121,
	[Rwstat]	5,
	[Tclwalk]	35,
	[Rclwalk]	13,
	[Tauth]		69,
	[Rauth]		35,
};

static Block *	putmsg(Queue*, Block*, int);

static uchar msglen[] = {
	  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
	  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
	  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
	  0,  0,  3,  3,  3,  3,  0, 67,  5,  3, 89, 13,  7,  5, 33, 13,
	  6, 13, 38, 13, 15,  8, 16,  7,  5,  5,  5,  5,  5,121,121,  5,
	 35, 13, 69, 35,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
	  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
	  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
	  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
	  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
	  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
	  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
	  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
	  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
	  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
	  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0
};
static void
fcallreset(void)
{}
{
}

static void
fcallopen(Queue *q, Stream *s)
{
	Fcalld *f;

	DPRINT("fcallopen %d\n", s->dev);

	q->ptr = allocb(sizeof(Fcalld));
	f = (Fcalld *)((Block *)q->ptr)->base;
	f->dev = s->dev;
	f->state = Startup;
	f->type = 0;
	f->need = 0;
	f->nhdr = 0;
	USED(q, s);
}

static void
fcallclose(Queue * q)
{
	Fcalld *f = (Fcalld *)((Block *)q->ptr)->base;

	DPRINT("fcallstclose %d\n", f->dev);
	freeb(q->ptr);
	q->ptr = 0;
	USED(q);
}

void


@@ 100,125 83,81 @@ fcalloput(Queue *q, Block *bp)
	PUTNEXT(q, bp);
}

void
upstream(Queue *q, ulong len)
{
	Block *bl, **tail, *bp;
	ulong l;

	tail = &bl;
	while(len) {
		l = BLEN(q->first);
		if(l > len)
			break;
		bp = getq(q);			/* Consume all of block */
		*tail = bp;
		tail = &bp->next;
		len -= l;
	}
	if(len) {				/* Consume partial block */
		lock(q);
		*tail = copyb(q->first, len);
		q->first->rptr += len;
		q->len -= len;
		unlock(q);
	}
	for(bp = bl; bp->next; bp = bp->next)
		;
	bp->flags |= S_DELIM;
	PUTNEXT(q, bl);
}

static void
fcalliput(Queue *q, Block *bp)
{
	Fcalld *f = (Fcalld *)((Block *)q->ptr)->base;
	int len, n;
	ulong len, need, off;

	len = BLEN(bp);
	DPRINT("fcalliput %d: blen=%d\n", f->dev, len);
	if(bp->type != M_DATA){
		DPRINT("fcalliput %d: type=%d\n", f->dev, bp->type);
	if(bp->type != M_DATA) {
		PUTNEXT(q, bp);
		return;
	}
	bp->flags &= ~S_DELIM;
	if(len == 0){
	if(BLEN(bp) == 0) {
		freeb(bp);
		return;
	}
	while(len > 0)switch(f->state){
	case Startup:
		if (len == 1 && bp->rptr[0] == 'O'){
			DPRINT("fcalliput %d: O\n", f->dev);
			PUTNEXT(q, bp);
			f->state = Startup1;
			return;
		}
		if(bp->rptr[0] == 'O' && bp->rptr[1] == 'K'){
			DPRINT("fcalliput %d: OK\n", f->dev);
			bp = putmsg(q, bp, 2);
			len -= 2;
		}
		f->state = Begin;
		break;

	case Startup1:
		if(bp->rptr[0] == 'K'){
			DPRINT("fcalliput %d: K\n", f->dev);
			bp = putmsg(q, bp, 1);
			len -= 1;
			f->state = Begin;
			break;
		}
		f->type = 'O';
		f->need = msglen['O']-1;
		f->state = Data;
		DPRINT("fcalliput %d: type=%d, need=%d\n",
			f->dev, f->type, f->need);
		break;
	/* Stash the data */
	bp->flags &= ~S_DELIM;
	putq(q, bp);

	case Begin:
		f->type = bp->rptr[0];
		f->need = msglen[f->type];
		f->nhdr = 0;
		if(f->type == Twrite || f->type == Rread)
			f->state = Header;
		else
			f->state = Data;
		DPRINT("fcalliput %d: type=%d, need=%d\n",
			f->dev, f->type, f->need);
		break;
	bp = q->first;
	switch(bp->rptr[0]) {		/* This is the type */
	default:
		len = msglen[bp->rptr[0]];
		if(len == 0)
			error(Emountrpc);
		if(q->len >= len)
			upstream(q, len);

	case Header:
		n = f->need;
		if(n > len)
			n = len;
		memmove(&f->hdr[f->nhdr], bp->rptr, n);
		f->nhdr += n;
		DPRINT("fcalliput %d: nhdr=%d\n",
			f->dev, f->nhdr);
		if(n == f->need){
			f->need += f->hdr[f->nhdr-3];
			f->need += f->hdr[f->nhdr-2] << 8;
			f->state = Data;
			DPRINT("fcalliput %d: need=%d\n",
				f->dev, f->need);
		}
		/* fall through */

	case Data:
		if(f->need > len){
			f->need -= len;
			PUTNEXT(q, bp);
			return;
		}
		bp = putmsg(q, bp, f->need);
		len -= f->need;
		f->state = Begin;
		return;
	case Twrite:			/* Fmt: TGGFFOOOOOOOOCC */
		len = Twritehdr;	/* T = type, G = tag, F = fid */
		off = Twritecnt;	/* O = offset, C = count */
		break;
	case Rread:			/* Fmt: TGGFFCC */
		len = Rreadhdr;
		off = Rreadcnt;
		break;
	}
}

static Block *
putmsg(Queue *q, Block *bp, int n)
{
	Block *xbp;
	int k;
	if(q->len < len)
		return;

	DPRINT("putmsg: n=%d\n\n", n);
	k = BLEN(bp) - n;
	if(k == 0){
		bp->flags |= S_DELIM;
		PUTNEXT(q, bp);
		return 0;
	}
	if(n <= k){
		xbp = allocb(n);
		memmove(xbp->wptr, bp->rptr, n);
		xbp->wptr += n;
		bp->rptr += n;
		xbp->flags |= S_DELIM;
		PUTNEXT(q, xbp);
		return bp;
	}
	xbp = allocb(k);
	memmove(xbp->wptr, bp->rptr+n, k);
	xbp->wptr += k;
	bp->wptr -= k;
	bp->flags |= S_DELIM;
	PUTNEXT(q, bp);
	return xbp;
	pullup(q->first, len);
	bp = q->first;
	need = len+bp->rptr[off]+(bp->rptr[off+1]<<8);
	if(q->len < need)
		return;

	upstream(q, need);
}

M port/stream.c => port/stream.c +45 -3
@@ 708,17 708,17 @@ nullput(Queue *q, Block *bp)
/*
 *  find the info structure for line discipline 'name'
 */
static Qinfo *
Qinfo *
qinfofind(char *name)
{
	Qinfo *qi;

	if(name == 0)
		error(Ebadld);
		return 0;
	for(qi = lds; qi; qi = qi->next)
		if(strcmp(qi->name, name)==0)
			return qi;
	error(Ebadld);
	return 0;
}

/*


@@ 1260,6 1260,8 @@ streamctlwrite(Chan *c, void *a, long n)
		freeb(bp);
	} else if(streamparse("push", bp)){
		qi = qinfofind((char *)bp->rptr);
		if(qi == 0)
			error(Ebadld);
		pushq(s, qi);
		freeb(bp);
	} else if(streamparse("pop", bp)){


@@ 1415,6 1417,46 @@ streamstat(Chan *c, char *db, char *name)
	convD2M(&dir, db);
}

Block *
copyb(Block *bp, int count)
{
	Block *nb, *head, **p;
	int l;

	p = &head;
	while(count) {
		l = BLEN(bp);
		if(count < l)
			l = count;
		nb = allocb(l);
		if(nb == 0)
			panic("copyb.1");
		memmove(nb->wptr, bp->rptr, l);
		nb->wptr += l;
		count -= l;
		if(bp->flags & S_DELIM)
			nb->flags |= S_DELIM;
		*p = nb;
		p = &nb->next;
		bp = bp->next;
		if(bp == 0)
			break;
	}
	if(count) {
		nb = allocb(count);
		if(nb == 0)
			panic("copyb.2");
		memset(nb->wptr, 0, count);
		nb->wptr += count;
		nb->flags |= S_DELIM;
		*p = nb;
	}
	if(blen(head) == 0)
		print("copyb: zero length\n");

	return head;
}

/*
 *  Dump all block information of how many blocks are in which queues
 */

M port/tcpinput.c => port/tcpinput.c +0 -40
@@ 748,46 748,6 @@ dupb(Block **hp, Block *bp, int offset, int count)
	return bytes;
}

Block *
copyb(Block *bp, int count)
{
	Block *nb, *head, **p;
	int l;

	p = &head;
	while(count) {
		l = BLEN(bp);
		if(count < l)
			l = count;
		nb = allocb(l);
		if(nb == 0)
			panic("copyb.1");
		memmove(nb->wptr, bp->rptr, l);
		nb->wptr += l;
		count -= l;
		if(bp->flags & S_DELIM)
			nb->flags |= S_DELIM;
		*p = nb;
		p = &nb->next;
		bp = bp->next;
		if(bp == 0)
			break;
	}
	if(count) {
		nb = allocb(count);
		if(nb == 0)
			panic("copyb.2");
		memset(nb->wptr, 0, count);
		nb->wptr += count;
		nb->flags |= S_DELIM;
		*p = nb;
	}
	if(blen(head) == 0)
		print("copyb: zero length\n");

	return head;
}

ushort tcp_mss = DEF_MSS;	/* Maximum segment size to be sent with SYN */
int tcp_irtt = DEF_RTT;		/* Initial guess at round trip time */


M power/boot.c => power/boot.c +1 -1
@@ 396,7 396,7 @@ key(void)
		close(fd);
		prerror("can't read key from nvram");
	}
	if(setkey && seek(fd, 1024+900, 0) < 0 || write(fd, key, 7) != 7){
	if(setkey && (seek(fd, 1024+900, 0) < 0 || write(fd, key, 7) != 7)){
		close(fd);
		prerror("can't write key to nvram");
	}

M power/l.s => power/l.s +1 -1
@@ 63,7 63,7 @@ clrbss:

TEXT	touser(SB), $-4

	MOVW	R1, SP
	MOVW	R1, SP			/* user stack pointer */
	MOVW	M(STATUS), R1
	OR	$(KUP|IEP), R1
	MOVW	R1, M(STATUS)