#include "u.h"#include "../port/lib.h"#include "mem.h"#include "dat.h"#include "fns.h"#include "../port/error.h" #include "ip.h"#include "ipv6.h" #define DPRINT if(0)print enum { Maxmedia = 32, Nself = Maxmedia*5, NHASH = (1<<6), NCACHE = 256, QMAX = 64*1024-1,}; Medium *media[Maxmedia] ={ 0}; /* * cache of local addresses (addresses we answer to) */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 */}; struct Ipselftab{ QLock; int inited; int acceptall; /* true if an interface has the null address */ Ipself *hash[NHASH]; /* hash chains */}; /* * 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(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*);static char* ipifcremlifc(Ipifc*, Iplifc*); /* * link in a new medium */voidaddipmedium(Medium *med){ int i; for(i = 0; i < nelem(media)-1; i++) if(media[i] == nil){ media[i] = med; break; }} /* * 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 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(); } /* do medium specific binding */ (*m->bind)(ifc, argc, argv); /* set the bound device name */ if(argc > 2) strncpy(ifc->dev, argv[2], sizeof(ifc->dev)); else snprint(ifc->dev, sizeof ifc->dev, "%s%d", m->name, c->x); ifc->dev[sizeof(ifc->dev)-1] = 0; /* set up parameters */ ifc->m = m; ifc->mintu = ifc->m->mintu; ifc->maxtu = ifc->m->maxtu; if(ifc->m->unbindonclose == 0) ifc->conv->inuse++; 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); /* any ancillary structures (like routes) no longer pertain */ ifc->ifcid++; /* reopen all the queues closed by a previous unbind */ qreopen(c->rq); qreopen(c->eq); qreopen(c->sq); wunlock(ifc); poperror(); return nil;} /* * detach a device from an interface, close the interface * called with ifc->conv closed */static char*ipifcunbind(Ipifc *ifc){ char *err; if(waserror()){ wunlock(ifc); nexterror(); } wlock(ifc); /* dissociate routes */ if(ifc->m != nil && ifc->m->unbindonclose == 0) ifc->conv->inuse--; ifc->ifcid++; /* disassociate device */ if(ifc->m != nil && ifc->m->unbind) (*ifc->m->unbind)(ifc); memset(ifc->dev, 0, sizeof(ifc->dev)); ifc->arg = nil; ifc->reassemble = 0; /* close queues to stop queuing of packets */ qclose(ifc->conv->rq); qclose(ifc->conv->wq); qclose(ifc->conv->sq); /* disassociate logical interfaces */ while(ifc->lifc){ err = ipifcremlifc(ifc, ifc->lifc); if(err) error(err); } ifc->m = nil; wunlock(ifc); poperror(); return nil;} 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"; char slineformat[] = " %-40I %-10M %-40I %-12lud %-12lud\n"; static intipifcstate(Conv *c, char *state, int n){ Ipifc *ifc; Iplifc *lifc; int m; ifc = (Ipifc*)c->ptcl; m = snprint(state, n, sfixedformat, ifc->dev, ifc->maxtu, 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); rlock(ifc); for(lifc = ifc->lifc; lifc && n > m; lifc = lifc->next) m += snprint(state+m, n - m, slineformat, lifc->local, lifc->mask, lifc->remote, lifc->validlt, lifc->preflt); if(ifc->lifc == nil) m += snprint(state+m, n - m, "\n"); runlock(ifc); return m;} static intipifclocal(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, "%-40.40I ->", lifc->local); for(link = lifc->link; link; link = link->lifclink) m += snprint(state+m, n - m, " %-40.40I", link->self->a); m += snprint(state+m, n - m, "\n"); } runlock(ifc); return m;} static intipifcinuse(Conv *c){ Ipifc *ifc; ifc = (Ipifc*)c->ptcl; return ifc->m != nil;} /* * called when a process writes to an interface's 'data' */static voidipifckick(void *x){ Conv *c = x; Block *bp; Ipifc *ifc; bp = qget(c->wq); if(bp == nil) return; ifc = (Ipifc*)c->ptcl; if(!canrlock(ifc)){ freeb(bp); return; } if(waserror()){ runlock(ifc); nexterror(); } if(ifc->m == nil || ifc->m->pktin == nil) freeb(bp); else (*ifc->m->pktin)(c->p->f, ifc, bp); runlock(ifc); poperror();} /* * called when a new ipifc structure is created */static voidipifccreate(Conv *c){ Ipifc *ifc; c->rq = qopen(QMAX, 0, 0, 0); c->sq = qopen(2*QMAX, 0, 0, 0); c->wq = qopen(QMAX, Qkick, ipifckick, c); ifc = (Ipifc*)c->ptcl; ifc->conv = c; ifc->unbinding = 0; ifc->m = nil; ifc->reassemble = 0;} /* * called after last close of ipifc data or ctl * called with c locked, we must unlock */static voidipifcclose(Conv *c){ Ipifc *ifc; Medium *m; ifc = (Ipifc*)c->ptcl; m = ifc->m; if(m != nil && m->unbindonclose) ipifcunbind(ifc);} /* * 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->mintu || mtu > ifc->m->maxtu) return Ebadarg; ifc->maxtu = mtu; return nil;} /* * add an address to an interface. */char*ipifcadd(Ipifc *ifc, char **argv, int argc, int tentative, Iplifc *lifcp){ uchar ip[IPaddrlen], mask[IPaddrlen], rem[IPaddrlen]; uchar bcast[IPaddrlen], net[IPaddrlen]; Iplifc *lifc, **l; int i, type, mtu; Fs *f; int sendnbrdisc = 0; if(ifc->m == nil) return "ipifc not yet bound to device"; f = ifc->conv->p->f; type = Rifc; memset(ip, 0, IPaddrlen); memset(mask, 0, IPaddrlen); memset(rem, 0, IPaddrlen); switch(argc){ case 6: if(strcmp(argv[5], "proxy") == 0) type |= Rproxy; /* fall through */ case 5: mtu = strtoul(argv[4], 0, 0); if(mtu >= ifc->m->mintu && mtu <= ifc->m->maxtu) ifc->maxtu = 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(isv4(ip)) tentative = 0; 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) { 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; } 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->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 = NOW / 10^3; } lifc->next = nil; for(l = &ifc->lifc; *l; l = &(*l)->next) ; *l = lifc; /* check for point-to-point interface */ if(ipcmp(ip, v6loopback)) /* skip v6 loopback, it's a special address */ if(ipcmp(mask, IPallbits) == 0) type |= Rptpt; /* add local routes */ if(isv4(ip)) v4addroute(f, tifc, rem+IPv4off, mask+IPv4off, rem+IPv4off, type); else v6addroute(f, tifc, rem, mask, rem, type); addselfcache(f, ifc, lifc, ip, Runi); if((type & (Rproxy|Rptpt)) == (Rproxy|Rptpt)){ ipifcregisterproxy(f, ifc, rem); goto out; } 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); /* 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); /* 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);Lines 1–500 of 1721. Load more
#include "u.h" #include "../port/lib.h" #include "mem.h" #include "dat.h" #include "fns.h" #include "../port/error.h" #include "ip.h" #include "ipv6.h" #define DPRINT if(0)print enum { Maxmedia = 32, Nself = Maxmedia*5, NHASH = (1<<6), NCACHE = 256, QMAX = 64*1024-1, }; Medium *media[Maxmedia] = { 0 }; /* * cache of local addresses (addresses we answer to) */ 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 */ }; struct Ipselftab { QLock; int inited; int acceptall; /* true if an interface has the null address */ Ipself *hash[NHASH]; /* hash chains */ }; /* * 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(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*); static char* ipifcremlifc(Ipifc*, Iplifc*); /* * 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; } } /* * 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 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(); } /* do medium specific binding */ (*m->bind)(ifc, argc, argv); /* set the bound device name */ if(argc > 2) strncpy(ifc->dev, argv[2], sizeof(ifc->dev)); else snprint(ifc->dev, sizeof ifc->dev, "%s%d", m->name, c->x); ifc->dev[sizeof(ifc->dev)-1] = 0; /* set up parameters */ ifc->m = m; ifc->mintu = ifc->m->mintu; ifc->maxtu = ifc->m->maxtu; if(ifc->m->unbindonclose == 0) ifc->conv->inuse++; 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); /* any ancillary structures (like routes) no longer pertain */ ifc->ifcid++; /* reopen all the queues closed by a previous unbind */ qreopen(c->rq); qreopen(c->eq); qreopen(c->sq); wunlock(ifc); poperror(); return nil; } /* * detach a device from an interface, close the interface * called with ifc->conv closed */ static char* ipifcunbind(Ipifc *ifc) { char *err; if(waserror()){ wunlock(ifc); nexterror(); } wlock(ifc); /* dissociate routes */ if(ifc->m != nil && ifc->m->unbindonclose == 0) ifc->conv->inuse--; ifc->ifcid++; /* disassociate device */ if(ifc->m != nil && ifc->m->unbind) (*ifc->m->unbind)(ifc); memset(ifc->dev, 0, sizeof(ifc->dev)); ifc->arg = nil; ifc->reassemble = 0; /* close queues to stop queuing of packets */ qclose(ifc->conv->rq); qclose(ifc->conv->wq); qclose(ifc->conv->sq); /* disassociate logical interfaces */ while(ifc->lifc){ err = ipifcremlifc(ifc, ifc->lifc); if(err) error(err); } ifc->m = nil; wunlock(ifc); poperror(); return nil; } 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"; char slineformat[] = " %-40I %-10M %-40I %-12lud %-12lud\n"; static int ipifcstate(Conv *c, char *state, int n) { Ipifc *ifc; Iplifc *lifc; int m; ifc = (Ipifc*)c->ptcl; m = snprint(state, n, sfixedformat, ifc->dev, ifc->maxtu, 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); rlock(ifc); for(lifc = ifc->lifc; lifc && n > m; lifc = lifc->next) m += snprint(state+m, n - m, slineformat, lifc->local, lifc->mask, lifc->remote, lifc->validlt, lifc->preflt); if(ifc->lifc == nil) 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, "%-40.40I ->", lifc->local); for(link = lifc->link; link; link = link->lifclink) m += snprint(state+m, n - m, " %-40.40I", link->self->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(void *x) { Conv *c = x; Block *bp; Ipifc *ifc; bp = qget(c->wq); if(bp == nil) return; ifc = (Ipifc*)c->ptcl; if(!canrlock(ifc)){ freeb(bp); return; } if(waserror()){ runlock(ifc); nexterror(); } if(ifc->m == nil || ifc->m->pktin == nil) freeb(bp); else (*ifc->m->pktin)(c->p->f, ifc, bp); runlock(ifc); poperror(); } /* * called when a new ipifc structure is created */ static void ipifccreate(Conv *c) { Ipifc *ifc; c->rq = qopen(QMAX, 0, 0, 0); c->sq = qopen(2*QMAX, 0, 0, 0); c->wq = qopen(QMAX, Qkick, ipifckick, c); ifc = (Ipifc*)c->ptcl; ifc->conv = c; ifc->unbinding = 0; ifc->m = nil; ifc->reassemble = 0; } /* * called after last close of ipifc data or ctl * called with c locked, we must unlock */ static void ipifcclose(Conv *c) { Ipifc *ifc; Medium *m; ifc = (Ipifc*)c->ptcl; m = ifc->m; if(m != nil && m->unbindonclose) ipifcunbind(ifc); } /* * 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->mintu || mtu > ifc->m->maxtu) return Ebadarg; ifc->maxtu = mtu; return nil; } /* * add an address to an interface. */ char* ipifcadd(Ipifc *ifc, char **argv, int argc, int tentative, Iplifc *lifcp) { uchar ip[IPaddrlen], mask[IPaddrlen], rem[IPaddrlen]; uchar bcast[IPaddrlen], net[IPaddrlen]; Iplifc *lifc, **l; int i, type, mtu; Fs *f; int sendnbrdisc = 0; if(ifc->m == nil) return "ipifc not yet bound to device"; f = ifc->conv->p->f; type = Rifc; memset(ip, 0, IPaddrlen); memset(mask, 0, IPaddrlen); memset(rem, 0, IPaddrlen); switch(argc){ case 6: if(strcmp(argv[5], "proxy") == 0) type |= Rproxy; /* fall through */ case 5: mtu = strtoul(argv[4], 0, 0); if(mtu >= ifc->m->mintu && mtu <= ifc->m->maxtu) ifc->maxtu = 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(isv4(ip)) tentative = 0; 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) { 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; } 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->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 = NOW / 10^3; } lifc->next = nil; for(l = &ifc->lifc; *l; l = &(*l)->next) ; *l = lifc; /* check for point-to-point interface */ if(ipcmp(ip, v6loopback)) /* skip v6 loopback, it's a special address */ if(ipcmp(mask, IPallbits) == 0) type |= Rptpt; /* add local routes */ if(isv4(ip)) v4addroute(f, tifc, rem+IPv4off, mask+IPv4off, rem+IPv4off, type); else v6addroute(f, tifc, rem, mask, rem, type); addselfcache(f, ifc, lifc, ip, Runi); if((type & (Rproxy|Rptpt)) == (Rproxy|Rptpt)){ ipifcregisterproxy(f, ifc, rem); goto out; } 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); /* 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); /* 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);