diff --git a/sys/net/if_ovpn.c b/sys/net/if_ovpn.c --- a/sys/net/if_ovpn.c +++ b/sys/net/if_ovpn.c @@ -75,6 +75,8 @@ #include +#include + #include "if_ovpn.h" struct ovpn_kkey_dir { @@ -141,6 +143,7 @@ struct ovpn_softc *sc; struct sockaddr_storage local; struct sockaddr_storage remote; + struct route_cache rc; struct in_addr vpn4; struct in6_addr vpn6; @@ -490,6 +493,7 @@ /* The peer should have been removed from the list already. */ MPASS(ovpn_find_peer(sc, peer->peerid) == NULL); + route_cache_unsubscribe_rib_event(&peer->rc); ovpn_notify_del_peer(sc, peer); for (int i = 0; i < 2; i++) { @@ -502,6 +506,7 @@ callout_stop(&peer->ping_send); callout_stop(&peer->ping_rcv); uma_zfree_pcpu(pcpu_zone_4, peer->last_active); + route_cache_uninit(&peer->rc, peer->remote.ss_family); free(peer, M_OVPN); if (! locked) @@ -671,7 +676,11 @@ goto error_locked; } + route_cache_init(&peer->rc, peer->remote.ss_family); OVPN_WUNLOCK(sc); + // FIXME: will proc fibnum change ? + route_cache_subscribe_rib_event(&peer->rc, peer->remote.ss_family, + curthread->td_proc->p_fibnum); goto done; @@ -2001,6 +2010,8 @@ struct sockaddr_in *in_local = TO_IN(&peer->local); struct sockaddr_in *in_remote = TO_IN(&peer->remote); struct ip *ip; + struct route *ro; + int error; /* * This requires knowing the source IP, which we don't. Happily @@ -2037,7 +2048,10 @@ OVPN_RUNLOCK(sc); OVPN_COUNTER_ADD(sc, transport_bytes_sent, m->m_pkthdr.len); - return (ip_output(m, NULL, NULL, 0, NULL, NULL)); + ro = route_cache_acquire(&peer->rc); + error = ip_output(m, NULL, ro, 0, NULL, NULL); + route_cache_release(ro); + return (error); } #endif #ifdef INET6 @@ -2045,6 +2059,8 @@ struct sockaddr_in6 *in6_local = TO_IN6(&peer->local); struct sockaddr_in6 *in6_remote = TO_IN6(&peer->remote); struct ip6_hdr *ip6; + struct route_in6 *ro; + int error; M_PREPEND(m, sizeof(struct ip6_hdr), M_NOWAIT); if (m == NULL) { @@ -2084,8 +2100,11 @@ OVPN_RUNLOCK(sc); OVPN_COUNTER_ADD(sc, transport_bytes_sent, m->m_pkthdr.len); - return (ip6_output(m, NULL, NULL, IPV6_UNSPECSRC, NULL, NULL, - NULL)); + ro = route_cache_acquire6(&peer->rc); + error = ip6_output(m, NULL, ro, IPV6_UNSPECSRC, NULL, NULL, + NULL); + route_cache_release6(ro); + return (error); } #endif default: