Implement fib*_lookup_nh_basic to provide fast non-refcounted
way to determine egress ifp / mtu.
This commit is contained in:
parent
c81ab40b6a
commit
9ae91cc416
@ -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
240
sys/net/rt_nhops.c
Normal 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
178
sys/net/rt_nhops.h
Normal 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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user