M gnot/lib.h => gnot/lib.h +1 -0
@@ 30,6 30,7 @@ extern int atoi(char*);
extern int runetochar(char*, Rune*);
extern int chartorune(Rune*, char*);
extern int countrune(char*);
+extern char* utfrune(char*, long);
/*
* print routines
M port/arp.h => port/arp.h +3 -0
@@ 1,3 1,6 @@
+/*
+ * this file used by (at least) the kernel, arpd, snoopy, tboot
+ */
typedef struct Arppkt Arppkt;
typedef struct Arpentry Arpentry;
typedef struct Arpstats Arpstats;
M port/chan.c => port/chan.c +12 -15
@@ 669,28 669,25 @@ nameok(char *elem)
char*
nextelem(char *name, char *elem)
{
- int i, user, c;
+ int i, user, w;
char *end, *e;
+ Rune r;
if(*name == '/')
error(Efilename);
- end = memchr(name, 0, NAMELEN);
- if(end == 0){
- end = memchr(name, '/', NAMELEN);
- if(end == 0)
- error(Efilename);
- }else{
- e = memchr(name, '/', end-name);
- if(e)
- end = e;
- }
+ end = utfrune(name, '/');
+ if(end == 0)
+ end = strchr(name, 0);
+ w = end-name;
+ if(w >= NAMELEN)
+ error(Efilename);
+ memmove(elem, name, w);
+ elem[w] = 0;
while(name < end){
- c = *(uchar*)name++;
- if(isfrog[c])
+ name += chartorune(&r, name);
+ if(r<sizeof(isfrog) && isfrog[r])
error(Ebadchar);
- *elem++ = c;
}
- *elem = 0;
return skipslash(name);
}
M port/devarp.c => port/devarp.c +44 -8
@@ 53,18 53,42 @@ char *padstr = " ";
enum{
arpdirqid,
+ arpdir2qid,
arpstatqid,
arpctlqid,
arpdataqid,
};
Dirtab arptab[]={
- "stats", {arpstatqid}, 0, 0666,
- "ctl", {arpctlqid}, 0, 0666,
- "data", {arpdataqid}, 0, 0666,
+ "stats", {arpstatqid}, 0, 0444,
+ "ctl", {arpctlqid}, 0, 0664,
+ "data", {arpdataqid}, 0, 0664,
};
#define Narptab (sizeof(arptab)/sizeof(Dirtab))
+/*
+ * create a 2-level directory
+ */
+int
+arpgen(Chan *c, void *vp, int ntab, int i, Dir *dp)
+{
+ Qid q;
+
+ q.vers = 0;
+
+ /* top level directory contains the directory arp */
+ if(c->qid.path == CHDIR){
+ if(i)
+ return -1;
+ q.path = CHDIR | arpdir2qid;
+ devdir(c, q, "arp", 0, eve, 0555, dp);
+ return 1;
+ }
+
+ /* next level uses table */
+ return devgen(c, arptab, Narptab, i, dp);
+}
+
void
arpreset(void)
{
@@ 109,13 133,13 @@ arpclone(Chan *c, Chan *nc)
int
arpwalk(Chan *c, char *name)
{
- return devwalk(c, name, arptab, (long)Narptab, devgen);
+ return devwalk(c, name, 0, 0, arpgen);
}
void
arpstat(Chan *c, char *db)
{
- devstat(c, db, arptab, (long)Narptab, devgen);
+ devstat(c, db, 0, 0, arpgen);
}
Chan *
@@ 182,7 206,7 @@ arpread(Chan *c, void *a, long n, ulong offset)
switch((int)(c->qid.path&~CHDIR)){
case arpdirqid:
- return devdirread(c, a, n, arptab, Narptab, devgen);
+ return devdirread(c, a, n, 0, 0, arpgen);
case arpdataqid:
bytes = c->offset;
while(bytes < conf.arp*ARP_ENTRYLEN && n) {
@@ 283,6 307,8 @@ arpoput(Queue *q, Block *bp)
{
uchar ip[4];
Etherhdr *eh;
+ Ipaddr addr;
+ static int dropped;
if(bp->type != M_DATA) {
if(Servq == 0 && streamparse("arpd", bp)) {
@@ 295,7 321,8 @@ arpoput(Queue *q, Block *bp)
}
if(!Servq) {
- print("arp: No server, packet dropped\n");
+ if((dropped++ % 1000) == 0)
+ print("arp: No server, packet dropped\n");
freeb(bp);
return;
}
@@ 308,12 335,20 @@ arpoput(Queue *q, Block *bp)
iproute(eh->dst, ip);
- /* Send downstream to the ethernet */
+ /* if a known ip addr, send downstream to the ethernet */
if(arplookup(ip, eh->d)) {
PUTNEXT(q, bp);
return;
}
+ /* if ip broadcast, use ether bcast address */
+ addr = nhgetl(eh->dst);
+ if(addr == Myip[Mybcast] || addr == Myip[Mynet] || addr == Myip[Mysubnet]){
+ memset(eh->d, 0xff, sizeof(eh->d));
+ PUTNEXT(q, bp);
+ return;
+ }
+
/* Push the packet up to the arp server for address resolution */
memmove(eh->d, ip, sizeof(ip));
PUTNEXT(Servq, bp);
@@ 443,6 478,7 @@ arplinkhead(Arpcache *ap)
ap->frwd = arplruhead;
ap->prev = 0;
+
arplruhead = ap;
}
}
M port/devcons.c => port/devcons.c +2 -0
@@ 850,6 850,8 @@ conswrite(Chan *c, void *va, long n, ulong offset)
break;
case Qswap:
+ if(conf.cntrlp && strcmp(u->p->user, eve) != 0)
+ error(Eperm);
if(n >= sizeof buf)
error(Egreg);
memmove(buf, va, n); /* so we can NUL-terminate */
M port/devip.c => port/devip.c +2 -2
@@ 433,7 433,7 @@ udpstoput(Queue *q, Block *bp)
uh->frag[1] = 0;
hnputs(uh->udpplen, ptcllen);
hnputl(uh->udpdst, ipc->dst);
- hnputl(uh->udpsrc, Myip);
+ hnputl(uh->udpsrc, Myip[Myself]);
hnputs(uh->udpsport, ipc->psrc);
hnputs(uh->udpdport, ipc->pdst);
hnputs(uh->udplen, ptcllen);
@@ 583,7 583,7 @@ iplocalfill(Chan *c, char *buf, int len)
connection = STREAMID(c->qid.path);
cp = &ipconv[c->dev][connection];
- sprint(buf, "%d.%d.%d.%d %d\n", fmtaddr(Myip), cp->psrc);
+ sprint(buf, "%d.%d.%d.%d %d\n", fmtaddr(Myip[Myself]), cp->psrc);
}
void
M port/deviproute.c => port/deviproute.c +1 -1
@@ 58,7 58,7 @@ iproute(uchar *dst, uchar *gate)
ulong udst;
udst = nhgetl(dst);
- if((udst&Mymask) == (Myip&Mymask)){
+ if((udst&Mymask) == (Myip[Myself]&Mymask)){
memmove(gate, dst, 4);
return;
}
M port/devroot.c => port/devroot.c +2 -0
@@ 12,6 12,7 @@ enum{
Qdev,
Qenv,
Qproc,
+ Qnet,
Qboot,
Qcfs,
@@ 31,6 32,7 @@ Dirtab rootdir[]={
"dev", {Qdev|CHDIR}, 0, 0777,
"env", {Qenv|CHDIR}, 0, 0777,
"proc", {Qproc|CHDIR}, 0, 0777,
+ "net", {Qnet|CHDIR}, 0, 0777,
};
#define NROOT (sizeof rootdir/sizeof(Dirtab))
Dirtab rootpdir[]={
M port/ipdat.h => port/ipdat.h +9 -1
@@ 503,7 503,7 @@ int ipforme(uchar*);
#define WORKBUF 64
-extern Ipaddr Myip;
+extern Ipaddr Myip[4];
extern Ipaddr Mymask;
extern Ipaddr classmask[4];
extern Ipconv *ipconv[];
@@ 516,3 516,11 @@ extern Qinfo udpinfo;
extern Qinfo ilinfo;
extern Qinfo arpinfo;
extern Queue *Ipoutput;
+
+/* offsets into Myip */
+enum {
+ Myself= 0,
+ Mybcast= 1,
+ Mynet= 3,
+ Mysubnet= 5,
+};
M port/lib.h => port/lib.h +1 -0
@@ 30,6 30,7 @@ extern int atoi(char*);
extern int runetochar(char*, Rune*);
extern int chartorune(Rune*, char*);
extern int countrune(char*);
+extern char* utfrune(char*, long);
/*
* print routines
M port/stil.c => port/stil.c +2 -2
@@ 154,7 154,7 @@ iloput(Queue *q, Block *bp)
/* Ip fields */
ih->frag[0] = 0;
ih->frag[1] = 0;
- hnputl(ih->src, Myip);
+ hnputl(ih->src, Myip[Myself]);
hnputl(ih->dst, ipc->dst);
ih->proto = IP_ILPROTO;
/* Il fields */
@@ 633,7 633,7 @@ ilsendctl(Ipconv *ipc, Ilhdr *inih, int type, ulong id, ulong ack)
/* Ip fields */
ih->proto = IP_ILPROTO;
- hnputl(ih->src, Myip);
+ hnputl(ih->src, Myip[Myself]);
hnputs(ih->illen, IL_HDRSIZE);
ih->frag[0] = 0;
ih->frag[1] = 0;
M port/stip.c => port/stip.c +33 -25
@@ 26,17 26,19 @@ QLock fraglock;
Queue *Etherq;
-Ipaddr Myip;
+Ipaddr Myip[4];
Ipaddr Mymask;
Ipaddr Mynetmask;
uchar Netmyip[4]; /* In Network byte order */
uchar bcast[4] = { 0xff, 0xff, 0xff, 0xff };
+Ipaddr Me[7]; /* possible addresses for me */
/* Predeclaration */
static void ipetherclose(Queue*);
static void ipetheriput(Queue*, Block*);
static void ipetheropen(Queue*, Stream*);
static void ipetheroput(Queue*, Block*);
+static void ipsetaddrs(void);
/*
* the ethernet multiplexor stream module definition
@@ 79,6 81,7 @@ ipetheropen(Queue *q, Stream *s)
Etherq = WR(q);
s->opens++; /* Hold this queue in place */
s->inuse++;
+ ipsetaddrs();
} else {
ipc = &ipconv[s->dev][s->id];
RD(q)->ptr = (void *)ipc;
@@ 179,18 182,20 @@ ipetheroput(Queue *q, Block *bp)
if(strncmp(eve, u->p->user, sizeof(eve)) != 0)
error(Eperm);
ptr = bp->rptr;
- Myip = ipparse((char *)ptr);
- Netmyip[0] = (Myip>>24)&0xff;
- Netmyip[1] = (Myip>>16)&0xff;
- Netmyip[2] = (Myip>>8)&0xff;
- Netmyip[3] = Myip&0xff;
- Mymask = classmask[Myip>>30];
+ Myip[Myself] = ipparse((char *)ptr);
+ Netmyip[0] = (Myip[Myself]>>24)&0xff;
+ Netmyip[1] = (Myip[Myself]>>16)&0xff;
+ Netmyip[2] = (Myip[Myself]>>8)&0xff;
+ Netmyip[3] = Myip[Myself]&0xff;
+ Mymask = classmask[Myip[Myself]>>30];
while(*ptr != ' ' && *ptr)
ptr++;
if(*ptr)
- Mymask = ipparse((char *)ptr);
- Mynetmask = Mymask;
+ Mynetmask = ipparse((char *)ptr);
+ else
+ Mynetmask = Mymask;
freeb(bp);
+ ipsetaddrs();
}
else
PUTNEXT(Etherq, bp);
@@ 353,34 358,37 @@ drop:
freeb(bp);
}
+void
+ipsetaddrs(void)
+{
+ Myip[1] = ~0; /* local broadcast */
+ Myip[2] = 0; /* local broadcast - old */
+ Myip[Mysubnet] = Myip[Myself] | ~Mynetmask; /* subnet broadcast */
+ Myip[Mysubnet+1] = Myip[Myself] & Mynetmask; /* subnet broadcast - old */
+ Myip[Mynet] = Myip[Myself] | ~Mymask; /* net broadcast */
+ Myip[Mynet+1] = Myip[Myself] & Mymask; /* net broadcast - old */
+}
+
int
ipforme(uchar *addr)
{
Ipaddr haddr;
-
- if(memcmp(addr, Netmyip, sizeof(Netmyip)) == 0)
- return 1;
+ Ipaddr *p;
haddr = nhgetl(addr);
- /* My subnet broadcast */
- if((haddr&Mymask) == (Myip&Mymask))
- return 1;
-
- /* My network broadcast */
- if((haddr&Mynetmask) == (Myip&Mynetmask))
- return 1;
+ /* try my address plus all the forms of ip broadcast */
+ for(p = Myip; p < &Myip[7]; p++)
+ if(haddr == *p);
+ return 1;
- /* Real ip broadcast */
- if(haddr == 0)
- return 1;
-
- /* Old style 255.255.255.255 address */
- if(haddr == ~0)
+ /* if we haven't set an address yet, accept anything we get */
+ if(Myip[Myself] == 0)
return 1;
return 0;
}
+
Block *
ip_reassemble(int offset, Block *bp, Etherhdr *ip)
{
M port/tcpoutput.c => port/tcpoutput.c +1 -1
@@ 129,7 129,7 @@ tcp_output(Ipconv *s)
/* Fill in fields of pseudo IP header */
hnputl(ph.tcpdst, s->dst);
- hnputl(ph.tcpsrc, Myip);
+ hnputl(ph.tcpsrc, Myip[Myself]);
hnputs(ph.tcpsport, s->psrc);
hnputs(ph.tcpdport, s->pdst);