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;