Implement fib*_lookup_nh_basic to provide fast non-refcounted

way to determine egress ifp / mtu.
This commit is contained in:
Alexander V. Chernikov 2014-10-12 11:22:25 +00:00
parent c81ab40b6a
commit 9ae91cc416
5 changed files with 469 additions and 169 deletions

View File

@ -3254,6 +3254,7 @@ net/radix_mpath.c standard
net/raw_cb.c standard
net/raw_usrreq.c standard
net/route.c standard
net/rt_nhops.c standard
net/rtsock.c standard
net/slcompress.c optional netgraph_vjc | sppp | \
netgraph_sppp

240
sys/net/rt_nhops.c Normal file
View File

@ -0,0 +1,240 @@
/*-
* Copyright (c) 2014
* Alexander V. Chernikov <melifaro@FreeBSD.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
/*
* Temporary file. In future it should be split between net/route.c
* and per-AF files like netinet/in_rmx.c | netinet6/in6_rmx.c
*/
#include "opt_inet.h"
#include "opt_inet6.h"
#include "opt_route.h"
#include "opt_mpath.h"
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/syslog.h>
#include <sys/malloc.h>
#include <sys/mbuf.h>
#include <sys/socket.h>
#include <sys/sysctl.h>
#include <sys/syslog.h>
#include <sys/sysproto.h>
#include <sys/proc.h>
#include <sys/domain.h>
#include <sys/kernel.h>
#include <sys/sbuf.h>
#include <net/if.h>
#include <net/if_var.h>
#include <net/if_dl.h>
#include <net/route.h>
#include <net/vnet.h>
#ifdef RADIX_MPATH
#include <net/radix_mpath.h>
#endif
#include <netinet/in.h>
#include <netinet/ip_mroute.h>
#include <netinet/ip6.h>
#include <net/rt_nhops.h>
#include <vm/uma.h>
struct fwd_info {
fib_lookup_t *lookup;
void *state;
};
#define FWD_FSM_NONE 0
#define FWD_FSM_INIT 1
#define FWD_FSM_FWD 2
struct fwd_control {
int fwd_state; /* FSM */
struct fwd_module *fm;
};
#if 0
static struct fwd_info *fwd_db[FWD_SIZE];
static struct fwd_control *fwd_ctl[FWD_SIZE];
static TAILQ_HEAD(fwd_module_list, fwd_module) modulehead = TAILQ_HEAD_INITIALIZER(modulehead);
static struct fwd_module_list fwd_modules[FWD_SIZE];
static uint8_t fwd_map_af[] = {
AF_INET,
AF_INET6,
};
static struct rwlock fwd_lock;
#define FWD_LOCK_INIT() rw_init(&fwd_lock, "fwd_lock")
#define FWD_RLOCK() rw_rlock(&fwd_lock)
#define FWD_RUNLOCK() rw_runlock(&fwd_lock)
#define FWD_WLOCK() rw_wlock(&fwd_lock)
#define FWD_WUNLOCK() rw_wunlock(&fwd_lock)
int fwd_attach_fib(struct fwd_module *fm, u_int fib);
int fwd_destroy_fib(struct fwd_module *fm, u_int fib);
#endif
MALLOC_DEFINE(M_RTFIB, "rtfib", "routing fwd");
/*
* Per-AF fast routines returning minimal needed info.
* It is not safe to dereference any pointers since it
* may end up with use-after-free case.
* Typically it may be used to check if outgoing
* interface matches or to calculate proper MTU.
*
* Note that returned interface pointer is logical one,
* e.g. actual transmit ifp may be different.
* Difference may be triggered by
* 1) loopback routes installed for interface addresses.
* e.g. for address 10.0.0.1 with prefix /24 bound to
* interface ix0, "logical" interface will be "ix0",
* while "trasmit" interface will be "lo0" since this is
* loopback route. You should consider using other
* functions if you need "transmit" interface or both.
*
*
* Returns 0 on match, error code overwise.
*/
#define NHOP_FLAGS_MASK (RTF_REJECT|RTF_BLACKHOLE)
//#define NHOP_DIRECT
#define RNTORT(p) ((struct rtentry *)(p))
#ifdef INET
int
fib4_lookup_nh_basic(uint32_t fibnum, struct in_addr dst, uint32_t flowid,
struct nhop4_basic *pnh4)
{
struct radix_node_head *rnh;
struct radix_node *rn;
struct sockaddr_in *gw, sin;
struct rtentry *rte;
KASSERT((fibnum < rt_numfibs), ("fib4_lookup_nh_basic: bad fibnum"));
rnh = rt_tables_get_rnh(fibnum, AF_INET);
if (rnh == NULL)
return (ENOENT);
/* Prepare lookup key */
memset(&sin, 0, sizeof(sin));
sin.sin_addr = dst;
RADIX_NODE_HEAD_RLOCK(rnh);
rn = rnh->rnh_matchaddr((void *)&sin, rnh);
if (rn != NULL && ((rn->rn_flags & RNF_ROOT) == 0)) {
rte = RNTORT(rn);
/* Ensure route & ifp is UP */
if (RT_LINK_IS_UP(rte->rt_ifp)) {
pnh4->nh_ifp = rte->rt_ifa->ifa_ifp;
pnh4->nh_mtu = min(rte->rt_mtu, rte->rt_ifp->if_mtu);
if (rte->rt_flags & RTF_GATEWAY) {
gw = (struct sockaddr_in *)rte->rt_gateway;
pnh4->nh_addr = gw->sin_addr;
} else
pnh4->nh_addr = dst;
/* Set flags */
pnh4->nh_flags = rte->rt_flags & NHOP_FLAGS_MASK;
gw = (struct sockaddr_in *)rt_key(rte);
if (gw->sin_addr.s_addr == 0)
pnh4->nh_flags |= NHOP_DEFAULT;
RADIX_NODE_HEAD_RUNLOCK(rnh);
return (0);
}
}
RADIX_NODE_HEAD_RUNLOCK(rnh);
return (ENOENT);
}
#endif
#ifdef INET6
int
fib6_lookup_nh_basic(uint32_t fibnum, struct in6_addr dst, uint32_t flowid,
struct nhop6_basic *pnh6)
{
struct radix_node_head *rnh;
struct radix_node *rn;
struct sockaddr_in6 *gw, sin6;
struct rtentry *rte;
KASSERT((fibnum < rt_numfibs), ("fib6_lookup_nh_basic: bad fibnum"));
rnh = rt_tables_get_rnh(fibnum, AF_INET);
if (rnh == NULL)
return (ENOENT);
/* Prepare lookup key */
memset(&sin6, 0, sizeof(sin6));
sin6.sin6_addr = dst;
RADIX_NODE_HEAD_RLOCK(rnh);
rn = rnh->rnh_matchaddr((void *)&sin6, rnh);
if (rn != NULL && ((rn->rn_flags & RNF_ROOT) == 0)) {
rte = RNTORT(rn);
/* Ensure route & ifp is UP */
if (RT_LINK_IS_UP(rte->rt_ifp)) {
pnh6->nh_ifp = rte->rt_ifa->ifa_ifp;
pnh6->nh_mtu = min(rte->rt_mtu, rte->rt_ifp->if_mtu);
if (rte->rt_flags & RTF_GATEWAY) {
gw = (struct sockaddr_in6 *)rte->rt_gateway;
pnh6->nh_addr = gw->sin6_addr;
} else
pnh6->nh_addr = dst;
/* Set flags */
pnh6->nh_flags = rte->rt_flags & NHOP_FLAGS_MASK;
gw = (struct sockaddr_in6 *)rt_key(rte);
if (IN6_IS_ADDR_UNSPECIFIED(&gw->sin6_addr))
pnh6->nh_flags |= NHOP_DEFAULT;
RADIX_NODE_HEAD_RUNLOCK(rnh);
return (0);
}
}
RADIX_NODE_HEAD_RUNLOCK(rnh);
return (ENOENT);
}
#endif

178
sys/net/rt_nhops.h Normal file
View File

@ -0,0 +1,178 @@
/*-
* Copyright (c) 2014
* Alexander V. Chernikov <melifaro@FreeBSD.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#ifndef _NET_RT_NHOPS_H_
#define _NET_RT_NHOPS_H_
#define MAX_PREPEND_LEN 64 /* Max data that can be prepended */
#define NH_TYPE_DIRECT 1 /* Directly reachable, no data */
#define NH_TYPE_BLACKHOLE 2 /* Blackhole route */
#define NH_TYPE_REJECT 3 /* Send reject */
#define NH_TYPE_L2 4 /* Provides full prepend header */
#define NH_TYPE_MUTATOR 5 /* NH+callback function */
#define NH_TYPE_MULTIPATH 6 /* Multipath route */
struct nhop_info {
uint64_t refcnt; /* Use references */
uint64_t flags; /* Options */
};
/* Multipath nhop info */
struct nhop_mpath_info {
uint16_t nhop; /* Netxthop id */
};
/* mutator info */
struct nhop_mutator_info;
struct nhop_data;
typedef int nhop_mutate_t(struct mbuf **, struct nhop_data *nd, void *storage);
struct nhop_mutator_info {
nhop_mutate_t *func;
char data[];
};
/* Structure used for forwarding purposes */
struct nhop_data {
uint8_t flags; /* NH flags */
uint8_t count; /* Number of nexthops or data length */
uint16_t mtu;
uint16_t lifp_idx; /* Logical interface index */
uint16_t ifp_idx; /* Transmit interface index */
union {
struct nhop_mpath_info mp[32]; /* Multipath info */
struct nhop_mutator_info mm; /* mutator info */
char data[MAX_PREPEND_LEN - 8]; /* data to prepend */
} d;
};
/* Per-AF per-fib nhop table */
struct nhops_descr {
uint32_t nhop_size; /* Nehthop data size */
uint32_t nhops_max; /* Max number of nhops */
void *nhops_data; /* Pointer to nhop data table */
void *nhops_info; /* Pointer to nhop info table */
};
#if 0
typedef int nhop_resolve_t(struct sockaddr *dst, u_int fib, struct nhop_data *nd, struct nhop_info *nf);
int
lla_create_notify(struct sockaddr *dst, u_int fib, lla_notify_t *func, void *state, int flags);
#endif
/* Basic nexthop info used for uRPF/mtu checks */
struct nhop4_basic {
struct ifnet *nh_ifp; /* Logical egress interface */
uint16_t nh_mtu; /* nexthop mtu */
uint16_t nh_flags; /* nhop flags */
struct in_addr nh_addr; /* GW/DST IPv4 address */
};
struct nhop6_basic {
struct ifnet *nh_ifp; /* Logical egress interface */
uint16_t nh_mtu; /* nexthop mtu */
uint16_t nh_flags; /* nhop flags */
struct in6_addr nh_addr; /* GW/DST IPv4 address */
};
struct nhop64_basic {
union {
struct nhop4_basic nh4;
struct nhop6_basic nh6;
} u;
};
int fib4_lookup_nh_basic(uint32_t fibnum, struct in_addr dst, uint32_t flowid,
struct nhop4_basic *pnh4);
int fib6_lookup_nh_basic(uint32_t fibnum, struct in6_addr dst, uint32_t flowid,
struct nhop6_basic *pnh6);
#define NHOP_REJECT RTF_REJECT
#define NHOP_BLACKHOLE RTF_BLACKHOLE
#define NHOP_DEFAULT 0x80 /* Default route */
#define FWD_INET 0
#define FWD_INET6 1
#define FWD_SIZE 2
#define FWD_NAME_MAX 15
#define FWD_MULTIPATH 0x0001 /* has multipath support */
#define FWD_OLDMASKS 0x0002 /* has support for non-contig masks */
#define FWD_DEFAULT 0x0004 /* installs as default fib mechanism */
#define FWD_MANAGELOCK 0x0004 /* manage its own locking */
typedef void *fib_init_t(u_int fibnum);
typedef void fib_destroy_t(void *state);
typedef int fib_dump_t(void *state, struct radix_node_head *rnh);
typedef int fib_change_t(void *state, int req, struct rtentry *rte,
struct rt_addrinfo *info);
typedef int fib_lookup_t(void *state, void *key, uint64_t *attr, u_int flowid,
void *nhop);
/* Structure used by external module */
struct fwd_module_info {
uint8_t fwd_family; /* family we're registering to */
char name[FWD_NAME_MAX]; /* fwd module name */
uint32_t capabilities;
fib_init_t *fib_init;
fib_destroy_t *fib_destroy;
fib_dump_t *fib_dump;
fib_change_t *fib_change;
fib_lookup_t *fib_lookup;
};
/* Internal version of previous structure */
struct fwd_module {
TAILQ_ENTRY(fwd_module) list;
uint8_t fwd_family;
char name[FWD_NAME_MAX];
uint32_t capabilities;
fib_init_t *fib_init;
fib_destroy_t *fib_destroy;
fib_dump_t *fib_dump;
fib_change_t *fib_change;
fib_lookup_t *fib_lookup;
};
int fwd_attach_module(struct fwd_module_info *m, void **);
int fwd_destroy_module(void *state);
int fwd_change_fib(struct radix_node_head *rnh, int req, struct rtentry *rte,
struct rt_addrinfo *info);
#endif

View File

@ -89,6 +89,7 @@ __FBSDID("$FreeBSD$");
#include <netinet6/scope6_var.h>
#include <netinet6/ip6_var.h>
#endif
#include <net/rt_nhops.h>
#include <netpfil/ipfw/ip_fw_private.h>
@ -434,19 +435,10 @@ verify_path(struct in_addr src, struct ifnet *ifp, u_int fib)
#if defined(USERSPACE) || !defined(__FreeBSD__)
return 0;
#else
struct route ro;
struct sockaddr_in *dst;
struct nhop4_basic nh4;
bzero(&ro, sizeof(ro));
dst = (struct sockaddr_in *)&(ro.ro_dst);
dst->sin_family = AF_INET;
dst->sin_len = sizeof(*dst);
dst->sin_addr = src;
in_rtalloc_ign(&ro, 0, fib);
if (ro.ro_rt == NULL)
return 0;
if (fib4_lookup_nh_basic(fib, src, 0, &nh4) != 0)
return (0);
/*
* If ifp is provided, check for equality with rtentry.
@ -455,27 +447,18 @@ verify_path(struct in_addr src, struct ifnet *ifp, u_int fib)
* routing entry (via lo0) for our own address
* may exist, so we need to handle routing assymetry.
*/
if (ifp != NULL && ro.ro_rt->rt_ifa->ifa_ifp != ifp) {
RTFREE(ro.ro_rt);
return 0;
}
if (ifp != NULL && ifp != nh4.nh_ifp)
return (0);
/* if no ifp provided, check if rtentry is not default route */
if (ifp == NULL &&
satosin(rt_key(ro.ro_rt))->sin_addr.s_addr == INADDR_ANY) {
RTFREE(ro.ro_rt);
return 0;
}
if (ifp == NULL && (nh4.nh_flags & NHOP_DEFAULT) != 0)
return (0);
/* or if this is a blackhole/reject route */
if (ifp == NULL && ro.ro_rt->rt_flags & (RTF_REJECT|RTF_BLACKHOLE)) {
RTFREE(ro.ro_rt);
return 0;
}
if (ifp == NULL && (nh4.nh_flags & (NHOP_REJECT|NHOP_BLACKHOLE)) != 0)
return (0);
/* found valid route */
RTFREE(ro.ro_rt);
return 1;
return (1);
#endif /* __FreeBSD__ */
}
@ -530,49 +513,24 @@ search_ip6_addr_net (struct in6_addr * ip6_addr)
static int
verify_path6(struct in6_addr *src, struct ifnet *ifp, u_int fib)
{
struct route_in6 ro;
struct sockaddr_in6 *dst;
struct nhop6_basic nh6;
bzero(&ro, sizeof(ro));
if (fib6_lookup_nh_basic(fib, *src, 0, &nh6) != 0)
return (0);
dst = (struct sockaddr_in6 * )&(ro.ro_dst);
dst->sin6_family = AF_INET6;
dst->sin6_len = sizeof(*dst);
dst->sin6_addr = *src;
in6_rtalloc_ign(&ro, 0, fib);
if (ro.ro_rt == NULL)
return 0;
/*
* if ifp is provided, check for equality with rtentry
* We should use rt->rt_ifa->ifa_ifp, instead of rt->rt_ifp,
* to support the case of sending packets to an address of our own.
* (where the former interface is the first argument of if_simloop()
* (=ifp), the latter is lo0)
*/
if (ifp != NULL && ro.ro_rt->rt_ifa->ifa_ifp != ifp) {
RTFREE(ro.ro_rt);
return 0;
}
/* If ifp is provided, check for equality with route table. */
if (ifp != NULL && ifp != nh6.nh_ifp)
return (0);
/* if no ifp provided, check if rtentry is not default route */
if (ifp == NULL &&
IN6_IS_ADDR_UNSPECIFIED(&satosin6(rt_key(ro.ro_rt))->sin6_addr)) {
RTFREE(ro.ro_rt);
return 0;
}
if (ifp == NULL && (nh6.nh_flags & NHOP_DEFAULT) != 0)
return (0);
/* or if this is a blackhole/reject route */
if (ifp == NULL && ro.ro_rt->rt_flags & (RTF_REJECT|RTF_BLACKHOLE)) {
RTFREE(ro.ro_rt);
return 0;
}
/* found valid route */
RTFREE(ro.ro_rt);
return 1;
if (ifp == NULL && (nh6.nh_flags & (NHOP_REJECT|NHOP_BLACKHOLE)) != 0)
return (0);
return (1);
}
static int

View File

@ -96,6 +96,8 @@ __FBSDID("$FreeBSD$");
#include <netinet6/in6_pcb.h>
#endif /* INET6 */
#include <net/rt_nhops.h>
#include <machine/in_cksum.h>
#include <security/mac/mac_framework.h>
@ -2906,15 +2908,7 @@ pf_get_mss(struct mbuf *m, int off, u_int16_t th_off, sa_family_t af)
static u_int16_t
pf_calc_mss(struct pf_addr *addr, sa_family_t af, int rtableid, u_int16_t offer)
{
#ifdef INET
struct sockaddr_in *dst;
struct route ro;
#endif /* INET */
#ifdef INET6
struct sockaddr_in6 *dst6;
struct route_in6 ro6;
#endif /* INET6 */
struct rtentry *rt = NULL;
struct nhop64_basic nh;
int hlen = 0;
u_int16_t mss = V_tcp_mssdflt;
@ -2922,34 +2916,19 @@ pf_calc_mss(struct pf_addr *addr, sa_family_t af, int rtableid, u_int16_t offer)
#ifdef INET
case AF_INET:
hlen = sizeof(struct ip);
bzero(&ro, sizeof(ro));
dst = (struct sockaddr_in *)&ro.ro_dst;
dst->sin_family = AF_INET;
dst->sin_len = sizeof(*dst);
dst->sin_addr = addr->v4;
in_rtalloc_ign(&ro, 0, rtableid);
rt = ro.ro_rt;
if (fib4_lookup_nh_basic(rtableid, addr->v4, 0, &nh.u.nh4) == 0)
mss = nh.u.nh4.nh_mtu - hlen - sizeof(struct tcphdr);
break;
#endif /* INET */
#ifdef INET6
case AF_INET6:
hlen = sizeof(struct ip6_hdr);
bzero(&ro6, sizeof(ro6));
dst6 = (struct sockaddr_in6 *)&ro6.ro_dst;
dst6->sin6_family = AF_INET6;
dst6->sin6_len = sizeof(*dst6);
dst6->sin6_addr = addr->v6;
in6_rtalloc_ign(&ro6, 0, rtableid);
rt = ro6.ro_rt;
if (fib6_lookup_nh_basic(rtableid, addr->v6, 0, &nh.u.nh6) == 0)
mss = nh.u.nh6.nh_mtu - hlen - sizeof(struct tcphdr);
break;
#endif /* INET6 */
}
if (rt && rt->rt_ifp) {
mss = rt->rt_ifp->if_mtu - hlen - sizeof(struct tcphdr);
mss = max(V_tcp_mssdflt, mss);
RTFREE(rt);
}
mss = min(mss, offer);
mss = max(mss, 64); /* sanity - at least max opt space */
return (mss);
@ -5105,37 +5084,14 @@ int
pf_routable(struct pf_addr *addr, sa_family_t af, struct pfi_kif *kif,
int rtableid)
{
#ifdef RADIX_MPATH
struct radix_node_head *rnh;
#endif
struct sockaddr_in *dst;
int ret = 1;
int check_mpath;
#ifdef INET6
struct sockaddr_in6 *dst6;
struct route_in6 ro;
#else
struct route ro;
#endif
struct radix_node *rn;
struct rtentry *rt;
struct ifnet *ifp;
struct nhop64_basic nh;
check_mpath = 0;
#ifdef RADIX_MPATH
/* XXX: stick to table 0 for now */
rnh = rt_tables_get_rnh(0, af);
if (rnh != NULL && rn_mpath_capable(rnh))
check_mpath = 1;
#endif
bzero(&ro, sizeof(ro));
/* Skip checks for ipsec interfaces */
if (kif != NULL && kif->pfik_ifp->if_type == IFT_ENC)
return (0);
bzero(&nh, sizeof(nh));
switch (af) {
case AF_INET:
dst = satosin(&ro.ro_dst);
dst->sin_family = AF_INET;
dst->sin_len = sizeof(*dst);
dst->sin_addr = addr->v4;
break;
#ifdef INET6
case AF_INET6:
/*
@ -5143,66 +5099,33 @@ pf_routable(struct pf_addr *addr, sa_family_t af, struct pfi_kif *kif,
* as they would always match anyway.
*/
if (IN6_IS_SCOPE_EMBED(&addr->v6))
goto out;
dst6 = (struct sockaddr_in6 *)&ro.ro_dst;
dst6->sin6_family = AF_INET6;
dst6->sin6_len = sizeof(*dst6);
dst6->sin6_addr = addr->v6;
break;
#endif /* INET6 */
default:
return (0);
}
/* Skip checks for ipsec interfaces */
if (kif != NULL && kif->pfik_ifp->if_type == IFT_ENC)
goto out;
switch (af) {
#ifdef INET6
case AF_INET6:
in6_rtalloc_ign(&ro, 0, rtableid);
return (1);
if (fib6_lookup_nh_basic(rtableid, addr->v6, 0, &nh.u.nh6) != 0)
return (0);
break;
#endif
#ifdef INET
case AF_INET:
in_rtalloc_ign((struct route *)&ro, 0, rtableid);
if (fib4_lookup_nh_basic(rtableid, addr->v4, 0, &nh.u.nh4) != 0)
return (0);
break;
#endif
default:
rtalloc_ign((struct route *)&ro, 0); /* No/default FIB. */
break;
return (0);
}
if (ro.ro_rt != NULL) {
/* No interface given, this is a no-route check */
if (kif == NULL)
goto out;
/* No interface given, this is a no-route check */
if (kif == NULL)
return (1);
if (kif->pfik_ifp == NULL) {
ret = 0;
goto out;
}
if (kif->pfik_ifp == NULL)
return (0);
/* Perform uRPF check if passed input interface */
ret = 0;
rn = (struct radix_node *)ro.ro_rt;
do {
rt = (struct rtentry *)rn;
ifp = rt->rt_ifp;
/* Perform uRPF check if passed input interface */
if (kif->pfik_ifp == nh.u.nh4.nh_ifp)
return (1);
if (kif->pfik_ifp == ifp)
ret = 1;
#ifdef RADIX_MPATH
rn = rn_mpath_next(rn);
#endif
} while (check_mpath == 1 && rn != NULL && ret == 0);
} else
ret = 0;
out:
if (ro.ro_rt != NULL)
RTFREE(ro.ro_rt);
return (ret);
return (0);
}
#ifdef INET