81728a538d
rtinit[1]() is a function used to add or remove interface address prefix routes, similar to ifa_maintain_loopback_route(). It was intended to be family-agnostic. There is a problem with this approach in reality. 1) IPv6 code does not use it for the ifa routes. There is a separate layer, nd6_prelist_(), providing interface for maintaining interface routes. Its part, responsible for the actual route table interaction, mimics rtenty() code. 2) rtinit tries to combine multiple actions in the same function: constructing proper route attributes and handling iterations over multiple fibs, for the non-zero net.add_addr_allfibs use case. It notably increases the code complexity. 3) dstaddr handling. flags parameter re-uses RTF_ flags. As there is no special flag for p2p connections, host routes and p2p routes are handled in the same way. Additionally, mapping IFA flags to RTF flags makes the interface pretty messy. It make rtinit() to clash with ifa_mainain_loopback_route() for IPV4 interface aliases. 4) rtinit() is the last customer passing non-masked prefixes to rib_action(), complicating rib_action() implementation. 5) rtinit() coupled ifa announce/withdrawal notifications, producing "false positive" ifa messages in certain corner cases. To address all these points, the following has been done: * rtinit() has been split into multiple functions: - Route attribute construction were moved to the per-address-family functions, dealing with (2), (3) and (4). - funnction providing net.add_addr_allfibs handling and route rtsock notificaions is the new routing table inteface. - rtsock ifa notificaion has been moved out as well. resulting set of funcion are only responsible for the actual route notifications. Side effects: * /32 alias does not result in interface routes (/32 route and "host" route) * RTF_PINNED is now set for IPv6 prefixes corresponding to the interface addresses Differential revision: https://reviews.freebsd.org/D28186
150 lines
5.5 KiB
C
150 lines
5.5 KiB
C
/*-
|
|
* SPDX-License-Identifier: BSD-2-Clause-FreeBSD
|
|
*
|
|
* Copyright (c) 2020 Alexander V. Chernikov
|
|
*
|
|
* 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.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
|
|
*
|
|
* $FreeBSD$
|
|
*/
|
|
|
|
/*
|
|
* This header file contains public functions and structures used for
|
|
* routing table manipulations.
|
|
*/
|
|
|
|
#ifndef _NET_ROUTE_ROUTE_CTL_H_
|
|
#define _NET_ROUTE_ROUTE_CTL_H_
|
|
|
|
struct rib_cmd_info {
|
|
uint8_t rc_cmd; /* RTM_ADD|RTM_DEL|RTM_CHANGE */
|
|
uint8_t spare[3];
|
|
uint32_t rc_nh_weight; /* new nhop weight */
|
|
struct rtentry *rc_rt; /* Target entry */
|
|
struct nhop_object *rc_nh_old; /* Target nhop OR mpath */
|
|
struct nhop_object *rc_nh_new; /* Target nhop OR mpath */
|
|
};
|
|
|
|
int rib_add_route(uint32_t fibnum, struct rt_addrinfo *info,
|
|
struct rib_cmd_info *rc);
|
|
int rib_del_route(uint32_t fibnum, struct rt_addrinfo *info,
|
|
struct rib_cmd_info *rc);
|
|
int rib_change_route(uint32_t fibnum, struct rt_addrinfo *info,
|
|
struct rib_cmd_info *rc);
|
|
int rib_action(uint32_t fibnum, int action, struct rt_addrinfo *info,
|
|
struct rib_cmd_info *rc);
|
|
int rib_handle_ifaddr_info(uint32_t fibnum, int cmd, struct rt_addrinfo *info);
|
|
|
|
typedef void route_notification_t(struct rib_cmd_info *rc, void *);
|
|
void rib_decompose_notification(struct rib_cmd_info *rc,
|
|
route_notification_t *cb, void *cbdata);
|
|
|
|
int rib_add_redirect(u_int fibnum, struct sockaddr *dst,
|
|
struct sockaddr *gateway, struct sockaddr *author, struct ifnet *ifp,
|
|
int flags, int expire_sec);
|
|
|
|
enum rib_walk_hook {
|
|
RIB_WALK_HOOK_PRE, /* Hook is called before iteration */
|
|
RIB_WALK_HOOK_POST, /* Hook is called after iteration */
|
|
};
|
|
typedef int rib_walktree_f_t(struct rtentry *, void *);
|
|
typedef void rib_walk_hook_f_t(struct rib_head *rnh, enum rib_walk_hook stage,
|
|
void *arg);
|
|
void rib_walk(uint32_t fibnum, int af, bool wlock, rib_walktree_f_t *wa_f,
|
|
void *arg);
|
|
void rib_walk_ext(uint32_t fibnum, int af, bool wlock, rib_walktree_f_t *wa_f,
|
|
rib_walk_hook_f_t *hook_f, void *arg);
|
|
void rib_walk_ext_internal(struct rib_head *rnh, bool wlock,
|
|
rib_walktree_f_t *wa_f, rib_walk_hook_f_t *hook_f, void *arg);
|
|
|
|
void rib_walk_del(u_int fibnum, int family, rib_filter_f_t *filter_f,
|
|
void *arg, bool report);
|
|
|
|
void rib_foreach_table_walk(int family, bool wlock, rib_walktree_f_t *wa_f,
|
|
rib_walk_hook_f_t *hook_f, void *arg);
|
|
void rib_foreach_table_walk_del(int family, rib_filter_f_t *filter_f, void *arg);
|
|
|
|
struct nhop_object;
|
|
struct nhgrp_object;
|
|
struct route_nhop_data {
|
|
union {
|
|
struct nhop_object *rnd_nhop;
|
|
struct nhgrp_object *rnd_nhgrp;
|
|
};
|
|
uint32_t rnd_weight;
|
|
};
|
|
|
|
const struct rtentry *rib_lookup_prefix(uint32_t fibnum, int family,
|
|
const struct sockaddr *dst, const struct sockaddr *netmask,
|
|
struct route_nhop_data *rnd);
|
|
const struct rtentry *rib_lookup_lpm(uint32_t fibnum, int family,
|
|
const struct sockaddr *dst, struct route_nhop_data *rnd);
|
|
|
|
/* rtentry accessors */
|
|
bool rt_is_host(const struct rtentry *rt);
|
|
sa_family_t rt_get_family(const struct rtentry *);
|
|
struct nhop_object *rt_get_raw_nhop(const struct rtentry *rt);
|
|
#ifdef INET
|
|
struct in_addr;
|
|
void rt_get_inet_prefix_plen(const struct rtentry *rt, struct in_addr *paddr,
|
|
int *plen, uint32_t *pscopeid);
|
|
void rt_get_inet_prefix_pmask(const struct rtentry *rt, struct in_addr *paddr,
|
|
struct in_addr *pmask, uint32_t *pscopeid);
|
|
#endif
|
|
#ifdef INET6
|
|
struct in6_addr;
|
|
void rt_get_inet6_prefix_plen(const struct rtentry *rt, struct in6_addr *paddr,
|
|
int *plen, uint32_t *pscopeid);
|
|
void rt_get_inet6_prefix_pmask(const struct rtentry *rt, struct in6_addr *paddr,
|
|
struct in6_addr *pmask, uint32_t *pscopeid);
|
|
#endif
|
|
|
|
/* Nexthops */
|
|
uint32_t nhops_get_count(struct rib_head *rh);
|
|
|
|
/* Multipath */
|
|
struct weightened_nhop;
|
|
|
|
struct weightened_nhop *nhgrp_get_nhops(struct nhgrp_object *nhg,
|
|
uint32_t *pnum_nhops);
|
|
uint32_t nhgrp_get_count(struct rib_head *rh);
|
|
|
|
/* Route subscriptions */
|
|
enum rib_subscription_type {
|
|
RIB_NOTIFY_IMMEDIATE,
|
|
RIB_NOTIFY_DELAYED
|
|
};
|
|
|
|
struct rib_subscription;
|
|
typedef void rib_subscription_cb_t(struct rib_head *rnh, struct rib_cmd_info *rc,
|
|
void *arg);
|
|
|
|
struct rib_subscription *rib_subscribe(uint32_t fibnum, int family,
|
|
rib_subscription_cb_t *f, void *arg, enum rib_subscription_type type,
|
|
bool waitok);
|
|
struct rib_subscription *rib_subscribe_internal(struct rib_head *rnh,
|
|
rib_subscription_cb_t *f, void *arg, enum rib_subscription_type type,
|
|
bool waitok);
|
|
void rib_unsibscribe(struct rib_subscription *rs);
|
|
|
|
#endif
|