~kris/9p

9hist

15408a804093865b265e2d13b5fafbea23a63194 — David du Colombier 24 years ago 191b674
Plan 9 from Bell Labs 2002-08-01
6 files changed, 108 insertions(+), 38 deletions(-)

M boot/boot.h
A boot/embed.c
D boot/rc.c
M ip/tcp.c
M port/chan.c
M port/portdat.h
M boot/boot.h => boot/boot.h +2 -2
@@ 67,8 67,8 @@ extern int	connectsac(void);
extern void	configpaq(Method*);
extern int	connectpaq(void);

extern void	configrc(Method*);
extern int	connectrc(void);
extern void	configembed(Method*);
extern int	connectembed(void);

/* hack for passing authentication address */
extern char	*authaddr;

A boot/embed.c => boot/embed.c +74 -0
@@ 0,0 1,74 @@
#include <u.h>
#include <libc.h>
#include <../boot/boot.h>

static char *paqfile;

void
configembed(Method *m)
{
	if(*sys == '/' || *sys == '#'){
		/*
		 *  if the user specifies the disk in the boot cmd or
		 * 'root is from' prompt, use it
		 */
		paqfile = sys;
	} else if(m->arg){
		/*
		 *  a default is supplied when the kernel is made
		 */
		paqfile = m->arg;
	}
}

int
connectembed(void)
{
	int i, p[2];
	Dir *dir;
	char **arg, **argp;

	dir = dirstat("/paqfs");
	if(dir == nil)
		return -1;
	free(dir);

	dir = dirstat(paqfile);
	if(dir == nil || dir->mode & DMDIR)
		return -1;
	free(dir);

	print("paqfs...");
	if(bind("#c", "/dev", MREPL) < 0)
		fatal("bind #c");
	if(bind("#p", "/proc", MREPL) < 0)
		fatal("bind #p");
	if(pipe(p)<0)
		fatal("pipe");
	switch(fork()){
	case -1:
		fatal("fork");
	case 0:
		arg = malloc((bargc+5)*sizeof(char*));
		argp = arg;
		*argp++ = "/paqfs";
		*argp++ = "-iv";
		*argp++ = paqfile;
		for(i=1; i<bargc; i++)
			*argp++ = bargv[i];
		*argp = 0;

		dup(p[0], 0);
		dup(p[1], 1);
		close(p[0]);
		close(p[1]);
		exec("/paqfs", arg);
		fatal("can't exec paqfs");
	default:
		break;
	}
	waitpid();

	close(p[1]);
	return p[0];
}

D boot/rc.c => boot/rc.c +0 -24
@@ 1,24 0,0 @@
#include <u.h>
#include <libc.h>
#include <../boot/boot.h>

/* minimal rc main */
char rcmain[] = "home=/\n"
		"ifs=' \t\n'\n"
		"prompt=('% ' '\t')\n"
		"path=/\n";
		
void
configrc(Method *)
{
	setenv("rcmain", rcmain);
	execl("/rc", "/rc", "-m", "#e/rcmain", "-i", 0);
	fatal("rc");
}

int
connectrc(void)
{
	// does not get here
	return -1;
}

M ip/tcp.c => ip/tcp.c +23 -11
@@ 50,6 50,7 @@ enum
	DEF_KAT		= 30000,	/* Default time ms) between keep alives */
	TCP_LISTEN	= 0,		/* Listen connection */
	TCP_CONNECT	= 1,		/* Outgoing connection */
	SYNACK_RXTIMER	= 250,		/* ms between SYNACK retransmits */

	TCPREXMTTHRESH  = 3,            /* dupack threshhold for rxt */



@@ 248,7 249,7 @@ struct Tcpctl
 *  New calls are put in limbo rather than having a conversation structure
 *  allocated.  Thus, a SYN attack results in lots of limbo'd calls but not
 *  any real Conv structures mucking things up.  Calls in limbo rexmit their
 *  SYN ACK every 250 ms up to 4 times, i.e., they disappear after 1 second.
 *  SYN ACK every SYNACK_RXTIMER ms up to 4 times, i.e., they disappear after 1 second.
 *
 *  In particular they aren't on a listener's queue so that they don't figure
 *  in the input queue limit.


@@ 342,6 343,17 @@ struct Tcppriv
	ulong	stats[Nstats];
};

/* 
 *  Setting tcpporthogdefense to non-zero enables Dong Lin's
 *  solution to hijacked systems staking out port's as a form
 *  of DoS attack.
 *
 *  To avoid stateless Conv hogs, we pick a sequence number at random.  If
 *  it that number gets acked by the other end, we shut down the connection.
 *  Look for tcpporthogedefense in the code.
 */
int tcpporthogdefense = 0;

int	addreseq(Tcpctl*, Tcp*, Block*, ushort);
void	getreseq(Tcpctl*, Tcp*, Block**, ushort*);
void	localclose(Conv*, char*);


@@ 1374,7 1386,7 @@ limbo(Conv *s, uchar *source, uchar *dest, Tcp *seg, int version)
}

/*
 *  resend SYN ACK's once every 250 ms.
 *  resend SYN ACK's once every SYNACK_RXTIMER ms.
 */
static void
limborexmit(Proto *tcp)


@@ 1395,11 1407,11 @@ limborexmit(Proto *tcp)
		for(l = &tpriv->lht[h]; *l != nil && seen < tpriv->nlimbo; ){
			lp = *l;
			seen++;
			if(now - lp->lastsend < 250)
			if(now - lp->lastsend < (lp->rexmits+1)*SYNACK_RXTIMER)
				continue;

			/* time it out after 1 second */
			if(++(lp->rexmits) > 4){
			if(++(lp->rexmits) > 5){
				tpriv->nlimbo--;
				*l = lp->next;
				free(lp);


@@ 1540,7 1552,7 @@ tcpincoming(Conv *s, Tcp *segp, uchar *src, uchar *dst, uchar version)
	tcb->cwind = tcb->mss;

	/* set initial round trip time */
	tcb->sndsyntime = lp->lastsend;
	tcb->sndsyntime = lp->lastsend+lp->rexmits*SYNACK_RXTIMER;
	tcpsynackrtt(new);

	free(lp);


@@ 1998,7 2010,8 @@ reset:
	 *  corresponding code in tcpsendka().
	 */
	if(tcb->state != Syn_received && (seg.flags & RST) == 0){
		if(seq_within(seg.ack, tcb->snd.una-(1<<31), tcb->snd.una-(1<<29))){
		if(tcpporthogdefense
		&& seq_within(seg.ack, tcb->snd.una-(1<<31), tcb->snd.una-(1<<29))){
			print("stateless hog %I.%d->%I.%d f %ux %lux - %lux - %lux\n",
				source, seg.source, dest, seg.dest, seg.flags,
				tcb->snd.una-(1<<31), seg.ack, tcb->snd.una-(1<<29));


@@ 2462,10 2475,6 @@ tcpoutput(Conv *s)

/*
 *  the BSD convention (hack?) for keep alives.  resend last uchar acked.
 *
 *  To avoid stateless Conv hogs, we pick a sequence number at random.  If
 *  it that number gets acked by the other end, we shut down the connection.
 *  See the equivalent code in tcpiput().
 */
void
tcpsendka(Conv *s)


@@ 2482,7 2491,10 @@ tcpsendka(Conv *s)
	seg.dest = s->rport;
	seg.flags = ACK|PSH;
	seg.mss = 0;
	seg.seq = tcb->snd.una-(1<<30)-nrand(1<<20);
	if(tcpporthogdefense)
		seg.seq = tcb->snd.una-(1<<30)-nrand(1<<20);
	else
		seg.seq = tcb->snd.una-1;
	seg.ack = tcb->rcv.nxt;
	tcb->rcv.lastacked = tcb->rcv.nxt;
	seg.wnd = tcb->rcv.wnd;

M port/chan.c => port/chan.c +8 -0
@@ 769,6 769,10 @@ walk(Chan **cp, char **names, int nnames, int nomount, int *nerror)
			cnameclose(cname);
			cclose(c);
			strcpy(up->errstr, Enotdir);
			if(mh != nil)
{print("walk 1\n");
				putmhead(mh);
}
			return -1;
		}
		ntry = nnames - nhave;


@@ 813,6 817,8 @@ walk(Chan **cp, char **names, int nnames, int nomount, int *nerror)
				cnameclose(cname);
				if(nerror)
					*nerror = nhave+1;
				if(mh != nil)
					putmhead(mh);
				return -1;
			}
		}


@@ 845,6 851,8 @@ walk(Chan **cp, char **names, int nnames, int nomount, int *nerror)
						strcpy(up->errstr, Enotdir);
					}
					free(wq);
					if(mh != nil)
						putmhead(mh);
					return -1;
				}
				n = wq->nqid;

M port/portdat.h => port/portdat.h +1 -1
@@ 556,7 556,7 @@ struct Schedq
struct Proc
{
	Label	sched;		/* known to l.s */
	char	*kstack;	/* known to l.s */
	char	*kstack;			/* known to l.s */
	Mach	*mach;		/* machine running this proc */
	char	*text;
	char	*user;