diff options
40 files changed, 7240 insertions, 0 deletions
| diff --git a/usr.sbin/XNSrouted/Makefile b/usr.sbin/XNSrouted/Makefile new file mode 100644 index 000000000000..1b3cf0e9f53d --- /dev/null +++ b/usr.sbin/XNSrouted/Makefile @@ -0,0 +1,9 @@ +#	@(#)Makefile	8.1 (Berkeley) 6/5/93 + +PROG=	XNSrouted +MAN8=	XNSrouted.0 +SRCS=	af.c if.c input.c main.c output.c startup.c tables.c timer.c trace.c +DPADD=	${LIBCOMPAT} +LDADD=	-lcompat + +.include <bsd.prog.mk> diff --git a/usr.sbin/XNSrouted/XNSrouted.8 b/usr.sbin/XNSrouted/XNSrouted.8 new file mode 100644 index 000000000000..7b278bd2d96f --- /dev/null +++ b/usr.sbin/XNSrouted/XNSrouted.8 @@ -0,0 +1,186 @@ +.\" Copyright (c) 1986, 1991, 1993 +.\"	The Regents of the University of California.  All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\"    notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\"    notice, this list of conditions and the following disclaimer in the +.\"    documentation and/or other materials provided with the distribution. +.\" 3. 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	8.1 (Berkeley) 6/5/93 +.\" +.Dd June 5, 1993 +.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 index 000000000000..6c81b47fcad7 --- /dev/null +++ b/usr.sbin/XNSrouted/af.c @@ -0,0 +1,246 @@ +/* + * Copyright (c) 1985, 1993 + *	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	8.1 (Berkeley) 6/5/93"; +#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 index 000000000000..9b74463dd684 --- /dev/null +++ b/usr.sbin/XNSrouted/af.h @@ -0,0 +1,64 @@ +/* + * Copyright (c) 1983, 1993 + *	The Regents of the University of California.  All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + *    notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + *    notice, this list of conditions and the following disclaimer in the + *    documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + *    must display the following acknowledgement: + *	This product includes software developed by the University of + *	California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + *    may be used to endorse or promote products derived from this software + *    without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + *	@(#)af.h	5.1 (Berkeley) 6/4/85 (routed/af.h) + * + *	@(#)af.h	8.1 (Berkeley) 6/5/93 + */ + +/* + * 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 index 000000000000..c380e816b224 --- /dev/null +++ b/usr.sbin/XNSrouted/defs.h @@ -0,0 +1,94 @@ +/* + * Copyright (c) 1983, 1993 + *	The Regents of the University of California.  All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + *    notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + *    notice, this list of conditions and the following disclaimer in the + *    documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + *    must display the following acknowledgement: + *	This product includes software developed by the University of + *	California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + *    may be used to endorse or promote products derived from this software + *    without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + *	@(#)defs.h	8.1 (Berkeley) 6/5/93 + */ + +#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 */ +int	r;			/* Routing socket to install updates with */ +struct	sockaddr_ns ns_netmask;	/* Used in installing routes */ + +char	packet[MAXPACKETSIZE+sizeof(struct idp)+1]; +struct	rip *msg; + +char	**argv0; + +int	sndmsg(); +int	supply(); +int	cleanup(); +int	rtioctl(); +#define	ADD	1 +#define	DELETE	2 +#define CHANGE	3 diff --git a/usr.sbin/XNSrouted/if.c b/usr.sbin/XNSrouted/if.c new file mode 100644 index 000000000000..422f75753ed0 --- /dev/null +++ b/usr.sbin/XNSrouted/if.c @@ -0,0 +1,147 @@ +/* + * Copyright (c) 1983, 1993 + *	The Regents of the University of California.  All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + *    notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + *    notice, this list of conditions and the following disclaimer in the + *    documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + *    must display the following acknowledgement: + *	This product includes software developed by the University of + *	California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + *    may be used to endorse or promote products derived from this software + *    without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * static char sccsid[] = "@(#)if.c	5.1 (Berkeley) 6/4/85"; (routed/if.c) + */ + +#ifndef lint +static char sccsid[] = "@(#)if.c	8.1 (Berkeley) 6/5/93"; +#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 index 000000000000..b64fca215233 --- /dev/null +++ b/usr.sbin/XNSrouted/input.c @@ -0,0 +1,189 @@ +/* + * Copyright (c) 1985, 1993 + *	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	8.1 (Berkeley) 6/5/93"; +#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 index 000000000000..64e15802fdd1 --- /dev/null +++ b/usr.sbin/XNSrouted/interface.h @@ -0,0 +1,90 @@ +/* + * Copyright (c) 1983, 1993 + *	The Regents of the University of California.  All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + *    notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + *    notice, this list of conditions and the following disclaimer in the + *    documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + *    must display the following acknowledgement: + *	This product includes software developed by the University of + *	California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + *    may be used to endorse or promote products derived from this software + *    without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + *	@(#)interface.h	8.1 (Berkeley) 6/5/93 + */ + +/* + * 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 index 000000000000..601a0050d6f2 --- /dev/null +++ b/usr.sbin/XNSrouted/main.c @@ -0,0 +1,255 @@ +/* + * Copyright (c) 1985, 1993 + *	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 copyright[] = +"@(#) Copyright (c) 1985, 1993\n\ +	The Regents of the University of California.  All rights reserved.\n"; +#endif /* not lint */ + +#ifndef lint +static char sccsid[] = "@(#)main.c	8.1 (Berkeley) 6/5/93"; +#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); + +	addr.sns_family = AF_NS; +	addr.sns_len = sizeof(addr); +	addr.sns_port = htons(IDPPORT_RIF); +	ns_anynet.s_net[0] = ns_anynet.s_net[1] = -1; +	ns_netmask.sns_addr.x_net = ns_anynet; +	ns_netmask.sns_len = 6; +	r = socket(AF_ROUTE, SOCK_RAW, 0); +	/* later, get smart about lookingforinterfaces */ +	if (r) +		shutdown(r, 0); /* for now, don't want reponses */ +	else { +		fprintf(stderr, "routed: no routing socket\n"); +		exit(1); +	} +	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 index 000000000000..fae1c3931527 --- /dev/null +++ b/usr.sbin/XNSrouted/output.c @@ -0,0 +1,147 @@ +/* + * Copyright (c) 1985, 1993 + *	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	8.1 (Berkeley) 6/5/93"; +#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 index 000000000000..72b0ddb0a05d --- /dev/null +++ b/usr.sbin/XNSrouted/protocol.h @@ -0,0 +1,85 @@ +/* + * Copyright (c) 1985, 1993 + *	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	8.1 (Berkeley) 6/5/93 + */ + +/* + * 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 index 000000000000..bcb5615ff6d9 --- /dev/null +++ b/usr.sbin/XNSrouted/startup.c @@ -0,0 +1,274 @@ +/* + * Copyright (c) 1985, 1993 + *	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	8.1 (Berkeley) 6/5/93"; +#endif /* not lint */ + +/* + * Routing Table Management Daemon + */ +#include "defs.h" + +#include <sys/param.h> +#include <sys/ioctl.h> +#include <sys/sysctl.h> + +#include <net/if.h> +#include <net/if_dl.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}; + + +void +quit(s) +	char *s; +{ +	extern int errno; +	int sverrno = errno; + +	(void) fprintf(stderr, "route: "); +	if (s) +		(void) fprintf(stderr, "%s: ", s); +	(void) fprintf(stderr, "%s\n", strerror(sverrno)); +	exit(1); +	/* NOTREACHED */ +} + +struct rt_addrinfo info; +/* Sleazy use of local variables throughout file, warning!!!! */ +#define netmask	info.rti_info[RTAX_NETMASK] +#define ifaaddr	info.rti_info[RTAX_IFA] +#define brdaddr	info.rti_info[RTAX_BRD] + +#define ROUNDUP(a) \ +	((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long)) +#define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len)) + +void +rt_xaddrs(cp, cplim, rtinfo) +	register caddr_t cp, cplim; +	register struct rt_addrinfo *rtinfo; +{ +	register struct sockaddr *sa; +	register int i; + +	bzero(rtinfo->rti_info, sizeof(rtinfo->rti_info)); +	for (i = 0; (i < RTAX_MAX) && (cp < cplim); i++) { +		if ((rtinfo->rti_addrs & (1 << i)) == 0) +			continue; +		rtinfo->rti_info[i] = sa = (struct sockaddr *)cp; +		ADVANCE(cp, sa); +	} +} + +/* + * 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; +	size_t needed; +	int mib[6], no_nsaddr = 0, flags = 0; +	char *buf, *cplim, *cp; +	register struct if_msghdr *ifm; +	register struct ifa_msghdr *ifam; +	struct sockaddr_dl *sdl; +	u_long i; + +        mib[0] = CTL_NET; +        mib[1] = PF_ROUTE; +        mib[2] = 0; +        mib[3] = AF_NS; +        mib[4] = NET_RT_IFLIST; +        mib[5] = 0; +        if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0) +                quit("route-sysctl-estimate"); +	if ((buf = malloc(needed)) == NULL) +		quit("malloc"); +        if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0) +	lookforinterfaces = 0; +	cplim = buf + needed; +	for (cp = buf; cp < cplim; cp += ifm->ifm_msglen) { +		ifm = (struct if_msghdr *)cp; +		if (ifm->ifm_type == RTM_IFINFO) { +			bzero(&ifs, sizeof(ifs)); +			ifs.int_flags = flags = ifm->ifm_flags | IFF_INTERFACE; +			if ((flags & IFF_UP) == 0 || no_nsaddr) +				lookforinterfaces = 1; +			sdl = (struct sockaddr_dl *) (ifm + 1); +			sdl->sdl_data[sdl->sdl_nlen] = 0; +			no_nsaddr = 1; +			continue; +		} +		if (ifm->ifm_type != RTM_NEWADDR) +			quit("ifinit: out of sync"); +		if ((flags & IFF_UP) == 0) +			continue; +		ifam = (struct ifa_msghdr *)ifm; +		info.rti_addrs = ifam->ifam_addrs; +		rt_xaddrs((char *)(ifam + 1), cp + ifam->ifam_msglen, &info); +		if (ifaaddr == 0) { +			syslog(LOG_ERR, "%s: (get addr)", sdl->sdl_data); +			continue; +		} +		ifs.int_addr = *ifaaddr; +		if (ifs.int_addr.sa_family != AF_NS) +			continue; +		no_nsaddr = 0; +		if (ifs.int_flags & IFF_POINTOPOINT) { +			if (brdaddr == 0) { +				syslog(LOG_ERR, "%s: (get dstaddr)", +					sdl->sdl_data); +				continue; +			} +			if (brdaddr->sa_family == AF_UNSPEC) { +				lookforinterfaces = 1; +				continue; +			} +			ifs.int_dstaddr = *brdaddr; +		} +		if (ifs.int_flags & IFF_BROADCAST) { +			if (brdaddr == 0) { +				syslog(LOG_ERR, "%s: (get broadaddr)", +					sdl->sdl_data); +				continue; +			} +			ifs.int_dstaddr = *brdaddr; +		} +		/*  +		 * 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 (ifs.int_flags & IFF_LOOPBACK) +			continue; +		ifp = (struct interface *) +			malloc(sdl->sdl_nlen + 1 + sizeof(ifs)); +		if (ifp == 0) { +			syslog(LOG_ERR, "XNSrouted: out of memory\n"); +			lookforinterfaces = 1; +			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 = (char *)(ifp + 1); +		strcpy(ifp->int_name, sdl->sdl_data); +		ifp->int_metric = ifam->ifam_metric; +		ifp->int_next = ifnet; +		ifnet = ifp; +		traceinit(ifp); +		addrouteforif(ifp); +	} +	if (externalinterfaces > 1 && supplier < 0) +		supplier = 1; +	free(buf); +} + +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 index 000000000000..1de2a950f416 --- /dev/null +++ b/usr.sbin/XNSrouted/table.h @@ -0,0 +1,99 @@ +/* + * Copyright (c) 1983, 1993 + *	The Regents of the University of California.  All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + *    notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + *    notice, this list of conditions and the following disclaimer in the + *    documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + *    must display the following acknowledgement: + *	This product includes software developed by the University of + *	California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + *    may be used to endorse or promote products derived from this software + *    without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + *	@(#)table.h	5.1 (Berkeley) 6/4/85 (routed/table.h) + * + *	@(#)table.h	8.1 (Berkeley) 6/5/93 + */ + +/* + * 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 index 000000000000..4b00dc55c55a --- /dev/null +++ b/usr.sbin/XNSrouted/tables.c @@ -0,0 +1,319 @@ +/* + * Copyright (c) 1985, 1993 + *	The Regents of the University of California.  All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + *    notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + *    notice, this list of conditions and the following disclaimer in the + *    documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + *    must display the following acknowledgement: + *	This product includes software developed by the University of + *	California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + *    may be used to endorse or promote products derived from this software + *    without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char sccsid[] = "@(#)tables.c	8.1 (Berkeley) 6/5/93"; +#endif /* not lint */ + +/* + * Routing Table Management Daemon + */ +#include "defs.h" +#include <sys/ioctl.h> +#include <errno.h> + +#ifndef DEBUG +#define	DEBUG	0 +#endif + +extern	char *xns_ntoa(); +#define FIXLEN(s) { if ((s)->sa_len == 0) (s)->sa_len = sizeof (*(s));} + +int	install = !DEBUG;		/* if 1 call kernel */ +int	delete = 1; +/* + * Lookup dst in the tables for an exact match. + */ +struct rt_entry * +rtlookup(dst) +	struct sockaddr *dst; +{ +	register struct rt_entry *rt; +	register struct rthash *rh; +	register u_int hash; +	struct afhash h; +	int doinghost = 1; + +	if (dst->sa_family >= AF_MAX) +		return (0); +	(*afswitch[dst->sa_family].af_hash)(dst, &h); +	hash = h.afh_hosthash; +	rh = &hosthash[hash & ROUTEHASHMASK]; +again: +	for (rt = rh->rt_forw; rt != (struct rt_entry *)rh; rt = rt->rt_forw) { +		if (rt->rt_hash != hash) +			continue; +		if (equal(&rt->rt_dst, dst)) +			return (rt); +	} +	if (doinghost) { +		doinghost = 0; +		hash = h.afh_nethash; +		rh = &nethash[hash & ROUTEHASHMASK]; +		goto again; +	} +	return (0); +} + +/* + * Find a route to dst as the kernel would. + */ +struct rt_entry * +rtfind(dst) +	struct sockaddr *dst; +{ +	register struct rt_entry *rt; +	register struct rthash *rh; +	register u_int hash; +	struct afhash h; +	int af = dst->sa_family; +	int doinghost = 1, (*match)(); + +	if (af >= AF_MAX) +		return (0); +	(*afswitch[af].af_hash)(dst, &h); +	hash = h.afh_hosthash; +	rh = &hosthash[hash & ROUTEHASHMASK]; + +again: +	for (rt = rh->rt_forw; rt != (struct rt_entry *)rh; rt = rt->rt_forw) { +		if (rt->rt_hash != hash) +			continue; +		if (doinghost) { +			if (equal(&rt->rt_dst, dst)) +				return (rt); +		} else { +			if (rt->rt_dst.sa_family == af && +			    (*match)(&rt->rt_dst, dst)) +				return (rt); +		} +	} +	if (doinghost) { +		doinghost = 0; +		hash = h.afh_nethash; +		rh = &nethash[hash & ROUTEHASHMASK]; +		match = afswitch[af].af_netmatch; +		goto again; +	} +	return (0); +} + +rtadd(dst, gate, metric, state) +	struct sockaddr *dst, *gate; +	int metric, state; +{ +	struct afhash h; +	register struct rt_entry *rt; +	struct rthash *rh; +	int af = dst->sa_family, flags; +	u_int hash; + +	FIXLEN(dst); +	FIXLEN(gate); +	if (af >= AF_MAX) +		return; +	(*afswitch[af].af_hash)(dst, &h); +	flags = (*afswitch[af].af_ishost)(dst) ? RTF_HOST : 0; +	if (flags & RTF_HOST) { +		hash = h.afh_hosthash; +		rh = &hosthash[hash & ROUTEHASHMASK]; +	} else { +		hash = h.afh_nethash; +		rh = &nethash[hash & ROUTEHASHMASK]; +	} +	rt = (struct rt_entry *)malloc(sizeof (*rt)); +	if (rt == 0) +		return; +	rt->rt_hash = hash; +	rt->rt_dst = *dst; +	rt->rt_router = *gate; +	rt->rt_metric = metric; +	rt->rt_timer = 0; +	rt->rt_flags = RTF_UP | flags; +	rt->rt_state = state | RTS_CHANGED; +	rt->rt_ifp = if_ifwithnet(&rt->rt_router); +	if (metric) +		rt->rt_flags |= RTF_GATEWAY; +	insque(rt, rh); +	TRACE_ACTION(ADD, rt); +	/* +	 * If the ioctl fails because the gateway is unreachable +	 * from this host, discard the entry.  This should only +	 * occur because of an incorrect entry in /etc/gateways. +	 */ +	if (install && rtioctl(ADD, &rt->rt_rt) < 0) { +		if (errno != EEXIST) +			perror("SIOCADDRT"); +		if (errno == ENETUNREACH) { +			TRACE_ACTION(DELETE, rt); +			remque(rt); +			free((char *)rt); +		} +	} +} + +rtchange(rt, gate, metric) +	struct rt_entry *rt; +	struct sockaddr *gate; +	short metric; +{ +	int doioctl = 0, metricchanged = 0; +	struct rtentry oldroute; + +	FIXLEN(gate); +	if (!equal(&rt->rt_router, gate)) +		doioctl++; +	if (metric != rt->rt_metric) +		metricchanged++; +	if (doioctl || metricchanged) { +		TRACE_ACTION(CHANGE FROM, rt); +		if (doioctl) { +			oldroute = rt->rt_rt; +			rt->rt_router = *gate; +		} +		rt->rt_metric = metric; +		if ((rt->rt_state & RTS_INTERFACE) && metric) { +			rt->rt_state &= ~RTS_INTERFACE; +			syslog(LOG_ERR, +				"changing route from interface %s (timed out)", +				rt->rt_ifp->int_name); +		} +		if (metric) +			rt->rt_flags |= RTF_GATEWAY; +		else +			rt->rt_flags &= ~RTF_GATEWAY; +		rt->rt_state |= RTS_CHANGED; +		TRACE_ACTION(CHANGE TO, rt); +	} +	if (doioctl && install) { +#ifndef RTM_ADD +		if (rtioctl(ADD, &rt->rt_rt) < 0) +		  syslog(LOG_ERR, "rtioctl ADD dst %s, gw %s: %m", +		   xns_ntoa(&((struct sockaddr_ns *)&rt->rt_dst)->sns_addr), +		   xns_ntoa(&((struct sockaddr_ns *)&rt->rt_router)->sns_addr)); +		if (delete && rtioctl(DELETE, &oldroute) < 0) +			perror("rtioctl DELETE"); +#else +		if (delete == 0) { +			if (rtioctl(ADD, &rt->rt_rt) >= 0) +				return; +		} else { +			if (rtioctl(CHANGE, &rt->rt_rt) >= 0) +				return; +		} +	        syslog(LOG_ERR, "rtioctl ADD dst %s, gw %s: %m", +		   xns_ntoa(&((struct sockaddr_ns *)&rt->rt_dst)->sns_addr), +		   xns_ntoa(&((struct sockaddr_ns *)&rt->rt_router)->sns_addr)); +#endif +	} +} + +rtdelete(rt) +	struct rt_entry *rt; +{ + +	struct sockaddr *sa = &(rt->rt_rt.rt_gateway); +	FIXLEN(sa); +#undef rt_dst +	sa = &(rt->rt_rt.rt_dst); +	FIXLEN(sa); +	if (rt->rt_state & RTS_INTERFACE) { +		syslog(LOG_ERR, "deleting route to interface %s (timed out)", +			rt->rt_ifp->int_name); +	} +	TRACE_ACTION(DELETE, rt); +	if (install && rtioctl(DELETE, &rt->rt_rt) < 0) +		perror("rtioctl DELETE"); +	remque(rt); +	free((char *)rt); +} + +rtinit() +{ +	register struct rthash *rh; + +	for (rh = nethash; rh < &nethash[ROUTEHASHSIZ]; rh++) +		rh->rt_forw = rh->rt_back = (struct rt_entry *)rh; +	for (rh = hosthash; rh < &hosthash[ROUTEHASHSIZ]; rh++) +		rh->rt_forw = rh->rt_back = (struct rt_entry *)rh; +} +int seqno; + +rtioctl(action, ort) +	int action; +	struct ortentry *ort; +{ +#ifndef RTM_ADD +	switch (action) { + +	case ADD: +		return (ioctl(s, SIOCADDRT, (char *)ort)); + +	case DELETE: +		return (ioctl(s, SIOCDELRT, (char *)ort)); + +	default: +		return (-1); +	} +#else /* RTM_ADD */ +	struct { +		struct rt_msghdr w_rtm; +		struct sockaddr w_dst; +		struct sockaddr w_gate; +		struct sockaddr_ns w_netmask; +	} w; +#define rtm w.w_rtm + +	bzero((char *)&w, sizeof(w)); +	rtm.rtm_msglen = sizeof(w); +	rtm.rtm_version = RTM_VERSION; +	rtm.rtm_type = (action == ADD ? RTM_ADD : +				(action == DELETE ? RTM_DELETE : RTM_CHANGE)); +#undef rt_flags +	rtm.rtm_flags = ort->rt_flags; +	rtm.rtm_seq = ++seqno; +	rtm.rtm_addrs = RTA_DST|RTA_GATEWAY; +	bcopy((char *)&ort->rt_dst, (char *)&w.w_dst, sizeof(w.w_dst)); +	bcopy((char *)&ort->rt_gateway, (char *)&w.w_gate, sizeof(w.w_gate)); +	w.w_gate.sa_family = w.w_dst.sa_family = AF_NS; +	w.w_gate.sa_len = w.w_dst.sa_len = sizeof(w.w_dst); +	if (rtm.rtm_flags & RTF_HOST) { +		rtm.rtm_msglen -= sizeof(w.w_netmask); +	} else { +		w.w_netmask = ns_netmask; +		rtm.rtm_msglen -= 8; +	} +	errno = 0; +	return write(r, (char *)&w, rtm.rtm_msglen); +#endif  /* RTM_ADD */ +} diff --git a/usr.sbin/XNSrouted/timer.c b/usr.sbin/XNSrouted/timer.c new file mode 100644 index 000000000000..32c2bff9dc56 --- /dev/null +++ b/usr.sbin/XNSrouted/timer.c @@ -0,0 +1,139 @@ +/* + * Copyright (c) 1985, 1993 + *	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	8.1 (Berkeley) 6/5/93"; +#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 index 000000000000..7deeac032011 --- /dev/null +++ b/usr.sbin/XNSrouted/tools/query.c @@ -0,0 +1,232 @@ +/*- + * Copyright (c) 1983, 1986, 1993 + *	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 +static char copyright[] = +"@(#) Copyright (c) 1983, 1986, 1993\n\ +	The Regents of the University of California.  All rights reserved.\n"; +#endif /* not lint */ + +#ifndef lint +static char sccsid[] = "@(#)query.c	8.1 (Berkeley) 6/5/93"; +#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(¬ime, sizeof(notime)); +	signal(SIGALRM, timeout); +	alarm(WTIME); +	while (!timedout ||  +	    select(20, &bits, 0, 0, ¬ime) > 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 index 000000000000..385bb9bf0b40 --- /dev/null +++ b/usr.sbin/XNSrouted/trace.c @@ -0,0 +1,313 @@ +/* + * Copyright (c) 1985, 1993 + *	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	8.1 (Berkeley) 6/5/93"; +#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 index 000000000000..b7cf3a8648bf --- /dev/null +++ b/usr.sbin/XNSrouted/trace.h @@ -0,0 +1,96 @@ +/* + * Copyright (c) 1983, 1993 + *	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	8.1 (Berkeley) 6/5/93 + */ + +/* + * 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/routed/Makefile b/usr.sbin/routed/Makefile new file mode 100644 index 000000000000..d9dd7f8f7ada --- /dev/null +++ b/usr.sbin/routed/Makefile @@ -0,0 +1,22 @@ +#	@(#)Makefile	8.1 (Berkeley) 6/19/93 + +PROG=	routed +SRCS=	af.c if.c input.c main.c output.c startup.c tables.c timer.c \ +	trace.c inet.c +MAN8=	routed.0 +#SUBDIR=	query trace +DPADD=	${LIBCOMPAT} +LDADD=	-lcompat + +.include <bsd.prog.mk> + +.if (${MACHINE} == "vax") +# The following can be deleted where not appropriate to use the kernel's +# inline code expansions. +INLINE=	/sys/vax/inline/obj/inline +C2=	/usr/libexec/c2 +.c.o: +	${CC} -S ${CFLAGS} ${.CURDIR}/${.PREFIX}.c +	@${C2} ${.PREFIX}.s | ${INLINE} | ${AS} -o ${.PREFIX}.o +	@rm -f ${.PREFIX}.s +.endif diff --git a/usr.sbin/routed/af.c b/usr.sbin/routed/af.c new file mode 100644 index 000000000000..05bf8fab805e --- /dev/null +++ b/usr.sbin/routed/af.c @@ -0,0 +1,171 @@ +/* + * Copyright (c) 1983, 1993 + *	The Regents of the University of California.  All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + *    notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + *    notice, this list of conditions and the following disclaimer in the + *    documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + *    must display the following acknowledgement: + *	This product includes software developed by the University of + *	California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + *    may be used to endorse or promote products derived from this software + *    without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char sccsid[] = "@(#)af.c	8.1 (Berkeley) 6/5/93"; +#endif /* not lint */ + +#include "defs.h" + +/* + * Address family support routines + */ +int	inet_hash(), inet_netmatch(), inet_output(), +	inet_portmatch(), inet_portcheck(), +	inet_checkhost(), inet_rtflags(), inet_sendroute(), inet_canon(); +char	*inet_format(); + +#define NIL	{ 0 } +#define	INET \ +	{ inet_hash,		inet_netmatch,		inet_output, \ +	  inet_portmatch,	inet_portcheck,		inet_checkhost, \ +	  inet_rtflags,		inet_sendroute,		inet_canon, \ +	  inet_format \ +	} + +struct afswitch afswitch[AF_MAX] = { +	NIL,		/* 0- unused */ +	NIL,		/* 1- Unix domain, unused */ +	INET,		/* Internet */ +}; + +int af_max = sizeof(afswitch) / sizeof(afswitch[0]); + +struct sockaddr_in inet_default = { +#ifdef RTM_ADD +	sizeof (inet_default), +#endif +	AF_INET, INADDR_ANY }; + +inet_hash(sin, hp) +	register struct sockaddr_in *sin; +	struct afhash *hp; +{ +	register u_long n; + +	n = inet_netof(sin->sin_addr); +	if (n) +	    while ((n & 0xff) == 0) +		n >>= 8; +	hp->afh_nethash = n; +	hp->afh_hosthash = ntohl(sin->sin_addr.s_addr); +	hp->afh_hosthash &= 0x7fffffff; +} + +inet_netmatch(sin1, sin2) +	struct sockaddr_in *sin1, *sin2; +{ + +	return (inet_netof(sin1->sin_addr) == inet_netof(sin2->sin_addr)); +} + +/* + * Verify the message is from the right port. + */ +inet_portmatch(sin) +	register struct sockaddr_in *sin; +{ +	 +	return (sin->sin_port == sp->s_port); +} + +/* + * Verify the message is from a "trusted" port. + */ +inet_portcheck(sin) +	struct sockaddr_in *sin; +{ + +	return (ntohs(sin->sin_port) <= IPPORT_RESERVED); +} + +/* + * Internet output routine. + */ +inet_output(s, flags, sin, size) +	int s, flags; +	struct sockaddr_in *sin; +	int size; +{ +	struct sockaddr_in dst; + +	dst = *sin; +	sin = &dst; +	if (sin->sin_port == 0) +		sin->sin_port = sp->s_port; +	if (sin->sin_len == 0) +		sin->sin_len = sizeof (*sin); +	if (sendto(s, packet, size, flags, +	    (struct sockaddr *)sin, sizeof (*sin)) < 0) +		perror("sendto"); +} + +/* + * Return 1 if the address is believed + * for an Internet host -- THIS IS A KLUDGE. + */ +inet_checkhost(sin) +	struct sockaddr_in *sin; +{ +	u_long i = ntohl(sin->sin_addr.s_addr); + +#ifndef IN_EXPERIMENTAL +#define	IN_EXPERIMENTAL(i)	(((long) (i) & 0xe0000000) == 0xe0000000) +#endif + +	if (IN_EXPERIMENTAL(i) || sin->sin_port != 0) +		return (0); +	if (i != 0 && (i & 0xff000000) == 0) +		return (0); +	for (i = 0; i < sizeof(sin->sin_zero)/sizeof(sin->sin_zero[0]); i++) +		if (sin->sin_zero[i]) +			return (0); +	return (1); +} + +inet_canon(sin) +	struct sockaddr_in *sin; +{ + +	sin->sin_port = 0; +	sin->sin_len = sizeof(*sin); +} + +char * +inet_format(sin) +	struct sockaddr_in *sin; +{ +	char *inet_ntoa(); + +	return (inet_ntoa(sin->sin_addr)); +} diff --git a/usr.sbin/routed/af.h b/usr.sbin/routed/af.h new file mode 100644 index 000000000000..2fff298bbcb0 --- /dev/null +++ b/usr.sbin/routed/af.h @@ -0,0 +1,65 @@ +/* + * Copyright (c) 1983, 1993 + *	The Regents of the University of California.  All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + *    notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + *    notice, this list of conditions and the following disclaimer in the + *    documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + *    must display the following acknowledgement: + *	This product includes software developed by the University of + *	California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + *    may be used to endorse or promote products derived from this software + *    without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + *	@(#)af.h	8.1 (Berkeley) 6/5/93 + */ + +/* + * 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 is valid */ +	int	(*af_rtflags)();	/* get flags for route (host or net) */ +	int	(*af_sendroute)();	/* check bounds of subnet broadcast */ +	int	(*af_canon)();		/* canonicalize address for compares */ +	char	*(*af_format)();	/* convert address to string */ +}; + +/* + * Structure returned by af_hash routines. + */ +struct afhash { +	u_int	afh_hosthash;		/* host based hash */ +	u_int	afh_nethash;		/* network based hash */ +}; + +extern struct	afswitch afswitch[];	/* table proper */ +extern int	af_max;			/* number of entries in table */ diff --git a/usr.sbin/routed/defs.h b/usr.sbin/routed/defs.h new file mode 100644 index 000000000000..5b5ccacbf2f9 --- /dev/null +++ b/usr.sbin/routed/defs.h @@ -0,0 +1,103 @@ +/* + * Copyright (c) 1983, 1988, 1993 + *	The Regents of the University of California.  All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + *    notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + *    notice, this list of conditions and the following disclaimer in the + *    documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + *    must display the following acknowledgement: + *	This product includes software developed by the University of + *	California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + *    may be used to endorse or promote products derived from this software + *    without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + *	@(#)defs.h	8.1 (Berkeley) 6/5/93 + */ + +/* + * Internal data structure definitions for + * user routing process.  Based on Xerox NS + * protocol specs with mods relevant to more + * general addressing scheme. + */ +#include <sys/param.h> +#include <sys/socket.h> +#include <sys/time.h> + +#include <net/route.h> +#include <netinet/in.h> +#include <protocols/routed.h> + +#include <stdio.h> +#include <netdb.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	(1*60) + +#define equal(a1, a2) \ +	(bcmp((caddr_t)(a1), (caddr_t)(a2), sizeof (struct sockaddr)) == 0) + +struct	sockaddr_in addr;	/* address of daemon's socket */ + +int	s;			/* source and sink of all data */ +int	r;			/* routing socket */ +pid_t	pid;			/* process id for identifying messages */ +uid_t	uid;			/* user id for identifying messages */ +int	seqno;			/* sequence number for identifying messages */ +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 */ +struct	timeval now;		/* current idea of time */ +struct	timeval lastbcast;	/* last time all/changes broadcast */ +struct	timeval lastfullupdate;	/* last time full table broadcast */ +struct	timeval nextbcast;	/* time to wait before changes broadcast */ +int	needupdate;		/* true if we need update at nextbcast */ + +char	packet[MAXPACKETSIZE+1]; +struct	rip *msg; + +char	**argv0; +struct	servent *sp; + +struct	in_addr inet_makeaddr(); +int	inet_addr(); +int	inet_maskof(); +int	sndmsg(); +int	supply(); +int	cleanup(); + +int	rtioctl(); +#define ADD 1 +#define DELETE 2 +#define CHANGE 3 diff --git a/usr.sbin/routed/if.c b/usr.sbin/routed/if.c new file mode 100644 index 000000000000..54e8705c7699 --- /dev/null +++ b/usr.sbin/routed/if.c @@ -0,0 +1,148 @@ +/* + * Copyright (c) 1983, 1993 + *	The Regents of the University of California.  All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + *    notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + *    notice, this list of conditions and the following disclaimer in the + *    documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + *    must display the following acknowledgement: + *	This product includes software developed by the University of + *	California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + *    may be used to endorse or promote products derived from this software + *    without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char sccsid[] = "@(#)if.c	8.1 (Berkeley) 6/5/93"; +#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 ((ifp->int_flags & IFF_POINTOPOINT) && +		    same(&ifp->int_dstaddr, addr)) +			break; +		if (maybe == 0 && (*netmatch)(addr, &ifp->int_addr)) +			maybe = ifp; +	} +	if (ifp == 0) +		ifp = maybe; +	return (ifp); +} diff --git a/usr.sbin/routed/inet.c b/usr.sbin/routed/inet.c new file mode 100644 index 000000000000..925472c287b4 --- /dev/null +++ b/usr.sbin/routed/inet.c @@ -0,0 +1,243 @@ +/* + * Copyright (c) 1983, 1993 + *	The Regents of the University of California.  All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + *    notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + *    notice, this list of conditions and the following disclaimer in the + *    documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + *    must display the following acknowledgement: + *	This product includes software developed by the University of + *	California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + *    may be used to endorse or promote products derived from this software + *    without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char sccsid[] = "@(#)inet.c	8.2 (Berkeley) 8/14/93"; +#endif /* not lint */ + +/* + * Temporarily, copy these routines from the kernel, + * as we need to know about subnets. + */ +#include "defs.h" + +extern struct interface *ifnet; + +/* + * Formulate an Internet address from network + host. + */ +struct in_addr +inet_makeaddr(net, host) +	u_long net, host; +{ +	register struct interface *ifp; +	register u_long mask; +	u_long addr; + +	if (IN_CLASSA(net)) +		mask = IN_CLASSA_HOST; +	else if (IN_CLASSB(net)) +		mask = IN_CLASSB_HOST; +	else +		mask = IN_CLASSC_HOST; +	for (ifp = ifnet; ifp; ifp = ifp->int_next) +		if ((ifp->int_netmask & net) == ifp->int_net) { +			mask = ~ifp->int_subnetmask; +			break; +		} +	addr = net | (host & mask); +	addr = htonl(addr); +	return (*(struct in_addr *)&addr); +} + +/* + * Return the network number from an internet address. + */ +inet_netof(in) +	struct in_addr in; +{ +	register u_long i = ntohl(in.s_addr); +	register u_long net; +	register struct interface *ifp; + +	if (IN_CLASSA(i)) +		net = i & IN_CLASSA_NET; +	else if (IN_CLASSB(i)) +		net = i & IN_CLASSB_NET; +	else +		net = i & IN_CLASSC_NET; + +	/* +	 * Check whether network is a subnet; +	 * if so, return subnet number. +	 */ +	for (ifp = ifnet; ifp; ifp = ifp->int_next) +		if ((ifp->int_netmask & net) == ifp->int_net) +			return (i & ifp->int_subnetmask); +	return (net); +} + +/* + * Return the host portion of an internet address. + */ +inet_lnaof(in) +	struct in_addr in; +{ +	register u_long i = ntohl(in.s_addr); +	register u_long net, host; +	register struct interface *ifp; + +	if (IN_CLASSA(i)) { +		net = i & IN_CLASSA_NET; +		host = i & IN_CLASSA_HOST; +	} else if (IN_CLASSB(i)) { +		net = i & IN_CLASSB_NET; +		host = i & IN_CLASSB_HOST; +	} else { +		net = i & IN_CLASSC_NET; +		host = i & IN_CLASSC_HOST; +	} + +	/* +	 * Check whether network is a subnet; +	 * if so, use the modified interpretation of `host'. +	 */ +	for (ifp = ifnet; ifp; ifp = ifp->int_next) +		if ((ifp->int_netmask & net) == ifp->int_net) +			return (host &~ ifp->int_subnetmask); +	return (host); +} + +/* + * Return the netmask pertaining to an internet address. + */ +inet_maskof(inaddr) +	u_long inaddr; +{ +	register u_long i = ntohl(inaddr); +	register u_long mask; +	register struct interface *ifp; + +	if (i == 0) { +		mask = 0; +	} else if (IN_CLASSA(i)) { +		mask = IN_CLASSA_NET; +	} else if (IN_CLASSB(i)) { +		mask = i & IN_CLASSB_NET; +	} else +		mask = i & IN_CLASSC_NET; + +	/* +	 * Check whether network is a subnet; +	 * if so, use the modified interpretation of `host'. +	 */ +	for (ifp = ifnet; ifp; ifp = ifp->int_next) +		if ((ifp->int_netmask & i) == ifp->int_net) +			mask = ifp->int_subnetmask; +	return (htonl(mask)); +} + +/* + * Return RTF_HOST if the address is + * for an Internet host, RTF_SUBNET for a subnet, + * 0 for a network. + */ +inet_rtflags(sin) +	struct sockaddr_in *sin; +{ +	register u_long i = ntohl(sin->sin_addr.s_addr); +	register u_long net, host; +	register struct interface *ifp; + +	if (IN_CLASSA(i)) { +		net = i & IN_CLASSA_NET; +		host = i & IN_CLASSA_HOST; +	} else if (IN_CLASSB(i)) { +		net = i & IN_CLASSB_NET; +		host = i & IN_CLASSB_HOST; +	} else { +		net = i & IN_CLASSC_NET; +		host = i & IN_CLASSC_HOST; +	} + +	/* +	 * Check whether this network is subnetted; +	 * if so, check whether this is a subnet or a host. +	 */ +	for (ifp = ifnet; ifp; ifp = ifp->int_next) +		if (net == ifp->int_net) { +			if (host &~ ifp->int_subnetmask) +				return (RTF_HOST); +			else if (ifp->int_subnetmask != ifp->int_netmask) +				return (RTF_SUBNET); +			else +				return (0);		/* network */ +		} +	if (host == 0) +		return (0);	/* network */ +	else +		return (RTF_HOST); +} + +/* + * Return true if a route to subnet/host of route rt should be sent to dst. + * Send it only if dst is on the same logical network if not "internal", + * otherwise only if the route is the "internal" route for the logical net. + */ +inet_sendroute(rt, dst) +	struct rt_entry *rt; +	struct sockaddr_in *dst; +{ +	register u_long r = +	    ntohl(((struct sockaddr_in *)&rt->rt_dst)->sin_addr.s_addr); +	register u_long d = ntohl(dst->sin_addr.s_addr); + +	if (IN_CLASSA(r)) { +		if ((r & IN_CLASSA_NET) == (d & IN_CLASSA_NET)) { +			if ((r & IN_CLASSA_HOST) == 0) +				return ((rt->rt_state & RTS_INTERNAL) == 0); +			return (1); +		} +		if (r & IN_CLASSA_HOST) +			return (0); +		return ((rt->rt_state & RTS_INTERNAL) != 0); +	} else if (IN_CLASSB(r)) { +		if ((r & IN_CLASSB_NET) == (d & IN_CLASSB_NET)) { +			if ((r & IN_CLASSB_HOST) == 0) +				return ((rt->rt_state & RTS_INTERNAL) == 0); +			return (1); +		} +		if (r & IN_CLASSB_HOST) +			return (0); +		return ((rt->rt_state & RTS_INTERNAL) != 0); +	} else { +		if ((r & IN_CLASSC_NET) == (d & IN_CLASSC_NET)) { +			if ((r & IN_CLASSC_HOST) == 0) +				return ((rt->rt_state & RTS_INTERNAL) == 0); +			return (1); +		} +		if (r & IN_CLASSC_HOST) +			return (0); +		return ((rt->rt_state & RTS_INTERNAL) != 0); +	} +} diff --git a/usr.sbin/routed/input.c b/usr.sbin/routed/input.c new file mode 100644 index 000000000000..fb0ee798bebd --- /dev/null +++ b/usr.sbin/routed/input.c @@ -0,0 +1,362 @@ +/* + * Copyright (c) 1983, 1988, 1993 + *	The Regents of the University of California.  All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + *    notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + *    notice, this list of conditions and the following disclaimer in the + *    documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + *    must display the following acknowledgement: + *	This product includes software developed by the University of + *	California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + *    may be used to endorse or promote products derived from this software + *    without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char sccsid[] = "@(#)input.c	8.1 (Berkeley) 6/5/93"; +#endif /* not lint */ + +/* + * Routing Table Management Daemon + */ +#include "defs.h" +#include <sys/syslog.h> + +/* + * Process a newly received packet. + */ +rip_input(from, rip, size) +	struct sockaddr *from; +	register struct rip *rip; +	int size; +{ +	register struct rt_entry *rt; +	register struct netinfo *n; +	register struct interface *ifp; +	struct interface *if_ifwithdstaddr(); +	int count, changes = 0; +	register struct afswitch *afp; +	static struct sockaddr badfrom, badfrom2; + +	ifp = 0; +	TRACE_INPUT(ifp, from, (char *)rip, size); +	if (from->sa_family >= af_max || +	    (afp = &afswitch[from->sa_family])->af_hash == (int (*)())0) { +		syslog(LOG_INFO, +	 "\"from\" address in unsupported address family (%d), cmd %d\n", +		    from->sa_family, rip->rip_cmd); +		return; +	} +	if (rip->rip_vers == 0) { +		syslog(LOG_ERR, +		    "RIP version 0 packet received from %s! (cmd %d)", +		    (*afswitch[from->sa_family].af_format)(from), rip->rip_cmd); +		return; +	} +	switch (rip->rip_cmd) { + +	case RIPCMD_REQUEST: +		n = rip->rip_nets; +		count = size - ((char *)n - (char *)rip); +		if (count < sizeof (struct netinfo)) +			return; +		for (; count > 0; n++) { +			if (count < sizeof (struct netinfo)) +				break; +			count -= sizeof (struct netinfo); + +#if BSD < 198810 +			if (sizeof(n->rip_dst.sa_family) > 1)	/* XXX */ +			    n->rip_dst.sa_family = ntohs(n->rip_dst.sa_family); +#else +#define osa(x) ((struct osockaddr *)(&(x))) +			    n->rip_dst.sa_family = +					ntohs(osa(n->rip_dst)->sa_family); +			    n->rip_dst.sa_len = sizeof(n->rip_dst); +#endif +			n->rip_metric = ntohl(n->rip_metric); +			/*  +			 * A single entry with sa_family == AF_UNSPEC and +			 * metric ``infinity'' means ``all routes''. +			 * We respond to routers only if we are acting +			 * as a supplier, or to anyone other than a router +			 * (eg, query). +			 */ +			if (n->rip_dst.sa_family == AF_UNSPEC && +			    n->rip_metric == HOPCNT_INFINITY && count == 0) { +			    	if (supplier || (*afp->af_portmatch)(from) == 0) +					supply(from, 0, 0, 0); +				return; +			} +			if (n->rip_dst.sa_family < af_max && +			    afswitch[n->rip_dst.sa_family].af_hash) +				rt = rtlookup(&n->rip_dst); +			else +				rt = 0; +#define min(a, b) (a < b ? a : b) +			n->rip_metric = rt == 0 ? HOPCNT_INFINITY : +				min(rt->rt_metric + 1, HOPCNT_INFINITY); +#if BSD < 198810 +			if (sizeof(n->rip_dst.sa_family) > 1)	/* XXX */ +			    n->rip_dst.sa_family = htons(n->rip_dst.sa_family); +#else +			    osa(n->rip_dst)->sa_family = +						htons(n->rip_dst.sa_family); +#endif +			n->rip_metric = htonl(n->rip_metric); +		} +		rip->rip_cmd = RIPCMD_RESPONSE; +		bcopy((char *)rip, packet, size); +		(*afp->af_output)(s, 0, from, size); +		return; + +	case RIPCMD_TRACEON: +	case RIPCMD_TRACEOFF: +		/* verify message came from a privileged port */ +		if ((*afp->af_portcheck)(from) == 0) +			return; +		if ((ifp = if_iflookup(from)) == 0 || (ifp->int_flags & +		    (IFF_BROADCAST | IFF_POINTOPOINT | IFF_REMOTE)) == 0 || +		    ifp->int_flags & IFF_PASSIVE) { +			syslog(LOG_ERR, "trace command from unknown router, %s", +			    (*afswitch[from->sa_family].af_format)(from)); +			return; +		} +		((char *)rip)[size] = '\0'; +		if (rip->rip_cmd == RIPCMD_TRACEON) +			traceon(rip->rip_tracefile); +		else +			traceoff(); +		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? */ +		ifp = if_ifwithaddr(from); +		if (ifp) { +			if (ifp->int_flags & IFF_PASSIVE) { +				syslog(LOG_ERR, +				  "bogus input (from passive interface, %s)", +				  (*afswitch[from->sa_family].af_format)(from)); +				return; +			} +			rt = rtfind(from); +			if (rt == 0 || ((rt->rt_state & RTS_INTERFACE) == 0) && +			    rt->rt_metric >= ifp->int_metric)  +				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 | RTS_REMOTE))) +			rt->rt_timer = 0; +		else if ((ifp = if_ifwithdstaddr(from)) && +		    (rt == 0 || rt->rt_metric >= ifp->int_metric)) +			addrouteforif(ifp); +		/* +		 * "Authenticate" router from which message originated. +		 * We accept routing packets from routers directly connected +		 * via broadcast or point-to-point networks, +		 * and from those listed in /etc/gateways. +		 */ +		if ((ifp = if_iflookup(from)) == 0 || (ifp->int_flags & +		    (IFF_BROADCAST | IFF_POINTOPOINT | IFF_REMOTE)) == 0 || +		    ifp->int_flags & IFF_PASSIVE) { +			if (bcmp((char *)from, (char *)&badfrom, +			    sizeof(badfrom)) != 0) { +				syslog(LOG_ERR, +				  "packet from unknown router, %s", +				  (*afswitch[from->sa_family].af_format)(from)); +				badfrom = *from; +			} +			return; +		} +		size -= 4 * sizeof (char); +		n = rip->rip_nets; +		for (; size > 0; size -= sizeof (struct netinfo), n++) { +			if (size < sizeof (struct netinfo)) +				break; +#if BSD < 198810 +			if (sizeof(n->rip_dst.sa_family) > 1)	/* XXX */ +				n->rip_dst.sa_family = +					ntohs(n->rip_dst.sa_family); +#else +			    n->rip_dst.sa_family = +					ntohs(osa(n->rip_dst)->sa_family); +			    n->rip_dst.sa_len = sizeof(n->rip_dst); +#endif +			n->rip_metric = ntohl(n->rip_metric); +			if (n->rip_dst.sa_family >= af_max || +			    (afp = &afswitch[n->rip_dst.sa_family])->af_hash == +			    (int (*)())0) { +				syslog(LOG_INFO, +		"route in unsupported address family (%d), from %s (af %d)\n", +				   n->rip_dst.sa_family, +				   (*afswitch[from->sa_family].af_format)(from), +				   from->sa_family); +				continue; +			} +			if (((*afp->af_checkhost)(&n->rip_dst)) == 0) { +				syslog(LOG_DEBUG, +				    "bad host in route from %s (af %d)\n", +				   (*afswitch[from->sa_family].af_format)(from), +				   from->sa_family); +				continue; +			} +			if (n->rip_metric == 0 || +			    (unsigned) n->rip_metric > HOPCNT_INFINITY) { +				if (bcmp((char *)from, (char *)&badfrom2, +				    sizeof(badfrom2)) != 0) { +					syslog(LOG_ERR, +					    "bad metric (%d) from %s\n", +					    n->rip_metric, +				  (*afswitch[from->sa_family].af_format)(from)); +					badfrom2 = *from; +				} +				continue; +			} +			/* +			 * Adjust metric according to incoming interface. +			 */ +			if ((unsigned) n->rip_metric < HOPCNT_INFINITY) +				n->rip_metric += ifp->int_metric; +			if ((unsigned) n->rip_metric > HOPCNT_INFINITY) +				n->rip_metric = HOPCNT_INFINITY; +			rt = rtlookup(&n->rip_dst); +			if (rt == 0 || +			    (rt->rt_state & (RTS_INTERNAL|RTS_INTERFACE)) == +			    (RTS_INTERNAL|RTS_INTERFACE)) { +				/* +				 * If we're hearing a logical network route +				 * back from a peer to which we sent it, +				 * ignore it. +				 */ +				if (rt && rt->rt_state & RTS_SUBNET && +				    (*afp->af_sendroute)(rt, from)) +					continue; +				if ((unsigned)n->rip_metric < HOPCNT_INFINITY) { +				    /* +				     * Look for an equivalent route that +				     * includes this one before adding +				     * this route. +				     */ +				    rt = rtfind(&n->rip_dst); +				    if (rt && equal(from, &rt->rt_router)) +					    continue; +				    rtadd(&n->rip_dst, from, n->rip_metric, 0); +				    changes++; +				} +				continue; +			} + +			/* +			 * Update if from gateway and different, +			 * shorter, or equivalent but old route +			 * is getting stale. +			 */ +			if (equal(from, &rt->rt_router)) { +				if (n->rip_metric != rt->rt_metric) { +					rtchange(rt, from, n->rip_metric); +					changes++; +					rt->rt_timer = 0; +					if (rt->rt_metric >= HOPCNT_INFINITY) +						rt->rt_timer = +						    GARBAGE_TIME - EXPIRE_TIME; +				} else if (rt->rt_metric < HOPCNT_INFINITY) +					rt->rt_timer = 0; +			} else if ((unsigned) n->rip_metric < rt->rt_metric || +			    (rt->rt_metric == n->rip_metric && +			    rt->rt_timer > (EXPIRE_TIME/2) && +			    (unsigned) n->rip_metric < HOPCNT_INFINITY)) { +				rtchange(rt, from, n->rip_metric); +				changes++; +				rt->rt_timer = 0; +			} +		} +		break; +	} + +	/* +	 * If changes have occurred, and if we have not sent a broadcast +	 * recently, send a dynamic update.  This update is sent only +	 * on interfaces other than the one on which we received notice +	 * of the change.  If we are within MIN_WAITTIME of a full update, +	 * don't bother sending; if we just sent a dynamic update +	 * and set a timer (nextbcast), delay until that time. +	 * If we just sent a full update, delay the dynamic update. +	 * Set a timer for a randomized value to suppress additional +	 * dynamic updates until it expires; if we delayed sending +	 * the current changes, set needupdate. +	 */ +	if (changes && supplier && +	   now.tv_sec - lastfullupdate.tv_sec < SUPPLY_INTERVAL-MAX_WAITTIME) { +		u_long delay; +		extern long random(); + +		if (now.tv_sec - lastbcast.tv_sec >= MIN_WAITTIME && +		    timercmp(&nextbcast, &now, <)) { +			if (traceactions) +				fprintf(ftrace, "send dynamic update\n"); +			toall(supply, RTS_CHANGED, ifp); +			lastbcast = now; +			needupdate = 0; +			nextbcast.tv_sec = 0; +		} else { +			needupdate++; +			if (traceactions) +				fprintf(ftrace, "delay dynamic update\n"); +		} +#define RANDOMDELAY()	(MIN_WAITTIME * 1000000 + \ +		(u_long)random() % ((MAX_WAITTIME - MIN_WAITTIME) * 1000000)) + +		if (nextbcast.tv_sec == 0) { +			delay = RANDOMDELAY(); +			if (traceactions) +				fprintf(ftrace, +				    "inhibit dynamic update for %d usec\n", +				    delay); +			nextbcast.tv_sec = delay / 1000000; +			nextbcast.tv_usec = delay % 1000000; +			timevaladd(&nextbcast, &now); +			/* +			 * If the next possibly dynamic update +			 * is within MIN_WAITTIME of the next full update, +			 * force the delay past the full update, +			 * or we might send a dynamic update just before +			 * the full update. +			 */ +			if (nextbcast.tv_sec > lastfullupdate.tv_sec + +			    SUPPLY_INTERVAL - MIN_WAITTIME) +				nextbcast.tv_sec = lastfullupdate.tv_sec + +				    SUPPLY_INTERVAL + 1; +		} +	} +} diff --git a/usr.sbin/routed/interface.h b/usr.sbin/routed/interface.h new file mode 100644 index 000000000000..fc576d428288 --- /dev/null +++ b/usr.sbin/routed/interface.h @@ -0,0 +1,90 @@ +/* + * Copyright (c) 1983, 1993 + *	The Regents of the University of California.  All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + *    notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + *    notice, this list of conditions and the following disclaimer in the + *    documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + *    must display the following acknowledgement: + *	This product includes software developed by the University of + *	California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + *    may be used to endorse or promote products derived from this software + *    without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + *	@(#)interface.h	8.1 (Berkeley) 6/5/93 + */ + +/* + * 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. + */ +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 */ +	/* START INTERNET SPECIFIC */ +	u_long	int_net;			/* network # */ +	u_long	int_netmask;			/* net mask for addr */ +	u_long	int_subnet;			/* subnet # */ +	u_long	int_subnetmask;			/* subnet mask for addr */ +	/* END INTERNET SPECIFIC */ +	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 */ +}; + +/* + * 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_LOOPBACK	0x8		/* software loopback net */ +#define	IFF_POINTOPOINT	0x10		/* interface is point-to-point link */ + +#define	IFF_SUBNET	0x100000	/* interface on subnetted network */ +#define	IFF_PASSIVE	0x200000	/* can't tell if up/down */ +#define	IFF_INTERFACE	0x400000	/* hardware interface */ +#define	IFF_REMOTE	0x800000	/* 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/routed/main.c b/usr.sbin/routed/main.c new file mode 100644 index 000000000000..187aca115544 --- /dev/null +++ b/usr.sbin/routed/main.c @@ -0,0 +1,351 @@ +/* + * Copyright (c) 1983, 1988, 1993 + *	The Regents of the University of California.  All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + *    notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + *    notice, this list of conditions and the following disclaimer in the + *    documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + *    must display the following acknowledgement: + *	This product includes software developed by the University of + *	California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + *    may be used to endorse or promote products derived from this software + *    without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char copyright[] = +"@(#) Copyright (c) 1983, 1988, 1993\n\ +	The Regents of the University of California.  All rights reserved.\n"; +#endif /* not lint */ + +#ifndef lint +static char sccsid[] = "@(#)main.c	8.1 (Berkeley) 6/5/93"; +#endif /* not lint */ + +/* + * Routing Table Management Daemon + */ +#include "defs.h" +#include <sys/ioctl.h> +#include <sys/file.h> + +#include <net/if.h> + +#include <sys/errno.h> +#include <sys/signal.h> +#include <sys/syslog.h> +#include "pathnames.h" + +int	supplier = -1;		/* process should supply updates */ +int	gateway = 0;		/* 1 if we are a gateway to parts beyond */ +int	debug = 0; +int	bufspace = 127*1024;	/* max. input buffer size to request */ + +struct	rip *msg = (struct rip *)packet; +void	hup(), rtdeleteall(), sigtrace(), timer(); + +main(argc, argv) +	int argc; +	char *argv[]; +{ +	int n, cc, nfd, omask, tflags = 0; +	struct sockaddr from; +	struct timeval *tvp, waittime; +	struct itimerval itval; +	register struct rip *query = msg; +	fd_set ibits; +	u_char retry; +	 +	argv0 = argv; +#if BSD >= 43 +	openlog("routed", LOG_PID | LOG_ODELAY, LOG_DAEMON); +	setlogmask(LOG_UPTO(LOG_WARNING)); +#else +	openlog("routed", LOG_PID); +#define LOG_UPTO(x) (x) +#define setlogmask(x) (x) +#endif +	sp = getservbyname("router", "udp"); +	if (sp == NULL) { +		fprintf(stderr, "routed: router/udp: unknown service\n"); +		exit(1); +	} +	addr.sin_family = AF_INET; +	addr.sin_port = sp->s_port; +	r = socket(AF_ROUTE, SOCK_RAW, 0); +	/* later, get smart about lookingforinterfaces */ +	if (r) +		shutdown(r, 0); /* for now, don't want reponses */ +	else { +		fprintf(stderr, "routed: no routing socket\n"); +		exit(1); +	} +	s = getsocket(AF_INET, SOCK_DGRAM, &addr); +	if (s < 0) +		exit(1); +	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, "-t") == 0) { +			tflags++; +			setlogmask(LOG_UPTO(LOG_DEBUG)); +			argv++, argc--; +			continue; +		} +		if (strcmp(*argv, "-d") == 0) { +			debug++; +			setlogmask(LOG_UPTO(LOG_DEBUG)); +			argv++, argc--; +			continue; +		} +		if (strcmp(*argv, "-g") == 0) { +			gateway = 1; +			argv++, argc--; +			continue; +		} +		fprintf(stderr, +			"usage: routed [ -s ] [ -q ] [ -t ] [ -g ]\n"); +		exit(1); +	} + +	if (debug == 0 && tflags == 0) +		daemon(0, 0); +	/* +	 * Any extra argument is considered +	 * a tracing log file. +	 */ +	if (argc > 0) +		traceon(*argv); +	while (tflags-- > 0) +		bumploglevel(); + +	(void) gettimeofday(&now, (struct timezone *)NULL); +	/* +	 * Collect an initial view of the world by +	 * checking the interface configuration and the gateway kludge +	 * file.  Then, send a request packet on all +	 * directly connected networks to find out what +	 * everyone else thinks. +	 */ +	rtinit(); +	ifinit(); +	gwkludge(); +	if (gateway > 0) +		rtdefault(); +	if (supplier < 0) +		supplier = 0; +	query->rip_cmd = RIPCMD_REQUEST; +	query->rip_vers = RIPVERSION; +	if (sizeof(query->rip_nets[0].rip_dst.sa_family) > 1)	/* XXX */ +		query->rip_nets[0].rip_dst.sa_family = htons((u_short)AF_UNSPEC); +	else +		query->rip_nets[0].rip_dst.sa_family = AF_UNSPEC; +	query->rip_nets[0].rip_metric = htonl((u_long)HOPCNT_INFINITY); +	toall(sndmsg); +	signal(SIGALRM, timer); +	signal(SIGHUP, hup); +	signal(SIGTERM, hup); +	signal(SIGINT, rtdeleteall); +	signal(SIGUSR1, sigtrace); +	signal(SIGUSR2, sigtrace); +	itval.it_interval.tv_sec = TIMER_RATE; +	itval.it_value.tv_sec = TIMER_RATE; +	itval.it_interval.tv_usec = 0; +	itval.it_value.tv_usec = 0; +	srandom(getpid()); +	if (setitimer(ITIMER_REAL, &itval, (struct itimerval *)NULL) < 0) +		syslog(LOG_ERR, "setitimer: %m\n"); + +	FD_ZERO(&ibits); +	nfd = s + 1;			/* 1 + max(fd's) */ +	for (;;) { +		FD_SET(s, &ibits); +		/* +		 * If we need a dynamic update that was held off, +		 * needupdate will be set, and nextbcast is the time +		 * by which we want select to return.  Compute time +		 * until dynamic update should be sent, and select only +		 * until then.  If we have already passed nextbcast, +		 * just poll. +		 */ +		if (needupdate) { +			waittime = nextbcast; +			timevalsub(&waittime, &now); +			if (waittime.tv_sec < 0) { +				waittime.tv_sec = 0; +				waittime.tv_usec = 0; +			} +			if (traceactions) +				fprintf(ftrace, +				 "select until dynamic update %d/%d sec/usec\n", +				    waittime.tv_sec, waittime.tv_usec); +			tvp = &waittime; +		} else +			tvp = (struct timeval *)NULL; +		n = select(nfd, &ibits, 0, 0, tvp); +		if (n <= 0) { +			/* +			 * Need delayed dynamic update if select returned +			 * nothing and we timed out.  Otherwise, ignore +			 * errors (e.g. EINTR). +			 */ +			if (n < 0) { +				if (errno == EINTR) +					continue; +				syslog(LOG_ERR, "select: %m"); +			} +			omask = sigblock(sigmask(SIGALRM)); +			if (n == 0 && needupdate) { +				if (traceactions) +					fprintf(ftrace, +					    "send delayed dynamic update\n"); +				(void) gettimeofday(&now, +					    (struct timezone *)NULL); +				toall(supply, RTS_CHANGED, +				    (struct interface *)NULL); +				lastbcast = now; +				needupdate = 0; +				nextbcast.tv_sec = 0; +			} +			sigsetmask(omask); +			continue; +		} +		(void) gettimeofday(&now, (struct timezone *)NULL); +		omask = sigblock(sigmask(SIGALRM)); +#ifdef doesntwork +/* +printf("s %d, ibits %x index %d, mod %d, sh %x, or %x &ibits %x\n", +	s, +	ibits.fds_bits[0], +	(s)/(sizeof(fd_mask) * 8), +	((s) % (sizeof(fd_mask) * 8)), +	(1 << ((s) % (sizeof(fd_mask) * 8))), +	ibits.fds_bits[(s)/(sizeof(fd_mask) * 8)] & (1 << ((s) % (sizeof(fd_mask) * 8))), +	&ibits +	); +*/ +		if (FD_ISSET(s, &ibits)) +#else +		if (ibits.fds_bits[s/32] & (1 << s)) +#endif +			process(s); +		/* handle ICMP redirects */ +		sigsetmask(omask); +	} +} + +timevaladd(t1, t2) +	struct timeval *t1, *t2; +{ + +	t1->tv_sec += t2->tv_sec; +	if ((t1->tv_usec += t2->tv_usec) > 1000000) { +		t1->tv_sec++; +		t1->tv_usec -= 1000000; +	} +} + +timevalsub(t1, t2) +	struct timeval *t1, *t2; +{ + +	t1->tv_sec -= t2->tv_sec; +	if ((t1->tv_usec -= t2->tv_usec) < 0) { +		t1->tv_sec--; +		t1->tv_usec += 1000000; +	} +} + +process(fd) +	int fd; +{ +	struct sockaddr from; +	int fromlen, cc; +	union { +		char	buf[MAXPACKETSIZE+1]; +		struct	rip rip; +	} inbuf; + +	for (;;) { +		fromlen = sizeof (from); +		cc = recvfrom(fd, &inbuf, sizeof (inbuf), 0, &from, &fromlen); +		if (cc <= 0) { +			if (cc < 0 && errno != EWOULDBLOCK) +				perror("recvfrom"); +			break; +		} +		if (fromlen != sizeof (struct sockaddr_in)) +			break; +		rip_input(&from, &inbuf.rip, cc); +	} +} + +getsocket(domain, type, sin) +	int domain, type; +	struct sockaddr_in *sin; +{ +	int sock, on = 1; + +	if ((sock = socket(domain, type, 0)) < 0) { +		perror("socket"); +		syslog(LOG_ERR, "socket: %m"); +		return (-1); +	} +#ifdef SO_BROADCAST +	if (setsockopt(sock, SOL_SOCKET, SO_BROADCAST, &on, sizeof (on)) < 0) { +		syslog(LOG_ERR, "setsockopt SO_BROADCAST: %m"); +		close(sock); +		return (-1); +	} +#endif +#ifdef SO_RCVBUF +	for (on = bufspace; ; on -= 1024) { +		if (setsockopt(sock, SOL_SOCKET, SO_RCVBUF, +		    &on, sizeof (on)) == 0) +			break; +		if (on <= 8*1024) { +			syslog(LOG_ERR, "setsockopt SO_RCVBUF: %m"); +			break; +		} +	} +	if (traceactions) +		fprintf(ftrace, "recv buf %d\n", on); +#endif +	if (bind(sock, (struct sockaddr *)sin, sizeof (*sin)) < 0) { +		perror("bind"); +		syslog(LOG_ERR, "bind: %m"); +		close(sock); +		return (-1); +	} +	if (fcntl(sock, F_SETFL, O_NONBLOCK) == -1) +		syslog(LOG_ERR, "fcntl O_NONBLOCK: %m\n"); +	return (sock); +} diff --git a/usr.sbin/routed/output.c b/usr.sbin/routed/output.c new file mode 100644 index 000000000000..528f7fc038e4 --- /dev/null +++ b/usr.sbin/routed/output.c @@ -0,0 +1,172 @@ +/* + * Copyright (c) 1983, 1988, 1993 + *	The Regents of the University of California.  All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + *    notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + *    notice, this list of conditions and the following disclaimer in the + *    documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + *    must display the following acknowledgement: + *	This product includes software developed by the University of + *	California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + *    may be used to endorse or promote products derived from this software + *    without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char sccsid[] = "@(#)output.c	8.1 (Berkeley) 6/5/93"; +#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, rtstate, skipif) +	int (*f)(); +	int rtstate; +	struct interface *skipif; +{ +	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 || ifp == skipif) +			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, rtstate); +	} +} + +/* + * Output a preformed packet. + */ +/*ARGSUSED*/ +sndmsg(dst, flags, ifp, rtstate) +	struct sockaddr *dst; +	int flags; +	struct interface *ifp; +	int rtstate; +{ + +	(*afswitch[dst->sa_family].af_output)(s, 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, rtstate) +	struct sockaddr *dst; +	int flags; +	register struct interface *ifp; +	int rtstate; +{ +	register struct rt_entry *rt; +	register struct netinfo *n = msg->rip_nets; +	register struct rthash *rh; +	struct rthash *base = hosthash; +	int doinghost = 1, size; +	int (*output)() = afswitch[dst->sa_family].af_output; +	int (*sendroute)() = afswitch[dst->sa_family].af_sendroute; +	int npackets = 0; + +	msg->rip_cmd = RIPCMD_RESPONSE; +	msg->rip_vers = RIPVERSION; +	bzero(msg->rip_res1, sizeof(msg->rip_res1)); +again: +	for (rh = base; rh < &base[ROUTEHASHSIZ]; rh++) +	for (rt = rh->rt_forw; rt != (struct rt_entry *)rh; rt = rt->rt_forw) { +		/* +		 * Don't resend the information on the network +		 * from which it was received (unless sending +		 * in response to a query). +		 */ +		if (ifp && rt->rt_ifp == ifp && +		    (rt->rt_state & RTS_INTERFACE) == 0) +			continue; +		if (rt->rt_state & RTS_EXTERNAL) +			continue; +		/* +		 * For dynamic updates, limit update to routes +		 * with the specified state. +		 */ +		if (rtstate && (rt->rt_state & rtstate) == 0) +			continue; +		/* +		 * Limit the spread of subnet information +		 * to those who are interested. +		 */ +		if (doinghost == 0 && rt->rt_state & RTS_SUBNET) { +			if (rt->rt_dst.sa_family != dst->sa_family) +				continue; +			if ((*sendroute)(rt, dst) == 0) +				continue; +		} +		size = (char *)n - packet; +		if (size > MAXPACKETSIZE - sizeof (struct netinfo)) { +			TRACE_OUTPUT(ifp, dst, size); +			(*output)(s, flags, dst, size); +			/* +			 * If only sending to ourselves, +			 * one packet is enough to monitor interface. +			 */ +			if (ifp && (ifp->int_flags & +			   (IFF_BROADCAST | IFF_POINTOPOINT | IFF_REMOTE)) == 0) +				return; +			n = msg->rip_nets; +			npackets++; +		} +		n->rip_dst = rt->rt_dst; +#if BSD < 198810 +		if (sizeof(n->rip_dst.sa_family) > 1)	/* XXX */ +		n->rip_dst.sa_family = htons(n->rip_dst.sa_family); +#else +#define osa(x) ((struct osockaddr *)(&(x))) +		osa(n->rip_dst)->sa_family = htons(n->rip_dst.sa_family); +#endif +		n->rip_metric = htonl(rt->rt_metric); +		n++; +	} +	if (doinghost) { +		doinghost = 0; +		base = nethash; +		goto again; +	} +	if (n != msg->rip_nets || (npackets == 0 && rtstate == 0)) { +		size = (char *)n - packet; +		TRACE_OUTPUT(ifp, dst, size); +		(*output)(s, flags, dst, size); +	} +} diff --git a/usr.sbin/routed/pathnames.h b/usr.sbin/routed/pathnames.h new file mode 100644 index 000000000000..461d82bfac4d --- /dev/null +++ b/usr.sbin/routed/pathnames.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) 1989, 1993 + *	The Regents of the University of California.  All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + *    notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + *    notice, this list of conditions and the following disclaimer in the + *    documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + *    must display the following acknowledgement: + *	This product includes software developed by the University of + *	California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + *    may be used to endorse or promote products derived from this software + *    without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + *	@(#)pathnames.h	8.1 (Berkeley) 6/5/93 + */ + +#include <paths.h> + +#define	_PATH_GATEWAYS	"/etc/gateways" diff --git a/usr.sbin/routed/query/Makefile b/usr.sbin/routed/query/Makefile new file mode 100644 index 000000000000..0e7d1cdcc436 --- /dev/null +++ b/usr.sbin/routed/query/Makefile @@ -0,0 +1,7 @@ +#	@(#)Makefile	8.1 (Berkeley) 6/5/93 + +PROG=	query +NOMAN=	noman + +.include "../../Makefile.inc" +.include <bsd.prog.mk> diff --git a/usr.sbin/routed/query/query.c b/usr.sbin/routed/query/query.c new file mode 100644 index 000000000000..a80038815544 --- /dev/null +++ b/usr.sbin/routed/query/query.c @@ -0,0 +1,294 @@ +/*- + * Copyright (c) 1982, 1986, 1993 + *	The Regents of the University of California.  All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + *    notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + *    notice, this list of conditions and the following disclaimer in the + *    documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + *    must display the following acknowledgement: + *	This product includes software developed by the University of + *	California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + *    may be used to endorse or promote products derived from this software + *    without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char copyright[] = +"@(#) Copyright (c) 1982, 1986, 1993\n\ +	The Regents of the University of California.  All rights reserved.\n"; +#endif /* not lint */ + +#ifndef lint +static char sccsid[] = "@(#)query.c	8.1 (Berkeley) 6/5/93"; +#endif /* not lint */ + +#include <sys/param.h> +#include <sys/protosw.h> +#include <sys/socket.h> +#include <sys/time.h> +#include <signal.h> +#include <netinet/in.h> +#include <protocols/routed.h> +#include <arpa/inet.h> +#include <netdb.h> +#include <errno.h> +#include <unistd.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#define	WTIME	5		/* Time to wait for all responses */ +#define	STIME	500000		/* usec to wait for another response */ + +int	s; +int	timedout; +void	timeout(); +char	packet[MAXPACKETSIZE]; +int	nflag; + +main(argc, argv) +	int argc; +	char *argv[]; +{ +	extern char *optarg; +	extern int optind; +	int ch, cc, count, bits; +	struct sockaddr from; +	struct sigaction sigact; +	int fromlen = sizeof(from), size = 32*1024; +	struct timeval shorttime; + +	while ((ch = getopt(argc, argv, "n")) != EOF) +		switch (ch) { +		case 'n': +			nflag++; +			break; +		case '?': +		default: +			goto usage; +		} +	argv += optind; + +	if (!*argv) { +usage:		printf("usage: query [-n] hosts...\n"); +		exit(1); +	} + +	s = socket(AF_INET, SOCK_DGRAM, 0); +	if (s < 0) { +		perror("socket"); +		exit(2); +	} +	if (setsockopt(s, SOL_SOCKET, SO_RCVBUF, &size, sizeof(size)) < 0) +		perror("setsockopt SO_RCVBUF"); + +	while (*argv) { +		query(*argv++); +		count++; +	} + +	/* +	 * Listen for returning packets; +	 * may be more than one packet per host. +	 */ +	bits = 1 << s; +	bzero(&shorttime, sizeof(shorttime)); +	shorttime.tv_usec = STIME; +	bzero(&sigact, sizeof(sigact)); +	sigact.sa_handler = timeout; +	/*sigact.sa_flags = 0;		/* no restart */ +	if (sigaction(SIGALRM, &sigact, (struct sigaction *)NULL) == -1) +		perror("sigaction"); +	alarm(WTIME); +	while ((count > 0 && !timedout) || +	    select(20, (fd_set *)&bits, NULL, NULL, &shorttime) > 0) { +		cc = recvfrom(s, packet, sizeof (packet), 0, +		  &from, &fromlen); +		if (cc <= 0) { +			if (cc < 0) { +				if (errno == EINTR) +					continue; +				perror("recvfrom"); +				(void) close(s); +				exit(1); +			} +			continue; +		} +		rip_input(&from, cc); +		count--; +	} +	exit (count > 0 ? count : 0); +} + +query(host) +	char *host; +{ +	struct sockaddr_in router; +	register struct rip *msg = (struct rip *)packet; +	struct hostent *hp; +	struct servent *sp; + +	bzero((char *)&router, sizeof (router)); +	router.sin_family = AF_INET; +	router.sin_addr.s_addr = inet_addr(host); +	if (router.sin_addr.s_addr == -1) { +		hp = gethostbyname(host); +		if (hp == NULL) { +			fprintf(stderr, "query: %s: ", host); +			herror((char *)NULL); +			exit(1); +		} +		bcopy(hp->h_addr, &router.sin_addr, hp->h_length); +	} +	sp = getservbyname("router", "udp"); +	if (sp == 0) { +		printf("udp/router: service unknown\n"); +		exit(1); +	} +	router.sin_port = sp->s_port; +	msg->rip_cmd = RIPCMD_REQUEST; +	msg->rip_vers = RIPVERSION; +	msg->rip_nets[0].rip_dst.sa_family = htons(AF_UNSPEC); +	msg->rip_nets[0].rip_metric = htonl(HOPCNT_INFINITY); +	if (sendto(s, packet, sizeof (struct rip), 0, +	  (struct sockaddr *)&router, sizeof(router)) < 0) +		perror(host); +} + +/* + * Handle an incoming routing packet. + */ +rip_input(from, size) +	struct sockaddr_in *from; +	int size; +{ +	register struct rip *msg = (struct rip *)packet; +	register struct netinfo *n; +	char *name; +	int lna, net, subnet; +	struct hostent *hp; +	struct netent *np; + +	if (msg->rip_cmd != RIPCMD_RESPONSE) +		return; +	printf("%d bytes from ", size); +	if (nflag) +		printf("%s:\n", inet_ntoa(from->sin_addr)); +	else { +		hp = gethostbyaddr((char *)&from->sin_addr, +		    sizeof (struct in_addr), AF_INET); +		name = hp == 0 ? "???" : hp->h_name; +		printf("%s(%s):\n", name, inet_ntoa(from->sin_addr)); +	} +	size -= sizeof (int); +	n = msg->rip_nets; +	while (size > 0) { +	    if (size < sizeof (struct netinfo)) +		    break; +	    if (msg->rip_vers > 0) { +		    n->rip_dst.sa_family = +			    ntohs(n->rip_dst.sa_family); +		    n->rip_metric = ntohl(n->rip_metric); +	    } +	    switch (n->rip_dst.sa_family) { + +	    case AF_INET: +		{ register struct sockaddr_in *sin; + +		sin = (struct sockaddr_in *)&n->rip_dst; +		net = inet_netof(sin->sin_addr); +		subnet = inet_subnetof(sin->sin_addr); +		lna = inet_lnaof(sin->sin_addr); +		name = "???"; +		if (!nflag) { +			if (sin->sin_addr.s_addr == 0) +				name = "default"; +			else if (lna == INADDR_ANY) { +				np = getnetbyaddr(net, AF_INET); +				if (np) +					name = np->n_name; +				else if (net == 0) +					name = "default"; +			} else if ((lna & 0xff) == 0 && +			    (np = getnetbyaddr(subnet, AF_INET))) { +				struct in_addr subnaddr, inet_makeaddr(); + +				subnaddr = inet_makeaddr(subnet, INADDR_ANY); +				if (bcmp(&sin->sin_addr, &subnaddr, +				    sizeof(subnaddr)) == 0) +					name = np->n_name; +				else +					goto host; +			} else { +	host: +				hp = gethostbyaddr((char *)&sin->sin_addr, +				    sizeof (struct in_addr), AF_INET); +				if (hp) +					name = hp->h_name; +			} +			printf("\t%-17s metric %2d name %s\n", +				inet_ntoa(sin->sin_addr), n->rip_metric, name); +		} else +			printf("\t%-17s metric %2d\n", +				inet_ntoa(sin->sin_addr), n->rip_metric); +		break; +		} + +	    default: +		{ u_short *p = (u_short *)n->rip_dst.sa_data; + +		printf("\t(af %d) %x %x %x %x %x %x %x, metric %d\n", +		    p[0], p[1], p[2], p[3], p[4], p[5], p[6], +		    n->rip_dst.sa_family, +		    n->rip_metric); +		break; +		} +			 +	    } +	    size -= sizeof (struct netinfo), n++; +	} +} + +void +timeout() +{ +	timedout = 1; +} + +/* + * Return the possible subnetwork number from an internet address. + * SHOULD FIND OUT WHETHER THIS IS A LOCAL NETWORK BEFORE LOOKING + * INSIDE OF THE HOST PART.  We can only believe this if we have other + * information (e.g., we can find a name for this number). + */ +inet_subnetof(in) +	struct in_addr in; +{ +	register u_long i = ntohl(in.s_addr); + +	if (IN_CLASSA(i)) +		return ((i & IN_CLASSB_NET) >> IN_CLASSB_NSHIFT); +	else if (IN_CLASSB(i)) +		return ((i & IN_CLASSC_NET) >> IN_CLASSC_NSHIFT); +	else +		return ((i & 0xffffffc0) >> 28); +} diff --git a/usr.sbin/routed/routed.8 b/usr.sbin/routed/routed.8 new file mode 100644 index 000000000000..8d9ea20e00b2 --- /dev/null +++ b/usr.sbin/routed/routed.8 @@ -0,0 +1,358 @@ +.\" Copyright (c) 1983, 1991, 1993 +.\"	The Regents of the University of California.  All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\"    notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\"    notice, this list of conditions and the following disclaimer in the +.\"    documentation and/or other materials provided with the distribution. +.\" 3. 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. +.\" +.\"     @(#)routed.8	8.2 (Berkeley) 12/11/93 +.\" +.Dd December 11, 1993 +.Dt ROUTED 8 +.Os BSD 4.2 +.Sh NAME +.Nm routed +.Nd network routing daemon +.Sh SYNOPSIS +.Nm routed +.Op Fl d +.Op Fl g +.Op Fl q +.Op Fl s +.Op Fl t +.Op Ar logfile +.Sh DESCRIPTION +.Nm Routed +is invoked at boot time to manage the network routing tables. +The routing daemon uses a variant of the Xerox NS Routing +Information Protocol in maintaining up to date kernel routing +table entries. +It used a generalized protocol capable of use with multiple +address types, but is currently used only for Internet routing +within a cluster of networks. +.Pp +In normal operation +.Nm routed +listens on the +.Xr udp 4 +socket for the +.Xr route 8 +service (see +.Xr services 5 ) +for routing information packets.  If the host is an +internetwork router, it periodically supplies copies +of its routing tables to any directly connected hosts +and networks. +.Pp +When +.Nm routed +is started, it uses the +.Dv SIOCGIFCONF +.Xr ioctl 2 +to find those +directly connected interfaces configured into the +system and marked ``up'' (the software loopback interface +is ignored).  If multiple interfaces +are present, it is assumed that the host will forward packets +between networks. +.Nm Routed +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 routed +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 ``hop count'' metric (a count of 16, or greater, is +considered ``infinite'').  The metric associated with each +route returned provides a metric +.Em relative to the sender . +.Pp +.Em Response +packets received by +.Nm routed +are used to update the routing tables if one of the following +conditions is satisfied: +.Bl -enum +.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 routed +records the change in its internal tables and updates the kernel +routing table. +The change is reflected in the next +.Em response +packet sent. +.Pp +In addition to processing incoming packets, +.Nm routed +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 +throughout the local internet. +.Pp +Hosts acting as internetwork routers gratuitously supply their +routing tables every 30 seconds to all directly connected hosts +and networks. +The response is sent to the broadcast address on nets capable of that function, +to the destination address on point-to-point links, and to the router's +own address on other networks. +The normal routing tables are bypassed when sending gratuitous responses. +The reception of responses on each network is used to determine that the +network and interface are functioning correctly. +If no response is received on an interface, another route may be chosen +to route around the interface, or the route may be dropped if no alternative +is available. +.Pp +Options supported by +.Nm routed : +.Bl -tag -width Ds +.It Fl d +Enable additional debugging information to be logged, +such as bad packets received. +.It Fl g +This flag is used on internetwork routers to offer a route +to the ``default'' destination. +This is typically used on a gateway to the Internet, +or on a gateway that uses another routing protocol whose routes +are not reported to other local routers. +.It Fl s +Supplying this +option forces  +.Nm routed +to supply routing information whether it is acting as an internetwork +router or not. +This is the default if multiple network interfaces are present, +or if a point-to-point link is in use. +.It Fl q +This +is the opposite of the +.Fl s +option. +.It Fl t +If the +.Fl t +option is specified, all packets sent or received are +printed on the standard output.  In addition, +.Nm routed +will not divorce itself from the controlling terminal +so that interrupts from the keyboard will kill the process. +.El +.Pp +Any other argument supplied is interpreted as the name +of file in which  +.Nm routed Ns \'s +actions should be logged.  This log contains information +about any changes to the routing tables and, if not tracing all packets, +a history of recent messages sent and received which are related to +the changed route. +.Pp +In addition to the facilities described above,  +.Nm routed +supports the notion of ``distant'' +.Em passive +and  +.Em active +gateways.  When  +.Nm routed +is started up, it reads the file +.Pa /etc/gateways +to find gateways which may not be located using +only information from the +.Dv SIOGIFCONF +.Xr ioctl 2 . +Gateways specified in this manner should be marked passive +if they are not expected to exchange routing information, +while gateways marked active +should be willing to exchange routing information (i.e. +they should have a +.Nm routed +process running on the machine). +Routes through passive gateways are installed in the +kernel's routing tables once upon startup. +Such routes are not included in +any routing information transmitted. +Active gateways are treated equally to network +interfaces.  Routing information is distributed +to the gateway and if no routing information is +received for a period of time, the associated +route is deleted. +Gateways marked +.Em external +are also passive, but are not placed in the kernel +routing table nor are they included in routing updates. +The function of external entries is to inform +.Nm routed +that another routing process +will install such a route, and that alternate routes to that destination +should not be installed. +Such entries are only required when both routers may learn of routes +to the same destination. +.Pp +The  +.Pa /etc/gateways +is comprised of a series of lines, each in +the following format: +.Bd -ragged +.Pf < Cm net No \&| +.Cm host Ns > +.Ar name1 +.Cm gateway +.Ar name2 +.Cm metric +.Ar value +.Pf < Cm passive No \&| +.Cm active No \&| +.Cm external Ns > +.Ed +.Pp +The  +.Cm net +or +.Cm host +keyword indicates if the route is to a network or specific host. +.Pp +.Ar Name1 +is the name of the destination network or host.  This may be a +symbolic name located in +.Pa /etc/networks +or +.Pa /etc/hosts +(or, if started after +.Xr named 8 , +known to the name server),  +or an Internet address specified in ``dot'' notation; see +.Xr inet 3 . +.Pp +.Ar Name2 +is the name or address of the gateway to which messages should +be forwarded. +.Pp +.Ar Value +is a metric indicating the hop count to the destination host +or network. +.Pp +One of the keywords +.Cm passive , +.Cm active +or +.Cm external +indicates if the gateway should be treated as  +.Em passive +or +.Em active +(as described above), +or whether the gateway is +.Em external +to the scope of the +.Nm routed +protocol. +.Pp +Internetwork routers that are directly attached to the Arpanet or Milnet +should use the Exterior Gateway Protocol +.Pq Tn EGP +to gather routing information +rather then using a static routing table of passive gateways. +.Tn EGP +is required in order to provide routes for local networks to the rest +of the Internet system. +.Sh FILES +.Bl -tag -width /etc/gateways -compact +.It Pa /etc/gateways +for distant gateways +.El +.Sh SEE ALSO +.Xr udp 4 , +.Xr icmp 4 , +.Xr XNSrouted 8 , +.Xr htable 8 +.Rs +.%T Internet Transport Protocols +.%R XSIS 028112 +.%Q Xerox System Integration Standard +.Re +.Sh BUGS +The kernel's routing tables may not correspond to those of +.Nm routed +when redirects change or add routes. +.Nm Routed +should note any redirects received by reading +the +.Tn ICMP +packets received via a raw socket. +.Pp +.Nm Routed +should incorporate other routing protocols, +such as Xerox +.Tn \&NS +.Pq Xr XNSrouted 8 +and +.Tn EGP . +Using separate processes for each requires configuration options +to avoid redundant or competing routes. +.Pp +.Nm Routed +should listen to intelligent interfaces, such as an +.Tn IMP , +to gather more information. +It does not always detect unidirectional failures in network interfaces +(e.g., when the output side fails). +.Sh HISTORY +The +.Nm +command appeared in +.Bx 4.2 . diff --git a/usr.sbin/routed/startup.c b/usr.sbin/routed/startup.c new file mode 100644 index 000000000000..e87d9e9b71c7 --- /dev/null +++ b/usr.sbin/routed/startup.c @@ -0,0 +1,515 @@ +/* + * Copyright (c) 1983, 1988, 1993 + *	The Regents of the University of California.  All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + *    notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + *    notice, this list of conditions and the following disclaimer in the + *    documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + *    must display the following acknowledgement: + *	This product includes software developed by the University of + *	California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + *    may be used to endorse or promote products derived from this software + *    without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char sccsid[] = "@(#)startup.c	8.1 (Berkeley) 6/5/93"; +#endif /* not lint */ + +/* + * Routing Table Management Daemon + */ +#include "defs.h" +#include <sys/ioctl.h> +#include <sys/sysctl.h> +#include <net/if.h> +#include <net/if_dl.h> +#include <syslog.h> +#include <stdlib.h> +#include "pathnames.h" + +struct	interface *ifnet; +struct	interface **ifnext = &ifnet; +int	lookforinterfaces = 1; +int	externalinterfaces = 0;		/* # of remote and local interfaces */ +int	foundloopback;			/* valid flag for loopaddr */ +struct	sockaddr loopaddr;		/* our address on loopback */ + + +void +quit(s) +	char *s; +{ +	extern int errno; +	int sverrno = errno; + +	(void) fprintf(stderr, "route: "); +	if (s) +		(void) fprintf(stderr, "%s: ", s); +	(void) fprintf(stderr, "%s\n", strerror(sverrno)); +	exit(1); +	/* NOTREACHED */ +} + +struct rt_addrinfo info; +/* Sleazy use of local variables throughout file, warning!!!! */ +#define netmask	info.rti_info[RTAX_NETMASK] +#define ifaaddr	info.rti_info[RTAX_IFA] +#define brdaddr	info.rti_info[RTAX_BRD] + +#define ROUNDUP(a) \ +	((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long)) +#define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len)) + +void +rt_xaddrs(cp, cplim, rtinfo) +	register caddr_t cp, cplim; +	register struct rt_addrinfo *rtinfo; +{ +	register struct sockaddr *sa; +	register int i; + +	bzero(rtinfo->rti_info, sizeof(rtinfo->rti_info)); +	for (i = 0; (i < RTAX_MAX) && (cp < cplim); i++) { +		if ((rtinfo->rti_addrs & (1 << i)) == 0) +			continue; +		rtinfo->rti_info[i] = sa = (struct sockaddr *)cp; +		ADVANCE(cp, sa); +	} +} + +/* + * 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; +	size_t needed; +	int mib[6], no_ipaddr = 0, flags = 0; +	char *buf, *cplim, *cp; +	register struct if_msghdr *ifm; +	register struct ifa_msghdr *ifam; +	struct sockaddr_dl *sdl; +        struct sockaddr_in *sin; +	u_long i; + +        mib[0] = CTL_NET; +        mib[1] = PF_ROUTE; +        mib[2] = 0; +        mib[3] = AF_INET; +        mib[4] = NET_RT_IFLIST; +        mib[5] = 0; +        if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0) +                quit("route-sysctl-estimate"); +	if ((buf = malloc(needed)) == NULL) +		quit("malloc"); +        if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0) +		quit("actual retrieval of interface table"); +	lookforinterfaces = 0; +	cplim = buf + needed; +	for (cp = buf; cp < cplim; cp += ifm->ifm_msglen) { +		ifm = (struct if_msghdr *)cp; +		if (ifm->ifm_type == RTM_IFINFO) { +			bzero(&ifs, sizeof(ifs)); +			ifs.int_flags = flags = (0xffff & ifm->ifm_flags) | IFF_INTERFACE; +			if ((flags & IFF_UP) == 0 || no_ipaddr) +				lookforinterfaces = 1; +			sdl = (struct sockaddr_dl *) (ifm + 1); +			sdl->sdl_data[sdl->sdl_nlen] = 0; +			no_ipaddr = 1; +			continue; +		} +		if (ifm->ifm_type != RTM_NEWADDR) +			quit("ifinit: out of sync"); +		if ((flags & IFF_UP) == 0) +			continue; +		ifam = (struct ifa_msghdr *)ifm; +		info.rti_addrs = ifam->ifam_addrs; +		rt_xaddrs((char *)(ifam + 1), cp + ifam->ifam_msglen, &info); +		if (ifaaddr == 0) { +			syslog(LOG_ERR, "%s: (get addr)", sdl->sdl_data); +			continue; +		} +		ifs.int_addr = *ifaaddr; +		if (ifs.int_addr.sa_family != AF_INET) +			continue; +		no_ipaddr = 0; +		if (ifs.int_flags & IFF_POINTOPOINT) { +			if (brdaddr == 0) { +				syslog(LOG_ERR, "%s: (get dstaddr)", +					sdl->sdl_data); +				continue; +			} +			if (brdaddr->sa_family == AF_UNSPEC) { +				lookforinterfaces = 1; +				continue; +			} +			ifs.int_dstaddr = *brdaddr; +		} +		/* +		 * already known to us? +		 * This allows multiple point-to-point links +		 * to share a source address (possibly with one +		 * other link), but assumes that there will not be +		 * multiple links with the same destination address. +		 */ +		if (ifs.int_flags & IFF_POINTOPOINT) { +			if (if_ifwithdstaddr(&ifs.int_dstaddr)) +				continue; +		} else if (if_ifwithaddr(&ifs.int_addr)) +			continue; +		if (ifs.int_flags & IFF_LOOPBACK) { +			ifs.int_flags |= IFF_PASSIVE; +			foundloopback = 1; +			loopaddr = ifs.int_addr; +			for (ifp = ifnet; ifp; ifp = ifp->int_next) +			    if (ifp->int_flags & IFF_POINTOPOINT) +				add_ptopt_localrt(ifp); +		} +		if (ifs.int_flags & IFF_BROADCAST) { +			if (brdaddr == 0) { +				syslog(LOG_ERR, "%s: (get broadaddr)", +					sdl->sdl_data); +				continue; +			} +			ifs.int_dstaddr = *brdaddr; +		} +		/* +		 * Use a minimum metric of one; +		 * treat the interface metric (default 0) +		 * as an increment to the hop count of one. +		 */ +		ifs.int_metric = ifam->ifam_metric + 1; +		if (netmask == 0) { +				syslog(LOG_ERR, "%s: (get netmask)", +					sdl->sdl_data); +				continue; +		} +		sin = (struct sockaddr_in *)netmask; +		ifs.int_subnetmask = ntohl(sin->sin_addr.s_addr); +		sin = (struct sockaddr_in *)&ifs.int_addr; +		i = ntohl(sin->sin_addr.s_addr); +		if (IN_CLASSA(i)) +			ifs.int_netmask = IN_CLASSA_NET; +		else if (IN_CLASSB(i)) +			ifs.int_netmask = IN_CLASSB_NET; +		else +			ifs.int_netmask = IN_CLASSC_NET; +		ifs.int_net = i & ifs.int_netmask; +		ifs.int_subnet = i & ifs.int_subnetmask; +		if (ifs.int_subnetmask != ifs.int_netmask) +			ifs.int_flags |= IFF_SUBNET; +		ifp = (struct interface *) +			malloc(sdl->sdl_nlen + 1 + sizeof(ifs)); +		if (ifp == 0) { +			printf("routed: out of memory\n"); +			lookforinterfaces = 1; +			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_LOOPBACK) == 0 && +		    ((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 = (char *)(ifp + 1); +		strcpy(ifp->int_name, sdl->sdl_data); +		*ifnext = ifp; +		ifnext = &ifp->int_next; +		traceinit(ifp); +		addrouteforif(ifp); +	} +	if (externalinterfaces > 1 && supplier < 0) +		supplier = 1; +	free(buf); +} + +/* + * Add route for interface if not currently installed. + * Create route to other end if a point-to-point link, + * otherwise a route to this (sub)network. + * INTERNET SPECIFIC. + */ +addrouteforif(ifp) +	register struct interface *ifp; +{ +	struct sockaddr_in net; +	struct sockaddr *dst; +	int state; +	register struct rt_entry *rt; + +	if (ifp->int_flags & IFF_POINTOPOINT) +		dst = &ifp->int_dstaddr; +	else { +		bzero((char *)&net, sizeof (net)); +		net.sin_family = AF_INET; +		net.sin_addr = inet_makeaddr(ifp->int_subnet, INADDR_ANY); +		dst = (struct sockaddr *)&net; +	} +	rt = rtfind(dst); +	if (rt && +	    (rt->rt_state & (RTS_INTERFACE | RTS_INTERNAL)) == RTS_INTERFACE) +		return; +	if (rt) +		rtdelete(rt); +	/* +	 * If interface on subnetted network, +	 * install route to network as well. +	 * This is meant for external viewers. +	 */ +	if ((ifp->int_flags & (IFF_SUBNET|IFF_POINTOPOINT)) == IFF_SUBNET) { +		struct in_addr subnet; + +		subnet = net.sin_addr; +		net.sin_addr = inet_makeaddr(ifp->int_net, INADDR_ANY); +		rt = rtfind(dst); +		if (rt == 0) +			rtadd(dst, &ifp->int_addr, ifp->int_metric, +			    ((ifp->int_flags & (IFF_INTERFACE|IFF_REMOTE)) | +			    RTS_PASSIVE | RTS_INTERNAL | RTS_SUBNET)); +		else if ((rt->rt_state & (RTS_INTERNAL|RTS_SUBNET)) ==  +		    (RTS_INTERNAL|RTS_SUBNET) && +		    ifp->int_metric < rt->rt_metric) +			rtchange(rt, &rt->rt_router, ifp->int_metric); +		net.sin_addr = subnet; +	} +	if (ifp->int_transitions++ > 0) +		syslog(LOG_ERR, "re-installing interface %s", ifp->int_name); +	state = ifp->int_flags & +	    (IFF_INTERFACE | IFF_PASSIVE | IFF_REMOTE | IFF_SUBNET); +	if (ifp->int_flags & IFF_POINTOPOINT && +	    (ntohl(((struct sockaddr_in *)&ifp->int_dstaddr)->sin_addr.s_addr) & +	    ifp->int_netmask) != ifp->int_net) +		state &= ~RTS_SUBNET; +	if (ifp->int_flags & IFF_LOOPBACK) +		state |= RTS_EXTERNAL; +	rtadd(dst, &ifp->int_addr, ifp->int_metric, state); +	if (ifp->int_flags & IFF_POINTOPOINT && foundloopback) +		add_ptopt_localrt(ifp); +} + +/* + * Add route to local end of point-to-point using loopback. + * If a route to this network is being sent to neighbors on other nets, + * mark this route as subnet so we don't have to propagate it too. + */ +add_ptopt_localrt(ifp) +	register struct interface *ifp; +{ +	struct rt_entry *rt; +	struct sockaddr *dst; +	struct sockaddr_in net; +	int state; + +	state = RTS_INTERFACE | RTS_PASSIVE; + +	/* look for route to logical network */ +	bzero((char *)&net, sizeof (net)); +	net.sin_family = AF_INET; +	net.sin_addr = inet_makeaddr(ifp->int_net, INADDR_ANY); +	dst = (struct sockaddr *)&net; +	rt = rtfind(dst); +	if (rt && rt->rt_state & RTS_INTERNAL) +		state |= RTS_SUBNET; + +	dst = &ifp->int_addr; +	if (rt = rtfind(dst)) { +		if (rt && rt->rt_state & RTS_INTERFACE) +			return; +		rtdelete(rt); +	} +	rtadd(dst, &loopaddr, 1, state); +} + +/* + * As a concession to the ARPANET we read a list of gateways + * from /etc/gateways and add them to our tables.  This file + * exists at each ARPANET gateway and indicates a set of ``remote'' + * gateways (i.e. a gateway which we can't immediately determine + * if it's present or not as we can do for those directly connected + * at the hardware level).  If a gateway is marked ``passive'' + * in the file, then we assume it doesn't have a routing process + * of our design and simply assume it's always present.  Those + * not marked passive are treated as if they were directly + * connected -- they're added into the interface list so we'll + * send them routing updates. + * + * PASSIVE ENTRIES AREN'T NEEDED OR USED ON GATEWAYS RUNNING EGP. + */ +gwkludge() +{ +	struct sockaddr_in dst, gate; +	FILE *fp; +	char *type, *dname, *gname, *qual, buf[BUFSIZ]; +	struct interface *ifp; +	int metric, n; +	struct rt_entry route; + +	fp = fopen(_PATH_GATEWAYS, "r"); +	if (fp == NULL) +		return; +	qual = buf; +	dname = buf + 64; +	gname = buf + ((BUFSIZ - 64) / 3); +	type = buf + (((BUFSIZ - 64) * 2) / 3); +	bzero((char *)&dst, sizeof (dst)); +	bzero((char *)&gate, sizeof (gate)); +	bzero((char *)&route, sizeof(route)); +/* format: {net | host} XX gateway XX metric DD [passive | external]\n */ +#define	readentry(fp) \ +	fscanf((fp), "%s %s gateway %s metric %d %s\n", \ +		type, dname, gname, &metric, qual) +	for (;;) { +		if ((n = readentry(fp)) == EOF) +			break; +		if (!getnetorhostname(type, dname, &dst)) +			continue; +		if (!gethostnameornumber(gname, &gate)) +			continue; +		if (metric == 0)			/* XXX */ +			metric = 1; +		if (strcmp(qual, "passive") == 0) { +			/* +			 * Passive entries aren't placed in our tables, +			 * only the kernel's, so we don't copy all of the +			 * external routing information within a net. +			 * Internal machines should use the default +			 * route to a suitable gateway (like us). +			 */ +			route.rt_dst = *(struct sockaddr *) &dst; +			route.rt_router = *(struct sockaddr *) &gate; +			route.rt_flags = RTF_UP; +			if (strcmp(type, "host") == 0) +				route.rt_flags |= RTF_HOST; +			if (metric) +				route.rt_flags |= RTF_GATEWAY; +			(void) rtioctl(ADD, &route.rt_rt); +			continue; +		} +		if (strcmp(qual, "external") == 0) { +			/* +			 * Entries marked external are handled +			 * by other means, e.g. EGP, +			 * and are placed in our tables only +			 * to prevent overriding them +			 * with something else. +			 */ +			rtadd(&dst, &gate, metric, RTS_EXTERNAL|RTS_PASSIVE); +			continue; +		} +		/* assume no duplicate entries */ +		externalinterfaces++; +		ifp = (struct interface *)malloc(sizeof (*ifp)); +		bzero((char *)ifp, sizeof (*ifp)); +		ifp->int_flags = IFF_REMOTE; +		/* can't identify broadcast capability */ +		ifp->int_net = inet_netof(dst.sin_addr); +		if (strcmp(type, "host") == 0) { +			ifp->int_flags |= IFF_POINTOPOINT; +			ifp->int_dstaddr = *((struct sockaddr *)&dst); +		} +		ifp->int_addr = *((struct sockaddr *)&gate); +		ifp->int_metric = metric; +		ifp->int_next = ifnet; +		ifnet = ifp; +		addrouteforif(ifp); +	} +	fclose(fp); +} + +getnetorhostname(type, name, sin) +	char *type, *name; +	struct sockaddr_in *sin; +{ + +	if (strcmp(type, "net") == 0) { +		struct netent *np = getnetbyname(name); +		int n; + +		if (np == 0) +			n = inet_network(name); +		else { +			if (np->n_addrtype != AF_INET) +				return (0); +			n = np->n_net; +			/* +			 * getnetbyname returns right-adjusted value. +			 */ +			if (n < 128) +				n <<= IN_CLASSA_NSHIFT; +			else if (n < 65536) +				n <<= IN_CLASSB_NSHIFT; +			else +				n <<= IN_CLASSC_NSHIFT; +		} +		sin->sin_family = AF_INET; +		sin->sin_addr = inet_makeaddr(n, INADDR_ANY); +		return (1); +	} +	if (strcmp(type, "host") == 0) { +		struct hostent *hp = gethostbyname(name); + +		if (hp == 0) +			sin->sin_addr.s_addr = inet_addr(name); +		else { +			if (hp->h_addrtype != AF_INET) +				return (0); +			bcopy(hp->h_addr, &sin->sin_addr, hp->h_length); +		} +		sin->sin_family = AF_INET; +		return (1); +	} +	return (0); +} + +gethostnameornumber(name, sin) +	char *name; +	struct sockaddr_in *sin; +{ +	struct hostent *hp; + +	hp = gethostbyname(name); +	if (hp) { +		bcopy(hp->h_addr, &sin->sin_addr, hp->h_length); +		sin->sin_family = hp->h_addrtype; +		return (1); +	} +	sin->sin_addr.s_addr = inet_addr(name); +	sin->sin_family = AF_INET; +	return (sin->sin_addr.s_addr != -1); +} diff --git a/usr.sbin/routed/table.h b/usr.sbin/routed/table.h new file mode 100644 index 000000000000..01336f0681af --- /dev/null +++ b/usr.sbin/routed/table.h @@ -0,0 +1,108 @@ +/* + * Copyright (c) 1983, 1993 + *	The Regents of the University of California.  All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + *    notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + *    notice, this list of conditions and the following disclaimer in the + *    documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + *    must display the following acknowledgement: + *	This product includes software developed by the University of + *	California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + *    may be used to endorse or promote products derived from this software + *    without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + *	@(#)table.h	8.1 (Berkeley) 6/5/93 + */ + +/* + * 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 rtuentry { +			u_long	rtu_hash; +			struct	sockaddr rtu_dst; +			struct	sockaddr rtu_router; +			short	rtu_rtflags; /* used by rtioctl */ +			short	rtu_wasted[5]; +			int	rtu_flags; +			int	rtu_state; +			int	rtu_timer; +			int	rtu_metric; +			int	rtu_ifmetric; +			struct	interface *rtu_ifp; +		} rtu_entry; +	} rt_rtu; +}; + +#define	rt_rt		rt_rtu.rtu_entry		/* 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_ifmetric	rt_rtu.rtu_entry.rtu_ifmetric	/* cost of route if */ +#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_EXTERNAL	0x2		/* extern info, not installed or sent */ +#define	RTS_INTERNAL	0x4		/* internal route, not installed */ +#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 */ +#define	RTS_SUBNET	IFF_SUBNET	/* route is for network subnet */ + +/* + * Flags are same as kernel, with this addition for af_rtflags: + */ +#define	RTF_SUBNET	0x80000		/* pseudo: route to subnet */ + +struct	rthash nethash[ROUTEHASHSIZ]; +struct	rthash hosthash[ROUTEHASHSIZ]; +struct	rt_entry *rtlookup(); +struct	rt_entry *rtfind(); diff --git a/usr.sbin/routed/tables.c b/usr.sbin/routed/tables.c new file mode 100644 index 000000000000..ac837f80dffb --- /dev/null +++ b/usr.sbin/routed/tables.c @@ -0,0 +1,428 @@ +/* + * Copyright (c) 1983, 1988, 1993 + *	The Regents of the University of California.  All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + *    notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + *    notice, this list of conditions and the following disclaimer in the + *    documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + *    must display the following acknowledgement: + *	This product includes software developed by the University of + *	California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + *    may be used to endorse or promote products derived from this software + *    without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char sccsid[] = "@(#)tables.c	8.1 (Berkeley) 6/5/93"; +#endif /* not lint */ + +/* + * Routing Table Management Daemon + */ +#include "defs.h" +#include <sys/ioctl.h> +#include <errno.h> +#include <sys/syslog.h> + +#ifndef DEBUG +#define	DEBUG	0 +#endif + +#ifdef RTM_ADD +#define FIXLEN(s) {if ((s)->sa_len == 0) (s)->sa_len = sizeof *(s);} +#else +#define FIXLEN(s) { } +#endif + +int	install = !DEBUG;		/* if 1 call kernel */ + +/* + * 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); +} + +struct sockaddr wildcard;	/* zero valued cookie for wildcard searches */ + +/* + * 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; +	} +#ifdef notyet +	/* +	 * Check for wildcard gateway, by convention network 0. +	 */ +	if (dst != &wildcard) { +		dst = &wildcard, hash = 0; +		goto again; +	} +#endif +	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; + +	if (af >= af_max) +		return; +	(*afswitch[af].af_hash)(dst, &h); +	flags = (*afswitch[af].af_rtflags)(dst); +	/* +	 * Subnet flag isn't visible to kernel, move to state.	XXX +	 */ +	FIXLEN(dst); +	FIXLEN(gate); +	if (flags & RTF_SUBNET) { +		state |= RTS_SUBNET; +		flags &= ~RTF_SUBNET; +	} +	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_timer = 0; +	rt->rt_flags = RTF_UP | flags; +	rt->rt_state = state | RTS_CHANGED; +	rt->rt_ifp = if_ifwithdstaddr(&rt->rt_dst); +	if (rt->rt_ifp == 0) +		rt->rt_ifp = if_ifwithnet(&rt->rt_router); +	if ((state & RTS_INTERFACE) == 0) +		rt->rt_flags |= RTF_GATEWAY; +	rt->rt_metric = metric; +	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 ((rt->rt_state & (RTS_INTERNAL | RTS_EXTERNAL)) == 0 && +	    rtioctl(ADD, &rt->rt_rt) < 0) { +		if (errno != EEXIST && gate->sa_family < af_max) +			syslog(LOG_ERR, +			"adding route to net/host %s through gateway %s: %m\n", +			   (*afswitch[dst->sa_family].af_format)(dst), +			   (*afswitch[gate->sa_family].af_format)(gate)); +		perror("ADD ROUTE"); +		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 add = 0, delete = 0, newgateway = 0; +	struct rtuentry oldroute; + +	FIXLEN(gate); +	FIXLEN(&(rt->rt_router)); +	FIXLEN(&(rt->rt_dst)); +	if (!equal(&rt->rt_router, gate)) { +		newgateway++; +		TRACE_ACTION("CHANGE FROM ", rt); +	} else if (metric != rt->rt_metric) +		TRACE_NEWMETRIC(rt, metric); +	if ((rt->rt_state & RTS_INTERNAL) == 0) { +		/* +		 * If changing to different router, we need to add +		 * new route and delete old one if in the kernel. +		 * If the router is the same, we need to delete +		 * the route if has become unreachable, or re-add +		 * it if it had been unreachable. +		 */ +		if (newgateway) { +			add++; +			if (rt->rt_metric != HOPCNT_INFINITY) +				delete++; +		} else if (metric == HOPCNT_INFINITY) +			delete++; +		else if (rt->rt_metric == HOPCNT_INFINITY) +			add++; +	} +	if (delete) +		oldroute = rt->rt_rt; +	if ((rt->rt_state & RTS_INTERFACE) && delete) { +		rt->rt_state &= ~RTS_INTERFACE; +		rt->rt_flags |= RTF_GATEWAY; +		if (metric > rt->rt_metric && delete) +			syslog(LOG_ERR, "%s route to interface %s (timed out)", +			    add? "changing" : "deleting", +			    rt->rt_ifp ? rt->rt_ifp->int_name : "?"); +	} +	if (add) { +		rt->rt_router = *gate; +		rt->rt_ifp = if_ifwithdstaddr(&rt->rt_router); +		if (rt->rt_ifp == 0) +			rt->rt_ifp = if_ifwithnet(&rt->rt_router); +	} +	rt->rt_metric = metric; +	rt->rt_state |= RTS_CHANGED; +	if (newgateway) +		TRACE_ACTION("CHANGE TO   ", rt); +#ifndef RTM_ADD +	if (add && rtioctl(ADD, &rt->rt_rt) < 0) +		perror("ADD ROUTE"); +	if (delete && rtioctl(DELETE, &oldroute) < 0) +		perror("DELETE ROUTE"); +#else +	if (delete && !add) { +		if (rtioctl(DELETE, &oldroute) < 0) +			perror("DELETE ROUTE"); +	} else if (!delete && add) { +		if (rtioctl(ADD, &rt->rt_rt) < 0) +			perror("ADD ROUTE"); +	} else if (delete && add) { +		if (rtioctl(CHANGE, &rt->rt_rt) < 0) +			perror("CHANGE ROUTE"); +	} +#endif +} + +rtdelete(rt) +	struct rt_entry *rt; +{ + +	TRACE_ACTION("DELETE", rt); +	FIXLEN(&(rt->rt_router)); +	FIXLEN(&(rt->rt_dst)); +	if (rt->rt_metric < HOPCNT_INFINITY) { +	    if ((rt->rt_state & (RTS_INTERFACE|RTS_INTERNAL)) == RTS_INTERFACE) +		syslog(LOG_ERR, +		    "deleting route to interface %s? (timed out?)", +		    rt->rt_ifp->int_name); +	    if ((rt->rt_state & (RTS_INTERNAL | RTS_EXTERNAL)) == 0 && +					    rtioctl(DELETE, &rt->rt_rt) < 0) +		    perror("rtdelete"); +	} +	remque(rt); +	free((char *)rt); +} + +rtdeleteall(sig) +	int sig; +{ +	register struct rthash *rh; +	register struct rt_entry *rt; +	struct rthash *base = hosthash; +	int doinghost = 1; + +again: +	for (rh = base; rh < &base[ROUTEHASHSIZ]; rh++) { +		rt = rh->rt_forw; +		for (; rt != (struct rt_entry *)rh; rt = rt->rt_forw) { +			if (rt->rt_state & RTS_INTERFACE || +			    rt->rt_metric >= HOPCNT_INFINITY) +				continue; +			TRACE_ACTION("DELETE", rt); +			if ((rt->rt_state & (RTS_INTERNAL|RTS_EXTERNAL)) == 0 && +			    rtioctl(DELETE, &rt->rt_rt) < 0) +				perror("rtdeleteall"); +		} +	} +	if (doinghost) { +		doinghost = 0; +		base = nethash; +		goto again; +	} +	exit(sig); +} + +/* + * If we have an interface to the wide, wide world, + * add an entry for an Internet default route (wildcard) to the internal + * tables and advertise it.  This route is not added to the kernel routes, + * but this entry prevents us from listening to other people's defaults + * and installing them in the kernel here. + */ +rtdefault() +{ +	extern struct sockaddr inet_default; + +	rtadd(&inet_default, &inet_default, 1, +		RTS_CHANGED | RTS_PASSIVE | RTS_INTERNAL); +} + +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; +} + +rtioctl(action, ort) +	int action; +	struct rtuentry *ort; +{ +#ifndef RTM_ADD +	if (install == 0) +		return (errno = 0); +	ort->rtu_rtflags = ort->rtu_flags; +	switch (action) { + +	case ADD: +		return (ioctl(s, SIOCADDRT, (char *)ort)); + +	case DELETE: +		return (ioctl(s, SIOCDELRT, (char *)ort)); + +	default: +		return (-1); +	} +#else /* RTM_ADD */ +	struct { +		struct rt_msghdr w_rtm; +		struct sockaddr_in w_dst; +		struct sockaddr w_gate; +		struct sockaddr_in w_netmask; +	} w; +#define rtm w.w_rtm + +	bzero((char *)&w, sizeof(w)); +	rtm.rtm_msglen = sizeof(w); +	rtm.rtm_version = RTM_VERSION; +	rtm.rtm_type = (action == ADD ? RTM_ADD : +				(action == DELETE ? RTM_DELETE : RTM_CHANGE)); +#undef rt_dst +	rtm.rtm_flags = ort->rtu_flags; +	rtm.rtm_seq = ++seqno; +	rtm.rtm_addrs = RTA_DST|RTA_GATEWAY; +	bcopy((char *)&ort->rtu_dst, (char *)&w.w_dst, sizeof(w.w_dst)); +	bcopy((char *)&ort->rtu_router, (char *)&w.w_gate, sizeof(w.w_gate)); +	w.w_dst.sin_family = AF_INET; +	w.w_dst.sin_len = sizeof(w.w_dst); +	w.w_gate.sa_family = AF_INET; +	w.w_gate.sa_len = sizeof(w.w_gate); +	if (rtm.rtm_flags & RTF_HOST) { +		rtm.rtm_msglen -= sizeof(w.w_netmask); +	} else { +		register char *cp; +		int len; + +		rtm.rtm_addrs |= RTA_NETMASK; +		w.w_netmask.sin_addr.s_addr = +			inet_maskof(w.w_dst.sin_addr.s_addr); +		for (cp = (char *)(1 + &w.w_netmask.sin_addr); +				    --cp > (char *) &w.w_netmask; ) +			if (*cp) +				break; +		len = cp - (char *)&w.w_netmask; +		if (len) { +			len++; +			w.w_netmask.sin_len = len; +			len = 1 + ((len - 1) | (sizeof(long) - 1)); +		} else  +			len = sizeof(long); +		rtm.rtm_msglen -= (sizeof(w.w_netmask) - len); +	} +	errno = 0; +	return (install ? write(r, (char *)&w, rtm.rtm_msglen) : (errno = 0)); +#endif  /* RTM_ADD */ +} diff --git a/usr.sbin/routed/timer.c b/usr.sbin/routed/timer.c new file mode 100644 index 000000000000..643e2f5ef55f --- /dev/null +++ b/usr.sbin/routed/timer.c @@ -0,0 +1,127 @@ +/* + * Copyright (c) 1983, 1988, 1993 + *	The Regents of the University of California.  All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + *    notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + *    notice, this list of conditions and the following disclaimer in the + *    documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + *    must display the following acknowledgement: + *	This product includes software developed by the University of + *	California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + *    may be used to endorse or promote products derived from this software + *    without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char sccsid[] = "@(#)timer.c	8.1 (Berkeley) 6/5/93"; +#endif /* not lint */ + +/* + * Routing Table Management Daemon + */ +#include "defs.h" + +int	faketime; + +/* + * Timer routine.  Performs routing information supply + * duties and manages timers on routing table entries. + * Management of the RTS_CHANGED bit assumes that we broadcast + * each time called. + */ +void +timer() +{ +	register struct rthash *rh; +	register struct rt_entry *rt; +	struct rthash *base = hosthash; +	int doinghost = 1, timetobroadcast; +	extern int externalinterfaces; + +	(void) gettimeofday(&now, (struct timezone *)NULL); +	faketime += TIMER_RATE; +	if (lookforinterfaces && (faketime % CHECK_INTERVAL) == 0) +		ifinit(); +	timetobroadcast = supplier && (faketime % 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 any interface if we're +			 * not acting as supplier. +			 */ +			if (!(rt->rt_state & RTS_PASSIVE) && +			    (supplier || !(rt->rt_state & RTS_INTERFACE))) +				rt->rt_timer += TIMER_RATE; +			if (rt->rt_timer >= GARBAGE_TIME) { +				rt = rt->rt_back; +				rtdelete(rt->rt_forw); +				continue; +			} +			if (rt->rt_timer >= EXPIRE_TIME && +			    rt->rt_metric < HOPCNT_INFINITY) +				rtchange(rt, &rt->rt_router, HOPCNT_INFINITY); +			rt->rt_state &= ~RTS_CHANGED; +		} +	} +	if (doinghost) { +		doinghost = 0; +		base = nethash; +		goto again; +	} +	if (timetobroadcast) { +		toall(supply, 0, (struct interface *)NULL); +		lastbcast = now; +		lastfullupdate = now; +		needupdate = 0;		/* cancel any pending dynamic update */ +		nextbcast.tv_sec = 0; +	} +} + +/* + * On hangup, let everyone know we're going away. + */ +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, 0, (struct interface *)NULL); +	} +	exit(1); +} diff --git a/usr.sbin/routed/trace.c b/usr.sbin/routed/trace.c new file mode 100644 index 000000000000..f630001cbf35 --- /dev/null +++ b/usr.sbin/routed/trace.c @@ -0,0 +1,426 @@ +/* + * Copyright (c) 1983, 1988, 1993 + *	The Regents of the University of California.  All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + *    notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + *    notice, this list of conditions and the following disclaimer in the + *    documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + *    must display the following acknowledgement: + *	This product includes software developed by the University of + *	California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + *    may be used to endorse or promote products derived from this software + *    without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char sccsid[] = "@(#)trace.c	8.1 (Berkeley) 6/5/93"; +#endif /* not lint */ + +/* + * Routing Table Management Daemon + */ +#define	RIPCMDS +#include "defs.h" +#include <sys/stat.h> +#include <sys/signal.h> +#include <fcntl.h> +#include <stdlib.h> +#include "pathnames.h" + +#define	NRECORDS	50		/* size of circular trace buffer */ +#ifdef DEBUG +FILE	*ftrace = stdout; +int	traceactions = 0; +#endif +static	struct timeval lastlog; +static	char *savetracename; + +traceinit(ifp) +	register struct interface *ifp; +{ +	static int iftraceinit(); + +	if (iftraceinit(ifp, &ifp->int_input) && +	    iftraceinit(ifp, &ifp->int_output)) +		return; +	tracehistory = 0; +	fprintf(stderr, "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; +{ +	struct stat stbuf; + +	if (ftrace != NULL) +		return; +	if (stat(file, &stbuf) >= 0 && (stbuf.st_mode & S_IFMT) != S_IFREG) +		return; +	savetracename = file; +	(void) gettimeofday(&now, (struct timezone *)NULL); +	ftrace = fopen(file, "a"); +	if (ftrace == NULL) +		return; +	dup2(fileno(ftrace), 1); +	dup2(fileno(ftrace), 2); +	traceactions = 1; +	fprintf(ftrace, "Tracing enabled %s\n", ctime((time_t *)&now.tv_sec)); +} + +traceoff() +{ +	if (!traceactions) +		return; +	if (ftrace != NULL) { +		int fd = open(_PATH_DEVNULL, O_RDWR); + +		fprintf(ftrace, "Tracing disabled %s\n", +		    ctime((time_t *)&now.tv_sec)); +		fflush(ftrace); +		(void) dup2(fd, 1); +		(void) dup2(fd, 2); +		(void) close(fd); +		fclose(ftrace); +		ftrace = NULL; +	} +	traceactions = 0; +	tracehistory = 0; +	tracepackets = 0; +	tracecontents = 0; +} + +void +sigtrace(s) +	int s; +{ + +	if (s == SIGUSR2) +		traceoff(); +	else if (ftrace == NULL && savetracename) +		traceon(savetracename); +	else +		bumploglevel(); +} + +/* + * Move to next higher level of tracing when -t option processed or + * SIGUSR1 is received.  Successive levels are: + *	traceactions + *	traceactions + tracepackets + *	traceactions + tracehistory (packets and contents after change) + *	traceactions + tracepackets + tracecontents + */ +bumploglevel() +{ + +	(void) gettimeofday(&now, (struct timezone *)NULL); +	if (traceactions == 0) { +		traceactions++; +		if (ftrace) +			fprintf(ftrace, "Tracing actions started %s\n", +			    ctime((time_t *)&now.tv_sec)); +	} else if (tracepackets == 0) { +		tracepackets++; +		tracehistory = 0; +		tracecontents = 0; +		if (ftrace) +			fprintf(ftrace, "Tracing packets started %s\n", +			    ctime((time_t *)&now.tv_sec)); +	} else if (tracehistory == 0) { +		tracehistory++; +		if (ftrace) +			fprintf(ftrace, "Tracing history started %s\n", +			    ctime((time_t *)&now.tv_sec)); +	} else { +		tracepackets++; +		tracecontents++; +		tracehistory = 0; +		if (ftrace) +			fprintf(ftrace, "Tracing packet contents started %s\n", +			    ctime((time_t *)&now.tv_sec)); +	} +	if (ftrace) +		fflush(ftrace); +} + +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_size < len && t->ift_packet) { +		free(t->ift_packet); +		t->ift_packet = 0; +	} +	t->ift_stamp = now; +	t->ift_who = *who; +	if (len > 0 && t->ift_packet == 0) { +		t->ift_packet = malloc(len); +		if (t->ift_packet == 0) +			len = 0; +	} +	if (len > 0) +		bcopy(p, t->ift_packet, len); +	t->ift_size = len; +	t->ift_metric = m; +} + +traceaction(fd, action, rt) +	FILE *fd; +	char *action; +	struct rt_entry *rt; +{ +	struct sockaddr_in *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" }, +		{ RTS_INTERNAL,	"INTERNAL" }, +		{ RTS_EXTERNAL,	"EXTERNAL" }, +		{ RTS_SUBNET,	"SUBNET" }, +		{ 0 } +	}; +	register struct bits *p; +	register int first; +	char *cp; +	struct interface *ifp; + +	if (fd == NULL) +		return; +	if (lastlog.tv_sec != now.tv_sec || lastlog.tv_usec != now.tv_usec) { +		fprintf(fd, "\n%.19s:\n", ctime((time_t *)&now.tv_sec)); +		lastlog = now; +	} +	fprintf(fd, "%s ", action); +	dst = (struct sockaddr_in *)&rt->rt_dst; +	gate = (struct sockaddr_in *)&rt->rt_router; +	fprintf(fd, "dst %s, ", inet_ntoa(dst->sin_addr)); +	fprintf(fd, "router %s, metric %d, flags", +	     inet_ntoa(gate->sin_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; +		} +	} +	fprintf(fd, " timer %d\n", rt->rt_timer); +	if (tracehistory && !tracepackets && +	    (rt->rt_state & RTS_PASSIVE) == 0 && rt->rt_ifp) +		dumpif(fd, rt->rt_ifp); +	fflush(fd); +	if (ferror(fd)) +		traceoff(); +} + +tracenewmetric(fd, rt, newmetric) +	FILE *fd; +	struct rt_entry *rt; +	int newmetric; +{ +	struct sockaddr_in *dst, *gate; + +	if (fd == NULL) +		return; +	if (lastlog.tv_sec != now.tv_sec || lastlog.tv_usec != now.tv_usec) { +		fprintf(fd, "\n%.19s:\n", ctime((time_t *)&now.tv_sec)); +		lastlog = now; +	} +	dst = (struct sockaddr_in *)&rt->rt_dst; +	gate = (struct sockaddr_in *)&rt->rt_router; +	fprintf(fd, "CHANGE metric dst %s, ", inet_ntoa(dst->sin_addr)); +	fprintf(fd, "router %s, from %d to %d\n", +	     inet_ntoa(gate->sin_addr), rt->rt_metric, newmetric); +	fflush(fd); +	if (ferror(fd)) +		traceoff(); +} + +dumpif(fd, ifp) +	FILE *fd; +	register struct interface *ifp; +{ +	if (ifp->int_input.ifd_count || ifp->int_output.ifd_count) { +		fprintf(fd, "*** Packet history for interface %s ***\n", +			ifp->int_name); +#ifdef notneeded +		dumptrace(fd, "to", &ifp->int_output); +#endif +		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); +		fflush(fd); +		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; +		dumppacket(fd, dir, &t->ift_who, t->ift_packet, t->ift_size, +		    &t->ift_stamp); +	} +} + +dumppacket(fd, dir, who, cp, size, stamp) +	FILE *fd; +	struct sockaddr_in *who;		/* should be sockaddr */ +	char *dir, *cp; +	register int size; +	struct timeval *stamp; +{ +	register struct rip *msg = (struct rip *)cp; +	register struct netinfo *n; + +	if (fd == NULL) +		return; +	if (msg->rip_cmd && msg->rip_cmd < RIPCMD_MAX) +		fprintf(fd, "%s %s %s.%d %.19s:\n", ripcmds[msg->rip_cmd], +		    dir, inet_ntoa(who->sin_addr), ntohs(who->sin_port), +		    ctime((time_t *)&stamp->tv_sec)); +	else { +		fprintf(fd, "Bad cmd 0x%x %s %x.%d %.19s\n", msg->rip_cmd, +		    dir, inet_ntoa(who->sin_addr), ntohs(who->sin_port)); +		fprintf(fd, "size=%d cp=%x packet=%x\n", size, cp, packet, +		    ctime((time_t *)&stamp->tv_sec)); +		fflush(fd); +		return; +	} +	if (tracepackets && tracecontents == 0) { +		fflush(fd); +		return; +	} +	switch (msg->rip_cmd) { + +	case RIPCMD_REQUEST: +	case RIPCMD_RESPONSE: +		size -= 4 * sizeof (char); +		n = msg->rip_nets; +		for (; size > 0; n++, size -= sizeof (struct netinfo)) { +			if (size < sizeof (struct netinfo)) { +				fprintf(fd, "(truncated record, len %d)\n", +				    size); +				break; +			} +			if (sizeof(n->rip_dst.sa_family) > 1) +			    n->rip_dst.sa_family = ntohs(n->rip_dst.sa_family); + +			switch ((int)n->rip_dst.sa_family) { + +			case AF_INET: +				fprintf(fd, "\tdst %s metric %d\n", +#define	satosin(sa)	((struct sockaddr_in *)&sa) +				     inet_ntoa(satosin(n->rip_dst)->sin_addr), +				     ntohl(n->rip_metric)); +				break; + +			default: +				fprintf(fd, "\taf %d? metric %d\n", +				     n->rip_dst.sa_family, +				     ntohl(n->rip_metric)); +				break; +			} +		} +		break; + +	case RIPCMD_TRACEON: +		fprintf(fd, "\tfile=%*s\n", size, msg->rip_tracefile); +		break; + +	case RIPCMD_TRACEOFF: +		break; +	} +	fflush(fd); +	if (ferror(fd)) +		traceoff(); +} diff --git a/usr.sbin/routed/trace.h b/usr.sbin/routed/trace.h new file mode 100644 index 000000000000..42521fc95dc1 --- /dev/null +++ b/usr.sbin/routed/trace.h @@ -0,0 +1,96 @@ +/* + * Copyright (c) 1983, 1988, 1993 + *	The Regents of the University of California.  All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + *    notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + *    notice, this list of conditions and the following disclaimer in the + *    documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + *    must display the following acknowledgement: + *	This product includes software developed by the University of + *	California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + *    may be used to endorse or promote products derived from this software + *    without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + *	@(#)trace.h	8.1 (Berkeley) 6/5/93 + */ + +/* + * Routing table management daemon. + */ + +/* + * Trace record format. + */ +struct	iftrace { +	struct	timeval 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 on associated 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	tracecontents;		/* watch packet contents as they go by */ +int	traceactions;		/* on/off */ +int	tracehistory;		/* on/off */ +FILE	*ftrace;		/* output trace file */ + +#define	TRACE_ACTION(action, route) { \ +	  if (traceactions) \ +		traceaction(ftrace, action, route); \ +	} +#define	TRACE_NEWMETRIC(route, newmetric) { \ +	  if (traceactions) \ +		tracenewmetric(ftrace, route, newmetric); \ +	} +#define	TRACE_INPUT(ifp, src, pack, size) { \ +	  if (tracehistory) { \ +		ifp = if_iflookup(src); \ +		if (ifp) \ +			trace(&ifp->int_input, src, pack, size, \ +				ntohl(ifp->int_metric)); \ +	  } \ +	  if (tracepackets) \ +		dumppacket(ftrace, "from", src, pack, size, &now); \ +	} +#define	TRACE_OUTPUT(ifp, dst, size) { \ +	  if (tracehistory && ifp) \ +		trace(&ifp->int_output, dst, packet, size, ifp->int_metric); \ +	  if (tracepackets) \ +		dumppacket(ftrace, "to", dst, packet, size, &now); \ +	} diff --git a/usr.sbin/routed/trace/Makefile b/usr.sbin/routed/trace/Makefile new file mode 100644 index 000000000000..01b16b3436be --- /dev/null +++ b/usr.sbin/routed/trace/Makefile @@ -0,0 +1,7 @@ +#	@(#)Makefile	8.1 (Berkeley) 6/5/93 + +PROG=	trace +NOMAN=	noman + +.include "../../Makefile.inc" +.include <bsd.prog.mk> diff --git a/usr.sbin/routed/trace/trace.c b/usr.sbin/routed/trace/trace.c new file mode 100644 index 000000000000..38c630cfe953 --- /dev/null +++ b/usr.sbin/routed/trace/trace.c @@ -0,0 +1,125 @@ +/*- + * Copyright (c) 1983, 1988, 1993 + *	The Regents of the University of California.  All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + *    notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + *    notice, this list of conditions and the following disclaimer in the + *    documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + *    must display the following acknowledgement: + *	This product includes software developed by the University of + *	California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + *    may be used to endorse or promote products derived from this software + *    without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char copyright[] = +"@(#) Copyright (c) 1983, 1988, 1993\n\ +	The Regents of the University of California.  All rights reserved.\n"; +#endif /* not lint */ + +#ifndef lint +static char sccsid[] = "@(#)trace.c	8.1 (Berkeley) 6/5/93"; +#endif /* not lint */ + +#include <sys/param.h> +#include <sys/protosw.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <protocols/routed.h> +#include <arpa/inet.h> +#include <netdb.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +struct	sockaddr_in myaddr; +char	packet[MAXPACKETSIZE]; + +main(argc, argv) +	int argc; +	char **argv; +{ +	int size, s; +	struct sockaddr from; +	struct sockaddr_in router; +	register struct rip *msg = (struct rip *)packet; +	struct hostent *hp; +	struct servent *sp; +	 +	if (argc < 3) { +usage: +		printf("usage: trace cmd machines,\n"); +		printf("cmd either \"on filename\", or \"off\"\n"); +		exit(1); +	} +	s = socket(AF_INET, SOCK_DGRAM, 0); +	if (s < 0) { +		perror("socket"); +		exit(2); +	} +	myaddr.sin_family = AF_INET; +	myaddr.sin_port = htons(IPPORT_RESERVED-1); +	if (bind(s, (struct sockaddr *)&myaddr, sizeof(myaddr)) < 0) { +		perror("bind"); +		exit(2); +	} + +	argv++, argc--; +	msg->rip_cmd = strcmp(*argv, "on") == 0 ? +		RIPCMD_TRACEON : RIPCMD_TRACEOFF; +	msg->rip_vers = RIPVERSION; +	argv++, argc--; +	size = sizeof (int); +	if (msg->rip_cmd == RIPCMD_TRACEON) { +		strcpy(msg->rip_tracefile, *argv); +		size += strlen(*argv); +		argv++, argc--; +	} +	if (argc == 0) +		goto usage; +	bzero((char *)&router, sizeof (router)); +	router.sin_family = AF_INET; +	sp = getservbyname("router", "udp"); +	if (sp == 0) { +		printf("udp/router: service unknown\n"); +		exit(1); +	} +	router.sin_port = sp->s_port; +	while (argc > 0) { +		router.sin_family = AF_INET; +		router.sin_addr.s_addr = inet_addr(*argv); +		if (router.sin_addr.s_addr == -1) { +			hp = gethostbyname(*argv); +			if (hp == NULL) { +				fprintf(stderr, "trace: %s: ", *argv); +				herror((char *)NULL); +				continue; +			} +			bcopy(hp->h_addr, &router.sin_addr, hp->h_length); +		} +		if (sendto(s, packet, size, 0, +		    (struct sockaddr *)&router, sizeof(router)) < 0) +			perror(*argv); +		argv++, argc--; +	} +} | 
