M ip/arp.c => ip/arp.c +8 -6
@@ 124,12 124,14 @@ arpget(Arp *arp, Block *bp, int version, Medium *type, uchar *ip, uchar *mac)
}
a->used = msec;
if(a->state == AWAIT){
- if(a->hold)
- a->last->list = bp;
- else
- a->hold = bp;
- a->last = bp;
- bp->list = nil;
+ if(bp != nil){
+ if(a->hold)
+ a->last->list = bp;
+ else
+ a->hold = bp;
+ a->last = bp;
+ bp->list = nil;
+ }
return a; /* return with arp qlocked */
}
M ip/ethermedium.c => ip/ethermedium.c +55 -20
@@ 24,29 24,24 @@ static void etheraddmulti(Ipifc *ifc, uchar *a, uchar *ia);
static void etherremmulti(Ipifc *ifc, uchar *a, uchar *ia);
static Block* multicastarp(Fs *f, Arpent *a, uchar *mac);
static void sendarp(Ipifc *ifc, Arpent *a);
+static void sendgarp(Ipifc *ifc, uchar*);
static int multicastea(uchar *ea, uchar *ip);
static void recvarpproc(void*);
Medium ethermedium =
{
- "ether",
- 14,
- 60,
- 1514,
- 6,
- etherbind,
- etherunbind,
- etherbwrite,
- etheraddmulti,
- etherremmulti,
- nil, /* pktin */
- nil, /* addroute */
- nil, /* remroute */
- nil, /* flushroute */
- nil, /* joinmulti */
- nil, /* leavemulti */
- arpenter, /* ares */
- 0, /* don't unbind on last close */
+.name= "ether",
+.hsize= 14,
+.minmtu= 60,
+.maxmtu= 1514,
+.maclen= 6,
+.bind= etherbind,
+.unbind= etherunbind,
+.bwrite= etherbwrite,
+.addmulti= etheraddmulti,
+.remmulti= etherremmulti,
+.ares= arpenter,
+.areg= sendgarp,
};
typedef struct Etherrock Etherrock;
@@ 373,6 368,46 @@ sendarp(Ipifc *ifc, Arpent *a)
print("arp: send: %r\n");
}
+/*
+ * send a gratuitous arp to refresh arp caches
+ */
+static void
+sendgarp(Ipifc *ifc, uchar *ip)
+{
+ int n;
+ Block *bp;
+ Etherarp *e;
+ Etherrock *er = ifc->arg;
+
+ /* don't arp for our initial non address */
+ if(ipcmp(ip, IPnoaddr) == 0)
+ return;
+
+ n = sizeof(Etherarp);
+ if(n < ethermedium.minmtu)
+ n = ethermedium.minmtu;
+ bp = allocb(n);
+ memset(bp->rp, 0, n);
+ e = (Etherarp*)bp->rp;
+ memmove(e->tpa, ip+IPv4off, sizeof(e->tpa));
+ memmove(e->spa, ip+IPv4off, sizeof(e->spa));
+ memmove(e->sha, ifc->mac, sizeof(e->sha));
+ memset(e->d, 0xff, sizeof(e->d)); /* ethernet broadcast */
+ memmove(e->s, ifc->mac, sizeof(e->s));
+
+ hnputs(e->type, ETARP);
+ hnputs(e->hrd, 1);
+ hnputs(e->pro, ETIP);
+ e->hln = sizeof(e->sha);
+ e->pln = sizeof(e->spa);
+ hnputs(e->op, ARPREQUEST);
+ bp->wp += n;
+
+ n = devtab[er->achan->type]->bwrite(er->achan, bp, 0);
+ if(n < 0)
+ print("garp: send: %r\n");
+}
+
static void
recvarp(Ipifc *ifc)
{
@@ 404,7 439,7 @@ recvarp(Ipifc *ifc)
/* check for someone that think's they're me */
v4tov6(ip, e->spa);
- if(iplocalonifc(ifc, ip)){
+ if(iplocalonifc(ifc, ip) || ipproxyifc(er->f, ifc, ip)){
if(memcmp(e->sha, ifc->mac, sizeof(e->sha)) != 0)
print("arp: 0x%E also has ip addr %V\n", e->sha, e->spa);
} else {
@@ 420,7 455,7 @@ recvarp(Ipifc *ifc)
/* answer only requests for our address or systems we're proxying for */
v4tov6(ip, e->tpa);
if(!iplocalonifc(ifc, ip))
- if(ipproxyifc(er->f, ifc, ip) == 0)
+ if(!ipproxyifc(er->f, ifc, ip))
break;
/* print("arp: rem %I %E (for %I)\n", e->spa, e->sha, e->tpa); /**/
M ip/ip.h => ip/ip.h +3 -1
@@ 126,7 126,9 @@ struct Medium
void (*joinmulti)(Ipifc *ifc, uchar *a, uchar *ia);
void (*leavemulti)(Ipifc *ifc, uchar *a, uchar *ia);
- void (*ares)(Fs*, int, uchar*, uchar*, int, int);
+ /* address resolution */
+ void (*ares)(Fs*, int, uchar*, uchar*, int, int); /* resolve */
+ void (*areg)(Ipifc*, uchar*); /* register */
int unbindonclose; /* if non-zero, unbind on last close */
};
M ip/ipifc.c => ip/ipifc.c +35 -1
@@ 66,6 66,7 @@ static void addselfcache(Fs *f, Ipifc *ifc, Iplifc *lifc, uchar *a, int type);
static void remselfcache(Fs *f, Ipifc *ifc, Iplifc *lifc, uchar *a);
static char* ipifcjoinmulti(Ipifc *ifc, char **argv, int argc);
static char* ipifcleavemulti(Ipifc *ifc, char **argv, int argc);
+static void ipifcregisterproxy(Fs*, Ipifc*, uchar*);
/*
* link in a new medium
@@ 409,8 410,10 @@ ipifcadd(Ipifc *ifc, char **argv, int argc)
addselfcache(f, ifc, lifc, ip, Runi);
- if(type & Rptpt)
+ if(type & Rptpt){
+ ipifcregisterproxy(f, ifc, rem);
goto out;
+ }
/* add subnet directed broadcast addresses to the self cache */
for(i = 0; i < IPaddrlen; i++)
@@ 436,6 439,10 @@ ipifcadd(Ipifc *ifc, char **argv, int argc)
addselfcache(f, ifc, lifc, IPv4bcast, Rbcast);
+ /* register the address on this network for address resolution */
+ if(ifc->m->areg != nil)
+ (*ifc->m->areg)(ifc, ip);
+
out:
wunlock(ifc);
return nil;
@@ 1231,3 1238,30 @@ ipifcleavemulti(Ipifc *ifc, char **argv, int argc)
return nil;
}
+static void
+ipifcregisterproxy(Fs *f, Ipifc *ifc, uchar *ip)
+{
+ Conv **cp, **e;
+ Ipifc *nifc;
+ Iplifc *lifc;
+ uchar net[IPaddrlen];
+
+ /* register the address on any network that will proxy for us */
+ e = &f->ipifc->conv[f->ipifc->nc];
+ for(cp = f->ipifc->conv; cp < e; cp++){
+ if(*cp == nil)
+ continue;
+ nifc = (Ipifc*)(*cp)->ptcl;
+ if(nifc->m->areg == nil)
+ continue;
+ if(nifc == ifc)
+ continue;
+ for(lifc = nifc->lifc; lifc; lifc = lifc->next){
+ maskip(ip, lifc->mask, net);
+ if(ipcmp(net, lifc->remote) == 0){
+ (*nifc->m->areg)(nifc, ip);
+ break;
+ }
+ }
+ }
+}
M ip/netlog.c => ip/netlog.c +2 -7
@@ 132,15 132,10 @@ netlogread(Fs *f, void *a, ulong, long n)
f->alog->len -= n;
unlock(f->alog);
- i = n;
+ i = n-d;
p = a;
- if(d){
- memmove(p, rptr, d);
- i -= d;
- p += d;
- rptr = f->alog->buf;
- }
memmove(p, rptr, i);
+ memmove(p+i, f->alog->buf, d);
break;
}
else
M ip/nullmedium.c => ip/nullmedium.c +4 -17
@@ 27,23 27,10 @@ nullbwrite(Ipifc*, Block*, int, uchar*)
Medium nullmedium =
{
- "null",
- 0, /* medium header size */
- 0, /* default min mtu */
- 0, /* default max mtu */
- 0, /* mac address length */
- nullbind,
- nullunbind,
- nullbwrite,
- nil, /* addmulti */
- nil, /* remmulti */
- nil, /* pktin */
- nil, /* addroute */
- nil, /* remroute */
- nil, /* flushroute */
- nil, /* joinmulti */
- nil, /* leave multi */
- 0, /* don't unbind on last close */
+.name= "null",
+.bind= nullbind,
+.unbind= nullunbind,
+.bwrite= nullbwrite,
};
void
M ip/pktmedium.c => ip/pktmedium.c +10 -18
@@ 16,24 16,16 @@ static void pktin(Fs*, Ipifc *ifc, Block *bp);
Medium pktmedium =
{
- "pkt",
- 14,
- 40,
- 4*1024,
- 6,
- pktbind,
- pktunbind,
- pktbwrite,
- nil, /* addmulti */
- nil, /* remmulti */
- pktin,
- nil, /* addroute */
- nil, /* remroute */
- nil, /* flushroute */
- nil, /* joinmulti */
- nil, /* leave multi */
- nil, /* ares */
- 1, /* unbind on last close */
+.name= "pkt",
+.hsize= 14,
+.minmtu= 40,
+.maxmtu= 4*1024,
+.maclen= 6,
+.bind= pktbind,
+.unbind= pktunbind,
+.bwrite= pktbwrite,
+.pktin= pktin,
+.unbindonclose= 1,
};
/*
M ip/tripmedium.c => ip/tripmedium.c +12 -22
@@ 21,28 21,18 @@ static void tripares(Fs*, int, uchar*, uchar*, int, int);
Medium tripmedium =
{
- "trip",
- 0, /* Header size */
-
- 20, /* Min TU */
- 64*1024, /* Max TU */
-
- LCIMACSIZE, /* Maximum MAC address length */
-
- tripbind,
- tripunbind,
- tripbwrite,
- tripaddmulti,
- tripremmulti,
- nil, /* pktin */
- tripaddroute,
- tripremroute,
- nil, /* flushroutes */
- nil, /* joinmulti */
- nil, /* leavemulti */
- tripares, /* address cache enter */
-
- 0
+.name= "trip",
+.minmtu= 20,
+.maxmtu= 64*1024,
+.maclen= LCIMACSIZE,
+.bind= tripbind,
+.unbind= tripunbind,
+.bwrite= tripbwrite,
+.addmulti= tripaddmulti,
+.remmulti= tripremmulti,
+.addroute= tripaddroute,
+.remroute= tripremroute,
+.ares= tripares,
};
typedef struct Tripinfo Tripinfo;
M port/devbridge.c => port/devbridge.c +6 -7
@@ 266,7 266,7 @@ bridgeread(Chan *c, void *a, long n, vlong off)
char buf[256];
Bridge *b = bridgetab + c->dev;
Port *port;
- int i;
+ int i, ingood, outgood;
USED(off);
switch(TYPE(c->qid)) {
@@ 294,9 294,11 @@ bridgeread(Chan *c, void *a, long n, vlong off)
i += snprint(buf+i, sizeof(buf)-i, "tunnel %I: ", port->addr);
break;
}
- i += snprint(buf+i, sizeof(buf)-i, "in=%d/%d/%d out=%d/%d/%d\n",
- port->in, port->inmulti, port->inunknown,
- port->out, port->outmulti, port->outunknown);
+ ingood = port->in-port->inmulti-port->inunknown;
+ outgood = port->out-port->outmulti-port->outunknown;
+ i += snprint(buf+i, sizeof(buf)-i, "in=%d(%d:%d:%d) out=%d(%d:%d:%d)\n",
+ port->in, ingood, port->inmulti, port->inunknown,
+ port->out, outgood, port->outmulti, port->outunknown);
USED(i);
}
n = readstr(off, a, n, buf);
@@ 317,7 319,6 @@ bridgewrite(Chan *c, void *a, long n, vlong off)
char *p;
USED(off);
-
switch(TYPE(c->qid)) {
default:
error(Eperm);
@@ 482,7 483,6 @@ portbind(Bridge *b, int argc, char *argv[])
portfree(port);
nexterror();
}
-
port->type = type;
memmove(port->addr, addr, Addrlen);
switch(port->type) {
@@ 822,7 822,6 @@ etherread(void *a)
if(waserror()) {
if(bp)
freeb(bp);
-print("devbridge: etherread: %r\n");
continue;
}
if(blocklen(bp) < ETHERMINTU)
M port/devroot.c => port/devroot.c +32 -45
@@ 7,37 7,21 @@
enum{
Qdir= 0,
- Qbin,
- Qdev,
- Qenv,
- Qproc,
- Qnet,
- Qnetalt,
Qrecover,
- Qroot, /* boot root */
- // add new entries above this
- Qboot, /* readable files */
-
- Nfiles=13, /* max root files */
+ Nfiles=32, /* max root files */
};
extern ulong bootlen;
extern uchar bootcode[];
-Dirtab rootdir[Nfiles]={
- "bin", {Qbin|CHDIR}, 0, 0777,
- "dev", {Qdev|CHDIR}, 0, 0777,
- "env", {Qenv|CHDIR}, 0, 0777,
- "proc", {Qproc|CHDIR}, 0, 0777,
- "net", {Qnet|CHDIR}, 0, 0777,
- "net.alt", {Qnetalt|CHDIR}, 0, 0777,
+Dirtab rootdir[Nfiles]=
+{
"recover", {Qrecover}, 0, 0777,
- "root", {Qroot|CHDIR}, 0, 0777,
};
static uchar *rootdata[Nfiles];
-static int nroot = Qboot - 1;
+static int nroot = 1;
static int recovbusy;
typedef struct Recover Recover;
@@ 59,45 43,55 @@ struct
/*
* add a root file
*/
-void
-addrootfile(char *name, uchar *contents, ulong len)
+static void
+addroot(char *name, uchar *contents, ulong len, int perm)
{
Dirtab *d;
-
if(nroot >= Nfiles)
panic("too many root files");
rootdata[nroot] = contents;
d = &rootdir[nroot];
strcpy(d->name, name);
d->length = len;
- d->perm = 0555;
+ d->perm = perm;
d->qid.path = nroot+1;
+ if(perm & CHDIR)
+ d->qid.path |= CHDIR;
nroot++;
}
/*
* add a root file
*/
+void
+addrootfile(char *name, uchar *contents, ulong len)
+{
+ addroot(name, contents, len, 0555);
+}
+
+/*
+ * add a root file
+ */
static void
addrootdir(char *name)
{
- Dirtab *d;
-
- if(nroot >= Nfiles)
- panic("too many root files");
- rootdata[nroot] = nil;
- d = &rootdir[nroot];
- strcpy(d->name, name);
- d->length = 0;
- d->perm = 0;
- d->qid.path = nroot+1;
- nroot++;
+ addroot(name, nil, 0, CHDIR);
}
static void
rootreset(void)
{
+ addrootdir("bin");
+ addrootdir("dev");
+ addrootdir("env");
+ addrootdir("proc");
+ addrootdir("net");
+ addrootdir("net.alt");
+ addrootdir("root");
+ addrootdir("srv");
+ addrootdir("xsrv");
+
addrootfile("boot", bootcode, bootlen); /* always have a boot file */
}
@@ 203,9 197,6 @@ rootread(Chan *c, void *buf, long n, vlong off)
return n;
}
- if(t < Qboot)
- return 0;
-
d = &rootdir[t-1];
data = rootdata[t-1];
if(offset >= d->length)
@@ 239,16 230,12 @@ rootwrite(Chan *c, void *buf, long n, vlong)
static void
rootcreate(Chan *c, char *name, int mode, ulong perm)
{
- if(!iseve())
- error(Eperm);
- if(c->qid.path != (CHDIR|Qdir))
- error(Eperm);
- perm &= 0777|CHDIR;
- if((perm & CHDIR) == 0)
+ if(!iseve() || c->qid.path != (CHDIR|Qdir) ||
+ (perm & CHDIR) == 0 || mode != OREAD)
error(Eperm);
addrootdir(name);
c->flag |= COPEN;
- c->mode = mode & ~OWRITE;
+ c->mode = OREAD;
}
Dev rootdevtab = {
M port/log.c => port/log.c +2 -7
@@ 82,15 82,10 @@ logread(Log *alog, void *a, ulong, long n)
alog->len -= n;
unlock(alog);
- i = n;
+ i = n-d;
p = a;
- if(d){
- memmove(p, rptr, d);
- i -= d;
- p += d;
- rptr = alog->buf;
- }
memmove(p, rptr, i);
+ memmove(p+i, alog->buf, d);
break;
}
else
M port/portdat.h => port/portdat.h +1 -1
@@ 735,7 735,7 @@ struct Logflag {
struct Cmdbuf
{
- char buf[64];
+ char buf[256];
char *f[16];
int nf;
};