/* * remove a multicast address from an interface, called with c->car locked */ void ipifcremmulti(Conv *c, uint8_t *ma, uint8_t *ia) { Proc *up = externup(); 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 && 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); }
/* * remove a multicast address from an interface, called with c locked */ void ipifcremmulti(struct conv *c, uint8_t * ma, uint8_t * ia) { ERRSTACK(1); struct Ipmulti *multi, **l; struct Iplifc *lifc; struct conv **p; struct Ipifc *ifc; struct 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 == NULL) return; /* we don't have it open */ *l = multi->next; for (p = f->ipifc->conv; *p; p++) { if ((*p)->inuse == 0) continue; ifc = (struct Ipifc *)(*p)->ptcl; if (waserror()) { wunlock(&ifc->rwlock); nexterror(); } wlock(&ifc->rwlock); for (lifc = ifc->lifc; lifc; lifc = lifc->next) if (ipcmp(ia, lifc->local) == 0) remselfcache(f, ifc, lifc, ma); wunlock(&ifc->rwlock); poperror(); } kfree(multi); }
/* * 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; }