From: William F. Jolitz Date: Wed, 17 Apr 1991 00:31:38 +0000 (-0800) Subject: 386BSD 0.1 development X-Git-Tag: 386BSD-0.1~1825 X-Git-Url: https://git.subgeniuskitty.com/unix-history/.git/commitdiff_plain/13bd785c3174863b5edbc96698b3961f91c6a30c 386BSD 0.1 development Work on file usr/src/sbin/routed/af.c Work on file usr/src/sbin/routed/if.c Work on file usr/src/sbin/routed/af.h Work on file usr/src/sbin/routed/defs.h Work on file usr/src/sbin/routed/inet.c Work on file usr/src/sbin/routed/input.c Work on file usr/src/sbin/routed/interface.h Work on file usr/src/sbin/routed/pathnames.h Work on file usr/src/sbin/routed/routed.8 Work on file usr/src/sbin/routed/startup.c Work on file usr/src/sbin/routed/output.c Work on file usr/src/sbin/routed/timer.c Work on file usr/src/sbin/routed/table.h Work on file usr/src/sbin/routed/trace.h Work on file usr/src/sbin/routed/trace.c Co-Authored-By: Lynne Greer Jolitz Synthesized-from: 386BSD-0.1 --- diff --git a/usr/src/sbin/routed/af.c b/usr/src/sbin/routed/af.c new file mode 100644 index 0000000000..19807b71db --- /dev/null +++ b/usr/src/sbin/routed/af.c @@ -0,0 +1,171 @@ +/* + * Copyright (c) 1983 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 5.11 (Berkeley) 2/28/91"; +#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/src/sbin/routed/af.h b/usr/src/sbin/routed/af.h new file mode 100644 index 0000000000..2d1bf293d3 --- /dev/null +++ b/usr/src/sbin/routed/af.h @@ -0,0 +1,65 @@ +/* + * Copyright (c) 1983 Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)af.h 5.7 (Berkeley) 6/1/90 + */ + +/* + * Routing table management daemon. + */ + +/* + * Per address family routines. + */ +struct afswitch { + int (*af_hash)(); /* returns keys based on address */ + int (*af_netmatch)(); /* verifies net # matching */ + int (*af_output)(); /* interprets address for sending */ + int (*af_portmatch)(); /* packet from some other router? */ + int (*af_portcheck)(); /* packet from privileged peer? */ + int (*af_checkhost)(); /* tells if address 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 */ +}; + +struct afswitch afswitch[]; /* table proper */ +int af_max; /* number of entries in table */ diff --git a/usr/src/sbin/routed/defs.h b/usr/src/sbin/routed/defs.h new file mode 100644 index 0000000000..f4fdf7a68f --- /dev/null +++ b/usr/src/sbin/routed/defs.h @@ -0,0 +1,93 @@ +/* + * Copyright (c) 1983, 1988 Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)defs.h 5.10 (Berkeley) 2/28/91 + */ + +/* + * 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 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 sndmsg(); +int supply(); +int cleanup(); diff --git a/usr/src/sbin/routed/if.c b/usr/src/sbin/routed/if.c new file mode 100644 index 0000000000..4871c9df32 --- /dev/null +++ b/usr/src/sbin/routed/if.c @@ -0,0 +1,148 @@ +/* + * Copyright (c) 1983 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 5.6 (Berkeley) 6/1/90"; +#endif /* not lint */ + +/* + * Routing Table Management Daemon + */ +#include "defs.h" + +extern struct interface *ifnet; + +/* + * Find the interface with address addr. + */ +struct interface * +if_ifwithaddr(addr) + struct sockaddr *addr; +{ + register struct interface *ifp; + +#define same(a1, a2) \ + (bcmp((caddr_t)((a1)->sa_data), (caddr_t)((a2)->sa_data), 14) == 0) + for (ifp = ifnet; ifp; ifp = ifp->int_next) { + if (ifp->int_flags & IFF_REMOTE) + continue; + if (ifp->int_addr.sa_family != addr->sa_family) + continue; + if (same(&ifp->int_addr, addr)) + break; + if ((ifp->int_flags & IFF_BROADCAST) && + same(&ifp->int_broadaddr, addr)) + break; + } + return (ifp); +} + +/* + * Find the point-to-point interface with destination address addr. + */ +struct interface * +if_ifwithdstaddr(addr) + struct sockaddr *addr; +{ + register struct interface *ifp; + + for (ifp = ifnet; ifp; ifp = ifp->int_next) { + if ((ifp->int_flags & IFF_POINTOPOINT) == 0) + continue; + if (same(&ifp->int_dstaddr, addr)) + break; + } + return (ifp); +} + +/* + * Find the interface on the network + * of the specified address. + */ +struct interface * +if_ifwithnet(addr) + register struct sockaddr *addr; +{ + register struct interface *ifp; + register int af = addr->sa_family; + register int (*netmatch)(); + + if (af >= af_max) + return (0); + netmatch = afswitch[af].af_netmatch; + for (ifp = ifnet; ifp; ifp = ifp->int_next) { + if (ifp->int_flags & IFF_REMOTE) + continue; + if (af != ifp->int_addr.sa_family) + continue; + if ((*netmatch)(addr, &ifp->int_addr)) + break; + } + return (ifp); +} + +/* + * Find an interface from which the specified address + * should have come from. Used for figuring out which + * interface a packet came in on -- for tracing. + */ +struct interface * +if_iflookup(addr) + struct sockaddr *addr; +{ + register struct interface *ifp, *maybe; + register int af = addr->sa_family; + register int (*netmatch)(); + + if (af >= af_max) + return (0); + maybe = 0; + netmatch = afswitch[af].af_netmatch; + for (ifp = ifnet; ifp; ifp = ifp->int_next) { + if (ifp->int_addr.sa_family != af) + continue; + if (same(&ifp->int_addr, addr)) + break; + if ((ifp->int_flags & IFF_BROADCAST) && + same(&ifp->int_broadaddr, addr)) + break; + if ((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/src/sbin/routed/inet.c b/usr/src/sbin/routed/inet.c new file mode 100644 index 0000000000..a465ac7637 --- /dev/null +++ b/usr/src/sbin/routed/inet.c @@ -0,0 +1,214 @@ +/* + * Copyright (c) 1983 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 5.8 (Berkeley) 6/1/90"; +#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 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/src/sbin/routed/input.c b/usr/src/sbin/routed/input.c new file mode 100644 index 0000000000..ec8c9d7623 --- /dev/null +++ b/usr/src/sbin/routed/input.c @@ -0,0 +1,362 @@ +/* + * Copyright (c) 1983, 1988 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 5.22 (Berkeley) 6/1/90"; +#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/src/sbin/routed/interface.h b/usr/src/sbin/routed/interface.h new file mode 100644 index 0000000000..6e555cb278 --- /dev/null +++ b/usr/src/sbin/routed/interface.h @@ -0,0 +1,90 @@ +/* + * Copyright (c) 1983 Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)interface.h 5.6 (Berkeley) 6/1/90 + */ + +/* + * Routing table management daemon. + */ + +/* + * An ``interface'' is similar to an ifnet structure, + * except it doesn't contain q'ing info, and it also + * handles ``logical'' interfaces (remote gateways + * that we want to keep polling even if they go down). + * The list of interfaces which we maintain is used + * in supplying the gratuitous routing table updates. + */ +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 0x1000 /* interface on subnetted network */ +#define IFF_PASSIVE 0x2000 /* can't tell if up/down */ +#define IFF_INTERFACE 0x4000 /* hardware interface */ +#define IFF_REMOTE 0x8000 /* interface isn't on this machine */ + +struct interface *if_ifwithaddr(); +struct interface *if_ifwithdstaddr(); +struct interface *if_ifwithnet(); +struct interface *if_iflookup(); diff --git a/usr/src/sbin/routed/output.c b/usr/src/sbin/routed/output.c new file mode 100644 index 0000000000..10c81b1a0c --- /dev/null +++ b/usr/src/sbin/routed/output.c @@ -0,0 +1,172 @@ +/* + * Copyright (c) 1983, 1988 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 5.15 (Berkeley) 2/28/91"; +#endif /* not lint */ + +/* + * Routing Table Management Daemon + */ +#include "defs.h" + +/* + * Apply the function "f" to all non-passive + * interfaces. If the interface supports the + * use of broadcasting use it, otherwise address + * the output to the known router. + */ +toall(f, 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/src/sbin/routed/pathnames.h b/usr/src/sbin/routed/pathnames.h new file mode 100644 index 0000000000..54bac2751e --- /dev/null +++ b/usr/src/sbin/routed/pathnames.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) 1989 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 5.3 (Berkeley) 6/1/90 + */ + +#include + +#define _PATH_GATEWAYS "/etc/gateways" diff --git a/usr/src/sbin/routed/routed.8 b/usr/src/sbin/routed/routed.8 new file mode 100644 index 0000000000..1d428a7b39 --- /dev/null +++ b/usr/src/sbin/routed/routed.8 @@ -0,0 +1,360 @@ +.\" Copyright (c) 1983, 1991 The Regents of the University of California. +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. All advertising materials mentioning features or use of this software +.\" must display the following acknowledgement: +.\" This product includes software developed by the University of +.\" California, Berkeley and its contributors. +.\" 4. Neither the name of the University nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" @(#)routed.8 6.6 (Berkeley) 3/16/91 +.\" +.Dd March 16, 1991 +.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 the 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. +Sites needing assistance with such configurations +should contact the Computer Systems Research Group at Berkeley. +.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/src/sbin/routed/startup.c b/usr/src/sbin/routed/startup.c new file mode 100644 index 0000000000..f88d5935c0 --- /dev/null +++ b/usr/src/sbin/routed/startup.c @@ -0,0 +1,486 @@ +/* + * Copyright (c) 1983, 1988 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 5.19 (Berkeley) 2/28/91"; +#endif /* not lint */ + +/* + * Routing Table Management Daemon + */ +#include "defs.h" +#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 */ + +/* + * Find the network interfaces which have configured themselves. + * If the interface is present but not yet up (for example an + * ARPANET IMP), set the lookforinterfaces flag so we'll + * come back later and look again. + */ +ifinit() +{ + struct interface ifs, *ifp; + int s; + char buf[BUFSIZ], *cp, *cplim; + struct ifconf ifc; + struct ifreq ifreq, *ifr; + struct sockaddr_in *sin; + u_long i; + + if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { + syslog(LOG_ERR, "socket: %m"); + close(s); + return; + } + ifc.ifc_len = sizeof (buf); + ifc.ifc_buf = buf; + if (ioctl(s, SIOCGIFCONF, (char *)&ifc) < 0) { + syslog(LOG_ERR, "ioctl (get interface configuration)"); + close(s); + return; + } + ifr = ifc.ifc_req; + lookforinterfaces = 0; +#ifdef RTM_ADD +#define max(a, b) (a > b ? a : b) +#define size(p) max((p).sa_len, sizeof(p)) +#else +#define size(p) (sizeof (p)) +#endif + cplim = buf + ifc.ifc_len; /*skip over if's with big ifr_addr's */ + for (cp = buf; cp < cplim; + cp += sizeof (ifr->ifr_name) + size(ifr->ifr_addr)) { + ifr = (struct ifreq *)cp; + bzero((char *)&ifs, sizeof(ifs)); + ifs.int_addr = ifr->ifr_addr; + ifreq = *ifr; + if (ioctl(s, SIOCGIFFLAGS, (char *)&ifreq) < 0) { + syslog(LOG_ERR, "%s: ioctl (get interface flags)", + ifr->ifr_name); + continue; + } + ifs.int_flags = ifreq.ifr_flags | IFF_INTERFACE; + if ((ifs.int_flags & IFF_UP) == 0 || + ifr->ifr_addr.sa_family == AF_UNSPEC) { + lookforinterfaces = 1; + continue; + } + /* argh, this'll have to change sometime */ + if (ifs.int_addr.sa_family != AF_INET) + continue; + if (ifs.int_flags & IFF_POINTOPOINT) { + if (ioctl(s, SIOCGIFDSTADDR, (char *)&ifreq) < 0) { + syslog(LOG_ERR, "%s: ioctl (get dstaddr)", + ifr->ifr_name); + continue; + } + if (ifr->ifr_addr.sa_family == AF_UNSPEC) { + lookforinterfaces = 1; + continue; + } + ifs.int_dstaddr = ifreq.ifr_dstaddr; + } + /* + * 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 (ioctl(s, SIOCGIFBRDADDR, (char *)&ifreq) < 0) { + syslog(LOG_ERR, "%s: ioctl (get broadaddr)", + ifr->ifr_name); + continue; + } +#ifndef sun + ifs.int_broadaddr = ifreq.ifr_broadaddr; +#else + ifs.int_broadaddr = ifreq.ifr_addr; +#endif + } +#ifdef SIOCGIFMETRIC + if (ioctl(s, SIOCGIFMETRIC, (char *)&ifreq) < 0) { + syslog(LOG_ERR, "%s: ioctl (get metric)", + ifr->ifr_name); + ifs.int_metric = 0; + } else + ifs.int_metric = ifreq.ifr_metric; +#else + ifs.int_metric = 0; +#endif + /* + * Use a minimum metric of one; + * treat the interface metric (default 0) + * as an increment to the hop count of one. + */ + ifs.int_metric++; + if (ioctl(s, SIOCGIFNETMASK, (char *)&ifreq) < 0) { + syslog(LOG_ERR, "%s: ioctl (get netmask)", + ifr->ifr_name); + continue; + } + sin = (struct sockaddr_in *)&ifreq.ifr_addr; + 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(sizeof (struct interface)); + if (ifp == 0) { + printf("routed: out of memory\n"); + break; + } + *ifp = ifs; + /* + * Count the # of directly connected networks + * and point to point links which aren't looped + * back to ourself. This is used below to + * decide if we should be a routing ``supplier''. + */ + if ((ifs.int_flags & IFF_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 = malloc(strlen(ifr->ifr_name) + 1); + if (ifp->int_name == 0) { + fprintf(stderr, "routed: ifinit: out of memory\n"); + syslog(LOG_ERR, "routed: ifinit: out of memory\n"); + close(s); + return; + } + strcpy(ifp->int_name, ifr->ifr_name); + *ifnext = ifp; + ifnext = &ifp->int_next; + traceinit(ifp); + addrouteforif(ifp); + } + if (externalinterfaces > 1 && supplier < 0) + supplier = 1; + close(s); +} + +/* + * 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) ioctl(s, SIOCADDRT, (char *)&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/src/sbin/routed/table.h b/usr/src/sbin/routed/table.h new file mode 100644 index 0000000000..124e098eb2 --- /dev/null +++ b/usr/src/sbin/routed/table.h @@ -0,0 +1,106 @@ +/* + * Copyright (c) 1983 Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)table.h 5.8 (Berkeley) 6/1/90 + */ + +/* + * Routing table management daemon. + */ + +/* + * Routing table structure; differs a bit from kernel tables. + * + * Note: the union below must agree in the first 4 members + * so the ioctl's will work. + */ +struct rthash { + struct rt_entry *rt_forw; + struct rt_entry *rt_back; +}; +#ifdef RTM_ADD +#define rtentry ortentry +#endif + +struct rt_entry { + struct rt_entry *rt_forw; + struct rt_entry *rt_back; + union { + struct rtentry rtu_rt; + struct { + u_long rtu_hash; + struct sockaddr rtu_dst; + struct sockaddr rtu_router; + short rtu_flags; + short rtu_state; + int rtu_timer; + int rtu_metric; + int rtu_ifmetric; + struct interface *rtu_ifp; + } rtu_entry; + } rt_rtu; +}; + +#define rt_rt rt_rtu.rtu_rt /* pass to ioctl */ +#define rt_hash rt_rtu.rtu_entry.rtu_hash /* for net or host */ +#define rt_dst rt_rtu.rtu_entry.rtu_dst /* match value */ +#define rt_router rt_rtu.rtu_entry.rtu_router /* who to forward to */ +#define rt_flags rt_rtu.rtu_entry.rtu_flags /* kernel flags */ +#define rt_timer rt_rtu.rtu_entry.rtu_timer /* for invalidation */ +#define rt_state rt_rtu.rtu_entry.rtu_state /* see below */ +#define rt_metric rt_rtu.rtu_entry.rtu_metric /* cost of route */ +#define rt_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 0x8000 /* pseudo: route to subnet */ + +struct rthash nethash[ROUTEHASHSIZ]; +struct rthash hosthash[ROUTEHASHSIZ]; +struct rt_entry *rtlookup(); +struct rt_entry *rtfind(); diff --git a/usr/src/sbin/routed/timer.c b/usr/src/sbin/routed/timer.c new file mode 100644 index 0000000000..fd0851d20a --- /dev/null +++ b/usr/src/sbin/routed/timer.c @@ -0,0 +1,127 @@ +/* + * Copyright (c) 1983, 1988 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 5.10 (Berkeley) 2/28/91"; +#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/src/sbin/routed/trace.c b/usr/src/sbin/routed/trace.c new file mode 100644 index 0000000000..6e0b478bc5 --- /dev/null +++ b/usr/src/sbin/routed/trace.c @@ -0,0 +1,426 @@ +/* + * Copyright (c) 1983, 1988 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 5.11 (Berkeley) 2/28/91"; +#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/src/sbin/routed/trace.h b/usr/src/sbin/routed/trace.h new file mode 100644 index 0000000000..741de720ce --- /dev/null +++ b/usr/src/sbin/routed/trace.h @@ -0,0 +1,96 @@ +/* + * Copyright (c) 1983, 1988 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 5.8 (Berkeley) 6/1/90 + */ + +/* + * 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); \ + }