svn commit: r367486 - head/sys/net/route

Alexander V. Chernikov melifaro at FreeBSD.org
Sun Nov 8 13:30:44 UTC 2020


Author: melifaro
Date: Sun Nov  8 13:30:44 2020
New Revision: 367486
URL: https://svnweb.freebsd.org/changeset/base/367486

Log:
  Fix build broken by r367484: add route_ifaddrs.c.
  
  Pointy hat to: melifaro
  Reported by:	jenkins

Added:
  head/sys/net/route/route_ifaddrs.c   (contents, props changed)

Added: head/sys/net/route/route_ifaddrs.c
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/sys/net/route/route_ifaddrs.c	Sun Nov  8 13:30:44 2020	(r367486)
@@ -0,0 +1,309 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1980, 1986, 1991, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * 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.
+ * 3. 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.
+ *
+ *	@(#)route.c	8.3.1.1 (Berkeley) 2/23/95
+ * $FreeBSD$
+ */
+
+#include "opt_mpath.h"
+#include "opt_route.h"
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/malloc.h>
+#include <sys/socket.h>
+#include <sys/sysctl.h>
+#include <sys/syslog.h>
+#include <sys/kernel.h>
+#include <sys/lock.h>
+#include <sys/rmlock.h>
+
+#include <net/if.h>
+#include <net/if_var.h>
+#include <net/if_dl.h>
+#include <net/route.h>
+#include <net/route/route_ctl.h>
+#include <net/route/route_var.h>
+#include <net/route/nhop.h>
+#include <net/vnet.h>
+
+#include <netinet/in.h>
+
+/*
+ * Control interface address fib propagation.
+ * By default, interface address routes are added to the fib of the interface.
+ * Once set to non-zero, adds interface address route to all fibs.
+ */
+VNET_DEFINE(u_int, rt_add_addr_allfibs) = 0;
+SYSCTL_UINT(_net, OID_AUTO, add_addr_allfibs, CTLFLAG_RWTUN | CTLFLAG_VNET,
+    &VNET_NAME(rt_add_addr_allfibs), 0, "");
+
+/*
+ * Set up a routing table entry, normally
+ * for an interface.
+ */
+static inline  int
+rtinit1(struct ifaddr *ifa, int cmd, int flags, int fibnum)
+{
+	RIB_RLOCK_TRACKER;
+	struct epoch_tracker et;
+	struct sockaddr *dst;
+	struct sockaddr *netmask;
+	struct rib_cmd_info rc;
+	struct rt_addrinfo info;
+	int error = 0;
+	int startfib, endfib;
+	struct sockaddr_storage ss;
+	int didwork = 0;
+	int a_failure = 0;
+	struct sockaddr_dl_short sdl;
+	struct rib_head *rnh;
+
+	if (flags & RTF_HOST) {
+		dst = ifa->ifa_dstaddr;
+		netmask = NULL;
+	} else {
+		dst = ifa->ifa_addr;
+		netmask = ifa->ifa_netmask;
+	}
+	if (dst->sa_len == 0)
+		return(EINVAL);
+	switch (dst->sa_family) {
+	case AF_INET6:
+	case AF_INET:
+		/* We support multiple FIBs. */
+		break;
+	default:
+		fibnum = RT_DEFAULT_FIB;
+		break;
+	}
+	if (fibnum == RT_ALL_FIBS) {
+		if (V_rt_add_addr_allfibs == 0 && cmd == (int)RTM_ADD)
+			startfib = endfib = ifa->ifa_ifp->if_fib;
+		else {
+			startfib = 0;
+			endfib = rt_numfibs - 1;
+		}
+	} else {
+		KASSERT((fibnum < rt_numfibs), ("rtinit1: bad fibnum"));
+		startfib = fibnum;
+		endfib = fibnum;
+	}
+
+	/*
+	 * If it's a delete, check that if it exists,
+	 * it's on the correct interface or we might scrub
+	 * a route to another ifa which would
+	 * be confusing at best and possibly worse.
+	 */
+	if (cmd == RTM_DELETE) {
+		/*
+		 * It's a delete, so it should already exist..
+		 * If it's a net, mask off the host bits
+		 * (Assuming we have a mask)
+		 * XXX this is kinda inet specific..
+		 */
+		if (netmask != NULL) {
+			rt_maskedcopy(dst, (struct sockaddr *)&ss, netmask);
+			dst = (struct sockaddr *)&ss;
+		}
+	}
+	bzero(&sdl, sizeof(struct sockaddr_dl_short));
+	sdl.sdl_family = AF_LINK;
+	sdl.sdl_len = sizeof(struct sockaddr_dl_short);
+	sdl.sdl_type = ifa->ifa_ifp->if_type;
+	sdl.sdl_index = ifa->ifa_ifp->if_index;
+	/*
+	 * Now go through all the requested tables (fibs) and do the
+	 * requested action. Realistically, this will either be fib 0
+	 * for protocols that don't do multiple tables or all the
+	 * tables for those that do.
+	 */
+	for ( fibnum = startfib; fibnum <= endfib; fibnum++) {
+		if (cmd == RTM_DELETE) {
+			struct radix_node *rn;
+			/*
+			 * Look up an rtentry that is in the routing tree and
+			 * contains the correct info.
+			 */
+			rnh = rt_tables_get_rnh(fibnum, dst->sa_family);
+			if (rnh == NULL)
+				/* this table doesn't exist but others might */
+				continue;
+			RIB_RLOCK(rnh);
+			rn = rnh->rnh_lookup(dst, netmask, &rnh->head);
+			error = (rn == NULL ||
+			    (rn->rn_flags & RNF_ROOT) ||
+			    RNTORT(rn)->rt_nhop->nh_ifa != ifa);
+			RIB_RUNLOCK(rnh);
+			if (error) {
+				/* this is only an error if bad on ALL tables */
+				continue;
+			}
+		}
+		/*
+		 * Do the actual request
+		 */
+		bzero((caddr_t)&info, sizeof(info));
+		info.rti_ifa = ifa;
+		info.rti_flags = flags |
+		    (ifa->ifa_flags & ~IFA_RTSELF) | RTF_PINNED;
+		info.rti_info[RTAX_DST] = dst;
+		info.rti_info[RTAX_GATEWAY] = (struct sockaddr *)&sdl;
+		info.rti_info[RTAX_NETMASK] = netmask;
+		NET_EPOCH_ENTER(et);
+		error = rib_action(fibnum, cmd, &info, &rc);
+		if (error == 0 && rc.rc_rt != NULL) {
+			/*
+			 * notify any listening routing agents of the change
+			 */
+
+			/* TODO: interface routes/aliases */
+			rt_newaddrmsg_fib(cmd, ifa, rc.rc_rt, fibnum);
+			didwork = 1;
+		}
+		NET_EPOCH_EXIT(et);
+		if (error)
+			a_failure = error;
+	}
+	if (cmd == RTM_DELETE) {
+		if (didwork) {
+			error = 0;
+		} else {
+			/* we only give an error if it wasn't in any table */
+			error = ((flags & RTF_HOST) ?
+			    EHOSTUNREACH : ENETUNREACH);
+		}
+	} else {
+		if (a_failure) {
+			/* return an error if any of them failed */
+			error = a_failure;
+		}
+	}
+	return (error);
+}
+
+/*
+ * Set up a routing table entry, normally
+ * for an interface.
+ */
+int
+rtinit(struct ifaddr *ifa, int cmd, int flags)
+{
+	struct sockaddr *dst;
+	int fib = RT_DEFAULT_FIB;
+
+	if (flags & RTF_HOST) {
+		dst = ifa->ifa_dstaddr;
+	} else {
+		dst = ifa->ifa_addr;
+	}
+
+	switch (dst->sa_family) {
+	case AF_INET6:
+	case AF_INET:
+		/* We do support multiple FIBs. */
+		fib = RT_ALL_FIBS;
+		break;
+	}
+	return (rtinit1(ifa, cmd, flags, fib));
+}
+
+static int
+ifa_maintain_loopback_route(int cmd, const char *otype, struct ifaddr *ifa,
+    struct sockaddr *ia)
+{
+	struct rib_cmd_info rc;
+	struct epoch_tracker et;
+	int error;
+	struct rt_addrinfo info;
+	struct sockaddr_dl null_sdl;
+	struct ifnet *ifp;
+	struct ifaddr *rti_ifa = NULL;
+
+	ifp = ifa->ifa_ifp;
+
+	NET_EPOCH_ENTER(et);
+	bzero(&info, sizeof(info));
+	if (cmd != RTM_DELETE)
+		info.rti_ifp = V_loif;
+	if (cmd == RTM_ADD) {
+		/* explicitly specify (loopback) ifa */
+		if (info.rti_ifp != NULL) {
+			rti_ifa = ifaof_ifpforaddr(ifa->ifa_addr, info.rti_ifp);
+			if (rti_ifa != NULL)
+				ifa_ref(rti_ifa);
+			info.rti_ifa = rti_ifa;
+		}
+	}
+	info.rti_flags = ifa->ifa_flags | RTF_HOST | RTF_STATIC | RTF_PINNED;
+	info.rti_info[RTAX_DST] = ia;
+	info.rti_info[RTAX_GATEWAY] = (struct sockaddr *)&null_sdl;
+	link_init_sdl(ifp, (struct sockaddr *)&null_sdl, ifp->if_type);
+
+	error = rib_action(ifp->if_fib, cmd, &info, &rc);
+	NET_EPOCH_EXIT(et);
+
+	if (rti_ifa != NULL)
+		ifa_free(rti_ifa);
+
+	if (error == 0 ||
+	    (cmd == RTM_ADD && error == EEXIST) ||
+	    (cmd == RTM_DELETE && (error == ENOENT || error == ESRCH)))
+		return (error);
+
+	log(LOG_DEBUG, "%s: %s failed for interface %s: %u\n",
+		__func__, otype, if_name(ifp), error);
+
+	return (error);
+}
+
+int
+ifa_add_loopback_route(struct ifaddr *ifa, struct sockaddr *ia)
+{
+
+	return (ifa_maintain_loopback_route(RTM_ADD, "insertion", ifa, ia));
+}
+
+int
+ifa_del_loopback_route(struct ifaddr *ifa, struct sockaddr *ia)
+{
+
+	return (ifa_maintain_loopback_route(RTM_DELETE, "deletion", ifa, ia));
+}
+
+int
+ifa_switch_loopback_route(struct ifaddr *ifa, struct sockaddr *ia)
+{
+
+	return (ifa_maintain_loopback_route(RTM_CHANGE, "switch", ifa, ia));
+}
+
+


More information about the svn-src-head mailing list