Merge-o-matic and add a bunch of $Id's
This commit is contained in:
commit
c90fe7dc24
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=46303
@ -1,13 +1,13 @@
|
|||||||
# From: @(#)Makefile 8.1 (Berkeley) 6/19/93
|
# Make `routed` for FreeBSD
|
||||||
# $Id$
|
# $Revision: 2.15 $
|
||||||
|
# $Id$
|
||||||
|
|
||||||
PROG= routed
|
PROG= routed
|
||||||
SRCS= if.c input.c main.c output.c parms.c radix.c rdisc.c table.c \
|
SRCS= if.c input.c main.c output.c parms.c radix.c rdisc.c table.c trace.c
|
||||||
trace.c
|
MAN8= routed.8
|
||||||
MAN8= routed.8
|
SUBDIR= rtquery
|
||||||
SUBDIR= rtquery
|
LDADD+= -lmd
|
||||||
LDADD+= -lmd
|
DPADD+= ${LIBMD}
|
||||||
DPADD+= ${LIBMD}
|
#COPTS= -g -DDEBUG -W -Wall -Wcast-align -Wcast-qual -Winline -Wpointer-arith -Wnested-externs -Wwrite-strings -Wunused
|
||||||
#COPTS= -g -DDEBUG -Wall
|
|
||||||
|
|
||||||
.include <bsd.prog.mk>
|
.include <bsd.prog.mk>
|
||||||
|
@ -11,7 +11,7 @@
|
|||||||
* notice, this list of conditions and the following disclaimer in the
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
* documentation and/or other materials provided with the distribution.
|
* documentation and/or other materials provided with the distribution.
|
||||||
* 3. All advertising materials mentioning features or use of this software
|
* 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
|
* This product includes software developed by the University of
|
||||||
* California, Berkeley and its contributors.
|
* California, Berkeley and its contributors.
|
||||||
* 4. Neither the name of the University nor the names of its contributors
|
* 4. Neither the name of the University nor the names of its contributors
|
||||||
@ -31,9 +31,14 @@
|
|||||||
* SUCH DAMAGE.
|
* SUCH DAMAGE.
|
||||||
*
|
*
|
||||||
* @(#)defs.h 8.1 (Berkeley) 6/5/93
|
* @(#)defs.h 8.1 (Berkeley) 6/5/93
|
||||||
* $Id: defs.h,v 1.9 1997/02/22 14:33:11 peter Exp $
|
*
|
||||||
|
* $Id$
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#ifdef sgi
|
||||||
|
#ident "$Revision: 2.17 $"
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Definitions for RIPv2 routing process.
|
/* Definitions for RIPv2 routing process.
|
||||||
*
|
*
|
||||||
* This code is based on the 4.4BSD `routed` daemon, with extensions to
|
* This code is based on the 4.4BSD `routed` daemon, with extensions to
|
||||||
@ -72,16 +77,20 @@
|
|||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <syslog.h>
|
#include <syslog.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
#include <sys/cdefs.h>
|
||||||
|
#include <sys/time.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/param.h>
|
#include <sys/param.h>
|
||||||
#include <sys/ioctl.h>
|
#include <sys/ioctl.h>
|
||||||
#include <sys/sysctl.h>
|
#include <sys/sysctl.h>
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
#include <sys/time.h>
|
|
||||||
#ifdef sgi
|
#ifdef sgi
|
||||||
|
#define _USER_ROUTE_TREE
|
||||||
#include <net/radix.h>
|
#include <net/radix.h>
|
||||||
#else
|
#else
|
||||||
#include "radix.h"
|
#include "radix.h"
|
||||||
|
#define UNUSED __attribute__((unused))
|
||||||
|
#define PATTRIB(f,l) __attribute__((format (printf,f,l)))
|
||||||
#endif
|
#endif
|
||||||
#include <net/if.h>
|
#include <net/if.h>
|
||||||
#include <net/route.h>
|
#include <net/route.h>
|
||||||
@ -99,13 +108,13 @@
|
|||||||
* It should be defined somewhere netinet/in.h, but it is not.
|
* It should be defined somewhere netinet/in.h, but it is not.
|
||||||
*/
|
*/
|
||||||
#ifdef sgi
|
#ifdef sgi
|
||||||
#define naddr __uint32_t
|
|
||||||
#else
|
|
||||||
#ifdef __NetBSD__
|
|
||||||
#define naddr u_int32_t
|
#define naddr u_int32_t
|
||||||
|
#elif defined (__NetBSD__)
|
||||||
|
#define naddr u_int32_t
|
||||||
|
#define _HAVE_SA_LEN
|
||||||
|
#define _HAVE_SIN_LEN
|
||||||
#else
|
#else
|
||||||
#define naddr u_long
|
#define naddr u_long
|
||||||
#endif
|
|
||||||
#define _HAVE_SA_LEN
|
#define _HAVE_SA_LEN
|
||||||
#define _HAVE_SIN_LEN
|
#define _HAVE_SIN_LEN
|
||||||
#endif
|
#endif
|
||||||
@ -113,7 +122,9 @@
|
|||||||
/* Turn on if IP_DROP_MEMBERSHIP and IP_ADD_MEMBERSHIP do not look at
|
/* Turn on if IP_DROP_MEMBERSHIP and IP_ADD_MEMBERSHIP do not look at
|
||||||
* the dstaddr of point-to-point interfaces.
|
* the dstaddr of point-to-point interfaces.
|
||||||
*/
|
*/
|
||||||
/* #define MCAST_PPP_BUG */
|
#ifdef __NetBSD__
|
||||||
|
#define MCAST_PPP_BUG
|
||||||
|
#endif
|
||||||
|
|
||||||
#define DAY (24*60*60)
|
#define DAY (24*60*60)
|
||||||
#define NEVER DAY /* a long time */
|
#define NEVER DAY /* a long time */
|
||||||
@ -165,6 +176,9 @@ union pkt_buf {
|
|||||||
struct rip rip;
|
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
|
/* No more routes than this, to protect ourself in case something goes
|
||||||
* whacko and starts broadcasting zillions of bogus routes.
|
* whacko and starts broadcasting zillions of bogus routes.
|
||||||
@ -195,19 +209,21 @@ struct rt_entry {
|
|||||||
char rts_metric;
|
char rts_metric;
|
||||||
u_short rts_tag;
|
u_short rts_tag;
|
||||||
time_t rts_time; /* timer to junk stale routes */
|
time_t rts_time; /* timer to junk stale routes */
|
||||||
|
u_int rts_de_ag; /* de-aggregation level */
|
||||||
#define NUM_SPARES 4
|
#define NUM_SPARES 4
|
||||||
} rt_spares[NUM_SPARES];
|
} rt_spares[NUM_SPARES];
|
||||||
u_int rt_seqno; /* when last changed */
|
u_int rt_seqno; /* when last changed */
|
||||||
char rt_poison_metric; /* to notice maximum recently */
|
char rt_poison_metric; /* to notice maximum recently */
|
||||||
time_t rt_poison_time; /* advertised metric */
|
time_t rt_poison_time; /* advertised metric */
|
||||||
};
|
};
|
||||||
#define rt_dst rt_dst_sock.sin_addr.s_addr
|
#define rt_dst rt_dst_sock.sin_addr.s_addr
|
||||||
#define rt_ifp rt_spares[0].rts_ifp
|
#define rt_ifp rt_spares[0].rts_ifp
|
||||||
#define rt_gate rt_spares[0].rts_gate
|
#define rt_gate rt_spares[0].rts_gate
|
||||||
#define rt_router rt_spares[0].rts_router
|
#define rt_router rt_spares[0].rts_router
|
||||||
#define rt_metric rt_spares[0].rts_metric
|
#define rt_metric rt_spares[0].rts_metric
|
||||||
#define rt_tag rt_spares[0].rts_tag
|
#define rt_tag rt_spares[0].rts_tag
|
||||||
#define rt_time rt_spares[0].rts_time
|
#define rt_time rt_spares[0].rts_time
|
||||||
|
#define rt_de_ag rt_spares[0].rts_de_ag
|
||||||
|
|
||||||
#define HOST_MASK 0xffffffff
|
#define HOST_MASK 0xffffffff
|
||||||
#define RT_ISHOST(rt) ((rt)->rt_mask == HOST_MASK)
|
#define RT_ISHOST(rt) ((rt)->rt_mask == HOST_MASK)
|
||||||
@ -235,7 +251,7 @@ struct rt_entry {
|
|||||||
* - or the current route is equal but stale
|
* - or the current route is equal but stale
|
||||||
* - or it is a host route advertised by a system for itself
|
* - 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 \
|
&& now_stale <= (A)->rts_time \
|
||||||
&& ((A)->rts_metric < (B)->rts_metric \
|
&& ((A)->rts_metric < (B)->rts_metric \
|
||||||
|| ((A)->rts_gate == (A)->rts_router \
|
|| ((A)->rts_gate == (A)->rts_router \
|
||||||
@ -256,7 +272,7 @@ struct interface {
|
|||||||
struct interface *int_bhash, **int_bhash_prev;
|
struct interface *int_bhash, **int_bhash_prev;
|
||||||
struct interface *int_rlink, **int_rlink_prev;
|
struct interface *int_rlink, **int_rlink_prev;
|
||||||
struct interface *int_nhash, **int_nhash_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;
|
u_short int_index;
|
||||||
naddr int_addr; /* address on this host (net order) */
|
naddr int_addr; /* address on this host (net order) */
|
||||||
naddr int_brdaddr; /* broadcast address (n) */
|
naddr int_brdaddr; /* broadcast address (n) */
|
||||||
@ -287,12 +303,13 @@ struct interface {
|
|||||||
} int_data;
|
} int_data;
|
||||||
# define MAX_AUTH_KEYS 5
|
# define MAX_AUTH_KEYS 5
|
||||||
struct auth { /* authentication info */
|
struct auth { /* authentication info */
|
||||||
u_char type;
|
u_int16_t type;
|
||||||
u_char key[RIP_AUTH_PW_LEN];
|
u_char key[RIP_AUTH_PW_LEN];
|
||||||
u_char keyid;
|
u_char keyid;
|
||||||
time_t start, end;
|
time_t start, end;
|
||||||
} int_auth[MAX_AUTH_KEYS];
|
} 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_int; /* MaxAdvertiseInterval */
|
||||||
int int_rdisc_cnt;
|
int int_rdisc_cnt;
|
||||||
struct timeval int_rdisc_timer;
|
struct timeval int_rdisc_timer;
|
||||||
@ -325,23 +342,19 @@ struct interface {
|
|||||||
#define IS_NO_RIP (IS_NO_RIP_OUT | IS_NO_RIP_IN)
|
#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_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_RIP_OFF(s) (((s) & IS_NO_RIP) == IS_NO_RIP)
|
||||||
#define IS_NO_ADV_IN 0x0100000
|
#define IS_NO_RIP_MCAST 0x0100000 /* broadcast RIPv2 */
|
||||||
#define IS_NO_SOL_OUT 0x0200000 /* no solicitations */
|
#define IS_NO_ADV_IN 0x0200000 /* do not listen to advertisements */
|
||||||
#define IS_SOL_OUT 0x0400000 /* send solicitations */
|
#define IS_NO_SOL_OUT 0x0400000 /* send no solicitations */
|
||||||
#define GROUP_IS_SOL (IS_NO_ADV_IN|IS_NO_SOL_OUT)
|
#define IS_SOL_OUT 0x0800000 /* send solicitations */
|
||||||
#define IS_NO_ADV_OUT 0x0800000 /* do not advertise rdisc */
|
#define GROUP_IS_SOL_OUT (IS_SOL_OUT | IS_NO_SOL_OUT)
|
||||||
#define IS_ADV_OUT 0x1000000 /* advertise rdisc */
|
#define IS_NO_ADV_OUT 0x1000000 /* do not advertise rdisc */
|
||||||
#define GROUP_IS_ADV (IS_NO_ADV_OUT|IS_ADV_OUT)
|
#define IS_ADV_OUT 0x2000000 /* advertise rdisc */
|
||||||
#define IS_BCAST_RDISC 0x2000000 /* broadcast instead of multicast */
|
#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_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(f) ((f) & IFF_UP)
|
||||||
#define IFF_UP_RUNNING (IFF_RUNNING|IFF_UP)
|
|
||||||
#else
|
|
||||||
#define IFF_UP_RUNNING IFF_UP
|
|
||||||
#endif
|
|
||||||
#define iff_alive(f) (((f) & IFF_UP_RUNNING) == IFF_UP_RUNNING)
|
|
||||||
|
|
||||||
|
|
||||||
/* Information for aggregating routes */
|
/* Information for aggregating routes */
|
||||||
@ -359,7 +372,7 @@ struct ag_info {
|
|||||||
u_short ag_tag;
|
u_short ag_tag;
|
||||||
u_short ag_state;
|
u_short ag_state;
|
||||||
#define AGS_SUPPRESS 0x001 /* combine with coarser mask */
|
#define AGS_SUPPRESS 0x001 /* combine with coarser mask */
|
||||||
#define AGS_PROMOTE 0x002 /* synthesize combined routes */
|
#define AGS_AGGREGATE 0x002 /* synthesize combined routes */
|
||||||
#define AGS_REDUN0 0x004 /* redundant, finer routes output */
|
#define AGS_REDUN0 0x004 /* redundant, finer routes output */
|
||||||
#define AGS_REDUN1 0x008
|
#define AGS_REDUN1 0x008
|
||||||
#define AG_IS_REDUN(state) (((state) & (AGS_REDUN0 | AGS_REDUN1)) \
|
#define AG_IS_REDUN(state) (((state) & (AGS_REDUN0 | AGS_REDUN1)) \
|
||||||
@ -374,37 +387,50 @@ struct ag_info {
|
|||||||
#define AGS_SPLIT_HZ 0x200 /* suppress for split horizon */
|
#define AGS_SPLIT_HZ 0x200 /* suppress for split horizon */
|
||||||
|
|
||||||
/* some bits are set if they are set on either route */
|
/* some bits are set if they are set on either route */
|
||||||
#define AGS_PROMOTE_EITHER (AGS_RIPV2 | AGS_GATEWAY | \
|
#define AGS_AGGREGATE_EITHER (AGS_RIPV2 | AGS_GATEWAY | \
|
||||||
AGS_SUPPRESS | AGS_CORS_GATE)
|
AGS_SUPPRESS | AGS_CORS_GATE)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/* parameters for interfaces */
|
/* parameters for interfaces */
|
||||||
extern struct parm {
|
extern struct parm {
|
||||||
struct parm *parm_next;
|
struct parm *parm_next;
|
||||||
char parm_name[IFNAMSIZ+1];
|
char parm_name[IF_NAME_LEN+1];
|
||||||
naddr parm_net;
|
naddr parm_net;
|
||||||
naddr parm_mask;
|
naddr parm_mask;
|
||||||
|
|
||||||
char parm_d_metric;
|
char parm_d_metric;
|
||||||
u_int parm_int_state;
|
u_int parm_int_state;
|
||||||
int parm_rdisc_pref;
|
int parm_rdisc_pref; /* signed IRDP preference */
|
||||||
int parm_rdisc_int;
|
int parm_rdisc_int; /* IRDP advertising interval */
|
||||||
struct auth parm_auth[MAX_AUTH_KEYS];
|
struct auth parm_auth[MAX_AUTH_KEYS];
|
||||||
} *parms;
|
} *parms;
|
||||||
|
|
||||||
/* authority for internal networks */
|
/* authority for internal networks */
|
||||||
extern struct intnet {
|
extern struct intnet {
|
||||||
struct intnet *intnet_next;
|
struct intnet *intnet_next;
|
||||||
naddr intnet_addr;
|
naddr intnet_addr; /* network byte order */
|
||||||
naddr intnet_mask;
|
naddr intnet_mask;
|
||||||
char intnet_metric;
|
char intnet_metric;
|
||||||
} *intnets;
|
} *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 */
|
/* trusted routers */
|
||||||
extern struct tgate {
|
extern struct tgate {
|
||||||
struct tgate *tgate_next;
|
struct tgate *tgate_next;
|
||||||
naddr tgate_addr;
|
naddr tgate_addr;
|
||||||
|
#define MAX_TGATE_NETS 32
|
||||||
|
struct tgate_net {
|
||||||
|
naddr net; /* host order */
|
||||||
|
naddr mask;
|
||||||
|
} tgate_nets[MAX_TGATE_NETS];
|
||||||
} *tgates;
|
} *tgates;
|
||||||
|
|
||||||
enum output_type {OUT_QUERY, OUT_UNICAST, OUT_BROADCAST, OUT_MULTICAST,
|
enum output_type {OUT_QUERY, OUT_UNICAST, OUT_BROADCAST, OUT_MULTICAST,
|
||||||
@ -433,8 +459,8 @@ extern int rdisc_sock; /* router-discovery raw socket */
|
|||||||
|
|
||||||
extern int seqno; /* sequence number for messages */
|
extern int seqno; /* sequence number for messages */
|
||||||
extern int supplier; /* process should supply updates */
|
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 supplier_set; /* -s or -q requested */
|
||||||
|
extern int lookforinterfaces; /* 1=probe for new up interfaces */
|
||||||
extern int ridhosts; /* 1=reduce host routes */
|
extern int ridhosts; /* 1=reduce host routes */
|
||||||
extern int mhome; /* 1=want multi-homed host route */
|
extern int mhome; /* 1=want multi-homed host route */
|
||||||
extern int advertise_mhome; /* 1=must continue advertising it */
|
extern int advertise_mhome; /* 1=must continue advertising it */
|
||||||
@ -464,7 +490,7 @@ extern int have_ripv1_out; /* have a RIPv1 interface */
|
|||||||
extern int have_ripv1_in;
|
extern int have_ripv1_in;
|
||||||
extern int need_flash; /* flash update needed */
|
extern int need_flash; /* flash update needed */
|
||||||
extern struct timeval need_kern; /* need to update kernel table */
|
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;
|
extern int tracelevel, new_tracelevel;
|
||||||
#define MAX_TRACELEVEL 4
|
#define MAX_TRACELEVEL 4
|
||||||
@ -483,7 +509,7 @@ extern struct radix_node_head *rhead;
|
|||||||
#define dup2(x,y) BSDdup2(x,y)
|
#define dup2(x,y) BSDdup2(x,y)
|
||||||
#endif /* sgi */
|
#endif /* sgi */
|
||||||
|
|
||||||
extern void fix_sock(int, char *);
|
extern void fix_sock(int, const char *);
|
||||||
extern void fix_select(void);
|
extern void fix_select(void);
|
||||||
extern void rip_off(void);
|
extern void rip_off(void);
|
||||||
extern void rip_on(struct interface *);
|
extern void rip_on(struct interface *);
|
||||||
@ -497,7 +523,7 @@ extern void rip_bcast(int);
|
|||||||
extern void supply(struct sockaddr_in *, struct interface *,
|
extern void supply(struct sockaddr_in *, struct interface *,
|
||||||
enum output_type, int, int, int);
|
enum output_type, int, int, int);
|
||||||
|
|
||||||
extern void msglog(char *, ...);
|
extern void msglog(const char *, ...) PATTRIB(1,2);
|
||||||
struct msg_limit {
|
struct msg_limit {
|
||||||
time_t reuse;
|
time_t reuse;
|
||||||
struct msg_sub {
|
struct msg_sub {
|
||||||
@ -506,9 +532,10 @@ struct msg_limit {
|
|||||||
# define MSG_SUBJECT_N 8
|
# define MSG_SUBJECT_N 8
|
||||||
} subs[MSG_SUBJECT_N];
|
} 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))
|
#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))
|
#define BADERR(dump,msg) logbad(dump,msg ": %s", strerror(errno))
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
#define DBGERR(dump,msg) BADERR(dump,msg)
|
#define DBGERR(dump,msg) BADERR(dump,msg)
|
||||||
@ -516,37 +543,38 @@ extern void logbad(int, char *, ...);
|
|||||||
#define DBGERR(dump,msg) LOGERR(msg)
|
#define DBGERR(dump,msg) LOGERR(msg)
|
||||||
#endif
|
#endif
|
||||||
extern char *naddr_ntoa(naddr);
|
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 timevaladd(struct timeval *, struct timeval *);
|
||||||
extern void intvl_random(struct timeval *, u_long, u_long);
|
extern void intvl_random(struct timeval *, u_long, u_long);
|
||||||
extern int getnet(char *, naddr *, naddr *);
|
extern int getnet(char *, naddr *, naddr *);
|
||||||
extern int gethost(char *, naddr *);
|
extern int gethost(char *, naddr *);
|
||||||
extern void gwkludge(void);
|
extern void gwkludge(void);
|
||||||
extern char *parse_parms(char *, int);
|
extern const char *parse_parms(char *, int);
|
||||||
extern char *check_parms(struct parm *);
|
extern const char *check_parms(struct parm *);
|
||||||
extern void get_parms(struct interface *);
|
extern void get_parms(struct interface *);
|
||||||
|
|
||||||
extern void lastlog(void);
|
extern void lastlog(void);
|
||||||
extern void set_tracefile(char *, char *, int);
|
extern void trace_close(int);
|
||||||
extern void tracelevel_msg(char *, int);
|
extern void set_tracefile(const char *, const char *, int);
|
||||||
extern void trace_off(char*, ...);
|
extern void tracelevel_msg(const char *, int);
|
||||||
|
extern void trace_off(const char*, ...) PATTRIB(1,2);
|
||||||
extern void set_tracelevel(void);
|
extern void set_tracelevel(void);
|
||||||
extern void trace_flush(void);
|
extern void trace_flush(void);
|
||||||
extern void trace_kernel(char *, ...);
|
extern void trace_misc(const char *, ...) PATTRIB(1,2);
|
||||||
extern void trace_act(char *, ...);
|
extern void trace_act(const char *, ...) PATTRIB(1,2);
|
||||||
extern void trace_pkt(char *, ...);
|
extern void trace_pkt(const char *, ...) PATTRIB(1,2);
|
||||||
extern void trace_add_del(char *, struct rt_entry *);
|
extern void trace_add_del(const char *, struct rt_entry *);
|
||||||
extern void trace_change(struct rt_entry *, u_int, naddr, naddr, int,
|
extern void trace_change(struct rt_entry *, u_int, struct rt_spare *,
|
||||||
u_short, struct interface *, time_t, char *);
|
const char *);
|
||||||
extern void trace_if(char *, struct interface *);
|
extern void trace_if(const char *, struct interface *);
|
||||||
extern void trace_upslot(struct rt_entry *, struct rt_spare *,
|
extern void trace_upslot(struct rt_entry *, struct rt_spare *,
|
||||||
naddr, naddr,
|
struct rt_spare *);
|
||||||
struct interface *, int, u_short, time_t);
|
extern void trace_rip(const char*, const char*, struct sockaddr_in *,
|
||||||
extern void trace_rip(char*, char*, struct sockaddr_in *,
|
|
||||||
struct interface *, struct rip *, int);
|
struct interface *, struct rip *, int);
|
||||||
extern char *addrname(naddr, naddr, int);
|
extern char *addrname(naddr, naddr, int);
|
||||||
|
extern char *rtname(naddr, naddr, naddr);
|
||||||
|
|
||||||
extern void rdisc_age(naddr);
|
extern void rdisc_age(naddr);
|
||||||
extern void set_rdisc_mg(struct interface *, int);
|
extern void set_rdisc_mg(struct interface *, int);
|
||||||
@ -571,21 +599,19 @@ extern void age(naddr);
|
|||||||
extern void ag_flush(naddr, naddr, void (*)(struct ag_info *));
|
extern void ag_flush(naddr, naddr, void (*)(struct ag_info *));
|
||||||
extern void ag_check(naddr, naddr, naddr, naddr, char, char, u_int,
|
extern void ag_check(naddr, naddr, naddr, naddr, char, char, u_int,
|
||||||
u_short, u_short, void (*)(struct ag_info *));
|
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 void del_redirects(naddr, time_t);
|
||||||
extern struct rt_entry *rtget(naddr, naddr);
|
extern struct rt_entry *rtget(naddr, naddr);
|
||||||
extern struct rt_entry *rtfind(naddr);
|
extern struct rt_entry *rtfind(naddr);
|
||||||
extern void rtinit(void);
|
extern void rtinit(void);
|
||||||
extern void rtadd(naddr, naddr, naddr, naddr,
|
extern void rtadd(naddr, naddr, u_int, struct rt_spare *);
|
||||||
int, u_short, u_int, struct interface *);
|
extern void rtchange(struct rt_entry *, u_int, struct rt_spare *, char *);
|
||||||
extern void rtchange(struct rt_entry *, u_int, naddr,naddr, int, u_short,
|
|
||||||
struct interface *ifp, time_t, char *);
|
|
||||||
extern void rtdelete(struct rt_entry *);
|
extern void rtdelete(struct rt_entry *);
|
||||||
|
extern void rts_delete(struct rt_entry *, struct rt_spare *);
|
||||||
extern void rtbad_sub(struct rt_entry *);
|
extern void rtbad_sub(struct rt_entry *);
|
||||||
extern void rtswitch(struct rt_entry *, struct rt_spare *);
|
extern void rtswitch(struct rt_entry *, struct rt_spare *);
|
||||||
extern void rtbad(struct rt_entry *);
|
extern void rtbad(struct rt_entry *);
|
||||||
|
|
||||||
|
|
||||||
#define S_ADDR(x) (((struct sockaddr_in *)(x))->sin_addr.s_addr)
|
#define S_ADDR(x) (((struct sockaddr_in *)(x))->sin_addr.s_addr)
|
||||||
#define INFO_DST(I) ((I)->rti_info[RTAX_DST])
|
#define INFO_DST(I) ((I)->rti_info[RTAX_DST])
|
||||||
#define INFO_GATE(I) ((I)->rti_info[RTAX_GATEWAY])
|
#define INFO_GATE(I) ((I)->rti_info[RTAX_GATEWAY])
|
||||||
@ -604,19 +630,27 @@ extern naddr ripv1_mask_host(naddr,struct interface *);
|
|||||||
extern int check_dst(naddr);
|
extern int check_dst(naddr);
|
||||||
extern struct interface *check_dup(naddr, naddr, naddr, int);
|
extern struct interface *check_dup(naddr, naddr, naddr, int);
|
||||||
extern int check_remote(struct interface *);
|
extern int check_remote(struct interface *);
|
||||||
extern int addrouteforif(register struct interface *);
|
extern int addrouteforif(struct interface *);
|
||||||
extern void ifinit(void);
|
extern void ifinit(void);
|
||||||
extern int walk_bad(struct radix_node *, struct walkarg *);
|
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_sick(struct interface *);
|
||||||
extern void if_bad(struct interface *);
|
extern void if_bad(struct interface *);
|
||||||
extern void if_link(struct interface *);
|
extern void if_link(struct interface *);
|
||||||
extern struct interface *ifwithaddr(naddr, int, int);
|
extern struct interface *ifwithaddr(naddr, int, int);
|
||||||
extern struct interface *ifwithname(char *, naddr);
|
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 interface *iflookup(naddr);
|
||||||
|
|
||||||
extern struct auth *find_auth(struct interface *);
|
extern struct auth *find_auth(struct interface *);
|
||||||
extern void end_md5_auth(struct ws_buf *, struct auth *);
|
extern void end_md5_auth(struct ws_buf *, struct auth *);
|
||||||
|
|
||||||
#include <md5.h>
|
#define MD5_DIGEST_LEN 16
|
||||||
|
typedef struct {
|
||||||
|
u_int32_t state[4]; /* state (ABCD) */
|
||||||
|
u_int32_t count[2]; /* # of bits, modulo 2^64 (LSB 1st) */
|
||||||
|
unsigned char buffer[64]; /* input buffer */
|
||||||
|
} MD5_CTX;
|
||||||
|
extern void MD5Init(MD5_CTX*);
|
||||||
|
extern void MD5Update(MD5_CTX*, u_char*, u_int);
|
||||||
|
extern void MD5Final(u_char[MD5_DIGEST_LEN], MD5_CTX*);
|
||||||
|
264
sbin/routed/if.c
264
sbin/routed/if.c
@ -11,7 +11,7 @@
|
|||||||
* notice, this list of conditions and the following disclaimer in the
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
* documentation and/or other materials provided with the distribution.
|
* documentation and/or other materials provided with the distribution.
|
||||||
* 3. All advertising materials mentioning features or use of this software
|
* 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
|
* This product includes software developed by the University of
|
||||||
* California, Berkeley and its contributors.
|
* California, Berkeley and its contributors.
|
||||||
* 4. Neither the name of the University nor the names of its contributors
|
* 4. Neither the name of the University nor the names of its contributors
|
||||||
@ -29,19 +29,21 @@
|
|||||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
* SUCH DAMAGE.
|
* SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* $Id$
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef lint
|
|
||||||
#if 0
|
|
||||||
static char sccsid[] = "@(#)if.c 8.1 (Berkeley) 6/5/93";
|
|
||||||
#endif
|
|
||||||
static const char rcsid[] =
|
|
||||||
"$Id$";
|
|
||||||
#endif /* not lint */
|
|
||||||
|
|
||||||
#include "defs.h"
|
#include "defs.h"
|
||||||
#include "pathnames.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 */
|
struct interface *ifnet; /* all interfaces */
|
||||||
|
|
||||||
/* hash table for all interfaces, big enough to tolerate ridiculous
|
/* hash table for all interfaces, big enough to tolerate ridiculous
|
||||||
@ -70,18 +72,22 @@ int tot_interfaces; /* # of remote and local interfaces */
|
|||||||
int rip_interfaces; /* # of interfaces doing RIP */
|
int rip_interfaces; /* # of interfaces doing RIP */
|
||||||
int foundloopback; /* valid flag for loopaddr */
|
int foundloopback; /* valid flag for loopaddr */
|
||||||
naddr loopaddr; /* our address on loopback */
|
naddr loopaddr; /* our address on loopback */
|
||||||
|
struct rt_spare loop_rts;
|
||||||
|
|
||||||
struct timeval ifinit_timer;
|
struct timeval ifinit_timer;
|
||||||
static struct timeval last_ifinit;
|
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_out; /* have a RIPv1 interface */
|
||||||
int have_ripv1_in;
|
int have_ripv1_in;
|
||||||
|
|
||||||
|
|
||||||
static struct interface**
|
static struct interface**
|
||||||
nhash(register char *p)
|
nhash(char *p)
|
||||||
{
|
{
|
||||||
register u_int i;
|
u_int i;
|
||||||
|
|
||||||
for (i = 0; *p != '\0'; p++) {
|
for (i = 0; *p != '\0'; p++) {
|
||||||
i = ((i<<1) & 0x7fffffff) | ((i>>31) & 1);
|
i = ((i<<1) & 0x7fffffff) | ((i>>31) & 1);
|
||||||
@ -200,8 +206,7 @@ ifwithname(char *name, /* "ec0" or whatever */
|
|||||||
/* If there is no known interface, maybe there is a
|
/* If there is no known interface, maybe there is a
|
||||||
* new interface. So just once look for new interfaces.
|
* new interface. So just once look for new interfaces.
|
||||||
*/
|
*/
|
||||||
if (last_ifinit.tv_sec == now.tv_sec
|
if (IF_RESCAN_DELAY())
|
||||||
&& last_ifinit.tv_usec == now.tv_usec)
|
|
||||||
return 0;
|
return 0;
|
||||||
ifinit();
|
ifinit();
|
||||||
}
|
}
|
||||||
@ -209,16 +214,25 @@ ifwithname(char *name, /* "ec0" or whatever */
|
|||||||
|
|
||||||
|
|
||||||
struct interface *
|
struct interface *
|
||||||
ifwithindex(u_short index)
|
ifwithindex(u_short index,
|
||||||
|
int rescan_ok)
|
||||||
{
|
{
|
||||||
struct interface *ifp;
|
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 there is no known interface, maybe there is a
|
||||||
if (ifp->int_index == index)
|
* new interface. So just once look for new interfaces.
|
||||||
return ifp;
|
*/
|
||||||
|
if (!rescan_ok
|
||||||
|
|| IF_RESCAN_DELAY())
|
||||||
|
return 0;
|
||||||
|
ifinit();
|
||||||
}
|
}
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -254,8 +268,7 @@ iflookup(naddr addr)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (maybe != 0
|
if (maybe != 0
|
||||||
|| (last_ifinit.tv_sec == now.tv_sec
|
|| IF_RESCAN_DELAY())
|
||||||
&& last_ifinit.tv_usec == now.tv_usec))
|
|
||||||
return maybe;
|
return maybe;
|
||||||
|
|
||||||
/* If there is no known interface, maybe there is a
|
/* If there is no known interface, maybe there is a
|
||||||
@ -291,12 +304,13 @@ naddr
|
|||||||
ripv1_mask_net(naddr addr, /* in network byte order */
|
ripv1_mask_net(naddr addr, /* in network byte order */
|
||||||
struct interface *ifp) /* as seen on this interface */
|
struct interface *ifp) /* as seen on this interface */
|
||||||
{
|
{
|
||||||
|
struct r1net *r1p;
|
||||||
naddr mask = 0;
|
naddr mask = 0;
|
||||||
|
|
||||||
if (addr == 0) /* default always has 0 mask */
|
if (addr == 0) /* default always has 0 mask */
|
||||||
return 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
|
/* If the target network is that of the associated interface
|
||||||
* on which it arrived, then use the netmask of the interface.
|
* on which it arrived, then use the netmask of the interface.
|
||||||
*/
|
*/
|
||||||
@ -312,15 +326,26 @@ ripv1_mask_net(naddr addr, /* in network byte order */
|
|||||||
*/
|
*/
|
||||||
for (ifp = ifnet; ifp != 0; ifp = ifp->int_next) {
|
for (ifp = ifnet; ifp != 0; ifp = ifp->int_next) {
|
||||||
if (on_net(addr, ifp->int_std_net, ifp->int_std_mask)
|
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;
|
mask = ifp->int_ripv1_mask;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Otherwise, make the classic A/B/C guess.
|
/* check special definitions */
|
||||||
*/
|
if (mask == 0) {
|
||||||
if (mask == 0)
|
for (r1p = r1nets; r1p != 0; r1p = r1p->r1net_next) {
|
||||||
mask = std_mask(addr);
|
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;
|
return mask;
|
||||||
}
|
}
|
||||||
@ -375,11 +400,11 @@ check_dup(naddr addr, /* IP address, so network byte order */
|
|||||||
if (ifp->int_mask != mask)
|
if (ifp->int_mask != mask)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (!iff_alive(ifp->int_if_flags))
|
if (!iff_up(ifp->int_if_flags))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* The local address can only be shared with a point-to-
|
/* The local address can only be shared with a point-to-point
|
||||||
* point link.
|
* link.
|
||||||
*/
|
*/
|
||||||
if (ifp->int_addr == addr
|
if (ifp->int_addr == addr
|
||||||
&& (((if_flags|ifp->int_if_flags) & IFF_POINTOPOINT) == 0))
|
&& (((if_flags|ifp->int_if_flags) & IFF_POINTOPOINT) == 0))
|
||||||
@ -496,8 +521,8 @@ ifdel(struct interface *ifp)
|
|||||||
rip_interfaces--;
|
rip_interfaces--;
|
||||||
|
|
||||||
/* Zap all routes associated with this interface.
|
/* Zap all routes associated with this interface.
|
||||||
* Assume routes just using gateways beyond this interface will
|
* Assume routes just using gateways beyond this interface
|
||||||
* timeout naturally, and have probably already died.
|
* will timeout naturally, and have probably already died.
|
||||||
*/
|
*/
|
||||||
(void)rn_walktree(rhead, walk_bad, 0);
|
(void)rn_walktree(rhead, walk_bad, 0);
|
||||||
|
|
||||||
@ -540,7 +565,7 @@ if_bad(struct interface *ifp)
|
|||||||
ifp->int_state |= (IS_BROKE | IS_SICK);
|
ifp->int_state |= (IS_BROKE | IS_SICK);
|
||||||
ifp->int_act_time = NEVER;
|
ifp->int_act_time = NEVER;
|
||||||
ifp->int_query_time = NEVER;
|
ifp->int_query_time = NEVER;
|
||||||
ifp->int_data.ts = 0;
|
ifp->int_data.ts = now.tv_sec;
|
||||||
|
|
||||||
trace_if("Chg", ifp);
|
trace_if("Chg", ifp);
|
||||||
|
|
||||||
@ -560,7 +585,7 @@ if_bad(struct interface *ifp)
|
|||||||
*/
|
*/
|
||||||
int /* 1=it was dead */
|
int /* 1=it was dead */
|
||||||
if_ok(struct interface *ifp,
|
if_ok(struct interface *ifp,
|
||||||
char *type)
|
const char *type)
|
||||||
{
|
{
|
||||||
struct interface *ifp1;
|
struct interface *ifp1;
|
||||||
|
|
||||||
@ -597,12 +622,7 @@ if_ok(struct interface *ifp,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#ifdef _HAVE_SA_LEN
|
/* disassemble routing message
|
||||||
static struct sockaddr sa_zero = { sizeof(struct sockaddr), AF_INET };
|
|
||||||
#endif
|
|
||||||
/*
|
|
||||||
* disassemble routing message
|
|
||||||
* copied bug for bug from the BSD kernel
|
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
rt_xaddrs(struct rt_addrinfo *info,
|
rt_xaddrs(struct rt_addrinfo *info,
|
||||||
@ -610,9 +630,10 @@ rt_xaddrs(struct rt_addrinfo *info,
|
|||||||
struct sockaddr *lim,
|
struct sockaddr *lim,
|
||||||
int addrs)
|
int addrs)
|
||||||
{
|
{
|
||||||
char *sa_limit; /* next byte after the sockaddr */
|
|
||||||
int i;
|
int i;
|
||||||
int len;
|
#ifdef _HAVE_SA_LEN
|
||||||
|
static struct sockaddr sa_zero;
|
||||||
|
#endif
|
||||||
#ifdef sgi
|
#ifdef sgi
|
||||||
#define ROUNDUP(a) ((a) > 0 ? (1 + (((a) - 1) | (sizeof(__uint64_t) - 1))) \
|
#define ROUNDUP(a) ((a) > 0 ? (1 + (((a) - 1) | (sizeof(__uint64_t) - 1))) \
|
||||||
: sizeof(__uint64_t))
|
: sizeof(__uint64_t))
|
||||||
@ -622,36 +643,20 @@ rt_xaddrs(struct rt_addrinfo *info,
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
bzero(info, sizeof(*info));
|
memset(info, 0, sizeof(*info));
|
||||||
info->rti_addrs = addrs;
|
info->rti_addrs = addrs;
|
||||||
for (i = 0; i < RTAX_MAX && sa < lim; i++) {
|
for (i = 0; i < RTAX_MAX && sa < lim; i++) {
|
||||||
if ((addrs & (1 << i)) == 0)
|
if ((addrs & (1 << i)) == 0)
|
||||||
continue;
|
continue;
|
||||||
#ifdef _HAVE_SA_LEN
|
#ifdef _HAVE_SA_LEN
|
||||||
len = sa->sa_len;
|
info->rti_info[i] = (sa->sa_len != 0) ? sa : &sa_zero;
|
||||||
|
sa = (struct sockaddr *)((char*)(sa)
|
||||||
/* Check the sockaddr doesn't go past the end of the buffer. */
|
+ ROUNDUP(sa->sa_len));
|
||||||
/* Cope with buggy (malicious?) sender.*/
|
|
||||||
if (len) {
|
|
||||||
sa_limit = ((char*)sa) + len;
|
|
||||||
if ( sa_limit > (char *)lim ) /* equal is ok */
|
|
||||||
return;
|
|
||||||
} else {
|
|
||||||
/*
|
|
||||||
* We allow the last broken sockaddr
|
|
||||||
* to be replaced by a good null one
|
|
||||||
* because some old versions of routing stuff
|
|
||||||
* would do this (4.4 route(1) for example).
|
|
||||||
* This should go away eventually.
|
|
||||||
*/
|
|
||||||
info->rti_info[i] = &sa_zero;
|
|
||||||
return; /* this one had unknown length */
|
|
||||||
}
|
|
||||||
#else
|
#else
|
||||||
len = _FAKE_SA_LEN_DST(sa);
|
|
||||||
#endif
|
|
||||||
info->rti_info[i] = sa;
|
info->rti_info[i] = sa;
|
||||||
sa = (struct sockaddr *)((char*)(sa) + ROUNDUP(len));
|
sa = (struct sockaddr *)((char*)(sa)
|
||||||
|
+ ROUNDUP(_FAKE_SA_LEN_DST(sa)));
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -713,14 +718,16 @@ ifinit(void)
|
|||||||
if ((needed = sysctl_buf_size) != 0) {
|
if ((needed = sysctl_buf_size) != 0) {
|
||||||
if (sysctl(mib, 6, sysctl_buf,&needed, 0, 0) >= 0)
|
if (sysctl(mib, 6, sysctl_buf,&needed, 0, 0) >= 0)
|
||||||
break;
|
break;
|
||||||
|
/* retry if the table grew */
|
||||||
if (errno != ENOMEM && errno != EFAULT)
|
if (errno != ENOMEM && errno != EFAULT)
|
||||||
BADERR(1, "ifinit: get interface table");
|
BADERR(1, "ifinit: sysctl(RT_IFLIST)");
|
||||||
free(sysctl_buf);
|
free(sysctl_buf);
|
||||||
needed = 0;
|
needed = 0;
|
||||||
}
|
}
|
||||||
if (sysctl(mib, 6, 0, &needed, 0, 0) < 0)
|
if (sysctl(mib, 6, 0, &needed, 0, 0) < 0)
|
||||||
BADERR(1,"ifinit: route-sysctl-estimate");
|
BADERR(1,"ifinit: sysctl(RT_IFLIST) estimate");
|
||||||
sysctl_buf = rtmalloc(sysctl_buf_size = needed, "ifinit");
|
sysctl_buf = rtmalloc(sysctl_buf_size = needed,
|
||||||
|
"ifinit sysctl");
|
||||||
}
|
}
|
||||||
|
|
||||||
ifam_lim = (struct ifa_msghdr *)(sysctl_buf + needed);
|
ifam_lim = (struct ifa_msghdr *)(sysctl_buf + needed);
|
||||||
@ -736,7 +743,7 @@ ifinit(void)
|
|||||||
ifm = (struct if_msghdr *)ifam;
|
ifm = (struct if_msghdr *)ifam;
|
||||||
/* make prototype structure for the IP aliases
|
/* make prototype structure for the IP aliases
|
||||||
*/
|
*/
|
||||||
bzero(&ifs0, sizeof(ifs0));
|
memset(&ifs0, 0, sizeof(ifs0));
|
||||||
ifs0.int_rip_sock = -1;
|
ifs0.int_rip_sock = -1;
|
||||||
ifs0.int_index = ifm->ifm_index;
|
ifs0.int_index = ifm->ifm_index;
|
||||||
ifs0.int_if_flags = ifm->ifm_flags;
|
ifs0.int_if_flags = ifm->ifm_flags;
|
||||||
@ -769,11 +776,11 @@ ifinit(void)
|
|||||||
* will be an alias.
|
* will be an alias.
|
||||||
* Do not output RIP or Router-Discovery packets via aliases.
|
* Do not output RIP or Router-Discovery packets via aliases.
|
||||||
*/
|
*/
|
||||||
bcopy(&ifs0, &ifs, sizeof(ifs));
|
memcpy(&ifs, &ifs0, sizeof(ifs));
|
||||||
ifs0.int_state |= (IS_ALIAS | IS_NO_RIP | IS_NO_RDISC);
|
ifs0.int_state |= (IS_ALIAS | IS_NO_RIP_OUT | IS_NO_RDISC);
|
||||||
|
|
||||||
if (INFO_IFA(&info) == 0) {
|
if (INFO_IFA(&info) == 0) {
|
||||||
if (iff_alive(ifs.int_if_flags)) {
|
if (iff_up(ifs.int_if_flags)) {
|
||||||
if (!(prev_complaints & COMP_NOADDR))
|
if (!(prev_complaints & COMP_NOADDR))
|
||||||
msglog("%s has no address",
|
msglog("%s has no address",
|
||||||
ifs.int_name);
|
ifs.int_name);
|
||||||
@ -782,7 +789,7 @@ ifinit(void)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (INFO_IFA(&info)->sa_family != AF_INET) {
|
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))
|
if (!(prev_complaints & COMP_NOT_INET))
|
||||||
trace_act("%s: not AF_INET",
|
trace_act("%s: not AF_INET",
|
||||||
ifs.int_name);
|
ifs.int_name);
|
||||||
@ -795,7 +802,7 @@ ifinit(void)
|
|||||||
|
|
||||||
if (ntohl(ifs.int_addr)>>24 == 0
|
if (ntohl(ifs.int_addr)>>24 == 0
|
||||||
|| ntohl(ifs.int_addr)>>24 == 0xff) {
|
|| 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))
|
if (!(prev_complaints & COMP_BADADDR))
|
||||||
msglog("%s has a bad address",
|
msglog("%s has a bad address",
|
||||||
ifs.int_name);
|
ifs.int_name);
|
||||||
@ -814,12 +821,14 @@ ifinit(void)
|
|||||||
if (!foundloopback) {
|
if (!foundloopback) {
|
||||||
foundloopback = 1;
|
foundloopback = 1;
|
||||||
loopaddr = ifs.int_addr;
|
loopaddr = ifs.int_addr;
|
||||||
|
loop_rts.rts_gate = loopaddr;
|
||||||
|
loop_rts.rts_router = loopaddr;
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if (ifs.int_if_flags & IFF_POINTOPOINT) {
|
} else if (ifs.int_if_flags & IFF_POINTOPOINT) {
|
||||||
if (INFO_BRD(&info) == 0
|
if (INFO_BRD(&info) == 0
|
||||||
|| INFO_BRD(&info)->sa_family != AF_INET) {
|
|| 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))
|
if (!(prev_complaints & COMP_NODST))
|
||||||
msglog("%s has a bad"
|
msglog("%s has a bad"
|
||||||
" destination address",
|
" destination address",
|
||||||
@ -831,7 +840,7 @@ ifinit(void)
|
|||||||
ifs.int_dstaddr = S_ADDR(INFO_BRD(&info));
|
ifs.int_dstaddr = S_ADDR(INFO_BRD(&info));
|
||||||
if (ntohl(ifs.int_dstaddr)>>24 == 0
|
if (ntohl(ifs.int_dstaddr)>>24 == 0
|
||||||
|| ntohl(ifs.int_dstaddr)>>24 == 0xff) {
|
|| 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))
|
if (!(prev_complaints & COMP_NODST))
|
||||||
msglog("%s has a bad"
|
msglog("%s has a bad"
|
||||||
" destination address",
|
" destination address",
|
||||||
@ -847,7 +856,7 @@ ifinit(void)
|
|||||||
|
|
||||||
} else {
|
} else {
|
||||||
if (INFO_MASK(&info) == 0) {
|
if (INFO_MASK(&info) == 0) {
|
||||||
if (iff_alive(ifs.int_if_flags)) {
|
if (iff_up(ifs.int_if_flags)) {
|
||||||
if (!(prev_complaints & COMP_NOMASK))
|
if (!(prev_complaints & COMP_NOMASK))
|
||||||
msglog("%s has no netmask",
|
msglog("%s has no netmask",
|
||||||
ifs.int_name);
|
ifs.int_name);
|
||||||
@ -865,7 +874,7 @@ ifinit(void)
|
|||||||
|
|
||||||
if (ifs.int_if_flags & IFF_BROADCAST) {
|
if (ifs.int_if_flags & IFF_BROADCAST) {
|
||||||
if (INFO_BRD(&info) == 0) {
|
if (INFO_BRD(&info) == 0) {
|
||||||
if (iff_alive(ifs.int_if_flags)) {
|
if (iff_up(ifs.int_if_flags)) {
|
||||||
if (!(prev_complaints
|
if (!(prev_complaints
|
||||||
& COMP_NOBADR))
|
& COMP_NOBADR))
|
||||||
msglog("%s has"
|
msglog("%s has"
|
||||||
@ -902,7 +911,7 @@ ifinit(void)
|
|||||||
if (ifs.int_metric > HOPCNT_INFINITY) {
|
if (ifs.int_metric > HOPCNT_INFINITY) {
|
||||||
ifs.int_metric = 0;
|
ifs.int_metric = 0;
|
||||||
if (!(prev_complaints & COMP_BAD_METRIC)
|
if (!(prev_complaints & COMP_BAD_METRIC)
|
||||||
&& iff_alive(ifs.int_if_flags)) {
|
&& iff_up(ifs.int_if_flags)) {
|
||||||
complaints |= COMP_BAD_METRIC;
|
complaints |= COMP_BAD_METRIC;
|
||||||
msglog("%s has a metric of %d",
|
msglog("%s has a metric of %d",
|
||||||
ifs.int_name, ifs.int_metric);
|
ifs.int_name, ifs.int_metric);
|
||||||
@ -951,19 +960,26 @@ ifinit(void)
|
|||||||
|
|
||||||
/* note interfaces that have been turned off
|
/* note interfaces that have been turned off
|
||||||
*/
|
*/
|
||||||
if (!iff_alive(ifs.int_if_flags)) {
|
if (!iff_up(ifs.int_if_flags)) {
|
||||||
if (iff_alive(ifp->int_if_flags)) {
|
if (iff_up(ifp->int_if_flags)) {
|
||||||
msglog("interface %s to %s turned off",
|
msglog("interface %s to %s turned off",
|
||||||
ifp->int_name,
|
ifp->int_name,
|
||||||
naddr_ntoa(ifp->int_dstaddr));
|
naddr_ntoa(ifp->int_dstaddr));
|
||||||
if_bad(ifp);
|
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;
|
continue;
|
||||||
}
|
}
|
||||||
/* or that were off and are now ok */
|
/* or that were off and are now ok */
|
||||||
if (!iff_alive(ifp->int_if_flags)) {
|
if (!iff_up(ifp->int_if_flags)) {
|
||||||
ifp->int_if_flags |= IFF_UP_RUNNING;
|
ifp->int_if_flags |= IFF_UP;
|
||||||
(void)if_ok(ifp, "");
|
(void)if_ok(ifp, "");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -979,7 +995,7 @@ ifinit(void)
|
|||||||
oerr = ifs.int_data.oerrors - ifp->int_data.oerrors;
|
oerr = ifs.int_data.oerrors - ifp->int_data.oerrors;
|
||||||
#ifdef sgi
|
#ifdef sgi
|
||||||
/* Through at least IRIX 6.2, PPP and SLIP
|
/* 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
|
* But FDDI rings stuck non-operational count
|
||||||
* dropped packets as they wait for improvement.
|
* dropped packets as they wait for improvement.
|
||||||
*/
|
*/
|
||||||
@ -1045,7 +1061,7 @@ ifinit(void)
|
|||||||
/* This is a new interface.
|
/* This is a new interface.
|
||||||
* If it is dead, forget it.
|
* If it is dead, forget it.
|
||||||
*/
|
*/
|
||||||
if (!iff_alive(ifs.int_if_flags))
|
if (!iff_up(ifs.int_if_flags))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* If it duplicates an existing interface,
|
/* If it duplicates an existing interface,
|
||||||
@ -1055,6 +1071,12 @@ ifinit(void)
|
|||||||
ifp = check_dup(ifs.int_addr,ifs.int_dstaddr,ifs.int_mask,
|
ifp = check_dup(ifs.int_addr,ifs.int_dstaddr,ifs.int_mask,
|
||||||
ifs.int_if_flags);
|
ifs.int_if_flags);
|
||||||
if (ifp != 0) {
|
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)) {
|
if (!(prev_complaints & COMP_DUP)) {
|
||||||
complaints |= COMP_DUP;
|
complaints |= COMP_DUP;
|
||||||
msglog("%s (%s%s%s) is duplicated by"
|
msglog("%s (%s%s%s) is duplicated by"
|
||||||
@ -1088,8 +1110,8 @@ ifinit(void)
|
|||||||
|
|
||||||
/* It is new and ok. Add it to the list of interfaces
|
/* It is new and ok. Add it to the list of interfaces
|
||||||
*/
|
*/
|
||||||
ifp = (struct interface *)rtmalloc(sizeof(*ifp), "ifinit");
|
ifp = (struct interface *)rtmalloc(sizeof(*ifp), "ifinit ifp");
|
||||||
bcopy(&ifs, ifp, sizeof(*ifp));
|
memcpy(ifp, &ifs, sizeof(*ifp));
|
||||||
get_parms(ifp);
|
get_parms(ifp);
|
||||||
if_link(ifp);
|
if_link(ifp);
|
||||||
trace_if("Add", ifp);
|
trace_if("Add", ifp);
|
||||||
@ -1159,14 +1181,18 @@ ifinit(void)
|
|||||||
rtdelete(rt);
|
rtdelete(rt);
|
||||||
rt = 0;
|
rt = 0;
|
||||||
} else {
|
} 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,
|
rtchange(rt, rt->rt_state | RS_MHOME,
|
||||||
loopaddr, loopaddr,
|
&loop_rts, 0);
|
||||||
0, 0, ifp, rt->rt_time, 0);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (rt == 0)
|
if (rt == 0) {
|
||||||
rtadd(myaddr, HOST_MASK, loopaddr, loopaddr,
|
loop_rts.rts_ifp = ifp;
|
||||||
0, 0, RS_MHOME, ifp);
|
loop_rts.rts_metric = 0;
|
||||||
|
rtadd(myaddr, HOST_MASK, RS_MHOME, &loop_rts);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (ifp = ifnet; ifp != 0; ifp = ifp1) {
|
for (ifp = ifnet; ifp != 0; ifp = ifp1) {
|
||||||
@ -1211,7 +1237,7 @@ ifinit(void)
|
|||||||
/* Delete any routes to the network address through
|
/* Delete any routes to the network address through
|
||||||
* foreign routers. Remove even static routes.
|
* 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);
|
rt = rtget(ifp->int_addr, HOST_MASK);
|
||||||
if (rt != 0 && rt->rt_router != loopaddr) {
|
if (rt != 0 && rt->rt_router != loopaddr) {
|
||||||
rtdelete(rt);
|
rtdelete(rt);
|
||||||
@ -1224,14 +1250,17 @@ ifinit(void)
|
|||||||
} else {
|
} else {
|
||||||
ifp1 = rt->rt_ifp;
|
ifp1 = rt->rt_ifp;
|
||||||
}
|
}
|
||||||
rtchange(rt,((rt->rt_state & ~RS_NET_SYN)
|
loop_rts.rts_ifp = ifp1;
|
||||||
| (RS_IF|RS_LOCAL)),
|
loop_rts.rts_metric = 0;
|
||||||
loopaddr, loopaddr,
|
loop_rts.rts_time = rt->rt_time;
|
||||||
0, 0, ifp1, rt->rt_time, 0);
|
rtchange(rt, ((rt->rt_state & ~RS_NET_SYN)
|
||||||
|
| (RS_IF|RS_LOCAL)),
|
||||||
|
&loop_rts, 0);
|
||||||
} else {
|
} else {
|
||||||
|
loop_rts.rts_ifp = ifp;
|
||||||
|
loop_rts.rts_metric = 0;
|
||||||
rtadd(ifp->int_addr, HOST_MASK,
|
rtadd(ifp->int_addr, HOST_MASK,
|
||||||
loopaddr, loopaddr,
|
(RS_IF | RS_LOCAL), &loop_rts);
|
||||||
0, 0, (RS_IF | RS_LOCAL), ifp);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1245,10 +1274,12 @@ ifinit(void)
|
|||||||
rtdelete(rt);
|
rtdelete(rt);
|
||||||
rt = 0;
|
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,
|
rtadd(intnetp->intnet_addr, intnetp->intnet_mask,
|
||||||
loopaddr, loopaddr, intnetp->intnet_metric-1,
|
RS_NET_SYN | RS_NET_INT, &loop_rts);
|
||||||
0, RS_NET_SYN | RS_NET_INT, 0);
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
prev_complaints = complaints;
|
prev_complaints = complaints;
|
||||||
@ -1259,6 +1290,7 @@ static void
|
|||||||
check_net_syn(struct interface *ifp)
|
check_net_syn(struct interface *ifp)
|
||||||
{
|
{
|
||||||
struct rt_entry *rt;
|
struct rt_entry *rt;
|
||||||
|
static struct rt_spare new;
|
||||||
|
|
||||||
|
|
||||||
/* Turn on the need to automatically synthesize a network route
|
/* Turn on the need to automatically synthesize a network route
|
||||||
@ -1275,10 +1307,14 @@ check_net_syn(struct interface *ifp)
|
|||||||
rtdelete(rt);
|
rtdelete(rt);
|
||||||
rt = 0;
|
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,
|
rtadd(ifp->int_std_addr, ifp->int_std_mask,
|
||||||
ifp->int_addr, ifp->int_addr,
|
RS_NET_SYN, &new);
|
||||||
ifp->int_metric, 0, RS_NET_SYN, ifp);
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
ifp->int_state &= ~IS_NEED_NET_SYN;
|
ifp->int_state &= ~IS_NEED_NET_SYN;
|
||||||
@ -1301,7 +1337,8 @@ int /* 0=bad interface */
|
|||||||
addrouteforif(struct interface *ifp)
|
addrouteforif(struct interface *ifp)
|
||||||
{
|
{
|
||||||
struct rt_entry *rt;
|
struct rt_entry *rt;
|
||||||
naddr dst, gate;
|
static struct rt_spare new;
|
||||||
|
naddr dst;
|
||||||
|
|
||||||
|
|
||||||
/* skip sick interfaces
|
/* skip sick interfaces
|
||||||
@ -1315,11 +1352,16 @@ addrouteforif(struct interface *ifp)
|
|||||||
if (ifp->int_state & IS_SUBNET)
|
if (ifp->int_state & IS_SUBNET)
|
||||||
check_net_syn(ifp);
|
check_net_syn(ifp);
|
||||||
|
|
||||||
gate = ifp->int_addr;
|
|
||||||
dst = (0 != (ifp->int_if_flags & (IFF_POINTOPOINT | IFF_LOOPBACK))
|
dst = (0 != (ifp->int_if_flags & (IFF_POINTOPOINT | IFF_LOOPBACK))
|
||||||
? ifp->int_dstaddr
|
? ifp->int_dstaddr
|
||||||
: htonl(ifp->int_net));
|
: 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,
|
/* If we are going to send packets to the gateway,
|
||||||
* it must be reachable using our physical interfaces
|
* it must be reachable using our physical interfaces
|
||||||
*/
|
*/
|
||||||
@ -1332,7 +1374,7 @@ addrouteforif(struct interface *ifp)
|
|||||||
* The right route must be for the right interface, not synthesized
|
* The right route must be for the right interface, not synthesized
|
||||||
* from a subnet, be a "gateway" or not as appropriate, and so forth.
|
* 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);
|
rt = rtget(dst, ifp->int_mask);
|
||||||
if (rt != 0) {
|
if (rt != 0) {
|
||||||
if ((rt->rt_ifp != ifp
|
if ((rt->rt_ifp != ifp
|
||||||
@ -1345,8 +1387,7 @@ addrouteforif(struct interface *ifp)
|
|||||||
} else {
|
} else {
|
||||||
rtchange(rt, ((rt->rt_state | RS_IF)
|
rtchange(rt, ((rt->rt_state | RS_IF)
|
||||||
& ~(RS_NET_SYN | RS_LOCAL)),
|
& ~(RS_NET_SYN | RS_LOCAL)),
|
||||||
ifp->int_addr, ifp->int_addr,
|
&new, 0);
|
||||||
ifp->int_metric, 0, ifp, now.tv_sec, 0);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (rt == 0) {
|
if (rt == 0) {
|
||||||
@ -1354,8 +1395,7 @@ addrouteforif(struct interface *ifp)
|
|||||||
trace_act("re-install interface %s",
|
trace_act("re-install interface %s",
|
||||||
ifp->int_name);
|
ifp->int_name);
|
||||||
|
|
||||||
rtadd(dst, ifp->int_mask, gate, gate,
|
rtadd(dst, ifp->int_mask, RS_IF, &new);
|
||||||
ifp->int_metric, 0, RS_IF, ifp);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -11,7 +11,7 @@
|
|||||||
* notice, this list of conditions and the following disclaimer in the
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
* documentation and/or other materials provided with the distribution.
|
* documentation and/or other materials provided with the distribution.
|
||||||
* 3. All advertising materials mentioning features or use of this software
|
* 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
|
* This product includes software developed by the University of
|
||||||
* California, Berkeley and its contributors.
|
* California, Berkeley and its contributors.
|
||||||
* 4. Neither the name of the University nor the names of its contributors
|
* 4. Neither the name of the University nor the names of its contributors
|
||||||
@ -29,22 +29,23 @@
|
|||||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
* SUCH DAMAGE.
|
* SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* $Id$
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef lint
|
|
||||||
#if 0
|
|
||||||
static char sccsid[] = "@(#)input.c 8.1 (Berkeley) 6/5/93";
|
|
||||||
#endif
|
|
||||||
static const char rcsid[] =
|
|
||||||
"$Id$";
|
|
||||||
#endif /* not lint */
|
|
||||||
|
|
||||||
#include "defs.h"
|
#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 *,
|
static void input(struct sockaddr_in *, struct interface *, struct interface *,
|
||||||
struct rip *, int);
|
struct rip *, int);
|
||||||
static void input_route(struct interface *, naddr,
|
static void input_route(naddr, naddr, struct rt_spare *, struct netinfo *);
|
||||||
naddr, naddr, naddr, struct netinfo *);
|
|
||||||
static int ck_passwd(struct interface *, struct rip *, void *,
|
static int ck_passwd(struct interface *, struct rip *, void *,
|
||||||
naddr, struct msg_limit *);
|
naddr, struct msg_limit *);
|
||||||
|
|
||||||
@ -141,14 +142,17 @@ input(struct sockaddr_in *from, /* received from this IP address */
|
|||||||
{
|
{
|
||||||
# define FROM_NADDR from->sin_addr.s_addr
|
# define FROM_NADDR from->sin_addr.s_addr
|
||||||
static struct msg_limit use_auth, bad_len, bad_mask;
|
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_entry *rt;
|
||||||
|
struct rt_spare new;
|
||||||
struct netinfo *n, *lim;
|
struct netinfo *n, *lim;
|
||||||
struct interface *ifp1;
|
struct interface *ifp1;
|
||||||
naddr gate, mask, v1_mask, dst, ddst_h;
|
naddr gate, mask, v1_mask, dst, ddst_h = 0;
|
||||||
struct auth *ap;
|
struct auth *ap;
|
||||||
int i;
|
struct tgate *tg = 0;
|
||||||
|
struct tgate_net *tn;
|
||||||
|
int i, j;
|
||||||
|
|
||||||
/* Notice when we hear from a remote gateway
|
/* Notice when we hear from a remote gateway
|
||||||
*/
|
*/
|
||||||
@ -166,7 +170,7 @@ input(struct sockaddr_in *from, /* received from this IP address */
|
|||||||
} else if (rip->rip_vers > RIPv2) {
|
} else if (rip->rip_vers > RIPv2) {
|
||||||
rip->rip_vers = RIPv2;
|
rip->rip_vers = RIPv2;
|
||||||
}
|
}
|
||||||
if (cc > OVER_MAXPACKETSIZE) {
|
if (cc > (int)OVER_MAXPACKETSIZE) {
|
||||||
msglim(&bad_router, FROM_NADDR,
|
msglim(&bad_router, FROM_NADDR,
|
||||||
"packet at least %d bytes too long received from %s",
|
"packet at least %d bytes too long received from %s",
|
||||||
cc-MAXPACKETSIZE, naddr_ntoa(FROM_NADDR));
|
cc-MAXPACKETSIZE, naddr_ntoa(FROM_NADDR));
|
||||||
@ -283,10 +287,10 @@ input(struct sockaddr_in *from, /* received from this IP address */
|
|||||||
*/
|
*/
|
||||||
if (n->n_family == RIP_AF_UNSPEC
|
if (n->n_family == RIP_AF_UNSPEC
|
||||||
&& n->n_metric == HOPCNT_INFINITY) {
|
&& n->n_metric == HOPCNT_INFINITY) {
|
||||||
|
/* Answer a query from a utility program
|
||||||
|
* with all we know.
|
||||||
|
*/
|
||||||
if (from->sin_port != htons(RIP_PORT)) {
|
if (from->sin_port != htons(RIP_PORT)) {
|
||||||
/* Answer a query from a utility
|
|
||||||
* program with all we know.
|
|
||||||
*/
|
|
||||||
supply(from, aifp, OUT_QUERY, 0,
|
supply(from, aifp, OUT_QUERY, 0,
|
||||||
rip->rip_vers, ap != 0);
|
rip->rip_vers, ap != 0);
|
||||||
return;
|
return;
|
||||||
@ -298,11 +302,7 @@ input(struct sockaddr_in *from, /* received from this IP address */
|
|||||||
*
|
*
|
||||||
* Only answer a router if we are a supplier
|
* Only answer a router if we are a supplier
|
||||||
* to keep an unwary host that is just starting
|
* to keep an unwary host that is just starting
|
||||||
* from picking us as a router. Respond with
|
* from picking us as a router.
|
||||||
* 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.
|
|
||||||
*/
|
*/
|
||||||
if (aifp == 0) {
|
if (aifp == 0) {
|
||||||
trace_pkt("ignore distant router");
|
trace_pkt("ignore distant router");
|
||||||
@ -314,8 +314,36 @@ input(struct sockaddr_in *from, /* received from this IP address */
|
|||||||
return;
|
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,
|
supply(from, aifp, OUT_UNICAST, 0,
|
||||||
(aifp->int_state&IS_NO_RIPV1_OUT)
|
(aifp->int_state & IS_NO_RIPV1_OUT)
|
||||||
? RIPv2 : RIPv1,
|
? RIPv2 : RIPv1,
|
||||||
ap != 0);
|
ap != 0);
|
||||||
return;
|
return;
|
||||||
@ -327,8 +355,8 @@ input(struct sockaddr_in *from, /* received from this IP address */
|
|||||||
|
|
||||||
if (n->n_family != RIP_AF_INET) {
|
if (n->n_family != RIP_AF_INET) {
|
||||||
msglim(&bad_router, FROM_NADDR,
|
msglim(&bad_router, FROM_NADDR,
|
||||||
"request from %s for unsupported (af"
|
"request from %s for unsupported"
|
||||||
" %d) %s",
|
" (af %d) %s",
|
||||||
naddr_ntoa(FROM_NADDR),
|
naddr_ntoa(FROM_NADDR),
|
||||||
ntohs(n->n_family),
|
ntohs(n->n_family),
|
||||||
naddr_ntoa(n->n_dst));
|
naddr_ntoa(n->n_dst));
|
||||||
@ -418,7 +446,13 @@ input(struct sockaddr_in *from, /* received from this IP address */
|
|||||||
|
|
||||||
case RIPCMD_TRACEON:
|
case RIPCMD_TRACEON:
|
||||||
case RIPCMD_TRACEOFF:
|
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) {
|
if (ntohs(from->sin_port) > IPPORT_RESERVED) {
|
||||||
msglog("trace command from untrusted port on %s",
|
msglog("trace command from untrusted port on %s",
|
||||||
naddr_ntoa(FROM_NADDR));
|
naddr_ntoa(FROM_NADDR));
|
||||||
@ -434,7 +468,7 @@ input(struct sockaddr_in *from, /* received from this IP address */
|
|||||||
set_tracefile((char*)rip->rip_tracefile,
|
set_tracefile((char*)rip->rip_tracefile,
|
||||||
"trace command: %s\n", 0);
|
"trace command: %s\n", 0);
|
||||||
} else {
|
} else {
|
||||||
trace_off("tracing turned off by %s\n",
|
trace_off("tracing turned off by %s",
|
||||||
naddr_ntoa(FROM_NADDR));
|
naddr_ntoa(FROM_NADDR));
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
@ -512,7 +546,7 @@ input(struct sockaddr_in *from, /* received from this IP address */
|
|||||||
/* Ignore routes via dead interface.
|
/* Ignore routes via dead interface.
|
||||||
*/
|
*/
|
||||||
if (aifp->int_state & IS_BROKE) {
|
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);
|
aifp->int_name);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -522,7 +556,7 @@ input(struct sockaddr_in *from, /* received from this IP address */
|
|||||||
* happens, it happens frequently.
|
* happens, it happens frequently.
|
||||||
*/
|
*/
|
||||||
if (aifp->int_state & IS_DISTRUST) {
|
if (aifp->int_state & IS_DISTRUST) {
|
||||||
struct tgate *tg = tgates;
|
tg = tgates;
|
||||||
while (tg->tgate_addr != FROM_NADDR) {
|
while (tg->tgate_addr != FROM_NADDR) {
|
||||||
tg = tg->tgate_next;
|
tg = tg->tgate_next;
|
||||||
if (tg == 0) {
|
if (tg == 0) {
|
||||||
@ -582,7 +616,7 @@ input(struct sockaddr_in *from, /* received from this IP address */
|
|||||||
*/
|
*/
|
||||||
gate = FROM_NADDR;
|
gate = FROM_NADDR;
|
||||||
if (n->n_nhop != 0) {
|
if (n->n_nhop != 0) {
|
||||||
if (rip->rip_vers == RIPv2) {
|
if (rip->rip_vers == RIPv1) {
|
||||||
n->n_nhop = 0;
|
n->n_nhop = 0;
|
||||||
} else {
|
} else {
|
||||||
/* Use it only if it is valid. */
|
/* Use it only if it is valid. */
|
||||||
@ -608,9 +642,9 @@ input(struct sockaddr_in *from, /* received from this IP address */
|
|||||||
} else if ((ntohl(dst) & ~mask) != 0) {
|
} else if ((ntohl(dst) & ~mask) != 0) {
|
||||||
msglim(&bad_mask, FROM_NADDR,
|
msglim(&bad_mask, FROM_NADDR,
|
||||||
"router %s sent bad netmask"
|
"router %s sent bad netmask"
|
||||||
" %#x with %s",
|
" %#lx with %s",
|
||||||
naddr_ntoa(FROM_NADDR),
|
naddr_ntoa(FROM_NADDR),
|
||||||
mask,
|
(u_long)mask,
|
||||||
naddr_ntoa(dst));
|
naddr_ntoa(dst));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -623,6 +657,20 @@ input(struct sockaddr_in *from, /* received from this IP address */
|
|||||||
if (n->n_metric > HOPCNT_INFINITY)
|
if (n->n_metric > HOPCNT_INFINITY)
|
||||||
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
|
/* Recognize and ignore a default route we faked
|
||||||
* which is being sent back to us by a machine with
|
* which is being sent back to us by a machine with
|
||||||
* broken split-horizon.
|
* broken split-horizon.
|
||||||
@ -631,7 +679,7 @@ input(struct sockaddr_in *from, /* received from this IP address */
|
|||||||
*/
|
*/
|
||||||
if (aifp->int_d_metric != 0
|
if (aifp->int_d_metric != 0
|
||||||
&& dst == RIP_DEFAULT
|
&& dst == RIP_DEFAULT
|
||||||
&& n->n_metric >= aifp->int_d_metric)
|
&& (int)n->n_metric >= aifp->int_d_metric)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* We can receive aggregated RIPv2 routes that must
|
/* We can receive aggregated RIPv2 routes that must
|
||||||
@ -664,13 +712,12 @@ input(struct sockaddr_in *from, /* received from this IP address */
|
|||||||
/* Punt if we would have to generate
|
/* Punt if we would have to generate
|
||||||
* an unreasonable number of routes.
|
* an unreasonable number of routes.
|
||||||
*/
|
*/
|
||||||
#ifdef DEBUG
|
if (TRACECONTENTS)
|
||||||
msglog("accept %s from %s as 1"
|
trace_misc("accept %s-->%s as 1"
|
||||||
" instead of %d routes",
|
" instead of %d routes",
|
||||||
addrname(dst,mask,0),
|
addrname(dst,mask,0),
|
||||||
naddr_ntoa(FROM_NADDR),
|
naddr_ntoa(FROM_NADDR),
|
||||||
i+1);
|
i+1);
|
||||||
#endif
|
|
||||||
i = 0;
|
i = 0;
|
||||||
} else {
|
} else {
|
||||||
mask = v1_mask;
|
mask = v1_mask;
|
||||||
@ -679,10 +726,17 @@ input(struct sockaddr_in *from, /* received from this IP address */
|
|||||||
i = 0;
|
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 (;;) {
|
for (;;) {
|
||||||
input_route(aifp, FROM_NADDR,
|
input_route(dst, mask, &new, n);
|
||||||
dst, mask, gate, n);
|
if (++j > i)
|
||||||
if (i-- == 0)
|
|
||||||
break;
|
break;
|
||||||
dst = htonl(ntohl(dst) + ddst_h);
|
dst = htonl(ntohl(dst) + ddst_h);
|
||||||
}
|
}
|
||||||
@ -696,18 +750,15 @@ input(struct sockaddr_in *from, /* received from this IP address */
|
|||||||
/* Process a single input route.
|
/* Process a single input route.
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
input_route(struct interface *ifp,
|
input_route(naddr dst, /* network order */
|
||||||
naddr from,
|
|
||||||
naddr dst,
|
|
||||||
naddr mask,
|
naddr mask,
|
||||||
naddr gate,
|
struct rt_spare *new,
|
||||||
struct netinfo *n)
|
struct netinfo *n)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
struct rt_entry *rt;
|
struct rt_entry *rt;
|
||||||
struct rt_spare *rts, *rts0;
|
struct rt_spare *rts, *rts0;
|
||||||
struct interface *ifp1;
|
struct interface *ifp1;
|
||||||
time_t new_time;
|
|
||||||
|
|
||||||
|
|
||||||
/* See if the other guy is telling us to send our packets to him.
|
/* See if the other guy is telling us to send our packets to him.
|
||||||
@ -731,7 +782,7 @@ input_route(struct interface *ifp,
|
|||||||
if (rt == 0) {
|
if (rt == 0) {
|
||||||
/* Ignore unknown routes being poisoned.
|
/* Ignore unknown routes being poisoned.
|
||||||
*/
|
*/
|
||||||
if (n->n_metric == HOPCNT_INFINITY)
|
if (new->rts_metric == HOPCNT_INFINITY)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* Ignore the route if it points to us */
|
/* Ignore the route if it points to us */
|
||||||
@ -743,8 +794,7 @@ input_route(struct interface *ifp,
|
|||||||
* our memory, accept the new route.
|
* our memory, accept the new route.
|
||||||
*/
|
*/
|
||||||
if (total_routes < MAX_ROUTES)
|
if (total_routes < MAX_ROUTES)
|
||||||
rtadd(dst, mask, gate, from, n->n_metric,
|
rtadd(dst, mask, 0, new);
|
||||||
n->n_tag, 0, ifp);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -769,7 +819,7 @@ input_route(struct interface *ifp,
|
|||||||
|
|
||||||
rts0 = rt->rt_spares;
|
rts0 = rt->rt_spares;
|
||||||
for (rts = rts0, i = NUM_SPARES; i != 0; i--, rts++) {
|
for (rts = rts0, i = NUM_SPARES; i != 0; i--, rts++) {
|
||||||
if (rts->rts_router == from)
|
if (rts->rts_router == new->rts_router)
|
||||||
break;
|
break;
|
||||||
/* Note the worst slot to reuse,
|
/* Note the worst slot to reuse,
|
||||||
* other than the current slot.
|
* other than the current slot.
|
||||||
@ -779,26 +829,34 @@ input_route(struct interface *ifp,
|
|||||||
rts0 = rts;
|
rts0 = rts;
|
||||||
}
|
}
|
||||||
if (i != 0) {
|
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
|
/* 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)
|
if (rts->rts_metric == HOPCNT_INFINITY
|
||||||
? rts->rts_time
|
&& new->rts_metric == HOPCNT_INFINITY)
|
||||||
: now.tv_sec);
|
new->rts_time = rts->rts_time;
|
||||||
|
|
||||||
/* If this is an update for the router we currently prefer,
|
/* If this is an update for the router we currently prefer,
|
||||||
* then note it.
|
* then note it.
|
||||||
*/
|
*/
|
||||||
if (i == NUM_SPARES) {
|
if (i == NUM_SPARES) {
|
||||||
rtchange(rt,rt->rt_state, gate,rt->rt_router,
|
rtchange(rt, rt->rt_state, new, 0);
|
||||||
n->n_metric, n->n_tag, ifp, new_time, 0);
|
|
||||||
/* If the route got worse, check for something better.
|
/* 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);
|
rtswitch(rt, 0);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -806,10 +864,17 @@ input_route(struct interface *ifp,
|
|||||||
/* This is an update for a spare route.
|
/* This is an update for a spare route.
|
||||||
* Finished if the route is unchanged.
|
* Finished if the route is unchanged.
|
||||||
*/
|
*/
|
||||||
if (rts->rts_gate == gate
|
if (rts->rts_gate == new->rts_gate
|
||||||
&& old_metric == n->n_metric
|
&& rts->rts_metric == new->rts_metric
|
||||||
&& rts->rts_tag == n->n_tag) {
|
&& rts->rts_tag == new->rts_tag) {
|
||||||
rts->rts_time = new_time;
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -823,6 +888,7 @@ input_route(struct interface *ifp,
|
|||||||
&& 0 != ifwithaddr(n->n_nhop, 1, 0))
|
&& 0 != ifwithaddr(n->n_nhop, 1, 0))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
/* the loop above set rts0=worst spare */
|
||||||
rts = rts0;
|
rts = rts0;
|
||||||
|
|
||||||
/* Save the route as a spare only if it has
|
/* Save the route as a spare only if it has
|
||||||
@ -830,20 +896,12 @@ input_route(struct interface *ifp,
|
|||||||
* This also ignores poisoned routes (those
|
* This also ignores poisoned routes (those
|
||||||
* received with metric HOPCNT_INFINITY).
|
* received with metric HOPCNT_INFINITY).
|
||||||
*/
|
*/
|
||||||
if (n->n_metric >= rts->rts_metric)
|
if (new->rts_metric >= rts->rts_metric)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
new_time = now.tv_sec;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
trace_upslot(rt, rts, gate, from, ifp, n->n_metric,n->n_tag, new_time);
|
trace_upslot(rt, rts, new);
|
||||||
|
*rts = *new;
|
||||||
rts->rts_gate = gate;
|
|
||||||
rts->rts_router = from;
|
|
||||||
rts->rts_metric = n->n_metric;
|
|
||||||
rts->rts_tag = n->n_tag;
|
|
||||||
rts->rts_time = new_time;
|
|
||||||
rts->rts_ifp = ifp;
|
|
||||||
|
|
||||||
/* try to switch to a better route */
|
/* try to switch to a better route */
|
||||||
rtswitch(rt, rts);
|
rtswitch(rt, rts);
|
||||||
@ -862,7 +920,7 @@ ck_passwd(struct interface *aifp,
|
|||||||
struct auth *ap;
|
struct auth *ap;
|
||||||
MD5_CTX md5_ctx;
|
MD5_CTX md5_ctx;
|
||||||
u_char hash[RIP_AUTH_PW_LEN];
|
u_char hash[RIP_AUTH_PW_LEN];
|
||||||
int i;
|
int i, len;
|
||||||
|
|
||||||
|
|
||||||
if ((void *)NA >= lim || NA->a_family != RIP_AF_AUTH) {
|
if ((void *)NA >= lim || NA->a_family != RIP_AF_AUTH) {
|
||||||
@ -880,7 +938,7 @@ ck_passwd(struct interface *aifp,
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (NA->a_type == RIP_AUTH_PW) {
|
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;
|
return 1;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
@ -889,28 +947,52 @@ ck_passwd(struct interface *aifp,
|
|||||||
if (NA->au.a_md5.md5_keyid != ap->keyid)
|
if (NA->au.a_md5.md5_keyid != ap->keyid)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
na2 = (struct netauth *)((char *)(NA+1)
|
len = ntohs(NA->au.a_md5.md5_pkt_len);
|
||||||
+ NA->au.a_md5.md5_pkt_len);
|
if ((len-sizeof(*rip)) % sizeof(*NA) != 0
|
||||||
if (NA->au.a_md5.md5_pkt_len % sizeof(*NA) != 0
|
|| len != (char *)lim-(char*)rip-(int)sizeof(*NA)) {
|
||||||
|| lim < (void *)(na2+1)) {
|
|
||||||
msglim(use_authp, from,
|
msglim(use_authp, from,
|
||||||
"bad MD5 RIP-II pkt length %d from %s",
|
"wrong MD5 RIPv2 packet length of %d"
|
||||||
NA->au.a_md5.md5_pkt_len,
|
" instead of %d from %s",
|
||||||
|
len, (int)((char *)lim-(char *)rip
|
||||||
|
-sizeof(*NA)),
|
||||||
naddr_ntoa(from));
|
naddr_ntoa(from));
|
||||||
return 0;
|
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);
|
MD5Init(&md5_ctx);
|
||||||
MD5Update(&md5_ctx, (u_char *)NA,
|
MD5Update(&md5_ctx, (u_char *)rip, len);
|
||||||
(char *)na2->au.au_pw - (char *)NA);
|
MD5Update(&md5_ctx, ap->key, RIP_AUTH_MD5_LEN);
|
||||||
MD5Update(&md5_ctx,
|
|
||||||
(u_char *)ap->key, sizeof(ap->key));
|
|
||||||
MD5Final(hash, &md5_ctx);
|
MD5Final(hash, &md5_ctx);
|
||||||
if (na2->a_family != RIP_AF_AUTH
|
if (!memcmp(hash, na2->au.au_pw, sizeof(hash)))
|
||||||
|| na2->a_type != 1
|
return 1;
|
||||||
|| NA->au.a_md5.md5_auth_len != RIP_AUTH_PW_LEN
|
|
||||||
|| bcmp(hash, na2->au.au_pw, sizeof(hash)))
|
|
||||||
return 0;
|
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -11,7 +11,7 @@
|
|||||||
* notice, this list of conditions and the following disclaimer in the
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
* documentation and/or other materials provided with the distribution.
|
* documentation and/or other materials provided with the distribution.
|
||||||
* 3. All advertising materials mentioning features or use of this software
|
* 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
|
* This product includes software developed by the University of
|
||||||
* California, Berkeley and its contributors.
|
* California, Berkeley and its contributors.
|
||||||
* 4. Neither the name of the University nor the names of its contributors
|
* 4. Neither the name of the University nor the names of its contributors
|
||||||
@ -29,33 +29,39 @@
|
|||||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
* SUCH DAMAGE.
|
* SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* $Id$
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef lint
|
|
||||||
char copyright[] =
|
|
||||||
"@(#) Copyright (c) 1983, 1988, 1993\n\
|
|
||||||
The Regents of the University of California. All rights reserved.\n";
|
|
||||||
#endif /* not lint */
|
|
||||||
|
|
||||||
#ifndef lint
|
|
||||||
#if 0
|
|
||||||
static char sccsid[] = "@(#)main.c 8.1 (Berkeley) 6/5/93";
|
|
||||||
#endif
|
|
||||||
static const char rcsid[] =
|
|
||||||
"$Id$";
|
|
||||||
#endif /* not lint */
|
|
||||||
|
|
||||||
#include "defs.h"
|
#include "defs.h"
|
||||||
|
#include "pathnames.h"
|
||||||
#ifdef sgi
|
#ifdef sgi
|
||||||
#include "math.h"
|
#include "math.h"
|
||||||
#endif
|
#endif
|
||||||
|
#include <signal.h>
|
||||||
#include <fcntl.h>
|
#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;
|
pid_t mypid;
|
||||||
|
|
||||||
naddr myaddr; /* system address */
|
naddr myaddr; /* system address */
|
||||||
char myname[MAXHOSTNAMELEN+1];
|
char myname[MAXHOSTNAMELEN+1];
|
||||||
|
|
||||||
|
int verbose;
|
||||||
|
|
||||||
int supplier; /* supply or broadcast updates */
|
int supplier; /* supply or broadcast updates */
|
||||||
int supplier_set;
|
int supplier_set;
|
||||||
int ipforwarding = 1; /* kernel forwarding on */
|
int ipforwarding = 1; /* kernel forwarding on */
|
||||||
@ -69,6 +75,7 @@ int auth_ok = 1; /* 1=ignore auth if we do not care */
|
|||||||
|
|
||||||
struct timeval epoch; /* when started */
|
struct timeval epoch; /* when started */
|
||||||
struct timeval clk, prev_clk;
|
struct timeval clk, prev_clk;
|
||||||
|
static int usec_fudge;
|
||||||
struct timeval now; /* current idea of time */
|
struct timeval now; /* current idea of time */
|
||||||
time_t now_stale;
|
time_t now_stale;
|
||||||
time_t now_expire;
|
time_t now_expire;
|
||||||
@ -77,6 +84,8 @@ time_t now_garbage;
|
|||||||
struct timeval next_bcast; /* next general broadcast */
|
struct timeval next_bcast; /* next general broadcast */
|
||||||
struct timeval no_flash = {EPOCH+SUPPLY_INTERVAL}; /* inhibit flash update */
|
struct timeval no_flash = {EPOCH+SUPPLY_INTERVAL}; /* inhibit flash update */
|
||||||
|
|
||||||
|
struct timeval flush_kern_timer;
|
||||||
|
|
||||||
fd_set fdbits;
|
fd_set fdbits;
|
||||||
int sock_max;
|
int sock_max;
|
||||||
int rip_sock = -1; /* RIP socket */
|
int rip_sock = -1; /* RIP socket */
|
||||||
@ -95,6 +104,7 @@ main(int argc,
|
|||||||
int n, mib[4], off;
|
int n, mib[4], off;
|
||||||
size_t len;
|
size_t len;
|
||||||
char *p, *q;
|
char *p, *q;
|
||||||
|
const char *cp;
|
||||||
struct timeval wtime, t2;
|
struct timeval wtime, t2;
|
||||||
time_t dt;
|
time_t dt;
|
||||||
fd_set ibits;
|
fd_set ibits;
|
||||||
@ -125,7 +135,7 @@ main(int argc,
|
|||||||
(void)gethostname(myname, sizeof(myname)-1);
|
(void)gethostname(myname, sizeof(myname)-1);
|
||||||
(void)gethost(myname, &myaddr);
|
(void)gethost(myname, &myaddr);
|
||||||
|
|
||||||
while ((n = getopt(argc, argv, "sqdghmAtT:F:P:")) != -1) {
|
while ((n = getopt(argc, argv, "sqdghmpAtvT:F:P:")) != -1) {
|
||||||
switch (n) {
|
switch (n) {
|
||||||
case 's':
|
case 's':
|
||||||
supplier = 1;
|
supplier = 1;
|
||||||
@ -142,11 +152,11 @@ main(int argc,
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case 'g':
|
case 'g':
|
||||||
bzero(&parm, sizeof(parm));
|
memset(&parm, 0, sizeof(parm));
|
||||||
parm.parm_d_metric = 1;
|
parm.parm_d_metric = 1;
|
||||||
p = check_parms(&parm);
|
cp = check_parms(&parm);
|
||||||
if (p != 0)
|
if (cp != 0)
|
||||||
msglog("bad -g: %s", p);
|
msglog("bad -g: %s", cp);
|
||||||
else
|
else
|
||||||
default_gateway = 1;
|
default_gateway = 1;
|
||||||
break;
|
break;
|
||||||
@ -189,26 +199,29 @@ main(int argc,
|
|||||||
optarg);
|
optarg);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
bzero(&parm, sizeof(parm));
|
memset(&parm, 0, sizeof(parm));
|
||||||
parm.parm_net = p_net;
|
parm.parm_net = p_net;
|
||||||
parm.parm_mask = p_mask;
|
parm.parm_mask = p_mask;
|
||||||
parm.parm_d_metric = n;
|
parm.parm_d_metric = n;
|
||||||
p = check_parms(&parm);
|
cp = check_parms(&parm);
|
||||||
if (p != 0)
|
if (cp != 0)
|
||||||
msglog("bad -F: %s", p);
|
msglog("bad -F: %s", cp);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'P':
|
case 'P':
|
||||||
/* handle arbitrary, (usually) per-interface
|
/* handle arbitrary parameters.
|
||||||
* parameters.
|
|
||||||
*/
|
*/
|
||||||
p = parse_parms(optarg, 0);
|
q = strdup(optarg);
|
||||||
if (p != 0) {
|
cp = parse_parms(q, 0);
|
||||||
if (strcasecmp(p,optarg))
|
if (cp != 0)
|
||||||
msglog("%s in \"%s\"", p, optarg);
|
msglog("%s in \"-P %s\"", cp, optarg);
|
||||||
else
|
free(q);
|
||||||
msglog("bad \"-P %s\"", optarg);
|
break;
|
||||||
}
|
|
||||||
|
case 'v':
|
||||||
|
/* display version */
|
||||||
|
verbose++;
|
||||||
|
msglog("version 2.17");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@ -226,11 +239,14 @@ main(int argc,
|
|||||||
goto usage;
|
goto usage;
|
||||||
if (argc != 0) {
|
if (argc != 0) {
|
||||||
usage:
|
usage:
|
||||||
logbad(0, "usage: routed [-sqdghmpAt] [-T tracefile]"
|
logbad(0, "usage: routed [-sqdghmpAtv] [-T tracefile]"
|
||||||
" [-F net[/mask[,metric]]] [-P parms]");
|
" [-F net[,metric]] [-P parms]");
|
||||||
}
|
}
|
||||||
if (geteuid() != 0)
|
if (geteuid() != 0) {
|
||||||
|
if (verbose)
|
||||||
|
exit(0);
|
||||||
logbad(0, "requires UID 0");
|
logbad(0, "requires UID 0");
|
||||||
|
}
|
||||||
|
|
||||||
mib[0] = CTL_NET;
|
mib[0] = CTL_NET;
|
||||||
mib[1] = PF_INET;
|
mib[1] = PF_INET;
|
||||||
@ -271,12 +287,10 @@ main(int argc,
|
|||||||
/* get into the background */
|
/* get into the background */
|
||||||
#ifdef sgi
|
#ifdef sgi
|
||||||
if (0 > _daemonize(background ? 0 : (_DF_NOCHDIR|_DF_NOFORK),
|
if (0 > _daemonize(background ? 0 : (_DF_NOCHDIR|_DF_NOFORK),
|
||||||
new_tracelevel == 0 ? -1 : STDOUT_FILENO,
|
STDIN_FILENO, STDOUT_FILENO, STDERR_FILENO))
|
||||||
new_tracelevel == 0 ? -1 : STDERR_FILENO,
|
|
||||||
-1))
|
|
||||||
BADERR(0, "_daemonize()");
|
BADERR(0, "_daemonize()");
|
||||||
#else
|
#else
|
||||||
if (background && daemon(0, new_tracelevel) < 0)
|
if (background && daemon(0, 1) < 0)
|
||||||
BADERR(0,"daemon()");
|
BADERR(0,"daemon()");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -298,13 +312,11 @@ main(int argc,
|
|||||||
fix_select();
|
fix_select();
|
||||||
|
|
||||||
|
|
||||||
if (background && new_tracelevel == 0)
|
|
||||||
ftrace = 0;
|
|
||||||
if (tracename != 0) {
|
if (tracename != 0) {
|
||||||
strncpy(inittracename, tracename, sizeof(inittracename)-1);
|
strncpy(inittracename, tracename, sizeof(inittracename)-1);
|
||||||
set_tracefile(inittracename, "%s\n", -1);
|
set_tracefile(inittracename, "%s", -1);
|
||||||
} else {
|
} else {
|
||||||
tracelevel_msg("%s\n", -1); /* turn on tracing to stdio */
|
tracelevel_msg("%s", -1); /* turn on tracing to stdio */
|
||||||
}
|
}
|
||||||
|
|
||||||
bufinit();
|
bufinit();
|
||||||
@ -330,28 +342,45 @@ main(int argc,
|
|||||||
*/
|
*/
|
||||||
gwkludge();
|
gwkludge();
|
||||||
ifinit();
|
ifinit();
|
||||||
flush_kern();
|
|
||||||
|
|
||||||
/* Ask for routes */
|
/* Ask for routes */
|
||||||
rip_query();
|
rip_query();
|
||||||
rdisc_sol();
|
rdisc_sol();
|
||||||
|
|
||||||
|
/* Now turn off stdio if not tracing */
|
||||||
|
if (new_tracelevel == 0)
|
||||||
|
trace_close(background);
|
||||||
|
|
||||||
/* Loop forever, listening and broadcasting.
|
/* Loop forever, listening and broadcasting.
|
||||||
*/
|
*/
|
||||||
for (;;) {
|
for (;;) {
|
||||||
prev_clk = clk;
|
prev_clk = clk;
|
||||||
gettimeofday(&clk, 0);
|
gettimeofday(&clk, 0);
|
||||||
timevalsub(&t2, &clk, &prev_clk);
|
if (prev_clk.tv_sec == clk.tv_sec
|
||||||
if (t2.tv_sec < 0
|
&& prev_clk.tv_usec == clk.tv_usec+usec_fudge) {
|
||||||
|| t2.tv_sec > wtime.tv_sec + 5) {
|
/* Much of `routed` depends on time always advancing.
|
||||||
/* Deal with time changes before other housekeeping to
|
* On systems that do not guarantee that gettimeofday()
|
||||||
* keep everything straight.
|
* produces unique timestamps even if called within
|
||||||
|
* a single tick, use trickery like that in classic
|
||||||
|
* BSD kernels.
|
||||||
*/
|
*/
|
||||||
dt = t2.tv_sec;
|
clk.tv_usec += ++usec_fudge;
|
||||||
if (dt > 0)
|
|
||||||
dt -= wtime.tv_sec;
|
} else {
|
||||||
trace_act("time changed by %d sec", dt);
|
usec_fudge = 0;
|
||||||
epoch.tv_sec += dt;
|
|
||||||
|
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);
|
timevalsub(&now, &clk, &epoch);
|
||||||
now_stale = now.tv_sec - STALE_TIME;
|
now_stale = now.tv_sec - STALE_TIME;
|
||||||
@ -364,7 +393,7 @@ main(int argc,
|
|||||||
if (stopint != 0) {
|
if (stopint != 0) {
|
||||||
rip_bcast(0);
|
rip_bcast(0);
|
||||||
rdisc_adv();
|
rdisc_adv();
|
||||||
trace_off("exiting with signal %d\n", stopint);
|
trace_off("exiting with signal %d", stopint);
|
||||||
exit(stopint | 128);
|
exit(stopint | 128);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -377,6 +406,19 @@ main(int argc,
|
|||||||
continue;
|
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 it is time, then broadcast our routes.
|
||||||
*/
|
*/
|
||||||
if (supplier || advertise_mhome) {
|
if (supplier || advertise_mhome) {
|
||||||
@ -447,7 +489,7 @@ main(int argc,
|
|||||||
wtime = t2;
|
wtime = t2;
|
||||||
|
|
||||||
/* take care of router discovery,
|
/* take care of router discovery,
|
||||||
* but do it to the millisecond
|
* but do it in the correct the millisecond
|
||||||
*/
|
*/
|
||||||
if (!timercmp(&rdisc_timer, &now, >)) {
|
if (!timercmp(&rdisc_timer, &now, >)) {
|
||||||
rdisc_age(0);
|
rdisc_age(0);
|
||||||
@ -495,7 +537,7 @@ main(int argc,
|
|||||||
|
|
||||||
/* ARGSUSED */
|
/* ARGSUSED */
|
||||||
void
|
void
|
||||||
sigalrm(int s)
|
sigalrm(int s UNUSED)
|
||||||
{
|
{
|
||||||
/* Historically, SIGALRM would cause the daemon to check for
|
/* Historically, SIGALRM would cause the daemon to check for
|
||||||
* new and broken interfaces.
|
* new and broken interfaces.
|
||||||
@ -548,7 +590,7 @@ fix_select(void)
|
|||||||
|
|
||||||
void
|
void
|
||||||
fix_sock(int sock,
|
fix_sock(int sock,
|
||||||
char *name)
|
const char *name)
|
||||||
{
|
{
|
||||||
int on;
|
int on;
|
||||||
#define MIN_SOCKBUF (4*1024)
|
#define MIN_SOCKBUF (4*1024)
|
||||||
@ -604,14 +646,14 @@ get_rip_sock(naddr addr,
|
|||||||
if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
|
if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
|
||||||
BADERR(1,"rip_sock = socket()");
|
BADERR(1,"rip_sock = socket()");
|
||||||
|
|
||||||
bzero(&sin,sizeof(sin));
|
memset(&sin, 0, sizeof(sin));
|
||||||
#ifdef _HAVE_SIN_LEN
|
#ifdef _HAVE_SIN_LEN
|
||||||
sin.sin_len = sizeof(sin);
|
sin.sin_len = sizeof(sin);
|
||||||
#endif
|
#endif
|
||||||
sin.sin_family = AF_INET;
|
sin.sin_family = AF_INET;
|
||||||
sin.sin_port = htons(RIP_PORT);
|
sin.sin_port = htons(RIP_PORT);
|
||||||
sin.sin_addr.s_addr = addr;
|
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)
|
if (serious)
|
||||||
BADERR(errno != EADDRINUSE, "bind(rip_sock)");
|
BADERR(errno != EADDRINUSE, "bind(rip_sock)");
|
||||||
return -1;
|
return -1;
|
||||||
@ -632,7 +674,7 @@ void
|
|||||||
rip_off(void)
|
rip_off(void)
|
||||||
{
|
{
|
||||||
struct interface *ifp;
|
struct interface *ifp;
|
||||||
register naddr addr;
|
naddr addr;
|
||||||
|
|
||||||
|
|
||||||
if (rip_sock >= 0 && !mhome) {
|
if (rip_sock >= 0 && !mhome) {
|
||||||
@ -701,8 +743,10 @@ rip_on(struct interface *ifp)
|
|||||||
|
|
||||||
/* If the main RIP socket is off and it makes sense to turn it on,
|
/* If the main RIP socket is off and it makes sense to turn it on,
|
||||||
* then turn it on for all of the interfaces.
|
* 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");
|
trace_act("turn on RIP");
|
||||||
|
|
||||||
/* Close all of the query sockets so that we can open
|
/* Close all of the query sockets so that we can open
|
||||||
@ -748,11 +792,11 @@ rip_on(struct interface *ifp)
|
|||||||
*/
|
*/
|
||||||
void *
|
void *
|
||||||
rtmalloc(size_t size,
|
rtmalloc(size_t size,
|
||||||
char *msg)
|
const char *msg)
|
||||||
{
|
{
|
||||||
void *p = malloc(size);
|
void *p = malloc(size);
|
||||||
if (p == NULL)
|
if (p == 0)
|
||||||
logbad(1,"malloc() failed in %s", msg);
|
logbad(1,"malloc(%lu) failed in %s", (u_long)size, msg);
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -802,7 +846,7 @@ timevalsub(struct timeval *t1,
|
|||||||
/* put a message into the system log
|
/* put a message into the system log
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
msglog(char *p, ...)
|
msglog(const char *p, ...)
|
||||||
{
|
{
|
||||||
va_list args;
|
va_list args;
|
||||||
|
|
||||||
@ -828,12 +872,12 @@ msglog(char *p, ...)
|
|||||||
* For example, there can be many systems with the wrong password.
|
* For example, there can be many systems with the wrong password.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
msglim(struct msg_limit *lim, naddr addr, char *p, ...)
|
msglim(struct msg_limit *lim, naddr addr, const char *p, ...)
|
||||||
{
|
{
|
||||||
va_list args;
|
va_list args;
|
||||||
int i;
|
int i;
|
||||||
struct msg_sub *ms1, *ms;
|
struct msg_sub *ms1, *ms;
|
||||||
char *p1;
|
const char *p1;
|
||||||
|
|
||||||
va_start(args, p);
|
va_start(args, p);
|
||||||
|
|
||||||
@ -883,7 +927,7 @@ msglim(struct msg_limit *lim, naddr addr, char *p, ...)
|
|||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
logbad(int dump, char *p, ...)
|
logbad(int dump, const char *p, ...)
|
||||||
{
|
{
|
||||||
va_list args;
|
va_list args;
|
||||||
|
|
||||||
|
@ -11,7 +11,7 @@
|
|||||||
* notice, this list of conditions and the following disclaimer in the
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
* documentation and/or other materials provided with the distribution.
|
* documentation and/or other materials provided with the distribution.
|
||||||
* 3. All advertising materials mentioning features or use of this software
|
* 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
|
* This product includes software developed by the University of
|
||||||
* California, Berkeley and its contributors.
|
* California, Berkeley and its contributors.
|
||||||
* 4. Neither the name of the University nor the names of its contributors
|
* 4. Neither the name of the University nor the names of its contributors
|
||||||
@ -29,20 +29,21 @@
|
|||||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
* SUCH DAMAGE.
|
* SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* $Id$
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef lint
|
|
||||||
#if 0
|
|
||||||
static char sccsid[] = "@(#)output.c 8.1 (Berkeley) 6/5/93";
|
|
||||||
#endif
|
|
||||||
static const char rcsid[] =
|
|
||||||
"$Id$";
|
|
||||||
#endif /* not lint */
|
|
||||||
|
|
||||||
#include "defs.h"
|
#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
|
/* walk the tree of routes with this for output
|
||||||
@ -63,10 +64,9 @@ struct {
|
|||||||
#define WS_ST_RIP2_ALL 0x002 /* send full featured RIPv2 */
|
#define WS_ST_RIP2_ALL 0x002 /* send full featured RIPv2 */
|
||||||
#define WS_ST_AG 0x004 /* ok to aggregate subnets */
|
#define WS_ST_AG 0x004 /* ok to aggregate subnets */
|
||||||
#define WS_ST_SUPER_AG 0x008 /* ok to aggregate networks */
|
#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 0x010 /* responding to a query */
|
||||||
#define WS_ST_QUERY 0x020 /* responding to a query */
|
#define WS_ST_TO_ON_NET 0x020 /* sending onto one of our nets */
|
||||||
#define WS_ST_TO_ON_NET 0x040 /* sending onto one of our nets */
|
#define WS_ST_DEFAULT 0x040 /* faking a default */
|
||||||
#define WS_ST_DEFAULT 0x080 /* faking a default */
|
|
||||||
} ws;
|
} ws;
|
||||||
|
|
||||||
/* A buffer for what can be heard by both RIPv1 and RIPv2 listeners */
|
/* A buffer for what can be heard by both RIPv1 and RIPv2 listeners */
|
||||||
@ -104,7 +104,7 @@ output(enum output_type type,
|
|||||||
{
|
{
|
||||||
struct sockaddr_in sin;
|
struct sockaddr_in sin;
|
||||||
int flags;
|
int flags;
|
||||||
char *msg;
|
const char *msg;
|
||||||
int res;
|
int res;
|
||||||
naddr tgt_mcast;
|
naddr tgt_mcast;
|
||||||
int soc;
|
int soc;
|
||||||
@ -233,7 +233,7 @@ find_auth(struct interface *ifp)
|
|||||||
/* stop looking after the last key */
|
/* stop looking after the last key */
|
||||||
if (ap->type == RIP_AUTH_NONE)
|
if (ap->type == RIP_AUTH_NONE)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* ignore keys that are not ready yet */
|
/* ignore keys that are not ready yet */
|
||||||
if ((u_long)ap->start > (u_long)clk.tv_sec)
|
if ((u_long)ap->start > (u_long)clk.tv_sec)
|
||||||
continue;
|
continue;
|
||||||
@ -261,25 +261,26 @@ clr_ws_buf(struct ws_buf *wb,
|
|||||||
|
|
||||||
wb->lim = wb->base + NETS_LEN;
|
wb->lim = wb->base + NETS_LEN;
|
||||||
wb->n = wb->base;
|
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)
|
if (ap == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
na = (struct netauth*)wb->n;
|
na = (struct netauth*)wb->n;
|
||||||
if (ap->type == RIP_AUTH_PW) {
|
if (ap->type == RIP_AUTH_PW) {
|
||||||
na->a_family = RIP_AF_AUTH;
|
na->a_family = RIP_AF_AUTH;
|
||||||
na->a_type = RIP_AUTH_PW;
|
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++;
|
wb->n++;
|
||||||
|
|
||||||
} else if (ap->type == RIP_AUTH_MD5) {
|
} else if (ap->type == RIP_AUTH_MD5) {
|
||||||
na->a_family = RIP_AF_AUTH;
|
na->a_family = RIP_AF_AUTH;
|
||||||
na->a_type = RIP_AUTH_MD5;
|
na->a_type = RIP_AUTH_MD5;
|
||||||
na->au.a_md5.md5_keyid = ap->keyid;
|
na->au.a_md5.md5_keyid = ap->keyid;
|
||||||
na->au.a_md5.md5_auth_len = RIP_AUTH_PW_LEN;
|
na->au.a_md5.md5_auth_len = RIP_AUTH_MD5_LEN;
|
||||||
na->au.a_md5.md5_seqno = clk.tv_sec;
|
na->au.a_md5.md5_seqno = htonl(clk.tv_sec);
|
||||||
wb->n++;
|
wb->n++;
|
||||||
wb->lim--; /* make room for trailer */
|
wb->lim--; /* make room for trailer */
|
||||||
}
|
}
|
||||||
@ -292,17 +293,18 @@ end_md5_auth(struct ws_buf *wb,
|
|||||||
{
|
{
|
||||||
struct netauth *na, *na2;
|
struct netauth *na, *na2;
|
||||||
MD5_CTX md5_ctx;
|
MD5_CTX md5_ctx;
|
||||||
|
int len;
|
||||||
|
|
||||||
|
|
||||||
na = (struct netauth*)wb->base;
|
na = (struct netauth*)wb->base;
|
||||||
na2 = (struct netauth*)wb->n;
|
na2 = (struct netauth*)wb->n;
|
||||||
|
len = (char *)na2-(char *)wb->buf;
|
||||||
na2->a_family = RIP_AF_AUTH;
|
na2->a_family = RIP_AF_AUTH;
|
||||||
na2->a_type = 1;
|
na2->a_type = htons(1);
|
||||||
bcopy(ap->key, na2->au.au_pw, sizeof(na2->au.au_pw));
|
na->au.a_md5.md5_pkt_len = htons(len);
|
||||||
na->au.a_md5.md5_pkt_len = (char *)na2-(char *)(na+1);
|
|
||||||
MD5Init(&md5_ctx);
|
MD5Init(&md5_ctx);
|
||||||
MD5Update(&md5_ctx, (u_char *)na,
|
MD5Update(&md5_ctx, (u_char *)wb->buf, len);
|
||||||
(char *)(na2+1) - (char *)na);
|
MD5Update(&md5_ctx, ap->key, RIP_AUTH_MD5_LEN);
|
||||||
MD5Final(na2->au.au_pw, &md5_ctx);
|
MD5Final(na2->au.au_pw, &md5_ctx);
|
||||||
wb->n++;
|
wb->n++;
|
||||||
}
|
}
|
||||||
@ -356,11 +358,6 @@ supply_out(struct ag_info *ag)
|
|||||||
&& (ws.state & WS_ST_FLASH))
|
&& (ws.state & WS_ST_FLASH))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* Skip this route if required by split-horizon.
|
|
||||||
*/
|
|
||||||
if (ag->ag_state & AGS_SPLIT_HZ)
|
|
||||||
return;
|
|
||||||
|
|
||||||
dst_h = ag->ag_dst_h;
|
dst_h = ag->ag_dst_h;
|
||||||
mask = ag->ag_mask;
|
mask = ag->ag_mask;
|
||||||
v1_mask = ripv1_mask_host(htonl(dst_h),
|
v1_mask = ripv1_mask_host(htonl(dst_h),
|
||||||
@ -396,13 +393,14 @@ supply_out(struct ag_info *ag)
|
|||||||
/* Punt if we would have to generate an
|
/* Punt if we would have to generate an
|
||||||
* unreasonable number of routes.
|
* unreasonable number of routes.
|
||||||
*/
|
*/
|
||||||
#ifdef DEBUG
|
if (TRACECONTENTS)
|
||||||
msglog("sending %s to %s as 1 instead"
|
trace_misc("sending %s-->%s as 1"
|
||||||
" of %d routes",
|
" instead of %d routes",
|
||||||
addrname(htonl(dst_h),mask,1),
|
addrname(htonl(dst_h), mask,
|
||||||
naddr_ntoa(ws.to.sin_addr.s_addr),
|
1),
|
||||||
i+1);
|
naddr_ntoa(ws.to.sin_addr
|
||||||
#endif
|
.s_addr),
|
||||||
|
i+1);
|
||||||
i = 0;
|
i = 0;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
@ -451,12 +449,14 @@ supply_out(struct ag_info *ag)
|
|||||||
/* ARGSUSED */
|
/* ARGSUSED */
|
||||||
static int
|
static int
|
||||||
walk_supply(struct radix_node *rn,
|
walk_supply(struct radix_node *rn,
|
||||||
struct walkarg *w)
|
struct walkarg *argp UNUSED)
|
||||||
{
|
{
|
||||||
#define RT ((struct rt_entry *)rn)
|
#define RT ((struct rt_entry *)rn)
|
||||||
u_short ags;
|
u_short ags;
|
||||||
char metric, pref;
|
char metric, pref;
|
||||||
naddr dst, nhop;
|
naddr dst, nhop;
|
||||||
|
struct rt_spare *rts;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
|
||||||
/* Do not advertise external remote interfaces or passive interfaces.
|
/* Do not advertise external remote interfaces or passive interfaces.
|
||||||
@ -512,6 +512,7 @@ walk_supply(struct radix_node *rn,
|
|||||||
/* Advertise the next hop if this is not a route for one
|
/* Advertise the next hop if this is not a route for one
|
||||||
* of our interfaces and the next hop is on the same
|
* of our interfaces and the next hop is on the same
|
||||||
* network as the target.
|
* network as the target.
|
||||||
|
* The final determination is made by supply_out().
|
||||||
*/
|
*/
|
||||||
if (!(RT->rt_state & RS_IF)
|
if (!(RT->rt_state & RS_IF)
|
||||||
&& RT->rt_gate != myaddr
|
&& RT->rt_gate != myaddr
|
||||||
@ -529,23 +530,30 @@ walk_supply(struct radix_node *rn,
|
|||||||
;
|
;
|
||||||
|
|
||||||
} else if (RT_ISHOST(RT)) {
|
} else if (RT_ISHOST(RT)) {
|
||||||
/* We should always aggregate the host routes
|
/* We should always suppress (into existing network routes)
|
||||||
* for the local end of our point-to-point links.
|
* the host routes for the local end of our point-to-point
|
||||||
|
* links.
|
||||||
* If we are suppressing host routes in general, then do so.
|
* If we are suppressing host routes in general, then do so.
|
||||||
* Avoid advertising host routes onto their own network,
|
* Avoid advertising host routes onto their own network,
|
||||||
* where they should be handled by proxy-ARP.
|
* where they should be handled by proxy-ARP.
|
||||||
*/
|
*/
|
||||||
if ((RT->rt_state & RS_LOCAL)
|
if ((RT->rt_state & RS_LOCAL)
|
||||||
|| ridhosts
|
|| ridhosts
|
||||||
|| (ws.state & WS_ST_SUPER_AG)
|
|
||||||
|| on_net(dst, ws.to_net, ws.to_mask))
|
|| on_net(dst, ws.to_net, ws.to_mask))
|
||||||
ags |= AGS_SUPPRESS;
|
ags |= AGS_SUPPRESS;
|
||||||
|
|
||||||
if (ws.state & WS_ST_SUPER_AG)
|
/* Aggregate stray host routes into network routes if allowed.
|
||||||
ags |= AGS_PROMOTE;
|
* 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) {
|
} else {
|
||||||
/* Aggregate network routes, if we are allowed.
|
/* Always suppress network routes into other, existing
|
||||||
|
* network routes
|
||||||
*/
|
*/
|
||||||
ags |= AGS_SUPPRESS;
|
ags |= AGS_SUPPRESS;
|
||||||
|
|
||||||
@ -554,10 +562,10 @@ walk_supply(struct radix_node *rn,
|
|||||||
* later convert back to ordinary nets.
|
* later convert back to ordinary nets.
|
||||||
* This unifies dealing with received supernets.
|
* This unifies dealing with received supernets.
|
||||||
*/
|
*/
|
||||||
if ((RT->rt_state & RS_SUBNET)
|
if ((ws.state & WS_ST_AG)
|
||||||
|| (ws.state & WS_ST_SUPER_AG))
|
&& ((RT->rt_state & RS_SUBNET)
|
||||||
ags |= AGS_PROMOTE;
|
|| (ws.state & WS_ST_SUPER_AG)))
|
||||||
|
ags |= AGS_AGGREGATE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Do not send RIPv1 advertisements of subnets to other
|
/* Do not send RIPv1 advertisements of subnets to other
|
||||||
@ -565,11 +573,9 @@ walk_supply(struct radix_node *rn,
|
|||||||
*/
|
*/
|
||||||
if ((RT->rt_state & RS_SUBNET)
|
if ((RT->rt_state & RS_SUBNET)
|
||||||
&& !(ws.state & WS_ST_RIP2_ALL)
|
&& !(ws.state & WS_ST_RIP2_ALL)
|
||||||
&& !on_net(dst, ws.to_std_net, ws.to_std_mask)) {
|
&& !on_net(dst, ws.to_std_net, ws.to_std_mask))
|
||||||
ags |= AGS_RIPV2 | AGS_PROMOTE;
|
ags |= AGS_RIPV2 | AGS_AGGREGATE;
|
||||||
if (ws.state & WS_ST_SUB_AG)
|
|
||||||
ags |= AGS_SUPPRESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Do not send a route back to where it came from, except in
|
/* Do not send a route back to where it came from, except in
|
||||||
* response to a query. This is "split-horizon". That means not
|
* response to a query. This is "split-horizon". That means not
|
||||||
@ -578,61 +584,72 @@ walk_supply(struct radix_node *rn,
|
|||||||
* We want to suppress routes that might have been fragmented
|
* 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
|
* 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
|
* cannot forget this route here. Let the split-horizon route
|
||||||
* aggregate (suppress) the fragmented routes and then itself be
|
* suppress the fragmented routes and then itself be forgotten.
|
||||||
* forgotten.
|
|
||||||
*
|
*
|
||||||
* Include the routes for both ends of point-to-point interfaces
|
* Include the routes for both ends of point-to-point interfaces
|
||||||
* among those suppressed by split-horizon, since the other side
|
* among those suppressed by split-horizon, since the other side
|
||||||
* should knows them as well as we do.
|
* 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_QUERY)
|
||||||
&& (ws.state & WS_ST_TO_ON_NET)
|
&& (ws.state & WS_ST_TO_ON_NET)
|
||||||
&& (!(RT->rt_state & RS_IF)
|
&& (!(RT->rt_state & RS_IF)
|
||||||
|| ws.ifp->int_if_flags & IFF_POINTOPOINT)) {
|
|| ws.ifp->int_if_flags & IFF_POINTOPOINT)) {
|
||||||
/* If we do not mark the route with AGS_SPLIT_HZ here,
|
for (rts = RT->rt_spares, i = NUM_SPARES; i != 0; i--, rts++) {
|
||||||
* it will be poisoned-reverse, or advertised back toward
|
if (rts->rts_metric > metric
|
||||||
* its source with an infinite metric. If we have recently
|
|| rts->rts_ifp != ws.ifp)
|
||||||
* advertised the route with a better metric than we now
|
continue;
|
||||||
* have, then we should poison-reverse the route before
|
|
||||||
* suppressing it for split-horizon.
|
/* If we do not mark the route with AGS_SPLIT_HZ here,
|
||||||
*
|
* it will be poisoned-reverse, or advertised back
|
||||||
* In almost all cases, if there is no spare for the route
|
* toward its source with an infinite metric.
|
||||||
* then it is either old and dead or a brand new route.
|
* If we have recently advertised the route with a
|
||||||
* If it is brand new, there is no need for poison-reverse.
|
* better metric than we now have, then we should
|
||||||
* If it is old and dead, it is already poisoned.
|
* poison-reverse the route before suppressing it for
|
||||||
*/
|
* split-horizon.
|
||||||
if (RT->rt_poison_time < now_expire
|
*
|
||||||
|| RT->rt_poison_metric >= metric
|
* In almost all cases, if there is no spare for the
|
||||||
|| RT->rt_spares[1].rts_gate == 0) {
|
* route then it is either old and dead or a brand
|
||||||
ags |= AGS_SPLIT_HZ;
|
* new route. If it is brand new, there is no need
|
||||||
ags &= ~(AGS_PROMOTE | AGS_SUPPRESS);
|
* 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.
|
/* Adjust the outgoing metric by the cost of the link.
|
||||||
|
* Avoid aggregation when a route is counting to infinity.
|
||||||
*/
|
*/
|
||||||
pref = metric + ws.metric;
|
pref = RT->rt_poison_metric + ws.metric;
|
||||||
if (pref < HOPCNT_INFINITY) {
|
metric += ws.metric;
|
||||||
/* 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;
|
|
||||||
|
|
||||||
} else {
|
/* Do not advertise stable routes that will be ignored,
|
||||||
/* Do not advertise stable routes that will be ignored,
|
* unless we are answering a query.
|
||||||
* unless we are answering a query.
|
* If the route recently was advertised with a metric that
|
||||||
* If the route recently was advertised with a metric that
|
* would have been less than infinity through this interface,
|
||||||
* would have been less than infinity through this interface,
|
* we need to continue to advertise it in order to poison it.
|
||||||
* we need to continue to advertise it in order to poison it.
|
*/
|
||||||
*/
|
if (metric >= HOPCNT_INFINITY) {
|
||||||
pref = RT->rt_poison_metric + ws.metric;
|
|
||||||
if (!(ws.state & WS_ST_QUERY)
|
if (!(ws.state & WS_ST_QUERY)
|
||||||
&& (pref >= HOPCNT_INFINITY
|
&& (pref >= HOPCNT_INFINITY
|
||||||
|| RT->rt_poison_time < now_garbage))
|
|| RT->rt_poison_time < now_garbage))
|
||||||
@ -687,8 +704,6 @@ supply(struct sockaddr_in *dst,
|
|||||||
ws.npackets = 0;
|
ws.npackets = 0;
|
||||||
if (flash)
|
if (flash)
|
||||||
ws.state |= WS_ST_FLASH;
|
ws.state |= WS_ST_FLASH;
|
||||||
if (type == OUT_QUERY)
|
|
||||||
ws.state |= WS_ST_QUERY;
|
|
||||||
|
|
||||||
if ((ws.ifp = ifp) == 0) {
|
if ((ws.ifp = ifp) == 0) {
|
||||||
ws.metric = 1;
|
ws.metric = 1;
|
||||||
@ -702,44 +717,42 @@ supply(struct sockaddr_in *dst,
|
|||||||
ripv12_buf.rip.rip_vers = vers;
|
ripv12_buf.rip.rip_vers = vers;
|
||||||
|
|
||||||
switch (type) {
|
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:
|
case OUT_MULTICAST:
|
||||||
v2buf.type = ((ifp != 0 && (ifp->int_if_flags & IFF_MULTICAST))
|
if (ifp->int_if_flags & IFF_MULTICAST)
|
||||||
? OUT_MULTICAST
|
v2buf.type = OUT_MULTICAST;
|
||||||
: NO_OUT_MULTICAST);
|
else
|
||||||
|
v2buf.type = NO_OUT_MULTICAST;
|
||||||
v12buf.type = OUT_BROADCAST;
|
v12buf.type = OUT_BROADCAST;
|
||||||
break;
|
break;
|
||||||
case OUT_UNICAST:
|
|
||||||
case OUT_QUERY:
|
case OUT_QUERY:
|
||||||
|
ws.state |= WS_ST_QUERY;
|
||||||
|
/* fall through */
|
||||||
|
case OUT_BROADCAST:
|
||||||
|
case OUT_UNICAST:
|
||||||
v2buf.type = (vers == RIPv2) ? type : NO_OUT_RIPV2;
|
v2buf.type = (vers == RIPv2) ? type : NO_OUT_RIPV2;
|
||||||
v12buf.type = type;
|
v12buf.type = type;
|
||||||
break;
|
break;
|
||||||
default:
|
|
||||||
v2buf.type = type;
|
case NO_OUT_MULTICAST:
|
||||||
v12buf.type = type;
|
case NO_OUT_RIPV2:
|
||||||
break;
|
break; /* no output */
|
||||||
}
|
}
|
||||||
|
|
||||||
if (vers == RIPv2) {
|
if (vers == RIPv2) {
|
||||||
/* full RIPv2 only if cannot be heard by RIPv1 listeners */
|
/* full RIPv2 only if cannot be heard by RIPv1 listeners */
|
||||||
if (type != OUT_BROADCAST)
|
if (type != OUT_BROADCAST)
|
||||||
ws.state |= WS_ST_RIP2_ALL;
|
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);
|
ws.state |= (WS_ST_AG | WS_ST_SUPER_AG);
|
||||||
} else if (ifp == 0 || !(ifp->int_state & IS_NO_AG)) {
|
} else if (ifp == 0 || !(ifp->int_state & IS_NO_AG)) {
|
||||||
ws.state |= WS_ST_AG;
|
ws.state |= WS_ST_AG;
|
||||||
if (type != OUT_BROADCAST
|
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;
|
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;
|
ws.a = (vers == RIPv2) ? find_auth(ifp) : 0;
|
||||||
@ -835,7 +848,7 @@ rip_bcast(int flash)
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* skip turned off interfaces */
|
/* skip turned off interfaces */
|
||||||
if (!iff_alive(ifp->int_if_flags))
|
if (!iff_up(ifp->int_if_flags))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
vers = (ifp->int_state & IS_NO_RIPV1_OUT) ? RIPv2 : RIPv1;
|
vers = (ifp->int_state & IS_NO_RIPV1_OUT) ? RIPv2 : RIPv1;
|
||||||
@ -844,11 +857,8 @@ rip_bcast(int flash)
|
|||||||
/* ordinary, hardware interface */
|
/* ordinary, hardware interface */
|
||||||
dst.sin_addr.s_addr = ifp->int_brdaddr;
|
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
|
if (vers == RIPv2
|
||||||
&& (ifp->int_state & IS_NO_RIPV1_OUT)) {
|
&& !(ifp->int_state & IS_NO_RIP_MCAST)) {
|
||||||
type = OUT_MULTICAST;
|
type = OUT_MULTICAST;
|
||||||
} else {
|
} else {
|
||||||
type = OUT_BROADCAST;
|
type = OUT_BROADCAST;
|
||||||
@ -896,7 +906,7 @@ rip_query(void)
|
|||||||
if (rip_sock < 0)
|
if (rip_sock < 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
bzero(&buf, sizeof(buf));
|
memset(&buf, 0, sizeof(buf));
|
||||||
|
|
||||||
for (ifp = ifnet; ifp; ifp = ifp->int_next) {
|
for (ifp = ifnet; ifp; ifp = ifp->int_next) {
|
||||||
/* Skip interfaces those already queried.
|
/* Skip interfaces those already queried.
|
||||||
@ -910,7 +920,7 @@ rip_query(void)
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* skip turned off interfaces */
|
/* skip turned off interfaces */
|
||||||
if (!iff_alive(ifp->int_if_flags))
|
if (!iff_up(ifp->int_if_flags))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
buf.rip_vers = (ifp->int_state&IS_NO_RIPV1_OUT) ? RIPv2:RIPv1;
|
buf.rip_vers = (ifp->int_state&IS_NO_RIPV1_OUT) ? RIPv2:RIPv1;
|
||||||
@ -918,14 +928,26 @@ rip_query(void)
|
|||||||
buf.rip_nets[0].n_family = RIP_AF_UNSPEC;
|
buf.rip_nets[0].n_family = RIP_AF_UNSPEC;
|
||||||
buf.rip_nets[0].n_metric = htonl(HOPCNT_INFINITY);
|
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) {
|
if (ifp->int_if_flags & IFF_BROADCAST) {
|
||||||
/* ordinary, hardware interface */
|
/* ordinary, hardware interface */
|
||||||
dst.sin_addr.s_addr = ifp->int_brdaddr;
|
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
|
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;
|
type = OUT_MULTICAST;
|
||||||
} else {
|
} else {
|
||||||
type = OUT_BROADCAST;
|
type = OUT_BROADCAST;
|
||||||
|
@ -11,7 +11,7 @@
|
|||||||
* notice, this list of conditions and the following disclaimer in the
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
* documentation and/or other materials provided with the distribution.
|
* documentation and/or other materials provided with the distribution.
|
||||||
* 3. All advertising materials mentioning features or use of this software
|
* 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
|
* This product includes software developed by the University of
|
||||||
* California, Berkeley and its contributors.
|
* California, Berkeley and its contributors.
|
||||||
* 4. Neither the name of the University nor the names of its contributors
|
* 4. Neither the name of the University nor the names of its contributors
|
||||||
@ -29,22 +29,25 @@
|
|||||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
* SUCH DAMAGE.
|
* SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* $Id$
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef lint
|
|
||||||
#if 0
|
|
||||||
static char sccsid[] = "@(#)if.c 8.1 (Berkeley) 6/5/93";
|
|
||||||
#endif
|
|
||||||
static const char rcsid[] =
|
|
||||||
"$Id$";
|
|
||||||
#endif /* not lint */
|
|
||||||
|
|
||||||
#include "defs.h"
|
#include "defs.h"
|
||||||
#include "pathnames.h"
|
#include "pathnames.h"
|
||||||
#include <sys/stat.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 parm *parms;
|
||||||
struct intnet *intnets;
|
struct intnet *intnets;
|
||||||
|
struct r1net *r1nets;
|
||||||
struct tgate *tgates;
|
struct tgate *tgates;
|
||||||
|
|
||||||
|
|
||||||
@ -53,7 +56,7 @@ struct tgate *tgates;
|
|||||||
void
|
void
|
||||||
get_parms(struct interface *ifp)
|
get_parms(struct interface *ifp)
|
||||||
{
|
{
|
||||||
static warned_auth_in, warned_auth_out;
|
static int warned_auth_in, warned_auth_out;
|
||||||
struct parm *parmp;
|
struct parm *parmp;
|
||||||
int i, num_passwds = 0;
|
int i, num_passwds = 0;
|
||||||
|
|
||||||
@ -74,9 +77,9 @@ get_parms(struct interface *ifp)
|
|||||||
if (parmp->parm_auth[0].type == RIP_AUTH_NONE
|
if (parmp->parm_auth[0].type == RIP_AUTH_NONE
|
||||||
|| num_passwds >= MAX_AUTH_KEYS)
|
|| num_passwds >= MAX_AUTH_KEYS)
|
||||||
break;
|
break;
|
||||||
bcopy(&parmp->parm_auth[i],
|
memcpy(&ifp->int_auth[num_passwds++],
|
||||||
&ifp->int_auth[num_passwds++],
|
&parmp->parm_auth[i],
|
||||||
sizeof(ifp->int_auth[0]));
|
sizeof(ifp->int_auth[0]));
|
||||||
}
|
}
|
||||||
if (parmp->parm_rdisc_pref != 0)
|
if (parmp->parm_rdisc_pref != 0)
|
||||||
ifp->int_rdisc_pref = parmp->parm_rdisc_pref;
|
ifp->int_rdisc_pref = parmp->parm_rdisc_pref;
|
||||||
@ -109,9 +112,9 @@ get_parms(struct interface *ifp)
|
|||||||
/* By default, point-to-point links should be passive
|
/* By default, point-to-point links should be passive
|
||||||
* about router-discovery for the sake of demand-dialing.
|
* 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;
|
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;
|
ifp->int_state |= IS_NO_ADV_OUT;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -163,13 +166,15 @@ gwkludge(void)
|
|||||||
{
|
{
|
||||||
FILE *fp;
|
FILE *fp;
|
||||||
char *p, *lptr;
|
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;
|
struct interface *ifp;
|
||||||
naddr dst, netmask, gate;
|
naddr dst, netmask, gate;
|
||||||
int metric, n;
|
int metric, n, lnum;
|
||||||
struct stat sb;
|
struct stat sb;
|
||||||
u_int state;
|
u_int state;
|
||||||
char *type;
|
const char *type;
|
||||||
|
|
||||||
|
|
||||||
fp = fopen(_PATH_GATEWAYS, "r");
|
fp = fopen(_PATH_GATEWAYS, "r");
|
||||||
@ -182,39 +187,36 @@ gwkludge(void)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (;;) {
|
for (lnum = 1; ; lnum++) {
|
||||||
if (0 == fgets(lbuf, sizeof(lbuf)-1, fp))
|
if (0 == fgets(lbuf, sizeof(lbuf), fp))
|
||||||
break;
|
break;
|
||||||
lptr = lbuf;
|
lptr = lbuf;
|
||||||
while (*lptr == ' ')
|
while (*lptr == ' ')
|
||||||
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 == '#')
|
|| *lptr == '#')
|
||||||
continue;
|
continue;
|
||||||
p = lptr+strlen(lptr)-1;
|
|
||||||
while (*p == '\n' || *p == ' ')
|
|
||||||
*p-- = '\0';
|
|
||||||
|
|
||||||
/* notice newfangled parameter lines
|
/* notice newfangled parameter lines
|
||||||
*/
|
*/
|
||||||
if (strncasecmp("net", lptr, 3)
|
if (strncasecmp("net", lptr, 3)
|
||||||
&& strncasecmp("host", lptr, 4)) {
|
&& strncasecmp("host", lptr, 4)) {
|
||||||
p = parse_parms(lptr,
|
cp = parse_parms(lptr,
|
||||||
(sb.st_uid == 0
|
(sb.st_uid == 0
|
||||||
&& !(sb.st_mode&(S_IRWXG|S_IRWXO))));
|
&& !(sb.st_mode&(S_IRWXG|S_IRWXO))));
|
||||||
if (p != 0) {
|
if (cp != 0)
|
||||||
if (strcasecmp(p,lptr))
|
msglog("%s in line %d of "_PATH_GATEWAYS,
|
||||||
msglog("%s in "_PATH_GATEWAYS
|
cp, lnum);
|
||||||
" entry \"%s\"", p, lptr);
|
|
||||||
else
|
|
||||||
msglog("bad \"%s\" in "_PATH_GATEWAYS,
|
|
||||||
lptr);
|
|
||||||
}
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* {net | host} XX[/M] XX gateway XX metric DD [passive | external]\n */
|
/* {net | host} XX[/M] XX gateway XX metric DD [passive | external]\n */
|
||||||
qual[0] = '\0';
|
qual[0] = '\0';
|
||||||
|
/* the '64' here must be GNAME_LEN */
|
||||||
n = sscanf(lptr, "%4s %129[^ \t] gateway"
|
n = sscanf(lptr, "%4s %129[^ \t] gateway"
|
||||||
" %64[^ / \t] metric %u %8s\n",
|
" %64[^ / \t] metric %u %8s\n",
|
||||||
net_host, dname, gname, &metric, qual);
|
net_host, dname, gname, &metric, qual);
|
||||||
@ -241,10 +243,16 @@ gwkludge(void)
|
|||||||
" entry \"%s\"", dname, lptr);
|
" entry \"%s\"", dname, lptr);
|
||||||
continue;
|
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 */
|
HTONL(dst); /* make network # into IP address */
|
||||||
} else {
|
} else {
|
||||||
msglog("bad \"%s\" in "_PATH_GATEWAYS
|
msglog("bad \"%s\" in "_PATH_GATEWAYS
|
||||||
" entry \"%s\"", lptr);
|
" entry \"%s\"", net_host, lptr);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -311,14 +319,14 @@ gwkludge(void)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
ifp = (struct interface *)rtmalloc(sizeof(*ifp), "gwkludge");
|
ifp = (struct interface *)rtmalloc(sizeof(*ifp), "gwkludge()");
|
||||||
bzero(ifp, sizeof(*ifp));
|
memset(ifp, 0, sizeof(*ifp));
|
||||||
|
|
||||||
ifp->int_state = state;
|
ifp->int_state = state;
|
||||||
if (netmask == HOST_MASK)
|
if (netmask == HOST_MASK)
|
||||||
ifp->int_if_flags = IFF_POINTOPOINT | IFF_UP_RUNNING;
|
ifp->int_if_flags = IFF_POINTOPOINT | IFF_UP;
|
||||||
else
|
else
|
||||||
ifp->int_if_flags = IFF_UP_RUNNING;
|
ifp->int_if_flags = IFF_UP;
|
||||||
ifp->int_act_time = NEVER;
|
ifp->int_act_time = NEVER;
|
||||||
ifp->int_addr = gate;
|
ifp->int_addr = gate;
|
||||||
ifp->int_dstaddr = dst;
|
ifp->int_dstaddr = dst;
|
||||||
@ -355,16 +363,17 @@ gwkludge(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* strtok(), but honoring backslash
|
/* like strtok(), but honoring backslash and not changing the source string
|
||||||
*/
|
*/
|
||||||
static int /* 0=ok, -1=bad */
|
static int /* 0=ok, -1=bad */
|
||||||
parse_quote(char **linep,
|
parse_quote(char **linep, /* look here */
|
||||||
char *delims,
|
const char *delims, /* for these delimiters */
|
||||||
char *delimp,
|
char *delimp, /* 0 or put found delimiter here */
|
||||||
char *buf,
|
char *buf, /* copy token to here */
|
||||||
int lim)
|
int lim) /* at most this many bytes */
|
||||||
{
|
{
|
||||||
char c, *pc, *p;
|
char c = '\0', *pc;
|
||||||
|
const char *p;
|
||||||
|
|
||||||
|
|
||||||
pc = *linep;
|
pc = *linep;
|
||||||
@ -408,10 +417,10 @@ parse_quote(char **linep,
|
|||||||
if (lim == 0)
|
if (lim == 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
*buf = '\0';
|
*buf = '\0'; /* terminate copy of token */
|
||||||
if (delimp != 0)
|
if (delimp != 0)
|
||||||
*delimp = c;
|
*delimp = c; /* return delimiter */
|
||||||
*linep = pc-1;
|
*linep = pc-1; /* say where we ended */
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -427,6 +436,9 @@ parse_ts(time_t *tp,
|
|||||||
u_int bufsize)
|
u_int bufsize)
|
||||||
{
|
{
|
||||||
struct tm tm;
|
struct tm tm;
|
||||||
|
#if defined(sgi) || defined(__NetBSD__)
|
||||||
|
char *ptr;
|
||||||
|
#endif
|
||||||
|
|
||||||
if (0 > parse_quote(valp, "| ,\n\r", delimp,
|
if (0 > parse_quote(valp, "| ,\n\r", delimp,
|
||||||
buf,bufsize)
|
buf,bufsize)
|
||||||
@ -436,15 +448,26 @@ parse_ts(time_t *tp,
|
|||||||
return buf;
|
return buf;
|
||||||
}
|
}
|
||||||
strcat(buf,"\n");
|
strcat(buf,"\n");
|
||||||
bzero(&tm, sizeof(tm));
|
memset(&tm, 0, sizeof(tm));
|
||||||
if (5 != sscanf(buf, "%u/%u/%u@%u:%u\n",
|
#if defined(sgi) || defined(__NetBSD__)
|
||||||
&tm.tm_year, &tm.tm_mon, &tm.tm_mday,
|
ptr = strptime(buf, "%y/%m/%d@%H:%M\n", &tm);
|
||||||
&tm.tm_hour, &tm.tm_min)) {
|
if (ptr == NULL || *ptr != '\0') {
|
||||||
sprintf(buf,"bad timestamp %.25s", val0);
|
sprintf(buf,"bad timestamp %.25s", val0);
|
||||||
return buf;
|
return buf;
|
||||||
}
|
}
|
||||||
if (tm.tm_year <= 37)
|
#else
|
||||||
tm.tm_year += 100;
|
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) {
|
if ((*tp = mktime(&tm)) == -1) {
|
||||||
sprintf(buf,"bad timestamp %.25s", val0);
|
sprintf(buf,"bad timestamp %.25s", val0);
|
||||||
@ -458,11 +481,11 @@ parse_ts(time_t *tp,
|
|||||||
/* Get a password, key ID, and expiration date in the format
|
/* Get a password, key ID, and expiration date in the format
|
||||||
* passwd|keyID|year/mon/day@hour:min|year/mon/day@hour:min
|
* 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,
|
get_passwd(char *tgt,
|
||||||
char *val,
|
char *val,
|
||||||
struct parm *parmp,
|
struct parm *parmp,
|
||||||
u_char type,
|
u_int16_t type,
|
||||||
int safe) /* 1=from secure file */
|
int safe) /* 1=from secure file */
|
||||||
{
|
{
|
||||||
static char buf[80];
|
static char buf[80];
|
||||||
@ -473,7 +496,7 @@ get_passwd(char *tgt,
|
|||||||
|
|
||||||
|
|
||||||
if (!safe)
|
if (!safe)
|
||||||
return "unsafe password";
|
return "ignore unsafe password";
|
||||||
|
|
||||||
for (ap = parmp->parm_auth, i = 0;
|
for (ap = parmp->parm_auth, i = 0;
|
||||||
ap->type != RIP_AUTH_NONE; i++, ap++) {
|
ap->type != RIP_AUTH_NONE; i++, ap++) {
|
||||||
@ -481,7 +504,7 @@ get_passwd(char *tgt,
|
|||||||
return "too many passwords";
|
return "too many passwords";
|
||||||
}
|
}
|
||||||
|
|
||||||
bzero(&k, sizeof(k));
|
memset(&k, 0, sizeof(k));
|
||||||
k.type = type;
|
k.type = type;
|
||||||
k.end = -1-DAY;
|
k.end = -1-DAY;
|
||||||
|
|
||||||
@ -532,14 +555,24 @@ get_passwd(char *tgt,
|
|||||||
if (delim != '\0')
|
if (delim != '\0')
|
||||||
return tgt;
|
return tgt;
|
||||||
|
|
||||||
bcopy(&k, ap, sizeof(*ap));
|
memmove(ap, &k, sizeof(*ap));
|
||||||
return 0;
|
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.
|
/* Parse a set of parameters for an interface.
|
||||||
*/
|
*/
|
||||||
char * /* 0 or error message */
|
const char * /* 0 or error message */
|
||||||
parse_parms(char *line,
|
parse_parms(char *line,
|
||||||
int safe) /* 1=from secure file */
|
int safe) /* 1=from secure file */
|
||||||
{
|
{
|
||||||
@ -549,31 +582,35 @@ parse_parms(char *line,
|
|||||||
parm.parm_int_state |= (b);}
|
parm.parm_int_state |= (b);}
|
||||||
struct parm parm;
|
struct parm parm;
|
||||||
struct intnet *intnetp;
|
struct intnet *intnetp;
|
||||||
|
struct r1net *r1netp;
|
||||||
struct tgate *tg;
|
struct tgate *tg;
|
||||||
naddr addr, mask;
|
naddr addr, mask;
|
||||||
char delim, *val0, *tgt, *val, *p;
|
char delim, *val0 = 0, *tgt, *val, *p;
|
||||||
char buf[64];
|
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)
|
if (!strncasecmp(line, "subnet=", sizeof("subnet=")-1)
|
||||||
&& *(val = &line[sizeof("subnet=")-1]) != '\0') {
|
&& *(val = &line[sizeof("subnet=")-1]) != '\0') {
|
||||||
intnetp = (struct intnet*)
|
if (0 > parse_quote(&val, ",", &delim, buf, sizeof(buf)))
|
||||||
rtmalloc(sizeof(*intnetp), "parse_parms");
|
return bad_str(line);
|
||||||
|
intnetp = (struct intnet*)rtmalloc(sizeof(*intnetp),
|
||||||
|
"parse_parms subnet");
|
||||||
intnetp->intnet_metric = 1;
|
intnetp->intnet_metric = 1;
|
||||||
if ((p = strrchr(val,','))) {
|
if (delim == ',') {
|
||||||
*p++ = '\0';
|
intnetp->intnet_metric = (int)strtol(val+1,&p,0);
|
||||||
intnetp->intnet_metric = (int)strtol(p,&p,0);
|
|
||||||
if (*p != '\0'
|
if (*p != '\0'
|
||||||
|| intnetp->intnet_metric <= 0
|
|| intnetp->intnet_metric <= 0
|
||||||
|| intnetp->intnet_metric >= HOPCNT_INFINITY)
|
|| 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_mask == HOST_MASK
|
||||||
|| intnetp->intnet_addr == RIP_DEFAULT) {
|
|| intnetp->intnet_addr == RIP_DEFAULT) {
|
||||||
free(intnetp);
|
free(intnetp);
|
||||||
return line;
|
return bad_str(line);
|
||||||
}
|
}
|
||||||
HTONL(intnetp->intnet_addr);
|
HTONL(intnetp->intnet_addr);
|
||||||
intnetp->intnet_next = intnets;
|
intnetp->intnet_next = intnets;
|
||||||
@ -581,29 +618,62 @@ parse_parms(char *line,
|
|||||||
return 0;
|
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 (;;) {
|
for (;;) {
|
||||||
tgt = line + strspn(line, " ,\n\r");
|
tgt = line + strspn(line, " ,\n\r");
|
||||||
if (*tgt == '\0')
|
if (*tgt == '\0' || *tgt == '#')
|
||||||
break;
|
break;
|
||||||
|
line = tgt+strcspn(tgt, "= #,\n\r");
|
||||||
line += strcspn(tgt, "= ,\n\r");
|
|
||||||
delim = *line;
|
delim = *line;
|
||||||
if (delim == '=') {
|
if (delim == '=') {
|
||||||
val0 = ++line;
|
val0 = ++line;
|
||||||
if (0 > parse_quote(&line," ,\n\r",&delim,
|
if (0 > parse_quote(&line, " #,\n\r",&delim,
|
||||||
buf,sizeof(buf)))
|
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 (PARSEQ("if")) {
|
||||||
if (parm.parm_name[0] != '\0'
|
if (parm.parm_name[0] != '\0'
|
||||||
|| strlen(buf) > IFNAMSIZ)
|
|| strlen(buf) > IF_NAME_LEN)
|
||||||
return tgt;
|
return bad_str(tgt);
|
||||||
strcpy(parm.parm_name, buf);
|
strcpy(parm.parm_name, buf);
|
||||||
|
|
||||||
} else if (PARSEQ("addr")) {
|
} else if (PARSEQ("addr")) {
|
||||||
@ -615,7 +685,7 @@ parse_parms(char *line,
|
|||||||
*/
|
*/
|
||||||
if (!getnet(val0, &addr, &mask)
|
if (!getnet(val0, &addr, &mask)
|
||||||
|| parm.parm_name[0] != '\0')
|
|| parm.parm_name[0] != '\0')
|
||||||
return tgt;
|
return bad_str(tgt);
|
||||||
parm.parm_net = addr;
|
parm.parm_net = addr;
|
||||||
parm.parm_mask = mask;
|
parm.parm_mask = mask;
|
||||||
parm.parm_name[0] = '\n';
|
parm.parm_name[0] = '\n';
|
||||||
@ -624,17 +694,17 @@ parse_parms(char *line,
|
|||||||
/* since cleartext passwords are so weak allow
|
/* since cleartext passwords are so weak allow
|
||||||
* them anywhere
|
* them anywhere
|
||||||
*/
|
*/
|
||||||
tgt = get_passwd(tgt,val0,&parm,RIP_AUTH_PW,1);
|
msg = get_passwd(tgt,val0,&parm,RIP_AUTH_PW,1);
|
||||||
if (tgt) {
|
if (msg) {
|
||||||
*val0 = '\0';
|
*val0 = '\0';
|
||||||
return tgt;
|
return bad_str(msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if (PARSEQ("md5_passwd")) {
|
} else if (PARSEQ("md5_passwd")) {
|
||||||
tgt = get_passwd(tgt,val0,&parm,RIP_AUTH_MD5,safe);
|
msg = get_passwd(tgt,val0,&parm,RIP_AUTH_MD5,safe);
|
||||||
if (tgt) {
|
if (msg) {
|
||||||
*val0 = '\0';
|
*val0 = '\0';
|
||||||
return tgt;
|
return bad_str(msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if (PARS("no_ag")) {
|
} else if (PARS("no_ag")) {
|
||||||
@ -651,50 +721,53 @@ parse_parms(char *line,
|
|||||||
|
|
||||||
} else if (PARS("ripv2_out")) {
|
} else if (PARS("ripv2_out")) {
|
||||||
if (parm.parm_int_state & IS_NO_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;
|
parm.parm_int_state |= IS_NO_RIPV1_OUT;
|
||||||
|
|
||||||
} else if (PARS("ripv2")) {
|
} else if (PARS("ripv2")) {
|
||||||
if ((parm.parm_int_state & IS_NO_RIPV2_OUT)
|
if ((parm.parm_int_state & IS_NO_RIPV2_OUT)
|
||||||
|| (parm.parm_int_state & IS_NO_RIPV2_IN))
|
|| (parm.parm_int_state & IS_NO_RIPV2_IN))
|
||||||
return tgt;
|
return bad_str(tgt);
|
||||||
parm.parm_int_state |= (IS_NO_RIPV1_IN
|
parm.parm_int_state |= (IS_NO_RIPV1_IN
|
||||||
| IS_NO_RIPV1_OUT);
|
| IS_NO_RIPV1_OUT);
|
||||||
|
|
||||||
} else if (PARS("no_rip")) {
|
} else if (PARS("no_rip")) {
|
||||||
CKF(IS_PM_RDISC, IS_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")) {
|
} 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")) {
|
} 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")) {
|
} 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")) {
|
} 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")) {
|
} 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")) {
|
} else if (PARS("bcast_rdisc")) {
|
||||||
parm.parm_int_state |= IS_BCAST_RDISC;
|
parm.parm_int_state |= IS_BCAST_RDISC;
|
||||||
|
|
||||||
} else if (PARS("passive")) {
|
} 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;
|
parm.parm_int_state |= IS_NO_RIP;
|
||||||
|
|
||||||
} else if (PARSEQ("rdisc_pref")) {
|
} else if (PARSEQ("rdisc_pref")) {
|
||||||
if (parm.parm_rdisc_pref != 0
|
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'))
|
*p != '\0'))
|
||||||
return tgt;
|
return bad_str(tgt);
|
||||||
|
|
||||||
} else if (PARS("pm_rdisc")) {
|
} else if (PARS("pm_rdisc")) {
|
||||||
if (IS_RIP_OUT_OFF(parm.parm_int_state))
|
if (IS_RIP_OUT_OFF(parm.parm_int_state))
|
||||||
return tgt;
|
return bad_str(tgt);
|
||||||
parm.parm_int_state |= IS_PM_RDISC;
|
parm.parm_int_state |= IS_PM_RDISC;
|
||||||
|
|
||||||
} else if (PARSEQ("rdisc_interval")) {
|
} else if (PARSEQ("rdisc_interval")) {
|
||||||
@ -703,7 +776,7 @@ parse_parms(char *line,
|
|||||||
*p != '\0')
|
*p != '\0')
|
||||||
|| parm.parm_rdisc_int < MinMaxAdvertiseInterval
|
|| parm.parm_rdisc_int < MinMaxAdvertiseInterval
|
||||||
|| parm.parm_rdisc_int > MaxMaxAdvertiseInterval)
|
|| parm.parm_rdisc_int > MaxMaxAdvertiseInterval)
|
||||||
return tgt;
|
return bad_str(tgt);
|
||||||
|
|
||||||
} else if (PARSEQ("fake_default")) {
|
} else if (PARSEQ("fake_default")) {
|
||||||
if (parm.parm_d_metric != 0
|
if (parm.parm_d_metric != 0
|
||||||
@ -711,15 +784,35 @@ parse_parms(char *line,
|
|||||||
|| (parm.parm_d_metric = (int)strtoul(buf,&p,0),
|
|| (parm.parm_d_metric = (int)strtoul(buf,&p,0),
|
||||||
*p != '\0')
|
*p != '\0')
|
||||||
|| parm.parm_d_metric > HOPCNT_INFINITY-1)
|
|| parm.parm_d_metric > HOPCNT_INFINITY-1)
|
||||||
return tgt;
|
return bad_str(tgt);
|
||||||
|
|
||||||
} else if (PARSEQ("trust_gateway")) {
|
} else if (PARSEQ("trust_gateway")) {
|
||||||
if (!gethost(buf,&addr))
|
/* look for trust_gateway=x.y.z|net/mask|...) */
|
||||||
return tgt;
|
p = buf;
|
||||||
tg = (struct tgate *)
|
if (0 > parse_quote(&p, "|", &delim,
|
||||||
rtmalloc(sizeof(*tg), "parse_parms");
|
buf2, sizeof(buf2))
|
||||||
tg->tgate_next = tgates;
|
|| !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;
|
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;
|
tgates = tg;
|
||||||
parm.parm_int_state |= IS_DISTRUST;
|
parm.parm_int_state |= IS_DISTRUST;
|
||||||
|
|
||||||
@ -727,7 +820,7 @@ parse_parms(char *line,
|
|||||||
parm.parm_int_state |= IS_REDIRECT_OK;
|
parm.parm_int_state |= IS_REDIRECT_OK;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
return tgt; /* error */
|
return bad_str(tgt); /* error */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -738,7 +831,7 @@ parse_parms(char *line,
|
|||||||
|
|
||||||
|
|
||||||
/* check for duplicate parameter specifications */
|
/* check for duplicate parameter specifications */
|
||||||
char * /* 0 or error message */
|
const char * /* 0 or error message */
|
||||||
check_parms(struct parm *new)
|
check_parms(struct parm *new)
|
||||||
{
|
{
|
||||||
struct parm *parmp, **parmpp;
|
struct parm *parmp, **parmpp;
|
||||||
@ -748,6 +841,8 @@ check_parms(struct parm *new)
|
|||||||
*/
|
*/
|
||||||
if (new->parm_int_state & IS_NO_ADV_IN)
|
if (new->parm_int_state & IS_NO_ADV_IN)
|
||||||
new->parm_int_state |= IS_NO_SOL_OUT;
|
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++) {
|
for (i = num_passwds = 0; i < MAX_AUTH_KEYS; i++) {
|
||||||
if (new->parm_auth[i].type != RIP_AUTH_NONE)
|
if (new->parm_auth[i].type != RIP_AUTH_NONE)
|
||||||
@ -774,14 +869,14 @@ check_parms(struct parm *new)
|
|||||||
if (num_passwds > MAX_AUTH_KEYS)
|
if (num_passwds > MAX_AUTH_KEYS)
|
||||||
return "too many conflicting passwords";
|
return "too many conflicting passwords";
|
||||||
|
|
||||||
if ((0 != (new->parm_int_state & GROUP_IS_SOL)
|
if ((0 != (new->parm_int_state & GROUP_IS_SOL_OUT)
|
||||||
&& 0 != (parmp->parm_int_state & GROUP_IS_SOL)
|
&& 0 != (parmp->parm_int_state & GROUP_IS_SOL_OUT)
|
||||||
&& 0 != ((new->parm_int_state ^ parmp->parm_int_state)
|
&& 0 != ((new->parm_int_state ^ parmp->parm_int_state)
|
||||||
&& GROUP_IS_SOL))
|
&& GROUP_IS_SOL_OUT))
|
||||||
|| (0 != (new->parm_int_state & GROUP_IS_ADV)
|
|| (0 != (new->parm_int_state & GROUP_IS_ADV_OUT)
|
||||||
&& 0 != (parmp->parm_int_state & GROUP_IS_ADV)
|
&& 0 != (parmp->parm_int_state & GROUP_IS_ADV_OUT)
|
||||||
&& 0 != ((new->parm_int_state ^ parmp->parm_int_state)
|
&& 0 != ((new->parm_int_state ^ parmp->parm_int_state)
|
||||||
&& GROUP_IS_ADV))
|
&& GROUP_IS_ADV_OUT))
|
||||||
|| (new->parm_rdisc_pref != 0
|
|| (new->parm_rdisc_pref != 0
|
||||||
&& parmp->parm_rdisc_pref != 0
|
&& parmp->parm_rdisc_pref != 0
|
||||||
&& new->parm_rdisc_pref != parmp->parm_rdisc_pref)
|
&& new->parm_rdisc_pref != parmp->parm_rdisc_pref)
|
||||||
@ -805,7 +900,7 @@ check_parms(struct parm *new)
|
|||||||
* they affect the result in the order the operator specified.
|
* they affect the result in the order the operator specified.
|
||||||
*/
|
*/
|
||||||
parmp = (struct parm*)rtmalloc(sizeof(*parmp), "check_parms");
|
parmp = (struct parm*)rtmalloc(sizeof(*parmp), "check_parms");
|
||||||
bcopy(new, parmp, sizeof(*parmp));
|
memcpy(parmp, new, sizeof(*parmp));
|
||||||
*parmpp = parmp;
|
*parmpp = parmp;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@ -817,7 +912,7 @@ check_parms(struct parm *new)
|
|||||||
*/
|
*/
|
||||||
int /* 0=bad */
|
int /* 0=bad */
|
||||||
getnet(char *name,
|
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 */
|
naddr *maskp) /* masks are always in host order */
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
@ -830,11 +925,11 @@ getnet(char *name,
|
|||||||
|
|
||||||
/* Detect and separate "1.2.3.4/24"
|
/* Detect and separate "1.2.3.4/24"
|
||||||
*/
|
*/
|
||||||
if (0 != (mname = rindex(name,'/'))) {
|
if (0 != (mname = strrchr(name,'/'))) {
|
||||||
i = (int)(mname - name);
|
i = (int)(mname - name);
|
||||||
if (i > sizeof(hname)-1) /* name too long */
|
if (i > (int)sizeof(hname)-1) /* name too long */
|
||||||
return 0;
|
return 0;
|
||||||
bcopy(name, hname, i);
|
memmove(hname, name, i);
|
||||||
hname[i] = '\0';
|
hname[i] = '\0';
|
||||||
mname++;
|
mname++;
|
||||||
name = hname;
|
name = hname;
|
||||||
@ -843,6 +938,12 @@ getnet(char *name,
|
|||||||
np = getnetbyname(name);
|
np = getnetbyname(name);
|
||||||
if (np != 0) {
|
if (np != 0) {
|
||||||
in.s_addr = (naddr)np->n_net;
|
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) {
|
} else if (inet_aton(name, &in) == 1) {
|
||||||
NTOHL(in.s_addr);
|
NTOHL(in.s_addr);
|
||||||
} else if (!mname && !strcasecmp(name,"default")) {
|
} else if (!mname && !strcasecmp(name,"default")) {
|
||||||
@ -862,7 +963,8 @@ getnet(char *name,
|
|||||||
mask = (naddr)strtoul(mname, &p, 0);
|
mask = (naddr)strtoul(mname, &p, 0);
|
||||||
if (*p != '\0' || mask > 32)
|
if (*p != '\0' || mask > 32)
|
||||||
return 0;
|
return 0;
|
||||||
mask = HOST_MASK << (32-mask);
|
if (mask != 0)
|
||||||
|
mask = HOST_MASK << (32-mask);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* must have mask of 0 with default */
|
/* must have mask of 0 with default */
|
||||||
@ -910,7 +1012,7 @@ gethost(char *name,
|
|||||||
|
|
||||||
hp = gethostbyname(name);
|
hp = gethostbyname(name);
|
||||||
if (hp) {
|
if (hp) {
|
||||||
bcopy(hp->h_addr, addrp, sizeof(*addrp));
|
memcpy(addrp, hp->h_addr, sizeof(*addrp));
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -11,7 +11,7 @@
|
|||||||
* notice, this list of conditions and the following disclaimer in the
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
* documentation and/or other materials provided with the distribution.
|
* documentation and/or other materials provided with the distribution.
|
||||||
* 3. All advertising materials mentioning features or use of this software
|
* 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
|
* This product includes software developed by the University of
|
||||||
* California, Berkeley and its contributors.
|
* California, Berkeley and its contributors.
|
||||||
* 4. Neither the name of the University nor the names of its contributors
|
* 4. Neither the name of the University nor the names of its contributors
|
||||||
@ -31,8 +31,8 @@
|
|||||||
* SUCH DAMAGE.
|
* SUCH DAMAGE.
|
||||||
*
|
*
|
||||||
* @(#)pathnames.h 8.1 (Berkeley) 6/5/93
|
* @(#)pathnames.h 8.1 (Berkeley) 6/5/93
|
||||||
|
*
|
||||||
* $Id$
|
* $Id$
|
||||||
* $NetBSD$
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <paths.h>
|
#include <paths.h>
|
||||||
@ -47,6 +47,8 @@
|
|||||||
* Leave this undefined, and only the trace file originally specified
|
* Leave this undefined, and only the trace file originally specified
|
||||||
* when routed was started, if any, will be appended to.
|
* when routed was started, if any, will be appended to.
|
||||||
*/
|
*/
|
||||||
#if 0
|
#ifndef __NetBSD__
|
||||||
#define _PATH_TRACE "/var/log/routed.trace"
|
#define _PATH_TRACE "/etc/routed.trace"
|
||||||
|
#else
|
||||||
|
#undef _PATH_TRACE
|
||||||
#endif
|
#endif
|
||||||
|
@ -11,7 +11,7 @@
|
|||||||
* notice, this list of conditions and the following disclaimer in the
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
* documentation and/or other materials provided with the distribution.
|
* documentation and/or other materials provided with the distribution.
|
||||||
* 3. All advertising materials mentioning features or use of this software
|
* 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
|
* This product includes software developed by the University of
|
||||||
* California, Berkeley and its contributors.
|
* California, Berkeley and its contributors.
|
||||||
* 4. Neither the name of the University nor the names of its contributors
|
* 4. Neither the name of the University nor the names of its contributors
|
||||||
@ -30,22 +30,24 @@
|
|||||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
* SUCH DAMAGE.
|
* SUCH DAMAGE.
|
||||||
*
|
*
|
||||||
|
* @(#)radix.c 8.4 (Berkeley) 11/2/94
|
||||||
|
*
|
||||||
|
* $Id$
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef lint
|
|
||||||
#if 0
|
|
||||||
static char sccsid[] = "@(#)radix.c 8.4 (Berkeley) 11/2/94";
|
|
||||||
#endif
|
|
||||||
static const char rcsid[] =
|
|
||||||
"$Id$";
|
|
||||||
#endif /* not lint */
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Routines to build and maintain radix trees for routing lookups.
|
* Routines to build and maintain radix trees for routing lookups.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "defs.h"
|
#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 log(x, msg) syslog(x, msg)
|
||||||
#define panic(s) {log(LOG_ERR,s); exit(1);}
|
#define panic(s) {log(LOG_ERR,s); exit(1);}
|
||||||
#define min(a,b) (((a)<(b))?(a):(b))
|
#define min(a,b) (((a)<(b))?(a):(b))
|
||||||
@ -59,9 +61,10 @@ static char *rn_zeros, *rn_ones;
|
|||||||
|
|
||||||
#define rn_masktop (mask_rnhead->rnh_treetop)
|
#define rn_masktop (mask_rnhead->rnh_treetop)
|
||||||
#undef Bcmp
|
#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
|
* The data structure for the keys is a radix tree with one way
|
||||||
@ -101,8 +104,8 @@ struct radix_node *
|
|||||||
rn_search(void *v_arg,
|
rn_search(void *v_arg,
|
||||||
struct radix_node *head)
|
struct radix_node *head)
|
||||||
{
|
{
|
||||||
register struct radix_node *x;
|
struct radix_node *x;
|
||||||
register caddr_t v;
|
caddr_t v;
|
||||||
|
|
||||||
for (x = head, v = v_arg; x->rn_b >= 0;) {
|
for (x = head, v = v_arg; x->rn_b >= 0;) {
|
||||||
if (x->rn_bmask & v[x->rn_off])
|
if (x->rn_bmask & v[x->rn_off])
|
||||||
@ -118,8 +121,8 @@ rn_search_m(void *v_arg,
|
|||||||
struct radix_node *head,
|
struct radix_node *head,
|
||||||
void *m_arg)
|
void *m_arg)
|
||||||
{
|
{
|
||||||
register struct radix_node *x;
|
struct radix_node *x;
|
||||||
register caddr_t v = v_arg, m = m_arg;
|
caddr_t v = v_arg, m = m_arg;
|
||||||
|
|
||||||
for (x = head; x->rn_b >= 0;) {
|
for (x = head; x->rn_b >= 0;) {
|
||||||
if ((x->rn_bmask & m[x->rn_off]) &&
|
if ((x->rn_bmask & m[x->rn_off]) &&
|
||||||
@ -134,8 +137,8 @@ rn_search_m(void *v_arg,
|
|||||||
int
|
int
|
||||||
rn_refines(void* m_arg, void *n_arg)
|
rn_refines(void* m_arg, void *n_arg)
|
||||||
{
|
{
|
||||||
register caddr_t m = m_arg, n = n_arg;
|
caddr_t m = m_arg, n = n_arg;
|
||||||
register caddr_t lim, lim2 = lim = n + *(u_char *)n;
|
caddr_t lim, lim2 = lim = n + *(u_char *)n;
|
||||||
int longer = (*(u_char *)n++) - (int)(*(u_char *)m++);
|
int longer = (*(u_char *)n++) - (int)(*(u_char *)m++);
|
||||||
int masks_are_equal = 1;
|
int masks_are_equal = 1;
|
||||||
|
|
||||||
@ -158,11 +161,9 @@ rn_refines(void* m_arg, void *n_arg)
|
|||||||
}
|
}
|
||||||
|
|
||||||
struct radix_node *
|
struct radix_node *
|
||||||
rn_lookup(v_arg, m_arg, head)
|
rn_lookup(void *v_arg, void *m_arg, struct radix_node_head *head)
|
||||||
void *v_arg, *m_arg;
|
|
||||||
struct radix_node_head *head;
|
|
||||||
{
|
{
|
||||||
register struct radix_node *x;
|
struct radix_node *x;
|
||||||
caddr_t netmask = 0;
|
caddr_t netmask = 0;
|
||||||
|
|
||||||
if (m_arg) {
|
if (m_arg) {
|
||||||
@ -179,11 +180,11 @@ rn_lookup(v_arg, m_arg, head)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
rn_satsifies_leaf(char *trial,
|
rn_satisfies_leaf(char *trial,
|
||||||
register struct radix_node *leaf,
|
struct radix_node *leaf,
|
||||||
int skip)
|
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;
|
char *cplim;
|
||||||
int length = min(*(u_char *)cp, *(u_char *)cp2);
|
int length = min(*(u_char *)cp, *(u_char *)cp2);
|
||||||
|
|
||||||
@ -203,12 +204,12 @@ rn_match(void *v_arg,
|
|||||||
struct radix_node_head *head)
|
struct radix_node_head *head)
|
||||||
{
|
{
|
||||||
caddr_t v = v_arg;
|
caddr_t v = v_arg;
|
||||||
register struct radix_node *t = head->rnh_treetop, *x;
|
struct radix_node *t = head->rnh_treetop, *x;
|
||||||
register caddr_t cp = v, cp2;
|
caddr_t cp = v, cp2;
|
||||||
caddr_t cplim;
|
caddr_t cplim;
|
||||||
struct radix_node *saved_t, *top = t;
|
struct radix_node *saved_t, *top = t;
|
||||||
int off = t->rn_off, vlen = *(u_char *)cp, matched_off;
|
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
|
* Open code rn_search(v, top) to avoid overhead of extra
|
||||||
@ -272,7 +273,7 @@ rn_match(void *v_arg,
|
|||||||
*/
|
*/
|
||||||
if ((saved_t = t)->rn_mask == 0)
|
if ((saved_t = t)->rn_mask == 0)
|
||||||
t = t->rn_dupedkey;
|
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,
|
* Even if we don't match exactly as a host,
|
||||||
* we may match if the leaf we wound up at is
|
* we may match if the leaf we wound up at is
|
||||||
@ -281,12 +282,14 @@ rn_match(void *v_arg,
|
|||||||
if (t->rn_flags & RNF_NORMAL) {
|
if (t->rn_flags & RNF_NORMAL) {
|
||||||
if (rn_b <= t->rn_b)
|
if (rn_b <= t->rn_b)
|
||||||
return t;
|
return t;
|
||||||
} else if (rn_satsifies_leaf(v, t, matched_off))
|
} else if (rn_satisfies_leaf(v, t, matched_off)) {
|
||||||
return t;
|
return t;
|
||||||
|
}
|
||||||
|
}
|
||||||
t = saved_t;
|
t = saved_t;
|
||||||
/* start searching up the tree */
|
/* start searching up the tree */
|
||||||
do {
|
do {
|
||||||
register struct radix_mask *m;
|
struct radix_mask *m;
|
||||||
t = t->rn_p;
|
t = t->rn_p;
|
||||||
if ((m = t->rn_mklist)) {
|
if ((m = t->rn_mklist)) {
|
||||||
/*
|
/*
|
||||||
@ -304,7 +307,7 @@ rn_match(void *v_arg,
|
|||||||
x = rn_search_m(v, t, m->rm_mask);
|
x = rn_search_m(v, t, m->rm_mask);
|
||||||
while (x && x->rn_mask != m->rm_mask)
|
while (x && x->rn_mask != m->rm_mask)
|
||||||
x = x->rn_dupedkey;
|
x = x->rn_dupedkey;
|
||||||
if (x && rn_satsifies_leaf(v, x, off))
|
if (x && rn_satisfies_leaf(v, x, off))
|
||||||
return x;
|
return x;
|
||||||
}
|
}
|
||||||
} while ((m = m->rm_mklist));
|
} while ((m = m->rm_mklist));
|
||||||
@ -323,7 +326,7 @@ int rn_debug = 1;
|
|||||||
struct radix_node *
|
struct radix_node *
|
||||||
rn_newpair(void *v, int b, struct radix_node nodes[2])
|
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_b = b; t->rn_bmask = 0x80 >> (b & 7);
|
||||||
t->rn_l = tt; t->rn_off = b >> 3;
|
t->rn_l = tt; t->rn_off = b >> 3;
|
||||||
tt->rn_b = -1; tt->rn_key = (caddr_t)v; tt->rn_p = t;
|
tt->rn_b = -1; tt->rn_key = (caddr_t)v; tt->rn_p = t;
|
||||||
@ -344,17 +347,17 @@ rn_insert(void* v_arg,
|
|||||||
caddr_t v = v_arg;
|
caddr_t v = v_arg;
|
||||||
struct radix_node *top = head->rnh_treetop;
|
struct radix_node *top = head->rnh_treetop;
|
||||||
int head_off = top->rn_off, vlen = (int)*((u_char *)v);
|
int head_off = top->rn_off, vlen = (int)*((u_char *)v);
|
||||||
register struct radix_node *t = rn_search(v_arg, top);
|
struct radix_node *t = rn_search(v_arg, top);
|
||||||
register caddr_t cp = v + head_off;
|
caddr_t cp = v + head_off;
|
||||||
register int b;
|
int b;
|
||||||
struct radix_node *tt;
|
struct radix_node *tt;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Find first bit at which v and t->rn_key differ
|
* Find first bit at which v and t->rn_key differ
|
||||||
*/
|
*/
|
||||||
{
|
{
|
||||||
register caddr_t cp2 = t->rn_key + head_off;
|
caddr_t cp2 = t->rn_key + head_off;
|
||||||
register int cmp_res;
|
int cmp_res;
|
||||||
caddr_t cplim = v + vlen;
|
caddr_t cplim = v + vlen;
|
||||||
|
|
||||||
while (cp < cplim)
|
while (cp < cplim)
|
||||||
@ -372,14 +375,14 @@ rn_insert(void* v_arg,
|
|||||||
cmp_res >>= 1;
|
cmp_res >>= 1;
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
register struct radix_node *p, *x = top;
|
struct radix_node *p, *x = top;
|
||||||
cp = v;
|
cp = v;
|
||||||
do {
|
do {
|
||||||
p = x;
|
p = x;
|
||||||
if (cp[x->rn_off] & x->rn_bmask)
|
if (cp[x->rn_off] & x->rn_bmask)
|
||||||
x = x->rn_r;
|
x = x->rn_r;
|
||||||
else x = x->rn_l;
|
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
|
#ifdef RN_DEBUG
|
||||||
if (rn_debug)
|
if (rn_debug)
|
||||||
log(LOG_DEBUG, "rn_insert: Going In:\n"), traverse(p);
|
log(LOG_DEBUG, "rn_insert: Going In:\n"), traverse(p);
|
||||||
@ -407,9 +410,9 @@ struct radix_node *
|
|||||||
rn_addmask(void *n_arg, int search, int skip)
|
rn_addmask(void *n_arg, int search, int skip)
|
||||||
{
|
{
|
||||||
caddr_t netmask = (caddr_t)n_arg;
|
caddr_t netmask = (caddr_t)n_arg;
|
||||||
register struct radix_node *x;
|
struct radix_node *x;
|
||||||
register caddr_t cp, cplim;
|
caddr_t cp, cplim;
|
||||||
register int b = 0, mlen, j;
|
int b = 0, mlen, j;
|
||||||
int maskduplicated, m0, isnormal;
|
int maskduplicated, m0, isnormal;
|
||||||
struct radix_node *saved_x;
|
struct radix_node *saved_x;
|
||||||
static int last_zeroed = 0;
|
static int last_zeroed = 0;
|
||||||
@ -443,10 +446,9 @@ rn_addmask(void *n_arg, int search, int skip)
|
|||||||
x = 0;
|
x = 0;
|
||||||
if (x || search)
|
if (x || search)
|
||||||
return (x);
|
return (x);
|
||||||
x = (struct radix_node *)
|
x = (struct radix_node *)rtmalloc(max_keylen + 2*sizeof(*x),
|
||||||
rtmalloc(max_keylen + 2 * sizeof (*x), "rn_addmask");
|
"rn_addmask");
|
||||||
if ((saved_x = x) == 0)
|
saved_x = x;
|
||||||
return (0);
|
|
||||||
Bzero(x, max_keylen + 2 * sizeof (*x));
|
Bzero(x, max_keylen + 2 * sizeof (*x));
|
||||||
netmask = cp = (caddr_t)(x + 2);
|
netmask = cp = (caddr_t)(x + 2);
|
||||||
Bcopy(addmask_key, cp, mlen);
|
Bcopy(addmask_key, cp, mlen);
|
||||||
@ -478,7 +480,7 @@ rn_addmask(void *n_arg, int search, int skip)
|
|||||||
static int /* XXX: arbitrary ordering for non-contiguous masks */
|
static int /* XXX: arbitrary ordering for non-contiguous masks */
|
||||||
rn_lexobetter(void *m_arg, void *n_arg)
|
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)
|
if (*mp > *np)
|
||||||
return 1; /* not really, but need to check longer one first */
|
return 1; /* not really, but need to check longer one first */
|
||||||
@ -490,10 +492,10 @@ rn_lexobetter(void *m_arg, void *n_arg)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static struct radix_mask *
|
static struct radix_mask *
|
||||||
rn_new_radix_mask(register struct radix_node *tt,
|
rn_new_radix_mask(struct radix_node *tt,
|
||||||
register struct radix_mask *next)
|
struct radix_mask *next)
|
||||||
{
|
{
|
||||||
register struct radix_mask *m;
|
struct radix_mask *m;
|
||||||
|
|
||||||
MKGet(m);
|
MKGet(m);
|
||||||
if (m == 0) {
|
if (m == 0) {
|
||||||
@ -519,7 +521,7 @@ rn_addroute(void *v_arg,
|
|||||||
struct radix_node treenodes[2])
|
struct radix_node treenodes[2])
|
||||||
{
|
{
|
||||||
caddr_t v = (caddr_t)v_arg, netmask = (caddr_t)n_arg;
|
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;
|
struct radix_node *saved_tt, *top = head->rnh_treetop;
|
||||||
short b = 0, b_leaf = 0;
|
short b = 0, b_leaf = 0;
|
||||||
int keyduplicated;
|
int keyduplicated;
|
||||||
@ -660,7 +662,7 @@ rn_delete(void *v_arg,
|
|||||||
void *netmask_arg,
|
void *netmask_arg,
|
||||||
struct radix_node_head *head)
|
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_mask *m, *saved_m, **mp;
|
||||||
struct radix_node *dupedkey, *saved_tt, *top;
|
struct radix_node *dupedkey, *saved_tt, *top;
|
||||||
caddr_t v, netmask;
|
caddr_t v, netmask;
|
||||||
@ -781,7 +783,7 @@ rn_delete(void *v_arg,
|
|||||||
m = mm;
|
m = mm;
|
||||||
}
|
}
|
||||||
if (m)
|
if (m)
|
||||||
syslog(LOG_ERR, "%s %lx at %lx\n",
|
syslog(LOG_ERR, "%s 0x%lx at 0x%lx\n",
|
||||||
"rn_delete: Orphaned Mask",
|
"rn_delete: Orphaned Mask",
|
||||||
(unsigned long)m,
|
(unsigned long)m,
|
||||||
(unsigned long)x);
|
(unsigned long)x);
|
||||||
@ -809,12 +811,12 @@ rn_delete(void *v_arg,
|
|||||||
|
|
||||||
int
|
int
|
||||||
rn_walktree(struct radix_node_head *h,
|
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)
|
struct walkarg *w)
|
||||||
{
|
{
|
||||||
int error;
|
int error;
|
||||||
struct radix_node *base, *next;
|
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
|
* This gets complicated because we may delete the node
|
||||||
* while applying the function f to it, so we need to calculate
|
* while applying the function f to it, so we need to calculate
|
||||||
@ -848,13 +850,11 @@ rn_walktree(struct radix_node_head *h,
|
|||||||
int
|
int
|
||||||
rn_inithead(void **head, int off)
|
rn_inithead(void **head, int off)
|
||||||
{
|
{
|
||||||
register struct radix_node_head *rnh;
|
struct radix_node_head *rnh;
|
||||||
register struct radix_node *t, *tt, *ttt;
|
struct radix_node *t, *tt, *ttt;
|
||||||
if (*head)
|
if (*head)
|
||||||
return (1);
|
return (1);
|
||||||
rnh = (struct radix_node_head *)rtmalloc(sizeof (*rnh), "rn_inithead");
|
rnh = (struct radix_node_head *)rtmalloc(sizeof(*rnh), "rn_inithead");
|
||||||
if (rnh == 0)
|
|
||||||
return (0);
|
|
||||||
Bzero(rnh, sizeof (*rnh));
|
Bzero(rnh, sizeof (*rnh));
|
||||||
*head = rnh;
|
*head = rnh;
|
||||||
t = rn_newpair(rn_zeros, off, rnh->rnh_nodes);
|
t = rn_newpair(rn_zeros, off, rnh->rnh_nodes);
|
||||||
@ -884,8 +884,6 @@ rn_init(void)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
rn_zeros = (char *)rtmalloc(3 * max_keylen, "rn_init");
|
rn_zeros = (char *)rtmalloc(3 * max_keylen, "rn_init");
|
||||||
if (rn_zeros == NULL)
|
|
||||||
panic("rn_init");
|
|
||||||
Bzero(rn_zeros, 3 * max_keylen);
|
Bzero(rn_zeros, 3 * max_keylen);
|
||||||
rn_ones = cp = rn_zeros + max_keylen;
|
rn_ones = cp = rn_zeros + max_keylen;
|
||||||
addmask_key = cplim = rn_ones + max_keylen;
|
addmask_key = cplim = rn_ones + max_keylen;
|
||||||
|
@ -11,7 +11,7 @@
|
|||||||
* notice, this list of conditions and the following disclaimer in the
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
* documentation and/or other materials provided with the distribution.
|
* documentation and/or other materials provided with the distribution.
|
||||||
* 3. All advertising materials mentioning features or use of this software
|
* 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
|
* This product includes software developed by the University of
|
||||||
* California, Berkeley and its contributors.
|
* California, Berkeley and its contributors.
|
||||||
* 4. Neither the name of the University nor the names of its contributors
|
* 4. Neither the name of the University nor the names of its contributors
|
||||||
@ -31,6 +31,7 @@
|
|||||||
* SUCH DAMAGE.
|
* SUCH DAMAGE.
|
||||||
*
|
*
|
||||||
* @(#)radix.h 8.2 (Berkeley) 10/31/94
|
* @(#)radix.h 8.2 (Berkeley) 10/31/94
|
||||||
|
*
|
||||||
* $Id$
|
* $Id$
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -103,7 +104,7 @@ extern struct radix_mask {
|
|||||||
m = rn_mkfreelist; \
|
m = rn_mkfreelist; \
|
||||||
rn_mkfreelist = (m)->rm_mklist; \
|
rn_mkfreelist = (m)->rm_mklist; \
|
||||||
} else \
|
} else \
|
||||||
m = (struct radix_mask *)rtmalloc(sizeof (*(m)), "MKGet"); }\
|
m = (struct radix_mask *)rtmalloc(sizeof(*(m)), "MKGet"); }\
|
||||||
|
|
||||||
#define MKFree(m) { (m)->rm_mklist = rn_mkfreelist; rn_mkfreelist = (m);}
|
#define MKFree(m) { (m)->rm_mklist = rn_mkfreelist; rn_mkfreelist = (m);}
|
||||||
|
|
||||||
@ -135,17 +136,18 @@ struct radix_node_head {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
#define Bcmp(a, b, n) bcmp(((char *)(a)), ((char *)(b)), (n))
|
#define Bcmp(a, b, n) memcmp(((void *)(a)), ((void *)(b)), (n))
|
||||||
#define Bcopy(a, b, n) bcopy(((char *)(a)), ((char *)(b)), (unsigned)(n))
|
#define Bcopy(a, b, n) memmove(((void *)(b)), ((void *)(a)), (size_t)(n))
|
||||||
#define Bzero(p, n) bzero((char *)(p), (int)(n));
|
#define Bzero(p, n) memset((void *)(p), 0, (size_t)(n));
|
||||||
#define Free(p) free((char *)p);
|
#define Free(p) free((void *)p);
|
||||||
|
|
||||||
void rn_init __P((void));
|
void rn_init __P((void));
|
||||||
int rn_inithead __P((void **, int));
|
int rn_inithead __P((void **, int));
|
||||||
int rn_refines __P((void *, void *));
|
int rn_refines __P((void *, void *));
|
||||||
int rn_walktree __P((struct radix_node_head *,
|
int rn_walktree __P((struct radix_node_head *,
|
||||||
int (*)__P((struct radix_node *, struct walkarg*)),
|
int (*)__P((struct radix_node *, struct walkarg *)),
|
||||||
struct walkarg*));
|
struct walkarg *));
|
||||||
|
|
||||||
struct radix_node
|
struct radix_node
|
||||||
*rn_addmask __P((void *, int, int)),
|
*rn_addmask __P((void *, int, int)),
|
||||||
*rn_addroute __P((void *, void *, struct radix_node_head *,
|
*rn_addroute __P((void *, void *, struct radix_node_head *,
|
||||||
@ -158,4 +160,6 @@ struct radix_node
|
|||||||
*rn_search __P((void *, struct radix_node *)),
|
*rn_search __P((void *, struct radix_node *)),
|
||||||
*rn_search_m __P((void *, struct radix_node *, void *));
|
*rn_search_m __P((void *, struct radix_node *, void *));
|
||||||
|
|
||||||
|
struct radix_node *rn_lookup __P((void *, void *, struct radix_node_head *));
|
||||||
|
|
||||||
#endif /* __RADIX_H_ */
|
#endif /* __RADIX_H_ */
|
||||||
|
@ -11,7 +11,7 @@
|
|||||||
* notice, this list of conditions and the following disclaimer in the
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
* documentation and/or other materials provided with the distribution.
|
* documentation and/or other materials provided with the distribution.
|
||||||
* 3. All advertising materials mentioning features or use of this software
|
* 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
|
* This product includes software developed by the University of
|
||||||
* California, Berkeley and its contributors.
|
* California, Berkeley and its contributors.
|
||||||
* 4. Neither the name of the University nor the names of its contributors
|
* 4. Neither the name of the University nor the names of its contributors
|
||||||
@ -29,21 +29,22 @@
|
|||||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
* SUCH DAMAGE.
|
* SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* $Id$
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef lint
|
|
||||||
#if 0
|
|
||||||
static char sccsid[] = "@(#)rdisc.c 8.1 (Berkeley) x/y/95";
|
|
||||||
#endif
|
|
||||||
static const char rcsid[] =
|
|
||||||
"$Id$";
|
|
||||||
#endif /* not lint */
|
|
||||||
|
|
||||||
#include "defs.h"
|
#include "defs.h"
|
||||||
#include <netinet/in_systm.h>
|
#include <netinet/in_systm.h>
|
||||||
#include <netinet/ip.h>
|
#include <netinet/ip.h>
|
||||||
#include <netinet/ip_icmp.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 */
|
/* router advertisement ICMP packet */
|
||||||
struct icmp_ad {
|
struct icmp_ad {
|
||||||
u_int8_t icmp_type; /* type of message */
|
u_int8_t icmp_type; /* type of message */
|
||||||
@ -80,7 +81,7 @@ struct timeval rdisc_timer;
|
|||||||
int rdisc_ok; /* using solicited route */
|
int rdisc_ok; /* using solicited route */
|
||||||
|
|
||||||
|
|
||||||
#define MAX_ADS 5
|
#define MAX_ADS 16 /* at least one per interface */
|
||||||
struct dr { /* accumulated advertisements */
|
struct dr { /* accumulated advertisements */
|
||||||
struct interface *dr_ifp;
|
struct interface *dr_ifp;
|
||||||
naddr dr_gate; /* gateway */
|
naddr dr_gate; /* gateway */
|
||||||
@ -90,8 +91,13 @@ struct dr { /* accumulated advertisements */
|
|||||||
n_long dr_pref; /* preference adjusted by metric */
|
n_long dr_pref; /* preference adjusted by metric */
|
||||||
} *cur_drp, drs[MAX_ADS];
|
} *cur_drp, drs[MAX_ADS];
|
||||||
|
|
||||||
/* adjust preference by interface metric without driving it to infinity */
|
/* convert between signed, balanced around zero,
|
||||||
#define PREF(p, ifp) ((p) <= (ifp)->int_metric ? ((p) != 0 ? 1 : 0) \
|
* 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))
|
: (p) - ((ifp)->int_metric))
|
||||||
|
|
||||||
static void rdisc_sort(void);
|
static void rdisc_sort(void);
|
||||||
@ -100,7 +106,7 @@ static void rdisc_sort(void);
|
|||||||
/* dump an ICMP Router Discovery Advertisement Message
|
/* dump an ICMP Router Discovery Advertisement Message
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
trace_rdisc(char *act,
|
trace_rdisc(const char *act,
|
||||||
naddr from,
|
naddr from,
|
||||||
naddr to,
|
naddr to,
|
||||||
struct interface *ifp,
|
struct interface *ifp,
|
||||||
@ -138,7 +144,7 @@ trace_rdisc(char *act,
|
|||||||
trace_act("%s Router Solic. from %s to %s via %s value=%#x",
|
trace_act("%s Router Solic. from %s to %s via %s value=%#x",
|
||||||
act, naddr_ntoa(from), naddr_ntoa(to),
|
act, naddr_ntoa(from), naddr_ntoa(to),
|
||||||
ifp ? ifp->int_name : "?",
|
ifp ? ifp->int_name : "?",
|
||||||
ntohl(p->so.icmp_so_rsvd));
|
(int)ntohl(p->so.icmp_so_rsvd));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -184,7 +190,7 @@ set_rdisc_mg(struct interface *ifp,
|
|||||||
if (ifp->int_if_flags & IFF_POINTOPOINT)
|
if (ifp->int_if_flags & IFF_POINTOPOINT)
|
||||||
return;
|
return;
|
||||||
#endif
|
#endif
|
||||||
bzero(&m, sizeof(m));
|
memset(&m, 0, sizeof(m));
|
||||||
m.imr_interface.s_addr = ((ifp->int_if_flags & IFF_POINTOPOINT)
|
m.imr_interface.s_addr = ((ifp->int_if_flags & IFF_POINTOPOINT)
|
||||||
? ifp->int_dstaddr
|
? ifp->int_dstaddr
|
||||||
: ifp->int_addr);
|
: ifp->int_addr);
|
||||||
@ -297,7 +303,7 @@ rdisc_age(naddr bad_gate)
|
|||||||
|
|
||||||
/* If only advertising, then do only that. */
|
/* If only advertising, then do only that. */
|
||||||
if (supplier) {
|
if (supplier) {
|
||||||
/* if switching from client to server, get rid of old
|
/* If switching from client to server, get rid of old
|
||||||
* default routes.
|
* default routes.
|
||||||
*/
|
*/
|
||||||
if (cur_drp != 0)
|
if (cur_drp != 0)
|
||||||
@ -337,14 +343,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_sol();
|
||||||
|
|
||||||
rdisc_sort();
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -360,10 +369,12 @@ if_bad_rdisc(struct interface *ifp)
|
|||||||
if (drp->dr_ifp != ifp)
|
if (drp->dr_ifp != ifp)
|
||||||
continue;
|
continue;
|
||||||
drp->dr_recv_pref = 0;
|
drp->dr_recv_pref = 0;
|
||||||
|
drp->dr_ts = 0;
|
||||||
drp->dr_life = 0;
|
drp->dr_life = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
rdisc_sort();
|
/* make a note to re-solicit, turn RIP on or off, etc. */
|
||||||
|
rdisc_timer.tv_sec = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -389,10 +400,11 @@ static void
|
|||||||
del_rdisc(struct dr *drp)
|
del_rdisc(struct dr *drp)
|
||||||
{
|
{
|
||||||
struct interface *ifp;
|
struct interface *ifp;
|
||||||
|
naddr gate;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
|
||||||
del_redirects(drp->dr_gate, 0);
|
del_redirects(gate = drp->dr_gate, 0);
|
||||||
drp->dr_ts = 0;
|
drp->dr_ts = 0;
|
||||||
drp->dr_life = 0;
|
drp->dr_life = 0;
|
||||||
|
|
||||||
@ -411,13 +423,21 @@ del_rdisc(struct dr *drp)
|
|||||||
* then solicit a new one.
|
* then solicit a new one.
|
||||||
* This is contrary to RFC 1256, but defends against black holes.
|
* This is contrary to RFC 1256, but defends against black holes.
|
||||||
*/
|
*/
|
||||||
if (i == 0
|
if (i != 0) {
|
||||||
&& ifp->int_rdisc_cnt >= MAX_SOLICITATIONS) {
|
trace_act("discovered router %s via %s"
|
||||||
trace_act("discovered route is bad--re-solicit routers via %s",
|
" is bad--have %d remaining",
|
||||||
ifp->int_name);
|
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_cnt = 0;
|
||||||
ifp->int_rdisc_timer.tv_sec = 0;
|
ifp->int_rdisc_timer.tv_sec = 0;
|
||||||
rdisc_sol();
|
rdisc_sol();
|
||||||
|
} else {
|
||||||
|
trace_act("last discovered router %s via %s"
|
||||||
|
" is bad--wait to solicit",
|
||||||
|
naddr_ntoa(gate), ifp->int_name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -430,9 +450,10 @@ rdisc_sort(void)
|
|||||||
{
|
{
|
||||||
struct dr *drp, *new_drp;
|
struct dr *drp, *new_drp;
|
||||||
struct rt_entry *rt;
|
struct rt_entry *rt;
|
||||||
|
struct rt_spare new;
|
||||||
struct interface *ifp;
|
struct interface *ifp;
|
||||||
u_int new_st;
|
u_int new_st = 0;
|
||||||
n_long new_pref;
|
n_long new_pref = 0;
|
||||||
|
|
||||||
|
|
||||||
/* Find the best discovered route.
|
/* Find the best discovered route.
|
||||||
@ -490,23 +511,20 @@ rdisc_sort(void)
|
|||||||
|
|
||||||
if (rt != 0
|
if (rt != 0
|
||||||
&& (rt->rt_state & RS_RDISC)) {
|
&& (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,
|
rtchange(rt, rt->rt_state & ~RS_RDISC,
|
||||||
rt->rt_gate, rt->rt_router,
|
&new, 0);
|
||||||
HOPCNT_INFINITY, 0, rt->rt_ifp,
|
|
||||||
now.tv_sec - GARBAGE_TIME, 0);
|
|
||||||
rtswitch(rt, 0);
|
rtswitch(rt, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* turn on RIP if permitted */
|
|
||||||
rip_on(0);
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
if (cur_drp == 0) {
|
if (cur_drp == 0) {
|
||||||
trace_act("turn on Router Discovery client"
|
trace_act("turn on Router Discovery client"
|
||||||
" using %s via %s",
|
" using %s via %s",
|
||||||
naddr_ntoa(new_drp->dr_gate),
|
naddr_ntoa(new_drp->dr_gate),
|
||||||
new_drp->dr_ifp->int_name);
|
new_drp->dr_ifp->int_name);
|
||||||
|
|
||||||
rdisc_ok = 1;
|
rdisc_ok = 1;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
@ -518,27 +536,28 @@ rdisc_sort(void)
|
|||||||
new_drp->dr_ifp->int_name);
|
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) {
|
if (rt != 0) {
|
||||||
rtchange(rt, rt->rt_state | RS_RDISC,
|
rtchange(rt, rt->rt_state | RS_RDISC, &new, 0);
|
||||||
new_drp->dr_gate, new_drp->dr_gate,
|
|
||||||
0,0, new_drp->dr_ifp,
|
|
||||||
now.tv_sec, 0);
|
|
||||||
} else {
|
} else {
|
||||||
rtadd(RIP_DEFAULT, 0,
|
rtadd(RIP_DEFAULT, 0, RS_RDISC, &new);
|
||||||
new_drp->dr_gate, new_drp->dr_gate,
|
|
||||||
HOPCNT_INFINITY-1, 0,
|
|
||||||
RS_RDISC, new_drp->dr_ifp);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Now turn off RIP and delete RIP routes,
|
|
||||||
* which might otherwise include the default
|
|
||||||
* we just modified.
|
|
||||||
*/
|
|
||||||
rip_off();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
cur_drp = new_drp;
|
cur_drp = new_drp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* turn RIP on or off */
|
||||||
|
if (!rdisc_ok || rip_interfaces > 1) {
|
||||||
|
rip_on(0);
|
||||||
|
} else {
|
||||||
|
rip_off();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -547,7 +566,7 @@ rdisc_sort(void)
|
|||||||
static void
|
static void
|
||||||
parse_ad(naddr from,
|
parse_ad(naddr from,
|
||||||
naddr gate,
|
naddr gate,
|
||||||
n_long pref,
|
n_long pref, /* signed and in network order */
|
||||||
u_short life,
|
u_short life,
|
||||||
struct interface *ifp)
|
struct interface *ifp)
|
||||||
{
|
{
|
||||||
@ -578,9 +597,9 @@ parse_ad(naddr from,
|
|||||||
/* Convert preference to an unsigned value
|
/* Convert preference to an unsigned value
|
||||||
* and later bias it by the metric of the interface.
|
* 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;
|
pref = 0;
|
||||||
life = 0;
|
life = 0;
|
||||||
}
|
}
|
||||||
@ -671,16 +690,16 @@ static void
|
|||||||
send_rdisc(union ad_u *p,
|
send_rdisc(union ad_u *p,
|
||||||
int p_size,
|
int p_size,
|
||||||
struct interface *ifp,
|
struct interface *ifp,
|
||||||
naddr dst, /* 0 or UNICAST destination */
|
naddr dst, /* 0 or unicast destination */
|
||||||
int type) /* 0=unicast, 1=bcast, 2=mcast */
|
int type) /* 0=unicast, 1=bcast, 2=mcast */
|
||||||
{
|
{
|
||||||
struct sockaddr_in sin;
|
struct sockaddr_in sin;
|
||||||
int flags;
|
int flags;
|
||||||
char *msg;
|
const char *msg;
|
||||||
naddr tgt_mcast;
|
naddr tgt_mcast;
|
||||||
|
|
||||||
|
|
||||||
bzero(&sin, sizeof(sin));
|
memset(&sin, 0, sizeof(sin));
|
||||||
sin.sin_addr.s_addr = dst;
|
sin.sin_addr.s_addr = dst;
|
||||||
sin.sin_family = AF_INET;
|
sin.sin_family = AF_INET;
|
||||||
#ifdef _HAVE_SIN_LEN
|
#ifdef _HAVE_SIN_LEN
|
||||||
@ -689,7 +708,7 @@ send_rdisc(union ad_u *p,
|
|||||||
flags = MSG_DONTROUTE;
|
flags = MSG_DONTROUTE;
|
||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case 0: /* UNICAST */
|
case 0: /* unicast */
|
||||||
default:
|
default:
|
||||||
msg = "Send";
|
msg = "Send";
|
||||||
break;
|
break;
|
||||||
@ -765,23 +784,27 @@ send_rdisc(union ad_u *p,
|
|||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
send_adv(struct interface *ifp,
|
send_adv(struct interface *ifp,
|
||||||
naddr dst, /* 0 or UNICAST destination */
|
naddr dst, /* 0 or unicast destination */
|
||||||
int type) /* 0=unicast, 1=bcast, 2=mcast */
|
int type) /* 0=unicast, 1=bcast, 2=mcast */
|
||||||
{
|
{
|
||||||
union ad_u u;
|
union ad_u u;
|
||||||
n_long pref;
|
n_long pref;
|
||||||
|
|
||||||
|
|
||||||
bzero(&u,sizeof(u.ad));
|
memset(&u, 0, sizeof(u.ad));
|
||||||
|
|
||||||
u.ad.icmp_type = ICMP_ROUTERADVERT;
|
u.ad.icmp_type = ICMP_ROUTERADVERT;
|
||||||
u.ad.icmp_ad_num = 1;
|
u.ad.icmp_ad_num = 1;
|
||||||
u.ad.icmp_ad_asize = sizeof(u.ad.icmp_ad_info[0])/4;
|
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);
|
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;
|
/* Convert the configured preference to an unsigned value,
|
||||||
u.ad.icmp_ad_info[0].icmp_ad_pref = htonl(pref);
|
* 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;
|
u.ad.icmp_ad_info[0].icmp_ad_addr = ifp->int_addr;
|
||||||
|
|
||||||
@ -851,7 +874,7 @@ rdisc_sol(void)
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (!timercmp(&ifp->int_rdisc_timer, &now, >)) {
|
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_type = ICMP_ROUTERSOLICIT;
|
||||||
u.so.icmp_cksum = in_cksum((u_short*)&u.so,
|
u.so.icmp_cksum = in_cksum((u_short*)&u.so,
|
||||||
sizeof(u.so));
|
sizeof(u.so));
|
||||||
@ -875,14 +898,14 @@ rdisc_sol(void)
|
|||||||
|
|
||||||
/* check the IP header of a possible Router Discovery ICMP packet */
|
/* check the IP header of a possible Router Discovery ICMP packet */
|
||||||
static struct interface * /* 0 if bad */
|
static struct interface * /* 0 if bad */
|
||||||
ck_icmp(char *act,
|
ck_icmp(const char *act,
|
||||||
naddr from,
|
naddr from,
|
||||||
struct interface *ifp,
|
struct interface *ifp,
|
||||||
naddr to,
|
naddr to,
|
||||||
union ad_u *p,
|
union ad_u *p,
|
||||||
u_int len)
|
u_int len)
|
||||||
{
|
{
|
||||||
char *type;
|
const char *type;
|
||||||
|
|
||||||
|
|
||||||
if (p->icmp.icmp_type == ICMP_ROUTERADVERT) {
|
if (p->icmp.icmp_type == ICMP_ROUTERADVERT) {
|
||||||
@ -988,7 +1011,7 @@ read_d(void)
|
|||||||
switch (p->icmp.icmp_type) {
|
switch (p->icmp.icmp_type) {
|
||||||
case ICMP_ROUTERADVERT:
|
case ICMP_ROUTERADVERT:
|
||||||
if (p->ad.icmp_ad_asize*4
|
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,
|
msglim(&bad_asize, from.sin_addr.s_addr,
|
||||||
"intolerable rdisc address size=%d",
|
"intolerable rdisc address size=%d",
|
||||||
p->ad.icmp_ad_asize);
|
p->ad.icmp_ad_asize);
|
||||||
@ -998,9 +1021,10 @@ read_d(void)
|
|||||||
trace_pkt(" empty?");
|
trace_pkt(" empty?");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (cc != (sizeof(p->ad) - sizeof(p->ad.icmp_ad_info)
|
if (cc != (int)(sizeof(p->ad)
|
||||||
+ (p->ad.icmp_ad_num
|
- sizeof(p->ad.icmp_ad_info)
|
||||||
* sizeof(p->ad.icmp_ad_info[0])))) {
|
+ (p->ad.icmp_ad_num
|
||||||
|
* sizeof(p->ad.icmp_ad_info[0])))) {
|
||||||
msglim(&bad_len, from.sin_addr.s_addr,
|
msglim(&bad_len, from.sin_addr.s_addr,
|
||||||
"rdisc length %d does not match ad_num"
|
"rdisc length %d does not match ad_num"
|
||||||
" %d", cc, p->ad.icmp_ad_num);
|
" %d", cc, p->ad.icmp_ad_num);
|
||||||
@ -1027,6 +1051,8 @@ read_d(void)
|
|||||||
continue;
|
continue;
|
||||||
if (ifp->int_state & IS_NO_ADV_OUT)
|
if (ifp->int_state & IS_NO_ADV_OUT)
|
||||||
continue;
|
continue;
|
||||||
|
if (stopint)
|
||||||
|
continue;
|
||||||
|
|
||||||
/* XXX
|
/* XXX
|
||||||
* We should handle messages from address 0.
|
* We should handle messages from address 0.
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
.\" $Revision: 2.17 $
|
||||||
|
.\"
|
||||||
.\" Copyright (c) 1983, 1991, 1993
|
.\" Copyright (c) 1983, 1991, 1993
|
||||||
.\" The Regents of the University of California. All rights reserved.
|
.\" The Regents of the University of California. All rights reserved.
|
||||||
.\"
|
.\"
|
||||||
@ -30,17 +32,19 @@
|
|||||||
.\" SUCH DAMAGE.
|
.\" SUCH DAMAGE.
|
||||||
.\"
|
.\"
|
||||||
.\" @(#)routed.8 8.2 (Berkeley) 12/11/93
|
.\" @(#)routed.8 8.2 (Berkeley) 12/11/93
|
||||||
.\" $Id: routed.8,v 1.10 1998/06/17 13:13:41 jkoshy Exp $
|
.\"
|
||||||
|
.\" $Id$
|
||||||
.\"
|
.\"
|
||||||
.Dd June 1, 1996
|
.Dd June 1, 1996
|
||||||
.Dt ROUTED 8
|
.Dt ROUTED 8
|
||||||
.Os BSD 4.4
|
.Os BSD 4.4
|
||||||
.Sh NAME
|
.Sh NAME
|
||||||
.Nm routed
|
.Nm routed ,
|
||||||
|
.Nm rdisc
|
||||||
.Nd network RIP and router discovery routing daemon
|
.Nd network RIP and router discovery routing daemon
|
||||||
.Sh SYNOPSIS
|
.Sh SYNOPSIS
|
||||||
.Nm routed
|
.Nm routed
|
||||||
.Op Fl sqdghmAt
|
.Op Fl sqdghmpAtv
|
||||||
.Op Fl T Ar tracefile
|
.Op Fl T Ar tracefile
|
||||||
.Oo
|
.Oo
|
||||||
.Fl F
|
.Fl F
|
||||||
@ -55,7 +59,9 @@ It uses Routing Information Protocol, RIPv1 (RFC\ 1058),
|
|||||||
RIPv2 (RFC\ 1723),
|
RIPv2 (RFC\ 1723),
|
||||||
and Internet Router Discovery Protocol (RFC 1256)
|
and Internet Router Discovery Protocol (RFC 1256)
|
||||||
to maintain the kernel routing table.
|
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
|
.Pp
|
||||||
It listens on the
|
It listens on the
|
||||||
.Xr udp 4
|
.Xr udp 4
|
||||||
@ -116,7 +122,7 @@ Advertised metrics reflect the metric associated with interface
|
|||||||
so setting the metric on an interface
|
so setting the metric on an interface
|
||||||
is an effective way to steer traffic.
|
is an effective way to steer traffic.
|
||||||
.Pp
|
.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
|
network to implement in part
|
||||||
.Em split-horizon .
|
.Em split-horizon .
|
||||||
Requests from query programs
|
Requests from query programs
|
||||||
@ -152,7 +158,7 @@ If an entry has not been updated for 3 minutes, the entry's metric
|
|||||||
is set to infinity and marked for deletion.
|
is set to infinity and marked for deletion.
|
||||||
Deletions are delayed until the route has been advertised with
|
Deletions are delayed until the route has been advertised with
|
||||||
an infinite metric to insure the invalidation
|
an infinite metric to insure the invalidation
|
||||||
is propagated throughout the local Internet.
|
is propagated throughout the local internet.
|
||||||
This is a form of
|
This is a form of
|
||||||
.Em poison reverse .
|
.Em poison reverse .
|
||||||
.Pp
|
.Pp
|
||||||
@ -180,7 +186,7 @@ support multicasting.
|
|||||||
If no response is received on a remote interface, if there are errors
|
If no response is received on a remote interface, if there are errors
|
||||||
while sending responses,
|
while sending responses,
|
||||||
or if there are more errors than input or output (see
|
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
|
then the cable or some other part of the interface is assumed to be
|
||||||
disconnected or broken, and routes are adjusted appropriately.
|
disconnected or broken, and routes are adjusted appropriately.
|
||||||
.Pp
|
.Pp
|
||||||
@ -189,15 +195,17 @@ The
|
|||||||
is handled similarly.
|
is handled similarly.
|
||||||
When the daemon is supplying RIP routes, it also listens for
|
When the daemon is supplying RIP routes, it also listens for
|
||||||
Router Discovery Solicitations and sends Advertisements.
|
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.
|
sends Solicitations and listens for Advertisements.
|
||||||
If it receives
|
If it receives
|
||||||
a good Advertisement, it stops listening for broadcast or multicast
|
a good Advertisement and it is not multi-homed,
|
||||||
RIP responses.
|
it stops listening for broadcast or multicast RIP responses.
|
||||||
It tracks several advertising routers to speed recovery when the
|
It tracks several advertising routers to speed recovery when the
|
||||||
currently chosen router dies.
|
currently chosen router dies.
|
||||||
If all discovered routers disappear,
|
If all discovered routers disappear,
|
||||||
the daemon resumes listening to RIP responses.
|
the daemon resumes listening to RIP responses.
|
||||||
|
It continues listening to RIP while using Router Discovery
|
||||||
|
if multi-homed to ensure all interfaces are used.
|
||||||
.Pp
|
.Pp
|
||||||
The Router Discovery standard requires that advertisements
|
The Router Discovery standard requires that advertisements
|
||||||
have a default "lifetime" of 30 minutes. That means should
|
have a default "lifetime" of 30 minutes. That means should
|
||||||
@ -217,9 +225,7 @@ is received), there is a single default route and a variable number of
|
|||||||
redirected host routes in the kernel table.
|
redirected host routes in the kernel table.
|
||||||
On a host with more than one network interface,
|
On a host with more than one network interface,
|
||||||
this default route will be via only one of the interfaces.
|
this default route will be via only one of the interfaces.
|
||||||
Thus, multi-homed hosts running with
|
Thus, multi-homed hosts running with \f3\-q\f1 might need
|
||||||
.Fl q
|
|
||||||
might need
|
|
||||||
.Cm no_rdisc
|
.Cm no_rdisc
|
||||||
described below.
|
described below.
|
||||||
.Pp
|
.Pp
|
||||||
@ -238,22 +244,24 @@ to infer the netmask used by the remote system when RIPv1 is used.
|
|||||||
The following options are available:
|
The following options are available:
|
||||||
.Bl -tag -width indent
|
.Bl -tag -width indent
|
||||||
.It Fl s
|
.It Fl s
|
||||||
Force
|
force
|
||||||
.Nm
|
.Nm
|
||||||
to supply routing information.
|
to supply routing information.
|
||||||
This is the default if multiple network interfaces are present on which
|
This is the default if multiple network interfaces are present on which
|
||||||
RIP or Router Discovery have not been disabled, and if the kernel switch
|
RIP or Router Discovery have not been disabled, and if the kernel switch
|
||||||
ipforwarding=1.
|
ipforwarding=1.
|
||||||
.It Fl q
|
.It Fl q
|
||||||
Is the opposite of the
|
is the opposite of the
|
||||||
.Fl s
|
.Fl s
|
||||||
option.
|
option.
|
||||||
This is the default when only one interface is present.
|
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
|
.It Fl d
|
||||||
Do not run in the background.
|
do not run in the background.
|
||||||
This option is meant for interactive use.
|
This option is meant for interactive use.
|
||||||
.It Fl g
|
.It Fl g
|
||||||
Used on internetwork routers to offer a route
|
used on internetwork routers to offer a route
|
||||||
to the "default" destination.
|
to the "default" destination.
|
||||||
It is equivalent to
|
It is equivalent to
|
||||||
.Fl F
|
.Fl F
|
||||||
@ -266,23 +274,23 @@ on the command line or
|
|||||||
in the
|
in the
|
||||||
.Pa /etc/gateways
|
.Pa /etc/gateways
|
||||||
file.
|
file.
|
||||||
Since a larger metric
|
since a larger metric
|
||||||
will be used, reducing the spread of the potentially dangerous
|
will be used, reducing the spread of the potentially dangerous
|
||||||
default route.
|
default route.
|
||||||
This is typically used on a gateway to the Internet,
|
This is typically used on a gateway to the Internet,
|
||||||
or on a gateway that uses another routing protocol whose routes
|
or on a gateway that uses another routing protocol whose routes
|
||||||
are not reported to other local routers.
|
are not reported to other local routers.
|
||||||
Notice that because a metric of 1 is used, this feature is
|
Notice that because a metric of 1 is used, this feature is
|
||||||
dangerous. It is more commonly accidentally used to create chaos with routing
|
dangerous. It is more commonly accidentally used to create chaos with a
|
||||||
loop than to solve problems.
|
routing loop than to solve problems.
|
||||||
.It Fl h
|
.It Fl h
|
||||||
Cause 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.
|
provided there is a network route going the same direction.
|
||||||
That is a limited kind of aggregation.
|
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.
|
machines connected with point-to-point links such as SLIP.
|
||||||
.It Fl m
|
.It Fl m
|
||||||
Cause 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.
|
its primary interface.
|
||||||
It is useful on multi-homed machines such as NFS servers.
|
It is useful on multi-homed machines such as NFS servers.
|
||||||
This option should not be used except when the cost of
|
This option should not be used except when the cost of
|
||||||
@ -296,20 +304,14 @@ option overrides the
|
|||||||
.Fl q
|
.Fl q
|
||||||
option to the limited extent of advertising the host route.
|
option to the limited extent of advertising the host route.
|
||||||
.It Fl A
|
.It Fl A
|
||||||
Do not ignore RIPv2 authentication if we do not care about RIPv2
|
do not ignore RIPv2 authentication if we do not care about RIPv2
|
||||||
authentication.
|
authentication.
|
||||||
This option is required for conformance with RFC 1723.
|
This option is required for conformance with RFC 1723.
|
||||||
However, it makes no sense and breaks using RIP as a discovery protocol
|
However, it makes no sense and breaks using RIP as a discovery protocol
|
||||||
to ignore all RIPv2 packets that carry authentication when this machine
|
to ignore all RIPv2 packets that carry authentication when this machine
|
||||||
does not care about authentication.
|
does not care about authentication.
|
||||||
.It Fl T Ar tracefile
|
|
||||||
Increase 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 t
|
.It Fl t
|
||||||
Increase 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
|
on the tracefile specified with
|
||||||
.Fl T
|
.Fl T
|
||||||
or standard out.
|
or standard out.
|
||||||
@ -321,8 +323,16 @@ or
|
|||||||
signals or with the
|
signals or with the
|
||||||
.Xr rtquery 8
|
.Xr rtquery 8
|
||||||
command.
|
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]
|
.It Fl F Ar net[/mask][,metric]
|
||||||
Minimize routes in transmissions via interfaces with addresses that match
|
minimize routes in transmissions via interfaces with addresses that match
|
||||||
.Em net/mask ,
|
.Em net/mask ,
|
||||||
and synthesizes a default route to this machine with the
|
and synthesizes a default route to this machine with the
|
||||||
.Em metric .
|
.Em metric .
|
||||||
@ -333,7 +343,6 @@ If
|
|||||||
.Em metric
|
.Em metric
|
||||||
is absent, a value of 14 is assumed to limit
|
is absent, a value of 14 is assumed to limit
|
||||||
the spread of the "fake" default route.
|
the spread of the "fake" default route.
|
||||||
|
|
||||||
This is a dangerous feature that when used carelessly can cause routing
|
This is a dangerous feature that when used carelessly can cause routing
|
||||||
loops.
|
loops.
|
||||||
Notice also that more than one interface can match the specified network
|
Notice also that more than one interface can match the specified network
|
||||||
@ -341,7 +350,7 @@ number and mask.
|
|||||||
See also
|
See also
|
||||||
.Fl g .
|
.Fl g .
|
||||||
.It Fl P Ar parms
|
.It Fl P Ar parms
|
||||||
Is equivalent to adding the parameter
|
is equivalent to adding the parameter
|
||||||
line
|
line
|
||||||
.Em parms
|
.Em parms
|
||||||
to the
|
to the
|
||||||
@ -397,10 +406,12 @@ route is restored.
|
|||||||
Such gateways can be useful on media that do not support broadcasts
|
Such gateways can be useful on media that do not support broadcasts
|
||||||
or multicasts but otherwise act like classic shared media like
|
or multicasts but otherwise act like classic shared media like
|
||||||
Ethernets such as some ATM networks.
|
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
|
.Pa /etc/gateways
|
||||||
with a series of
|
with a series of
|
||||||
"host" lines.
|
"host" lines.
|
||||||
|
Note that it is usually desirable to use RIPv2 in such situations
|
||||||
|
to avoid generating lists of inferred host routes.
|
||||||
.Pp
|
.Pp
|
||||||
Gateways marked
|
Gateways marked
|
||||||
.Em external
|
.Em external
|
||||||
@ -409,7 +420,7 @@ routing table nor are they included in routing updates.
|
|||||||
The function of external entries is to indicate
|
The function of external entries is to indicate
|
||||||
that another routing process
|
that another routing process
|
||||||
will install such a route if necessary,
|
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
|
by
|
||||||
.Nm Ns .
|
.Nm Ns .
|
||||||
Such entries are only required when both routers may learn of routes
|
Such entries are only required when both routers may learn of routes
|
||||||
@ -418,7 +429,8 @@ to the same destination.
|
|||||||
The
|
The
|
||||||
.Pa /etc/gateways
|
.Pa /etc/gateways
|
||||||
file is comprised of a series of lines, each in
|
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
|
.Pp
|
||||||
.Bd -ragged
|
.Bd -ragged
|
||||||
.Cm net
|
.Cm net
|
||||||
@ -488,6 +500,15 @@ or whether the gateway is
|
|||||||
.Cm external
|
.Cm external
|
||||||
to the scope of the RIP protocol.
|
to the scope of the RIP protocol.
|
||||||
.Pp
|
.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
|
Lines that start with neither "net" nor "host" must consist of one
|
||||||
or more of the following parameter settings, separated by commas or
|
or more of the following parameter settings, separated by commas or
|
||||||
blanks:
|
blanks:
|
||||||
@ -504,14 +525,21 @@ with mask
|
|||||||
and the supplied metric (default 1).
|
and the supplied metric (default 1).
|
||||||
This is useful for filling "holes" in CIDR allocations.
|
This is useful for filling "holes" in CIDR allocations.
|
||||||
This parameter must appear by itself on a line.
|
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
|
.Pp
|
||||||
Do not use this feature unless necessary. It is dangerous.
|
Do not use this feature unless necessary. It is dangerous.
|
||||||
.It Cm passwd Ns \&= Ns Ar XXX
|
.It Cm ripv1_mask Ns \&= Ns Ar nname/mask1,mask2
|
||||||
specifies a RIPv2 password that will be included on all RIPv2
|
specifies that netmask of the network of which
|
||||||
responses sent and checked on all RIPv2 responses received.
|
.Cm nname/mask1\f1
|
||||||
The password must not contain any blanks, tab characters, commas
|
is
|
||||||
or '#' characters.
|
a subnet should be
|
||||||
.It Cm passwd Ns \&= Ns Ar XXX1[|KeyID[start|stop]]
|
.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
|
specifies a RIPv2 cleartext password that will be included on
|
||||||
all RIPv2 responses sent, and checked on all RIPv2 responses received.
|
all RIPv2 responses sent, and checked on all RIPv2 responses received.
|
||||||
Any blanks, tab characters, commas, or '#', '|', or NULL characters in the
|
Any blanks, tab characters, commas, or '#', '|', or NULL characters in the
|
||||||
@ -533,15 +561,15 @@ recently is used, or unless no passwords are valid yet, in which case
|
|||||||
no password is output.
|
no password is output.
|
||||||
Incoming packets can carry any password that is valid, will
|
Incoming packets can carry any password that is valid, will
|
||||||
be valid within 24 hours, or that was valid within 24 hours.
|
be valid within 24 hours, or that was valid within 24 hours.
|
||||||
.It Cm md5_passwd Ns \&= Ns Ar XXX1|KeyID[start|stop]
|
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.
|
specifies a RIPv2 MD5 password.
|
||||||
Except that a
|
Except that a
|
||||||
.Cm KeyID
|
.Cm KeyID
|
||||||
is required, this keyword is similar to
|
is required, this keyword is similar to
|
||||||
.Cm passwd .
|
.Cm passwd .
|
||||||
To protect the secrets, this parameter setting is valid only in the
|
|
||||||
.Pa /etc/gateways
|
|
||||||
file and only when that file is readable only by UID 0.
|
|
||||||
.It Cm no_ag
|
.It Cm no_ag
|
||||||
turns off aggregation of subnets in RIPv1 and RIPv2 responses.
|
turns off aggregation of subnets in RIPv1 and RIPv2 responses.
|
||||||
.It Cm no_super_ag
|
.It Cm no_super_ag
|
||||||
@ -563,18 +591,21 @@ or
|
|||||||
causes
|
causes
|
||||||
.Nm
|
.Nm
|
||||||
to act as a client router discovery daemon, not advertising.
|
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
|
.It Cm no_ripv1_in
|
||||||
causes RIPv1 received responses to be ignored.
|
causes RIPv1 received responses to be ignored.
|
||||||
.It Cm no_ripv2_in
|
.It Cm no_ripv2_in
|
||||||
causes RIPv2 received responses to be ignored.
|
causes RIPv2 received responses to be ignored.
|
||||||
.It Cm ripv2_out
|
.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.
|
multicast when possible.
|
||||||
.It Cm ripv2
|
.It Cm ripv2
|
||||||
is equivalent to
|
is equivalent to
|
||||||
.Cm no_ripv1_in
|
.Cm no_ripv1_in
|
||||||
and
|
and
|
||||||
.Cm no_ripv1_out .
|
.Cm no_ripv1_out .
|
||||||
|
This enables RIPv2.
|
||||||
.It Cm no_rdisc
|
.It Cm no_rdisc
|
||||||
disables the Internet Router Discovery Protocol.
|
disables the Internet Router Discovery Protocol.
|
||||||
.It Cm no_solicit
|
.It Cm no_solicit
|
||||||
@ -593,8 +624,12 @@ which by default only listen to Router Discovery messages.
|
|||||||
specifies that Router Discovery packets should be broadcast instead of
|
specifies that Router Discovery packets should be broadcast instead of
|
||||||
multicast.
|
multicast.
|
||||||
.It Cm rdisc_pref Ns \&= Ns Ar N
|
.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 .
|
.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
|
.It Cm rdisc_interval Ns \&= Ns Ar N
|
||||||
sets the nominal interval with which Router Discovery Advertisements
|
sets the nominal interval with which Router Discovery Advertisements
|
||||||
are transmitted to N seconds and their lifetime to 3*N.
|
are transmitted to N seconds and their lifetime to 3*N.
|
||||||
@ -612,15 +647,17 @@ Unless modified with
|
|||||||
.Cm fake_default ,
|
.Cm fake_default ,
|
||||||
the default route is broadcast with a metric of 14.
|
the default route is broadcast with a metric of 14.
|
||||||
That serves as a "poor man's router discovery" protocol.
|
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
|
causes RIP packets from that router and other routers named in
|
||||||
other
|
other
|
||||||
.Cm trust_gateway
|
.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
|
.It Cm redirect_ok
|
||||||
causes RIP to allow ICMP Redirect messages when the system is acting
|
causes RIP to allow ICMP Redirect messages when the system is acting
|
||||||
as a router and forwarding packets.
|
as a router and forwarding packets.
|
||||||
Otherwise, ICMP Redirect messages are are overridden.
|
Otherwise, ICMP Redirect messages are overridden.
|
||||||
.El
|
.El
|
||||||
.Pp
|
.Pp
|
||||||
.Sh FILES
|
.Sh FILES
|
||||||
@ -632,15 +669,16 @@ for distant gateways
|
|||||||
.Xr icmp 4 ,
|
.Xr icmp 4 ,
|
||||||
.Xr udp 4 ,
|
.Xr udp 4 ,
|
||||||
.Xr gated 8 ,
|
.Xr gated 8 ,
|
||||||
.Xr rtquery 8
|
.Xr htable 8 ,
|
||||||
|
.Xr rtquery 8 .
|
||||||
.Rs
|
.Rs
|
||||||
.%T Internet Transport Protocols
|
.%T Internet Transport Protocols
|
||||||
.%R XSIS 028112
|
.%R XSIS 028112
|
||||||
.%Q Xerox System Integration Standard
|
.%Q Xerox System Integration Standard
|
||||||
.Re
|
.Re
|
||||||
.Sh BUGS
|
.Sh BUGS
|
||||||
It does not always detect unidirectional failures in network interfaces
|
It does not always detect unidirectional failures in network interfaces,
|
||||||
(e.g., when the output side fails).
|
for example, when the output side fails.
|
||||||
.Sh HISTORY
|
.Sh HISTORY
|
||||||
The
|
The
|
||||||
.Nm
|
.Nm
|
||||||
|
@ -1,10 +1,11 @@
|
|||||||
# From: @(#)Makefile 8.1 (Berkeley) 6/5/93
|
# Make `routed` tools for BSD/OS
|
||||||
|
# $Revision: 2.15 $
|
||||||
# $Id$
|
# $Id$
|
||||||
|
|
||||||
PROG= rtquery
|
PROG= rtquery
|
||||||
MAN8= rtquery.8
|
MAN8= rtquery.8
|
||||||
LDADD+= -lmd
|
LDADD+= -lmd
|
||||||
DPADD+= ${LIBMD}
|
DPADD+= ${LIBMD}
|
||||||
#COPTS= -g -DDEBUG -Wall
|
#COPTS= -g -DDEBUG -W -Wall -Wcast-align -Wcast-qual -Winline -Wpointer-arith -Wnested-externs -Wwrite-strings -Wunused
|
||||||
|
|
||||||
.include <bsd.prog.mk>
|
.include <bsd.prog.mk>
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
.\" $Id: rtquery.8,v 1.7 1997/06/13 20:58:09 max Exp $
|
.\" $Revision: 2.17 $
|
||||||
|
.\" $Id$
|
||||||
|
.\"
|
||||||
.Dd June 1, 1996
|
.Dd June 1, 1996
|
||||||
.Dt RTQUERY 8
|
.Dt RTQUERY 8
|
||||||
.Os BSD 4.4
|
.Os BSD 4.4
|
||||||
@ -6,17 +8,16 @@
|
|||||||
.Nm rtquery
|
.Nm rtquery
|
||||||
.Nd query routing daemons for their routing tables
|
.Nd query routing daemons for their routing tables
|
||||||
.Sh SYNOPSIS
|
.Sh SYNOPSIS
|
||||||
.Nm rtquery
|
.Nm
|
||||||
.Op Fl np1
|
.Op Fl np1
|
||||||
.Op Fl w Ar timeout
|
.Op Fl w Ar timeout
|
||||||
.Op Fl r Ar addr
|
.Op Fl r Ar addr
|
||||||
.Op Fl a Ar secret
|
.Op Fl a Ar secret
|
||||||
.Ar host
|
.Ar host ...
|
||||||
.Ar
|
.br
|
||||||
.Nm rtquery
|
.Nm
|
||||||
.Op Fl t Ar op
|
.Op Fl t Ar op
|
||||||
.Ar host
|
.Ar host ...
|
||||||
.Ar
|
|
||||||
.Sh DESCRIPTION
|
.Sh DESCRIPTION
|
||||||
.Nm Rtquery
|
.Nm Rtquery
|
||||||
is used to query a RIP network routing daemon,
|
is used to query a RIP network routing daemon,
|
||||||
@ -27,7 +28,8 @@ for its routing table by sending a
|
|||||||
.Em request
|
.Em request
|
||||||
or
|
or
|
||||||
.Em poll
|
.Em poll
|
||||||
command. The routing information in any routing
|
command.
|
||||||
|
The routing information in any routing
|
||||||
.Em response
|
.Em response
|
||||||
packets returned is displayed numerically and symbolically.
|
packets returned is displayed numerically and symbolically.
|
||||||
.Pp
|
.Pp
|
||||||
@ -51,82 +53,71 @@ the
|
|||||||
command is preferred over the
|
command is preferred over the
|
||||||
.Em request
|
.Em request
|
||||||
command because the response is not subject to Split Horizon and/or
|
command because the response is not subject to Split Horizon and/or
|
||||||
Poisoned Reverse, and because some versions of
|
Poisoned Reverse, and because some versions of gated do not answer the
|
||||||
.Xr gated 8
|
|
||||||
do not answer
|
|
||||||
the
|
|
||||||
.Em request
|
.Em request
|
||||||
command.
|
command.
|
||||||
.Nm Routed
|
.Xr Routed 8
|
||||||
does not answer the
|
does not answer the
|
||||||
.Em poll
|
.Em poll
|
||||||
command, but
|
command, but recognizes
|
||||||
recognizes
|
.Em requests
|
||||||
.Em request
|
coming from
|
||||||
commands coming from
|
|
||||||
.Nm
|
.Nm
|
||||||
and so answers completely.
|
and so answers completely.
|
||||||
.Pp
|
.Pp
|
||||||
.Nm Rtquery
|
.Nm Rtquery
|
||||||
is also used to turn tracing on or off in
|
is also used to turn tracing on or off in
|
||||||
.Nm routed .
|
.Xr routed 8 .
|
||||||
.Pp
|
.Pp
|
||||||
The following options are available:
|
The following options are available:
|
||||||
.Bl -tag -width indent
|
.Bl -tag -width indent
|
||||||
.It Fl n
|
.It Fl n
|
||||||
Normally network and host numbers are displayed both symbolically
|
displays only the numeric network and host numbers instead of both
|
||||||
and numerically.
|
numeric and symbolic.
|
||||||
The
|
|
||||||
.Fl n
|
|
||||||
option displays only the numeric network and host numbers.
|
|
||||||
.It Fl p
|
.It Fl p
|
||||||
Use the
|
uses the
|
||||||
.Em Poll
|
.Em poll
|
||||||
command to request full routing information from
|
command to request full routing information from
|
||||||
.Xr gated 8 .
|
.Xr gated 8 .
|
||||||
This is an undocumented extension RIP protocol supported only by
|
This is an undocumented extension RIP protocol supported only by
|
||||||
.Xr gated 8 .
|
.Xr gated 8 .
|
||||||
.It Fl 1
|
.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
|
.It Fl w Ar timeout
|
||||||
Change the delay for an answer from each host.
|
changes the delay for an answer from each host.
|
||||||
By default, each host is given 15 seconds to respond.
|
By default, each host is given 15 seconds to respond.
|
||||||
.It Fl r Ar addr
|
.It Fl r Ar addr
|
||||||
Ask about the route to destination
|
asks about the route to destination
|
||||||
.Em addr .
|
.Em addr .
|
||||||
.It Fl a Ar passwd=XXX
|
.It Fl a Ar passwd=XXX
|
||||||
.It Fl a Ar md5_passwd=XXX|KeyID
|
.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
|
.It Fl t Ar op
|
||||||
Change tracing, where
|
changes tracing, where
|
||||||
.Em op
|
.Em op
|
||||||
is one of the following.
|
is one of the following.
|
||||||
Requests from processes not running with UID 0 or on distant networks
|
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.
|
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.
|
is likely to ignore these debugging requests.
|
||||||
.El
|
.El
|
||||||
.Bl -tag -width Ds -offset indent-two
|
.Bl -tag -width Ds -offset indent-two
|
||||||
.It Em on=tracefile
|
.It Em on=tracefile
|
||||||
Turn tracing on into the specified file. That file must usually
|
turns tracing on into the specified file.
|
||||||
have been specified when the daemon was started or be the same
|
That file must usually have been specified when the daemon was
|
||||||
as a fixed name, often
|
started or be the same as a fixed name, often
|
||||||
.Pa /etc/routed.trace .
|
.Pa /etc/routed.trace .
|
||||||
.It Em more
|
.It Em more
|
||||||
Increase the debugging level.
|
increases the debugging level.
|
||||||
.It Em off
|
.It Em off
|
||||||
Turn off tracing.
|
turns off tracing.
|
||||||
.It Em dump
|
.It Em dump
|
||||||
Dump the daemon's routing table to the current tracefile.
|
dumps the daemon's routing table to the current tracefile.
|
||||||
.El
|
.El
|
||||||
.Sh SEE ALSO
|
.Sh SEE ALSO
|
||||||
.Xr gated 8 ,
|
.Xr routed 8 ,
|
||||||
.Xr routed 8
|
.Xr gated 8
|
||||||
.Rs
|
.br
|
||||||
.%T Routing Information Protocol, RIPV1
|
RFC\ 1058 - Routing Information Protocol, RIPv1
|
||||||
.%O RFC1058
|
.br
|
||||||
.Re
|
RFC\ 1723 - Routing Information Protocol, RIPv2
|
||||||
.Rs
|
|
||||||
.%T Routing Information Protocol, RIPv2
|
|
||||||
.%O RFC1723
|
|
||||||
.Re
|
|
||||||
|
@ -11,7 +11,7 @@
|
|||||||
* notice, this list of conditions and the following disclaimer in the
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
* documentation and/or other materials provided with the distribution.
|
* documentation and/or other materials provided with the distribution.
|
||||||
* 3. All advertising materials mentioning features or use of this software
|
* 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
|
* This product includes software developed by the University of
|
||||||
* California, Berkeley and its contributors.
|
* California, Berkeley and its contributors.
|
||||||
* 4. Neither the name of the University nor the names of its contributors
|
* 4. Neither the name of the University nor the names of its contributors
|
||||||
@ -29,50 +29,62 @@
|
|||||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
* SUCH DAMAGE.
|
* SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* $Id$
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef lint
|
char copyright[] =
|
||||||
static const char copyright[] =
|
|
||||||
"@(#) Copyright (c) 1982, 1986, 1993\n\
|
"@(#) Copyright (c) 1982, 1986, 1993\n\
|
||||||
The Regents of the University of California. All rights reserved.\n";
|
The Regents of the University of California. All rights reserved.\n";
|
||||||
#endif /* not lint */
|
|
||||||
|
|
||||||
#ifndef lint
|
|
||||||
#if 0
|
|
||||||
static char sccsid[] = "@(#)query.c 8.1 (Berkeley) 6/5/93";
|
|
||||||
#endif
|
|
||||||
static const char rcsid[] =
|
|
||||||
"$Id: rtquery.c,v 1.8 1998/07/22 05:49:36 phk Exp $";
|
|
||||||
#endif /* not lint */
|
|
||||||
|
|
||||||
|
#include <sys/cdefs.h>
|
||||||
#include <sys/param.h>
|
#include <sys/param.h>
|
||||||
|
#include <sys/protosw.h>
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
#define RIPVERSION RIPv2
|
#define RIPVERSION RIPv2
|
||||||
#include <protocols/routed.h>
|
#include <protocols/routed.h>
|
||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
#include <err.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include <netdb.h>
|
#include <netdb.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <unistd.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <unistd.h>
|
|
||||||
#ifdef sgi
|
#ifdef sgi
|
||||||
#include <strings.h>
|
#include <strings.h>
|
||||||
#include <bstring.h>
|
#include <bstring.h>
|
||||||
#endif
|
#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
|
#ifndef sgi
|
||||||
#define _HAVE_SIN_LEN
|
#define _HAVE_SIN_LEN
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <md5.h>
|
#define MD5_DIGEST_LEN 16
|
||||||
|
typedef struct {
|
||||||
|
u_int32_t state[4]; /* state (ABCD) */
|
||||||
|
u_int32_t count[2]; /* # of bits, modulo 2^64 (LSB 1st) */
|
||||||
|
unsigned char buffer[64]; /* input buffer */
|
||||||
|
} MD5_CTX;
|
||||||
|
extern void MD5Init(MD5_CTX*);
|
||||||
|
extern void MD5Update(MD5_CTX*, u_char*, u_int);
|
||||||
|
extern void MD5Final(u_char[MD5_DIGEST_LEN], MD5_CTX*);
|
||||||
|
|
||||||
|
|
||||||
#define WTIME 15 /* Time to wait for all responses */
|
#define WTIME 15 /* Time to wait for all responses */
|
||||||
#define STIME (250*1000) /* usec to wait for another response */
|
#define STIME (250*1000) /* usec to wait for another response */
|
||||||
|
|
||||||
int s;
|
int soc;
|
||||||
|
|
||||||
|
const char *pgmname;
|
||||||
|
|
||||||
union {
|
union {
|
||||||
struct rip rip;
|
struct rip rip;
|
||||||
@ -99,26 +111,32 @@ u_long keyid;
|
|||||||
|
|
||||||
struct timeval sent; /* when query sent */
|
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 void rip_input(struct sockaddr_in*, int);
|
||||||
static int out(char *);
|
static int out(const char *);
|
||||||
static void trace_loop(char *argv[]);
|
static void trace_loop(char *argv[]) __attribute((__noreturn__));
|
||||||
static void query_loop(char *argv[], int);
|
static void query_loop(char *argv[], int) __attribute((__noreturn__));
|
||||||
static int getnet(char *, struct netinfo *);
|
static int getnet(char *, struct netinfo *);
|
||||||
static u_int std_mask(u_int);
|
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);
|
static void usage(void);
|
||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
main(int argc,
|
main(int argc,
|
||||||
char *argv[])
|
char *argv[])
|
||||||
{
|
{
|
||||||
int ch, bsize;
|
int ch, bsize;
|
||||||
char *p, *options, *value, delim;
|
char *p, *options, *value, delim;
|
||||||
|
const char *result;
|
||||||
|
|
||||||
OMSG.rip_nets[0].n_dst = RIP_DEFAULT;
|
OMSG.rip_nets[0].n_dst = RIP_DEFAULT;
|
||||||
OMSG.rip_nets[0].n_family = RIP_AF_UNSPEC;
|
OMSG.rip_nets[0].n_family = RIP_AF_UNSPEC;
|
||||||
OMSG.rip_nets[0].n_metric = htonl(HOPCNT_INFINITY);
|
OMSG.rip_nets[0].n_metric = htonl(HOPCNT_INFINITY);
|
||||||
|
|
||||||
|
pgmname = argv[0];
|
||||||
while ((ch = getopt(argc, argv, "np1w:r:t:a:")) != -1)
|
while ((ch = getopt(argc, argv, "np1w:r:t:a:")) != -1)
|
||||||
switch (ch) {
|
switch (ch) {
|
||||||
case 'n':
|
case 'n':
|
||||||
@ -150,11 +168,14 @@ main(int argc,
|
|||||||
rflag = getnet(optarg, &OMSG.rip_nets[0]);
|
rflag = getnet(optarg, &OMSG.rip_nets[0]);
|
||||||
if (!rflag) {
|
if (!rflag) {
|
||||||
struct hostent *hp = gethostbyname(optarg);
|
struct hostent *hp = gethostbyname(optarg);
|
||||||
if (hp == 0)
|
if (hp == 0) {
|
||||||
errx(1, "%s: %s",
|
fprintf(stderr, "%s: %s:",
|
||||||
optarg, hstrerror(h_errno));
|
pgmname, optarg);
|
||||||
bcopy(hp->h_addr, &OMSG.rip_nets[0].n_dst,
|
herror(0);
|
||||||
sizeof(OMSG.rip_nets[0].n_dst));
|
exit(1);
|
||||||
|
}
|
||||||
|
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_family = RIP_AF_INET;
|
||||||
OMSG.rip_nets[0].n_mask = -1;
|
OMSG.rip_nets[0].n_mask = -1;
|
||||||
rflag = 1;
|
rflag = 1;
|
||||||
@ -165,47 +186,52 @@ main(int argc,
|
|||||||
trace = 1;
|
trace = 1;
|
||||||
options = optarg;
|
options = optarg;
|
||||||
while (*options != '\0') {
|
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
|
# define TRACE_ON 0
|
||||||
"on",
|
on_str,
|
||||||
# define TRACE_MORE 1
|
# define TRACE_MORE 1
|
||||||
"more",
|
more_str,
|
||||||
# define TRACE_OFF 2
|
# define TRACE_OFF 2
|
||||||
"off",
|
off_str,
|
||||||
# define TRACE_DUMP 3
|
# define TRACE_DUMP 3
|
||||||
"dump",
|
dump_str,
|
||||||
0
|
0
|
||||||
};
|
};
|
||||||
|
result = "";
|
||||||
switch (getsubopt(&options,traceopts,&value)) {
|
switch (getsubopt(&options,traceopts,&value)) {
|
||||||
case TRACE_ON:
|
case TRACE_ON:
|
||||||
OMSG.rip_cmd = RIPCMD_TRACEON;
|
OMSG.rip_cmd = RIPCMD_TRACEON;
|
||||||
if (!value
|
if (!value
|
||||||
|| strlen(value) > MAXPATHLEN)
|
|| strlen(value) > MAXPATHLEN)
|
||||||
usage();
|
usage();
|
||||||
|
result = value;
|
||||||
break;
|
break;
|
||||||
case TRACE_MORE:
|
case TRACE_MORE:
|
||||||
if (value)
|
if (value)
|
||||||
usage();
|
usage();
|
||||||
OMSG.rip_cmd = RIPCMD_TRACEON;
|
OMSG.rip_cmd = RIPCMD_TRACEON;
|
||||||
value = "";
|
|
||||||
break;
|
break;
|
||||||
case TRACE_OFF:
|
case TRACE_OFF:
|
||||||
if (value)
|
if (value)
|
||||||
usage();
|
usage();
|
||||||
OMSG.rip_cmd = RIPCMD_TRACEOFF;
|
OMSG.rip_cmd = RIPCMD_TRACEOFF;
|
||||||
value = "";
|
|
||||||
break;
|
break;
|
||||||
case TRACE_DUMP:
|
case TRACE_DUMP:
|
||||||
if (value)
|
if (value)
|
||||||
usage();
|
usage();
|
||||||
OMSG.rip_cmd = RIPCMD_TRACEON;
|
OMSG.rip_cmd = RIPCMD_TRACEON;
|
||||||
value = "dump/../table";
|
result = "dump/../table";
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
usage();
|
usage();
|
||||||
}
|
}
|
||||||
strcpy((char*)OMSG.rip_tracefile, value);
|
strcpy((char*)OMSG.rip_tracefile, result);
|
||||||
omsg_len += strlen(value) - sizeof(OMSG.ripun);
|
omsg_len += strlen(result) - sizeof(OMSG.ripun);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -222,7 +248,7 @@ main(int argc,
|
|||||||
else
|
else
|
||||||
usage();
|
usage();
|
||||||
if (0 > parse_quote(&p,"|",&delim,
|
if (0 > parse_quote(&p,"|",&delim,
|
||||||
passwd,sizeof(passwd)))
|
passwd, sizeof(passwd)))
|
||||||
usage();
|
usage();
|
||||||
if (auth_type == RIP_AUTH_MD5
|
if (auth_type == RIP_AUTH_MD5
|
||||||
&& delim == '|') {
|
&& delim == '|') {
|
||||||
@ -239,20 +265,26 @@ main(int argc,
|
|||||||
}
|
}
|
||||||
argv += optind;
|
argv += optind;
|
||||||
argc -= optind;
|
argc -= optind;
|
||||||
if ((not_trace && trace) || argc == 0)
|
if (not_trace && trace)
|
||||||
usage();
|
usage();
|
||||||
|
if (argc == 0) {
|
||||||
|
argc = 1;
|
||||||
|
argv = default_argv;
|
||||||
|
}
|
||||||
|
|
||||||
s = socket(AF_INET, SOCK_DGRAM, 0);
|
soc = socket(AF_INET, SOCK_DGRAM, 0);
|
||||||
if (s < 0)
|
if (soc < 0) {
|
||||||
err(2, "socket");
|
perror("socket");
|
||||||
|
exit(2);
|
||||||
|
}
|
||||||
|
|
||||||
/* be prepared to receive a lot of routes */
|
/* be prepared to receive a lot of routes */
|
||||||
for (bsize = 127*1024; ; bsize -= 1024) {
|
for (bsize = 127*1024; ; bsize -= 1024) {
|
||||||
if (setsockopt(s, SOL_SOCKET, SO_RCVBUF,
|
if (setsockopt(soc, SOL_SOCKET, SO_RCVBUF,
|
||||||
&bsize, sizeof(bsize)) == 0)
|
&bsize, sizeof(bsize)) == 0)
|
||||||
break;
|
break;
|
||||||
if (bsize <= 4*1024) {
|
if (bsize <= 4*1024) {
|
||||||
warn("setsockopt SO_RCVBUF");
|
perror("setsockopt SO_RCVBUF");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -261,19 +293,23 @@ main(int argc,
|
|||||||
trace_loop(argv);
|
trace_loop(argv);
|
||||||
else
|
else
|
||||||
query_loop(argv, argc);
|
query_loop(argv, argc);
|
||||||
return(0);
|
|
||||||
/* NOTREACHED */
|
/* NOTREACHED */
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
usage()
|
usage(void)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "%s\n%s\n",
|
fprintf(stderr,
|
||||||
"usage: rtquery [-np1v] [-r addr] [-w timeout] [-a secret] host ...",
|
"usage: rtquery [-np1] [-r tgt_rt] [-w wtime]"
|
||||||
" rtquery [-t op] host ...");
|
" [-a type=passwd] host1 [host2 ...]\n"
|
||||||
|
"\trtquery -t {on=filename|more|off|dump}"
|
||||||
|
" host1 [host2 ...]\n");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* tell the target hosts about tracing
|
/* tell the target hosts about tracing
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
@ -282,8 +318,10 @@ trace_loop(char *argv[])
|
|||||||
struct sockaddr_in myaddr;
|
struct sockaddr_in myaddr;
|
||||||
int res;
|
int res;
|
||||||
|
|
||||||
if (geteuid() != 0)
|
if (geteuid() != 0) {
|
||||||
errx(1, "-t requires UID 0");
|
(void)fprintf(stderr, "-t requires UID 0\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
if (ripv2) {
|
if (ripv2) {
|
||||||
OMSG.rip_vers = RIPv2;
|
OMSG.rip_vers = RIPv2;
|
||||||
@ -291,15 +329,18 @@ trace_loop(char *argv[])
|
|||||||
OMSG.rip_vers = RIPv1;
|
OMSG.rip_vers = RIPv1;
|
||||||
}
|
}
|
||||||
|
|
||||||
bzero(&myaddr, sizeof(myaddr));
|
memset(&myaddr, 0, sizeof(myaddr));
|
||||||
myaddr.sin_family = AF_INET;
|
myaddr.sin_family = AF_INET;
|
||||||
#ifdef _HAVE_SIN_LEN
|
#ifdef _HAVE_SIN_LEN
|
||||||
myaddr.sin_len = sizeof(myaddr);
|
myaddr.sin_len = sizeof(myaddr);
|
||||||
#endif
|
#endif
|
||||||
myaddr.sin_port = htons(IPPORT_RESERVED-1);
|
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)
|
if (errno != EADDRINUSE
|
||||||
err(2, "bind");
|
|| myaddr.sin_port == 0) {
|
||||||
|
perror("bind");
|
||||||
|
exit(2);
|
||||||
|
}
|
||||||
myaddr.sin_port = htons(ntohs(myaddr.sin_port)-1);
|
myaddr.sin_port = htons(ntohs(myaddr.sin_port)-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -339,8 +380,7 @@ query_loop(char *argv[], int argc)
|
|||||||
OMSG.rip_nets[1] = OMSG.rip_nets[0];
|
OMSG.rip_nets[1] = OMSG.rip_nets[0];
|
||||||
NA0.a_family = RIP_AF_AUTH;
|
NA0.a_family = RIP_AF_AUTH;
|
||||||
NA0.a_type = RIP_AUTH_PW;
|
NA0.a_type = RIP_AUTH_PW;
|
||||||
bcopy(passwd, NA0.au.au_pw,
|
memcpy(NA0.au.au_pw, passwd, RIP_AUTH_PW_LEN);
|
||||||
RIP_AUTH_PW_LEN);
|
|
||||||
omsg_len += sizeof(OMSG.rip_nets[0]);
|
omsg_len += sizeof(OMSG.rip_nets[0]);
|
||||||
|
|
||||||
} else if (auth_type == RIP_AUTH_MD5) {
|
} else if (auth_type == RIP_AUTH_MD5) {
|
||||||
@ -348,15 +388,17 @@ query_loop(char *argv[], int argc)
|
|||||||
NA0.a_family = RIP_AF_AUTH;
|
NA0.a_family = RIP_AF_AUTH;
|
||||||
NA0.a_type = RIP_AUTH_MD5;
|
NA0.a_type = RIP_AUTH_MD5;
|
||||||
NA0.au.a_md5.md5_keyid = (int8_t)keyid;
|
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_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_family = RIP_AF_AUTH;
|
||||||
NA2.a_type = 1;
|
NA2.a_type = htons(1);
|
||||||
bcopy(passwd, NA2.au.au_pw, sizeof(NA2.au.au_pw));
|
|
||||||
MD5Init(&md5_ctx);
|
MD5Init(&md5_ctx);
|
||||||
MD5Update(&md5_ctx, (u_char *)&NA0,
|
MD5Update(&md5_ctx,
|
||||||
(char *)(&NA2+1) - (char *)&NA0);
|
(u_char *)&OMSG, cc);
|
||||||
|
MD5Update(&md5_ctx,
|
||||||
|
(u_char *)passwd, RIP_AUTH_MD5_LEN);
|
||||||
MD5Final(NA2.au.au_pw, &md5_ctx);
|
MD5Final(NA2.au.au_pw, &md5_ctx);
|
||||||
omsg_len += 2*sizeof(OMSG.rip_nets[0]);
|
omsg_len += 2*sizeof(OMSG.rip_nets[0]);
|
||||||
}
|
}
|
||||||
@ -370,23 +412,25 @@ query_loop(char *argv[], int argc)
|
|||||||
seen = 0;
|
seen = 0;
|
||||||
while (0 > out(*argv++)) {
|
while (0 > out(*argv++)) {
|
||||||
if (*argv == 0)
|
if (*argv == 0)
|
||||||
exit(1);
|
exit(-1);
|
||||||
answered++;
|
answered++;
|
||||||
}
|
}
|
||||||
|
|
||||||
FD_ZERO(&bits);
|
FD_ZERO(&bits);
|
||||||
for (;;) {
|
for (;;) {
|
||||||
FD_SET(s, &bits);
|
FD_SET(soc, &bits);
|
||||||
delay.tv_sec = 0;
|
delay.tv_sec = 0;
|
||||||
delay.tv_usec = STIME;
|
delay.tv_usec = STIME;
|
||||||
cc = select(s+1, &bits, 0,0, &delay);
|
cc = select(soc+1, &bits, 0,0, &delay);
|
||||||
if (cc > 0) {
|
if (cc > 0) {
|
||||||
fromlen = sizeof(from);
|
fromlen = sizeof(from);
|
||||||
cc = recvfrom(s, imsg_buf.packet,
|
cc = recvfrom(soc, imsg_buf.packet,
|
||||||
sizeof(imsg_buf.packet), 0,
|
sizeof(imsg_buf.packet), 0,
|
||||||
(struct sockaddr *)&from, &fromlen);
|
(struct sockaddr *)&from, &fromlen);
|
||||||
if (cc < 0)
|
if (cc < 0) {
|
||||||
err(1, "recvfrom");
|
perror("recvfrom");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
/* count the distinct responding hosts.
|
/* count the distinct responding hosts.
|
||||||
* You cannot match responding hosts with
|
* You cannot match responding hosts with
|
||||||
* addresses to which queries were transmitted,
|
* addresses to which queries were transmitted,
|
||||||
@ -399,6 +443,11 @@ query_loop(char *argv[], int argc)
|
|||||||
}
|
}
|
||||||
if (sp == 0) {
|
if (sp == 0) {
|
||||||
sp = malloc(sizeof(*sp));
|
sp = malloc(sizeof(*sp));
|
||||||
|
if (sp == 0) {
|
||||||
|
fprintf(stderr,
|
||||||
|
"rtquery: malloc failed\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
sp->addr = from.sin_addr;
|
sp->addr = from.sin_addr;
|
||||||
sp->next = seen;
|
sp->next = seen;
|
||||||
seen = sp;
|
seen = sp;
|
||||||
@ -412,7 +461,8 @@ query_loop(char *argv[], int argc)
|
|||||||
if (cc < 0) {
|
if (cc < 0) {
|
||||||
if (errno == EINTR)
|
if (errno == EINTR)
|
||||||
continue;
|
continue;
|
||||||
err(1, "select");
|
perror("select");
|
||||||
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* After a pause in responses, probe another host.
|
/* After a pause in responses, probe another host.
|
||||||
@ -429,8 +479,10 @@ query_loop(char *argv[], int argc)
|
|||||||
|
|
||||||
/* or until we have waited a long time
|
/* or until we have waited a long time
|
||||||
*/
|
*/
|
||||||
if (gettimeofday(&now, 0) < 0)
|
if (gettimeofday(&now, 0) < 0) {
|
||||||
err(1, "gettimeofday(now)");
|
perror("gettimeofday(now)");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
if (sent.tv_sec + wtime <= now.tv_sec)
|
if (sent.tv_sec + wtime <= now.tv_sec)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -443,17 +495,17 @@ query_loop(char *argv[], int argc)
|
|||||||
/* send to one host
|
/* send to one host
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
out(char *host)
|
out(const char *host)
|
||||||
{
|
{
|
||||||
struct sockaddr_in router;
|
struct sockaddr_in router;
|
||||||
struct hostent *hp;
|
struct hostent *hp;
|
||||||
|
|
||||||
if (gettimeofday(&sent, 0) < 0) {
|
if (gettimeofday(&sent, 0) < 0) {
|
||||||
warn("gettimeofday(sent)");
|
perror("gettimeofday(sent)");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
bzero(&router, sizeof(router));
|
memset(&router, 0, sizeof(router));
|
||||||
router.sin_family = AF_INET;
|
router.sin_family = AF_INET;
|
||||||
#ifdef _HAVE_SIN_LEN
|
#ifdef _HAVE_SIN_LEN
|
||||||
router.sin_len = sizeof(router);
|
router.sin_len = sizeof(router);
|
||||||
@ -464,13 +516,13 @@ out(char *host)
|
|||||||
herror(host);
|
herror(host);
|
||||||
return -1;
|
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);
|
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) {
|
(struct sockaddr *)&router, sizeof(router)) < 0) {
|
||||||
warn("%s", host);
|
perror(host);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -541,8 +593,11 @@ rip_input(struct sockaddr_in *from,
|
|||||||
{
|
{
|
||||||
struct netinfo *n, *lim;
|
struct netinfo *n, *lim;
|
||||||
struct in_addr in;
|
struct in_addr in;
|
||||||
char *name;
|
const char *name;
|
||||||
char net_buf[80];
|
char net_buf[80];
|
||||||
|
u_char hash[RIP_AUTH_MD5_LEN];
|
||||||
|
MD5_CTX md5_ctx;
|
||||||
|
u_char md5_authed = 0;
|
||||||
u_int mask, dmask;
|
u_int mask, dmask;
|
||||||
char *sp;
|
char *sp;
|
||||||
int i;
|
int i;
|
||||||
@ -572,10 +627,10 @@ rip_input(struct sockaddr_in *from,
|
|||||||
(IMSG.rip_vers != RIPv1 && IMSG.rip_vers != RIPv2) ? " ?" : "",
|
(IMSG.rip_vers != RIPv1 && IMSG.rip_vers != RIPv2) ? " ?" : "",
|
||||||
size);
|
size);
|
||||||
if (size > MAXPACKETSIZE) {
|
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",
|
printf(" at least %d bytes too long\n",
|
||||||
size-MAXPACKETSIZE);
|
size-MAXPACKETSIZE);
|
||||||
size = sizeof(imsg_buf) - sizeof(*n);
|
size = (int)sizeof(imsg_buf) - (int)sizeof(*n);
|
||||||
} else {
|
} else {
|
||||||
printf(" %d bytes too long\n",
|
printf(" %d bytes too long\n",
|
||||||
size-MAXPACKETSIZE);
|
size-MAXPACKETSIZE);
|
||||||
@ -657,22 +712,38 @@ rip_input(struct sockaddr_in *from,
|
|||||||
|
|
||||||
if (na->a_type == RIP_AUTH_MD5
|
if (na->a_type == RIP_AUTH_MD5
|
||||||
&& n == IMSG.rip_nets) {
|
&& n == IMSG.rip_nets) {
|
||||||
(void)printf(" MD5 Authentication"
|
(void)printf(" MD5 Auth"
|
||||||
" len=%d KeyID=%d"
|
" len=%d KeyID=%d"
|
||||||
" seqno=%d"
|
" auth_len=%d"
|
||||||
|
" seqno=%#x"
|
||||||
" rsvd=%#x,%#x\n",
|
" 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_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[0],
|
||||||
na->au.a_md5.rsvd[1]);
|
na->au.a_md5.rsvd[1]);
|
||||||
|
md5_authed = 1;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
(void)printf(" Authentication type %d: ",
|
(void)printf(" Authentication type %d: ",
|
||||||
ntohs(na->a_type));
|
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]);
|
(void)printf("%02x ", na->au.au_pw[i]);
|
||||||
putc('\n', stdout);
|
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;
|
continue;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
@ -685,7 +756,7 @@ rip_input(struct sockaddr_in *from,
|
|||||||
}
|
}
|
||||||
|
|
||||||
(void)printf(" %-18s metric %2d %-10s",
|
(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) {
|
if (n->n_nhop != 0) {
|
||||||
in.s_addr = n->n_nhop;
|
in.s_addr = n->n_nhop;
|
||||||
@ -740,11 +811,11 @@ getnet(char *name,
|
|||||||
|
|
||||||
/* Detect and separate "1.2.3.4/24"
|
/* Detect and separate "1.2.3.4/24"
|
||||||
*/
|
*/
|
||||||
if (0 != (mname = rindex(name,'/'))) {
|
if (0 != (mname = strrchr(name,'/'))) {
|
||||||
i = (int)(mname - name);
|
i = (int)(mname - name);
|
||||||
if (i > sizeof(hname)-1) /* name too long */
|
if (i > (int)sizeof(hname)-1) /* name too long */
|
||||||
return 0;
|
return 0;
|
||||||
bcopy(name, hname, i);
|
memmove(hname, name, i);
|
||||||
hname[i] = '\0';
|
hname[i] = '\0';
|
||||||
mname++;
|
mname++;
|
||||||
name = hname;
|
name = hname;
|
||||||
@ -781,12 +852,13 @@ getnet(char *name,
|
|||||||
*/
|
*/
|
||||||
static int /* -1=bad */
|
static int /* -1=bad */
|
||||||
parse_quote(char **linep,
|
parse_quote(char **linep,
|
||||||
char *delims,
|
const char *delims,
|
||||||
char *delimp,
|
char *delimp,
|
||||||
char *buf,
|
char *buf,
|
||||||
int lim)
|
int lim)
|
||||||
{
|
{
|
||||||
char c, *pc, *p;
|
char c, *pc;
|
||||||
|
const char *p;
|
||||||
|
|
||||||
|
|
||||||
pc = *linep;
|
pc = *linep;
|
||||||
|
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
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
* documentation and/or other materials provided with the distribution.
|
* documentation and/or other materials provided with the distribution.
|
||||||
* 3. All advertising materials mentioning features or use of this software
|
* 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
|
* This product includes software developed by the University of
|
||||||
* California, Berkeley and its contributors.
|
* California, Berkeley and its contributors.
|
||||||
* 4. Neither the name of the University nor the names of its contributors
|
* 4. Neither the name of the University nor the names of its contributors
|
||||||
@ -29,22 +29,25 @@
|
|||||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
* SUCH DAMAGE.
|
* SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* $Id$
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef lint
|
|
||||||
#if 0
|
|
||||||
static char sccsid[] = "@(#)trace.c 8.1 (Berkeley) 6/5/93";
|
|
||||||
#endif
|
|
||||||
static const char rcsid[] =
|
|
||||||
"$Id$";
|
|
||||||
#endif /* not lint */
|
|
||||||
|
|
||||||
#define RIPCMDS
|
#define RIPCMDS
|
||||||
#include "defs.h"
|
#include "defs.h"
|
||||||
#include "pathnames.h"
|
#include "pathnames.h"
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
#include <sys/signal.h>
|
||||||
#include <fcntl.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
|
#ifdef sgi
|
||||||
/* use *stat64 for files on large filesystems */
|
/* use *stat64 for files on large filesystems */
|
||||||
#define stat stat64
|
#define stat stat64
|
||||||
@ -54,12 +57,13 @@ static const char rcsid[] =
|
|||||||
|
|
||||||
int tracelevel, new_tracelevel;
|
int tracelevel, new_tracelevel;
|
||||||
FILE *ftrace = stdout; /* output trace file */
|
FILE *ftrace = stdout; /* output trace file */
|
||||||
static char *sigtrace_pat = "%s\n";
|
static const char *sigtrace_pat = "%s";
|
||||||
static char savetracename[MAXPATHLEN+1];
|
static char savetracename[MAXPATHLEN+1];
|
||||||
char inittracename[MAXPATHLEN+1];
|
char inittracename[MAXPATHLEN+1];
|
||||||
int file_trace; /* 1=tracing to file, not stdout */
|
int file_trace; /* 1=tracing to file, not stdout */
|
||||||
|
|
||||||
static void trace_dump(void);
|
static void trace_dump(void);
|
||||||
|
static void tmsg(const char *, ...) PATTRIB(1,2);
|
||||||
|
|
||||||
|
|
||||||
/* convert string to printable characters
|
/* convert string to printable characters
|
||||||
@ -136,7 +140,7 @@ naddr_ntoa(naddr a)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
char *
|
const char *
|
||||||
saddr_ntoa(struct sockaddr *sa)
|
saddr_ntoa(struct sockaddr *sa)
|
||||||
{
|
{
|
||||||
return (sa == 0) ? "?" : naddr_ntoa(S_ADDR(sa));
|
return (sa == 0) ? "?" : naddr_ntoa(S_ADDR(sa));
|
||||||
@ -151,7 +155,7 @@ ts(time_t secs) {
|
|||||||
#ifdef sgi
|
#ifdef sgi
|
||||||
(void)cftime(s, "%T", &secs);
|
(void)cftime(s, "%T", &secs);
|
||||||
#else
|
#else
|
||||||
bcopy(ctime(&secs)+11, s, 8);
|
memcpy(s, ctime(&secs)+11, 8);
|
||||||
s[8] = '\0';
|
s[8] = '\0';
|
||||||
#endif
|
#endif
|
||||||
return s;
|
return s;
|
||||||
@ -176,7 +180,7 @@ lastlog(void)
|
|||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
tmsg(char *p, ...)
|
tmsg(const char *p, ...)
|
||||||
{
|
{
|
||||||
va_list args;
|
va_list args;
|
||||||
|
|
||||||
@ -184,13 +188,14 @@ tmsg(char *p, ...)
|
|||||||
lastlog();
|
lastlog();
|
||||||
va_start(args, p);
|
va_start(args, p);
|
||||||
vfprintf(ftrace, p, args);
|
vfprintf(ftrace, p, args);
|
||||||
|
(void)fputc('\n',ftrace);
|
||||||
fflush(ftrace);
|
fflush(ftrace);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
void
|
||||||
trace_close(void)
|
trace_close(int zap_stdio)
|
||||||
{
|
{
|
||||||
int fd;
|
int fd;
|
||||||
|
|
||||||
@ -198,14 +203,17 @@ trace_close(void)
|
|||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
fflush(stderr);
|
fflush(stderr);
|
||||||
|
|
||||||
if (ftrace != 0 && file_trace) {
|
if (ftrace != 0 && zap_stdio) {
|
||||||
if (ftrace != stdout)
|
if (ftrace != stdout)
|
||||||
fclose(ftrace);
|
fclose(ftrace);
|
||||||
ftrace = 0;
|
ftrace = 0;
|
||||||
fd = open(_PATH_DEVNULL, O_RDWR);
|
fd = open(_PATH_DEVNULL, O_RDWR);
|
||||||
(void)dup2(fd, STDIN_FILENO);
|
if (isatty(STDIN_FILENO))
|
||||||
(void)dup2(fd, STDOUT_FILENO);
|
(void)dup2(fd, STDIN_FILENO);
|
||||||
(void)dup2(fd, STDERR_FILENO);
|
if (isatty(STDOUT_FILENO))
|
||||||
|
(void)dup2(fd, STDOUT_FILENO);
|
||||||
|
if (isatty(STDERR_FILENO))
|
||||||
|
(void)dup2(fd, STDERR_FILENO);
|
||||||
(void)close(fd);
|
(void)close(fd);
|
||||||
}
|
}
|
||||||
lastlog_time.tv_sec = 0;
|
lastlog_time.tv_sec = 0;
|
||||||
@ -218,13 +226,13 @@ trace_flush(void)
|
|||||||
if (ftrace != 0) {
|
if (ftrace != 0) {
|
||||||
fflush(ftrace);
|
fflush(ftrace);
|
||||||
if (ferror(ftrace))
|
if (ferror(ftrace))
|
||||||
trace_off("tracing off: ", strerror(ferror(ftrace)));
|
trace_off("tracing off: %s", strerror(ferror(ftrace)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
trace_off(char *p, ...)
|
trace_off(const char *p, ...)
|
||||||
{
|
{
|
||||||
va_list args;
|
va_list args;
|
||||||
|
|
||||||
@ -233,8 +241,9 @@ trace_off(char *p, ...)
|
|||||||
lastlog();
|
lastlog();
|
||||||
va_start(args, p);
|
va_start(args, p);
|
||||||
vfprintf(ftrace, p, args);
|
vfprintf(ftrace, p, args);
|
||||||
|
(void)fputc('\n',ftrace);
|
||||||
}
|
}
|
||||||
trace_close();
|
trace_close(file_trace);
|
||||||
|
|
||||||
new_tracelevel = tracelevel = 0;
|
new_tracelevel = tracelevel = 0;
|
||||||
}
|
}
|
||||||
@ -243,16 +252,16 @@ trace_off(char *p, ...)
|
|||||||
/* log a change in tracing
|
/* log a change in tracing
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
tracelevel_msg(char *pat,
|
tracelevel_msg(const char *pat,
|
||||||
int dump) /* -1=no dump, 0=default, 1=force */
|
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 actions stopped",
|
||||||
"Tracing packets stopped",
|
"Tracing packets stopped",
|
||||||
"Tracing packet contents stopped",
|
"Tracing packet contents stopped",
|
||||||
"Tracing kernel changes stopped",
|
"Tracing kernel changes stopped",
|
||||||
};
|
};
|
||||||
static char *on_msgs[MAX_TRACELEVEL] = {
|
static const char *on_msgs[MAX_TRACELEVEL] = {
|
||||||
"Tracing actions started",
|
"Tracing actions started",
|
||||||
"Tracing packets started",
|
"Tracing packets started",
|
||||||
"Tracing packet contents started",
|
"Tracing packet contents started",
|
||||||
@ -287,13 +296,13 @@ tracelevel_msg(char *pat,
|
|||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
set_tracefile(char *filename,
|
set_tracefile(const char *filename,
|
||||||
char *pat,
|
const char *pat,
|
||||||
int dump) /* -1=no dump, 0=default, 1=force */
|
int dump) /* -1=no dump, 0=default, 1=force */
|
||||||
{
|
{
|
||||||
struct stat stbuf;
|
struct stat stbuf;
|
||||||
FILE *n_ftrace;
|
FILE *n_ftrace;
|
||||||
char *fn;
|
const char *fn;
|
||||||
|
|
||||||
|
|
||||||
/* Allow a null filename to increase the level if the trace file
|
/* Allow a null filename to increase the level if the trace file
|
||||||
@ -335,8 +344,7 @@ set_tracefile(char *filename,
|
|||||||
|
|
||||||
/* If the new tracefile exists, it must be a regular file.
|
/* If the new tracefile exists, it must be a regular file.
|
||||||
*/
|
*/
|
||||||
if (stat(filename, &stbuf) >= 0
|
if (stat(filename, &stbuf) >= 0 && !S_ISREG(stbuf.st_mode)) {
|
||||||
&& (stbuf.st_mode & S_IFMT) != S_IFREG) {
|
|
||||||
msglog("wrong type (%#x) of trace file \"%s\"",
|
msglog("wrong type (%#x) of trace file \"%s\"",
|
||||||
stbuf.st_mode, filename);
|
stbuf.st_mode, filename);
|
||||||
return;
|
return;
|
||||||
@ -355,10 +363,9 @@ set_tracefile(char *filename,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
tmsg("switch to trace file %s\n", fn);
|
tmsg("switch to trace file %s", fn);
|
||||||
|
|
||||||
file_trace = 1;
|
trace_close(file_trace = 1);
|
||||||
trace_close();
|
|
||||||
|
|
||||||
if (fn != savetracename)
|
if (fn != savetracename)
|
||||||
strncpy(savetracename, fn, sizeof(savetracename)-1);
|
strncpy(savetracename, fn, sizeof(savetracename)-1);
|
||||||
@ -378,19 +385,19 @@ set_tracefile(char *filename,
|
|||||||
|
|
||||||
/* ARGSUSED */
|
/* ARGSUSED */
|
||||||
void
|
void
|
||||||
sigtrace_on(int s)
|
sigtrace_on(int s UNUSED)
|
||||||
{
|
{
|
||||||
new_tracelevel++;
|
new_tracelevel++;
|
||||||
sigtrace_pat = "SIGUSR1: %s\n";
|
sigtrace_pat = "SIGUSR1: %s";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* ARGSUSED */
|
/* ARGSUSED */
|
||||||
void
|
void
|
||||||
sigtrace_off(int s)
|
sigtrace_off(int s UNUSED)
|
||||||
{
|
{
|
||||||
new_tracelevel--;
|
new_tracelevel--;
|
||||||
sigtrace_pat = "SIGUSR2: %s\n";
|
sigtrace_pat = "SIGUSR2: %s";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -461,9 +468,9 @@ addrname(naddr addr, /* in network byte order */
|
|||||||
/* display a bit-field
|
/* display a bit-field
|
||||||
*/
|
*/
|
||||||
struct bits {
|
struct bits {
|
||||||
int bits_mask;
|
u_int bits_mask;
|
||||||
int bits_clear;
|
u_int bits_clear;
|
||||||
char *bits_name;
|
const char *bits_name;
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct bits if_bits[] = {
|
static struct bits if_bits[] = {
|
||||||
@ -530,11 +537,11 @@ static struct bits rs_bits[] = {
|
|||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
trace_bits(struct bits *tbl,
|
trace_bits(const struct bits *tbl,
|
||||||
u_int field,
|
u_int field,
|
||||||
int force)
|
int force)
|
||||||
{
|
{
|
||||||
int b;
|
u_int b;
|
||||||
char c;
|
char c;
|
||||||
|
|
||||||
if (force) {
|
if (force) {
|
||||||
@ -570,17 +577,17 @@ trace_bits(struct bits *tbl,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static char *
|
char *
|
||||||
trace_pair(naddr dst,
|
rtname(naddr dst,
|
||||||
naddr mask,
|
naddr mask,
|
||||||
char *gate)
|
naddr gate)
|
||||||
{
|
{
|
||||||
static char buf[3*4+3+1+2+3 /* "xxx.xxx.xxx.xxx/xx-->" */
|
static char buf[3*4+3+1+2+3 /* "xxx.xxx.xxx.xxx/xx-->" */
|
||||||
+3*4+3+1]; /* "xxx.xxx.xxx.xxx" */
|
+3*4+3+1]; /* "xxx.xxx.xxx.xxx" */
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
i = sprintf(buf, "%-16s-->", addrname(dst, mask, 0));
|
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;
|
return buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -593,6 +600,9 @@ print_rts(struct rt_spare *rts,
|
|||||||
int force_tag, /* -1=suppress, 0=default, 1=display */
|
int force_tag, /* -1=suppress, 0=default, 1=display */
|
||||||
int force_time) /* 0=suppress, 1=display */
|
int force_time) /* 0=suppress, 1=display */
|
||||||
{
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
|
||||||
if (force_metric >= 0)
|
if (force_metric >= 0)
|
||||||
(void)fprintf(ftrace, "metric=%-2d ", rts->rts_metric);
|
(void)fprintf(ftrace, "metric=%-2d ", rts->rts_metric);
|
||||||
if (force_ifp >= 0)
|
if (force_ifp >= 0)
|
||||||
@ -606,14 +616,19 @@ print_rts(struct rt_spare *rts,
|
|||||||
(void)fprintf(ftrace, "%s ", ts(rts->rts_time));
|
(void)fprintf(ftrace, "%s ", ts(rts->rts_time));
|
||||||
if (force_tag > 0
|
if (force_tag > 0
|
||||||
|| (force_tag == 0 && rts->rts_tag != 0))
|
|| (force_tag == 0 && rts->rts_tag != 0))
|
||||||
(void)fprintf(ftrace, "tag=%#x ",
|
(void)fprintf(ftrace, "tag=%#x ", ntohs(rts->rts_tag));
|
||||||
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
|
void
|
||||||
trace_if(char *act,
|
trace_if(const char *act,
|
||||||
struct interface *ifp)
|
struct interface *ifp)
|
||||||
{
|
{
|
||||||
if (!TRACEACTIONS || ftrace == 0)
|
if (!TRACEACTIONS || ftrace == 0)
|
||||||
return;
|
return;
|
||||||
@ -640,85 +655,82 @@ trace_if(char *act,
|
|||||||
void
|
void
|
||||||
trace_upslot(struct rt_entry *rt,
|
trace_upslot(struct rt_entry *rt,
|
||||||
struct rt_spare *rts,
|
struct rt_spare *rts,
|
||||||
naddr gate,
|
struct rt_spare *new)
|
||||||
naddr router,
|
|
||||||
struct interface *ifp,
|
|
||||||
int metric,
|
|
||||||
u_short tag,
|
|
||||||
time_t new_time)
|
|
||||||
{
|
{
|
||||||
struct rt_spare new;
|
|
||||||
|
|
||||||
if (!TRACEACTIONS || ftrace == 0)
|
if (!TRACEACTIONS || ftrace == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (rts->rts_gate == gate
|
if (rts->rts_gate == new->rts_gate
|
||||||
&& rts->rts_router == router
|
&& rts->rts_router == new->rts_router
|
||||||
&& rts->rts_metric == metric
|
&& rts->rts_metric == new->rts_metric
|
||||||
&& rts->rts_tag == tag)
|
&& rts->rts_tag == new->rts_tag
|
||||||
|
&& rts->rts_de_ag == new->rts_de_ag)
|
||||||
return;
|
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();
|
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 ",
|
(void)fprintf(ftrace, "Chg #%d %-35s ",
|
||||||
rts - rt->rt_spares,
|
(int)(rts - rt->rt_spares),
|
||||||
trace_pair(rt->rt_dst, rt->rt_mask,
|
rtname(rt->rt_dst, rt->rt_mask, rts->rts_gate));
|
||||||
naddr_ntoa(rts->rts_gate)));
|
|
||||||
print_rts(rts, 0,0,
|
print_rts(rts, 0,0,
|
||||||
rts->rts_gate != gate,
|
rts->rts_gate != new->rts_gate,
|
||||||
rts->rts_tag != tag,
|
rts->rts_tag != new->rts_tag,
|
||||||
rts != rt->rt_spares || AGE_RT(rt->rt_state,
|
rts != rt->rt_spares || AGE_RT(rt->rt_state,
|
||||||
rt->rt_ifp));
|
rt->rt_ifp));
|
||||||
|
|
||||||
(void)fprintf(ftrace, "\n %19s%-16s ", "",
|
(void)fprintf(ftrace, "\n %19s%-16s ", "",
|
||||||
gate != rts->rts_gate ? naddr_ntoa(gate) : "");
|
(new->rts_gate != rts->rts_gate
|
||||||
print_rts(&new,
|
? naddr_ntoa(new->rts_gate) : ""));
|
||||||
-(metric == rts->rts_metric),
|
print_rts(new,
|
||||||
-(ifp == rts->rts_ifp),
|
-(new->rts_metric == rts->rts_metric),
|
||||||
|
-(new->rts_ifp == rts->rts_ifp),
|
||||||
0,
|
0,
|
||||||
rts->rts_tag != tag,
|
rts->rts_tag != new->rts_tag,
|
||||||
new_time != rts->rts_time && (rts != rt->rt_spares
|
(new->rts_time != rts->rts_time
|
||||||
|| AGE_RT(rt->rt_state,
|
&& (rts != rt->rt_spares
|
||||||
ifp)));
|
|| AGE_RT(rt->rt_state, new->rts_ifp))));
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
(void)fprintf(ftrace, "Add #%d %-35s ",
|
(void)fprintf(ftrace, "Add #%d %-35s ",
|
||||||
rts - rt->rt_spares,
|
(int)(rts - rt->rt_spares),
|
||||||
trace_pair(rt->rt_dst, rt->rt_mask,
|
rtname(rt->rt_dst, rt->rt_mask, new->rts_gate));
|
||||||
naddr_ntoa(gate)));
|
print_rts(new, 0,0,0,0,
|
||||||
print_rts(&new, 0,0,0,0,
|
(rts != rt->rt_spares
|
||||||
rts != rt->rt_spares || AGE_RT(rt->rt_state,ifp));
|
|| AGE_RT(rt->rt_state,new->rts_ifp)));
|
||||||
}
|
}
|
||||||
(void)fputc('\n',ftrace);
|
(void)fputc('\n',ftrace);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* talk about a change made to the kernel table
|
/* miscellaneous message checked by the caller
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
trace_kernel(char *p, ...)
|
trace_misc(const char *p, ...)
|
||||||
{
|
{
|
||||||
va_list args;
|
va_list args;
|
||||||
|
|
||||||
if (!TRACEKERNEL || ftrace == 0)
|
if (ftrace == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
lastlog();
|
lastlog();
|
||||||
va_start(args, p);
|
va_start(args, p);
|
||||||
vfprintf(ftrace, p, args);
|
vfprintf(ftrace, p, args);
|
||||||
|
(void)fputc('\n',ftrace);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* display a message if tracing actions
|
/* display a message if tracing actions
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
trace_act(char *p, ...)
|
trace_act(const char *p, ...)
|
||||||
{
|
{
|
||||||
va_list args;
|
va_list args;
|
||||||
|
|
||||||
@ -735,7 +747,7 @@ trace_act(char *p, ...)
|
|||||||
/* display a message if tracing packets
|
/* display a message if tracing packets
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
trace_pkt(char *p, ...)
|
trace_pkt(const char *p, ...)
|
||||||
{
|
{
|
||||||
va_list args;
|
va_list args;
|
||||||
|
|
||||||
@ -752,50 +764,39 @@ trace_pkt(char *p, ...)
|
|||||||
void
|
void
|
||||||
trace_change(struct rt_entry *rt,
|
trace_change(struct rt_entry *rt,
|
||||||
u_int state,
|
u_int state,
|
||||||
naddr gate, /* forward packets here */
|
struct rt_spare *new,
|
||||||
naddr router, /* on the authority of this router */
|
const char *label)
|
||||||
int metric,
|
|
||||||
u_short tag,
|
|
||||||
struct interface *ifp,
|
|
||||||
time_t new_time,
|
|
||||||
char *label)
|
|
||||||
{
|
{
|
||||||
struct rt_spare new;
|
|
||||||
|
|
||||||
if (ftrace == 0)
|
if (ftrace == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (rt->rt_metric == metric
|
if (rt->rt_metric == new->rts_metric
|
||||||
&& rt->rt_gate == gate
|
&& rt->rt_gate == new->rts_gate
|
||||||
&& rt->rt_router == router
|
&& rt->rt_router == new->rts_router
|
||||||
&& rt->rt_state == state
|
&& rt->rt_state == state
|
||||||
&& rt->rt_tag == tag)
|
&& rt->rt_tag == new->rts_tag
|
||||||
|
&& rt->rt_de_ag == new->rts_de_ag)
|
||||||
return;
|
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();
|
lastlog();
|
||||||
(void)fprintf(ftrace, "%s %-35s ",
|
(void)fprintf(ftrace, "%s %-35s ",
|
||||||
label,
|
label,
|
||||||
trace_pair(rt->rt_dst, rt->rt_mask,
|
rtname(rt->rt_dst, rt->rt_mask, rt->rt_gate));
|
||||||
naddr_ntoa(rt->rt_gate)));
|
|
||||||
print_rts(rt->rt_spares,
|
print_rts(rt->rt_spares,
|
||||||
0,0,0,0, AGE_RT(rt->rt_state, rt->rt_ifp));
|
0,0,0,0, AGE_RT(rt->rt_state, rt->rt_ifp));
|
||||||
trace_bits(rs_bits, rt->rt_state, rt->rt_state != state);
|
trace_bits(rs_bits, rt->rt_state, rt->rt_state != state);
|
||||||
|
|
||||||
(void)fprintf(ftrace, "\n%*s %19s%-16s ",
|
(void)fprintf(ftrace, "\n%*s %19s%-16s ",
|
||||||
strlen(label), "", "",
|
(int)strlen(label), "", "",
|
||||||
rt->rt_gate != gate ? naddr_ntoa(gate) : "");
|
(rt->rt_gate != new->rts_gate
|
||||||
print_rts(&new,
|
? naddr_ntoa(new->rts_gate) : ""));
|
||||||
-(metric == rt->rt_metric),
|
print_rts(new,
|
||||||
-(ifp == rt->rt_ifp),
|
-(new->rts_metric == rt->rt_metric),
|
||||||
|
-(new->rts_ifp == rt->rt_ifp),
|
||||||
0,
|
0,
|
||||||
rt->rt_tag != tag,
|
rt->rt_tag != new->rts_tag,
|
||||||
rt->rt_time != new_time && AGE_RT(rt->rt_state,ifp));
|
(rt->rt_time != new->rts_time
|
||||||
|
&& AGE_RT(rt->rt_state,new->rts_ifp)));
|
||||||
if (rt->rt_state != state)
|
if (rt->rt_state != state)
|
||||||
trace_bits(rs_bits, state, 1);
|
trace_bits(rs_bits, state, 1);
|
||||||
(void)fputc('\n',ftrace);
|
(void)fputc('\n',ftrace);
|
||||||
@ -803,7 +804,7 @@ trace_change(struct rt_entry *rt,
|
|||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
trace_add_del(char * action, struct rt_entry *rt)
|
trace_add_del(const char * action, struct rt_entry *rt)
|
||||||
{
|
{
|
||||||
if (ftrace == 0)
|
if (ftrace == 0)
|
||||||
return;
|
return;
|
||||||
@ -811,8 +812,7 @@ trace_add_del(char * action, struct rt_entry *rt)
|
|||||||
lastlog();
|
lastlog();
|
||||||
(void)fprintf(ftrace, "%s %-35s ",
|
(void)fprintf(ftrace, "%s %-35s ",
|
||||||
action,
|
action,
|
||||||
trace_pair(rt->rt_dst, rt->rt_mask,
|
rtname(rt->rt_dst, rt->rt_mask, rt->rt_gate));
|
||||||
naddr_ntoa(rt->rt_gate)));
|
|
||||||
print_rts(rt->rt_spares, 0,0,0,0,AGE_RT(rt->rt_state,rt->rt_ifp));
|
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);
|
trace_bits(rs_bits, rt->rt_state, 0);
|
||||||
(void)fputc('\n',ftrace);
|
(void)fputc('\n',ftrace);
|
||||||
@ -822,21 +822,20 @@ trace_add_del(char * action, struct rt_entry *rt)
|
|||||||
/* ARGSUSED */
|
/* ARGSUSED */
|
||||||
static int
|
static int
|
||||||
walk_trace(struct radix_node *rn,
|
walk_trace(struct radix_node *rn,
|
||||||
struct walkarg *w)
|
struct walkarg *w UNUSED)
|
||||||
{
|
{
|
||||||
#define RT ((struct rt_entry *)rn)
|
#define RT ((struct rt_entry *)rn)
|
||||||
struct rt_spare *rts;
|
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,
|
(void)fprintf(ftrace, " %-35s ",
|
||||||
naddr_ntoa(RT->rt_gate)));
|
rtname(RT->rt_dst, RT->rt_mask, RT->rt_gate));
|
||||||
print_rts(&RT->rt_spares[0], 0,0,0,0,age);
|
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);
|
trace_bits(rs_bits, RT->rt_state, 0);
|
||||||
if (RT->rt_poison_time >= now_garbage
|
if (RT->rt_poison_time >= now_garbage
|
||||||
&& RT->rt_poison_metric < RT->rt_metric)
|
&& RT->rt_poison_metric < RT->rt_metric)
|
||||||
(void)fprintf(ftrace, "pm=%d@%s",
|
(void)fprintf(ftrace, "pm=%d@%s",
|
||||||
RT->rt_poison_metric,
|
RT->rt_poison_metric, ts(RT->rt_poison_time));
|
||||||
ts(RT->rt_poison_time));
|
|
||||||
|
|
||||||
rts = &RT->rt_spares[1];
|
rts = &RT->rt_spares[1];
|
||||||
for (i = 1; i < NUM_SPARES; i++, rts++) {
|
for (i = 1; i < NUM_SPARES; i++, rts++) {
|
||||||
@ -869,14 +868,14 @@ trace_dump(void)
|
|||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
trace_rip(char *dir1, char *dir2,
|
trace_rip(const char *dir1, const char *dir2,
|
||||||
struct sockaddr_in *who,
|
struct sockaddr_in *who,
|
||||||
struct interface *ifp,
|
struct interface *ifp,
|
||||||
struct rip *msg,
|
struct rip *msg,
|
||||||
int size) /* total size of message */
|
int size) /* total size of message */
|
||||||
{
|
{
|
||||||
struct netinfo *n, *lim;
|
struct netinfo *n, *lim;
|
||||||
# define NA (msg->rip_auths)
|
# define NA ((struct netauth*)n)
|
||||||
int i, seen_route;
|
int i, seen_route;
|
||||||
|
|
||||||
if (!TRACEPACKETS || ftrace == 0)
|
if (!TRACEPACKETS || ftrace == 0)
|
||||||
@ -946,23 +945,24 @@ trace_rip(char *dir1, char *dir2,
|
|||||||
if (NA->a_type == RIP_AUTH_MD5
|
if (NA->a_type == RIP_AUTH_MD5
|
||||||
&& n == msg->rip_nets) {
|
&& n == msg->rip_nets) {
|
||||||
(void)fprintf(ftrace,
|
(void)fprintf(ftrace,
|
||||||
"\tMD5 Authentication"
|
"\tMD5 Auth"
|
||||||
" len=%d KeyID=%u"
|
" pkt_len=%d KeyID=%u"
|
||||||
" seqno=%u"
|
" auth_len=%d"
|
||||||
|
" seqno=%#x"
|
||||||
" rsvd=%#x,%#x\n",
|
" 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_keyid,
|
||||||
NA->au.a_md5.md5_seqno,
|
NA->au.a_md5.md5_auth_len,
|
||||||
NA->au.a_md5.rsvd[0],
|
(int)ntohl(NA->au.a_md5.md5_seqno),
|
||||||
NA->au.a_md5.rsvd[1]);
|
(int)ntohs(NA->au.a_md5.rsvd[0]),
|
||||||
|
(int)ntohs(NA->au.a_md5.rsvd[1]));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
(void)fprintf(ftrace,
|
(void)fprintf(ftrace,
|
||||||
"\tAuthentication"
|
"\tAuthentication type %d: ",
|
||||||
" type %d: ",
|
|
||||||
ntohs(NA->a_type));
|
ntohs(NA->a_type));
|
||||||
for (i = 0;
|
for (i = 0;
|
||||||
i < sizeof(NA->au.au_pw);
|
i < (int)sizeof(NA->au.au_pw);
|
||||||
i++)
|
i++)
|
||||||
(void)fprintf(ftrace, "%02x ",
|
(void)fprintf(ftrace, "%02x ",
|
||||||
NA->au.au_pw[i]);
|
NA->au.au_pw[i]);
|
||||||
|
Loading…
Reference in New Issue
Block a user