summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sbin/routed/Makefile28
-rw-r--r--sbin/routed/defs.h177
-rw-r--r--sbin/routed/if.c225
-rw-r--r--sbin/routed/input.c271
-rw-r--r--sbin/routed/main.c177
-rw-r--r--sbin/routed/md5.c4
-rw-r--r--sbin/routed/output.c279
-rw-r--r--sbin/routed/parms.c346
-rw-r--r--sbin/routed/pathnames.h6
-rw-r--r--sbin/routed/radix.c120
-rw-r--r--sbin/routed/radix.h20
-rw-r--r--sbin/routed/rdisc.c167
-rw-r--r--sbin/routed/routed.8184
-rw-r--r--sbin/routed/routed.h6
-rw-r--r--sbin/routed/rtquery/Makefile12
-rw-r--r--sbin/routed/rtquery/md5.c4
-rw-r--r--sbin/routed/rtquery/rtquery.874
-rw-r--r--sbin/routed/rtquery/rtquery.c218
-rw-r--r--sbin/routed/table.c627
-rw-r--r--sbin/routed/trace.c283
20 files changed, 1900 insertions, 1328 deletions
diff --git a/sbin/routed/Makefile b/sbin/routed/Makefile
index 1ef573674d90..fb8c3de6b475 100644
--- a/sbin/routed/Makefile
+++ b/sbin/routed/Makefile
@@ -1,21 +1,13 @@
-# @(#)Makefile 8.1 (Berkeley) 6/19/93
+# Make `routed` for FreeBSD
+# $Revision: 2.15 $
+# $Id$
-PROG= routed
-SRCS= if.c input.c main.c md5.c output.c parms.c radix.c rdisc.c table.c \
- trace.c
-MAN8= routed.0
-SUBDIR= rtquery
-#COPTS= -g -DDEBUG -Wall
+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
+LDADD+= -lmd
+DPADD+= ${LIBMD}
+#COPTS= -g -DDEBUG -W -Wall -Wcast-align -Wcast-qual -Winline -Wpointer-arith -Wnested-externs -Wwrite-strings -Wunused
.include <bsd.prog.mk>
-
-.if (${MACHINE} == "vax")
-# The following can be deleted where not appropriate to use the kernel's
-# inline code expansions.
-INLINE= /sys/vax/inline/obj/inline
-C2= /usr/libexec/c2
-.c.o:
- ${CC} -S ${CFLAGS} ${.CURDIR}/${.PREFIX}.c
- @${C2} ${.PREFIX}.s | ${INLINE} | ${AS} -o ${.PREFIX}.o
- @rm -f ${.PREFIX}.s
-.endif
diff --git a/sbin/routed/defs.h b/sbin/routed/defs.h
index 9e70add9fe85..806689efeace 100644
--- a/sbin/routed/defs.h
+++ b/sbin/routed/defs.h
@@ -11,7 +11,7 @@
* 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:
+ * must display the following acknowledgment:
* 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
@@ -35,8 +35,8 @@
* $NetBSD$
*/
-#ifndef __NetBSD__
-#ident "$Revision: 1.21 $"
+#ifdef sgi
+#ident "$Revision: 2.17 $"
#endif
/* Definitions for RIPv2 routing process.
@@ -55,7 +55,7 @@
* tell the kernel hop counts
* do not advertise if ipforwarding=0
*
- * The vestigual support for other protocols has been removed. There
+ * The vestigial 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.
@@ -77,6 +77,7 @@
#include <stdarg.h>
#include <syslog.h>
#include <time.h>
+#include <sys/cdefs.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/param.h>
@@ -84,9 +85,12 @@
#include <sys/sysctl.h>
#include <sys/socket.h>
#ifdef sgi
+#define _USER_ROUTE_TREE
#include <net/radix.h>
#else
#include "radix.h"
+#define UNUSED __attribute__((unused))
+#define PATTRIB(f,l) __attribute__((format (printf,f,l)))
#endif
#include <net/if.h>
#include <net/route.h>
@@ -104,13 +108,13 @@
* 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
+#elif defined (__NetBSD__)
+#define naddr u_int32_t
+#define _HAVE_SA_LEN
+#define _HAVE_SIN_LEN
#else
#define naddr u_long
-#endif
#define _HAVE_SA_LEN
#define _HAVE_SIN_LEN
#endif
@@ -118,7 +122,9 @@
/* 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 */
+#ifdef __NetBSD__
+#define MCAST_PPP_BUG
+#endif
#define DAY (24*60*60)
#define NEVER DAY /* a long time */
@@ -170,6 +176,9 @@ union pkt_buf {
struct rip rip;
};
+#define GNAME_LEN 64 /* assumed=64 in parms.c */
+/* bigger than IFNAMSIZ, with room for "external()" or "remote()" */
+#define IF_NAME_LEN (GNAME_LEN+15)
/* No more routes than this, to protect ourself in case something goes
* whacko and starts broadcasting zillions of bogus routes.
@@ -200,19 +209,21 @@ struct rt_entry {
char rts_metric;
u_short rts_tag;
time_t rts_time; /* timer to junk stale routes */
+ u_int rts_de_ag; /* de-aggregation level */
#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 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 rt_de_ag rt_spares[0].rts_de_ag
#define HOST_MASK 0xffffffff
#define RT_ISHOST(rt) ((rt)->rt_mask == HOST_MASK)
@@ -240,7 +251,7 @@ struct rt_entry {
* - 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 \
+#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 \
@@ -261,7 +272,7 @@ struct interface {
struct interface *int_bhash, **int_bhash_prev;
struct interface *int_rlink, **int_rlink_prev;
struct interface *int_nhash, **int_nhash_prev;
- char int_name[IFNAMSIZ+15+1]; /* big enough for IS_REMOTE */
+ char int_name[IF_NAME_LEN+1];
u_short int_index;
naddr int_addr; /* address on this host (net order) */
naddr int_brdaddr; /* broadcast address (n) */
@@ -292,12 +303,13 @@ struct interface {
} int_data;
# define MAX_AUTH_KEYS 5
struct auth { /* authentication info */
- u_char type;
- u_char key[RIP_AUTH_PW_LEN];
+ u_int16_t type;
+ u_char key[RIP_AUTH_PW_LEN];
u_char keyid;
time_t start, end;
} int_auth[MAX_AUTH_KEYS];
- int int_rdisc_pref; /* advertised rdisc preference */
+ /* router discovery parameters */
+ int int_rdisc_pref; /* signed preference to advertise */
int int_rdisc_int; /* MaxAdvertiseInterval */
int int_rdisc_cnt;
struct timeval int_rdisc_timer;
@@ -330,23 +342,19 @@ struct interface {
#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_RIP_MCAST 0x0100000 /* broadcast RIPv2 */
+#define IS_NO_ADV_IN 0x0200000 /* do not listen to advertisements */
+#define IS_NO_SOL_OUT 0x0400000 /* send no solicitations */
+#define IS_SOL_OUT 0x0800000 /* send solicitations */
+#define GROUP_IS_SOL_OUT (IS_SOL_OUT | IS_NO_SOL_OUT)
+#define IS_NO_ADV_OUT 0x1000000 /* do not advertise rdisc */
+#define IS_ADV_OUT 0x2000000 /* advertise rdisc */
+#define GROUP_IS_ADV_OUT (IS_NO_ADV_OUT | IS_ADV_OUT)
+#define IS_BCAST_RDISC 0x4000000 /* 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 */
+#define IS_PM_RDISC 0x8000000 /* 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)
+#define iff_up(f) ((f) & IFF_UP)
/* Information for aggregating routes */
@@ -363,8 +371,8 @@ struct ag_info {
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_SUPPRESS 0x001 /* combine with coarser mask */
+#define AGS_AGGREGATE 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)) \
@@ -375,41 +383,54 @@ struct ag_info {
#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 */
+ * has the coarser netmasks */
#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)
+#define AGS_AGGREGATE_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];
+ char parm_name[IF_NAME_LEN+1];
naddr parm_net;
naddr parm_mask;
char parm_d_metric;
u_int parm_int_state;
- int parm_rdisc_pref;
- int parm_rdisc_int;
+ int parm_rdisc_pref; /* signed IRDP preference */
+ int parm_rdisc_int; /* IRDP advertising interval */
struct auth parm_auth[MAX_AUTH_KEYS];
} *parms;
/* authority for internal networks */
extern struct intnet {
struct intnet *intnet_next;
- naddr intnet_addr;
+ naddr intnet_addr; /* network byte order */
naddr intnet_mask;
char intnet_metric;
} *intnets;
+/* defined RIPv1 netmasks */
+extern struct r1net {
+ struct r1net *r1net_next;
+ naddr r1net_net; /* host order */
+ naddr r1net_match;
+ naddr r1net_mask;
+} *r1nets;
+
/* trusted routers */
extern struct tgate {
struct tgate *tgate_next;
naddr tgate_addr;
+#define MAX_TGATE_NETS 32
+ struct tgate_net {
+ naddr net; /* host order */
+ naddr mask;
+ } tgate_nets[MAX_TGATE_NETS];
} *tgates;
enum output_type {OUT_QUERY, OUT_UNICAST, OUT_BROADCAST, OUT_MULTICAST,
@@ -438,11 +459,11 @@ 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 lookforinterfaces; /* 1=probe for new up interfaces */
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 advertise_mhome; /* 1=must continue advertising it */
extern int auth_ok; /* 1=ignore auth if we do not care */
extern struct timeval clk; /* system clock's idea of time */
@@ -469,7 +490,7 @@ 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 update_seqno; /* a route has changed */
extern int tracelevel, new_tracelevel;
#define MAX_TRACELEVEL 4
@@ -488,7 +509,7 @@ extern struct radix_node_head *rhead;
#define dup2(x,y) BSDdup2(x,y)
#endif /* sgi */
-extern void fix_sock(int, char *);
+extern void fix_sock(int, const char *);
extern void fix_select(void);
extern void rip_off(void);
extern void rip_on(struct interface *);
@@ -502,7 +523,7 @@ extern void rip_bcast(int);
extern void supply(struct sockaddr_in *, struct interface *,
enum output_type, int, int, int);
-extern void msglog(char *, ...);
+extern void msglog(const char *, ...) PATTRIB(1,2);
struct msg_limit {
time_t reuse;
struct msg_sub {
@@ -511,9 +532,10 @@ struct msg_limit {
# define MSG_SUBJECT_N 8
} subs[MSG_SUBJECT_N];
};
-extern void msglim(struct msg_limit *, naddr, char *, ...);
+extern void msglim(struct msg_limit *, naddr,
+ const char *, ...) PATTRIB(3,4);
#define LOGERR(msg) msglog(msg ": %s", strerror(errno))
-extern void logbad(int, char *, ...);
+extern void logbad(int, const char *, ...) PATTRIB(2,3);
#define BADERR(dump,msg) logbad(dump,msg ": %s", strerror(errno))
#ifdef DEBUG
#define DBGERR(dump,msg) BADERR(dump,msg)
@@ -521,37 +543,38 @@ extern void logbad(int, char *, ...);
#define DBGERR(dump,msg) LOGERR(msg)
#endif
extern char *naddr_ntoa(naddr);
-extern char *saddr_ntoa(struct sockaddr *);
+extern const char *saddr_ntoa(struct sockaddr *);
-extern void *rtmalloc(size_t, char *);
+extern void *rtmalloc(size_t, const 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 *, int);
-extern char *check_parms(struct parm *);
+extern const char *parse_parms(char *, int);
+extern const char *check_parms(struct parm *);
extern void get_parms(struct interface *);
extern void lastlog(void);
-extern void set_tracefile(char *, char *, int);
-extern void tracelevel_msg(char *, int);
-extern void trace_off(char*, ...);
+extern void trace_close(int);
+extern void set_tracefile(const char *, const char *, int);
+extern void tracelevel_msg(const char *, int);
+extern void trace_off(const char*, ...) PATTRIB(1,2);
extern void set_tracelevel(void);
extern void trace_flush(void);
-extern void trace_kernel(char *, ...);
-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_misc(const char *, ...) PATTRIB(1,2);
+extern void trace_act(const char *, ...) PATTRIB(1,2);
+extern void trace_pkt(const char *, ...) PATTRIB(1,2);
+extern void trace_add_del(const char *, struct rt_entry *);
+extern void trace_change(struct rt_entry *, u_int, struct rt_spare *,
+ const char *);
+extern void trace_if(const 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 rt_spare *);
+extern void trace_rip(const char*, const char*, struct sockaddr_in *,
struct interface *, struct rip *, int);
extern char *addrname(naddr, naddr, int);
+extern char *rtname(naddr, naddr, naddr);
extern void rdisc_age(naddr);
extern void set_rdisc_mg(struct interface *, int);
@@ -576,21 +599,19 @@ 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_static(naddr, 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 rtadd(naddr, naddr, u_int, struct rt_spare *);
+extern void rtchange(struct rt_entry *, u_int, struct rt_spare *, char *);
extern void rtdelete(struct rt_entry *);
+extern void rts_delete(struct rt_entry *, struct rt_spare *);
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])
@@ -609,16 +630,16 @@ extern naddr ripv1_mask_host(naddr,struct interface *);
extern int check_dst(naddr);
extern struct interface *check_dup(naddr, naddr, naddr, int);
extern int check_remote(struct interface *);
-extern int addrouteforif(register struct interface *);
+extern int addrouteforif(struct interface *);
extern void ifinit(void);
extern int walk_bad(struct radix_node *, struct walkarg *);
-extern int if_ok(struct interface *, char *);
+extern int if_ok(struct interface *, const char *);
extern void if_sick(struct interface *);
extern void if_bad(struct interface *);
extern void if_link(struct interface *);
extern struct interface *ifwithaddr(naddr, int, int);
extern struct interface *ifwithname(char *, naddr);
-extern struct interface *ifwithindex(u_short);
+extern struct interface *ifwithindex(u_short, int);
extern struct interface *iflookup(naddr);
extern struct auth *find_auth(struct interface *);
diff --git a/sbin/routed/if.c b/sbin/routed/if.c
index b68ff52a9134..54228ce24aa8 100644
--- a/sbin/routed/if.c
+++ b/sbin/routed/if.c
@@ -11,7 +11,7 @@
* 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:
+ * must display the following acknowledgment:
* 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
@@ -31,16 +31,17 @@
* 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.23 $"
-
#include "defs.h"
#include "pathnames.h"
+#if !defined(sgi) && !defined(__NetBSD__)
+static char sccsid[] __attribute__((unused)) = "@(#)if.c 8.1 (Berkeley) 6/5/93";
+#elif defined(__NetBSD__)
+#include <sys/cdefs.h>
+__RCSID("$NetBSD$");
+#endif
+#ident "$Revision: 2.17 $"
+
struct interface *ifnet; /* all interfaces */
/* hash table for all interfaces, big enough to tolerate ridiculous
@@ -69,18 +70,22 @@ 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 rt_spare loop_rts;
struct timeval ifinit_timer;
static struct timeval last_ifinit;
+#define IF_RESCAN_DELAY() (last_ifinit.tv_sec == now.tv_sec \
+ && last_ifinit.tv_usec == now.tv_usec \
+ && timercmp(&ifinit_timer, &now, >))
int have_ripv1_out; /* have a RIPv1 interface */
int have_ripv1_in;
static struct interface**
-nhash(register char *p)
+nhash(char *p)
{
- register u_int i;
+ u_int i;
for (i = 0; *p != '\0'; p++) {
i = ((i<<1) & 0x7fffffff) | ((i>>31) & 1);
@@ -199,8 +204,7 @@ ifwithname(char *name, /* "ec0" or whatever */
/* If there is no known interface, maybe there is a
* new interface. So just once look for new interfaces.
*/
- if (last_ifinit.tv_sec == now.tv_sec
- && last_ifinit.tv_usec == now.tv_usec)
+ if (IF_RESCAN_DELAY())
return 0;
ifinit();
}
@@ -208,16 +212,25 @@ ifwithname(char *name, /* "ec0" or whatever */
struct interface *
-ifwithindex(u_short index)
+ifwithindex(u_short index,
+ int rescan_ok)
{
struct interface *ifp;
+ for (;;) {
+ for (ifp = ifnet; 0 != ifp; ifp = ifp->int_next) {
+ if (ifp->int_index == index)
+ return ifp;
+ }
- for (ifp = ifnet; 0 != ifp; ifp = ifp->int_next) {
- if (ifp->int_index == index)
- return ifp;
+ /* If there is no known interface, maybe there is a
+ * new interface. So just once look for new interfaces.
+ */
+ if (!rescan_ok
+ || IF_RESCAN_DELAY())
+ return 0;
+ ifinit();
}
- return 0;
}
@@ -253,8 +266,7 @@ iflookup(naddr addr)
}
if (maybe != 0
- || (last_ifinit.tv_sec == now.tv_sec
- && last_ifinit.tv_usec == now.tv_usec))
+ || IF_RESCAN_DELAY())
return maybe;
/* If there is no known interface, maybe there is a
@@ -290,12 +302,13 @@ naddr
ripv1_mask_net(naddr addr, /* in network byte order */
struct interface *ifp) /* as seen on this interface */
{
+ struct r1net *r1p;
naddr mask = 0;
if (addr == 0) /* default always has 0 mask */
return mask;
- if (ifp != 0) {
+ if (ifp != 0 && ifp->int_ripv1_mask != HOST_MASK) {
/* If the target network is that of the associated interface
* on which it arrived, then use the netmask of the interface.
*/
@@ -311,15 +324,26 @@ ripv1_mask_net(naddr addr, /* in network byte order */
*/
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)
+ && ifp->int_ripv1_mask > mask
+ && ifp->int_ripv1_mask != HOST_MASK)
mask = ifp->int_ripv1_mask;
}
+
}
- /* Otherwise, make the classic A/B/C guess.
- */
- if (mask == 0)
- mask = std_mask(addr);
+ /* check special definitions */
+ if (mask == 0) {
+ for (r1p = r1nets; r1p != 0; r1p = r1p->r1net_next) {
+ if (on_net(addr, r1p->r1net_net, r1p->r1net_match)
+ && r1p->r1net_mask > mask)
+ mask = r1p->r1net_mask;
+ }
+
+ /* Otherwise, make the classic A/B/C guess.
+ */
+ if (mask == 0)
+ mask = std_mask(addr);
+ }
return mask;
}
@@ -374,11 +398,11 @@ check_dup(naddr addr, /* IP address, so network byte order */
if (ifp->int_mask != mask)
continue;
- if (!iff_alive(ifp->int_if_flags))
+ if (!iff_up(ifp->int_if_flags))
continue;
- /* The local address can only be shared with a point-to-
- * point link.
+ /* The local address can only be shared with a point-to-point
+ * link.
*/
if (ifp->int_addr == addr
&& (((if_flags|ifp->int_if_flags) & IFF_POINTOPOINT) == 0))
@@ -495,8 +519,8 @@ ifdel(struct interface *ifp)
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.
+ * Assume routes just using gateways beyond this interface
+ * will timeout naturally, and have probably already died.
*/
(void)rn_walktree(rhead, walk_bad, 0);
@@ -539,7 +563,7 @@ if_bad(struct interface *ifp)
ifp->int_state |= (IS_BROKE | IS_SICK);
ifp->int_act_time = NEVER;
ifp->int_query_time = NEVER;
- ifp->int_data.ts = 0;
+ ifp->int_data.ts = now.tv_sec;
trace_if("Chg", ifp);
@@ -559,7 +583,7 @@ if_bad(struct interface *ifp)
*/
int /* 1=it was dead */
if_ok(struct interface *ifp,
- char *type)
+ const char *type)
{
struct interface *ifp1;
@@ -617,7 +641,7 @@ rt_xaddrs(struct rt_addrinfo *info,
#endif
- bzero(info, sizeof(*info));
+ memset(info, 0, sizeof(*info));
info->rti_addrs = addrs;
for (i = 0; i < RTAX_MAX && sa < lim; i++) {
if ((addrs & (1 << i)) == 0)
@@ -675,7 +699,7 @@ ifinit(void)
? CHECK_ACT_INTERVAL
: CHECK_QUIET_INTERVAL);
- /* mark all interfaces so we can get rid of thost that disappear */
+ /* mark all interfaces so we can get rid of those that disappear */
for (ifp = ifnet; 0 != ifp; ifp = ifp->int_next)
ifp->int_state &= ~(IS_CHECKED | IS_DUP);
@@ -692,14 +716,16 @@ ifinit(void)
if ((needed = sysctl_buf_size) != 0) {
if (sysctl(mib, 6, sysctl_buf,&needed, 0, 0) >= 0)
break;
+ /* retry if the table grew */
if (errno != ENOMEM && errno != EFAULT)
- BADERR(1, "ifinit: get interface table");
+ BADERR(1, "ifinit: sysctl(RT_IFLIST)");
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");
+ BADERR(1,"ifinit: sysctl(RT_IFLIST) estimate");
+ sysctl_buf = rtmalloc(sysctl_buf_size = needed,
+ "ifinit sysctl");
}
ifam_lim = (struct ifa_msghdr *)(sysctl_buf + needed);
@@ -715,7 +741,7 @@ ifinit(void)
ifm = (struct if_msghdr *)ifam;
/* make prototype structure for the IP aliases
*/
- bzero(&ifs0, sizeof(ifs0));
+ memset(&ifs0, 0, sizeof(ifs0));
ifs0.int_rip_sock = -1;
ifs0.int_index = ifm->ifm_index;
ifs0.int_if_flags = ifm->ifm_flags;
@@ -748,11 +774,11 @@ ifinit(void)
* will be an alias.
* Do not output RIP or Router-Discovery packets via aliases.
*/
- bcopy(&ifs0, &ifs, sizeof(ifs));
- ifs0.int_state |= (IS_ALIAS | IS_NO_RIP | IS_NO_RDISC);
+ memcpy(&ifs, &ifs0, sizeof(ifs));
+ ifs0.int_state |= (IS_ALIAS | IS_NO_RIP_OUT | IS_NO_RDISC);
if (INFO_IFA(&info) == 0) {
- if (iff_alive(ifs.int_if_flags)) {
+ if (iff_up(ifs.int_if_flags)) {
if (!(prev_complaints & COMP_NOADDR))
msglog("%s has no address",
ifs.int_name);
@@ -761,7 +787,7 @@ ifinit(void)
continue;
}
if (INFO_IFA(&info)->sa_family != AF_INET) {
- if (iff_alive(ifs.int_if_flags)) {
+ if (iff_up(ifs.int_if_flags)) {
if (!(prev_complaints & COMP_NOT_INET))
trace_act("%s: not AF_INET",
ifs.int_name);
@@ -774,7 +800,7 @@ ifinit(void)
if (ntohl(ifs.int_addr)>>24 == 0
|| ntohl(ifs.int_addr)>>24 == 0xff) {
- if (iff_alive(ifs.int_if_flags)) {
+ if (iff_up(ifs.int_if_flags)) {
if (!(prev_complaints & COMP_BADADDR))
msglog("%s has a bad address",
ifs.int_name);
@@ -793,12 +819,14 @@ ifinit(void)
if (!foundloopback) {
foundloopback = 1;
loopaddr = ifs.int_addr;
+ loop_rts.rts_gate = loopaddr;
+ loop_rts.rts_router = loopaddr;
}
} 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 (iff_up(ifs.int_if_flags)) {
if (!(prev_complaints & COMP_NODST))
msglog("%s has a bad"
" destination address",
@@ -810,7 +838,7 @@ ifinit(void)
ifs.int_dstaddr = S_ADDR(INFO_BRD(&info));
if (ntohl(ifs.int_dstaddr)>>24 == 0
|| ntohl(ifs.int_dstaddr)>>24 == 0xff) {
- if (iff_alive(ifs.int_if_flags)) {
+ if (iff_up(ifs.int_if_flags)) {
if (!(prev_complaints & COMP_NODST))
msglog("%s has a bad"
" destination address",
@@ -826,7 +854,7 @@ ifinit(void)
} else {
if (INFO_MASK(&info) == 0) {
- if (iff_alive(ifs.int_if_flags)) {
+ if (iff_up(ifs.int_if_flags)) {
if (!(prev_complaints & COMP_NOMASK))
msglog("%s has no netmask",
ifs.int_name);
@@ -844,7 +872,7 @@ ifinit(void)
if (ifs.int_if_flags & IFF_BROADCAST) {
if (INFO_BRD(&info) == 0) {
- if (iff_alive(ifs.int_if_flags)) {
+ if (iff_up(ifs.int_if_flags)) {
if (!(prev_complaints
& COMP_NOBADR))
msglog("%s has"
@@ -881,7 +909,7 @@ ifinit(void)
if (ifs.int_metric > HOPCNT_INFINITY) {
ifs.int_metric = 0;
if (!(prev_complaints & COMP_BAD_METRIC)
- && iff_alive(ifs.int_if_flags)) {
+ && iff_up(ifs.int_if_flags)) {
complaints |= COMP_BAD_METRIC;
msglog("%s has a metric of %d",
ifs.int_name, ifs.int_metric);
@@ -930,19 +958,26 @@ ifinit(void)
/* note interfaces that have been turned off
*/
- if (!iff_alive(ifs.int_if_flags)) {
- if (iff_alive(ifp->int_if_flags)) {
+ if (!iff_up(ifs.int_if_flags)) {
+ if (iff_up(ifp->int_if_flags)) {
msglog("interface %s to %s turned off",
ifp->int_name,
naddr_ntoa(ifp->int_dstaddr));
if_bad(ifp);
- ifp->int_if_flags &= ~IFF_UP_RUNNING;
+ ifp->int_if_flags &= ~IFF_UP;
+ } else if (now.tv_sec>(ifp->int_data.ts
+ + CHECK_BAD_INTERVAL)) {
+ trace_act("interface %s has been off"
+ " %ld seconds; forget it",
+ ifp->int_name,
+ now.tv_sec-ifp->int_data.ts);
+ ifdel(ifp);
}
continue;
}
/* or that were off and are now ok */
- if (!iff_alive(ifp->int_if_flags)) {
- ifp->int_if_flags |= IFF_UP_RUNNING;
+ if (!iff_up(ifp->int_if_flags)) {
+ ifp->int_if_flags |= IFF_UP;
(void)if_ok(ifp, "");
}
@@ -958,7 +993,7 @@ ifinit(void)
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.
+ * count packets dropped by the filters.
* But FDDI rings stuck non-operational count
* dropped packets as they wait for improvement.
*/
@@ -974,7 +1009,7 @@ ifinit(void)
}
ifp->int_data = ifs.int_data;
- /* Withhold judgement when the short error
+ /* Withhold judgment when the short error
* counters wrap or the interface is reset.
*/
if (ierr < 0 || in < 0 || oerr < 0 || out < 0) {
@@ -1024,7 +1059,7 @@ ifinit(void)
/* This is a new interface.
* If it is dead, forget it.
*/
- if (!iff_alive(ifs.int_if_flags))
+ if (!iff_up(ifs.int_if_flags))
continue;
/* If it duplicates an existing interface,
@@ -1034,6 +1069,12 @@ ifinit(void)
ifp = check_dup(ifs.int_addr,ifs.int_dstaddr,ifs.int_mask,
ifs.int_if_flags);
if (ifp != 0) {
+ /* Ignore duplicates of itself, caused by having
+ * IP aliases on the same network.
+ */
+ if (!strcmp(ifp->int_name, ifs.int_name))
+ continue;
+
if (!(prev_complaints & COMP_DUP)) {
complaints |= COMP_DUP;
msglog("%s (%s%s%s) is duplicated by"
@@ -1067,8 +1108,8 @@ ifinit(void)
/* It is new and ok. Add it to the list of interfaces
*/
- ifp = (struct interface *)rtmalloc(sizeof(*ifp), "ifinit");
- bcopy(&ifs, ifp, sizeof(*ifp));
+ ifp = (struct interface *)rtmalloc(sizeof(*ifp), "ifinit ifp");
+ memcpy(ifp, &ifs, sizeof(*ifp));
get_parms(ifp);
if_link(ifp);
trace_if("Add", ifp);
@@ -1138,14 +1179,18 @@ ifinit(void)
rtdelete(rt);
rt = 0;
} else {
+ loop_rts.rts_ifp = ifp;
+ loop_rts.rts_metric = 0;
+ loop_rts.rts_time = rt->rt_time;
rtchange(rt, rt->rt_state | RS_MHOME,
- loopaddr, loopaddr,
- 0, 0, ifp, rt->rt_time, 0);
+ &loop_rts, 0);
}
}
- if (rt == 0)
- rtadd(myaddr, HOST_MASK, loopaddr, loopaddr,
- 0, 0, RS_MHOME, ifp);
+ if (rt == 0) {
+ loop_rts.rts_ifp = ifp;
+ loop_rts.rts_metric = 0;
+ rtadd(myaddr, HOST_MASK, RS_MHOME, &loop_rts);
+ }
}
for (ifp = ifnet; ifp != 0; ifp = ifp1) {
@@ -1190,7 +1235,7 @@ ifinit(void)
/* Delete any routes to the network address through
* foreign routers. Remove even static routes.
*/
- del_static(ifp->int_addr, HOST_MASK, 0);
+ del_static(ifp->int_addr, HOST_MASK, 0, 0);
rt = rtget(ifp->int_addr, HOST_MASK);
if (rt != 0 && rt->rt_router != loopaddr) {
rtdelete(rt);
@@ -1203,14 +1248,17 @@ ifinit(void)
} 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);
+ loop_rts.rts_ifp = ifp1;
+ loop_rts.rts_metric = 0;
+ loop_rts.rts_time = rt->rt_time;
+ rtchange(rt, ((rt->rt_state & ~RS_NET_SYN)
+ | (RS_IF|RS_LOCAL)),
+ &loop_rts, 0);
} else {
+ loop_rts.rts_ifp = ifp;
+ loop_rts.rts_metric = 0;
rtadd(ifp->int_addr, HOST_MASK,
- loopaddr, loopaddr,
- 0, 0, (RS_IF | RS_LOCAL), ifp);
+ (RS_IF | RS_LOCAL), &loop_rts);
}
}
}
@@ -1224,10 +1272,12 @@ ifinit(void)
rtdelete(rt);
rt = 0;
}
- if (rt == 0)
+ if (rt == 0) {
+ loop_rts.rts_ifp = 0;
+ loop_rts.rts_metric = intnetp->intnet_metric-1;
rtadd(intnetp->intnet_addr, intnetp->intnet_mask,
- loopaddr, loopaddr, intnetp->intnet_metric-1,
- 0, RS_NET_SYN | RS_NET_INT, 0);
+ RS_NET_SYN | RS_NET_INT, &loop_rts);
+ }
}
prev_complaints = complaints;
@@ -1238,6 +1288,7 @@ static void
check_net_syn(struct interface *ifp)
{
struct rt_entry *rt;
+ static struct rt_spare new;
/* Turn on the need to automatically synthesize a network route
@@ -1254,10 +1305,14 @@ check_net_syn(struct interface *ifp)
rtdelete(rt);
rt = 0;
}
- if (rt == 0)
+ if (rt == 0) {
+ new.rts_ifp = ifp;
+ new.rts_gate = ifp->int_addr;
+ new.rts_router = ifp->int_addr;
+ new.rts_metric = ifp->int_metric;
rtadd(ifp->int_std_addr, ifp->int_std_mask,
- ifp->int_addr, ifp->int_addr,
- ifp->int_metric, 0, RS_NET_SYN, ifp);
+ RS_NET_SYN, &new);
+ }
} else {
ifp->int_state &= ~IS_NEED_NET_SYN;
@@ -1280,7 +1335,8 @@ int /* 0=bad interface */
addrouteforif(struct interface *ifp)
{
struct rt_entry *rt;
- naddr dst, gate;
+ static struct rt_spare new;
+ naddr dst;
/* skip sick interfaces
@@ -1294,11 +1350,16 @@ addrouteforif(struct interface *ifp)
if (ifp->int_state & IS_SUBNET)
check_net_syn(ifp);
- gate = ifp->int_addr;
dst = (0 != (ifp->int_if_flags & (IFF_POINTOPOINT | IFF_LOOPBACK))
? ifp->int_dstaddr
: htonl(ifp->int_net));
+ new.rts_ifp = ifp;
+ new.rts_router = ifp->int_addr;
+ new.rts_gate = ifp->int_addr;
+ new.rts_metric = ifp->int_metric;
+ new.rts_time = now.tv_sec;
+
/* If we are going to send packets to the gateway,
* it must be reachable using our physical interfaces
*/
@@ -1311,7 +1372,7 @@ addrouteforif(struct interface *ifp)
* 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);
+ del_static(dst, ifp->int_mask, 0, 0);
rt = rtget(dst, ifp->int_mask);
if (rt != 0) {
if ((rt->rt_ifp != ifp
@@ -1324,8 +1385,7 @@ addrouteforif(struct interface *ifp)
} 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);
+ &new, 0);
}
}
if (rt == 0) {
@@ -1333,8 +1393,7 @@ addrouteforif(struct interface *ifp)
trace_act("re-install interface %s",
ifp->int_name);
- rtadd(dst, ifp->int_mask, gate, gate,
- ifp->int_metric, 0, RS_IF, ifp);
+ rtadd(dst, ifp->int_mask, RS_IF, &new);
}
return 1;
diff --git a/sbin/routed/input.c b/sbin/routed/input.c
index 0e2c16fd7414..55162fcd87be 100644
--- a/sbin/routed/input.c
+++ b/sbin/routed/input.c
@@ -11,7 +11,7 @@
* 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:
+ * must display the following acknowledgment:
* 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
@@ -31,19 +31,19 @@
* SUCH DAMAGE.
*/
-#if !defined(lint) && !defined(sgi) && !defined(__NetBSD__)
-static char sccsid[] = "@(#)input.c 8.1 (Berkeley) 6/5/93";
+#include "defs.h"
+
+#if !defined(sgi) && !defined(__NetBSD__)
+static char sccsid[] __attribute__((unused)) = "@(#)input.c 8.1 (Berkeley) 6/5/93";
#elif defined(__NetBSD__)
-static char rcsid[] = "$NetBSD$";
+#include <sys/cdefs.h>
+__RCSID("$NetBSD$");
#endif
-#ident "$Revision: 1.21 $"
-
-#include "defs.h"
+#ident "$Revision: 2.17 $"
static void input(struct sockaddr_in *, struct interface *, struct interface *,
struct rip *, int);
-static void input_route(struct interface *, naddr,
- naddr, naddr, naddr, struct netinfo *);
+static void input_route(naddr, naddr, struct rt_spare *, struct netinfo *);
static int ck_passwd(struct interface *, struct rip *, void *,
naddr, struct msg_limit *);
@@ -140,14 +140,17 @@ input(struct sockaddr_in *from, /* received from this IP address */
{
# define FROM_NADDR from->sin_addr.s_addr
static struct msg_limit use_auth, bad_len, bad_mask;
- static struct msg_limit unk_router, bad_router, bad_nhop;
+ static struct msg_limit unk_router, bad_router, bad_nhop;
struct rt_entry *rt;
+ struct rt_spare new;
struct netinfo *n, *lim;
struct interface *ifp1;
- naddr gate, mask, v1_mask, dst, ddst_h;
+ naddr gate, mask, v1_mask, dst, ddst_h = 0;
struct auth *ap;
- int i;
+ struct tgate *tg = 0;
+ struct tgate_net *tn;
+ int i, j;
/* Notice when we hear from a remote gateway
*/
@@ -165,7 +168,7 @@ input(struct sockaddr_in *from, /* received from this IP address */
} else if (rip->rip_vers > RIPv2) {
rip->rip_vers = RIPv2;
}
- if (cc > OVER_MAXPACKETSIZE) {
+ if (cc > (int)OVER_MAXPACKETSIZE) {
msglim(&bad_router, FROM_NADDR,
"packet at least %d bytes too long received from %s",
cc-MAXPACKETSIZE, naddr_ntoa(FROM_NADDR));
@@ -181,7 +184,7 @@ input(struct sockaddr_in *from, /* received from this IP address */
*
* RIPv2 authentication is lame. Why authenticate queries?
* Why should a RIPv2 implementation with authentication disabled
- * not be able to listen to RIPv2 packets with authenication, while
+ * not be able to listen to RIPv2 packets with authentication, while
* RIPv1 systems will listen? Crazy!
*/
if (!auth_ok
@@ -231,7 +234,7 @@ input(struct sockaddr_in *from, /* received from this IP address */
}
}
- /* According to RFC 1723, we should ignore unathenticated
+ /* According to RFC 1723, we should ignore unauthenticated
* 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? When RIP
@@ -282,10 +285,10 @@ input(struct sockaddr_in *from, /* received from this IP address */
*/
if (n->n_family == RIP_AF_UNSPEC
&& n->n_metric == HOPCNT_INFINITY) {
+ /* Answer a query from a utility program
+ * with all we know.
+ */
if (from->sin_port != htons(RIP_PORT)) {
- /* Answer a query from a utility
- * program with all we know.
- */
supply(from, aifp, OUT_QUERY, 0,
rip->rip_vers, ap != 0);
return;
@@ -297,11 +300,7 @@ input(struct sockaddr_in *from, /* received from this IP address */
*
* Only answer a router if we are a supplier
* to keep an unwary host that is just starting
- * from picking us as a router. Respond with
- * RIPv1 instead of RIPv2 if that is what we
- * are broadcasting on the interface to keep
- * the remote router from getting the wrong
- * initial idea of the routes we send.
+ * from picking us as a router.
*/
if (aifp == 0) {
trace_pkt("ignore distant router");
@@ -313,8 +312,36 @@ input(struct sockaddr_in *from, /* received from this IP address */
return;
}
+ /* Do not answer a RIPv1 router if
+ * we are sending RIPv2. But do offer
+ * poor man's router discovery.
+ */
+ if ((aifp->int_state & IS_NO_RIPV1_OUT)
+ && rip->rip_vers == RIPv1) {
+ if (!(aifp->int_state & IS_PM_RDISC)) {
+ trace_pkt("ignore; sending RIPv2");
+ return;
+ }
+
+ v12buf.n->n_family = RIP_AF_INET;
+ v12buf.n->n_dst = RIP_DEFAULT;
+ i = aifp->int_d_metric;
+ if (0 != (rt = rtget(RIP_DEFAULT, 0)))
+ i = MIN(i, (rt->rt_metric
+ +aifp->int_metric+1));
+ v12buf.n->n_metric = htonl(i);
+ v12buf.n++;
+ break;
+ }
+
+ /* Respond with RIPv1 instead of RIPv2 if
+ * that is what we are broadcasting on the
+ * interface to keep the remote router from
+ * getting the wrong initial idea of the
+ * routes we send.
+ */
supply(from, aifp, OUT_UNICAST, 0,
- (aifp->int_state&IS_NO_RIPV1_OUT)
+ (aifp->int_state & IS_NO_RIPV1_OUT)
? RIPv2 : RIPv1,
ap != 0);
return;
@@ -326,8 +353,8 @@ input(struct sockaddr_in *from, /* received from this IP address */
if (n->n_family != RIP_AF_INET) {
msglim(&bad_router, FROM_NADDR,
- "request from %s for unsupported (af"
- " %d) %s",
+ "request from %s for unsupported"
+ " (af %d) %s",
naddr_ntoa(FROM_NADDR),
ntohs(n->n_family),
naddr_ntoa(n->n_dst));
@@ -417,7 +444,13 @@ input(struct sockaddr_in *from, /* received from this IP address */
case RIPCMD_TRACEON:
case RIPCMD_TRACEOFF:
- /* verify message came from a privileged port */
+ /* Notice that trace messages are turned off for all possible
+ * abuse if _PATH_TRACE is undefined in pathnames.h.
+ * Notice also that because of the way the trace file is
+ * handled in trace.c, no abuse is plausible even if
+ * _PATH_TRACE_ is defined.
+ *
+ * First 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));
@@ -433,7 +466,7 @@ input(struct sockaddr_in *from, /* received from this IP address */
set_tracefile((char*)rip->rip_tracefile,
"trace command: %s\n", 0);
} else {
- trace_off("tracing turned off by %s\n",
+ trace_off("tracing turned off by %s",
naddr_ntoa(FROM_NADDR));
}
return;
@@ -511,7 +544,7 @@ input(struct sockaddr_in *from, /* received from this IP address */
/* Ignore routes via dead interface.
*/
if (aifp->int_state & IS_BROKE) {
- trace_pkt("%sdiscard response via broken interface %s",
+ trace_pkt("discard response via broken interface %s",
aifp->int_name);
return;
}
@@ -521,7 +554,7 @@ input(struct sockaddr_in *from, /* received from this IP address */
* happens, it happens frequently.
*/
if (aifp->int_state & IS_DISTRUST) {
- struct tgate *tg = tgates;
+ tg = tgates;
while (tg->tgate_addr != FROM_NADDR) {
tg = tg->tgate_next;
if (tg == 0) {
@@ -581,7 +614,7 @@ input(struct sockaddr_in *from, /* received from this IP address */
*/
gate = FROM_NADDR;
if (n->n_nhop != 0) {
- if (rip->rip_vers == RIPv2) {
+ if (rip->rip_vers == RIPv1) {
n->n_nhop = 0;
} else {
/* Use it only if it is valid. */
@@ -607,9 +640,9 @@ input(struct sockaddr_in *from, /* received from this IP address */
} else if ((ntohl(dst) & ~mask) != 0) {
msglim(&bad_mask, FROM_NADDR,
"router %s sent bad netmask"
- " %#x with %s",
+ " %#lx with %s",
naddr_ntoa(FROM_NADDR),
- mask,
+ (u_long)mask,
naddr_ntoa(dst));
continue;
}
@@ -622,6 +655,20 @@ input(struct sockaddr_in *from, /* received from this IP address */
if (n->n_metric > HOPCNT_INFINITY)
n->n_metric = HOPCNT_INFINITY;
+ /* Should we trust this route from this router? */
+ if (tg && (tn = tg->tgate_nets)->mask != 0) {
+ for (i = 0; i < MAX_TGATE_NETS; i++, tn++) {
+ if (on_net(dst, tn->net, tn->mask)
+ && tn->mask <= mask)
+ break;
+ }
+ if (i >= MAX_TGATE_NETS || tn->mask == 0) {
+ trace_pkt(" ignored unauthorized %s",
+ addrname(dst,mask,0));
+ continue;
+ }
+ }
+
/* Recognize and ignore a default route we faked
* which is being sent back to us by a machine with
* broken split-horizon.
@@ -630,7 +677,7 @@ input(struct sockaddr_in *from, /* received from this IP address */
*/
if (aifp->int_d_metric != 0
&& dst == RIP_DEFAULT
- && n->n_metric >= aifp->int_d_metric)
+ && (int)n->n_metric >= aifp->int_d_metric)
continue;
/* We can receive aggregated RIPv2 routes that must
@@ -663,13 +710,12 @@ input(struct sockaddr_in *from, /* received from this IP address */
/* 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
+ if (TRACECONTENTS)
+ trace_misc("accept %s-->%s as 1"
+ " instead of %d routes",
+ addrname(dst,mask,0),
+ naddr_ntoa(FROM_NADDR),
+ i+1);
i = 0;
} else {
mask = v1_mask;
@@ -678,10 +724,17 @@ input(struct sockaddr_in *from, /* received from this IP address */
i = 0;
}
+ new.rts_gate = gate;
+ new.rts_router = FROM_NADDR;
+ new.rts_metric = n->n_metric;
+ new.rts_tag = n->n_tag;
+ new.rts_time = now.tv_sec;
+ new.rts_ifp = aifp;
+ new.rts_de_ag = i;
+ j = 0;
for (;;) {
- input_route(aifp, FROM_NADDR,
- dst, mask, gate, n);
- if (i-- == 0)
+ input_route(dst, mask, &new, n);
+ if (++j > i)
break;
dst = htonl(ntohl(dst) + ddst_h);
}
@@ -695,18 +748,15 @@ input(struct sockaddr_in *from, /* received from this IP address */
/* Process a single input route.
*/
static void
-input_route(struct interface *ifp,
- naddr from,
- naddr dst,
+input_route(naddr dst, /* network order */
naddr mask,
- naddr gate,
+ struct rt_spare *new,
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.
@@ -730,7 +780,7 @@ input_route(struct interface *ifp,
if (rt == 0) {
/* Ignore unknown routes being poisoned.
*/
- if (n->n_metric == HOPCNT_INFINITY)
+ if (new->rts_metric == HOPCNT_INFINITY)
return;
/* Ignore the route if it points to us */
@@ -742,8 +792,7 @@ input_route(struct interface *ifp,
* our memory, accept the new route.
*/
if (total_routes < MAX_ROUTES)
- rtadd(dst, mask, gate, from, n->n_metric,
- n->n_tag, 0, ifp);
+ rtadd(dst, mask, 0, new);
return;
}
@@ -768,7 +817,7 @@ input_route(struct interface *ifp,
rts0 = rt->rt_spares;
for (rts = rts0, i = NUM_SPARES; i != 0; i--, rts++) {
- if (rts->rts_router == from)
+ if (rts->rts_router == new->rts_router)
break;
/* Note the worst slot to reuse,
* other than the current slot.
@@ -778,26 +827,34 @@ input_route(struct interface *ifp,
rts0 = rts;
}
if (i != 0) {
- /* Found the router
+ /* Found a route from the router already in the table.
+ */
+
+ /* If the new route is a route broken down from an
+ * aggregated route, and if the previous route is either
+ * not a broken down route or was broken down from a finer
+ * netmask, and if the previous route is current,
+ * then forget this one.
*/
- int old_metric = rts->rts_metric;
+ if (new->rts_de_ag > rts->rts_de_ag
+ && now_stale <= rts->rts_time)
+ return;
/* Keep poisoned routes around only long enough to pass
- * the poison on. Get a new timestamp for good routes.
+ * the poison on. Use a new timestamp for good routes.
*/
- new_time =((old_metric == HOPCNT_INFINITY)
- ? rts->rts_time
- : now.tv_sec);
+ if (rts->rts_metric == HOPCNT_INFINITY
+ && new->rts_metric == HOPCNT_INFINITY)
+ new->rts_time = rts->rts_time;
/* 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);
+ rtchange(rt, rt->rt_state, new, 0);
/* If the route got worse, check for something better.
*/
- if (n->n_metric > old_metric)
+ if (new->rts_metric > rts->rts_metric)
rtswitch(rt, 0);
return;
}
@@ -805,10 +862,17 @@ input_route(struct interface *ifp,
/* 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;
+ if (rts->rts_gate == new->rts_gate
+ && rts->rts_metric == new->rts_metric
+ && rts->rts_tag == new->rts_tag) {
+ trace_upslot(rt, rts, new);
+ *rts = *new;
+ return;
+ }
+ /* Forget it if it has gone bad.
+ */
+ if (new->rts_metric == HOPCNT_INFINITY) {
+ rts_delete(rt, rts);
return;
}
@@ -822,6 +886,7 @@ input_route(struct interface *ifp,
&& 0 != ifwithaddr(n->n_nhop, 1, 0))
return;
+ /* the loop above set rts0=worst spare */
rts = rts0;
/* Save the route as a spare only if it has
@@ -829,20 +894,12 @@ input_route(struct interface *ifp,
* This also ignores poisoned routes (those
* received with metric HOPCNT_INFINITY).
*/
- if (n->n_metric >= rts->rts_metric)
+ if (new->rts_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;
+ trace_upslot(rt, rts, new);
+ *rts = *new;
/* try to switch to a better route */
rtswitch(rt, rts);
@@ -861,7 +918,7 @@ ck_passwd(struct interface *aifp,
struct auth *ap;
MD5_CTX md5_ctx;
u_char hash[RIP_AUTH_PW_LEN];
- int i;
+ int i, len;
if ((void *)NA >= lim || NA->a_family != RIP_AF_AUTH) {
@@ -879,7 +936,7 @@ ck_passwd(struct interface *aifp,
continue;
if (NA->a_type == RIP_AUTH_PW) {
- if (!bcmp(NA->au.au_pw, ap->key, RIP_AUTH_PW_LEN))
+ if (!memcmp(NA->au.au_pw, ap->key, RIP_AUTH_PW_LEN))
return 1;
} else {
@@ -888,28 +945,52 @@ ck_passwd(struct interface *aifp,
if (NA->au.a_md5.md5_keyid != ap->keyid)
continue;
- na2 = (struct netauth *)((char *)(NA+1)
- + NA->au.a_md5.md5_pkt_len);
- if (NA->au.a_md5.md5_pkt_len % sizeof(*NA) != 0
- || lim < (void *)(na2+1)) {
+ len = ntohs(NA->au.a_md5.md5_pkt_len);
+ if ((len-sizeof(*rip)) % sizeof(*NA) != 0
+ || len != (char *)lim-(char*)rip-(int)sizeof(*NA)) {
msglim(use_authp, from,
- "bad MD5 RIP-II pkt length %d from %s",
- NA->au.a_md5.md5_pkt_len,
+ "wrong MD5 RIPv2 packet length of %d"
+ " instead of %d from %s",
+ len, (int)((char *)lim-(char *)rip
+ -sizeof(*NA)),
naddr_ntoa(from));
return 0;
}
+ na2 = (struct netauth *)((char *)rip+len);
+
+ /* Given a good hash value, these are not security
+ * problems so be generous and accept the routes,
+ * after complaining.
+ */
+ if (TRACEPACKETS) {
+ if (NA->au.a_md5.md5_auth_len
+ != RIP_AUTH_MD5_LEN)
+ msglim(use_authp, from,
+ "unknown MD5 RIPv2 auth len %#x"
+ " instead of %#x from %s",
+ NA->au.a_md5.md5_auth_len,
+ RIP_AUTH_MD5_LEN,
+ naddr_ntoa(from));
+ if (na2->a_family != RIP_AF_AUTH)
+ msglim(use_authp, from,
+ "unknown MD5 RIPv2 family %#x"
+ " instead of %#x from %s",
+ na2->a_family, RIP_AF_AUTH,
+ naddr_ntoa(from));
+ if (na2->a_type != ntohs(1))
+ msglim(use_authp, from,
+ "MD5 RIPv2 hash has %#x"
+ " instead of %#x from %s",
+ na2->a_type, ntohs(1),
+ naddr_ntoa(from));
+ }
+
MD5Init(&md5_ctx);
- MD5Update(&md5_ctx, (u_char *)NA,
- (char *)na2->au.au_pw - (char *)NA);
- MD5Update(&md5_ctx,
- (u_char *)ap->key, sizeof(ap->key));
+ MD5Update(&md5_ctx, (u_char *)rip, len);
+ MD5Update(&md5_ctx, ap->key, RIP_AUTH_MD5_LEN);
MD5Final(hash, &md5_ctx);
- if (na2->a_family != RIP_AF_AUTH
- || na2->a_type != 1
- || NA->au.a_md5.md5_auth_len != RIP_AUTH_PW_LEN
- || bcmp(hash, na2->au.au_pw, sizeof(hash)))
- return 0;
- return 1;
+ if (!memcmp(hash, na2->au.au_pw, sizeof(hash)))
+ return 1;
}
}
diff --git a/sbin/routed/main.c b/sbin/routed/main.c
index 58cce95616fc..3d88c83f7c39 100644
--- a/sbin/routed/main.c
+++ b/sbin/routed/main.c
@@ -11,7 +11,7 @@
* 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:
+ * must display the following acknowledgment:
* 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
@@ -31,16 +31,6 @@
* 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.20 $"
-
#include "defs.h"
#include "pathnames.h"
#ifdef sgi
@@ -50,11 +40,26 @@ static char rcsid[] = "$NetBSD$";
#include <fcntl.h>
#include <sys/file.h>
+#if !defined(sgi) && !defined(__NetBSD__)
+char copyright[] =
+"@(#) Copyright (c) 1983, 1988, 1993\n\
+ The Regents of the University of California. All rights reserved.\n";
+static char sccsid[] __attribute__((unused)) = "@(#)main.c 8.1 (Berkeley) 6/5/93";
+#elif defined(__NetBSD__)
+__RCSID("$NetBSD$");
+__COPYRIGHT("@(#) Copyright (c) 1983, 1988, 1993\n\
+ The Regents of the University of California. All rights reserved.\n");
+#endif
+#ident "$Revision: 2.17 $"
+
+
pid_t mypid;
naddr myaddr; /* system address */
char myname[MAXHOSTNAMELEN+1];
+int verbose;
+
int supplier; /* supply or broadcast updates */
int supplier_set;
int ipforwarding = 1; /* kernel forwarding on */
@@ -63,11 +68,12 @@ 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 advertise_mhome; /* 1=must continue advertising it */
int auth_ok = 1; /* 1=ignore auth if we do not care */
struct timeval epoch; /* when started */
struct timeval clk, prev_clk;
+static int usec_fudge;
struct timeval now; /* current idea of time */
time_t now_stale;
time_t now_expire;
@@ -76,6 +82,8 @@ time_t now_garbage;
struct timeval next_bcast; /* next general broadcast */
struct timeval no_flash = {EPOCH+SUPPLY_INTERVAL}; /* inhibit flash update */
+struct timeval flush_kern_timer;
+
fd_set fdbits;
int sock_max;
int rip_sock = -1; /* RIP socket */
@@ -94,6 +102,7 @@ main(int argc,
int n, mib[4], off;
size_t len;
char *p, *q;
+ const char *cp;
struct timeval wtime, t2;
time_t dt;
fd_set ibits;
@@ -124,7 +133,7 @@ main(int argc,
(void)gethostname(myname, sizeof(myname)-1);
(void)gethost(myname, &myaddr);
- while ((n = getopt(argc, argv, "sqdghmpAtT:F:P:")) != EOF) {
+ while ((n = getopt(argc, argv, "sqdghmpAtvT:F:P:")) != -1) {
switch (n) {
case 's':
supplier = 1;
@@ -141,11 +150,11 @@ main(int argc,
break;
case 'g':
- bzero(&parm, sizeof(parm));
+ memset(&parm, 0, sizeof(parm));
parm.parm_d_metric = 1;
- p = check_parms(&parm);
- if (p != 0)
- msglog("bad -g: %s", p);
+ cp = check_parms(&parm);
+ if (cp != 0)
+ msglog("bad -g: %s", cp);
else
default_gateway = 1;
break;
@@ -188,26 +197,29 @@ main(int argc,
optarg);
break;
}
- bzero(&parm, sizeof(parm));
+ memset(&parm, 0, sizeof(parm));
parm.parm_net = p_net;
parm.parm_mask = p_mask;
parm.parm_d_metric = n;
- p = check_parms(&parm);
- if (p != 0)
- msglog("bad -F: %s", p);
+ cp = check_parms(&parm);
+ if (cp != 0)
+ msglog("bad -F: %s", cp);
break;
case 'P':
- /* handle arbirary, (usually) per-interface
- * parameters.
+ /* handle arbitrary parameters.
*/
- p = parse_parms(optarg, 0);
- if (p != 0) {
- if (strcasecmp(p,optarg))
- msglog("%s in \"%s\"", p, optarg);
- else
- msglog("bad \"-P %s\"", optarg);
- }
+ q = strdup(optarg);
+ cp = parse_parms(q, 0);
+ if (cp != 0)
+ msglog("%s in \"-P %s\"", cp, optarg);
+ free(q);
+ break;
+
+ case 'v':
+ /* display version */
+ verbose++;
+ msglog("version 2.17");
break;
default:
@@ -225,11 +237,14 @@ main(int argc,
goto usage;
if (argc != 0) {
usage:
- logbad(0, "usage: routed [-sqdghmpAt] [-T tracefile]"
+ logbad(0, "usage: routed [-sqdghmpAtv] [-T tracefile]"
" [-F net[,metric]] [-P parms]");
}
- if (geteuid() != 0)
+ if (geteuid() != 0) {
+ if (verbose)
+ exit(0);
logbad(0, "requires UID 0");
+ }
mib[0] = CTL_NET;
mib[1] = PF_INET;
@@ -270,12 +285,10 @@ usage:
/* get into the background */
#ifdef sgi
if (0 > _daemonize(background ? 0 : (_DF_NOCHDIR|_DF_NOFORK),
- new_tracelevel == 0 ? -1 : STDOUT_FILENO,
- new_tracelevel == 0 ? -1 : STDERR_FILENO,
- -1))
+ STDIN_FILENO, STDOUT_FILENO, STDERR_FILENO))
BADERR(0, "_daemonize()");
#else
- if (background && daemon(0, new_tracelevel) < 0)
+ if (background && daemon(0, 1) < 0)
BADERR(0,"daemon()");
#endif
@@ -297,13 +310,11 @@ usage:
fix_select();
- if (background && new_tracelevel == 0)
- ftrace = 0;
if (tracename != 0) {
strncpy(inittracename, tracename, sizeof(inittracename)-1);
- set_tracefile(inittracename, "%s\n", -1);
+ set_tracefile(inittracename, "%s", -1);
} else {
- tracelevel_msg("%s\n", -1); /* turn on tracing to stdio */
+ tracelevel_msg("%s", -1); /* turn on tracing to stdio */
}
bufinit();
@@ -329,28 +340,45 @@ usage:
*/
gwkludge();
ifinit();
- flush_kern();
/* Ask for routes */
rip_query();
rdisc_sol();
+ /* Now turn off stdio if not tracing */
+ if (new_tracelevel == 0)
+ trace_close(background);
+
/* 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.
+ if (prev_clk.tv_sec == clk.tv_sec
+ && prev_clk.tv_usec == clk.tv_usec+usec_fudge) {
+ /* Much of `routed` depends on time always advancing.
+ * On systems that do not guarantee that gettimeofday()
+ * produces unique timestamps even if called within
+ * a single tick, use trickery like that in classic
+ * BSD kernels.
*/
- dt = t2.tv_sec;
- if (dt > 0)
- dt -= wtime.tv_sec;
- trace_act("time changed by %d sec", dt);
- epoch.tv_sec += dt;
+ clk.tv_usec += ++usec_fudge;
+
+ } else {
+ usec_fudge = 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", (int)dt);
+ epoch.tv_sec += dt;
+ }
}
timevalsub(&now, &clk, &epoch);
now_stale = now.tv_sec - STALE_TIME;
@@ -363,7 +391,7 @@ usage:
if (stopint != 0) {
rip_bcast(0);
rdisc_adv();
- trace_off("exiting with signal %d\n", stopint);
+ trace_off("exiting with signal %d", stopint);
exit(stopint | 128);
}
@@ -376,6 +404,19 @@ usage:
continue;
}
+ /* Check the kernel table occassionally for mysteriously
+ * evaporated routes
+ */
+ timevalsub(&t2, &flush_kern_timer, &now);
+ if (t2.tv_sec <= 0) {
+ flush_kern();
+ flush_kern_timer.tv_sec = (now.tv_sec
+ + CHECK_QUIET_INTERVAL);
+ continue;
+ }
+ if (timercmp(&t2, &wtime, <))
+ wtime = t2;
+
/* If it is time, then broadcast our routes.
*/
if (supplier || advertise_mhome) {
@@ -391,7 +432,7 @@ usage:
/* 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
+ * scheduled, instead of 30 seconds after
* the previous update was finished.
* Even if we just started after discovering
* a 2nd interface or were otherwise delayed,
@@ -446,7 +487,7 @@ usage:
wtime = t2;
/* take care of router discovery,
- * but do it to the millisecond
+ * but do it in the correct the millisecond
*/
if (!timercmp(&rdisc_timer, &now, >)) {
rdisc_age(0);
@@ -494,7 +535,7 @@ usage:
/* ARGSUSED */
void
-sigalrm(int s)
+sigalrm(int s UNUSED)
{
/* Historically, SIGALRM would cause the daemon to check for
* new and broken interfaces.
@@ -547,7 +588,7 @@ fix_select(void)
void
fix_sock(int sock,
- char *name)
+ const char *name)
{
int on;
#define MIN_SOCKBUF (4*1024)
@@ -603,14 +644,14 @@ get_rip_sock(naddr addr,
if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
BADERR(1,"rip_sock = socket()");
- bzero(&sin,sizeof(sin));
+ memset(&sin, 0, 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 (bind(s, (struct sockaddr *)&sin, sizeof(sin)) < 0) {
if (serious)
BADERR(errno != EADDRINUSE, "bind(rip_sock)");
return -1;
@@ -631,7 +672,7 @@ void
rip_off(void)
{
struct interface *ifp;
- register naddr addr;
+ naddr addr;
if (rip_sock >= 0 && !mhome) {
@@ -700,8 +741,10 @@ rip_on(struct interface *ifp)
/* If the main RIP socket is off and it makes sense to turn it on,
* then turn it on for all of the interfaces.
+ * It makes sense if either router discovery is off, or if
+ * router discover is on and at most one interface is doing RIP.
*/
- if (rip_interfaces > 0 && !rdisc_ok) {
+ if (rip_interfaces > 0 && (!rdisc_ok || rip_interfaces > 1)) {
trace_act("turn on RIP");
/* Close all of the query sockets so that we can open
@@ -747,11 +790,11 @@ rip_on(struct interface *ifp)
*/
void *
rtmalloc(size_t size,
- char *msg)
+ const char *msg)
{
void *p = malloc(size);
if (p == 0)
- logbad(1,"malloc() failed in %s", msg);
+ logbad(1,"malloc(%lu) failed in %s", (u_long)size, msg);
return p;
}
@@ -776,7 +819,7 @@ timevaladd(struct timeval *t1,
{
t1->tv_sec += t2->tv_sec;
- if ((t1->tv_usec += t2->tv_usec) > 1000000) {
+ if ((t1->tv_usec += t2->tv_usec) >= 1000000) {
t1->tv_sec++;
t1->tv_usec -= 1000000;
}
@@ -801,7 +844,7 @@ timevalsub(struct timeval *t1,
/* put a message into the system log
*/
void
-msglog(char *p, ...)
+msglog(const char *p, ...)
{
va_list args;
@@ -827,12 +870,12 @@ msglog(char *p, ...)
* For example, there can be many systems with the wrong password.
*/
void
-msglim(struct msg_limit *lim, naddr addr, char *p, ...)
+msglim(struct msg_limit *lim, naddr addr, const char *p, ...)
{
va_list args;
int i;
struct msg_sub *ms1, *ms;
- char *p1;
+ const char *p1;
va_start(args, p);
@@ -882,7 +925,7 @@ msglim(struct msg_limit *lim, naddr addr, char *p, ...)
void
-logbad(int dump, char *p, ...)
+logbad(int dump, const char *p, ...)
{
va_list args;
diff --git a/sbin/routed/md5.c b/sbin/routed/md5.c
index dc52a8fdc96e..b0b98845746d 100644
--- a/sbin/routed/md5.c
+++ b/sbin/routed/md5.c
@@ -1,5 +1,3 @@
-/* This code could be made a lot faster for PPP */
-
/* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
* rights reserved.
*
@@ -22,7 +20,7 @@
* documentation and/or software.
*/
-#ident "$Revision: 1.4 $"
+#ident "$Revision: 2.16 $"
#include <strings.h>
#ifdef sgi
diff --git a/sbin/routed/output.c b/sbin/routed/output.c
index de8f97dd6329..fc832bf0f031 100644
--- a/sbin/routed/output.c
+++ b/sbin/routed/output.c
@@ -11,7 +11,7 @@
* 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:
+ * must display the following acknowledgment:
* 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
@@ -31,17 +31,17 @@
* SUCH DAMAGE.
*/
-#if !defined(lint) && !defined(sgi) && !defined(__NetBSD__)
-static char sccsid[] = "@(#)output.c 8.1 (Berkeley) 6/5/93";
+#include "defs.h"
+
+#if !defined(sgi) && !defined(__NetBSD__)
+static char sccsid[] __attribute__((unused)) = "@(#)output.c 8.1 (Berkeley) 6/5/93";
#elif defined(__NetBSD__)
-static char rcsid[] = "$NetBSD$";
+__RCSID("$NetBSD$");
#endif
-#ident "$Revision: 1.21 $"
-
-#include "defs.h"
+#ident "$Revision: 2.17 $"
-int update_seqno;
+u_int update_seqno;
/* walk the tree of routes with this for output
@@ -62,10 +62,9 @@ struct {
#define WS_ST_RIP2_ALL 0x002 /* send full featured RIPv2 */
#define WS_ST_AG 0x004 /* ok to aggregate subnets */
#define WS_ST_SUPER_AG 0x008 /* ok to aggregate networks */
-#define WS_ST_SUB_AG 0x010 /* aggregate subnets in odd case */
-#define WS_ST_QUERY 0x020 /* responding to a query */
-#define WS_ST_TO_ON_NET 0x040 /* sending onto one of our nets */
-#define WS_ST_DEFAULT 0x080 /* faking a default */
+#define WS_ST_QUERY 0x010 /* responding to a query */
+#define WS_ST_TO_ON_NET 0x020 /* sending onto one of our nets */
+#define WS_ST_DEFAULT 0x040 /* faking a default */
} ws;
/* A buffer for what can be heard by both RIPv1 and RIPv2 listeners */
@@ -103,7 +102,7 @@ output(enum output_type type,
{
struct sockaddr_in sin;
int flags;
- char *msg;
+ const char *msg;
int res;
naddr tgt_mcast;
int soc;
@@ -152,7 +151,7 @@ output(enum output_type type,
msg = "Send mcast";
if (rip_sock_mcast != ifp) {
#ifdef MCAST_PPP_BUG
- /* Do not specifiy the primary interface
+ /* Do not specify the primary interface
* explicitly if we have the multicast
* point-to-point kernel bug, since the
* kernel will do the wrong thing if the
@@ -212,7 +211,7 @@ output(enum output_type type,
/* Find the first key for a packet to send.
- * Try for a key that is eligable and has not expired, but settle for
+ * Try for a key that is eligible and has not expired, but settle for
* the last key if they have all expired.
* If no key is ready yet, give up.
*/
@@ -232,7 +231,7 @@ find_auth(struct interface *ifp)
/* stop looking after the last key */
if (ap->type == RIP_AUTH_NONE)
break;
-
+
/* ignore keys that are not ready yet */
if ((u_long)ap->start > (u_long)clk.tv_sec)
continue;
@@ -260,25 +259,26 @@ clr_ws_buf(struct ws_buf *wb,
wb->lim = wb->base + NETS_LEN;
wb->n = wb->base;
- bzero(wb->n, NETS_LEN*sizeof(*wb->n));
+ memset(wb->n, 0, NETS_LEN*sizeof(*wb->n));
- /* install authentication if appropriate
+ /* (start to) install authentication if appropriate
*/
if (ap == 0)
return;
+
na = (struct netauth*)wb->n;
if (ap->type == RIP_AUTH_PW) {
na->a_family = RIP_AF_AUTH;
na->a_type = RIP_AUTH_PW;
- bcopy(ap->key, na->au.au_pw, sizeof(na->au.au_pw));
+ memcpy(na->au.au_pw, ap->key, sizeof(na->au.au_pw));
wb->n++;
} else if (ap->type == RIP_AUTH_MD5) {
na->a_family = RIP_AF_AUTH;
na->a_type = RIP_AUTH_MD5;
na->au.a_md5.md5_keyid = ap->keyid;
- na->au.a_md5.md5_auth_len = RIP_AUTH_PW_LEN;
- na->au.a_md5.md5_seqno = clk.tv_sec;
+ na->au.a_md5.md5_auth_len = RIP_AUTH_MD5_LEN;
+ na->au.a_md5.md5_seqno = htonl(clk.tv_sec);
wb->n++;
wb->lim--; /* make room for trailer */
}
@@ -291,17 +291,18 @@ end_md5_auth(struct ws_buf *wb,
{
struct netauth *na, *na2;
MD5_CTX md5_ctx;
+ int len;
na = (struct netauth*)wb->base;
na2 = (struct netauth*)wb->n;
+ len = (char *)na2-(char *)wb->buf;
na2->a_family = RIP_AF_AUTH;
- na2->a_type = 1;
- bcopy(ap->key, na2->au.au_pw, sizeof(na2->au.au_pw));
- na->au.a_md5.md5_pkt_len = (char *)na2-(char *)(na+1);
+ na2->a_type = htons(1);
+ na->au.a_md5.md5_pkt_len = htons(len);
MD5Init(&md5_ctx);
- MD5Update(&md5_ctx, (u_char *)na,
- (char *)(na2+1) - (char *)na);
+ MD5Update(&md5_ctx, (u_char *)wb->buf, len);
+ MD5Update(&md5_ctx, ap->key, RIP_AUTH_MD5_LEN);
MD5Final(na2->au.au_pw, &md5_ctx);
wb->n++;
}
@@ -313,7 +314,7 @@ 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
+ * If we would multicast and it would be illegal, then discard the
* packet.
*/
switch (wb->type) {
@@ -355,11 +356,6 @@ supply_out(struct ag_info *ag)
&& (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),
@@ -395,13 +391,14 @@ supply_out(struct ag_info *ag)
/* 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
+ if (TRACECONTENTS)
+ trace_misc("sending %s-->%s as 1"
+ " instead of %d routes",
+ addrname(htonl(dst_h), mask,
+ 1),
+ naddr_ntoa(ws.to.sin_addr
+ .s_addr),
+ i+1);
i = 0;
} else {
@@ -450,12 +447,14 @@ supply_out(struct ag_info *ag)
/* ARGSUSED */
static int
walk_supply(struct radix_node *rn,
- struct walkarg *w)
+ struct walkarg *argp UNUSED)
{
#define RT ((struct rt_entry *)rn)
u_short ags;
char metric, pref;
naddr dst, nhop;
+ struct rt_spare *rts;
+ int i;
/* Do not advertise external remote interfaces or passive interfaces.
@@ -492,7 +491,7 @@ walk_supply(struct radix_node *rn,
} else {
/* Do not send automatic synthetic network routes
- * if they are not needed becaus no RIPv1 listeners
+ * if they are not needed because no RIPv1 listeners
* can hear them.
*/
if (ws.state & WS_ST_RIP2_ALL)
@@ -511,6 +510,7 @@ walk_supply(struct radix_node *rn,
/* 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.
+ * The final determination is made by supply_out().
*/
if (!(RT->rt_state & RS_IF)
&& RT->rt_gate != myaddr
@@ -528,23 +528,30 @@ walk_supply(struct radix_node *rn,
;
} else if (RT_ISHOST(RT)) {
- /* We should always aggregate the host routes
- * for the local end of our point-to-point links.
+ /* We should always suppress (into existing network routes)
+ * 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;
+ /* Aggregate stray host routes into network routes if allowed.
+ * We cannot aggregate host routes into small network routes
+ * without confusing RIPv1 listeners into thinking the
+ * network routes are host routes.
+ */
+ if ((ws.state & WS_ST_AG)
+ && !(ws.state & WS_ST_RIP2_ALL))
+ ags |= AGS_AGGREGATE;
- } else if (ws.state & WS_ST_AG) {
- /* Aggregate network routes, if we are allowed.
+ } else {
+ /* Always suppress network routes into other, existing
+ * network routes
*/
ags |= AGS_SUPPRESS;
@@ -553,10 +560,10 @@ walk_supply(struct radix_node *rn,
* 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;
-
+ if ((ws.state & WS_ST_AG)
+ && ((RT->rt_state & RS_SUBNET)
+ || (ws.state & WS_ST_SUPER_AG)))
+ ags |= AGS_AGGREGATE;
}
/* Do not send RIPv1 advertisements of subnets to other
@@ -564,11 +571,9 @@ walk_supply(struct radix_node *rn,
*/
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;
- }
+ && !on_net(dst, ws.to_std_net, ws.to_std_mask))
+ ags |= AGS_RIPV2 | AGS_AGGREGATE;
+
/* Do not send a route back to where it came from, except in
* response to a query. This is "split-horizon". That means not
@@ -577,61 +582,72 @@ walk_supply(struct radix_node *rn,
* 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.
+ * suppress the fragmented routes and then itself be forgotten.
*
* Include the routes for both ends of point-to-point interfaces
* among those suppressed by split-horizon, since the other side
* should knows them as well as we do.
+ *
+ * Notice spare routes with the same metric that we are about to
+ * advertise, to split the horizon on redundant, inactive paths.
*/
- if (RT->rt_ifp == ws.ifp && ws.ifp != 0
+ if (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)) {
- /* If we do not mark the route with AGS_SPLIT_HZ here,
- * it will be poisoned-reverse, or advertised back toward
- * its source with an infinite metric. If we have recently
- * advertised the route with a better metric than we now
- * have, then we should poison-reverse the route before
- * suppressing it for split-horizon.
- *
- * In almost all cases, if there is no spare for the route
- * then it is either old and dead or a brand new route.
- * If it is brand new, there is no need for poison-reverse.
- * If it is old and dead, it is already poisoned.
- */
- if (RT->rt_poison_time < now_expire
- || RT->rt_poison_metric >= metric
- || RT->rt_spares[1].rts_gate == 0) {
- ags |= AGS_SPLIT_HZ;
- ags &= ~(AGS_PROMOTE | AGS_SUPPRESS);
+ for (rts = RT->rt_spares, i = NUM_SPARES; i != 0; i--, rts++) {
+ if (rts->rts_metric > metric
+ || rts->rts_ifp != ws.ifp)
+ continue;
+
+ /* If we do not mark the route with AGS_SPLIT_HZ here,
+ * it will be poisoned-reverse, or advertised back
+ * toward its source with an infinite metric.
+ * If we have recently advertised the route with a
+ * better metric than we now have, then we should
+ * poison-reverse the route before suppressing it for
+ * split-horizon.
+ *
+ * In almost all cases, if there is no spare for the
+ * route then it is either old and dead or a brand
+ * new route. If it is brand new, there is no need
+ * for poison-reverse. If it is old and dead, it
+ * is already poisoned.
+ */
+ if (RT->rt_poison_time < now_expire
+ || RT->rt_poison_metric >= metric
+ || RT->rt_spares[1].rts_gate == 0) {
+ ags |= AGS_SPLIT_HZ;
+ ags &= ~AGS_SUPPRESS;
+ }
+ metric = HOPCNT_INFINITY;
+ break;
}
- metric = HOPCNT_INFINITY;
}
- /* Adjust the outgoing metric by the cost of the link.
+ /* Keep track of the best metric with which the
+ * route has been advertised recently.
*/
- pref = 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_expire) {
- RT->rt_poison_time = now.tv_sec;
- RT->rt_poison_metric = metric;
- }
- metric = pref;
+ if (RT->rt_poison_metric >= metric
+ || RT->rt_poison_time < now_expire) {
+ RT->rt_poison_time = now.tv_sec;
+ RT->rt_poison_metric = metric;
+ }
- } else {
- /* Do not advertise stable routes that will be ignored,
- * unless we are answering a query.
- * 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;
+ /* Adjust the outgoing metric by the cost of the link.
+ * Avoid aggregation when a route is counting to infinity.
+ */
+ pref = RT->rt_poison_metric + ws.metric;
+ metric += ws.metric;
+
+ /* Do not advertise stable routes that will be ignored,
+ * unless we are answering a query.
+ * 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.
+ */
+ if (metric >= HOPCNT_INFINITY) {
if (!(ws.state & WS_ST_QUERY)
&& (pref >= HOPCNT_INFINITY
|| RT->rt_poison_time < now_garbage))
@@ -686,8 +702,6 @@ supply(struct sockaddr_in *dst,
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;
@@ -701,44 +715,42 @@ supply(struct sockaddr_in *dst,
ripv12_buf.rip.rip_vers = vers;
switch (type) {
- case OUT_BROADCAST:
- v2buf.type = ((ifp != 0 && (ifp->int_if_flags & IFF_MULTICAST))
- ? OUT_MULTICAST
- : NO_OUT_MULTICAST);
- v12buf.type = OUT_BROADCAST;
- break;
case OUT_MULTICAST:
- v2buf.type = ((ifp != 0 && (ifp->int_if_flags & IFF_MULTICAST))
- ? OUT_MULTICAST
- : NO_OUT_MULTICAST);
+ if (ifp->int_if_flags & IFF_MULTICAST)
+ v2buf.type = OUT_MULTICAST;
+ else
+ v2buf.type = NO_OUT_MULTICAST;
v12buf.type = OUT_BROADCAST;
break;
- case OUT_UNICAST:
+
case OUT_QUERY:
+ ws.state |= WS_ST_QUERY;
+ /* fall through */
+ case OUT_BROADCAST:
+ case OUT_UNICAST:
v2buf.type = (vers == RIPv2) ? type : NO_OUT_RIPV2;
v12buf.type = type;
break;
- default:
- v2buf.type = type;
- v12buf.type = type;
- break;
+
+ case NO_OUT_MULTICAST:
+ case NO_OUT_RIPV2:
+ break; /* no output */
}
if (vers == RIPv2) {
/* 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)) {
+ if ((ws.state & WS_ST_QUERY)
+ || !(ws.state & WS_ST_TO_ON_NET)) {
ws.state |= (WS_ST_AG | WS_ST_SUPER_AG);
} else if (ifp == 0 || !(ifp->int_state & IS_NO_AG)) {
ws.state |= WS_ST_AG;
if (type != OUT_BROADCAST
- && (ifp == 0 || !(ifp->int_state&IS_NO_SUPER_AG)))
+ && (ifp == 0
+ || !(ifp->int_state & IS_NO_SUPER_AG)))
ws.state |= WS_ST_SUPER_AG;
}
-
- } else if (ifp == 0 || !(ifp->int_state & IS_NO_AG)) {
- ws.state |= WS_ST_SUB_AG;
}
ws.a = (vers == RIPv2) ? find_auth(ifp) : 0;
@@ -834,7 +846,7 @@ rip_bcast(int flash)
continue;
/* skip turned off interfaces */
- if (!iff_alive(ifp->int_if_flags))
+ if (!iff_up(ifp->int_if_flags))
continue;
vers = (ifp->int_state & IS_NO_RIPV1_OUT) ? RIPv2 : RIPv1;
@@ -843,11 +855,8 @@ rip_bcast(int flash)
/* 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)) {
+ && !(ifp->int_state & IS_NO_RIP_MCAST)) {
type = OUT_MULTICAST;
} else {
type = OUT_BROADCAST;
@@ -895,7 +904,7 @@ rip_query(void)
if (rip_sock < 0)
return;
- bzero(&buf, sizeof(buf));
+ memset(&buf, 0, sizeof(buf));
for (ifp = ifnet; ifp; ifp = ifp->int_next) {
/* Skip interfaces those already queried.
@@ -909,7 +918,7 @@ rip_query(void)
continue;
/* skip turned off interfaces */
- if (!iff_alive(ifp->int_if_flags))
+ if (!iff_up(ifp->int_if_flags))
continue;
buf.rip_vers = (ifp->int_state&IS_NO_RIPV1_OUT) ? RIPv2:RIPv1;
@@ -917,14 +926,26 @@ rip_query(void)
buf.rip_nets[0].n_family = RIP_AF_UNSPEC;
buf.rip_nets[0].n_metric = htonl(HOPCNT_INFINITY);
+ /* Send a RIPv1 query only if allowed and if we will
+ * listen to RIPv1 routers.
+ */
+ if ((ifp->int_state & IS_NO_RIPV1_OUT)
+ || (ifp->int_state & IS_NO_RIPV1_IN)) {
+ buf.rip_vers = RIPv2;
+ } else {
+ buf.rip_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.
+
+ /* Broadcast RIPv1 queries and RIPv2 queries
+ * when the hardware cannot multicast.
*/
if (buf.rip_vers == RIPv2
- && (ifp->int_state & IS_NO_RIPV1_OUT)) {
+ && (ifp->int_if_flags & IFF_MULTICAST)
+ && !(ifp->int_state & IS_NO_RIP_MCAST)) {
type = OUT_MULTICAST;
} else {
type = OUT_BROADCAST;
diff --git a/sbin/routed/parms.c b/sbin/routed/parms.c
index 87ca4a810e26..da301fa3dc10 100644
--- a/sbin/routed/parms.c
+++ b/sbin/routed/parms.c
@@ -11,7 +11,7 @@
* 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:
+ * must display the following acknowledgment:
* 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
@@ -31,20 +31,21 @@
* 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.12 $"
-
#include "defs.h"
#include "pathnames.h"
#include <sys/stat.h>
+#if !defined(sgi) && !defined(__NetBSD__)
+static char sccsid[] __attribute__((unused)) = "@(#)if.c 8.1 (Berkeley) 6/5/93";
+#elif defined(__NetBSD__)
+__RCSID("$NetBSD$");
+#endif
+#ident "$Revision: 2.17 $"
+
struct parm *parms;
struct intnet *intnets;
+struct r1net *r1nets;
struct tgate *tgates;
@@ -53,7 +54,7 @@ struct tgate *tgates;
void
get_parms(struct interface *ifp)
{
- static warned_auth_in, warned_auth_out;
+ static int warned_auth_in, warned_auth_out;
struct parm *parmp;
int i, num_passwds = 0;
@@ -74,9 +75,9 @@ get_parms(struct interface *ifp)
if (parmp->parm_auth[0].type == RIP_AUTH_NONE
|| num_passwds >= MAX_AUTH_KEYS)
break;
- bcopy(&parmp->parm_auth[i],
- &ifp->int_auth[num_passwds++],
- sizeof(ifp->int_auth[0]));
+ memcpy(&ifp->int_auth[num_passwds++],
+ &parmp->parm_auth[i],
+ sizeof(ifp->int_auth[0]));
}
if (parmp->parm_rdisc_pref != 0)
ifp->int_rdisc_pref = parmp->parm_rdisc_pref;
@@ -109,9 +110,9 @@ get_parms(struct interface *ifp)
/* By default, point-to-point links should be passive
* about router-discovery for the sake of demand-dialing.
*/
- if (0 == (ifp->int_state & GROUP_IS_SOL))
+ if (0 == (ifp->int_state & GROUP_IS_SOL_OUT))
ifp->int_state |= IS_NO_SOL_OUT;
- if (0 == (ifp->int_state & GROUP_IS_ADV))
+ if (0 == (ifp->int_state & GROUP_IS_ADV_OUT))
ifp->int_state |= IS_NO_ADV_OUT;
}
@@ -163,13 +164,15 @@ gwkludge(void)
{
FILE *fp;
char *p, *lptr;
- char lbuf[200], net_host[5], dname[64+1+64+1], gname[64+1], qual[9];
+ const char *cp;
+ char lbuf[200], net_host[5], dname[64+1+64+1];
+ char gname[GNAME_LEN+1], qual[9];
struct interface *ifp;
naddr dst, netmask, gate;
- int metric, n;
+ int metric, n, lnum;
struct stat sb;
u_int state;
- char *type;
+ const char *type;
fp = fopen(_PATH_GATEWAYS, "r");
@@ -182,39 +185,36 @@ gwkludge(void)
return;
}
- for (;;) {
- if (0 == fgets(lbuf, sizeof(lbuf)-1, fp))
+ for (lnum = 1; ; lnum++) {
+ if (0 == fgets(lbuf, sizeof(lbuf), fp))
break;
lptr = lbuf;
while (*lptr == ' ')
lptr++;
- if (*lptr == '\n' /* ignore null and comment lines */
- || *lptr == '#')
- continue;
p = lptr+strlen(lptr)-1;
- while (*p == '\n' || *p == ' ')
+ while (*p == '\n'
+ || (*p == ' ' && (p == lptr+1 || *(p-1) != '\\')))
*p-- = '\0';
+ if (*lptr == '\0' /* ignore null and comment lines */
+ || *lptr == '#')
+ continue;
/* notice newfangled parameter lines
*/
if (strncasecmp("net", lptr, 3)
&& strncasecmp("host", lptr, 4)) {
- p = parse_parms(lptr,
- (sb.st_uid == 0
- && !(sb.st_mode&(S_IRWXG|S_IRWXO))));
- if (p != 0) {
- if (strcasecmp(p,lptr))
- msglog("%s in "_PATH_GATEWAYS
- " entry \"%s\"", p, lptr);
- else
- msglog("bad \"%s\" in "_PATH_GATEWAYS,
- lptr);
- }
+ cp = parse_parms(lptr,
+ (sb.st_uid == 0
+ && !(sb.st_mode&(S_IRWXG|S_IRWXO))));
+ if (cp != 0)
+ msglog("%s in line %d of "_PATH_GATEWAYS,
+ cp, lnum);
continue;
}
/* {net | host} XX[/M] XX gateway XX metric DD [passive | external]\n */
qual[0] = '\0';
+ /* the '64' here must be GNAME_LEN */
n = sscanf(lptr, "%4s %129[^ \t] gateway"
" %64[^ / \t] metric %u %8s\n",
net_host, dname, gname, &metric, qual);
@@ -241,10 +241,16 @@ gwkludge(void)
" entry \"%s\"", dname, lptr);
continue;
}
+ if (dst == RIP_DEFAULT) {
+ msglog("bad net \"%s\" in "_PATH_GATEWAYS
+ " entry \"%s\"--cannot be default",
+ dname, lptr);
+ continue;
+ }
HTONL(dst); /* make network # into IP address */
} else {
msglog("bad \"%s\" in "_PATH_GATEWAYS
- " entry \"%s\"", lptr);
+ " entry \"%s\"", net_host, lptr);
continue;
}
@@ -311,14 +317,14 @@ gwkludge(void)
continue;
}
- ifp = (struct interface *)malloc(sizeof(*ifp));
- bzero(ifp, sizeof(*ifp));
+ ifp = (struct interface *)rtmalloc(sizeof(*ifp), "gwkludge()");
+ memset(ifp, 0, sizeof(*ifp));
ifp->int_state = state;
if (netmask == HOST_MASK)
- ifp->int_if_flags = IFF_POINTOPOINT | IFF_UP_RUNNING;
+ ifp->int_if_flags = IFF_POINTOPOINT | IFF_UP;
else
- ifp->int_if_flags = IFF_UP_RUNNING;
+ ifp->int_if_flags = IFF_UP;
ifp->int_act_time = NEVER;
ifp->int_addr = gate;
ifp->int_dstaddr = dst;
@@ -355,16 +361,17 @@ gwkludge(void)
}
-/* strtok(), but honoring backslash
+/* like strtok(), but honoring backslash and not changing the source string
*/
static int /* 0=ok, -1=bad */
-parse_quote(char **linep,
- char *delims,
- char *delimp,
- char *buf,
- int lim)
+parse_quote(char **linep, /* look here */
+ const char *delims, /* for these delimiters */
+ char *delimp, /* 0 or put found delimiter here */
+ char *buf, /* copy token to here */
+ int lim) /* at most this many bytes */
{
- char c, *pc, *p;
+ char c = '\0', *pc;
+ const char *p;
pc = *linep;
@@ -376,7 +383,7 @@ parse_quote(char **linep,
if (c == '\0')
break;
- if (c == '\\' && pc != '\0') {
+ if (c == '\\' && *pc != '\0') {
if ((c = *pc++) == 'n') {
c = '\n';
} else if (c == 'r') {
@@ -408,10 +415,10 @@ exit:
if (lim == 0)
return -1;
- *buf = '\0';
+ *buf = '\0'; /* terminate copy of token */
if (delimp != 0)
- *delimp = c;
- *linep = pc-1;
+ *delimp = c; /* return delimiter */
+ *linep = pc-1; /* say where we ended */
return 0;
}
@@ -427,6 +434,9 @@ parse_ts(time_t *tp,
u_int bufsize)
{
struct tm tm;
+#if defined(sgi) || defined(__NetBSD__)
+ char *ptr;
+#endif
if (0 > parse_quote(valp, "| ,\n\r", delimp,
buf,bufsize)
@@ -436,15 +446,26 @@ parse_ts(time_t *tp,
return buf;
}
strcat(buf,"\n");
- bzero(&tm, sizeof(tm));
+ memset(&tm, 0, sizeof(tm));
+#if defined(sgi) || defined(__NetBSD__)
+ ptr = strptime(buf, "%y/%m/%d@%H:%M\n", &tm);
+ if (ptr == NULL || *ptr != '\0') {
+ sprintf(buf,"bad timestamp %.25s", val0);
+ return buf;
+ }
+#else
if (5 != sscanf(buf, "%u/%u/%u@%u:%u\n",
&tm.tm_year, &tm.tm_mon, &tm.tm_mday,
- &tm.tm_hour, &tm.tm_min)) {
+ &tm.tm_hour, &tm.tm_min)
+ || tm.tm_mon < 1 || tm.tm_mon > 12
+ || tm.tm_mday < 1 || tm.tm_mday > 31) {
sprintf(buf,"bad timestamp %.25s", val0);
return buf;
}
- if (tm.tm_year <= 37)
- tm.tm_year += 100;
+ tm.tm_mon--;
+ if (tm.tm_year <= 37) /* assume small years are in the */
+ tm.tm_year += 100; /* 3rd millenium */
+#endif
if ((*tp = mktime(&tm)) == -1) {
sprintf(buf,"bad timestamp %.25s", val0);
@@ -458,11 +479,11 @@ parse_ts(time_t *tp,
/* Get a password, key ID, and expiration date in the format
* passwd|keyID|year/mon/day@hour:min|year/mon/day@hour:min
*/
-static char * /* 0 or error message */
+static const char * /* 0 or error message */
get_passwd(char *tgt,
char *val,
struct parm *parmp,
- u_char type,
+ u_int16_t type,
int safe) /* 1=from secure file */
{
static char buf[80];
@@ -473,7 +494,7 @@ get_passwd(char *tgt,
if (!safe)
- return "unsafe password";
+ return "ignore unsafe password";
for (ap = parmp->parm_auth, i = 0;
ap->type != RIP_AUTH_NONE; i++, ap++) {
@@ -481,7 +502,7 @@ get_passwd(char *tgt,
return "too many passwords";
}
- bzero(&k, sizeof(k));
+ memset(&k, 0, sizeof(k));
k.type = type;
k.end = -1-DAY;
@@ -532,14 +553,24 @@ get_passwd(char *tgt,
if (delim != '\0')
return tgt;
- bcopy(&k, ap, sizeof(*ap));
+ memmove(ap, &k, sizeof(*ap));
return 0;
}
+static const char *
+bad_str(const char *estr)
+{
+ static char buf[100+8];
+
+ sprintf(buf, "bad \"%.100s\"", estr);
+ return buf;
+}
+
+
/* Parse a set of parameters for an interface.
*/
-char * /* 0 or error message */
+const char * /* 0 or error message */
parse_parms(char *line,
int safe) /* 1=from secure file */
{
@@ -549,30 +580,35 @@ parse_parms(char *line,
parm.parm_int_state |= (b);}
struct parm parm;
struct intnet *intnetp;
+ struct r1net *r1netp;
struct tgate *tg;
naddr addr, mask;
- char delim, *val0, *tgt, *val, *p;
- char buf[64];
+ char delim, *val0 = 0, *tgt, *val, *p;
+ const char *msg;
+ char buf[BUFSIZ], buf2[BUFSIZ];
+ int i;
- /* "subnet=x.y.z.u/mask,metric" must be alone on the line */
+ /* "subnet=x.y.z.u/mask[,metric]" must be alone on the line */
if (!strncasecmp(line, "subnet=", sizeof("subnet=")-1)
- && *(val = &line[sizeof("subnet=")]) != '\0') {
- intnetp = (struct intnet*)malloc(sizeof(*intnetp));
+ && *(val = &line[sizeof("subnet=")-1]) != '\0') {
+ if (0 > parse_quote(&val, ",", &delim, buf, sizeof(buf)))
+ return bad_str(line);
+ intnetp = (struct intnet*)rtmalloc(sizeof(*intnetp),
+ "parse_parms subnet");
intnetp->intnet_metric = 1;
- if ((p = strrchr(val,','))) {
- *p++ = '\0';
- intnetp->intnet_metric = (int)strtol(p,&p,0);
+ if (delim == ',') {
+ intnetp->intnet_metric = (int)strtol(val+1,&p,0);
if (*p != '\0'
|| intnetp->intnet_metric <= 0
|| intnetp->intnet_metric >= HOPCNT_INFINITY)
- return line;
+ return bad_str(line);
}
- if (!getnet(val, &intnetp->intnet_addr, &intnetp->intnet_mask)
+ if (!getnet(buf, &intnetp->intnet_addr, &intnetp->intnet_mask)
|| intnetp->intnet_mask == HOST_MASK
|| intnetp->intnet_addr == RIP_DEFAULT) {
free(intnetp);
- return line;
+ return bad_str(line);
}
HTONL(intnetp->intnet_addr);
intnetp->intnet_next = intnets;
@@ -580,29 +616,62 @@ parse_parms(char *line,
return 0;
}
- bzero(&parm, sizeof(parm));
+ /* "ripv1_mask=x.y.z.u/mask1,mask2" must be alone on the line.
+ * This requires that x.y.z.u/mask1 be considered a subnet of
+ * x.y.z.u/mask2, as if x.y.z.u/mask2 were a class-full network.
+ */
+ if (!strncasecmp(line, "ripv1_mask=", sizeof("ripv1_mask=")-1)
+ && *(val = &line[sizeof("ripv1_mask=")-1]) != '\0') {
+ if (0 > parse_quote(&val, ",", &delim, buf, sizeof(buf))
+ || delim == '\0')
+ return bad_str(line);
+ if ((i = (int)strtol(val+1, &p, 0)) <= 0
+ || i > 32 || *p != '\0')
+ return bad_str(line);
+ r1netp = (struct r1net *)rtmalloc(sizeof(*r1netp),
+ "parse_parms ripv1_mask");
+ r1netp->r1net_mask = HOST_MASK << (32-i);
+ if (!getnet(buf, &r1netp->r1net_net, &r1netp->r1net_match)
+ || r1netp->r1net_net == RIP_DEFAULT
+ || r1netp->r1net_mask > r1netp->r1net_match) {
+ free(r1netp);
+ return bad_str(line);
+ }
+ r1netp->r1net_next = r1nets;
+ r1nets = r1netp;
+ return 0;
+ }
+
+ memset(&parm, 0, sizeof(parm));
- tgt = "null";
for (;;) {
tgt = line + strspn(line, " ,\n\r");
- if (*tgt == '\0')
+ if (*tgt == '\0' || *tgt == '#')
break;
-
- line += strcspn(tgt, "= ,\n\r");
+ line = tgt+strcspn(tgt, "= #,\n\r");
delim = *line;
if (delim == '=') {
val0 = ++line;
- if (0 > parse_quote(&line," ,\n\r",&delim,
+ if (0 > parse_quote(&line, " #,\n\r",&delim,
buf,sizeof(buf)))
- return tgt;
+ return bad_str(tgt);
+ }
+ if (delim != '\0') {
+ for (;;) {
+ *line = '\0';
+ if (delim == '#')
+ break;
+ ++line;
+ if (delim != ' '
+ || (delim = *line) != ' ')
+ break;
+ }
}
- if (delim != '\0')
- *line++ = '\0';
if (PARSEQ("if")) {
if (parm.parm_name[0] != '\0'
- || strlen(buf) > IFNAMSIZ)
- return tgt;
+ || strlen(buf) > IF_NAME_LEN)
+ return bad_str(tgt);
strcpy(parm.parm_name, buf);
} else if (PARSEQ("addr")) {
@@ -614,7 +683,7 @@ parse_parms(char *line,
*/
if (!getnet(val0, &addr, &mask)
|| parm.parm_name[0] != '\0')
- return tgt;
+ return bad_str(tgt);
parm.parm_net = addr;
parm.parm_mask = mask;
parm.parm_name[0] = '\n';
@@ -623,17 +692,17 @@ parse_parms(char *line,
/* since cleartext passwords are so weak allow
* them anywhere
*/
- tgt = get_passwd(tgt,val0,&parm,RIP_AUTH_PW,1);
- if (tgt) {
+ msg = get_passwd(tgt,val0,&parm,RIP_AUTH_PW,1);
+ if (msg) {
*val0 = '\0';
- return tgt;
+ return bad_str(msg);
}
} else if (PARSEQ("md5_passwd")) {
- tgt = get_passwd(tgt,val0,&parm,RIP_AUTH_MD5,safe);
- if (tgt) {
+ msg = get_passwd(tgt,val0,&parm,RIP_AUTH_MD5,safe);
+ if (msg) {
*val0 = '\0';
- return tgt;
+ return bad_str(msg);
}
} else if (PARS("no_ag")) {
@@ -650,50 +719,53 @@ parse_parms(char *line,
} else if (PARS("ripv2_out")) {
if (parm.parm_int_state & IS_NO_RIPV2_OUT)
- return tgt;
+ return bad_str(tgt);
parm.parm_int_state |= IS_NO_RIPV1_OUT;
} else if (PARS("ripv2")) {
if ((parm.parm_int_state & IS_NO_RIPV2_OUT)
|| (parm.parm_int_state & IS_NO_RIPV2_IN))
- return tgt;
+ return bad_str(tgt);
parm.parm_int_state |= (IS_NO_RIPV1_IN
| IS_NO_RIPV1_OUT);
} else if (PARS("no_rip")) {
CKF(IS_PM_RDISC, IS_NO_RIP);
+ } else if (PARS("no_rip_mcast")) {
+ parm.parm_int_state |= IS_NO_RIP_MCAST;
+
} else if (PARS("no_rdisc")) {
- CKF((GROUP_IS_SOL|GROUP_IS_ADV), IS_NO_RDISC);
+ CKF((GROUP_IS_SOL_OUT|GROUP_IS_ADV_OUT), IS_NO_RDISC);
} else if (PARS("no_solicit")) {
- CKF(GROUP_IS_SOL, IS_NO_SOL_OUT);
+ CKF(GROUP_IS_SOL_OUT, IS_NO_SOL_OUT);
} else if (PARS("send_solicit")) {
- CKF(GROUP_IS_SOL, IS_SOL_OUT);
+ CKF(GROUP_IS_SOL_OUT, IS_SOL_OUT);
} else if (PARS("no_rdisc_adv")) {
- CKF(GROUP_IS_ADV, IS_NO_ADV_OUT);
+ CKF(GROUP_IS_ADV_OUT, IS_NO_ADV_OUT);
} else if (PARS("rdisc_adv")) {
- CKF(GROUP_IS_ADV, IS_ADV_OUT);
+ CKF(GROUP_IS_ADV_OUT, IS_ADV_OUT);
} else if (PARS("bcast_rdisc")) {
parm.parm_int_state |= IS_BCAST_RDISC;
} else if (PARS("passive")) {
- CKF((GROUP_IS_SOL|GROUP_IS_ADV), IS_NO_RDISC);
+ CKF((GROUP_IS_SOL_OUT|GROUP_IS_ADV_OUT), IS_NO_RDISC);
parm.parm_int_state |= IS_NO_RIP;
} else if (PARSEQ("rdisc_pref")) {
if (parm.parm_rdisc_pref != 0
- || (parm.parm_rdisc_pref = (int)strtoul(buf, &p,0),
+ || (parm.parm_rdisc_pref = (int)strtol(buf,&p,0),
*p != '\0'))
- return tgt;
+ return bad_str(tgt);
} else if (PARS("pm_rdisc")) {
if (IS_RIP_OUT_OFF(parm.parm_int_state))
- return tgt;
+ return bad_str(tgt);
parm.parm_int_state |= IS_PM_RDISC;
} else if (PARSEQ("rdisc_interval")) {
@@ -702,7 +774,7 @@ parse_parms(char *line,
*p != '\0')
|| parm.parm_rdisc_int < MinMaxAdvertiseInterval
|| parm.parm_rdisc_int > MaxMaxAdvertiseInterval)
- return tgt;
+ return bad_str(tgt);
} else if (PARSEQ("fake_default")) {
if (parm.parm_d_metric != 0
@@ -710,14 +782,35 @@ parse_parms(char *line,
|| (parm.parm_d_metric = (int)strtoul(buf,&p,0),
*p != '\0')
|| parm.parm_d_metric > HOPCNT_INFINITY-1)
- return tgt;
+ return bad_str(tgt);
} else if (PARSEQ("trust_gateway")) {
- if (!gethost(buf,&addr))
- return tgt;
- tg = (struct tgate *)malloc(sizeof(*tg));
- tg->tgate_next = tgates;
+ /* look for trust_gateway=x.y.z|net/mask|...) */
+ p = buf;
+ if (0 > parse_quote(&p, "|", &delim,
+ buf2, sizeof(buf2))
+ || !gethost(buf2,&addr))
+ return bad_str(tgt);
+ tg = (struct tgate *)rtmalloc(sizeof(*tg),
+ "parse_parms"
+ "trust_gateway");
+ memset(tg, 0, sizeof(*tg));
tg->tgate_addr = addr;
+ i = 0;
+ /* The default is to trust all routes. */
+ while (delim == '|') {
+ p++;
+ if (i >= MAX_TGATE_NETS
+ || 0 > parse_quote(&p, "|", &delim,
+ buf2, sizeof(buf2))
+ || !getnet(buf2, &tg->tgate_nets[i].net,
+ &tg->tgate_nets[i].mask)
+ || tg->tgate_nets[i].net == RIP_DEFAULT
+ || tg->tgate_nets[i].mask == 0)
+ return bad_str(tgt);
+ i++;
+ }
+ tg->tgate_next = tgates;
tgates = tg;
parm.parm_int_state |= IS_DISTRUST;
@@ -725,7 +818,7 @@ parse_parms(char *line,
parm.parm_int_state |= IS_REDIRECT_OK;
} else {
- return tgt; /* error */
+ return bad_str(tgt); /* error */
}
}
@@ -736,7 +829,7 @@ parse_parms(char *line,
/* check for duplicate parameter specifications */
-char * /* 0 or error message */
+const char * /* 0 or error message */
check_parms(struct parm *new)
{
struct parm *parmp, **parmpp;
@@ -746,6 +839,8 @@ check_parms(struct parm *new)
*/
if (new->parm_int_state & IS_NO_ADV_IN)
new->parm_int_state |= IS_NO_SOL_OUT;
+ if (new->parm_int_state & IS_NO_SOL_OUT)
+ new->parm_int_state |= IS_NO_ADV_IN;
for (i = num_passwds = 0; i < MAX_AUTH_KEYS; i++) {
if (new->parm_auth[i].type != RIP_AUTH_NONE)
@@ -772,14 +867,14 @@ check_parms(struct parm *new)
if (num_passwds > MAX_AUTH_KEYS)
return "too many conflicting passwords";
- if ((0 != (new->parm_int_state & GROUP_IS_SOL)
- && 0 != (parmp->parm_int_state & GROUP_IS_SOL)
+ if ((0 != (new->parm_int_state & GROUP_IS_SOL_OUT)
+ && 0 != (parmp->parm_int_state & GROUP_IS_SOL_OUT)
&& 0 != ((new->parm_int_state ^ parmp->parm_int_state)
- && GROUP_IS_SOL))
- || (0 != (new->parm_int_state & GROUP_IS_ADV)
- && 0 != (parmp->parm_int_state & GROUP_IS_ADV)
+ && GROUP_IS_SOL_OUT))
+ || (0 != (new->parm_int_state & GROUP_IS_ADV_OUT)
+ && 0 != (parmp->parm_int_state & GROUP_IS_ADV_OUT)
&& 0 != ((new->parm_int_state ^ parmp->parm_int_state)
- && GROUP_IS_ADV))
+ && GROUP_IS_ADV_OUT))
|| (new->parm_rdisc_pref != 0
&& parmp->parm_rdisc_pref != 0
&& new->parm_rdisc_pref != parmp->parm_rdisc_pref)
@@ -802,8 +897,8 @@ check_parms(struct parm *new)
/* link new entry on the so that when the entries are scanned,
* they affect the result in the order the operator specified.
*/
- parmp = (struct parm*)malloc(sizeof(*parmp));
- bcopy(new, parmp, sizeof(*parmp));
+ parmp = (struct parm*)rtmalloc(sizeof(*parmp), "check_parms");
+ memcpy(parmp, new, sizeof(*parmp));
*parmpp = parmp;
return 0;
@@ -815,7 +910,7 @@ check_parms(struct parm *new)
*/
int /* 0=bad */
getnet(char *name,
- naddr *netp, /* a network so host byte order */
+ naddr *netp, /* network in host byte order */
naddr *maskp) /* masks are always in host order */
{
int i;
@@ -828,11 +923,11 @@ getnet(char *name,
/* Detect and separate "1.2.3.4/24"
*/
- if (0 != (mname = rindex(name,'/'))) {
+ if (0 != (mname = strrchr(name,'/'))) {
i = (int)(mname - name);
- if (i > sizeof(hname)-1) /* name too long */
+ if (i > (int)sizeof(hname)-1) /* name too long */
return 0;
- bcopy(name, hname, i);
+ memmove(hname, name, i);
hname[i] = '\0';
mname++;
name = hname;
@@ -841,6 +936,12 @@ getnet(char *name,
np = getnetbyname(name);
if (np != 0) {
in.s_addr = (naddr)np->n_net;
+ if (0 == (in.s_addr & 0xff000000))
+ in.s_addr <<= 8;
+ if (0 == (in.s_addr & 0xff000000))
+ in.s_addr <<= 8;
+ if (0 == (in.s_addr & 0xff000000))
+ in.s_addr <<= 8;
} else if (inet_aton(name, &in) == 1) {
NTOHL(in.s_addr);
} else if (!mname && !strcasecmp(name,"default")) {
@@ -860,7 +961,8 @@ getnet(char *name,
mask = (naddr)strtoul(mname, &p, 0);
if (*p != '\0' || mask > 32)
return 0;
- mask = HOST_MASK << (32-mask);
+ if (mask != 0)
+ mask = HOST_MASK << (32-mask);
}
/* must have mask of 0 with default */
@@ -908,7 +1010,7 @@ gethost(char *name,
hp = gethostbyname(name);
if (hp) {
- bcopy(hp->h_addr, addrp, sizeof(*addrp));
+ memcpy(addrp, hp->h_addr, sizeof(*addrp));
return 1;
}
diff --git a/sbin/routed/pathnames.h b/sbin/routed/pathnames.h
index 14b721c2d473..317331068aa9 100644
--- a/sbin/routed/pathnames.h
+++ b/sbin/routed/pathnames.h
@@ -11,7 +11,7 @@
* 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:
+ * must display the following acknowledgment:
* 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
@@ -47,4 +47,8 @@
* Leave this undefined, and only the trace file originally specified
* when routed was started, if any, will be appended to.
*/
+#ifndef __NetBSD__
#define _PATH_TRACE "/etc/routed.trace"
+#else
+#undef _PATH_TRACE
+#endif
diff --git a/sbin/routed/radix.c b/sbin/routed/radix.c
index 7f7e1e47b79e..e92bcad2c05e 100644
--- a/sbin/routed/radix.c
+++ b/sbin/routed/radix.c
@@ -11,7 +11,7 @@
* 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:
+ * must display the following acknowledgment:
* 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
@@ -36,15 +36,16 @@
/*
* Routines to build and maintain radix trees for routing lookups.
*/
-#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.10 $"
#include "defs.h"
+#if !defined(sgi) && !defined(__NetBSD__)
+static char sccsid[] __attribute__((unused)) = "@(#)rdisc.c 8.1 (Berkeley) x/y/95";
+#elif defined(__NetBSD__)
+__RCSID("$NetBSD$");
+#endif
+#ident "$Revision: 2.17 $"
+
#define log(x, msg) syslog(x, msg)
#define panic(s) {log(LOG_ERR,s); exit(1);}
#define min(a,b) (((a)<(b))?(a):(b))
@@ -58,9 +59,10 @@ 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))
+#define Bcmp(a, b, l) (l == 0 ? 0 \
+ : memcmp((caddr_t)(a), (caddr_t)(b), (size_t)l))
-static int rn_satsifies_leaf(char *, struct radix_node *, int);
+static int rn_satisfies_leaf(char *, struct radix_node *, int);
/*
* The data structure for the keys is a radix tree with one way
@@ -100,8 +102,8 @@ struct radix_node *
rn_search(void *v_arg,
struct radix_node *head)
{
- register struct radix_node *x;
- register caddr_t v;
+ struct radix_node *x;
+ caddr_t v;
for (x = head, v = v_arg; x->rn_b >= 0;) {
if (x->rn_bmask & v[x->rn_off])
@@ -117,8 +119,8 @@ rn_search_m(void *v_arg,
struct radix_node *head,
void *m_arg)
{
- register struct radix_node *x;
- register caddr_t v = v_arg, m = m_arg;
+ struct radix_node *x;
+ caddr_t v = v_arg, m = m_arg;
for (x = head; x->rn_b >= 0;) {
if ((x->rn_bmask & m[x->rn_off]) &&
@@ -133,8 +135,8 @@ rn_search_m(void *v_arg,
int
rn_refines(void* m_arg, void *n_arg)
{
- register caddr_t m = m_arg, n = n_arg;
- register caddr_t lim, lim2 = lim = n + *(u_char *)n;
+ caddr_t m = m_arg, n = n_arg;
+ caddr_t lim, lim2 = lim = n + *(u_char *)n;
int longer = (*(u_char *)n++) - (int)(*(u_char *)m++);
int masks_are_equal = 1;
@@ -157,11 +159,9 @@ rn_refines(void* m_arg, void *n_arg)
}
struct radix_node *
-rn_lookup(v_arg, m_arg, head)
- void *v_arg, *m_arg;
- struct radix_node_head *head;
+rn_lookup(void *v_arg, void *m_arg, struct radix_node_head *head)
{
- register struct radix_node *x;
+ struct radix_node *x;
caddr_t netmask = 0;
if (m_arg) {
@@ -178,11 +178,11 @@ rn_lookup(v_arg, m_arg, head)
}
static int
-rn_satsifies_leaf(char *trial,
- register struct radix_node *leaf,
+rn_satisfies_leaf(char *trial,
+ struct radix_node *leaf,
int skip)
{
- register char *cp = trial, *cp2 = leaf->rn_key, *cp3 = leaf->rn_mask;
+ char *cp = trial, *cp2 = leaf->rn_key, *cp3 = leaf->rn_mask;
char *cplim;
int length = min(*(u_char *)cp, *(u_char *)cp2);
@@ -202,12 +202,12 @@ rn_match(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;
+ struct radix_node *t = head->rnh_treetop, *x;
+ 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;
+ int test, b, rn_b;
/*
* Open code rn_search(v, top) to avoid overhead of extra
@@ -271,7 +271,7 @@ on2:
*/
if ((saved_t = t)->rn_mask == 0)
t = t->rn_dupedkey;
- for (; t; 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
@@ -280,12 +280,14 @@ on2:
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;
+ } else if (rn_satisfies_leaf(v, t, matched_off)) {
+ return t;
+ }
+ }
t = saved_t;
/* start searching up the tree */
do {
- register struct radix_mask *m;
+ struct radix_mask *m;
t = t->rn_p;
if ((m = t->rn_mklist)) {
/*
@@ -303,7 +305,7 @@ on2:
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))
+ if (x && rn_satisfies_leaf(v, x, off))
return x;
}
} while ((m = m->rm_mklist));
@@ -322,7 +324,7 @@ int rn_debug = 1;
struct radix_node *
rn_newpair(void *v, int b, struct radix_node nodes[2])
{
- register struct radix_node *tt = nodes, *t = tt + 1;
+ 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;
@@ -343,17 +345,17 @@ rn_insert(void* v_arg,
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 *t = rn_search(v_arg, top);
+ caddr_t cp = v + head_off;
+ 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 cp2 = t->rn_key + head_off;
+ int cmp_res;
caddr_t cplim = v + vlen;
while (cp < cplim)
@@ -371,14 +373,14 @@ on1:
cmp_res >>= 1;
}
{
- register struct radix_node *p, *x = top;
+ 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 */
+ } while ((unsigned)b > (unsigned)x->rn_b);
#ifdef RN_DEBUG
if (rn_debug)
log(LOG_DEBUG, "rn_insert: Going In:\n"), traverse(p);
@@ -406,9 +408,9 @@ struct radix_node *
rn_addmask(void *n_arg, int search, int skip)
{
caddr_t netmask = (caddr_t)n_arg;
- register struct radix_node *x;
- register caddr_t cp, cplim;
- register int b = 0, mlen, j;
+ struct radix_node *x;
+ caddr_t cp, cplim;
+ int b = 0, mlen, j;
int maskduplicated, m0, isnormal;
struct radix_node *saved_x;
static int last_zeroed = 0;
@@ -442,9 +444,9 @@ rn_addmask(void *n_arg, int search, int skip)
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);
+ x = (struct radix_node *)rtmalloc(max_keylen + 2*sizeof(*x),
+ "rn_addmask");
+ saved_x = x;
Bzero(x, max_keylen + 2 * sizeof (*x));
netmask = cp = (caddr_t)(x + 2);
Bcopy(addmask_key, cp, mlen);
@@ -476,7 +478,7 @@ rn_addmask(void *n_arg, int search, int skip)
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;
+ u_char *mp = m_arg, *np = n_arg, *lim;
if (*mp > *np)
return 1; /* not really, but need to check longer one first */
@@ -488,10 +490,10 @@ rn_lexobetter(void *m_arg, void *n_arg)
}
static struct radix_mask *
-rn_new_radix_mask(register struct radix_node *tt,
- register struct radix_mask *next)
+rn_new_radix_mask(struct radix_node *tt,
+ struct radix_mask *next)
{
- register struct radix_mask *m;
+ struct radix_mask *m;
MKGet(m);
if (m == 0) {
@@ -517,7 +519,7 @@ rn_addroute(void *v_arg,
struct radix_node treenodes[2])
{
caddr_t v = (caddr_t)v_arg, netmask = (caddr_t)n_arg;
- register struct radix_node *t, *x = 0, *tt;
+ struct radix_node *t, *x = 0, *tt;
struct radix_node *saved_tt, *top = head->rnh_treetop;
short b = 0, b_leaf = 0;
int keyduplicated;
@@ -658,7 +660,7 @@ rn_delete(void *v_arg,
void *netmask_arg,
struct radix_node_head *head)
{
- register struct radix_node *t, *p, *x, *tt;
+ 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;
@@ -779,7 +781,7 @@ on1:
m = mm;
}
if (m)
- syslog(LOG_ERR, "%s %lx at %lx\n",
+ syslog(LOG_ERR, "%s 0x%lx at 0x%lx\n",
"rn_delete: Orphaned Mask",
(unsigned long)m,
(unsigned long)x);
@@ -807,12 +809,12 @@ out:
int
rn_walktree(struct radix_node_head *h,
- register int (*f)(struct radix_node *, struct walkarg*),
+ int (*f)(struct radix_node *, struct walkarg *),
struct walkarg *w)
{
int error;
struct radix_node *base, *next;
- register struct radix_node *rn = h->rnh_treetop;
+ 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
@@ -846,13 +848,11 @@ rn_walktree(struct radix_node_head *h,
int
rn_inithead(void **head, int off)
{
- register struct radix_node_head *rnh;
- register struct radix_node *t, *tt, *ttt;
+ struct radix_node_head *rnh;
+ struct radix_node *t, *tt, *ttt;
if (*head)
return (1);
- R_Malloc(rnh, struct radix_node_head *, sizeof (*rnh));
- if (rnh == 0)
- return (0);
+ rnh = (struct radix_node_head *)rtmalloc(sizeof(*rnh), "rn_inithead");
Bzero(rnh, sizeof (*rnh));
*head = rnh;
t = rn_newpair(rn_zeros, off, rnh->rnh_nodes);
@@ -881,9 +881,7 @@ rn_init(void)
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");
+ rn_zeros = (char *)rtmalloc(3 * max_keylen, "rn_init");
Bzero(rn_zeros, 3 * max_keylen);
rn_ones = cp = rn_zeros + max_keylen;
addmask_key = cplim = rn_ones + max_keylen;
diff --git a/sbin/routed/radix.h b/sbin/routed/radix.h
index fddf02ead7a6..c79bbe05b7b1 100644
--- a/sbin/routed/radix.h
+++ b/sbin/routed/radix.h
@@ -11,7 +11,7 @@
* 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:
+ * must display the following acknowledgment:
* 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
@@ -102,7 +102,7 @@ extern struct radix_mask {
m = rn_mkfreelist; \
rn_mkfreelist = (m)->rm_mklist; \
} else \
- R_Malloc(m, struct radix_mask *, sizeof (*(m))); }\
+ m = (struct radix_mask *)rtmalloc(sizeof(*(m)), "MKGet"); }\
#define MKFree(m) { (m)->rm_mklist = rn_mkfreelist; rn_mkfreelist = (m);}
@@ -134,18 +134,18 @@ struct radix_node_head {
};
-#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);
+#define Bcmp(a, b, n) memcmp(((void *)(a)), ((void *)(b)), (n))
+#define Bcopy(a, b, n) memmove(((void *)(b)), ((void *)(a)), (size_t)(n))
+#define Bzero(p, n) memset((void *)(p), 0, (size_t)(n));
+#define Free(p) free((void *)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*));
+ 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 *,
@@ -158,4 +158,6 @@ struct radix_node
*rn_search __P((void *, struct radix_node *)),
*rn_search_m __P((void *, struct radix_node *, void *));
+struct radix_node *rn_lookup __P((void *, void *, struct radix_node_head *));
+
#endif /* __RADIX_H_ */
diff --git a/sbin/routed/rdisc.c b/sbin/routed/rdisc.c
index bccb3d9374dd..5123442be844 100644
--- a/sbin/routed/rdisc.c
+++ b/sbin/routed/rdisc.c
@@ -11,7 +11,7 @@
* 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:
+ * must display the following acknowledgment:
* 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
@@ -31,18 +31,18 @@
* 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.20 $"
-
#include "defs.h"
#include <netinet/in_systm.h>
#include <netinet/ip.h>
#include <netinet/ip_icmp.h>
+#if !defined(sgi) && !defined(__NetBSD__)
+static char sccsid[] __attribute__((unused)) = "@(#)rdisc.c 8.1 (Berkeley) x/y/95";
+#elif defined(__NetBSD__)
+__RCSID"$NetBSD$");
+#endif
+#ident "$Revision: 2.17 $"
+
/* router advertisement ICMP packet */
struct icmp_ad {
u_int8_t icmp_type; /* type of message */
@@ -79,7 +79,7 @@ struct timeval rdisc_timer;
int rdisc_ok; /* using solicited route */
-#define MAX_ADS 5
+#define MAX_ADS 16 /* at least one per interface */
struct dr { /* accumulated advertisements */
struct interface *dr_ifp;
naddr dr_gate; /* gateway */
@@ -89,8 +89,13 @@ struct dr { /* accumulated advertisements */
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) \
+/* convert between signed, balanced around zero,
+ * and unsigned zero-based preferences */
+#define SIGN_PREF(p) ((p) ^ MIN_PreferenceLevel)
+#define UNSIGN_PREF(p) SIGN_PREF(p)
+/* adjust unsigned preference by interface metric,
+ * without driving it to infinity */
+#define PREF(p, ifp) ((int)(p) <= (ifp)->int_metric ? ((p) != 0 ? 1 : 0) \
: (p) - ((ifp)->int_metric))
static void rdisc_sort(void);
@@ -99,7 +104,7 @@ static void rdisc_sort(void);
/* dump an ICMP Router Discovery Advertisement Message
*/
static void
-trace_rdisc(char *act,
+trace_rdisc(const char *act,
naddr from,
naddr to,
struct interface *ifp,
@@ -137,7 +142,7 @@ trace_rdisc(char *act,
trace_act("%s Router Solic. from %s to %s via %s value=%#x",
act, naddr_ntoa(from), naddr_ntoa(to),
ifp ? ifp->int_name : "?",
- ntohl(p->so.icmp_so_rsvd));
+ (int)ntohl(p->so.icmp_so_rsvd));
}
}
@@ -183,7 +188,7 @@ set_rdisc_mg(struct interface *ifp,
if (ifp->int_if_flags & IFF_POINTOPOINT)
return;
#endif
- bzero(&m, sizeof(m));
+ memset(&m, 0, sizeof(m));
m.imr_interface.s_addr = ((ifp->int_if_flags & IFF_POINTOPOINT)
? ifp->int_dstaddr
: ifp->int_addr);
@@ -252,7 +257,7 @@ set_supplier(void)
if (supplier_set)
return;
- trace_act("start suppying routes");
+ trace_act("start supplying routes");
/* Forget discovered routes.
*/
@@ -294,9 +299,9 @@ rdisc_age(naddr bad_gate)
struct dr *drp;
- /* If only adverising, then do only that. */
+ /* If only advertising, then do only that. */
if (supplier) {
- /* if switching from client to server, get rid of old
+ /* If switching from client to server, get rid of old
* default routes.
*/
if (cur_drp != 0)
@@ -307,7 +312,7 @@ rdisc_age(naddr bad_gate)
/* If we are being told about a bad router,
* then age the discovered default route, and if there is
- * no alternative, solicite a replacement.
+ * no alternative, solicit a replacement.
*/
if (bad_gate != 0) {
/* Look for the bad discovered default route.
@@ -336,14 +341,17 @@ rdisc_age(naddr bad_gate)
}
}
- /* 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();
+
+ /* Delete old redirected routes to keep the kernel table small,
+ * and to prevent black holes. Check that the kernel table
+ * matches the daemon table (i.e. has the default route).
+ * But only if RIP is not running and we are not dealing with
+ * a bad gateway, since otherwise age() will be called.
+ */
+ if (rip_sock < 0 && bad_gate == 0)
+ age(0);
}
@@ -359,10 +367,12 @@ if_bad_rdisc(struct interface *ifp)
if (drp->dr_ifp != ifp)
continue;
drp->dr_recv_pref = 0;
+ drp->dr_ts = 0;
drp->dr_life = 0;
}
- rdisc_sort();
+ /* make a note to re-solicit, turn RIP on or off, etc. */
+ rdisc_timer.tv_sec = 0;
}
@@ -388,10 +398,11 @@ static void
del_rdisc(struct dr *drp)
{
struct interface *ifp;
+ naddr gate;
int i;
- del_redirects(drp->dr_gate, 0);
+ del_redirects(gate = drp->dr_gate, 0);
drp->dr_ts = 0;
drp->dr_life = 0;
@@ -410,13 +421,21 @@ del_rdisc(struct dr *drp)
* 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",
- ifp->int_name);
+ if (i != 0) {
+ trace_act("discovered router %s via %s"
+ " is bad--have %d remaining",
+ naddr_ntoa(gate), ifp->int_name, i);
+ } else if (ifp->int_rdisc_cnt >= MAX_SOLICITATIONS) {
+ trace_act("last discovered router %s via %s"
+ " is bad--re-solicit",
+ naddr_ntoa(gate), ifp->int_name);
ifp->int_rdisc_cnt = 0;
ifp->int_rdisc_timer.tv_sec = 0;
rdisc_sol();
+ } else {
+ trace_act("last discovered router %s via %s"
+ " is bad--wait to solicit",
+ naddr_ntoa(gate), ifp->int_name);
}
}
@@ -429,9 +448,10 @@ rdisc_sort(void)
{
struct dr *drp, *new_drp;
struct rt_entry *rt;
+ struct rt_spare new;
struct interface *ifp;
- u_int new_st;
- n_long new_pref;
+ u_int new_st = 0;
+ n_long new_pref = 0;
/* Find the best discovered route.
@@ -489,23 +509,20 @@ rdisc_sort(void)
if (rt != 0
&& (rt->rt_state & RS_RDISC)) {
+ new = rt->rt_spares[0];
+ new.rts_metric = HOPCNT_INFINITY;
+ new.rts_time = now.tv_sec - GARBAGE_TIME;
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);
+ &new, 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",
naddr_ntoa(new_drp->dr_gate),
new_drp->dr_ifp->int_name);
-
rdisc_ok = 1;
} else {
@@ -517,27 +534,28 @@ rdisc_sort(void)
new_drp->dr_ifp->int_name);
}
+ memset(&new, 0, sizeof(new));
+ new.rts_ifp = new_drp->dr_ifp;
+ new.rts_gate = new_drp->dr_gate;
+ new.rts_router = new_drp->dr_gate;
+ new.rts_metric = HOPCNT_INFINITY-1;
+ new.rts_time = now.tv_sec;
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);
+ rtchange(rt, rt->rt_state | RS_RDISC, &new, 0);
} else {
- rtadd(RIP_DEFAULT, 0,
- new_drp->dr_gate, new_drp->dr_gate,
- HOPCNT_INFINITY-1, 0,
- RS_RDISC, new_drp->dr_ifp);
+ rtadd(RIP_DEFAULT, 0, RS_RDISC, &new);
}
-
- /* Now turn off RIP and delete RIP routes,
- * which might otherwise include the default
- * we just modified.
- */
- rip_off();
}
cur_drp = new_drp;
}
+
+ /* turn RIP on or off */
+ if (!rdisc_ok || rip_interfaces > 1) {
+ rip_on(0);
+ } else {
+ rip_off();
+ }
}
@@ -546,7 +564,7 @@ rdisc_sort(void)
static void
parse_ad(naddr from,
naddr gate,
- n_long pref,
+ n_long pref, /* signed and in network order */
u_short life,
struct interface *ifp)
{
@@ -577,9 +595,9 @@ parse_ad(naddr from,
/* Convert preference to an unsigned value
* and later bias it by the metric of the interface.
*/
- pref = ntohl(pref) ^ MIN_PreferenceLevel;
+ pref = UNSIGN_PREF(ntohl(pref));
- if (pref == 0 || life == 0) {
+ if (pref == 0 || life < MinMaxAdvertiseInterval) {
pref = 0;
life = 0;
}
@@ -610,7 +628,7 @@ parse_ad(naddr from,
new_drp = drp;
} else if (new_drp->dr_ts != 0) {
- /* look for the least valueable entry to reuse
+ /* look for the least valuable entry to reuse
*/
if ((!(new_drp->dr_ifp->int_state & IS_SICK)
&& (drp->dr_ifp->int_state & IS_SICK))
@@ -675,11 +693,11 @@ send_rdisc(union ad_u *p,
{
struct sockaddr_in sin;
int flags;
- char *msg;
+ const char *msg;
naddr tgt_mcast;
- bzero(&sin, sizeof(sin));
+ memset(&sin, 0, sizeof(sin));
sin.sin_addr.s_addr = dst;
sin.sin_family = AF_INET;
#ifdef _HAVE_SIN_LEN
@@ -714,7 +732,7 @@ send_rdisc(union ad_u *p,
if (rdisc_sock_mcast != ifp) {
/* select the right interface. */
#ifdef MCAST_PPP_BUG
- /* Do not specifiy the primary interface explicitly
+ /* Do not specify 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
@@ -771,16 +789,20 @@ send_adv(struct interface *ifp,
n_long pref;
- bzero(&u,sizeof(u.ad));
+ memset(&u, 0, 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);
+
+ /* Convert the configured preference to an unsigned value,
+ * bias it by the interface metric, and then send it as a
+ * signed, network byte order value.
+ */
+ pref = UNSIGN_PREF(ifp->int_rdisc_pref);
+ u.ad.icmp_ad_info[0].icmp_ad_pref = htonl(SIGN_PREF(PREF(pref, ifp)));
u.ad.icmp_ad_info[0].icmp_ad_addr = ifp->int_addr;
@@ -850,7 +872,7 @@ rdisc_sol(void)
continue;
if (!timercmp(&ifp->int_rdisc_timer, &now, >)) {
- bzero(&u,sizeof(u.so));
+ memset(&u, 0, sizeof(u.so));
u.so.icmp_type = ICMP_ROUTERSOLICIT;
u.so.icmp_cksum = in_cksum((u_short*)&u.so,
sizeof(u.so));
@@ -874,14 +896,14 @@ rdisc_sol(void)
/* check the IP header of a possible Router Discovery ICMP packet */
static struct interface * /* 0 if bad */
-ck_icmp(char *act,
+ck_icmp(const char *act,
naddr from,
struct interface *ifp,
naddr to,
union ad_u *p,
u_int len)
{
- char *type;
+ const char *type;
if (p->icmp.icmp_type == ICMP_ROUTERADVERT) {
@@ -987,7 +1009,7 @@ read_d(void)
switch (p->icmp.icmp_type) {
case ICMP_ROUTERADVERT:
if (p->ad.icmp_ad_asize*4
- < sizeof(p->ad.icmp_ad_info[0])) {
+ < (int)sizeof(p->ad.icmp_ad_info[0])) {
msglim(&bad_asize, from.sin_addr.s_addr,
"intolerable rdisc address size=%d",
p->ad.icmp_ad_asize);
@@ -997,9 +1019,10 @@ read_d(void)
trace_pkt(" empty?");
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 (cc != (int)(sizeof(p->ad)
+ - sizeof(p->ad.icmp_ad_info)
+ + (p->ad.icmp_ad_num
+ * sizeof(p->ad.icmp_ad_info[0])))) {
msglim(&bad_len, from.sin_addr.s_addr,
"rdisc length %d does not match ad_num"
" %d", cc, p->ad.icmp_ad_num);
@@ -1026,6 +1049,8 @@ read_d(void)
continue;
if (ifp->int_state & IS_NO_ADV_OUT)
continue;
+ if (stopint)
+ continue;
/* XXX
* We should handle messages from address 0.
diff --git a/sbin/routed/routed.8 b/sbin/routed/routed.8
index 424a851c48c3..d521e4519bd0 100644
--- a/sbin/routed/routed.8
+++ b/sbin/routed/routed.8
@@ -1,3 +1,5 @@
+.\" $Revision: 2.17 $
+.\"
.\" Copyright (c) 1983, 1991, 1993
.\" The Regents of the University of California. All rights reserved.
.\"
@@ -35,26 +37,29 @@
.Dt ROUTED 8
.Os BSD 4.4
.Sh NAME
-.Nm routed
+.Nm routed ,
+.Nm rdisc
.Nd network RIP and router discovery routing daemon
.Sh SYNOPSIS
-.Nm
-.Op Fl sqdghmpAt
+.Nm routed
+.Op Fl sqdghmpAtv
.Op Fl T Ar tracefile
.Oo
.Fl F
.Ar net Ns Op /mask Ns Op ,metric
.Oc
-.OP Fl P Ar parms
+.Op Fl P Ar parms
.Sh DESCRIPTION
.Nm Routed
-is a dameon invoked at boot time to manage the network
+is a daemon 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.
+The RIPv1 protocol is based on the reference
+.Bx 4.3
+daemon.
.Pp
It listens on the
.Xr udp 4
@@ -115,7 +120,7 @@ Advertised metrics reflect the metric associated with interface
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
+Responses do not include routes with a first hop on the requesting
network to implement in part
.Em split-horizon .
Requests from query programs
@@ -160,7 +165,7 @@ 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 ,
+.Nm Ns ,
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
@@ -179,7 +184,7 @@ support multicasting.
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 ),
+.Xr netstat 1 ),
then the cable or some other part of the interface is assumed to be
disconnected or broken, and routes are adjusted appropriately.
.Pp
@@ -188,20 +193,17 @@ The
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
+When it is quiet and 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.
+a good Advertisement and it is not multi-homed,
+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 Discovery Advertisement
-is received), there is a single default route and a variable number of
-redirected host routes in the kernel table.
+It continues listening to RIP while using Router Discovery
+if multi-homed to ensure all interfaces are used.
.Pp
The Router Discovery standard requires that advertisements
have a default "lifetime" of 30 minutes. That means should
@@ -234,15 +236,13 @@ By default, neither Router Discovery advertisements nor solicitations
are sent over point to point links (e.g. PPP).
The netmask associated with point-to-point links (such as SLIP
or PPP, with the IFF_POINTOPOINT flag) is used by
-.Nm routed
+.Nm
to infer the netmask used by the remote system when RIPv1 is used.
-
.Pp
-Options supported by
-.Nm routed :
-.Bl -tag -width Ds
+The following options are available:
+.Bl -tag -width indent
.It Fl s
-this option forces
+force
.Nm
to supply routing information.
This is the default if multiple network interfaces are present on which
@@ -253,11 +253,13 @@ is the opposite of the
.Fl s
option.
This is the default when only one interface is present.
+With this explicit option, the daemon is always in "quite-mode" for RIP
+and does not supply routing information to other computers.
.It Fl d
-Do not run in the background.
+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
+used on internetwork routers to offer a route
to the "default" destination.
It is equivalent to
.Fl F
@@ -266,7 +268,8 @@ 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
+.Cm pm_rdisc
+in the
.Pa /etc/gateways
file.
since a larger metric
@@ -276,16 +279,16 @@ 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 accidentally used to create chaos with routing
-loop than to solve problems.
+dangerous. It is more commonly accidentally used to create chaos with a
+routing loop than to solve problems.
.It Fl h
-This causes host or point-to-point routes to not be advertised,
+cause 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
+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
+cause 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
@@ -305,14 +308,8 @@ 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.
-Note that because of security concerns, it is wisest to not run
-.Nm routed
-routinely with tracing directed to a file.
.It Fl t
-increases the debugging level, which causes more information to be logged
+increase the debugging level, which causes more information to be logged
on the tracefile specified with
.Fl T
or standard out.
@@ -322,8 +319,16 @@ with the
or
.Em SIGUSR2
signals or with the
-.Cm rtquery
+.Xr rtquery 8
command.
+.It Fl T Ar tracefile
+increases the debugging level to at least 1 and
+causes debugging information to be appended to the trace file.
+Note that because of security concerns, it is wisest to not run
+.Nm
+routinely with tracing directed to a file.
+.It Fl v
+display and logs the version of daemon.
.It Fl F Ar net[/mask][,metric]
minimize routes in transmissions via interfaces with addresses that match
.Em net/mask ,
@@ -336,7 +341,6 @@ 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
@@ -361,7 +365,7 @@ It is better to use
instead of
appending the name of the trace file to the command.
.Pp
-.Nm
+.Nm Routed
also supports the notion of
"distant"
.Em passive
@@ -400,10 +404,12 @@ route is restored.
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
+One can list all RIP routers reachable on the HIPPI or ATM network in
.Pa /etc/gateways
with a series of
"host" lines.
+Note that it is usually desirable to use RIPv2 in such situations
+to avoid generating lists of inferred host routes.
.Pp
Gateways marked
.Em external
@@ -412,16 +418,17 @@ 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 necessary,
-and that alternate routes to that destination should not be installed
+and that other routes to that destination should not be installed
by
-.Nm routed .
+.Nm Ns .
Such entries are only required when both routers may learn of routes
to the same destination.
.Pp
The
-.Em /etc/gateways
+.Pa /etc/gateways
file is comprised of a series of lines, each in
-one of the following formats or consist of parameters described below:
+one of the following two formats or consist of parameters described later.
+Blank lines and lines starting with '#' are comments.
.Pp
.Bd -ragged
.Cm net
@@ -460,9 +467,9 @@ or
or
.Xr named 8 ,
must have been started before
-.Xr routed Ns .)
+.Nm Ns .)
.Pp
-.Ar mask
+.Ar Mask
is an optional number between 1 and 32 indicating the netmask associated
with
.Ar Nname .
@@ -473,7 +480,7 @@ be forwarded.
.Pp
.Ar Value
is the hop count to the destination host or network.
-.Ar " host hname "
+.Ar " Host hname "
is equivalent to
.Ar " net nname/32 ".
.Pp
@@ -491,6 +498,15 @@ or whether the gateway is
.Cm external
to the scope of the RIP protocol.
.Pp
+As can be seen when debugging is turned on with
+.Fl t ,
+such lines create pseudo-interfaces.
+To set parameters for remote or external interfaces,
+a line starting with
+.Cm if=alias(Hname) ,
+.Cm if=remote(Hname) ,
+etc. should be used.
+.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:
@@ -501,20 +517,27 @@ name
.Ar ifname .
.It Cm subnet Ns \&= Ns Ar nname[/mask][,metric]
advertises a route to network
-.AR nname
+.Ar nname
with mask
-.AR 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.
+The network number must specify a full, 32-bit value, as in 192.0.2.0
+instead of 192.0.2.
.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 passwd Ns \&= Ns Ar XXX1[|KeyID[start|stop]]
+.It Cm ripv1_mask Ns \&= Ns Ar nname/mask1,mask2
+specifies that netmask of the network of which
+.Cm nname/mask1\f1
+is
+a subnet should be
+.Cm mask2 .
+For example \f2ripv1_mask=192.0.2.16/28,27\f1 marks 192.0.2.16/28
+as a subnet of 192.0.2.0/27 instead of 192.0.2.0/24.
+It is better to turn on RIPv2 instead of using this facility, for example
+with \f2ripv2_out\f1.
+.It Cm passwd Ns \&= Ns Ar XXX[|KeyID[start|stop]]
specifies a RIPv2 cleartext password that will be included on
all RIPv2 responses sent, and checked on all RIPv2 responses received.
Any blanks, tab characters, commas, or '#', '|', or NULL characters in the
@@ -536,15 +559,15 @@ recently is used, or unless no passwords are valid yet, in which case
no password is output.
Incoming packets can carry any password that is valid, will
be valid within 24 hours, or that was valid within 24 hours.
-.It Cm md5_passwd Ns \&= Ns Ar XXX1|KeyID[start|stop]
-specifes a RIPv2 MD5 password.
+To protect the secrets, the passwd settings are valid only in the
+.Em /etc/gateways
+file and only when that file is readable only by UID 0.
+.It Cm md5_passwd Ns \&= Ns Ar XXX|KeyID[start|stop]
+specifies a RIPv2 MD5 password.
Except that a
.Cm KeyID
is required, this keyword is similar to
.Cm passwd .
-To protect the secrets, this parameter setting is valid only in the
-.Em /etc/gateways
-file and only when that file is readable only by UID 0.
.It Cm no_ag
turns off aggregation of subnets in RIPv1 and RIPv2 responses.
.It Cm no_super_ag
@@ -557,27 +580,30 @@ 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.
-
+.Pp
Note that turning off RIP without explicitly turning on router
discovery advertisements with
.Cm rdisc_adv
or
.Fl s
causes
-.Nm routed
+.Nm
to act as a client router discovery daemon, not advertising.
+.It Cm no_rip_mcast
+causes RIPv2 packets to be broadcast instead of multicast.
.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
+turns on RIPv2 output and causes RIPv2 advertisements to be
multicast when possible.
.It Cm ripv2
is equivalent to
.Cm no_ripv1_in
and
.Cm no_ripv1_out .
+This enables RIPv2.
.It Cm no_rdisc
disables the Internet Router Discovery Protocol.
.It Cm no_solicit
@@ -587,24 +613,28 @@ 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
+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
+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
+sets the preference in Router Discovery Advertisements to the optionally
+signed integer
.Ar N .
+The default preference is 0.
+Default routes with smaller or more negative preferences are preferred by
+clients.
.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.
+with the network and mask coming from the specified interface.
.It Cm pm_rdisc
is similar to
.Cm fake_default .
@@ -615,15 +645,17 @@ 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.
-.It Cm trust_gateway Ns \&= Ns Ar rname
+.It Cm trust_gateway Ns \&= Ns Ar rname[|net1/mask1|net2/mask2|...]
causes RIP packets from that router and other routers named in
other
.Cm trust_gateway
-keywords to be accept, and packets from other routers to be ignored.
+keywords to be accepted, and packets from other routers to be ignored.
+If networks are specified, then routes to other networks will be ignored
+from that router.
.It Cm redirect_ok
causes RIP to allow ICMP Redirect messages when the system is acting
as a router and forwarding packets.
-Otherwise, ICMP Redirect messages are are overridden.
+Otherwise, ICMP Redirect messages are overridden.
.El
.Pp
.Sh FILES
@@ -632,9 +664,9 @@ Otherwise, ICMP Redirect messages are are overridden.
for distant gateways
.El
.Sh SEE ALSO
-.Xr gated 8 ,
-.Xr udp 4 ,
.Xr icmp 4 ,
+.Xr udp 4 ,
+.Xr gated 8 ,
.Xr htable 8 ,
.Xr rtquery 8 .
.Rs
@@ -643,8 +675,8 @@ for distant gateways
.%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).
+It does not always detect unidirectional failures in network interfaces,
+for example, when the output side fails.
.Sh HISTORY
The
.Nm
diff --git a/sbin/routed/routed.h b/sbin/routed/routed.h
index 5885ac5136e8..385d301838d3 100644
--- a/sbin/routed/routed.h
+++ b/sbin/routed/routed.h
@@ -11,7 +11,7 @@
* 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:
+ * must display the following acknowledgment:
* 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
@@ -40,7 +40,7 @@
#ifdef __cplusplus
extern "C" {
#endif
-#ident "$Revision: 1.11 $"
+#ident "$Revision: 2.16 $"
/*
* Routing Information Protocol
@@ -134,7 +134,7 @@ struct rip {
#define RIPCMD_MAX 6
#ifdef RIPCMDS
-char *ripcmds[RIPCMD_MAX] = {
+const char *ripcmds[RIPCMD_MAX] = {
"#0", "REQUEST", "RESPONSE", "TRACEON", "TRACEOFF"
};
#endif
diff --git a/sbin/routed/rtquery/Makefile b/sbin/routed/rtquery/Makefile
index 8c4bfd6306fd..d371d5d6651d 100644
--- a/sbin/routed/rtquery/Makefile
+++ b/sbin/routed/rtquery/Makefile
@@ -1,9 +1,11 @@
-# @(#)Makefile 8.1 (Berkeley) 6/5/93
+# Make `routed` tools for BSD/OS
+# $Revision: 2.15 $
+# $Id$
PROG= rtquery
-SRCS= rtquery.c md5.c
-MAN8= rtquery.0
-#COPTS= -g -DDEBUG -Wall
+MAN8= rtquery.8
+LDADD+= -lmd
+DPADD+= ${LIBMD}
+#COPTS= -g -DDEBUG -W -Wall -Wcast-align -Wcast-qual -Winline -Wpointer-arith -Wnested-externs -Wwrite-strings -Wunused
-.include "../../Makefile.inc"
.include <bsd.prog.mk>
diff --git a/sbin/routed/rtquery/md5.c b/sbin/routed/rtquery/md5.c
index dc52a8fdc96e..b0b98845746d 100644
--- a/sbin/routed/rtquery/md5.c
+++ b/sbin/routed/rtquery/md5.c
@@ -1,5 +1,3 @@
-/* This code could be made a lot faster for PPP */
-
/* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
* rights reserved.
*
@@ -22,7 +20,7 @@
* documentation and/or software.
*/
-#ident "$Revision: 1.4 $"
+#ident "$Revision: 2.16 $"
#include <strings.h>
#ifdef sgi
diff --git a/sbin/routed/rtquery/rtquery.8 b/sbin/routed/rtquery/rtquery.8
index 7227bc41157f..2cf931eecc60 100644
--- a/sbin/routed/rtquery/rtquery.8
+++ b/sbin/routed/rtquery/rtquery.8
@@ -1,3 +1,6 @@
+.\" $Revision: 2.17 $
+.\" $NetBSD: rtquery.8,v 1.14 1999/02/23 10:47:41 christos Exp $
+.\"
.Dd June 1, 1996
.Dt RTQUERY 8
.Os BSD 4.4
@@ -11,7 +14,7 @@
.Op Fl r Ar addr
.Op Fl a Ar secret
.Ar host ...
-
+.br
.Nm
.Op Fl t Ar op
.Ar host ...
@@ -25,77 +28,84 @@ for its routing table by sending a
.Em request
or
.Em poll
-command. The routing information in any routing
+command.
+The routing information in any routing
.Em response
packets returned is displayed numerically and symbolically.
.Pp
-.Em Rtquery
+.Nm Rtquery
by default uses the
.Em request
command.
When the
-.Ar -p
+.Fl p
option is specified,
-.Nm rtquery
+.Nm
uses the
.Em poll
command, an
undocumented extension to the RIP protocol supported by
.Xr gated 8 .
-When querying gated, the
+When querying
+.Xr gated 8 ,
+the
.Em poll
command is preferred over the
-.I Request
+.Em request
command because the response is not subject to Split Horizon and/or
-Poisoned Reverse, and because some versions of gated do not answer
-the Request command. Routed does not answer the Poll command, but
-recognizes Requests coming from rtquery and so answers completely.
+Poisoned Reverse, and because some versions of gated do not answer the
+.Em request
+command.
+.Xr Routed 8
+does not answer the
+.Em poll
+command, but recognizes
+.Em requests
+coming from
+.Nm
+and so answers completely.
.Pp
-.Em Rtquery
+.Nm Rtquery
is also used to turn tracing on or off in
-.Em routed .
+.Xr routed 8 .
.Pp
-Options supported by
-.Nm rtquery :
-.Bl -tag -width Ds
+The following options are available:
+.Bl -tag -width indent
.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.
+displays only the numeric network and host numbers instead of both
+numeric and symbolic.
.It Fl p
-Uses the
-.Em Poll
+uses the
+.Em poll
command to request full routing information from
-.Xr gated 8 ,
+.Xr gated 8 .
This is an undocumented extension RIP protocol supported only by
.Xr gated 8 .
.It Fl 1
-query using RIP version 1 instead of RIP version 2.
+queries 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
+asks about the route to destination
.Em addr .
.It Fl a Ar passwd=XXX
.It Fl a Ar md5_passwd=XXX|KeyID
-cause the query to be sent with the indicated cleartext or MD5 password.
+causes the query to be sent with the indicated cleartext or MD5 password.
.It Fl t Ar op
-change tracing, where
+changes tracing, where
.Em op
is one of the following.
Requests from processes not running with UID 0 or on distant networks
are generally ignored by the daemon except for a message in the system log.
-.Xr gated 8
+.Xr Gated 8
is likely to ignore these debugging requests.
.El
.Bl -tag -width Ds -offset indent-two
.It Em on=tracefile
-turn tracing on into the specified file. That file must usually
-have been specified when the daemon was started or be the same
-as a fixed name, often
+turns tracing on into the specified file.
+That file must usually have been specified when the daemon was
+started or be the same as a fixed name, often
.Pa /etc/routed.trace .
.It Em more
increases the debugging level.
@@ -106,7 +116,7 @@ dumps the daemon's routing table to the current tracefile.
.El
.Sh SEE ALSO
.Xr routed 8 ,
-.Xr gated 8 .
+.Xr gated 8
.br
RFC\ 1058 - Routing Information Protocol, RIPv1
.br
diff --git a/sbin/routed/rtquery/rtquery.c b/sbin/routed/rtquery/rtquery.c
index 82e768c0b235..2f484384e2e6 100644
--- a/sbin/routed/rtquery/rtquery.c
+++ b/sbin/routed/rtquery/rtquery.c
@@ -11,7 +11,7 @@
* 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:
+ * must display the following acknowledgment:
* 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
@@ -35,13 +35,7 @@ char copyright[] =
"@(#) Copyright (c) 1982, 1986, 1993\n\
The Regents of the University of California. All rights reserved.\n";
-#if !defined(lint) && !defined(sgi) && !defined(__NetBSD__)
-static char sccsid[] = "@(#)query.c 8.1 (Berkeley) 6/5/93";
-#elif defined(__NetBSD__)
-static char rcsid[] = "$NetBSD$";
-#endif
-#ident "$Revision: 1.11 $"
-
+#include <sys/cdefs.h>
#include <sys/param.h>
#include <sys/protosw.h>
#include <sys/socket.h>
@@ -61,6 +55,13 @@ static char rcsid[] = "$NetBSD$";
#include <bstring.h>
#endif
+#if !defined(sgi) && !defined(__NetBSD__)
+static char sccsid[] __attribute__((unused))= "@(#)query.c 8.1 (Berkeley) 6/5/93";
+#elif defined(__NetBSD__)
+__RCSID("$NetBSD: rtquery.c,v 1.10 1999/02/23 10:47:41 christos Exp $");
+#endif
+#ident "$Revision: 2.17 $"
+
#ifndef sgi
#define _HAVE_SIN_LEN
#endif
@@ -79,9 +80,9 @@ extern void MD5Final(u_char[MD5_DIGEST_LEN], MD5_CTX*);
#define WTIME 15 /* Time to wait for all responses */
#define STIME (250*1000) /* usec to wait for another response */
-int s;
+int soc;
-char *pgmname;
+const char *pgmname;
union {
struct rip rip;
@@ -108,28 +109,33 @@ u_long keyid;
struct timeval sent; /* when query sent */
+static char localhost_str[] = "localhost";
+static char *default_argv[] = {localhost_str, 0};
+
static void rip_input(struct sockaddr_in*, int);
-static int out(char *);
-static void trace_loop(char *argv[]);
-static void query_loop(char *argv[], int);
+static int out(const char *);
+static void trace_loop(char *argv[]) __attribute((__noreturn__));
+static void query_loop(char *argv[], int) __attribute((__noreturn__));
static int getnet(char *, struct netinfo *);
static u_int std_mask(u_int);
-static int parse_quote(char **, char *, char *, char *, int);
+static int parse_quote(char **, const char *, char *, char *, int);
+static void usage(void);
-void
+int
main(int argc,
char *argv[])
{
int ch, bsize;
char *p, *options, *value, delim;
+ const char *result;
OMSG.rip_nets[0].n_dst = RIP_DEFAULT;
OMSG.rip_nets[0].n_family = RIP_AF_UNSPEC;
OMSG.rip_nets[0].n_metric = htonl(HOPCNT_INFINITY);
pgmname = argv[0];
- while ((ch = getopt(argc, argv, "np1w:r:t:a:")) != EOF)
+ while ((ch = getopt(argc, argv, "np1w:r:t:a:")) != -1)
switch (ch) {
case 'n':
not_trace = 1;
@@ -150,13 +156,13 @@ main(int argc,
wtime = (int)strtoul(optarg, &p, 0);
if (*p != '\0'
|| wtime <= 0)
- goto usage;
+ usage();
break;
case 'r':
not_trace = 1;
if (rflag)
- goto usage;
+ usage();
rflag = getnet(optarg, &OMSG.rip_nets[0]);
if (!rflag) {
struct hostent *hp = gethostbyname(optarg);
@@ -166,8 +172,8 @@ main(int argc,
herror(0);
exit(1);
}
- bcopy(hp->h_addr, &OMSG.rip_nets[0].n_dst,
- sizeof(OMSG.rip_nets[0].n_dst));
+ memcpy(&OMSG.rip_nets[0].n_dst, hp->h_addr,
+ sizeof(OMSG.rip_nets[0].n_dst));
OMSG.rip_nets[0].n_family = RIP_AF_INET;
OMSG.rip_nets[0].n_mask = -1;
rflag = 1;
@@ -178,47 +184,52 @@ main(int argc,
trace = 1;
options = optarg;
while (*options != '\0') {
- char *traceopts[] = {
+ /* messy complications to make -W -Wall happy */
+ static char on_str[] = "on";
+ static char more_str[] = "more";
+ static char off_str[] = "off";
+ static char dump_str[] = "dump";
+ static char *traceopts[] = {
# define TRACE_ON 0
- "on",
+ on_str,
# define TRACE_MORE 1
- "more",
+ more_str,
# define TRACE_OFF 2
- "off",
+ off_str,
# define TRACE_DUMP 3
- "dump",
+ dump_str,
0
};
+ result = "";
switch (getsubopt(&options,traceopts,&value)) {
case TRACE_ON:
OMSG.rip_cmd = RIPCMD_TRACEON;
if (!value
|| strlen(value) > MAXPATHLEN)
- goto usage;
+ usage();
+ result = value;
break;
case TRACE_MORE:
if (value)
- goto usage;
+ usage();
OMSG.rip_cmd = RIPCMD_TRACEON;
- value = "";
break;
case TRACE_OFF:
if (value)
- goto usage;
+ usage();
OMSG.rip_cmd = RIPCMD_TRACEOFF;
- value = "";
break;
case TRACE_DUMP:
if (value)
- goto usage;
+ usage();
OMSG.rip_cmd = RIPCMD_TRACEON;
- value = "dump/../table";
+ result = "dump/../table";
break;
default:
- goto usage;
+ usage();
}
- strcpy((char*)OMSG.rip_tracefile, value);
- omsg_len += strlen(value) - sizeof(OMSG.ripun);
+ strcpy((char*)OMSG.rip_tracefile, result);
+ omsg_len += strlen(result) - sizeof(OMSG.ripun);
}
break;
@@ -226,50 +237,48 @@ main(int argc,
not_trace = 1;
p = strchr(optarg,'=');
if (!p)
- goto usage;
+ usage();
*p++ = '\0';
if (!strcasecmp("passwd",optarg))
auth_type = RIP_AUTH_PW;
else if (!strcasecmp("md5_passwd",optarg))
auth_type = RIP_AUTH_MD5;
else
- goto usage;
+ usage();
if (0 > parse_quote(&p,"|",&delim,
- passwd,sizeof(passwd)))
- goto usage;
+ passwd, sizeof(passwd)))
+ usage();
if (auth_type == RIP_AUTH_MD5
&& delim == '|') {
keyid = strtoul(p+1,&p,0);
if (keyid > 255 || *p != '\0')
- goto usage;
+ usage();
} else if (delim != '\0') {
- goto usage;
+ usage();
}
break;
default:
- goto usage;
+ usage();
}
argv += optind;
argc -= optind;
- if ((not_trace && trace) || argc == 0) {
-usage: fprintf(stderr, "%s: [-np1v] [-r tgt_rt] [-w wtime]"
- " [-a type=passwd] host1 [host2 ...]\n"
- "or\t-t {on=filename|more|off|dump}"
- " host1 [host2 ...]\n",
- pgmname);
- exit(1);
+ if (not_trace && trace)
+ usage();
+ if (argc == 0) {
+ argc = 1;
+ argv = default_argv;
}
- s = socket(AF_INET, SOCK_DGRAM, 0);
- if (s < 0) {
+ soc = socket(AF_INET, SOCK_DGRAM, 0);
+ if (soc < 0) {
perror("socket");
exit(2);
}
/* be prepared to receive a lot of routes */
for (bsize = 127*1024; ; bsize -= 1024) {
- if (setsockopt(s, SOL_SOCKET, SO_RCVBUF,
+ if (setsockopt(soc, SOL_SOCKET, SO_RCVBUF,
&bsize, sizeof(bsize)) == 0)
break;
if (bsize <= 4*1024) {
@@ -283,6 +292,19 @@ usage: fprintf(stderr, "%s: [-np1v] [-r tgt_rt] [-w wtime]"
else
query_loop(argv, argc);
/* NOTREACHED */
+ return 0;
+}
+
+
+static void
+usage(void)
+{
+ fprintf(stderr,
+ "usage: rtquery [-np1] [-r tgt_rt] [-w wtime]"
+ " [-a type=passwd] host1 [host2 ...]\n"
+ "\trtquery -t {on=filename|more|off|dump}"
+ " host1 [host2 ...]\n");
+ exit(1);
}
@@ -305,13 +327,13 @@ trace_loop(char *argv[])
OMSG.rip_vers = RIPv1;
}
- bzero(&myaddr, sizeof(myaddr));
+ memset(&myaddr, 0, sizeof(myaddr));
myaddr.sin_family = AF_INET;
#ifdef _HAVE_SIN_LEN
myaddr.sin_len = sizeof(myaddr);
#endif
myaddr.sin_port = htons(IPPORT_RESERVED-1);
- while (bind(s, (struct sockaddr *)&myaddr, sizeof(myaddr)) < 0) {
+ while (bind(soc, (struct sockaddr *)&myaddr, sizeof(myaddr)) < 0) {
if (errno != EADDRINUSE
|| myaddr.sin_port == 0) {
perror("bind");
@@ -356,8 +378,7 @@ query_loop(char *argv[], int argc)
OMSG.rip_nets[1] = OMSG.rip_nets[0];
NA0.a_family = RIP_AF_AUTH;
NA0.a_type = RIP_AUTH_PW;
- bcopy(passwd, NA0.au.au_pw,
- RIP_AUTH_PW_LEN);
+ memcpy(NA0.au.au_pw, passwd, RIP_AUTH_PW_LEN);
omsg_len += sizeof(OMSG.rip_nets[0]);
} else if (auth_type == RIP_AUTH_MD5) {
@@ -365,15 +386,17 @@ query_loop(char *argv[], int argc)
NA0.a_family = RIP_AF_AUTH;
NA0.a_type = RIP_AUTH_MD5;
NA0.au.a_md5.md5_keyid = (int8_t)keyid;
- NA0.au.a_md5.md5_auth_len = RIP_AUTH_PW_LEN;
+ NA0.au.a_md5.md5_auth_len = RIP_AUTH_MD5_LEN;
NA0.au.a_md5.md5_seqno = 0;
- NA0.au.a_md5.md5_pkt_len = sizeof(OMSG.rip_nets[1]);
+ cc = (char *)&NA2-(char *)&OMSG;
+ NA0.au.a_md5.md5_pkt_len = htons(cc);
NA2.a_family = RIP_AF_AUTH;
- NA2.a_type = 1;
- bcopy(passwd, NA2.au.au_pw, sizeof(NA2.au.au_pw));
+ NA2.a_type = htons(1);
MD5Init(&md5_ctx);
- MD5Update(&md5_ctx, (u_char *)&NA0,
- (char *)(&NA2+1) - (char *)&NA0);
+ MD5Update(&md5_ctx,
+ (u_char *)&OMSG, cc);
+ MD5Update(&md5_ctx,
+ (u_char *)passwd, RIP_AUTH_MD5_LEN);
MD5Final(NA2.au.au_pw, &md5_ctx);
omsg_len += 2*sizeof(OMSG.rip_nets[0]);
}
@@ -393,13 +416,13 @@ query_loop(char *argv[], int argc)
FD_ZERO(&bits);
for (;;) {
- FD_SET(s, &bits);
+ FD_SET(soc, &bits);
delay.tv_sec = 0;
delay.tv_usec = STIME;
- cc = select(s+1, &bits, 0,0, &delay);
+ cc = select(soc+1, &bits, 0,0, &delay);
if (cc > 0) {
fromlen = sizeof(from);
- cc = recvfrom(s, imsg_buf.packet,
+ cc = recvfrom(soc, imsg_buf.packet,
sizeof(imsg_buf.packet), 0,
(struct sockaddr *)&from, &fromlen);
if (cc < 0) {
@@ -418,6 +441,11 @@ query_loop(char *argv[], int argc)
}
if (sp == 0) {
sp = malloc(sizeof(*sp));
+ if (sp == 0) {
+ fprintf(stderr,
+ "rtquery: malloc failed\n");
+ exit(1);
+ }
sp->addr = from.sin_addr;
sp->next = seen;
seen = sp;
@@ -429,7 +457,7 @@ query_loop(char *argv[], int argc)
}
if (cc < 0) {
- if ( errno == EINTR)
+ if (errno == EINTR)
continue;
perror("select");
exit(1);
@@ -465,7 +493,7 @@ query_loop(char *argv[], int argc)
/* send to one host
*/
static int
-out(char *host)
+out(const char *host)
{
struct sockaddr_in router;
struct hostent *hp;
@@ -475,7 +503,7 @@ out(char *host)
return -1;
}
- bzero(&router, sizeof(router));
+ memset(&router, 0, sizeof(router));
router.sin_family = AF_INET;
#ifdef _HAVE_SIN_LEN
router.sin_len = sizeof(router);
@@ -486,11 +514,11 @@ out(char *host)
herror(host);
return -1;
}
- bcopy(hp->h_addr, &router.sin_addr, sizeof(router.sin_addr));
+ memcpy(&router.sin_addr, hp->h_addr, sizeof(router.sin_addr));
}
router.sin_port = htons(RIP_PORT);
- if (sendto(s, &omsg_buf, omsg_len, 0,
+ if (sendto(soc, &omsg_buf, omsg_len, 0,
(struct sockaddr *)&router, sizeof(router)) < 0) {
perror(host);
return -1;
@@ -563,8 +591,11 @@ rip_input(struct sockaddr_in *from,
{
struct netinfo *n, *lim;
struct in_addr in;
- char *name;
+ const char *name;
char net_buf[80];
+ u_char hash[RIP_AUTH_MD5_LEN];
+ MD5_CTX md5_ctx;
+ u_char md5_authed = 0;
u_int mask, dmask;
char *sp;
int i;
@@ -594,10 +625,10 @@ rip_input(struct sockaddr_in *from,
(IMSG.rip_vers != RIPv1 && IMSG.rip_vers != RIPv2) ? " ?" : "",
size);
if (size > MAXPACKETSIZE) {
- if (size > sizeof(imsg_buf) - sizeof(*n)) {
+ if (size > (int)sizeof(imsg_buf) - (int)sizeof(*n)) {
printf(" at least %d bytes too long\n",
size-MAXPACKETSIZE);
- size = sizeof(imsg_buf) - sizeof(*n);
+ size = (int)sizeof(imsg_buf) - (int)sizeof(*n);
} else {
printf(" %d bytes too long\n",
size-MAXPACKETSIZE);
@@ -679,22 +710,38 @@ rip_input(struct sockaddr_in *from,
if (na->a_type == RIP_AUTH_MD5
&& n == IMSG.rip_nets) {
- (void)printf(" MD5 Authentication"
+ (void)printf(" MD5 Auth"
" len=%d KeyID=%d"
- " seqno=%d"
+ " auth_len=%d"
+ " seqno=%#x"
" rsvd=%#x,%#x\n",
- na->au.a_md5.md5_pkt_len,
+ ntohs(na->au.a_md5.md5_pkt_len),
na->au.a_md5.md5_keyid,
- na->au.a_md5.md5_seqno,
+ na->au.a_md5.md5_auth_len,
+ (int)ntohl(na->au.a_md5.md5_seqno),
na->au.a_md5.rsvd[0],
na->au.a_md5.rsvd[1]);
+ md5_authed = 1;
continue;
}
(void)printf(" Authentication type %d: ",
ntohs(na->a_type));
- for (i = 0; i < sizeof(na->au.au_pw); i++)
+ for (i = 0; i < (int)sizeof(na->au.au_pw); i++)
(void)printf("%02x ", na->au.au_pw[i]);
putc('\n', stdout);
+ if (md5_authed && n+1 > lim
+ && na->a_type == ntohs(1)) {
+ MD5Init(&md5_ctx);
+ MD5Update(&md5_ctx, (u_char *)&IMSG,
+ (char *)na-(char *)&IMSG);
+ MD5Update(&md5_ctx, (u_char *)passwd,
+ RIP_AUTH_MD5_LEN);
+ MD5Final(hash, &md5_ctx);
+ (void)printf(" %s hash\n",
+ memcmp(hash, na->au.au_pw,
+ sizeof(hash))
+ ? "WRONG" : "correct");
+ }
continue;
} else {
@@ -707,7 +754,7 @@ rip_input(struct sockaddr_in *from,
}
(void)printf(" %-18s metric %2d %-10s",
- net_buf, ntohl(n->n_metric), name);
+ net_buf, (int)ntohl(n->n_metric), name);
if (n->n_nhop != 0) {
in.s_addr = n->n_nhop;
@@ -762,11 +809,11 @@ getnet(char *name,
/* Detect and separate "1.2.3.4/24"
*/
- if (0 != (mname = rindex(name,'/'))) {
+ if (0 != (mname = strrchr(name,'/'))) {
i = (int)(mname - name);
- if (i > sizeof(hname)-1) /* name too long */
+ if (i > (int)sizeof(hname)-1) /* name too long */
return 0;
- bcopy(name, hname, i);
+ memmove(hname, name, i);
hname[i] = '\0';
mname++;
name = hname;
@@ -803,12 +850,13 @@ getnet(char *name,
*/
static int /* -1=bad */
parse_quote(char **linep,
- char *delims,
+ const char *delims,
char *delimp,
char *buf,
int lim)
{
- char c, *pc, *p;
+ char c, *pc;
+ const char *p;
pc = *linep;
@@ -822,7 +870,7 @@ parse_quote(char **linep,
if (c == '\0')
break;
- if (c == '\\' && pc != '\0') {
+ if (c == '\\' && *pc != '\0') {
if ((c = *pc++) == 'n') {
c = '\n';
} else if (c == 'r') {
diff --git a/sbin/routed/table.c b/sbin/routed/table.c
index d00279e082fc..0c41248adbb1 100644
--- a/sbin/routed/table.c
+++ b/sbin/routed/table.c
@@ -11,7 +11,7 @@
* 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:
+ * must display the following acknowledgment:
* 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
@@ -31,16 +31,24 @@
* SUCH DAMAGE.
*/
-#if !defined(lint) && !defined(sgi) && !defined(__NetBSD__)
-static char sccsid[] = "@(#)tables.c 8.1 (Berkeley) 6/5/93";
+#include "defs.h"
+
+#if !defined(sgi) && !defined(__NetBSD__)
+static char sccsid[] __attribute__((unused)) = "@(#)tables.c 8.1 (Berkeley) 6/5/93";
#elif defined(__NetBSD__)
-static char rcsid[] = "$NetBSD$";
+__RCSID("$NetBSD$");
#endif
-#ident "$Revision: 1.28 $"
-
-#include "defs.h"
+#ident "$Revision: 2.17 $"
static struct rt_spare *rts_better(struct rt_entry *);
+static struct rt_spare rts_empty = {0,0,0,HOPCNT_INFINITY,0,0,0};
+static void set_need_flash(void);
+#ifdef _HAVE_SIN_LEN
+static void masktrim(struct sockaddr_in *ap);
+#else
+static void masktrim(struct sockaddr_in_new *ap);
+#endif
+
struct radix_node_head *rhead; /* root of the radix tree */
@@ -116,6 +124,10 @@ ag_out(struct ag_info *ag,
naddr bit;
+ /* Forget it if this route should not be output for split-horizon. */
+ if (ag->ag_state & AGS_SPLIT_HZ)
+ return;
+
/* 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.
@@ -141,12 +153,14 @@ ag_out(struct ag_info *ag,
*/
if (ag->ag_state & AGS_REDUN0) {
if (ag->ag_state & AGS_REDUN1)
- return;
+ return; /* quit if fully redundant */
+ /* make it finer if it is half-redundant */
bit = (-ag->ag_mask) >> 1;
ag->ag_dst_h |= bit;
ag->ag_mask |= bit;
} else if (ag->ag_state & AGS_REDUN1) {
+ /* make it finer if it is half-redundant */
bit = (-ag->ag_mask) >> 1;
ag->ag_mask |= bit;
}
@@ -176,11 +190,11 @@ ag_del(struct ag_info *ag)
}
-/* Flush routes waiting for aggretation.
+/* Flush routes waiting for aggregation.
* 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
+ * in lexical order, and with the most restrictive mask first
* among routes to the same destination.
*/
void
@@ -233,6 +247,8 @@ ag_flush(naddr lim_dst_h, /* flush routes to here */
/* If the coarse route has a good enough
* metric, it suppresses the target.
+ * If the suppressed target was redundant,
+ * then mark the suppressor redundant.
*/
if (ag_cors->ag_pref <= ag->ag_pref) {
if (ag_cors->ag_seqno > ag->ag_seqno)
@@ -317,8 +333,8 @@ ag_check(naddr dst,
* 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.
+ * This check keeps poor routes (e.g. with large hop counts)
+ * from preventing suppression of finer routes.
*/
if (ag_cors != 0
&& ag->ag_dst_h < dst
@@ -330,6 +346,9 @@ ag_check(naddr dst,
|| (ag_cors->ag_state & AGS_CORS_GATE))) {
if (ag_cors->ag_seqno > ag->ag_seqno)
ag_cors->ag_seqno = ag->ag_seqno;
+ /* If the suppressed target was redundant,
+ * then mark the suppressor redundant.
+ */
if (AG_IS_REDUN(ag->ag_state)
&& ag_cors->ag_mask==ag->ag_mask<<1) {
if (ag_cors->ag_dst_h == dst)
@@ -372,11 +391,11 @@ ag_check(naddr dst,
* 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.
+ * a promoted (or aggregated) 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
+ * or the aggregated one if not, following a sort
* of longest-match rule.
*/
if (pref <= ag->ag_pref) {
@@ -396,9 +415,13 @@ ag_check(naddr dst,
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));
+ /* Some bits are set if they are set on either route,
+ * except when the route is for an interface.
+ */
+ if (!(ag->ag_state & AGS_IF))
+ ag->ag_state |= (state & (AGS_AGGREGATE_EITHER
+ | AGS_REDUN0
+ | AGS_REDUN1));
return;
}
@@ -406,12 +429,12 @@ ag_check(naddr dst,
* be suppressed, it may be possible to combine them or
* worthwhile to promote one.
*
- * Note that any route that can be promoted is always
+ * Any route that can be promoted is always
* marked to be eligible to be suppressed.
*/
- if (!((state & AGS_PROMOTE)
+ if (!((state & AGS_AGGREGATE)
&& (ag->ag_state & AGS_SUPPRESS))
- && !((ag->ag_state & AGS_PROMOTE)
+ && !((ag->ag_state & AGS_AGGREGATE)
&& (state & AGS_SUPPRESS)))
break;
@@ -423,13 +446,13 @@ ag_check(naddr dst,
|| AG_IS_REDUN(state)
|| (ag->ag_gate == gate
&& ag->ag_pref == pref
- && (state & ag->ag_state & AGS_PROMOTE) != 0)) {
+ && (state & ag->ag_state & AGS_AGGREGATE) != 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.
+ * Combine and promote (aggregate) the pair of routes.
*/
if (seqno > ag->ag_seqno)
seqno = ag->ag_seqno;
@@ -439,7 +462,7 @@ ag_check(naddr dst,
state |= AGS_REDUN0;
else
state &= ~AGS_REDUN0;
- state |= (ag->ag_state & AGS_PROMOTE_EITHER);
+ state |= (ag->ag_state & AGS_AGGREGATE_EITHER);
if (ag->ag_tag != tag)
tag = 0;
if (ag->ag_nhop != nhop)
@@ -451,7 +474,7 @@ ag_check(naddr dst,
ag_del(ag);
} else if (ag->ag_pref >= pref
- && (ag->ag_state & AGS_PROMOTE)) {
+ && (ag->ag_state & AGS_AGGREGATE)) {
/* If we cannot combine the pair, maybe the route
* with the worse metric can be promoted.
*
@@ -472,11 +495,17 @@ ag_check(naddr dst,
ag->ag_tag = tag;
tag = x;
+ /* The promoted route is even-redundant only if the
+ * even twin was fully redundant. It is not
+ * odd-redundant because the odd-twin will still be
+ * in the table.
+ */
x = ag->ag_state;
+ if (!AG_IS_REDUN(x))
+ x &= ~AGS_REDUN0;
+ x &= ~AGS_REDUN1;
ag->ag_state = state;
state = x;
- if (!AG_IS_REDUN(state))
- state &= ~AGS_REDUN0;
x = ag->ag_metric;
ag->ag_metric = metric;
@@ -486,24 +515,30 @@ ag_check(naddr dst,
ag->ag_pref = pref;
pref = x;
+ /* take the newest sequence number */
if (seqno >= ag->ag_seqno)
seqno = ag->ag_seqno;
else
ag->ag_seqno = seqno;
} else {
- if (!(state & AGS_PROMOTE))
+ if (!(state & AGS_AGGREGATE))
break; /* cannot promote either twin */
- /* promote the new, odd twin by shaving its
+ /* Promote the new, odd twin by shaving its
* mask and address.
+ * The promoted route is odd-redundant only if the
+ * odd twin was fully redundant. It is not
+ * even-redundant because the even twin is still in
+ * the table.
*/
+ if (!AG_IS_REDUN(state))
+ state &= ~AGS_REDUN1;
+ state &= ~AGS_REDUN0;
if (seqno > ag->ag_seqno)
seqno = ag->ag_seqno;
else
ag->ag_seqno = seqno;
- if (!AG_IS_REDUN(state))
- state &= ~AGS_REDUN1;
}
mask <<= 1;
@@ -580,10 +615,10 @@ ag_check(naddr dst,
}
-static char *
+static const char *
rtm_type_name(u_char type)
{
- static char *rtm_types[] = {
+ static const char *rtm_types[] = {
"RTM_ADD",
"RTM_DELETE",
"RTM_CHANGE",
@@ -623,7 +658,7 @@ masktrim(struct sockaddr_in *ap)
masktrim(struct sockaddr_in_new *ap)
#endif
{
- register char *cp;
+ char *cp;
if (ap->sin_addr.s_addr == 0) {
ap->sin_len = 0;
@@ -657,16 +692,18 @@ rtioctl(int action, /* RTM_DELETE, etc */
#endif
} w;
long cc;
+# define PAT " %-10s %s metric=%d flags=%#x"
+# define ARGS rtm_type_name(action), rtname(dst,mask,gate), metric, flags
again:
- bzero(&w, sizeof(w));
+ memset(&w, 0, 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) {
+ if (metric != 0 || action == RTM_CHANGE) {
w.w_rtm.rtm_rmx.rmx_hopcount = metric;
w.w_rtm.rtm_inits |= RTV_HOPCOUNT;
}
@@ -692,37 +729,30 @@ again:
#endif
}
- if (TRACEKERNEL)
- trace_kernel("write kernel %s %s->%s metric=%d flags=%#x\n",
- rtm_type_name(action),
- addrname(dst, mask, 0), naddr_ntoa(gate),
- metric, flags);
-
#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",
- addrname(dst, mask, 0),
- rtm_type_name(action));
+ trace_act("route disappeared before" PAT, ARGS);
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);
+ msglog("write(rt_sock)" PAT ": %s", ARGS, strerror(errno));
+ return;
+ } else if (cc != w.w_rtm.rtm_msglen) {
+ msglog("write(rt_sock) wrote %ld instead of %d for" PAT,
+ cc, w.w_rtm.rtm_msglen, ARGS);
+ return;
}
#endif
+ if (TRACEKERNEL)
+ trace_misc("write kernel" PAT, ARGS);
+#undef PAT
+#undef ARGS
}
@@ -736,14 +766,15 @@ static struct khash {
short k_metric;
u_short k_state;
#define KS_NEW 0x001
-#define KS_DELETE 0x002
+#define KS_DELETE 0x002 /* need to delete the route */
#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 */
+#define KS_DELETED 0x100 /* already deleted from kernel */
+#define KS_CHECK 0x200
time_t k_keep;
#define K_KEEP_LIM 30
time_t k_redirect_time; /* when redirected route 1st seen */
@@ -774,9 +805,9 @@ kern_add(naddr dst, naddr mask)
if (k != 0)
return k;
- k = (struct khash *)malloc(sizeof(*k));
+ k = (struct khash *)rtmalloc(sizeof(*k), "kern_add");
- bzero(k, sizeof(*k));
+ memset(k, 0, sizeof(*k));
k->k_dst = dst;
k->k_mask = mask;
k->k_state = KS_NEW;
@@ -795,23 +826,55 @@ kern_check_static(struct khash *k,
struct interface *ifp)
{
struct rt_entry *rt;
- naddr int_addr;
+ struct rt_spare new;
if (k->k_metric == 0)
return;
- int_addr = (ifp != 0) ? ifp->int_addr : loopaddr;
+ memset(&new, 0, sizeof(new));
+ new.rts_ifp = ifp;
+ new.rts_gate = k->k_gate;
+ new.rts_router = (ifp != 0) ? ifp->int_addr : loopaddr;
+ new.rts_metric = k->k_metric;
+ new.rts_time = now.tv_sec;
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);
+ rtchange(rt, rt->rt_state | RS_STATIC, &new, 0);
} else {
- rtadd(k->k_dst, k->k_mask, k->k_gate, int_addr,
- k->k_metric, 0, RS_STATIC, ifp);
+ rtadd(k->k_dst, k->k_mask, RS_STATIC, &new);
+ }
+}
+
+
+/* operate on a kernel entry
+ */
+static void
+kern_ioctl(struct khash *k,
+ int action, /* RTM_DELETE, etc */
+ int flags)
+
+{
+ switch (action) {
+ case RTM_DELETE:
+ k->k_state &= ~KS_DYNAMIC;
+ if (k->k_state & KS_DELETED)
+ return;
+ k->k_state |= KS_DELETED;
+ break;
+ case RTM_ADD:
+ k->k_state &= ~KS_DELETED;
+ break;
+ case RTM_CHANGE:
+ if (k->k_state & KS_DELETED) {
+ action = RTM_ADD;
+ k->k_state &= ~KS_DELETED;
+ }
+ break;
}
+
+ rtioctl(action, k->k_dst, k->k_gate, k->k_mask, k->k_metric, flags);
}
@@ -836,23 +899,29 @@ rtm_add(struct rt_msghdr *rtm,
return;
}
- if (INFO_GATE(info) == 0
- || INFO_GATE(info)->sa_family != AF_INET) {
- msglog("ignore %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 (INFO_GATE(info) == 0) {
+ trace_act("note %s without gateway",
+ rtm_type_name(rtm->rtm_type));
+ k->k_metric = HOPCNT_INFINITY;
+ } else if (INFO_GATE(info)->sa_family != AF_INET) {
+ trace_act("note %s with gateway AF=%d",
+ rtm_type_name(rtm->rtm_type),
+ INFO_GATE(info)->sa_family);
+ k->k_metric = HOPCNT_INFINITY;
+ } else {
+ 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-1)
+ k->k_metric = HOPCNT_INFINITY-1;
+ }
+ k->k_state &= ~(KS_DELETE | KS_ADD | KS_CHANGE | KS_DEL_ADD
+ | KS_DELETED | KS_GATEWAY | KS_STATIC
+ | KS_NEW | KS_CHECK);
if (rtm->rtm_flags & RTF_GATEWAY)
k->k_state |= KS_GATEWAY;
if (rtm->rtm_flags & RTF_STATIC)
@@ -926,44 +995,104 @@ rtm_lose(struct rt_msghdr *rtm,
return;
}
- if (!supplier)
+ if (rdisc_ok)
rdisc_age(S_ADDR(INFO_GATE(info)));
-
age(S_ADDR(INFO_GATE(info)));
}
+/* Make the gateway slot of an info structure point to something
+ * useful. If it is not already useful, but it specifies an interface,
+ * then fill in the sockaddr_in provided and point it there.
+ */
+static int
+get_info_gate(struct sockaddr **sap,
+ struct sockaddr_in *sin)
+{
+ struct sockaddr_dl *sdl = (struct sockaddr_dl *)*sap;
+ struct interface *ifp;
+
+ if (sdl == 0)
+ return 0;
+ if ((sdl)->sdl_family == AF_INET)
+ return 1;
+ if ((sdl)->sdl_family != AF_LINK)
+ return 0;
+
+ ifp = ifwithindex(sdl->sdl_index, 1);
+ if (ifp == 0)
+ return 0;
+
+ sin->sin_addr.s_addr = ifp->int_addr;
+#ifdef _HAVE_SA_LEN
+ sin->sin_len = sizeof(*sin);
+#endif
+ sin->sin_family = AF_INET;
+ *sap = (struct sockaddr*)sin;
+
+ return 1;
+}
+
+
/* Clean the kernel table by copying it to the daemon image.
* Eventually the daemon will delete any extra routes.
*/
void
flush_kern(void)
{
+ static char *sysctl_buf;
+ static size_t sysctl_buf_size = 0;
size_t needed;
int mib[6];
- char *buf, *next, *lim;
+ char *next, *lim;
struct rt_msghdr *rtm;
- struct interface *ifp;
- static struct sockaddr_in gate_sa;
+ struct sockaddr_in gate_sin;
struct rt_addrinfo info;
+ int i;
+ struct khash *k;
+ for (i = 0; i < KHASH_SIZE; i++) {
+ for (k = khash_bins[i]; k != 0; k = k->k_next) {
+ k->k_state |= KS_CHECK;
+ }
+ }
+
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;
+ 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,"flush_kern: sysctl(RT_DUMP)");
+ free(sysctl_buf);
+ needed = 0;
+ }
+ if (sysctl(mib, 6, 0, &needed, 0, 0) < 0)
+ BADERR(1,"flush_kern: sysctl(RT_DUMP) estimate");
+ /* Kludge around the habit of some systems, such as
+ * BSD/OS 3.1, to not admit how many routes are in the
+ * kernel, or at least to be quite wrong.
+ */
+ needed += 50*(sizeof(*rtm)+5*sizeof(struct sockaddr));
+ sysctl_buf = rtmalloc(sysctl_buf_size = needed,
+ "flush_kern sysctl(RT_DUMP)");
}
- 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) {
+
+ lim = sysctl_buf + needed;
+ for (next = sysctl_buf; next < lim; next += rtm->rtm_msglen) {
rtm = (struct rt_msghdr *)next;
+ if (rtm->rtm_msglen == 0) {
+ msglog("zero length kernel route at "
+ " %#lx in buffer %#lx before %#lx",
+ (u_long)rtm, (u_long)sysctl_buf, (u_long)lim);
+ break;
+ }
rt_xaddrs(&info,
(struct sockaddr *)(rtm+1),
@@ -980,32 +1109,14 @@ flush_kern(void)
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;
+ if (!get_info_gate(&INFO_GATE(&info), &gate_sin))
+ 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
@@ -1015,7 +1126,17 @@ flush_kern(void)
*/
rtm_add(rtm,&info,MIN_WAITTIME);
}
- free(buf);
+
+ for (i = 0; i < KHASH_SIZE; i++) {
+ for (k = khash_bins[i]; k != 0; k = k->k_next) {
+ if (k->k_state & KS_CHECK) {
+ msglog("%s --> %s disappeared from kernel",
+ addrname(k->k_dst, k->k_mask, 0),
+ naddr_ntoa(k->k_gate));
+ del_static(k->k_dst, k->k_mask, k->k_gate, 1);
+ }
+ }
+ }
}
@@ -1026,7 +1147,8 @@ read_rt(void)
{
long cc;
struct interface *ifp;
- naddr mask;
+ struct sockaddr_in gate_sin;
+ naddr mask, gate;
union {
struct {
struct rt_msghdr rtm;
@@ -1067,10 +1189,11 @@ read_rt(void)
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);
+ ifp = ifwithindex(m.ifm.ifm_index,
+ m.r.rtm.rtm_type != RTM_DELADDR);
if (ifp == 0)
trace_act("note %s with flags %#x"
- " for index #%d",
+ " for unknown interface index #%d",
rtm_type_name(m.r.rtm.rtm_type),
m.ifm.ifm_flags,
m.ifm.ifm_index);
@@ -1089,7 +1212,7 @@ read_rt(void)
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)
+ & IFF_UP) != 0)
ifinit_timer.tv_sec = now.tv_sec;
continue;
}
@@ -1127,10 +1250,17 @@ read_rt(void)
continue;
}
- if (INFO_GATE(&info) != 0
- && INFO_GATE(&info)->sa_family == AF_INET)
- strp += sprintf(strp, " --> %s",
- saddr_ntoa(INFO_GATE(&info)));
+ if (m.r.rtm.rtm_flags & RTF_LLINFO) {
+ trace_act("ignore ARP %s", str);
+ continue;
+ }
+
+ if (get_info_gate(&INFO_GATE(&info), &gate_sin)) {
+ gate = S_ADDR(INFO_GATE(&info));
+ strp += sprintf(strp, " --> %s", naddr_ntoa(gate));
+ } else {
+ gate = 0;
+ }
if (INFO_AUTHOR(&info) != 0)
strp += sprintf(strp, " by authority of %s",
@@ -1150,12 +1280,14 @@ read_rt(void)
break;
case RTM_DELETE:
- if (m.r.rtm.rtm_errno != 0) {
+ if (m.r.rtm.rtm_errno != 0
+ && m.r.rtm.rtm_errno != ESRCH) {
trace_act("ignore %s with \"%s\" error",
str, strerror(m.r.rtm.rtm_errno));
} else {
trace_act("%s", str);
- del_static(S_ADDR(INFO_DST(&info)), mask, 1);
+ del_static(S_ADDR(INFO_DST(&info)), mask,
+ gate, 1);
}
break;
@@ -1208,12 +1340,20 @@ kern_out(struct ag_info *ag)
/* modify existing kernel entry if necessary */
if (k->k_gate != ag->ag_gate
|| k->k_metric != ag->ag_metric) {
+ /* Must delete bad interface routes etc. to change them. */
+ if (k->k_metric == HOPCNT_INFINITY)
+ k->k_state |= KS_DEL_ADD;
k->k_gate = ag->ag_gate;
k->k_metric = ag->ag_metric;
k->k_state |= KS_CHANGE;
}
- if (k->k_state & KS_DYNAMIC) {
+ /* If the daemon thinks the route should exist, forget
+ * about any redirections.
+ * If the daemon thinks the route should exist, eventually
+ * override manual intervention by the operator.
+ */
+ if ((k->k_state & (KS_DYNAMIC | KS_DELETED)) != 0) {
k->k_state &= ~KS_DYNAMIC;
k->k_state |= (KS_ADD | KS_DEL_ADD);
}
@@ -1244,7 +1384,7 @@ kern_out(struct ag_info *ag)
/* ARGSUSED */
static int
walk_kern(struct radix_node *rn,
- struct walkarg *w)
+ struct walkarg *argp UNUSED)
{
#define RT ((struct rt_entry *)rn)
char metric, pref;
@@ -1256,15 +1396,33 @@ walk_kern(struct radix_node *rn,
return 0;
if (!(RT->rt_state & RS_IF)) {
- ags |= (AGS_GATEWAY | AGS_SUPPRESS | AGS_PROMOTE);
+ /* This is an ordinary route, not for an interface.
+ */
+
+ /* aggregate, ordinary good routes without regard to
+ * their metric
+ */
+ pref = 1;
+ ags |= (AGS_GATEWAY | AGS_SUPPRESS | AGS_AGGREGATE);
+
+ /* Do not install host routes directly to hosts, to avoid
+ * interfering with ARP entries in the kernel table.
+ */
+ if (RT_ISHOST(RT)
+ && ntohl(RT->rt_dst) == RT->rt_gate)
+ return 0;
} else {
- /* Do not install routes for "external" remote interfaces.
+ /* This is an interface route.
+ * 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;
+ /* Interfaces should override received routes.
+ */
+ pref = 0;
+ ags |= (AGS_IF | AGS_CORS_GATE);
/* If it is not an interface, or an alias for an interface,
* it must be a "gateway."
@@ -1274,19 +1432,23 @@ walk_kern(struct radix_node *rn,
*/
if (RT->rt_ifp == 0
|| (RT->rt_ifp->int_state & IS_REMOTE))
- ags |= (AGS_GATEWAY | AGS_SUPPRESS | AGS_PROMOTE);
+ ags |= (AGS_GATEWAY | AGS_SUPPRESS | AGS_AGGREGATE);
}
- if (RT->rt_state & RS_RDISC)
+ /* If RIP is off and IRDP is on, let the route to the discovered
+ * route suppress any RIP routes. Eventually the RIP routes
+ * will time-out and be deleted. This reaches the steady-state
+ * quicker.
+ */
+ if ((RT->rt_state & RS_RDISC) && rip_sock < 0)
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);
+ ags &= ~(AGS_IF | AGS_CORS_GATE);
}
ag_check(RT->rt_dst, RT->rt_mask, RT->rt_gate, 0,
@@ -1301,7 +1463,7 @@ walk_kern(struct radix_node *rn,
static void
fix_kern(void)
{
- int i, flags;
+ int i;
struct khash *k, **pk;
@@ -1323,46 +1485,37 @@ fix_kern(void)
/* check hold on routes deleted by the operator */
if (k->k_keep > now.tv_sec) {
+ /* ensure we check when the hold is over */
LIM_SEC(need_kern, k->k_keep);
+ /* mark for the next cycle */
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);
+ if ((k->k_state & KS_DELETE)
+ && !(k->k_state & KS_DYNAMIC)) {
+ kern_ioctl(k, RTM_DELETE, 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);
+ if (k->k_state & KS_DEL_ADD)
+ kern_ioctl(k, RTM_DELETE, 0);
+
+ if (k->k_state & KS_ADD) {
+ kern_ioctl(k, RTM_ADD,
+ ((0 != (k->k_state & (KS_GATEWAY
+ | KS_DYNAMIC)))
+ ? RTF_GATEWAY : 0));
+ } else if (k->k_state & KS_CHANGE) {
+ kern_ioctl(k, RTM_CHANGE,
+ ((0 != (k->k_state & (KS_GATEWAY
+ | KS_DYNAMIC)))
+ ? RTF_GATEWAY : 0));
}
+ 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
@@ -1382,6 +1535,7 @@ fix_kern(void)
void
del_static(naddr dst,
naddr mask,
+ naddr gate,
int gone)
{
struct khash *k;
@@ -1395,8 +1549,8 @@ del_static(naddr dst,
* and add a replacement.
*/
k = kern_find(dst, mask, 0);
- if (k != 0) {
- k->k_state &= ~(KS_STATIC | KS_DYNAMIC);
+ if (k != 0 && (gate == 0 || k->k_gate == gate)) {
+ k->k_state &= ~(KS_STATIC | KS_DYNAMIC | KS_CHECK);
k->k_state |= KS_DELETE;
if (gone) {
k->k_state |= KS_DELETED;
@@ -1445,10 +1599,11 @@ del_redirects(naddr bad_gate,
/* Start the daemon tables.
*/
+extern int max_keylen;
+
void
rtinit(void)
{
- extern int max_keylen;
int i;
struct ag_info *ag;
@@ -1475,7 +1630,7 @@ static struct sockaddr_in_new mask_sock = {_SIN_ADDR_SIZE, AF_INET};
#endif
-void
+static void
set_need_flash(void)
{
if (!need_flash) {
@@ -1523,12 +1678,8 @@ rtfind(naddr dst)
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)
+ u_int state, /* rt_state for the entry */
+ struct rt_spare *new)
{
struct rt_entry *rt;
naddr smask;
@@ -1536,7 +1687,7 @@ rtadd(naddr dst,
struct rt_spare *rts;
rt = (struct rt_entry *)rtmalloc(sizeof (*rt), "rtadd");
- bzero(rt, sizeof(*rt));
+ memset(rt, 0, sizeof(*rt));
for (rts = rt->rt_spares, i = NUM_SPARES; i != 0; i--, rts++)
rts->rts_metric = HOPCNT_INFINITY;
@@ -1555,13 +1706,9 @@ rtadd(naddr dst,
masktrim(&mask_sock);
rt->rt_mask = mask;
rt->rt_state = state;
- rt->rt_gate = gate;
- rt->rt_router = router;
+ rt->rt_spares[0] = *new;
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)
@@ -1574,8 +1721,8 @@ rtadd(naddr dst,
if (0 == rhead->rnh_addaddr(&rt->rt_dst_sock, &mask_sock,
rhead, rt->rt_nodes)) {
- msglog("rnh_addaddr() failed for %s mask=%#x",
- naddr_ntoa(dst), mask);
+ msglog("rnh_addaddr() failed for %s mask=%#lx",
+ naddr_ntoa(dst), (u_long)mask);
}
}
@@ -1585,29 +1732,24 @@ rtadd(naddr dst,
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,
+ struct rt_spare *new,
char *label)
{
- if (rt->rt_metric != metric) {
+ if (rt->rt_metric != new->rts_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) {
+ if (new->rts_metric == HOPCNT_INFINITY) {
need_kern.tv_sec = now.tv_sec;
- if (new_time >= now.tv_sec - EXPIRE_TIME)
- new_time = now.tv_sec - EXPIRE_TIME;
+ if (new->rts_time >= now.tv_sec - EXPIRE_TIME)
+ new->rts_time = now.tv_sec - EXPIRE_TIME;
}
rt->rt_seqno = update_seqno;
set_need_flash();
}
- if (rt->rt_gate != gate) {
+ if (rt->rt_gate != new->rts_gate) {
need_kern.tv_sec = now.tv_sec;
rt->rt_seqno = update_seqno;
set_need_flash();
@@ -1617,21 +1759,15 @@ rtchange(struct rt_entry *rt,
/* Keep various things from deciding ageless routes are stale.
*/
- if (!AGE_RT(state, ifp))
- new_time = now.tv_sec;
+ if (!AGE_RT(state, new->rts_ifp))
+ new->rts_time = now.tv_sec;
if (TRACEACTIONS)
- trace_change(rt, state, gate, router, metric, tag, ifp,
- new_time,
+ trace_change(rt, state, new,
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;
+ rt->rt_spares[0] = *new;
}
@@ -1679,11 +1815,13 @@ rtswitch(struct rt_entry *rt,
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)sprintf(label, "Use #%d", (int)(rts - rt->rt_spares));
+ rtchange(rt, rt->rt_state & ~(RS_NET_SYN | RS_RDISC), rts, label);
+ if (swap.rts_metric == HOPCNT_INFINITY) {
+ *rts = rts_empty;
+ } else {
+ *rts = swap;
+ }
}
@@ -1715,16 +1853,26 @@ rtdelete(struct rt_entry *rt)
}
+void
+rts_delete(struct rt_entry *rt,
+ struct rt_spare *rts)
+{
+ trace_upslot(rt, rts, &rts_empty);
+ *rts = rts_empty;
+}
+
+
/* 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);
+ struct rt_spare new;
+ /* Poison the route */
+ new = rt->rt_spares[0];
+ new.rts_metric = HOPCNT_INFINITY;
+ rtchange(rt, rt->rt_state & ~(RS_IF | RS_LOCAL | RS_STATIC), &new, 0);
rtswitch(rt, 0);
}
@@ -1789,10 +1937,10 @@ rtbad_sub(struct rt_entry *rt)
}
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);
+ struct rt_spare new = rt->rt_spares[0];
+ new.rts_ifp = ifp1;
+ rtchange(rt, ((rt->rt_state & ~(RS_NET_SYN|RS_LOCAL)) | state),
+ &new, 0);
} else {
rtbad(rt);
}
@@ -1805,12 +1953,11 @@ rtbad_sub(struct rt_entry *rt)
/* ARGSUSED */
int
walk_bad(struct radix_node *rn,
- struct walkarg *w)
+ struct walkarg *argp UNUSED)
{
#define RT ((struct rt_entry *)rn)
struct rt_spare *rts;
int i;
- time_t new_time;
/* fix any spare routes through the interface
@@ -1818,21 +1965,10 @@ walk_bad(struct radix_node *rn,
rts = RT->rt_spares;
for (i = NUM_SPARES; i != 1; i--) {
rts++;
-
- if (rts->rts_ifp != 0
- && (rts->rts_ifp->int_state & IS_BROKE)) {
- /* mark the spare route to be deleted immediately */
- 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;
- }
+ if (rts->rts_metric < HOPCNT_INFINITY
+ && (rts->rts_ifp == 0
+ || (rts->rts_ifp->int_state & IS_BROKE)))
+ rts_delete(RT, rts);
}
/* Deal with the main route
@@ -1860,7 +1996,7 @@ walk_bad(struct radix_node *rn,
/* ARGSUSED */
static int
walk_age(struct radix_node *rn,
- struct walkarg *w)
+ struct walkarg *argp UNUSED)
{
#define RT ((struct rt_entry *)rn)
struct interface *ifp;
@@ -1901,13 +2037,9 @@ walk_age(struct radix_node *rn,
/* 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;
- }
+ && now_garbage > rts->rts_time
+ && i != NUM_SPARES)
+ rts_delete(RT, rts);
}
@@ -1925,10 +2057,11 @@ walk_age(struct radix_node *rn,
}
/* 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);
+ if (now.tv_sec - RT->rt_time > EXPIRE_TIME) {
+ struct rt_spare new = RT->rt_spares[0];
+ new.rts_metric = HOPCNT_INFINITY;
+ rtchange(RT, RT->rt_state, &new, 0);
+ }
return 0;
}
@@ -1957,6 +2090,7 @@ age(naddr bad_gate)
/* ignore unreachable remote interfaces */
if (!check_remote(ifp))
continue;
+
/* Restore remote interface that has become reachable
*/
if (ifp->int_state & IS_BROKE)
@@ -1965,7 +2099,7 @@ age(naddr bad_gate)
if (ifp->int_act_time != NEVER
&& now.tv_sec - ifp->int_act_time > EXPIRE_TIME) {
msglog("remote interface %s to %s timed out after"
- " %d:%d",
+ " %ld:%ld",
ifp->int_name,
naddr_ntoa(ifp->int_dstaddr),
(now.tv_sec - ifp->int_act_time)/60,
@@ -1986,6 +2120,11 @@ age(naddr bad_gate)
age_bad_gate = bad_gate;
(void)rn_walktree(rhead, walk_age, 0);
+ /* delete old redirected routes to keep the kernel table small
+ * and prevent blackholes
+ */
+ del_redirects(bad_gate, now.tv_sec-STALE_TIME);
+
/* Update the kernel routing table. */
fix_kern();
diff --git a/sbin/routed/trace.c b/sbin/routed/trace.c
index 28c65f3f136d..da497a03607a 100644
--- a/sbin/routed/trace.c
+++ b/sbin/routed/trace.c
@@ -11,7 +11,7 @@
* 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:
+ * must display the following acknowledgment:
* 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
@@ -31,13 +31,6 @@
* 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.17 $"
-
#define RIPCMDS
#include "defs.h"
#include "pathnames.h"
@@ -45,6 +38,13 @@ static char rcsid[] = "$NetBSD$";
#include <sys/signal.h>
#include <fcntl.h>
+#if !defined(sgi) && !defined(__NetBSD__)
+static char sccsid[] __attribute__((unused)) = "@(#)trace.c 8.1 (Berkeley) 6/5/93";
+#elif defined(__NetBSD__)
+__RCSID("$NetBSD$");
+#endif
+#ident "$Revision: 2.17 $"
+
#ifdef sgi
/* use *stat64 for files on large filesystems */
@@ -55,12 +55,13 @@ static char rcsid[] = "$NetBSD$";
int tracelevel, new_tracelevel;
FILE *ftrace = stdout; /* output trace file */
-static char *sigtrace_pat = "%s\n";
+static const char *sigtrace_pat = "%s";
static char savetracename[MAXPATHLEN+1];
char inittracename[MAXPATHLEN+1];
int file_trace; /* 1=tracing to file, not stdout */
static void trace_dump(void);
+static void tmsg(const char *, ...) PATTRIB(1,2);
/* convert string to printable characters
@@ -137,7 +138,7 @@ naddr_ntoa(naddr a)
}
-char *
+const char *
saddr_ntoa(struct sockaddr *sa)
{
return (sa == 0) ? "?" : naddr_ntoa(S_ADDR(sa));
@@ -152,7 +153,7 @@ ts(time_t secs) {
#ifdef sgi
(void)cftime(s, "%T", &secs);
#else
- bcopy(ctime(&secs)+11, s, 8);
+ memcpy(s, ctime(&secs)+11, 8);
s[8] = '\0';
#endif
return s;
@@ -177,7 +178,7 @@ lastlog(void)
static void
-tmsg(char *p, ...)
+tmsg(const char *p, ...)
{
va_list args;
@@ -185,13 +186,14 @@ tmsg(char *p, ...)
lastlog();
va_start(args, p);
vfprintf(ftrace, p, args);
+ (void)fputc('\n',ftrace);
fflush(ftrace);
}
}
-static void
-trace_close(void)
+void
+trace_close(int zap_stdio)
{
int fd;
@@ -199,14 +201,17 @@ trace_close(void)
fflush(stdout);
fflush(stderr);
- if (ftrace != 0 && file_trace) {
+ if (ftrace != 0 && zap_stdio) {
if (ftrace != stdout)
fclose(ftrace);
ftrace = 0;
fd = open(_PATH_DEVNULL, O_RDWR);
- (void)dup2(fd, STDIN_FILENO);
- (void)dup2(fd, STDOUT_FILENO);
- (void)dup2(fd, STDERR_FILENO);
+ if (isatty(STDIN_FILENO))
+ (void)dup2(fd, STDIN_FILENO);
+ if (isatty(STDOUT_FILENO))
+ (void)dup2(fd, STDOUT_FILENO);
+ if (isatty(STDERR_FILENO))
+ (void)dup2(fd, STDERR_FILENO);
(void)close(fd);
}
lastlog_time.tv_sec = 0;
@@ -219,13 +224,13 @@ trace_flush(void)
if (ftrace != 0) {
fflush(ftrace);
if (ferror(ftrace))
- trace_off("tracing off: ", strerror(ferror(ftrace)));
+ trace_off("tracing off: %s", strerror(ferror(ftrace)));
}
}
void
-trace_off(char *p, ...)
+trace_off(const char *p, ...)
{
va_list args;
@@ -234,8 +239,9 @@ trace_off(char *p, ...)
lastlog();
va_start(args, p);
vfprintf(ftrace, p, args);
+ (void)fputc('\n',ftrace);
}
- trace_close();
+ trace_close(file_trace);
new_tracelevel = tracelevel = 0;
}
@@ -244,16 +250,16 @@ trace_off(char *p, ...)
/* log a change in tracing
*/
void
-tracelevel_msg(char *pat,
+tracelevel_msg(const char *pat,
int dump) /* -1=no dump, 0=default, 1=force */
{
- static char *off_msgs[MAX_TRACELEVEL] = {
+ static const char *off_msgs[MAX_TRACELEVEL] = {
"Tracing actions stopped",
"Tracing packets stopped",
"Tracing packet contents stopped",
"Tracing kernel changes stopped",
};
- static char *on_msgs[MAX_TRACELEVEL] = {
+ static const char *on_msgs[MAX_TRACELEVEL] = {
"Tracing actions started",
"Tracing packets started",
"Tracing packet contents started",
@@ -288,13 +294,13 @@ tracelevel_msg(char *pat,
void
-set_tracefile(char *filename,
- char *pat,
+set_tracefile(const char *filename,
+ const char *pat,
int dump) /* -1=no dump, 0=default, 1=force */
{
struct stat stbuf;
FILE *n_ftrace;
- char *fn;
+ const char *fn;
/* Allow a null filename to increase the level if the trace file
@@ -336,8 +342,7 @@ set_tracefile(char *filename,
/* If the new tracefile exists, it must be a regular file.
*/
- if (stat(filename, &stbuf) >= 0
- && (stbuf.st_mode & S_IFMT) != S_IFREG) {
+ if (stat(filename, &stbuf) >= 0 && !S_ISREG(stbuf.st_mode)) {
msglog("wrong type (%#x) of trace file \"%s\"",
stbuf.st_mode, filename);
return;
@@ -356,10 +361,9 @@ set_tracefile(char *filename,
return;
}
- tmsg("switch to trace file %s\n", fn);
+ tmsg("switch to trace file %s", fn);
- file_trace = 1;
- trace_close();
+ trace_close(file_trace = 1);
if (fn != savetracename)
strncpy(savetracename, fn, sizeof(savetracename)-1);
@@ -379,19 +383,19 @@ set_tracefile(char *filename,
/* ARGSUSED */
void
-sigtrace_on(int s)
+sigtrace_on(int s UNUSED)
{
new_tracelevel++;
- sigtrace_pat = "SIGUSR1: %s\n";
+ sigtrace_pat = "SIGUSR1: %s";
}
/* ARGSUSED */
void
-sigtrace_off(int s)
+sigtrace_off(int s UNUSED)
{
new_tracelevel--;
- sigtrace_pat = "SIGUSR2: %s\n";
+ sigtrace_pat = "SIGUSR2: %s";
}
@@ -462,9 +466,9 @@ addrname(naddr addr, /* in network byte order */
/* display a bit-field
*/
struct bits {
- int bits_mask;
- int bits_clear;
- char *bits_name;
+ u_int bits_mask;
+ u_int bits_clear;
+ const char *bits_name;
};
static struct bits if_bits[] = {
@@ -531,11 +535,11 @@ static struct bits rs_bits[] = {
static void
-trace_bits(struct bits *tbl,
+trace_bits(const struct bits *tbl,
u_int field,
int force)
{
- int b;
+ u_int b;
char c;
if (force) {
@@ -571,17 +575,17 @@ trace_bits(struct bits *tbl,
}
-static char *
-trace_pair(naddr dst,
- naddr mask,
- char *gate)
+char *
+rtname(naddr dst,
+ naddr mask,
+ naddr 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);
+ (void)sprintf(&buf[i], "%-*s", 15+20-MAX(20,i), naddr_ntoa(gate));
return buf;
}
@@ -594,6 +598,9 @@ print_rts(struct rt_spare *rts,
int force_tag, /* -1=suppress, 0=default, 1=display */
int force_time) /* 0=suppress, 1=display */
{
+ int i;
+
+
if (force_metric >= 0)
(void)fprintf(ftrace, "metric=%-2d ", rts->rts_metric);
if (force_ifp >= 0)
@@ -607,14 +614,19 @@ print_rts(struct rt_spare *rts,
(void)fprintf(ftrace, "%s ", ts(rts->rts_time));
if (force_tag > 0
|| (force_tag == 0 && rts->rts_tag != 0))
- (void)fprintf(ftrace, "tag=%#x ",
- ntohs(rts->rts_tag));
+ (void)fprintf(ftrace, "tag=%#x ", ntohs(rts->rts_tag));
+ if (rts->rts_de_ag != 0) {
+ for (i = 1; (u_int)(1 << i) <= rts->rts_de_ag; i++)
+ continue;
+ (void)fprintf(ftrace, "de_ag=%d ", i);
+ }
+
}
void
-trace_if(char *act,
- struct interface *ifp)
+trace_if(const char *act,
+ struct interface *ifp)
{
if (!TRACEACTIONS || ftrace == 0)
return;
@@ -641,85 +653,82 @@ trace_if(char *act,
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)
+ struct rt_spare *new)
{
- struct rt_spare new;
-
if (!TRACEACTIONS || ftrace == 0)
return;
- if (rts->rts_gate == gate
- && rts->rts_router == router
- && rts->rts_metric == metric
- && rts->rts_tag == tag)
+ if (rts->rts_gate == new->rts_gate
+ && rts->rts_router == new->rts_router
+ && rts->rts_metric == new->rts_metric
+ && rts->rts_tag == new->rts_tag
+ && rts->rts_de_ag == new->rts_de_ag)
return;
- new.rts_ifp = ifp;
- new.rts_gate = gate;
- new.rts_router = router;
- new.rts_metric = metric;
- new.rts_time = new_time;
- new.rts_tag = tag;
lastlog();
- if (rts->rts_gate != RIP_DEFAULT) {
+ if (new->rts_gate == 0) {
+ (void)fprintf(ftrace, "Del #%d %-35s ",
+ (int)(rts - rt->rt_spares),
+ rtname(rt->rt_dst, rt->rt_mask, rts->rts_gate));
+ print_rts(rts, 0,0,0,0,
+ (rts != rt->rt_spares
+ || AGE_RT(rt->rt_state,new->rts_ifp)));
+
+ } else 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)));
+ (int)(rts - rt->rt_spares),
+ rtname(rt->rt_dst, rt->rt_mask, rts->rts_gate));
print_rts(rts, 0,0,
- rts->rts_gate != gate,
- rts->rts_tag != tag,
+ rts->rts_gate != new->rts_gate,
+ rts->rts_tag != new->rts_tag,
rts != rt->rt_spares || AGE_RT(rt->rt_state,
rt->rt_ifp));
(void)fprintf(ftrace, "\n %19s%-16s ", "",
- gate != rts->rts_gate ? naddr_ntoa(gate) : "");
- print_rts(&new,
- -(metric == rts->rts_metric),
- -(ifp == rts->rts_ifp),
+ (new->rts_gate != rts->rts_gate
+ ? naddr_ntoa(new->rts_gate) : ""));
+ print_rts(new,
+ -(new->rts_metric == rts->rts_metric),
+ -(new->rts_ifp == rts->rts_ifp),
0,
- rts->rts_tag != tag,
- new_time != rts->rts_time && (rts != rt->rt_spares
- || AGE_RT(rt->rt_state,
- ifp)));
+ rts->rts_tag != new->rts_tag,
+ (new->rts_time != rts->rts_time
+ && (rts != rt->rt_spares
+ || AGE_RT(rt->rt_state, new->rts_ifp))));
} else {
(void)fprintf(ftrace, "Add #%d %-35s ",
- rts - rt->rt_spares,
- trace_pair(rt->rt_dst, rt->rt_mask,
- naddr_ntoa(gate)));
- print_rts(&new, 0,0,0,0,
- rts != rt->rt_spares || AGE_RT(rt->rt_state,ifp));
+ (int)(rts - rt->rt_spares),
+ rtname(rt->rt_dst, rt->rt_mask, new->rts_gate));
+ print_rts(new, 0,0,0,0,
+ (rts != rt->rt_spares
+ || AGE_RT(rt->rt_state,new->rts_ifp)));
}
(void)fputc('\n',ftrace);
}
-/* talk about a change made to the kernel table
+/* miscellaneous message checked by the caller
*/
void
-trace_kernel(char *p, ...)
+trace_misc(const char *p, ...)
{
va_list args;
- if (!TRACEKERNEL || ftrace == 0)
+ if (ftrace == 0)
return;
lastlog();
va_start(args, p);
vfprintf(ftrace, p, args);
+ (void)fputc('\n',ftrace);
}
/* display a message if tracing actions
*/
void
-trace_act(char *p, ...)
+trace_act(const char *p, ...)
{
va_list args;
@@ -736,7 +745,7 @@ trace_act(char *p, ...)
/* display a message if tracing packets
*/
void
-trace_pkt(char *p, ...)
+trace_pkt(const char *p, ...)
{
va_list args;
@@ -753,50 +762,39 @@ trace_pkt(char *p, ...)
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)
+ struct rt_spare *new,
+ const char *label)
{
- struct rt_spare new;
-
if (ftrace == 0)
return;
- if (rt->rt_metric == metric
- && rt->rt_gate == gate
- && rt->rt_router == router
+ if (rt->rt_metric == new->rts_metric
+ && rt->rt_gate == new->rts_gate
+ && rt->rt_router == new->rts_router
&& rt->rt_state == state
- && rt->rt_tag == tag)
+ && rt->rt_tag == new->rts_tag
+ && rt->rt_de_ag == new->rts_de_ag)
return;
- new.rts_ifp = ifp;
- new.rts_gate = gate;
- new.rts_router = router;
- new.rts_metric = metric;
- new.rts_time = new_time;
- new.rts_tag = tag;
lastlog();
(void)fprintf(ftrace, "%s %-35s ",
label,
- trace_pair(rt->rt_dst, rt->rt_mask,
- naddr_ntoa(rt->rt_gate)));
+ rtname(rt->rt_dst, rt->rt_mask, rt->rt_gate));
print_rts(rt->rt_spares,
0,0,0,0, AGE_RT(rt->rt_state, rt->rt_ifp));
trace_bits(rs_bits, rt->rt_state, rt->rt_state != state);
(void)fprintf(ftrace, "\n%*s %19s%-16s ",
- strlen(label), "", "",
- rt->rt_gate != gate ? naddr_ntoa(gate) : "");
- print_rts(&new,
- -(metric == rt->rt_metric),
- -(ifp == rt->rt_ifp),
+ (int)strlen(label), "", "",
+ (rt->rt_gate != new->rts_gate
+ ? naddr_ntoa(new->rts_gate) : ""));
+ print_rts(new,
+ -(new->rts_metric == rt->rt_metric),
+ -(new->rts_ifp == rt->rt_ifp),
0,
- rt->rt_tag != tag,
- rt->rt_time != new_time && AGE_RT(rt->rt_state,ifp));
+ rt->rt_tag != new->rts_tag,
+ (rt->rt_time != new->rts_time
+ && AGE_RT(rt->rt_state,new->rts_ifp)));
if (rt->rt_state != state)
trace_bits(rs_bits, state, 1);
(void)fputc('\n',ftrace);
@@ -804,7 +802,7 @@ trace_change(struct rt_entry *rt,
void
-trace_add_del(char * action, struct rt_entry *rt)
+trace_add_del(const char * action, struct rt_entry *rt)
{
if (ftrace == 0)
return;
@@ -812,8 +810,7 @@ trace_add_del(char * action, struct rt_entry *rt)
lastlog();
(void)fprintf(ftrace, "%s %-35s ",
action,
- trace_pair(rt->rt_dst, rt->rt_mask,
- naddr_ntoa(rt->rt_gate)));
+ rtname(rt->rt_dst, rt->rt_mask, rt->rt_gate));
print_rts(rt->rt_spares, 0,0,0,0,AGE_RT(rt->rt_state,rt->rt_ifp));
trace_bits(rs_bits, rt->rt_state, 0);
(void)fputc('\n',ftrace);
@@ -823,21 +820,20 @@ trace_add_del(char * action, struct rt_entry *rt)
/* ARGSUSED */
static int
walk_trace(struct radix_node *rn,
- struct walkarg *w)
+ struct walkarg *w UNUSED)
{
#define RT ((struct rt_entry *)rn)
struct rt_spare *rts;
- int i, age = AGE_RT(RT->rt_state, RT->rt_ifp);
+ int i;
- (void)fprintf(ftrace, " %-35s ", trace_pair(RT->rt_dst, RT->rt_mask,
- naddr_ntoa(RT->rt_gate)));
- print_rts(&RT->rt_spares[0], 0,0,0,0,age);
+ (void)fprintf(ftrace, " %-35s ",
+ rtname(RT->rt_dst, RT->rt_mask, RT->rt_gate));
+ print_rts(&RT->rt_spares[0], 0,0,0,0, AGE_RT(RT->rt_state, RT->rt_ifp));
trace_bits(rs_bits, RT->rt_state, 0);
if (RT->rt_poison_time >= now_garbage
&& RT->rt_poison_metric < RT->rt_metric)
(void)fprintf(ftrace, "pm=%d@%s",
- RT->rt_poison_metric,
- ts(RT->rt_poison_time));
+ RT->rt_poison_metric, ts(RT->rt_poison_time));
rts = &RT->rt_spares[1];
for (i = 1; i < NUM_SPARES; i++, rts++) {
@@ -870,14 +866,14 @@ trace_dump(void)
void
-trace_rip(char *dir1, char *dir2,
+trace_rip(const char *dir1, const char *dir2,
struct sockaddr_in *who,
struct interface *ifp,
struct rip *msg,
int size) /* total size of message */
{
struct netinfo *n, *lim;
-# define NA (msg->rip_auths)
+# define NA ((struct netauth*)n)
int i, seen_route;
if (!TRACEPACKETS || ftrace == 0)
@@ -947,23 +943,24 @@ trace_rip(char *dir1, char *dir2,
if (NA->a_type == RIP_AUTH_MD5
&& n == msg->rip_nets) {
(void)fprintf(ftrace,
- "\tMD5 Authentication"
- " len=%d KeyID=%u"
- " seqno=%u"
+ "\tMD5 Auth"
+ " pkt_len=%d KeyID=%u"
+ " auth_len=%d"
+ " seqno=%#x"
" rsvd=%#x,%#x\n",
- NA->au.a_md5.md5_pkt_len,
- NA->au.a_md5.md5_keyid,
- NA->au.a_md5.md5_seqno,
- NA->au.a_md5.rsvd[0],
- NA->au.a_md5.rsvd[1]);
+ ntohs(NA->au.a_md5.md5_pkt_len),
+ NA->au.a_md5.md5_keyid,
+ NA->au.a_md5.md5_auth_len,
+ (int)ntohl(NA->au.a_md5.md5_seqno),
+ (int)ntohs(NA->au.a_md5.rsvd[0]),
+ (int)ntohs(NA->au.a_md5.rsvd[1]));
continue;
}
(void)fprintf(ftrace,
- "\tAuthentication"
- " type %d: ",
+ "\tAuthentication type %d: ",
ntohs(NA->a_type));
for (i = 0;
- i < sizeof(NA->au.au_pw);
+ i < (int)sizeof(NA->au.au_pw);
i++)
(void)fprintf(ftrace, "%02x ",
NA->au.au_pw[i]);