/* * Check for alternatives when higher level complains * about service problems. For now, invalidate cached * routing information. If the route was created dynamically * (by a redirect), time to try a default gateway again. */ void in6_losing(struct in6pcb *in6p) { struct rtentry *rt; struct rt_addrinfo info; if (in6p->in6p_af != AF_INET6) return; if ((rt = rtcache_validate(&in6p->in6p_route)) == NULL) return; memset(&info, 0, sizeof(info)); info.rti_info[RTAX_DST] = rtcache_getdst(&in6p->in6p_route); info.rti_info[RTAX_GATEWAY] = rt->rt_gateway; info.rti_info[RTAX_NETMASK] = rt_mask(rt); rt_missmsg(RTM_LOSING, &info, rt->rt_flags, 0); if (rt->rt_flags & RTF_DYNAMIC) { (void)rtrequest(RTM_DELETE, rt_getkey(rt), rt->rt_gateway, rt_mask(rt), rt->rt_flags, NULL); } /* * A new route can be allocated * the next time output is attempted. */ rtcache_free(&in6p->in6p_route); }
void in6_pcbdetach(struct in6pcb *in6p) { struct socket *so = in6p->in6p_socket; int s; if (in6p->in6p_af != AF_INET6) return; #if defined(IPSEC) || defined(FAST_IPSEC) ipsec6_delete_pcbpolicy(in6p); #endif /* IPSEC */ so->so_pcb = 0; if (in6p->in6p_options) m_freem(in6p->in6p_options); if (in6p->in6p_outputopts != NULL) { ip6_clearpktopts(in6p->in6p_outputopts, -1); free(in6p->in6p_outputopts, M_IP6OPT); } rtcache_free(&in6p->in6p_route); ip6_freemoptions(in6p->in6p_moptions); s = splnet(); in6_pcbstate(in6p, IN6P_ATTACHED); LIST_REMOVE(&in6p->in6p_head, inph_lhash); CIRCLEQ_REMOVE(&in6p->in6p_table->inpt_queue, &in6p->in6p_head, inph_queue); pool_put(&in6pcb_pool, in6p); splx(s); sofree(so); /* drops the socket's lock */ mutex_enter(softnet_lock); /* reacquire it */ }
/* * After a routing change, flush old routing. A new route can be * allocated the next time output is attempted. */ void in6_rtchange(struct in6pcb *in6p, int errno) { if (in6p->in6p_af != AF_INET6) return; rtcache_free(&in6p->in6p_route); /* * A new route can be allocated the next time * output is attempted. */ }
static int gif_clone_destroy(struct ifnet *ifp) { struct gif_softc *sc = (void *) ifp; gif_delete_tunnel(&sc->gif_if); LIST_REMOVE(sc, gif_list); #ifdef INET6 encap_detach(sc->encap_cookie6); #endif #ifdef INET encap_detach(sc->encap_cookie4); #endif bpf_detach(ifp); if_detach(ifp); rtcache_free(&sc->gif_ro); free(sc, M_DEVBUF); return (0); }