summaryrefslogtreecommitdiffstats
path: root/usr.sbin
diff options
context:
space:
mode:
authorwollman <wollman@FreeBSD.org>1996-09-16 16:56:00 +0000
committerwollman <wollman@FreeBSD.org>1996-09-16 16:56:00 +0000
commit5dd2c963ce7fe11b20171b5fc8e2398c1303a926 (patch)
treeed286bb6211bca3d82711f7f30bb44234497ea38 /usr.sbin
parent51fe89959db2bf393dbac9c84aa7024ab4dae90c (diff)
downloadFreeBSD-src-5dd2c963ce7fe11b20171b5fc8e2398c1303a926.zip
FreeBSD-src-5dd2c963ce7fe11b20171b5fc8e2398c1303a926.tar.gz
Delete old routed(8).
Diffstat (limited to 'usr.sbin')
-rw-r--r--usr.sbin/routed/Makefile10
-rw-r--r--usr.sbin/routed/Makefile.inc1
-rw-r--r--usr.sbin/routed/defs.h561
-rw-r--r--usr.sbin/routed/if.c1132
-rw-r--r--usr.sbin/routed/input.c714
-rw-r--r--usr.sbin/routed/main.c824
-rw-r--r--usr.sbin/routed/output.c858
-rw-r--r--usr.sbin/routed/parms.c563
-rw-r--r--usr.sbin/routed/pathnames.h47
-rw-r--r--usr.sbin/routed/radix.c894
-rw-r--r--usr.sbin/routed/radix.h161
-rw-r--r--usr.sbin/routed/rdisc.c1032
-rw-r--r--usr.sbin/routed/routed.8602
-rw-r--r--usr.sbin/routed/rtquery/Makefile8
-rw-r--r--usr.sbin/routed/rtquery/rtquery.879
-rw-r--r--usr.sbin/routed/rtquery/rtquery.c516
-rw-r--r--usr.sbin/routed/table.c1961
-rw-r--r--usr.sbin/routed/trace.c800
18 files changed, 0 insertions, 10763 deletions
diff --git a/usr.sbin/routed/Makefile b/usr.sbin/routed/Makefile
deleted file mode 100644
index b17fd70..0000000
--- a/usr.sbin/routed/Makefile
+++ /dev/null
@@ -1,10 +0,0 @@
-# From: @(#)Makefile 8.1 (Berkeley) 6/19/93
-# $Id$
-
-PROG= routed
-SRCS= if.c input.c main.c output.c parms.c radix.c rdisc.c table.c trace.c
-MAN8= routed.8
-SUBDIR= rtquery
-#COPTS= -g -DDEBUG -Wall
-
-.include <bsd.prog.mk>
diff --git a/usr.sbin/routed/Makefile.inc b/usr.sbin/routed/Makefile.inc
deleted file mode 100644
index 10fa13f..0000000
--- a/usr.sbin/routed/Makefile.inc
+++ /dev/null
@@ -1 +0,0 @@
-.include "../../Makefile.inc"
diff --git a/usr.sbin/routed/defs.h b/usr.sbin/routed/defs.h
deleted file mode 100644
index 05c2403..0000000
--- a/usr.sbin/routed/defs.h
+++ /dev/null
@@ -1,561 +0,0 @@
-/*
- * Copyright (c) 1983, 1988, 1993
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * @(#)defs.h 8.1 (Berkeley) 6/5/93
- * $Id: defs.h,v 1.4 1996/07/22 21:12:14 wollman Exp $
- */
-
-#ifndef __NetBSD__
-#ident "$Revision: 1.1.3.3 $"
-#endif
-
-/* Definitions for RIPv2 routing process.
- *
- * This code is based on the 4.4BSD `routed` daemon, with extensions to
- * support:
- * RIPv2, including variable length subnet masks.
- * Router Discovery
- * aggregate routes in the kernel tables.
- * aggregate advertised routes.
- * maintain spare routes for faster selection of another gateway
- * when the current gateway dies.
- * timers on routes with second granularity so that selection
- * of a new route does not wait 30-60 seconds.
- * tolerance of static routes.
- * tell the kernel hop counts
- * do not advertise if ipforwarding=0
- *
- * The vestigual support for other protocols has been removed. There
- * is no likelihood that IETF RIPv1 or RIPv2 will ever be used with
- * other protocols. The result is far smaller, faster, cleaner, and
- * perhaps understandable.
- *
- * The accumulation of special flags and kludges added over the many
- * years have been simplified and integrated.
- */
-
-#include <stdio.h>
-#include <netdb.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <errno.h>
-#include <string.h>
-#ifdef sgi
-#include <strings.h>
-#include <bstring.h>
-#endif
-#include <stdarg.h>
-#include <syslog.h>
-#include <time.h>
-#include <sys/types.h>
-#include <sys/param.h>
-#include <sys/ioctl.h>
-#include <sys/sysctl.h>
-#include <sys/socket.h>
-#ifdef sgi
-#include <net/radix.h>
-#else
-#include "radix.h"
-#endif
-#include <net/if.h>
-#include <net/route.h>
-#include <net/if_dl.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#define RIPVERSION RIPv2
-#include <protocols/routed.h>
-
-
-/* Type of an IP address.
- * Some systems do not like to pass structures, so do not use in_addr.
- * Some systems think a long has 64 bits, which would be a gross waste.
- * So define it here so it can be changed for the target system.
- * It should be defined somewhere netinet/in.h, but it is not.
- */
-#ifdef sgi
-#define naddr __uint32_t
-#else
-#ifdef __NetBSD__
-#define naddr u_int32_t
-#else
-#define naddr u_long
-#endif
-#define _HAVE_SA_LEN
-#define _HAVE_SIN_LEN
-#endif
-
-/* Turn on if IP_DROP_MEMBERSHIP and IP_ADD_MEMBERSHIP do not look at
- * the dstaddr of point-to-point interfaces.
- */
-/* #define MCAST_PPP_BUG */
-
-#define NEVER (24*60*60) /* a long time */
-#define EPOCH NEVER /* bias time by this to avoid <0 */
-
-/* Scan the kernel regularly to see if any interfaces have appeared or been
- * turned off. These must be less than STALE_TIME.
- */
-#define CHECK_BAD_INTERVAL 5 /* when an interface is known bad */
-#define CHECK_ACT_INTERVAL 30 /* when advertising */
-#define CHECK_QUIET_INTERVAL 300 /* when not */
-
-#define LIM_SEC(s,l) ((s).tv_sec = MIN((s).tv_sec, (l)))
-
-
-/* Router Discovery parameters */
-#ifndef sgi
-#define INADDR_ALLROUTERS_GROUP 0xe0000002 /* 224.0.0.2 */
-#endif
-#define MaxMaxAdvertiseInterval 1800
-#define MinMaxAdvertiseInterval 4
-#define DefMaxAdvertiseInterval 600
-#define DEF_PreferenceLevel 0
-#define MIN_PreferenceLevel 0x80000000
-
-#define MAX_INITIAL_ADVERT_INTERVAL 16
-#define MAX_INITIAL_ADVERTS 3
-#define MAX_RESPONSE_DELAY 2
-
-#define MAX_SOLICITATION_DELAY 1
-#define SOLICITATION_INTERVAL 3
-#define MAX_SOLICITATIONS 3
-
-
-/* typical packet buffers */
-union pkt_buf {
- char packet[MAXPACKETSIZE+1];
- struct rip rip;
-};
-
-
-/* no more routes than this, to protect ourself in case something goes
- * whacko and starts broadcast zillions of bogus routes.
- */
-#define MAX_ROUTES (128*1024)
-extern int total_routes;
-
-/* Main, daemon routing table structure
- */
-struct rt_entry {
- struct radix_node rt_nodes[2]; /* radix tree glue */
- u_int rt_state;
-# define RS_IF 0x001 /* for network interface */
-# define RS_NET_INT 0x002 /* authority route */
-# define RS_NET_SYN 0x004 /* fake net route for subnet */
-# define RS_NO_NET_SYN (RS_LOCAL | RS_LOCAL | RS_IF)
-# define RS_SUBNET 0x008 /* subnet route from any source */
-# define RS_LOCAL 0x010 /* loopback for pt-to-pt */
-# define RS_MHOME 0x020 /* from -m */
-# define RS_STATIC 0x040 /* from the kernel */
-# define RS_RDISC 0x080 /* from router discovery */
-# define RS_PERMANENT (RS_MHOME | RS_STATIC | RS_NET_SYN | RS_RDISC)
- struct sockaddr_in rt_dst_sock;
- naddr rt_mask;
- struct rt_spare {
- struct interface *rts_ifp;
- naddr rts_gate; /* forward packets here */
- naddr rts_router; /* on the authority of this router */
- char rts_metric;
- u_short rts_tag;
- time_t rts_time; /* timer to junk stale routes */
-#define NUM_SPARES 4
- } rt_spares[NUM_SPARES];
- u_int rt_seqno; /* when last changed */
- char rt_poison_metric; /* to notice maximum recently */
- time_t rt_poison_time; /* advertised metric */
-};
-#define rt_dst rt_dst_sock.sin_addr.s_addr
-#define rt_ifp rt_spares[0].rts_ifp
-#define rt_gate rt_spares[0].rts_gate
-#define rt_router rt_spares[0].rts_router
-#define rt_metric rt_spares[0].rts_metric
-#define rt_tag rt_spares[0].rts_tag
-#define rt_time rt_spares[0].rts_time
-
-#define HOST_MASK 0xffffffff
-#define RT_ISHOST(rt) ((rt)->rt_mask == HOST_MASK)
-
-/* age all routes that
- * are not from -g, -m, or static routes from the kernel
- * not unbroken interface routes
- * but not broken interfaces
- * nor non-passive, remote interfaces that are not aliases
- * (i.e. remote & metric=0)
- */
-#define AGE_RT(rt,ifp) (0 == ((rt)->rt_state & RS_PERMANENT) \
- && (!((rt)->rt_state & RS_IF) \
- || (ifp) == 0 \
- || (((ifp)->int_state & IS_REMOTE) \
- && !((ifp)->int_state & IS_PASSIVE))))
-
-/* true if A is better than B
- * Better if
- * - A is not a poisoned route
- * - and A is not stale
- * - and A has a shorter path
- * - or is the router speaking for itself
- * - or the current route is equal but stale
- * - or it is a host route advertised by a system for itself
- */
-#define BETTER_LINK(rt,A,B) ((A)->rts_metric < HOPCNT_INFINITY \
- && now_stale <= (A)->rts_time \
- && ((A)->rts_metric < (B)->rts_metric \
- || ((A)->rts_gate == (A)->rts_router \
- && (B)->rts_gate != (B)->rts_router) \
- || ((A)->rts_metric == (B)->rts_metric \
- && now_stale > (B)->rts_time) \
- || (RT_ISHOST(rt) \
- && (rt)->rt_dst == (A)->rts_router \
- && (A)->rts_metric == (B)->rts_metric)))
-
-
-/* An "interface" is similar to a kernel ifnet structure, except it also
- * handles "logical" or "IS_REMOTE" interfaces (remote gateways).
- */
-struct interface {
- struct interface *int_next, *int_prev;
- char int_name[IFNAMSIZ+15+1]; /* big enough for IS_REMOTE */
- u_short int_index;
- naddr int_addr; /* address on this host (net order) */
- naddr int_brdaddr; /* broadcast address (n) */
- naddr int_dstaddr; /* other end of pt-to-pt link (n) */
- naddr int_net; /* working network # (host order)*/
- naddr int_mask; /* working net mask (host order) */
- naddr int_ripv1_mask; /* for inferring a mask (n) */
- naddr int_std_addr; /* class A/B/C address (n) */
- naddr int_std_net; /* class A/B/C network (h) */
- naddr int_std_mask; /* class A/B/C netmask (h) */
- int int_rip_sock; /* for queries */
- int int_if_flags; /* copied from kernel */
- u_int int_state;
- time_t int_act_time; /* last thought healthy */
- u_short int_transitions; /* times gone up-down */
- char int_metric;
- char int_d_metric; /* for faked default route */
- struct int_data {
- u_int ipackets; /* previous network stats */
- u_int ierrors;
- u_int opackets;
- u_int oerrors;
-#ifdef sgi
- u_int odrops;
-#endif
- time_t ts; /* timestamp on network stats */
- } int_data;
- char int_passwd[RIP_AUTH_PW_LEN]; /* RIPv2 password */
- int int_rdisc_pref; /* advertised rdisc preference */
- int int_rdisc_int; /* MaxAdvertiseInterval */
- int int_rdisc_cnt;
- struct timeval int_rdisc_timer;
-};
-
-#define IS_ALIAS 0x0000001 /* interface alias */
-#define IS_SUBNET 0x0000002 /* interface on subnetted network */
-#define IS_REMOTE 0x0000004 /* interface is not on this machine */
-#define IS_PASSIVE 0x0000008 /* remote and does not do RIP */
-#define IS_EXTERNAL 0x0000010 /* handled by EGP or something */
-#define IS_CHECKED 0x0000020 /* still exists */
-#define IS_ALL_HOSTS 0x0000040 /* in INADDR_ALLHOSTS_GROUP */
-#define IS_ALL_ROUTERS 0x0000080 /* in INADDR_ALLROUTERS_GROUP */
-#define IS_RIP_QUERIED 0x0000100 /* query broadcast */
-#define IS_BROKE 0x0000200 /* seems to be broken */
-#define IS_SICK 0x0000400 /* seems to be broken */
-#define IS_DUP 0x0000800 /* has a duplicate address */
-#define IS_ACTIVE 0x0001000 /* heard from it at least once */
-#define IS_NEED_NET_SYN 0x0002000 /* need RS_NET_SYN route */
-#define IS_NO_AG 0x0004000 /* do not aggregate subnets */
-#define IS_NO_SUPER_AG 0x0008000 /* do not aggregate networks */
-#define IS_NO_RIPV1_IN 0x0010000 /* no RIPv1 input at all */
-#define IS_NO_RIPV2_IN 0x0020000 /* no RIPv2 input at all */
-#define IS_NO_RIP_IN (IS_NO_RIPV1_IN | IS_NO_RIPV2_IN)
-#define IS_RIP_IN_OFF(s) (((s) & IS_NO_RIP_IN) == IS_NO_RIP_IN)
-#define IS_NO_RIPV1_OUT 0x0040000 /* no RIPv1 output at all */
-#define IS_NO_RIPV2_OUT 0x0080000 /* no RIPv2 output at all */
-#define IS_NO_RIP_OUT (IS_NO_RIPV1_OUT | IS_NO_RIPV2_OUT)
-#define IS_NO_RIP (IS_NO_RIP_OUT | IS_NO_RIP_IN)
-#define IS_RIP_OUT_OFF(s) (((s) & IS_NO_RIP_OUT) == IS_NO_RIP_OUT)
-#define IS_RIP_OFF(s) (((s) & IS_NO_RIP) == IS_NO_RIP)
-#define IS_NO_ADV_IN 0x0100000
-#define IS_NO_SOL_OUT 0x0200000 /* no solicitations */
-#define IS_SOL_OUT 0x0400000 /* send solicitations */
-#define GROUP_IS_SOL (IS_NO_ADV_IN|IS_NO_SOL_OUT)
-#define IS_NO_ADV_OUT 0x0800000 /* do not advertise rdisc */
-#define IS_ADV_OUT 0x1000000 /* advertise rdisc */
-#define GROUP_IS_ADV (IS_NO_ADV_OUT|IS_ADV_OUT)
-#define IS_BCAST_RDISC 0x2000000 /* broadcast instead of multicast */
-#define IS_NO_RDISC (IS_NO_ADV_IN | IS_NO_SOL_OUT | IS_NO_ADV_OUT)
-#define IS_PM_RDISC 0x4000000 /* poor-man's router discovery */
-
-#ifdef sgi
-#define IFF_UP_RUNNING (IFF_RUNNING|IFF_UP)
-#else
-#define IFF_UP_RUNNING IFF_UP
-#endif
-#define iff_alive(f) (((f) & IFF_UP_RUNNING) == IFF_UP_RUNNING)
-
-
-/* Information for aggregating routes */
-#define NUM_AG_SLOTS 32
-struct ag_info {
- struct ag_info *ag_fine; /* slot with finer netmask */
- struct ag_info *ag_cors; /* more coarse netmask */
- naddr ag_dst_h; /* destination in host byte order */
- naddr ag_mask;
- naddr ag_gate;
- naddr ag_nhop;
- char ag_metric; /* metric to be advertised */
- char ag_pref; /* aggregate based on this */
- u_int ag_seqno;
- u_short ag_tag;
- u_short ag_state;
-#define AGS_SUPPRESS 0x001 /* combine with coaser mask */
-#define AGS_PROMOTE 0x002 /* synthesize combined routes */
-#define AGS_REDUN0 0x004 /* redundant, finer routes output */
-#define AGS_REDUN1 0x008
-#define AG_IS_REDUN(state) (((state) & (AGS_REDUN0 | AGS_REDUN1)) \
- == (AGS_REDUN0 | AGS_REDUN1))
-#define AGS_GATEWAY 0x010 /* tell kernel RTF_GATEWAY */
-#define AGS_IF 0x020 /* for an interface */
-#define AGS_RIPV2 0x040 /* send only as RIPv2 */
-#define AGS_FINE_GATE 0x080 /* ignore differing ag_gate when this
- * has the finer netmask */
-#define AGS_CORS_GATE 0x100 /* ignore differing gate when this
- * has the coarser netmaks */
-#define AGS_SPLIT_HZ 0x200 /* suppress for split horizon */
-
- /* some bits are set if they are set on either route */
-#define AGS_PROMOTE_EITHER (AGS_RIPV2 | AGS_GATEWAY | \
- AGS_SUPPRESS | AGS_CORS_GATE)
-};
-
-
-/* parameters for interfaces */
-extern struct parm {
- struct parm *parm_next;
- char parm_name[IFNAMSIZ+1];
- naddr parm_addr_h;
- naddr parm_mask;
-
- char parm_d_metric;
- u_int parm_int_state;
- int parm_rdisc_pref;
- int parm_rdisc_int;
- char parm_passwd[RIP_AUTH_PW_LEN+1];
-} *parms;
-
-/* authority for internal networks */
-extern struct intnet {
- struct intnet *intnet_next;
- naddr intnet_addr;
- naddr intnet_mask;
- char intnet_metric;
-} *intnets;
-
-
-
-extern pid_t mypid;
-extern naddr myaddr; /* main address of this system */
-
-extern int stopint; /* !=0 to stop */
-
-extern int sock_max;
-extern int rip_sock; /* RIP socket */
-extern struct interface *rip_sock_mcast; /* current multicast interface */
-extern int rt_sock; /* routing socket */
-extern int rt_sock_seqno;
-extern int rdisc_sock; /* router-discovery raw socket */
-
-extern int seqno; /* sequence number for messages */
-extern int supplier; /* process should supply updates */
-extern int lookforinterfaces; /* 1=probe for new up interfaces */
-extern int supplier_set; /* -s or -q requested */
-extern int ridhosts; /* 1=reduce host routes */
-extern int mhome; /* 1=want multi-homed host route */
-extern int advertise_mhome; /* 1=must continue adverising it */
-extern int auth_ok; /* 1=ignore auth if we do not care */
-
-extern struct timeval epoch; /* when started */
-extern struct timeval now; /* current idea of time */
-extern time_t now_stale;
-extern time_t now_garbage;
-
-extern struct timeval next_bcast; /* next general broadcast */
-extern struct timeval age_timer; /* next check of old routes */
-extern struct timeval no_flash; /* inhibit flash update until then */
-extern struct timeval rdisc_timer; /* next advert. or solicitation */
-extern int rdisc_ok; /* using solicited route */
-
-extern struct timeval ifinit_timer; /* time to check interfaces */
-
-extern naddr loopaddr; /* our address on loopback */
-extern int tot_interfaces; /* # of remote and local interfaces */
-extern int rip_interfaces; /* # of interfaces doing RIP */
-extern struct interface *ifnet; /* all interfaces */
-extern int have_ripv1_out; /* have a RIPv1 interface */
-extern int have_ripv1_in;
-extern int need_flash; /* flash update needed */
-extern struct timeval need_kern; /* need to update kernel table */
-extern int update_seqno; /* a route has changed */
-
-extern u_int tracelevel, new_tracelevel;
-#define MAX_TRACELEVEL 3
-#define TRACECONTENTS (tracelevel >= 3) /* display packet contents */
-#define TRACEPACKETS (tracelevel >= 2) /* note packets */
-#define TRACEACTIONS (tracelevel != 0)
-extern FILE *ftrace; /* output trace file */
-
-extern struct radix_node_head *rhead;
-
-
-#ifdef sgi
-/* Fix conflicts */
-#define dup2(x,y) BSDdup2(x,y)
-#endif /* sgi */
-
-extern void fix_sock(int, char *);
-extern void fix_select(void);
-extern void rip_off(void);
-extern void rip_on(struct interface *);
-
-enum output_type {OUT_QUERY, OUT_UNICAST, OUT_BROADCAST, OUT_MULTICAST,
- NO_OUT_MULTICAST, NO_OUT_RIPV2};
-extern int output(enum output_type, struct sockaddr_in *,
- struct interface *, struct rip *, int);
-extern void rip_query(void);
-extern void rip_bcast(int);
-extern void supply(struct sockaddr_in *, struct interface *,
- enum output_type, int, int);
-
-extern void msglog(char *, ...);
-#define LOGERR(msg) msglog(msg ": %s", strerror(errno))
-extern void logbad(int, char *, ...);
-#define BADERR(dump,msg) logbad(dump,msg ": %s", strerror(errno))
-#ifdef DEBUG
-#define DBGERR(dump,msg) BADERR(dump,msg)
-#else
-#define DBGERR(dump,msg) LOGERR(msg)
-#endif
-extern char *naddr_ntoa(naddr);
-extern char *saddr_ntoa(struct sockaddr *);
-
-extern void *rtmalloc(size_t, char *);
-extern void timevaladd(struct timeval *, struct timeval *);
-extern void intvl_random(struct timeval *, u_long, u_long);
-extern int getnet(char *, naddr *, naddr *);
-extern int gethost(char *, naddr *);
-extern void gwkludge(void);
-extern char *parse_parms(char *);
-extern char *check_parms(struct parm *);
-extern void get_parms(struct interface *);
-
-extern void lastlog(void);
-extern void trace_on(char *, int);
-extern void trace_off(char*, ...);
-extern void trace_flush(void);
-extern void set_tracelevel(void);
-extern void trace_act(char *, ...);
-extern void trace_pkt(char *, ...);
-extern void trace_add_del(char *, struct rt_entry *);
-extern void trace_change(struct rt_entry *, u_int, naddr, naddr, int,
- u_short, struct interface *, time_t, char *);
-extern void trace_if(char *, struct interface *);
-extern void trace_upslot(struct rt_entry *, struct rt_spare *,
- naddr, naddr,
- struct interface *, int, u_short, time_t);
-extern void trace_rip(char*, char*, struct sockaddr_in *,
- struct interface *, struct rip *, int);
-extern char *addrname(naddr, naddr, int);
-
-extern void rdisc_age(naddr);
-extern void set_rdisc_mg(struct interface *, int);
-extern void set_supplier(void);
-extern void if_bad_rdisc(struct interface *);
-extern void if_ok_rdisc(struct interface *);
-extern void read_rip(int, struct interface *);
-extern void read_rt(void);
-extern void read_d(void);
-extern void rdisc_adv(void);
-extern void rdisc_sol(void);
-
-extern void sigalrm(int);
-extern void sigterm(int);
-
-extern void sigtrace_on(int);
-extern void sigtrace_off(int);
-
-extern void flush_kern(void);
-extern void age(naddr);
-
-extern void ag_flush(naddr, naddr, void (*)(struct ag_info *));
-extern void ag_check(naddr, naddr, naddr, naddr, char, char, u_int,
- u_short, u_short, void (*)(struct ag_info *));
-extern void del_static(naddr, naddr, int);
-extern void del_redirects(naddr, time_t);
-extern struct rt_entry *rtget(naddr, naddr);
-extern struct rt_entry *rtfind(naddr);
-extern void rtinit(void);
-extern void rtadd(naddr, naddr, naddr, naddr,
- int, u_short, u_int, struct interface *);
-extern void rtchange(struct rt_entry *, u_int, naddr,naddr, int, u_short,
- struct interface *ifp, time_t, char *);
-extern void rtdelete(struct rt_entry *);
-extern void rtbad_sub(struct rt_entry *);
-extern void rtswitch(struct rt_entry *, struct rt_spare *);
-extern void rtbad(struct rt_entry *);
-
-
-#define S_ADDR(x) (((struct sockaddr_in *)(x))->sin_addr.s_addr)
-#define INFO_DST(I) ((I)->rti_info[RTAX_DST])
-#define INFO_GATE(I) ((I)->rti_info[RTAX_GATEWAY])
-#define INFO_MASK(I) ((I)->rti_info[RTAX_NETMASK])
-#define INFO_IFA(I) ((I)->rti_info[RTAX_IFA])
-#define INFO_IFP(I) ((I)->rti_info[RTAX_IFP])
-#define INFO_AUTHOR(I) ((I)->rti_info[RTAX_AUTHOR])
-#define INFO_BRD(I) ((I)->rti_info[RTAX_BRD])
-void rt_xaddrs(struct rt_addrinfo *, struct sockaddr *, struct sockaddr *,
- int);
-
-extern naddr std_mask(naddr);
-extern naddr ripv1_mask_net(naddr, struct interface *);
-extern naddr ripv1_mask_host(naddr,struct interface *);
-#define on_net(a,net,mask) (((ntohl(a) ^ (net)) & (mask)) == 0)
-extern int check_dst(naddr);
-extern void addrouteforif(register struct interface *);
-extern void ifinit(void);
-extern int walk_bad(struct radix_node *, struct walkarg *);
-extern int if_ok(struct interface *, char *);
-extern void if_sick(struct interface *);
-extern void if_bad(struct interface *);
-extern struct interface *ifwithaddr(naddr, int, int);
-extern struct interface *ifwithname(char *, naddr);
-extern struct interface *ifwithindex(u_short);
-extern struct interface *iflookup(naddr);
diff --git a/usr.sbin/routed/if.c b/usr.sbin/routed/if.c
deleted file mode 100644
index 71b4ad5..0000000
--- a/usr.sbin/routed/if.c
+++ /dev/null
@@ -1,1132 +0,0 @@
-/*
- * Copyright (c) 1983, 1993
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#if !defined(lint) && !defined(sgi) && !defined(__NetBSD__)
-static char sccsid[] = "@(#)if.c 8.1 (Berkeley) 6/5/93";
-#elif defined(__NetBSD__)
-static char rcsid[] = "$NetBSD$";
-#endif
-#ident "$Revision: 1.1.3.3 $"
-
-#include "defs.h"
-#include "pathnames.h"
-
-struct interface *ifnet; /* all interfaces */
-int tot_interfaces; /* # of remote and local interfaces */
-int rip_interfaces; /* # of interfaces doing RIP */
-int foundloopback; /* valid flag for loopaddr */
-naddr loopaddr; /* our address on loopback */
-
-struct timeval ifinit_timer;
-
-int have_ripv1_out; /* have a RIPv1 interface */
-int have_ripv1_in;
-
-
-/* Find the interface with an address
- */
-struct interface *
-ifwithaddr(naddr addr,
- int bcast, /* notice IFF_BROADCAST address */
- int remote) /* include IS_REMOTE interfaces */
-{
- struct interface *ifp, *possible = 0;
-
- for (ifp = ifnet; ifp; ifp = ifp->int_next) {
- if (ifp->int_addr == addr
- || ((ifp->int_if_flags & IFF_BROADCAST)
- && ifp->int_brdaddr == addr
- && bcast)) {
- if ((ifp->int_state & IS_REMOTE) && !remote)
- continue;
-
- if (!(ifp->int_state & IS_BROKE)
- && !(ifp->int_state & IS_PASSIVE))
- return ifp;
-
- possible = ifp;
- }
- }
-
- return possible;
-}
-
-
-/* find the interface with a name
- */
-struct interface *
-ifwithname(char *name, /* "ec0" or whatever */
- naddr addr) /* 0 or network address */
-{
- struct interface *ifp;
-
-
- for (ifp = ifnet; 0 != ifp; ifp = ifp->int_next) {
- if (!strcmp(ifp->int_name, name)
- && (ifp->int_addr == addr
- || (addr == 0 && !(ifp->int_state & IS_ALIAS))))
- return ifp;
- }
- return 0;
-}
-
-
-struct interface *
-ifwithindex(u_short index)
-{
- struct interface *ifp;
-
-
- for (ifp = ifnet; 0 != ifp; ifp = ifp->int_next) {
- if (ifp->int_index == index)
- return ifp;
- }
- return 0;
-}
-
-
-/* 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 *
-iflookup(naddr addr)
-{
- struct interface *ifp, *maybe;
-
- maybe = 0;
- for (ifp = ifnet; ifp; ifp = ifp->int_next) {
- if (ifp->int_if_flags & IFF_POINTOPOINT) {
- if (ifp->int_dstaddr == addr)
- /* finished with a match */
- return ifp;
-
- } else {
- /* finished with an exact match */
- if (ifp->int_addr == addr)
- return ifp;
- if ((ifp->int_if_flags & IFF_BROADCAST)
- && ifp->int_brdaddr == addr)
- return ifp;
-
- /* Look for the longest approximate match.
- */
- if (on_net(addr, ifp->int_net, ifp->int_mask)
- && (maybe == 0
- || ifp->int_mask > maybe->int_mask))
- maybe = ifp;
- }
- }
-
- return maybe;
-}
-
-
-/* Return the classical netmask for an IP address.
- */
-naddr
-std_mask(naddr addr) /* in network order */
-{
- NTOHL(addr); /* was a host, not a network */
-
- if (addr == 0) /* default route has mask 0 */
- return 0;
- if (IN_CLASSA(addr))
- return IN_CLASSA_NET;
- if (IN_CLASSB(addr))
- return IN_CLASSB_NET;
- return IN_CLASSC_NET;
-}
-
-
-/* Find the netmask that would be inferred by RIPv1 listeners
- * on the given interface for a given network.
- * If no interface is specified, look for the best fitting interface.
- */
-naddr
-ripv1_mask_net(naddr addr, /* in network byte order */
- struct interface *ifp) /* as seen on this interface */
-{
- naddr mask = 0;
-
- if (addr == 0) /* default always has 0 mask */
- return mask;
-
- if (ifp != 0) {
- /* If the target network is that of the associated interface
- * on which it arrived, then use the netmask of the interface.
- */
- if (on_net(addr, ifp->int_net, ifp->int_std_mask))
- mask = ifp->int_ripv1_mask;
-
- } else {
- /* Examine all interfaces, and if it the target seems
- * to have the same network number of an interface, use the
- * netmask of that interface. If there is more than one
- * such interface, prefer the interface with the longest
- * match.
- */
- for (ifp = ifnet; ifp != 0; ifp = ifp->int_next) {
- if (on_net(addr, ifp->int_std_net, ifp->int_std_mask)
- && ifp->int_ripv1_mask > mask)
- mask = ifp->int_ripv1_mask;
- }
- }
-
- /* Otherwise, make the classic A/B/C guess.
- */
- if (mask == 0)
- mask = std_mask(addr);
-
- return mask;
-}
-
-
-naddr
-ripv1_mask_host(naddr addr, /* in network byte order */
- struct interface *ifp) /* as seen on this interface */
-{
- naddr mask = ripv1_mask_net(addr, ifp);
-
-
- /* If the computed netmask does not mask the address,
- * then assume it is a host address
- */
- if ((ntohl(addr) & ~mask) != 0)
- mask = HOST_MASK;
- return mask;
-}
-
-
-/* See if a IP address looks reasonable as a destination
- */
-int /* 0=bad */
-check_dst(naddr addr)
-{
- NTOHL(addr);
-
- if (IN_CLASSA(addr)) {
- if (addr == 0)
- return 1; /* default */
-
- addr >>= IN_CLASSA_NSHIFT;
- return (addr != 0 && addr != IN_LOOPBACKNET);
- }
-
- return (IN_CLASSB(addr) || IN_CLASSC(addr));
-}
-
-
-/* Delete an interface.
- */
-static void
-ifdel(struct interface *ifp)
-{
- struct ip_mreq m;
- struct interface *ifp1;
-
-
- trace_if("Del", ifp);
-
- ifp->int_state |= IS_BROKE;
-
- /* unlink the interface
- */
- if (rip_sock_mcast == ifp)
- rip_sock_mcast = 0;
- if (ifp->int_next != 0)
- ifp->int_next->int_prev = ifp->int_prev;
- if (ifp->int_prev != 0)
- ifp->int_prev->int_next = ifp->int_next;
- else
- ifnet = ifp->int_next;
-
- if (!(ifp->int_state & IS_ALIAS)) {
- /* delete aliases
- */
- for (ifp1 = ifnet; 0 != ifp1; ifp1 = ifp1->int_next) {
- if (ifp1 != ifp
- && !strcmp(ifp->int_name, ifp1->int_name))
- ifdel(ifp1);
- }
-
- if ((ifp->int_if_flags & IFF_MULTICAST)
-#ifdef MCAST_PPP_BUG
- && !(ifp->int_if_flags & IFF_POINTOPOINT)
-#endif
- && rip_sock >= 0) {
- m.imr_multiaddr.s_addr = htonl(INADDR_RIP_GROUP);
- m.imr_interface.s_addr = ((ifp->int_if_flags
- & IFF_POINTOPOINT)
- ? ifp->int_dstaddr
- : ifp->int_addr);
- if (setsockopt(rip_sock,IPPROTO_IP,IP_DROP_MEMBERSHIP,
- &m, sizeof(m)) < 0
- && errno != EADDRNOTAVAIL
- && !TRACEACTIONS)
- LOGERR("setsockopt(IP_DROP_MEMBERSHIP RIP)");
- }
- if (ifp->int_rip_sock >= 0) {
- (void)close(ifp->int_rip_sock);
- ifp->int_rip_sock = -1;
- fix_select();
- }
-
- tot_interfaces--;
- if (!IS_RIP_OFF(ifp->int_state))
- rip_interfaces--;
-
- /* Zap all routes associated with this interface.
- * Assume routes just using gateways beyond this interface will
- * timeout naturally, and have probably already died.
- */
- (void)rn_walktree(rhead, walk_bad, 0);
-
- set_rdisc_mg(ifp, 0);
- if_bad_rdisc(ifp);
- }
-
- free(ifp);
-}
-
-
-/* Mark an interface ill.
- */
-void
-if_sick(struct interface *ifp)
-{
- if (0 == (ifp->int_state & (IS_SICK | IS_BROKE))) {
- ifp->int_state |= IS_SICK;
- trace_if("Chg", ifp);
-
- LIM_SEC(ifinit_timer, now.tv_sec+CHECK_BAD_INTERVAL);
- }
-}
-
-
-/* Mark an interface dead.
- */
-void
-if_bad(struct interface *ifp)
-{
- struct interface *ifp1;
-
-
- if (ifp->int_state & IS_BROKE)
- return;
-
- LIM_SEC(ifinit_timer, now.tv_sec+CHECK_BAD_INTERVAL);
-
- ifp->int_state |= (IS_BROKE | IS_SICK);
- ifp->int_state &= ~(IS_RIP_QUERIED | IS_ACTIVE);
- ifp->int_data.ts = 0;
-
- trace_if("Chg", ifp);
-
- if (!(ifp->int_state & IS_ALIAS)) {
- for (ifp1 = ifnet; 0 != ifp1; ifp1 = ifp1->int_next) {
- if (ifp1 != ifp
- && !strcmp(ifp->int_name, ifp1->int_name))
- if_bad(ifp1);
- }
- (void)rn_walktree(rhead, walk_bad, 0);
- if_bad_rdisc(ifp);
- }
-}
-
-
-/* Mark an interface alive
- */
-int /* 1=it was dead */
-if_ok(struct interface *ifp,
- char *type)
-{
- struct interface *ifp1;
-
-
- if (!(ifp->int_state & IS_BROKE)) {
- if (ifp->int_state & IS_SICK) {
- trace_act("%sinterface %s to %s working better\n",
- type,
- ifp->int_name, naddr_ntoa(ifp->int_addr));
- ifp->int_state &= ~IS_SICK;
- }
- return 0;
- }
-
- msglog("%sinterface %s to %s restored",
- type, ifp->int_name, naddr_ntoa(ifp->int_addr));
- ifp->int_state &= ~(IS_BROKE | IS_SICK);
- ifp->int_data.ts = 0;
-
- if (!(ifp->int_state & IS_ALIAS)) {
- for (ifp1 = ifnet; 0 != ifp1; ifp1 = ifp1->int_next) {
- if (ifp1 != ifp
- && !strcmp(ifp->int_name, ifp1->int_name))
- if_ok(ifp1, type);
- }
- if_ok_rdisc(ifp);
- }
- return 1;
-}
-
-
-/* disassemble routing message
- */
-void
-rt_xaddrs(struct rt_addrinfo *info,
- struct sockaddr *sa,
- struct sockaddr *lim,
- int addrs)
-{
- int i;
-#ifdef _HAVE_SA_LEN
- static struct sockaddr sa_zero;
-#endif
-#ifdef sgi
-#define ROUNDUP(a) ((a) > 0 ? (1 + (((a) - 1) | (sizeof(__uint64_t) - 1))) \
- : sizeof(__uint64_t))
-#else
-#define ROUNDUP(a) ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) \
- : sizeof(long))
-#endif
-
-
- bzero(info, sizeof(*info));
- info->rti_addrs = addrs;
- for (i = 0; i < RTAX_MAX && sa < lim; i++) {
- if ((addrs & (1 << i)) == 0)
- continue;
-#ifdef _HAVE_SA_LEN
- info->rti_info[i] = (sa->sa_len != 0) ? sa : &sa_zero;
- sa = (struct sockaddr *)((char*)(sa)
- + ROUNDUP(sa->sa_len));
-#else
- info->rti_info[i] = sa;
- sa = (struct sockaddr *)((char*)(sa)
- + ROUNDUP(_FAKE_SA_LEN_DST(sa)));
-#endif
- }
-}
-
-
-/* Find the network interfaces which have configured themselves.
- * This must be done regularly, if only for extra addresses
- * that come and go on interfaces.
- */
-void
-ifinit(void)
-{
- static char *sysctl_buf;
- static size_t sysctl_buf_size = 0;
- uint complaints = 0;
- static u_int prev_complaints = 0;
-# define COMP_NOT_INET 0x001
-# define COMP_WIERD 0x002
-# define COMP_NOADDR 0x004
-# define COMP_NODST 0x008
-# define COMP_NOBADR 0x010
-# define COMP_NOMASK 0x020
-# define COMP_DUP 0x040
-# define COMP_BAD_METRIC 0x080
-# define COMP_NETMASK 0x100
-
- struct interface ifs, ifs0, *ifp, *ifp1;
- struct rt_entry *rt;
- size_t needed;
- int mib[6];
- struct if_msghdr *ifm;
- struct ifa_msghdr *ifam, *ifam_lim, *ifam2;
- struct sockaddr_dl *sdl;
- int in, ierr, out, oerr;
- struct intnet *intnetp;
- struct rt_addrinfo info;
-#ifdef SIOCGIFMETRIC
- struct ifreq ifr;
-#endif
-
-
- ifinit_timer.tv_sec = now.tv_sec + (supplier
- ? CHECK_ACT_INTERVAL
- : CHECK_QUIET_INTERVAL);
-
- /* mark all interfaces so we can get rid of thost that disappear */
- for (ifp = ifnet; 0 != ifp; ifp = ifp->int_next)
- ifp->int_state &= ~(IS_CHECKED | IS_DUP);
-
- /* Fetch the interface list, without too many system calls
- * since we do it repeatedly.
- */
- mib[0] = CTL_NET;
- mib[1] = PF_ROUTE;
- mib[2] = 0;
- mib[3] = AF_INET;
- mib[4] = NET_RT_IFLIST;
- mib[5] = 0;
- for (;;) {
- if ((needed = sysctl_buf_size) != 0) {
- if (sysctl(mib, 6, sysctl_buf,&needed, 0, 0) >= 0)
- break;
- if (errno != ENOMEM && errno != EFAULT)
- BADERR(1, "ifinit: get interface table");
- free(sysctl_buf);
- needed = 0;
- }
- if (sysctl(mib, 6, 0, &needed, 0, 0) < 0)
- BADERR(1,"ifinit: route-sysctl-estimate");
- sysctl_buf = rtmalloc(sysctl_buf_size = needed, "ifinit");
- }
-
- ifam_lim = (struct ifa_msghdr *)(sysctl_buf + needed);
- for (ifam = (struct ifa_msghdr *)sysctl_buf;
- ifam < ifam_lim;
- ifam = ifam2) {
-
- ifam2 = (struct ifa_msghdr*)((char*)ifam + ifam->ifam_msglen);
-
- if (ifam->ifam_type == RTM_IFINFO) {
- ifm = (struct if_msghdr *)ifam;
- /* make prototype structure for the IP aliases
- */
- bzero(&ifs0, sizeof(ifs0));
- ifs0.int_rip_sock = -1;
- ifs0.int_index = ifm->ifm_index;
- ifs0.int_if_flags = ifm->ifm_flags;
- ifs0.int_state = IS_CHECKED;
- ifs0.int_act_time = now.tv_sec;
- ifs0.int_data.ts = now.tv_sec;
- ifs0.int_data.ipackets = ifm->ifm_data.ifi_ipackets;
- ifs0.int_data.ierrors = ifm->ifm_data.ifi_ierrors;
- ifs0.int_data.opackets = ifm->ifm_data.ifi_opackets;
- ifs0.int_data.oerrors = ifm->ifm_data.ifi_oerrors;
-#ifdef sgi
- ifs0.int_data.odrops = ifm->ifm_data.ifi_odrops;
-#endif
- sdl = (struct sockaddr_dl *)(ifm + 1);
- sdl->sdl_data[sdl->sdl_nlen] = 0;
- continue;
- }
- if (ifam->ifam_type != RTM_NEWADDR) {
- logbad(1,"ifinit: out of sync");
- continue;
- }
-
- rt_xaddrs(&info, (struct sockaddr *)(ifam+1),
- (struct sockaddr *)ifam2,
- ifam->ifam_addrs);
-
- if (INFO_IFA(&info) == 0) {
- if (iff_alive(ifs.int_if_flags)) {
- if (!(prev_complaints & COMP_NOADDR))
- msglog("%s has a bad address",
- sdl->sdl_data);
- complaints |= COMP_NOADDR;
- }
- continue;
- }
- if (INFO_IFA(&info)->sa_family != AF_INET) {
- if (iff_alive(ifs.int_if_flags)) {
- if (!(prev_complaints & COMP_NOT_INET))
- trace_act("%s: not AF_INET\n",
- sdl->sdl_data);
- complaints |= COMP_NOT_INET;
- }
- continue;
- }
-
- bcopy(&ifs0, &ifs, sizeof(ifs0));
- ifs0.int_state |= IS_ALIAS; /* next will be an alias */
-
- ifs.int_addr = S_ADDR(INFO_IFA(&info));
-
- if (ifs.int_if_flags & IFF_BROADCAST) {
- if (INFO_MASK(&info) == 0) {
- if (iff_alive(ifs.int_if_flags)) {
- if (!(prev_complaints & COMP_NOMASK))
- msglog("%s has no netmask",
- sdl->sdl_data);
- complaints |= COMP_NOMASK;
- }
- continue;
- }
- ifs.int_dstaddr = ifs.int_addr;
- ifs.int_mask = ntohl(S_ADDR(INFO_MASK(&info)));
- ifs.int_ripv1_mask = ifs.int_mask;
- ifs.int_net = ntohl(ifs.int_addr) & ifs.int_mask;
- ifs.int_std_mask = std_mask(ifs.int_addr);
- if (ifs.int_mask != ifs.int_std_mask)
- ifs.int_state |= IS_SUBNET;
-
- if (INFO_BRD(&info) == 0) {
- if (iff_alive(ifs.int_if_flags)) {
- if (!(prev_complaints & COMP_NOBADR))
- msglog("%s has no"
- " broadcast address",
- sdl->sdl_data);
- complaints |= COMP_NOBADR;
- }
- continue;
- }
- ifs.int_brdaddr = S_ADDR(INFO_BRD(&info));
-
- } else if (ifs.int_if_flags & IFF_POINTOPOINT) {
- if (INFO_BRD(&info) == 0
- || INFO_BRD(&info)->sa_family != AF_INET) {
- if (iff_alive(ifs.int_if_flags)) {
- if (!(prev_complaints & COMP_NODST))
- msglog("%s has a bad"
- " destination address",
- sdl->sdl_data);
- complaints |= COMP_NODST;
- }
- continue;
- }
- ifs.int_dstaddr = S_ADDR(INFO_BRD(&info));
- ifs.int_mask = HOST_MASK;
- ifs.int_ripv1_mask = ntohl(S_ADDR(INFO_MASK(&info)));
- ifs.int_net = ntohl(ifs.int_dstaddr);
- ifs.int_std_mask = std_mask(ifs.int_dstaddr);
-
- } else if (ifs.int_if_flags & IFF_LOOPBACK) {
- ifs.int_state |= IS_PASSIVE | IS_NO_RIP;
- ifs.int_dstaddr = ifs.int_addr;
- ifs.int_mask = HOST_MASK;
- ifs.int_ripv1_mask = HOST_MASK;
- ifs.int_net = ntohl(ifs.int_dstaddr);
- ifs.int_std_mask = std_mask(ifs.int_dstaddr);
- if (!foundloopback) {
- foundloopback = 1;
- loopaddr = ifs.int_addr;
- }
-
- } else {
- if (!(prev_complaints & COMP_WIERD))
- trace_act("%s is neither broadcast"
- " nor point-to-point nor loopback",
- sdl->sdl_data);
- complaints |= COMP_WIERD;
- continue;
- }
- ifs.int_std_net = ifs.int_net & ifs.int_std_mask;
- ifs.int_std_addr = htonl(ifs.int_std_net);
-
- /* Use a minimum metric of one. Treat the interface metric
- * (default 0) as an increment to the hop count of one.
- *
- * The metric obtained from the routing socket dump of
- * interface addresses is wrong. It is not set by the
- * SIOCSIFMETRIC ioctl.
- */
-#ifdef SIOCGIFMETRIC
- strncpy(ifr.ifr_name, sdl->sdl_data, sizeof(ifr.ifr_name));
- if (ioctl(rt_sock, SIOCGIFMETRIC, &ifr) < 0) {
- DBGERR(1, "ioctl(SIOCGIFMETRIC)");
- ifs.int_metric = 0;
- } else {
- ifs.int_metric = ifr.ifr_metric;
- }
-#else
- ifs.int_metric = ifam->ifam_metric;
-#endif
- if (ifs.int_metric > HOPCNT_INFINITY) {
- ifs.int_metric = 0;
- if (!(prev_complaints & COMP_BAD_METRIC)
- && iff_alive(ifs.int_if_flags)) {
- complaints |= COMP_BAD_METRIC;
- msglog("%s has a metric of %d",
- sdl->sdl_data, ifs.int_metric);
- }
- }
-
- /* See if this is a familiar interface.
- * If so, stop worrying about it if it is the same.
- * Start it over if it now is to somewhere else, as happens
- * frequently with PPP and SLIP.
- */
- ifp = ifwithname(sdl->sdl_data, ((ifs.int_state & IS_ALIAS)
- ? ifs.int_addr
- : 0));
- if (ifp != 0) {
- ifp->int_state |= IS_CHECKED;
-
- if (0 != ((ifp->int_if_flags ^ ifs.int_if_flags)
- & (IFF_BROADCAST
- | IFF_LOOPBACK
- | IFF_POINTOPOINT
- | IFF_MULTICAST))
- || 0 != ((ifp->int_state ^ ifs.int_state)
- & IS_ALIAS)
- || ifp->int_addr != ifs.int_addr
- || ifp->int_brdaddr != ifs.int_brdaddr
- || ifp->int_dstaddr != ifs.int_dstaddr
- || ifp->int_mask != ifs.int_mask
- || ifp->int_metric != ifs.int_metric) {
- /* Forget old information about
- * a changed interface.
- */
- trace_act("interface %s has changed\n",
- ifp->int_name);
- ifdel(ifp);
- ifp = 0;
- }
- }
-
- if (ifp != 0) {
- /* The primary representative of an alias worries
- * about how things are working.
- */
- if (ifp->int_state & IS_ALIAS)
- continue;
-
- /* note interfaces that have been turned off
- */
- if (!iff_alive(ifs.int_if_flags)) {
- if (iff_alive(ifp->int_if_flags)) {
- msglog("interface %s to %s turned off",
- ifp->int_name,
- naddr_ntoa(ifp->int_addr));
- if_bad(ifp);
- ifp->int_if_flags &= ~IFF_UP_RUNNING;
- }
- continue;
- }
- /* or that were off and are now ok */
- if (!iff_alive(ifp->int_if_flags)) {
- ifp->int_if_flags |= IFF_UP_RUNNING;
- (void)if_ok(ifp, "");
- }
-
- /* If it has been long enough,
- * see if the interface is broken.
- */
- if (now.tv_sec < ifp->int_data.ts+CHECK_BAD_INTERVAL)
- continue;
-
- in = ifs.int_data.ipackets - ifp->int_data.ipackets;
- ierr = ifs.int_data.ierrors - ifp->int_data.ierrors;
- out = ifs.int_data.opackets - ifp->int_data.opackets;
- oerr = ifs.int_data.oerrors - ifp->int_data.oerrors;
-#ifdef sgi
- /* Through at least IRIX 6.2, PPP and SLIP
- * count packets dropped by the filters.
- * But FDDI rings stuck non-operational count
- * dropped packets as they wait for improvement.
- */
- if (!(ifp->int_if_flags & IFF_POINTOPOINT))
- oerr += (ifs.int_data.odrops
- - ifp->int_data.odrops);
-#endif
- /* If the interface just awoke, restart the counters.
- */
- if (ifp->int_data.ts == 0) {
- ifp->int_data = ifs.int_data;
- continue;
- }
- ifp->int_data = ifs.int_data;
-
- /* Withhold judgement when the short error
- * counters wrap or the interface is reset.
- */
- if (ierr < 0 || in < 0 || oerr < 0 || out < 0) {
- LIM_SEC(ifinit_timer,
- now.tv_sec+CHECK_BAD_INTERVAL);
- continue;
- }
-
- /* Withhold judgement when there is no traffic
- */
- if (in == 0 && out == 0 && ierr == 0 && oerr == 0)
- continue;
-
- /* It is bad if input or output is not working.
- * Require presistent problems before marking it dead.
- */
- if ((in <= ierr && ierr > 0)
- || (out <= oerr && oerr > 0)) {
- if (!(ifp->int_state & IS_SICK)) {
- trace_act("interface %s to %s"
- " sick: in=%d ierr=%d"
- " out=%d oerr=%d\n",
- ifp->int_name,
- naddr_ntoa(ifp->int_addr),
- in, ierr, out, oerr);
- if_sick(ifp);
- continue;
- }
- if (!(ifp->int_state & IS_BROKE)) {
- msglog("interface %s to %s bad:"
- " in=%d ierr=%d out=%d oerr=%d",
- ifp->int_name,
- naddr_ntoa(ifp->int_addr),
- in, ierr, out, oerr);
- if_bad(ifp);
- }
- continue;
- }
-
- /* otherwise, it is active and healthy
- */
- ifp->int_act_time = now.tv_sec;
- (void)if_ok(ifp, "");
- continue;
- }
-
- /* This is a new interface.
- * If it is dead, forget it.
- */
- if (!iff_alive(ifs.int_if_flags))
- continue;
-
- /* See if it duplicates an existing interface.
- */
- for (ifp = ifnet; 0 != ifp; ifp = ifp->int_next) {
- if (ifp->int_mask != ifs.int_mask)
- continue;
- if (((ifp->int_addr != ifs.int_addr
- && ifs.int_mask != HOST_MASK)
- || (ifp->int_dstaddr != ifs.int_dstaddr
- && ifs.int_mask == HOST_MASK)))
- continue;
- if (!iff_alive(ifp->int_if_flags))
- continue;
- /* Let one of our real interfaces be marked
- * passive.
- */
- if ((ifp->int_state & IS_PASSIVE)
- && !(ifp->int_state & IS_EXTERNAL))
- continue;
-
- /* It does duplicate an existing interface,
- * so complain about it, mark the other one
- * duplicated, and for get this one.
- */
- if (!(prev_complaints & COMP_DUP)) {
- complaints |= COMP_DUP;
- msglog("%s is duplicated by %s at %s",
- sdl->sdl_data, ifp->int_name,
- naddr_ntoa(ifp->int_addr));
- }
- ifp->int_state |= IS_DUP;
- break;
- }
- if (ifp != 0)
- continue;
-
- /* It is new and ok. So make it real
- */
- strncpy(ifs.int_name, sdl->sdl_data,
- MIN(sizeof(ifs.int_name)-1, sdl->sdl_nlen));
- get_parms(&ifs);
-
- /* Add it to the list of interfaces
- */
- ifp = (struct interface *)rtmalloc(sizeof(*ifp), "ifinit");
- bcopy(&ifs, ifp, sizeof(*ifp));
- if (ifnet != 0) {
- ifp->int_next = ifnet;
- ifnet->int_prev = ifp;
- }
- ifnet = ifp;
- trace_if("Add", ifp);
-
- /* Notice likely bad netmask.
- */
- if (!(prev_complaints & COMP_NETMASK)
- && !(ifp->int_if_flags & IFF_POINTOPOINT)) {
- for (ifp1 = ifnet; 0 != ifp1; ifp1 = ifp1->int_next) {
- if (ifp1->int_mask == ifp->int_mask)
- continue;
- if (ifp1->int_if_flags & IFF_POINTOPOINT)
- continue;
- if (on_net(ifp->int_addr,
- ifp1->int_net, ifp1->int_mask)
- || on_net(ifp1->int_addr,
- ifp->int_net, ifp->int_mask)) {
- msglog("possible netmask problem"
- " betwen %s:%s and %s:%s",
- ifp->int_name,
- addrname(htonl(ifp->int_net),
- ifp->int_mask, 1),
- ifp1->int_name,
- addrname(htonl(ifp1->int_net),
- ifp1->int_mask, 1));
- complaints |= COMP_NETMASK;
- }
- }
- }
-
- /* Count the # of directly connected networks.
- */
- if (!(ifp->int_state & IS_ALIAS)) {
- if (!(ifp->int_if_flags & IFF_LOOPBACK))
- tot_interfaces++;
- if (!IS_RIP_OFF(ifp->int_state))
- rip_interfaces++;
- }
-
- if_ok_rdisc(ifp);
- rip_on(ifp);
- }
-
- /* If we are multi-homed and have at least one interface
- * listening to RIP, then output by default.
- */
- if (!supplier_set && rip_interfaces > 1)
- set_supplier();
-
- /* If we are multi-homed, optionally advertise a route to
- * our main address.
- */
- if (advertise_mhome
- || (tot_interfaces > 1
- && mhome
- && (ifp = ifwithaddr(myaddr, 0, 0)) != 0
- && foundloopback)) {
- advertise_mhome = 1;
- rt = rtget(myaddr, HOST_MASK);
- if (rt != 0) {
- if (rt->rt_ifp != ifp
- || rt->rt_router != loopaddr) {
- rtdelete(rt);
- rt = 0;
- } else {
- rtchange(rt, rt->rt_state | RS_MHOME,
- loopaddr, loopaddr,
- 0, 0, ifp, rt->rt_time, 0);
- }
- }
- if (rt == 0)
- rtadd(myaddr, HOST_MASK, loopaddr, loopaddr,
- 0, 0, RS_MHOME, ifp);
- }
-
- for (ifp = ifnet; ifp != 0; ifp = ifp1) {
- ifp1 = ifp->int_next; /* because we may delete it */
-
- /* Forget any interfaces that have disappeared.
- */
- if (!(ifp->int_state & (IS_CHECKED | IS_REMOTE))) {
- trace_act("interface %s has disappeared\n",
- ifp->int_name);
- ifdel(ifp);
- continue;
- }
-
- if ((ifp->int_state & IS_BROKE)
- && !(ifp->int_state & IS_PASSIVE))
- LIM_SEC(ifinit_timer, now.tv_sec+CHECK_BAD_INTERVAL);
-
- /* If we ever have a RIPv1 interface, assume we always will.
- * It might come back if it ever goes away.
- */
- if (!(ifp->int_if_flags & IFF_LOOPBACK)) {
- if (!(ifp->int_state & IS_NO_RIPV1_OUT))
- have_ripv1_out = 1;
- if (!(ifp->int_state & IS_NO_RIPV1_IN))
- have_ripv1_in = 1;
- }
- }
-
- for (ifp = ifnet; ifp != 0; ifp = ifp->int_next) {
- /* Ensure there is always a network route for interfaces,
- * after any dead interfaces have been deleted, which
- * might affect routes for point-to-point links.
- */
- addrouteforif(ifp);
-
- /* Add routes to the local end of point-to-point interfaces
- * using loopback.
- */
- if ((ifp->int_if_flags & IFF_POINTOPOINT)
- && !(ifp->int_state & IS_REMOTE)
- && foundloopback) {
- /* Delete any routes to the network address through
- * foreign routers. Remove even static routes.
- */
- del_static(ifp->int_addr, HOST_MASK, 0);
- rt = rtget(ifp->int_addr, HOST_MASK);
- if (rt != 0 && rt->rt_router != loopaddr) {
- rtdelete(rt);
- rt = 0;
- }
- if (rt != 0) {
- if (!(rt->rt_state & RS_LOCAL)
- || rt->rt_metric > ifp->int_metric) {
- ifp1 = ifp;
- } else {
- ifp1 = rt->rt_ifp;
- }
- rtchange(rt,((rt->rt_state & ~RS_NET_SYN)
- | (RS_IF|RS_LOCAL)),
- loopaddr, loopaddr,
- 0, 0, ifp1, rt->rt_time, 0);
- } else {
- rtadd(ifp->int_addr, HOST_MASK,
- loopaddr, loopaddr,
- 0, 0, (RS_IF | RS_LOCAL), ifp);
- }
- }
- }
-
- /* add the authority routes */
- for (intnetp = intnets; intnetp!=0; intnetp = intnetp->intnet_next) {
- rt = rtget(intnetp->intnet_addr, intnetp->intnet_mask);
- if (rt != 0
- && !(rt->rt_state & RS_NO_NET_SYN)
- && !(rt->rt_state & RS_NET_INT)) {
- rtdelete(rt);
- rt = 0;
- }
- if (rt == 0)
- rtadd(intnetp->intnet_addr, intnetp->intnet_mask,
- loopaddr, loopaddr, intnetp->intnet_metric-1,
- 0, RS_NET_SYN | RS_NET_INT, 0);
- }
-
- prev_complaints = complaints;
-}
-
-
-static void
-check_net_syn(struct interface *ifp)
-{
- struct rt_entry *rt;
-
-
- /* Turn on the need to automatically synthesize a network route
- * for this interface only if we are running RIPv1 on some other
- * interface that is on a different class-A,B,or C network.
- */
- if (have_ripv1_out || have_ripv1_in) {
- ifp->int_state |= IS_NEED_NET_SYN;
- rt = rtget(ifp->int_std_addr, ifp->int_std_mask);
- if (rt != 0
- && 0 == (rt->rt_state & RS_NO_NET_SYN)
- && (!(rt->rt_state & RS_NET_SYN)
- || rt->rt_metric > ifp->int_metric)) {
- rtdelete(rt);
- rt = 0;
- }
- if (rt == 0)
- rtadd(ifp->int_std_addr, ifp->int_std_mask,
- ifp->int_addr, ifp->int_addr,
- ifp->int_metric, 0, RS_NET_SYN, ifp);
-
- } else {
- ifp->int_state &= ~IS_NEED_NET_SYN;
-
- rt = rtget(ifp->int_std_addr,
- ifp->int_std_mask);
- if (rt != 0
- && (rt->rt_state & RS_NET_SYN)
- && rt->rt_ifp == ifp)
- rtbad_sub(rt);
- }
-}
-
-
-/* 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.
- */
-void
-addrouteforif(struct interface *ifp)
-{
- struct rt_entry *rt;
- naddr dst, gate;
-
-
- /* skip sick interfaces
- */
- if (ifp->int_state & IS_BROKE)
- return;
-
- /* If the interface on a subnet, then install a RIPv1 route to
- * the network as well (unless it is sick).
- */
- if (ifp->int_state & IS_SUBNET)
- check_net_syn(ifp);
-
- if (ifp->int_state & IS_REMOTE) {
- dst = ifp->int_addr;
- gate = ifp->int_dstaddr;
- /* If we are going to send packets to the gateway,
- * it must be reachable using our physical interfaces
- */
- if (!(ifp->int_state && IS_EXTERNAL)
- && !rtfind(ifp->int_dstaddr)
- && ifp->int_transitions == 0) {
- msglog("unreachable gateway %s in "
- _PATH_GATEWAYS" entry %s",
- naddr_ntoa(gate), ifp->int_name);
- return;
- }
-
- } else {
- dst = (0 != (ifp->int_if_flags & (IFF_POINTOPOINT
- | IFF_LOOPBACK))
- ? ifp->int_dstaddr
- : htonl(ifp->int_net));
- gate = ifp->int_addr;
- }
-
- /* We are finished if the correct main interface route exists.
- * The right route must be for the right interface, not synthesized
- * from a subnet, be a "gateway" or not as appropriate, and so forth.
- */
- del_static(dst, ifp->int_mask, 0);
- rt = rtget(dst, ifp->int_mask);
- if (rt != 0) {
- if ((rt->rt_ifp != ifp
- || rt->rt_router != ifp->int_addr)
- && (!(ifp->int_state & IS_DUP)
- || rt->rt_ifp == 0
- || (rt->rt_ifp->int_state & IS_BROKE))) {
- rtdelete(rt);
- rt = 0;
- } else {
- rtchange(rt, ((rt->rt_state | RS_IF)
- & ~(RS_NET_SYN | RS_LOCAL)),
- ifp->int_addr, ifp->int_addr,
- ifp->int_metric, 0, ifp, now.tv_sec, 0);
- }
- }
- if (rt == 0) {
- if (ifp->int_transitions++ > 0)
- trace_act("re-install interface %s\n",
- ifp->int_name);
-
- rtadd(dst, ifp->int_mask, gate, gate,
- ifp->int_metric, 0, RS_IF, ifp);
- }
-}
diff --git a/usr.sbin/routed/input.c b/usr.sbin/routed/input.c
deleted file mode 100644
index 7df5988..0000000
--- a/usr.sbin/routed/input.c
+++ /dev/null
@@ -1,714 +0,0 @@
-/*
- * Copyright (c) 1983, 1988, 1993
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#if !defined(lint) && !defined(sgi) && !defined(__NetBSD__)
-static char sccsid[] = "@(#)input.c 8.1 (Berkeley) 6/5/93";
-#elif defined(__NetBSD__)
-static char rcsid[] = "$NetBSD$";
-#endif
-#ident "$Revision: 1.1.3.3 $"
-
-#include "defs.h"
-
-static void input(struct sockaddr_in *, struct interface*, struct rip *, int);
-static void input_route(struct interface *, naddr,
- naddr, naddr, naddr, struct netinfo *);
-
-
-/* process RIP input
- */
-void
-read_rip(int sock,
- struct interface *ifp)
-{
- struct sockaddr_in from;
- int fromlen, cc;
- union pkt_buf inbuf;
-
-
- for (;;) {
- fromlen = sizeof(from);
- cc = recvfrom(sock, &inbuf, sizeof(inbuf), 0,
- (struct sockaddr*)&from, &fromlen);
- if (cc <= 0) {
- if (cc < 0 && errno != EWOULDBLOCK)
- LOGERR("recvfrom(rip)");
- break;
- }
- if (fromlen != sizeof(struct sockaddr_in))
- logbad(1,"impossible recvfrom(rip) fromlen=%d",
- fromlen);
-
- input(&from,
- (ifp != 0) ? ifp : iflookup(from.sin_addr.s_addr),
- &inbuf.rip, cc);
- }
-}
-
-
-/* Process a RIP packet
- */
-static void
-input(struct sockaddr_in *from, /* received from this IP address */
- struct interface *ifp,
- struct rip *rip,
- int size)
-{
-# define FROM_NADDR from->sin_addr.s_addr
- static naddr use_auth, bad_len, bad_mask;
- static naddr unk_router, bad_router, bad_nhop;
-
- struct rt_entry *rt;
- struct netinfo *n, *lim;
- struct interface *ifp1;
- naddr gate, mask, v1_mask, dst, ddst_h;
- int i;
-
-
- if (ifp != 0)
- ifp->int_state |= IS_ACTIVE;
-
- trace_rip("Recv", "from", from, ifp, rip, size);
-
- if (rip->rip_vers == 0) {
- if (from->sin_addr.s_addr != bad_router)
- msglog("RIP version 0, cmd %d, packet received"
- " from %s",
- rip->rip_cmd, naddr_ntoa(FROM_NADDR));
- bad_router = from->sin_addr.s_addr;
- return;
- }
- if (size > MAXPACKETSIZE) {
- if (from->sin_addr.s_addr != bad_router)
- msglog("packet at least %d bytes too long received"
- " from %s",
- size-MAXPACKETSIZE, naddr_ntoa(FROM_NADDR));
- bad_router = from->sin_addr.s_addr;
- return;
- }
-
- n = rip->rip_nets;
- lim = (struct netinfo *)((char*)rip + size);
-
- /* Notice authentication.
- * As required by section 4.2 in RFC 1723, discard authenticated
- * RIPv2 messages, but only if configured for that silliness.
- *
- * RIPv2 authentication is lame, since snooping on the wire makes
- * its simple passwords evident. Also, why authenticate queries?
- * Why should a RIPv2 implementation with authentication disabled
- * not be able to listen to RIPv2 packets with authenication, while
- * RIPv1 systems will listen? Crazy!
- */
- if (!auth_ok
- && rip->rip_vers >= RIPv2
- && n < lim && n->n_family == RIP_AF_AUTH) {
- if (from->sin_addr.s_addr != use_auth)
- msglog("RIPv2 message with authentication"
- " from %s discarded",
- naddr_ntoa(FROM_NADDR));
- use_auth = from->sin_addr.s_addr;
- trace_pkt("discard authenticated RIPv2 message\n");
- return;
- }
-
- switch (rip->rip_cmd) {
- case RIPCMD_REQUEST:
- /* did the request come from a router?
- */
- if (from->sin_port == htons(RIP_PORT)) {
- /* yes, ignore it if RIP is off so that it does not
- * depend on us.
- */
- if (rip_sock < 0) {
- trace_pkt("ignore request while RIP off\n");
- return;
- }
-
- /* Ignore the request if we talking to ourself
- * (and not a remote gateway).
- */
- if (ifwithaddr(FROM_NADDR, 0, 0) != 0) {
- trace_pkt("discard our own RIP request\n");
- return;
- }
- }
-
- /* According to RFC 1723, we should ignore unathenticated
- * queries. That is too silly to bother with. Sheesh!
- * Are forwarding tables supposed to be secret? When
- * a bad guy can infer them with test traffic?
- * Maybe on firewalls you'd care, but not enough to
- * give up the diagnostic facilities of remote probing.
- */
-
- if (n >= lim
- || size%sizeof(*n) != sizeof(struct rip)%sizeof(*n)) {
- if (from->sin_addr.s_addr != bad_len)
- msglog("request of bad length (%d) from %s",
- size, naddr_ntoa(FROM_NADDR));
- bad_len = from->sin_addr.s_addr;
- }
- for (; n < lim; n++) {
- n->n_metric = ntohl(n->n_metric);
-
- /* A single entry with family RIP_AF_UNSPEC and
- * metric HOPCNT_INFINITY means "all routes".
- * We respond to routers only if we are acting
- * as a supplier, or to anyone other than a router
- * (i.e. a query).
- *
- * Answer a query from a stray program with all
- * we know. Filter the answer to a query from a
- * router in the about same way broadcasts are
- * filtered.
- *
- * Only answer a router if we are a supplier
- * to keep an unwary host that is just starting
- * from picking us an a router.
- */
- if (n->n_family == RIP_AF_UNSPEC
- && n->n_metric == HOPCNT_INFINITY
- && n == rip->rip_nets
- && n+1 == lim) {
- if (from->sin_port != htons(RIP_PORT)) {
- /* query from `rtquery` or similar
- */
- supply(from, ifp,
- OUT_QUERY, 0, rip->rip_vers);
- } else if (supplier) {
- /* a router trying to prime its
- * tables.
- */
- supply(from, ifp,
- OUT_UNICAST, 0, rip->rip_vers);
- }
- return;
- }
-
- if (n->n_family != RIP_AF_INET) {
- if (from->sin_addr.s_addr != bad_router)
- msglog("request from %s"
- " for unsupported (af %d) %s",
- naddr_ntoa(FROM_NADDR),
- ntohs(n->n_family),
- naddr_ntoa(n->n_dst));
- bad_router = from->sin_addr.s_addr;
- return;
- }
-
- dst = n->n_dst;
- if (!check_dst(dst)) {
- if (from->sin_addr.s_addr != bad_router)
- msglog("bad queried destination"
- " %s from %s",
- naddr_ntoa(dst),
- naddr_ntoa(FROM_NADDR));
- bad_router = from->sin_addr.s_addr;
- return;
- }
-
- if (rip->rip_vers == RIPv1
- || 0 == (mask = ntohl(n->n_mask))
- || 0 != (ntohl(dst) & ~mask))
- mask = ripv1_mask_host(dst,ifp);
-
- rt = rtget(dst, mask);
- if (!rt && dst != RIP_DEFAULT)
- rt = rtfind(n->n_dst);
-
- n->n_tag = 0;
- n->n_nhop = 0;
- if (rip->rip_vers == RIPv1) {
- n->n_mask = 0;
- } else {
- n->n_mask = mask;
- }
- if (rt == 0) {
- n->n_metric = HOPCNT_INFINITY;
- } else {
- n->n_metric = rt->rt_metric+1;
- n->n_metric += (ifp!=0) ? ifp->int_metric : 1;
- if (n->n_metric > HOPCNT_INFINITY)
- n->n_metric = HOPCNT_INFINITY;
- if (rip->rip_vers != RIPv1) {
- n->n_tag = rt->rt_tag;
- if (ifp != 0
- && on_net(rt->rt_gate,
- ifp->int_net,
- ifp->int_mask)
- && rt->rt_gate != ifp->int_addr)
- n->n_nhop = rt->rt_gate;
- }
- }
- HTONL(n->n_metric);
- }
- /* Answer about specific routes.
- * Only answer a router if we are a supplier
- * to keep an unwary host that is just starting
- * from picking us an a router.
- */
- rip->rip_cmd = RIPCMD_RESPONSE;
- rip->rip_res1 = 0;
- if (rip->rip_vers != RIPv1)
- rip->rip_vers = RIPv2;
- if (from->sin_port != htons(RIP_PORT)) {
- /* query */
- (void)output(OUT_QUERY, from, ifp, rip, size);
- } else if (supplier) {
- (void)output(OUT_UNICAST, from, ifp, rip, size);
- }
- return;
-
- case RIPCMD_TRACEON:
- case RIPCMD_TRACEOFF:
- /* verify message came from a privileged port */
- if (ntohs(from->sin_port) > IPPORT_RESERVED) {
- msglog("trace command from untrusted port on %s",
- naddr_ntoa(FROM_NADDR));
- return;
- }
- if (ifp == 0) {
- msglog("trace command from unknown router %s",
- naddr_ntoa(FROM_NADDR));
- return;
- }
- if (rip->rip_cmd == RIPCMD_TRACEON) {
- rip->rip_tracefile[size-4] = '\0';
- trace_on((char*)rip->rip_tracefile, 0);
- } else {
- trace_off("tracing turned off by %s\n",
- naddr_ntoa(FROM_NADDR));
- }
- return;
-
- case RIPCMD_RESPONSE:
- if (size%sizeof(*n) != sizeof(struct rip)%sizeof(*n)) {
- if (from->sin_addr.s_addr != bad_len)
- msglog("response of bad length (%d) from %s",
- size, naddr_ntoa(FROM_NADDR));
- bad_len = from->sin_addr.s_addr;
- }
-
- /* verify message came from a router */
- if (from->sin_port != ntohs(RIP_PORT)) {
- trace_pkt("discard RIP response from unknown port\n");
- return;
- }
-
- if (rip_sock < 0) {
- trace_pkt("discard response while RIP off\n");
- return;
- }
-
- /* Are we talking to ourself or a remote gateway?
- */
- ifp1 = ifwithaddr(FROM_NADDR, 0, 1);
- if (ifp1) {
- if (ifp1->int_state & IS_REMOTE) {
- if (ifp1->int_state & IS_PASSIVE) {
- msglog("bogus input from %s on"
- " supposedly passive %s",
- naddr_ntoa(FROM_NADDR),
- ifp1->int_name);
- } else {
- ifp1->int_act_time = now.tv_sec;
- if (if_ok(ifp1, "remote "))
- addrouteforif(ifp1);
- }
- } else {
- trace_pkt("discard our own RIP response\n");
- }
- return;
- }
-
- /* Check the 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 (from->sin_addr.s_addr != unk_router)
- msglog("packet from unknown router %s"
- " or via unidentified interface",
- naddr_ntoa(FROM_NADDR));
- unk_router = from->sin_addr.s_addr;
- return;
- }
- if (ifp->int_state & IS_PASSIVE) {
- trace_act("packet from %s via passive interface %s\n",
- naddr_ntoa(FROM_NADDR),
- ifp->int_name);
- return;
- }
-
- /* Check required version
- */
- if (((ifp->int_state & IS_NO_RIPV1_IN)
- && rip->rip_vers == RIPv1)
- || ((ifp->int_state & IS_NO_RIPV2_IN)
- && rip->rip_vers != RIPv1)) {
- trace_pkt("discard RIPv%d response\n",
- rip->rip_vers);
- return;
- }
-
- /* Ignore routes via dead interface.
- */
- if (ifp->int_state & IS_BROKE) {
- trace_pkt("discard response via broken interface %s\n",
- ifp->int_name);
- return;
- }
-
- /* Authenticate the packet if we have a secret.
- */
- if (ifp->int_passwd[0] != '\0') {
- if (n >= lim
- || n->n_family != RIP_AF_AUTH
- || ((struct netauth*)n)->a_type != RIP_AUTH_PW) {
- if (from->sin_addr.s_addr != use_auth)
- msglog("missing password from %s",
- naddr_ntoa(FROM_NADDR));
- use_auth = from->sin_addr.s_addr;
- return;
-
- } else if (0 != bcmp(((struct netauth*)n)->au.au_pw,
- ifp->int_passwd,
- sizeof(ifp->int_passwd))) {
- if (from->sin_addr.s_addr != use_auth)
- msglog("bad password from %s",
- naddr_ntoa(FROM_NADDR));
- use_auth = from->sin_addr.s_addr;
- return;
- }
- }
-
- for (; n < lim; n++) {
- if (n->n_family == RIP_AF_AUTH)
- continue;
-
- NTOHL(n->n_metric);
- dst = n->n_dst;
- if (n->n_family != RIP_AF_INET
- && (n->n_family != RIP_AF_UNSPEC
- || dst != RIP_DEFAULT)) {
- if (from->sin_addr.s_addr != bad_router)
- msglog("route from %s to unsupported"
- " address family %d,"
- " destination %s",
- naddr_ntoa(FROM_NADDR),
- n->n_family,
- naddr_ntoa(dst));
- bad_router = from->sin_addr.s_addr;
- continue;
- }
- if (!check_dst(dst)) {
- if (from->sin_addr.s_addr != bad_router)
- msglog("bad destination %s from %s",
- naddr_ntoa(dst),
- naddr_ntoa(FROM_NADDR));
- bad_router = from->sin_addr.s_addr;
- return;
- }
- if (n->n_metric == 0
- || n->n_metric > HOPCNT_INFINITY) {
- if (from->sin_addr.s_addr != bad_router)
- msglog("bad metric %d from %s"
- " for destination %s",
- n->n_metric,
- naddr_ntoa(FROM_NADDR),
- naddr_ntoa(dst));
- bad_router = from->sin_addr.s_addr;
- return;
- }
-
- /* Notice the next-hop.
- */
- gate = from->sin_addr.s_addr;
- if (n->n_nhop != 0
- && rip->rip_vers == RIPv2) {
- /* Ignore the route if it points to us */
- if (0 != ifwithaddr(n->n_nhop, 1, 0))
- continue;
-
- /* Use it only if it is valid. */
- if (on_net(n->n_nhop,
- ifp->int_net, ifp->int_mask)
- && check_dst(n->n_nhop)) {
- gate = n->n_nhop;
- } else {
- if (bad_nhop != from->sin_addr.s_addr)
- msglog("router %s to %s has"
- " bad next hop %s",
- naddr_ntoa(FROM_NADDR),
- naddr_ntoa(dst),
- naddr_ntoa(n->n_nhop));
- bad_nhop = from->sin_addr.s_addr;
- }
- }
-
- if (rip->rip_vers == RIPv1
- || 0 == (mask = ntohl(n->n_mask))) {
- mask = ripv1_mask_host(dst,ifp);
- } else if ((ntohl(dst) & ~mask) != 0) {
- if (bad_mask != from->sin_addr.s_addr) {
- msglog("router %s sent bad netmask"
- " %#x with %s",
- naddr_ntoa(FROM_NADDR),
- mask,
- naddr_ntoa(dst));
- bad_mask = from->sin_addr.s_addr;
- }
- continue;
- }
- if (rip->rip_vers == RIPv1)
- n->n_tag = 0;
-
- /* Adjust metric according to incoming interface..
- */
- n->n_metric += ifp->int_metric;
- if (n->n_metric > HOPCNT_INFINITY)
- n->n_metric = HOPCNT_INFINITY;
-
- /* Recognize and ignore a default route we faked
- * which is being sent back to us by a machine with
- * broken split-horizon.
- * Be a little more paranoid than that, and reject
- * default routes with the same metric we advertised.
- */
- if (ifp->int_d_metric != 0
- && dst == RIP_DEFAULT
- && n->n_metric >= ifp->int_d_metric)
- continue;
-
- /* We can receive aggregated RIPv2 routes that must
- * be broken down before they are transmitted by
- * RIPv1 via an interface on a subnet.
- * We might also receive the same routes aggregated
- * via other RIPv2 interfaces.
- * This could cause duplicate routes to be sent on
- * the RIPv1 interfaces. "Longest matching variable
- * length netmasks" lets RIPv2 listeners understand,
- * but breaking down the aggregated routes for RIPv1
- * listeners can produce duplicate routes.
- *
- * Breaking down aggregated routes here bloats
- * the daemon table, but does not hurt the kernel
- * table, since routes are always aggregated for
- * the kernel.
- *
- * Notice that this does not break down network
- * routes corresponding to subnets. This is part
- * of the defense against RS_NET_SYN.
- */
- if (have_ripv1_out
- && (v1_mask = ripv1_mask_net(dst,0)) > mask
- && (((rt = rtget(dst,mask)) == 0
- || !(rt->rt_state & RS_NET_SYN)))) {
- ddst_h = v1_mask & -v1_mask;
- i = (v1_mask & ~mask)/ddst_h;
- if (i >= 511) {
- /* Punt if we would have to generate
- * an unreasonable number of routes.
- */
-#ifdef DEBUG
- msglog("accept %s from %s as 1"
- " instead of %d routes",
- addrname(dst,mask,0),
- naddr_ntoa(FROM_NADDR),
- i+1);
-#endif
- i = 0;
- } else {
- mask = v1_mask;
- }
- } else {
- i = 0;
- }
-
- for (;;) {
- input_route(ifp, FROM_NADDR,
- dst, mask, gate, n);
- if (i-- == 0)
- break;
- dst = htonl(ntohl(dst) + ddst_h);
- }
- }
- break;
- }
-}
-
-
-/* Process a single input route.
- */
-static void
-input_route(struct interface *ifp,
- naddr from,
- naddr dst,
- naddr mask,
- naddr gate,
- struct netinfo *n)
-{
- int i;
- struct rt_entry *rt;
- struct rt_spare *rts, *rts0;
- struct interface *ifp1;
- time_t new_time;
-
-
- /* See if the other guy is telling us to send our packets to him.
- * Sometimes network routes arrive over a point-to-point link for
- * the network containing the address(es) of the link.
- *
- * If our interface is broken, switch to using the other guy.
- */
- ifp1 = ifwithaddr(dst, 1, 1);
- if (ifp1 != 0
- && !(ifp1->int_state & IS_BROKE))
- return;
-
- /* Look for the route in our table.
- */
- rt = rtget(dst, mask);
-
- /* Consider adding the route if we do not already have it.
- */
- if (rt == 0) {
- /* Ignore unknown routes being poisoned.
- */
- if (n->n_metric == HOPCNT_INFINITY)
- return;
-
- if (total_routes < MAX_ROUTES)
- rtadd(dst, mask, gate, from, n->n_metric,
- n->n_tag, 0, ifp);
- return;
- }
-
- /* We already know about the route. Consider this update.
- *
- * If (rt->rt_state & RS_NET_SYN), then this route
- * is the same as a network route we have inferred
- * for subnets we know, in order to tell RIPv1 routers
- * about the subnets.
- *
- * It is impossible to tell if the route is coming
- * from a distant RIPv2 router with the standard
- * netmask because that router knows about the entire
- * network, or if it is a round-about echo of a
- * synthetic, RIPv1 network route of our own.
- * The worst is that both kinds of routes might be
- * received, and the bad one might have the smaller
- * metric. Partly solve this problem by faking the
- * RIPv1 route with a metric that reflects the most
- * distant part of the subnet. Also never
- * aggregate into such a route. Also keep it
- * around as long as the interface exists.
- */
-
- rts0 = rt->rt_spares;
- for (rts = rts0, i = NUM_SPARES; i != 0; i--, rts++) {
- if (rts->rts_router == from)
- break;
- /* Note the worst slot to reuse,
- * other than the current slot.
- */
- if (rts0 == rt->rt_spares
- || BETTER_LINK(rt, rts0, rts))
- rts0 = rts;
- }
- if (i != 0) {
- /* Found the router
- */
- int old_metric = rts->rts_metric;
-
- /* Keep poisoned routes around only long enough to pass
- * the poison on. Get a new timestamp for good routes.
- */
- new_time =((old_metric == HOPCNT_INFINITY)
- ? rts->rts_time
- : now.tv_sec);
-
- /* If this is an update for the router we currently prefer,
- * then note it.
- */
- if (i == NUM_SPARES) {
- rtchange(rt,rt->rt_state, gate,rt->rt_router,
- n->n_metric, n->n_tag, ifp, new_time, 0);
- /* If the route got worse, check for something better.
- */
- if (n->n_metric > old_metric)
- rtswitch(rt, 0);
- return;
- }
-
- /* This is an update for a spare route.
- * Finished if the route is unchanged.
- */
- if (rts->rts_gate == gate
- && old_metric == n->n_metric
- && rts->rts_tag == n->n_tag) {
- rts->rts_time = new_time;
- return;
- }
-
- } else {
- /* The update is for a route we know about,
- * but not from a familiar router.
- */
- rts = rts0;
-
- /* Save the route as a spare only if it has
- * a better metric than our worst spare.
- * This also ignores poisoned routes (those
- * received with metric HOPCNT_INFINITY).
- */
- if (n->n_metric >= rts->rts_metric)
- return;
-
- new_time = now.tv_sec;
- }
-
- trace_upslot(rt, rts, gate, from, ifp, n->n_metric,n->n_tag, new_time);
-
- rts->rts_gate = gate;
- rts->rts_router = from;
- rts->rts_metric = n->n_metric;
- rts->rts_tag = n->n_tag;
- rts->rts_time = new_time;
- rts->rts_ifp = ifp;
-
- /* try to switch to a better route */
- rtswitch(rt, rts);
-}
diff --git a/usr.sbin/routed/main.c b/usr.sbin/routed/main.c
deleted file mode 100644
index b96fe71..0000000
--- a/usr.sbin/routed/main.c
+++ /dev/null
@@ -1,824 +0,0 @@
-/*
- * Copyright (c) 1983, 1988, 1993
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-char copyright[] =
-"@(#) Copyright (c) 1983, 1988, 1993\n\
- The Regents of the University of California. All rights reserved.\n";
-#if !defined(lint) && !defined(sgi) && !defined(__NetBSD__)
-static char sccsid[] = "@(#)main.c 8.1 (Berkeley) 6/5/93";
-#elif defined(__NetBSD__)
-static char rcsid[] = "$NetBSD$";
-#endif
-#ident "$Revision: 1.1.3.3 $"
-
-#include "defs.h"
-#include "pathnames.h"
-#ifdef sgi
-#include "math.h"
-#endif
-#include <signal.h>
-#include <fcntl.h>
-#include <sys/file.h>
-
-pid_t mypid;
-
-naddr myaddr; /* system address */
-char myname[MAXHOSTNAMELEN+1];
-
-int supplier; /* supply or broadcast updates */
-int supplier_set;
-int ipforwarding = 1; /* kernel forwarding on */
-
-int default_gateway; /* 1=advertise default */
-int background = 1;
-int ridhosts; /* 1=reduce host routes */
-int mhome; /* 1=want multi-homed host route */
-int advertise_mhome; /* 1=must continue adverising it */
-int auth_ok = 1; /* 1=ignore auth if we do not care */
-
-struct timeval epoch; /* when started */
-struct timeval clk, prev_clk;
-struct timeval now; /* current idea of time */
-time_t now_stale;
-time_t now_garbage;
-
-struct timeval next_bcast; /* next general broadcast */
-struct timeval no_flash = {EPOCH+SUPPLY_INTERVAL}; /* inhibit flash update */
-
-fd_set fdbits;
-int sock_max;
-int rip_sock = -1; /* RIP socket */
-struct interface *rip_sock_mcast; /* current multicast interface */
-int rt_sock; /* routing socket */
-int rt_sock_seqno;
-
-
-static int get_rip_sock(naddr, int);
-static void timevalsub(struct timeval *, struct timeval *, struct timeval *);
-
-int
-main(int argc,
- char *argv[])
-{
- int n, mib[4], off;
- size_t len;
- char *p, *q;
- struct timeval wtime, t2;
- time_t dt;
- fd_set ibits;
- naddr p_addr, p_mask;
- struct interface *ifp;
- struct parm parm;
- char *tracename = 0;
-
-
- openlog("routed", LOG_PID | LOG_ODELAY, LOG_DAEMON);
- ftrace = stdout;
-
- gettimeofday(&clk, 0);
- prev_clk = clk;
- epoch = clk;
- epoch.tv_sec -= EPOCH;
- now.tv_sec = EPOCH;
- now_stale = EPOCH - STALE_TIME;
- now_garbage = EPOCH - GARBAGE_TIME;
- wtime.tv_sec = 0;
-
- (void)gethostname(myname, sizeof(myname)-1);
- (void)gethost(myname, &myaddr);
-
- while ((n = getopt(argc, argv, "sqdghmAtT:F:P:")) != EOF) {
- switch (n) {
- case 's':
- supplier = 1;
- supplier_set = 1;
- break;
-
- case 'q':
- supplier = 0;
- supplier_set = 1;
- break;
-
- case 'd':
- background = 0;
- break;
-
- case 'g':
- bzero(&parm, sizeof(parm));
- parm.parm_d_metric = 1;
- p = check_parms(&parm);
- if (p != 0)
- msglog("bad -g: %s", p);
- else
- default_gateway = 1;
- break;
-
- case 'h': /* suppress extra host routes */
- ridhosts = 1;
- break;
-
- case 'm': /* advertise host route */
- mhome = 1; /* on multi-homed hosts */
- break;
-
- case 'A':
- /* Ignore authentication if we do not care.
- * Crazy as it is, that is what RFC 1723 requires.
- */
- auth_ok = 0;
- break;
-
- case 't':
- new_tracelevel++;
- break;
-
- case 'T':
- tracename = optarg;
- break;
-
- case 'F': /* minimal routes for SLIP */
- n = HOPCNT_INFINITY-2;
- p = strchr(optarg,',');
- if (p && *p != '\0') {
- n = (int)strtoul(p+1, &q, 0);
- if (*q == '\0'
- && n <= HOPCNT_INFINITY-1
- && n >= 1)
- *p = '\0';
- }
- if (!getnet(optarg, &p_addr, &p_mask)) {
- msglog("bad network; \"-F %s\"",
- optarg);
- break;
- }
- bzero(&parm, sizeof(parm));
- parm.parm_addr_h = ntohl(p_addr);
- parm.parm_mask = p_mask;
- parm.parm_d_metric = n;
- p = check_parms(&parm);
- if (p != 0)
- msglog("bad -F: %s", p);
- break;
-
- case 'P':
- /* handle arbirary, (usually) per-interface
- * parameters.
- */
- p = parse_parms(optarg);
- if (p != 0)
- msglog("bad \"%s\" in \"%s\"",
- p, optarg);
- break;
-
- default:
- goto usage;
- }
- }
- argc -= optind;
- argv += optind;
-
- if (tracename == 0 && argc >= 1) {
- tracename = *argv++;
- argc--;
- }
- if (argc != 0) {
-usage:
- logbad(0, "usage: routed [-sqdghmpAt] [-T /tracefile]"
- " [-F net[,metric]] [-P parms]");
- }
- if (geteuid() != 0)
- logbad(0, "requires UID 0");
-
- mib[0] = CTL_NET;
- mib[1] = PF_INET;
- mib[2] = IPPROTO_IP;
- mib[3] = IPCTL_FORWARDING;
- len = sizeof(ipforwarding);
- if (sysctl(mib, 4, &ipforwarding, &len, 0, 0) < 0)
- LOGERR("sysctl(IPCTL_FORWARDING)");
-
- if (!ipforwarding) {
- if (supplier)
- msglog("-s incompatible with ipforwarding=0");
- if (default_gateway) {
- msglog("-g incompatible with ipforwarding=0");
- default_gateway = 0;
- }
- supplier = 0;
- supplier_set = 1;
- }
- if (default_gateway) {
- if (supplier_set && !supplier) {
- msglog("-g and -q incompatible");
- } else {
- supplier = 1;
- supplier_set = 1;
- }
- }
-
-
- /* get into the background */
- if (background) {
-#ifdef sgi
- if (0 > _daemonize(_DF_NOCHDIR,
- new_tracelevel == 0 ? -1 : STDOUT_FILENO,
- new_tracelevel == 0 ? -1 : STDERR_FILENO,
- -1))
- BADERR(0, "_daemonize()");
-#else
- if (daemon(1, 1) < 0)
- BADERR(0,"daemon()");
-#endif
- }
-
- mypid = getpid();
- srandom((int)(clk.tv_sec ^ clk.tv_usec ^ mypid));
-
- /* prepare socket connected to the kernel.
- */
- rt_sock = socket(AF_ROUTE, SOCK_RAW, 0);
- if (rt_sock < 0)
- BADERR(1,"rt_sock = socket()");
- if (fcntl(rt_sock, F_SETFL, O_NONBLOCK) == -1)
- logbad(1, "fcntl(rt_sock) O_NONBLOCK: %s", strerror(errno));
- off = 0;
- if (setsockopt(rt_sock, SOL_SOCKET,SO_USELOOPBACK,
- &off,sizeof(off)) < 0)
- LOGERR("setsockopt(SO_USELOOPBACK,0)");
-
- fix_select();
-
-
- if (background && new_tracelevel == 0)
- ftrace = 0;
- if (tracename != 0) {
- trace_on(tracename, 1);
- if (new_tracelevel == 0) /* use stdout if file is bad */
- new_tracelevel = 1;
- }
- set_tracelevel();
-
- /* initialize radix tree */
- rtinit();
-
- /* Pick a random part of the second for our output to minimize
- * collisions.
- *
- * Start broadcasting after hearing from other routers, and
- * at a random time so a bunch of systems do not get synchronized
- * after a power failure.
- */
- intvl_random(&next_bcast, EPOCH+MIN_WAITTIME, EPOCH+SUPPLY_INTERVAL);
- age_timer.tv_usec = next_bcast.tv_usec;
- age_timer.tv_sec = EPOCH+MIN_WAITTIME;
- rdisc_timer = next_bcast;
- ifinit_timer.tv_usec = next_bcast.tv_usec;
-
- signal(SIGALRM, sigalrm);
- signal(SIGHUP, sigterm);
- signal(SIGTERM, sigterm);
- signal(SIGINT, sigterm);
- signal(SIGUSR1, sigtrace_on);
- signal(SIGUSR2, sigtrace_off);
-
- /* Collect an initial view of the world by checking the interface
- * configuration and the kludge file.
- */
- gwkludge();
- ifinit();
- flush_kern();
-
- /* Ask for routes */
- rip_query();
- if (!supplier)
- rdisc_sol();
-
- /* Loop forever, listening and broadcasting.
- */
- for (;;) {
- prev_clk = clk;
- gettimeofday(&clk, 0);
- timevalsub(&t2, &clk, &prev_clk);
- if (t2.tv_sec < 0
- || t2.tv_sec > wtime.tv_sec + 5) {
- /* Deal with time changes before other housekeeping to
- * keep everything straight.
- */
- dt = t2.tv_sec;
- if (dt > 0)
- dt -= wtime.tv_sec;
- trace_act("time changed by %d sec\n", dt);
- epoch.tv_sec += dt;
- }
- timevalsub(&now, &clk, &epoch);
- now_stale = now.tv_sec - STALE_TIME;
- now_garbage = now.tv_sec - GARBAGE_TIME;
-
- /* deal with interrupts that should affect tracing */
- set_tracelevel();
-
- if (stopint != 0) {
- if (supplier) {
- rip_bcast(0);
- rdisc_adv();
- }
- trace_off("exiting with signal %d\n", stopint);
- exit(stopint | 128);
- }
-
- /* look for new or dead interfaces */
- timevalsub(&wtime, &ifinit_timer, &now);
- if (wtime.tv_sec <= 0) {
- wtime.tv_sec = 0;
- ifinit();
- rip_query();
- continue;
- }
-
- /* If it is time, then broadcast our routes.
- */
- if (supplier || advertise_mhome) {
- timevalsub(&t2, &next_bcast, &now);
- if (t2.tv_sec <= 0) {
- /* Synchronize the aging and broadcast
- * timers to minimize awakenings
- */
- age(0);
-
- rip_bcast(0);
-
- /* It is desirable to send routing updates
- * regularly. So schedule the next update
- * 30 seconds after the previous one was
- * secheduled, instead of 30 seconds after
- * the previous update was finished.
- * Even if we just started after discovering
- * a 2nd interface or were otherwise delayed,
- * pick a 30-second aniversary of the
- * original broadcast time.
- */
- n = 1 + (0-t2.tv_sec)/SUPPLY_INTERVAL;
- next_bcast.tv_sec += n*SUPPLY_INTERVAL;
-
- continue;
- }
-
- if (timercmp(&t2, &wtime, <))
- wtime = t2;
- }
-
- /* If we need a flash update, either do it now or
- * set the delay to end when it is time.
- *
- * If we are within MIN_WAITTIME seconds of a full update,
- * do not bother.
- */
- if (need_flash
- && supplier
- && no_flash.tv_sec+MIN_WAITTIME < next_bcast.tv_sec) {
- /* accurate to the millisecond */
- if (!timercmp(&no_flash, &now, >))
- rip_bcast(1);
- timevalsub(&t2, &no_flash, &now);
- if (timercmp(&t2, &wtime, <))
- wtime = t2;
- }
-
- /* trigger the main aging timer.
- */
- timevalsub(&t2, &age_timer, &now);
- if (t2.tv_sec <= 0) {
- age(0);
- continue;
- }
- if (timercmp(&t2, &wtime, <))
- wtime = t2;
-
- /* update the kernel routing table
- */
- timevalsub(&t2, &need_kern, &now);
- if (t2.tv_sec <= 0) {
- age(0);
- continue;
- }
- if (timercmp(&t2, &wtime, <))
- wtime = t2;
-
- /* take care of router discovery,
- * but do it to the millisecond
- */
- if (!timercmp(&rdisc_timer, &now, >)) {
- rdisc_age(0);
- continue;
- }
- timevalsub(&t2, &rdisc_timer, &now);
- if (timercmp(&t2, &wtime, <))
- wtime = t2;
-
-
- /* wait for input or a timer to expire.
- */
- trace_flush();
- ibits = fdbits;
- n = select(sock_max, &ibits, 0, 0, &wtime);
- if (n <= 0) {
- if (n < 0 && errno != EINTR && errno != EAGAIN)
- BADERR(1,"select");
- continue;
- }
-
- if (FD_ISSET(rt_sock, &ibits)) {
- read_rt();
- n--;
- }
- if (rdisc_sock >= 0 && FD_ISSET(rdisc_sock, &ibits)) {
- read_d();
- n--;
- }
- if (rip_sock >= 0 && FD_ISSET(rip_sock, &ibits)) {
- read_rip(rip_sock, 0);
- n--;
- }
-
- for (ifp = ifnet; n > 0 && 0 != ifp; ifp = ifp->int_next) {
- if (ifp->int_rip_sock >= 0
- && FD_ISSET(ifp->int_rip_sock, &ibits)) {
- read_rip(ifp->int_rip_sock, ifp);
- n--;
- }
- }
- }
-}
-
-
-/* ARGSUSED */
-void
-sigalrm(int sig)
-{
- /* Historically, SIGALRM would cause the daemon to check for
- * new and broken interfaces.
- */
- ifinit_timer.tv_sec = now.tv_sec;
- trace_act("SIGALRM\n");
-}
-
-
-/* watch for fatal signals */
-void
-sigterm(int sig)
-{
- stopint = sig;
- (void)signal(sig, SIG_DFL); /* catch it only once */
-}
-
-
-void
-fix_select(void)
-{
- struct interface *ifp;
-
-
- FD_ZERO(&fdbits);
- sock_max = 0;
-
- FD_SET(rt_sock, &fdbits);
- if (sock_max <= rt_sock)
- sock_max = rt_sock+1;
- if (rip_sock >= 0) {
- FD_SET(rip_sock, &fdbits);
- if (sock_max <= rip_sock)
- sock_max = rip_sock+1;
- }
- for (ifp = ifnet; 0 != ifp; ifp = ifp->int_next) {
- if (ifp->int_rip_sock >= 0) {
- FD_SET(ifp->int_rip_sock, &fdbits);
- if (sock_max <= ifp->int_rip_sock)
- sock_max = ifp->int_rip_sock+1;
- }
- }
- if (rdisc_sock >= 0) {
- FD_SET(rdisc_sock, &fdbits);
- if (sock_max <= rdisc_sock)
- sock_max = rdisc_sock+1;
- }
-}
-
-
-void
-fix_sock(int sock,
- char *name)
-{
- int on;
-#define MIN_SOCKBUF (4*1024)
- static int rbuf;
-
- if (fcntl(sock, F_SETFL, O_NONBLOCK) == -1)
- logbad(1, "fcntl(%s) O_NONBLOCK: %s",
- name, strerror(errno));
- on = 1;
- if (setsockopt(sock, SOL_SOCKET,SO_BROADCAST,
- &on,sizeof(on)) < 0)
- msglog("setsockopt(%s,SO_BROADCAST): %s",
- name, strerror(errno));
- if (rbuf >= MIN_SOCKBUF) {
- if (setsockopt(sock, SOL_SOCKET, SO_RCVBUF,
- &rbuf, sizeof(rbuf)) < 0)
- msglog("setsockopt(%s,SO_RCVBUF=%d): %s",
- name, rbuf, strerror(errno));
- } else {
- for (rbuf = 60*1024; ; rbuf -= 4096) {
- if (setsockopt(sock, SOL_SOCKET, SO_RCVBUF,
- &rbuf, sizeof(rbuf)) == 0) {
- trace_act("RCVBUF=%d\n", rbuf);
- break;
- }
- if (rbuf < MIN_SOCKBUF) {
- msglog("setsockopt(%s,SO_RCVBUF = %d): %s",
- name, rbuf, strerror(errno));
- break;
- }
- }
- }
-}
-
-
-/* get a rip socket
- */
-static int /* <0 or file descriptor */
-get_rip_sock(naddr addr,
- int serious) /* 1=failure to bind is serious */
-{
- struct sockaddr_in sin;
- unsigned char ttl;
- int s;
-
-
- if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
- BADERR(1,"rip_sock = socket()");
-
- bzero(&sin,sizeof(sin));
-#ifdef _HAVE_SIN_LEN
- sin.sin_len = sizeof(sin);
-#endif
- sin.sin_family = AF_INET;
- sin.sin_port = htons(RIP_PORT);
- sin.sin_addr.s_addr = addr;
- if (bind(s, (struct sockaddr *)&sin,sizeof(sin)) < 0) {
- if (serious)
- BADERR(errno != EADDRINUSE, "bind(rip_sock)");
- return -1;
- }
- fix_sock(s,"rip_sock");
-
- ttl = 1;
- if (setsockopt(s, IPPROTO_IP, IP_MULTICAST_TTL,
- &ttl, sizeof(ttl)) < 0)
- DBGERR(1,"rip_sock setsockopt(IP_MULTICAST_TTL)");
-
- return s;
-}
-
-
-/* turn off main RIP socket */
-void
-rip_off(void)
-{
- struct interface *ifp;
- register naddr addr;
-
-
- if (rip_sock >= 0 && !mhome) {
- trace_act("turn off RIP\n");
-
- (void)close(rip_sock);
- rip_sock = -1;
-
- /* get non-broadcast sockets to listen to queries.
- */
- for (ifp = ifnet; ifp != 0; ifp = ifp->int_next) {
- if (ifp->int_rip_sock < 0
- && !(ifp->int_state & IS_ALIAS)) {
- addr = ((ifp->int_if_flags & IFF_POINTOPOINT)
- ? ifp->int_dstaddr
- : ifp->int_addr);
- ifp->int_rip_sock = get_rip_sock(addr, 0);
- }
- }
-
- fix_select();
-
- age(0);
- }
-}
-
-
-/* turn on RIP multicast input via an interface
- */
-static void
-rip_mcast_on(struct interface *ifp)
-{
- struct ip_mreq m;
-
- if (!IS_RIP_IN_OFF(ifp->int_state)
- && (ifp->int_if_flags & IFF_MULTICAST)
-#ifdef MCAST_PPP_BUG
- && !(ifp->int_if_flags & IFF_POINTOPOINT)
-#endif
- && !(ifp->int_state & IS_ALIAS)) {
- m.imr_multiaddr.s_addr = htonl(INADDR_RIP_GROUP);
- m.imr_interface.s_addr = ((ifp->int_if_flags & IFF_POINTOPOINT)
- ? ifp->int_dstaddr
- : ifp->int_addr);
- if (setsockopt(rip_sock,IPPROTO_IP, IP_ADD_MEMBERSHIP,
- &m, sizeof(m)) < 0)
- LOGERR("setsockopt(IP_ADD_MEMBERSHIP RIP)");
- }
-}
-
-
-/* Prepare socket used for RIP.
- */
-void
-rip_on(struct interface *ifp)
-{
- /* If the main RIP socket is already alive, only start receiving
- * multicasts for this interface.
- */
- if (rip_sock >= 0) {
- if (ifp != 0)
- rip_mcast_on(ifp);
- return;
- }
-
- /* If the main RIP socket is off, and it makes sense to turn it on,
- * turn it on for all of the interfaces.
- */
- if (rip_interfaces > 0 && !rdisc_ok) {
- trace_act("turn on RIP\n");
-
- /* Close all of the query sockets so that we can open
- * the main socket. SO_REUSEPORT is not a solution,
- * since that would let two daemons bind to the broadcast
- * socket.
- */
- for (ifp = ifnet; ifp != 0; ifp = ifp->int_next) {
- if (ifp->int_rip_sock >= 0) {
- (void)close(ifp->int_rip_sock);
- ifp->int_rip_sock = -1;
- }
- }
-
- rip_sock = get_rip_sock(INADDR_ANY, 1);
- rip_sock_mcast = 0;
-
- /* Do not advertise anything until we have heard something
- */
- if (next_bcast.tv_sec < now.tv_sec+MIN_WAITTIME)
- next_bcast.tv_sec = now.tv_sec+MIN_WAITTIME;
-
- for (ifp = ifnet; ifp != 0; ifp = ifp->int_next) {
- if (!IS_RIP_IN_OFF(ifp->int_state))
- ifp->int_state &= ~IS_RIP_QUERIED;
- rip_mcast_on(ifp);
- }
-
- ifinit_timer.tv_sec = now.tv_sec;
-
- fix_select();
-
- } else if (ifp != 0
- && ifp->int_rip_sock < 0
- && !(ifp->int_state & IS_ALIAS)) {
- /* RIP is off, so ensure there are sockets on which
- * to listen for queries.
- */
- ifp->int_rip_sock = get_rip_sock(ifp->int_addr, 0);
-
- fix_select();
- }
-}
-
-
-/* die if malloc(3) fails
- */
-void *
-rtmalloc(size_t size,
- char *msg)
-{
- void *p = malloc(size);
- if (p == 0)
- logbad(1,"malloc() failed in %s", msg);
- return p;
-}
-
-
-/* get a random instant in an interval
- */
-void
-intvl_random(struct timeval *tp, /* put value here */
- u_long lo, /* value is after this second */
- u_long hi) /* and before this */
-{
- tp->tv_sec = (time_t)(hi == lo
- ? lo
- : (lo + random() % ((hi - lo))));
- tp->tv_usec = random() % 1000000;
-}
-
-
-void
-timevaladd(struct timeval *t1,
- struct timeval *t2)
-{
-
- t1->tv_sec += t2->tv_sec;
- if ((t1->tv_usec += t2->tv_usec) > 1000000) {
- t1->tv_sec++;
- t1->tv_usec -= 1000000;
- }
-}
-
-
-/* t1 = t2 - t3
- */
-static void
-timevalsub(struct timeval *t1,
- struct timeval *t2,
- struct timeval *t3)
-{
- t1->tv_sec = t2->tv_sec - t3->tv_sec;
- if ((t1->tv_usec = t2->tv_usec - t3->tv_usec) < 0) {
- t1->tv_sec--;
- t1->tv_usec += 1000000;
- }
-}
-
-
-void
-msglog(char *p, ...)
-{
- va_list args;
-
- trace_flush();
-
- va_start(args, p);
- vsyslog(LOG_ERR, p, args);
-
- if (ftrace != 0) {
- if (ftrace == stdout)
- (void)fputs("routed: ", ftrace);
- (void)vfprintf(ftrace, p, args);
- (void)fputc('\n', ftrace);
- }
-}
-
-
-void
-logbad(int dump, char *p, ...)
-{
- va_list args;
-
- trace_flush();
-
- va_start(args, p);
- vsyslog(LOG_ERR, p, args);
-
- (void)fputs("routed: ", stderr);
- (void)vfprintf(stderr, p, args);
- (void)fputs("; giving up\n",stderr);
- (void)fflush(stderr);
-
- if (dump)
- abort();
- exit(1);
-}
diff --git a/usr.sbin/routed/output.c b/usr.sbin/routed/output.c
deleted file mode 100644
index 5f646d8..0000000
--- a/usr.sbin/routed/output.c
+++ /dev/null
@@ -1,858 +0,0 @@
-/*
- * Copyright (c) 1983, 1988, 1993
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#if !defined(lint) && !defined(sgi) && !defined(__NetBSD__)
-static char sccsid[] = "@(#)output.c 8.1 (Berkeley) 6/5/93";
-#elif defined(__NetBSD__)
-static char rcsid[] = "$NetBSD$";
-#endif
-#ident "$Revision: 1.1.3.3 $"
-
-#include "defs.h"
-
-
-int update_seqno;
-
-
-/* walk the tree of routes with this for output
- */
-struct {
- struct sockaddr_in to;
- naddr to_mask;
- naddr to_net;
- naddr to_std_mask;
- naddr to_std_net;
- struct interface *ifp; /* usually output interface */
- struct ws_buf { /* info for each buffer */
- struct rip *buf;
- struct netinfo *n;
- struct netinfo *base;
- struct netinfo *lim;
- enum output_type type;
- } v12, v2;
- char metric; /* adjust metrics by interface */
- int npackets;
- int gen_limit;
- u_int state;
-#define WS_ST_FLASH 0x001 /* send only changed routes */
-#define WS_ST_RIP2_SAFE 0x002 /* send RIPv2 safe for RIPv1 */
-#define WS_ST_RIP2_ALL 0x004 /* send full featured RIPv2 */
-#define WS_ST_AG 0x008 /* ok to aggregate subnets */
-#define WS_ST_SUPER_AG 0x010 /* ok to aggregate networks */
-#define WS_ST_SUB_AG 0x020 /* aggregate subnets in odd case */
-#define WS_ST_QUERY 0x040 /* responding to a query */
-#define WS_ST_TO_ON_NET 0x080 /* sending onto one of our nets */
-#define WS_ST_DEFAULT 0x100 /* faking a default */
-#define WS_ST_PM_RDISC 0x200 /* poor-man's router discovery */
-} ws;
-
-/* A buffer for what can be heard by both RIPv1 and RIPv2 listeners */
-union pkt_buf ripv12_buf;
-
-/* Another for only RIPv2 listeners */
-union pkt_buf rip_v2_buf;
-
-
-
-/* Send the contents of the global buffer via the non-multicast socket
- */
-int /* <0 on failure */
-output(enum output_type type,
- struct sockaddr_in *dst, /* send to here */
- struct interface *ifp,
- struct rip *buf,
- int size) /* this many bytes */
-{
- struct sockaddr_in sin;
- int flags;
- char *msg;
- int res;
- naddr tgt_mcast;
- int soc;
- int serrno;
-
- sin = *dst;
- if (sin.sin_port == 0)
- sin.sin_port = htons(RIP_PORT);
-#ifdef _HAVE_SIN_LEN
- if (sin.sin_len == 0)
- sin.sin_len = sizeof(sin);
-#endif
-
- soc = rip_sock;
- flags = 0;
-
- switch (type) {
- case OUT_QUERY:
- msg = "Answer Query";
- if (soc < 0)
- soc = ifp->int_rip_sock;
- break;
- case OUT_UNICAST:
- msg = "Send";
- if (soc < 0)
- soc = ifp->int_rip_sock;
- flags = MSG_DONTROUTE;
- break;
- case OUT_BROADCAST:
- if (ifp->int_if_flags & IFF_POINTOPOINT) {
- msg = "Send";
- } else {
- msg = "Send bcast";
- }
- flags = MSG_DONTROUTE;
- break;
- case OUT_MULTICAST:
- if (ifp->int_if_flags & IFF_POINTOPOINT) {
- msg = "Send pt-to-pt";
- } else if (ifp->int_state & IS_DUP) {
- trace_act("abort multicast output via %s"
- " with duplicate address\n",
- ifp->int_name);
- return 0;
- } else {
- msg = "Send mcast";
- if (rip_sock_mcast != ifp) {
-#ifdef MCAST_PPP_BUG
- /* Do not specifiy the primary interface
- * explicitly if we have the multicast
- * point-to-point kernel bug, since the
- * kernel will do the wrong thing if the
- * local address of a point-to-point link
- * is the same as the address of an ordinary
- * interface.
- */
- if (ifp->int_addr == myaddr) {
- tgt_mcast = 0;
- } else
-#endif
- tgt_mcast = ifp->int_addr;
- if (0 > setsockopt(rip_sock,
- IPPROTO_IP, IP_MULTICAST_IF,
- &tgt_mcast,
- sizeof(tgt_mcast))) {
- serrno = errno;
- LOGERR("setsockopt(rip_sock,"
- "IP_MULTICAST_IF)");
- errno = serrno;
- ifp = 0;
- return -1;
- }
- rip_sock_mcast = ifp;
- }
- sin.sin_addr.s_addr = htonl(INADDR_RIP_GROUP);
- }
-
- case NO_OUT_MULTICAST:
- case NO_OUT_RIPV2:
- break;
- }
-
- trace_rip(msg, "to", &sin, ifp, buf, size);
-
- res = sendto(soc, buf, size, flags,
- (struct sockaddr *)&sin, sizeof(sin));
- if (res < 0
- && (ifp == 0 || !(ifp->int_state & IS_BROKE))) {
- serrno = errno;
- msglog("%s sendto(%s%s%s.%d): %s", msg,
- ifp != 0 ? ifp->int_name : "",
- ifp != 0 ? ", " : "",
- inet_ntoa(sin.sin_addr),
- ntohs(sin.sin_port),
- strerror(errno));
- errno = serrno;
- }
-
- return res;
-}
-
-
-/* install authentication if appropriate
- */
-static void
-set_auth(struct ws_buf *w)
-{
- if (ws.ifp != 0
- && ws.ifp->int_passwd[0] != '\0'
- && (ws.state & WS_ST_RIP2_SAFE)) {
- w->n->n_family = RIP_AF_AUTH;
- ((struct netauth*)w->n)->a_type = RIP_AUTH_PW;
- bcopy(ws.ifp->int_passwd, ((struct netauth*)w->n)->au.au_pw,
- sizeof(((struct netauth*)w->n)->au.au_pw));
- w->n++;
- }
-}
-
-
-/* Send the buffer
- */
-static void
-supply_write(struct ws_buf *wb)
-{
- /* Output multicast only if legal.
- * If we would multcast and it would be illegal, then discard the
- * packet.
- */
- switch (wb->type) {
- case NO_OUT_MULTICAST:
- trace_pkt("skip multicast to %s because impossible\n",
- naddr_ntoa(ws.to.sin_addr.s_addr));
- break;
- case NO_OUT_RIPV2:
- break;
- default:
- if (output(wb->type, &ws.to, ws.ifp, wb->buf,
- ((char *)wb->n - (char*)wb->buf)) < 0
- && ws.ifp != 0)
- if_sick(ws.ifp);
- ws.npackets++;
- break;
- }
-
- bzero(wb->n = wb->base, sizeof(*wb->n)*NETS_LEN);
- if (wb->buf->rip_vers == RIPv2)
- set_auth(wb);
-}
-
-
-/* put an entry into the packet
- */
-static void
-supply_out(struct ag_info *ag)
-{
- int i;
- naddr mask, v1_mask, s_mask, dst_h, ddst_h;
- struct ws_buf *wb;
-
-
- /* Skip this route if doing a flash update and it and the routes
- * it aggregates have not changed recently.
- */
- if (ag->ag_seqno < update_seqno
- && (ws.state & WS_ST_FLASH))
- return;
-
- /* Skip this route if required by split-horizon
- */
- if (ag->ag_state & AGS_SPLIT_HZ)
- return;
-
- dst_h = ag->ag_dst_h;
- mask = ag->ag_mask;
- v1_mask = ripv1_mask_host(htonl(dst_h),
- (ws.state & WS_ST_TO_ON_NET) ? ws.ifp : 0);
- s_mask = std_mask(htonl(dst_h));
- i = 0;
-
- /* If we are sending RIPv2 packets that cannot (or must not) be
- * heard by RIPv1 listeners, do not worry about sub- or supernets.
- * Subnets (from other networks) can only be sent via multicast.
- * A pair of subnet routes might have been promoted so that they
- * are legal to send by RIPv1.
- * If RIPv1 is off, use the multicast buffer, unless this is the
- * fake default route and it is acting as a poor-man's router-
- * discovery mechanism.
- */
- if (((ws.state & WS_ST_RIP2_ALL)
- && (dst_h != RIP_DEFAULT || !(ws.state & WS_ST_PM_RDISC)))
- || ((ag->ag_state & AGS_RIPV2) && v1_mask != mask)) {
- /* use the RIPv2-only buffer */
- wb = &ws.v2;
-
- } else {
- /* use the RIPv1-or-RIPv2 buffer */
- wb = &ws.v12;
-
- /* Convert supernet route into corresponding set of network
- * routes for RIPv1, but leave non-contiguous netmasks
- * to ag_check().
- */
- if (v1_mask > mask
- && mask + (mask & -mask) == 0) {
- ddst_h = v1_mask & -v1_mask;
- i = (v1_mask & ~mask)/ddst_h;
-
- if (i > ws.gen_limit) {
- /* Punt if we would have to generate an
- * unreasonable number of routes.
- */
-#ifdef DEBUG
- msglog("sending %s to %s as 1 instead"
- " of %d routes",
- addrname(htonl(dst_h),mask,1),
- naddr_ntoa(ws.to.sin_addr.s_addr),
- i+1);
-#endif
- i = 0;
-
- } else {
- mask = v1_mask;
- ws.gen_limit -= i;
- }
- }
- }
-
- do {
- wb->n->n_family = RIP_AF_INET;
- wb->n->n_dst = htonl(dst_h);
- /* If the route is from router-discovery or we are
- * shutting down, admit only a bad metric.
- */
- wb->n->n_metric = ((stopint || ag->ag_metric < 1)
- ? HOPCNT_INFINITY
- : ag->ag_metric);
- HTONL(wb->n->n_metric);
- if (wb->buf->rip_vers == RIPv2) {
- if (ag->ag_nhop != 0
- && (ws.state & WS_ST_RIP2_SAFE)
- && ((ws.state & WS_ST_QUERY)
- || (ag->ag_nhop != ws.ifp->int_addr
- && on_net(ag->ag_nhop,
- ws.ifp->int_net,
- ws.ifp->int_mask))))
- wb->n->n_nhop = ag->ag_nhop;
- if ((ws.state & WS_ST_RIP2_ALL)
- || mask != s_mask)
- wb->n->n_mask = htonl(mask);
- wb->n->n_tag = ag->ag_tag;
- }
- dst_h += ddst_h;
-
- if (++wb->n >= wb->lim)
- supply_write(wb);
- } while (i-- != 0);
-}
-
-
-/* supply one route from the table
- */
-/* ARGSUSED */
-static int
-walk_supply(struct radix_node *rn,
- struct walkarg *w)
-{
-#define RT ((struct rt_entry *)rn)
- u_short ags = 0;
- char metric, pref;
- naddr dst, nhop;
-
-
- /* Do not advertise the loopback interface
- * or external remote interfaces
- */
- if (RT->rt_ifp != 0
- && ((RT->rt_ifp->int_if_flags & IFF_LOOPBACK)
- || (RT->rt_ifp->int_state & IS_EXTERNAL))
- && !(RT->rt_state & RS_MHOME))
- return 0;
-
- /* If being quiet about our ability to forward, then
- * do not say anything unless responding to a query.
- */
- if (!supplier && !(ws.state & WS_ST_QUERY))
- return 0;
-
- dst = RT->rt_dst;
-
- /* do not collide with the fake default route */
- if (dst == RIP_DEFAULT
- && (ws.state & WS_ST_DEFAULT))
- return 0;
-
- if (RT->rt_state & RS_NET_SYN) {
- if (RT->rt_state & RS_NET_INT) {
- /* Do not send manual synthetic network routes
- * into the subnet.
- */
- if (on_net(ws.to.sin_addr.s_addr,
- ntohl(dst), RT->rt_mask))
- return 0;
-
- } else {
- /* Do not send automatic synthetic network routes
- * if they are not needed becaus no RIPv1 listeners
- * can hear them.
- */
- if (ws.state & WS_ST_RIP2_ALL)
- return 0;
-
- /* Do not send automatic synthetic network routes to
- * the real subnet.
- */
- if (on_net(ws.to.sin_addr.s_addr,
- ntohl(dst), RT->rt_mask))
- return 0;
- }
- nhop = 0;
-
- } else {
- /* Advertise the next hop if this is not a route for one
- * of our interfaces and the next hop is on the same
- * network as the target.
- */
- if (!(RT->rt_state & RS_IF)
- && RT->rt_gate != myaddr
- && RT->rt_gate != loopaddr)
- nhop = RT->rt_gate;
- else
- nhop = 0;
- }
-
- /* Adjust the outgoing metric by the cost of the link.
- */
- pref = metric = RT->rt_metric + ws.metric;
- if (pref < HOPCNT_INFINITY) {
- /* Keep track of the best metric with which the
- * route has been advertised recently.
- */
- if (RT->rt_poison_metric >= metric
- || RT->rt_poison_time <= now_garbage) {
- RT->rt_poison_time = now.tv_sec;
- RT->rt_poison_metric = RT->rt_metric;
- }
-
- } else {
- /* Do not advertise stable routes that will be ignored,
- * unless they are being held down and poisoned. If the
- * route recently was advertised with a metric that would
- * have been less than infinity through this interface, we
- * need to continue to advertise it in order to poison it.
- */
- pref = RT->rt_poison_metric + ws.metric;
- if (pref >= HOPCNT_INFINITY)
- return 0;
-
- metric = HOPCNT_INFINITY;
- }
-
- if (RT->rt_state & RS_MHOME) {
- /* retain host route of multi-homed servers */
- ;
-
- } else if (RT_ISHOST(RT)) {
- /* We should always aggregate the host routes
- * for the local end of our point-to-point links.
- * If we are suppressing host routes in general, then do so.
- * Avoid advertising host routes onto their own network,
- * where they should be handled by proxy-ARP.
- */
- if ((RT->rt_state & RS_LOCAL)
- || ridhosts
- || (ws.state & WS_ST_SUPER_AG)
- || on_net(dst, ws.to_net, ws.to_mask))
- ags |= AGS_SUPPRESS;
-
- if (ws.state & WS_ST_SUPER_AG)
- ags |= AGS_PROMOTE;
-
- } else if (ws.state & WS_ST_AG) {
- /* Aggregate network routes, if we are allowed.
- */
- ags |= AGS_SUPPRESS;
-
- /* Generate supernets if allowed.
- * If we can be heard by RIPv1 systems, we will
- * later convert back to ordinary nets.
- * This unifies dealing with received supernets.
- */
- if ((RT->rt_state & RS_SUBNET)
- || (ws.state & WS_ST_SUPER_AG))
- ags |= AGS_PROMOTE;
-
- }
-
- /* Do not send RIPv1 advertisements of subnets to other
- * networks. If possible, multicast them by RIPv2.
- */
- if ((RT->rt_state & RS_SUBNET)
- && !(ws.state & WS_ST_RIP2_ALL)
- && !on_net(dst, ws.to_std_net, ws.to_std_mask)) {
- ags |= AGS_RIPV2 | AGS_PROMOTE;
- if (ws.state & WS_ST_SUB_AG)
- ags |= AGS_SUPPRESS;
- }
-
- /* Do not send a route back to where it came from, except in
- * response to a query. This is "split-horizon". That means not
- * advertising back to the same network and so via the same interface.
- *
- * We want to suppress routes that might have been fragmented
- * from this route by a RIPv1 router and sent back to us, and so we
- * cannot forget this route here. Let the split-horizon route
- * aggregate (suppress) the fragmented routes and then itself be
- * forgotten.
- *
- * Include the routes for both ends of point-to-point interfaces
- * since the other side presumably knows them as well as we do.
- */
- if (RT->rt_ifp == ws.ifp && ws.ifp != 0
- && !(ws.state & WS_ST_QUERY)
- && (ws.state & WS_ST_TO_ON_NET)
- && (!(RT->rt_state & RS_IF)
- || ws.ifp->int_if_flags & IFF_POINTOPOINT)) {
- ags |= AGS_SPLIT_HZ;
- ags &= ~(AGS_PROMOTE | AGS_SUPPRESS);
- }
-
- ag_check(dst, RT->rt_mask, 0, nhop, metric, pref,
- RT->rt_seqno, RT->rt_tag, ags, supply_out);
- return 0;
-#undef RT
-}
-
-
-/* Supply dst with the contents of the routing tables.
- * If this won't fit in one packet, chop it up into several.
- */
-void
-supply(struct sockaddr_in *dst,
- struct interface *ifp, /* output interface */
- enum output_type type,
- int flash, /* 1=flash update */
- int vers) /* RIP version */
-{
- static int init = 1;
- struct rt_entry *rt;
-
-
- ws.state = 0;
- ws.gen_limit = 1024;
-
- ws.to = *dst;
- ws.to_std_mask = std_mask(ws.to.sin_addr.s_addr);
- ws.to_std_net = ntohl(ws.to.sin_addr.s_addr) & ws.to_std_mask;
-
- if (ifp != 0) {
- ws.to_mask = ifp->int_mask;
- ws.to_net = ifp->int_net;
- if (on_net(ws.to.sin_addr.s_addr, ws.to_net, ws.to_mask))
- ws.state |= WS_ST_TO_ON_NET;
-
- } else {
- ws.to_mask = ripv1_mask_net(ws.to.sin_addr.s_addr, 0);
- ws.to_net = ntohl(ws.to.sin_addr.s_addr) & ws.to_mask;
- rt = rtfind(dst->sin_addr.s_addr);
- if (rt)
- ifp = rt->rt_ifp;
- }
-
- ws.npackets = 0;
- if (flash)
- ws.state |= WS_ST_FLASH;
- if (type == OUT_QUERY)
- ws.state |= WS_ST_QUERY;
-
- if ((ws.ifp = ifp) == 0) {
- ws.metric = 1;
- } else {
- /* Adjust the advertised metric by the outgoing interface
- * metric.
- */
- ws.metric = ifp->int_metric+1;
- }
-
- if (init) {
- init = 0;
-
- bzero(&ripv12_buf, sizeof(ripv12_buf));
- ripv12_buf.rip.rip_cmd = RIPCMD_RESPONSE;
- ws.v12.buf = &ripv12_buf.rip;
- ws.v12.base = &ws.v12.buf->rip_nets[0];
- ws.v12.lim = ws.v12.base + NETS_LEN;
-
- bzero(&rip_v2_buf, sizeof(rip_v2_buf));
- rip_v2_buf.rip.rip_cmd = RIPCMD_RESPONSE;
- rip_v2_buf.rip.rip_vers = RIPv2;
- ws.v2.buf = &rip_v2_buf.rip;
- ws.v2.base = &ws.v2.buf->rip_nets[0];
- ws.v2.lim = ws.v2.base + NETS_LEN;
- }
- ripv12_buf.rip.rip_vers = vers;
-
- ws.v12.n = ws.v12.base;
- set_auth(&ws.v12);
- ws.v2.n = ws.v2.base;
- set_auth(&ws.v2);
-
- switch (type) {
- case OUT_BROADCAST:
- ws.v2.type = ((ws.ifp != 0
- && (ws.ifp->int_if_flags & IFF_MULTICAST))
- ? OUT_MULTICAST
- : NO_OUT_MULTICAST);
- ws.v12.type = OUT_BROADCAST;
- break;
- case OUT_MULTICAST:
- ws.v2.type = ((ws.ifp != 0
- && (ws.ifp->int_if_flags & IFF_MULTICAST))
- ? OUT_MULTICAST
- : NO_OUT_MULTICAST);
- ws.v12.type = OUT_BROADCAST;
- break;
- case OUT_UNICAST:
- case OUT_QUERY:
- ws.v2.type = (vers == RIPv2) ? type : NO_OUT_RIPV2;
- ws.v12.type = type;
- break;
- default:
- ws.v2.type = type;
- ws.v12.type = type;
- break;
- }
-
- if (vers == RIPv2) {
- /* if asked to send RIPv2, send at least that which can
- * be safely heard by RIPv1 listeners.
- */
- ws.state |= WS_ST_RIP2_SAFE;
-
- /* full RIPv2 only if cannot be heard by RIPv1 listeners */
- if (type != OUT_BROADCAST)
- ws.state |= WS_ST_RIP2_ALL;
- if (!(ws.state & WS_ST_TO_ON_NET)) {
- ws.state |= (WS_ST_AG | WS_ST_SUPER_AG);
- } else if (ws.ifp == 0 || !(ws.ifp->int_state & IS_NO_AG)) {
- ws.state |= WS_ST_AG;
- if (type != OUT_BROADCAST
- && (ws.ifp == 0
- || !(ws.ifp->int_state & IS_NO_SUPER_AG)))
- ws.state |= WS_ST_SUPER_AG;
- }
-
- } else if (ws.ifp == 0 || !(ws.ifp->int_state & IS_NO_AG)) {
- ws.state |= WS_ST_SUB_AG;
- }
-
- if (supplier) {
- /* Fake a default route if asked, and if there is not
- * a better, real default route.
- */
- if (ifp->int_d_metric != 0
- && (0 == (rt = rtget(RIP_DEFAULT, 0))
- || rt->rt_metric+ws.metric >= ifp->int_d_metric)) {
- ws.state |= WS_ST_DEFAULT;
- ag_check(0, 0, 0, 0,
- ifp->int_d_metric,ifp->int_d_metric,
- 0, 0, 0, supply_out);
- }
- if ((ws.state & WS_ST_RIP2_ALL)
- && (ifp->int_state & IS_PM_RDISC)) {
- ws.state |= WS_ST_PM_RDISC;
- ripv12_buf.rip.rip_vers = RIPv1;
- }
- }
-
- (void)rn_walktree(rhead, walk_supply, 0);
- ag_flush(0,0,supply_out);
-
- /* Flush the packet buffers, provided they are not empty and
- * do not contain only the password.
- */
- if (ws.v12.n != ws.v12.base
- && (ws.v12.n > ws.v12.base+1
- || ws.v12.n->n_family != RIP_AF_AUTH))
- supply_write(&ws.v12);
- if (ws.v2.n != ws.v2.base
- && (ws.v2.n > ws.v2.base+1
- || ws.v2.n->n_family != RIP_AF_AUTH))
- supply_write(&ws.v2);
-
- /* If we sent nothing and this is an answer to a query, send
- * an empty buffer.
- */
- if (ws.npackets == 0
- && (ws.state & WS_ST_QUERY))
- supply_write(&ws.v12);
-}
-
-
-/* send all of the routing table or just do a flash update
- */
-void
-rip_bcast(int flash)
-{
-#ifdef _HAVE_SIN_LEN
- static struct sockaddr_in dst = {sizeof(dst), AF_INET};
-#else
- static struct sockaddr_in dst = {AF_INET};
-#endif
- struct interface *ifp;
- enum output_type type;
- int vers;
- struct timeval rtime;
-
-
- need_flash = 0;
- intvl_random(&rtime, MIN_WAITTIME, MAX_WAITTIME);
- no_flash = rtime;
- timevaladd(&no_flash, &now);
-
- if (rip_sock < 0)
- return;
-
- trace_act("send %s and inhibit dynamic updates for %.3f sec\n",
- flash ? "dynamic update" : "all routes",
- rtime.tv_sec + ((float)rtime.tv_usec)/1000000.0);
-
- for (ifp = ifnet; ifp != 0; ifp = ifp->int_next) {
- /* skip interfaces not doing RIP, those already queried,
- * and aliases. Do try broken interfaces to see
- * if they have healed.
- */
- if (0 != (ifp->int_state & (IS_PASSIVE | IS_ALIAS)))
- continue;
-
- /* skip turned off interfaces */
- if (!iff_alive(ifp->int_if_flags))
- continue;
-
- /* default to RIPv1 output */
- if (ifp->int_state & IS_NO_RIPV1_OUT) {
- /* Say nothing if this interface is turned off */
- if (ifp->int_state & IS_NO_RIPV2_OUT)
- continue;
- vers = RIPv2;
- } else {
- vers = RIPv1;
- }
-
- if (ifp->int_if_flags & IFF_BROADCAST) {
- /* ordinary, hardware interface */
- dst.sin_addr.s_addr = ifp->int_brdaddr;
- /* if RIPv1 is not turned off, then broadcast so
- * that RIPv1 listeners can hear.
- */
- if (vers == RIPv2
- && (ifp->int_state & IS_NO_RIPV1_OUT)) {
- type = OUT_MULTICAST;
- } else {
- type = OUT_BROADCAST;
- }
-
- } else if (ifp->int_if_flags & IFF_POINTOPOINT) {
- /* point-to-point hardware interface */
- dst.sin_addr.s_addr = ifp->int_dstaddr;
- type = OUT_UNICAST;
-
- } else {
- /* remote interface */
- dst.sin_addr.s_addr = ifp->int_addr;
- type = OUT_UNICAST;
- }
-
- supply(&dst, ifp, type, flash, vers);
- }
-
- update_seqno++; /* all routes are up to date */
-}
-
-
-/* Ask for routes
- * Do it only once to an interface, and not even after the interface
- * was broken and recovered.
- */
-void
-rip_query(void)
-{
-#ifdef _HAVE_SIN_LEN
- static struct sockaddr_in dst = {sizeof(dst), AF_INET};
-#else
- static struct sockaddr_in dst = {AF_INET};
-#endif
- struct interface *ifp;
- struct rip buf;
- enum output_type type;
-
-
- if (rip_sock < 0)
- return;
-
- bzero(&buf, sizeof(buf));
-
- for (ifp = ifnet; ifp; ifp = ifp->int_next) {
- /* skip interfaces not doing RIP, those already queried,
- * and aliases. Do try broken interfaces to see
- * if they have healed.
- */
- if (0 != (ifp->int_state & (IS_RIP_QUERIED
- | IS_PASSIVE | IS_ALIAS)))
- continue;
-
- /* skip turned off interfaces */
- if (!iff_alive(ifp->int_if_flags))
- continue;
-
- /* default to RIPv1 output */
- if (ifp->int_state & IS_NO_RIPV2_OUT) {
- /* Say nothing if this interface is turned off */
- if (ifp->int_state & IS_NO_RIPV1_OUT)
- continue;
- buf.rip_vers = RIPv1;
- } else {
- buf.rip_vers = RIPv2;
- }
-
- buf.rip_cmd = RIPCMD_REQUEST;
- buf.rip_nets[0].n_family = RIP_AF_UNSPEC;
- buf.rip_nets[0].n_metric = htonl(HOPCNT_INFINITY);
-
- if (ifp->int_if_flags & IFF_BROADCAST) {
- /* ordinary, hardware interface */
- dst.sin_addr.s_addr = ifp->int_brdaddr;
- /* if RIPv1 is not turned off, then broadcast so
- * that RIPv1 listeners can hear.
- */
- if (buf.rip_vers == RIPv2
- && (ifp->int_state & IS_NO_RIPV1_OUT)) {
- type = OUT_MULTICAST;
- } else {
- type = OUT_BROADCAST;
- }
-
- } else if (ifp->int_if_flags & IFF_POINTOPOINT) {
- /* point-to-point hardware interface */
- dst.sin_addr.s_addr = ifp->int_dstaddr;
- type = OUT_UNICAST;
-
- } else {
- /* remote interface */
- dst.sin_addr.s_addr = ifp->int_addr;
- type = OUT_UNICAST;
- }
-
- ifp->int_state |= IS_RIP_QUERIED;
- if (output(type, &dst, ifp, &buf, sizeof(buf)) < 0)
- if_sick(ifp);
- }
-}
diff --git a/usr.sbin/routed/parms.c b/usr.sbin/routed/parms.c
deleted file mode 100644
index 1fc0b85..0000000
--- a/usr.sbin/routed/parms.c
+++ /dev/null
@@ -1,563 +0,0 @@
-/*
- * Copyright (c) 1983, 1993
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#ifndef lint
-static char sccsid[] = "@(#)if.c 8.1 (Berkeley) 6/5/93";
-#endif /* not lint */
-
-#ident "$Revision: 1.1 $"
-
-#include "defs.h"
-#include "pathnames.h"
-
-
-struct parm *parms;
-struct intnet *intnets;
-
-
-/* parse a set of parameters for an interface
- */
-char * /* error message */
-parse_parms(char *line)
-{
-#define PARS(str) (0 == (tgt = str, strcasecmp(tok, tgt)))
-#define PARSE(str) (0 == (tgt = str, strncasecmp(tok, str "=", sizeof(str))))
-#define CKF(g,b) {if (0 != (parm.parm_int_state & ((g) & ~(b)))) break; \
- parm.parm_int_state |= (b);}
-#define DELIMS " ,\t\n"
- struct parm parm, *parmp;
- struct intnet *intnetp;
- char *tok, *tgt, *p;
-
-
- /* "subnet=x.y.z.u/mask" must be alone on the line */
- if (!strncasecmp("subnet=",line,7)) {
- intnetp = (struct intnet*)malloc(sizeof(*intnetp));
- if (!getnet(&line[7], &intnetp->intnet_addr,
- &intnetp->intnet_mask)) {
- free(intnetp);
- return line;
- }
- HTONL(intnetp->intnet_addr);
- intnetp->intnet_next = intnets;
- intnets = intnetp;
- return 0;
- }
-
- bzero(&parm, sizeof(parm));
-
- tgt = "null";
- for (tok = strtok(line, DELIMS);
- tok != 0 && tok[0] != '\0';
- tgt = 0, tok = strtok(0,DELIMS)) {
- if (PARSE("if")) {
- if (parm.parm_name[0] != '\0'
- || tok[3] == '\0'
- || strlen(tok) > IFNAMSIZ+3)
- break;
- strcpy(parm.parm_name, tok+3);
-
- } else if (PARSE("passwd")) {
- if (tok[7] == '\0'
- || strlen(tok) > RIP_AUTH_PW_LEN+7)
- break;
- strcpy(parm.parm_passwd, tok+7);
-
- } else if (PARS("no_ag")) {
- parm.parm_int_state |= IS_NO_AG;
-
- } else if (PARS("no_super_ag")) {
- parm.parm_int_state |= IS_NO_SUPER_AG;
-
- } else if (PARS("no_rip")) {
- parm.parm_int_state |= (IS_NO_RIPV1_IN
- | IS_NO_RIPV2_IN
- | IS_NO_RIPV1_OUT
- | IS_NO_RIPV2_OUT);
-
- } else if (PARS("no_ripv1_in")) {
- parm.parm_int_state |= IS_NO_RIPV1_IN;
-
- } else if (PARS("no_ripv2_in")) {
- parm.parm_int_state |= IS_NO_RIPV2_IN;
-
- } else if (PARS("no_ripv2_out")) {
- parm.parm_int_state |= IS_NO_RIPV2_OUT;
-
- } else if (PARS("ripv2_out")) {
- if (parm.parm_int_state & IS_NO_RIPV2_OUT)
- break;
- parm.parm_int_state |= IS_NO_RIPV1_OUT;
-
- } else if (PARS("no_rdisc")) {
- CKF((GROUP_IS_SOL|GROUP_IS_ADV),
- IS_NO_ADV_IN | IS_NO_SOL_OUT | IS_NO_ADV_OUT);
-
- } else if (PARS("no_solicit")) {
- CKF(GROUP_IS_SOL, IS_NO_SOL_OUT);
-
- } else if (PARS("send_solicit")) {
- CKF(GROUP_IS_SOL, IS_SOL_OUT);
-
- } else if (PARS("no_rdisc_adv")) {
- CKF(GROUP_IS_ADV, IS_NO_ADV_OUT);
-
- } else if (PARS("rdisc_adv")) {
- CKF(GROUP_IS_ADV, IS_ADV_OUT);
-
- } else if (PARS("bcast_rdisc")) {
- parm.parm_int_state |= IS_BCAST_RDISC;
-
- } else if (PARSE("rdisc_pref")) {
- if (parm.parm_rdisc_pref != 0
- || tok[11] == '\0'
- || (parm.parm_rdisc_pref = (int)strtol(&tok[11],
- &p,0),
- *p != '\0'))
- break;
-
- } else if (PARSE("rdisc_interval")) {
- if (parm.parm_rdisc_int != 0
- || tok[15] == '\0'
- || (parm.parm_rdisc_int = (int)strtol(&tok[15],
- &p,0),
- *p != '\0')
- || parm.parm_rdisc_int < MinMaxAdvertiseInterval
- || parm.parm_rdisc_int > MaxMaxAdvertiseInterval)
- break;
-
- } else if (PARSE("fake_default")) {
- if (parm.parm_d_metric != 0
- || tok[13] == '\0'
- || (parm.parm_d_metric=(int)strtol(&tok[13],&p,0),
- *p != '\0')
- || parm.parm_d_metric >= HOPCNT_INFINITY-2)
- break;
-
- } else {
- tgt = tok;
- break;
- }
- }
- if (tgt != 0)
- return tgt;
-
- if (parm.parm_int_state & IS_NO_ADV_IN)
- parm.parm_int_state |= IS_NO_SOL_OUT;
-
- /* check for duplicate specification */
- for (parmp = parms; parmp != 0; parmp = parmp->parm_next) {
- if (strcmp(parm.parm_name, parmp->parm_name))
- continue;
- if (parmp->parm_a_h != (parm.parm_a_h & parmp->parm_m)
- && parm.parm_a_h != (parmp->parm_a_h & parm.parm_m))
- continue;
-
- if (strcmp(parmp->parm_passwd, parm.parm_passwd)
- || (0 != (parm.parm_int_state & GROUP_IS_SOL)
- && 0 != (parmp->parm_int_state & GROUP_IS_SOL)
- && 0 != ((parm.parm_int_state ^ parmp->parm_int_state)
- && GROUP_IS_SOL))
- || (0 != (parm.parm_int_state & GROUP_IS_ADV)
- && 0 != (parmp->parm_int_state & GROUP_IS_ADV)
- && 0 != ((parm.parm_int_state ^ parmp->parm_int_state)
- && GROUP_IS_ADV))
- || (parm.parm_rdisc_pref != 0
- && parmp->parm_rdisc_pref != 0
- && parm.parm_rdisc_pref != parmp->parm_rdisc_pref)
- || (parm.parm_rdisc_int != 0
- && parmp->parm_rdisc_int != 0
- && parm.parm_rdisc_int != parmp->parm_rdisc_int)
- || (parm.parm_d_metric != 0
- && parmp->parm_d_metric != 0
- && parm.parm_d_metric != parmp->parm_d_metric))
- return "duplicate";
- }
-
- parmp = (struct parm*)malloc(sizeof(*parmp));
- bcopy(&parm, parmp, sizeof(*parmp));
- parmp->parm_next = parms;
- parms = parmp;
-
- return 0;
-#undef DELIMS
-#undef PARS
-#undef PARSE
-}
-
-
-/* use configured parameters
- */
-void
-get_parms(struct interface *ifp)
-{
- struct parm *parmp;
-
- for (parmp = parms; parmp != 0; parmp = parmp->parm_next) {
- if ((parmp->parm_a_h == (ntohl(ifp->int_addr)
- & parmp->parm_m)
- && parmp->parm_name[0] == '\0')
- || (parmp->parm_name[0] != '\0'
- && !strcmp(ifp->int_name, parmp->parm_name))) {
- ifp->int_state |= parmp->parm_int_state;
- bcopy(parmp->parm_passwd, ifp->int_passwd,
- sizeof(ifp->int_passwd));
- ifp->int_rdisc_pref = parmp->parm_rdisc_pref;
- ifp->int_rdisc_int = parmp->parm_rdisc_int;
- ifp->int_d_metric = parmp->parm_d_metric;
- }
- }
-
- if ((ifp->int_state & IS_NO_RIP_IN) == IS_NO_RIP_IN)
- ifp->int_state |= IS_NO_RIP_OUT;
-
- if (ifp->int_rdisc_int == 0)
- ifp->int_rdisc_int = DefMaxAdvertiseInterval;
-
- if ((ifp->int_state & IS_PASSIVE)
- || (ifp->int_state & IS_REMOTE))
- ifp->int_state |= IS_NO_ADV_IN|IS_NO_SOL_OUT|IS_NO_ADV_OUT;
-
-
- if (!(ifp->int_state & IS_PASSIVE)) {
- if (!(ifp->int_if_flags & IFF_MULTICAST)
- && !(ifp->int_if_flags & IFF_POINTOPOINT))
- ifp->int_state |= IS_NO_RIPV2_OUT;
- }
-
- if (!(ifp->int_if_flags & IFF_MULTICAST))
- ifp->int_state |= IS_BCAST_RDISC;
-
- if (ifp->int_if_flags & IFF_POINTOPOINT) {
- ifp->int_state |= IS_BCAST_RDISC;
- /* point-to-point links should be passive for the sake
- * of demand-dialing
- */
- if (0 == (ifp->int_state & GROUP_IS_SOL))
- ifp->int_state |= IS_NO_SOL_OUT;
- if (0 == (ifp->int_state & GROUP_IS_ADV))
- ifp->int_state |= IS_NO_ADV_OUT;
- }
-}
-
-
-/* Read a list of gateways from /etc/gateways and add them to our tables.
- *
- * This file contains a list of "remote" gateways. That is usually
- * a gateway which we cannot immediately determine if it is present or
- * not as we can do for those provided by directly connected hardware.
- *
- * If a gateway is marked "passive" in the file, then we assume it
- * does not understand RIP and assume it is always present. Those
- * not marked passive are treated as if they were directly connected
- * and assumed to be broken if they do not send us advertisements.
- * All remote interfaces are added to our list, and those not marked
- * passive are sent routing updates.
- *
- * A passive interface can also be local, hardware interface exempt
- * from RIP.
- */
-void
-gwkludge(void)
-{
- FILE *fp;
- char *p, *lptr;
- char lbuf[200], net_host[5], dname[64+1+64+1], gname[64+1], qual[9];
- struct interface *ifp;
- naddr dst, netmask, gate;
- int metric, n;
- u_int state;
- char *type;
- struct parm *parmp;
-
-
- fp = fopen(_PATH_GATEWAYS, "r");
- if (fp == 0)
- return;
-
- for (;;) {
- if (0 == fgets(lbuf, sizeof(lbuf)-1, fp))
- break;
- lptr = lbuf;
- while (*lptr == ' ')
- lptr++;
- if (*lptr == '\n' /* ignore null and comment lines */
- || *lptr == '#')
- continue;
-
- /* notice parameter lines */
- if (strncasecmp("net", lptr, 3)
- && strncasecmp("host", lptr, 4)) {
- p = parse_parms(lptr);
- if (p != 0)
- msglog("bad \"%s\" in "_PATH_GATEWAYS
- " entry %s", lptr, p);
- continue;
- }
-
-/* {net | host} XX[/M] XX gateway XX metric DD [passive | external]\n */
- n = sscanf(lptr, "%4s %129[^ ] gateway"
- " %64[^ / ] metric %d %8s\n",
- net_host, dname, gname, &metric, qual);
- if (n != 5) {
- msglog("bad "_PATH_GATEWAYS" entry %s", lptr);
- continue;
- }
- if (metric < 0 || metric >= HOPCNT_INFINITY) {
- msglog("bad metric in "_PATH_GATEWAYS" entry %s",
- lptr);
- continue;
- }
- if (!strcmp(net_host, "host")) {
- if (!gethost(dname, &dst)) {
- msglog("bad host %s in "_PATH_GATEWAYS
- " entry %s", dname, lptr);
- continue;
- }
- netmask = HOST_MASK;
- } else if (!strcmp(net_host, "net")) {
- if (!getnet(dname, &dst, &netmask)) {
- msglog("bad net %s in "_PATH_GATEWAYS
- " entry %s", dname, lptr);
- continue;
- }
- HTONL(dst);
- } else {
- msglog("bad \"%s\" in "_PATH_GATEWAYS
- " entry %s", lptr);
- continue;
- }
-
- if (!gethost(gname, &gate)) {
- msglog("bad gateway %s in "_PATH_GATEWAYS
- " entry %s", gname, lptr);
- continue;
- }
-
- if (strcmp(qual, type = "passive") == 0) {
- /* Passive entries are not 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).
- */
- state = IS_REMOTE | IS_PASSIVE;
- if (metric == 0)
- metric = 1;
-
- } else if (strcmp(qual, type = "external") == 0) {
- /* External entries are handled by other means
- * such as EGP, and are placed only in the daemon
- * tables to prevent overriding them with something
- * else.
- */
- state = IS_REMOTE | IS_PASSIVE | IS_EXTERNAL;
- if (metric == 0)
- metric = 1;
-
- } else if (qual[0] == '\0') {
- if (metric != 0) {
- /* Entries that are neither "passive" nor
- * "external" are "remote" and must behave
- * like physical interfaces. If they are not
- * heard from regularly, they are deleted.
- */
- state = IS_REMOTE;
- type = "remote";
- } else {
- /* "remote" entries with a metric of 0
- * are aliases for our own interfaces
- */
- state = IS_REMOTE | IS_PASSIVE;
- type = "alias";
- }
-
- } else {
- msglog("bad "_PATH_GATEWAYS" entry %s", lptr);
- continue;
- }
-
- if (!(state & IS_EXTERNAL)) {
- /* If we are going to send packets to the gateway,
- * it must be reachable using our physical interfaces
- */
- if (!rtfind(gate)) {
- msglog("unreachable gateway %s in "
- _PATH_GATEWAYS" entry %s",
- gname, lptr);
- continue;
- }
-
- /* Remember to advertise the corresponding logical
- * network.
- */
- if (netmask != std_mask(dst))
- state |= IS_SUBNET;
- }
-
- parmp = (struct parm*)malloc(sizeof(*parmp));
- bzero(parmp, sizeof(*parmp));
- parmp->parm_next = parms;
- parms = parmp;
- parmp->parm_a_h = ntohl(dst);
- parmp->parm_m = -1;
- parmp->parm_d_metric = 0;
- parmp->parm_int_state = state;
-
- /* See if this new interface duplicates an existing
- * interface.
- */
- for (ifp = ifnet; 0 != ifp; ifp = ifp->int_next) {
- if (ifp->int_addr == dst
- && ifp->int_mask == netmask)
- break;
- }
- if (ifp != 0) {
- /* Let one of our real interfaces be marked passive.
- */
- if ((state & IS_PASSIVE) && !(state & IS_EXTERNAL)) {
- ifp->int_state |= state;
- } else {
- msglog("%s is duplicated in "_PATH_GATEWAYS
- " by %s",
- ifp->int_name, lptr);
- }
- continue;
- }
-
- tot_interfaces++;
-
- ifp = (struct interface *)malloc(sizeof(*ifp));
- bzero(ifp, sizeof(*ifp));
- if (ifnet != 0) {
- ifp->int_next = ifnet;
- ifnet->int_prev = ifp;
- }
- ifnet = ifp;
-
- ifp->int_state = state;
- ifp->int_net = ntohl(dst) & netmask;
- ifp->int_mask = netmask;
- if (netmask == HOST_MASK)
- ifp->int_if_flags |= IFF_POINTOPOINT;
- ifp->int_dstaddr = dst;
- ifp->int_addr = gate;
- ifp->int_metric = metric;
- (void)sprintf(ifp->int_name, "%s-%s", type, naddr_ntoa(dst));
- ifp->int_index = -1;
-
- get_parms(ifp);
-
- if (TRACEACTIONS)
- trace_if("Add", ifp);
- }
-}
-
-
-/* get a network number as a name or a number, with an optional "/xx"
- * netmask.
- */
-int /* 0=bad */
-getnet(char *name,
- naddr *addr_hp,
- naddr *maskp)
-{
- int i;
- struct netent *nentp;
- naddr mask;
- struct in_addr in;
- char hname[MAXHOSTNAMELEN+1];
- char *mname, *p;
-
-
- /* Detect and separate "1.2.3.4/24"
- */
- if (0 != (mname = rindex(name,'/'))) {
- i = (int)(mname - name);
- if (i > sizeof(hname)-1) /* name too long */
- return 0;
- bcopy(name, hname, i);
- hname[i] = '\0';
- mname++;
- name = hname;
- }
-
- nentp = getnetbyname(name);
- if (nentp != 0) {
- in.s_addr = (naddr)nentp->n_net;
- } else if (inet_aton(name, &in) == 1) {
- NTOHL(in.s_addr);
- } else {
- return 0;
- }
-
- if (mname == 0) {
- mask = std_mask(in.s_addr);
- } else {
- mask = (naddr)strtoul(mname, &p, 0);
- if (*p != '\0' || mask > 32)
- return 0;
- mask = HOST_MASK << (32-mask);
- }
-
- *addr_hp = in.s_addr;
- *maskp = mask;
- return 1;
-}
-
-
-int /* 0=bad */
-gethost(char *name,
- naddr *addrp)
-{
- struct hostent *hp;
- struct in_addr in;
-
-
- /* Try for a number first, even in IRIX where gethostbyname()
- * is smart. This avoids hitting the name server which
- * might be sick because routing is.
- */
- if (inet_aton(name, &in) == 1) {
- *addrp = in.s_addr;
- return 1;
- }
-
- hp = gethostbyname(name);
- if (hp) {
- bcopy(hp->h_addr, addrp, sizeof(*addrp));
- return 1;
- }
-
- return 0;
-}
diff --git a/usr.sbin/routed/pathnames.h b/usr.sbin/routed/pathnames.h
deleted file mode 100644
index e9e6c48..0000000
--- a/usr.sbin/routed/pathnames.h
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright (c) 1989, 1993
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * @(#)pathnames.h 8.1 (Berkeley) 6/5/93
- *
- * $NetBSD$
- */
-
-#include <paths.h>
-
-#define _PATH_GATEWAYS "/etc/gateways"
-
-/* All remotely requested trace files must either start with this prefix
- * or be the same as the tracefile specified when the daemon was started.
- * If this is a directory, routed will create log files in it. That
- * might be a security problem.
- */
-#define _PATH_TRACE "/tmp/routed.log"
diff --git a/usr.sbin/routed/radix.c b/usr.sbin/routed/radix.c
deleted file mode 100644
index 7552e08..0000000
--- a/usr.sbin/routed/radix.c
+++ /dev/null
@@ -1,894 +0,0 @@
-/*
- * Copyright (c) 1988, 1989, 1993
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * @(#)radix.c 8.4 (Berkeley) 11/2/94
- */
-
-/*
- * Routines to build and maintain radix trees for routing lookups.
- */
-#include <sys/param.h>
-#include <sys/malloc.h>
-#include <sys/domain.h>
-#include <sys/syslog.h>
-#include <net/radix.h>
-#include <stdlib.h>
-#define min(a,b) (((a)<(b))?(a):(b))
-#define log(x, msg) syslog(x, msg)
-#define panic(s) {log(LOG_ERR,s); exit(1);}
-
-
-int max_keylen;
-struct radix_mask *rn_mkfreelist;
-struct radix_node_head *mask_rnhead;
-static char *addmask_key;
-static char normal_chars[] = {0, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, -1};
-static char *rn_zeros, *rn_ones;
-
-#define rn_masktop (mask_rnhead->rnh_treetop)
-#undef Bcmp
-#define Bcmp(a, b, l) (l == 0 ? 0 : bcmp((caddr_t)(a), (caddr_t)(b), (u_long)l))
-
-static int rn_satsifies_leaf(char *, struct radix_node *, int);
-
-/*
- * The data structure for the keys is a radix tree with one way
- * branching removed. The index rn_b at an internal node n represents a bit
- * position to be tested. The tree is arranged so that all descendants
- * of a node n have keys whose bits all agree up to position rn_b - 1.
- * (We say the index of n is rn_b.)
- *
- * There is at least one descendant which has a one bit at position rn_b,
- * and at least one with a zero there.
- *
- * A route is determined by a pair of key and mask. We require that the
- * bit-wise logical and of the key and mask to be the key.
- * We define the index of a route to associated with the mask to be
- * the first bit number in the mask where 0 occurs (with bit number 0
- * representing the highest order bit).
- *
- * We say a mask is normal if every bit is 0, past the index of the mask.
- * If a node n has a descendant (k, m) with index(m) == index(n) == rn_b,
- * and m is a normal mask, then the route applies to every descendant of n.
- * If the index(m) < rn_b, this implies the trailing last few bits of k
- * before bit b are all 0, (and hence consequently true of every descendant
- * of n), so the route applies to all descendants of the node as well.
- *
- * Similar logic shows that a non-normal mask m such that
- * index(m) <= index(n) could potentially apply to many children of n.
- * Thus, for each non-host route, we attach its mask to a list at an internal
- * node as high in the tree as we can go.
- *
- * The present version of the code makes use of normal routes in short-
- * circuiting an explict mask and compare operation when testing whether
- * a key satisfies a normal route, and also in remembering the unique leaf
- * that governs a subtree.
- */
-
-struct radix_node *
-rn_search(v_arg, head)
- void *v_arg;
- struct radix_node *head;
-{
- register struct radix_node *x;
- register caddr_t v;
-
- for (x = head, v = v_arg; x->rn_b >= 0;) {
- if (x->rn_bmask & v[x->rn_off])
- x = x->rn_r;
- else
- x = x->rn_l;
- }
- return (x);
-}
-
-struct radix_node *
-rn_search_m(v_arg, head, m_arg)
- struct radix_node *head;
- void *v_arg, *m_arg;
-{
- register struct radix_node *x;
- register caddr_t v = v_arg, m = m_arg;
-
- for (x = head; x->rn_b >= 0;) {
- if ((x->rn_bmask & m[x->rn_off]) &&
- (x->rn_bmask & v[x->rn_off]))
- x = x->rn_r;
- else
- x = x->rn_l;
- }
- return x;
-}
-
-int
-rn_refines(m_arg, n_arg)
- void *m_arg, *n_arg;
-{
- register caddr_t m = m_arg, n = n_arg;
- register caddr_t lim, lim2 = lim = n + *(u_char *)n;
- int longer = (*(u_char *)n++) - (int)(*(u_char *)m++);
- int masks_are_equal = 1;
-
- if (longer > 0)
- lim -= longer;
- while (n < lim) {
- if (*n & ~(*m))
- return 0;
- if (*n++ != *m++)
- masks_are_equal = 0;
- }
- while (n < lim2)
- if (*n++)
- return 0;
- if (masks_are_equal && (longer < 0))
- for (lim2 = m - longer; m < lim2; )
- if (*m++)
- return 1;
- return (!masks_are_equal);
-}
-
-struct radix_node *
-rn_lookup(v_arg, m_arg, head)
- void *v_arg, *m_arg;
- struct radix_node_head *head;
-{
- register struct radix_node *x;
- caddr_t netmask = 0;
-
- if (m_arg) {
- if ((x = rn_addmask(m_arg, 1, head->rnh_treetop->rn_off)) == 0)
- return (0);
- netmask = x->rn_key;
- }
- x = rn_match(v_arg, head);
- if (x && netmask) {
- while (x && x->rn_mask != netmask)
- x = x->rn_dupedkey;
- }
- return x;
-}
-
-static int
-rn_satsifies_leaf(char *trial,
- register struct radix_node *leaf,
- int skip)
-{
- register char *cp = trial, *cp2 = leaf->rn_key, *cp3 = leaf->rn_mask;
- char *cplim;
- int length = min(*(u_char *)cp, *(u_char *)cp2);
-
- if (cp3 == 0)
- cp3 = rn_ones;
- else
- length = min(length, *(u_char *)cp3);
- cplim = cp + length; cp3 += skip; cp2 += skip;
- for (cp += skip; cp < cplim; cp++, cp2++, cp3++)
- if ((*cp ^ *cp2) & *cp3)
- return 0;
- return 1;
-}
-
-struct radix_node *
-rn_match(v_arg, head)
- void *v_arg;
- struct radix_node_head *head;
-{
- caddr_t v = v_arg;
- register struct radix_node *t = head->rnh_treetop, *x;
- register caddr_t cp = v, cp2;
- caddr_t cplim;
- struct radix_node *saved_t, *top = t;
- int off = t->rn_off, vlen = *(u_char *)cp, matched_off;
- register int test, b, rn_b;
-
- /*
- * Open code rn_search(v, top) to avoid overhead of extra
- * subroutine call.
- */
- for (; t->rn_b >= 0; ) {
- if (t->rn_bmask & cp[t->rn_off])
- t = t->rn_r;
- else
- t = t->rn_l;
- }
- /*
- * See if we match exactly as a host destination
- * or at least learn how many bits match, for normal mask finesse.
- *
- * It doesn't hurt us to limit how many bytes to check
- * to the length of the mask, since if it matches we had a genuine
- * match and the leaf we have is the most specific one anyway;
- * if it didn't match with a shorter length it would fail
- * with a long one. This wins big for class B&C netmasks which
- * are probably the most common case...
- */
- if (t->rn_mask)
- vlen = *(u_char *)t->rn_mask;
- cp += off; cp2 = t->rn_key + off; cplim = v + vlen;
- for (; cp < cplim; cp++, cp2++)
- if (*cp != *cp2)
- goto on1;
- /*
- * This extra grot is in case we are explicitly asked
- * to look up the default. Ugh!
- */
- if ((t->rn_flags & RNF_ROOT) && t->rn_dupedkey)
- t = t->rn_dupedkey;
- return t;
-on1:
- test = (*cp ^ *cp2) & 0xff; /* find first bit that differs */
- for (b = 7; (test >>= 1) > 0;)
- b--;
- matched_off = cp - v;
- b += matched_off << 3;
- rn_b = -1 - b;
- /*
- * If there is a host route in a duped-key chain, it will be first.
- */
- if ((saved_t = t)->rn_mask == 0)
- t = t->rn_dupedkey;
- for (; t; t = t->rn_dupedkey)
- /*
- * Even if we don't match exactly as a host,
- * we may match if the leaf we wound up at is
- * a route to a net.
- */
- if (t->rn_flags & RNF_NORMAL) {
- if (rn_b <= t->rn_b)
- return t;
- } else if (rn_satsifies_leaf(v, t, matched_off))
- return t;
- t = saved_t;
- /* start searching up the tree */
- do {
- register struct radix_mask *m;
- t = t->rn_p;
- if (m = t->rn_mklist) {
- /*
- * If non-contiguous masks ever become important
- * we can restore the masking and open coding of
- * the search and satisfaction test and put the
- * calculation of "off" back before the "do".
- */
- do {
- if (m->rm_flags & RNF_NORMAL) {
- if (rn_b <= m->rm_b)
- return (m->rm_leaf);
- } else {
- off = min(t->rn_off, matched_off);
- x = rn_search_m(v, t, m->rm_mask);
- while (x && x->rn_mask != m->rm_mask)
- x = x->rn_dupedkey;
- if (x && rn_satsifies_leaf(v, x, off))
- return x;
- }
- } while (m = m->rm_mklist);
- }
- } while (t != top);
- return 0;
-}
-
-#ifdef RN_DEBUG
-int rn_nodenum;
-struct radix_node *rn_clist;
-int rn_saveinfo;
-int rn_debug = 1;
-#endif
-
-struct radix_node *
-rn_newpair(v, b, nodes)
- void *v;
- int b;
- struct radix_node nodes[2];
-{
- register struct radix_node *tt = nodes, *t = tt + 1;
- t->rn_b = b; t->rn_bmask = 0x80 >> (b & 7);
- t->rn_l = tt; t->rn_off = b >> 3;
- tt->rn_b = -1; tt->rn_key = (caddr_t)v; tt->rn_p = t;
- tt->rn_flags = t->rn_flags = RNF_ACTIVE;
-#ifdef RN_DEBUG
- tt->rn_info = rn_nodenum++; t->rn_info = rn_nodenum++;
- tt->rn_twin = t; tt->rn_ybro = rn_clist; rn_clist = tt;
-#endif
- return t;
-}
-
-struct radix_node *
-rn_insert(v_arg, head, dupentry, nodes)
- void *v_arg;
- struct radix_node_head *head;
- int *dupentry;
- struct radix_node nodes[2];
-{
- caddr_t v = v_arg;
- struct radix_node *top = head->rnh_treetop;
- int head_off = top->rn_off, vlen = (int)*((u_char *)v);
- register struct radix_node *t = rn_search(v_arg, top);
- register caddr_t cp = v + head_off;
- register int b;
- struct radix_node *tt;
- /*
- * Find first bit at which v and t->rn_key differ
- */
- {
- register caddr_t cp2 = t->rn_key + head_off;
- register int cmp_res;
- caddr_t cplim = v + vlen;
-
- while (cp < cplim)
- if (*cp2++ != *cp++)
- goto on1;
- *dupentry = 1;
- return t;
-on1:
- *dupentry = 0;
- cmp_res = (cp[-1] ^ cp2[-1]) & 0xff;
- for (b = (cp - v) << 3; cmp_res; b--)
- cmp_res >>= 1;
- }
- {
- register struct radix_node *p, *x = top;
- cp = v;
- do {
- p = x;
- if (cp[x->rn_off] & x->rn_bmask)
- x = x->rn_r;
- else x = x->rn_l;
- } while (b > (unsigned) x->rn_b); /* x->rn_b < b && x->rn_b >= 0 */
-#ifdef RN_DEBUG
- if (rn_debug)
- log(LOG_DEBUG, "rn_insert: Going In:\n"), traverse(p);
-#endif
- t = rn_newpair(v_arg, b, nodes); tt = t->rn_l;
- if ((cp[p->rn_off] & p->rn_bmask) == 0)
- p->rn_l = t;
- else
- p->rn_r = t;
- x->rn_p = t; t->rn_p = p; /* frees x, p as temp vars below */
- if ((cp[t->rn_off] & t->rn_bmask) == 0) {
- t->rn_r = x;
- } else {
- t->rn_r = tt; t->rn_l = x;
- }
-#ifdef RN_DEBUG
- if (rn_debug)
- log(LOG_DEBUG, "rn_insert: Coming Out:\n"), traverse(p);
-#endif
- }
- return (tt);
-}
-
-struct radix_node *
-rn_addmask(n_arg, search, skip)
- int search, skip;
- void *n_arg;
-{
- caddr_t netmask = (caddr_t)n_arg;
- register struct radix_node *x;
- register caddr_t cp, cplim;
- register int b = 0, mlen, j;
- int maskduplicated, m0, isnormal;
- struct radix_node *saved_x;
- static int last_zeroed = 0;
-
- if ((mlen = *(u_char *)netmask) > max_keylen)
- mlen = max_keylen;
- if (skip == 0)
- skip = 1;
- if (mlen <= skip)
- return (mask_rnhead->rnh_nodes);
- if (skip > 1)
- Bcopy(rn_ones + 1, addmask_key + 1, skip - 1);
- if ((m0 = mlen) > skip)
- Bcopy(netmask + skip, addmask_key + skip, mlen - skip);
- /*
- * Trim trailing zeroes.
- */
- for (cp = addmask_key + mlen; (cp > addmask_key) && cp[-1] == 0;)
- cp--;
- mlen = cp - addmask_key;
- if (mlen <= skip) {
- if (m0 >= last_zeroed)
- last_zeroed = mlen;
- return (mask_rnhead->rnh_nodes);
- }
- if (m0 < last_zeroed)
- Bzero(addmask_key + m0, last_zeroed - m0);
- *addmask_key = last_zeroed = mlen;
- x = rn_search(addmask_key, rn_masktop);
- if (Bcmp(addmask_key, x->rn_key, mlen) != 0)
- x = 0;
- if (x || search)
- return (x);
- R_Malloc(x, struct radix_node *, max_keylen + 2 * sizeof (*x));
- if ((saved_x = x) == 0)
- return (0);
- Bzero(x, max_keylen + 2 * sizeof (*x));
- netmask = cp = (caddr_t)(x + 2);
- Bcopy(addmask_key, cp, mlen);
- x = rn_insert(cp, mask_rnhead, &maskduplicated, x);
- if (maskduplicated) {
- log(LOG_ERR, "rn_addmask: mask impossibly already in tree");
- Free(saved_x);
- return (x);
- }
- /*
- * Calculate index of mask, and check for normalcy.
- */
- cplim = netmask + mlen; isnormal = 1;
- for (cp = netmask + skip; (cp < cplim) && *(u_char *)cp == 0xff;)
- cp++;
- if (cp != cplim) {
- for (j = 0x80; (j & *cp) != 0; j >>= 1)
- b++;
- if (*cp != normal_chars[b] || cp != (cplim - 1))
- isnormal = 0;
- }
- b += (cp - netmask) << 3;
- x->rn_b = -1 - b;
- if (isnormal)
- x->rn_flags |= RNF_NORMAL;
- return (x);
-}
-
-static int /* XXX: arbitrary ordering for non-contiguous masks */
-rn_lexobetter(void *m_arg, void *n_arg)
-{
- register u_char *mp = m_arg, *np = n_arg, *lim;
-
- if (*mp > *np)
- return 1; /* not really, but need to check longer one first */
- if (*mp == *np)
- for (lim = mp + *mp; mp < lim;)
- if (*mp++ > *np++)
- return 1;
- return 0;
-}
-
-static struct radix_mask *
-rn_new_radix_mask(register struct radix_node *tt,
- register struct radix_mask *next)
-{
- register struct radix_mask *m;
-
- MKGet(m);
- if (m == 0) {
- log(LOG_ERR, "Mask for route not entered\n");
- return (0);
- }
- Bzero(m, sizeof *m);
- m->rm_b = tt->rn_b;
- m->rm_flags = tt->rn_flags;
- if (tt->rn_flags & RNF_NORMAL)
- m->rm_leaf = tt;
- else
- m->rm_mask = tt->rn_mask;
- m->rm_mklist = next;
- tt->rn_mklist = m;
- return m;
-}
-
-struct radix_node *
-rn_addroute(v_arg, n_arg, head, treenodes)
- void *v_arg, *n_arg;
- struct radix_node_head *head;
- struct radix_node treenodes[2];
-{
- caddr_t v = (caddr_t)v_arg, netmask = (caddr_t)n_arg;
- register struct radix_node *t, *x, *tt;
- struct radix_node *saved_tt, *top = head->rnh_treetop;
- short b = 0, b_leaf;
- int keyduplicated;
- caddr_t mmask;
- struct radix_mask *m, **mp;
-
- /*
- * In dealing with non-contiguous masks, there may be
- * many different routes which have the same mask.
- * We will find it useful to have a unique pointer to
- * the mask to speed avoiding duplicate references at
- * nodes and possibly save time in calculating indices.
- */
- if (netmask) {
- if ((x = rn_addmask(netmask, 0, top->rn_off)) == 0)
- return (0);
- b_leaf = x->rn_b;
- b = -1 - x->rn_b;
- netmask = x->rn_key;
- }
- /*
- * Deal with duplicated keys: attach node to previous instance
- */
- saved_tt = tt = rn_insert(v, head, &keyduplicated, treenodes);
- if (keyduplicated) {
- for (t = tt; tt; t = tt, tt = tt->rn_dupedkey) {
- if (tt->rn_mask == netmask)
- return (0);
- if (netmask == 0 ||
- (tt->rn_mask &&
- ((b_leaf < tt->rn_b) || /* index(netmask) > node */
- rn_refines(netmask, tt->rn_mask) ||
- rn_lexobetter(netmask, tt->rn_mask))))
- break;
- }
- /*
- * If the mask is not duplicated, we wouldn't
- * find it among possible duplicate key entries
- * anyway, so the above test doesn't hurt.
- *
- * We sort the masks for a duplicated key the same way as
- * in a masklist -- most specific to least specific.
- * This may require the unfortunate nuisance of relocating
- * the head of the list.
- */
- if (tt == saved_tt) {
- struct radix_node *xx = x;
- /* link in at head of list */
- (tt = treenodes)->rn_dupedkey = t;
- tt->rn_flags = t->rn_flags;
- tt->rn_p = x = t->rn_p;
- if (x->rn_l == t) x->rn_l = tt; else x->rn_r = tt;
- saved_tt = tt; x = xx;
- } else {
- (tt = treenodes)->rn_dupedkey = t->rn_dupedkey;
- t->rn_dupedkey = tt;
- }
-#ifdef RN_DEBUG
- t=tt+1; tt->rn_info = rn_nodenum++; t->rn_info = rn_nodenum++;
- tt->rn_twin = t; tt->rn_ybro = rn_clist; rn_clist = tt;
-#endif
- tt->rn_key = (caddr_t) v;
- tt->rn_b = -1;
- tt->rn_flags = RNF_ACTIVE;
- }
- /*
- * Put mask in tree.
- */
- if (netmask) {
- tt->rn_mask = netmask;
- tt->rn_b = x->rn_b;
- tt->rn_flags |= x->rn_flags & RNF_NORMAL;
- }
- t = saved_tt->rn_p;
- if (keyduplicated)
- goto on2;
- b_leaf = -1 - t->rn_b;
- if (t->rn_r == saved_tt) x = t->rn_l; else x = t->rn_r;
- /* Promote general routes from below */
- if (x->rn_b < 0) {
- for (mp = &t->rn_mklist; x; x = x->rn_dupedkey)
- if (x->rn_mask && (x->rn_b >= b_leaf) && x->rn_mklist == 0) {
- if (*mp = m = rn_new_radix_mask(x, 0))
- mp = &m->rm_mklist;
- }
- } else if (x->rn_mklist) {
- /*
- * Skip over masks whose index is > that of new node
- */
- for (mp = &x->rn_mklist; m = *mp; mp = &m->rm_mklist)
- if (m->rm_b >= b_leaf)
- break;
- t->rn_mklist = m; *mp = 0;
- }
-on2:
- /* Add new route to highest possible ancestor's list */
- if ((netmask == 0) || (b > t->rn_b ))
- return tt; /* can't lift at all */
- b_leaf = tt->rn_b;
- do {
- x = t;
- t = t->rn_p;
- } while (b <= t->rn_b && x != top);
- /*
- * Search through routes associated with node to
- * insert new route according to index.
- * Need same criteria as when sorting dupedkeys to avoid
- * double loop on deletion.
- */
- for (mp = &x->rn_mklist; m = *mp; mp = &m->rm_mklist) {
- if (m->rm_b < b_leaf)
- continue;
- if (m->rm_b > b_leaf)
- break;
- if (m->rm_flags & RNF_NORMAL) {
- mmask = m->rm_leaf->rn_mask;
- if (tt->rn_flags & RNF_NORMAL) {
- log(LOG_ERR,
- "Non-unique normal route, mask not entered");
- return tt;
- }
- } else
- mmask = m->rm_mask;
- if (mmask == netmask) {
- m->rm_refs++;
- tt->rn_mklist = m;
- return tt;
- }
- if (rn_refines(netmask, mmask) || rn_lexobetter(netmask, mmask))
- break;
- }
- *mp = rn_new_radix_mask(tt, *mp);
- return tt;
-}
-
-struct radix_node *
-rn_delete(v_arg, netmask_arg, head)
- void *v_arg, *netmask_arg;
- struct radix_node_head *head;
-{
- register struct radix_node *t, *p, *x, *tt;
- struct radix_mask *m, *saved_m, **mp;
- struct radix_node *dupedkey, *saved_tt, *top;
- caddr_t v, netmask;
- int b, head_off, vlen;
-
- v = v_arg;
- netmask = netmask_arg;
- x = head->rnh_treetop;
- tt = rn_search(v, x);
- head_off = x->rn_off;
- vlen = *(u_char *)v;
- saved_tt = tt;
- top = x;
- if (tt == 0 ||
- Bcmp(v + head_off, tt->rn_key + head_off, vlen - head_off))
- return (0);
- /*
- * Delete our route from mask lists.
- */
- if (netmask) {
- if ((x = rn_addmask(netmask, 1, head_off)) == 0)
- return (0);
- netmask = x->rn_key;
- while (tt->rn_mask != netmask)
- if ((tt = tt->rn_dupedkey) == 0)
- return (0);
- }
- if (tt->rn_mask == 0 || (saved_m = m = tt->rn_mklist) == 0)
- goto on1;
- if (tt->rn_flags & RNF_NORMAL) {
- if (m->rm_leaf != tt || m->rm_refs > 0) {
- log(LOG_ERR, "rn_delete: inconsistent annotation\n");
- return 0; /* dangling ref could cause disaster */
- }
- } else {
- if (m->rm_mask != tt->rn_mask) {
- log(LOG_ERR, "rn_delete: inconsistent annotation\n");
- goto on1;
- }
- if (--m->rm_refs >= 0)
- goto on1;
- }
- b = -1 - tt->rn_b;
- t = saved_tt->rn_p;
- if (b > t->rn_b)
- goto on1; /* Wasn't lifted at all */
- do {
- x = t;
- t = t->rn_p;
- } while (b <= t->rn_b && x != top);
- for (mp = &x->rn_mklist; m = *mp; mp = &m->rm_mklist)
- if (m == saved_m) {
- *mp = m->rm_mklist;
- MKFree(m);
- break;
- }
- if (m == 0) {
- log(LOG_ERR, "rn_delete: couldn't find our annotation\n");
- if (tt->rn_flags & RNF_NORMAL)
- return (0); /* Dangling ref to us */
- }
-on1:
- /*
- * Eliminate us from tree
- */
- if (tt->rn_flags & RNF_ROOT)
- return (0);
-#ifdef RN_DEBUG
- /* Get us out of the creation list */
- for (t = rn_clist; t && t->rn_ybro != tt; t = t->rn_ybro) {}
- if (t) t->rn_ybro = tt->rn_ybro;
-#endif
- t = tt->rn_p;
- if (dupedkey = saved_tt->rn_dupedkey) {
- if (tt == saved_tt) {
- x = dupedkey; x->rn_p = t;
- if (t->rn_l == tt) t->rn_l = x; else t->rn_r = x;
- } else {
- for (x = p = saved_tt; p && p->rn_dupedkey != tt;)
- p = p->rn_dupedkey;
- if (p) p->rn_dupedkey = tt->rn_dupedkey;
- else log(LOG_ERR, "rn_delete: couldn't find us\n");
- }
- t = tt + 1;
- if (t->rn_flags & RNF_ACTIVE) {
-#ifndef RN_DEBUG
- *++x = *t; p = t->rn_p;
-#else
- b = t->rn_info; *++x = *t; t->rn_info = b; p = t->rn_p;
-#endif
- if (p->rn_l == t) p->rn_l = x; else p->rn_r = x;
- x->rn_l->rn_p = x; x->rn_r->rn_p = x;
- }
- goto out;
- }
- if (t->rn_l == tt) x = t->rn_r; else x = t->rn_l;
- p = t->rn_p;
- if (p->rn_r == t) p->rn_r = x; else p->rn_l = x;
- x->rn_p = p;
- /*
- * Demote routes attached to us.
- */
- if (t->rn_mklist) {
- if (x->rn_b >= 0) {
- for (mp = &x->rn_mklist; m = *mp;)
- mp = &m->rm_mklist;
- *mp = t->rn_mklist;
- } else {
- /* If there are any key,mask pairs in a sibling
- duped-key chain, some subset will appear sorted
- in the same order attached to our mklist */
- for (m = t->rn_mklist; m && x; x = x->rn_dupedkey)
- if (m == x->rn_mklist) {
- struct radix_mask *mm = m->rm_mklist;
- x->rn_mklist = 0;
- if (--(m->rm_refs) < 0)
- MKFree(m);
- m = mm;
- }
- if (m)
-#ifdef _KERNEL
- printf("%s %x at %x\n",
- "rn_delete: Orphaned Mask", m, x);
-#else
- syslog(LOG_ERR, "%s %x at %x\n",
- "rn_delete: Orphaned Mask", m, x);
-#endif
- }
- }
- /*
- * We may be holding an active internal node in the tree.
- */
- x = tt + 1;
- if (t != x) {
-#ifndef RN_DEBUG
- *t = *x;
-#else
- b = t->rn_info; *t = *x; t->rn_info = b;
-#endif
- t->rn_l->rn_p = t; t->rn_r->rn_p = t;
- p = x->rn_p;
- if (p->rn_l == x) p->rn_l = t; else p->rn_r = t;
- }
-out:
- tt->rn_flags &= ~RNF_ACTIVE;
- tt[1].rn_flags &= ~RNF_ACTIVE;
- return (tt);
-}
-
-int
-rn_walktree(h, f, w)
- struct radix_node_head *h;
- register int (*f)();
- void *w;
-{
- int error;
- struct radix_node *base, *next;
- register struct radix_node *rn = h->rnh_treetop;
- /*
- * This gets complicated because we may delete the node
- * while applying the function f to it, so we need to calculate
- * the successor node in advance.
- */
- /* First time through node, go left */
- while (rn->rn_b >= 0)
- rn = rn->rn_l;
- for (;;) {
- base = rn;
- /* If at right child go back up, otherwise, go right */
- while (rn->rn_p->rn_r == rn && (rn->rn_flags & RNF_ROOT) == 0)
- rn = rn->rn_p;
- /* Find the next *leaf* since next node might vanish, too */
- for (rn = rn->rn_p->rn_r; rn->rn_b >= 0;)
- rn = rn->rn_l;
- next = rn;
- /* Process leaves */
- while (rn = base) {
- base = rn->rn_dupedkey;
- if (!(rn->rn_flags & RNF_ROOT) && (error = (*f)(rn, w)))
- return (error);
- }
- rn = next;
- if (rn->rn_flags & RNF_ROOT)
- return (0);
- }
- /* NOTREACHED */
-}
-
-int
-rn_inithead(head, off)
- void **head;
- int off;
-{
- register struct radix_node_head *rnh;
- register struct radix_node *t, *tt, *ttt;
- if (*head)
- return (1);
- R_Malloc(rnh, struct radix_node_head *, sizeof (*rnh));
- if (rnh == 0)
- return (0);
- Bzero(rnh, sizeof (*rnh));
- *head = rnh;
- t = rn_newpair(rn_zeros, off, rnh->rnh_nodes);
- ttt = rnh->rnh_nodes + 2;
- t->rn_r = ttt;
- t->rn_p = t;
- tt = t->rn_l;
- tt->rn_flags = t->rn_flags = RNF_ROOT | RNF_ACTIVE;
- tt->rn_b = -1 - off;
- *ttt = *tt;
- ttt->rn_key = rn_ones;
- rnh->rnh_addaddr = rn_addroute;
- rnh->rnh_deladdr = rn_delete;
- rnh->rnh_matchaddr = rn_match;
- rnh->rnh_lookup = rn_lookup;
- rnh->rnh_walktree = rn_walktree;
- rnh->rnh_treetop = t;
- return (1);
-}
-
-void
-rn_init()
-{
- char *cp, *cplim;
-#ifdef KERNEL
- struct domain *dom;
-
- for (dom = domains; dom; dom = dom->dom_next)
- if (dom->dom_maxrtkey > max_keylen)
- max_keylen = dom->dom_maxrtkey;
-#endif
- if (max_keylen == 0) {
- printf("rn_init: radix functions require max_keylen be set\n");
- return;
- }
- R_Malloc(rn_zeros, char *, 3 * max_keylen);
- if (rn_zeros == NULL)
- panic("rn_init");
- Bzero(rn_zeros, 3 * max_keylen);
- rn_ones = cp = rn_zeros + max_keylen;
- addmask_key = cplim = rn_ones + max_keylen;
- while (cp < cplim)
- *cp++ = -1;
- if (rn_inithead((void **)&mask_rnhead, 0) == 0)
- panic("rn_init 2");
-}
diff --git a/usr.sbin/routed/radix.h b/usr.sbin/routed/radix.h
deleted file mode 100644
index fddf02e..0000000
--- a/usr.sbin/routed/radix.h
+++ /dev/null
@@ -1,161 +0,0 @@
-/*
- * Copyright (c) 1988, 1989, 1993
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * @(#)radix.h 8.2 (Berkeley) 10/31/94
- */
-
-#ifndef __RADIX_H_
-#define __RADIX_H_
-
-#include <sys/cdefs.h>
-struct walkarg;
-
-/*
- * Radix search tree node layout.
- */
-
-struct radix_node {
- struct radix_mask *rn_mklist; /* list of masks contained in subtree */
- struct radix_node *rn_p; /* parent */
- short rn_b; /* bit offset; -1-index(netmask) */
- char rn_bmask; /* node: mask for bit test*/
- u_char rn_flags; /* enumerated next */
-#define RNF_NORMAL 1 /* leaf contains normal route */
-#define RNF_ROOT 2 /* leaf is root leaf for tree */
-#define RNF_ACTIVE 4 /* This node is alive (for rtfree) */
- union {
- struct { /* leaf only data: */
- caddr_t rn_Key; /* object of search */
- caddr_t rn_Mask; /* netmask, if present */
- struct radix_node *rn_Dupedkey;
- } rn_leaf;
- struct { /* node only data: */
- int rn_Off; /* where to start compare */
- struct radix_node *rn_L;/* progeny */
- struct radix_node *rn_R;/* progeny */
- }rn_node;
- } rn_u;
-#ifdef RN_DEBUG
- int rn_info;
- struct radix_node *rn_twin;
- struct radix_node *rn_ybro;
-#endif
-};
-
-#define rn_dupedkey rn_u.rn_leaf.rn_Dupedkey
-#define rn_key rn_u.rn_leaf.rn_Key
-#define rn_mask rn_u.rn_leaf.rn_Mask
-#define rn_off rn_u.rn_node.rn_Off
-#define rn_l rn_u.rn_node.rn_L
-#define rn_r rn_u.rn_node.rn_R
-
-/*
- * Annotations to tree concerning potential routes applying to subtrees.
- */
-
-extern struct radix_mask {
- short rm_b; /* bit offset; -1-index(netmask) */
- char rm_unused; /* cf. rn_bmask */
- u_char rm_flags; /* cf. rn_flags */
- struct radix_mask *rm_mklist; /* more masks to try */
- union {
- caddr_t rmu_mask; /* the mask */
- struct radix_node *rmu_leaf; /* for normal routes */
- } rm_rmu;
- int rm_refs; /* # of references to this struct */
-} *rn_mkfreelist;
-
-#define rm_mask rm_rmu.rmu_mask
-#define rm_leaf rm_rmu.rmu_leaf /* extra field would make 32 bytes */
-
-#define MKGet(m) {\
- if (rn_mkfreelist) {\
- m = rn_mkfreelist; \
- rn_mkfreelist = (m)->rm_mklist; \
- } else \
- R_Malloc(m, struct radix_mask *, sizeof (*(m))); }\
-
-#define MKFree(m) { (m)->rm_mklist = rn_mkfreelist; rn_mkfreelist = (m);}
-
-struct radix_node_head {
- struct radix_node *rnh_treetop;
- int rnh_addrsize; /* permit, but not require fixed keys */
- int rnh_pktsize; /* permit, but not require fixed keys */
- struct radix_node *(*rnh_addaddr) /* add based on sockaddr */
- __P((void *v, void *mask,
- struct radix_node_head *head, struct radix_node nodes[]));
- struct radix_node *(*rnh_addpkt) /* add based on packet hdr */
- __P((void *v, void *mask,
- struct radix_node_head *head, struct radix_node nodes[]));
- struct radix_node *(*rnh_deladdr) /* remove based on sockaddr */
- __P((void *v, void *mask, struct radix_node_head *head));
- struct radix_node *(*rnh_delpkt) /* remove based on packet hdr */
- __P((void *v, void *mask, struct radix_node_head *head));
- struct radix_node *(*rnh_matchaddr) /* locate based on sockaddr */
- __P((void *v, struct radix_node_head *head));
- struct radix_node *(*rnh_lookup) /* locate based on sockaddr */
- __P((void *v, void *mask, struct radix_node_head *head));
- struct radix_node *(*rnh_matchpkt) /* locate based on packet hdr */
- __P((void *v, struct radix_node_head *head));
- int (*rnh_walktree) /* traverse tree */
- (struct radix_node_head *head,
- int (*f)(struct radix_node *, struct walkarg *),
- struct walkarg *w);
- struct radix_node rnh_nodes[3]; /* empty tree for common case */
-};
-
-
-#define Bcmp(a, b, n) bcmp(((char *)(a)), ((char *)(b)), (n))
-#define Bcopy(a, b, n) bcopy(((char *)(a)), ((char *)(b)), (unsigned)(n))
-#define Bzero(p, n) bzero((char *)(p), (int)(n));
-#define R_Malloc(p, t, n) (p = (t) malloc((unsigned int)(n)))
-#define Free(p) free((char *)p);
-
-void rn_init __P((void));
-int rn_inithead __P((void **, int));
-int rn_refines __P((void *, void *));
-int rn_walktree __P((struct radix_node_head *,
- int (*)__P((struct radix_node *, struct walkarg*)),
- struct walkarg*));
-struct radix_node
- *rn_addmask __P((void *, int, int)),
- *rn_addroute __P((void *, void *, struct radix_node_head *,
- struct radix_node [2])),
- *rn_delete __P((void *, void *, struct radix_node_head *)),
- *rn_insert __P((void *, struct radix_node_head *, int *,
- struct radix_node [2])),
- *rn_match __P((void *, struct radix_node_head *)),
- *rn_newpair __P((void *, int, struct radix_node[2])),
- *rn_search __P((void *, struct radix_node *)),
- *rn_search_m __P((void *, struct radix_node *, void *));
-
-#endif /* __RADIX_H_ */
diff --git a/usr.sbin/routed/rdisc.c b/usr.sbin/routed/rdisc.c
deleted file mode 100644
index 489da11..0000000
--- a/usr.sbin/routed/rdisc.c
+++ /dev/null
@@ -1,1032 +0,0 @@
-/*
- * Copyright (c) 1995
- * 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.
- */
-
-#if !defined(lint) && !defined(sgi) && !defined(__NetBSD__)
-static char sccsid[] = "@(#)rdisc.c 8.1 (Berkeley) x/y/95";
-#elif defined(__NetBSD__)
-static char rcsid[] = "$NetBSD$";
-#endif
-#ident "$Revision: 1.1.3.3 $"
-
-#include "defs.h"
-#include <netinet/in_systm.h>
-#include <netinet/ip.h>
-#include <netinet/ip_icmp.h>
-
-/* router advertisement ICMP packet */
-struct icmp_ad {
- u_int8_t icmp_type; /* type of message */
- u_int8_t icmp_code; /* type sub code */
- u_int16_t icmp_cksum; /* ones complement cksum of struct */
- u_int8_t icmp_ad_num; /* # of following router addresses */
- u_int8_t icmp_ad_asize; /* 2--words in each advertisement */
- u_int16_t icmp_ad_life; /* seconds of validity */
- struct icmp_ad_info {
- n_long icmp_ad_addr;
- n_long icmp_ad_pref;
- } icmp_ad_info[1];
-};
-
-/* router solicitation ICMP packet */
-struct icmp_so {
- u_int8_t icmp_type; /* type of message */
- u_int8_t icmp_code; /* type sub code */
- u_int16_t icmp_cksum; /* ones complement cksum of struct */
- n_long icmp_so_rsvd;
-};
-
-union ad_u {
- struct icmp icmp;
- struct icmp_ad ad;
- struct icmp_so so;
-};
-
-
-int rdisc_sock = -1; /* router-discovery raw socket */
-struct interface *rdisc_sock_mcast; /* current multicast interface */
-
-struct timeval rdisc_timer;
-int rdisc_ok; /* using solicited route */
-
-
-#define MAX_ADS 5
-struct dr { /* accumulated advertisements */
- struct interface *dr_ifp;
- naddr dr_gate; /* gateway */
- time_t dr_ts; /* when received */
- time_t dr_life; /* lifetime */
- n_long dr_recv_pref; /* received but biased preference */
- n_long dr_pref; /* preference adjusted by metric */
-} *cur_drp, drs[MAX_ADS];
-
-/* adjust preference by interface metric without driving it to infinity */
-#define PREF(p, ifp) ((p) <= (ifp)->int_metric ? ((p) != 0 ? 1 : 0) \
- : (p) - ((ifp)->int_metric))
-
-static void rdisc_sort(void);
-
-
-/* dump an ICMP Router Discovery Advertisement Message
- */
-static void
-trace_rdisc(char *act,
- naddr from,
- naddr to,
- struct interface *ifp,
- union ad_u *p,
- u_int len)
-{
- int i;
- n_long *wp, *lim;
-
-
- if (!TRACEPACKETS || ftrace == 0)
- return;
-
- lastlog();
-
- if (p->icmp.icmp_type == ICMP_ROUTERADVERT) {
- (void)fprintf(ftrace, "%s Router Ad"
- " from %s to %s via %s life=%d\n",
- act, naddr_ntoa(from), naddr_ntoa(to),
- ifp ? ifp->int_name : "?",
- ntohs(p->ad.icmp_ad_life));
- if (!TRACECONTENTS)
- return;
-
- wp = &p->ad.icmp_ad_info[0].icmp_ad_addr;
- lim = &wp[(len - sizeof(p->ad)) / sizeof(*wp)];
- for (i = 0; i < p->ad.icmp_ad_num && wp <= lim; i++) {
- (void)fprintf(ftrace, "\t%s preference=%#x",
- naddr_ntoa(wp[0]), (int)ntohl(wp[1]));
- wp += p->ad.icmp_ad_asize;
- }
- (void)fputc('\n',ftrace);
-
- } else {
- trace_act("%s Router Solic. from %s to %s via %s"
- " value=%#x\n",
- act, naddr_ntoa(from), naddr_ntoa(to),
- ifp ? ifp->int_name : "?",
- ntohl(p->so.icmp_so_rsvd));
- }
-}
-
-/* prepare Router Discovery socket.
- */
-static void
-get_rdisc_sock(void)
-{
- if (rdisc_sock < 0) {
- rdisc_sock = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
- if (rdisc_sock < 0)
- BADERR(1,"rdisc_sock = socket()");
- fix_sock(rdisc_sock,"rdisc_sock");
- fix_select();
- }
-}
-
-
-/* Pick multicast group for router-discovery socket
- */
-void
-set_rdisc_mg(struct interface *ifp,
- int on) { /* 0=turn it off */
- struct ip_mreq m;
-
- if (rdisc_sock < 0) {
- /* Create the raw socket so that we can hear at least
- * broadcast router discovery packets.
- */
- if ((ifp->int_state & IS_NO_RDISC) == IS_NO_RDISC
- || !on)
- return;
- get_rdisc_sock();
- }
-
- if (!(ifp->int_if_flags & IFF_MULTICAST)
- || (ifp->int_state & IS_ALIAS)) {
- ifp->int_state &= ~(IS_ALL_HOSTS | IS_ALL_ROUTERS);
- return;
- }
-
-#ifdef MCAST_PPP_BUG
- if (ifp->int_if_flags & IFF_POINTOPOINT)
- return;
-#endif
- bzero(&m, sizeof(m));
- m.imr_interface.s_addr = ((ifp->int_if_flags & IFF_POINTOPOINT)
- ? ifp->int_dstaddr
- : ifp->int_addr);
- if (supplier
- || (ifp->int_state & IS_NO_ADV_IN)
- || !on) {
- /* stop listening to advertisements
- */
- if (ifp->int_state & IS_ALL_HOSTS) {
- m.imr_multiaddr.s_addr = htonl(INADDR_ALLHOSTS_GROUP);
- if (setsockopt(rdisc_sock, IPPROTO_IP,
- IP_DROP_MEMBERSHIP,
- &m, sizeof(m)) < 0)
- LOGERR("IP_DROP_MEMBERSHIP ALLHOSTS");
- ifp->int_state &= ~IS_ALL_HOSTS;
- }
-
- } else if (!(ifp->int_state & IS_ALL_HOSTS)) {
- /* start listening to advertisements
- */
- m.imr_multiaddr.s_addr = htonl(INADDR_ALLHOSTS_GROUP);
- if (setsockopt(rdisc_sock, IPPROTO_IP, IP_ADD_MEMBERSHIP,
- &m, sizeof(m)) < 0) {
- LOGERR("IP_ADD_MEMBERSHIP ALLHOSTS");
- } else {
- ifp->int_state |= IS_ALL_HOSTS;
- }
- }
-
- if (!supplier
- || (ifp->int_state & IS_NO_ADV_OUT)
- || !on) {
- /* stop listening to solicitations
- */
- if (ifp->int_state & IS_ALL_ROUTERS) {
- m.imr_multiaddr.s_addr=htonl(INADDR_ALLROUTERS_GROUP);
- if (setsockopt(rdisc_sock, IPPROTO_IP,
- IP_DROP_MEMBERSHIP,
- &m, sizeof(m)) < 0)
- LOGERR("IP_DROP_MEMBERSHIP ALLROUTERS");
- ifp->int_state &= ~IS_ALL_ROUTERS;
- }
-
- } else if (!(ifp->int_state & IS_ALL_ROUTERS)) {
- /* start hearing solicitations
- */
- m.imr_multiaddr.s_addr=htonl(INADDR_ALLROUTERS_GROUP);
- if (setsockopt(rdisc_sock, IPPROTO_IP, IP_ADD_MEMBERSHIP,
- &m, sizeof(m)) < 0) {
- LOGERR("IP_ADD_MEMBERSHIP ALLROUTERS");
- } else {
- ifp->int_state |= IS_ALL_ROUTERS;
- }
- }
-}
-
-
-/* start supplying routes
- */
-void
-set_supplier(void)
-{
- struct interface *ifp;
- struct dr *drp;
-
- if (supplier_set)
- return;
-
- trace_act("start suppying routes\n");
-
- /* Forget discovered routes.
- */
- for (drp = drs; drp < &drs[MAX_ADS]; drp++) {
- drp->dr_recv_pref = 0;
- drp->dr_life = 0;
- }
- rdisc_age(0);
-
- supplier_set = 1;
- supplier = 1;
-
- /* Do not start advertising until we have heard some RIP routes */
- LIM_SEC(rdisc_timer, now.tv_sec+MIN_WAITTIME);
-
- /* Switch router discovery multicast groups from soliciting
- * to advertising.
- */
- for (ifp = ifnet; ifp; ifp = ifp->int_next) {
- if (ifp->int_state & IS_BROKE)
- continue;
- ifp->int_rdisc_cnt = 0;
- ifp->int_rdisc_timer.tv_usec = rdisc_timer.tv_usec;
- ifp->int_rdisc_timer.tv_sec = now.tv_sec+MIN_WAITTIME;
- set_rdisc_mg(ifp, 1);
- }
-
- /* get rid of any redirects */
- del_redirects(0,0);
-}
-
-
-/* age discovered routes and find the best one
- */
-void
-rdisc_age(naddr bad_gate)
-{
- time_t sec;
- struct dr *drp;
-
-
- /* If only adverising, then do only that. */
- if (supplier) {
- /* if switching from client to server, get rid of old
- * default routes.
- */
- if (cur_drp != 0)
- rdisc_sort();
- rdisc_adv();
- return;
- }
-
- /* If we are being told about a bad router,
- * then age the discovered default route, and if there is
- * no alternative, solicite a replacement.
- */
- if (bad_gate != 0) {
- /* Look for the bad discovered default route.
- * Age it and note its interface.
- */
- for (drp = drs; drp < &drs[MAX_ADS]; drp++) {
- if (drp->dr_ts == 0)
- continue;
-
- /* When we find the bad router, then age the route
- * to at most SUPPLY_INTERVAL.
- * This is contrary to RFC 1256, but defends against
- * black holes.
- */
- if (drp->dr_gate == bad_gate) {
- sec = (now.tv_sec - drp->dr_life
- + SUPPLY_INTERVAL);
- if (drp->dr_ts > sec) {
- trace_act("age 0.0.0.0 --> %s"
- " via %s\n",
- naddr_ntoa(drp->dr_gate),
- drp->dr_ifp->int_name);
- drp->dr_ts = sec;
- }
- break;
- }
- }
- }
-
- /* delete old redirected routes to keep the kernel table small
- */
- sec = (cur_drp == 0) ? MaxMaxAdvertiseInterval : cur_drp->dr_life;
- del_redirects(bad_gate, now.tv_sec-sec);
-
- rdisc_sol();
-
- rdisc_sort();
-}
-
-
-/* Zap all routes discovered via an interface that has gone bad
- * This should only be called when !(ifp->int_state & IS_ALIAS)
- */
-void
-if_bad_rdisc(struct interface *ifp)
-{
- struct dr *drp;
-
- for (drp = drs; drp < &drs[MAX_ADS]; drp++) {
- if (drp->dr_ifp != ifp)
- continue;
- drp->dr_recv_pref = 0;
- drp->dr_life = 0;
- }
-
- rdisc_sort();
-}
-
-
-/* mark an interface ok for router discovering.
- */
-void
-if_ok_rdisc(struct interface *ifp)
-{
- set_rdisc_mg(ifp, 1);
-
- ifp->int_rdisc_cnt = 0;
- ifp->int_rdisc_timer.tv_sec = now.tv_sec + (supplier
- ? MIN_WAITTIME
- : MAX_SOLICITATION_DELAY);
- if (timercmp(&rdisc_timer, &ifp->int_rdisc_timer, >))
- rdisc_timer = ifp->int_rdisc_timer;
-}
-
-
-/* get rid of a dead discovered router
- */
-static void
-del_rdisc(struct dr *drp)
-{
- struct interface *ifp;
- int i;
-
-
- del_redirects(drp->dr_gate, 0);
- drp->dr_ts = 0;
- drp->dr_life = 0;
-
-
- /* Count the other discovered routes on the interface.
- */
- i = 0;
- ifp = drp->dr_ifp;
- for (drp = drs; drp < &drs[MAX_ADS]; drp++) {
- if (drp->dr_ts != 0
- && drp->dr_ifp == ifp)
- i++;
- }
-
- /* If that was the last good discovered router on the interface,
- * then solicit a new one.
- * This is contrary to RFC 1256, but defends against black holes.
- */
- if (i == 0
- && ifp->int_rdisc_cnt >= MAX_SOLICITATIONS) {
- trace_act("discovered route is bad"
- "--re-solicit routers via %s\n", ifp->int_name);
- ifp->int_rdisc_cnt = 0;
- ifp->int_rdisc_timer.tv_sec = 0;
- rdisc_sol();
- }
-}
-
-
-/* Find the best discovered route,
- * and discard stale routers.
- */
-static void
-rdisc_sort(void)
-{
- struct dr *drp, *new_drp;
- struct rt_entry *rt;
- struct interface *ifp;
- u_int new_st;
- n_long new_pref;
-
-
- /* Find the best discovered route.
- */
- new_drp = 0;
- for (drp = drs; drp < &drs[MAX_ADS]; drp++) {
- if (drp->dr_ts == 0)
- continue;
- ifp = drp->dr_ifp;
-
- /* Get rid of expired discovered routers.
- */
- if (drp->dr_ts + drp->dr_life <= now.tv_sec) {
- del_rdisc(drp);
- continue;
- }
-
- LIM_SEC(rdisc_timer, drp->dr_ts+drp->dr_life+1);
-
- /* Update preference with possibly changed interface
- * metric.
- */
- drp->dr_pref = PREF(drp->dr_recv_pref, ifp);
-
- /* Prefer the current route to prevent thrashing.
- * Prefer shorter lifetimes to speed the detection of
- * bad routers.
- * Avoid sick interfaces.
- */
- if (new_drp == 0
- || (!((new_st ^ drp->dr_ifp->int_state) & IS_SICK)
- && (new_pref < drp->dr_pref
- || (new_pref == drp->dr_pref
- && (drp == cur_drp
- || (new_drp != cur_drp
- && new_drp->dr_life > drp->dr_life)))))
- || ((new_st & IS_SICK)
- && !(drp->dr_ifp->int_state & IS_SICK))) {
- new_drp = drp;
- new_st = drp->dr_ifp->int_state;
- new_pref = drp->dr_pref;
- }
- }
-
- /* switch to a better default route
- */
- if (new_drp != cur_drp) {
- rt = rtget(RIP_DEFAULT, 0);
-
- /* Stop using discovered routes if they are all bad
- */
- if (new_drp == 0) {
- trace_act("turn off Router Discovery client\n");
- rdisc_ok = 0;
-
- if (rt != 0
- && (rt->rt_state & RS_RDISC)) {
- rtchange(rt, rt->rt_state & ~RS_RDISC,
- rt->rt_gate, rt->rt_router,
- HOPCNT_INFINITY, 0, rt->rt_ifp,
- now.tv_sec - GARBAGE_TIME, 0);
- rtswitch(rt, 0);
- }
-
- /* turn on RIP if permitted */
- rip_on(0);
-
- } else {
- if (cur_drp == 0) {
- trace_act("turn on Router Discovery client"
- " using %s via %s\n",
- naddr_ntoa(new_drp->dr_gate),
- new_drp->dr_ifp->int_name);
-
- rdisc_ok = 1;
-
- } else {
- trace_act("switch Router Discovery from"
- " %s via %s to %s via %s\n",
- naddr_ntoa(cur_drp->dr_gate),
- cur_drp->dr_ifp->int_name,
- naddr_ntoa(new_drp->dr_gate),
- new_drp->dr_ifp->int_name);
- }
-
- if (rt != 0) {
- rtchange(rt, rt->rt_state | RS_RDISC,
- new_drp->dr_gate, new_drp->dr_gate,
- 0,0, new_drp->dr_ifp,
- now.tv_sec, 0);
- } else {
- rtadd(RIP_DEFAULT, 0,
- new_drp->dr_gate, new_drp->dr_gate,
- 0, 0, RS_RDISC, new_drp->dr_ifp);
- }
-
- /* Now turn off RIP and delete RIP routes,
- * which might otherwise include the default
- * we just modified.
- */
- rip_off();
- }
-
- cur_drp = new_drp;
- }
-}
-
-
-/* handle a single address in an advertisement
- */
-static void
-parse_ad(naddr from,
- naddr gate,
- n_long pref,
- u_short life,
- struct interface *ifp)
-{
- static naddr bad_gate;
- struct dr *drp, *new_drp;
-
-
- if (gate == RIP_DEFAULT
- || !check_dst(gate)) {
- if (bad_gate != from) {
- msglog("router %s advertising bad gateway %s",
- naddr_ntoa(from),
- naddr_ntoa(gate));
- bad_gate = from;
- }
- return;
- }
-
- /* ignore pointers to ourself and routes via unreachable networks
- */
- if (ifwithaddr(gate, 1, 0) != 0) {
- trace_pkt("\tdiscard Router Discovery Ad pointing at us\n");
- return;
- }
- if (!on_net(gate, ifp->int_net, ifp->int_mask)) {
- trace_pkt("\tdiscard Router Discovery Ad"
- " toward unreachable net\n");
- return;
- }
-
- /* Convert preference to an unsigned value
- * and later bias it by the metric of the interface.
- */
- pref = ntohl(pref) ^ MIN_PreferenceLevel;
-
- if (pref == 0 || life == 0) {
- pref = 0;
- life = 0;
- }
-
- for (new_drp = 0, drp = drs; drp < &drs[MAX_ADS]; drp++) {
- /* accept new info for a familiar entry
- */
- if (drp->dr_gate == gate) {
- new_drp = drp;
- break;
- }
-
- if (life == 0)
- continue; /* do not worry about dead ads */
-
- if (drp->dr_ts == 0) {
- new_drp = drp; /* use unused entry */
-
- } else if (new_drp == 0) {
- /* look for an entry worse than the new one to
- * reuse.
- */
- if ((!(ifp->int_state & IS_SICK)
- && (drp->dr_ifp->int_state & IS_SICK))
- || (pref > drp->dr_pref
- && !((ifp->int_state ^ drp->dr_ifp->int_state)
- & IS_SICK)))
- new_drp = drp;
-
- } else if (new_drp->dr_ts != 0) {
- /* look for the least valueable entry to reuse
- */
- if ((!(new_drp->dr_ifp->int_state & IS_SICK)
- && (drp->dr_ifp->int_state & IS_SICK))
- || (new_drp->dr_pref > drp->dr_pref
- && !((new_drp->dr_ifp->int_state
- ^ drp->dr_ifp->int_state)
- & IS_SICK)))
- new_drp = drp;
- }
- }
-
- /* forget it if all of the current entries are better */
- if (new_drp == 0)
- return;
-
- new_drp->dr_ifp = ifp;
- new_drp->dr_gate = gate;
- new_drp->dr_ts = now.tv_sec;
- new_drp->dr_life = ntohs(life);
- new_drp->dr_recv_pref = pref;
- /* bias functional preference by metric of the interface */
- new_drp->dr_pref = PREF(pref,ifp);
-
- /* after hearing a good advertisement, stop asking
- */
- if (!(ifp->int_state & IS_SICK))
- ifp->int_rdisc_cnt = MAX_SOLICITATIONS;
-}
-
-
-/* Compute the IP checksum
- * This assumes the packet is less than 32K long.
- */
-static u_short
-in_cksum(u_short *p,
- u_int len)
-{
- u_int sum = 0;
- int nwords = len >> 1;
-
- while (nwords-- != 0)
- sum += *p++;
-
- if (len & 1)
- sum += *(u_char *)p;
-
- /* end-around-carry */
- sum = (sum >> 16) + (sum & 0xffff);
- sum += (sum >> 16);
- return (~sum);
-}
-
-
-/* Send a router discovery advertisement or solicitation ICMP packet.
- */
-static void
-send_rdisc(union ad_u *p,
- int p_size,
- struct interface *ifp,
- naddr dst, /* 0 or unicast destination */
- int type) /* 0=unicast, 1=bcast, 2=mcast */
-{
- struct sockaddr_in sin;
- int flags;
- char *msg;
- naddr tgt_mcast;
-
-
- bzero(&sin, sizeof(sin));
- sin.sin_addr.s_addr = dst;
- sin.sin_family = AF_INET;
-#ifdef _HAVE_SIN_LEN
- sin.sin_len = sizeof(sin);
-#endif
- flags = MSG_DONTROUTE;
-
- switch (type) {
- case 0: /* unicast */
- msg = "Send";
- break;
-
- case 1: /* broadcast */
- if (ifp->int_if_flags & IFF_POINTOPOINT) {
- msg = "Send pt-to-pt";
- sin.sin_addr.s_addr = ifp->int_dstaddr;
- } else {
- msg = "Send broadcast";
- sin.sin_addr.s_addr = ifp->int_brdaddr;
- }
- break;
-
- case 2: /* multicast */
- msg = "Send multicast";
- if (ifp->int_state & IS_DUP) {
- trace_act("abort multicast output via %s"
- " with duplicate address\n",
- ifp->int_name);
- return;
- }
- if (rdisc_sock_mcast != ifp) {
- /* select the right interface. */
-#ifdef MCAST_PPP_BUG
- /* Do not specifiy the primary interface explicitly
- * if we have the multicast point-to-point kernel
- * bug, since the kernel will do the wrong thing
- * if the local address of a point-to-point link
- * is the same as the address of an ordinary
- * interface.
- */
- if (ifp->int_addr == myaddr) {
- tgt_mcast = 0;
- } else
-#endif
- tgt_mcast = ifp->int_addr;
- if (0 > setsockopt(rdisc_sock,
- IPPROTO_IP, IP_MULTICAST_IF,
- &tgt_mcast, sizeof(tgt_mcast))) {
- LOGERR("setsockopt(rdisc_sock,"
- "IP_MULTICAST_IF)");
- rdisc_sock_mcast = 0;
- return;
- }
- rdisc_sock_mcast = ifp;
- }
- flags = 0;
- break;
- }
-
- if (rdisc_sock < 0)
- get_rdisc_sock();
-
- trace_rdisc(msg, ifp->int_addr, sin.sin_addr.s_addr, ifp,
- p, p_size);
-
- if (0 > sendto(rdisc_sock, p, p_size, flags,
- (struct sockaddr *)&sin, sizeof(sin))) {
- if (ifp == 0 || !(ifp->int_state & IS_BROKE))
- msglog("sendto(%s%s%s): %s",
- ifp != 0 ? ifp->int_name : "",
- ifp != 0 ? ", " : "",
- inet_ntoa(sin.sin_addr),
- strerror(errno));
- if (ifp != 0)
- if_sick(ifp);
- }
-}
-
-
-/* Send an advertisement
- */
-static void
-send_adv(struct interface *ifp,
- naddr dst, /* 0 or unicast destination */
- int type) /* 0=unicast, 1=bcast, 2=mcast */
-{
- union ad_u u;
- n_long pref;
-
-
- bzero(&u,sizeof(u.ad));
-
- u.ad.icmp_type = ICMP_ROUTERADVERT;
- u.ad.icmp_ad_num = 1;
- u.ad.icmp_ad_asize = sizeof(u.ad.icmp_ad_info[0])/4;
-
- u.ad.icmp_ad_life = stopint ? 0 : htons(ifp->int_rdisc_int*3);
- pref = ifp->int_rdisc_pref ^ MIN_PreferenceLevel;
- pref = PREF(pref, ifp) ^ MIN_PreferenceLevel;
- u.ad.icmp_ad_info[0].icmp_ad_pref = htonl(pref);
-
- u.ad.icmp_ad_info[0].icmp_ad_addr = ifp->int_addr;
-
- u.ad.icmp_cksum = in_cksum((u_short*)&u.ad, sizeof(u.ad));
-
- send_rdisc(&u, sizeof(u.ad), ifp, dst, type);
-}
-
-
-/* Advertise for Router Discovery
- */
-void
-rdisc_adv(void)
-{
- struct interface *ifp;
-
-
- rdisc_timer.tv_sec = now.tv_sec + NEVER;
-
- for (ifp = ifnet; ifp; ifp = ifp->int_next) {
- if (0 != (ifp->int_state & (IS_NO_ADV_OUT
- | IS_PASSIVE
- | IS_ALIAS
- | IS_BROKE)))
- continue;
-
- if (!timercmp(&ifp->int_rdisc_timer, &now, >)
- || stopint) {
- send_adv(ifp, htonl(INADDR_ALLHOSTS_GROUP),
- (ifp->int_state&IS_BCAST_RDISC) ? 1 : 2);
- ifp->int_rdisc_cnt++;
-
- intvl_random(&ifp->int_rdisc_timer,
- (ifp->int_rdisc_int*3)/4,
- ifp->int_rdisc_int);
- if (ifp->int_rdisc_cnt < MAX_INITIAL_ADVERTS
- && (ifp->int_rdisc_timer.tv_sec
- > MAX_INITIAL_ADVERT_INTERVAL)) {
- ifp->int_rdisc_timer.tv_sec
- = MAX_INITIAL_ADVERT_INTERVAL;
- }
- timevaladd(&ifp->int_rdisc_timer, &now);
- }
-
- if (timercmp(&rdisc_timer, &ifp->int_rdisc_timer, >))
- rdisc_timer = ifp->int_rdisc_timer;
- }
-}
-
-
-/* Solicit for Router Discovery
- */
-void
-rdisc_sol(void)
-{
- struct interface *ifp;
- union ad_u u;
-
-
- rdisc_timer.tv_sec = now.tv_sec + NEVER;
-
- for (ifp = ifnet; ifp; ifp = ifp->int_next) {
- if (0 != (ifp->int_state & (IS_NO_SOL_OUT
- | IS_PASSIVE
- | IS_ALIAS
- | IS_BROKE))
- || ifp->int_rdisc_cnt >= MAX_SOLICITATIONS)
- continue;
-
- if (!timercmp(&ifp->int_rdisc_timer, &now, >)) {
- bzero(&u,sizeof(u.so));
- u.so.icmp_type = ICMP_ROUTERSOLICIT;
- u.so.icmp_cksum = in_cksum((u_short*)&u.so,
- sizeof(u.so));
- send_rdisc(&u, sizeof(u.so), ifp,
- htonl(INADDR_ALLROUTERS_GROUP),
- ((ifp->int_state&IS_BCAST_RDISC) ? 1 : 2));
-
- if (++ifp->int_rdisc_cnt >= MAX_SOLICITATIONS)
- continue;
-
- ifp->int_rdisc_timer.tv_sec = SOLICITATION_INTERVAL;
- ifp->int_rdisc_timer.tv_usec = 0;
- timevaladd(&ifp->int_rdisc_timer, &now);
- }
-
- if (timercmp(&rdisc_timer, &ifp->int_rdisc_timer, >))
- rdisc_timer = ifp->int_rdisc_timer;
- }
-}
-
-
-/* check the IP header of a possible Router Discovery ICMP packet */
-static struct interface * /* 0 if bad */
-ck_icmp(char *act,
- naddr from,
- naddr to,
- union ad_u *p,
- u_int len)
-{
- struct interface *ifp;
- char *type;
-
-
- /* If we could tell the interface on which a packet from address 0
- * arrived, we could deal with such solicitations.
- */
-
- ifp = ((from == 0) ? 0 : iflookup(from));
-
- if (p->icmp.icmp_type == ICMP_ROUTERADVERT) {
- type = "advertisement";
- } else if (p->icmp.icmp_type == ICMP_ROUTERSOLICIT) {
- type = "solicitation";
- } else {
- return 0;
- }
-
- if (p->icmp.icmp_code != 0) {
- trace_pkt("unrecognized ICMP Router"
- " %s code=%d from %s to %s\n",
- type, p->icmp.icmp_code,
- naddr_ntoa(from), naddr_ntoa(to));
- return 0;
- }
-
- trace_rdisc(act, from, to, ifp, p, len);
-
- if (ifp == 0)
- trace_pkt("unknown interface for router-discovery %s"
- " from %s to %s",
- type, naddr_ntoa(from), naddr_ntoa(to));
-
- return ifp;
-}
-
-
-/* read packets from the router discovery socket
- */
-void
-read_d(void)
-{
- static naddr bad_asize, bad_len;
- struct sockaddr_in from;
- int n, fromlen, cc, hlen;
- union {
- struct ip ip;
- u_short s[512/2];
- u_char b[512];
- } pkt;
- union ad_u *p;
- n_long *wp;
- struct interface *ifp;
-
-
- for (;;) {
- fromlen = sizeof(from);
- cc = recvfrom(rdisc_sock, &pkt, sizeof(pkt), 0,
- (struct sockaddr*)&from,
- &fromlen);
- if (cc <= 0) {
- if (cc < 0 && errno != EWOULDBLOCK)
- LOGERR("recvfrom(rdisc_sock)");
- break;
- }
- if (fromlen != sizeof(struct sockaddr_in))
- logbad(1,"impossible recvfrom(rdisc_sock) fromlen=%d",
- fromlen);
-
- hlen = pkt.ip.ip_hl << 2;
- if (cc < hlen + ICMP_MINLEN)
- continue;
- p = (union ad_u *)&pkt.b[hlen];
- cc -= hlen;
-
- ifp = ck_icmp("Recv",
- from.sin_addr.s_addr, pkt.ip.ip_dst.s_addr,
- p, cc);
- if (ifp == 0)
- continue;
- if (ifwithaddr(from.sin_addr.s_addr, 0, 0)) {
- trace_pkt("\tdiscard our own Router Discovery msg\n");
- continue;
- }
-
- switch (p->icmp.icmp_type) {
- case ICMP_ROUTERADVERT:
- if (p->ad.icmp_ad_asize*4
- < sizeof(p->ad.icmp_ad_info[0])) {
- if (bad_asize != from.sin_addr.s_addr) {
- msglog("intolerable rdisc address"
- " size=%d",
- p->ad.icmp_ad_asize);
- bad_asize = from.sin_addr.s_addr;
- }
- continue;
- }
- if (p->ad.icmp_ad_num == 0) {
- trace_pkt("\tempty?\n");
- continue;
- }
- if (cc != (sizeof(p->ad) - sizeof(p->ad.icmp_ad_info)
- + (p->ad.icmp_ad_num
- * sizeof(p->ad.icmp_ad_info[0])))) {
- if (bad_len != from.sin_addr.s_addr) {
- msglog("rdisc length %d does not"
- " match ad_num %d",
- cc, p->ad.icmp_ad_num);
- bad_len = from.sin_addr.s_addr;
- }
- continue;
- }
- if (supplier)
- continue;
- if (ifp->int_state & IS_NO_ADV_IN)
- continue;
-
- wp = &p->ad.icmp_ad_info[0].icmp_ad_addr;
- for (n = 0; n < p->ad.icmp_ad_num; n++) {
- parse_ad(from.sin_addr.s_addr,
- wp[0], wp[1],
- ntohs(p->ad.icmp_ad_life),
- ifp);
- wp += p->ad.icmp_ad_asize;
- }
- break;
-
-
- case ICMP_ROUTERSOLICIT:
- if (!supplier)
- continue;
- if (ifp->int_state & IS_NO_ADV_OUT)
- continue;
-
- /* XXX
- * We should handle messages from address 0.
- */
-
- /* Respond with a point-to-point advertisement */
- send_adv(ifp, from.sin_addr.s_addr, 0);
- break;
- }
- }
-
- rdisc_sort();
-}
diff --git a/usr.sbin/routed/routed.8 b/usr.sbin/routed/routed.8
deleted file mode 100644
index c4fe516..0000000
--- a/usr.sbin/routed/routed.8
+++ /dev/null
@@ -1,602 +0,0 @@
-.\" Copyright (c) 1983, 1991, 1993
-.\" The Regents of the University of California. All rights reserved.
-.\"
-.\" Redistribution and use in source and binary forms, with or without
-.\" modification, are permitted provided that the following conditions
-.\" are met:
-.\" 1. Redistributions of source code must retain the above copyright
-.\" notice, this list of conditions and the following disclaimer.
-.\" 2. Redistributions in binary form must reproduce the above copyright
-.\" notice, this list of conditions and the following disclaimer in the
-.\" documentation and/or other materials provided with the distribution.
-.\" 3. All advertising materials mentioning features or use of this software
-.\" must display the following acknowledgement:
-.\" This product includes software developed by the University of
-.\" California, Berkeley and its contributors.
-.\" 4. Neither the name of the University nor the names of its contributors
-.\" may be used to endorse or promote products derived from this software
-.\" without specific prior written permission.
-.\"
-.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
-.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
-.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
-.\" SUCH DAMAGE.
-.\"
-.\" @(#)routed.8 8.2 (Berkeley) 12/11/93
-.\"
-.Dd June 1, 1996
-.Dt ROUTED 8
-.Os BSD 4.4
-.Sh NAME
-.Nm routed
-.Nd network RIP and router discovery routing daemon
-.Sh SYNOPSIS
-.Nm
-.Op Fl sqdghmAt
-.Op Fl T Ar tracefile
-.Oo
-.Fl F
-.Ar net Ns Op /mask Ns Op ,metric
-.Oc
-.OP Fl P Ar parms
-.Sh DESCRIPTION
-.Nm Routed
-is a dameon invoked at boot time to manage the network
-routing tables.
-It uses Routing Information Protocol, RIPv1 (RFC\ 1058),
-RIPv2 (RFC\ 1723),
-and Internet Router Discovery Protocol (RFC 1256)
-to maintain the kernel routing table.
-The RIPv1 protocol is based on the reference 4.3BSD daemon.
-.Pp
-It listens on the
-.Xr udp 4
-socket for the
-.Xr route 8
-service (see
-.Xr services 5 )
-for Routing Information Protocol packets.
-It also sends and receives multicast Router Discovery ICMP messages.
-If the host is a router,
-.Nm
-periodically supplies copies
-of its routing tables to any directly connected hosts and networks.
-It also advertise or solicits default routes using Router Discovery
-ICMP messages.
-.Pp
-When started (or when a network interface is later turned on),
-.Nm
-uses an AF_ROUTE address family facility to find those
-directly connected interfaces configured into the
-system and marked "up".
-It adds necessary routes for the interfaces
-to the kernel routing table.
-Soon after being first started, and provided there is at least one
-interface on which RIP has not been disabled,
-.Nm
-deletes all pre-existing
-non-static routes in kernel table.
-Static routes in the kernel table are preserved and
-included in RIP responses if they have a valid RIP metric
-(see
-.Xr route 8 ).
-.Pp
-If more than one interface is present (not counting the loopback interface),
-it is assumed that the host should forward packets among the
-connected networks.
-After transmitting a RIP
-.Em request
-and
-Router Discovery Advertisements or Solicitations on a new interface,
-the daemon enters a loop, listening for
-RIP request and response and Router Discover packets from other hosts.
-.Pp
-When a
-.Em request
-packet is received,
-.Nm
-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").
-Advertised metrics reflect the metric associated with interface
-(see
-.Xr ifconfig 8 ),
-so setting the metric on an interface
-is an effective way to steer traffic.
-.Pp
-Responses do not contain routes with a first hop on the requesting
-network to implement in part
-.Em split-horizon .
-Requests from query programs
-such as
-.Xr rtquery 8
-are answered with the complete table.
-.Pp
-The routing table maintained by the daemon
-includes space for several gateways for each destination
-to speed recovery from a failing router.
-RIP
-.Em response
-packets received are used to update the routing tables provided they are
-from one of the several currently recognized gateways or
-advertise a better metric than at least one of the existing
-gateways.
-.Pp
-When an update is applied,
-.Nm
-records the change in its own tables and updates the kernel routing table
-if the best route to the destination changes.
-The change in the kernel routing tableis reflected in the next batch of
-.Em response
-packets sent.
-If the next response is not scheduled for a while, a
-.Em flash update
-response containing only recently changed routes is sent.
-.Pp
-In addition to processing incoming packets,
-.Nm
-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 until the route has been advertised with
-an infinite metric to insure the invalidation
-is propagated throughout the local internet.
-This is a form of
-.Em poison reverse .
-.Pp
-Routes in the kernel table that are added or changed as a result
-of ICMP Redirect messages are deleted after a while to minimize
-.Em black-holes .
-When a TCP connection suffers a timeout,
-the kernel tells
-.Nm routed ,
-which deletes all redirected routes
-through the gateway involved, advances the age of all RIP routes through
-the gateway to allow an alternate to be chosen, and advances of the
-age of any relevant Router Discovery Protocol default routes.
-.Pp
-Hosts acting as internetwork routers gratuitously supply their
-routing tables every 30 seconds to all directly connected hosts
-and networks.
-These RIP responses are sent to the broadcast address on nets that support
-broadcasting,
-to the destination address on point-to-point links, and to the router's
-own address on other networks.
-If RIPv2 is enabled, multicast packets are sent on interfaces that
-support multicasting.
-.Pp
-If no response is received on a remote interface, if there are errors
-while sending responses,
-or if there are more errors than input or output (see
-.Xr netstat 8 ),
-then the cable or some other part of the interface is assumed to be
-disconnected or broken, and routes are adjusted appropriately.
-.Pp
-The
-.Em Internet Router Discovery Protocol
-is handled similarly.
-When the daemon is supplying RIP routes, it also listens for
-Router Discovery Solicitations and sends Advertisements.
-When it is quiet and only listening to other RIP routers, it
-sends Solicitations and listens for Advertisements.
-If it receives
-a good Advertisement, it stops listening for broadcast or multicast
-RIP responses.
-It tracks several advertising routers to speed recovery when the
-currently chosen router dies.
-If all discovered routers disappear,
-the daemon resumes listening to RIP responses.
-.Pp
-While using Router Discovery (which happens by default when
-the system has a single network interface and a Router Discover Advertisement
-is received), there is a single default route and a variable number of
-redirected host routes in the kernel table.
-.Pp
-The Router Discover standard requires that advertisements
-have a default "lifetime" of 30 minutes. That means should
-something happen, a client can be without a good route for
-30 minutes. It is a good idea to reduce the default to 45
-seconds using
-.Fl P Cm rdisc_interval=45
-on the command line or
-.Cm rdisc_interval=45
-in the
-.Pa /etc/gateways
-file.
-.Pp
-While using Router Discovery (which happens by default when
-the system has a single network interface and a Router Discover Advertisement
-is received), there is a single default route and a variable number of
-redirected host routes in the kernel table.
-.Pp
-See the
-.Cm pm_rdisc
-facility described below to support "legacy" systems
-that can handle neither RIPv2 nor Router Discovery.
-.Pp
-By default, neither Router Discovery advertisements nor solicications
-are sent over point to point links (e.g. PPP).
-
-.Pp
-Options supported by
-.Nm routed :
-.Bl -tag -width Ds
-.It Fl s
-this option forces
-.Nm
-to supply routing information.
-This is the default if multiple network interfaces are present on which
-RIP or Router Discovery have not been disabled, and if the kernel switch
-ipforwarding=1.
-.It Fl q
-is the opposite of the
-.Fl s
-option.
-.It Fl d
-Do not run in the background.
-This option is meant for interactive use.
-.It Fl g
-This flag is used on internetwork routers to offer a route
-to the "default" destination.
-It is equivalent to
-.Fl F
-.Cm 0/0,1
-and is present mostly for historical reasons.
-A better choice is
-.Fl P Cm pm_rdisc
-on the command line or
-.CM pm_rdisc in the
-.Pa /etc/gateways
-file.
-since a larger metric
-will be used, reducing the spread of the potentially dangerous
-default route.
-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.
-Notice that because a metric of 1 is used, this feature is
-dangerous. It is more commonly accidently used to create chaos with routing
-loop than to solve problems.
-.It Fl h
-This causes host or point-to-point routes to not be advertised,
-provided there is a network route going the same direction.
-That is a limited kind of aggregation.
-This option is useful on gateways to ethernets that have other gateway
-machines connected with point-to-point links such as SLIP.
-.It Fl m
-This causes the machine to advertise a host or point-to-point route to
-its primary interface.
-It is useful on multi-homed machines such as NFS servers.
-This option should not be used except when the cost of
-the host routes it generates is justified by the popularity of
-the server.
-It is effective only when the machine is supplying
-routing information, because there is more than one interface.
-The
-.Fl m
-option overrides the
-.Fl q
-option to the limited extent of advertising the host route.
-.It Fl A
-do not ignore RIPv2 authentication if we do not care about RIPv2
-authentication.
-This option is required for conformance with RFC 1723.
-However, it makes no sense and breaks using RIP as a discovery protocol
-to ignore all RIPv2 packets that carry authentication when this machine
-does not care about authentication.
-.It Fl T Ar tracefile
-increases the debugging level to at least 1 and
-causes debugging information to be appended to the trace file.
-.It Fl t
-increases the debugging level, which causes more information to be logged
-on the tracefile specified with
-.Fl T
-or standard out.
-The debugging level can be increased or decreased
-with the
-.Em SIGUSR1
-or
-.Em SIGUSR2
-signals or with the
-.Cm rtquery
-command.
-.It Fl F Ar net[/mask][,metric]
-minimize routes in transmissions via interfaces with addresses that match
-.Em net/mask ,
-and synthesizes a default route to this machine with the
-.Em metric .
-The intent is to reduce RIP traffic on slow, point-to-point links
-such as PPP links by replacing many large UDP packets of RIP information
-with a single, small packet containing a "fake" default route.
-If
-.Em metric
-is absent, a value of 14 is assumed to limit
-the spread of the "fake" default route.
-
-This is a dangerous feature that when used carelessly can cause routing
-loops.
-Notice also that more than one interface can match the specified network
-number and mask.
-See also
-.Fl g .
-.It Fl P Ar parms
-is equivalent to adding the parameter
-line
-.Em parms
-to the
-.Pa /etc/gateways
-file.
-.El
-.Pp
-Any other argument supplied is interpreted as the name
-of a file in which the actions of
-.Nm
-should be logged.
-It is better to use
-.Fl T
-instead of
-appending the name of the trace file to the command.
-.Pp
-.Nm
-also supports the notion of
-"distant"
-.Em passive
-or
-.Em active
-gateways.
-When
-.Nm
-is started, it reads the file
-.Pa /etc/gateways
-to find such distant gateways which may not be located using
-only information from a routing socket, to discover if some
-of the local gateways are
-.Em passive ,
-and to obtain other parameters.
-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 RIP packets.
-Routes through
-.Em passive
-gateways are installed in the
-kernel's routing tables once upon startup and are not included in
-transmitted RIP responses.
-.Pp
-Distant active gateways are treated like network interfaces.
-RIP responses are sent
-to the distant
-.Em active
-gateway.
-If no responses are received, the associated route is deleted from
-the kernel table and RIP responses advertised via other interfaces.
-If the distant gateway resumes sending RIP responses, the associated
-route is restored.
-.Pp
-Such gateways can be useful on media that do not support broadcasts
-or multicasts but otherwise act like classic shared media like
-Ethernets such as some ATM networks.
-One can list all RIP routers reachable on the ATM network in
-.Pa /etc/gateways
-with a series of
-"host" lines.
-.Pp
-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 indicate
-that another routing process
-will install such a route if ncessary,
-and that alternate routes to that destination should not be installed
-by
-.Nm routed .
-Such entries are only required when both routers may learn of routes
-to the same destination.
-.Pp
-The
-.Em /etc/gateways
-file is comprised of a series of lines, each in
-one of the following formats or consist of parameters described below:
-.Pp
-.Bd -ragged
-.Cm net
-.Ar Nname[/mask]
-.Cm gateway
-.Ar Gname
-.Cm metric
-.Ar value
-.Pf < Cm passive No \&|
-.Cm active No \&|
-.Cm extern Ns >
-.Ed
-.Bd -ragged
-.Cm host
-.Ar Hname
-.Cm gateway
-.Ar Gname
-.Cm metric
-.Ar value
-.Pf < Cm passive No \&|
-.Cm active No \&|
-.Cm extern Ns >
-.Ed
-.Pp
-.Ar Nname
-or
-.Ar Hname
-is the name of the destination network or host.
-It may be a symbolic network name or an Internet address
-specified in "dot" notation (see
-.Xr inet 3 ).
-(If it is a name, then it must either be defined in
-.Pa /etc/networks
-or
-.Pa /etc/hosts ,
-or
-.Xr named 8 ,
-must have been started before
-.Xr routed Ns .)
-.Pp
-.Ar mask
-is an optional number between 1 and 32 indicating the netmask associated
-with
-.Ar Nname .
-.Pp
-.Ar Gname
-is the name or address of the gateway to which RIP responses should
-be forwarded.
-.Pp
-.Ar Value
-is the hop count to the destination host or network.
-.Ar " host hname "
-is equivalent to
-.Ar " net nname/32 ".
-.Pp
-One of the keywords
-.Cm passive ,
-.Cm active
-or
-.Cm external
-must be present to indicate whether the gateway should be treated as
-.Cm passive
-or
-.Cm active
-(as described above),
-or whether the gateway is
-.Cm external
-to the scope of the RIP protocol.
-.Pp
-Lines that start with neither "net" nor "host" must consist of one
-or more of the following parameter settings, separated by commas or
-blanks:
-.Bl -tag -width Ds
-.It Cm if Ns \&= Ns Ar ifname
-indicates that the other parameters on the line apply to the interface
-name
-.Ar ifname .
-.It Cm subnet Ns \&= Ns Ar nname[/mask][,metric]
-advertises a route to network
-.AR nname
-with mask
-.AR mask
-and the supplied metric (default 1).
-This is useful for filling "holes" in CIDR allocations.
-This parameter must appear by itself on a line.
-.Pp
-Do not use this feature unless necessary. It is dangerous.
-.It Cm passwd Ns \&= Ns Ar XXX
-specifies a RIPv2 password that will be included on all RIPv2
-responses sent and checked on all RIPv2 responses received.
-The password must not contain any blanks, tab characters, commas
-or '#' characters.
-.It Cm no_ag
-turns off aggregation of subnets in RIPv1 and RIPv2 responses.
-.It Cm no_super_ag
-turns off aggregation of networks into supernets in RIPv2 responses.
-.It Cm passive
-is equivalent
-.Cm no_rip Cm no_rdisc .
-.It Cm no_rip
-disables all RIP processing on the specified interface.
-If no interfaces are allowed to process RIP packets,
-.Nm
-acts purely as a router discovery daemon.
-.Cm No_rip
-is equivalent to
-.Cm no_ripv1_in no_ripv2_in no_ripv1_out no_ripv2_out .
-
-Note that turning off RIP without explicitly turning on router
-discovery advertisements with
-.Cm rdisc_adv
-or
-.Fl s
-causes
-.Nm routed
-to act as a client router discovery daemon, not adveritising.
-.It Cm no_ripv1_in
-causes RIPv1 received responses to be ignored.
-.It Cm no_ripv2_in
-causes RIPv2 received responses to be ignored.
-.It Cm ripv2_out
-turns off RIPv1 output and causes RIPv2 advertisements to be
-multicast when possible.
-.It Cm no_rdisc
-disables the Internet Router Discovery Protocol.
-.It Cm no_solicit
-disables the tranmission of Router Discovery Solicitations.
-.It Cm send_solicit
-specifies that Router Discovery solicitations should be sent,
-even on point-to-point links,
-which by default only listen to Router Discovery messages.
-.It Cm no_rdisc_adv
-disables the transmission of Router Discovery Advertisements
-.It Cm rdisc_adv
-specifies that Router Discovery advertisements should be sent,
-even on point-to-point links,
-which by default only listen to Router Discovery messages
-.It Cm bcast_rdisc
-specifies that Router Discovery packets should be broadcast instead of
-multicast.
-.It Cm rdisc_pref Ns \&= Ns Ar N
-sets the preference in Router Discovery Advertisements to the integer
-.Ar N .
-.It Cm rdisc_interval Ns \&= Ns Ar N
-sets the nominal interval with which Router Discovery Advertisements
-are transmitted to N seconds and their lifetime to 3*N.
-.It Cm fake_default Ns \&= Ns Ar metric
-has an identical effect to
-.Fl F Ar net[/mask][,metric]
-with the network and mask coming from the sepcified interface.
-.It Cm pm_rdisc
-is similar to
-.Cm fake_default .
-When RIPv2 routes are multicast, so that RIPv1 listeners cannot
-receive them, this feature causes a RIPv1 default route to be
-broadcast to RIPv1 listeners.
-Unless modified with
-.Cm fake_default ,
-the default route is broadcast with a metric of 14.
-That serves as a "poor man's router discovery" protocol.
-.El
-.Pp
-Note that the netmask associated with point-to-point links (such as SLIP
-or PPP, with the IFF_POINTOPOINT flag) is used by
-.Nm routed
-to infer the netmask used by the remote system when RIPv1 is used.
-.Pp
-.Sh FILES
-.Bl -tag -width /etc/gateways -compact
-.It Pa /etc/gateways
-for distant gateways
-.El
-.Sh SEE ALSO
-.Xr gated 8 ,
-.Xr udp 4 ,
-.Xr icmp 4 ,
-.Xr htable 8 ,
-.Xr rtquery 8 .
-.Rs
-.%T Internet Transport Protocols
-.%R XSIS 028112
-.%Q Xerox System Integration Standard
-.Re
-.Sh BUGS
-It does not always detect unidirectional failures in network interfaces
-(e.g., when the output side fails).
-.Sh HISTORY
-The
-.Nm
-command appeared in
-.Bx 4.2 .
diff --git a/usr.sbin/routed/rtquery/Makefile b/usr.sbin/routed/rtquery/Makefile
deleted file mode 100644
index e748e73..0000000
--- a/usr.sbin/routed/rtquery/Makefile
+++ /dev/null
@@ -1,8 +0,0 @@
-# From: @(#)Makefile 8.1 (Berkeley) 6/5/93
-# $Id$
-
-PROG= rtquery
-MAN8= rtquery.8
-#COPTS= -g -DDEBUG -Wall
-
-.include <bsd.prog.mk>
diff --git a/usr.sbin/routed/rtquery/rtquery.8 b/usr.sbin/routed/rtquery/rtquery.8
deleted file mode 100644
index 3c59efd..0000000
--- a/usr.sbin/routed/rtquery/rtquery.8
+++ /dev/null
@@ -1,79 +0,0 @@
-.Dd April 9, 1996
-.Dt RTQUERY 8
-.Os BSD 4.4
-.Sh NAME
-.Nm rtquery
-.Nd query routing daemons for their routing tables
-.Sh SYNOPSIS
-.Nm
-.Op Fl np1
-.Op Fl 1 Ar timeout
-.Op Fl r Ar addr
-.Ar host ...
-.Sh DESCRIPTION
-.Nm Rtquery
-is used to query a network routing daemon,
-.Xr routed 8
-or
-.Xr gated 8 ,
-for its routing table by sending a
-.Em request
-or
-.Em poll
-command. The routing information in any routing
-.Em response
-packets returned is displayed numerically and symbolically.
-.Pp
-.Em Rtquery
-by default uses the
-.Em request
-command.
-When the
-.B \-p
-option is specified,
-.Nm rtquery
-uses the
-.Em poll
-command, which is an
-undocumented extension to the RIP specification supported by
-.IR gated (1M).
-When querying
-.IR gated (1M),
-the
-.I poll
-command is preferred over the
-.I request
-command because the response is not subject to Split Horizon and/or
-Poisioned Reverse.
-.Pp
-Options supported by
-.Nm rtquery :
-.Bl -tag -width Ds
-.It Fl n
-Normally network and host numbers are displayed both symbolically
-and numerically.
-The
-.Fl n
-option displays only the numeric network and host numbers.
-.It Fl p
-Uses the
-.Em poll
-command to request full routing information from
-.Xr gated 8 ,
-This is an undocumented extension supported only by
-.Xr gated 8 .
-.It Fl 1
-query using RIP version 1 instead of RIP version 2.
-.It Fl w Ar timeout
-changes the delay for an answer from each host.
-By default, each host is given 15 seconds to respond.
-.It Fl r Ar addr
-ask about the route to destination
-.Em parms
-.Sh SEE ALSO
-.Xr routed 8,
-.Xr gated 8,
-.br
-RFC\ 1058 - Routing Information Protocol, RIPv1
-.br
-RFC\ 1723 - Routing Information Protocol, RIPv2
diff --git a/usr.sbin/routed/rtquery/rtquery.c b/usr.sbin/routed/rtquery/rtquery.c
deleted file mode 100644
index 97899c9..0000000
--- a/usr.sbin/routed/rtquery/rtquery.c
+++ /dev/null
@@ -1,516 +0,0 @@
-/*-
- * Copyright (c) 1982, 1986, 1993
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#ifndef lint
-static char copyright[] =
-"@(#) Copyright (c) 1982, 1986, 1993\n\
- The Regents of the University of California. All rights reserved.\n";
-#endif /* not lint */
-
-#ifndef lint
-static char sccsid[] = "@(#)query.c 8.1 (Berkeley) 6/5/93";
-#endif /* not lint */
-
-#include <sys/param.h>
-#include <sys/protosw.h>
-#include <sys/socket.h>
-#include <sys/time.h>
-#include <netinet/in.h>
-#define RIPVERSION RIPv2
-#include <protocols/routed.h>
-#include <arpa/inet.h>
-#include <netdb.h>
-#include <errno.h>
-#include <unistd.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#ifdef sgi
-#include <strings.h>
-#include <bstring.h>
-#endif
-
-#ifndef sgi
-#define _HAVE_SIN_LEN
-#endif
-
-#define WTIME 15 /* Time to wait for all responses */
-#define STIME (250*1000) /* usec to wait for another response */
-
-int s;
-
-char *pgmname;
-
-union pkt_buf {
- char packet[MAXPACKETSIZE+4096];
- struct rip rip;
-} msg_buf;
-#define MSG msg_buf.rip
-#define MSG_LIM ((struct rip*)(&msg_buf.packet[MAXPACKETSIZE \
- - sizeof(struct netinfo)]))
-
-int nflag; /* numbers, no names */
-int pflag; /* play the `gated` game */
-int ripv2 = 1; /* use RIP version 2 */
-int wtime = WTIME;
-int rflag; /* 1=ask about a particular route */
-
-struct timeval start; /* when query sent */
-
-static void rip_input(struct sockaddr_in*, int);
-static int query(char *, struct netinfo *);
-static int getnet(char *, struct netinfo *);
-static u_int std_mask(u_int);
-
-
-int
-main(int argc,
- char *argv[])
-{
- char *p;
- struct seen {
- struct seen *next;
- struct in_addr addr;
- } *seen, *sp;
- int answered = 0;
- int ch, cc, bsize;
- fd_set bits;
- struct timeval now, delay;
- struct sockaddr_in from;
- int fromlen;
- struct netinfo rt;
-
-
- bzero(&rt, sizeof(rt));
-
- pgmname = argv[0];
- while ((ch = getopt(argc, argv, "np1w:r:")) != EOF)
- switch (ch) {
- case 'n':
- nflag = 1;
- break;
- case 'p':
- pflag = 1;
- break;
- case '1':
- ripv2 = 0;
- break;
- case 'w':
- wtime = (int)strtoul(optarg, &p, 0);
- if (*p != '\0'
- || wtime <= 0)
- goto usage;
- break;
- case 'r':
- if (rflag)
- goto usage;
- rflag = getnet(optarg, &rt);
- break;
- case '?':
- default:
- goto usage;
- }
- argv += optind;
- argc -= optind;
- if (argc == 0) {
-usage: printf("usage: query [-np1v] [-w wtime] host1 [host2 ...]\n");
- exit(1);
- }
-
- if (!rflag) {
- rt.n_dst = RIP_DEFAULT;
- rt.n_family = RIP_AF_UNSPEC;
- rt.n_metric = htonl(HOPCNT_INFINITY);
- }
-
- s = socket(AF_INET, SOCK_DGRAM, 0);
- if (s < 0) {
- perror("socket");
- exit(2);
- }
- for (bsize = 127*1024; ; bsize -= 1024) {
- if (setsockopt(s, SOL_SOCKET, SO_RCVBUF,
- &bsize, sizeof(bsize)) == 0)
- break;
- if (bsize <= 4*1024) {
- perror("setsockopt SO_RCVBUF");
- break;
- }
- }
-
- /* ask the first host */
- seen = 0;
- while (0 > query(*argv++, &rt) && *argv != 0)
- answered++;
-
- FD_ZERO(&bits);
- for (;;) {
- FD_SET(s, &bits);
- delay.tv_sec = 0;
- delay.tv_usec = STIME;
- cc = select(s+1, &bits, 0,0, &delay);
- if (cc > 0) {
- fromlen = sizeof(from);
- cc = recvfrom(s, msg_buf.packet,
- sizeof(msg_buf.packet), 0,
- (struct sockaddr *)&from, &fromlen);
- if (cc < 0) {
- perror("recvfrom");
- exit(1);
- }
- /* count the distinct responding hosts.
- * You cannot match responding hosts with
- * addresses to which queries were transmitted,
- * because a router might respond with a
- * different source address.
- */
- for (sp = seen; sp != 0; sp = sp->next) {
- if (sp->addr.s_addr == from.sin_addr.s_addr)
- break;
- }
- if (sp == 0) {
- sp = malloc(sizeof(*sp));
- sp->addr = from.sin_addr;
- sp->next = seen;
- seen = sp;
- answered++;
- }
-
- rip_input(&from, cc);
- continue;
- }
-
- if (cc < 0) {
- if ( errno == EINTR)
- continue;
- perror("select");
- exit(1);
- }
-
- /* After a pause in responses, probe another host.
- * This reduces the intermingling of answers.
- */
- while (*argv != 0 && 0 > query(*argv++, &rt))
- answered++;
-
- /* continue until no more packets arrive
- * or we have heard from all hosts
- */
- if (answered >= argc)
- break;
-
- /* or until we have waited a long time
- */
- if (gettimeofday(&now, 0) < 0) {
- perror("gettimeofday(now)");
- exit(1);
- }
- if (start.tv_sec + wtime <= now.tv_sec)
- break;
- }
-
- /* fail if there was no answer */
- exit (answered >= argc ? 0 : 1);
- /* NOTREACHED */
-}
-
-
-/*
- * Poll one host.
- */
-static int
-query(char *host,
- struct netinfo *rt)
-{
- struct sockaddr_in router;
- struct hostent *hp;
-
- if (gettimeofday(&start, 0) < 0) {
- perror("gettimeofday(start)");
- return -1;
- }
-
- bzero(&router, sizeof(router));
- router.sin_family = AF_INET;
-#ifdef _HAVE_SIN_LEN
- router.sin_len = sizeof(router);
-#endif
- router.sin_addr.s_addr = inet_addr(host);
- if (router.sin_addr.s_addr == -1) {
- hp = gethostbyname(host);
- if (hp == 0) {
- fprintf(stderr,"%s: %s:", pgmname, host);
- herror(0);
- return -1;
- }
- bcopy(hp->h_addr, &router.sin_addr, hp->h_length);
- }
-
- router.sin_port = htons(RIP_PORT);
-
- MSG.rip_cmd = (pflag)? RIPCMD_POLL : RIPCMD_REQUEST;
- MSG.rip_nets[0] = *rt;
- if (ripv2) {
- MSG.rip_vers = RIPv2;
- } else {
- MSG.rip_vers = RIPv1;
- MSG.rip_nets[0].n_mask = 0;
- }
-
- if (sendto(s, msg_buf.packet, sizeof(struct rip), 0,
- (struct sockaddr *)&router, sizeof(router)) < 0) {
- perror(host);
- return -1;
- }
-
- return 0;
-}
-
-
-/*
- * Handle an incoming RIP packet.
- */
-static void
-rip_input(struct sockaddr_in *from,
- int size)
-{
- struct netinfo *n, *lim;
- struct in_addr in;
- char *name;
- char net_buf[80];
- u_int mask, dmask;
- char *sp;
- int i;
- struct hostent *hp;
- struct netent *np;
- struct netauth *a;
-
-
- if (nflag) {
- printf("%s:", inet_ntoa(from->sin_addr));
- } else {
- hp = gethostbyaddr((char*)&from->sin_addr,
- sizeof(struct in_addr), AF_INET);
- if (hp == 0) {
- printf("%s:",
- inet_ntoa(from->sin_addr));
- } else {
- printf("%s (%s):", hp->h_name,
- inet_ntoa(from->sin_addr));
- }
- }
- if (MSG.rip_cmd != RIPCMD_RESPONSE) {
- printf("\n unexpected response type %d\n", MSG.rip_cmd);
- return;
- }
- printf(" RIPv%d%s %d bytes\n", MSG.rip_vers,
- (MSG.rip_vers != RIPv1 && MSG.rip_vers != RIPv2) ? " ?" : "",
- size);
- if (size > MAXPACKETSIZE) {
- if (size > sizeof(msg_buf) - sizeof(*n)) {
- printf(" at least %d bytes too long\n",
- size-MAXPACKETSIZE);
- size = sizeof(msg_buf) - sizeof(*n);
- } else {
- printf(" %d bytes too long\n",
- size-MAXPACKETSIZE);
- }
- } else if (size%sizeof(*n) != sizeof(struct rip)%sizeof(*n)) {
- printf(" response of bad length=%d\n", size);
- }
-
- n = MSG.rip_nets;
- lim = (struct netinfo *)((char*)n + size) - 1;
- for (; n <= lim; n++) {
- name = "";
- if (n->n_family == RIP_AF_INET) {
- in.s_addr = n->n_dst;
- (void)strcpy(net_buf, inet_ntoa(in));
-
- mask = ntohl(n->n_mask);
- dmask = mask & -mask;
- if (mask != 0) {
- sp = &net_buf[strlen(net_buf)];
- if (MSG.rip_vers == RIPv1) {
- (void)sprintf(sp," mask=%#x ? ",mask);
- mask = 0;
- } else if (mask + dmask == 0) {
- for (i = 0;
- (i != 32
- && ((1<<i)&mask) == 0);
- i++)
- continue;
- (void)sprintf(sp, "/%d",32-i);
- } else {
- (void)sprintf(sp," (mask %#x)", mask);
- }
- }
-
- if (!nflag) {
- if (mask == 0) {
- mask = std_mask(in.s_addr);
- if ((ntohl(in.s_addr) & ~mask) != 0)
- mask = 0;
- }
- /* Without a netmask, do not worry about
- * whether the destination is a host or a
- * network. Try both and use the first name
- * we get.
- *
- * If we have a netmask we can make a
- * good guess.
- */
- if ((in.s_addr & ~mask) == 0) {
- np = getnetbyaddr(in.s_addr, AF_INET);
- if (np != 0)
- name = np->n_name;
- else if (in.s_addr == 0)
- name = "default";
- }
- if (name[0] == '\0'
- && (in.s_addr & ~mask) != 0) {
- hp = gethostbyaddr((char*)&in,
- sizeof(in),
- AF_INET);
- if (hp != 0)
- name = hp->h_name;
- }
- }
-
- } else if (n->n_family == RIP_AF_AUTH) {
- a = (struct netauth*)n;
- (void)printf(" authentication type %d: ",
- a->a_type);
- for (i = 0; i < sizeof(a->au.au_pw); i++)
- (void)printf("%02x ", a->au.au_pw[i]);
- putc('\n', stdout);
- continue;
-
- } else {
- (void)sprintf(net_buf, "(af %#x) %d.%d.%d.%d",
- n->n_family,
- (char)(n->n_dst >> 24),
- (char)(n->n_dst >> 16),
- (char)(n->n_dst >> 8),
- (char)n->n_dst);
- }
-
- (void)printf(" %-18s metric %2d %8s",
- net_buf, ntohl(n->n_metric), name);
-
- if (n->n_nhop != 0) {
- in.s_addr = n->n_nhop;
- if (nflag)
- hp = 0;
- else
- hp = gethostbyaddr((char*)&in, sizeof(in),
- AF_INET);
- (void)printf(" nhop=%-15s%s",
- (hp != 0) ? hp->h_name : inet_ntoa(in),
- (MSG.rip_vers == RIPv1) ? " ?" : "");
- }
- if (n->n_tag != 0)
- (void)printf(" tag=%#x%s", n->n_tag,
- (MSG.rip_vers == RIPv1) ? " ?" : "");
- putc('\n', stdout);
- }
-}
-
-
-/* Return the classical netmask for an IP address.
- */
-static u_int
-std_mask(u_int addr)
-{
- NTOHL(addr);
-
- if (addr == 0)
- return 0;
- if (IN_CLASSA(addr))
- return IN_CLASSA_NET;
- if (IN_CLASSB(addr))
- return IN_CLASSB_NET;
- return IN_CLASSC_NET;
-}
-
-
-/* get a network number as a name or a number, with an optional "/xx"
- * netmask.
- */
-static int /* 0=bad */
-getnet(char *name,
- struct netinfo *rt)
-{
- int i;
- struct netent *nentp;
- u_int mask;
- struct in_addr in;
- char hname[MAXHOSTNAMELEN+1];
- char *mname, *p;
-
-
- /* Detect and separate "1.2.3.4/24"
- */
- if (0 != (mname = rindex(name,'/'))) {
- i = (int)(mname - name);
- if (i > sizeof(hname)-1) /* name too long */
- return 0;
- bcopy(name, hname, i);
- hname[i] = '\0';
- mname++;
- name = hname;
- }
-
- nentp = getnetbyname(name);
- if (nentp != 0) {
- in.s_addr = nentp->n_net;
- } else if (inet_aton(name, &in) == 1) {
- NTOHL(in.s_addr);
- } else {
- return 0;
- }
-
- if (mname == 0) {
- mask = std_mask(in.s_addr);
- } else {
- mask = (u_int)strtoul(mname, &p, 0);
- if (*p != '\0' || mask > 32)
- return 0;
- mask = 0xffffffff << (32-mask);
- }
-
- rt->n_dst = in.s_addr;
- rt->n_family = AF_INET;
- rt->n_mask = htonl(mask);
- return 1;
-}
diff --git a/usr.sbin/routed/table.c b/usr.sbin/routed/table.c
deleted file mode 100644
index aa7510c..0000000
--- a/usr.sbin/routed/table.c
+++ /dev/null
@@ -1,1961 +0,0 @@
-/*
- * Copyright (c) 1983, 1988, 1993
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#if !defined(lint) && !defined(sgi) && !defined(__NetBSD__)
-static char sccsid[] = "@(#)tables.c 8.1 (Berkeley) 6/5/93";
-#elif defined(__NetBSD__)
-static char rcsid[] = "$NetBSD$";
-#endif
-#ident "$Revision: 1.1.3.3 $"
-
-#include "defs.h"
-
-static struct rt_spare *rts_better(struct rt_entry *);
-
-struct radix_node_head *rhead; /* root of the radix tree */
-
-int need_flash = 1; /* flash update needed
- * start =1 to suppress the 1st
- */
-
-struct timeval age_timer; /* next check of old routes */
-struct timeval need_kern = { /* need to update kernel table */
- EPOCH+MIN_WAITTIME-1
-};
-
-int stopint;
-
-int total_routes;
-
-naddr age_bad_gate;
-
-
-/* It is desirable to "aggregate" routes, to combine differing routes of
- * the same metric and next hop into a common route with a smaller netmask
- * or to suppress redundant routes, routes that add no information to
- * routes with smaller netmasks.
- *
- * A route is redundant if and only if any and all routes with smaller
- * but matching netmasks and nets are the same. Since routes are
- * kept sorted in the radix tree, redundant routes always come second.
- *
- * There are two kinds of aggregations. First, two routes of the same bit
- * mask and differing only in the least significant bit of the network
- * number can be combined into a single route with a coarser mask.
- *
- * Second, a route can be suppressed in favor of another route with a more
- * coarse mask provided no incompatible routes with intermediate masks
- * are present. The second kind of aggregation involves suppressing routes.
- * A route must not be suppressed if an incompatible route exists with
- * an intermediate mask, since the suppressed route would be covered
- * by the intermediate.
- *
- * This code relies on the radix tree walk encountering routes
- * sorted first by address, with the smallest address first.
- */
-
-struct ag_info ag_slots[NUM_AG_SLOTS], *ag_avail, *ag_corsest, *ag_finest;
-
-/* #define DEBUG_AG */
-#ifdef DEBUG_AG
-#define CHECK_AG() {int acnt = 0; struct ag_info *cag; \
- for (cag = ag_avail; cag != 0; cag = cag->ag_fine) \
- acnt++; \
- for (cag = ag_corsest; cag != 0; cag = cag->ag_fine) \
- acnt++; \
- if (acnt != NUM_AG_SLOTS) { \
- (void)fflush(stderr); \
- abort(); \
- } \
-}
-#else
-#define CHECK_AG()
-#endif
-
-
-/* Output the contents of an aggregation table slot.
- * This function must always be immediately followed with the deletion
- * of the target slot.
- */
-static void
-ag_out(struct ag_info *ag,
- void (*out)(struct ag_info *))
-{
- struct ag_info *ag_cors;
- naddr bit;
-
-
- /* If we output both the even and odd twins, then the immediate parent,
- * if it is present, is redundant, unless the parent manages to
- * aggregate into something coarser.
- * On successive calls, this code detects the even and odd twins,
- * and marks the parent.
- *
- * Note that the order in which the radix tree code emits routes
- * ensures that the twins are seen before the parent is emitted.
- */
- ag_cors = ag->ag_cors;
- if (ag_cors != 0
- && ag_cors->ag_mask == ag->ag_mask<<1
- && ag_cors->ag_dst_h == (ag->ag_dst_h & ag_cors->ag_mask)) {
- ag_cors->ag_state |= ((ag_cors->ag_dst_h == ag->ag_dst_h)
- ? AGS_REDUN0
- : AGS_REDUN1);
- }
-
- /* Skip it if this route is itself redundant.
- *
- * It is ok to change the contents of the slot here, since it is
- * always deleted next.
- */
- if (ag->ag_state & AGS_REDUN0) {
- if (ag->ag_state & AGS_REDUN1)
- return;
- bit = (-ag->ag_mask) >> 1;
- ag->ag_dst_h |= bit;
- ag->ag_mask |= bit;
-
- } else if (ag->ag_state & AGS_REDUN1) {
- bit = (-ag->ag_mask) >> 1;
- ag->ag_mask |= bit;
- }
- out(ag);
-}
-
-
-static void
-ag_del(struct ag_info *ag)
-{
- CHECK_AG();
-
- if (ag->ag_cors == 0)
- ag_corsest = ag->ag_fine;
- else
- ag->ag_cors->ag_fine = ag->ag_fine;
-
- if (ag->ag_fine == 0)
- ag_finest = ag->ag_cors;
- else
- ag->ag_fine->ag_cors = ag->ag_cors;
-
- ag->ag_fine = ag_avail;
- ag_avail = ag;
-
- CHECK_AG();
-}
-
-
-/* Flush routes waiting for aggretation.
- * This must not suppress a route unless it is known that among all
- * routes with coarser masks that match it, the one with the longest
- * mask is appropriate. This is ensured by scanning the routes
- * in lexical order, and with the most restritive mask first
- * among routes to the same destination.
- */
-void
-ag_flush(naddr lim_dst_h, /* flush routes to here */
- naddr lim_mask, /* matching this mask */
- void (*out)(struct ag_info *))
-{
- struct ag_info *ag, *ag_cors;
- naddr dst_h;
-
-
- for (ag = ag_finest;
- ag != 0 && ag->ag_mask >= lim_mask;
- ag = ag_cors) {
- ag_cors = ag->ag_cors;
-
- /* work on only the specified routes */
- dst_h = ag->ag_dst_h;
- if ((dst_h & lim_mask) != lim_dst_h)
- continue;
-
- if (!(ag->ag_state & AGS_SUPPRESS))
- ag_out(ag, out);
-
- else for ( ; ; ag_cors = ag_cors->ag_cors) {
- /* Look for a route that can suppress the
- * current route */
- if (ag_cors == 0) {
- /* failed, so output it and look for
- * another route to work on
- */
- ag_out(ag, out);
- break;
- }
-
- if ((dst_h & ag_cors->ag_mask) == ag_cors->ag_dst_h) {
- /* We found a route with a coarser mask that
- * aggregates the current target.
- *
- * If it has a different next hop, it
- * cannot replace the target, so output
- * the target.
- */
- if (ag->ag_gate != ag_cors->ag_gate
- && !(ag->ag_state & AGS_FINE_GATE)
- && !(ag_cors->ag_state & AGS_CORS_GATE)) {
- ag_out(ag, out);
- break;
- }
-
- /* If the coarse route has a good enough
- * metric, it suppresses the target.
- */
- if (ag_cors->ag_pref <= ag->ag_pref) {
- if (ag_cors->ag_seqno > ag->ag_seqno)
- ag_cors->ag_seqno = ag->ag_seqno;
- if (AG_IS_REDUN(ag->ag_state)
- && ag_cors->ag_mask==ag->ag_mask<<1) {
- if (ag_cors->ag_dst_h == dst_h)
- ag_cors->ag_state |= AGS_REDUN0;
- else
- ag_cors->ag_state |= AGS_REDUN1;
- }
- if (ag->ag_tag != ag_cors->ag_tag)
- ag_cors->ag_tag = 0;
- if (ag->ag_nhop != ag_cors->ag_nhop)
- ag_cors->ag_nhop = 0;
- break;
- }
- }
- }
-
- /* That route has either been output or suppressed */
- ag_cors = ag->ag_cors;
- ag_del(ag);
- }
-
- CHECK_AG();
-}
-
-
-/* Try to aggregate a route with previous routes.
- */
-void
-ag_check(naddr dst,
- naddr mask,
- naddr gate,
- naddr nhop,
- char metric,
- char pref,
- u_int seqno,
- u_short tag,
- u_short state,
- void (*out)(struct ag_info *)) /* output using this */
-{
- struct ag_info *ag, *nag, *ag_cors;
- naddr xaddr;
- int x;
-
- NTOHL(dst);
-
- /* Punt non-contiguous subnet masks.
- *
- * (X & -X) contains a single bit if and only if X is a power of 2.
- * (X + (X & -X)) == 0 if and only if X is a power of 2.
- */
- if ((mask & -mask) + mask != 0) {
- struct ag_info nc_ag;
-
- nc_ag.ag_dst_h = dst;
- nc_ag.ag_mask = mask;
- nc_ag.ag_gate = gate;
- nc_ag.ag_nhop = nhop;
- nc_ag.ag_metric = metric;
- nc_ag.ag_pref = pref;
- nc_ag.ag_tag = tag;
- nc_ag.ag_state = state;
- nc_ag.ag_seqno = seqno;
- out(&nc_ag);
- return;
- }
-
- /* Search for the right slot in the aggregation table.
- */
- ag_cors = 0;
- ag = ag_corsest;
- while (ag != 0) {
- if (ag->ag_mask >= mask)
- break;
-
- /* Suppress old routes (i.e. combine with compatible routes
- * with coarser masks) as we look for the right slot in the
- * aggregation table for the new route.
- * A route to an address less than the current destination
- * will not be affected by the current route or any route
- * seen hereafter. That means it is safe to suppress it.
- * This check keeps poor routes (eg. with large hop counts)
- * from preventing suppresion of finer routes.
- */
- if (ag_cors != 0
- && ag->ag_dst_h < dst
- && (ag->ag_state & AGS_SUPPRESS)
- && ag_cors->ag_pref <= ag->ag_pref
- && (ag->ag_dst_h & ag_cors->ag_mask) == ag_cors->ag_dst_h
- && (ag_cors->ag_gate == ag->ag_gate
- || (ag->ag_state & AGS_FINE_GATE)
- || (ag_cors->ag_state & AGS_CORS_GATE))) {
- if (ag_cors->ag_seqno > ag->ag_seqno)
- ag_cors->ag_seqno = ag->ag_seqno;
- if (AG_IS_REDUN(ag->ag_state)
- && ag_cors->ag_mask==ag->ag_mask<<1) {
- if (ag_cors->ag_dst_h == dst)
- ag_cors->ag_state |= AGS_REDUN0;
- else
- ag_cors->ag_state |= AGS_REDUN1;
- }
- if (ag->ag_tag != ag_cors->ag_tag)
- ag_cors->ag_tag = 0;
- if (ag->ag_nhop != ag_cors->ag_nhop)
- ag_cors->ag_nhop = 0;
- ag_del(ag);
- CHECK_AG();
- } else {
- ag_cors = ag;
- }
- ag = ag_cors->ag_fine;
- }
-
- /* If we find the even/odd twin of the new route, and if the
- * masks and so forth are equal, we can aggregate them.
- * We can probably promote one of the pair.
- *
- * Since the routes are encountered in lexical order,
- * the new route must be odd. However, the second or later
- * times around this loop, it could be the even twin promoted
- * from the even/odd pair of twins of the finer route.
- */
- while (ag != 0
- && ag->ag_mask == mask
- && ((ag->ag_dst_h ^ dst) & (mask<<1)) == 0) {
-
- /* Here we know the target route and the route in the current
- * slot have the same netmasks and differ by at most the
- * last bit. They are either for the same destination, or
- * for an even/odd pair of destinations.
- */
- if (ag->ag_dst_h == dst) {
- /* We have two routes to the same destination.
- * Routes are encountered in lexical order, so a
- * route is never promoted until the parent route is
- * already present. So we know that the new route is
- * a promoted pair and the route already in the slot
- * is the explicit route.
- *
- * Prefer the best route if their metrics differ,
- * or the promoted one if not, following a sort
- * of longest-match rule.
- */
- if (pref <= ag->ag_pref) {
- ag->ag_gate = gate;
- ag->ag_nhop = nhop;
- ag->ag_tag = tag;
- ag->ag_metric = metric;
- ag->ag_pref = pref;
- x = ag->ag_state;
- ag->ag_state = state;
- state = x;
- }
-
- /* The sequence number controls flash updating,
- * and should be the smaller of the two.
- */
- if (ag->ag_seqno > seqno)
- ag->ag_seqno = seqno;
-
- /* some bits are set if they are set on either route */
- ag->ag_state |= (state & (AGS_PROMOTE_EITHER
- | AGS_REDUN0 | AGS_REDUN1));
- return;
- }
-
- /* If one of the routes can be promoted and the other can
- * be suppressed, it may be possible to combine them or
- * worthwhile to promote one.
- *
- * Note that any route that can be promoted is always
- * marked to be eligible to be suppressed.
- */
- if (!((state & AGS_PROMOTE)
- && (ag->ag_state & AGS_SUPPRESS))
- && !((ag->ag_state & AGS_PROMOTE)
- && (state & AGS_SUPPRESS)))
- break;
-
- /* A pair of even/odd twin routes can be combined
- * if either is redundant, or if they are via the
- * same gateway and have the same metric.
- */
- if (AG_IS_REDUN(ag->ag_state)
- || AG_IS_REDUN(state)
- || (ag->ag_gate == gate
- && ag->ag_pref == pref
- && (state & ag->ag_state & AGS_PROMOTE) != 0)) {
-
- /* We have both the even and odd pairs.
- * Since the routes are encountered in order,
- * the route in the slot must be the even twin.
- *
- * Combine and promote the pair of routes.
- */
- if (seqno > ag->ag_seqno)
- seqno = ag->ag_seqno;
- if (!AG_IS_REDUN(state))
- state &= ~AGS_REDUN1;
- if (AG_IS_REDUN(ag->ag_state))
- state |= AGS_REDUN0;
- else
- state &= ~AGS_REDUN0;
- state |= (ag->ag_state & AGS_PROMOTE_EITHER);
- if (ag->ag_tag != tag)
- tag = 0;
- if (ag->ag_nhop != nhop)
- nhop = 0;
-
- /* Get rid of the even twin that was already
- * in the slot.
- */
- ag_del(ag);
-
- } else if (ag->ag_pref >= pref
- && (ag->ag_state & AGS_PROMOTE)) {
- /* If we cannot combine the pair, maybe the route
- * with the worse metric can be promoted.
- *
- * Promote the old, even twin, by giving its slot
- * in the table to the new, odd twin.
- */
- ag->ag_dst_h = dst;
-
- xaddr = ag->ag_gate;
- ag->ag_gate = gate;
- gate = xaddr;
-
- xaddr = ag->ag_nhop;
- ag->ag_nhop = nhop;
- nhop = xaddr;
-
- x = ag->ag_tag;
- ag->ag_tag = tag;
- tag = x;
-
- x = ag->ag_state;
- ag->ag_state = state;
- state = x;
- if (!AG_IS_REDUN(state))
- state &= ~AGS_REDUN0;
-
- x = ag->ag_metric;
- ag->ag_metric = metric;
- metric = x;
-
- x = ag->ag_pref;
- ag->ag_pref = pref;
- pref = x;
-
- if (seqno >= ag->ag_seqno)
- seqno = ag->ag_seqno;
- else
- ag->ag_seqno = seqno;
-
- } else {
- if (!(state & AGS_PROMOTE))
- break; /* cannot promote either twin */
-
- /* promote the new, odd twin by shaving its
- * mask and address.
- */
- if (seqno > ag->ag_seqno)
- seqno = ag->ag_seqno;
- else
- ag->ag_seqno = seqno;
- if (!AG_IS_REDUN(state))
- state &= ~AGS_REDUN1;
- }
-
- mask <<= 1;
- dst &= mask;
-
- if (ag_cors == 0) {
- ag = ag_corsest;
- break;
- }
- ag = ag_cors;
- ag_cors = ag->ag_cors;
- }
-
- /* When we can no longer promote and combine routes,
- * flush the old route in the target slot. Also flush
- * any finer routes that we know will never be aggregated by
- * the new route.
- *
- * In case we moved toward coarser masks,
- * get back where we belong
- */
- if (ag != 0
- && ag->ag_mask < mask) {
- ag_cors = ag;
- ag = ag->ag_fine;
- }
-
- /* Empty the target slot
- */
- if (ag != 0 && ag->ag_mask == mask) {
- ag_flush(ag->ag_dst_h, ag->ag_mask, out);
- ag = (ag_cors == 0) ? ag_corsest : ag_cors->ag_fine;
- }
-
-#ifdef DEBUG_AG
- (void)fflush(stderr);
- if (ag == 0 && ag_cors != ag_finest)
- abort();
- if (ag_cors == 0 && ag != ag_corsest)
- abort();
- if (ag != 0 && ag->ag_cors != ag_cors)
- abort();
- if (ag_cors != 0 && ag_cors->ag_fine != ag)
- abort();
- CHECK_AG();
-#endif
-
- /* Save the new route on the end of the table.
- */
- nag = ag_avail;
- ag_avail = nag->ag_fine;
-
- nag->ag_dst_h = dst;
- nag->ag_mask = mask;
- nag->ag_gate = gate;
- nag->ag_nhop = nhop;
- nag->ag_metric = metric;
- nag->ag_pref = pref;
- nag->ag_tag = tag;
- nag->ag_state = state;
- nag->ag_seqno = seqno;
-
- nag->ag_fine = ag;
- if (ag != 0)
- ag->ag_cors = nag;
- else
- ag_finest = nag;
- nag->ag_cors = ag_cors;
- if (ag_cors == 0)
- ag_corsest = nag;
- else
- ag_cors->ag_fine = nag;
- CHECK_AG();
-}
-
-
-static char *
-rtm_type_name(u_char type)
-{
- static char *rtm_types[] = {
- "RTM_ADD",
- "RTM_DELETE",
- "RTM_CHANGE",
- "RTM_GET",
- "RTM_LOSING",
- "RTM_REDIRECT",
- "RTM_MISS",
- "RTM_LOCK",
- "RTM_OLDADD",
- "RTM_OLDDEL",
- "RTM_RESOLVE",
- "RTM_NEWADDR",
- "RTM_DELADDR",
- "RTM_IFINFO"
- };
- static char name0[10];
-
-
- if (type > sizeof(rtm_types)/sizeof(rtm_types[0])
- || type == 0) {
- sprintf(name0, "RTM type %#x", type);
- return name0;
- } else {
- return rtm_types[type-1];
- }
-}
-
-
-/* Trim a mask in a sockaddr
- * Produce a length of 0 for an address of 0.
- * Otherwise produce the index of the first zero byte.
- */
-void
-#ifdef _HAVE_SIN_LEN
-masktrim(struct sockaddr_in *ap)
-#else
-masktrim(struct sockaddr_in_new *ap)
-#endif
-{
- register char *cp;
-
- if (ap->sin_addr.s_addr == 0) {
- ap->sin_len = 0;
- return;
- }
- cp = (char *)(&ap->sin_addr.s_addr+1);
- while (*--cp == 0)
- continue;
- ap->sin_len = cp - (char*)ap + 1;
-}
-
-
-/* Tell the kernel to add, delete or change a route
- */
-static void
-rtioctl(int action, /* RTM_DELETE, etc */
- naddr dst,
- naddr gate,
- naddr mask,
- int metric,
- int flags)
-{
- struct {
- struct rt_msghdr w_rtm;
- struct sockaddr_in w_dst;
- struct sockaddr_in w_gate;
-#ifdef _HAVE_SA_LEN
- struct sockaddr_in w_mask;
-#else
- struct sockaddr_in_new w_mask;
-#endif
- } w;
- long cc;
-
-again:
- bzero(&w, sizeof(w));
- w.w_rtm.rtm_msglen = sizeof(w);
- w.w_rtm.rtm_version = RTM_VERSION;
- w.w_rtm.rtm_type = action;
- w.w_rtm.rtm_flags = flags;
- w.w_rtm.rtm_seq = ++rt_sock_seqno;
- w.w_rtm.rtm_addrs = RTA_DST|RTA_GATEWAY;
- if (metric != 0) {
- w.w_rtm.rtm_rmx.rmx_hopcount = metric;
- w.w_rtm.rtm_inits |= RTV_HOPCOUNT;
- }
- w.w_dst.sin_family = AF_INET;
- w.w_dst.sin_addr.s_addr = dst;
- w.w_gate.sin_family = AF_INET;
- w.w_gate.sin_addr.s_addr = gate;
-#ifdef _HAVE_SA_LEN
- w.w_dst.sin_len = sizeof(w.w_dst);
- w.w_gate.sin_len = sizeof(w.w_gate);
-#endif
- if (mask == HOST_MASK) {
- w.w_rtm.rtm_flags |= RTF_HOST;
- w.w_rtm.rtm_msglen -= sizeof(w.w_mask);
- } else {
- w.w_rtm.rtm_addrs |= RTA_NETMASK;
- w.w_mask.sin_addr.s_addr = htonl(mask);
-#ifdef _HAVE_SA_LEN
- masktrim(&w.w_mask);
- if (w.w_mask.sin_len == 0)
- w.w_mask.sin_len = sizeof(long);
- w.w_rtm.rtm_msglen -= (sizeof(w.w_mask) - w.w_mask.sin_len);
-#endif
- }
-#ifndef NO_INSTALL
- cc = write(rt_sock, &w, w.w_rtm.rtm_msglen);
- if (cc == w.w_rtm.rtm_msglen)
- return;
- if (cc < 0) {
- if (errno == ESRCH
- && (action == RTM_CHANGE || action == RTM_DELETE)) {
- trace_act("route to %s disappeared before %s\n",
- addrname(dst, mask, 0),
- rtm_type_name(action));
- if (action == RTM_CHANGE) {
- action = RTM_ADD;
- goto again;
- }
- return;
- }
- msglog("write(rt_sock) %s %s --> %s: %s",
- rtm_type_name(action),
- addrname(dst, mask, 0), naddr_ntoa(gate),
- strerror(errno));
- } else {
- msglog("write(rt_sock) wrote %d instead of %d",
- cc, w.w_rtm.rtm_msglen);
- }
-#endif
-}
-
-
-#define KHASH_SIZE 71 /* should be prime */
-#define KHASH(a,m) khash_bins[((a) ^ (m)) % KHASH_SIZE]
-static struct khash {
- struct khash *k_next;
- naddr k_dst;
- naddr k_mask;
- naddr k_gate;
- short k_metric;
- u_short k_state;
-#define KS_NEW 0x001
-#define KS_DELETE 0x002
-#define KS_ADD 0x004 /* add to the kernel */
-#define KS_CHANGE 0x008 /* tell kernel to change the route */
-#define KS_DEL_ADD 0x010 /* delete & add to change the kernel */
-#define KS_STATIC 0x020 /* Static flag in kernel */
-#define KS_GATEWAY 0x040 /* G flag in kernel */
-#define KS_DYNAMIC 0x080 /* result of redirect */
-#define KS_DELETED 0x100 /* already deleted */
- time_t k_keep;
-#define K_KEEP_LIM 30
- time_t k_redirect_time;
-} *khash_bins[KHASH_SIZE];
-
-
-static struct khash*
-kern_find(naddr dst, naddr mask, struct khash ***ppk)
-{
- struct khash *k, **pk;
-
- for (pk = &KHASH(dst,mask); (k = *pk) != 0; pk = &k->k_next) {
- if (k->k_dst == dst && k->k_mask == mask)
- break;
- }
- if (ppk != 0)
- *ppk = pk;
- return k;
-}
-
-
-static struct khash*
-kern_add(naddr dst, naddr mask)
-{
- struct khash *k, **pk;
-
- k = kern_find(dst, mask, &pk);
- if (k != 0)
- return k;
-
- k = (struct khash *)malloc(sizeof(*k));
-
- bzero(k, sizeof(*k));
- k->k_dst = dst;
- k->k_mask = mask;
- k->k_state = KS_NEW;
- k->k_keep = now.tv_sec;
- *pk = k;
-
- return k;
-}
-
-
-/* If a kernel route has a non-zero metric, check that it is still in the
- * daemon table, and not deleted by interfaces coming and going.
- */
-static void
-kern_check_static(struct khash *k,
- struct interface *ifp)
-{
- struct rt_entry *rt;
- naddr int_addr;
-
- if (k->k_metric == 0)
- return;
-
- int_addr = (ifp != 0) ? ifp->int_addr : loopaddr;
-
- rt = rtget(k->k_dst, k->k_mask);
- if (rt != 0) {
- if (!(rt->rt_state & RS_STATIC))
- rtchange(rt, rt->rt_state | RS_STATIC,
- k->k_gate, int_addr,
- k->k_metric, 0, ifp, now.tv_sec, 0);
- } else {
- rtadd(k->k_dst, k->k_mask, k->k_gate, int_addr,
- k->k_metric, 0, RS_STATIC, ifp);
- }
-}
-
-
-/* add a route the kernel told us
- */
-static void
-rtm_add(struct rt_msghdr *rtm,
- struct rt_addrinfo *info,
- time_t keep)
-{
- struct khash *k;
- struct interface *ifp;
- naddr mask;
-
-
- if (rtm->rtm_flags & RTF_HOST) {
- mask = HOST_MASK;
- } else if (INFO_MASK(info) != 0) {
- mask = ntohl(S_ADDR(INFO_MASK(info)));
- } else {
- msglog("punt %s without mask",
- rtm_type_name(rtm->rtm_type));
- return;
- }
-
- if (INFO_GATE(info) == 0
- || INFO_GATE(info)->sa_family != AF_INET) {
- msglog("punt %s without gateway",
- rtm_type_name(rtm->rtm_type));
- return;
- }
-
- k = kern_add(S_ADDR(INFO_DST(info)), mask);
- if (k->k_state & KS_NEW)
- k->k_keep = now.tv_sec+keep;
- k->k_gate = S_ADDR(INFO_GATE(info));
- k->k_metric = rtm->rtm_rmx.rmx_hopcount;
- if (k->k_metric < 0)
- k->k_metric = 0;
- else if (k->k_metric > HOPCNT_INFINITY)
- k->k_metric = HOPCNT_INFINITY;
- k->k_state &= ~(KS_DELETED | KS_GATEWAY | KS_STATIC | KS_NEW);
- if (rtm->rtm_flags & RTF_GATEWAY)
- k->k_state |= KS_GATEWAY;
- if (rtm->rtm_flags & RTF_STATIC)
- k->k_state |= KS_STATIC;
- if (0 != (rtm->rtm_flags & (RTF_DYNAMIC | RTF_MODIFIED))) {
- if (supplier) {
- /* Routers are not supposed to listen to redirects,
- * so delete it.
- */
- k->k_state &= ~KS_DYNAMIC;
- k->k_state |= KS_DELETE;
- trace_act("mark redirected %s --> %s for deletion"
- " since this is a router\n",
- addrname(k->k_dst, k->k_mask, 0),
- naddr_ntoa(k->k_gate));
- } else {
- k->k_state |= KS_DYNAMIC;
- k->k_redirect_time = now.tv_sec;
- }
- }
-
- /* If it is not a static route, quit until the next comparison
- * between the kernel and daemon tables, when it will be deleted.
- */
- if (!(k->k_state & KS_STATIC)) {
- k->k_state |= KS_DELETE;
- LIM_SEC(need_kern, k->k_keep);
- return;
- }
-
- /* Put static routes with real metrics into the daemon table so
- * they can be advertised.
- *
- * Find the interface concerned
- */
- ifp = iflookup(k->k_gate);
- if (ifp == 0) {
- /* if there is no known interface,
- * maybe there is a new interface
- */
- ifinit();
- ifp = iflookup(k->k_gate);
- if (ifp == 0)
- msglog("static route %s --> %s impossibly lacks ifp",
- addrname(S_ADDR(INFO_DST(info)), mask, 0),
- naddr_ntoa(k->k_gate));
- }
-
- kern_check_static(k, ifp);
-}
-
-
-/* deal with packet loss
- */
-static void
-rtm_lose(struct rt_msghdr *rtm,
- struct rt_addrinfo *info)
-{
- if (INFO_GATE(info) == 0
- || INFO_GATE(info)->sa_family != AF_INET) {
- msglog("punt %s without gateway",
- rtm_type_name(rtm->rtm_type));
- return;
- }
-
- if (!supplier)
- rdisc_age(S_ADDR(INFO_GATE(info)));
-
- age(S_ADDR(INFO_GATE(info)));
-}
-
-
-/* Clean the kernel table by copying it to the daemon image.
- * Eventually the daemon will delete any extra routes.
- */
-void
-flush_kern(void)
-{
- size_t needed;
- int mib[6];
- char *buf, *next, *lim;
- struct rt_msghdr *rtm;
- struct interface *ifp;
- static struct sockaddr_in gate_sa;
- struct rt_addrinfo info;
-
-
- mib[0] = CTL_NET;
- mib[1] = PF_ROUTE;
- mib[2] = 0; /* protocol */
- mib[3] = 0; /* wildcard address family */
- mib[4] = NET_RT_DUMP;
- mib[5] = 0; /* no flags */
- if (sysctl(mib, 6, 0, &needed, 0, 0) < 0) {
- DBGERR(1,"RT_DUMP-sysctl-estimate");
- return;
- }
- buf = malloc(needed);
- if (sysctl(mib, 6, buf, &needed, 0, 0) < 0)
- BADERR(1,"RT_DUMP");
- lim = buf + needed;
- for (next = buf; next < lim; next += rtm->rtm_msglen) {
- rtm = (struct rt_msghdr *)next;
-
- rt_xaddrs(&info,
- (struct sockaddr *)(rtm+1),
- (struct sockaddr *)(next + rtm->rtm_msglen),
- rtm->rtm_addrs);
-
- if (INFO_DST(&info) == 0
- || INFO_DST(&info)->sa_family != AF_INET)
- continue;
-
- /* ignore ARP table entries on systems with a merged route
- * and ARP table.
- */
- if (rtm->rtm_flags & RTF_LLINFO)
- continue;
-
- if (INFO_GATE(&info) == 0)
- continue;
- if (INFO_GATE(&info)->sa_family != AF_INET) {
- if (INFO_GATE(&info)->sa_family != AF_LINK)
- continue;
- ifp = ifwithindex(((struct sockaddr_dl *)
- INFO_GATE(&info))->sdl_index);
- if (ifp == 0)
- continue;
- if ((ifp->int_if_flags & IFF_POINTOPOINT)
- || S_ADDR(INFO_DST(&info)) == ifp->int_addr)
- gate_sa.sin_addr.s_addr = ifp->int_addr;
- else
- gate_sa.sin_addr.s_addr = htonl(ifp->int_net);
-#ifdef _HAVE_SA_LEN
- gate_sa.sin_len = sizeof(gate_sa);
-#endif
- gate_sa.sin_family = AF_INET;
- INFO_GATE(&info) = (struct sockaddr *)&gate_sa;
- }
-
- /* ignore multicast addresses
- */
- if (IN_MULTICAST(ntohl(S_ADDR(INFO_DST(&info)))))
- continue;
-
- /* Note static routes and interface routes, and also
- * preload the image of the kernel table so that
- * we can later clean it, as well as avoid making
- * unneeded changes. Keep the old kernel routes for a
- * few seconds to allow a RIP or router-discovery
- * response to be heard.
- */
- rtm_add(rtm,&info,MIN_WAITTIME);
- }
- free(buf);
-}
-
-
-/* Listen to announcements from the kernel
- */
-void
-read_rt(void)
-{
- long cc;
- struct interface *ifp;
- naddr mask;
- union {
- struct {
- struct rt_msghdr rtm;
- struct sockaddr addrs[RTAX_MAX];
- } r;
- struct if_msghdr ifm;
- } m;
- char str[100], *strp;
- struct rt_addrinfo info;
-
-
- for (;;) {
- cc = read(rt_sock, &m, sizeof(m));
- if (cc <= 0) {
- if (cc < 0 && errno != EWOULDBLOCK)
- LOGERR("read(rt_sock)");
- return;
- }
-
- if (m.r.rtm.rtm_version != RTM_VERSION) {
- msglog("bogus routing message version %d",
- m.r.rtm.rtm_version);
- continue;
- }
-
- /* Ignore our own results.
- */
- if (m.r.rtm.rtm_type <= RTM_CHANGE
- && m.r.rtm.rtm_pid == mypid) {
- static int complained = 0;
- if (!complained) {
- msglog("receiving our own change messages");
- complained = 1;
- }
- continue;
- }
-
- if (m.r.rtm.rtm_type == RTM_IFINFO
- || m.r.rtm.rtm_type == RTM_NEWADDR
- || m.r.rtm.rtm_type == RTM_DELADDR) {
- ifp = ifwithindex(m.ifm.ifm_index);
- if (ifp == 0)
- trace_act("note %s with flags %#x"
- " for index #%d\n",
- rtm_type_name(m.r.rtm.rtm_type),
- m.ifm.ifm_flags,
- m.ifm.ifm_index);
- else
- trace_act("note %s with flags %#x for %s\n",
- rtm_type_name(m.r.rtm.rtm_type),
- m.ifm.ifm_flags,
- ifp->int_name);
-
- /* After being informed of a change to an interface,
- * check them all now if the check would otherwise
- * be a long time from now, if the interface is
- * not known, or if the interface has been turned
- * off or on.
- */
- if (ifinit_timer.tv_sec-now.tv_sec>=CHECK_BAD_INTERVAL
- || ifp == 0
- || ((ifp->int_if_flags ^ m.ifm.ifm_flags)
- & IFF_UP_RUNNING) != 0)
- ifinit_timer.tv_sec = now.tv_sec;
- continue;
- }
-
- strcpy(str, rtm_type_name(m.r.rtm.rtm_type));
- strp = &str[strlen(str)];
- if (m.r.rtm.rtm_type <= RTM_CHANGE)
- strp += sprintf(strp," from pid %d",m.r.rtm.rtm_pid);
-
- rt_xaddrs(&info, m.r.addrs, &m.r.addrs[RTAX_MAX],
- m.r.rtm.rtm_addrs);
-
- if (INFO_DST(&info) == 0) {
- trace_act("ignore %s without dst\n", str);
- continue;
- }
-
- if (INFO_DST(&info)->sa_family != AF_INET) {
- trace_act("ignore %s for AF %d\n", str,
- INFO_DST(&info)->sa_family);
- continue;
- }
-
- mask = ((INFO_MASK(&info) != 0)
- ? ntohl(S_ADDR(INFO_MASK(&info)))
- : (m.r.rtm.rtm_flags & RTF_HOST)
- ? HOST_MASK
- : std_mask(S_ADDR(INFO_DST(&info))));
-
- strp += sprintf(strp, ": %s",
- addrname(S_ADDR(INFO_DST(&info)), mask, 0));
-
- if (IN_MULTICAST(ntohl(S_ADDR(INFO_DST(&info))))) {
- trace_act("ignore multicast %s\n", str);
- continue;
- }
-
- if (INFO_GATE(&info) != 0
- && INFO_GATE(&info)->sa_family == AF_INET)
- strp += sprintf(strp, " --> %s",
- saddr_ntoa(INFO_GATE(&info)));
-
- if (INFO_AUTHOR(&info) != 0)
- strp += sprintf(strp, " by authority of %s",
- saddr_ntoa(INFO_AUTHOR(&info)));
-
- switch (m.r.rtm.rtm_type) {
- case RTM_ADD:
- case RTM_CHANGE:
- case RTM_REDIRECT:
- if (m.r.rtm.rtm_errno != 0) {
- trace_act("ignore %s with \"%s\" error\n",
- str, strerror(m.r.rtm.rtm_errno));
- } else {
- trace_act("%s\n", str);
- rtm_add(&m.r.rtm,&info,0);
- }
- break;
-
- case RTM_DELETE:
- if (m.r.rtm.rtm_errno != 0) {
- trace_act("ignore %s with \"%s\" error\n",
- str, strerror(m.r.rtm.rtm_errno));
- } else {
- trace_act("%s\n", str);
- del_static(S_ADDR(INFO_DST(&info)), mask, 1);
- }
- break;
-
- case RTM_LOSING:
- trace_act("%s\n", str);
- rtm_lose(&m.r.rtm,&info);
- break;
-
- default:
- trace_act("ignore %s\n", str);
- break;
- }
- }
-}
-
-
-/* after aggregating, note routes that belong in the kernel
- */
-static void
-kern_out(struct ag_info *ag)
-{
- struct khash *k;
-
-
- /* Do not install bad routes if they are not already present.
- * This includes routes that had RS_NET_SYN for interfaces that
- * recently died.
- */
- if (ag->ag_metric == HOPCNT_INFINITY) {
- k = kern_find(htonl(ag->ag_dst_h), ag->ag_mask, 0);
- if (k == 0)
- return;
- } else {
- k = kern_add(htonl(ag->ag_dst_h), ag->ag_mask);
- }
-
- if (k->k_state & KS_NEW) {
- /* will need to add new entry to the kernel table */
- k->k_state = KS_ADD;
- if (ag->ag_state & AGS_GATEWAY)
- k->k_state |= KS_GATEWAY;
- k->k_gate = ag->ag_gate;
- k->k_metric = ag->ag_metric;
- return;
- }
-
- if (k->k_state & KS_STATIC)
- return;
-
- /* modify existing kernel entry if necessary */
- if (k->k_gate != ag->ag_gate
- || k->k_metric != ag->ag_metric) {
- k->k_gate = ag->ag_gate;
- k->k_metric = ag->ag_metric;
- k->k_state |= KS_CHANGE;
- }
-
- if (k->k_state & KS_DYNAMIC) {
- k->k_state &= ~KS_DYNAMIC;
- k->k_state |= (KS_ADD | KS_DEL_ADD);
- }
-
- if ((k->k_state & KS_GATEWAY)
- && !(ag->ag_state & AGS_GATEWAY)) {
- k->k_state &= ~KS_GATEWAY;
- k->k_state |= (KS_ADD | KS_DEL_ADD);
- } else if (!(k->k_state & KS_GATEWAY)
- && (ag->ag_state & AGS_GATEWAY)) {
- k->k_state |= KS_GATEWAY;
- k->k_state |= (KS_ADD | KS_DEL_ADD);
- }
-
- /* Deleting-and-adding is necessary to change aspects of a route.
- * Just delete instead of deleting and then adding a bad route.
- * Otherwise, we want to keep the route in the kernel.
- */
- if (k->k_metric == HOPCNT_INFINITY
- && (k->k_state & KS_DEL_ADD))
- k->k_state |= KS_DELETE;
- else
- k->k_state &= ~KS_DELETE;
-#undef RT
-}
-
-
-/* ARGSUSED */
-static int
-walk_kern(struct radix_node *rn,
- struct walkarg *w)
-{
-#define RT ((struct rt_entry *)rn)
- char metric, pref;
- u_int ags = 0;
-
-
- /* Do not install synthetic routes */
- if (RT->rt_state & RS_NET_SYN)
- return 0;
-
- if (!(RT->rt_state & RS_IF)) {
- ags |= (AGS_GATEWAY | AGS_SUPPRESS | AGS_PROMOTE);
-
- } else {
- /* Do not install routes for "external" remote interfaces.
- */
- if (RT->rt_ifp != 0 && (RT->rt_ifp->int_state & IS_EXTERNAL))
- return 0;
-
- ags |= AGS_IF;
-
- /* If it is not an interface, or an alias for an interface,
- * it must be a "gateway."
- *
- * If it is a "remote" interface, it is also a "gateway" to
- * the kernel if is not a alias.
- */
- if (RT->rt_ifp == 0
- || ((RT->rt_ifp->int_state & IS_REMOTE)
- && RT->rt_ifp->int_metric == 0))
- ags |= (AGS_GATEWAY | AGS_SUPPRESS | AGS_PROMOTE);
- }
-
- if (RT->rt_state & RS_RDISC)
- ags |= AGS_CORS_GATE;
-
- /* aggregate good routes without regard to their metric */
- pref = 1;
- metric = RT->rt_metric;
- if (metric == HOPCNT_INFINITY) {
- /* if the route is dead, so try hard to aggregate. */
- pref = HOPCNT_INFINITY;
- ags |= (AGS_FINE_GATE | AGS_SUPPRESS);
- }
-
- ag_check(RT->rt_dst, RT->rt_mask, RT->rt_gate, 0,
- metric,pref, 0, 0, ags, kern_out);
- return 0;
-#undef RT
-}
-
-
-/* Update the kernel table to match the daemon table.
- */
-static void
-fix_kern(void)
-{
- int i, flags;
- struct khash *k, **pk;
-
-
- need_kern = age_timer;
-
- /* Walk daemon table, updating the copy of the kernel table.
- */
- (void)rn_walktree(rhead, walk_kern, 0);
- ag_flush(0,0,kern_out);
-
- for (i = 0; i < KHASH_SIZE; i++) {
- for (pk = &khash_bins[i]; (k = *pk) != 0; ) {
- /* Do not touch static routes */
- if (k->k_state & KS_STATIC) {
- kern_check_static(k,0);
- pk = &k->k_next;
- continue;
- }
-
- /* check hold on routes deleted by the operator */
- if (k->k_keep > now.tv_sec) {
- LIM_SEC(need_kern, k->k_keep);
- k->k_state |= KS_DELETE;
- pk = &k->k_next;
- continue;
- }
-
- if ((k->k_state & (KS_DELETE | KS_DYNAMIC))
- == KS_DELETE) {
- if (!(k->k_state & KS_DELETED))
- rtioctl(RTM_DELETE,
- k->k_dst, k->k_gate, k->k_mask,
- 0, 0);
- *pk = k->k_next;
- free(k);
- continue;
- }
-
- if (0 != (k->k_state&(KS_ADD|KS_CHANGE|KS_DEL_ADD))) {
- if (k->k_state & KS_DEL_ADD) {
- rtioctl(RTM_DELETE,
- k->k_dst,k->k_gate,k->k_mask,
- 0, 0);
- k->k_state &= ~KS_DYNAMIC;
- }
-
- flags = 0;
- if (0 != (k->k_state&(KS_GATEWAY|KS_DYNAMIC)))
- flags |= RTF_GATEWAY;
-
- if (k->k_state & KS_ADD) {
- rtioctl(RTM_ADD,
- k->k_dst, k->k_gate, k->k_mask,
- k->k_metric, flags);
- } else if (k->k_state & KS_CHANGE) {
- rtioctl(RTM_CHANGE,
- k->k_dst,k->k_gate,k->k_mask,
- k->k_metric, flags);
- }
- k->k_state &= ~(KS_ADD|KS_CHANGE|KS_DEL_ADD);
- }
-
- /* Mark this route to be deleted in the next cycle.
- * This deletes routes that disappear from the
- * daemon table, since the normal aging code
- * will clear the bit for routes that have not
- * disappeared from the daemon table.
- */
- k->k_state |= KS_DELETE;
- pk = &k->k_next;
- }
- }
-}
-
-
-/* Delete a static route in the image of the kernel table.
- */
-void
-del_static(naddr dst,
- naddr mask,
- int gone)
-{
- struct khash *k;
- struct rt_entry *rt;
-
- /* Just mark it in the table to be deleted next time the kernel
- * table is updated.
- * If it has already been deleted, mark it as such, and set its
- * keep-timer so that it will not be deleted again for a while.
- * This lets the operator delete a route added by the daemon
- * and add a replacement.
- */
- k = kern_find(dst, mask, 0);
- if (k != 0) {
- k->k_state &= ~(KS_STATIC | KS_DYNAMIC);
- k->k_state |= KS_DELETE;
- if (gone) {
- k->k_state |= KS_DELETED;
- k->k_keep = now.tv_sec + K_KEEP_LIM;
- }
- }
-
- rt = rtget(dst, mask);
- if (rt != 0 && (rt->rt_state & RS_STATIC))
- rtbad(rt);
-}
-
-
-/* Delete all routes generated from ICMP Redirects that use a given gateway,
- * as well as old redirected routes.
- */
-void
-del_redirects(naddr bad_gate,
- time_t old)
-{
- int i;
- struct khash *k;
-
-
- for (i = 0; i < KHASH_SIZE; i++) {
- for (k = khash_bins[i]; k != 0; k = k->k_next) {
- if (!(k->k_state & KS_DYNAMIC)
- || (k->k_state & KS_STATIC))
- continue;
-
- if (k->k_gate != bad_gate
- && k->k_redirect_time > old
- && !supplier)
- continue;
-
- k->k_state |= KS_DELETE;
- k->k_state &= ~KS_DYNAMIC;
- need_kern.tv_sec = now.tv_sec;
- trace_act("mark redirected %s --> %s for deletion\n",
- addrname(k->k_dst, k->k_mask, 0),
- naddr_ntoa(k->k_gate));
- }
- }
-}
-
-
-/* Start the daemon tables.
- */
-void
-rtinit(void)
-{
- extern int max_keylen;
- int i;
- struct ag_info *ag;
-
- /* Initialize the radix trees */
- max_keylen = sizeof(struct sockaddr_in);
- rn_init();
- rn_inithead((void**)&rhead, 32);
-
- /* mark all of the slots in the table free */
- ag_avail = ag_slots;
- for (ag = ag_slots, i = 1; i < NUM_AG_SLOTS; i++) {
- ag->ag_fine = ag+1;
- ag++;
- }
-}
-
-
-#ifdef _HAVE_SIN_LEN
-static struct sockaddr_in dst_sock = {sizeof(dst_sock), AF_INET};
-static struct sockaddr_in mask_sock = {sizeof(mask_sock), AF_INET};
-#else
-static struct sockaddr_in_new dst_sock = {_SIN_ADDR_SIZE, AF_INET};
-static struct sockaddr_in_new mask_sock = {_SIN_ADDR_SIZE, AF_INET};
-#endif
-
-
-void
-set_need_flash(void)
-{
- if (!need_flash) {
- need_flash = 1;
- /* Do not send the flash update immediately. Wait a little
- * while to hear from other routers.
- */
- no_flash.tv_sec = now.tv_sec + MIN_WAITTIME;
- }
-}
-
-
-/* Get a particular routing table entry
- */
-struct rt_entry *
-rtget(naddr dst, naddr mask)
-{
- struct rt_entry *rt;
-
- dst_sock.sin_addr.s_addr = dst;
- mask_sock.sin_addr.s_addr = mask;
- masktrim(&mask_sock);
- rt = (struct rt_entry *)rhead->rnh_lookup(&dst_sock,&mask_sock,rhead);
- if (!rt
- || rt->rt_dst != dst
- || rt->rt_mask != mask)
- return 0;
-
- return rt;
-}
-
-
-/* Find a route to dst as the kernel would.
- */
-struct rt_entry *
-rtfind(naddr dst)
-{
- dst_sock.sin_addr.s_addr = dst;
- return (struct rt_entry *)rhead->rnh_matchaddr(&dst_sock, rhead);
-}
-
-
-/* add a route to the table
- */
-void
-rtadd(naddr dst,
- naddr mask,
- naddr gate, /* forward packets here */
- naddr router, /* on the authority of this router */
- int metric,
- u_short tag,
- u_int state, /* rs_state for the entry */
- struct interface *ifp)
-{
- struct rt_entry *rt;
- naddr smask;
- int i;
- struct rt_spare *rts;
-
- rt = (struct rt_entry *)rtmalloc(sizeof (*rt), "rtadd");
- bzero(rt, sizeof(*rt));
- for (rts = rt->rt_spares, i = NUM_SPARES; i != 0; i--, rts++)
- rts->rts_metric = HOPCNT_INFINITY;
-
- rt->rt_nodes->rn_key = (caddr_t)&rt->rt_dst_sock;
- rt->rt_dst = dst;
- rt->rt_dst_sock.sin_family = AF_INET;
-#ifdef _HAVE_SIN_LEN
- rt->rt_dst_sock.sin_len = dst_sock.sin_len;
-#endif
- if (mask != HOST_MASK) {
- smask = std_mask(dst);
- if ((smask & ~mask) == 0 && mask > smask)
- state |= RS_SUBNET;
- }
- mask_sock.sin_addr.s_addr = mask;
- masktrim(&mask_sock);
- rt->rt_mask = mask;
- rt->rt_state = state;
- rt->rt_gate = gate;
- rt->rt_router = router;
- rt->rt_time = now.tv_sec;
- rt->rt_metric = metric;
- rt->rt_poison_metric = HOPCNT_INFINITY;
- rt->rt_tag = tag;
- rt->rt_ifp = ifp;
- rt->rt_seqno = update_seqno;
-
- if (++total_routes == MAX_ROUTES)
- msglog("have maximum (%d) routes", total_routes);
- if (TRACEACTIONS)
- trace_add_del("Add", rt);
-
- need_kern.tv_sec = now.tv_sec;
- set_need_flash();
-
- if (0 == rhead->rnh_addaddr(&rt->rt_dst_sock, &mask_sock,
- rhead, rt->rt_nodes)) {
-/*
- * This will happen if RIP1 and RIP2 routeds talk to one another and
- * there are variable subnets. This is only good for filling up your
- * syslog. -jkh
- */
-#if 0
- msglog("rnh_addaddr() failed for %s mask=%#x",
- naddr_ntoa(dst), mask);
-#endif
- }
-}
-
-
-/* notice a changed route
- */
-void
-rtchange(struct rt_entry *rt,
- u_int state, /* new state bits */
- naddr gate, /* now forward packets here */
- naddr router, /* on the authority of this router */
- int metric, /* new metric */
- u_short tag,
- struct interface *ifp,
- time_t new_time,
- char *label)
-{
- if (rt->rt_metric != metric) {
- /* Fix the kernel immediately if it seems the route
- * has gone bad, since there may be a working route that
- * aggregates this route.
- */
- if (metric == HOPCNT_INFINITY)
- need_kern.tv_sec = now.tv_sec;
- rt->rt_seqno = update_seqno;
- set_need_flash();
- }
-
- if (rt->rt_gate != gate) {
- need_kern.tv_sec = now.tv_sec;
- rt->rt_seqno = update_seqno;
- set_need_flash();
- }
-
- state |= (rt->rt_state & RS_SUBNET);
-
- if (TRACEACTIONS)
- trace_change(rt, state, gate, router, metric, tag, ifp,
- new_time,
- label ? label : "Chg ");
-
- rt->rt_state = state;
- rt->rt_gate = gate;
- rt->rt_router = router;
- rt->rt_metric = metric;
- rt->rt_tag = tag;
- rt->rt_ifp = ifp;
- rt->rt_time = new_time;
-}
-
-
-/* check for a better route among the spares
- */
-static struct rt_spare *
-rts_better(struct rt_entry *rt)
-{
- struct rt_spare *rts, *rts1;
- int i;
-
- /* find the best alternative among the spares */
- rts = rt->rt_spares+1;
- for (i = NUM_SPARES, rts1 = rts+1; i > 2; i--, rts1++) {
- if (BETTER_LINK(rt,rts1,rts))
- rts = rts1;
- }
-
- return rts;
-}
-
-
-/* switch to a backup route
- */
-void
-rtswitch(struct rt_entry *rt,
- struct rt_spare *rts)
-{
- struct rt_spare swap;
- char label[10];
-
-
- /* Do not change permanent routes */
- if (0 != (rt->rt_state & RS_PERMANENT))
- return;
-
- /* Do not discard synthetic routes until they go bad */
- if ((rt->rt_state & RS_NET_SYN)
- && rt->rt_metric < HOPCNT_INFINITY)
- return;
-
- /* find the best alternative among the spares */
- if (rts == 0)
- rts = rts_better(rt);
-
- /* Do not bother if it is not worthwhile.
- */
- if (!BETTER_LINK(rt, rts, rt->rt_spares))
- return;
-
- swap = rt->rt_spares[0];
- (void)sprintf(label, "Use #%d", rts - rt->rt_spares);
- rtchange(rt, rt->rt_state & ~(RS_NET_SYN | RS_RDISC),
- rts->rts_gate, rts->rts_router, rts->rts_metric,
- rts->rts_tag, rts->rts_ifp, rts->rts_time, label);
- *rts = swap;
-}
-
-
-void
-rtdelete(struct rt_entry *rt)
-{
- struct khash *k;
-
-
- if (TRACEACTIONS)
- trace_add_del("Del", rt);
-
- k = kern_find(rt->rt_dst, rt->rt_mask, 0);
- if (k != 0) {
- k->k_state |= KS_DELETE;
- need_kern.tv_sec = now.tv_sec;
- }
-
- dst_sock.sin_addr.s_addr = rt->rt_dst;
- mask_sock.sin_addr.s_addr = rt->rt_mask;
- masktrim(&mask_sock);
- if (rt != (struct rt_entry *)rhead->rnh_deladdr(&dst_sock, &mask_sock,
- rhead)) {
- msglog("rnh_deladdr() failed");
- } else {
- free(rt);
- total_routes--;
- }
-}
-
-
-/* Get rid of a bad route, and try to switch to a replacement.
- */
-void
-rtbad(struct rt_entry *rt)
-{
- /* Poison the route */
- rtchange(rt, rt->rt_state & ~(RS_IF | RS_LOCAL | RS_STATIC),
- rt->rt_gate, rt->rt_router, HOPCNT_INFINITY, rt->rt_tag,
- 0, rt->rt_time, 0);
-
- rtswitch(rt, 0);
-}
-
-
-/* Junk a RS_NET_SYN or RS_LOCAL route,
- * unless it is needed by another interface.
- */
-void
-rtbad_sub(struct rt_entry *rt)
-{
- struct interface *ifp, *ifp1;
- struct intnet *intnetp;
- u_int state;
-
-
- ifp1 = 0;
- state = 0;
-
- if (rt->rt_state & RS_LOCAL) {
- /* Is this the route through loopback for the interface?
- * If so, see if it is used by any other interfaces, such
- * as a point-to-point interface with the same local address.
- */
- for (ifp = ifnet; ifp != 0; ifp = ifp->int_next) {
- /* Retain it if another interface needs it.
- */
- if (ifp->int_addr == rt->rt_ifp->int_addr) {
- state |= RS_LOCAL;
- ifp1 = ifp;
- break;
- }
- }
-
- }
-
- if (!(state & RS_LOCAL)) {
- /* Retain RIPv1 logical network route if there is another
- * interface that justifies it.
- */
- if (rt->rt_state & RS_NET_SYN) {
- for (ifp = ifnet; ifp != 0; ifp = ifp->int_next) {
- if ((ifp->int_state & IS_NEED_NET_SYN)
- && rt->rt_mask == ifp->int_std_mask
- && rt->rt_dst == ifp->int_std_addr) {
- state |= RS_NET_SYN;
- ifp1 = ifp;
- break;
- }
- }
- }
-
- /* or if there is an authority route that needs it. */
- for (intnetp = intnets;
- intnetp != 0;
- intnetp = intnetp->intnet_next) {
- if (intnetp->intnet_addr == rt->rt_dst
- && intnetp->intnet_mask == rt->rt_mask) {
- state |= (RS_NET_SYN | RS_NET_INT);
- break;
- }
- }
- }
-
- if (ifp1 != 0 || (state & RS_NET_SYN)) {
- rtchange(rt, ((rt->rt_state & ~(RS_NET_SYN | RS_LOCAL))
- | state),
- rt->rt_gate, rt->rt_router, rt->rt_metric,
- rt->rt_tag, ifp1, rt->rt_time, 0);
- } else {
- rtbad(rt);
- }
-}
-
-
-/* Called while walking the table looking for sick interfaces
- * or after a time change.
- */
-/* ARGSUSED */
-int
-walk_bad(struct radix_node *rn,
- struct walkarg *w)
-{
-#define RT ((struct rt_entry *)rn)
- struct rt_spare *rts;
- int i;
- time_t new_time;
-
-
- /* fix any spare routes through the interface
- */
- rts = RT->rt_spares;
- for (i = NUM_SPARES; i != 1; i--) {
- rts++;
-
- if (rts->rts_ifp != 0
- && (rts->rts_ifp->int_state & IS_BROKE)) {
- new_time = rts->rts_time;
- if (new_time >= now_garbage)
- new_time = now_garbage-1;
- trace_upslot(RT, rts, rts->rts_gate,
- rts->rts_router, 0,
- HOPCNT_INFINITY, rts->rts_tag,
- new_time);
- rts->rts_ifp = 0;
- rts->rts_metric = HOPCNT_INFINITY;
- rts->rts_time = new_time;
- }
- }
-
- /* Deal with the main route
- */
- /* finished if it has been handled before or if its interface is ok
- */
- if (RT->rt_ifp == 0 || !(RT->rt_ifp->int_state & IS_BROKE))
- return 0;
-
- /* Bad routes for other than interfaces are easy.
- */
- if (0 == (RT->rt_state & (RS_IF | RS_NET_SYN | RS_LOCAL))) {
- rtbad(RT);
- return 0;
- }
-
- rtbad_sub(RT);
- return 0;
-#undef RT
-}
-
-
-/* Check the age of an individual route.
- */
-/* ARGSUSED */
-static int
-walk_age(struct radix_node *rn,
- struct walkarg *w)
-{
-#define RT ((struct rt_entry *)rn)
- struct interface *ifp;
- struct rt_spare *rts;
- int i;
-
-
- /* age all of the spare routes, including the primary route
- * currently in use
- */
- rts = RT->rt_spares;
- for (i = NUM_SPARES; i != 0; i--, rts++) {
-
- ifp = rts->rts_ifp;
- if (i == NUM_SPARES) {
- if (!AGE_RT(RT, ifp)) {
- /* Keep various things from deciding ageless
- * routes are stale */
- rts->rts_time = now.tv_sec;
- continue;
- }
-
- /* forget RIP routes after RIP has been turned off.
- */
- if (rip_sock < 0) {
- rtdelete(RT);
- return 0;
- }
- }
-
- /* age failing routes
- */
- if (age_bad_gate == rts->rts_gate
- && rts->rts_time >= now_stale) {
- rts->rts_time -= SUPPLY_INTERVAL;
- }
-
- /* trash the spare routes when they go bad */
- if (rts->rts_metric < HOPCNT_INFINITY
- && now_garbage > rts->rts_time) {
- trace_upslot(RT, rts, rts->rts_gate,
- rts->rts_router, rts->rts_ifp,
- HOPCNT_INFINITY, rts->rts_tag,
- rts->rts_time);
- rts->rts_metric = HOPCNT_INFINITY;
- }
- }
-
-
- /* finished if the active route is still fresh */
- if (now_stale <= RT->rt_time)
- return 0;
-
- /* try to switch to an alternative */
- rtswitch(RT, 0);
-
- /* Delete a dead route after it has been publically mourned. */
- if (now_garbage > RT->rt_time) {
- rtdelete(RT);
- return 0;
- }
-
- /* Start poisoning a bad route before deleting it. */
- if (now.tv_sec - RT->rt_time > EXPIRE_TIME)
- rtchange(RT, RT->rt_state, RT->rt_gate, RT->rt_router,
- HOPCNT_INFINITY, RT->rt_tag, RT->rt_ifp,
- RT->rt_time, 0);
- return 0;
-}
-
-
-/* Watch for dead routes and interfaces.
- */
-void
-age(naddr bad_gate)
-{
- struct interface *ifp;
-
-
- age_timer.tv_sec = now.tv_sec + (rip_sock < 0
- ? NEVER
- : SUPPLY_INTERVAL);
-
- for (ifp = ifnet; ifp; ifp = ifp->int_next) {
- /* Check for dead IS_REMOTE interfaces by timing their
- * transmissions.
- */
- if ((ifp->int_state & IS_REMOTE)
- && !(ifp->int_state & IS_PASSIVE)
- && (ifp->int_state & IS_ACTIVE)) {
- LIM_SEC(age_timer, now.tv_sec+SUPPLY_INTERVAL);
-
- if (now.tv_sec - ifp->int_act_time > EXPIRE_TIME
- && !(ifp->int_state & IS_BROKE)) {
- msglog("remote interface %s to %s timed out"
- "--turned off",
- ifp->int_name,
- naddr_ntoa(ifp->int_addr));
- if_bad(ifp);
- }
- }
- }
-
- /* Age routes. */
- age_bad_gate = bad_gate;
- (void)rn_walktree(rhead, walk_age, 0);
-
- /* Update the kernel routing table. */
- fix_kern();
-}
diff --git a/usr.sbin/routed/trace.c b/usr.sbin/routed/trace.c
deleted file mode 100644
index f38b393..0000000
--- a/usr.sbin/routed/trace.c
+++ /dev/null
@@ -1,800 +0,0 @@
-/*
- * Copyright (c) 1983, 1988, 1993
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#if !defined(lint) && !defined(sgi) && !defined(__NetBSD__)
-static char sccsid[] = "@(#)trace.c 8.1 (Berkeley) 6/5/93";
-#elif defined(__NetBSD__)
-static char rcsid[] = "$NetBSD$";
-#endif
-#ident "$Revision: 1.1.3.3 $"
-
-#define RIPCMDS
-#include "defs.h"
-#include "pathnames.h"
-#include <sys/stat.h>
-#include <sys/signal.h>
-#include <fcntl.h>
-
-
-#ifdef sgi
-/* use *stat64 for files on large filesystems */
-#define stat stat64
-#endif
-
-#define NRECORDS 50 /* size of circular trace buffer */
-
-u_int tracelevel, new_tracelevel;
-FILE *ftrace = stdout; /* output trace file */
-static char *tracelevel_pat = "%s\n";
-
-char savetracename[MAXPATHLEN+1];
-
-
-/* convert IP address to a string, but not into a single buffer
- */
-char *
-naddr_ntoa(naddr a)
-{
-#define NUM_BUFS 4
- static int bufno;
- static struct {
- char str[16]; /* xxx.xxx.xxx.xxx\0 */
- } bufs[NUM_BUFS];
- char *s;
- struct in_addr addr;
-
- addr.s_addr = a;
- s = strcpy(bufs[bufno].str, inet_ntoa(addr));
- bufno = (bufno+1) % NUM_BUFS;
- return s;
-#undef NUM_BUFS
-}
-
-
-char *
-saddr_ntoa(struct sockaddr *sa)
-{
- return (sa == 0) ? "?" : naddr_ntoa(S_ADDR(sa));
-}
-
-
-static char *
-ts(time_t secs) {
- static char s[20];
-
- secs += epoch.tv_sec;
-#ifdef sgi
- (void)cftime(s, "%T", &secs);
-#else
- bcopy(ctime(&secs)+11, s, 8);
- s[8] = '\0';
-#endif
- return s;
-}
-
-
-/* On each event, display a time stamp.
- * This assumes that 'now' is update once for each event, and
- * that at least now.tv_usec changes.
- */
-void
-lastlog(void)
-{
- static struct timeval last;
-
- if (last.tv_sec != now.tv_sec
- || last.tv_usec != now.tv_usec) {
- (void)fprintf(ftrace, "-- %s --\n", ts(now.tv_sec));
- last = now;
- }
-}
-
-
-static void
-tmsg(char *p, ...)
-{
- va_list args;
-
- if (ftrace != 0) {
- lastlog();
- va_start(args, p);
- vfprintf(ftrace, p, args);
- fflush(ftrace);
- }
-}
-
-
-static void
-trace_close(void)
-{
- int fd;
-
-
- fflush(stdout);
- fflush(stderr);
-
- if (ftrace != 0
- && savetracename[0] != '\0') {
- fd = open(_PATH_DEVNULL, O_RDWR);
- (void)dup2(fd, STDOUT_FILENO);
- (void)dup2(fd, STDERR_FILENO);
- (void)close(fd);
- fclose(ftrace);
- ftrace = 0;
- }
-}
-
-
-void
-trace_flush(void)
-{
- if (ftrace != 0) {
- fflush(ftrace);
- if (ferror(ftrace))
- trace_off("tracing off: ", strerror(ferror(ftrace)));
- }
-}
-
-
-void
-trace_off(char *p, ...)
-{
- va_list args;
-
-
- if (ftrace != 0) {
- lastlog();
- va_start(args, p);
- vfprintf(ftrace, p, args);
- fflush(ftrace);
- }
- trace_close();
-
- new_tracelevel = tracelevel = 0;
-}
-
-
-void
-trace_on(char *filename,
- int trusted)
-{
- struct stat stbuf;
- FILE *n_ftrace;
-
-
- /* Given a null filename when tracing is already on, increase the
- * debugging level and re-open the file in case it has been unlinked.
- */
- if (filename[0] == '\0') {
- if (tracelevel != 0) {
- new_tracelevel++;
- tracelevel_pat = "trace command: %s\n";
- } else if (savetracename[0] == '\0') {
- msglog("missing trace file name");
- return;
- }
- filename = savetracename;
-
- } else if (stat(filename, &stbuf) >= 0) {
- if (!trusted) {
- msglog("trace file \"%s\" already exists");
- return;
- }
- if ((stbuf.st_mode & S_IFMT) != S_IFREG) {
- msglog("wrong type (%#x) of trace file \"%s\"",
- stbuf.st_mode, filename);
- return;
- }
-
- if (!trusted
- && strcmp(filename, savetracename)
- && strncmp(filename, _PATH_TRACE, sizeof(_PATH_TRACE)-1)) {
- msglog("wrong directory for trace file: \"%s\"",
- filename);
- return;
- }
- }
-
- n_ftrace = fopen(filename, "a");
- if (n_ftrace == 0) {
- msglog("failed to open trace file \"%s\" %s",
- filename, strerror(errno));
- return;
- }
-
- tmsg("switch to trace file %s\n", filename);
- trace_close();
- if (filename != savetracename)
- strncpy(savetracename, filename, sizeof(savetracename)-1);
- ftrace = n_ftrace;
-
- fflush(stdout);
- fflush(stderr);
- dup2(fileno(ftrace), STDOUT_FILENO);
- dup2(fileno(ftrace), STDERR_FILENO);
-
- if (new_tracelevel == 0)
- new_tracelevel = 1;
- set_tracelevel();
-}
-
-
-/* ARGSUSED */
-void
-sigtrace_on(int s)
-{
- new_tracelevel++;
- tracelevel_pat = "SIGUSR1: %s\n";
-}
-
-
-/* ARGSUSED */
-void
-sigtrace_off(int s)
-{
- new_tracelevel--;
- tracelevel_pat = "SIGUSR2: %s\n";
-}
-
-
-/* Move to next higher level of tracing when -t option processed or
- * SIGUSR1 is received. Successive levels are:
- * actions
- * actions + packets
- * actions + packets + contents
- */
-void
-set_tracelevel(void)
-{
- static char *off_msgs[MAX_TRACELEVEL] = {
- "Tracing actions stopped",
- "Tracing packets stopped",
- "Tracing packet contents stopped",
- };
- static char *on_msgs[MAX_TRACELEVEL] = {
- "Tracing actions started",
- "Tracing packets started",
- "Tracing packet contents started",
- };
-
-
- if (new_tracelevel > MAX_TRACELEVEL) {
- new_tracelevel = MAX_TRACELEVEL;
- if (new_tracelevel == tracelevel) {
- tmsg(tracelevel_pat, on_msgs[tracelevel-1]);
- return;
- }
- }
- while (new_tracelevel != tracelevel) {
- if (new_tracelevel < tracelevel) {
- if (--tracelevel == 0)
- trace_off(tracelevel_pat, off_msgs[0]);
- else
- tmsg(tracelevel_pat, off_msgs[tracelevel]);
- } else {
- if (ftrace == 0) {
- if (savetracename[0] != '\0')
- trace_on(savetracename, 1);
- else
- ftrace = stdout;
- }
- tmsg(tracelevel_pat, on_msgs[tracelevel++]);
- }
- }
- tracelevel_pat = "%s\n";
-}
-
-
-/* display an address
- */
-char *
-addrname(naddr addr, /* in network byte order */
- naddr mask,
- int force) /* 0=show mask if nonstandard, */
-{ /* 1=always show mask, 2=never */
-#define NUM_BUFS 4
- static int bufno;
- static struct {
- char str[15+20];
- } bufs[NUM_BUFS];
- char *s, *sp;
- naddr dmask;
- int i;
-
- s = strcpy(bufs[bufno].str, naddr_ntoa(addr));
- bufno = (bufno+1) % NUM_BUFS;
-
- if (force == 1 || (force == 0 && mask != std_mask(addr))) {
- sp = &s[strlen(s)];
-
- dmask = mask & -mask;
- if (mask + dmask == 0) {
- for (i = 0; i != 32 && ((1<<i) & mask) == 0; i++)
- continue;
- (void)sprintf(sp, "/%d", 32-i);
-
- } else {
- (void)sprintf(sp, " (mask %#x)", (u_int)mask);
- }
- }
-
- return s;
-#undef NUM_BUFS
-}
-
-
-/* display a bit-field
- */
-struct bits {
- int bits_mask;
- int bits_clear;
- char *bits_name;
-};
-
-static struct bits if_bits[] = {
- { IFF_LOOPBACK, 0, "LOOPBACK" },
- { IFF_POINTOPOINT, 0, "PT-TO-PT" },
- { 0, 0, 0}
-};
-
-static struct bits is_bits[] = {
- { IS_SUBNET, 0, "" },
- { IS_REMOTE, 0, "REMOTE" },
- { IS_PASSIVE, (IS_NO_RDISC
- | IS_BCAST_RDISC
- | IS_NO_RIP
- | IS_NO_SUPER_AG
- | IS_PM_RDISC
- | IS_NO_AG), "PASSIVE" },
- { IS_EXTERNAL, 0, "EXTERNAL" },
- { IS_CHECKED, 0, "" },
- { IS_ALL_HOSTS, 0, "" },
- { IS_ALL_ROUTERS, 0, "" },
- { IS_RIP_QUERIED, 0, "" },
- { IS_BROKE, IS_SICK, "BROKEN" },
- { IS_SICK, 0, "SICK" },
- { IS_ACTIVE, 0, "ACTIVE" },
- { IS_NEED_NET_SYN, 0, "" },
- { IS_NO_AG, IS_NO_SUPER_AG, "NO_AG" },
- { IS_NO_SUPER_AG, 0, "NO_SUPER_AG" },
- { (IS_NO_RIPV1_IN
- | IS_NO_RIPV2_IN
- | IS_NO_RIPV1_OUT
- | IS_NO_RIPV2_OUT), 0, "NO_RIP" },
- { (IS_NO_RIPV1_IN
- | IS_NO_RIPV1_OUT), 0, "RIPV2" },
- { IS_NO_RIPV1_IN, 0, "NO_RIPV1_IN" },
- { IS_NO_RIPV2_IN, 0, "NO_RIPV2_IN" },
- { IS_NO_RIPV1_OUT, 0, "NO_RIPV1_OUT" },
- { IS_NO_RIPV2_OUT, 0, "NO_RIPV2_OUT" },
- { (IS_NO_ADV_IN
- | IS_NO_SOL_OUT
- | IS_NO_ADV_OUT), IS_BCAST_RDISC, "NO_RDISC" },
- { IS_NO_SOL_OUT, 0, "NO_SOLICIT" },
- { IS_SOL_OUT, 0, "SEND_SOLICIT" },
- { IS_NO_ADV_OUT, IS_BCAST_RDISC, "NO_RDISC_ADV" },
- { IS_ADV_OUT, 0, "RDISC_ADV" },
- { IS_BCAST_RDISC, 0, "BCAST_RDISC" },
- { IS_PM_RDISC, 0, "PM_RDISC" },
- { 0, 0, "%#x"}
-};
-
-static struct bits rs_bits[] = {
- { RS_IF, 0, "IF" },
- { RS_NET_INT, RS_NET_SYN, "NET_INT" },
- { RS_NET_SYN, 0, "NET_SYN" },
- { RS_SUBNET, 0, "" },
- { RS_LOCAL, 0, "LOCAL" },
- { RS_MHOME, 0, "MHOME" },
- { RS_STATIC, 0, "STATIC" },
- { RS_RDISC, 0, "RDISC" },
- { 0, 0, "%#x"}
-};
-
-
-static void
-trace_bits(struct bits *tbl,
- u_int field,
- int force)
-{
- int b;
- char c;
-
- if (force) {
- (void)putc('<', ftrace);
- c = 0;
- } else {
- c = '<';
- }
-
- while (field != 0
- && (b = tbl->bits_mask) != 0) {
- if ((b & field) == b) {
- if (tbl->bits_name[0] != '\0') {
- if (c)
- (void)putc(c, ftrace);
- (void)fprintf(ftrace, "%s", tbl->bits_name);
- c = '|';
- }
- if (0 == (field &= ~(b | tbl->bits_clear)))
- break;
- }
- tbl++;
- }
- if (field != 0 && tbl->bits_name != 0) {
- if (c)
- (void)putc(c, ftrace);
- (void)fprintf(ftrace, tbl->bits_name, field);
- c = '|';
- }
-
- if (c != '<' || force)
- (void)fputs("> ", ftrace);
-}
-
-
-static char *
-trace_pair(naddr dst,
- naddr mask,
- char *gate)
-{
- static char buf[3*4+3+1+2+3 /* "xxx.xxx.xxx.xxx/xx-->" */
- +3*4+3+1]; /* "xxx.xxx.xxx.xxx" */
- int i;
-
- i = sprintf(buf, "%-16s-->", addrname(dst, mask, 0));
- (void)sprintf(&buf[i], "%-*s", 15+20-MAX(20,i), gate);
- return buf;
-}
-
-
-void
-trace_if(char *act,
- struct interface *ifp)
-{
- if (!TRACEACTIONS || ftrace == 0)
- return;
-
- lastlog();
- (void)fprintf(ftrace, "%s interface %-4s ", act, ifp->int_name);
- (void)fprintf(ftrace, "%-15s-->%-15s ",
- naddr_ntoa(ifp->int_addr),
- addrname(htonl((ifp->int_if_flags & IFF_POINTOPOINT)
- ? ifp->int_dstaddr
- : ifp->int_net),
- ifp->int_mask, 1));
- if (ifp->int_metric != 0)
- (void)fprintf(ftrace, "metric=%d ", ifp->int_metric);
- trace_bits(if_bits, ifp->int_if_flags, 0);
- trace_bits(is_bits, ifp->int_state, 0);
- (void)fputc('\n',ftrace);
-}
-
-
-void
-trace_upslot(struct rt_entry *rt,
- struct rt_spare *rts,
- naddr gate,
- naddr router,
- struct interface *ifp,
- int metric,
- u_short tag,
- time_t new_time)
-{
- if (!TRACEACTIONS || ftrace == 0)
- return;
- if (rts->rts_gate == gate
- && rts->rts_router == router
- && rts->rts_metric == metric
- && rts->rts_tag == tag)
- return;
-
- lastlog();
- if (rts->rts_gate != RIP_DEFAULT) {
- (void)fprintf(ftrace, "Chg #%d %-35s ",
- rts - rt->rt_spares,
- trace_pair(rt->rt_dst, rt->rt_mask,
- naddr_ntoa(rts->rts_gate)));
- if (rts->rts_gate != rts->rts_gate)
- (void)fprintf(ftrace, "router=%s ",
- naddr_ntoa(rts->rts_gate));
- if (rts->rts_tag != 0)
- (void)fprintf(ftrace, "tag=%#x ", ntohs(rts->rts_tag));
- (void)fprintf(ftrace, "metric=%-2d ", rts->rts_metric);
- if (rts->rts_ifp != 0)
- (void)fprintf(ftrace, "%s ",
- rts->rts_ifp->int_name);
- (void)fprintf(ftrace, "%s\n", ts(rts->rts_time));
-
- (void)fprintf(ftrace, " %19s%-16s ",
- "",
- gate != rts->rts_gate ? naddr_ntoa(gate) : "");
- if (gate != router)
- (void)fprintf(ftrace,"router=%s ",naddr_ntoa(router));
- if (tag != rts->rts_tag)
- (void)fprintf(ftrace, "tag=%#x ", ntohs(tag));
- if (metric != rts->rts_metric)
- (void)fprintf(ftrace, "metric=%-2d ", metric);
- if (ifp != rts->rts_ifp && ifp != 0 )
- (void)fprintf(ftrace, "%s ", ifp->int_name);
- (void)fprintf(ftrace, "%s\n",
- new_time != rts->rts_time ? ts(new_time) : "");
-
- } else {
- (void)fprintf(ftrace, "Add #%d %-35s ",
- rts - rt->rt_spares,
- trace_pair(rt->rt_dst, rt->rt_mask,
- naddr_ntoa(gate)));
- if (gate != router)
- (void)fprintf(ftrace, "router=%s ", naddr_ntoa(gate));
- if (tag != 0)
- (void)fprintf(ftrace, "tag=%#x ", ntohs(tag));
- (void)fprintf(ftrace, "metric=%-2d ", metric);
- if (ifp != 0)
- (void)fprintf(ftrace, "%s ", ifp->int_name);
- (void)fprintf(ftrace, "%s\n", ts(new_time));
- }
-}
-
-
-/* display a message if tracing actions
- */
-void
-trace_act(char *p, ...)
-{
- va_list args;
-
- if (!TRACEACTIONS || ftrace == 0)
- return;
-
- lastlog();
- va_start(args, p);
- vfprintf(ftrace, p, args);
-}
-
-
-/* display a message if tracing packets
- */
-void
-trace_pkt(char *p, ...)
-{
- va_list args;
-
- if (!TRACEPACKETS || ftrace == 0)
- return;
-
- lastlog();
- va_start(args, p);
- vfprintf(ftrace, p, args);
-}
-
-
-void
-trace_change(struct rt_entry *rt,
- u_int state,
- naddr gate, /* forward packets here */
- naddr router, /* on the authority of this router */
- int metric,
- u_short tag,
- struct interface *ifp,
- time_t new_time,
- char *label)
-{
- if (ftrace == 0)
- return;
-
- if (rt->rt_metric == metric
- && rt->rt_gate == gate
- && rt->rt_router == router
- && rt->rt_state == state
- && rt->rt_tag == tag)
- return;
-
- lastlog();
- (void)fprintf(ftrace, "%s %-35s metric=%-2d ",
- label,
- trace_pair(rt->rt_dst, rt->rt_mask,
- naddr_ntoa(rt->rt_gate)),
- rt->rt_metric);
- if (rt->rt_router != rt->rt_gate)
- (void)fprintf(ftrace, "router=%s ",
- naddr_ntoa(rt->rt_router));
- if (rt->rt_tag != 0)
- (void)fprintf(ftrace, "tag=%#x ", ntohs(rt->rt_tag));
- trace_bits(rs_bits, rt->rt_state, rt->rt_state != state);
- (void)fprintf(ftrace, "%s ",
- rt->rt_ifp == 0 ? "?" : rt->rt_ifp->int_name);
- (void)fprintf(ftrace, "%s\n",
- AGE_RT(rt, rt->rt_ifp) ? ts(rt->rt_time) : "");
-
- (void)fprintf(ftrace, "%*s %19s%-16s ",
- strlen(label), "", "",
- rt->rt_gate != gate ? naddr_ntoa(gate) : "");
- if (rt->rt_metric != metric)
- (void)fprintf(ftrace, "metric=%-2d ", metric);
- if (router != gate)
- (void)fprintf(ftrace, "router=%s ", naddr_ntoa(router));
- if (rt->rt_tag != tag)
- (void)fprintf(ftrace, "tag=%#x ", ntohs(tag));
- if (rt->rt_state != state)
- trace_bits(rs_bits, state, 1);
- if (rt->rt_ifp != ifp)
- (void)fprintf(ftrace, "%s ",
- ifp != 0 ? ifp->int_name : "?");
- (void)fprintf(ftrace, "%s\n",
- ((rt->rt_time == new_time || !AGE_RT(rt, ifp))
- ? "" : ts(new_time)));
-}
-
-
-void
-trace_add_del(char * action, struct rt_entry *rt)
-{
- u_int state = rt->rt_state;
-
- if (ftrace == 0)
- return;
-
- lastlog();
- (void)fprintf(ftrace, "%s %-35s metric=%-2d ",
- action,
- trace_pair(rt->rt_dst, rt->rt_mask,
- naddr_ntoa(rt->rt_gate)),
- rt->rt_metric);
- if (rt->rt_router != rt->rt_gate)
- (void)fprintf(ftrace, "router=%s ",
- naddr_ntoa(rt->rt_router));
- if (rt->rt_tag != 0)
- (void)fprintf(ftrace, "tag=%#x ", ntohs(rt->rt_tag));
- trace_bits(rs_bits, state, 0);
- (void)fprintf(ftrace, "%s ",
- rt->rt_ifp != 0 ? rt->rt_ifp->int_name : "?");
- (void)fprintf(ftrace, "%s\n", ts(rt->rt_time));
-}
-
-
-void
-trace_rip(char *dir1, char *dir2,
- struct sockaddr_in *who,
- struct interface *ifp,
- struct rip *msg,
- int size) /* total size of message */
-{
- struct netinfo *n, *lim;
- struct netauth *a;
- int i;
-
- if (!TRACEPACKETS || ftrace == 0)
- return;
-
- lastlog();
- if (msg->rip_cmd >= RIPCMD_MAX
- || msg->rip_vers == 0) {
- (void)fprintf(ftrace, "%s bad RIPv%d cmd=%d %s"
- " %s.%d size=%d\n",
- dir1, msg->rip_vers, msg->rip_cmd, dir2,
- naddr_ntoa(who->sin_addr.s_addr),
- ntohs(who->sin_port),
- size);
- return;
- }
-
- (void)fprintf(ftrace, "%s RIPv%d %s %s %s.%d%s%s\n",
- dir1, msg->rip_vers, ripcmds[msg->rip_cmd], dir2,
- naddr_ntoa(who->sin_addr.s_addr), ntohs(who->sin_port),
- ifp ? " via " : "", ifp ? ifp->int_name : "");
- if (!TRACECONTENTS)
- return;
-
- switch (msg->rip_cmd) {
- case RIPCMD_REQUEST:
- case RIPCMD_RESPONSE:
- n = msg->rip_nets;
- lim = (struct netinfo *)((char*)msg + size);
- for (; n < lim; n++) {
- if (n->n_family == RIP_AF_UNSPEC
- && ntohl(n->n_metric) == HOPCNT_INFINITY
- && n+1 == lim
- && n == msg->rip_nets
- && msg->rip_cmd == RIPCMD_REQUEST) {
- (void)fputs("\tQUERY ", ftrace);
- if (n->n_dst != 0)
- (void)fprintf(ftrace, "%s ",
- naddr_ntoa(n->n_dst));
- if (n->n_mask != 0)
- (void)fprintf(ftrace, "mask=%#x ",
- (u_int)ntohl(n->n_mask));
- if (n->n_nhop != 0)
- (void)fprintf(ftrace, " nhop=%s ",
- naddr_ntoa(n->n_nhop));
- if (n->n_tag != 0)
- (void)fprintf(ftrace, "tag=%#x",
- ntohs(n->n_tag));
- (void)fputc('\n',ftrace);
- continue;
- }
-
- if (n->n_family == RIP_AF_AUTH) {
- a = (struct netauth*)n;
- (void)fprintf(ftrace,
- "\tAuthentication type %d: ",
- ntohs(a->a_type));
- for (i = 0;
- i < sizeof(a->au.au_pw);
- i++)
- (void)fprintf(ftrace, "%02x ",
- a->au.au_pw[i]);
- (void)fputc('\n',ftrace);
- continue;
- }
-
- if (n->n_family != RIP_AF_INET) {
- (void)fprintf(ftrace,
- "\t(af %d) %-18s mask=%#x",
- ntohs(n->n_family),
- naddr_ntoa(n->n_dst),
- (u_int)ntohl(n->n_mask));
- } else if (msg->rip_vers == RIPv1) {
- (void)fprintf(ftrace, "\t%-18s ",
- addrname(n->n_dst,
- ntohl(n->n_mask),
- n->n_mask==0 ? 2 : 1));
- } else {
- (void)fprintf(ftrace, "\t%-18s ",
- addrname(n->n_dst,
- ntohl(n->n_mask),
- n->n_mask==0 ? 2 : 0));
- }
- (void)fprintf(ftrace, "metric=%-2d ",
- (u_int)ntohl(n->n_metric));
- if (n->n_nhop != 0)
- (void)fprintf(ftrace, " nhop=%s ",
- naddr_ntoa(n->n_nhop));
- if (n->n_tag != 0)
- (void)fprintf(ftrace, "tag=%#x",
- ntohs(n->n_tag));
- (void)fputc('\n',ftrace);
- }
- if (size != (char *)n - (char *)msg)
- (void)fprintf(ftrace, "truncated record, len %d\n",
- size);
- break;
-
- case RIPCMD_TRACEON:
- fprintf(ftrace, "\tfile=%*s\n", size-4, msg->rip_tracefile);
- break;
-
- case RIPCMD_TRACEOFF:
- break;
- }
-}
OpenPOWER on IntegriCloud