summaryrefslogtreecommitdiffstats
path: root/usr.sbin/XNSrouted/tables.c
diff options
context:
space:
mode:
authorrgrimes <rgrimes@FreeBSD.org>1994-05-26 06:39:07 +0000
committerrgrimes <rgrimes@FreeBSD.org>1994-05-26 06:39:07 +0000
commit2a27bd86e6002c871e3b5561a5334653bb222a77 (patch)
tree9c2944770734d3bd64a72d3a0abca1f69087e278 /usr.sbin/XNSrouted/tables.c
parentd038e02fd667ab6c02875840105798aaa7029504 (diff)
downloadFreeBSD-src-2a27bd86e6002c871e3b5561a5334653bb222a77.zip
FreeBSD-src-2a27bd86e6002c871e3b5561a5334653bb222a77.tar.gz
BSD 4.4 Lite sbin -> usr.sbin Sources
Note: The sources for XNSrouted and routed are being imported to usr.sbin instead of sbin.
Diffstat (limited to 'usr.sbin/XNSrouted/tables.c')
-rw-r--r--usr.sbin/XNSrouted/tables.c319
1 files changed, 319 insertions, 0 deletions
diff --git a/usr.sbin/XNSrouted/tables.c b/usr.sbin/XNSrouted/tables.c
new file mode 100644
index 0000000..4b00dc5
--- /dev/null
+++ b/usr.sbin/XNSrouted/tables.c
@@ -0,0 +1,319 @@
+/*
+ * Copyright (c) 1985, 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 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 lint
+static char sccsid[] = "@(#)tables.c 8.1 (Berkeley) 6/5/93";
+#endif /* not lint */
+
+/*
+ * Routing Table Management Daemon
+ */
+#include "defs.h"
+#include <sys/ioctl.h>
+#include <errno.h>
+
+#ifndef DEBUG
+#define DEBUG 0
+#endif
+
+extern char *xns_ntoa();
+#define FIXLEN(s) { if ((s)->sa_len == 0) (s)->sa_len = sizeof (*(s));}
+
+int install = !DEBUG; /* if 1 call kernel */
+int delete = 1;
+/*
+ * Lookup dst in the tables for an exact match.
+ */
+struct rt_entry *
+rtlookup(dst)
+ struct sockaddr *dst;
+{
+ register struct rt_entry *rt;
+ register struct rthash *rh;
+ register u_int hash;
+ struct afhash h;
+ int doinghost = 1;
+
+ if (dst->sa_family >= AF_MAX)
+ return (0);
+ (*afswitch[dst->sa_family].af_hash)(dst, &h);
+ hash = h.afh_hosthash;
+ rh = &hosthash[hash & ROUTEHASHMASK];
+again:
+ for (rt = rh->rt_forw; rt != (struct rt_entry *)rh; rt = rt->rt_forw) {
+ if (rt->rt_hash != hash)
+ continue;
+ if (equal(&rt->rt_dst, dst))
+ return (rt);
+ }
+ if (doinghost) {
+ doinghost = 0;
+ hash = h.afh_nethash;
+ rh = &nethash[hash & ROUTEHASHMASK];
+ goto again;
+ }
+ return (0);
+}
+
+/*
+ * Find a route to dst as the kernel would.
+ */
+struct rt_entry *
+rtfind(dst)
+ struct sockaddr *dst;
+{
+ register struct rt_entry *rt;
+ register struct rthash *rh;
+ register u_int hash;
+ struct afhash h;
+ int af = dst->sa_family;
+ int doinghost = 1, (*match)();
+
+ if (af >= AF_MAX)
+ return (0);
+ (*afswitch[af].af_hash)(dst, &h);
+ hash = h.afh_hosthash;
+ rh = &hosthash[hash & ROUTEHASHMASK];
+
+again:
+ for (rt = rh->rt_forw; rt != (struct rt_entry *)rh; rt = rt->rt_forw) {
+ if (rt->rt_hash != hash)
+ continue;
+ if (doinghost) {
+ if (equal(&rt->rt_dst, dst))
+ return (rt);
+ } else {
+ if (rt->rt_dst.sa_family == af &&
+ (*match)(&rt->rt_dst, dst))
+ return (rt);
+ }
+ }
+ if (doinghost) {
+ doinghost = 0;
+ hash = h.afh_nethash;
+ rh = &nethash[hash & ROUTEHASHMASK];
+ match = afswitch[af].af_netmatch;
+ goto again;
+ }
+ return (0);
+}
+
+rtadd(dst, gate, metric, state)
+ struct sockaddr *dst, *gate;
+ int metric, state;
+{
+ struct afhash h;
+ register struct rt_entry *rt;
+ struct rthash *rh;
+ int af = dst->sa_family, flags;
+ u_int hash;
+
+ FIXLEN(dst);
+ FIXLEN(gate);
+ if (af >= AF_MAX)
+ return;
+ (*afswitch[af].af_hash)(dst, &h);
+ flags = (*afswitch[af].af_ishost)(dst) ? RTF_HOST : 0;
+ if (flags & RTF_HOST) {
+ hash = h.afh_hosthash;
+ rh = &hosthash[hash & ROUTEHASHMASK];
+ } else {
+ hash = h.afh_nethash;
+ rh = &nethash[hash & ROUTEHASHMASK];
+ }
+ rt = (struct rt_entry *)malloc(sizeof (*rt));
+ if (rt == 0)
+ return;
+ rt->rt_hash = hash;
+ rt->rt_dst = *dst;
+ rt->rt_router = *gate;
+ rt->rt_metric = metric;
+ rt->rt_timer = 0;
+ rt->rt_flags = RTF_UP | flags;
+ rt->rt_state = state | RTS_CHANGED;
+ rt->rt_ifp = if_ifwithnet(&rt->rt_router);
+ if (metric)
+ rt->rt_flags |= RTF_GATEWAY;
+ insque(rt, rh);
+ TRACE_ACTION(ADD, rt);
+ /*
+ * If the ioctl fails because the gateway is unreachable
+ * from this host, discard the entry. This should only
+ * occur because of an incorrect entry in /etc/gateways.
+ */
+ if (install && rtioctl(ADD, &rt->rt_rt) < 0) {
+ if (errno != EEXIST)
+ perror("SIOCADDRT");
+ if (errno == ENETUNREACH) {
+ TRACE_ACTION(DELETE, rt);
+ remque(rt);
+ free((char *)rt);
+ }
+ }
+}
+
+rtchange(rt, gate, metric)
+ struct rt_entry *rt;
+ struct sockaddr *gate;
+ short metric;
+{
+ int doioctl = 0, metricchanged = 0;
+ struct rtentry oldroute;
+
+ FIXLEN(gate);
+ if (!equal(&rt->rt_router, gate))
+ doioctl++;
+ if (metric != rt->rt_metric)
+ metricchanged++;
+ if (doioctl || metricchanged) {
+ TRACE_ACTION(CHANGE FROM, rt);
+ if (doioctl) {
+ oldroute = rt->rt_rt;
+ rt->rt_router = *gate;
+ }
+ rt->rt_metric = metric;
+ if ((rt->rt_state & RTS_INTERFACE) && metric) {
+ rt->rt_state &= ~RTS_INTERFACE;
+ syslog(LOG_ERR,
+ "changing route from interface %s (timed out)",
+ rt->rt_ifp->int_name);
+ }
+ if (metric)
+ rt->rt_flags |= RTF_GATEWAY;
+ else
+ rt->rt_flags &= ~RTF_GATEWAY;
+ rt->rt_state |= RTS_CHANGED;
+ TRACE_ACTION(CHANGE TO, rt);
+ }
+ if (doioctl && install) {
+#ifndef RTM_ADD
+ if (rtioctl(ADD, &rt->rt_rt) < 0)
+ syslog(LOG_ERR, "rtioctl ADD dst %s, gw %s: %m",
+ xns_ntoa(&((struct sockaddr_ns *)&rt->rt_dst)->sns_addr),
+ xns_ntoa(&((struct sockaddr_ns *)&rt->rt_router)->sns_addr));
+ if (delete && rtioctl(DELETE, &oldroute) < 0)
+ perror("rtioctl DELETE");
+#else
+ if (delete == 0) {
+ if (rtioctl(ADD, &rt->rt_rt) >= 0)
+ return;
+ } else {
+ if (rtioctl(CHANGE, &rt->rt_rt) >= 0)
+ return;
+ }
+ syslog(LOG_ERR, "rtioctl ADD dst %s, gw %s: %m",
+ xns_ntoa(&((struct sockaddr_ns *)&rt->rt_dst)->sns_addr),
+ xns_ntoa(&((struct sockaddr_ns *)&rt->rt_router)->sns_addr));
+#endif
+ }
+}
+
+rtdelete(rt)
+ struct rt_entry *rt;
+{
+
+ struct sockaddr *sa = &(rt->rt_rt.rt_gateway);
+ FIXLEN(sa);
+#undef rt_dst
+ sa = &(rt->rt_rt.rt_dst);
+ FIXLEN(sa);
+ if (rt->rt_state & RTS_INTERFACE) {
+ syslog(LOG_ERR, "deleting route to interface %s (timed out)",
+ rt->rt_ifp->int_name);
+ }
+ TRACE_ACTION(DELETE, rt);
+ if (install && rtioctl(DELETE, &rt->rt_rt) < 0)
+ perror("rtioctl DELETE");
+ remque(rt);
+ free((char *)rt);
+}
+
+rtinit()
+{
+ register struct rthash *rh;
+
+ for (rh = nethash; rh < &nethash[ROUTEHASHSIZ]; rh++)
+ rh->rt_forw = rh->rt_back = (struct rt_entry *)rh;
+ for (rh = hosthash; rh < &hosthash[ROUTEHASHSIZ]; rh++)
+ rh->rt_forw = rh->rt_back = (struct rt_entry *)rh;
+}
+int seqno;
+
+rtioctl(action, ort)
+ int action;
+ struct ortentry *ort;
+{
+#ifndef RTM_ADD
+ switch (action) {
+
+ case ADD:
+ return (ioctl(s, SIOCADDRT, (char *)ort));
+
+ case DELETE:
+ return (ioctl(s, SIOCDELRT, (char *)ort));
+
+ default:
+ return (-1);
+ }
+#else /* RTM_ADD */
+ struct {
+ struct rt_msghdr w_rtm;
+ struct sockaddr w_dst;
+ struct sockaddr w_gate;
+ struct sockaddr_ns w_netmask;
+ } w;
+#define rtm w.w_rtm
+
+ bzero((char *)&w, sizeof(w));
+ rtm.rtm_msglen = sizeof(w);
+ rtm.rtm_version = RTM_VERSION;
+ rtm.rtm_type = (action == ADD ? RTM_ADD :
+ (action == DELETE ? RTM_DELETE : RTM_CHANGE));
+#undef rt_flags
+ rtm.rtm_flags = ort->rt_flags;
+ rtm.rtm_seq = ++seqno;
+ rtm.rtm_addrs = RTA_DST|RTA_GATEWAY;
+ bcopy((char *)&ort->rt_dst, (char *)&w.w_dst, sizeof(w.w_dst));
+ bcopy((char *)&ort->rt_gateway, (char *)&w.w_gate, sizeof(w.w_gate));
+ w.w_gate.sa_family = w.w_dst.sa_family = AF_NS;
+ w.w_gate.sa_len = w.w_dst.sa_len = sizeof(w.w_dst);
+ if (rtm.rtm_flags & RTF_HOST) {
+ rtm.rtm_msglen -= sizeof(w.w_netmask);
+ } else {
+ w.w_netmask = ns_netmask;
+ rtm.rtm_msglen -= 8;
+ }
+ errno = 0;
+ return write(r, (char *)&w, rtm.rtm_msglen);
+#endif /* RTM_ADD */
+}
OpenPOWER on IntegriCloud