Import of XNSrouted from ftp.uu.net bsd-sources, compiles and installs,
authorRod Grimes <rgrimes@FreeBSD.org>
Tue, 7 Sep 1993 14:13:28 +0000 (14:13 +0000)
committerRod Grimes <rgrimes@FreeBSD.org>
Tue, 7 Sep 1993 14:13:28 +0000 (14:13 +0000)
not sure how well it works since I don't have XNS up and running yet.

36 files changed:
sbin/XNSrouted/Makefile [new file with mode: 0644]
sbin/XNSrouted/XNSrouted.8 [new file with mode: 0644]
sbin/XNSrouted/af.c [new file with mode: 0644]
sbin/XNSrouted/af.h [new file with mode: 0644]
sbin/XNSrouted/defs.h [new file with mode: 0644]
sbin/XNSrouted/if.c [new file with mode: 0644]
sbin/XNSrouted/input.c [new file with mode: 0644]
sbin/XNSrouted/interface.h [new file with mode: 0644]
sbin/XNSrouted/main.c [new file with mode: 0644]
sbin/XNSrouted/output.c [new file with mode: 0644]
sbin/XNSrouted/protocol.h [new file with mode: 0644]
sbin/XNSrouted/startup.c [new file with mode: 0644]
sbin/XNSrouted/table.h [new file with mode: 0644]
sbin/XNSrouted/tables.c [new file with mode: 0644]
sbin/XNSrouted/timer.c [new file with mode: 0644]
sbin/XNSrouted/tools/query.c [new file with mode: 0644]
sbin/XNSrouted/trace.c [new file with mode: 0644]
sbin/XNSrouted/trace.h [new file with mode: 0644]
usr.sbin/XNSrouted/Makefile [new file with mode: 0644]
usr.sbin/XNSrouted/XNSrouted.8 [new file with mode: 0644]
usr.sbin/XNSrouted/af.c [new file with mode: 0644]
usr.sbin/XNSrouted/af.h [new file with mode: 0644]
usr.sbin/XNSrouted/defs.h [new file with mode: 0644]
usr.sbin/XNSrouted/if.c [new file with mode: 0644]
usr.sbin/XNSrouted/input.c [new file with mode: 0644]
usr.sbin/XNSrouted/interface.h [new file with mode: 0644]
usr.sbin/XNSrouted/main.c [new file with mode: 0644]
usr.sbin/XNSrouted/output.c [new file with mode: 0644]
usr.sbin/XNSrouted/protocol.h [new file with mode: 0644]
usr.sbin/XNSrouted/startup.c [new file with mode: 0644]
usr.sbin/XNSrouted/table.h [new file with mode: 0644]
usr.sbin/XNSrouted/tables.c [new file with mode: 0644]
usr.sbin/XNSrouted/timer.c [new file with mode: 0644]
usr.sbin/XNSrouted/tools/query.c [new file with mode: 0644]
usr.sbin/XNSrouted/trace.c [new file with mode: 0644]
usr.sbin/XNSrouted/trace.h [new file with mode: 0644]

diff --git a/sbin/XNSrouted/Makefile b/sbin/XNSrouted/Makefile
new file mode 100644 (file)
index 0000000..1722c6f
--- /dev/null
@@ -0,0 +1,10 @@
+#      From: @(#)Makefile      5.14 (Berkeley) 2/26/91
+#      $Id$
+
+PROG=  XNSrouted
+MAN8=  XNSrouted.8
+SRCS=  af.c if.c input.c main.c output.c startup.c tables.c timer.c trace.c
+DPADD= ${LIBUTIL}
+LDADD= -lutil
+
+.include <bsd.prog.mk>
diff --git a/sbin/XNSrouted/XNSrouted.8 b/sbin/XNSrouted/XNSrouted.8
new file mode 100644 (file)
index 0000000..144cb1d
--- /dev/null
@@ -0,0 +1,186 @@
+.\" Copyright (c) 1986, 1991 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.
+.\"
+.\"     @(#)XNSrouted.8        6.4 (Berkeley) 3/16/91
+.\"
+.Dd March 16, 1991
+.Dt XNSROUTED 8
+.Os BSD 4.3
+.Sh NAME
+.Nm XNSrouted
+.Nd NS Routing Information Protocol daemon
+.Sh SYNOPSIS
+.Nm XNSrouted
+.Op Fl q
+.Op Fl s
+.Op Fl t
+.Op Ar logfile
+.Sh DESCRIPTION
+.Nm XNSrouted
+is invoked at boot time to manage the Xerox NS routing tables.
+The NS routing daemon uses the Xerox NS Routing
+Information Protocol in maintaining up to date kernel routing
+table entries.
+.Pp
+Available options:
+.Bl -tag -width logfile
+.It Fl q
+Do not supply routing information (opposite of
+.Fl s
+option below).
+.It Fl s
+Forces 
+.Nm XNSrouted
+to supply routing information whether it is acting as an internetwork
+router or not.
+.It Fl t
+All packets sent or received are
+printed on the standard output.  In addition,
+.Nm XNSrouted
+will not divorce itself from the controlling terminal
+so that interrupts from the keyboard will kill the process.
+.It Ar logfile
+Name of file in which 
+.Nm XNSrouted Ns 's
+actions should be logged.  This log contains information
+about any changes to the routing tables and a history of
+recent messages sent and received which are related to
+the changed route.
+.El
+.Pp
+In normal operation
+.Nm XNSrouted
+listens
+for routing information packets.  If the host is connected to
+multiple NS networks, it periodically supplies copies
+of its routing tables to any directly connected hosts
+and networks.
+.Pp
+When
+.Nm XNSrouted
+is started, it uses the
+.Dv SIOCGIFCONF
+.Xr ioctl 2
+to find those
+directly connected interfaces configured into the
+system and marked
+.Dq up
+(the software loopback interface
+is ignored).  If multiple interfaces
+are present, it is assumed the host will forward packets
+between networks.
+.Nm XNSrouted
+then transmits a 
+.Em request
+packet on each interface (using a broadcast packet if
+the interface supports it) and enters a loop, listening
+for
+.Em request
+and
+.Em response
+packets from other hosts.
+.Pp
+When a
+.Em request
+packet is received, 
+.Nm XNSrouted
+formulates a reply based on the information maintained in its
+internal tables.  The
+.Em response
+packet generated contains a list of known routes, each marked
+with a
+.Dq hop count
+metric (a count of 16, or greater, is
+considered
+.Dq infinite ) .
+The metric associated with each
+route returned provides a metric
+.Em relative to the sender .
+.Pp
+.Em Response
+packets received by
+.Nm XNSrouted
+are used to update the routing tables if one of the following
+conditions is satisfied:
+.Bl -bullet
+.It
+No routing table entry exists for the destination network
+or host, and the metric indicates the destination is ``reachable''
+(i.e. the hop count is not infinite).
+.It
+The source host of the packet is the same as the router in the
+existing routing table entry.  That is, updated information is
+being received from the very internetwork router through which
+packets for the destination are being routed.
+.It
+The existing entry in the routing table has not been updated for
+some time (defined to be 90 seconds) and the route is at least
+as cost effective as the current route.
+.It
+The new route describes a shorter route to the destination than
+the one currently stored in the routing tables; the metric of
+the new route is compared against the one stored in the table
+to decide this.
+.El
+.Pp
+When an update is applied,
+.Nm XNSrouted
+records the change in its internal tables and generates a
+.Em response
+packet to all directly connected hosts and networks.
+.Xr Routed 8
+waits a short period
+of time (no more than 30 seconds) before modifying the kernel's
+routing tables to allow possible unstable situations to settle.
+.Pp
+In addition to processing incoming packets,
+.Nm XNSrouted
+also periodically checks the routing table entries.
+If an entry has not been updated for 3 minutes, the entry's metric
+is set to infinity and marked for deletion.  Deletions are delayed
+an additional 60 seconds to insure the invalidation is propagated
+to other routers.
+.Pp
+Hosts acting as internetwork routers gratuitously supply their
+routing tables every 30 seconds to all directly connected hosts
+and networks.
+.Sh SEE ALSO
+.Xr idp 4
+.Rs
+.%T "Internet Transport Protocols"
+.%R "XSIS 028112"
+.%Q "Xerox System Integration Standard"
+.Re
+.Sh HISTORY
+The
+.Nm
+command appeared in
+.Bx 4.3 .
diff --git a/sbin/XNSrouted/af.c b/sbin/XNSrouted/af.c
new file mode 100644 (file)
index 0000000..d131e87
--- /dev/null
@@ -0,0 +1,246 @@
+/*
+ * Copyright (c) 1985 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This file includes significant work done at Cornell University by
+ * Bill Nesheim.  That work included by permission.
+ *
+ * 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[] = "@(#)af.c       5.11 (Berkeley) 2/26/91";
+#endif /* not lint */
+
+#include "defs.h"
+
+/*
+ * Address family support routines
+ */
+int    null_hash(), null_netmatch(), null_output(),
+       null_portmatch(), null_portcheck(),
+       null_checkhost(), null_ishost(), null_canon();
+int    xnnet_hash(), xnnet_netmatch(), xnnet_output(),
+       xnnet_portmatch(),
+       xnnet_checkhost(), xnnet_ishost(), xnnet_canon();
+#define NIL \
+       { null_hash,            null_netmatch,          null_output, \
+         null_portmatch,       null_portcheck,         null_checkhost, \
+         null_ishost,          null_canon }
+#define        XNSNET \
+       { xnnet_hash,           xnnet_netmatch,         xnnet_output, \
+         xnnet_portmatch,      xnnet_portmatch,        xnnet_checkhost, \
+         xnnet_ishost,         xnnet_canon }
+
+struct afswitch afswitch[AF_MAX] =
+       { NIL, NIL, NIL, NIL, NIL, NIL, XNSNET, NIL, NIL, NIL, NIL };
+
+struct sockaddr_ns xnnet_default = { sizeof(struct sockaddr_ns), AF_NS };
+
+union ns_net ns_anynet;
+union ns_net ns_zeronet;
+
+xnnet_hash(sns, hp)
+       register struct sockaddr_ns *sns;
+       struct afhash *hp;
+{
+       register long hash = 0;
+       register u_short *s = sns->sns_addr.x_host.s_host;
+       union ns_net_u net;
+
+       net.net_e = sns->sns_addr.x_net;
+       hp->afh_nethash = net.long_e;
+       hash = *s++; hash <<= 8; hash += *s++; hash <<= 8; hash += *s;
+       hp->afh_hosthash = hash;
+}
+
+xnnet_netmatch(sxn1, sxn2)
+       struct sockaddr_ns *sxn1, *sxn2;
+{
+       return (ns_neteq(sxn1->sns_addr, sxn2->sns_addr));
+}
+
+/*
+ * Verify the message is from the right port.
+ */
+xnnet_portmatch(sns)
+       register struct sockaddr_ns *sns;
+{
+       
+       return (ntohs(sns->sns_addr.x_port) == IDPPORT_RIF );
+}
+
+
+/*
+ * xns output routine.
+ */
+#ifdef DEBUG
+int do_output = 0;
+#endif
+xnnet_output(flags, sns, size)
+       int flags;
+       struct sockaddr_ns *sns;
+       int size;
+{
+       struct sockaddr_ns dst;
+
+       dst = *sns;
+       sns = &dst;
+       if (sns->sns_addr.x_port == 0)
+               sns->sns_addr.x_port = htons(IDPPORT_RIF);
+#ifdef DEBUG
+       if(do_output || ntohs(msg->rip_cmd) == RIPCMD_REQUEST)
+#endif 
+       /*
+        * Kludge to allow us to get routes out to machines that
+        * don't know their addresses yet; send to that address on
+        * ALL connected nets
+        */
+        if (ns_neteqnn(sns->sns_addr.x_net, ns_zeronet)) {
+               extern  struct interface *ifnet;
+               register struct interface *ifp;
+               
+               for (ifp = ifnet; ifp; ifp = ifp->int_next) {
+                       sns->sns_addr.x_net = 
+                               satons_addr(ifp->int_addr).x_net;
+                       (void) sendto(s, msg, size, flags,
+                           (struct sockaddr *)sns, sizeof (*sns));
+               }
+               return;
+       }
+       
+       (void) sendto(s, msg, size, flags,
+           (struct sockaddr *)sns, sizeof (*sns));
+}
+
+/*
+ * Return 1 if we want this route.
+ * We use this to disallow route net G entries for one for multiple
+ * point to point links.
+ */
+xnnet_checkhost(sns)
+       struct sockaddr_ns *sns;
+{
+       register struct interface *ifp = if_ifwithnet(sns);
+       /*
+        * We want this route if there is no more than one 
+        * point to point interface with this network.
+        */
+       if (ifp == 0 || (ifp->int_flags & IFF_POINTOPOINT)==0) return (1);
+       return (ifp->int_sq.n == ifp->int_sq.p);
+}
+
+/*
+ * Return 1 if the address is
+ * for a host, 0 for a network.
+ */
+xnnet_ishost(sns)
+struct sockaddr_ns *sns;
+{
+       register u_short *s = sns->sns_addr.x_host.s_host;
+
+       if ((s[0]==0xffff) && (s[1]==0xffff) && (s[2]==0xffff))
+               return (0);
+       else
+               return (1);
+}
+
+xnnet_canon(sns)
+       struct sockaddr_ns *sns;
+{
+
+       sns->sns_addr.x_port = 0;
+}
+
+/*ARGSUSED*/
+null_hash(addr, hp)
+       struct sockaddr *addr;
+       struct afhash *hp;
+{
+
+       hp->afh_nethash = hp->afh_hosthash = 0;
+}
+
+/*ARGSUSED*/
+null_netmatch(a1, a2)
+       struct sockaddr *a1, *a2;
+{
+
+       return (0);
+}
+
+/*ARGSUSED*/
+null_output(s, f, a1, n)
+       int s, f;
+       struct sockaddr *a1;
+       int n;
+{
+
+       ;
+}
+
+/*ARGSUSED*/
+null_portmatch(a1)
+       struct sockaddr *a1;
+{
+
+       return (0);
+}
+
+/*ARGSUSED*/
+null_portcheck(a1)
+       struct sockaddr *a1;
+{
+
+       return (0);
+}
+
+/*ARGSUSED*/
+null_ishost(a1)
+       struct sockaddr *a1;
+{
+
+       return (0);
+}
+
+/*ARGSUSED*/
+null_checkhost(a1)
+       struct sockaddr *a1;
+{
+
+       return (0);
+}
+
+/*ARGSUSED*/
+null_canon(a1)
+       struct sockaddr *a1;
+{
+
+       ;
+}
diff --git a/sbin/XNSrouted/af.h b/sbin/XNSrouted/af.h
new file mode 100644 (file)
index 0000000..d2b27c5
--- /dev/null
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 1983 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.
+ *
+ *     @(#)af.h        5.1 (Berkeley) 6/4/85 (routed/af.h)
+ *
+ *     @(#)af.h        5.2 (Berkeley) 6/1/90
+ */
+
+/*
+ * Routing table management daemon.
+ */
+
+/*
+ * Per address family routines.
+ */
+struct afswitch {
+       int     (*af_hash)();           /* returns keys based on address */
+       int     (*af_netmatch)();       /* verifies net # matching */
+       int     (*af_output)();         /* interprets address for sending */
+       int     (*af_portmatch)();      /* packet from some other router? */
+       int     (*af_portcheck)();      /* packet from privileged peer? */
+       int     (*af_checkhost)();      /* tells if address for host or net */
+       int     (*af_ishost)();         /* tells if address is valid */
+       int     (*af_canon)();          /* canonicalize address for compares */
+};
+
+/*
+ * Structure returned by af_hash routines.
+ */
+struct afhash {
+       u_int   afh_hosthash;           /* host based hash */
+       u_int   afh_nethash;            /* network based hash */
+};
+
+struct afswitch afswitch[AF_MAX];      /* table proper */
diff --git a/sbin/XNSrouted/defs.h b/sbin/XNSrouted/defs.h
new file mode 100644 (file)
index 0000000..5414d8c
--- /dev/null
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 1983 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.
+ *
+ *     @(#)defs.h      5.9 (Berkeley) 2/26/91
+ */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#include <net/route.h>
+#include <netns/ns.h>
+#include <netns/idp.h>
+#if defined(vax) || defined(pdp11)
+#define xnnet(x) ((u_long) (x)->rip_dst[1] << 16 | (u_long) (x)->rip_dst[0] )
+#else
+#define xnnet(x) ((u_long) (x)->rip_dst[0] << 16 | (u_long) (x)->rip_dst[1] )
+#endif
+#define        IDPPORT_RIF     1
+
+#include <stdio.h>
+#include <syslog.h>
+
+#include "protocol.h"
+#include "trace.h"
+#include "interface.h"
+#include "table.h"
+#include "af.h"
+
+
+/*
+ * When we find any interfaces marked down we rescan the
+ * kernel every CHECK_INTERVAL seconds to see if they've
+ * come up.
+ */
+#define        CHECK_INTERVAL  (5*60)
+
+#define equal(a1, a2) \
+       (bcmp((caddr_t)(a1), (caddr_t)(a2), sizeof (struct sockaddr)) == 0)
+#define        min(a,b)        ((a)>(b)?(b):(a))
+
+struct sockaddr_ns addr;       /* Daemon's Address */
+int    s;                      /* Socket to listen on */
+int    kmem;
+int    supplier;               /* process should supply updates */
+int    install;                /* if 1 call kernel */
+int    lookforinterfaces;      /* if 1 probe kernel for new up interfaces */
+int    performnlist;           /* if 1 check if /vmunix has changed */
+int    externalinterfaces;     /* # of remote and local interfaces */
+int    timeval;                /* local idea of time */
+int    noteremoterequests;     /* squawk on requests from non-local nets */
+
+char   packet[MAXPACKETSIZE+sizeof(struct idp)+1];
+struct rip *msg;
+
+char   **argv0;
+
+int    sndmsg();
+int    supply();
+int    cleanup();
diff --git a/sbin/XNSrouted/if.c b/sbin/XNSrouted/if.c
new file mode 100644 (file)
index 0000000..0f597a6
--- /dev/null
@@ -0,0 +1,147 @@
+/*
+ * Copyright (c) 1983 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.
+ *
+ * static char sccsid[] = "@(#)if.c    5.1 (Berkeley) 6/4/85"; (routed/if.c)
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)if.c       5.2 (Berkeley) 6/1/90";
+#endif /* not lint */
+
+/*
+ * Routing Table Management Daemon
+ */
+#include "defs.h"
+
+extern struct interface *ifnet;
+
+/*
+ * Find the interface with address addr.
+ */
+struct interface *
+if_ifwithaddr(addr)
+       struct sockaddr *addr;
+{
+       register struct interface *ifp;
+
+#define        same(a1, a2) \
+       (bcmp((caddr_t)((a1)->sa_data), (caddr_t)((a2)->sa_data), 14) == 0)
+       for (ifp = ifnet; ifp; ifp = ifp->int_next) {
+               if (ifp->int_flags & IFF_REMOTE)
+                       continue;
+               if (ifp->int_addr.sa_family != addr->sa_family)
+                       continue;
+               if (same(&ifp->int_addr, addr))
+                       break;
+               if ((ifp->int_flags & IFF_BROADCAST) &&
+                   same(&ifp->int_broadaddr, addr))
+                       break;
+       }
+       return (ifp);
+}
+
+/*
+ * Find the point-to-point interface with destination address addr.
+ */
+struct interface *
+if_ifwithdstaddr(addr)
+       struct sockaddr *addr;
+{
+       register struct interface *ifp;
+
+       for (ifp = ifnet; ifp; ifp = ifp->int_next) {
+               if ((ifp->int_flags & IFF_POINTOPOINT) == 0)
+                       continue;
+               if (same(&ifp->int_dstaddr, addr))
+                       break;
+       }
+       return (ifp);
+}
+
+/*
+ * Find the interface on the network 
+ * of the specified address.
+ */
+struct interface *
+if_ifwithnet(addr)
+       register struct sockaddr *addr;
+{
+       register struct interface *ifp;
+       register int af = addr->sa_family;
+       register int (*netmatch)();
+
+       if (af >= AF_MAX)
+               return (0);
+       netmatch = afswitch[af].af_netmatch;
+       for (ifp = ifnet; ifp; ifp = ifp->int_next) {
+               if (ifp->int_flags & IFF_REMOTE)
+                       continue;
+               if (af != ifp->int_addr.sa_family)
+                       continue;
+               if ((*netmatch)(addr, &ifp->int_addr))
+                       break;
+       }
+       return (ifp);
+}
+
+/*
+ * Find an interface from which the specified address
+ * should have come from.  Used for figuring out which
+ * interface a packet came in on -- for tracing.
+ */
+struct interface *
+if_iflookup(addr)
+       struct sockaddr *addr;
+{
+       register struct interface *ifp, *maybe;
+       register int af = addr->sa_family;
+       register int (*netmatch)();
+
+       if (af >= AF_MAX)
+               return (0);
+       maybe = 0;
+       netmatch = afswitch[af].af_netmatch;
+       for (ifp = ifnet; ifp; ifp = ifp->int_next) {
+               if (ifp->int_addr.sa_family != af)
+                       continue;
+               if (same(&ifp->int_addr, addr))
+                       break;
+               if ((ifp->int_flags & IFF_BROADCAST) &&
+                   same(&ifp->int_broadaddr, addr))
+                       break;
+               if (maybe == 0 && (*netmatch)(addr, &ifp->int_addr))
+                       maybe = ifp;
+       }
+       if (ifp == 0)
+               ifp = maybe;
+       return (ifp);
+}
diff --git a/sbin/XNSrouted/input.c b/sbin/XNSrouted/input.c
new file mode 100644 (file)
index 0000000..7dc64fa
--- /dev/null
@@ -0,0 +1,189 @@
+/*
+ * Copyright (c) 1985 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This file includes significant work done at Cornell University by
+ * Bill Nesheim.  That work included by permission.
+ *
+ * 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[] = "@(#)input.c    5.9 (Berkeley) 6/1/90";
+#endif /* not lint */
+
+/*
+ * XNS Routing Table Management Daemon
+ */
+#include "defs.h"
+
+struct sockaddr *
+xns_nettosa(net)
+union ns_net net;
+{
+       static struct sockaddr_ns sxn;
+       extern char ether_broadcast_addr[6];
+       
+       bzero(&sxn, sizeof (struct sockaddr_ns));
+       sxn.sns_family = AF_NS;
+       sxn.sns_len = sizeof (sxn);
+       sxn.sns_addr.x_net = net;
+       sxn.sns_addr.x_host = *(union ns_host *)ether_broadcast_addr;
+       return( (struct sockaddr *)&sxn);
+       
+}
+
+/*
+ * Process a newly received packet.
+ */
+rip_input(from, size)
+       struct sockaddr *from;
+       int size;
+{
+       struct rt_entry *rt;
+       struct netinfo *n;
+       struct interface *ifp;
+       int newsize;
+       struct afswitch *afp;
+
+       
+       ifp = 0;
+       TRACE_INPUT(ifp, from, size);
+       if (from->sa_family >= AF_MAX)
+               return;
+       afp = &afswitch[from->sa_family];
+       
+       size -= sizeof (u_short)        /* command */;
+       n = msg->rip_nets;
+
+       switch (ntohs(msg->rip_cmd)) {
+
+       case RIPCMD_REQUEST:
+               newsize = 0;
+               while (size > 0) {
+                       if (size < sizeof (struct netinfo))
+                               break;
+                       size -= sizeof (struct netinfo);
+
+                       /* 
+                        * A single entry with rip_dst == DSTNETS_ALL and
+                        * metric ``infinity'' means ``all routes''.
+                        */
+                       if (ns_neteqnn(n->rip_dst, ns_anynet) &&
+                           ntohs(n->rip_metric) == HOPCNT_INFINITY &&
+                           size == 0) {
+                               ifp = if_ifwithnet(from);
+                               supply(from, 0, ifp);
+                               return;
+                       }
+                       /*
+                        * request for specific nets
+                        */
+                       rt = rtlookup(xns_nettosa(n->rip_dst));
+                       if (ftrace) {
+                               fprintf(ftrace,
+                                       "specific request for %s",
+                                       xns_nettoa(n->rip_dst));
+                               fprintf(ftrace,
+                                       " yields route %x\n",
+                                       rt);
+                       }
+                       n->rip_metric = htons( rt == 0 ? HOPCNT_INFINITY :
+                               min(rt->rt_metric+1, HOPCNT_INFINITY));
+                       n++;
+                       newsize += sizeof (struct netinfo);
+               }
+               if (newsize > 0) {
+                       msg->rip_cmd = htons(RIPCMD_RESPONSE);
+                       newsize += sizeof (u_short);
+                       /* should check for if with dstaddr(from) first */
+                       (*afp->af_output)(0, from, newsize);
+                       ifp = if_ifwithnet(from);
+                       TRACE_OUTPUT(ifp, from, newsize);
+                       if (ftrace) {
+                               fprintf(ftrace,
+                                       "request arrived on interface %s\n",
+                                       ifp->int_name);
+                       }
+               }
+               return;
+
+       case RIPCMD_RESPONSE:
+               /* verify message came from a router */
+               if ((*afp->af_portmatch)(from) == 0)
+                       return;
+               (*afp->af_canon)(from);
+               /* are we talking to ourselves? */
+               if (ifp = if_ifwithaddr(from)) {
+                       rt = rtfind(from);
+                       if (rt == 0 || (rt->rt_state & RTS_INTERFACE) == 0)
+                               addrouteforif(ifp);
+                       else
+                               rt->rt_timer = 0;
+                       return;
+               }
+               /* Update timer for interface on which the packet arrived.
+                * If from other end of a point-to-point link that isn't
+                * in the routing tables, (re-)add the route.
+                */
+               if ((rt = rtfind(from)) && (rt->rt_state & RTS_INTERFACE)) {
+                       if(ftrace) fprintf(ftrace, "Got route\n");
+                       rt->rt_timer = 0;
+               } else if (ifp = if_ifwithdstaddr(from)) {
+                       if(ftrace) fprintf(ftrace, "Got partner\n");
+                       addrouteforif(ifp);
+               }
+               for (; size > 0; size -= sizeof (struct netinfo), n++) {
+                       struct sockaddr *sa;
+                       if (size < sizeof (struct netinfo))
+                               break;
+                       if ((unsigned) ntohs(n->rip_metric) >= HOPCNT_INFINITY)
+                               continue;
+                       rt = rtfind(sa = xns_nettosa(n->rip_dst));
+                       if (rt == 0) {
+                               rtadd(sa, from, ntohs(n->rip_metric), 0);
+                               continue;
+                       }
+
+                       /*
+                        * Update if from gateway and different,
+                        * from anywhere and shorter, or getting stale and equivalent.
+                        */
+                       if ((equal(from, &rt->rt_router) &&
+                           ntohs(n->rip_metric) != rt->rt_metric ) ||
+                           (unsigned) ntohs(n->rip_metric) < rt->rt_metric ||
+                           (rt->rt_timer > (EXPIRE_TIME/2) &&
+                           rt->rt_metric == ntohs(n->rip_metric))) {
+                               rtchange(rt, from, ntohs(n->rip_metric));
+                               rt->rt_timer = 0;
+                       }
+               }
+               return;
+       }
+}
diff --git a/sbin/XNSrouted/interface.h b/sbin/XNSrouted/interface.h
new file mode 100644 (file)
index 0000000..7cb4166
--- /dev/null
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 1983 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.
+ *
+ *     @(#)interface.h 5.5 (Berkeley) 6/1/90
+ */
+
+/*
+ * Routing table management daemon.
+ */
+
+/*
+ * An ``interface'' is similar to an ifnet structure,
+ * except it doesn't contain q'ing info, and it also
+ * handles ``logical'' interfaces (remote gateways
+ * that we want to keep polling even if they go down).
+ * The list of interfaces which we maintain is used
+ * in supplying the gratuitous routing table updates.
+ * We list only one address for  each interface, the AF_XNS one.
+ */
+#define NIFADDR 3
+struct interface {
+       struct  interface *int_next;
+       struct  sockaddr int_addr;              /* address on this host */
+       union {
+               struct  sockaddr intu_broadaddr;
+               struct  sockaddr intu_dstaddr;
+       } int_intu;
+#define        int_broadaddr   int_intu.intu_broadaddr /* broadcast address */
+#define        int_dstaddr     int_intu.intu_dstaddr   /* other end of p-to-p link */
+       int     int_metric;                     /* init's routing entry */
+       int     int_flags;                      /* see below */
+       struct  ifdebug int_input, int_output;  /* packet tracing stuff */
+       int     int_ipackets;                   /* input packets received */
+       int     int_opackets;                   /* output packets sent */
+       char    *int_name;                      /* from kernel if structure */
+       u_short int_transitions;                /* times gone up-down */
+/*XNS Specific entry */
+       struct  sameq {
+               struct sameq *n;                /* q of other pt-to-pt links */
+               struct sameq *p;                /* with same net # */
+       }       int_sq;
+};
+
+/*
+ * 0x1 to 0x10 are reused from the kernel's ifnet definitions,
+ * the others agree with the RTS_ flags defined elsewhere.
+ */
+#define        IFF_UP          0x1             /* interface is up */
+#define        IFF_BROADCAST   0x2             /* broadcast address valid */
+#define        IFF_DEBUG       0x4             /* turn on debugging */
+#define        IFF_ROUTE       0x8             /* routing entry installed */
+#define        IFF_POINTOPOINT 0x10            /* interface is point-to-point link */
+
+#define        IFF_PASSIVE     0x2000          /* can't tell if up/down */
+#define        IFF_INTERFACE   0x4000          /* hardware interface */
+#define        IFF_REMOTE      0x8000          /* interface isn't on this machine */
+
+struct interface *if_ifwithaddr();
+struct interface *if_ifwithdstaddr();
+struct interface *if_ifwithnet();
+struct interface *if_iflookup();
diff --git a/sbin/XNSrouted/main.c b/sbin/XNSrouted/main.c
new file mode 100644 (file)
index 0000000..f4ddf28
--- /dev/null
@@ -0,0 +1,245 @@
+/*
+ * Copyright (c) 1985 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This file includes significant work done at Cornell University by
+ * Bill Nesheim.  That work included by permission.
+ *
+ * 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
+char copyright[] =
+"@(#) Copyright (c) 1985 The Regents of the University of California.\n\
+ All rights reserved.\n";
+#endif /* not lint */
+
+#ifndef lint
+static char sccsid[] = "@(#)main.c     5.11 (Berkeley) 2/26/91";
+#endif /* not lint */
+
+/*
+ * XNS Routing Information Protocol Daemon
+ */
+#include "defs.h"
+#include <sys/time.h>
+
+#include <net/if.h>
+
+#include <errno.h>
+#include <nlist.h>
+#include <signal.h>
+#include <paths.h>
+
+int    supplier = -1;          /* process should supply updates */
+extern int gateway;
+
+struct rip *msg = (struct rip *) &packet[sizeof (struct idp)]; 
+void   hup(), fkexit(), timer();
+
+main(argc, argv)
+       int argc;
+       char *argv[];
+{
+       int cc;
+       struct sockaddr from;
+       u_char retry;
+       
+       argv0 = argv;
+       argv++, argc--;
+       while (argc > 0 && **argv == '-') {
+               if (strcmp(*argv, "-s") == 0) {
+                       supplier = 1;
+                       argv++, argc--;
+                       continue;
+               }
+               if (strcmp(*argv, "-q") == 0) {
+                       supplier = 0;
+                       argv++, argc--;
+                       continue;
+               }
+               if (strcmp(*argv, "-R") == 0) {
+                       noteremoterequests++;
+                       argv++, argc--;
+                       continue;
+               }
+               if (strcmp(*argv, "-t") == 0) {
+                       tracepackets++;
+                       argv++, argc--;
+                       ftrace = stderr;
+                       tracing = 1; 
+                       continue;
+               }
+               if (strcmp(*argv, "-g") == 0) {
+                       gateway = 1;
+                       argv++, argc--;
+                       continue;
+               }
+               if (strcmp(*argv, "-l") == 0) {
+                       gateway = -1;
+                       argv++, argc--;
+                       continue;
+               }
+               fprintf(stderr,
+                       "usage: xnsrouted [ -s ] [ -q ] [ -t ] [ -g ] [ -l ]\n");
+               exit(1);
+       }
+       
+       
+#ifndef DEBUG
+       if (!tracepackets)
+               daemon(0, 0);
+#endif
+       openlog("XNSrouted", LOG_PID, LOG_DAEMON);
+
+       ns_anynet.s_net[0] = -1; ns_anynet.s_net[1] = -1;
+       addr.sns_family = AF_NS;
+       addr.sns_len = sizeof(addr);
+       addr.sns_port = htons(IDPPORT_RIF);
+       s = getsocket(SOCK_DGRAM, 0, &addr);
+       if (s < 0)
+               exit(1);
+       /*
+        * Any extra argument is considered
+        * a tracing log file.
+        */
+       if (argc > 0)
+               traceon(*argv);
+       /*
+        * Collect an initial view of the world by
+        * snooping in the kernel.  Then, send a request packet on all
+        * directly connected networks to find out what
+        * everyone else thinks.
+        */
+       rtinit();
+       ifinit();
+       if (supplier < 0)
+               supplier = 0;
+       /* request the state of the world */
+       msg->rip_cmd = htons(RIPCMD_REQUEST);
+       msg->rip_nets[0].rip_dst = ns_anynet;
+       msg->rip_nets[0].rip_metric =  htons(HOPCNT_INFINITY);
+       toall(sndmsg);
+       signal(SIGALRM, timer);
+       signal(SIGHUP, hup);
+       signal(SIGINT, hup);
+       signal(SIGEMT, fkexit);
+       timer();
+       
+
+       for (;;) 
+               process(s);
+       
+}
+
+process(fd)
+       int fd;
+{
+       struct sockaddr from;
+       int fromlen = sizeof (from), cc, omask;
+       struct idp *idp = (struct idp *)packet;
+
+       cc = recvfrom(fd, packet, sizeof (packet), 0, &from, &fromlen);
+       if (cc <= 0) {
+               if (cc < 0 && errno != EINTR)
+                       syslog(LOG_ERR, "recvfrom: %m");
+               return;
+       }
+       if (tracepackets > 1 && ftrace) {
+           fprintf(ftrace,"rcv %d bytes on %s ", cc, xns_ntoa(&idp->idp_dna));
+           fprintf(ftrace," from %s\n", xns_ntoa(&idp->idp_sna));
+       }
+       
+       if (noteremoterequests && !ns_neteqnn(idp->idp_sna.x_net, ns_zeronet)
+               && !ns_neteq(idp->idp_sna, idp->idp_dna))
+       {
+               syslog(LOG_ERR,
+                      "net of interface (%s) != net on ether (%s)!\n",
+                      xns_nettoa(idp->idp_dna.x_net),
+                      xns_nettoa(idp->idp_sna.x_net));
+       }
+                       
+       /* We get the IDP header in front of the RIF packet*/
+       cc -= sizeof (struct idp);
+#define        mask(s) (1<<((s)-1))
+       omask = sigblock(mask(SIGALRM));
+       rip_input(&from, cc);
+       sigsetmask(omask);
+}
+
+getsocket(type, proto, sns)
+       int type, proto; 
+       struct sockaddr_ns *sns;
+{
+       int domain = sns->sns_family;
+       int retry, s, on = 1;
+
+       retry = 1;
+       while ((s = socket(domain, type, proto)) < 0 && retry) {
+               syslog(LOG_ERR, "socket: %m");
+               sleep(5 * retry);
+               retry <<= 1;
+       }
+       if (retry == 0)
+               return (-1);
+       while (bind(s, (struct sockaddr *)sns, sizeof (*sns)) < 0 && retry) {
+               syslog(LOG_ERR, "bind: %m");
+               sleep(5 * retry);
+               retry <<= 1;
+       }
+       if (retry == 0)
+               return (-1);
+       if (domain==AF_NS) {
+               struct idp idp;
+               if (setsockopt(s, 0, SO_HEADERS_ON_INPUT, &on, sizeof(on))) {
+                       syslog(LOG_ERR, "setsockopt SEE HEADERS: %m");
+                       exit(1);
+               }
+               idp.idp_pt = NSPROTO_RI;
+               if (setsockopt(s, 0, SO_DEFAULT_HEADERS, &idp, sizeof(idp))) {
+                       syslog(LOG_ERR, "setsockopt SET HEADER: %m");
+                       exit(1);
+               }
+       }
+       if (setsockopt(s, SOL_SOCKET, SO_BROADCAST, &on, sizeof (on)) < 0) {
+               syslog(LOG_ERR, "setsockopt SO_BROADCAST: %m");
+               exit(1);
+       }
+       return (s);
+}
+
+/*
+ * Fork and exit on EMT-- for profiling.
+ */
+void
+fkexit()
+{
+       if (fork() == 0)
+               exit(0);
+}
diff --git a/sbin/XNSrouted/output.c b/sbin/XNSrouted/output.c
new file mode 100644 (file)
index 0000000..cdea11f
--- /dev/null
@@ -0,0 +1,147 @@
+/*
+ * Copyright (c) 1985 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This file includes significant work done at Cornell University by
+ * Bill Nesheim.  That work included by permission.
+ *
+ * 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[] = "@(#)output.c   5.8 (Berkeley) 2/26/91";
+#endif /* not lint */
+
+/*
+ * Routing Table Management Daemon
+ */
+#include "defs.h"
+
+/*
+ * Apply the function "f" to all non-passive
+ * interfaces.  If the interface supports the
+ * use of broadcasting use it, otherwise address
+ * the output to the known router.
+ */
+toall(f)
+       int (*f)();
+{
+       register struct interface *ifp;
+       register struct sockaddr *dst;
+       register int flags;
+       extern struct interface *ifnet;
+
+       for (ifp = ifnet; ifp; ifp = ifp->int_next) {
+               if (ifp->int_flags & IFF_PASSIVE)
+                       continue;
+               dst = ifp->int_flags & IFF_BROADCAST ? &ifp->int_broadaddr :
+                     ifp->int_flags & IFF_POINTOPOINT ? &ifp->int_dstaddr :
+                     &ifp->int_addr;
+               flags = ifp->int_flags & IFF_INTERFACE ? MSG_DONTROUTE : 0;
+               (*f)(dst, flags, ifp);
+       }
+}
+
+/*
+ * Output a preformed packet.
+ */
+/*ARGSUSED*/
+sndmsg(dst, flags, ifp)
+       struct sockaddr *dst;
+       int flags;
+       struct interface *ifp;
+{
+
+       (*afswitch[dst->sa_family].af_output)
+               (flags, dst, sizeof (struct rip));
+       TRACE_OUTPUT(ifp, dst, sizeof (struct rip));
+}
+
+/*
+ * Supply dst with the contents of the routing tables.
+ * If this won't fit in one packet, chop it up into several.
+ */
+supply(dst, flags, ifp)
+       struct sockaddr *dst;
+       int flags;
+       struct interface *ifp;
+{
+       register struct rt_entry *rt;
+       register struct rthash *rh;
+       register struct netinfo *nn;
+       register struct netinfo *n = msg->rip_nets;
+       struct rthash *base = hosthash;
+       struct sockaddr_ns *sns =  (struct sockaddr_ns *) dst;
+       int (*output)() = afswitch[dst->sa_family].af_output;
+       int doinghost = 1, size, metric;
+       union ns_net net;
+
+       msg->rip_cmd = ntohs(RIPCMD_RESPONSE);
+again:
+       for (rh = base; rh < &base[ROUTEHASHSIZ]; rh++)
+       for (rt = rh->rt_forw; rt != (struct rt_entry *)rh; rt = rt->rt_forw) {
+               size = (char *)n - (char *)msg;
+               if (size > MAXPACKETSIZE - sizeof (struct netinfo)) {
+                       (*output)(flags, dst, size);
+                       TRACE_OUTPUT(ifp, dst, size);
+                       n = msg->rip_nets;
+               }
+               sns = (struct sockaddr_ns *)&rt->rt_dst;
+               if ((rt->rt_flags & (RTF_HOST|RTF_GATEWAY)) == RTF_HOST)
+                       sns = (struct sockaddr_ns *)&rt->rt_router;
+               metric = min(rt->rt_metric + 1, HOPCNT_INFINITY);
+               net = sns->sns_addr.x_net;
+               /*
+                * Make sure that we don't put out a two net entries
+                * for a pt to pt link (one for the G route, one for the if)
+                * This is a kludge, and won't work if there are lots of nets.
+                */
+               for (nn = msg->rip_nets; nn < n; nn++) {
+                       if (ns_neteqnn(net, nn->rip_dst)) {
+                               if (metric < ntohs(nn->rip_metric))
+                                       nn->rip_metric = htons(metric);
+                               goto next;
+                       }
+               }
+               n->rip_dst = net;
+               n->rip_metric = htons(metric);
+               n++;
+       next:;
+       }
+       if (doinghost) {
+               doinghost = 0;
+               base = nethash;
+               goto again;
+       }
+       if (n != msg->rip_nets) {
+               size = (char *)n - (char *)msg;
+               (*output)(flags, dst, size);
+               TRACE_OUTPUT(ifp, dst, size);
+       }
+}
diff --git a/sbin/XNSrouted/protocol.h b/sbin/XNSrouted/protocol.h
new file mode 100644 (file)
index 0000000..9bf422b
--- /dev/null
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 1985 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This file includes significant work done at Cornell University by
+ * Bill Nesheim.  That work included by permission.
+ *
+ * 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.
+ *
+ *     @(#)protocol.h  5.6 (Berkeley) 6/1/90
+ */
+
+/*
+ * Xerox Routing Information Protocol
+ *
+ */
+
+struct netinfo {
+       union ns_net    rip_dst;                /* destination net */
+       u_short         rip_metric;             /* cost of route */
+};
+
+struct rip {
+       u_short rip_cmd;                /* request/response */
+       struct netinfo rip_nets[1];     /* variable length */
+};
+/*
+ * Packet types.
+ */
+#define        RIPCMD_REQUEST          1       /* want info */
+#define        RIPCMD_RESPONSE         2       /* responding to request */
+
+#define        RIPCMD_MAX              3
+#ifdef RIPCMDS
+char *ripcmds[RIPCMD_MAX] =
+  { "#0", "REQUEST", "RESPONSE" };
+#endif
+
+#define        HOPCNT_INFINITY         16              /* per Xerox NS */
+#define        DSTNETS_ALL             0xffffffff      /* per Xerox NS */
+#define        MAXPACKETSIZE           512             /* max broadcast size */
+
+extern union ns_net ns_anynet;
+extern union ns_net ns_zeronet;
+
+/*
+ * Timer values used in managing the routing table.
+ * Every update forces an entry's timer to be reset.  After
+ * EXPIRE_TIME without updates, the entry is marked invalid,
+ * but held onto until GARBAGE_TIME so that others may
+ * see it "be deleted".
+ */
+#define        TIMER_RATE              30      /* alarm clocks every 30 seconds */
+
+#define        SUPPLY_INTERVAL         30      /* time to supply tables */
+
+#define        EXPIRE_TIME             180     /* time to mark entry invalid */
+#define        GARBAGE_TIME            240     /* time to garbage collect */
diff --git a/sbin/XNSrouted/startup.c b/sbin/XNSrouted/startup.c
new file mode 100644 (file)
index 0000000..8887c1f
--- /dev/null
@@ -0,0 +1,218 @@
+/*
+ * Copyright (c) 1985 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This file includes significant work done at Cornell University by
+ * Bill Nesheim.  That work included by permission.
+ *
+ * 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[] = "@(#)startup.c  5.11 (Berkeley) 2/26/91";
+#endif /* not lint */
+
+/*
+ * Routing Table Management Daemon
+ */
+#include "defs.h"
+#include <sys/ioctl.h>
+#include <net/if.h>
+#include <nlist.h>
+#include <stdlib.h>
+
+struct interface *ifnet;
+int    lookforinterfaces = 1;
+int    performnlist = 1;
+int    gateway = 0;
+int    externalinterfaces = 0;         /* # of remote and local interfaces */
+char ether_broadcast_addr[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
+
+
+/*
+ * Find the network interfaces which have configured themselves.
+ * If the interface is present but not yet up (for example an
+ * ARPANET IMP), set the lookforinterfaces flag so we'll
+ * come back later and look again.
+ */
+ifinit()
+{
+       struct interface ifs, *ifp;
+       int s;
+        struct ifconf ifc;
+       char buf[BUFSIZ], *cp, *cplim;
+        struct ifreq ifreq, *ifr;
+       u_long i;
+
+       if ((s = socket(AF_NS, SOCK_DGRAM, 0)) < 0) {
+               syslog(LOG_ERR, "socket: %m");
+               exit(1);
+       }
+        ifc.ifc_len = sizeof (buf);
+        ifc.ifc_buf = buf;
+        if (ioctl(s, SIOCGIFCONF, (char *)&ifc) < 0) {
+                syslog(LOG_ERR, "ioctl (get interface configuration)");
+               close(s);
+                exit(1);
+        }
+        ifr = ifc.ifc_req;
+       lookforinterfaces = 0;
+#ifdef RTM_ADD
+#define max(a, b) (a > b ? a : b)
+#define size(p)        max((p).sa_len, sizeof(p))
+#else
+#define size(p) (sizeof (p))
+#endif
+       cplim = buf + ifc.ifc_len; /*skip over if's with big ifr_addr's */
+       for (cp = buf; cp < cplim;
+                       cp += sizeof (ifr->ifr_name) + size(ifr->ifr_addr)) {
+               ifr = (struct ifreq *)cp;
+               bzero((char *)&ifs, sizeof(ifs));
+               ifs.int_addr = ifr->ifr_addr;
+               ifreq = *ifr;
+                if (ioctl(s, SIOCGIFFLAGS, (char *)&ifreq) < 0) {
+                        syslog(LOG_ERR, "ioctl (get interface flags)");
+                        continue;
+                }
+               ifs.int_flags = ifreq.ifr_flags | IFF_INTERFACE;
+               if ((ifs.int_flags & IFF_UP) == 0 ||
+                   ifr->ifr_addr.sa_family == AF_UNSPEC) {
+                       lookforinterfaces = 1;
+                       continue;
+               }
+               if (ifs.int_addr.sa_family != AF_NS)
+                       continue;
+                if (ifs.int_flags & IFF_POINTOPOINT) {
+                        if (ioctl(s, SIOCGIFDSTADDR, (char *)&ifreq) < 0) {
+                                syslog(LOG_ERR, "ioctl (get dstaddr): %m");
+                                continue;
+                       }
+                       ifs.int_dstaddr = ifreq.ifr_dstaddr;
+               }
+                if (ifs.int_flags & IFF_BROADCAST) {
+                        if (ioctl(s, SIOCGIFBRDADDR, (char *)&ifreq) < 0) {
+                                syslog(LOG_ERR, "ioctl (get broadaddr: %m");
+                                continue;
+                        }
+                       ifs.int_broadaddr = ifreq.ifr_broadaddr;
+               }
+               /* 
+                * already known to us? 
+                * what makes a POINTOPOINT if unique is its dst addr,
+                * NOT its source address 
+                */
+               if ( ((ifs.int_flags & IFF_POINTOPOINT) &&
+                       if_ifwithdstaddr(&ifs.int_dstaddr)) ||
+                       ( ((ifs.int_flags & IFF_POINTOPOINT) == 0) &&
+                       if_ifwithaddr(&ifs.int_addr)))
+                       continue;
+               /* no one cares about software loopback interfaces */
+               if (strncmp(ifr->ifr_name,"lo", 2)==0)
+                       continue;
+               ifp = (struct interface *)malloc(sizeof (struct interface));
+               if (ifp == 0) {
+                       syslog(LOG_ERR,"XNSrouted: out of memory\n");
+                       break;
+               }
+               *ifp = ifs;
+               /*
+                * Count the # of directly connected networks
+                * and point to point links which aren't looped
+                * back to ourself.  This is used below to
+                * decide if we should be a routing ``supplier''.
+                */
+               if ((ifs.int_flags & IFF_POINTOPOINT) == 0 ||
+                   if_ifwithaddr(&ifs.int_dstaddr) == 0)
+                       externalinterfaces++;
+               /*
+                * If we have a point-to-point link, we want to act
+                * as a supplier even if it's our only interface,
+                * as that's the only way our peer on the other end
+                * can tell that the link is up.
+                */
+               if ((ifs.int_flags & IFF_POINTOPOINT) && supplier < 0)
+                       supplier = 1;
+               ifp->int_name = malloc(strlen(ifr->ifr_name) + 1);
+               if (ifp->int_name == 0) {
+                       syslog(LOG_ERR,"XNSrouted: out of memory\n");
+                       exit(1);
+               }
+               strcpy(ifp->int_name, ifr->ifr_name);
+               ifp->int_metric = 0;
+               ifp->int_next = ifnet;
+               ifnet = ifp;
+               traceinit(ifp);
+               addrouteforif(ifp);
+       }
+       if (externalinterfaces > 1 && supplier < 0)
+               supplier = 1;
+       close(s);
+}
+
+addrouteforif(ifp)
+       struct interface *ifp;
+{
+       struct sockaddr_ns net;
+       struct sockaddr *dst;
+       int state, metric;
+       struct rt_entry *rt;
+
+       if (ifp->int_flags & IFF_POINTOPOINT) {
+               int (*match)();
+               register struct interface *ifp2 = ifnet;
+               register struct interface *ifprev = ifnet;
+               
+               dst = &ifp->int_dstaddr;
+
+               /* Search for interfaces with the same net */
+               ifp->int_sq.n = ifp->int_sq.p = &(ifp->int_sq);
+               match = afswitch[dst->sa_family].af_netmatch;
+               if (match)
+               for (ifp2 = ifnet; ifp2; ifp2 =ifp2->int_next) {
+                       if (ifp->int_flags & IFF_POINTOPOINT == 0)
+                               continue;
+                       if ((*match)(&ifp2->int_dstaddr,&ifp->int_dstaddr)) {
+                               insque(&ifp2->int_sq,&ifp->int_sq);
+                               break;
+                       }
+               }
+       } else {
+               dst = &ifp->int_broadaddr;
+       }
+       rt = rtlookup(dst);
+       if (rt)
+               rtdelete(rt);
+       if (tracing)
+               fprintf(stderr, "Adding route to interface %s\n", ifp->int_name);
+       if (ifp->int_transitions++ > 0)
+               syslog(LOG_ERR, "re-installing interface %s", ifp->int_name);
+       rtadd(dst, &ifp->int_addr, ifp->int_metric,
+               ifp->int_flags & (IFF_INTERFACE|IFF_PASSIVE|IFF_REMOTE));
+}
+
diff --git a/sbin/XNSrouted/table.h b/sbin/XNSrouted/table.h
new file mode 100644 (file)
index 0000000..159dc4e
--- /dev/null
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 1983 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.
+ *
+ *     @(#)table.h     5.1 (Berkeley) 6/4/85 (routed/table.h)
+ *
+ *     @(#)table.h     5.3 (Berkeley) 6/1/90
+ */
+
+/*
+ * Routing table management daemon.
+ */
+
+/*
+ * Routing table structure; differs a bit from kernel tables.
+ *
+ * Note: the union below must agree in the first 4 members
+ * so the ioctl's will work.
+ */
+struct rthash {
+       struct  rt_entry *rt_forw;
+       struct  rt_entry *rt_back;
+};
+
+#ifdef RTM_ADD
+#define rtentry ortentry
+#endif
+
+struct rt_entry {
+       struct  rt_entry *rt_forw;
+       struct  rt_entry *rt_back;
+       union {
+               struct  rtentry rtu_rt;
+               struct {
+                       u_long  rtu_hash;
+                       struct  sockaddr rtu_dst;
+                       struct  sockaddr rtu_router;
+                       short   rtu_flags;
+                       short   rtu_state;
+                       int     rtu_timer;
+                       int     rtu_metric;
+                       struct  interface *rtu_ifp;
+               } rtu_entry;
+       } rt_rtu;
+};
+
+#define        rt_rt           rt_rtu.rtu_rt                   /* pass to ioctl */
+#define        rt_hash         rt_rtu.rtu_entry.rtu_hash       /* for net or host */
+#define        rt_dst          rt_rtu.rtu_entry.rtu_dst        /* match value */
+#define        rt_router       rt_rtu.rtu_entry.rtu_router     /* who to forward to */
+#define        rt_flags        rt_rtu.rtu_entry.rtu_flags      /* kernel flags */
+#define        rt_timer        rt_rtu.rtu_entry.rtu_timer      /* for invalidation */
+#define        rt_state        rt_rtu.rtu_entry.rtu_state      /* see below */
+#define        rt_metric       rt_rtu.rtu_entry.rtu_metric     /* cost of route */
+#define        rt_ifp          rt_rtu.rtu_entry.rtu_ifp        /* interface to take */
+
+#define        ROUTEHASHSIZ    32              /* must be a power of 2 */
+#define        ROUTEHASHMASK   (ROUTEHASHSIZ - 1)
+
+/*
+ * "State" of routing table entry.
+ */
+#define        RTS_CHANGED     0x1             /* route has been altered recently */
+#define        RTS_PASSIVE     IFF_PASSIVE     /* don't time out route */
+#define        RTS_INTERFACE   IFF_INTERFACE   /* route is for network interface */
+#define        RTS_REMOTE      IFF_REMOTE      /* route is for ``remote'' entity */
+
+struct rthash nethash[ROUTEHASHSIZ];
+struct rthash hosthash[ROUTEHASHSIZ];
+struct rt_entry *rtlookup();
+struct rt_entry *rtfind();
diff --git a/sbin/XNSrouted/tables.c b/sbin/XNSrouted/tables.c
new file mode 100644 (file)
index 0000000..38ce438
--- /dev/null
@@ -0,0 +1,265 @@
+/*
+ * Copyright (c) 1985 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   5.9 (Berkeley) 6/1/90";
+#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 && ioctl(s, SIOCADDRT, (char *)&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 (ioctl(s, SIOCADDRT, (char *)&rt->rt_rt) < 0)
+                 syslog(LOG_ERR, "SIOCADDRT 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 && ioctl(s, SIOCDELRT, (char *)&oldroute) < 0)
+                       perror("SIOCDELRT");
+#else
+               if (delete && ioctl(s, SIOCDELRT, (char *)&oldroute) < 0)
+                       perror("SIOCDELRT");
+               if (ioctl(s, SIOCADDRT, (char *)&rt->rt_rt) < 0)
+                 syslog(LOG_ERR, "SIOCADDRT 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 && ioctl(s, SIOCDELRT, (char *)&rt->rt_rt))
+               perror("SIOCDELRT");
+       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;
+}
diff --git a/sbin/XNSrouted/timer.c b/sbin/XNSrouted/timer.c
new file mode 100644 (file)
index 0000000..f420bc0
--- /dev/null
@@ -0,0 +1,139 @@
+/*
+ * Copyright (c) 1985 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This file includes significant work done at Cornell University by
+ * Bill Nesheim.  That work included by permission.
+ *
+ * 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[] = "@(#)timer.c    5.7 (Berkeley) 2/26/91";
+#endif /* not lint */
+
+/*
+ * Routing Table Management Daemon
+ */
+#include "defs.h"
+
+int    timeval = -TIMER_RATE;
+
+/*
+ * Timer routine.  Performs routing information supply
+ * duties and manages timers on routing table entries.
+ */
+void
+timer()
+{
+       register struct rthash *rh;
+       register struct rt_entry *rt;
+       struct rthash *base = hosthash;
+       int doinghost = 1, timetobroadcast;
+
+       timeval += TIMER_RATE;
+       if (lookforinterfaces && (timeval % CHECK_INTERVAL) == 0)
+               ifinit();
+       timetobroadcast = supplier && (timeval % SUPPLY_INTERVAL) == 0;
+again:
+       for (rh = base; rh < &base[ROUTEHASHSIZ]; rh++) {
+               rt = rh->rt_forw;
+               for (; rt != (struct rt_entry *)rh; rt = rt->rt_forw) {
+                       /*
+                        * We don't advance time on a routing entry for
+                        * a passive gateway or that for our only interface. 
+                        * The latter is excused because we don't act as
+                        * a routing information supplier and hence would
+                        * time it out.  This is fair as if it's down
+                        * we're cut off from the world anyway and it's
+                        * not likely we'll grow any new hardware in
+                        * the mean time.
+                        */
+                       if (!(rt->rt_state & RTS_PASSIVE) &&
+                           (supplier || !(rt->rt_state & RTS_INTERFACE)))
+                               rt->rt_timer += TIMER_RATE;
+                       if (rt->rt_timer >= EXPIRE_TIME)
+                               rt->rt_metric = HOPCNT_INFINITY;
+                       if (rt->rt_timer >= GARBAGE_TIME) {
+                               rt = rt->rt_back;
+                               /* Perhaps we should send a REQUEST for this route? */
+                               rtdelete(rt->rt_forw);
+                               continue;
+                       }
+                       if (rt->rt_state & RTS_CHANGED) {
+                               rt->rt_state &= ~RTS_CHANGED;
+                               /* don't send extraneous packets */
+                               if (!supplier || timetobroadcast)
+                                       continue;
+                               msg->rip_cmd = htons(RIPCMD_RESPONSE);
+                               msg->rip_nets[0].rip_dst =
+                                       (satons_addr(rt->rt_dst)).x_net;
+                               msg->rip_nets[0].rip_metric =
+                                       htons(min(rt->rt_metric+1, HOPCNT_INFINITY));
+                               toall(sndmsg);
+                       }
+               }
+       }
+       if (doinghost) {
+               doinghost = 0;
+               base = nethash;
+               goto again;
+       }
+       if (timetobroadcast)
+               toall(supply);
+       alarm(TIMER_RATE);
+}
+
+/*
+ * On hangup, let everyone know we're going away.
+ */
+void
+hup()
+{
+       register struct rthash *rh;
+       register struct rt_entry *rt;
+       struct rthash *base = hosthash;
+       int doinghost = 1;
+
+       if (supplier) {
+again:
+               for (rh = base; rh < &base[ROUTEHASHSIZ]; rh++) {
+                       rt = rh->rt_forw;
+                       for (; rt != (struct rt_entry *)rh; rt = rt->rt_forw)
+                               rt->rt_metric = HOPCNT_INFINITY;
+               }
+               if (doinghost) {
+                       doinghost = 0;
+                       base = nethash;
+                       goto again;
+               }
+               toall(supply);
+       }
+       exit(1);
+}
diff --git a/sbin/XNSrouted/tools/query.c b/sbin/XNSrouted/tools/query.c
new file mode 100644 (file)
index 0000000..2e6374d
--- /dev/null
@@ -0,0 +1,232 @@
+/*-
+ * Copyright (c) 1983, 1986 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code includes software contributed to Berkeley by
+ * Bill Nesheim at Cornell University.
+ *
+ * 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
+char copyright[] =
+"@(#) Copyright (c) 1983, 1986 The Regents of the University of California.\n\
+ All rights reserved.\n";
+#endif /* not lint */
+
+#ifndef lint
+static char sccsid[] = "@(#)query.c    5.8 (Berkeley) 4/16/91";
+#endif /* not lint */
+
+#include <sys/param.h>
+#include <sys/protosw.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+#include <netinet/in.h>
+#include <netns/ns.h>
+#include <netns/idp.h>
+#include <errno.h>
+#include <stdio.h>
+#include <netdb.h>
+#include "../protocol.h"
+#define IDPPORT_RIF 1
+
+#define        WTIME   5               /* Time to wait for responses */
+
+int    s;
+int    timedout, timeout();
+char   packet[MAXPACKETSIZE];
+extern int errno;
+struct sockaddr_ns     myaddr = {sizeof(myaddr), AF_NS};
+char *ns_ntoa();
+struct ns_addr ns_addr();
+main(argc, argv)
+int argc;
+char *argv[];
+{
+       int cc, count, bits;
+       struct sockaddr from;
+       int fromlen = sizeof(from);
+       struct timeval notime;
+       
+       if (argc < 2) {
+               printf("usage: query hosts...\n");
+               exit(1);
+       }
+       s = getsocket(SOCK_DGRAM, 0);
+       if (s < 0) {
+               perror("socket");
+               exit(2);
+       }
+
+       argv++, argc--;
+       query(argv,argc);
+
+       /*
+        * Listen for returning packets;
+        * may be more than one packet per host.
+        */
+       bits = 1 << s;
+       bzero(&notime, sizeof(notime));
+       signal(SIGALRM, timeout);
+       alarm(WTIME);
+       while (!timedout || 
+           select(20, &bits, 0, 0, &notime) > 0) {
+               struct nspacket {
+                       struct idp hdr;
+                       char    data[512];
+               } response;
+               cc = recvfrom(s, &response, sizeof (response), 0,
+                 &from, &fromlen);
+               if (cc <= 0) {
+                       if (cc < 0) {
+                               if (errno == EINTR)
+                                       continue;
+                               perror("recvfrom");
+                               (void) close(s);
+                               exit(1);
+                       }
+                       continue;
+               }
+               rip_input(&from, response.data, cc);
+               count--;
+       }
+}
+static struct sockaddr_ns router = {sizeof(myaddr), AF_NS};
+static struct ns_addr zero_addr;
+static short allones[] = {-1, -1, -1};
+
+query(argv,argc)
+char **argv;
+{
+       register struct rip *msg = (struct rip *)packet;
+       char *host = *argv;
+       int flags = 0;
+       struct ns_addr specific;
+
+       if (bcmp(*argv, "-r", 3) == 0) {
+               flags = MSG_DONTROUTE; argv++; argc--;
+       }
+       host = *argv;
+       router.sns_addr = ns_addr(host);
+       router.sns_addr.x_port = htons(IDPPORT_RIF);
+       if (ns_hosteq(zero_addr, router.sns_addr)) {
+               router.sns_addr.x_host = *(union ns_host *) allones;
+       }
+       msg->rip_cmd = htons(RIPCMD_REQUEST);
+       msg->rip_nets[0].rip_dst = *(union ns_net *) allones;
+       msg->rip_nets[0].rip_metric = htons(HOPCNT_INFINITY);
+       if (argc > 0) {
+               specific = ns_addr(*argv);
+               msg->rip_nets[0].rip_dst = specific.x_net;
+               specific.x_host = zero_addr.x_host;
+               specific.x_port = zero_addr.x_port;
+               printf("Net asked for was %s\n", ns_ntoa(specific));
+       }
+       if (sendto(s, packet, sizeof (struct rip), flags,
+         &router, sizeof(router)) < 0)
+               perror(host);
+}
+
+/*
+ * Handle an incoming routing packet.
+ */
+rip_input(from, msg,  size)
+       struct sockaddr_ns *from;
+       register struct rip *msg;
+       int size;
+{
+       struct netinfo *n;
+       char *name;
+       int lna, net, subnet;
+       struct hostent *hp;
+       struct netent *np;
+       static struct ns_addr work;
+
+       if (htons(msg->rip_cmd) != RIPCMD_RESPONSE)
+               return;
+       printf("from %s\n", ns_ntoa(from->sns_addr));
+       size -= sizeof (struct idp);
+       size -= sizeof (short);
+       n = msg->rip_nets;
+       while (size > 0) {
+               union ns_net_u net;
+               if (size < sizeof (struct netinfo))
+                       break;
+               net.net_e = n->rip_dst;
+               printf("\t%d, metric %d\n", ntohl(net.long_e),
+                       ntohs(n->rip_metric));
+               size -= sizeof (struct netinfo), n++;
+       }
+}
+
+timeout()
+{
+       timedout = 1;
+}
+getsocket(type, proto)
+       int type, proto; 
+{
+       struct sockaddr_ns *sns = &myaddr;
+       int domain = sns->sns_family;
+       int retry, s, on = 1;
+
+       retry = 1;
+       while ((s = socket(domain, type, proto)) < 0 && retry) {
+               perror("socket");
+               sleep(5 * retry);
+               retry <<= 1;
+       }
+       if (retry == 0)
+               return (-1);
+       while (bind(s, sns, sizeof (*sns), 0) < 0 && retry) {
+               perror("bind");
+               sleep(5 * retry);
+               retry <<= 1;
+       }
+       if (retry == 0)
+               return (-1);
+       if (domain==AF_NS) {
+               struct idp idp;
+               if (setsockopt(s, 0, SO_HEADERS_ON_INPUT, &on, sizeof(on))) {
+                       perror("setsockopt SEE HEADERS");
+                       exit(1);
+               }
+               idp.idp_pt = NSPROTO_RI;
+               if (setsockopt(s, 0, SO_DEFAULT_HEADERS, &idp, sizeof(idp))) {
+                       perror("setsockopt SET HEADERS");
+                       exit(1);
+               }
+       }
+       if (setsockopt(s, SOL_SOCKET, SO_BROADCAST, &on, sizeof (on)) < 0) {
+               perror("setsockopt SO_BROADCAST");
+               exit(1);
+       }
+       return (s);
+}
diff --git a/sbin/XNSrouted/trace.c b/sbin/XNSrouted/trace.c
new file mode 100644 (file)
index 0000000..5172873
--- /dev/null
@@ -0,0 +1,313 @@
+/*
+ * Copyright (c) 1985 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This file includes significant work done at Cornell University by
+ * Bill Nesheim.  That work included by permission.
+ *
+ * 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[] = "@(#)trace.c    5.11 (Berkeley) 2/26/91";
+#endif /* not lint */
+
+/*
+ * Routing Table Management Daemon
+ */
+#define        RIPCMDS
+#include <stdlib.h>
+#include "defs.h"
+
+#define        NRECORDS        50              /* size of circular trace buffer */
+#ifdef DEBUG
+FILE   *ftrace = stdout;
+int    tracing = 1;
+#else DEBUG
+FILE   *ftrace = NULL;
+int    tracing = 0;
+#endif
+
+char *xns_ntoa();
+
+traceinit(ifp)
+       register struct interface *ifp;
+{
+       static int iftraceinit();
+
+       if (iftraceinit(ifp, &ifp->int_input) &&
+           iftraceinit(ifp, &ifp->int_output))
+               return;
+       tracing = 0;
+       syslog(LOG_ERR, "traceinit: can't init %s\n", ifp->int_name);
+}
+
+static
+iftraceinit(ifp, ifd)
+       struct interface *ifp;
+       register struct ifdebug *ifd;
+{
+       register struct iftrace *t;
+
+       ifd->ifd_records =
+         (struct iftrace *)malloc(NRECORDS * sizeof (struct iftrace));
+       if (ifd->ifd_records == 0)
+               return (0);
+       ifd->ifd_front = ifd->ifd_records;
+       ifd->ifd_count = 0;
+       for (t = ifd->ifd_records; t < ifd->ifd_records + NRECORDS; t++) {
+               t->ift_size = 0;
+               t->ift_packet = 0;
+       }
+       ifd->ifd_if = ifp;
+       return (1);
+}
+
+traceon(file)
+       char *file;
+{
+
+       if (ftrace != NULL)
+               return;
+       ftrace = fopen(file, "a");
+       if (ftrace == NULL)
+               return;
+       dup2(fileno(ftrace), 1);
+       dup2(fileno(ftrace), 2);
+       tracing = 1;
+}
+
+traceoff()
+{
+       if (!tracing)
+               return;
+       if (ftrace != NULL)
+               fclose(ftrace);
+       ftrace = NULL;
+       tracing = 0;
+}
+
+trace(ifd, who, p, len, m)
+       register struct ifdebug *ifd;
+       struct sockaddr *who;
+       char *p;
+       int len, m;
+{
+       register struct iftrace *t;
+
+       if (ifd->ifd_records == 0)
+               return;
+       t = ifd->ifd_front++;
+       if (ifd->ifd_front >= ifd->ifd_records + NRECORDS)
+               ifd->ifd_front = ifd->ifd_records;
+       if (ifd->ifd_count < NRECORDS)
+               ifd->ifd_count++;
+       if (t->ift_size > 0 && t->ift_packet)
+               free(t->ift_packet);
+       t->ift_packet = 0;
+       t->ift_stamp = time(0);
+       t->ift_who = *who;
+       if (len > 0) {
+               t->ift_packet = malloc(len);
+               if (t->ift_packet)
+                       bcopy(p, t->ift_packet, len);
+               else
+                       len = 0;
+       }
+       t->ift_size = len;
+       t->ift_metric = m;
+}
+
+traceaction(fd, action, rt)
+       FILE *fd;
+       char *action;
+       struct rt_entry *rt;
+{
+       struct sockaddr_ns *dst, *gate;
+       static struct bits {
+               int     t_bits;
+               char    *t_name;
+       } flagbits[] = {
+               { RTF_UP,       "UP" },
+               { RTF_GATEWAY,  "GATEWAY" },
+               { RTF_HOST,     "HOST" },
+               { 0 }
+       }, statebits[] = {
+               { RTS_PASSIVE,  "PASSIVE" },
+               { RTS_REMOTE,   "REMOTE" },
+               { RTS_INTERFACE,"INTERFACE" },
+               { RTS_CHANGED,  "CHANGED" },
+               { 0 }
+       };
+       register struct bits *p;
+       register int first;
+       char *cp;
+       struct interface *ifp;
+
+       if (fd == NULL)
+               return;
+       fprintf(fd, "%s ", action);
+       dst = (struct sockaddr_ns *)&rt->rt_dst;
+       gate = (struct sockaddr_ns *)&rt->rt_router;
+       fprintf(fd, "dst %s, ", xns_ntoa(&dst->sns_addr));
+       fprintf(fd, "router %s, metric %d, flags",
+            xns_ntoa(&gate->sns_addr), rt->rt_metric);
+       cp = " %s";
+       for (first = 1, p = flagbits; p->t_bits > 0; p++) {
+               if ((rt->rt_flags & p->t_bits) == 0)
+                       continue;
+               fprintf(fd, cp, p->t_name);
+               if (first) {
+                       cp = "|%s";
+                       first = 0;
+               }
+       }
+       fprintf(fd, " state");
+       cp = " %s";
+       for (first = 1, p = statebits; p->t_bits > 0; p++) {
+               if ((rt->rt_state & p->t_bits) == 0)
+                       continue;
+               fprintf(fd, cp, p->t_name);
+               if (first) {
+                       cp = "|%s";
+                       first = 0;
+               }
+       }
+       putc('\n', fd);
+       if (!tracepackets && (rt->rt_state & RTS_PASSIVE) == 0 && rt->rt_ifp)
+               dumpif(fd, rt->rt_ifp);
+       fflush(fd);
+}
+
+dumpif(fd, ifp)
+       register struct interface *ifp;
+       FILE *fd;
+{
+       if (ifp->int_input.ifd_count || ifp->int_output.ifd_count) {
+               fprintf(fd, "*** Packet history for interface %s ***\n",
+                       ifp->int_name);
+               dumptrace(fd, "to", &ifp->int_output);
+               dumptrace(fd, "from", &ifp->int_input);
+               fprintf(fd, "*** end packet history ***\n");
+       }
+}
+
+dumptrace(fd, dir, ifd)
+       FILE *fd;
+       char *dir;
+       register struct ifdebug *ifd;
+{
+       register struct iftrace *t;
+       char *cp = !strcmp(dir, "to") ? "Output" : "Input";
+
+       if (ifd->ifd_front == ifd->ifd_records &&
+           ifd->ifd_front->ift_size == 0) {
+               fprintf(fd, "%s: no packets.\n", cp);
+               return;
+       }
+       fprintf(fd, "%s trace:\n", cp);
+       t = ifd->ifd_front - ifd->ifd_count;
+       if (t < ifd->ifd_records)
+               t += NRECORDS;
+       for ( ; ifd->ifd_count; ifd->ifd_count--, t++) {
+               if (t >= ifd->ifd_records + NRECORDS)
+                       t = ifd->ifd_records;
+               if (t->ift_size == 0)
+                       continue;
+               fprintf(fd, "%.24s: metric=%d\n", ctime(&t->ift_stamp),
+                       t->ift_metric);
+               dumppacket(fd, dir, &t->ift_who, t->ift_packet, t->ift_size);
+       }
+}
+
+dumppacket(fd, dir, who, cp, size)
+       FILE *fd;
+       struct sockaddr_ns *who;                /* should be sockaddr */
+       char *dir, *cp;
+       register int size;
+{
+       register struct rip *msg = (struct rip *)cp;
+       register struct netinfo *n;
+       char *xns_nettoa();
+
+       if (msg->rip_cmd && ntohs(msg->rip_cmd) < RIPCMD_MAX)
+               fprintf(fd, "%s %s %s#%x", ripcmds[ntohs(msg->rip_cmd)],
+                   dir, xns_ntoa(&who->sns_addr), ntohs(who->sns_addr.x_port));
+       else {
+               fprintf(fd, "Bad cmd 0x%x %s %s#%x\n", ntohs(msg->rip_cmd),
+                   dir, xns_ntoa(&who->sns_addr), ntohs(who->sns_addr.x_port));
+               fprintf(fd, "size=%d cp=%x packet=%x\n", size, cp, packet);
+               return;
+       }
+       switch (ntohs(msg->rip_cmd)) {
+
+       case RIPCMD_REQUEST:
+       case RIPCMD_RESPONSE:
+               fprintf(fd, ":\n");
+               size -= sizeof (u_short);
+               n = msg->rip_nets;
+               for (; size > 0; n++, size -= sizeof (struct netinfo)) {
+                       if (size < sizeof (struct netinfo))
+                               break;
+                       fprintf(fd, "\tnet %s metric %d\n",
+                            xns_nettoa(n->rip_dst),
+                            ntohs(n->rip_metric));
+               }
+               break;
+
+       }
+}
+
+union ns_net_u net;
+
+char *
+xns_nettoa(val)
+union ns_net val;
+{
+       static char buf[100];
+       net.net_e = val;
+       (void)sprintf(buf, "%lx", ntohl(net.long_e));
+       return (buf);
+}
+
+
+char *
+xns_ntoa(addr)
+struct ns_addr *addr;
+{
+    static char buf[100];
+
+    (void)sprintf(buf, "%s#%x:%x:%x:%x:%x:%x",
+       xns_nettoa(addr->x_net),
+       addr->x_host.c_host[0], addr->x_host.c_host[1], 
+       addr->x_host.c_host[2], addr->x_host.c_host[3], 
+       addr->x_host.c_host[4], addr->x_host.c_host[5]);
+       
+    return(buf);
+}
diff --git a/sbin/XNSrouted/trace.h b/sbin/XNSrouted/trace.h
new file mode 100644 (file)
index 0000000..be48553
--- /dev/null
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 1983 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This file includes significant work done at Cornell University by
+ * Bill Nesheim.  That work included by permission.
+ *
+ * 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.
+ *
+ *     @(#)trace.h     5.6 (Berkeley) 6/1/90
+ */
+
+/*
+ * Xerox Routing Information Protocol.
+ */
+
+/*
+ * Trace record format.
+ */
+struct iftrace {
+       time_t  ift_stamp;              /* time stamp */
+       struct  sockaddr ift_who;       /* from/to */
+       char    *ift_packet;            /* pointer to packet */
+       short   ift_size;               /* size of packet */
+       short   ift_metric;             /* metric  */
+};
+
+/*
+ * Per interface packet tracing buffers.  An incoming and
+ * outgoing circular buffer of packets is maintained, per
+ * interface, for debugging.  Buffers are dumped whenever
+ * an interface is marked down.
+ */
+struct ifdebug {
+       struct  iftrace *ifd_records;   /* array of trace records */
+       struct  iftrace *ifd_front;     /* next empty trace record */
+       int     ifd_count;              /* number of unprinted records */
+       struct  interface *ifd_if;      /* for locating stuff */
+};
+
+/*
+ * Packet tracing stuff.
+ */
+int    tracepackets;           /* watch packets as they go by */
+int    tracing;                /* on/off */
+FILE   *ftrace;                /* output trace file */
+
+#define        TRACE_ACTION(action, route) { \
+         if (tracing) \
+               traceaction(ftrace, "action", route); \
+       }
+#define        TRACE_INPUT(ifp, src, size) { \
+         if (tracing) { \
+               ifp = if_iflookup(src); \
+               if (ifp) \
+                       trace(&ifp->int_input, src, &packet[sizeof(struct idp)], size, \
+                               ntohl(ifp->int_metric)); \
+         } \
+         if (tracepackets && ftrace) \
+               dumppacket(ftrace, "from", src, &packet[sizeof(struct idp)], size); \
+       }
+#define        TRACE_OUTPUT(ifp, dst, size) { \
+         if (tracing) { \
+               ifp = if_iflookup(dst); \
+               if (ifp) \
+                   trace(&ifp->int_output, dst, &packet[sizeof(struct idp)], size, ifp->int_metric); \
+         } \
+         if (tracepackets && ftrace) \
+               dumppacket(ftrace, "to", dst, &packet[sizeof(struct idp)], size); \
+       }
diff --git a/usr.sbin/XNSrouted/Makefile b/usr.sbin/XNSrouted/Makefile
new file mode 100644 (file)
index 0000000..1722c6f
--- /dev/null
@@ -0,0 +1,10 @@
+#      From: @(#)Makefile      5.14 (Berkeley) 2/26/91
+#      $Id$
+
+PROG=  XNSrouted
+MAN8=  XNSrouted.8
+SRCS=  af.c if.c input.c main.c output.c startup.c tables.c timer.c trace.c
+DPADD= ${LIBUTIL}
+LDADD= -lutil
+
+.include <bsd.prog.mk>
diff --git a/usr.sbin/XNSrouted/XNSrouted.8 b/usr.sbin/XNSrouted/XNSrouted.8
new file mode 100644 (file)
index 0000000..144cb1d
--- /dev/null
@@ -0,0 +1,186 @@
+.\" Copyright (c) 1986, 1991 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.
+.\"
+.\"     @(#)XNSrouted.8        6.4 (Berkeley) 3/16/91
+.\"
+.Dd March 16, 1991
+.Dt XNSROUTED 8
+.Os BSD 4.3
+.Sh NAME
+.Nm XNSrouted
+.Nd NS Routing Information Protocol daemon
+.Sh SYNOPSIS
+.Nm XNSrouted
+.Op Fl q
+.Op Fl s
+.Op Fl t
+.Op Ar logfile
+.Sh DESCRIPTION
+.Nm XNSrouted
+is invoked at boot time to manage the Xerox NS routing tables.
+The NS routing daemon uses the Xerox NS Routing
+Information Protocol in maintaining up to date kernel routing
+table entries.
+.Pp
+Available options:
+.Bl -tag -width logfile
+.It Fl q
+Do not supply routing information (opposite of
+.Fl s
+option below).
+.It Fl s
+Forces 
+.Nm XNSrouted
+to supply routing information whether it is acting as an internetwork
+router or not.
+.It Fl t
+All packets sent or received are
+printed on the standard output.  In addition,
+.Nm XNSrouted
+will not divorce itself from the controlling terminal
+so that interrupts from the keyboard will kill the process.
+.It Ar logfile
+Name of file in which 
+.Nm XNSrouted Ns 's
+actions should be logged.  This log contains information
+about any changes to the routing tables and a history of
+recent messages sent and received which are related to
+the changed route.
+.El
+.Pp
+In normal operation
+.Nm XNSrouted
+listens
+for routing information packets.  If the host is connected to
+multiple NS networks, it periodically supplies copies
+of its routing tables to any directly connected hosts
+and networks.
+.Pp
+When
+.Nm XNSrouted
+is started, it uses the
+.Dv SIOCGIFCONF
+.Xr ioctl 2
+to find those
+directly connected interfaces configured into the
+system and marked
+.Dq up
+(the software loopback interface
+is ignored).  If multiple interfaces
+are present, it is assumed the host will forward packets
+between networks.
+.Nm XNSrouted
+then transmits a 
+.Em request
+packet on each interface (using a broadcast packet if
+the interface supports it) and enters a loop, listening
+for
+.Em request
+and
+.Em response
+packets from other hosts.
+.Pp
+When a
+.Em request
+packet is received, 
+.Nm XNSrouted
+formulates a reply based on the information maintained in its
+internal tables.  The
+.Em response
+packet generated contains a list of known routes, each marked
+with a
+.Dq hop count
+metric (a count of 16, or greater, is
+considered
+.Dq infinite ) .
+The metric associated with each
+route returned provides a metric
+.Em relative to the sender .
+.Pp
+.Em Response
+packets received by
+.Nm XNSrouted
+are used to update the routing tables if one of the following
+conditions is satisfied:
+.Bl -bullet
+.It
+No routing table entry exists for the destination network
+or host, and the metric indicates the destination is ``reachable''
+(i.e. the hop count is not infinite).
+.It
+The source host of the packet is the same as the router in the
+existing routing table entry.  That is, updated information is
+being received from the very internetwork router through which
+packets for the destination are being routed.
+.It
+The existing entry in the routing table has not been updated for
+some time (defined to be 90 seconds) and the route is at least
+as cost effective as the current route.
+.It
+The new route describes a shorter route to the destination than
+the one currently stored in the routing tables; the metric of
+the new route is compared against the one stored in the table
+to decide this.
+.El
+.Pp
+When an update is applied,
+.Nm XNSrouted
+records the change in its internal tables and generates a
+.Em response
+packet to all directly connected hosts and networks.
+.Xr Routed 8
+waits a short period
+of time (no more than 30 seconds) before modifying the kernel's
+routing tables to allow possible unstable situations to settle.
+.Pp
+In addition to processing incoming packets,
+.Nm XNSrouted
+also periodically checks the routing table entries.
+If an entry has not been updated for 3 minutes, the entry's metric
+is set to infinity and marked for deletion.  Deletions are delayed
+an additional 60 seconds to insure the invalidation is propagated
+to other routers.
+.Pp
+Hosts acting as internetwork routers gratuitously supply their
+routing tables every 30 seconds to all directly connected hosts
+and networks.
+.Sh SEE ALSO
+.Xr idp 4
+.Rs
+.%T "Internet Transport Protocols"
+.%R "XSIS 028112"
+.%Q "Xerox System Integration Standard"
+.Re
+.Sh HISTORY
+The
+.Nm
+command appeared in
+.Bx 4.3 .
diff --git a/usr.sbin/XNSrouted/af.c b/usr.sbin/XNSrouted/af.c
new file mode 100644 (file)
index 0000000..d131e87
--- /dev/null
@@ -0,0 +1,246 @@
+/*
+ * Copyright (c) 1985 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This file includes significant work done at Cornell University by
+ * Bill Nesheim.  That work included by permission.
+ *
+ * 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[] = "@(#)af.c       5.11 (Berkeley) 2/26/91";
+#endif /* not lint */
+
+#include "defs.h"
+
+/*
+ * Address family support routines
+ */
+int    null_hash(), null_netmatch(), null_output(),
+       null_portmatch(), null_portcheck(),
+       null_checkhost(), null_ishost(), null_canon();
+int    xnnet_hash(), xnnet_netmatch(), xnnet_output(),
+       xnnet_portmatch(),
+       xnnet_checkhost(), xnnet_ishost(), xnnet_canon();
+#define NIL \
+       { null_hash,            null_netmatch,          null_output, \
+         null_portmatch,       null_portcheck,         null_checkhost, \
+         null_ishost,          null_canon }
+#define        XNSNET \
+       { xnnet_hash,           xnnet_netmatch,         xnnet_output, \
+         xnnet_portmatch,      xnnet_portmatch,        xnnet_checkhost, \
+         xnnet_ishost,         xnnet_canon }
+
+struct afswitch afswitch[AF_MAX] =
+       { NIL, NIL, NIL, NIL, NIL, NIL, XNSNET, NIL, NIL, NIL, NIL };
+
+struct sockaddr_ns xnnet_default = { sizeof(struct sockaddr_ns), AF_NS };
+
+union ns_net ns_anynet;
+union ns_net ns_zeronet;
+
+xnnet_hash(sns, hp)
+       register struct sockaddr_ns *sns;
+       struct afhash *hp;
+{
+       register long hash = 0;
+       register u_short *s = sns->sns_addr.x_host.s_host;
+       union ns_net_u net;
+
+       net.net_e = sns->sns_addr.x_net;
+       hp->afh_nethash = net.long_e;
+       hash = *s++; hash <<= 8; hash += *s++; hash <<= 8; hash += *s;
+       hp->afh_hosthash = hash;
+}
+
+xnnet_netmatch(sxn1, sxn2)
+       struct sockaddr_ns *sxn1, *sxn2;
+{
+       return (ns_neteq(sxn1->sns_addr, sxn2->sns_addr));
+}
+
+/*
+ * Verify the message is from the right port.
+ */
+xnnet_portmatch(sns)
+       register struct sockaddr_ns *sns;
+{
+       
+       return (ntohs(sns->sns_addr.x_port) == IDPPORT_RIF );
+}
+
+
+/*
+ * xns output routine.
+ */
+#ifdef DEBUG
+int do_output = 0;
+#endif
+xnnet_output(flags, sns, size)
+       int flags;
+       struct sockaddr_ns *sns;
+       int size;
+{
+       struct sockaddr_ns dst;
+
+       dst = *sns;
+       sns = &dst;
+       if (sns->sns_addr.x_port == 0)
+               sns->sns_addr.x_port = htons(IDPPORT_RIF);
+#ifdef DEBUG
+       if(do_output || ntohs(msg->rip_cmd) == RIPCMD_REQUEST)
+#endif 
+       /*
+        * Kludge to allow us to get routes out to machines that
+        * don't know their addresses yet; send to that address on
+        * ALL connected nets
+        */
+        if (ns_neteqnn(sns->sns_addr.x_net, ns_zeronet)) {
+               extern  struct interface *ifnet;
+               register struct interface *ifp;
+               
+               for (ifp = ifnet; ifp; ifp = ifp->int_next) {
+                       sns->sns_addr.x_net = 
+                               satons_addr(ifp->int_addr).x_net;
+                       (void) sendto(s, msg, size, flags,
+                           (struct sockaddr *)sns, sizeof (*sns));
+               }
+               return;
+       }
+       
+       (void) sendto(s, msg, size, flags,
+           (struct sockaddr *)sns, sizeof (*sns));
+}
+
+/*
+ * Return 1 if we want this route.
+ * We use this to disallow route net G entries for one for multiple
+ * point to point links.
+ */
+xnnet_checkhost(sns)
+       struct sockaddr_ns *sns;
+{
+       register struct interface *ifp = if_ifwithnet(sns);
+       /*
+        * We want this route if there is no more than one 
+        * point to point interface with this network.
+        */
+       if (ifp == 0 || (ifp->int_flags & IFF_POINTOPOINT)==0) return (1);
+       return (ifp->int_sq.n == ifp->int_sq.p);
+}
+
+/*
+ * Return 1 if the address is
+ * for a host, 0 for a network.
+ */
+xnnet_ishost(sns)
+struct sockaddr_ns *sns;
+{
+       register u_short *s = sns->sns_addr.x_host.s_host;
+
+       if ((s[0]==0xffff) && (s[1]==0xffff) && (s[2]==0xffff))
+               return (0);
+       else
+               return (1);
+}
+
+xnnet_canon(sns)
+       struct sockaddr_ns *sns;
+{
+
+       sns->sns_addr.x_port = 0;
+}
+
+/*ARGSUSED*/
+null_hash(addr, hp)
+       struct sockaddr *addr;
+       struct afhash *hp;
+{
+
+       hp->afh_nethash = hp->afh_hosthash = 0;
+}
+
+/*ARGSUSED*/
+null_netmatch(a1, a2)
+       struct sockaddr *a1, *a2;
+{
+
+       return (0);
+}
+
+/*ARGSUSED*/
+null_output(s, f, a1, n)
+       int s, f;
+       struct sockaddr *a1;
+       int n;
+{
+
+       ;
+}
+
+/*ARGSUSED*/
+null_portmatch(a1)
+       struct sockaddr *a1;
+{
+
+       return (0);
+}
+
+/*ARGSUSED*/
+null_portcheck(a1)
+       struct sockaddr *a1;
+{
+
+       return (0);
+}
+
+/*ARGSUSED*/
+null_ishost(a1)
+       struct sockaddr *a1;
+{
+
+       return (0);
+}
+
+/*ARGSUSED*/
+null_checkhost(a1)
+       struct sockaddr *a1;
+{
+
+       return (0);
+}
+
+/*ARGSUSED*/
+null_canon(a1)
+       struct sockaddr *a1;
+{
+
+       ;
+}
diff --git a/usr.sbin/XNSrouted/af.h b/usr.sbin/XNSrouted/af.h
new file mode 100644 (file)
index 0000000..d2b27c5
--- /dev/null
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 1983 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.
+ *
+ *     @(#)af.h        5.1 (Berkeley) 6/4/85 (routed/af.h)
+ *
+ *     @(#)af.h        5.2 (Berkeley) 6/1/90
+ */
+
+/*
+ * Routing table management daemon.
+ */
+
+/*
+ * Per address family routines.
+ */
+struct afswitch {
+       int     (*af_hash)();           /* returns keys based on address */
+       int     (*af_netmatch)();       /* verifies net # matching */
+       int     (*af_output)();         /* interprets address for sending */
+       int     (*af_portmatch)();      /* packet from some other router? */
+       int     (*af_portcheck)();      /* packet from privileged peer? */
+       int     (*af_checkhost)();      /* tells if address for host or net */
+       int     (*af_ishost)();         /* tells if address is valid */
+       int     (*af_canon)();          /* canonicalize address for compares */
+};
+
+/*
+ * Structure returned by af_hash routines.
+ */
+struct afhash {
+       u_int   afh_hosthash;           /* host based hash */
+       u_int   afh_nethash;            /* network based hash */
+};
+
+struct afswitch afswitch[AF_MAX];      /* table proper */
diff --git a/usr.sbin/XNSrouted/defs.h b/usr.sbin/XNSrouted/defs.h
new file mode 100644 (file)
index 0000000..5414d8c
--- /dev/null
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 1983 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.
+ *
+ *     @(#)defs.h      5.9 (Berkeley) 2/26/91
+ */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#include <net/route.h>
+#include <netns/ns.h>
+#include <netns/idp.h>
+#if defined(vax) || defined(pdp11)
+#define xnnet(x) ((u_long) (x)->rip_dst[1] << 16 | (u_long) (x)->rip_dst[0] )
+#else
+#define xnnet(x) ((u_long) (x)->rip_dst[0] << 16 | (u_long) (x)->rip_dst[1] )
+#endif
+#define        IDPPORT_RIF     1
+
+#include <stdio.h>
+#include <syslog.h>
+
+#include "protocol.h"
+#include "trace.h"
+#include "interface.h"
+#include "table.h"
+#include "af.h"
+
+
+/*
+ * When we find any interfaces marked down we rescan the
+ * kernel every CHECK_INTERVAL seconds to see if they've
+ * come up.
+ */
+#define        CHECK_INTERVAL  (5*60)
+
+#define equal(a1, a2) \
+       (bcmp((caddr_t)(a1), (caddr_t)(a2), sizeof (struct sockaddr)) == 0)
+#define        min(a,b)        ((a)>(b)?(b):(a))
+
+struct sockaddr_ns addr;       /* Daemon's Address */
+int    s;                      /* Socket to listen on */
+int    kmem;
+int    supplier;               /* process should supply updates */
+int    install;                /* if 1 call kernel */
+int    lookforinterfaces;      /* if 1 probe kernel for new up interfaces */
+int    performnlist;           /* if 1 check if /vmunix has changed */
+int    externalinterfaces;     /* # of remote and local interfaces */
+int    timeval;                /* local idea of time */
+int    noteremoterequests;     /* squawk on requests from non-local nets */
+
+char   packet[MAXPACKETSIZE+sizeof(struct idp)+1];
+struct rip *msg;
+
+char   **argv0;
+
+int    sndmsg();
+int    supply();
+int    cleanup();
diff --git a/usr.sbin/XNSrouted/if.c b/usr.sbin/XNSrouted/if.c
new file mode 100644 (file)
index 0000000..0f597a6
--- /dev/null
@@ -0,0 +1,147 @@
+/*
+ * Copyright (c) 1983 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.
+ *
+ * static char sccsid[] = "@(#)if.c    5.1 (Berkeley) 6/4/85"; (routed/if.c)
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)if.c       5.2 (Berkeley) 6/1/90";
+#endif /* not lint */
+
+/*
+ * Routing Table Management Daemon
+ */
+#include "defs.h"
+
+extern struct interface *ifnet;
+
+/*
+ * Find the interface with address addr.
+ */
+struct interface *
+if_ifwithaddr(addr)
+       struct sockaddr *addr;
+{
+       register struct interface *ifp;
+
+#define        same(a1, a2) \
+       (bcmp((caddr_t)((a1)->sa_data), (caddr_t)((a2)->sa_data), 14) == 0)
+       for (ifp = ifnet; ifp; ifp = ifp->int_next) {
+               if (ifp->int_flags & IFF_REMOTE)
+                       continue;
+               if (ifp->int_addr.sa_family != addr->sa_family)
+                       continue;
+               if (same(&ifp->int_addr, addr))
+                       break;
+               if ((ifp->int_flags & IFF_BROADCAST) &&
+                   same(&ifp->int_broadaddr, addr))
+                       break;
+       }
+       return (ifp);
+}
+
+/*
+ * Find the point-to-point interface with destination address addr.
+ */
+struct interface *
+if_ifwithdstaddr(addr)
+       struct sockaddr *addr;
+{
+       register struct interface *ifp;
+
+       for (ifp = ifnet; ifp; ifp = ifp->int_next) {
+               if ((ifp->int_flags & IFF_POINTOPOINT) == 0)
+                       continue;
+               if (same(&ifp->int_dstaddr, addr))
+                       break;
+       }
+       return (ifp);
+}
+
+/*
+ * Find the interface on the network 
+ * of the specified address.
+ */
+struct interface *
+if_ifwithnet(addr)
+       register struct sockaddr *addr;
+{
+       register struct interface *ifp;
+       register int af = addr->sa_family;
+       register int (*netmatch)();
+
+       if (af >= AF_MAX)
+               return (0);
+       netmatch = afswitch[af].af_netmatch;
+       for (ifp = ifnet; ifp; ifp = ifp->int_next) {
+               if (ifp->int_flags & IFF_REMOTE)
+                       continue;
+               if (af != ifp->int_addr.sa_family)
+                       continue;
+               if ((*netmatch)(addr, &ifp->int_addr))
+                       break;
+       }
+       return (ifp);
+}
+
+/*
+ * Find an interface from which the specified address
+ * should have come from.  Used for figuring out which
+ * interface a packet came in on -- for tracing.
+ */
+struct interface *
+if_iflookup(addr)
+       struct sockaddr *addr;
+{
+       register struct interface *ifp, *maybe;
+       register int af = addr->sa_family;
+       register int (*netmatch)();
+
+       if (af >= AF_MAX)
+               return (0);
+       maybe = 0;
+       netmatch = afswitch[af].af_netmatch;
+       for (ifp = ifnet; ifp; ifp = ifp->int_next) {
+               if (ifp->int_addr.sa_family != af)
+                       continue;
+               if (same(&ifp->int_addr, addr))
+                       break;
+               if ((ifp->int_flags & IFF_BROADCAST) &&
+                   same(&ifp->int_broadaddr, addr))
+                       break;
+               if (maybe == 0 && (*netmatch)(addr, &ifp->int_addr))
+                       maybe = ifp;
+       }
+       if (ifp == 0)
+               ifp = maybe;
+       return (ifp);
+}
diff --git a/usr.sbin/XNSrouted/input.c b/usr.sbin/XNSrouted/input.c
new file mode 100644 (file)
index 0000000..7dc64fa
--- /dev/null
@@ -0,0 +1,189 @@
+/*
+ * Copyright (c) 1985 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This file includes significant work done at Cornell University by
+ * Bill Nesheim.  That work included by permission.
+ *
+ * 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[] = "@(#)input.c    5.9 (Berkeley) 6/1/90";
+#endif /* not lint */
+
+/*
+ * XNS Routing Table Management Daemon
+ */
+#include "defs.h"
+
+struct sockaddr *
+xns_nettosa(net)
+union ns_net net;
+{
+       static struct sockaddr_ns sxn;
+       extern char ether_broadcast_addr[6];
+       
+       bzero(&sxn, sizeof (struct sockaddr_ns));
+       sxn.sns_family = AF_NS;
+       sxn.sns_len = sizeof (sxn);
+       sxn.sns_addr.x_net = net;
+       sxn.sns_addr.x_host = *(union ns_host *)ether_broadcast_addr;
+       return( (struct sockaddr *)&sxn);
+       
+}
+
+/*
+ * Process a newly received packet.
+ */
+rip_input(from, size)
+       struct sockaddr *from;
+       int size;
+{
+       struct rt_entry *rt;
+       struct netinfo *n;
+       struct interface *ifp;
+       int newsize;
+       struct afswitch *afp;
+
+       
+       ifp = 0;
+       TRACE_INPUT(ifp, from, size);
+       if (from->sa_family >= AF_MAX)
+               return;
+       afp = &afswitch[from->sa_family];
+       
+       size -= sizeof (u_short)        /* command */;
+       n = msg->rip_nets;
+
+       switch (ntohs(msg->rip_cmd)) {
+
+       case RIPCMD_REQUEST:
+               newsize = 0;
+               while (size > 0) {
+                       if (size < sizeof (struct netinfo))
+                               break;
+                       size -= sizeof (struct netinfo);
+
+                       /* 
+                        * A single entry with rip_dst == DSTNETS_ALL and
+                        * metric ``infinity'' means ``all routes''.
+                        */
+                       if (ns_neteqnn(n->rip_dst, ns_anynet) &&
+                           ntohs(n->rip_metric) == HOPCNT_INFINITY &&
+                           size == 0) {
+                               ifp = if_ifwithnet(from);
+                               supply(from, 0, ifp);
+                               return;
+                       }
+                       /*
+                        * request for specific nets
+                        */
+                       rt = rtlookup(xns_nettosa(n->rip_dst));
+                       if (ftrace) {
+                               fprintf(ftrace,
+                                       "specific request for %s",
+                                       xns_nettoa(n->rip_dst));
+                               fprintf(ftrace,
+                                       " yields route %x\n",
+                                       rt);
+                       }
+                       n->rip_metric = htons( rt == 0 ? HOPCNT_INFINITY :
+                               min(rt->rt_metric+1, HOPCNT_INFINITY));
+                       n++;
+                       newsize += sizeof (struct netinfo);
+               }
+               if (newsize > 0) {
+                       msg->rip_cmd = htons(RIPCMD_RESPONSE);
+                       newsize += sizeof (u_short);
+                       /* should check for if with dstaddr(from) first */
+                       (*afp->af_output)(0, from, newsize);
+                       ifp = if_ifwithnet(from);
+                       TRACE_OUTPUT(ifp, from, newsize);
+                       if (ftrace) {
+                               fprintf(ftrace,
+                                       "request arrived on interface %s\n",
+                                       ifp->int_name);
+                       }
+               }
+               return;
+
+       case RIPCMD_RESPONSE:
+               /* verify message came from a router */
+               if ((*afp->af_portmatch)(from) == 0)
+                       return;
+               (*afp->af_canon)(from);
+               /* are we talking to ourselves? */
+               if (ifp = if_ifwithaddr(from)) {
+                       rt = rtfind(from);
+                       if (rt == 0 || (rt->rt_state & RTS_INTERFACE) == 0)
+                               addrouteforif(ifp);
+                       else
+                               rt->rt_timer = 0;
+                       return;
+               }
+               /* Update timer for interface on which the packet arrived.
+                * If from other end of a point-to-point link that isn't
+                * in the routing tables, (re-)add the route.
+                */
+               if ((rt = rtfind(from)) && (rt->rt_state & RTS_INTERFACE)) {
+                       if(ftrace) fprintf(ftrace, "Got route\n");
+                       rt->rt_timer = 0;
+               } else if (ifp = if_ifwithdstaddr(from)) {
+                       if(ftrace) fprintf(ftrace, "Got partner\n");
+                       addrouteforif(ifp);
+               }
+               for (; size > 0; size -= sizeof (struct netinfo), n++) {
+                       struct sockaddr *sa;
+                       if (size < sizeof (struct netinfo))
+                               break;
+                       if ((unsigned) ntohs(n->rip_metric) >= HOPCNT_INFINITY)
+                               continue;
+                       rt = rtfind(sa = xns_nettosa(n->rip_dst));
+                       if (rt == 0) {
+                               rtadd(sa, from, ntohs(n->rip_metric), 0);
+                               continue;
+                       }
+
+                       /*
+                        * Update if from gateway and different,
+                        * from anywhere and shorter, or getting stale and equivalent.
+                        */
+                       if ((equal(from, &rt->rt_router) &&
+                           ntohs(n->rip_metric) != rt->rt_metric ) ||
+                           (unsigned) ntohs(n->rip_metric) < rt->rt_metric ||
+                           (rt->rt_timer > (EXPIRE_TIME/2) &&
+                           rt->rt_metric == ntohs(n->rip_metric))) {
+                               rtchange(rt, from, ntohs(n->rip_metric));
+                               rt->rt_timer = 0;
+                       }
+               }
+               return;
+       }
+}
diff --git a/usr.sbin/XNSrouted/interface.h b/usr.sbin/XNSrouted/interface.h
new file mode 100644 (file)
index 0000000..7cb4166
--- /dev/null
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 1983 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.
+ *
+ *     @(#)interface.h 5.5 (Berkeley) 6/1/90
+ */
+
+/*
+ * Routing table management daemon.
+ */
+
+/*
+ * An ``interface'' is similar to an ifnet structure,
+ * except it doesn't contain q'ing info, and it also
+ * handles ``logical'' interfaces (remote gateways
+ * that we want to keep polling even if they go down).
+ * The list of interfaces which we maintain is used
+ * in supplying the gratuitous routing table updates.
+ * We list only one address for  each interface, the AF_XNS one.
+ */
+#define NIFADDR 3
+struct interface {
+       struct  interface *int_next;
+       struct  sockaddr int_addr;              /* address on this host */
+       union {
+               struct  sockaddr intu_broadaddr;
+               struct  sockaddr intu_dstaddr;
+       } int_intu;
+#define        int_broadaddr   int_intu.intu_broadaddr /* broadcast address */
+#define        int_dstaddr     int_intu.intu_dstaddr   /* other end of p-to-p link */
+       int     int_metric;                     /* init's routing entry */
+       int     int_flags;                      /* see below */
+       struct  ifdebug int_input, int_output;  /* packet tracing stuff */
+       int     int_ipackets;                   /* input packets received */
+       int     int_opackets;                   /* output packets sent */
+       char    *int_name;                      /* from kernel if structure */
+       u_short int_transitions;                /* times gone up-down */
+/*XNS Specific entry */
+       struct  sameq {
+               struct sameq *n;                /* q of other pt-to-pt links */
+               struct sameq *p;                /* with same net # */
+       }       int_sq;
+};
+
+/*
+ * 0x1 to 0x10 are reused from the kernel's ifnet definitions,
+ * the others agree with the RTS_ flags defined elsewhere.
+ */
+#define        IFF_UP          0x1             /* interface is up */
+#define        IFF_BROADCAST   0x2             /* broadcast address valid */
+#define        IFF_DEBUG       0x4             /* turn on debugging */
+#define        IFF_ROUTE       0x8             /* routing entry installed */
+#define        IFF_POINTOPOINT 0x10            /* interface is point-to-point link */
+
+#define        IFF_PASSIVE     0x2000          /* can't tell if up/down */
+#define        IFF_INTERFACE   0x4000          /* hardware interface */
+#define        IFF_REMOTE      0x8000          /* interface isn't on this machine */
+
+struct interface *if_ifwithaddr();
+struct interface *if_ifwithdstaddr();
+struct interface *if_ifwithnet();
+struct interface *if_iflookup();
diff --git a/usr.sbin/XNSrouted/main.c b/usr.sbin/XNSrouted/main.c
new file mode 100644 (file)
index 0000000..f4ddf28
--- /dev/null
@@ -0,0 +1,245 @@
+/*
+ * Copyright (c) 1985 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This file includes significant work done at Cornell University by
+ * Bill Nesheim.  That work included by permission.
+ *
+ * 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
+char copyright[] =
+"@(#) Copyright (c) 1985 The Regents of the University of California.\n\
+ All rights reserved.\n";
+#endif /* not lint */
+
+#ifndef lint
+static char sccsid[] = "@(#)main.c     5.11 (Berkeley) 2/26/91";
+#endif /* not lint */
+
+/*
+ * XNS Routing Information Protocol Daemon
+ */
+#include "defs.h"
+#include <sys/time.h>
+
+#include <net/if.h>
+
+#include <errno.h>
+#include <nlist.h>
+#include <signal.h>
+#include <paths.h>
+
+int    supplier = -1;          /* process should supply updates */
+extern int gateway;
+
+struct rip *msg = (struct rip *) &packet[sizeof (struct idp)]; 
+void   hup(), fkexit(), timer();
+
+main(argc, argv)
+       int argc;
+       char *argv[];
+{
+       int cc;
+       struct sockaddr from;
+       u_char retry;
+       
+       argv0 = argv;
+       argv++, argc--;
+       while (argc > 0 && **argv == '-') {
+               if (strcmp(*argv, "-s") == 0) {
+                       supplier = 1;
+                       argv++, argc--;
+                       continue;
+               }
+               if (strcmp(*argv, "-q") == 0) {
+                       supplier = 0;
+                       argv++, argc--;
+                       continue;
+               }
+               if (strcmp(*argv, "-R") == 0) {
+                       noteremoterequests++;
+                       argv++, argc--;
+                       continue;
+               }
+               if (strcmp(*argv, "-t") == 0) {
+                       tracepackets++;
+                       argv++, argc--;
+                       ftrace = stderr;
+                       tracing = 1; 
+                       continue;
+               }
+               if (strcmp(*argv, "-g") == 0) {
+                       gateway = 1;
+                       argv++, argc--;
+                       continue;
+               }
+               if (strcmp(*argv, "-l") == 0) {
+                       gateway = -1;
+                       argv++, argc--;
+                       continue;
+               }
+               fprintf(stderr,
+                       "usage: xnsrouted [ -s ] [ -q ] [ -t ] [ -g ] [ -l ]\n");
+               exit(1);
+       }
+       
+       
+#ifndef DEBUG
+       if (!tracepackets)
+               daemon(0, 0);
+#endif
+       openlog("XNSrouted", LOG_PID, LOG_DAEMON);
+
+       ns_anynet.s_net[0] = -1; ns_anynet.s_net[1] = -1;
+       addr.sns_family = AF_NS;
+       addr.sns_len = sizeof(addr);
+       addr.sns_port = htons(IDPPORT_RIF);
+       s = getsocket(SOCK_DGRAM, 0, &addr);
+       if (s < 0)
+               exit(1);
+       /*
+        * Any extra argument is considered
+        * a tracing log file.
+        */
+       if (argc > 0)
+               traceon(*argv);
+       /*
+        * Collect an initial view of the world by
+        * snooping in the kernel.  Then, send a request packet on all
+        * directly connected networks to find out what
+        * everyone else thinks.
+        */
+       rtinit();
+       ifinit();
+       if (supplier < 0)
+               supplier = 0;
+       /* request the state of the world */
+       msg->rip_cmd = htons(RIPCMD_REQUEST);
+       msg->rip_nets[0].rip_dst = ns_anynet;
+       msg->rip_nets[0].rip_metric =  htons(HOPCNT_INFINITY);
+       toall(sndmsg);
+       signal(SIGALRM, timer);
+       signal(SIGHUP, hup);
+       signal(SIGINT, hup);
+       signal(SIGEMT, fkexit);
+       timer();
+       
+
+       for (;;) 
+               process(s);
+       
+}
+
+process(fd)
+       int fd;
+{
+       struct sockaddr from;
+       int fromlen = sizeof (from), cc, omask;
+       struct idp *idp = (struct idp *)packet;
+
+       cc = recvfrom(fd, packet, sizeof (packet), 0, &from, &fromlen);
+       if (cc <= 0) {
+               if (cc < 0 && errno != EINTR)
+                       syslog(LOG_ERR, "recvfrom: %m");
+               return;
+       }
+       if (tracepackets > 1 && ftrace) {
+           fprintf(ftrace,"rcv %d bytes on %s ", cc, xns_ntoa(&idp->idp_dna));
+           fprintf(ftrace," from %s\n", xns_ntoa(&idp->idp_sna));
+       }
+       
+       if (noteremoterequests && !ns_neteqnn(idp->idp_sna.x_net, ns_zeronet)
+               && !ns_neteq(idp->idp_sna, idp->idp_dna))
+       {
+               syslog(LOG_ERR,
+                      "net of interface (%s) != net on ether (%s)!\n",
+                      xns_nettoa(idp->idp_dna.x_net),
+                      xns_nettoa(idp->idp_sna.x_net));
+       }
+                       
+       /* We get the IDP header in front of the RIF packet*/
+       cc -= sizeof (struct idp);
+#define        mask(s) (1<<((s)-1))
+       omask = sigblock(mask(SIGALRM));
+       rip_input(&from, cc);
+       sigsetmask(omask);
+}
+
+getsocket(type, proto, sns)
+       int type, proto; 
+       struct sockaddr_ns *sns;
+{
+       int domain = sns->sns_family;
+       int retry, s, on = 1;
+
+       retry = 1;
+       while ((s = socket(domain, type, proto)) < 0 && retry) {
+               syslog(LOG_ERR, "socket: %m");
+               sleep(5 * retry);
+               retry <<= 1;
+       }
+       if (retry == 0)
+               return (-1);
+       while (bind(s, (struct sockaddr *)sns, sizeof (*sns)) < 0 && retry) {
+               syslog(LOG_ERR, "bind: %m");
+               sleep(5 * retry);
+               retry <<= 1;
+       }
+       if (retry == 0)
+               return (-1);
+       if (domain==AF_NS) {
+               struct idp idp;
+               if (setsockopt(s, 0, SO_HEADERS_ON_INPUT, &on, sizeof(on))) {
+                       syslog(LOG_ERR, "setsockopt SEE HEADERS: %m");
+                       exit(1);
+               }
+               idp.idp_pt = NSPROTO_RI;
+               if (setsockopt(s, 0, SO_DEFAULT_HEADERS, &idp, sizeof(idp))) {
+                       syslog(LOG_ERR, "setsockopt SET HEADER: %m");
+                       exit(1);
+               }
+       }
+       if (setsockopt(s, SOL_SOCKET, SO_BROADCAST, &on, sizeof (on)) < 0) {
+               syslog(LOG_ERR, "setsockopt SO_BROADCAST: %m");
+               exit(1);
+       }
+       return (s);
+}
+
+/*
+ * Fork and exit on EMT-- for profiling.
+ */
+void
+fkexit()
+{
+       if (fork() == 0)
+               exit(0);
+}
diff --git a/usr.sbin/XNSrouted/output.c b/usr.sbin/XNSrouted/output.c
new file mode 100644 (file)
index 0000000..cdea11f
--- /dev/null
@@ -0,0 +1,147 @@
+/*
+ * Copyright (c) 1985 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This file includes significant work done at Cornell University by
+ * Bill Nesheim.  That work included by permission.
+ *
+ * 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[] = "@(#)output.c   5.8 (Berkeley) 2/26/91";
+#endif /* not lint */
+
+/*
+ * Routing Table Management Daemon
+ */
+#include "defs.h"
+
+/*
+ * Apply the function "f" to all non-passive
+ * interfaces.  If the interface supports the
+ * use of broadcasting use it, otherwise address
+ * the output to the known router.
+ */
+toall(f)
+       int (*f)();
+{
+       register struct interface *ifp;
+       register struct sockaddr *dst;
+       register int flags;
+       extern struct interface *ifnet;
+
+       for (ifp = ifnet; ifp; ifp = ifp->int_next) {
+               if (ifp->int_flags & IFF_PASSIVE)
+                       continue;
+               dst = ifp->int_flags & IFF_BROADCAST ? &ifp->int_broadaddr :
+                     ifp->int_flags & IFF_POINTOPOINT ? &ifp->int_dstaddr :
+                     &ifp->int_addr;
+               flags = ifp->int_flags & IFF_INTERFACE ? MSG_DONTROUTE : 0;
+               (*f)(dst, flags, ifp);
+       }
+}
+
+/*
+ * Output a preformed packet.
+ */
+/*ARGSUSED*/
+sndmsg(dst, flags, ifp)
+       struct sockaddr *dst;
+       int flags;
+       struct interface *ifp;
+{
+
+       (*afswitch[dst->sa_family].af_output)
+               (flags, dst, sizeof (struct rip));
+       TRACE_OUTPUT(ifp, dst, sizeof (struct rip));
+}
+
+/*
+ * Supply dst with the contents of the routing tables.
+ * If this won't fit in one packet, chop it up into several.
+ */
+supply(dst, flags, ifp)
+       struct sockaddr *dst;
+       int flags;
+       struct interface *ifp;
+{
+       register struct rt_entry *rt;
+       register struct rthash *rh;
+       register struct netinfo *nn;
+       register struct netinfo *n = msg->rip_nets;
+       struct rthash *base = hosthash;
+       struct sockaddr_ns *sns =  (struct sockaddr_ns *) dst;
+       int (*output)() = afswitch[dst->sa_family].af_output;
+       int doinghost = 1, size, metric;
+       union ns_net net;
+
+       msg->rip_cmd = ntohs(RIPCMD_RESPONSE);
+again:
+       for (rh = base; rh < &base[ROUTEHASHSIZ]; rh++)
+       for (rt = rh->rt_forw; rt != (struct rt_entry *)rh; rt = rt->rt_forw) {
+               size = (char *)n - (char *)msg;
+               if (size > MAXPACKETSIZE - sizeof (struct netinfo)) {
+                       (*output)(flags, dst, size);
+                       TRACE_OUTPUT(ifp, dst, size);
+                       n = msg->rip_nets;
+               }
+               sns = (struct sockaddr_ns *)&rt->rt_dst;
+               if ((rt->rt_flags & (RTF_HOST|RTF_GATEWAY)) == RTF_HOST)
+                       sns = (struct sockaddr_ns *)&rt->rt_router;
+               metric = min(rt->rt_metric + 1, HOPCNT_INFINITY);
+               net = sns->sns_addr.x_net;
+               /*
+                * Make sure that we don't put out a two net entries
+                * for a pt to pt link (one for the G route, one for the if)
+                * This is a kludge, and won't work if there are lots of nets.
+                */
+               for (nn = msg->rip_nets; nn < n; nn++) {
+                       if (ns_neteqnn(net, nn->rip_dst)) {
+                               if (metric < ntohs(nn->rip_metric))
+                                       nn->rip_metric = htons(metric);
+                               goto next;
+                       }
+               }
+               n->rip_dst = net;
+               n->rip_metric = htons(metric);
+               n++;
+       next:;
+       }
+       if (doinghost) {
+               doinghost = 0;
+               base = nethash;
+               goto again;
+       }
+       if (n != msg->rip_nets) {
+               size = (char *)n - (char *)msg;
+               (*output)(flags, dst, size);
+               TRACE_OUTPUT(ifp, dst, size);
+       }
+}
diff --git a/usr.sbin/XNSrouted/protocol.h b/usr.sbin/XNSrouted/protocol.h
new file mode 100644 (file)
index 0000000..9bf422b
--- /dev/null
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 1985 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This file includes significant work done at Cornell University by
+ * Bill Nesheim.  That work included by permission.
+ *
+ * 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.
+ *
+ *     @(#)protocol.h  5.6 (Berkeley) 6/1/90
+ */
+
+/*
+ * Xerox Routing Information Protocol
+ *
+ */
+
+struct netinfo {
+       union ns_net    rip_dst;                /* destination net */
+       u_short         rip_metric;             /* cost of route */
+};
+
+struct rip {
+       u_short rip_cmd;                /* request/response */
+       struct netinfo rip_nets[1];     /* variable length */
+};
+/*
+ * Packet types.
+ */
+#define        RIPCMD_REQUEST          1       /* want info */
+#define        RIPCMD_RESPONSE         2       /* responding to request */
+
+#define        RIPCMD_MAX              3
+#ifdef RIPCMDS
+char *ripcmds[RIPCMD_MAX] =
+  { "#0", "REQUEST", "RESPONSE" };
+#endif
+
+#define        HOPCNT_INFINITY         16              /* per Xerox NS */
+#define        DSTNETS_ALL             0xffffffff      /* per Xerox NS */
+#define        MAXPACKETSIZE           512             /* max broadcast size */
+
+extern union ns_net ns_anynet;
+extern union ns_net ns_zeronet;
+
+/*
+ * Timer values used in managing the routing table.
+ * Every update forces an entry's timer to be reset.  After
+ * EXPIRE_TIME without updates, the entry is marked invalid,
+ * but held onto until GARBAGE_TIME so that others may
+ * see it "be deleted".
+ */
+#define        TIMER_RATE              30      /* alarm clocks every 30 seconds */
+
+#define        SUPPLY_INTERVAL         30      /* time to supply tables */
+
+#define        EXPIRE_TIME             180     /* time to mark entry invalid */
+#define        GARBAGE_TIME            240     /* time to garbage collect */
diff --git a/usr.sbin/XNSrouted/startup.c b/usr.sbin/XNSrouted/startup.c
new file mode 100644 (file)
index 0000000..8887c1f
--- /dev/null
@@ -0,0 +1,218 @@
+/*
+ * Copyright (c) 1985 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This file includes significant work done at Cornell University by
+ * Bill Nesheim.  That work included by permission.
+ *
+ * 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[] = "@(#)startup.c  5.11 (Berkeley) 2/26/91";
+#endif /* not lint */
+
+/*
+ * Routing Table Management Daemon
+ */
+#include "defs.h"
+#include <sys/ioctl.h>
+#include <net/if.h>
+#include <nlist.h>
+#include <stdlib.h>
+
+struct interface *ifnet;
+int    lookforinterfaces = 1;
+int    performnlist = 1;
+int    gateway = 0;
+int    externalinterfaces = 0;         /* # of remote and local interfaces */
+char ether_broadcast_addr[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
+
+
+/*
+ * Find the network interfaces which have configured themselves.
+ * If the interface is present but not yet up (for example an
+ * ARPANET IMP), set the lookforinterfaces flag so we'll
+ * come back later and look again.
+ */
+ifinit()
+{
+       struct interface ifs, *ifp;
+       int s;
+        struct ifconf ifc;
+       char buf[BUFSIZ], *cp, *cplim;
+        struct ifreq ifreq, *ifr;
+       u_long i;
+
+       if ((s = socket(AF_NS, SOCK_DGRAM, 0)) < 0) {
+               syslog(LOG_ERR, "socket: %m");
+               exit(1);
+       }
+        ifc.ifc_len = sizeof (buf);
+        ifc.ifc_buf = buf;
+        if (ioctl(s, SIOCGIFCONF, (char *)&ifc) < 0) {
+                syslog(LOG_ERR, "ioctl (get interface configuration)");
+               close(s);
+                exit(1);
+        }
+        ifr = ifc.ifc_req;
+       lookforinterfaces = 0;
+#ifdef RTM_ADD
+#define max(a, b) (a > b ? a : b)
+#define size(p)        max((p).sa_len, sizeof(p))
+#else
+#define size(p) (sizeof (p))
+#endif
+       cplim = buf + ifc.ifc_len; /*skip over if's with big ifr_addr's */
+       for (cp = buf; cp < cplim;
+                       cp += sizeof (ifr->ifr_name) + size(ifr->ifr_addr)) {
+               ifr = (struct ifreq *)cp;
+               bzero((char *)&ifs, sizeof(ifs));
+               ifs.int_addr = ifr->ifr_addr;
+               ifreq = *ifr;
+                if (ioctl(s, SIOCGIFFLAGS, (char *)&ifreq) < 0) {
+                        syslog(LOG_ERR, "ioctl (get interface flags)");
+                        continue;
+                }
+               ifs.int_flags = ifreq.ifr_flags | IFF_INTERFACE;
+               if ((ifs.int_flags & IFF_UP) == 0 ||
+                   ifr->ifr_addr.sa_family == AF_UNSPEC) {
+                       lookforinterfaces = 1;
+                       continue;
+               }
+               if (ifs.int_addr.sa_family != AF_NS)
+                       continue;
+                if (ifs.int_flags & IFF_POINTOPOINT) {
+                        if (ioctl(s, SIOCGIFDSTADDR, (char *)&ifreq) < 0) {
+                                syslog(LOG_ERR, "ioctl (get dstaddr): %m");
+                                continue;
+                       }
+                       ifs.int_dstaddr = ifreq.ifr_dstaddr;
+               }
+                if (ifs.int_flags & IFF_BROADCAST) {
+                        if (ioctl(s, SIOCGIFBRDADDR, (char *)&ifreq) < 0) {
+                                syslog(LOG_ERR, "ioctl (get broadaddr: %m");
+                                continue;
+                        }
+                       ifs.int_broadaddr = ifreq.ifr_broadaddr;
+               }
+               /* 
+                * already known to us? 
+                * what makes a POINTOPOINT if unique is its dst addr,
+                * NOT its source address 
+                */
+               if ( ((ifs.int_flags & IFF_POINTOPOINT) &&
+                       if_ifwithdstaddr(&ifs.int_dstaddr)) ||
+                       ( ((ifs.int_flags & IFF_POINTOPOINT) == 0) &&
+                       if_ifwithaddr(&ifs.int_addr)))
+                       continue;
+               /* no one cares about software loopback interfaces */
+               if (strncmp(ifr->ifr_name,"lo", 2)==0)
+                       continue;
+               ifp = (struct interface *)malloc(sizeof (struct interface));
+               if (ifp == 0) {
+                       syslog(LOG_ERR,"XNSrouted: out of memory\n");
+                       break;
+               }
+               *ifp = ifs;
+               /*
+                * Count the # of directly connected networks
+                * and point to point links which aren't looped
+                * back to ourself.  This is used below to
+                * decide if we should be a routing ``supplier''.
+                */
+               if ((ifs.int_flags & IFF_POINTOPOINT) == 0 ||
+                   if_ifwithaddr(&ifs.int_dstaddr) == 0)
+                       externalinterfaces++;
+               /*
+                * If we have a point-to-point link, we want to act
+                * as a supplier even if it's our only interface,
+                * as that's the only way our peer on the other end
+                * can tell that the link is up.
+                */
+               if ((ifs.int_flags & IFF_POINTOPOINT) && supplier < 0)
+                       supplier = 1;
+               ifp->int_name = malloc(strlen(ifr->ifr_name) + 1);
+               if (ifp->int_name == 0) {
+                       syslog(LOG_ERR,"XNSrouted: out of memory\n");
+                       exit(1);
+               }
+               strcpy(ifp->int_name, ifr->ifr_name);
+               ifp->int_metric = 0;
+               ifp->int_next = ifnet;
+               ifnet = ifp;
+               traceinit(ifp);
+               addrouteforif(ifp);
+       }
+       if (externalinterfaces > 1 && supplier < 0)
+               supplier = 1;
+       close(s);
+}
+
+addrouteforif(ifp)
+       struct interface *ifp;
+{
+       struct sockaddr_ns net;
+       struct sockaddr *dst;
+       int state, metric;
+       struct rt_entry *rt;
+
+       if (ifp->int_flags & IFF_POINTOPOINT) {
+               int (*match)();
+               register struct interface *ifp2 = ifnet;
+               register struct interface *ifprev = ifnet;
+               
+               dst = &ifp->int_dstaddr;
+
+               /* Search for interfaces with the same net */
+               ifp->int_sq.n = ifp->int_sq.p = &(ifp->int_sq);
+               match = afswitch[dst->sa_family].af_netmatch;
+               if (match)
+               for (ifp2 = ifnet; ifp2; ifp2 =ifp2->int_next) {
+                       if (ifp->int_flags & IFF_POINTOPOINT == 0)
+                               continue;
+                       if ((*match)(&ifp2->int_dstaddr,&ifp->int_dstaddr)) {
+                               insque(&ifp2->int_sq,&ifp->int_sq);
+                               break;
+                       }
+               }
+       } else {
+               dst = &ifp->int_broadaddr;
+       }
+       rt = rtlookup(dst);
+       if (rt)
+               rtdelete(rt);
+       if (tracing)
+               fprintf(stderr, "Adding route to interface %s\n", ifp->int_name);
+       if (ifp->int_transitions++ > 0)
+               syslog(LOG_ERR, "re-installing interface %s", ifp->int_name);
+       rtadd(dst, &ifp->int_addr, ifp->int_metric,
+               ifp->int_flags & (IFF_INTERFACE|IFF_PASSIVE|IFF_REMOTE));
+}
+
diff --git a/usr.sbin/XNSrouted/table.h b/usr.sbin/XNSrouted/table.h
new file mode 100644 (file)
index 0000000..159dc4e
--- /dev/null
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 1983 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.
+ *
+ *     @(#)table.h     5.1 (Berkeley) 6/4/85 (routed/table.h)
+ *
+ *     @(#)table.h     5.3 (Berkeley) 6/1/90
+ */
+
+/*
+ * Routing table management daemon.
+ */
+
+/*
+ * Routing table structure; differs a bit from kernel tables.
+ *
+ * Note: the union below must agree in the first 4 members
+ * so the ioctl's will work.
+ */
+struct rthash {
+       struct  rt_entry *rt_forw;
+       struct  rt_entry *rt_back;
+};
+
+#ifdef RTM_ADD
+#define rtentry ortentry
+#endif
+
+struct rt_entry {
+       struct  rt_entry *rt_forw;
+       struct  rt_entry *rt_back;
+       union {
+               struct  rtentry rtu_rt;
+               struct {
+                       u_long  rtu_hash;
+                       struct  sockaddr rtu_dst;
+                       struct  sockaddr rtu_router;
+                       short   rtu_flags;
+                       short   rtu_state;
+                       int     rtu_timer;
+                       int     rtu_metric;
+                       struct  interface *rtu_ifp;
+               } rtu_entry;
+       } rt_rtu;
+};
+
+#define        rt_rt           rt_rtu.rtu_rt                   /* pass to ioctl */
+#define        rt_hash         rt_rtu.rtu_entry.rtu_hash       /* for net or host */
+#define        rt_dst          rt_rtu.rtu_entry.rtu_dst        /* match value */
+#define        rt_router       rt_rtu.rtu_entry.rtu_router     /* who to forward to */
+#define        rt_flags        rt_rtu.rtu_entry.rtu_flags      /* kernel flags */
+#define        rt_timer        rt_rtu.rtu_entry.rtu_timer      /* for invalidation */
+#define        rt_state        rt_rtu.rtu_entry.rtu_state      /* see below */
+#define        rt_metric       rt_rtu.rtu_entry.rtu_metric     /* cost of route */
+#define        rt_ifp          rt_rtu.rtu_entry.rtu_ifp        /* interface to take */
+
+#define        ROUTEHASHSIZ    32              /* must be a power of 2 */
+#define        ROUTEHASHMASK   (ROUTEHASHSIZ - 1)
+
+/*
+ * "State" of routing table entry.
+ */
+#define        RTS_CHANGED     0x1             /* route has been altered recently */
+#define        RTS_PASSIVE     IFF_PASSIVE     /* don't time out route */
+#define        RTS_INTERFACE   IFF_INTERFACE   /* route is for network interface */
+#define        RTS_REMOTE      IFF_REMOTE      /* route is for ``remote'' entity */
+
+struct rthash nethash[ROUTEHASHSIZ];
+struct rthash hosthash[ROUTEHASHSIZ];
+struct rt_entry *rtlookup();
+struct rt_entry *rtfind();
diff --git a/usr.sbin/XNSrouted/tables.c b/usr.sbin/XNSrouted/tables.c
new file mode 100644 (file)
index 0000000..38ce438
--- /dev/null
@@ -0,0 +1,265 @@
+/*
+ * Copyright (c) 1985 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   5.9 (Berkeley) 6/1/90";
+#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 && ioctl(s, SIOCADDRT, (char *)&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 (ioctl(s, SIOCADDRT, (char *)&rt->rt_rt) < 0)
+                 syslog(LOG_ERR, "SIOCADDRT 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 && ioctl(s, SIOCDELRT, (char *)&oldroute) < 0)
+                       perror("SIOCDELRT");
+#else
+               if (delete && ioctl(s, SIOCDELRT, (char *)&oldroute) < 0)
+                       perror("SIOCDELRT");
+               if (ioctl(s, SIOCADDRT, (char *)&rt->rt_rt) < 0)
+                 syslog(LOG_ERR, "SIOCADDRT 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 && ioctl(s, SIOCDELRT, (char *)&rt->rt_rt))
+               perror("SIOCDELRT");
+       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;
+}
diff --git a/usr.sbin/XNSrouted/timer.c b/usr.sbin/XNSrouted/timer.c
new file mode 100644 (file)
index 0000000..f420bc0
--- /dev/null
@@ -0,0 +1,139 @@
+/*
+ * Copyright (c) 1985 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This file includes significant work done at Cornell University by
+ * Bill Nesheim.  That work included by permission.
+ *
+ * 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[] = "@(#)timer.c    5.7 (Berkeley) 2/26/91";
+#endif /* not lint */
+
+/*
+ * Routing Table Management Daemon
+ */
+#include "defs.h"
+
+int    timeval = -TIMER_RATE;
+
+/*
+ * Timer routine.  Performs routing information supply
+ * duties and manages timers on routing table entries.
+ */
+void
+timer()
+{
+       register struct rthash *rh;
+       register struct rt_entry *rt;
+       struct rthash *base = hosthash;
+       int doinghost = 1, timetobroadcast;
+
+       timeval += TIMER_RATE;
+       if (lookforinterfaces && (timeval % CHECK_INTERVAL) == 0)
+               ifinit();
+       timetobroadcast = supplier && (timeval % SUPPLY_INTERVAL) == 0;
+again:
+       for (rh = base; rh < &base[ROUTEHASHSIZ]; rh++) {
+               rt = rh->rt_forw;
+               for (; rt != (struct rt_entry *)rh; rt = rt->rt_forw) {
+                       /*
+                        * We don't advance time on a routing entry for
+                        * a passive gateway or that for our only interface. 
+                        * The latter is excused because we don't act as
+                        * a routing information supplier and hence would
+                        * time it out.  This is fair as if it's down
+                        * we're cut off from the world anyway and it's
+                        * not likely we'll grow any new hardware in
+                        * the mean time.
+                        */
+                       if (!(rt->rt_state & RTS_PASSIVE) &&
+                           (supplier || !(rt->rt_state & RTS_INTERFACE)))
+                               rt->rt_timer += TIMER_RATE;
+                       if (rt->rt_timer >= EXPIRE_TIME)
+                               rt->rt_metric = HOPCNT_INFINITY;
+                       if (rt->rt_timer >= GARBAGE_TIME) {
+                               rt = rt->rt_back;
+                               /* Perhaps we should send a REQUEST for this route? */
+                               rtdelete(rt->rt_forw);
+                               continue;
+                       }
+                       if (rt->rt_state & RTS_CHANGED) {
+                               rt->rt_state &= ~RTS_CHANGED;
+                               /* don't send extraneous packets */
+                               if (!supplier || timetobroadcast)
+                                       continue;
+                               msg->rip_cmd = htons(RIPCMD_RESPONSE);
+                               msg->rip_nets[0].rip_dst =
+                                       (satons_addr(rt->rt_dst)).x_net;
+                               msg->rip_nets[0].rip_metric =
+                                       htons(min(rt->rt_metric+1, HOPCNT_INFINITY));
+                               toall(sndmsg);
+                       }
+               }
+       }
+       if (doinghost) {
+               doinghost = 0;
+               base = nethash;
+               goto again;
+       }
+       if (timetobroadcast)
+               toall(supply);
+       alarm(TIMER_RATE);
+}
+
+/*
+ * On hangup, let everyone know we're going away.
+ */
+void
+hup()
+{
+       register struct rthash *rh;
+       register struct rt_entry *rt;
+       struct rthash *base = hosthash;
+       int doinghost = 1;
+
+       if (supplier) {
+again:
+               for (rh = base; rh < &base[ROUTEHASHSIZ]; rh++) {
+                       rt = rh->rt_forw;
+                       for (; rt != (struct rt_entry *)rh; rt = rt->rt_forw)
+                               rt->rt_metric = HOPCNT_INFINITY;
+               }
+               if (doinghost) {
+                       doinghost = 0;
+                       base = nethash;
+                       goto again;
+               }
+               toall(supply);
+       }
+       exit(1);
+}
diff --git a/usr.sbin/XNSrouted/tools/query.c b/usr.sbin/XNSrouted/tools/query.c
new file mode 100644 (file)
index 0000000..2e6374d
--- /dev/null
@@ -0,0 +1,232 @@
+/*-
+ * Copyright (c) 1983, 1986 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code includes software contributed to Berkeley by
+ * Bill Nesheim at Cornell University.
+ *
+ * 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
+char copyright[] =
+"@(#) Copyright (c) 1983, 1986 The Regents of the University of California.\n\
+ All rights reserved.\n";
+#endif /* not lint */
+
+#ifndef lint
+static char sccsid[] = "@(#)query.c    5.8 (Berkeley) 4/16/91";
+#endif /* not lint */
+
+#include <sys/param.h>
+#include <sys/protosw.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+#include <netinet/in.h>
+#include <netns/ns.h>
+#include <netns/idp.h>
+#include <errno.h>
+#include <stdio.h>
+#include <netdb.h>
+#include "../protocol.h"
+#define IDPPORT_RIF 1
+
+#define        WTIME   5               /* Time to wait for responses */
+
+int    s;
+int    timedout, timeout();
+char   packet[MAXPACKETSIZE];
+extern int errno;
+struct sockaddr_ns     myaddr = {sizeof(myaddr), AF_NS};
+char *ns_ntoa();
+struct ns_addr ns_addr();
+main(argc, argv)
+int argc;
+char *argv[];
+{
+       int cc, count, bits;
+       struct sockaddr from;
+       int fromlen = sizeof(from);
+       struct timeval notime;
+       
+       if (argc < 2) {
+               printf("usage: query hosts...\n");
+               exit(1);
+       }
+       s = getsocket(SOCK_DGRAM, 0);
+       if (s < 0) {
+               perror("socket");
+               exit(2);
+       }
+
+       argv++, argc--;
+       query(argv,argc);
+
+       /*
+        * Listen for returning packets;
+        * may be more than one packet per host.
+        */
+       bits = 1 << s;
+       bzero(&notime, sizeof(notime));
+       signal(SIGALRM, timeout);
+       alarm(WTIME);
+       while (!timedout || 
+           select(20, &bits, 0, 0, &notime) > 0) {
+               struct nspacket {
+                       struct idp hdr;
+                       char    data[512];
+               } response;
+               cc = recvfrom(s, &response, sizeof (response), 0,
+                 &from, &fromlen);
+               if (cc <= 0) {
+                       if (cc < 0) {
+                               if (errno == EINTR)
+                                       continue;
+                               perror("recvfrom");
+                               (void) close(s);
+                               exit(1);
+                       }
+                       continue;
+               }
+               rip_input(&from, response.data, cc);
+               count--;
+       }
+}
+static struct sockaddr_ns router = {sizeof(myaddr), AF_NS};
+static struct ns_addr zero_addr;
+static short allones[] = {-1, -1, -1};
+
+query(argv,argc)
+char **argv;
+{
+       register struct rip *msg = (struct rip *)packet;
+       char *host = *argv;
+       int flags = 0;
+       struct ns_addr specific;
+
+       if (bcmp(*argv, "-r", 3) == 0) {
+               flags = MSG_DONTROUTE; argv++; argc--;
+       }
+       host = *argv;
+       router.sns_addr = ns_addr(host);
+       router.sns_addr.x_port = htons(IDPPORT_RIF);
+       if (ns_hosteq(zero_addr, router.sns_addr)) {
+               router.sns_addr.x_host = *(union ns_host *) allones;
+       }
+       msg->rip_cmd = htons(RIPCMD_REQUEST);
+       msg->rip_nets[0].rip_dst = *(union ns_net *) allones;
+       msg->rip_nets[0].rip_metric = htons(HOPCNT_INFINITY);
+       if (argc > 0) {
+               specific = ns_addr(*argv);
+               msg->rip_nets[0].rip_dst = specific.x_net;
+               specific.x_host = zero_addr.x_host;
+               specific.x_port = zero_addr.x_port;
+               printf("Net asked for was %s\n", ns_ntoa(specific));
+       }
+       if (sendto(s, packet, sizeof (struct rip), flags,
+         &router, sizeof(router)) < 0)
+               perror(host);
+}
+
+/*
+ * Handle an incoming routing packet.
+ */
+rip_input(from, msg,  size)
+       struct sockaddr_ns *from;
+       register struct rip *msg;
+       int size;
+{
+       struct netinfo *n;
+       char *name;
+       int lna, net, subnet;
+       struct hostent *hp;
+       struct netent *np;
+       static struct ns_addr work;
+
+       if (htons(msg->rip_cmd) != RIPCMD_RESPONSE)
+               return;
+       printf("from %s\n", ns_ntoa(from->sns_addr));
+       size -= sizeof (struct idp);
+       size -= sizeof (short);
+       n = msg->rip_nets;
+       while (size > 0) {
+               union ns_net_u net;
+               if (size < sizeof (struct netinfo))
+                       break;
+               net.net_e = n->rip_dst;
+               printf("\t%d, metric %d\n", ntohl(net.long_e),
+                       ntohs(n->rip_metric));
+               size -= sizeof (struct netinfo), n++;
+       }
+}
+
+timeout()
+{
+       timedout = 1;
+}
+getsocket(type, proto)
+       int type, proto; 
+{
+       struct sockaddr_ns *sns = &myaddr;
+       int domain = sns->sns_family;
+       int retry, s, on = 1;
+
+       retry = 1;
+       while ((s = socket(domain, type, proto)) < 0 && retry) {
+               perror("socket");
+               sleep(5 * retry);
+               retry <<= 1;
+       }
+       if (retry == 0)
+               return (-1);
+       while (bind(s, sns, sizeof (*sns), 0) < 0 && retry) {
+               perror("bind");
+               sleep(5 * retry);
+               retry <<= 1;
+       }
+       if (retry == 0)
+               return (-1);
+       if (domain==AF_NS) {
+               struct idp idp;
+               if (setsockopt(s, 0, SO_HEADERS_ON_INPUT, &on, sizeof(on))) {
+                       perror("setsockopt SEE HEADERS");
+                       exit(1);
+               }
+               idp.idp_pt = NSPROTO_RI;
+               if (setsockopt(s, 0, SO_DEFAULT_HEADERS, &idp, sizeof(idp))) {
+                       perror("setsockopt SET HEADERS");
+                       exit(1);
+               }
+       }
+       if (setsockopt(s, SOL_SOCKET, SO_BROADCAST, &on, sizeof (on)) < 0) {
+               perror("setsockopt SO_BROADCAST");
+               exit(1);
+       }
+       return (s);
+}
diff --git a/usr.sbin/XNSrouted/trace.c b/usr.sbin/XNSrouted/trace.c
new file mode 100644 (file)
index 0000000..5172873
--- /dev/null
@@ -0,0 +1,313 @@
+/*
+ * Copyright (c) 1985 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This file includes significant work done at Cornell University by
+ * Bill Nesheim.  That work included by permission.
+ *
+ * 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[] = "@(#)trace.c    5.11 (Berkeley) 2/26/91";
+#endif /* not lint */
+
+/*
+ * Routing Table Management Daemon
+ */
+#define        RIPCMDS
+#include <stdlib.h>
+#include "defs.h"
+
+#define        NRECORDS        50              /* size of circular trace buffer */
+#ifdef DEBUG
+FILE   *ftrace = stdout;
+int    tracing = 1;
+#else DEBUG
+FILE   *ftrace = NULL;
+int    tracing = 0;
+#endif
+
+char *xns_ntoa();
+
+traceinit(ifp)
+       register struct interface *ifp;
+{
+       static int iftraceinit();
+
+       if (iftraceinit(ifp, &ifp->int_input) &&
+           iftraceinit(ifp, &ifp->int_output))
+               return;
+       tracing = 0;
+       syslog(LOG_ERR, "traceinit: can't init %s\n", ifp->int_name);
+}
+
+static
+iftraceinit(ifp, ifd)
+       struct interface *ifp;
+       register struct ifdebug *ifd;
+{
+       register struct iftrace *t;
+
+       ifd->ifd_records =
+         (struct iftrace *)malloc(NRECORDS * sizeof (struct iftrace));
+       if (ifd->ifd_records == 0)
+               return (0);
+       ifd->ifd_front = ifd->ifd_records;
+       ifd->ifd_count = 0;
+       for (t = ifd->ifd_records; t < ifd->ifd_records + NRECORDS; t++) {
+               t->ift_size = 0;
+               t->ift_packet = 0;
+       }
+       ifd->ifd_if = ifp;
+       return (1);
+}
+
+traceon(file)
+       char *file;
+{
+
+       if (ftrace != NULL)
+               return;
+       ftrace = fopen(file, "a");
+       if (ftrace == NULL)
+               return;
+       dup2(fileno(ftrace), 1);
+       dup2(fileno(ftrace), 2);
+       tracing = 1;
+}
+
+traceoff()
+{
+       if (!tracing)
+               return;
+       if (ftrace != NULL)
+               fclose(ftrace);
+       ftrace = NULL;
+       tracing = 0;
+}
+
+trace(ifd, who, p, len, m)
+       register struct ifdebug *ifd;
+       struct sockaddr *who;
+       char *p;
+       int len, m;
+{
+       register struct iftrace *t;
+
+       if (ifd->ifd_records == 0)
+               return;
+       t = ifd->ifd_front++;
+       if (ifd->ifd_front >= ifd->ifd_records + NRECORDS)
+               ifd->ifd_front = ifd->ifd_records;
+       if (ifd->ifd_count < NRECORDS)
+               ifd->ifd_count++;
+       if (t->ift_size > 0 && t->ift_packet)
+               free(t->ift_packet);
+       t->ift_packet = 0;
+       t->ift_stamp = time(0);
+       t->ift_who = *who;
+       if (len > 0) {
+               t->ift_packet = malloc(len);
+               if (t->ift_packet)
+                       bcopy(p, t->ift_packet, len);
+               else
+                       len = 0;
+       }
+       t->ift_size = len;
+       t->ift_metric = m;
+}
+
+traceaction(fd, action, rt)
+       FILE *fd;
+       char *action;
+       struct rt_entry *rt;
+{
+       struct sockaddr_ns *dst, *gate;
+       static struct bits {
+               int     t_bits;
+               char    *t_name;
+       } flagbits[] = {
+               { RTF_UP,       "UP" },
+               { RTF_GATEWAY,  "GATEWAY" },
+               { RTF_HOST,     "HOST" },
+               { 0 }
+       }, statebits[] = {
+               { RTS_PASSIVE,  "PASSIVE" },
+               { RTS_REMOTE,   "REMOTE" },
+               { RTS_INTERFACE,"INTERFACE" },
+               { RTS_CHANGED,  "CHANGED" },
+               { 0 }
+       };
+       register struct bits *p;
+       register int first;
+       char *cp;
+       struct interface *ifp;
+
+       if (fd == NULL)
+               return;
+       fprintf(fd, "%s ", action);
+       dst = (struct sockaddr_ns *)&rt->rt_dst;
+       gate = (struct sockaddr_ns *)&rt->rt_router;
+       fprintf(fd, "dst %s, ", xns_ntoa(&dst->sns_addr));
+       fprintf(fd, "router %s, metric %d, flags",
+            xns_ntoa(&gate->sns_addr), rt->rt_metric);
+       cp = " %s";
+       for (first = 1, p = flagbits; p->t_bits > 0; p++) {
+               if ((rt->rt_flags & p->t_bits) == 0)
+                       continue;
+               fprintf(fd, cp, p->t_name);
+               if (first) {
+                       cp = "|%s";
+                       first = 0;
+               }
+       }
+       fprintf(fd, " state");
+       cp = " %s";
+       for (first = 1, p = statebits; p->t_bits > 0; p++) {
+               if ((rt->rt_state & p->t_bits) == 0)
+                       continue;
+               fprintf(fd, cp, p->t_name);
+               if (first) {
+                       cp = "|%s";
+                       first = 0;
+               }
+       }
+       putc('\n', fd);
+       if (!tracepackets && (rt->rt_state & RTS_PASSIVE) == 0 && rt->rt_ifp)
+               dumpif(fd, rt->rt_ifp);
+       fflush(fd);
+}
+
+dumpif(fd, ifp)
+       register struct interface *ifp;
+       FILE *fd;
+{
+       if (ifp->int_input.ifd_count || ifp->int_output.ifd_count) {
+               fprintf(fd, "*** Packet history for interface %s ***\n",
+                       ifp->int_name);
+               dumptrace(fd, "to", &ifp->int_output);
+               dumptrace(fd, "from", &ifp->int_input);
+               fprintf(fd, "*** end packet history ***\n");
+       }
+}
+
+dumptrace(fd, dir, ifd)
+       FILE *fd;
+       char *dir;
+       register struct ifdebug *ifd;
+{
+       register struct iftrace *t;
+       char *cp = !strcmp(dir, "to") ? "Output" : "Input";
+
+       if (ifd->ifd_front == ifd->ifd_records &&
+           ifd->ifd_front->ift_size == 0) {
+               fprintf(fd, "%s: no packets.\n", cp);
+               return;
+       }
+       fprintf(fd, "%s trace:\n", cp);
+       t = ifd->ifd_front - ifd->ifd_count;
+       if (t < ifd->ifd_records)
+               t += NRECORDS;
+       for ( ; ifd->ifd_count; ifd->ifd_count--, t++) {
+               if (t >= ifd->ifd_records + NRECORDS)
+                       t = ifd->ifd_records;
+               if (t->ift_size == 0)
+                       continue;
+               fprintf(fd, "%.24s: metric=%d\n", ctime(&t->ift_stamp),
+                       t->ift_metric);
+               dumppacket(fd, dir, &t->ift_who, t->ift_packet, t->ift_size);
+       }
+}
+
+dumppacket(fd, dir, who, cp, size)
+       FILE *fd;
+       struct sockaddr_ns *who;                /* should be sockaddr */
+       char *dir, *cp;
+       register int size;
+{
+       register struct rip *msg = (struct rip *)cp;
+       register struct netinfo *n;
+       char *xns_nettoa();
+
+       if (msg->rip_cmd && ntohs(msg->rip_cmd) < RIPCMD_MAX)
+               fprintf(fd, "%s %s %s#%x", ripcmds[ntohs(msg->rip_cmd)],
+                   dir, xns_ntoa(&who->sns_addr), ntohs(who->sns_addr.x_port));
+       else {
+               fprintf(fd, "Bad cmd 0x%x %s %s#%x\n", ntohs(msg->rip_cmd),
+                   dir, xns_ntoa(&who->sns_addr), ntohs(who->sns_addr.x_port));
+               fprintf(fd, "size=%d cp=%x packet=%x\n", size, cp, packet);
+               return;
+       }
+       switch (ntohs(msg->rip_cmd)) {
+
+       case RIPCMD_REQUEST:
+       case RIPCMD_RESPONSE:
+               fprintf(fd, ":\n");
+               size -= sizeof (u_short);
+               n = msg->rip_nets;
+               for (; size > 0; n++, size -= sizeof (struct netinfo)) {
+                       if (size < sizeof (struct netinfo))
+                               break;
+                       fprintf(fd, "\tnet %s metric %d\n",
+                            xns_nettoa(n->rip_dst),
+                            ntohs(n->rip_metric));
+               }
+               break;
+
+       }
+}
+
+union ns_net_u net;
+
+char *
+xns_nettoa(val)
+union ns_net val;
+{
+       static char buf[100];
+       net.net_e = val;
+       (void)sprintf(buf, "%lx", ntohl(net.long_e));
+       return (buf);
+}
+
+
+char *
+xns_ntoa(addr)
+struct ns_addr *addr;
+{
+    static char buf[100];
+
+    (void)sprintf(buf, "%s#%x:%x:%x:%x:%x:%x",
+       xns_nettoa(addr->x_net),
+       addr->x_host.c_host[0], addr->x_host.c_host[1], 
+       addr->x_host.c_host[2], addr->x_host.c_host[3], 
+       addr->x_host.c_host[4], addr->x_host.c_host[5]);
+       
+    return(buf);
+}
diff --git a/usr.sbin/XNSrouted/trace.h b/usr.sbin/XNSrouted/trace.h
new file mode 100644 (file)
index 0000000..be48553
--- /dev/null
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 1983 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This file includes significant work done at Cornell University by
+ * Bill Nesheim.  That work included by permission.
+ *
+ * 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.
+ *
+ *     @(#)trace.h     5.6 (Berkeley) 6/1/90
+ */
+
+/*
+ * Xerox Routing Information Protocol.
+ */
+
+/*
+ * Trace record format.
+ */
+struct iftrace {
+       time_t  ift_stamp;              /* time stamp */
+       struct  sockaddr ift_who;       /* from/to */
+       char    *ift_packet;            /* pointer to packet */
+       short   ift_size;               /* size of packet */
+       short   ift_metric;             /* metric  */
+};
+
+/*
+ * Per interface packet tracing buffers.  An incoming and
+ * outgoing circular buffer of packets is maintained, per
+ * interface, for debugging.  Buffers are dumped whenever
+ * an interface is marked down.
+ */
+struct ifdebug {
+       struct  iftrace *ifd_records;   /* array of trace records */
+       struct  iftrace *ifd_front;     /* next empty trace record */
+       int     ifd_count;              /* number of unprinted records */
+       struct  interface *ifd_if;      /* for locating stuff */
+};
+
+/*
+ * Packet tracing stuff.
+ */
+int    tracepackets;           /* watch packets as they go by */
+int    tracing;                /* on/off */
+FILE   *ftrace;                /* output trace file */
+
+#define        TRACE_ACTION(action, route) { \
+         if (tracing) \
+               traceaction(ftrace, "action", route); \
+       }
+#define        TRACE_INPUT(ifp, src, size) { \
+         if (tracing) { \
+               ifp = if_iflookup(src); \
+               if (ifp) \
+                       trace(&ifp->int_input, src, &packet[sizeof(struct idp)], size, \
+                               ntohl(ifp->int_metric)); \
+         } \
+         if (tracepackets && ftrace) \
+               dumppacket(ftrace, "from", src, &packet[sizeof(struct idp)], size); \
+       }
+#define        TRACE_OUTPUT(ifp, dst, size) { \
+         if (tracing) { \
+               ifp = if_iflookup(dst); \
+               if (ifp) \
+                   trace(&ifp->int_output, dst, &packet[sizeof(struct idp)], size, ifp->int_metric); \
+         } \
+         if (tracepackets && ftrace) \
+               dumppacket(ftrace, "to", dst, &packet[sizeof(struct idp)], size); \
+       }