Latest-and-greatest routed.
Includes RIPv2 and Router Discovery. Submitted by: Vernon Schryver <vjs@calcite.rhyolite.com>
This commit is contained in:
parent
cdb877c33d
commit
2c7a97817b
|
@ -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
|
||||
|
|
|
@ -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 *);
|
||||
|
|
225
sbin/routed/if.c
225
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;
|
||||
|
|
|
@ -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";
|
||||
#elif defined(__NetBSD__)
|
||||
static char rcsid[] = "$NetBSD$";
|
||||
#endif
|
||||
#ident "$Revision: 1.21 $"
|
||||
|
||||
#include "defs.h"
|
||||
|
||||
#if !defined(sgi) && !defined(__NetBSD__)
|
||||
static char sccsid[] __attribute__((unused)) = "@(#)input.c 8.1 (Berkeley) 6/5/93";
|
||||
#elif defined(__NetBSD__)
|
||||
#include <sys/cdefs.h>
|
||||
__RCSID("$NetBSD$");
|
||||
#endif
|
||||
#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.
|
||||
*/
|
||||
int old_metric = rts->rts_metric;
|
||||
|
||||
/* 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.
|
||||
*/
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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";
|
||||
#elif defined(__NetBSD__)
|
||||
static char rcsid[] = "$NetBSD$";
|
||||
#endif
|
||||
#ident "$Revision: 1.21 $"
|
||||
|
||||
#include "defs.h"
|
||||
|
||||
#if !defined(sgi) && !defined(__NetBSD__)
|
||||
static char sccsid[] __attribute__((unused)) = "@(#)output.c 8.1 (Berkeley) 6/5/93";
|
||||
#elif defined(__NetBSD__)
|
||||
__RCSID("$NetBSD$");
|
||||
#endif
|
||||
#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;
|
||||
}
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
/* Adjust the outgoing metric by the cost of the link.
|
||||
* Avoid aggregation when a route is counting to infinity.
|
||||
*/
|
||||
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;
|
||||
pref = RT->rt_poison_metric + ws.metric;
|
||||
metric += ws.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;
|
||||
/* 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;
|
||||
|
|
|
@ -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 */
|
||||
p = lptr+strlen(lptr)-1;
|
||||
while (*p == '\n'
|
||||
|| (*p == ' ' && (p == lptr+1 || *(p-1) != '\\')))
|
||||
*p-- = '\0';
|
||||
if (*lptr == '\0' /* ignore null and comment lines */
|
||||
|| *lptr == '#')
|
||||
continue;
|
||||
p = lptr+strlen(lptr)-1;
|
||||
while (*p == '\n' || *p == ' ')
|
||||
*p-- = '\0';
|
||||
|
||||
/* 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));
|
||||
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)) {
|
||||
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;
|
||||
}
|
||||
if (tm.tm_year <= 37)
|
||||
tm.tm_year += 100;
|
||||
#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_mon < 1 || tm.tm_mon > 12
|
||||
|| tm.tm_mday < 1 || tm.tm_mday > 31) {
|
||||
sprintf(buf,"bad timestamp %.25s", val0);
|
||||
return buf;
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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_ */
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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') {
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -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]);
|
||||
|
|
Loading…
Reference in New Issue