/* * remove a logical interface from an ifc * always called with ifc wlock'd */ static char* ipifcremlifc(Ipifc *ifc, Iplifc *lifc) { Iplifc **l; Fs *f; f = ifc->conv->p->f; /* * find address on this interface and remove from chain. * for pt to pt we actually specify the remote address as the * addresss to remove. */ for(l = &ifc->lifc; *l != nil && *l != lifc; l = &(*l)->next) ; if(*l == nil) return "address not on this interface"; *l = lifc->next; /* disassociate any addresses */ while(lifc->link) remselfcache(f, ifc, lifc, lifc->link->self->a); /* remove the route for this logical interface */ if(isv4(lifc->local)) v4delroute(f, lifc->remote+IPv4off, lifc->mask+IPv4off, 1); else { v6delroute(f, lifc->remote, lifc->mask, 1); if(ipcmp(lifc->local, v6loopback) == 0) /* remove route for all node multicast */ v6delroute(f, v6allnodesN, v6allnodesNmask, 1); else if(memcmp(lifc->local, v6linklocal, v6llpreflen) == 0) /* remove route for all link multicast */ v6delroute(f, v6allnodesL, v6allnodesLmask, 1); } free(lifc); return nil; }
// added for new v6 mesg types static void adddefroute6(struct Fs *f, uint8_t * gate, int force) { struct route *r; r = v6lookup(f, v6Unspecified, NULL); if (r != NULL) if (!(force) && (strcmp(r->rt.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); }
/* added for new v6 mesg types */ static void adddefroute6(Fs *f, uint8_t *gate, int force) { Route *r; r = v6lookup(f, v6Unspecified, nil); /* * route entries generated by all other means take precedence * over router announcements. */ if (r && !force && strcmp(r->tag, "ra") != 0) return; v6delroute(f, v6Unspecified, v6Unspecified, 1); v6addroute(f, "ra", v6Unspecified, v6Unspecified, gate, 0); }
/* * 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(Fs *f, Ipifc *ifc, Iplifc *lifc, uint8_t *a) { Ipself *p, **l; Iplink *link, **l_self, **l_lifc; qlock(f->self); /* find the unique selftab entry */ l = &f->self->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 */ l_lifc = &lifc->link; for(link = *l_lifc; link; link = *l_lifc){ if(link->self == p) break; l_lifc = &link->lifclink; } if(link == nil) goto out; /* * walk down the links from the selftab looking for * the one we just found */ l_self = &p->link; for(link = *l_self; link; link = *l_self){ if(link == *l_lifc) break; l_self = &link->selflink; } if(link == nil) panic("remselfcache"); if(--(link->ref) != 0) goto out; if((p->type & Rmulti) && ifc->medium->remmulti != nil) (*ifc->medium->remmulti)(ifc, a, lifc->local); /* ref == 0, remove from both chains and free the link */ *l_lifc = link->lifclink; *l_self = link->selflink; iplinkfree(link); if(p->link != nil) goto out; /* remove from routing table */ if(isv4(a)) v4delroute(f, a+IPv4off, IPallbits+IPv4off, 1); else v6delroute(f, a, IPallbits, 1); /* 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) f->self->acceptall = 0; out: qunlock(f->self); }