## diffname ip/ipifc.c 1998/0306
## diff -e /dev/null /n/emeliedump/1998/0306/sys/src/brazil/ip/ipifc.c
0a
#include "u.h"
#include "../port/lib.h"
#include "mem.h"
#include "dat.h"
#include "fns.h"
#include "../port/error.h"
#include "ip.h"
#define DPRINT if(0)print
enum {
Maxmedia = 16,
Nself = Maxmedia*5,
NHASH = (1<<6),
NCACHE = 256,
QMAX = 64*1024-1,
};
Proto ipifc;
extern Fs fs;
Medium *media[] =
{
ðermedium,
&nullmedium,
0
};
/*
* cache of local addresses (addresses we answer to)
*/
typedef struct Ipself Ipself;
struct Ipself
{
uchar a[IPaddrlen];
Ipself *hnext; /* next address in the hash table */
Iplink *link; /* binding twixt Ipself and Ipifc */
ulong expire;
uchar type; /* type of address */
int ref;
Ipself *next; /* free list */
};
typedef struct Ipselftab Ipselftab;
struct Ipselftab
{
QLock;
int inited;
int acceptall; /* true if an interface has the null address */
Ipself *hash[NHASH]; /* hash chains */
};
Ipselftab selftab;
/*
* Multicast addresses are chained onto a Chan so that
* we can remove them when the Chan is closed.
*/
typedef struct Ipmcast Ipmcast;
struct Ipmcast
{
Ipmcast *next;
uchar ma[IPaddrlen]; /* multicast address */
uchar ia[IPaddrlen]; /* interface address */
};
/* quick hash for ip addresses */
#define hashipa(a) ( ( ((a)[IPaddrlen-2]<<8) | (a)[IPaddrlen-1] )%NHASH )
static char tifc[] = "ifc ";
static void addselfcache(Ipifc *ifc, Iplifc *lifc, uchar *a, int type);
static void remselfcache(Ipifc *ifc, Iplifc *lifc, uchar *a);
static char* ipifcjoinmulti(Ipifc *ifc, char **argv, int argc);
static char* ipifcleavemulti(Ipifc *ifc, char **argv, int argc);
/*
* find the medium with this name
*/
Medium*
ipfindmedium(char *name)
{
Medium **mp;
for(mp = media; *mp != nil; mp++)
if(strcmp((*mp)->name, name) == 0)
break;
return *mp;
}
/*
* attach a device (or pkt driver) to the interface.
* called with c->car locked
*/
static char*
ipifcbind(Conv *c, char **argv, int argc)
{
Ipifc *ifc;
Medium *m;
if(argc < 2)
return Ebadarg;
ifc = (Ipifc*)c->ptcl;
/* bind the device to the interface */
m = ipfindmedium(argv[1]);
if(m == nil)
return "unknown interface type";
wlock(ifc);
if(ifc->m != nil){
wunlock(ifc);
return "interface already bound";
}
if(waserror()){
wunlock(ifc);
nexterror();
}
(*m->bind)(ifc, argc, argv);
if(argc > 2)
strncpy(ifc->dev, argv[2], sizeof(ifc->dev));
else
sprint(ifc->dev, "%s%d", m->name, c->x);
ifc->dev[sizeof(ifc->dev)-1] = 0;
ifc->m = m;
ifc->minmtu = ifc->m->minmtu;
ifc->maxmtu = ifc->m->maxmtu;
ifc->ifcid++;
wunlock(ifc);
poperror();
return nil;
}
/*
* detach a device from an interface, close the interface
*/
static char*
ipifcunbind(Ipifc *ifc)
{
char *av[4];
char ip[32];
char mask[32];
if(waserror()){
wunlock(ifc);
nexterror();
}
wlock(ifc);
if(ipifcgrab(ifc) == 0);
goto out;
/* hangup queues to stop queuing of packets */
qhangup(ifc->conv->rq, "unbind");
qhangup(ifc->conv->wq, "unbind");
/* dissociate routes */
ifc->ifcid++;
/* disassociate logical interfaces */
av[0] = "remove";
av[1] = ip;
av[2] = mask;
av[3] = 0;
while(ifc->lifc){
sprint(ip, "%I", ifc->lifc->local);
sprint(mask, "%M", ifc->lifc->mask);
ipifcrem(ifc, av, 3, 0);
}
/* disassociate device */
(*ifc->m->unbind)(ifc);
memset(ifc->dev, 0, sizeof(ifc->dev));
ifc->arg = nil;
ifc->m = &nullmedium;
ifc->unbinding = 0;
out:
wunlock(ifc);
poperror();
return nil;
}
static int
ipifcstate(Conv *c, char *state, int n)
{
Ipifc *ifc;
Iplifc *lifc;
int m;
ifc = (Ipifc*)c->ptcl;
m = snprint(state, n, "%-12.12s %-5d", ifc->dev, ifc->maxmtu);
rlock(ifc);
for(lifc = ifc->lifc; lifc; lifc = lifc->next)
m += snprint(state+m, n - m,
" %-20.20I %-20.20M %-20.20I %-7d %-7d %-7d %-7d",
lifc->local, lifc->mask, lifc->remote,
ifc->in, ifc->out, ifc->inerr, ifc->outerr);
m += snprint(state+m, n - m, "\n");
runlock(ifc);
return m;
}
static int
ipifclocal(Conv *c, char *state, int n)
{
Ipifc *ifc;
Iplifc *lifc;
Iplink *link;
int m;
ifc = (Ipifc*)c->ptcl;
m = 0;
rlock(ifc);
for(lifc = ifc->lifc; lifc; lifc = lifc->next){
m += snprint(state+m, n - m, "%-20.20I ->", lifc->local);
for(link = lifc->link; link; link = link->lifclink)
m += snprint(state+m, n - m, " %-20.20I", link->local->a);
m += snprint(state+m, n - m, "\n");
}
runlock(ifc);
return m;
}
static int
ipifcinuse(Conv *c)
{
Ipifc *ifc;
ifc = (Ipifc*)c->ptcl;
return ifc->m != nil;
}
/*
* called when a process writes to an interface's 'data'
*/
static void
ipifckick(Conv *c, int)
{
Block *bp;
Ipifc *ifc;
bp = qget(c->wq);
if(bp == nil)
return;
ifc = (Ipifc*)c->ptcl;
if(ifc->m == nil || ifc->m->pktin == nil)
freeb(bp);
else
(*ifc->m->pktin)(ifc, bp);
}
/*
* we'll have to have a kick routine at
* some point to deal with these
*/
static void
ipifccreate(Conv *c)
{
Ipifc *ifc;
c->rq = qopen(QMAX, 0, 0, 0);
c->wq = qopen(QMAX, 0, 0, 0);
ifc = (Ipifc*)c->ptcl;
ifc->conv = c;
}
/*
* called after last close of ipifc data or ctl
* called with c locked, we must unlock
*/
static void
ipifcclose(Conv *c)
{
/*
* nothing to do since conversation stays open
* till the device is unbound.
*/
unlock(c);
}
/*
* add an address to an interface.
*/
char*
ipifcadd(Ipifc *ifc, char **argv, int argc)
{
uchar ip[IPaddrlen], mask[IPaddrlen], rem[IPaddrlen];
uchar bcast[IPaddrlen], net[IPaddrlen];
Iplifc *lifc, **l;
int i, type, mtu;
memset(ip, 0, IPaddrlen);
memset(mask, 0, IPaddrlen);
memset(rem, 0, IPaddrlen);
switch(argc){
case 5:
mtu = strtoul(argv[4], 0, 0);
if(mtu >= ifc->m->minmtu && mtu <= ifc->m->maxmtu)
ifc->maxmtu = mtu;
/* fall through */
case 4:
parseip(ip, argv[1]);
parseipmask(mask, argv[2]);
parseip(rem, argv[3]);
maskip(rem, mask, net);
break;
case 3:
parseip(ip, argv[1]);
parseipmask(mask, argv[2]);
maskip(ip, mask, rem);
maskip(rem, mask, net);
break;
case 2:
parseip(ip, argv[1]);
memmove(mask, defmask(ip), IPaddrlen);
maskip(ip, mask, rem);
maskip(rem, mask, net);
break;
default:
return Ebadarg;
break;
}
if(waserror()){
wunlock(ifc);
panic("ipifcadd");
}
wlock(ifc);
/* ignore if this is already a local address for this ifc */
for(lifc = ifc->lifc; lifc; lifc = lifc->next)
if(ipcmp(lifc->local, ip) == 0)
goto out;
/* add the address to the list of logical ifc's for this ifc */
lifc = smalloc(sizeof(Iplifc));
ipmove(lifc->local, ip);
ipmove(lifc->mask, mask);
ipmove(lifc->remote, rem);
ipmove(lifc->net, net);
lifc->next = nil;
for(l = &ifc->lifc; *l; l = &(*l)->next)
;
*l = lifc;
/* add a route for the local network */
type = Rifc;
if(ipcmp(mask, IPallbits) == 0)
type |= Rptpt;
if(isv4(ip))
v4addroute(tifc, rem+IPv4off, mask+IPv4off, ip+IPv4off, type);
else
v6addroute(tifc, ip, mask, rem, type);
addselfcache(ifc, lifc, ip, Runi);
/* add subnet directed broadcast addresses to the self cache */
for(i = 0; i < IPaddrlen; i++)
bcast[i] = (ip[i] & mask[i]) | ~mask[i];
addselfcache(ifc, lifc, bcast, Rbcast);
/* add network directed broadcast addresses to the self cache */
memmove(mask, defmask(ip), IPaddrlen);
for(i = 0; i < IPaddrlen; i++)
bcast[i] = (ip[i] & mask[i]) | ~mask[i];
addselfcache(ifc, lifc, bcast, Rbcast);
addselfcache(ifc, lifc, IPv4bcast, Rbcast);
out:
wunlock(ifc);
poperror();
return nil;
}
/*
* remove an address from an interface.
* called with c->car locked
*/
char*
ipifcrem(Ipifc *ifc, char **argv, int argc, int dolock)
{
uchar ip[IPaddrlen];
uchar mask[IPaddrlen];
Iplifc *lifc, **l;
if(argc < 3)
return Ebadarg;
parseip(ip, argv[1]);
parseipmask(mask, argv[2]);
if(dolock){
if(waserror()){
wunlock(ifc);
nexterror();
}
wlock(ifc);
}
/* find address on this interface and remove from chain */
lifc = nil;
for(l = &ifc->lifc; *l; l = &(*l)->next)
if(memcmp(ip, (*l)->local, IPaddrlen) == 0)
if(memcmp(mask, (*l)->mask, IPaddrlen) == 0){
lifc = *l;
*l = lifc->next;
break;
}
if(lifc == nil)
return "address not on this interface";
/* disassociate any addresses */
while(lifc->link)
remselfcache(ifc, lifc, lifc->link->local->a);
/* remove the route for this logical interface */
if(isv4(ip))
v4delroute(lifc->remote+IPv4off, lifc->mask+IPv4off);
else
v6delroute(lifc->remote, lifc->mask);
free(lifc);
out:
if(dolock){
wunlock(ifc);
poperror();
}
return nil;
}
/*
* distrbute routes to active interfaces like the
* TRIP linecards
*/
void
ipifcaddroute(int vers, uchar *addr, uchar *mask, uchar *gate, int type)
{
Medium *m;
Conv **cp;
Ipifc *ifc;
for(cp = ipifc.conv; cp < &ipifc.conv[ipifc.nc]; cp++){
if(*cp != nil) {
ifc = (Ipifc*)(*cp)->ptcl;
m = ifc->m;
if(m->addroute != nil)
m->addroute(ifc, vers, addr, mask, gate, type);
}
}
}
void
ipifcremroute(int vers, uchar *addr, uchar *mask)
{
Medium *m;
Conv **cp;
Ipifc *ifc;
for(cp = ipifc.conv; cp < &ipifc.conv[ipifc.nc]; cp++){
if(*cp != nil) {
ifc = (Ipifc*)(*cp)->ptcl;
m = ifc->m;
if(m->remroute != nil)
m->remroute(ifc, vers, addr, mask);
}
}
}
/*
* associate an address with the interface. This wipes out any previous
* addresses. This is a macro that means, remove all the old interfaces
* and add a new one.
*/
static char*
ipifcconnect(Conv* c, char **argv, int argc)
{
char *err;
Ipifc *ifc;
char *av[4];
char ip[80], mask[80];
ifc = (Ipifc*)c->ptcl;
if(ifc->m == nil)
return "ipifc not yet bound to device";
av[0] = "remove";
av[1] = ip;
av[2] = mask;
av[3] = 0;
if(waserror()){
wunlock(ifc);
nexterror();
}
wlock(ifc);
while(ifc->lifc){
sprint(ip, "%I", ifc->lifc->local);
sprint(mask, "%I", ifc->lifc->mask);
ipifcrem(ifc, av, 3, 0);
}
wunlock(ifc);
poperror();
err = ipifcadd(ifc, argv, argc);
if(err)
return err;
Fsconnected(&fs, c, nil);
return nil;
}
/*
* non-standard control messages.
* called with c->car locked.
*/
static char*
ipifcctl(Conv* c, char**argv, int argc)
{
Ipifc *ifc;
ifc = (Ipifc*)c->ptcl;
if(strcmp(argv[0], "add") == 0)
return ipifcadd(ifc, argv, argc);
else if(strcmp(argv[0], "remove") == 0)
return ipifcrem(ifc, argv, argc, 1);
else if(strcmp(argv[0], "unbind") == 0)
return ipifcunbind(ifc);
else if(strcmp(argv[0], "joinmulti") == 0)
return ipifcjoinmulti(ifc, argv, argc);
else if(strcmp(argv[0], "leavemulti") == 0)
return ipifcleavemulti(ifc, argv, argc);
return "unsupported ctl";
}
void
ipifcinit(Fs *fs)
{
ipifc.name = "ipifc";
ipifc.kick = ipifckick;
ipifc.connect = ipifcconnect;
ipifc.announce = nil;
ipifc.bind = ipifcbind;
ipifc.state = ipifcstate;
ipifc.create = ipifccreate;
ipifc.close = ipifcclose;
ipifc.rcv = nil;
ipifc.ctl = ipifcctl;
ipifc.advise = nil;
ipifc.stats = ipstats;
ipifc.inuse = ipifcinuse;
ipifc.local = ipifclocal;
ipifc.ipproto = -1;
ipifc.nc = Maxmedia;
ipifc.ptclsize = sizeof(Ipifc);
Fsproto(fs, &ipifc);
}
/*
* add to self routing cache
* called with c->car locked
*/
static void
addselfcache(Ipifc *ifc, Iplifc *lifc, uchar *a, int type)
{
Ipself *p;
Iplink *lp;
int h;
qlock(&selftab);
/* see if the address already exists */
h = hashipa(a);
for(p = selftab.hash[h]; p; p = p->next)
if(memcmp(a, p->a, IPaddrlen) == 0)
break;
/* allocate a local address and add to hash chain */
if(p == nil){
p = smalloc(sizeof(*p));
ipmove(p->a, a);
p->type = type;
p->next = selftab.hash[h];
selftab.hash[h] = p;
/* if the null address, accept all packets */
if(ipcmp(a, v4prefix) == 0 || ipcmp(a, IPnoaddr) == 0)
selftab.acceptall = 1;
}
/* look for a link for this lifc */
for(lp = p->link; lp; lp = lp->locallink)
if(lp->lifc == lifc)
break;
/* allocate a lifc-to-local link and link to both */
if(lp == nil){
lp = smalloc(sizeof(*lp));
lp->ref = 1;
lp->lifc = lifc;
lp->local = p;
lp->locallink = p->link;
p->link = lp;
lp->lifclink = lifc->link;
lifc->link = lp;
/* add to routing table */
if(isv4(a))
v4addroute(tifc, a+IPv4off, IPallbits+IPv4off, a+IPv4off, type);
else
v6addroute(tifc, a, IPallbits, a, type);
if((type & Rmulti) && ifc->m->addmulti != nil)
(*ifc->m->addmulti)(ifc, a, lifc->local);
} else {
lp->ref++;
}
qunlock(&selftab);
}
/*
* These structures are unlinked from their chains while
* other threads may be using them. To avoid excessive locking,
* just put them aside for a while before freeing them.
* called with &selftab locked
*/
static Iplink *freeiplink;
static Ipself *freeipself;
static void
iplinkfree(Iplink *p)
{
Iplink **l, *np;
ulong now = msec;
l = &freeiplink;
for(np = *l; np; np = *l){
if(np->expire > now){
*l = np->next;
free(np);
continue;
}
l = &np->next;
}
p->expire = now + 5000; /* give other threads 5 secs to get out */
p->next = nil;
*l = p;
}
static void
ipselffree(Ipself *p)
{
Ipself **l, *np;
ulong now = msec;
l = &freeipself;
for(np = *l; np; np = *l){
if(np->expire > now){
*l = np->next;
free(np);
continue;
}
l = &np->next;
}
p->expire = now + 5000; /* give other threads 5 secs to get out */
p->next = nil;
*l = p;
}
/*
* Decrement reference for this address on this link.
* Unlink from selftab if this is the last ref.
* called with c->car locked
*/
static void
remselfcache(Ipifc *ifc, Iplifc *lifc, uchar *a)
{
Ipself *p, **l;
Iplink *lp, *llp, **ill, **lll;
qlock(&selftab);
/* find the unique selftab entry */
l = &selftab.hash[hashipa(a)];
for(p = *l; p; p = *l){
if(ipcmp(p->a, a) == 0)
break;
l = &p->next;
}
if(p == nil)
goto out;
/*
* walk down links from an ifc looking for one
* that matches the selftab entry
*/
ill = &lifc->link;
for(lp = *ill; lp; lp = *ill){
if(lp->local == p)
break;
ill = &lp->lifclink;
}
if(lp == nil)
goto out;
/*
* walk down the links from the selftab looking for
* the one we just found
*/
lll = &p->link;
for(llp = *lll; llp; llp = *lll){
if(llp == lp)
break;
lll = &lp->locallink;
}
if(llp == nil)
panic("remselfcache");
if(--(llp->ref) != 0)
goto out;
if((p->type & Rmulti) && ifc->m->remmulti != nil)
(*ifc->m->remmulti)(ifc, a, lifc->local);
/* ref == 0, remove from both chains and free the link */
*ill = lp->lifclink;
*lll = llp->locallink;
iplinkfree(lp);
/* remove from routing table */
if(isv4(a))
v4delroute(a+IPv4off, IPallbits+IPv4off);
else
v6delroute(a, IPallbits);
if(p->link != nil)
goto out;
/* no more links, remove from hash and free */
*l = p->next;
ipselffree(p);
/* if IPnoaddr, forget */
if(ipcmp(a, v4prefix) == 0 || ipcmp(a, IPnoaddr) == 0)
selftab.acceptall = 0;
out:
qunlock(&selftab);
}
static void
dumpselftab(void)
{
int i, count;
Ipself *p;
qlock(&selftab);
for(i = 0; i < NHASH; i++){
p = selftab.hash[i];
if(p == nil)
continue;
count = 0;
for(; p != nil && count++ < 6; p = p->next)
print("(%i %d %lux)", p->a, p->type, p);
print("\n");
}
qunlock(&selftab);
}
/*
* returns
* 0 - no match
* Runi
* Rbcast
* Rmcast
*/
int
ipforme(uchar *addr)
{
Ipself *p;
int count;
p = selftab.hash[hashipa(addr)];
count = 0;
for(; p; p = p->next){
if(count++ > 1000){ /* check for loops */
dumpselftab();
break;
}
if(ipcmp(addr, p->a) == 0)
return p->type;
}
/* hack to say accept anything */
if(selftab.acceptall)
return Runi;
return 0;
}
/*
* find the ifc on same net as the remote system. If none,
* return nil.
*/
Ipifc*
findipifc(uchar *remote, int type)
{
Ipifc *ifc;
Iplifc *lifc;
Conv **cp;
uchar gnet[IPaddrlen];
for(cp = ipifc.conv; cp < &ipifc.conv[ipifc.nc]; cp++){
if(*cp == 0)
continue;
ifc = (Ipifc*)(*cp)->ptcl;
for(lifc = ifc->lifc; lifc; lifc = lifc->next){
maskip(remote, lifc->mask, gnet);
if(ipcmp(gnet, lifc->net) == 0){
qunlock(&ipifc);
return ifc;
}
}
}
/* for now for broadcast and mutlicast, just use first interface */
if(type & (Rbcast|Rmulti)){
for(cp = ipifc.conv; cp < &ipifc.conv[ipifc.nc]; cp++){
if(*cp == 0)
continue;
ifc = (Ipifc*)(*cp)->ptcl;
if(ifc->lifc != nil)
return ifc;
}
}
return nil;
}
/*
* find the local address 'closest' to the remote system, copy it to
* local and return the ifc for that address
*/
void
findlocalip(uchar *local, uchar *remote)
{
Ipifc *ifc;
Iplifc *lifc;
Conv **cp;
Route *r;
uchar gate[IPaddrlen];
uchar gnet[IPaddrlen];
qlock(&ipifc);
r = v6lookup(remote);
if(r != nil){
ifc = r->ifc;
if(r->type & Rv4)
v4tov6(gate, r->v4.gate);
else
ipmove(gate, r->v6.gate);
if(r->type & Rifc){
ipmove(local, gate);
goto out;
}
/* find ifc address closest to the gateway to use */
for(lifc = ifc->lifc; lifc; lifc = lifc->next){
maskip(gate, lifc->mask, gnet);
if(ipcmp(gnet, lifc->net) == 0){
ipmove(local, lifc->local);
goto out;
}
}
}
/* no match, choose first ifc local address */
for(cp = ipifc.conv; cp < &ipifc.conv[ipifc.nc]; cp++){
if(*cp == 0)
continue;
ifc = (Ipifc*)(*cp)->ptcl;
for(lifc = ifc->lifc; lifc; lifc = lifc->next){
ipmove(local, lifc->local);
goto out;
}
}
out:
qunlock(&ipifc);
}
/*
* return first v4 address associated with an interface
*/
int
ipv4local(Ipifc *ifc, uchar *addr)
{
Iplifc *lifc;
for(lifc = ifc->lifc; lifc; lifc = lifc->next){
if(isv4(lifc->local)){
memmove(addr, lifc->local+IPv4off, IPv4addrlen);
return 1;
}
}
return 0;
}
/*
* return first v6 address associated with an interface
*/
int
ipv6local(Ipifc *ifc, uchar *addr)
{
Iplifc *lifc;
for(lifc = ifc->lifc; lifc; lifc = lifc->next){
if(!isv4(lifc->local)){
ipmove(addr, lifc->local);
return 1;
}
}
return 0;
}
/*
* see if this address is bound to the interface
*/
Iplifc*
iplocalonifc(Ipifc *ifc, uchar *ip)
{
Iplifc *lifc;
for(lifc = ifc->lifc; lifc; lifc = lifc->next)
if(ipcmp(ip, lifc->local) == 0)
return lifc;
return nil;
}
/*
* See if we're proxying for this address on this interface
*/
int
ipproxyifc(Ipifc *ifc, uchar *ip)
{
Route *r;
uchar net[IPaddrlen];
Iplifc *lifc;
/* see if this is a direct connected pt to pt address */
r = v6lookup(ip);
if(r == nil)
return 0;
if((r->type & Rifc) == 0)
return 0;
if((r->type & Rptpt) == 0)
return 0;
/* see if this is on the right interface */
for(lifc = ifc->lifc; lifc; lifc = lifc->next){
maskip(ip, lifc->mask, net);
if(ipcmp(net, lifc->remote) == 0)
return 1;
}
return 0;
}
/*
* return multicast version if any
*/
int
ipismulticast(uchar *ip)
{
if(isv4(ip)){
if(ip[IPv4off] >= 0xe0 && ip[IPv4off] < 0xf0)
return V4;
} else {
if(ip[0] == 0xff)
return V6;
}
return 0;
}
/*
* used to allow on the fly unbinds, return -1 if interface unusable
*/
int
ipifccheckin(Ipifc *ifc, Medium *med)
{
int rv;
lock(&ifc->idlock);
if(ifc->unbinding || ifc->m != med)
rv = -1;
else
rv = ++(ifc->ref);
if(ifc->ref < 0) panic("ipifccheckin");
unlock(&ifc->idlock);
return rv;
}
void
ipifccheckout(Ipifc *ifc)
{
lock(&ifc->idlock);
if(--(ifc->ref) == 0)
if(ifc->unbinding)
wakeup(&ifc->wait);
if(ifc->ref < 0) panic("ipifccheckin");
unlock(&ifc->idlock);
}
static int
allout(void *x)
{
Ipifc *ifc = x;
return ifc->ref == 0;
}
int
ipifcgrab(Ipifc *ifc)
{
lock(&ifc->idlock);
if(ifc->unbinding){
unlock(&ifc->idlock);
return 0;
}
ifc->unbinding = 1; /* after this ref can only go down */
unlock(&ifc->idlock);
sleep(&ifc->wait, allout, ifc);
return 1;
}
/*
* add a multicast address to an interface, called with c->car locked
*/
void
ipifcaddmulti(Conv *c, uchar *ma, uchar *ia)
{
Ipifc *ifc;
Iplifc *lifc;
Conv **p;
Ipmulti *multi, **l;
for(l = &c->multi; *l; l = &(*l)->next)
if(ipcmp(ma, (*l)->ma) == 0)
if(ipcmp(ia, (*l)->ia) == 0)
return; /* it's already there */
multi = *l = smalloc(sizeof(*multi));
ipmove(multi->ma, ma);
ipmove(multi->ia, ia);
multi->next = nil;
for(p = ipifc.conv; *p; p++){
if((*p)->inuse == 0)
continue;
ifc = (Ipifc*)(*p)->ptcl;
if(waserror()){
wunlock(ifc);
nexterror();
}
wlock(ifc);
for(lifc = ifc->lifc; lifc; lifc = lifc->next)
if(ipcmp(ia, lifc->local) == 0)
addselfcache(ifc, lifc, ma, Rmulti);
wunlock(ifc);
poperror();
}
}
/*
* remove a multicast address from an interface, called with c->car locked
*/
void
ipifcremmulti(Conv *c, uchar *ma, uchar *ia)
{
Ipmulti *multi, **l;
Iplifc *lifc;
Conv **p;
Ipifc *ifc;
for(l = &c->multi; *l; l = &(*l)->next)
if(ipcmp(ma, (*l)->ma) == 0)
if(ipcmp(ia, (*l)->ia) == 0)
break;
multi = *l;
if(multi == nil)
return; /* we don't have it open */
*l = multi->next;
for(p = ipifc.conv; *p; p++){
if((*p)->inuse == 0)
continue;
ifc = (Ipifc*)(*p)->ptcl;
if(waserror()){
wunlock(ifc);
nexterror();
}
wlock(ifc);
for(lifc = ifc->lifc; lifc; lifc = lifc->next)
if(ipcmp(ia, lifc->local) == 0)
remselfcache(ifc, lifc, ma);
wunlock(ifc);
poperror();
}
free(multi);
}
/*
* make lifc's join and leave multicast groups
*/
static char*
ipifcjoinmulti(Ipifc *ifc, char **argv, int argc)
{
USED(ifc, argv, argc);
return nil;
}
static char*
ipifcleavemulti(Ipifc *ifc, char **argv, int argc)
{
USED(ifc, argv, argc);
return nil;
}
.
## diffname ip/ipifc.c 1998/0307
## diff -e /n/emeliedump/1998/0306/sys/src/brazil/ip/ipifc.c /n/emeliedump/1998/0307/sys/src/brazil/ip/ipifc.c
1004,1056d
743,745c
*l_lifc = link->lifclink;
*l_self = link->selflink;
iplinkfree(link);
.
736c
if(--(link->ref) != 0)
.
733c
if(link == nil)
.
730c
l_self = &link->selflink;
.
726,728c
l_self = &p->link;
for(link = *l_self; link; link = *l_self){
if(link == *(l_lifc))
.
719c
if(link == nil)
.
716c
l_lifc = &link->lifclink;
.
712,714c
l_lifc = &lifc->link;
for(link = *l_lifc; link; link = *l_lifc){
if(link->self == p)
.
693c
Iplink *link, **l_self, **l_lifc;
.
615,616c
lp->self = p;
lp->selflink = p->link;
.
606c
for(lp = p->link; lp; lp = lp->selflink)
.
475a
if(m == nil)
continue;
.
458a
if(m == nil)
continue;
.
426c
remselfcache(ifc, lifc, lifc->link->self->a);
.
284,287c
Ipifc *ifc;
Medium *m;
ifc = (Ipifc*)c->ptcl;
m = ifc->m;
if(m != nil && m->unbindonclose)
ipifcunbind(ifc);
.
274a
ifc->unbinding = 0;
ifc->m = nil;
.
226c
m += snprint(state+m, n - m, " %-20.20I", link->self->a);
.
175,182c
ifc->m = nil;
.
161,163d
156a
/* disassociate device */
(*ifc->m->unbind)(ifc);
memset(ifc->dev, 0, sizeof(ifc->dev));
ifc->arg = nil;
.
154,155c
/* dissociate routes */
ifc->ifcid++;
.
25a
&pktmedium,
.
## diffname ip/ipifc.c 1998/0310
## diff -e /n/emeliedump/1998/0307/sys/src/brazil/ip/ipifc.c /n/emeliedump/1998/0310/sys/src/brazil/ip/ipifc.c
789a
}
static char *stformat = "%-32.32I %2.2d %4.4s\n";
enum
{
Nstformat= 41,
};
long
ipselftabread(char *cp, ulong offset, int n)
{
int i, m, nifc;
Ipself *p;
Iplink *link;
char state[8];
m = 0;
qlock(&selftab);
for(i = 0; i < NHASH && m < n; i++){
for(p = selftab.hash[i]; p != nil && m < n; p = p->next){
if(offset == 0){
nifc = 0;
for(link = p->link; link; link = link->selflink)
nifc++;
routetype(p->type, state);
m += snprint(cp + m, n - m, stformat, p->a, nifc, state);
}
offset -= Nstformat;
}
}
qunlock(&selftab);
return m;
.
786c
print("(%I %d %lux)", p->a, p->type, p);
.
758,760d
751a
if(p->link != nil)
goto out;
.
## diffname ip/ipifc.c 1998/0313
## diff -e /n/emeliedump/1998/0310/sys/src/brazil/ip/ipifc.c /n/emeliedump/1998/0313/sys/src/brazil/ip/ipifc.c
1116c
remselfcache(f, ifc, lifc, ma);
.
1104c
for(p = f->ipifc->conv; *p; p++){
.
1091a
Fs *f;
f = c->p->f;
.
1075c
addselfcache(f, ifc, lifc, ma, Rmulti);
.
1064c
for(p = f->ipifc->conv; *p; p++){
.
1052a
Fs *f;
f = c->p->f;
.
1009c
r = v6lookup(f, ip);
.
1002c
ipproxyifc(Fs *f, Ipifc *ifc, uchar *ip)
.
946c
qunlock(f->ipifc);
.
935c
e = &f->ipifc->conv[f->ipifc->nc];
for(cp = f->ipifc->conv; cp < e; cp++){
.
909,910c
qlock(f->ipifc);
r = v6lookup(f, remote);
.
904c
Conv **cp, **e;
.
900c
findlocalip(Fs *f, uchar *local, uchar *remote)
.
883c
for(cp = f->ipifc->conv; cp < e; cp++){
.
877d
874,875c
if(ipcmp(gnet, lifc->net) == 0)
.
868c
e = &f->ipifc->conv[f->ipifc->nc];
for(cp = f->ipifc->conv; cp < e; cp++){
.
865c
Conv **cp, **e;
.
861c
findipifc(Fs *f, uchar *remote, int type)
.
850c
if(f->self->acceptall)
.
841,844d
838,839c
p = f->self->hash[hashipa(addr)];
.
836d
833c
ipforme(Fs *f, uchar *addr)
.
820c
qunlock(f->self);
.
809c
for(p = f->self->hash[i]; p != nil && m < n; p = p->next){
.
807c
qlock(f->self);
.
799c
ipselftabread(Fs *f, char *cp, ulong offset, int n)
.
773,791d
770c
qunlock(f->self);
.
767c
f->self->acceptall = 0;
.
759c
v6delroute(f, a, IPallbits);
.
757c
v4delroute(f, a+IPv4off, IPallbits+IPv4off);
.
703c
l = &f->self->hash[hashipa(a)];
.
700c
qlock(f->self);
.
695c
remselfcache(Fs *f, Ipifc *ifc, Iplifc *lifc, uchar *a)
.
645c
* called with f->self locked
.
638c
qunlock(f->self);
.
630c
v6addroute(f, tifc, a, IPallbits, a, type);
.
628c
v4addroute(f, tifc, a+IPv4off, IPallbits+IPv4off, a+IPv4off, type);
.
607c
f->self->acceptall = 1;
.
602,603c
p->next = f->self->hash[h];
f->self->hash[h] = p;
.
593c
for(p = f->self->hash[h]; p; p = p->next)
.
589c
qlock(f->self);
.
583c
addselfcache(Fs *f, Ipifc *ifc, Iplifc *lifc, uchar *a, int type)
.
575c
ipifc = smalloc(sizeof(Ipifc));
ipifc->name = "ipifc";
ipifc->kick = ipifckick;
ipifc->connect = ipifcconnect;
ipifc->announce = nil;
ipifc->bind = ipifcbind;
ipifc->state = ipifcstate;
ipifc->create = ipifccreate;
ipifc->close = ipifcclose;
ipifc->rcv = nil;
ipifc->ctl = ipifcctl;
ipifc->advise = nil;
ipifc->stats = ipifcstats;
ipifc->inuse = ipifcinuse;
ipifc->local = ipifclocal;
ipifc->ipproto = -1;
ipifc->nc = Maxmedia;
ipifc->ptclsize = sizeof(Ipifc);
f->ipifc = ipifc; /* hack for ipifcremroute, findipifc, ... */
f->self = smalloc(sizeof(Ipselftab)); /* hack for ipforme */
Fsproto(f, ipifc);
.
557,573c
Proto *ipifc;
.
555c
ipifcinit(Fs *f)
.
553a
ipifcstats(Proto *ipifc, char *buf, int len)
{
return ipstats(ipifc->f, buf, len);
}
.
542a
else if(strcmp(argv[0], "bootp") == 0)
return bootp(ifc);
.
526c
Fsconnected(c, nil);
.
475c
e = &f->ipifc->conv[f->ipifc->nc];
for(cp = f->ipifc->conv; cp < e; cp++){
.
472c
Conv **cp, **e;
.
469c
ipifcremroute(Fs *f, int vers, uchar *addr, uchar *mask)
.
456c
e = &f->ipifc->conv[f->ipifc->nc];
for(cp = f->ipifc->conv; cp < e; cp++){
.
453c
Conv **cp, **e;
.
450c
ipifcaddroute(Fs *f, int vers, uchar *addr, uchar *mask, uchar *gate, int type)
.
433c
v6delroute(f, lifc->remote, lifc->mask);
.
431c
v4delroute(f, lifc->remote+IPv4off, lifc->mask+IPv4off);
.
427c
remselfcache(f, ifc, lifc, lifc->link->self->a);
.
400a
f = ifc->conv->p->f;
.
396a
Fs *f;
.
379c
addselfcache(f, ifc, lifc, IPv4bcast, Rbcast);
.
377c
addselfcache(f, ifc, lifc, bcast, Rbcast);
.
371c
addselfcache(f, ifc, lifc, bcast, Rbcast);
.
366c
addselfcache(f, ifc, lifc, ip, Runi);
.
364c
v6addroute(f, tifc, ip, mask, rem, type);
.
362c
v4addroute(f, tifc, rem+IPv4off, mask+IPv4off, ip+IPv4off, type);
.
302a
f = ifc->conv->p->f;
.
301a
Fs *f;
.
255c
(*ifc->m->pktin)(c->p->f, ifc, bp);
.
73,74c
static void addselfcache(Fs *f, Ipifc *ifc, Iplifc *lifc, uchar *a, int type);
static void remselfcache(Fs *f, Ipifc *ifc, Iplifc *lifc, uchar *a);
.
54d
46d
27a
&tripmedium,
.
20,22d
## diffname ip/ipifc.c 1998/0314
## diff -e /n/emeliedump/1998/0313/sys/src/brazil/ip/ipifc.c /n/emeliedump/1998/0314/sys/src/brazil/ip/ipifc.c
556a
else if(strcmp(argv[0], "iprouting") == 0){
i = 1;
if(argc > 1)
i = atoi(argv[1]);
iprouting(c->p->f, i);
return nil;
}
.
542a
int i;
.
## diffname ip/ipifc.c 1998/0316
## diff -e /n/emeliedump/1998/0314/sys/src/brazil/ip/ipifc.c /n/emeliedump/1998/0316/sys/src/brazil/ip/ipifc.c
880c
/* for now for broadcast and multicast, just use first interface */
.
878a
if(x != nil)
return x;
.
875,876c
if(ipcmp(gnet, lifc->net) == 0){
if(x == nil || ipcmp(lifc->mask, xmask) > 0){
x = ifc;
ipmove(xmask, lifc->mask);
}
}
.
867a
x = nil;
/* find most specific match */
.
866a
uchar xmask[IPaddrlen];
.
863c
Ipifc *ifc, *x;
.
363c
v6addroute(f, tifc, rem, mask, ip, type);
.
## diffname ip/ipifc.c 1998/0318
## diff -e /n/emeliedump/1998/0316/sys/src/brazil/ip/ipifc.c /n/emeliedump/1998/0318/sys/src/brazil/ip/ipifc.c
375a
addselfcache(f, ifc, lifc, bcast, Rbcast);
/* add old network directed broadcast addresses to the self cache */
memmove(mask, defmask(ip), IPaddrlen);
for(i = 0; i < IPaddrlen; i++)
bcast[i] = (ip[i] & mask[i]) & mask[i];
.
371a
/* add old subnet directed broadcast addresses to the self cache */
for(i = 0; i < IPaddrlen; i++)
bcast[i] = (ip[i] & mask[i]) & mask[i];
addselfcache(f, ifc, lifc, bcast, Rbcast);
.
## diffname ip/ipifc.c 1998/0330
## diff -e /n/emeliedump/1998/0318/sys/src/brazil/ip/ipifc.c /n/emeliedump/1998/0330/sys/src/brazil/ip/ipifc.c
568a
else if(strcmp(argv[0], "mtu") == 0)
return ipifcsetmtu(ifc, argv, argc);
.
288a
* change an interface's mtu
*/
char*
ipifcsetmtu(Ipifc *ifc, char **argv, int argc)
{
int mtu;
if(argc < 2)
return Ebadarg;
if(ifc->m == nil)
return Ebadarg;
mtu = strtoul(argv[1], 0, 0);
if(mtu < ifc->m->minmtu || mtu > ifc->m->maxmtu)
return Ebadarg;
ifc->maxmtu = mtu;
return nil;
}
/*
.
## diffname ip/ipifc.c 1998/0423
## diff -e /n/emeliedump/1998/0330/sys/src/brazil/ip/ipifc.c /n/emeliedump/1998/0423/sys/src/brazil/ip/ipifc.c
72a
/*
* link in a new medium
*/
void
addipmedium(Medium *med)
{
int i;
for(i = 0; i < nelem(media)-1; i++)
if(media[i] == nil){
media[i] = med;
break;
}
}
.
22,25d
20c
Medium *media[32] =
.
## diffname ip/ipifc.c 1998/0507
## diff -e /n/emeliedump/1998/0423/sys/src/brazil/ip/ipifc.c /n/emeliedump/1998/0507/sys/src/brazil/ip/ipifc.c
162a
ifc->conv->inuse--;
.
137a
ifc->conv->inuse++;
.
## diffname ip/ipifc.c 1998/0515
## diff -e /n/emeliedump/1998/0507/sys/src/brazil/ip/ipifc.c /n/emeliedump/1998/0515/sys/src/brazil/ip/ipifc.c
296c
if(m == nil || m->unbindonclose)
.
168c
if(ifc->m)
(*ifc->m->unbind)(ifc);
.
## diffname ip/ipifc.c 1998/0516
## diff -e /n/emeliedump/1998/0515/sys/src/brazil/ip/ipifc.c /n/emeliedump/1998/0516/sys/src/brazil/ip/ipifc.c
297c
if(m != nil && m->unbindonclose)
.
190a
.
168c
if(ifc->m != nil && ifc->m->unbind)
.
164c
if(ifc->m != nil && ifc->m->unbindonclose == 0){
lock(ifc->conv);
ifc->conv->inuse--;
unlock(ifc->conv);
}
.
138c
if(ifc->m->unbindonclose == 0){
lock(ifc->conv);
ifc->conv->inuse++;
unlock(ifc->conv);
}
.
## diffname ip/ipifc.c 1998/0630
## diff -e /n/emeliedump/1998/0516/sys/src/brazil/ip/ipifc.c /n/emeliedump/1998/0630/sys/src/brazil/ip/ipifc.c
839c
v6delroute(f, a, IPallbits, 1);
.
837c
v4delroute(f, a+IPv4off, IPallbits+IPv4off, 1);
.
488c
v6delroute(f, lifc->remote, lifc->mask, 1);
.
486c
v4delroute(f, lifc->remote+IPv4off, lifc->mask+IPv4off, 1);
.
220c
}
.
217c
" %-20.20I %-20.20M %-20.20I %-7d %-7d %-7d %-7d\n",
.
215c
m = 0;
for(lifc = ifc->lifc; lifc; lifc = lifc->next) {
m += snprint(state, n, "%-12.12s %-5d", ifc->dev, ifc->maxmtu);
.
212,213d
199d
176,177c
(*ifc->m->unbind)(ifc);
.
168,172c
ifc->conv->inuse--;
.
138,142c
ifc->conv->inuse++;
.
## diffname ip/ipifc.c 1998/0702
## diff -e /n/emeliedump/1998/0630/sys/src/brazil/ip/ipifc.c /n/emeliedump/1998/0702/sys/src/brazil/ip/ipifc.c
331a
if(ifc->m == nil)
return "ipifc not yet bound to device";
.
## diffname ip/ipifc.c 1998/0709
## diff -e /n/emeliedump/1998/0702/sys/src/brazil/ip/ipifc.c /n/emeliedump/1998/0709/sys/src/brazil/ip/ipifc.c
210d
203,205c
for(lifc = ifc->lifc; lifc; lifc = lifc->next)
.
201a
m = snprint(state, n, "%-12.12s %-5d", ifc->dev, ifc->maxmtu);
.
168c
if(ifc->m != nil && ifc->m->unbind)
(*ifc->m->unbind)(ifc);
.
164c
if(ifc->m != nil && ifc->m->unbindonclose == 0){
lock(ifc->conv);
ifc->conv->inuse--;
unlock(ifc->conv);
}
.
138c
if(ifc->m->unbindonclose == 0){
lock(ifc->conv);
ifc->conv->inuse++;
unlock(ifc->conv);
}
.
## diffname ip/ipifc.c 1998/0717
## diff -e /n/emeliedump/1998/0709/sys/src/brazil/ip/ipifc.c /n/emeliedump/1998/0717/sys/src/brazil/ip/ipifc.c
496,497d
494c
if(dolock)
.
479a
}
.
478c
if(lifc == nil){
if(dolock)
wunlock(ifc);
.
466d
460,464c
if(dolock)
.
436d
377,380d
214c
for(lifc = ifc->lifc; lifc && n > m; lifc = lifc->next)
.
## diffname ip/ipifc.c 1998/0728
## diff -e /n/emeliedump/1998/0717/sys/src/brazil/ip/ipifc.c /n/emeliedump/1998/0728/sys/src/brazil/ip/ipifc.c
1098a
int
ipisbm(uchar *ip)
{
if(isv4(ip)){
if(ip[IPv4off] >= 0xe0 && ip[IPv4off] < 0xf0)
return V4;
if(ipcmp(ip, IPv4bcast) == 0)
return V4;
} else {
if(ip[0] == 0xff)
return V6;
}
return 0;
}
.
## diffname ip/ipifc.c 1998/0825
## diff -e /n/emeliedump/1998/0728/sys/src/brazil/ip/ipifc.c /n/emeliedump/1998/0825/sys/src/brazil/ip/ipifc.c
216c
" %-20.20I %-20.20M %-20.20I %-7lud %-7lud %-7lud %-7lud\n",
.
## diffname ip/ipifc.c 1998/0930
## diff -e /n/emeliedump/1998/0825/sys/src/brazil/ip/ipifc.c /n/emeliedump/1998/0930/sys/src/brazil/ip/ipifc.c
486d
## diffname ip/ipifc.c 1998/1005
## diff -e /n/emeliedump/1998/0930/sys/src/brazil/ip/ipifc.c /n/emeliedump/1998/1005/sys/src/brazil/ip/ipifc.c
988,999c
findprimaryip(f, local);
.
974,978d
959d
950a
* returns first ip address configured
*/
void
findprimaryip(Fs *f, uchar *local)
{
Conv **cp, **e;
Ipifc *ifc;
Iplifc *lifc;
/* find first ifc local address */
e = &f->ipifc->conv[f->ipifc->nc];
for(cp = f->ipifc->conv; cp < e; cp++){
if(*cp == 0)
continue;
ifc = (Ipifc*)(*cp)->ptcl;
for(lifc = ifc->lifc; lifc; lifc = lifc->next){
ipmove(local, lifc->local);
return;
}
}
}
/*
.
405a
if(type & Rptpt)
goto out;
.
398a
}
.
397c
if(ipcmp(mask, IPallbits) == 0){
/* point to point networks are a hack */
if(ipcmp(ip, rem) == 0)
findprimaryip(f, lifc->local);
.
218a
if(ifc->lifc == nil)
m += snprint(state+m, n - m, "\n");
.
## diffname ip/ipifc.c 1999/0223
## diff -e /n/emeliedump/1998/1005/sys/src/brazil/ip/ipifc.c /n/emeliedump/1999/0223/sys/src/brazil/ip/ipifc.c
211c
m = snprint(state, n, "%-12s %-5d", ifc->dev, ifc->maxmtu);
.
## diffname ip/ipifc.c 1999/0302
## diff -e /n/emeliedump/1999/0223/sys/src/brazil/ip/ipifc.c /n/emeliedump/1999/0302/sys/src/brazil/ip/ipifc.c
308c
qunlock(c);
.
171c
qunlock(ifc->conv);
.
169c
qlock(ifc->conv);
.
141c
qunlock(ifc->conv);
.
139c
qlock(ifc->conv);
.
## diffname ip/ipifc.c 1999/0731
## diff -e /n/emeliedump/1999/0302/sys/src/brazil/ip/ipifc.c /n/emeliedump/1999/0731/sys/src/brazil/ip/ipifc.c
1233a
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;
}
}
}
}
.
438a
/* register the address on this network for address resolution */
if(ifc->m->areg != nil)
(*ifc->m->areg)(ifc, ip);
.
413a
}
.
412c
if(type & Rptpt){
ipifcregisterproxy(f, ifc, rem);
.
68a
static void ipifcregisterproxy(Fs*, Ipifc*, uchar*);
.
## diffname ip/ipifc.c 1999/0803
## diff -e /n/emeliedump/1999/0731/sys/src/brazil/ip/ipifc.c /n/emeliedump/1999/0803/sys/src/brazil/ip/ipifc.c
1265a
runlock(nifc);
.
1262c
(*m->areg)(nifc, ip);
.
1258a
rlock(nifc);
m = nifc->m;
if(m == nil || m->areg == nil){
runlock(nifc);
continue;
}
.
1255,1256d
1246a
Medium *m;
.
## diffname ip/ipifc.c 1999/0909
## diff -e /n/emeliedump/1999/0803/sys/src/brazil/ip/ipifc.c /n/emeliedump/1999/0909/sys/src/brazil/ip/ipifc.c
1091,1093c
if((r->type & (Rifc|Rptpt|Rproxy)) != (Rifc|Rptpt|Rproxy))
.
413c
if((type & (Rptpt|Rproxy)) == (Rptpt|Rproxy)){
.
399d
351a
case 6:
if(strcmp(argv[5], "proxy") == 0)
type |= Rproxy;
/* fall through */
.
347a
type = Rifc;
.
## diffname ip/ipifc.c 1999/1029
## diff -e /n/emeliedump/1999/0909/sys/src/brazil/ip/ipifc.c /n/emeliedump/1999/1029/sys/src/brazil/ip/ipifc.c
486a
l = &lifc->next;
}
.
478,483c
/* Are we point to point */
type = 0;
if(ipcmp(mask, IPallbits) == 0)
type = Rptpt;
/*
* find address on this interface and remove from chain.
* for pt to pt we actually specify the remote address at the
* addresss to remove.
*/
l = &ifc->lifc;
for(lifc = *l; lifc != nil; lifc = lifc->next) {
addr = lifc->local;
if(type == Rptpt)
addr = lifc->remote;
if(memcmp(ip, addr, IPaddrlen) == 0 && memcmp(mask, lifc->mask, IPaddrlen) == 0) {
.
## diffname ip/ipifc.c 1999/1031
## diff -e /n/emeliedump/1999/1029/sys/src/brazil/ip/ipifc.c /n/emeliedump/1999/1031/sys/src/9/ip/ipifc.c
493c
if(memcmp(ip, addr, IPaddrlen) == 0)
if(memcmp(mask, lifc->mask, IPaddrlen) == 0) {
.
465a
uchar *addr;
int type;
.
## diffname ip/ipifc.c 2000/0107
## diff -e /n/emeliedump/1999/1031/sys/src/9/ip/ipifc.c /n/emeliedump/2000/0107/sys/src/9/ip/ipifc.c
598,599c
if(ipcmp(ifc->lifc->mask, IPallbits) == 0)
sprint(ip, "%I", ifc->lifc->remote);
else
sprint(ip, "%I", ifc->lifc->local);
sprint(mask, "%M", ifc->lifc->mask);
.
192c
if(ipcmp(ifc->lifc->mask, IPallbits) == 0)
sprint(ip, "%I", ifc->lifc->remote);
else
sprint(ip, "%I", ifc->lifc->local);
.
## diffname ip/ipifc.c 2000/0126
## diff -e /n/emeliedump/2000/0107/sys/src/9/ip/ipifc.c /n/emeliedump/2000/0126/sys/src/9/ip/ipifc.c
20c
Medium *media[Maxmedia] =
.
13c
Maxmedia = 32,
.
## diffname ip/ipifc.c 2000/0913
## diff -e /n/emeliedump/2000/0126/sys/src/9/ip/ipifc.c /n/emeliedump/2000/0913/sys/src/9/ip/ipifc.c
665c
ipifc = smalloc(sizeof(Proto));
.
## diffname ip/ipifc.c 2000/1111
## diff -e /n/emeliedump/2000/0913/sys/src/9/ip/ipifc.c /n/emeliedump/2000/1111/sys/src/9/ip/ipifc.c
633,634d
## diffname ip/ipifc.c 2000/1220
## diff -e /n/emeliedump/2000/1111/sys/src/9/ip/ipifc.c /n/emeliedump/2000/1220/sys/src/9/ip/ipifc.c
312d
172,173d
169,170c
if(ifc->m != nil && ifc->m->unbindonclose == 0)
.
153a
* called with ifc->conv closed
.
142,143d
139,140c
if(ifc->m->unbindonclose == 0)
.
102c
* called with c locked
.
## diffname ip/ipifc.c 2001/0306
## diff -e /n/emeliedump/2000/1220/sys/src/9/ip/ipifc.c /n/emeliedump/2001/0306/sys/src/9/ip/ipifc.c
260c
ipifckick(Conv *c)
.
## diffname ip/ipifc.c 2001/0710
## diff -e /n/emeliedump/2001/0306/sys/src/9/ip/ipifc.c /n/emeliedump/2001/0710/sys/src/9/ip/ipifc.c
504a
ifc->ifcid++;
.
410c
v6addroute(f, tifc, rem, mask, rem, type);
.
408c
v4addroute(f, tifc, rem+IPv4off, mask+IPv4off, rem+IPv4off, type);
.
## diffname ip/ipifc.c 2001/1117
## diff -e /n/emeliedump/2001/0710/sys/src/9/ip/ipifc.c /n/emeliedump/2001/1117/sys/src/9/ip/ipifc.c
639c
else if(strcmp(argv[0], "reassemble") == 0){
ifc->reassemble = 1;
return nil;
} else if(strcmp(argv[0], "iprouting") == 0){
.
290a
ifc->reassemble = 0;
.
175a
ifc->reassemble = 0;
.
## diffname ip/ipifc.c 2002/0221
## diff -e /n/emeliedump/2001/1117/sys/src/9/ip/ipifc.c /n/emeliedump/2002/0221/sys/src/9/ip/ipifc.c
909d
902,907c
nifc = 0;
for(link = p->link; link; link = link->selflink)
nifc++;
routetype(p->type, state);
m += snprint(cp + m, n - m, stformat, p->a, nifc, state);
if(off > 0){
off -= m;
m = 0;
.
898a
off = offset;
.
893c
int i, m, nifc, off;
.
885,888d
## diffname ip/ipifc.c 2002/0507
## diff -e /n/emeliedump/2002/0221/sys/src/9/ip/ipifc.c /n/emeliedump/2002/0507/sys/src/9/ip/ipifc.c
1293a
if(found==0) {
if(routerlt <= 0)
return nil;
else if((force) && (j<0)) {
j = f->v6p->cdrouter;
f->v6p->cdrouter = -1;
}
}
// assert((found && (j>=0))||(!found && routerlt>0));
if(routerlt > 0) {
memset(&r[j], 0, sizeof(v6router));
r[j].inuse = 1;
r[j].ifc = ifc;
r[j].ifcid = ifc->ifcid;
ipmove(r[j].routeraddr, routeraddr);
r[j].ltorigin = msec / 10^3;
r[j].rp.mflag = (mflag!=0);
r[j].rp.oflag = (oflag!=0);
r[j].rp.rxmitra = rxmitra;
r[j].rp.reachtime = reachtime;
r[j].rp.routerlt = routerlt;
r[j].rp.ttl = ttl;
if((f->v6p->cdrouter < 0) || (force==1)) {
f->v6p->cdrouter = j;
adddefroute6(f, routeraddr, force);
}
}
else if(j >= 0) { // remove router
r[j].inuse = 0;
if(f->v6p->cdrouter==j) {
f->v6p->cdrouter = -1;
v6delroute(f, v6Unspecified, v6Unspecified, 1);
for(i=0; i<Ngates; i++) {
if(r[i].inuse) {
f->v6p->cdrouter = i;
adddefroute6(f, r[i].routeraddr, 1);
break;
}
}
}
}
return nil;
}
char*
ipifcaddpref6(Ipifc *ifc, char**argv, int argc)
{
uchar onlink = 1;
uchar autoflag = 1;
long validlt = 0xffffffff;
long preflt = 0xffffffff;
long origint = msec / 10^3;
uchar prefix[IPaddrlen];
int plen = 64;
Iplifc *lifc;
char addr[40];
char *params[3];
switch(argc) {
case 7:
preflt = atoi(argv[6]);
/* fall through */
case 6:
validlt = atoi(argv[5]);
/* fall through */
case 5:
autoflag = atoi(argv[4]);
/* fall through */
case 4:
onlink = atoi(argv[3]);
/* fall through */
case 3:
plen = atoi(argv[2]);
case 2:
break;
default:
return Ebadarg;
}
if((parseip(prefix, argv[1])!=6) ||
(validlt < preflt) ||
(plen > 64) ||
(islinklocal(prefix))
)
return Ebadarg;
lifc = smalloc(sizeof(Iplifc));
lifc->onlink = (onlink!=0);
lifc->autoflag = (autoflag!=0);
lifc->validlt = validlt;
lifc->preflt = preflt;
lifc->origint = origint;
if(ifc->m->pref2addr!=nil)
ifc->m->pref2addr(prefix, ifc->mac);
else
return Ebadarg;
sprint(addr, "%I", prefix);
params[0] = "add";
params[1] = addr;
params[2] = "/64";
return ipifcadd(ifc, params, 3, 0, lifc);
}
static char *gateformat = "%-1.1s %-40.40I %20ld %10d %-40.40s\n";
enum
{
Ngateformat= 116,
};
static char *rtrstat[] =
{
[0] "*",
[1] "-",
};
/* line corresponding to current default router, if in f->v6p->v6rlist,
starts with a "*", others with a "-". */
long
ipgateread6(Fs *f, char *cp, ulong offset, int n)
{
v6router *r = f->v6p->v6rlist;
int i, j, k, l;
long m;
if(offset % Ngateformat)
return 0;
offset = offset/Ngateformat;
n = n/Ngateformat;
i = f->v6p->cdrouter;
k = i;
if((i<0)||(i>2))
i = 0;
m = 0;
for(j = 0; (n > 0) && (j < Ngates) ; j++){
if(offset > 0){
offset--;
i = (i+1) % Ngates;
continue;
}
n--;
if(r[i].inuse) {
l = (i==k) ? 0 : 1;
m += sprint(cp + m, gateformat,
rtrstat[l], r[i].routeraddr, r[i].ltorigin,
r[i].rp.routerlt, r[i].ifc->dev);
}
i = (i+1) % Ngates;
}
return m;
.
1292c
else {
j = i;
}
.
1285,1288c
return;
}
else { // V4
for(cp = f->ipifc->conv; cp < e; cp++){
if(*cp == nil)
continue;
nifc = (Ipifc*)(*cp)->ptcl;
if(nifc == ifc)
continue;
rlock(nifc);
m = nifc->m;
if(m == nil || m->areg == nil){
runlock(nifc);
continue;
}
for(lifc = nifc->lifc; lifc; lifc = lifc->next){
maskip(ip, lifc->mask, net);
if(ipcmp(net, lifc->remote) == 0){
(*m->areg)(nifc, ip);
break;
}
}
runlock(nifc);
}
}
}
// added for new v6 mesg types
static void
adddefroute6(Fs *f, uchar *gate, int force)
{
Route *r;
r = v6lookup(f, v6Unspecified);
if(r!=nil)
if(!(force) && (strcmp(r->tag,"ra")!=0)) // route entries generated
return; // by all other means take
// precedence over router annc
v6delroute(f, v6Unspecified, v6Unspecified, 1);
v6addroute(f, "ra", v6Unspecified, v6Unspecified, gate, 0);
}
enum
{
Ngates = 3,
};
char*
ipifcaddgate6(Fs *f, Ipifc *ifc, char**argv, int argc)
{
v6router *r = f->v6p->v6rlist;
uchar routeraddr[IPaddrlen];
int mflag = f->v6p->rp.mflag;
int oflag = f->v6p->rp.oflag;
int reachtime = f->v6p->rp.reachtime;
int rxmitra = f->v6p->rp.rxmitra;
int ttl = MAXTTL;
int routerlt = f->v6p->rp.routerlt;
int force; // force == 1 forces argv[1] to
// be the default router.
int i, j;
int found = 0;
if((argc<3)||(argc>9))
return Ebadarg;
if( (parseip(routeraddr, argv[1])!=6) || !(islinklocal(routeraddr)) )
return Ebadarg;
force = (atoi(argv[2])!=0);
switch(argc){
case 9:
rxmitra = atoi(argv[8]);
/* fall through */
case 8:
reachtime = atoi(argv[7]);
/* fall through */
case 7:
routerlt = atoi(argv[6]);
/* fall through */
case 6:
oflag = atoi(argv[5]);
/* fall through */
case 5:
mflag = atoi(argv[4]);
/* fall through */
case 4:
ttl = atoi(argv[3]);
/* fall through */
}
if((force) && (routerlt < 0))
return Ebadarg;
if((ttl < 0) || (255 < ttl))
return Ebadarg;
j = -1;
for(i=0; i<Ngates; i++) {
if(r[i].inuse) {
if((ipcmp(routeraddr, r[i].routeraddr)==0) &&
(r[i].ifc==ifc)) {
j = i;
found = 1;
.
1283d
1279,1281c
if(!isv4(ip)) { // V6
for(cp = f->ipifc->conv; cp < e; cp++){
if(*cp == nil)
continue;
nifc = (Ipifc*)(*cp)->ptcl;
if(nifc == ifc)
continue;
rlock(nifc);
m = nifc->m;
if(m == nil || m->addmulti == nil) {
runlock(nifc);
continue;
}
for(lifc = nifc->lifc; lifc; lifc = lifc->next){
maskip(ip, lifc->mask, net);
if(ipcmp(net, lifc->remote) == 0) { /* add solicited-node multicast address */
ipv62smcast(net, ip);
addselfcache(f, nifc, lifc, net, Rmulti);
arpenter(f, V6, ip, nifc->mac, 6, 0);
//(*m->addmulti)(nifc, net, ip);
break;
}
}
.
1272,1277d
1075a
if(!isv4(lifc->local) && !(lifc->tentative)){
ipmove(addr, lifc->local);
return 1;
}
}
return 0;
}
int
ipv6anylocal(Ipifc *ifc, uchar *addr)
{
Iplifc *lifc;
for(lifc = ifc->lifc; lifc; lifc = lifc->next){
.
1045a
.
1044c
if(version == 4)
findprimaryip(f, local);
else
findprimaryip6(f, local);
.
1041a
else {
for(lifc = ifc->lifc; lifc; lifc = lifc->next){
atypel = v6addrtype(lifc->local);
maskip(gate, lifc->mask, gnet);
if(ipcmp(gnet, lifc->net) == 0)
if(atypel > atype)
if(v6addrcurr(lifc)) {
ipmove(local, lifc->local);
atype = atypel;
if(atype == globalv6)
break;
}
}
if(atype > unspecifiedv6)
goto out;
}
.
1035,1039c
if(version == 4) {
for(lifc = ifc->lifc; lifc; lifc = lifc->next){
maskip(gate, lifc->mask, gnet);
if(ipcmp(gnet, lifc->net) == 0){
ipmove(local, lifc->local);
goto out;
}
.
1032a
ipmove(local, v6Unspecified);
}
.
1031c
else {
.
1025a
version = (memcmp(remote, v4prefix, IPv4off) == 0) ? 4 : 6;
.
1023a
USED(atype);
USED(atypel);
.
1022a
int version;
int atype = unspecifiedv6, atypel = unknownv6;
.
989c
* returns first ip address configured
.
987a
enum {
unknownv6,
multicastv6,
unspecifiedv6,
linklocalv6,
sitelocalv6,
globalv6,
};
int
v6addrtype(uchar *addr)
{
if(isv6global(addr))
return globalv6;
if(islinklocal(addr))
return linklocalv6;
if(isv6mcast(addr))
return multicastv6;
if(issitelocal(addr))
return sitelocalv6;
return unknownv6;
}
#define v6addrcurr(lifc) (( (lifc)->origint + (lifc)->preflt >= (msec/10^3) ) || ( (lifc)->preflt == 0xffffffff ))
void
findprimaryip6(Fs *f, uchar *local)
{
Conv **cp, **e;
Ipifc *ifc;
Iplifc *lifc;
int atype, atypel;
ipmove(local, v6Unspecified);
atype = unspecifiedv6;
/* find "best" (global > sitelocal > link local > unspecified)
* local address; address must be current */
e = &f->ipifc->conv[f->ipifc->nc];
for(cp = f->ipifc->conv; cp < e; cp++){
if(*cp == 0)
continue;
ifc = (Ipifc*)(*cp)->ptcl;
for(lifc = ifc->lifc; lifc; lifc = lifc->next){
atypel = v6addrtype(lifc->local);
if(atypel > atype)
if(v6addrcurr(lifc)) {
ipmove(local, lifc->local);
atype = atypel;
if(atype == globalv6)
return;
}
}
}
}
.
960a
.
959a
.
953c
x = nil; memset(xmask, 0, IPaddrlen);
.
914a
p = f->self->hash[hashipa(addr)];
for(; p; p = p->next){
if(ipcmp(addr, p->a) == 0) {
return p->link->lifc->tentative;
}
}
return 0;
}
.
913a
int
iptentative(Fs *f, uchar *addr)
{
Ipself *p;
.
884a
enum
{
Nstformat= 41,
};
.
650a
else if(strcmp(argv[0], "gate6") == 0)
return ipifcaddgate6(c->p->f, ifc, argv, argc);
else if(strcmp(argv[0], "addpref6") == 0)
return ipifcaddpref6(ifc, argv, argc);
else if(strcmp(argv[0], "setpar6") == 0)
return ipifcsetpar6(ifc, argv, argc);
else if(strcmp(argv[0], "sendra6") == 0)
return ipifcsendra6(ifc, argv, argc);
else if(strcmp(argv[0], "recvra6") == 0)
return ipifcrecvra6(ifc, argv, argc);
.
644c
}
else if(strcmp(argv[0], "iprouting") == 0){
.
630c
return ipifcadd(ifc, argv, argc, 0, nil);
else if(strcmp(argv[0], "try") == 0)
return ipifcadd(ifc, argv, argc, 1, nil);
.
617a
char*
ipifcsetpar6(Ipifc *ifc, char **argv, int argc)
{
int i, argsleft, vmax = ifc->rp.maxraint, vmin = ifc->rp.minraint;
argsleft = argc - 1;
i = 1;
if(argsleft % 2 != 0)
return Ebadarg;
while (argsleft > 1) {
if(strcmp(argv[i],"recvra")==0)
ifc->recvra6 = (atoi(argv[i+1]) != 0);
else if(strcmp(argv[i],"sendra")==0)
ifc->sendra6 = (atoi(argv[i+1]) != 0);
else if(strcmp(argv[i],"mflag")==0)
ifc->rp.mflag = (atoi(argv[i+1]) != 0);
else if(strcmp(argv[i],"oflag")==0)
ifc->rp.oflag = (atoi(argv[i+1]) != 0);
else if(strcmp(argv[i],"maxraint")==0)
ifc->rp.maxraint = atoi(argv[i+1]);
else if(strcmp(argv[i],"minraint")==0)
ifc->rp.minraint = atoi(argv[i+1]);
else if(strcmp(argv[i],"linkmtu")==0)
ifc->rp.linkmtu = atoi(argv[i+1]);
else if(strcmp(argv[i],"reachtime")==0)
ifc->rp.reachtime = atoi(argv[i+1]);
else if(strcmp(argv[i],"rxmitra")==0)
ifc->rp.rxmitra = atoi(argv[i+1]);
else if(strcmp(argv[i],"ttl")==0)
ifc->rp.ttl = atoi(argv[i+1]);
else if(strcmp(argv[i],"routerlt")==0)
ifc->rp.routerlt = atoi(argv[i+1]);
else
return Ebadarg;
argsleft -= 2;
i += 2;
}
// consistency check
if(ifc->rp.maxraint < ifc->rp.minraint) {
ifc->rp.maxraint = vmax;
ifc->rp.minraint = vmin;
return Ebadarg;
}
return nil;
}
char*
ipifcsendra6(Ipifc *ifc, char **argv, int argc)
{
int i;
i = 0;
if(argc > 1)
i = atoi(argv[1]);
ifc->sendra6 = (i!=0);
return nil;
}
char*
ipifcrecvra6(Ipifc *ifc, char **argv, int argc)
{
int i;
i = 0;
if(argc > 1)
i = atoi(argv[1]);
ifc->recvra6 = (i!=0);
return nil;
}
.
609c
err = ipifcadd(ifc, argv, argc, 0, nil);
.
528c
* distribute routes to active interfaces like the
.
518a
if(ipcmp(ip, v6loopback) == 0)
/* remove route for all node multicast */
v6delroute(f, v6allnodesN, v6allnodesNmask, 1);
else if(memcmp(ip, v6linklocal, v6linklocalprefix) == 0)
/* remove route for all link multicast */
v6delroute(f, v6allnodesL, v6allnodesLmask, 1);
}
.
517c
else {
.
508,509d
450a
if(tentative && sendnbrdisc)
icmpns(f, 0, SRC_UNSPEC, ip, TARG_MULTI, ifc->mac);
.
446c
if(isv4(ip) && ifc->m->areg != nil)
.
444a
else if(memcmp(ip, v6linklocal, v6linklocalprefix) == 0) {
/* add link-local mcast address */
addselfcache(f, ifc, lifc, v6allnodesL, Rmulti);
/* add route for all link multicast */
v6addroute(f, tifc, v6allnodesL, v6allnodesLmask, v6allnodesL, Rmulti);
/* add solicited-node multicast address */
ipv62smcast(bcast, ip);
addselfcache(f, ifc, lifc, bcast, Rmulti);
}
sendnbrdisc = 1;
}
.
443c
/* add route for all node multicast */
v6addroute(f, tifc, v6allnodesN, v6allnodesNmask, v6allnodesN, Rmulti);
}
.
437,441c
/* add network directed network address to the self cache */
memmove(mask, defmask(ip), IPaddrlen);
for(i = 0; i < IPaddrlen; i++)
bcast[i] = (ip[i] & mask[i]) & mask[i];
addselfcache(f, ifc, lifc, bcast, Rbcast);
addselfcache(f, ifc, lifc, IPv4bcast, Rbcast);
}
else {
if(ipcmp(ip, v6loopback) == 0) {
/* add node-local mcast address */
addselfcache(f, ifc, lifc, v6allnodesN, Rmulti);
.
431,435c
/* add network directed broadcast address to the self cache */
memmove(mask, defmask(ip), IPaddrlen);
for(i = 0; i < IPaddrlen; i++)
bcast[i] = (ip[i] & mask[i]) | ~mask[i];
addselfcache(f, ifc, lifc, bcast, Rbcast);
.
426,429c
/* add subnet directed network address to the self cache */
for(i = 0; i < IPaddrlen; i++)
bcast[i] = (ip[i] & mask[i]) & mask[i];
addselfcache(f, ifc, lifc, bcast, Rbcast);
.
421,424c
if(isv4(ip) || ipcmp(ip, IPnoaddr) == 0) {
/* add subnet directed broadcast address to the self cache */
for(i = 0; i < IPaddrlen; i++)
bcast[i] = (ip[i] & mask[i]) | ~mask[i];
addselfcache(f, ifc, lifc, bcast, Rbcast);
.
408a
/* add local routes */
.
402c
/* check for point-to-point interface */
if(ipcmp(ip, v6loopback)) /* skip v6 loopback, it's a special address */
.
397a
.
396a
lifc->tentative = tentative;
if(lifcp != nil) {
lifc->onlink = lifcp->onlink;
lifc->autoflag = lifcp->autoflag;
lifc->validlt = lifcp->validlt;
lifc->preflt = lifcp->preflt;
lifc->origint = lifcp->origint;
}
else { // default values
lifc->onlink = 1;
lifc->autoflag = 1;
lifc->validlt = 0xffffffff;
lifc->preflt = 0xffffffff;
lifc->origint = msec / 10^3;
}
.
389a
}
}
.
387,388c
for(lifc = ifc->lifc; lifc; lifc = lifc->next) {
if(ipcmp(lifc->local, ip) == 0) {
if(lifc->tentative != tentative)
lifc->tentative = tentative;
if(lifcp != nil) {
lifc->onlink = lifcp->onlink;
lifc->autoflag = lifcp->autoflag;
lifc->validlt = lifcp->validlt;
lifc->preflt = lifcp->preflt;
lifc->origint = lifcp->origint;
}
.
383c
if(isv4(ip))
tentative = 0;
.
340a
int sendnbrdisc = 0;
.
334c
ipifcadd(Ipifc *ifc, char **argv, int argc, int tentative, Iplifc *lifcp)
.
241c
m += snprint(state+m, n - m, " %-40.40I", link->self->a);
.
239c
m += snprint(state+m, n - m, "%-40.40I ->", lifc->local);
.
215,218c
m += snprint(state+m, n - m, slineformat,
lifc->local, lifc->mask, lifc->remote,
lifc->validlt, lifc->preflt);
.
211c
m = snprint(state, n, sfixedformat,
ifc->dev, ifc->maxmtu, ifc->sendra6, ifc->recvra6,
ifc->rp.mflag, ifc->rp.oflag, ifc->rp.maxraint,
ifc->rp.minraint, ifc->rp.linkmtu, ifc->rp.reachtime,
ifc->rp.rxmitra, ifc->rp.ttl, ifc->rp.routerlt,
ifc->in, ifc->out, ifc->inerr, ifc->outerr);
.
201a
char *sfixedformat = "device %-12s maxmtu %-5d sendra %-1d recvra %-1d mflag %-1d oflag %-1d maxraint %-10d minraint %-10d linkmtu %-10d reachtime %-10d rxmitra %-10d ttl %-10d routerlt %-10d pktin %-7lud pktout %-7lud errin %-7lud errout %-7lud\n";
char *slineformat = " %-40.40I %-10.10M %-40.40I %-12lud %-12lud\n";
.
140a
ifc->rp.mflag = 0; // default not managed
ifc->rp.oflag = 0;
ifc->rp.maxraint = 600000; // millisecs
ifc->rp.minraint = 200000;
ifc->rp.linkmtu = 0; // no mtu sent
ifc->rp.reachtime = 0;
ifc->rp.rxmitra = 0;
ifc->rp.ttl = MAXTTL;
ifc->rp.routerlt = 3*(ifc->rp.maxraint);
.
8a
#include "ipv6.h"
.
## diffname ip/ipifc.c 2002/0517
## diff -e /n/emeliedump/2002/0507/sys/src/9/ip/ipifc.c /n/emeliedump/2002/0517/sys/src/9/ip/ipifc.c
218c
char slineformat[] = " %-40.40I %-10.10M %-40.40I %-12lud %-12lud\n";
.
216c
char sfixedformat[] = "device %s maxmtu %d sendra %d recvra %d mflag %d oflag %d maxraint %d minraint %d linkmtu %d reachtime %d rxmitra %d ttl %d routerlt %d pktin %lud pktout %lud errin %lud errout %lud\n";
.
## diffname ip/ipifc.c 2002/0601
## diff -e /n/emeliedump/2002/0517/sys/src/9/ip/ipifc.c /n/emeliedump/2002/0601/sys/src/9/ip/ipifc.c
1324c
break;
default:
panic("findlocalip2: version %d", version);
}
.
1322c
break;
case V6:
.
1320c
switch(version){
case V4:
.
1316a
break;
default:
panic("findlocalip: version %d", version);
.
1301,1302c
break;
case V6:
.
1293c
switch(version) {
case V4:
.
1281c
version = (memcmp(remote, v4prefix, IPv4off) == 0) ? V4 : V6;
.
## diffname ip/ipifc.c 2002/0615
## diff -e /n/emeliedump/2002/0601/sys/src/9/ip/ipifc.c /n/emeliedump/2002/0615/sys/src/9/ip/ipifc.c
586a
print("ipifcrem: wrong address\n");
.
576,577c
if (memcmp(ip, addr, IPaddrlen) == 0
&& memcmp(mask, lifc->mask, IPaddrlen) == 0) {
.
205c
if (err = ipifcrem(ifc, av, 3, 0))
print("ipifcunbind, addr %s, mask %s: %s\n", ip, mask, err);
.
170a
char *err;
.
## diffname ip/ipifc.c 2002/0710
## diff -e /n/emeliedump/2002/0615/sys/src/9/ip/ipifc.c /n/emeliedump/2002/0710/sys/src/9/ip/ipifc.c
1772c
long origint = NOW / 10^3;
.
1735c
r[j].ltorigin = NOW / 10^3;
.
1208c
#define v6addrcurr(lifc) (( (lifc)->origint + (lifc)->preflt >= (NOW/10^3) ) || ( (lifc)->preflt == 0xffffffff ))
.
962c
ulong now = NOW;
.
943c
ulong now = NOW;
.
448c
lifc->origint = NOW / 10^3;
.
## diffname ip/ipifc.c 2002/0712
## diff -e /n/emeliedump/2002/0710/sys/src/9/ip/ipifc.c /n/emeliedump/2002/0712/sys/src/9/ip/ipifc.c
844d
287a
Conv *c = x;
.
286c
ipifckick(void *x)
.
## diffname ip/ipifc.c 2002/0717
## diff -e /n/emeliedump/2002/0712/sys/src/9/ip/ipifc.c /n/emeliedump/2002/0717/sys/src/9/ip/ipifc.c
313c
c->wq = qopen(QMAX, Qkick, ipifckick, c);
.
## diffname ip/ipifc.c 2002/1110
## diff -e /n/emeliedump/2002/0717/sys/src/9/ip/ipifc.c /n/emeliedump/2002/1110/sys/src/9/ip/ipifc.c
312a
c->sq = qopen(2*QMAX, 0, 0, 0);
.
304,305c
* called when a new ipifc structure is created
.
191,193c
/* close queues to stop queuing of packets */
qclose(ifc->conv->rq);
qclose(ifc->conv->wq);
qclose(ifc->conv->sq);
.
154a
/* reopen all the queues closed by a previous unbind */
qreopen(c->rq);
qreopen(c->eq);
qreopen(c->sq);
.
152a
/* any ancillary structures (like routes) no longer pertain */
.
151c
ifc->rp.routerlt = 3*(ifc->rp.maxraint);
.
142d
136a
/* set up parameters */
.
131a
/* set the bound device name */
.
130a
/* do medium specific binding */
.
## diffname ip/ipifc.c 2002/1112
## diff -e /n/emeliedump/2002/1110/sys/src/9/ip/ipifc.c /n/emeliedump/2002/1112/sys/src/9/ip/ipifc.c
582c
* for pt to pt we actually specify the remote address as the
.
## diffname ip/ipifc.c 2003/0209
## diff -e /n/emeliedump/2002/1112/sys/src/9/ip/ipifc.c /n/emeliedump/2003/0209/sys/src/9/ip/ipifc.c
396,397c
if(mtu >= ifc->m->mintu && mtu <= ifc->m->maxtu)
ifc->maxtu = mtu;
.
363c
ifc->maxtu = mtu;
.
361c
if(mtu < ifc->m->mintu || mtu > ifc->m->maxtu)
.
244c
ifc->dev, ifc->maxtu, ifc->sendra6, ifc->recvra6,
.
229c
char sfixedformat[] = "device %s maxtu %d sendra %d recvra %d mflag %d oflag %d maxraint %d minraint %d linkmtu %d reachtime %d rxmitra %d ttl %d routerlt %d pktin %lud pktout %lud errin %lud errout %lud\n";
.
143,144c
ifc->mintu = ifc->m->mintu;
ifc->maxtu = ifc->m->maxtu;
.
## diffname ip/ipifc.c 2003/0308
## diff -e /n/emeliedump/2003/0209/sys/src/9/ip/ipifc.c /n/emeliedump/2003/0308/sys/src/9/ip/ipifc.c
1651c
r = v6lookup(f, v6Unspecified, nil);
.
1427c
r = v6lookup(f, ip, nil);
.
1294c
r = v6lookup(f, remote, nil);
.
## diffname ip/ipifc.c 2003/0318
## diff -e /n/emeliedump/2003/0308/sys/src/9/ip/ipifc.c /n/emeliedump/2003/0318/sys/src/9/ip/ipifc.c
311a
runlock(ifc);
.
307a
if(!canrlock(ifc)){
freeb(bp);
return;
}
if(waserror()){
runlock(ifc);
nexterror();
}
.
## diffname ip/ipifc.c 2003/0322
## diff -e /n/emeliedump/2003/0318/sys/src/9/ip/ipifc.c /n/emeliedump/2003/0322/sys/src/9/ip/ipifc.c
320a
poperror();
.
|