#!/bin/sh
# this is vxrouted_5.1.1-shar.07 (part 7 of a multipart archive)
# do not concatenate these parts, unpack them in order with /bin/sh
# file vxrouted_5.1.1/BSDrouted/main.c continued
#
touch -am 1231235999 $$.touch >/dev/null 2>&1
if test ! -f 1231235999 && test -f $$.touch; then
  shar_touch=touch
else
  shar_touch=:
  echo 'WARNING: not restoring timestamps'
fi
rm -f 1231235999 $$.touch
#
if test ! -r _sharseq.tmp; then
  echo 'Please unpack part 1 first!'
  exit 1
fi
shar_sequence=`cat _sharseq.tmp`
if test "$shar_sequence" != 7; then
  echo "Please unpack part $shar_sequence next!"
  exit 1
fi
if test ! -f _sharnew.tmp; then
  echo 'x - still skipping vxrouted_5.1.1/BSDrouted/main.c'
else
  echo 'x - continuing file vxrouted_5.1.1/BSDrouted/main.c'
  sed 's/^X//' << 'SHAR_EOF' >> 'vxrouted_5.1.1/BSDrouted/main.c' &&
X	ibits.fds_bits[(s)/(sizeof(fd_mask) * 8)] & (1 << ((s) % (sizeof(fd_mask) * 8))),
X	&ibits
X	);
*/
X		if (FD_ISSET(s, &ibits))
#else
X		if (ibits.fds_bits[s/32] & (1 << s))
#endif
X			process(s);
X		/* handle ICMP redirects */
X		sigsetmask(omask);
X	}
}
X
timevaladd(t1, t2)
X	struct timeval *t1, *t2;
{
X
X	t1->tv_sec += t2->tv_sec;
X	if ((t1->tv_usec += t2->tv_usec) > 1000000) {
X		t1->tv_sec++;
X		t1->tv_usec -= 1000000;
X	}
}
X
timevalsub(t1, t2)
X	struct timeval *t1, *t2;
{
X
X	t1->tv_sec -= t2->tv_sec;
X	if ((t1->tv_usec -= t2->tv_usec) < 0) {
X		t1->tv_sec--;
X		t1->tv_usec += 1000000;
X	}
}
X
process(fd)
X	int fd;
{
X	struct sockaddr from;
X	int fromlen, cc;
X	union {
X		char	buf[MAXPACKETSIZE+1];
X		struct	rip rip;
X	} inbuf;
X
X	for (;;) {
X		fromlen = sizeof (from);
X		cc = recvfrom(fd, &inbuf, sizeof (inbuf), 0, &from, &fromlen);
X		if (cc <= 0) {
X			if (cc < 0 && errno != EWOULDBLOCK)
X				perror("recvfrom");
X			break;
X		}
X		if (fromlen != sizeof (struct sockaddr_in))
X			break;
X		rip_input(&from, &inbuf.rip, cc);
X	}
}
X
getsocket(domain, type, sin)
X	int domain, type;
X	struct sockaddr_in *sin;
{
X	int sock, on = 1;
X
X	if ((sock = socket(domain, type, 0)) < 0) {
X		perror("socket");
X		syslog(LOG_ERR, "socket: %m");
X		return (-1);
X	}
#ifdef SO_BROADCAST
X	if (setsockopt(sock, SOL_SOCKET, SO_BROADCAST, &on, sizeof (on)) < 0) {
X		syslog(LOG_ERR, "setsockopt SO_BROADCAST: %m");
X		close(sock);
X		return (-1);
X	}
#endif
#ifdef SO_RCVBUF
X	for (on = bufspace; ; on -= 1024) {
X		if (setsockopt(sock, SOL_SOCKET, SO_RCVBUF,
X		    &on, sizeof (on)) == 0)
X			break;
X		if (on <= 8*1024) {
X			syslog(LOG_ERR, "setsockopt SO_RCVBUF: %m");
X			break;
X		}
X	}
X	if (traceactions)
X		fprintf(ftrace, "recv buf %d\n", on);
#endif
X	if (bind(sock, sin, sizeof (*sin), 0) < 0) {
X		perror("bind");
X		syslog(LOG_ERR, "bind: %m");
X		close(sock);
X		return (-1);
X	}
X	if (fcntl(sock, F_SETFL, FNDELAY) == -1)
X		syslog(LOG_ERR, "fcntl FNDELAY: %m\n");
X	return (sock);
}
SHAR_EOF
  echo 'File vxrouted_5.1.1/BSDrouted/main.c is complete' &&
  $shar_touch -am 0220182189 'vxrouted_5.1.1/BSDrouted/main.c' &&
  chmod 0444 'vxrouted_5.1.1/BSDrouted/main.c' ||
  echo 'restore of vxrouted_5.1.1/BSDrouted/main.c failed'
  shar_count="`wc -c < 'vxrouted_5.1.1/BSDrouted/main.c'`"
  test 8098 -eq "$shar_count" ||
    echo "vxrouted_5.1.1/BSDrouted/main.c: original size 8098, current size $shar_count"
  rm -f _sharnew.tmp
fi
# ============= vxrouted_5.1.1/BSDrouted/output.c ==============
if test -f 'vxrouted_5.1.1/BSDrouted/output.c' && test X"$1" != X"-c"; then
  echo 'x - skipping vxrouted_5.1.1/BSDrouted/output.c (File already exists)'
  rm -f _sharnew.tmp
else
  > _sharnew.tmp
  echo 'x - extracting vxrouted_5.1.1/BSDrouted/output.c (Text)'
  sed 's/^X//' << 'SHAR_EOF' > 'vxrouted_5.1.1/BSDrouted/output.c' &&
/*
X * Copyright (c) 1983, 1988 Regents of the University of California.
X * All rights reserved.
X *
X * Redistribution and use in source and binary forms are permitted
X * provided that the above copyright notice and this paragraph are
X * duplicated in all such forms and that any documentation,
X * advertising materials, and other materials related to such
X * distribution and use acknowledge that the software was developed
X * by the University of California, Berkeley.  The name of the
X * University may not be used to endorse or promote products derived
X * from this software without specific prior written permission.
X * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
X * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
X * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
X */
X
#ifndef lint
static char sccsid[] = "@(#)output.c	5.12 (Berkeley) 2/18/89";
#endif /* not lint */
X
/*
X * Routing Table Management Daemon
X */
#include "defs.h"
X
/*
X * Apply the function "f" to all non-passive
X * interfaces.  If the interface supports the
X * use of broadcasting use it, otherwise address
X * the output to the known router.
X */
toall(f, rtstate, skipif)
X	int (*f)();
X	int rtstate;
X	struct interface *skipif;
{
X	register struct interface *ifp;
X	register struct sockaddr *dst;
X	register int flags;
X	extern struct interface *ifnet;
X
X	for (ifp = ifnet; ifp; ifp = ifp->int_next) {
X		if (ifp->int_flags & IFF_PASSIVE || ifp == skipif)
X			continue;
X		dst = ifp->int_flags & IFF_BROADCAST ? &ifp->int_broadaddr :
X		      ifp->int_flags & IFF_POINTOPOINT ? &ifp->int_dstaddr :
X		      &ifp->int_addr;
X		flags = ifp->int_flags & IFF_INTERFACE ? MSG_DONTROUTE : 0;
X		(*f)(dst, flags, ifp, rtstate);
X	}
}
X
/*
X * Output a preformed packet.
X */
/*ARGSUSED*/
sendmsg(dst, flags, ifp, rtstate)
X	struct sockaddr *dst;
X	int flags;
X	struct interface *ifp;
X	int rtstate;
{
X
X	(*afswitch[dst->sa_family].af_output)(s, flags,
X		dst, sizeof (struct rip));
X	TRACE_OUTPUT(ifp, dst, sizeof (struct rip));
}
X
/*
X * Supply dst with the contents of the routing tables.
X * If this won't fit in one packet, chop it up into several.
X */
supply(dst, flags, ifp, rtstate)
X	struct sockaddr *dst;
X	int flags;
X	register struct interface *ifp;
X	int rtstate;
{
X	register struct rt_entry *rt;
X	register struct netinfo *n = msg->rip_nets;
X	register struct rthash *rh;
X	struct rthash *base = hosthash;
X	int doinghost = 1, size;
X	int (*output)() = afswitch[dst->sa_family].af_output;
X	int (*sendroute)() = afswitch[dst->sa_family].af_sendroute;
X	int npackets = 0;
X
X	msg->rip_cmd = RIPCMD_RESPONSE;
X	msg->rip_vers = RIPVERSION;
X	bzero(msg->rip_res1, sizeof(msg->rip_res1));
again:
X	for (rh = base; rh < &base[ROUTEHASHSIZ]; rh++)
X	for (rt = rh->rt_forw; rt != (struct rt_entry *)rh; rt = rt->rt_forw) {
X		/*
X		 * Don't resend the information on the network
X		 * from which it was received (unless sending
X		 * in response to a query).
X		 */
X		if (ifp && rt->rt_ifp == ifp &&
X		    (rt->rt_state & RTS_INTERFACE) == 0)
X			continue;
X		if (rt->rt_state & RTS_EXTERNAL)
X			continue;
X		/*
X		 * For dynamic updates, limit update to routes
X		 * with the specified state.
X		 */
X		if (rtstate && (rt->rt_state & rtstate) == 0)
X			continue;
X		/*
X		 * Limit the spread of subnet information
X		 * to those who are interested.
X		 */
X		if (doinghost == 0 && rt->rt_state & RTS_SUBNET) {
X			if (rt->rt_dst.sa_family != dst->sa_family)
X				continue;
X			if ((*sendroute)(rt, dst) == 0)
X				continue;
X		}
X		size = (char *)n - packet;
X		if (size > MAXPACKETSIZE - sizeof (struct netinfo)) {
X			TRACE_OUTPUT(ifp, dst, size);
X			(*output)(s, flags, dst, size);
X			/*
X			 * If only sending to ourselves,
X			 * one packet is enough to monitor interface.
X			 */
X			if (ifp && (ifp->int_flags &
X			   (IFF_BROADCAST | IFF_POINTOPOINT | IFF_REMOTE)) == 0)
X				return;
X			n = msg->rip_nets;
X			npackets++;
X		}
X		n->rip_dst = rt->rt_dst;
#if BSD < 198810
X		if (sizeof(n->rip_dst.sa_family) > 1)	/* XXX */
X		n->rip_dst.sa_family = htons(n->rip_dst.sa_family);
#endif
X		n->rip_metric = htonl(rt->rt_metric);
X		n++;
X	}
X	if (doinghost) {
X		doinghost = 0;
X		base = nethash;
X		goto again;
X	}
X	if (n != msg->rip_nets || (npackets == 0 && rtstate == 0)) {
X		size = (char *)n - packet;
X		TRACE_OUTPUT(ifp, dst, size);
X		(*output)(s, flags, dst, size);
X	}
}
SHAR_EOF
  $shar_touch -am 0218122889 'vxrouted_5.1.1/BSDrouted/output.c' &&
  chmod 0444 'vxrouted_5.1.1/BSDrouted/output.c' ||
  echo 'restore of vxrouted_5.1.1/BSDrouted/output.c failed'
  shar_count="`wc -c < 'vxrouted_5.1.1/BSDrouted/output.c'`"
  test 4318 -eq "$shar_count" ||
    echo "vxrouted_5.1.1/BSDrouted/output.c: original size 4318, current size $shar_count"
  rm -f _sharnew.tmp
fi
# ============= vxrouted_5.1.1/BSDrouted/startup.c ==============
if test -f 'vxrouted_5.1.1/BSDrouted/startup.c' && test X"$1" != X"-c"; then
  echo 'x - skipping vxrouted_5.1.1/BSDrouted/startup.c (File already exists)'
  rm -f _sharnew.tmp
else
  > _sharnew.tmp
  echo 'x - extracting vxrouted_5.1.1/BSDrouted/startup.c (Text)'
  sed 's/^X//' << 'SHAR_EOF' > 'vxrouted_5.1.1/BSDrouted/startup.c' &&
/*
X * Copyright (c) 1983, 1988 Regents of the University of California.
X * All rights reserved.
X *
X * Redistribution and use in source and binary forms are permitted
X * provided that the above copyright notice and this paragraph are
X * duplicated in all such forms and that any documentation,
X * advertising materials, and other materials related to such
X * distribution and use acknowledge that the software was developed
X * by the University of California, Berkeley.  The name of the
X * University may not be used to endorse or promote products derived
X * from this software without specific prior written permission.
X * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
X * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
X * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
X */
X
#ifndef lint
static char sccsid[] = "@(#)startup.c	5.15 (Berkeley) 2/18/89";
#endif /* not lint */
X
/*
X * Routing Table Management Daemon
X */
#include "defs.h"
#include <sys/ioctl.h>
#include <net/if.h>
#include <syslog.h>
X
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 */
X
/*
X * Find the network interfaces which have configured themselves.
X * If the interface is present but not yet up (for example an
X * ARPANET IMP), set the lookforinterfaces flag so we'll
X * come back later and look again.
X */
ifinit()
{
X	struct interface ifs, *ifp;
X	int s, n;
X	char buf[BUFSIZ];
X        struct ifconf ifc;
X        struct ifreq ifreq, *ifr;
X        struct sockaddr_in *sin;
X	u_long i;
X
X	if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
X		syslog(LOG_ERR, "socket: %m");
X		close(s);
X                return;
X	}
X        ifc.ifc_len = sizeof (buf);
X        ifc.ifc_buf = buf;
X        if (ioctl(s, SIOCGIFCONF, (char *)&ifc) < 0) {
X                syslog(LOG_ERR, "ioctl (get interface configuration)");
X		close(s);
X                return;
X        }
X        ifr = ifc.ifc_req;
X	lookforinterfaces = 0;
X        for (n = ifc.ifc_len / sizeof (struct ifreq); n > 0; n--, ifr++) {
X		bzero((char *)&ifs, sizeof(ifs));
X		ifs.int_addr = ifr->ifr_addr;
X		ifreq = *ifr;
X                if (ioctl(s, SIOCGIFFLAGS, (char *)&ifreq) < 0) {
X                        syslog(LOG_ERR, "%s: ioctl (get interface flags)",
X			    ifr->ifr_name);
X                        continue;
X                }
X		ifs.int_flags = ifreq.ifr_flags | IFF_INTERFACE;
X		if ((ifs.int_flags & IFF_UP) == 0 ||
X		    ifr->ifr_addr.sa_family == AF_UNSPEC) {
X			lookforinterfaces = 1;
X			continue;
X		}
X		/* argh, this'll have to change sometime */
X		if (ifs.int_addr.sa_family != AF_INET)
X			continue;
X                if (ifs.int_flags & IFF_POINTOPOINT) {
X                        if (ioctl(s, SIOCGIFDSTADDR, (char *)&ifreq) < 0) {
X                                syslog(LOG_ERR, "%s: ioctl (get dstaddr)",
X				    ifr->ifr_name);
X                                continue;
X			}
X			if (ifr->ifr_addr.sa_family == AF_UNSPEC) {
X				lookforinterfaces = 1;
X				continue;
X			}
X			ifs.int_dstaddr = ifreq.ifr_dstaddr;
X		}
X		/*
X		 * already known to us?
X		 * This allows multiple point-to-point links
X		 * to share a source address (possibly with one
X		 * other link), but assumes that there will not be
X		 * multiple links with the same destination address.
X		 */
X		if (ifs.int_flags & IFF_POINTOPOINT) {
X			if (if_ifwithdstaddr(&ifs.int_dstaddr))
X				continue;
X		} else if (if_ifwithaddr(&ifs.int_addr))
X			continue;
X		if (ifs.int_flags & IFF_LOOPBACK) {
X			ifs.int_flags |= IFF_PASSIVE;
X			foundloopback = 1;
X			loopaddr = ifs.int_addr;
X			for (ifp = ifnet; ifp; ifp = ifp->int_next)
X			    if (ifp->int_flags & IFF_POINTOPOINT)
X				add_ptopt_localrt(ifp);
X		}
X                if (ifs.int_flags & IFF_BROADCAST) {
X                        if (ioctl(s, SIOCGIFBRDADDR, (char *)&ifreq) < 0) {
X                                syslog(LOG_ERR, "%s: ioctl (get broadaddr)",
X				    ifr->ifr_name);
X                                continue;
X                        }
#ifndef sun
X			ifs.int_broadaddr = ifreq.ifr_broadaddr;
#else
X			ifs.int_broadaddr = ifreq.ifr_addr;
#endif
X		}
#ifdef SIOCGIFMETRIC
X		if (ioctl(s, SIOCGIFMETRIC, (char *)&ifreq) < 0) {
X			syslog(LOG_ERR, "%s: ioctl (get metric)",
X			    ifr->ifr_name);
X			ifs.int_metric = 0;
X		} else
X			ifs.int_metric = ifreq.ifr_metric;
#else
X		ifs.int_metric = 0;
#endif
X		/*
X		 * Use a minimum metric of one;
X		 * treat the interface metric (default 0)
X		 * as an increment to the hop count of one.
X		 */
X		ifs.int_metric++;
X		if (ioctl(s, SIOCGIFNETMASK, (char *)&ifreq) < 0) {
X			syslog(LOG_ERR, "%s: ioctl (get netmask)",
X			    ifr->ifr_name);
X			continue;
X		}
X		sin = (struct sockaddr_in *)&ifreq.ifr_addr;
X		ifs.int_subnetmask = ntohl(sin->sin_addr.s_addr);
X		sin = (struct sockaddr_in *)&ifs.int_addr;
X		i = ntohl(sin->sin_addr.s_addr);
X		if (IN_CLASSA(i))
X			ifs.int_netmask = IN_CLASSA_NET;
X		else if (IN_CLASSB(i))
X			ifs.int_netmask = IN_CLASSB_NET;
X		else
X			ifs.int_netmask = IN_CLASSC_NET;
X		ifs.int_net = i & ifs.int_netmask;
X		ifs.int_subnet = i & ifs.int_subnetmask;
X		if (ifs.int_subnetmask != ifs.int_netmask)
X			ifs.int_flags |= IFF_SUBNET;
X		ifp = (struct interface *)malloc(sizeof (struct interface));
X		if (ifp == 0) {
X			printf("routed: out of memory\n");
X			break;
X		}
X		*ifp = ifs;
X		/*
X		 * Count the # of directly connected networks
X		 * and point to point links which aren't looped
X		 * back to ourself.  This is used below to
X		 * decide if we should be a routing ``supplier''.
X		 */
X		if ((ifs.int_flags & IFF_LOOPBACK) == 0 &&
X		    ((ifs.int_flags & IFF_POINTOPOINT) == 0 ||
X		    if_ifwithaddr(&ifs.int_dstaddr) == 0))
X			externalinterfaces++;
X		/*
X		 * If we have a point-to-point link, we want to act
X		 * as a supplier even if it's our only interface,
X		 * as that's the only way our peer on the other end
X		 * can tell that the link is up.
X		 */
X		if ((ifs.int_flags & IFF_POINTOPOINT) && supplier < 0)
X			supplier = 1;
X		ifp->int_name = malloc(strlen(ifr->ifr_name) + 1);
X		if (ifp->int_name == 0) {
X			fprintf(stderr, "routed: ifinit: out of memory\n");
X			syslog(LOG_ERR, "routed: ifinit: out of memory\n");
X			close(s);
X			return;
X		}
X		strcpy(ifp->int_name, ifr->ifr_name);
X		*ifnext = ifp;
X		ifnext = &ifp->int_next;
X		traceinit(ifp);
X		addrouteforif(ifp);
X	}
X	if (externalinterfaces > 1 && supplier < 0)
X		supplier = 1;
X	close(s);
}
X
/*
X * Add route for interface if not currently installed.
X * Create route to other end if a point-to-point link,
X * otherwise a route to this (sub)network.
X * INTERNET SPECIFIC.
X */
addrouteforif(ifp)
X	register struct interface *ifp;
{
X	struct sockaddr_in net;
X	struct sockaddr *dst;
X	int state;
X	register struct rt_entry *rt;
X
X	if (ifp->int_flags & IFF_POINTOPOINT)
X		dst = &ifp->int_dstaddr;
X	else {
X		bzero((char *)&net, sizeof (net));
X		net.sin_family = AF_INET;
X		net.sin_addr = inet_makeaddr(ifp->int_subnet, INADDR_ANY);
X		dst = (struct sockaddr *)&net;
X	}
X	rt = rtfind(dst);
X	if (rt &&
X	    (rt->rt_state & (RTS_INTERFACE | RTS_INTERNAL)) == RTS_INTERFACE)
X		return;
X	if (rt)
X		rtdelete(rt);
X	/*
X	 * If interface on subnetted network,
X	 * install route to network as well.
X	 * This is meant for external viewers.
X	 */
X	if ((ifp->int_flags & (IFF_SUBNET|IFF_POINTOPOINT)) == IFF_SUBNET) {
X		struct in_addr subnet;
X
X		subnet = net.sin_addr;
X		net.sin_addr = inet_makeaddr(ifp->int_net, INADDR_ANY);
X		rt = rtfind(dst);
X		if (rt == 0)
X			rtadd(dst, &ifp->int_addr, ifp->int_metric,
X			    ((ifp->int_flags & (IFF_INTERFACE|IFF_REMOTE)) |
X			    RTS_PASSIVE | RTS_INTERNAL | RTS_SUBNET));
X		else if ((rt->rt_state & (RTS_INTERNAL|RTS_SUBNET)) == 
X		    (RTS_INTERNAL|RTS_SUBNET) &&
X		    ifp->int_metric < rt->rt_metric)
X			rtchange(rt, &rt->rt_router, ifp->int_metric);
X		net.sin_addr = subnet;
X	}
X	if (ifp->int_transitions++ > 0)
X		syslog(LOG_ERR, "re-installing interface %s", ifp->int_name);
X	state = ifp->int_flags &
X	    (IFF_INTERFACE | IFF_PASSIVE | IFF_REMOTE | IFF_SUBNET);
X	if (ifp->int_flags & IFF_POINTOPOINT &&
X	    (ntohl(((struct sockaddr_in *)&ifp->int_dstaddr)->sin_addr.s_addr) &
X	    ifp->int_netmask) != ifp->int_net)
X		state &= ~RTS_SUBNET;
X	if (ifp->int_flags & IFF_LOOPBACK)
X		state |= RTS_EXTERNAL;
X	rtadd(dst, &ifp->int_addr, ifp->int_metric, state);
X	if (ifp->int_flags & IFF_POINTOPOINT && foundloopback)
X		add_ptopt_localrt(ifp);
}
X
/*
X * Add route to local end of point-to-point using loopback.
X * If a route to this network is being sent to neighbors on other nets,
X * mark this route as subnet so we don't have to propagate it too.
X */
add_ptopt_localrt(ifp)
X	register struct interface *ifp;
{
X	struct rt_entry *rt;
X	struct sockaddr *dst;
X	struct sockaddr_in net;
X	int state;
X
X	state = RTS_INTERFACE | RTS_PASSIVE;
X
X	/* look for route to logical network */
X	bzero((char *)&net, sizeof (net));
X	net.sin_family = AF_INET;
X	net.sin_addr = inet_makeaddr(ifp->int_net, INADDR_ANY);
X	dst = (struct sockaddr *)&net;
X	rt = rtfind(dst);
X	if (rt && rt->rt_state & RTS_INTERNAL)
X		state |= RTS_SUBNET;
X
X	dst = &ifp->int_addr;
X	if (rt = rtfind(dst)) {
X		if (rt && rt->rt_state & RTS_INTERFACE)
X			return;
X		rtdelete(rt);
X	}
X	rtadd(dst, &loopaddr, 1, state);
}
X
/*
X * As a concession to the ARPANET we read a list of gateways
X * from /etc/gateways and add them to our tables.  This file
X * exists at each ARPANET gateway and indicates a set of ``remote''
X * gateways (i.e. a gateway which we can't immediately determine
X * if it's present or not as we can do for those directly connected
X * at the hardware level).  If a gateway is marked ``passive''
X * in the file, then we assume it doesn't have a routing process
X * of our design and simply assume it's always present.  Those
X * not marked passive are treated as if they were directly
X * connected -- they're added into the interface list so we'll
X * send them routing updates.
X *
X * PASSIVE ENTRIES AREN'T NEEDED OR USED ON GATEWAYS RUNNING EGP.
X */
gwkludge()
{
X	struct sockaddr_in dst, gate;
X	FILE *fp;
X	char *type, *dname, *gname, *qual, buf[BUFSIZ];
X	struct interface *ifp;
X	int metric, n;
X	struct rt_entry route;
X
X	fp = fopen("/etc/gateways", "r");
X	if (fp == NULL)
X		return;
X	qual = buf;
X	dname = buf + 64;
X	gname = buf + ((BUFSIZ - 64) / 3);
X	type = buf + (((BUFSIZ - 64) * 2) / 3);
X	bzero((char *)&dst, sizeof (dst));
X	bzero((char *)&gate, sizeof (gate));
X	bzero((char *)&route, sizeof(route));
/* format: {net | host} XX gateway XX metric DD [passive | external]\n */
#define	readentry(fp) \
X	fscanf((fp), "%s %s gateway %s metric %d %s\n", \
X		type, dname, gname, &metric, qual)
X	for (;;) {
X		if ((n = readentry(fp)) == EOF)
X			break;
X		if (!getnetorhostname(type, dname, &dst))
X			continue;
X		if (!gethostnameornumber(gname, &gate))
X			continue;
X		if (metric == 0)			/* XXX */
X			metric = 1;
X		if (strcmp(qual, "passive") == 0) {
X			/*
X			 * Passive entries aren't placed in our tables,
X			 * only the kernel's, so we don't copy all of the
X			 * external routing information within a net.
X			 * Internal machines should use the default
X			 * route to a suitable gateway (like us).
X			 */
X			route.rt_dst = *(struct sockaddr *) &dst;
X			route.rt_router = *(struct sockaddr *) &gate;
X			route.rt_flags = RTF_UP;
X			if (strcmp(type, "host") == 0)
X				route.rt_flags |= RTF_HOST;
X			if (metric)
X				route.rt_flags |= RTF_GATEWAY;
X			(void) ioctl(s, SIOCADDRT, (char *)&route.rt_rt);
X			continue;
X		}
X		if (strcmp(qual, "external") == 0) {
X			/*
X			 * Entries marked external are handled
X			 * by other means, e.g. EGP,
X			 * and are placed in our tables only
X			 * to prevent overriding them
X			 * with something else.
X			 */
X			rtadd(&dst, &gate, metric, RTS_EXTERNAL|RTS_PASSIVE);
X			continue;
X		}
X		/* assume no duplicate entries */
X		externalinterfaces++;
X		ifp = (struct interface *)malloc(sizeof (*ifp));
X		bzero((char *)ifp, sizeof (*ifp));
X		ifp->int_flags = IFF_REMOTE;
X		/* can't identify broadcast capability */
X		ifp->int_net = inet_netof(dst.sin_addr);
X		if (strcmp(type, "host") == 0) {
X			ifp->int_flags |= IFF_POINTOPOINT;
X			ifp->int_dstaddr = *((struct sockaddr *)&dst);
X		}
X		ifp->int_addr = *((struct sockaddr *)&gate);
X		ifp->int_metric = metric;
X		ifp->int_next = ifnet;
X		ifnet = ifp;
X		addrouteforif(ifp);
X	}
X	fclose(fp);
}
X
getnetorhostname(type, name, sin)
X	char *type, *name;
X	struct sockaddr_in *sin;
{
X
X	if (strcmp(type, "net") == 0) {
X		struct netent *np = getnetbyname(name);
X		int n;
X
X		if (np == 0)
X			n = inet_network(name);
X		else {
X			if (np->n_addrtype != AF_INET)
X				return (0);
X			n = np->n_net;
X			/*
X			 * getnetbyname returns right-adjusted value.
X			 */
X			if (n < 128)
X				n <<= IN_CLASSA_NSHIFT;
X			else if (n < 65536)
X				n <<= IN_CLASSB_NSHIFT;
X			else
X				n <<= IN_CLASSC_NSHIFT;
X		}
X		sin->sin_family = AF_INET;
X		sin->sin_addr = inet_makeaddr(n, INADDR_ANY);
X		return (1);
X	}
X	if (strcmp(type, "host") == 0) {
X		struct hostent *hp = gethostbyname(name);
X
X		if (hp == 0)
X			sin->sin_addr.s_addr = inet_addr(name);
X		else {
X			if (hp->h_addrtype != AF_INET)
X				return (0);
X			bcopy(hp->h_addr, &sin->sin_addr, hp->h_length);
X		}
X		sin->sin_family = AF_INET;
X		return (1);
X	}
X	return (0);
}
X
gethostnameornumber(name, sin)
X	char *name;
X	struct sockaddr_in *sin;
{
X	struct hostent *hp;
X
X	hp = gethostbyname(name);
X	if (hp) {
X		bcopy(hp->h_addr, &sin->sin_addr, hp->h_length);
X		sin->sin_family = hp->h_addrtype;
X		return (1);
X	}
X	sin->sin_addr.s_addr = inet_addr(name);
X	sin->sin_family = AF_INET;
X	return (sin->sin_addr.s_addr != -1);
}
SHAR_EOF
  $shar_touch -am 0218122889 'vxrouted_5.1.1/BSDrouted/startup.c' &&
  chmod 0444 'vxrouted_5.1.1/BSDrouted/startup.c' ||
  echo 'restore of vxrouted_5.1.1/BSDrouted/startup.c failed'
  shar_count="`wc -c < 'vxrouted_5.1.1/BSDrouted/startup.c'`"
  test 13572 -eq "$shar_count" ||
    echo "vxrouted_5.1.1/BSDrouted/startup.c: original size 13572, current size $shar_count"
  rm -f _sharnew.tmp
fi
# ============= vxrouted_5.1.1/BSDrouted/table.h ==============
if test -f 'vxrouted_5.1.1/BSDrouted/table.h' && test X"$1" != X"-c"; then
  echo 'x - skipping vxrouted_5.1.1/BSDrouted/table.h (File already exists)'
  rm -f _sharnew.tmp
else
  > _sharnew.tmp
  echo 'x - extracting vxrouted_5.1.1/BSDrouted/table.h (Text)'
  sed 's/^X//' << 'SHAR_EOF' > 'vxrouted_5.1.1/BSDrouted/table.h' &&
/*
X * Copyright (c) 1983 Regents of the University of California.
X * All rights reserved.
X *
X * Redistribution and use in source and binary forms are permitted
X * provided that the above copyright notice and this paragraph are
X * duplicated in all such forms and that any documentation,
X * advertising materials, and other materials related to such
X * distribution and use acknowledge that the software was developed
X * by the University of California, Berkeley.  The name of the
X * University may not be used to endorse or promote products derived
X * from this software without specific prior written permission.
X * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
X * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
X * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
X *
X *	@(#)table.h	5.6 (Berkeley) 6/18/88
X */
X
/*
X * Routing table management daemon.
X */
X
/*
X * Routing table structure; differs a bit from kernel tables.
X *
X * Note: the union below must agree in the first 4 members
X * so the ioctl's will work.
X */
struct rthash {
X	struct	rt_entry *rt_forw;
X	struct	rt_entry *rt_back;
};
X
struct rt_entry {
X	struct	rt_entry *rt_forw;
X	struct	rt_entry *rt_back;
X	union {
X		struct	rtentry rtu_rt;
X		struct {
X			u_long	rtu_hash;
X			struct	sockaddr rtu_dst;
X			struct	sockaddr rtu_router;
X			short	rtu_flags;
X			short	rtu_state;
X			int	rtu_timer;
X			int	rtu_metric;
X			int	rtu_ifmetric;
X			struct	interface *rtu_ifp;
X		} rtu_entry;
X	} rt_rtu;
};
X
#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 */
X
#define	ROUTEHASHSIZ	32		/* must be a power of 2 */
#define	ROUTEHASHMASK	(ROUTEHASHSIZ - 1)
X
/*
X * "State" of routing table entry.
X */
#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 */
X
/*
X * Flags are same as kernel, with this addition for af_rtflags:
X */
#define	RTF_SUBNET	0x8000		/* pseudo: route to subnet */
X
struct	rthash nethash[ROUTEHASHSIZ];
struct	rthash hosthash[ROUTEHASHSIZ];
struct	rt_entry *rtlookup();
struct	rt_entry *rtfind();
SHAR_EOF
  $shar_touch -am 0218122989 'vxrouted_5.1.1/BSDrouted/table.h' &&
  chmod 0444 'vxrouted_5.1.1/BSDrouted/table.h' ||
  echo 'restore of vxrouted_5.1.1/BSDrouted/table.h failed'
  shar_count="`wc -c < 'vxrouted_5.1.1/BSDrouted/table.h'`"
  test 2987 -eq "$shar_count" ||
    echo "vxrouted_5.1.1/BSDrouted/table.h: original size 2987, current size $shar_count"
  rm -f _sharnew.tmp
fi
# ============= vxrouted_5.1.1/BSDrouted/timer.c ==============
if test -f 'vxrouted_5.1.1/BSDrouted/timer.c' && test X"$1" != X"-c"; then
  echo 'x - skipping vxrouted_5.1.1/BSDrouted/timer.c (File already exists)'
  rm -f _sharnew.tmp
else
  > _sharnew.tmp
  echo 'x - extracting vxrouted_5.1.1/BSDrouted/timer.c (Text)'
  sed 's/^X//' << 'SHAR_EOF' > 'vxrouted_5.1.1/BSDrouted/timer.c' &&
/*
X * Copyright (c) 1983, 1988 Regents of the University of California.
X * All rights reserved.
X *
X * Redistribution and use in source and binary forms are permitted
X * provided that the above copyright notice and this paragraph are
X * duplicated in all such forms and that any documentation,
X * advertising materials, and other materials related to such
X * distribution and use acknowledge that the software was developed
X * by the University of California, Berkeley.  The name of the
X * University may not be used to endorse or promote products derived
X * from this software without specific prior written permission.
X * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
X * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
X * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
X */
X
#ifndef lint
static char sccsid[] = "@(#)timer.c	5.8 (Berkeley) 2/18/89";
#endif /* not lint */
X
/*
X * Routing Table Management Daemon
X */
#include "defs.h"
X
int	faketime;
X
/*
X * Timer routine.  Performs routing information supply
X * duties and manages timers on routing table entries.
X * Management of the RTS_CHANGED bit assumes that we broadcast
X * each time called.
X */
timer()
{
X	register struct rthash *rh;
X	register struct rt_entry *rt;
X	struct rthash *base = hosthash;
X	int doinghost = 1, timetobroadcast;
X	extern int externalinterfaces;
X
X	(void) gettimeofday(&now, (struct timezone *)NULL);
X	faketime += TIMER_RATE;
X	if (lookforinterfaces && (faketime % CHECK_INTERVAL) == 0)
X		ifinit();
X	timetobroadcast = supplier && (faketime % SUPPLY_INTERVAL) == 0;
again:
X	for (rh = base; rh < &base[ROUTEHASHSIZ]; rh++) {
X		rt = rh->rt_forw;
X		for (; rt != (struct rt_entry *)rh; rt = rt->rt_forw) {
X			/*
X			 * We don't advance time on a routing entry for
X			 * a passive gateway, or any interface if we're
X			 * not acting as supplier.
X			 */
X			if (!(rt->rt_state & RTS_PASSIVE) &&
X			    (supplier || !(rt->rt_state & RTS_INTERFACE)))
X				rt->rt_timer += TIMER_RATE;
X			if (rt->rt_timer >= GARBAGE_TIME) {
X				rt = rt->rt_back;
X				rtdelete(rt->rt_forw);
X				continue;
X			}
X			if (rt->rt_timer >= EXPIRE_TIME &&
X			    rt->rt_metric < HOPCNT_INFINITY)
X				rtchange(rt, &rt->rt_router, HOPCNT_INFINITY);
X			rt->rt_state &= ~RTS_CHANGED;
X		}
X	}
X	if (doinghost) {
X		doinghost = 0;
X		base = nethash;
X		goto again;
X	}
X	if (timetobroadcast) {
X		toall(supply, 0, (struct interface *)NULL);
X		lastbcast = now;
X		lastfullupdate = now;
X		needupdate = 0;		/* cancel any pending dynamic update */
X		nextbcast.tv_sec = 0;
X	}
}
X
/*
X * On hangup, let everyone know we're going away.
X */
hup()
{
X	register struct rthash *rh;
X	register struct rt_entry *rt;
X	struct rthash *base = hosthash;
X	int doinghost = 1;
X
X	if (supplier) {
again:
X		for (rh = base; rh < &base[ROUTEHASHSIZ]; rh++) {
X			rt = rh->rt_forw;
X			for (; rt != (struct rt_entry *)rh; rt = rt->rt_forw)
X				rt->rt_metric = HOPCNT_INFINITY;
X		}
X		if (doinghost) {
X			doinghost = 0;
X			base = nethash;
X			goto again;
X		}
X		toall(supply, 0, (struct interface *)NULL);
X	}
X	exit(1);
}
SHAR_EOF
  $shar_touch -am 0218122889 'vxrouted_5.1.1/BSDrouted/timer.c' &&
  chmod 0444 'vxrouted_5.1.1/BSDrouted/timer.c' ||
  echo 'restore of vxrouted_5.1.1/BSDrouted/timer.c failed'
  shar_count="`wc -c < 'vxrouted_5.1.1/BSDrouted/timer.c'`"
  test 3056 -eq "$shar_count" ||
    echo "vxrouted_5.1.1/BSDrouted/timer.c: original size 3056, current size $shar_count"
  rm -f _sharnew.tmp
fi
# ============= vxrouted_5.1.1/BSDrouted/trace.c ==============
if test -f 'vxrouted_5.1.1/BSDrouted/trace.c' && test X"$1" != X"-c"; then
  echo 'x - skipping vxrouted_5.1.1/BSDrouted/trace.c (File already exists)'
  rm -f _sharnew.tmp
else
  > _sharnew.tmp
  echo 'x - extracting vxrouted_5.1.1/BSDrouted/trace.c (Text)'
  sed 's/^X//' << 'SHAR_EOF' > 'vxrouted_5.1.1/BSDrouted/trace.c' &&
/*
X * Copyright (c) 1983, 1988 Regents of the University of California.
X * All rights reserved.
X *
X * Redistribution and use in source and binary forms are permitted
X * provided that the above copyright notice and this paragraph are
X * duplicated in all such forms and that any documentation,
X * advertising materials, and other materials related to such
X * distribution and use acknowledge that the software was developed
X * by the University of California, Berkeley.  The name of the
X * University may not be used to endorse or promote products derived
X * from this software without specific prior written permission.
X * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
X * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
X * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
X */
X
#ifndef lint
static char sccsid[] = "@(#)trace.c	5.8 (Berkeley) 2/18/89";
#endif /* not lint */
X
/*
X * Routing Table Management Daemon
X */
#define	RIPCMDS
#include "defs.h"
#include <sys/file.h>
#include <sys/stat.h>
#include <sys/signal.h>
X
#define	NRECORDS	50		/* size of circular trace buffer */
#ifdef DEBUG
FILE	*ftrace = stdout;
int	traceactions = 0;
#endif
static	struct timeval lastlog;
static	char *savetracename;
X
traceinit(ifp)
X	register struct interface *ifp;
{
X
X	if (iftraceinit(ifp, &ifp->int_input) &&
X	    iftraceinit(ifp, &ifp->int_output))
X		return;
X	tracehistory = 0;
X	fprintf(stderr, "traceinit: can't init %s\n", ifp->int_name);
}
X
static
iftraceinit(ifp, ifd)
X	struct interface *ifp;
X	register struct ifdebug *ifd;
{
X	register struct iftrace *t;
X
X	ifd->ifd_records =
X	  (struct iftrace *)malloc(NRECORDS * sizeof (struct iftrace));
X	if (ifd->ifd_records == 0)
X		return (0);
X	ifd->ifd_front = ifd->ifd_records;
X	ifd->ifd_count = 0;
X	for (t = ifd->ifd_records; t < ifd->ifd_records + NRECORDS; t++) {
X		t->ift_size = 0;
X		t->ift_packet = 0;
X	}
X	ifd->ifd_if = ifp;
X	return (1);
}
X
traceon(file)
X	char *file;
{
X	struct stat stbuf;
X
X	if (ftrace != NULL)
X		return;
X	if (stat(file, &stbuf) >= 0 && (stbuf.st_mode & S_IFMT) != S_IFREG)
X		return;
X	savetracename = file;
X	(void) gettimeofday(&now, (struct timezone *)NULL);
X	ftrace = fopen(file, "a");
X	if (ftrace == NULL)
X		return;
X	dup2(fileno(ftrace), 1);
X	dup2(fileno(ftrace), 2);
X	traceactions = 1;
X	fprintf(ftrace, "Tracing enabled %s\n", ctime((time_t *)&now.tv_sec));
}
X
traceoff()
{
X	if (!traceactions)
X		return;
X	if (ftrace != NULL) {
X		int fd = open("/dev/null", O_RDWR);
X
X		fprintf(ftrace, "Tracing disabled %s\n",
X		    ctime((time_t *)&now.tv_sec));
X		fflush(ftrace);
X		(void) dup2(fd, 1);
X		(void) dup2(fd, 2);
X		(void) close(fd);
X		fclose(ftrace);
X		ftrace = NULL;
X	}
X	traceactions = 0;
X	tracehistory = 0;
X	tracepackets = 0;
X	tracecontents = 0;
}
X
sigtrace(s)
X	int s;
{
X
X	if (s == SIGUSR2)
X		traceoff();
X	else if (ftrace == NULL && savetracename)
X		traceon(savetracename);
X	else
X		bumploglevel();
}
X
/*
X * Move to next higher level of tracing when -t option processed or
X * SIGUSR1 is received.  Successive levels are:
X *	traceactions
X *	traceactions + tracepackets
X *	traceactions + tracehistory (packets and contents after change)
X *	traceactions + tracepackets + tracecontents
X */
bumploglevel()
{
X
X	(void) gettimeofday(&now, (struct timezone *)NULL);
X	if (traceactions == 0) {
X		traceactions++;
X		if (ftrace)
X			fprintf(ftrace, "Tracing actions started %s\n",
X			    ctime((time_t *)&now.tv_sec));
X	} else if (tracepackets == 0) {
X		tracepackets++;
X		tracehistory = 0;
X		tracecontents = 0;
X		if (ftrace)
X			fprintf(ftrace, "Tracing packets started %s\n",
X			    ctime((time_t *)&now.tv_sec));
X	} else if (tracehistory == 0) {
X		tracehistory++;
X		if (ftrace)
X			fprintf(ftrace, "Tracing history started %s\n",
X			    ctime((time_t *)&now.tv_sec));
X	} else {
X		tracepackets++;
X		tracecontents++;
X		tracehistory = 0;
X		if (ftrace)
X			fprintf(ftrace, "Tracing packet contents started %s\n",
X			    ctime((time_t *)&now.tv_sec));
X	}
X	if (ftrace)
X		fflush(ftrace);
}
X
trace(ifd, who, p, len, m)
X	register struct ifdebug *ifd;
X	struct sockaddr *who;
X	char *p;
X	int len, m;
{
X	register struct iftrace *t;
X
X	if (ifd->ifd_records == 0)
X		return;
X	t = ifd->ifd_front++;
X	if (ifd->ifd_front >= ifd->ifd_records + NRECORDS)
X		ifd->ifd_front = ifd->ifd_records;
X	if (ifd->ifd_count < NRECORDS)
X		ifd->ifd_count++;
X	if (t->ift_size > 0 && t->ift_size < len && t->ift_packet) {
X		free(t->ift_packet);
X		t->ift_packet = 0;
X	}
X	t->ift_stamp = now;
X	t->ift_who = *who;
X	if (len > 0 && t->ift_packet == 0) {
X		t->ift_packet = malloc(len);
X		if (t->ift_packet == 0)
X			len = 0;
X	}
X	if (len > 0)
X		bcopy(p, t->ift_packet, len);
X	t->ift_size = len;
X	t->ift_metric = m;
}
X
traceaction(fd, action, rt)
X	FILE *fd;
X	char *action;
X	struct rt_entry *rt;
{
X	struct sockaddr_in *dst, *gate;
X	static struct bits {
X		int	t_bits;
X		char	*t_name;
X	} flagbits[] = {
X		{ RTF_UP,	"UP" },
X		{ RTF_GATEWAY,	"GATEWAY" },
X		{ RTF_HOST,	"HOST" },
X		{ 0 }
X	}, statebits[] = {
X		{ RTS_PASSIVE,	"PASSIVE" },
X		{ RTS_REMOTE,	"REMOTE" },
X		{ RTS_INTERFACE,"INTERFACE" },
X		{ RTS_CHANGED,	"CHANGED" },
X		{ RTS_INTERNAL,	"INTERNAL" },
X		{ RTS_EXTERNAL,	"EXTERNAL" },
X		{ RTS_SUBNET,	"SUBNET" },
X		{ 0 }
X	};
X	register struct bits *p;
X	register int first;
X	char *cp;
X	struct interface *ifp;
X
X	if (fd == NULL)
X		return;
X	if (lastlog.tv_sec != now.tv_sec || lastlog.tv_usec != now.tv_usec) {
X		fprintf(fd, "\n%.19s:\n", ctime((time_t *)&now.tv_sec));
X		lastlog = now;
X	}
X	fprintf(fd, "%s ", action);
X	dst = (struct sockaddr_in *)&rt->rt_dst;
X	gate = (struct sockaddr_in *)&rt->rt_router;
X	fprintf(fd, "dst %s, ", inet_ntoa(dst->sin_addr));
X	fprintf(fd, "router %s, metric %d, flags",
X	     inet_ntoa(gate->sin_addr), rt->rt_metric);
X	cp = " %s";
X	for (first = 1, p = flagbits; p->t_bits > 0; p++) {
X		if ((rt->rt_flags & p->t_bits) == 0)
X			continue;
X		fprintf(fd, cp, p->t_name);
X		if (first) {
X			cp = "|%s";
X			first = 0;
X		}
X	}
X	fprintf(fd, " state");
X	cp = " %s";
X	for (first = 1, p = statebits; p->t_bits > 0; p++) {
X		if ((rt->rt_state & p->t_bits) == 0)
X			continue;
X		fprintf(fd, cp, p->t_name);
X		if (first) {
X			cp = "|%s";
X			first = 0;
X		}
X	}
X	fprintf(fd, " timer %d\n", rt->rt_timer);
X	if (tracehistory && !tracepackets &&
X	    (rt->rt_state & RTS_PASSIVE) == 0 && rt->rt_ifp)
X		dumpif(fd, rt->rt_ifp);
X	fflush(fd);
X	if (ferror(fd))
X		traceoff();
}
X
tracenewmetric(fd, rt, newmetric)
X	FILE *fd;
X	struct rt_entry *rt;
X	int newmetric;
{
X	struct sockaddr_in *dst, *gate;
X
X	if (fd == NULL)
X		return;
X	if (lastlog.tv_sec != now.tv_sec || lastlog.tv_usec != now.tv_usec) {
X		fprintf(fd, "\n%.19s:\n", ctime((time_t *)&now.tv_sec));
X		lastlog = now;
X	}
X	dst = (struct sockaddr_in *)&rt->rt_dst;
X	gate = (struct sockaddr_in *)&rt->rt_router;
X	fprintf(fd, "CHANGE metric dst %s, ", inet_ntoa(dst->sin_addr));
X	fprintf(fd, "router %s, from %d to %d\n",
X	     inet_ntoa(gate->sin_addr), rt->rt_metric, newmetric);
X	fflush(fd);
X	if (ferror(fd))
X		traceoff();
}
X
dumpif(fd, ifp)
X	FILE *fd;
X	register struct interface *ifp;
{
X	if (ifp->int_input.ifd_count || ifp->int_output.ifd_count) {
X		fprintf(fd, "*** Packet history for interface %s ***\n",
X			ifp->int_name);
#ifdef notneeded
X		dumptrace(fd, "to", &ifp->int_output);
#endif
X		dumptrace(fd, "from", &ifp->int_input);
X		fprintf(fd, "*** end packet history ***\n");
X	}
}
X
dumptrace(fd, dir, ifd)
X	FILE *fd;
X	char *dir;
X	register struct ifdebug *ifd;
{
X	register struct iftrace *t;
X	char *cp = !strcmp(dir, "to") ? "Output" : "Input";
X
X	if (ifd->ifd_front == ifd->ifd_records &&
X	    ifd->ifd_front->ift_size == 0) {
X		fprintf(fd, "%s: no packets.\n", cp);
X		fflush(fd);
X		return;
X	}
X	fprintf(fd, "%s trace:\n", cp);
X	t = ifd->ifd_front - ifd->ifd_count;
X	if (t < ifd->ifd_records)
X		t += NRECORDS;
X	for ( ; ifd->ifd_count; ifd->ifd_count--, t++) {
X		if (t >= ifd->ifd_records + NRECORDS)
X			t = ifd->ifd_records;
X		if (t->ift_size == 0)
X			continue;
X		dumppacket(fd, dir, &t->ift_who, t->ift_packet, t->ift_size,
X		    &t->ift_stamp);
X	}
}
X
dumppacket(fd, dir, who, cp, size, stamp)
X	FILE *fd;
X	struct sockaddr_in *who;		/* should be sockaddr */
X	char *dir, *cp;
X	register int size;
X	struct timeval *stamp;
{
X	register struct rip *msg = (struct rip *)cp;
X	register struct netinfo *n;
X
X	if (fd == NULL)
X		return;
X	if (msg->rip_cmd && msg->rip_cmd < RIPCMD_MAX)
X		fprintf(fd, "%s %s %s.%d %.19s:\n", ripcmds[msg->rip_cmd],
X		    dir, inet_ntoa(who->sin_addr), ntohs(who->sin_port),
X		    ctime((time_t *)&stamp->tv_sec));
X	else {
X		fprintf(fd, "Bad cmd 0x%x %s %x.%d %.19s\n", msg->rip_cmd,
X		    dir, inet_ntoa(who->sin_addr), ntohs(who->sin_port));
SHAR_EOF
  : || echo 'restore of vxrouted_5.1.1/BSDrouted/trace.c failed'
fi
echo 'End of archive part 7'
echo 'File vxrouted_5.1.1/BSDrouted/trace.c is continued in part 8'
echo 8 > _sharseq.tmp
exit 0
