📄 ipifc.c
字号:
x = nil; memset(xmask, 0, IPaddrlen); /* find most specific match */ 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){ maskip(remote, lifc->mask, gnet); if(ipcmp(gnet, lifc->net) == 0){ if(x == nil || ipcmp(lifc->mask, xmask) > 0){ x = ifc; ipmove(xmask, lifc->mask); } } } } if(x != nil) return x; /* for now for broadcast and multicast, just use first interface */ if(type & (Rbcast|Rmulti)){ for(cp = f->ipifc->conv; cp < e; cp++){ if(*cp == 0) continue; ifc = (Ipifc*)(*cp)->ptcl; if(ifc->lifc != nil) return ifc; } } return nil;}enum { unknownv6, multicastv6, unspecifiedv6, linklocalv6, sitelocalv6, globalv6,};intv6addrtype(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 >= (NOW/10^3) ) || ( (lifc)->preflt == 0xffffffff ))static voidfindprimaryipv6(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; } } }}/* * returns first ip address configured */static voidfindprimaryipv4(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; if((lifc = ifc->lifc) != nil){ ipmove(local, lifc->local); return; } }}/* * find the local address 'closest' to the remote system, copy it to * local and return the ifc for that address */voidfindlocalip(Fs *f, uchar *local, uchar *remote){ Ipifc *ifc; Iplifc *lifc; Route *r; uchar gate[IPaddrlen]; uchar gnet[IPaddrlen]; int version; int atype = unspecifiedv6, atypel = unknownv6; USED(atype); USED(atypel); qlock(f->ipifc); r = v6lookup(f, remote, nil); version = (memcmp(remote, v4prefix, IPv4off) == 0) ? V4 : V6; if(r != nil){ ifc = r->ifc; if(r->type & Rv4) v4tov6(gate, r->v4.gate); else { ipmove(gate, r->v6.gate); ipmove(local, v6Unspecified); } /* find ifc address closest to the gateway to use */ switch(version) { case V4: 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; } } break; case V6: 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; break; default: panic("findlocalip: version %d", version); } } switch(version){ case V4: findprimaryipv4(f, local); break; case V6: findprimaryipv6(f, local); break; default: panic("findlocalip2: version %d", version); }out: qunlock(f->ipifc);}/* * return first v4 address associated with an interface */intipv4local(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 */intipv6local(Ipifc *ifc, uchar *addr){ Iplifc *lifc; for(lifc = ifc->lifc; lifc; lifc = lifc->next){ if(!isv4(lifc->local) && !(lifc->tentative)){ ipmove(addr, lifc->local); return 1; } } return 0;}intipv6anylocal(Ipifc *ifc, uchar *addr){ Iplifc *lifc; for(lifc = ifc->lifc; lifc; lifc = lifc->next){ if(!isv4(lifc->local)){ ipmove(addr, lifc->local); return SRC_UNI; } } return SRC_UNSPEC;}/* * 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 */intipproxyifc(Fs *f, Ipifc *ifc, uchar *ip){ Route *r; uchar net[IPaddrlen]; Iplifc *lifc; /* see if this is a direct connected pt to pt address */ r = v6lookup(f, ip, nil); if(r == nil) return 0; if((r->type & (Rifc|Rproxy)) != (Rifc|Rproxy)) 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 */intipismulticast(uchar *ip){ if(isv4(ip)){ if(ip[IPv4off] >= 0xe0 && ip[IPv4off] < 0xf0) return V4; } else { if(ip[0] == 0xff) return V6; } return 0;}intipisbm(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;}/* * add a multicast address to an interface, called with c->car locked */voidipifcaddmulti(Conv *c, uchar *ma, uchar *ia){ Ipifc *ifc; Iplifc *lifc; Conv **p; Ipmulti *multi, **l; Fs *f; f = c->p->f; 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 = f->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(f, ifc, lifc, ma, Rmulti); wunlock(ifc); poperror(); }}/* * remove a multicast address from an interface, called with c->car locked */voidipifcremmulti(Conv *c, uchar *ma, uchar *ia){ Ipmulti *multi, **l; Iplifc *lifc; Conv **p; Ipifc *ifc; Fs *f; f = c->p->f; 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 = f->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(f, 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;}static voidipifcregisterproxy(Fs *f, Ipifc *ifc, uchar *ip){ Conv **cp, **e; Ipifc *nifc; Iplifc *lifc; Medium *m; uchar net[IPaddrlen]; /* register the address on any network that will proxy for us */ e = &f->ipifc->conv[f->ipifc->nc]; 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; } } runlock(nifc); } 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 typesstatic voidadddefroute6(Fs *f, uchar *gate, int force){ Route *r; r = v6lookup(f, v6Unspecified, nil); 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*ipifcaddpref6(Ipifc *ifc, char**argv, int argc){ uchar onlink = 1; uchar autoflag = 1; long validlt = 0xffffffff; long preflt = 0xffffffff; long origint = NOW / 10^3; uchar prefix[IPaddrlen]; int plen = 64; Iplifc *lifc; char addr[40], preflen[6]; 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 < 0) || (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); sprint(preflen, "/%d", plen); params[0] = "add"; params[1] = addr; params[2] = preflen; return ipifcadd(ifc, params, 3, 0, lifc);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -