From 3219c922a9b5bb60c7773ad93345d871bce72a68 Mon Sep 17 00:00:00 2001 From: "Rodney W. Grimes" Date: Thu, 26 May 1994 06:39:07 +0000 Subject: BSD 4.4 Lite sbin -> usr.sbin Sources Note: The sources for XNSrouted and routed are being imported to usr.sbin instead of sbin. --- usr.sbin/routed/Makefile | 22 ++ usr.sbin/routed/af.c | 171 ++++++++++++++ usr.sbin/routed/af.h | 65 ++++++ usr.sbin/routed/defs.h | 103 +++++++++ usr.sbin/routed/if.c | 148 ++++++++++++ usr.sbin/routed/inet.c | 243 +++++++++++++++++++ usr.sbin/routed/input.c | 362 +++++++++++++++++++++++++++++ usr.sbin/routed/interface.h | 90 +++++++ usr.sbin/routed/main.c | 351 ++++++++++++++++++++++++++++ usr.sbin/routed/output.c | 172 ++++++++++++++ usr.sbin/routed/pathnames.h | 38 +++ usr.sbin/routed/query/Makefile | 7 + usr.sbin/routed/query/query.c | 294 +++++++++++++++++++++++ usr.sbin/routed/routed.8 | 358 ++++++++++++++++++++++++++++ usr.sbin/routed/startup.c | 515 +++++++++++++++++++++++++++++++++++++++++ usr.sbin/routed/table.h | 108 +++++++++ usr.sbin/routed/tables.c | 428 ++++++++++++++++++++++++++++++++++ usr.sbin/routed/timer.c | 127 ++++++++++ usr.sbin/routed/trace.c | 426 ++++++++++++++++++++++++++++++++++ usr.sbin/routed/trace.h | 96 ++++++++ usr.sbin/routed/trace/Makefile | 7 + usr.sbin/routed/trace/trace.c | 125 ++++++++++ 22 files changed, 4256 insertions(+) create mode 100644 usr.sbin/routed/Makefile create mode 100644 usr.sbin/routed/af.c create mode 100644 usr.sbin/routed/af.h create mode 100644 usr.sbin/routed/defs.h create mode 100644 usr.sbin/routed/if.c create mode 100644 usr.sbin/routed/inet.c create mode 100644 usr.sbin/routed/input.c create mode 100644 usr.sbin/routed/interface.h create mode 100644 usr.sbin/routed/main.c create mode 100644 usr.sbin/routed/output.c create mode 100644 usr.sbin/routed/pathnames.h create mode 100644 usr.sbin/routed/query/Makefile create mode 100644 usr.sbin/routed/query/query.c create mode 100644 usr.sbin/routed/routed.8 create mode 100644 usr.sbin/routed/startup.c create mode 100644 usr.sbin/routed/table.h create mode 100644 usr.sbin/routed/tables.c create mode 100644 usr.sbin/routed/timer.c create mode 100644 usr.sbin/routed/trace.c create mode 100644 usr.sbin/routed/trace.h create mode 100644 usr.sbin/routed/trace/Makefile create mode 100644 usr.sbin/routed/trace/trace.c (limited to 'usr.sbin/routed') 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 + +.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 +#include +#include + +#include +#include +#include + +#include +#include + +#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 + +/* + * 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 +#include + +#include + +#include +#include +#include +#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 + +#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 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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 +#include +#include +#include +#include +#include +#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 +#include +#include + +#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 +#include +#include +#include +#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 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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--; + } +} -- cgit v1.2.3