The latest and greatest routed from Vern Schryver. This version includes
many fixes to router discovery, including a number of endianness bug fixes. (Router discovery appears to actually work now.) This should be the end of it for the Sun `rdisc' program. (People currently using rdisc(8) should be able to go back to routed again.) Obtained from: Vernon J. Schryver <vjs@mica.denver.sgi.com>
This commit is contained in:
parent
9979ce1560
commit
1823680765
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/vendor/SGI/dist/; revision=17250
@ -3,6 +3,6 @@
|
|||||||
PROG= routed
|
PROG= routed
|
||||||
SRCS= if.c input.c main.c output.c parms.c radix.c rdisc.c table.c trace.c
|
SRCS= if.c input.c main.c output.c parms.c radix.c rdisc.c table.c trace.c
|
||||||
MAN8= routed.8
|
MAN8= routed.8
|
||||||
SUBDIR= rtquery rttrace
|
SUBDIR= rtquery
|
||||||
|
|
||||||
.include <bsd.prog.mk>
|
.include <bsd.prog.mk>
|
||||||
|
@ -33,7 +33,7 @@
|
|||||||
* @(#)defs.h 8.1 (Berkeley) 6/5/93
|
* @(#)defs.h 8.1 (Berkeley) 6/5/93
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ident "$Revision: 1.1 $"
|
#ident "$Revision: 1.11 $"
|
||||||
|
|
||||||
/* Definitions for RIPv2 routing process.
|
/* Definitions for RIPv2 routing process.
|
||||||
*
|
*
|
||||||
@ -104,12 +104,10 @@ struct walkarg;
|
|||||||
#define _HAVE_SIN_LEN
|
#define _HAVE_SIN_LEN
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef sgi
|
|
||||||
/* 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
|
/* #define MCAST_PPP_BUG */
|
||||||
#endif
|
|
||||||
|
|
||||||
#define NEVER (24*60*60) /* a long time */
|
#define NEVER (24*60*60) /* a long time */
|
||||||
#define EPOCH NEVER /* bias time by this to avoid <0 */
|
#define EPOCH NEVER /* bias time by this to avoid <0 */
|
||||||
@ -121,12 +119,6 @@ struct walkarg;
|
|||||||
#define CHECK_ACT_INTERVAL 30 /* when advertising */
|
#define CHECK_ACT_INTERVAL 30 /* when advertising */
|
||||||
#define CHECK_QUIET_INTERVAL 300 /* when not */
|
#define CHECK_QUIET_INTERVAL 300 /* when not */
|
||||||
|
|
||||||
|
|
||||||
/* set times to this to continue poisoning a route */
|
|
||||||
#define POISON_SECS (GARBAGE_TIME - POISON_TIME)
|
|
||||||
|
|
||||||
#define NET_S_METRIC 1 /* metric used on synthetic routes */
|
|
||||||
|
|
||||||
#define LIM_SEC(s,l) ((s).tv_sec = MIN((s).tv_sec, (l)))
|
#define LIM_SEC(s,l) ((s).tv_sec = MIN((s).tv_sec, (l)))
|
||||||
|
|
||||||
|
|
||||||
@ -162,16 +154,15 @@ struct rt_entry {
|
|||||||
struct radix_node rt_nodes[2]; /* radix tree glue */
|
struct radix_node rt_nodes[2]; /* radix tree glue */
|
||||||
u_int rt_state;
|
u_int rt_state;
|
||||||
# define RS_IF 0x001 /* for network interface */
|
# define RS_IF 0x001 /* for network interface */
|
||||||
# define RS_NET_SUB 0x002 /* fake net route for subnet */
|
# define RS_NET_INT 0x002 /* authority route */
|
||||||
# define RS_NET_HOST 0x004 /* fake net route for host */
|
# define RS_NET_SYN 0x004 /* fake net route for subnet */
|
||||||
# define RS_NET_INT 0x008 /* authority route */
|
# define RS_NO_NET_SYN (RS_LOCAL | RS_LOCAL | RS_IF)
|
||||||
# define RS_NET_S (RS_NET_SUB | RS_NET_HOST | RS_NET_INT)
|
# define RS_SUBNET 0x008 /* subnet route from any source */
|
||||||
# define RS_SUBNET 0x010 /* subnet route from any source */
|
# define RS_LOCAL 0x010 /* loopback for pt-to-pt */
|
||||||
# define RS_LOCAL 0x020 /* loopback for pt-to-pt */
|
# define RS_MHOME 0x020 /* from -m */
|
||||||
# define RS_MHOME 0x040 /* from -m */
|
# define RS_STATIC 0x040 /* from the kernel */
|
||||||
# define RS_GW 0x080 /* from -g */
|
# define RS_RDISC 0x080 /* from router discovery */
|
||||||
# define RS_STATIC 0x100 /* from the kernel */
|
# define RS_PERMANENT (RS_MHOME | RS_STATIC | RS_NET_SYN | RS_RDISC)
|
||||||
# define RS_RDISC 0x200 /* from router discovery */
|
|
||||||
struct sockaddr_in rt_dst_sock;
|
struct sockaddr_in rt_dst_sock;
|
||||||
naddr rt_mask;
|
naddr rt_mask;
|
||||||
struct rt_spare {
|
struct rt_spare {
|
||||||
@ -184,8 +175,8 @@ struct rt_entry {
|
|||||||
#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_hold_metric;
|
char rt_poison_metric; /* to notice maximum recently */
|
||||||
time_t rt_hold_down;
|
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
|
||||||
@ -205,9 +196,7 @@ struct rt_entry {
|
|||||||
* nor non-passive, remote interfaces that are not aliases
|
* nor non-passive, remote interfaces that are not aliases
|
||||||
* (i.e. remote & metric=0)
|
* (i.e. remote & metric=0)
|
||||||
*/
|
*/
|
||||||
#define AGE_RT(rt,ifp) (0 == ((rt)->rt_state & (RS_GW | RS_MHOME | RS_STATIC \
|
#define AGE_RT(rt,ifp) (0 == ((rt)->rt_state & RS_PERMANENT) \
|
||||||
| RS_NET_SUB | RS_NET_HOST \
|
|
||||||
| RS_RDISC)) \
|
|
||||||
&& (!((rt)->rt_state & RS_IF) \
|
&& (!((rt)->rt_state & RS_IF) \
|
||||||
|| (ifp) == 0 \
|
|| (ifp) == 0 \
|
||||||
|| (((ifp)->int_state & IS_REMOTE) \
|
|| (((ifp)->int_state & IS_REMOTE) \
|
||||||
@ -220,14 +209,18 @@ struct rt_entry {
|
|||||||
* - and A has a shorter path
|
* - and A has a shorter path
|
||||||
* - or is the router speaking for itself
|
* - or is the router speaking for itself
|
||||||
* - 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
|
||||||
*/
|
*/
|
||||||
#define BETTER_LINK(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 \
|
||||||
&& (B)->rts_gate != (B)->rts_router) \
|
&& (B)->rts_gate != (B)->rts_router) \
|
||||||
|| ((A)->rts_metric == (B)->rts_metric \
|
|| ((A)->rts_metric == (B)->rts_metric \
|
||||||
&& now_stale > (B)->rts_time)))
|
&& now_stale > (B)->rts_time) \
|
||||||
|
|| (RT_ISHOST(rt) \
|
||||||
|
&& (rt)->rt_dst == (A)->rts_router \
|
||||||
|
&& (A)->rts_metric == (B)->rts_metric)))
|
||||||
|
|
||||||
|
|
||||||
/* An "interface" is similar to a kernel ifnet structure, except it also
|
/* An "interface" is similar to a kernel ifnet structure, except it also
|
||||||
@ -242,27 +235,27 @@ struct interface {
|
|||||||
naddr int_dstaddr; /* other end of pt-to-pt link (n) */
|
naddr int_dstaddr; /* other end of pt-to-pt link (n) */
|
||||||
naddr int_net; /* working network # (host order)*/
|
naddr int_net; /* working network # (host order)*/
|
||||||
naddr int_mask; /* working net mask (host order) */
|
naddr int_mask; /* working net mask (host order) */
|
||||||
|
naddr int_ripv1_mask; /* for inferring a mask (n) */
|
||||||
naddr int_std_addr; /* class A/B/C address (n) */
|
naddr int_std_addr; /* class A/B/C address (n) */
|
||||||
naddr int_std_net; /* class A/B/C network (h) */
|
naddr int_std_net; /* class A/B/C network (h) */
|
||||||
naddr int_std_mask; /* class A/B/C netmask (h) */
|
naddr int_std_mask; /* class A/B/C netmask (h) */
|
||||||
naddr int_host_addr; /* RIPv1 net for pt-to-pt link (h) */
|
|
||||||
naddr int_host_mask; /* RIPv1 mask for pt-to-pt (h) */
|
|
||||||
int int_rip_sock; /* for queries */
|
int int_rip_sock; /* for queries */
|
||||||
int int_if_flags; /* copied from kernel */
|
int int_if_flags; /* copied from kernel */
|
||||||
u_int int_state;
|
u_int int_state;
|
||||||
time_t int_act_time; /* last thought healthy */
|
time_t int_act_time; /* last thought healthy */
|
||||||
time_t int_quiet_time; /* last inactive */
|
|
||||||
u_short int_transitions; /* times gone up-down */
|
u_short int_transitions; /* times gone up-down */
|
||||||
char int_metric;
|
char int_metric;
|
||||||
char int_d_metric; /* for faked default route */
|
char int_d_metric; /* for faked default route */
|
||||||
u_int int_data_ipackets; /* previous network stats */
|
struct int_data {
|
||||||
u_int int_data_ierrors;
|
u_int ipackets; /* previous network stats */
|
||||||
u_int int_data_opackets;
|
u_int ierrors;
|
||||||
u_int int_data_oerrors;
|
u_int opackets;
|
||||||
|
u_int oerrors;
|
||||||
#ifdef sgi
|
#ifdef sgi
|
||||||
u_int int_data_odrops;
|
u_int odrops;
|
||||||
#endif
|
#endif
|
||||||
time_t int_data_ts; /* timestamp on network stats */
|
time_t ts; /* timestamp on network stats */
|
||||||
|
} int_data;
|
||||||
char int_passwd[RIP_AUTH_PW_LEN]; /* RIPv2 password */
|
char int_passwd[RIP_AUTH_PW_LEN]; /* RIPv2 password */
|
||||||
int int_rdisc_pref; /* advertised rdisc preference */
|
int int_rdisc_pref; /* advertised rdisc preference */
|
||||||
int int_rdisc_int; /* MaxAdvertiseInterval */
|
int int_rdisc_int; /* MaxAdvertiseInterval */
|
||||||
@ -280,25 +273,32 @@ struct interface {
|
|||||||
#define IS_ALL_ROUTERS 0x0000080 /* in INADDR_ALLROUTERS_GROUP */
|
#define IS_ALL_ROUTERS 0x0000080 /* in INADDR_ALLROUTERS_GROUP */
|
||||||
#define IS_RIP_QUERIED 0x0000100 /* query broadcast */
|
#define IS_RIP_QUERIED 0x0000100 /* query broadcast */
|
||||||
#define IS_BROKE 0x0000200 /* seems to be broken */
|
#define IS_BROKE 0x0000200 /* seems to be broken */
|
||||||
#define IS_ACTIVE 0x0000400 /* heard from it at least once */
|
#define IS_SICK 0x0000400 /* seems to be broken */
|
||||||
#define IS_QUIET 0x0000800 /* have not heard from it recently */
|
#define IS_DUP 0x0000800 /* has a duplicate address */
|
||||||
#define IS_NEED_NET_SUB 0x0001000 /* need RS_NET_SUB route */
|
#define IS_ACTIVE 0x0001000 /* heard from it at least once */
|
||||||
#define IS_NO_AG 0x0002000 /* do not aggregate subnets */
|
#define IS_NEED_NET_SYN 0x0002000 /* need RS_NET_SYN route */
|
||||||
#define IS_NO_SUPER_AG 0x0004000 /* do not aggregate networks */
|
#define IS_NO_AG 0x0004000 /* do not aggregate subnets */
|
||||||
#define IS_NO_RIPV1_IN 0x0008000 /* no RIPv1 input at all */
|
#define IS_NO_SUPER_AG 0x0008000 /* do not aggregate networks */
|
||||||
#define IS_NO_RIPV2_IN 0x0010000 /* no RIPv2 input at all */
|
#define IS_NO_RIPV1_IN 0x0010000 /* no RIPv1 input at all */
|
||||||
#define IS_NO_RIP_IN (IS_NO_RIPV2_IN | IS_NO_RIPV2_IN)
|
#define IS_NO_RIPV2_IN 0x0020000 /* no RIPv2 input at all */
|
||||||
#define IS_NO_RIPV1_OUT 0x0020000 /* no RIPv1 output at all */
|
#define IS_NO_RIP_IN (IS_NO_RIPV1_IN | IS_NO_RIPV2_IN)
|
||||||
#define IS_NO_RIPV2_OUT 0x0040000 /* no RIPv2 output at all */
|
#define IS_RIP_IN_OFF(s) (((s) & IS_NO_RIP_IN) == IS_NO_RIP_IN)
|
||||||
|
#define IS_NO_RIPV1_OUT 0x0040000 /* no RIPv1 output at all */
|
||||||
|
#define IS_NO_RIPV2_OUT 0x0080000 /* no RIPv2 output at all */
|
||||||
#define IS_NO_RIP_OUT (IS_NO_RIPV1_OUT | IS_NO_RIPV2_OUT)
|
#define IS_NO_RIP_OUT (IS_NO_RIPV1_OUT | IS_NO_RIPV2_OUT)
|
||||||
#define IS_NO_ADV_IN 0x0080000
|
#define IS_NO_RIP (IS_NO_RIP_OUT | IS_NO_RIP_IN)
|
||||||
#define IS_NO_SOL_OUT 0x0100000 /* no solicitations */
|
#define IS_RIP_OUT_OFF(s) (((s) & IS_NO_RIP_OUT) == IS_NO_RIP_OUT)
|
||||||
#define IS_SOL_OUT 0x0200000 /* send solicitations */
|
#define IS_RIP_OFF(s) (((s) & IS_NO_RIP) == IS_NO_RIP)
|
||||||
|
#define IS_NO_ADV_IN 0x0100000
|
||||||
|
#define IS_NO_SOL_OUT 0x0200000 /* no solicitations */
|
||||||
|
#define IS_SOL_OUT 0x0400000 /* send solicitations */
|
||||||
#define GROUP_IS_SOL (IS_NO_ADV_IN|IS_NO_SOL_OUT)
|
#define GROUP_IS_SOL (IS_NO_ADV_IN|IS_NO_SOL_OUT)
|
||||||
#define IS_NO_ADV_OUT 0x0400000 /* do not advertise rdisc */
|
#define IS_NO_ADV_OUT 0x0800000 /* do not advertise rdisc */
|
||||||
#define IS_ADV_OUT 0x0800000 /* advertise rdisc */
|
#define IS_ADV_OUT 0x1000000 /* advertise rdisc */
|
||||||
#define GROUP_IS_ADV (IS_NO_ADV_OUT|IS_ADV_OUT)
|
#define GROUP_IS_ADV (IS_NO_ADV_OUT|IS_ADV_OUT)
|
||||||
#define IS_BCAST_RDISC 0x1000000 /* broadcast instead of multicast */
|
#define IS_BCAST_RDISC 0x2000000 /* broadcast instead of multicast */
|
||||||
|
#define IS_NO_RDISC (IS_NO_ADV_IN | IS_NO_SOL_OUT | IS_NO_ADV_OUT)
|
||||||
|
#define IS_PM_RDISC 0x4000000 /* poor-man's router discovery */
|
||||||
|
|
||||||
#ifdef sgi
|
#ifdef sgi
|
||||||
#define IFF_UP_RUNNING (IFF_RUNNING|IFF_UP)
|
#define IFF_UP_RUNNING (IFF_RUNNING|IFF_UP)
|
||||||
@ -316,21 +316,30 @@ struct ag_info {
|
|||||||
naddr ag_dst_h; /* destination in host byte order */
|
naddr ag_dst_h; /* destination in host byte order */
|
||||||
naddr ag_mask;
|
naddr ag_mask;
|
||||||
naddr ag_gate;
|
naddr ag_gate;
|
||||||
|
naddr ag_nhop;
|
||||||
char ag_metric; /* metric to be advertised */
|
char ag_metric; /* metric to be advertised */
|
||||||
char ag_pref; /* aggregate based on this */
|
char ag_pref; /* aggregate based on this */
|
||||||
u_int ag_seqno;
|
u_int ag_seqno;
|
||||||
u_short ag_tag;
|
u_short ag_tag;
|
||||||
u_short ag_state;
|
u_short ag_state;
|
||||||
#define AGS_SUPPRESS 0x01 /* combine with coaser mask */
|
#define AGS_SUPPRESS 0x001 /* combine with coaser mask */
|
||||||
#define AGS_PROMOTE 0x002 /* synthesize combined routes */
|
#define AGS_PROMOTE 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)) \
|
||||||
== (AGS_REDUN0 | AGS_REDUN1))
|
== (AGS_REDUN0 | AGS_REDUN1))
|
||||||
#define AGS_GATEWAY 0x010 /* tell kernel RTF_GATEWAY */
|
#define AGS_GATEWAY 0x010 /* tell kernel RTF_GATEWAY */
|
||||||
#define AGS_RIPV2 0x020 /* send only as RIPv2 */
|
#define AGS_IF 0x020 /* for an interface */
|
||||||
#define AGS_DEAD 0x080 /* dead--ignore differing gate */
|
#define AGS_RIPV2 0x040 /* send only as RIPv2 */
|
||||||
#define AGS_RDISC 0x100 /* suppresses most routes */
|
#define AGS_FINE_GATE 0x080 /* ignore differing ag_gate when this
|
||||||
|
* has the finer netmask */
|
||||||
|
#define AGS_CORS_GATE 0x100 /* ignore differing gate when this
|
||||||
|
* has the coarser netmaks */
|
||||||
|
#define AGS_SPLIT_HZ 0x200 /* suppress for split horizon */
|
||||||
|
|
||||||
|
/* some bits are set if they are set on either route */
|
||||||
|
#define AGS_PROMOTE_EITHER (AGS_RIPV2 | AGS_GATEWAY | \
|
||||||
|
AGS_SUPPRESS | AGS_CORS_GATE)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -338,8 +347,8 @@ struct ag_info {
|
|||||||
extern struct parm {
|
extern struct parm {
|
||||||
struct parm *parm_next;
|
struct parm *parm_next;
|
||||||
char parm_name[IFNAMSIZ+1];
|
char parm_name[IFNAMSIZ+1];
|
||||||
naddr parm_a_h;
|
naddr parm_addr_h;
|
||||||
naddr parm_m;
|
naddr parm_mask;
|
||||||
|
|
||||||
char parm_d_metric;
|
char parm_d_metric;
|
||||||
u_int parm_int_state;
|
u_int parm_int_state;
|
||||||
@ -353,6 +362,7 @@ extern struct intnet {
|
|||||||
struct intnet *intnet_next;
|
struct intnet *intnet_next;
|
||||||
naddr intnet_addr;
|
naddr intnet_addr;
|
||||||
naddr intnet_mask;
|
naddr intnet_mask;
|
||||||
|
char intnet_metric;
|
||||||
} *intnets;
|
} *intnets;
|
||||||
|
|
||||||
|
|
||||||
@ -371,11 +381,9 @@ 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 default_gateway; /* 1=advertise default */
|
|
||||||
extern int lookforinterfaces; /* 1=probe for new up interfaces */
|
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 ridhosts; /* 1=reduce host routes */
|
extern int ridhosts; /* 1=reduce host routes */
|
||||||
extern int ppp_noage; /* 1=do not age quiet link 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 adverising it */
|
extern int advertise_mhome; /* 1=must continue adverising it */
|
||||||
extern int auth_ok; /* 1=ignore auth if we do not care */
|
extern int auth_ok; /* 1=ignore auth if we do not care */
|
||||||
@ -397,15 +405,16 @@ extern naddr loopaddr; /* our address on loopback */
|
|||||||
extern int tot_interfaces; /* # of remote and local interfaces */
|
extern int tot_interfaces; /* # of remote and local interfaces */
|
||||||
extern int rip_interfaces; /* # of interfaces doing RIP */
|
extern int rip_interfaces; /* # of interfaces doing RIP */
|
||||||
extern struct interface *ifnet; /* all interfaces */
|
extern struct interface *ifnet; /* all interfaces */
|
||||||
extern int have_ripv1; /* have a RIPv1 interface */
|
extern int have_ripv1_out; /* have a RIPv1 interface */
|
||||||
|
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 int update_seqno; /* a route has changed */
|
||||||
|
|
||||||
extern u_int tracelevel, new_tracelevel;
|
extern u_int tracelevel, new_tracelevel;
|
||||||
#define MAX_TRACELEVEL 3
|
#define MAX_TRACELEVEL 3
|
||||||
#define TRACEPACKETS (tracelevel >= 2) /* note packets */
|
|
||||||
#define TRACECONTENTS (tracelevel >= 3) /* display packet contents */
|
#define TRACECONTENTS (tracelevel >= 3) /* display packet contents */
|
||||||
|
#define TRACEPACKETS (tracelevel >= 2) /* note packets */
|
||||||
#define TRACEACTIONS (tracelevel != 0)
|
#define TRACEACTIONS (tracelevel != 0)
|
||||||
extern FILE *ftrace; /* output trace file */
|
extern FILE *ftrace; /* output trace file */
|
||||||
|
|
||||||
@ -422,7 +431,8 @@ 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 *);
|
||||||
|
|
||||||
enum output_type {OUT_QUERY, OUT_UNICAST, OUT_BROADCAST, OUT_MULTICAST};
|
enum output_type {OUT_QUERY, OUT_UNICAST, OUT_BROADCAST, OUT_MULTICAST,
|
||||||
|
NO_OUT_MULTICAST, NO_OUT_RIPV2};
|
||||||
extern int output(enum output_type, struct sockaddr_in *,
|
extern int output(enum output_type, struct sockaddr_in *,
|
||||||
struct interface *, struct rip *, int);
|
struct interface *, struct rip *, int);
|
||||||
extern void rip_query(void);
|
extern void rip_query(void);
|
||||||
@ -454,14 +464,16 @@ 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 *);
|
extern char *parse_parms(char *);
|
||||||
|
extern 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 trace_on(char *, int);
|
extern void trace_on(char *, int);
|
||||||
extern void trace_off(char*, char*);
|
extern void trace_off(char*, ...);
|
||||||
extern void trace_flush(void);
|
extern void trace_flush(void);
|
||||||
extern void set_tracelevel(void);
|
extern void set_tracelevel(void);
|
||||||
extern void trace_msg(char *, ...);
|
extern void trace_act(char *, ...);
|
||||||
|
extern void trace_pkt(char *, ...);
|
||||||
extern void trace_add_del(char *, struct rt_entry *);
|
extern void trace_add_del(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, naddr, naddr, int,
|
||||||
u_short, struct interface *, time_t, char *);
|
u_short, struct interface *, time_t, char *);
|
||||||
@ -476,8 +488,8 @@ extern char *addrname(naddr, naddr, int);
|
|||||||
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);
|
||||||
extern void set_supplier(void);
|
extern void set_supplier(void);
|
||||||
extern void ifbad_rdisc(struct interface *);
|
extern void if_bad_rdisc(struct interface *);
|
||||||
extern void ifok_rdisc(struct interface *);
|
extern void if_ok_rdisc(struct interface *);
|
||||||
extern void read_rip(int, struct interface *);
|
extern void read_rip(int, struct interface *);
|
||||||
extern void read_rt(void);
|
extern void read_rt(void);
|
||||||
extern void read_d(void);
|
extern void read_d(void);
|
||||||
@ -490,12 +502,11 @@ extern void sigterm(int);
|
|||||||
extern void sigtrace_on(int);
|
extern void sigtrace_on(int);
|
||||||
extern void sigtrace_off(int);
|
extern void sigtrace_off(int);
|
||||||
|
|
||||||
extern void fix_kern(void);
|
|
||||||
extern void flush_kern(void);
|
extern void flush_kern(void);
|
||||||
extern void age(naddr);
|
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, 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, int);
|
||||||
extern void del_redirects(naddr, time_t);
|
extern void del_redirects(naddr, time_t);
|
||||||
@ -512,21 +523,21 @@ extern void rtswitch(struct rt_entry *, struct rt_spare *);
|
|||||||
extern void rtbad(struct rt_entry *);
|
extern void rtbad(struct rt_entry *);
|
||||||
|
|
||||||
|
|
||||||
extern struct rt_addrinfo rtinfo;
|
|
||||||
#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 RTINFO_DST rtinfo.rti_info[RTAX_DST]
|
#define INFO_DST(I) ((I)->rti_info[RTAX_DST])
|
||||||
#define RTINFO_GATE rtinfo.rti_info[RTAX_GATEWAY]
|
#define INFO_GATE(I) ((I)->rti_info[RTAX_GATEWAY])
|
||||||
#define RTINFO_NETMASK rtinfo.rti_info[RTAX_NETMASK]
|
#define INFO_MASK(I) ((I)->rti_info[RTAX_NETMASK])
|
||||||
#define RTINFO_IFA rtinfo.rti_info[RTAX_IFA]
|
#define INFO_IFA(I) ((I)->rti_info[RTAX_IFA])
|
||||||
#define RTINFO_AUTHOR rtinfo.rti_info[RTAX_AUTHOR]
|
#define INFO_IFP(I) ((I)->rti_info[RTAX_IFP])
|
||||||
#define RTINFO_BRD rtinfo.rti_info[RTAX_BRD]
|
#define INFO_AUTHOR(I) ((I)->rti_info[RTAX_AUTHOR])
|
||||||
#define RTINFO_IFP ((struct sockaddr_dl *)rtinfo.rti_info[RTAX_IFP])
|
#define INFO_BRD(I) ((I)->rti_info[RTAX_BRD])
|
||||||
void rt_xaddrs(struct sockaddr *, struct sockaddr *, int);
|
void rt_xaddrs(struct rt_addrinfo *, struct sockaddr *, struct sockaddr *,
|
||||||
|
int);
|
||||||
|
|
||||||
extern naddr std_mask(naddr);
|
extern naddr std_mask(naddr);
|
||||||
extern naddr ripv1_mask_net(naddr, struct interface *, struct interface *);
|
extern naddr ripv1_mask_net(naddr, struct interface *);
|
||||||
extern naddr ripv1_mask_host(naddr,struct interface *, struct interface *);
|
extern naddr ripv1_mask_host(naddr,struct interface *);
|
||||||
#define on_net(tgt, net, mask) ((ntohl(tgt) & mask) == (net & mask))
|
#define on_net(a,net,mask) (((ntohl(a) ^ (net)) & (mask)) == 0)
|
||||||
extern int check_dst(naddr);
|
extern int check_dst(naddr);
|
||||||
#ifdef sgi
|
#ifdef sgi
|
||||||
extern int sysctl(int *, u_int, void *, size_t *, void *, size_t);
|
extern int sysctl(int *, u_int, void *, size_t *, void *, size_t);
|
||||||
@ -534,8 +545,9 @@ extern int sysctl(int *, u_int, void *, size_t *, void *, size_t);
|
|||||||
extern void addrouteforif(register struct interface *);
|
extern void addrouteforif(register 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 ifok(struct interface *, char *);
|
extern int if_ok(struct interface *, char *);
|
||||||
extern void ifbad(struct interface *, char *);
|
extern void if_sick(struct interface *);
|
||||||
|
extern void if_bad(struct interface *);
|
||||||
extern struct interface *ifwithaddr(naddr, int, int);
|
extern struct interface *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);
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -31,17 +31,17 @@
|
|||||||
* SUCH DAMAGE.
|
* SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef lint
|
#if !defined(lint) && !defined(sgi)
|
||||||
static char sccsid[] = "@(#)input.c 8.1 (Berkeley) 6/5/93";
|
static char sccsid[] = "@(#)input.c 8.1 (Berkeley) 6/5/93";
|
||||||
#endif /* not lint */
|
#endif /* not lint */
|
||||||
|
|
||||||
#ident "$Revision: 1.1 $"
|
#ident "$Revision: 1.10 $"
|
||||||
|
|
||||||
#include "defs.h"
|
#include "defs.h"
|
||||||
|
|
||||||
static void input(struct sockaddr_in *, struct interface*, struct rip *, int);
|
static void input(struct sockaddr_in *, struct interface*, struct rip *, int);
|
||||||
static void input_route(struct interface *, naddr,
|
static void input_route(struct interface *, naddr,
|
||||||
naddr, naddr, naddr, int, u_short);
|
naddr, naddr, naddr, struct netinfo *);
|
||||||
|
|
||||||
|
|
||||||
/* process RIP input
|
/* process RIP input
|
||||||
@ -97,8 +97,7 @@ input(struct sockaddr_in *from, /* received from this IP address */
|
|||||||
if (ifp != 0)
|
if (ifp != 0)
|
||||||
ifp->int_state |= IS_ACTIVE;
|
ifp->int_state |= IS_ACTIVE;
|
||||||
|
|
||||||
if (TRACEPACKETS)
|
trace_rip("Recv", "from", from, ifp, rip, size);
|
||||||
trace_rip("Recv", "from", from, ifp, rip, size);
|
|
||||||
|
|
||||||
if (rip->rip_vers == 0) {
|
if (rip->rip_vers == 0) {
|
||||||
if (from->sin_addr.s_addr != bad_router)
|
if (from->sin_addr.s_addr != bad_router)
|
||||||
@ -138,8 +137,7 @@ input(struct sockaddr_in *from, /* received from this IP address */
|
|||||||
" from %s discarded",
|
" from %s discarded",
|
||||||
naddr_ntoa(FROM_NADDR));
|
naddr_ntoa(FROM_NADDR));
|
||||||
use_auth = from->sin_addr.s_addr;
|
use_auth = from->sin_addr.s_addr;
|
||||||
if (TRACEPACKETS)
|
trace_pkt("discard authenticated RIPv2 message\n");
|
||||||
trace_msg("discard authenticated RIPv2 message\n");
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -148,28 +146,29 @@ input(struct sockaddr_in *from, /* received from this IP address */
|
|||||||
/* did the request come from a router?
|
/* did the request come from a router?
|
||||||
*/
|
*/
|
||||||
if (from->sin_port == htons(RIP_PORT)) {
|
if (from->sin_port == htons(RIP_PORT)) {
|
||||||
/* yes, ignore it if RIP is off
|
/* yes, ignore it if RIP is off so that it does not
|
||||||
|
* depend on us.
|
||||||
*/
|
*/
|
||||||
if (rip_sock < 0) {
|
if (rip_sock < 0) {
|
||||||
trace_msg("ignore request while RIP off");
|
trace_pkt("ignore request while RIP off\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Ignore the request if we talking to ourself
|
/* Ignore the request if we talking to ourself
|
||||||
* (and not a remote gateway).
|
* (and not a remote gateway).
|
||||||
*/
|
*/
|
||||||
ifp1 = ifwithaddr(FROM_NADDR, 0, 0);
|
if (ifwithaddr(FROM_NADDR, 0, 0) != 0) {
|
||||||
if (ifp1 != 0
|
trace_pkt("discard our own RIP request\n");
|
||||||
&& (!(ifp1->int_state & IS_REMOTE)
|
|
||||||
|| ifp->int_metric != 0)) {
|
|
||||||
if (TRACEPACKETS)
|
|
||||||
trace_msg("discard our own packet\n");
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* According to RFC 1723, we should ignore unathenticated
|
/* According to RFC 1723, we should ignore unathenticated
|
||||||
* queries. That is too silly to bother with.
|
* queries. That is too silly to bother with. Sheesh!
|
||||||
|
* Are forwarding tables supposed to be secret? When
|
||||||
|
* a bad guy can infer them with test traffic?
|
||||||
|
* Maybe on firewalls you'd care, but not enough to
|
||||||
|
* give up the diagnostic facilities of remote probing.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (n >= lim
|
if (n >= lim
|
||||||
@ -234,13 +233,10 @@ input(struct sockaddr_in *from, /* received from this IP address */
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rip->rip_vers == RIPv1) {
|
if (rip->rip_vers == RIPv1
|
||||||
mask = ripv1_mask_host(dst,ifp,0);
|
|| 0 == (mask = ntohl(n->n_mask)))
|
||||||
} else {
|
mask = ripv1_mask_host(dst,ifp);
|
||||||
mask = ntohl(n->n_mask);
|
|
||||||
if (mask == 0)
|
|
||||||
mask = ripv1_mask_host(dst,ifp,0);
|
|
||||||
}
|
|
||||||
rt = rtget(dst, mask);
|
rt = rtget(dst, mask);
|
||||||
if (!rt)
|
if (!rt)
|
||||||
rt = rtfind(n->n_dst);
|
rt = rtfind(n->n_dst);
|
||||||
@ -250,8 +246,9 @@ input(struct sockaddr_in *from, /* received from this IP address */
|
|||||||
if (!rt) {
|
if (!rt) {
|
||||||
n->n_metric = HOPCNT_INFINITY;
|
n->n_metric = HOPCNT_INFINITY;
|
||||||
} else {
|
} else {
|
||||||
n->n_metric = (rt->rt_metric
|
n->n_metric = rt->rt_metric+1;
|
||||||
+ (ifp ? ifp->int_metric : 1));
|
if (ifp != 0)
|
||||||
|
n->n_metric += ifp->int_metric;
|
||||||
if (n->n_metric > HOPCNT_INFINITY)
|
if (n->n_metric > HOPCNT_INFINITY)
|
||||||
n->n_metric = HOPCNT_INFINITY;
|
n->n_metric = HOPCNT_INFINITY;
|
||||||
if (rip->rip_vers == RIPv1) {
|
if (rip->rip_vers == RIPv1) {
|
||||||
@ -304,7 +301,7 @@ input(struct sockaddr_in *from, /* received from this IP address */
|
|||||||
rip->rip_tracefile[size-4] = '\0';
|
rip->rip_tracefile[size-4] = '\0';
|
||||||
trace_on(rip->rip_tracefile, 0);
|
trace_on(rip->rip_tracefile, 0);
|
||||||
} else {
|
} else {
|
||||||
trace_off("tracing turned off by ",
|
trace_off("tracing turned off by %s\n",
|
||||||
naddr_ntoa(FROM_NADDR));
|
naddr_ntoa(FROM_NADDR));
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
@ -319,15 +316,12 @@ input(struct sockaddr_in *from, /* received from this IP address */
|
|||||||
|
|
||||||
/* verify message came from a router */
|
/* verify message came from a router */
|
||||||
if (from->sin_port != ntohs(RIP_PORT)) {
|
if (from->sin_port != ntohs(RIP_PORT)) {
|
||||||
if (TRACEPACKETS)
|
trace_pkt("discard RIP response from unknown port\n");
|
||||||
trace_msg("discard response"
|
|
||||||
" from unknown port\n");
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rip_sock < 0) {
|
if (rip_sock < 0) {
|
||||||
if (TRACEPACKETS)
|
trace_pkt("discard response while RIP off\n");
|
||||||
trace_msg("discard response while RIP off");
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -335,18 +329,19 @@ input(struct sockaddr_in *from, /* received from this IP address */
|
|||||||
*/
|
*/
|
||||||
ifp1 = ifwithaddr(FROM_NADDR, 0, 1);
|
ifp1 = ifwithaddr(FROM_NADDR, 0, 1);
|
||||||
if (ifp1) {
|
if (ifp1) {
|
||||||
if (ifp1->int_state & IS_PASSIVE) {
|
if (ifp1->int_state & IS_REMOTE) {
|
||||||
msglog("bogus input from %s on supposedly"
|
if (ifp1->int_state & IS_PASSIVE) {
|
||||||
" passive interface %s",
|
msglog("bogus input from %s on"
|
||||||
naddr_ntoa(FROM_NADDR),
|
" supposedly passive %s",
|
||||||
ifp1->int_name);
|
naddr_ntoa(FROM_NADDR),
|
||||||
|
ifp1->int_name);
|
||||||
} else if (ifp1->int_state & IS_REMOTE) {
|
} else {
|
||||||
ifp1->int_act_time = now.tv_sec;
|
ifp1->int_act_time = now.tv_sec;
|
||||||
if (ifok(ifp1, "remote "))
|
if (if_ok(ifp1, "remote "))
|
||||||
addrouteforif(ifp1);
|
addrouteforif(ifp1);
|
||||||
} else if (TRACEPACKETS) {
|
}
|
||||||
trace_msg("discard our own packet\n");
|
} else {
|
||||||
|
trace_pkt("discard our own RIP response\n");
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -356,13 +351,20 @@ input(struct sockaddr_in *from, /* received from this IP address */
|
|||||||
* broadcast or point-to-point networks, and from
|
* broadcast or point-to-point networks, and from
|
||||||
* those listed in /etc/gateways.
|
* those listed in /etc/gateways.
|
||||||
*/
|
*/
|
||||||
if (!ifp || (ifp->int_state & IS_PASSIVE)) {
|
if (!ifp) {
|
||||||
if (from->sin_addr.s_addr != unk_router)
|
if (from->sin_addr.s_addr != unk_router)
|
||||||
msglog("packet from unknown router %s",
|
msglog("packet from unknown router %s"
|
||||||
|
" or via unidentified interface",
|
||||||
naddr_ntoa(FROM_NADDR));
|
naddr_ntoa(FROM_NADDR));
|
||||||
unk_router = from->sin_addr.s_addr;
|
unk_router = from->sin_addr.s_addr;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (ifp->int_state & IS_PASSIVE) {
|
||||||
|
trace_act("packet from %s via passive interface %s\n",
|
||||||
|
naddr_ntoa(FROM_NADDR),
|
||||||
|
ifp->int_name);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
/* Check required version
|
/* Check required version
|
||||||
*/
|
*/
|
||||||
@ -370,19 +372,16 @@ input(struct sockaddr_in *from, /* received from this IP address */
|
|||||||
&& rip->rip_vers == RIPv1)
|
&& rip->rip_vers == RIPv1)
|
||||||
|| ((ifp->int_state & IS_NO_RIPV2_IN)
|
|| ((ifp->int_state & IS_NO_RIPV2_IN)
|
||||||
&& rip->rip_vers != RIPv1)) {
|
&& rip->rip_vers != RIPv1)) {
|
||||||
if (TRACEPACKETS)
|
trace_pkt("discard RIPv%d response\n",
|
||||||
trace_msg("discard RIPv%d response\n",
|
rip->rip_vers);
|
||||||
rip->rip_vers);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Ignore routes via dead interface.
|
/* Ignore routes via dead interface.
|
||||||
*/
|
*/
|
||||||
if (ifp->int_state & IS_BROKE) {
|
if (ifp->int_state & IS_BROKE) {
|
||||||
if (TRACEPACKETS)
|
trace_pkt("discard response via broken interface %s\n",
|
||||||
trace_msg("discard response via"
|
ifp->int_name);
|
||||||
" broken interface %s\n",
|
|
||||||
ifp->int_name);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -466,9 +465,9 @@ input(struct sockaddr_in *from, /* received from this IP address */
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mask = ntohl(n->n_mask);
|
if (rip->rip_vers == RIPv1
|
||||||
if (rip->rip_vers == RIPv1 || mask == 0) {
|
|| 0 == (mask = ntohl(n->n_mask))) {
|
||||||
mask = ripv1_mask_host(dst,ifp,0);
|
mask = ripv1_mask_host(dst,ifp);
|
||||||
} else if ((ntohl(dst) & ~mask) != 0) {
|
} else if ((ntohl(dst) & ~mask) != 0) {
|
||||||
if (bad_mask != from->sin_addr.s_addr) {
|
if (bad_mask != from->sin_addr.s_addr) {
|
||||||
msglog("router %s sent bad netmask"
|
msglog("router %s sent bad netmask"
|
||||||
@ -480,14 +479,10 @@ input(struct sockaddr_in *from, /* received from this IP address */
|
|||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
v1_mask = (have_ripv1
|
|
||||||
? ripv1_mask_host(dst,0,0)
|
|
||||||
: mask);
|
|
||||||
|
|
||||||
if (rip->rip_vers == RIPv1)
|
if (rip->rip_vers == RIPv1)
|
||||||
n->n_tag = 0;
|
n->n_tag = 0;
|
||||||
|
|
||||||
/* Adjust metric according to incoming interface.
|
/* Adjust metric according to incoming interface..
|
||||||
*/
|
*/
|
||||||
n->n_metric += ifp->int_metric;
|
n->n_metric += ifp->int_metric;
|
||||||
if (n->n_metric > HOPCNT_INFINITY)
|
if (n->n_metric > HOPCNT_INFINITY)
|
||||||
@ -496,18 +491,19 @@ input(struct sockaddr_in *from, /* received from this IP address */
|
|||||||
/* 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.
|
||||||
|
* Be a little more paranoid than that, and reject
|
||||||
|
* default routes with the same metric we advertised.
|
||||||
*/
|
*/
|
||||||
if (ifp->int_d_metric != 0
|
if (ifp->int_d_metric != 0
|
||||||
&& dst == RIP_DEFAULT
|
&& dst == RIP_DEFAULT
|
||||||
&& n->n_family == RIP_AF_UNSPEC
|
&& n->n_metric >= ifp->int_d_metric)
|
||||||
&& n->n_metric > ifp->int_d_metric)
|
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* We can receive aggregated RIPv2 routes via one
|
/* We can receive aggregated RIPv2 routes that must
|
||||||
* interface that must be broken down before
|
* be broken down before they are transmitted by
|
||||||
* they are transmitted by RIPv1 via an interface
|
* RIPv1 via an interface on a subnet.
|
||||||
* on a subnet. We might receive the same routes
|
* We might also receive the same routes aggregated
|
||||||
* aggregated otherwise via other RIPv2 interfaces.
|
* via other RIPv2 interfaces.
|
||||||
* This could cause duplicate routes to be sent on
|
* This could cause duplicate routes to be sent on
|
||||||
* the RIPv1 interfaces. "Longest matching variable
|
* the RIPv1 interfaces. "Longest matching variable
|
||||||
* length netmasks" lets RIPv2 listeners understand,
|
* length netmasks" lets RIPv2 listeners understand,
|
||||||
@ -521,9 +517,12 @@ input(struct sockaddr_in *from, /* received from this IP address */
|
|||||||
*
|
*
|
||||||
* Notice that this does not break down network
|
* Notice that this does not break down network
|
||||||
* routes corresponding to subnets. This is part
|
* routes corresponding to subnets. This is part
|
||||||
* of the defense against RS_NET_SUB.
|
* of the defense against RS_NET_SYN.
|
||||||
*/
|
*/
|
||||||
if (0 != (ntohl(dst) & (v1_mask & ~mask))) {
|
if (have_ripv1_out
|
||||||
|
&& (v1_mask = ripv1_mask_net(dst,0)) > mask
|
||||||
|
&& (((rt = rtget(dst,mask)) == 0
|
||||||
|
|| !(rt->rt_state & RS_NET_SYN)))) {
|
||||||
ddst_h = v1_mask & -v1_mask;
|
ddst_h = v1_mask & -v1_mask;
|
||||||
i = (v1_mask & ~mask)/ddst_h;
|
i = (v1_mask & ~mask)/ddst_h;
|
||||||
if (i >= 1024) {
|
if (i >= 1024) {
|
||||||
@ -546,8 +545,7 @@ input(struct sockaddr_in *from, /* received from this IP address */
|
|||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
input_route(ifp, FROM_NADDR,
|
input_route(ifp, FROM_NADDR,
|
||||||
dst, mask, gate,
|
dst, mask, gate, n);
|
||||||
n->n_metric, n->n_tag);
|
|
||||||
if (i-- == 0)
|
if (i-- == 0)
|
||||||
break;
|
break;
|
||||||
dst = htonl(ntohl(dst) + ddst_h);
|
dst = htonl(ntohl(dst) + ddst_h);
|
||||||
@ -566,8 +564,7 @@ input_route(struct interface *ifp,
|
|||||||
naddr dst,
|
naddr dst,
|
||||||
naddr mask,
|
naddr mask,
|
||||||
naddr gate,
|
naddr gate,
|
||||||
int metric,
|
struct netinfo *n)
|
||||||
u_short tag)
|
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
struct rt_entry *rt;
|
struct rt_entry *rt;
|
||||||
@ -594,19 +591,18 @@ input_route(struct interface *ifp,
|
|||||||
/* Consider adding the route if we do not already have it.
|
/* Consider adding the route if we do not already have it.
|
||||||
*/
|
*/
|
||||||
if (rt == 0) {
|
if (rt == 0) {
|
||||||
/* Usually ignore routes being poisoned.
|
/* Ignore unknown routes being poisoned.
|
||||||
*/
|
*/
|
||||||
if (metric == HOPCNT_INFINITY)
|
if (n->n_metric == HOPCNT_INFINITY)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
rtadd(dst, mask, gate, from, metric, tag, 0, ifp);
|
rtadd(dst, mask, gate, from, n->n_metric, n->n_tag, 0, ifp);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* We already know about the route. Consider
|
/* We already know about the route. Consider this update.
|
||||||
* this update.
|
|
||||||
*
|
*
|
||||||
* If (rt->rt_state & RS_NET_SUB), then this route
|
* If (rt->rt_state & RS_NET_SYN), then this route
|
||||||
* is the same as a network route we have inferred
|
* is the same as a network route we have inferred
|
||||||
* for subnets we know, in order to tell RIPv1 routers
|
* for subnets we know, in order to tell RIPv1 routers
|
||||||
* about the subnets.
|
* about the subnets.
|
||||||
@ -633,7 +629,7 @@ input_route(struct interface *ifp,
|
|||||||
* other than the current slot.
|
* other than the current slot.
|
||||||
*/
|
*/
|
||||||
if (rts0 == rt->rt_spares
|
if (rts0 == rt->rt_spares
|
||||||
|| BETTER_LINK(rts0, rts))
|
|| BETTER_LINK(rt, rts0, rts))
|
||||||
rts0 = rts;
|
rts0 = rts;
|
||||||
}
|
}
|
||||||
if (i != 0) {
|
if (i != 0) {
|
||||||
@ -641,26 +637,21 @@ input_route(struct interface *ifp,
|
|||||||
*/
|
*/
|
||||||
int old_metric = rts->rts_metric;
|
int old_metric = rts->rts_metric;
|
||||||
|
|
||||||
if (old_metric < HOPCNT_INFINITY) {
|
/* Keep poisoned routes around only long
|
||||||
|
* enough to pass the poison on.
|
||||||
|
*/
|
||||||
|
if (old_metric < HOPCNT_INFINITY)
|
||||||
new_time = now.tv_sec;
|
new_time = now.tv_sec;
|
||||||
} else {
|
|
||||||
/* Keep poisoned routes around only long
|
|
||||||
* enough to pass the poison on.
|
|
||||||
*/
|
|
||||||
new_time = rts->rts_time;
|
|
||||||
if (new_time > now.tv_sec-POISON_SECS)
|
|
||||||
new_time = now.tv_sec-POISON_SECS;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 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, gate,rt->rt_router,
|
||||||
metric, tag, ifp, new_time, 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 (metric > old_metric)
|
if (n->n_metric > old_metric)
|
||||||
rtswitch(rt, 0);
|
rtswitch(rt, 0);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -669,8 +660,8 @@ input_route(struct interface *ifp,
|
|||||||
* Finished if the route is unchanged.
|
* Finished if the route is unchanged.
|
||||||
*/
|
*/
|
||||||
if (rts->rts_gate == gate
|
if (rts->rts_gate == gate
|
||||||
&& old_metric == metric
|
&& old_metric == n->n_metric
|
||||||
&& rts->rts_tag == tag) {
|
&& rts->rts_tag == n->n_tag) {
|
||||||
rts->rts_time = new_time;
|
rts->rts_time = new_time;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -684,20 +675,20 @@ input_route(struct interface *ifp,
|
|||||||
/* Save the route as a spare only if it has
|
/* Save the route as a spare only if it has
|
||||||
* a better metric than our worst spare.
|
* a better metric than our worst spare.
|
||||||
* This also ignores poisoned routes (those
|
* This also ignores poisoned routes (those
|
||||||
* with metric HOPCNT_INFINITY).
|
* received with metric HOPCNT_INFINITY).
|
||||||
*/
|
*/
|
||||||
if (metric >= rts->rts_metric)
|
if (n->n_metric >= rts->rts_metric)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
new_time = now.tv_sec;
|
new_time = now.tv_sec;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (TRACEACTIONS)
|
trace_upslot(rt, rts, gate, from, ifp, n->n_metric,n->n_tag, new_time);
|
||||||
trace_upslot(rt, rts, gate, from, ifp, metric, tag, new_time);
|
|
||||||
rts->rts_gate = gate;
|
rts->rts_gate = gate;
|
||||||
rts->rts_router = from;
|
rts->rts_router = from;
|
||||||
rts->rts_metric = metric;
|
rts->rts_metric = n->n_metric;
|
||||||
rts->rts_tag = tag;
|
rts->rts_tag = n->n_tag;
|
||||||
rts->rts_time = new_time;
|
rts->rts_time = new_time;
|
||||||
rts->rts_ifp = ifp;
|
rts->rts_ifp = ifp;
|
||||||
|
|
||||||
|
@ -31,15 +31,14 @@
|
|||||||
* SUCH DAMAGE.
|
* SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef lint
|
char copyright[] =
|
||||||
static char copyright[] =
|
|
||||||
"@(#) Copyright (c) 1983, 1988, 1993\n\
|
"@(#) Copyright (c) 1983, 1988, 1993\n\
|
||||||
The Regents of the University of California. All rights reserved.\n";
|
The Regents of the University of California. All rights reserved.\n";
|
||||||
|
#if !defined(lint) && !defined(sgi)
|
||||||
static char sccsid[] = "@(#)main.c 8.1 (Berkeley) 6/5/93";
|
static char sccsid[] = "@(#)main.c 8.1 (Berkeley) 6/5/93";
|
||||||
#endif /* not lint */
|
#endif /* not lint */
|
||||||
|
|
||||||
#ident "$Revision: 1.2 $"
|
#ident "$Revision: 1.13 $"
|
||||||
|
|
||||||
#include "defs.h"
|
#include "defs.h"
|
||||||
#include "pathnames.h"
|
#include "pathnames.h"
|
||||||
@ -62,7 +61,6 @@ int ipforwarding = 1; /* kernel forwarding on */
|
|||||||
int default_gateway; /* 1=advertise default */
|
int default_gateway; /* 1=advertise default */
|
||||||
int background = 1;
|
int background = 1;
|
||||||
int ridhosts; /* 1=reduce host routes */
|
int ridhosts; /* 1=reduce host routes */
|
||||||
int ppp_noage; /* do not age routes on quiet links */
|
|
||||||
int mhome; /* 1=want multi-homed host route */
|
int mhome; /* 1=want multi-homed host route */
|
||||||
int advertise_mhome; /* 1=must continue adverising it */
|
int advertise_mhome; /* 1=must continue adverising it */
|
||||||
int auth_ok = 1; /* 1=ignore auth if we do not care */
|
int auth_ok = 1; /* 1=ignore auth if we do not care */
|
||||||
@ -94,12 +92,12 @@ 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;
|
||||||
struct timeval wtime, wtime2;
|
struct timeval wtime, t2;
|
||||||
time_t dt;
|
time_t dt;
|
||||||
fd_set ibits;
|
fd_set ibits;
|
||||||
naddr p_addr_h, p_mask;
|
naddr p_addr, p_mask;
|
||||||
struct parm *parmp;
|
|
||||||
struct interface *ifp;
|
struct interface *ifp;
|
||||||
|
struct parm parm;
|
||||||
char *tracename = 0;
|
char *tracename = 0;
|
||||||
|
|
||||||
|
|
||||||
@ -135,7 +133,13 @@ main(int argc,
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case 'g':
|
case 'g':
|
||||||
default_gateway = 1;
|
bzero(&parm, sizeof(parm));
|
||||||
|
parm.parm_d_metric = 1;
|
||||||
|
p = check_parms(&parm);
|
||||||
|
if (p != 0)
|
||||||
|
msglog("bad -g: %s", p);
|
||||||
|
else
|
||||||
|
default_gateway = 1;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'h': /* suppress extra host routes */
|
case 'h': /* suppress extra host routes */
|
||||||
@ -146,10 +150,6 @@ main(int argc,
|
|||||||
mhome = 1; /* on multi-homed hosts */
|
mhome = 1; /* on multi-homed hosts */
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'p': /* do not age routes on quiet */
|
|
||||||
ppp_noage = 1; /* point-to-point links */
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'A':
|
case 'A':
|
||||||
/* Ignore authentication if we do not care.
|
/* Ignore authentication if we do not care.
|
||||||
* Crazy as it is, that is what RFC 1723 requires.
|
* Crazy as it is, that is what RFC 1723 requires.
|
||||||
@ -171,23 +171,22 @@ main(int argc,
|
|||||||
if (p && *p != '\0') {
|
if (p && *p != '\0') {
|
||||||
n = (int)strtoul(p+1, &q, 0);
|
n = (int)strtoul(p+1, &q, 0);
|
||||||
if (*q == '\0'
|
if (*q == '\0'
|
||||||
&& n <= HOPCNT_INFINITY-2
|
&& n <= HOPCNT_INFINITY-1
|
||||||
&& n >= 1)
|
&& n >= 1)
|
||||||
*p = '\0';
|
*p = '\0';
|
||||||
}
|
}
|
||||||
if (!getnet(optarg, &p_addr_h, &p_mask)) {
|
if (!getnet(optarg, &p_addr, &p_mask)) {
|
||||||
msglog("routed: bad network;"
|
msglog("bad network; \"-F %s\"",
|
||||||
" \"-F %s\" ignored",
|
|
||||||
optarg);
|
optarg);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
parmp = (struct parm*)malloc(sizeof(*parmp));
|
bzero(&parm, sizeof(parm));
|
||||||
bzero(parmp, sizeof(*parmp));
|
parm.parm_addr_h = ntohl(p_addr);
|
||||||
parmp->parm_next = parms;
|
parm.parm_mask = p_mask;
|
||||||
parms = parmp;
|
parm.parm_d_metric = n;
|
||||||
parmp->parm_a_h = p_addr_h;
|
p = check_parms(&parm);
|
||||||
parmp->parm_m = p_mask;
|
if (p != 0)
|
||||||
parmp->parm_d_metric = n;
|
msglog("bad -F: %s", p);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'P':
|
case 'P':
|
||||||
@ -195,10 +194,9 @@ main(int argc,
|
|||||||
* parameters.
|
* parameters.
|
||||||
*/
|
*/
|
||||||
p = parse_parms(optarg);
|
p = parse_parms(optarg);
|
||||||
if (p != 0) {
|
if (p != 0)
|
||||||
msglog("routed: bad \"%s\" in \"%s\"",
|
msglog("bad \"%s\" in \"%s\"",
|
||||||
p, optarg);
|
p, optarg);
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@ -217,6 +215,8 @@ main(int argc,
|
|||||||
logbad(0, "usage: routed [-sqdghmpAt] [-T /tracefile]"
|
logbad(0, "usage: routed [-sqdghmpAt] [-T /tracefile]"
|
||||||
" [-F net[,metric]] [-P parms]");
|
" [-F net[,metric]] [-P parms]");
|
||||||
}
|
}
|
||||||
|
if (geteuid() != 0)
|
||||||
|
logbad(0, "requires UID 0");
|
||||||
|
|
||||||
mib[0] = CTL_NET;
|
mib[0] = CTL_NET;
|
||||||
mib[1] = PF_INET;
|
mib[1] = PF_INET;
|
||||||
@ -249,7 +249,10 @@ main(int argc,
|
|||||||
/* get into the background */
|
/* get into the background */
|
||||||
if (background) {
|
if (background) {
|
||||||
#ifdef sgi
|
#ifdef sgi
|
||||||
if (_daemonize(_DF_NOCHDIR,STDOUT_FILENO,STDERR_FILENO,-1)<0)
|
if (0 > _daemonize(_DF_NOCHDIR,
|
||||||
|
new_tracelevel == 0 ? -1 : STDOUT_FILENO,
|
||||||
|
new_tracelevel == 0 ? -1 : STDERR_FILENO,
|
||||||
|
-1))
|
||||||
BADERR(0, "_daemonize()");
|
BADERR(0, "_daemonize()");
|
||||||
#else
|
#else
|
||||||
if (daemon(1, 1) < 0)
|
if (daemon(1, 1) < 0)
|
||||||
@ -286,7 +289,7 @@ main(int argc,
|
|||||||
ftrace = 0;
|
ftrace = 0;
|
||||||
if (tracename != 0) {
|
if (tracename != 0) {
|
||||||
trace_on(tracename, 1);
|
trace_on(tracename, 1);
|
||||||
if (new_tracelevel == 0)
|
if (new_tracelevel == 0) /* use stdout if file is bad */
|
||||||
new_tracelevel = 1;
|
new_tracelevel = 1;
|
||||||
}
|
}
|
||||||
set_tracelevel();
|
set_tracelevel();
|
||||||
@ -314,15 +317,6 @@ main(int argc,
|
|||||||
signal(SIGUSR1, sigtrace_on);
|
signal(SIGUSR1, sigtrace_on);
|
||||||
signal(SIGUSR2, sigtrace_off);
|
signal(SIGUSR2, sigtrace_off);
|
||||||
|
|
||||||
/* If we have an interface to the wide, wide world, add an entry for
|
|
||||||
* an Internet default route to the internal tables and advertise it.
|
|
||||||
* This route is not added to the kernel routes, but this entry
|
|
||||||
* prevents us from listening to default routes from other
|
|
||||||
* systems and installing them in the kernel.
|
|
||||||
*/
|
|
||||||
if (default_gateway > 0)
|
|
||||||
rtadd(RIP_DEFAULT, 0, myaddr, myaddr, 1, 0, RS_GW, 0);
|
|
||||||
|
|
||||||
/* Collect an initial view of the world by checking the interface
|
/* Collect an initial view of the world by checking the interface
|
||||||
* configuration and the kludge file.
|
* configuration and the kludge file.
|
||||||
*/
|
*/
|
||||||
@ -340,16 +334,16 @@ main(int argc,
|
|||||||
for (;;) {
|
for (;;) {
|
||||||
prev_clk = clk;
|
prev_clk = clk;
|
||||||
gettimeofday(&clk, 0);
|
gettimeofday(&clk, 0);
|
||||||
timevalsub(&wtime2, &clk, &prev_clk);
|
timevalsub(&t2, &clk, &prev_clk);
|
||||||
if (wtime2.tv_sec < 0
|
if (t2.tv_sec < 0
|
||||||
|| wtime2.tv_sec > wtime.tv_sec + 5) {
|
|| t2.tv_sec > wtime.tv_sec + 5) {
|
||||||
/* Deal with time changes before other housekeeping to
|
/* Deal with time changes before other housekeeping to
|
||||||
* keep everything straight.
|
* keep everything straight.
|
||||||
*/
|
*/
|
||||||
dt = wtime2.tv_sec;
|
dt = t2.tv_sec;
|
||||||
if (dt > 0)
|
if (dt > 0)
|
||||||
dt -= wtime.tv_sec;
|
dt -= wtime.tv_sec;
|
||||||
trace_msg("time changed by %d sec\n", dt);
|
trace_act("time changed by %d sec\n", dt);
|
||||||
epoch.tv_sec += dt;
|
epoch.tv_sec += dt;
|
||||||
}
|
}
|
||||||
timevalsub(&now, &clk, &epoch);
|
timevalsub(&now, &clk, &epoch);
|
||||||
@ -364,13 +358,14 @@ main(int argc,
|
|||||||
rip_bcast(0);
|
rip_bcast(0);
|
||||||
rdisc_adv();
|
rdisc_adv();
|
||||||
}
|
}
|
||||||
trace_off("exiting","");
|
trace_off("exiting with signal %d\n", stopint);
|
||||||
exit(stopint | 128);
|
exit(stopint | 128);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* look for new or dead interfaces */
|
/* look for new or dead interfaces */
|
||||||
timevalsub(&wtime, &ifinit_timer, &now);
|
timevalsub(&wtime, &ifinit_timer, &now);
|
||||||
if (wtime.tv_sec <= 0) {
|
if (wtime.tv_sec <= 0) {
|
||||||
|
wtime.tv_sec = 0;
|
||||||
ifinit();
|
ifinit();
|
||||||
rip_query();
|
rip_query();
|
||||||
continue;
|
continue;
|
||||||
@ -379,8 +374,8 @@ main(int argc,
|
|||||||
/* If it is time, then broadcast our routes.
|
/* If it is time, then broadcast our routes.
|
||||||
*/
|
*/
|
||||||
if (supplier || advertise_mhome) {
|
if (supplier || advertise_mhome) {
|
||||||
timevalsub(&wtime2, &next_bcast, &now);
|
timevalsub(&t2, &next_bcast, &now);
|
||||||
if (wtime2.tv_sec <= 0) {
|
if (t2.tv_sec <= 0) {
|
||||||
/* Synchronize the aging and broadcast
|
/* Synchronize the aging and broadcast
|
||||||
* timers to minimize awakenings
|
* timers to minimize awakenings
|
||||||
*/
|
*/
|
||||||
@ -398,14 +393,14 @@ main(int argc,
|
|||||||
* pick a 30-second aniversary of the
|
* pick a 30-second aniversary of the
|
||||||
* original broadcast time.
|
* original broadcast time.
|
||||||
*/
|
*/
|
||||||
n = 1 + (0-wtime2.tv_sec)/SUPPLY_INTERVAL;
|
n = 1 + (0-t2.tv_sec)/SUPPLY_INTERVAL;
|
||||||
next_bcast.tv_sec += n*SUPPLY_INTERVAL;
|
next_bcast.tv_sec += n*SUPPLY_INTERVAL;
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (timercmp(&wtime2, &wtime, <))
|
if (timercmp(&t2, &wtime, <))
|
||||||
wtime = wtime2;
|
wtime = t2;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If we need a flash update, either do it now or
|
/* If we need a flash update, either do it now or
|
||||||
@ -420,30 +415,30 @@ main(int argc,
|
|||||||
/* accurate to the millisecond */
|
/* accurate to the millisecond */
|
||||||
if (!timercmp(&no_flash, &now, >))
|
if (!timercmp(&no_flash, &now, >))
|
||||||
rip_bcast(1);
|
rip_bcast(1);
|
||||||
timevalsub(&wtime2, &no_flash, &now);
|
timevalsub(&t2, &no_flash, &now);
|
||||||
if (timercmp(&wtime2, &wtime, <))
|
if (timercmp(&t2, &wtime, <))
|
||||||
wtime = wtime2;
|
wtime = t2;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* trigger the main aging timer.
|
/* trigger the main aging timer.
|
||||||
*/
|
*/
|
||||||
timevalsub(&wtime2, &age_timer, &now);
|
timevalsub(&t2, &age_timer, &now);
|
||||||
if (wtime2.tv_sec <= 0) {
|
if (t2.tv_sec <= 0) {
|
||||||
age(0);
|
age(0);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (timercmp(&wtime2, &wtime, <))
|
if (timercmp(&t2, &wtime, <))
|
||||||
wtime = wtime2;
|
wtime = t2;
|
||||||
|
|
||||||
/* update the kernel routing table
|
/* update the kernel routing table
|
||||||
*/
|
*/
|
||||||
timevalsub(&wtime2, &need_kern, &now);
|
timevalsub(&t2, &need_kern, &now);
|
||||||
if (wtime2.tv_sec <= 0) {
|
if (t2.tv_sec <= 0) {
|
||||||
age(0);
|
age(0);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (timercmp(&wtime2, &wtime, <))
|
if (timercmp(&t2, &wtime, <))
|
||||||
wtime = wtime2;
|
wtime = t2;
|
||||||
|
|
||||||
/* take care of router discovery,
|
/* take care of router discovery,
|
||||||
* but do it to the millisecond
|
* but do it to the millisecond
|
||||||
@ -452,15 +447,15 @@ main(int argc,
|
|||||||
rdisc_age(0);
|
rdisc_age(0);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
timevalsub(&wtime2, &rdisc_timer, &now);
|
timevalsub(&t2, &rdisc_timer, &now);
|
||||||
if (timercmp(&wtime2, &wtime, <))
|
if (timercmp(&t2, &wtime, <))
|
||||||
wtime = wtime2;
|
wtime = t2;
|
||||||
|
|
||||||
|
|
||||||
/* wait for input or a timer to expire.
|
/* wait for input or a timer to expire.
|
||||||
*/
|
*/
|
||||||
ibits = fdbits;
|
|
||||||
trace_flush();
|
trace_flush();
|
||||||
|
ibits = fdbits;
|
||||||
n = select(sock_max, &ibits, 0, 0, &wtime);
|
n = select(sock_max, &ibits, 0, 0, &wtime);
|
||||||
if (n <= 0) {
|
if (n <= 0) {
|
||||||
if (n < 0 && errno != EINTR && errno != EAGAIN)
|
if (n < 0 && errno != EINTR && errno != EAGAIN)
|
||||||
@ -500,6 +495,7 @@ sigalrm(int sig)
|
|||||||
* new and broken interfaces.
|
* new and broken interfaces.
|
||||||
*/
|
*/
|
||||||
ifinit_timer.tv_sec = now.tv_sec;
|
ifinit_timer.tv_sec = now.tv_sec;
|
||||||
|
trace_act("SIGALRM\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -569,7 +565,7 @@ fix_sock(int sock,
|
|||||||
for (rbuf = 60*1024; ; rbuf -= 4096) {
|
for (rbuf = 60*1024; ; rbuf -= 4096) {
|
||||||
if (setsockopt(sock, SOL_SOCKET, SO_RCVBUF,
|
if (setsockopt(sock, SOL_SOCKET, SO_RCVBUF,
|
||||||
&rbuf, sizeof(rbuf)) == 0) {
|
&rbuf, sizeof(rbuf)) == 0) {
|
||||||
trace_msg("RCVBUF=%d\n", rbuf);
|
trace_act("RCVBUF=%d\n", rbuf);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (rbuf < MIN_SOCKBUF) {
|
if (rbuf < MIN_SOCKBUF) {
|
||||||
@ -627,8 +623,8 @@ rip_off(void)
|
|||||||
register naddr addr;
|
register naddr addr;
|
||||||
|
|
||||||
|
|
||||||
if (rip_sock >= 0) {
|
if (rip_sock >= 0 && !mhome) {
|
||||||
trace_msg("turn off RIP\n");
|
trace_act("turn off RIP\n");
|
||||||
|
|
||||||
(void)close(rip_sock);
|
(void)close(rip_sock);
|
||||||
rip_sock = -1;
|
rip_sock = -1;
|
||||||
@ -652,36 +648,49 @@ rip_off(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* turn on RIP multicast input via an interface
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
rip_mcast_on(struct interface *ifp)
|
||||||
|
{
|
||||||
|
struct ip_mreq m;
|
||||||
|
|
||||||
|
if (!IS_RIP_IN_OFF(ifp->int_state)
|
||||||
|
&& (ifp->int_if_flags & IFF_MULTICAST)
|
||||||
|
#ifdef MCAST_PPP_BUG
|
||||||
|
&& !(ifp->int_if_flags & IFF_POINTOPOINT)
|
||||||
|
#endif
|
||||||
|
&& !(ifp->int_state & IS_ALIAS)) {
|
||||||
|
m.imr_multiaddr.s_addr = htonl(INADDR_RIP_GROUP);
|
||||||
|
m.imr_interface.s_addr = ((ifp->int_if_flags & IFF_POINTOPOINT)
|
||||||
|
? ifp->int_dstaddr
|
||||||
|
: ifp->int_addr);
|
||||||
|
if (setsockopt(rip_sock,IPPROTO_IP, IP_ADD_MEMBERSHIP,
|
||||||
|
&m, sizeof(m)) < 0)
|
||||||
|
LOGERR("setsockopt(IP_ADD_MEMBERSHIP RIP)");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Prepare socket used for RIP.
|
/* Prepare socket used for RIP.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
rip_on(struct interface *ifp)
|
rip_on(struct interface *ifp)
|
||||||
{
|
{
|
||||||
struct ip_mreq m;
|
/* If the main RIP socket is already alive, only start receiving
|
||||||
|
* multicasts for this interface.
|
||||||
|
*/
|
||||||
if (rip_sock >= 0) {
|
if (rip_sock >= 0) {
|
||||||
if (ifp != 0
|
if (ifp != 0)
|
||||||
&& 0 == (ifp->int_state & (IS_NO_RIP_IN|IS_PASSIVE))
|
rip_mcast_on(ifp);
|
||||||
&& (ifp->int_if_flags & IFF_MULTICAST)
|
|
||||||
#ifdef MCAST_PPP_BUG
|
|
||||||
&& !(ifp->int_if_flags & IFF_POINTOPOINT)
|
|
||||||
#endif
|
|
||||||
&& !(ifp->int_state & IS_ALIAS)) {
|
|
||||||
m.imr_multiaddr.s_addr = htonl(INADDR_RIP_GROUP);
|
|
||||||
m.imr_interface.s_addr = ((ifp->int_if_flags
|
|
||||||
& IFF_POINTOPOINT)
|
|
||||||
? ifp->int_dstaddr
|
|
||||||
: ifp->int_addr);
|
|
||||||
if (setsockopt(rip_sock,IPPROTO_IP, IP_ADD_MEMBERSHIP,
|
|
||||||
&m, sizeof(m)) < 0)
|
|
||||||
DBGERR(1,"setsockopt(IP_ADD_MEMBERSHIP RIP)");
|
|
||||||
}
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* If the main RIP socket is off, and it makes sense to turn it on,
|
||||||
|
* turn it on for all of the interfaces.
|
||||||
|
*/
|
||||||
if (rip_interfaces > 0 && !rdisc_ok) {
|
if (rip_interfaces > 0 && !rdisc_ok) {
|
||||||
trace_msg("turn on RIP\n");
|
trace_act("turn on RIP\n");
|
||||||
|
|
||||||
/* Close all of the query sockets so that we can open
|
/* Close all of the query sockets so that we can open
|
||||||
* the main socket. SO_REUSEPORT is not a solution,
|
* the main socket. SO_REUSEPORT is not a solution,
|
||||||
@ -704,18 +713,9 @@ rip_on(struct interface *ifp)
|
|||||||
next_bcast.tv_sec = now.tv_sec+MIN_WAITTIME;
|
next_bcast.tv_sec = now.tv_sec+MIN_WAITTIME;
|
||||||
|
|
||||||
for (ifp = ifnet; ifp != 0; ifp = ifp->int_next) {
|
for (ifp = ifnet; ifp != 0; ifp = ifp->int_next) {
|
||||||
if ((ifp->int_state & IS_NO_RIP_IN) != IS_NO_RIP_IN)
|
if (!IS_RIP_IN_OFF(ifp->int_state))
|
||||||
ifp->int_state &= ~IS_RIP_QUERIED;
|
ifp->int_state &= ~IS_RIP_QUERIED;
|
||||||
|
rip_mcast_on(ifp);
|
||||||
if ((ifp->int_if_flags & IFF_MULTICAST)
|
|
||||||
&& !(ifp->int_state & IS_ALIAS)) {
|
|
||||||
m.imr_multiaddr.s_addr = htonl(INADDR_RIP_GROUP);
|
|
||||||
m.imr_interface.s_addr = ifp->int_addr;
|
|
||||||
if (setsockopt(rip_sock, IPPROTO_IP,
|
|
||||||
IP_ADD_MEMBERSHIP,
|
|
||||||
&m, sizeof(m)) < 0)
|
|
||||||
DBGERR(1,"setsockopt(IP_ADD_MEMBERSHIP RIP)");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ifinit_timer.tv_sec = now.tv_sec;
|
ifinit_timer.tv_sec = now.tv_sec;
|
||||||
|
@ -31,11 +31,11 @@
|
|||||||
* SUCH DAMAGE.
|
* SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef lint
|
#if !defined(lint) && !defined(sgi)
|
||||||
static char sccsid[] = "@(#)output.c 8.1 (Berkeley) 6/5/93";
|
static char sccsid[] = "@(#)output.c 8.1 (Berkeley) 6/5/93";
|
||||||
#endif /* not lint */
|
#endif /* not lint */
|
||||||
|
|
||||||
#ident "$Revision: 1.1 $"
|
#ident "$Revision: 1.14 $"
|
||||||
|
|
||||||
#include "defs.h"
|
#include "defs.h"
|
||||||
|
|
||||||
@ -52,31 +52,33 @@ struct {
|
|||||||
naddr to_std_mask;
|
naddr to_std_mask;
|
||||||
naddr to_std_net;
|
naddr to_std_net;
|
||||||
struct interface *ifp; /* usually output interface */
|
struct interface *ifp; /* usually output interface */
|
||||||
struct ws_buf { /* for each buffer */
|
struct ws_buf { /* info for each buffer */
|
||||||
struct rip *buf;
|
struct rip *buf;
|
||||||
struct netinfo *n;
|
struct netinfo *n;
|
||||||
struct netinfo *base;
|
struct netinfo *base;
|
||||||
struct netinfo *lim;
|
struct netinfo *lim;
|
||||||
enum output_type type;
|
enum output_type type;
|
||||||
} v2, mcast;
|
} v12, v2;
|
||||||
char metric; /* adjust metrics by interface */
|
char metric; /* adjust metrics by interface */
|
||||||
int npackets;
|
int npackets;
|
||||||
int state;
|
u_int state;
|
||||||
#define WS_ST_FLASH 0x01 /* send only changed routes */
|
#define WS_ST_FLASH 0x001 /* send only changed routes */
|
||||||
#define WS_ST_RIP2_SAFE 0x02 /* send RIPv2 safe for RIPv1 */
|
#define WS_ST_RIP2_SAFE 0x002 /* send RIPv2 safe for RIPv1 */
|
||||||
#define WS_ST_RIP2_ALL 0x04 /* full featured RIPv2 */
|
#define WS_ST_RIP2_ALL 0x004 /* send full featured RIPv2 */
|
||||||
#define WS_ST_AG 0x08 /* ok to aggregate subnets */
|
#define WS_ST_AG 0x008 /* ok to aggregate subnets */
|
||||||
#define WS_ST_SUPER_AG 0x10 /* ok to aggregate networks */
|
#define WS_ST_SUPER_AG 0x010 /* ok to aggregate networks */
|
||||||
#define WS_ST_QUERY 0x20 /* responding to a query */
|
#define WS_ST_SUB_AG 0x020 /* aggregate subnets in odd case */
|
||||||
#define WS_ST_TO_ON_NET 0x40 /* sending onto one of our nets */
|
#define WS_ST_QUERY 0x040 /* responding to a query */
|
||||||
#define WS_ST_DEFAULT 0x80 /* faking a default */
|
#define WS_ST_TO_ON_NET 0x080 /* sending onto one of our nets */
|
||||||
|
#define WS_ST_DEFAULT 0x100 /* faking a default */
|
||||||
|
#define WS_ST_PM_RDISC 0x200 /* poor-man's router discovery */
|
||||||
} ws;
|
} 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 */
|
||||||
union pkt_buf ripv2_buf;
|
union pkt_buf ripv12_buf;
|
||||||
|
|
||||||
/* Another for only RIPv2 listeners */
|
/* Another for only RIPv2 listeners */
|
||||||
union pkt_buf rip_mcast_buf;
|
union pkt_buf rip_v2_buf;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -92,9 +94,10 @@ output(enum output_type type,
|
|||||||
struct sockaddr_in sin;
|
struct sockaddr_in sin;
|
||||||
int flags;
|
int flags;
|
||||||
char *msg;
|
char *msg;
|
||||||
int res, serrno;
|
int res;
|
||||||
naddr tgt_mcast;
|
naddr tgt_mcast;
|
||||||
int soc;
|
int soc;
|
||||||
|
int serrno;
|
||||||
|
|
||||||
sin = *dst;
|
sin = *dst;
|
||||||
if (sin.sin_port == 0)
|
if (sin.sin_port == 0)
|
||||||
@ -106,7 +109,7 @@ output(enum output_type type,
|
|||||||
|
|
||||||
soc = rip_sock;
|
soc = rip_sock;
|
||||||
flags = 0;
|
flags = 0;
|
||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case OUT_QUERY:
|
case OUT_QUERY:
|
||||||
msg = "Answer Query";
|
msg = "Answer Query";
|
||||||
@ -121,15 +124,20 @@ output(enum output_type type,
|
|||||||
break;
|
break;
|
||||||
case OUT_BROADCAST:
|
case OUT_BROADCAST:
|
||||||
if (ifp->int_if_flags & IFF_POINTOPOINT) {
|
if (ifp->int_if_flags & IFF_POINTOPOINT) {
|
||||||
msg = "Send pt-to-pt";
|
|
||||||
} else {
|
|
||||||
msg = "Send";
|
msg = "Send";
|
||||||
|
} else {
|
||||||
|
msg = "Send bcast";
|
||||||
}
|
}
|
||||||
flags = MSG_DONTROUTE;
|
flags = MSG_DONTROUTE;
|
||||||
break;
|
break;
|
||||||
case OUT_MULTICAST:
|
case OUT_MULTICAST:
|
||||||
if (ifp->int_if_flags & IFF_POINTOPOINT) {
|
if (ifp->int_if_flags & IFF_POINTOPOINT) {
|
||||||
msg = "Send pt-to-pt";
|
msg = "Send pt-to-pt";
|
||||||
|
} else if (ifp->int_state & IS_DUP) {
|
||||||
|
trace_act("abort multicast output via %s"
|
||||||
|
" with duplicate address\n",
|
||||||
|
ifp->int_name);
|
||||||
|
return 0;
|
||||||
} else {
|
} else {
|
||||||
msg = "Send mcast";
|
msg = "Send mcast";
|
||||||
if (rip_sock_mcast != ifp) {
|
if (rip_sock_mcast != ifp) {
|
||||||
@ -147,25 +155,31 @@ output(enum output_type type,
|
|||||||
} else
|
} else
|
||||||
#endif
|
#endif
|
||||||
tgt_mcast = ifp->int_addr;
|
tgt_mcast = ifp->int_addr;
|
||||||
if (setsockopt(rip_sock,
|
if (0 > setsockopt(rip_sock,
|
||||||
IPPROTO_IP, IP_MULTICAST_IF,
|
IPPROTO_IP, IP_MULTICAST_IF,
|
||||||
&tgt_mcast, sizeof(tgt_mcast)))
|
&tgt_mcast,
|
||||||
BADERR(1,"setsockopt(rip_sock,"
|
sizeof(tgt_mcast))) {
|
||||||
|
serrno = errno;
|
||||||
|
LOGERR("setsockopt(rip_sock,"
|
||||||
"IP_MULTICAST_IF)");
|
"IP_MULTICAST_IF)");
|
||||||
|
errno = serrno;
|
||||||
|
ifp = 0;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
rip_sock_mcast = ifp;
|
rip_sock_mcast = ifp;
|
||||||
}
|
}
|
||||||
sin.sin_addr.s_addr = htonl(INADDR_RIP_GROUP);
|
sin.sin_addr.s_addr = htonl(INADDR_RIP_GROUP);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (TRACEPACKETS)
|
trace_rip(msg, "to", &sin, ifp, buf, size);
|
||||||
trace_rip(msg, "to", &sin, ifp, buf, size);
|
|
||||||
|
|
||||||
res = sendto(soc, buf, size, flags,
|
res = sendto(soc, buf, size, flags,
|
||||||
(struct sockaddr *)&sin, sizeof(sin));
|
(struct sockaddr *)&sin, sizeof(sin));
|
||||||
if (res < 0) {
|
if (res < 0
|
||||||
|
&& (ifp == 0 || !(ifp->int_state & IS_BROKE))) {
|
||||||
serrno = errno;
|
serrno = errno;
|
||||||
msglog("sendto(%s%s%s.%d): %s",
|
msglog("%s sendto(%s%s%s.%d): %s", msg,
|
||||||
ifp != 0 ? ifp->int_name : "",
|
ifp != 0 ? ifp->int_name : "",
|
||||||
ifp != 0 ? ", " : "",
|
ifp != 0 ? ", " : "",
|
||||||
inet_ntoa(sin.sin_addr),
|
inet_ntoa(sin.sin_addr),
|
||||||
@ -198,27 +212,31 @@ set_auth(struct ws_buf *w)
|
|||||||
/* Send the buffer
|
/* Send the buffer
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
supply_write(struct ws_buf *w)
|
supply_write(struct ws_buf *wb)
|
||||||
{
|
{
|
||||||
/* Output multicast only if legal.
|
/* Output multicast only if legal.
|
||||||
* If we would multcast and it would be illegal, then discard the
|
* If we would multcast and it would be illegal, then discard the
|
||||||
* packet.
|
* packet.
|
||||||
*/
|
*/
|
||||||
if (w != &ws.mcast
|
switch (wb->type) {
|
||||||
|| ((ws.state & WS_ST_RIP2_SAFE)
|
case NO_OUT_MULTICAST:
|
||||||
&& (ws.ifp == 0
|
trace_pkt("skip multicast to %s because impossible\n",
|
||||||
|| (ws.ifp->int_if_flags & IFF_MULTICAST)))) {
|
naddr_ntoa(ws.to.sin_addr.s_addr));
|
||||||
if (output(w->type, &ws.to, ws.ifp, w->buf,
|
break;
|
||||||
((char *)w->n - (char*)w->buf)) < 0
|
case NO_OUT_RIPV2:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
if (output(wb->type, &ws.to, ws.ifp, wb->buf,
|
||||||
|
((char *)wb->n - (char*)wb->buf)) < 0
|
||||||
&& ws.ifp != 0)
|
&& ws.ifp != 0)
|
||||||
ifbad(ws.ifp, 0);
|
if_sick(ws.ifp);
|
||||||
ws.npackets++;
|
ws.npackets++;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
bzero(w->n = w->base, sizeof(*w->n)*NETS_LEN);
|
bzero(wb->n = wb->base, sizeof(*wb->n)*NETS_LEN);
|
||||||
|
if (wb->buf->rip_vers == RIPv2)
|
||||||
if (w->buf->rip_vers == RIPv2)
|
set_auth(wb);
|
||||||
set_auth(w);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -229,35 +247,46 @@ supply_out(struct ag_info *ag)
|
|||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
naddr mask, v1_mask, s_mask, dst_h, ddst_h;
|
naddr mask, v1_mask, s_mask, dst_h, ddst_h;
|
||||||
struct ws_buf *w;
|
struct ws_buf *wb;
|
||||||
|
|
||||||
|
|
||||||
/* Skip this route if doing a flash update and it and the routes
|
/* Skip this route if doing a flash update and it and the routes
|
||||||
* it aggregates have not changed recently.
|
* it aggregates have not changed recently.
|
||||||
*/
|
*/
|
||||||
if (ag->ag_seqno <= update_seqno
|
if (ag->ag_seqno < update_seqno
|
||||||
&& (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),
|
||||||
(ws.state & WS_ST_TO_ON_NET) ? ws.ifp : 0,
|
(ws.state & WS_ST_TO_ON_NET) ? ws.ifp : 0);
|
||||||
0);
|
|
||||||
s_mask = std_mask(htonl(dst_h));
|
s_mask = std_mask(htonl(dst_h));
|
||||||
i = 0;
|
i = 0;
|
||||||
|
|
||||||
/* If we are sending RIPv2 packets that cannot (or must not) be
|
/* If we are sending RIPv2 packets that cannot (or must not) be
|
||||||
* heard by RIPv1 listeners, do not worry about sub- or supernets.
|
* heard by RIPv1 listeners, do not worry about sub- or supernets.
|
||||||
* Subnets (from other networks) can only be sent via multicast.
|
* Subnets (from other networks) can only be sent via multicast.
|
||||||
|
* A pair of subnet routes might have been promoted so that they
|
||||||
|
* are legal to send by RIPv1.
|
||||||
|
* If RIPv1 is off, use the multicast buffer, unless this is the
|
||||||
|
* fake default route and it is acting as a poor-man's router-
|
||||||
|
* discovery mechanism.
|
||||||
*/
|
*/
|
||||||
if ((ws.state & WS_ST_RIP2_ALL)
|
if (((ws.state & WS_ST_RIP2_ALL)
|
||||||
|| ((ag->ag_state & AGS_RIPV2)
|
&& (dst_h != RIP_DEFAULT || !(ws.state & WS_ST_PM_RDISC)))
|
||||||
&& v1_mask != mask)) {
|
|| ((ag->ag_state & AGS_RIPV2) && v1_mask != mask)) {
|
||||||
w = &ws.mcast; /* use the multicast-only buffer */
|
/* use the RIPv2-only buffer */
|
||||||
|
wb = &ws.v2;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
w = &ws.v2;
|
/* use the RIPv1-or-RIPv2 buffer */
|
||||||
|
wb = &ws.v12;
|
||||||
|
|
||||||
/* Convert supernet route into corresponding set of network
|
/* Convert supernet route into corresponding set of network
|
||||||
* routes for RIPv1, but leave non-contiguous netmasks
|
* routes for RIPv1, but leave non-contiguous netmasks
|
||||||
@ -287,21 +316,33 @@ supply_out(struct ag_info *ag)
|
|||||||
}
|
}
|
||||||
|
|
||||||
do {
|
do {
|
||||||
w->n->n_family = RIP_AF_INET;
|
wb->n->n_family = RIP_AF_INET;
|
||||||
w->n->n_dst = htonl(dst_h);
|
wb->n->n_dst = htonl(dst_h);
|
||||||
w->n->n_metric = stopint ? HOPCNT_INFINITY : ag->ag_metric;
|
/* If the route is from router-discovery or we are
|
||||||
HTONL(w->n->n_metric);
|
* shutting down, admit only a bad metric.
|
||||||
if (w->buf->rip_vers == RIPv2) {
|
*/
|
||||||
w->n->n_nhop = ag->ag_gate;
|
wb->n->n_metric = ((stopint || ag->ag_metric < 1)
|
||||||
|
? HOPCNT_INFINITY
|
||||||
|
: ag->ag_metric);
|
||||||
|
HTONL(wb->n->n_metric);
|
||||||
|
if (wb->buf->rip_vers == RIPv2) {
|
||||||
|
if (ag->ag_nhop != 0
|
||||||
|
&& (ws.state & WS_ST_RIP2_SAFE)
|
||||||
|
&& ((ws.state & WS_ST_QUERY)
|
||||||
|
|| (ag->ag_nhop != ws.ifp->int_addr
|
||||||
|
&& on_net(ag->ag_nhop,
|
||||||
|
ws.ifp->int_net,
|
||||||
|
ws.ifp->int_mask))))
|
||||||
|
wb->n->n_nhop = ag->ag_nhop;
|
||||||
if ((ws.state & WS_ST_RIP2_ALL)
|
if ((ws.state & WS_ST_RIP2_ALL)
|
||||||
|| mask != s_mask)
|
|| mask != s_mask)
|
||||||
w->n->n_mask = htonl(mask);
|
wb->n->n_mask = htonl(mask);
|
||||||
w->n->n_tag = ag->ag_tag;
|
wb->n->n_tag = ag->ag_tag;
|
||||||
}
|
}
|
||||||
dst_h += ddst_h;
|
dst_h += ddst_h;
|
||||||
|
|
||||||
if (++w->n >= w->lim)
|
if (++wb->n >= wb->lim)
|
||||||
supply_write(w);
|
supply_write(wb);
|
||||||
} while (i-- != 0);
|
} while (i-- != 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -314,57 +355,119 @@ walk_supply(struct radix_node *rn,
|
|||||||
struct walkarg *w)
|
struct walkarg *w)
|
||||||
{
|
{
|
||||||
#define RT ((struct rt_entry *)rn)
|
#define RT ((struct rt_entry *)rn)
|
||||||
u_short ags;
|
u_short ags = 0;
|
||||||
char metric, pref;
|
char metric, pref;
|
||||||
naddr dst, gate;
|
naddr dst, nhop;
|
||||||
|
|
||||||
|
|
||||||
/* Do not advertise the loopback interface
|
/* Do not advertise the loopback interface
|
||||||
* or external remote interfaces
|
* or external remote interfaces
|
||||||
*/
|
*/
|
||||||
if (RT->rt_ifp != 0
|
if (RT->rt_ifp != 0
|
||||||
&& ((RT->rt_ifp->int_if_flags & IFF_LOOPBACK)
|
&& ((RT->rt_ifp->int_if_flags & IFF_LOOPBACK)
|
||||||
|| (RT->rt_ifp->int_state & IS_EXTERNAL)))
|
|| (RT->rt_ifp->int_state & IS_EXTERNAL))
|
||||||
|
&& !(RT->rt_state & RS_MHOME))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* Do not send a route back to where it came from, except in
|
/* If being quiet about our ability to forward, then
|
||||||
* response to a query. This is "split-horizon".
|
* do not say anything unless responding to a query.
|
||||||
*
|
|
||||||
* That means not advertising back to the same network
|
|
||||||
* and so via the same interface.
|
|
||||||
*/
|
*/
|
||||||
if (RT->rt_ifp == ws.ifp && ws.ifp != 0
|
if (!supplier && !(ws.state & WS_ST_QUERY))
|
||||||
&& !(ws.state & WS_ST_QUERY)
|
|
||||||
&& (ws.state & WS_ST_TO_ON_NET)
|
|
||||||
&& !(RT->rt_state & RS_IF))
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
dst = RT->rt_dst;
|
dst = RT->rt_dst;
|
||||||
|
|
||||||
/* If being quiet about our ability to forward, then
|
/* do not collide with the fake default route */
|
||||||
* do not say anything except our own host number,
|
|
||||||
* unless responding to a query.
|
|
||||||
*/
|
|
||||||
if (!supplier
|
|
||||||
&& (!mhome || myaddr != dst)
|
|
||||||
&& !(ws.state & WS_ST_QUERY))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
ags = 0;
|
|
||||||
|
|
||||||
/* do not override the fake default route */
|
|
||||||
if (dst == RIP_DEFAULT
|
if (dst == RIP_DEFAULT
|
||||||
&& (ws.state & WS_ST_DEFAULT))
|
&& (ws.state & WS_ST_DEFAULT))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (RT_ISHOST(RT)) {
|
if (RT->rt_state & RS_NET_SYN) {
|
||||||
|
if (RT->rt_state & RS_NET_INT) {
|
||||||
|
/* Do not send manual synthetic network routes
|
||||||
|
* into the subnet.
|
||||||
|
*/
|
||||||
|
if (on_net(ws.to.sin_addr.s_addr,
|
||||||
|
ntohl(dst), RT->rt_mask))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
/* Do not send automatic synthetic network routes
|
||||||
|
* if they are not needed becaus no RIPv1 listeners
|
||||||
|
* can hear them.
|
||||||
|
*/
|
||||||
|
if (ws.state & WS_ST_RIP2_ALL)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/* Do not send automatic synthetic network routes to
|
||||||
|
* the real subnet.
|
||||||
|
*/
|
||||||
|
if (on_net(ws.to.sin_addr.s_addr,
|
||||||
|
ntohl(dst), RT->rt_mask))
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
nhop = 0;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
/* Advertise the next hop if this is not a route for one
|
||||||
|
* of our interfaces and the next hop is on the same
|
||||||
|
* network as the target.
|
||||||
|
*/
|
||||||
|
if (!(RT->rt_state & RS_IF)
|
||||||
|
&& RT->rt_gate != myaddr
|
||||||
|
&& RT->rt_gate != loopaddr)
|
||||||
|
nhop = RT->rt_gate;
|
||||||
|
else
|
||||||
|
nhop = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Adjust the outgoing metric by the cost of the link.
|
||||||
|
*/
|
||||||
|
pref = metric = RT->rt_metric + ws.metric;
|
||||||
|
if (pref < HOPCNT_INFINITY) {
|
||||||
|
/* Keep track of the best metric with which the
|
||||||
|
* route has been advertised recently.
|
||||||
|
*/
|
||||||
|
if (RT->rt_poison_metric >= metric
|
||||||
|
|| RT->rt_poison_time <= now_garbage) {
|
||||||
|
RT->rt_poison_time = now.tv_sec;
|
||||||
|
RT->rt_poison_metric = RT->rt_metric;
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
/* Do not advertise stable routes that will be ignored,
|
||||||
|
* unless they are being held down and poisoned. If the
|
||||||
|
* route recently was advertised with a metric that would
|
||||||
|
* have been less than infinity through this interface, we
|
||||||
|
* need to continue to advertise it in order to poison it.
|
||||||
|
*/
|
||||||
|
pref = RT->rt_poison_metric + ws.metric;
|
||||||
|
if (pref >= HOPCNT_INFINITY)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
metric = HOPCNT_INFINITY;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (RT->rt_state & RS_MHOME) {
|
||||||
|
/* retain host route of multi-homed servers */
|
||||||
|
;
|
||||||
|
|
||||||
|
} else if (RT_ISHOST(RT)) {
|
||||||
/* We should always aggregate the host routes
|
/* We should always aggregate the host routes
|
||||||
* for the local end of our point-to-point links.
|
* for the local end of our point-to-point links.
|
||||||
* If we are suppressing host routes, then do so.
|
* If we are suppressing host routes in general, then do so.
|
||||||
|
* Avoid advertising host routes onto their own network,
|
||||||
|
* where they should be handled by proxy-ARP.
|
||||||
*/
|
*/
|
||||||
if ((RT->rt_state & RS_LOCAL)
|
if ((RT->rt_state & RS_LOCAL)
|
||||||
|| ridhosts)
|
|| ridhosts
|
||||||
|
|| (ws.state & WS_ST_SUPER_AG)
|
||||||
|
|| on_net(dst, ws.to_net, ws.to_mask))
|
||||||
ags |= AGS_SUPPRESS;
|
ags |= AGS_SUPPRESS;
|
||||||
|
|
||||||
|
if (ws.state & WS_ST_SUPER_AG)
|
||||||
|
ags |= AGS_PROMOTE;
|
||||||
|
|
||||||
} else if (ws.state & WS_ST_AG) {
|
} else if (ws.state & WS_ST_AG) {
|
||||||
/* Aggregate network routes, if we are allowed.
|
/* Aggregate network routes, if we are allowed.
|
||||||
*/
|
*/
|
||||||
@ -372,82 +475,49 @@ walk_supply(struct radix_node *rn,
|
|||||||
|
|
||||||
/* Generate supernets if allowed.
|
/* Generate supernets if allowed.
|
||||||
* If we can be heard by RIPv1 systems, we will
|
* If we can be heard by RIPv1 systems, we will
|
||||||
* later convert back to ordinary nets. This unifies
|
* later convert back to ordinary nets.
|
||||||
* dealing with received supernets.
|
* This unifies dealing with received supernets.
|
||||||
*/
|
*/
|
||||||
if ((RT->rt_state & RS_SUBNET)
|
if ((RT->rt_state & RS_SUBNET)
|
||||||
|| (ws.state & WS_ST_SUPER_AG))
|
|| (ws.state & WS_ST_SUPER_AG))
|
||||||
ags |= AGS_PROMOTE;
|
ags |= AGS_PROMOTE;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Never aggregate our own interfaces,
|
/* Do not send RIPv1 advertisements of subnets to other
|
||||||
* or the host route for multi-homed servers.
|
* networks. If possible, multicast them by RIPv2.
|
||||||
*/
|
*/
|
||||||
if (0 != (RT->rt_state & (RS_IF | RS_MHOME)))
|
if ((RT->rt_state & RS_SUBNET)
|
||||||
ags &= ~(AGS_SUPPRESS | AGS_PROMOTE);
|
&& !(ws.state & WS_ST_RIP2_ALL)
|
||||||
|
&& !on_net(dst, ws.to_std_net, ws.to_std_mask)) {
|
||||||
|
ags |= AGS_RIPV2 | AGS_PROMOTE;
|
||||||
if (RT->rt_state & RS_SUBNET) {
|
if (ws.state & WS_ST_SUB_AG)
|
||||||
/* Do not send authority routes into the subnet,
|
ags |= AGS_SUPPRESS;
|
||||||
* or when RIP is off.
|
|
||||||
*/
|
|
||||||
if ((RT->rt_state & RS_NET_INT)
|
|
||||||
&& (on_net(dst, ws.to_net, ws.to_mask)
|
|
||||||
|| rip_sock < 0))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
/* Do not send RIPv1 advertisements of subnets to
|
|
||||||
* other networks.
|
|
||||||
*
|
|
||||||
* If possible, multicast them by RIPv2.
|
|
||||||
*/
|
|
||||||
if (!(ws.state & WS_ST_RIP2_ALL)
|
|
||||||
&& !on_net(dst, ws.to_std_net, ws.to_std_mask))
|
|
||||||
ags |= AGS_RIPV2;
|
|
||||||
|
|
||||||
} else if (RT->rt_state & RS_NET_SUB) {
|
|
||||||
/* do not send synthetic network routes if no RIPv1
|
|
||||||
* listeners might hear.
|
|
||||||
*/
|
|
||||||
if (ws.state & WS_ST_RIP2_ALL)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
/* Do not send synthetic network routes on the real subnet */
|
|
||||||
if (on_net(dst, ws.to_std_net, ws.to_std_mask))
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* forget synthetic routes when RIP is off */
|
/* Do not send a route back to where it came from, except in
|
||||||
if (rip_sock < 0 && 0 != (RT->rt_state & RS_NET_S))
|
* response to a query. This is "split-horizon". That means not
|
||||||
return 0;
|
* advertising back to the same network and so via the same interface.
|
||||||
|
*
|
||||||
|
* We want to suppress routes that might have been fragmented
|
||||||
/* Adjust outgoing metric by the cost of the link.
|
* from this route by a RIPv1 router and sent back to us, and so we
|
||||||
* Interface routes have already been adjusted.
|
* cannot forget this route here. Let the split-horizon route
|
||||||
|
* aggregate (suppress) the fragmented routes and then itself be
|
||||||
|
* forgotten.
|
||||||
|
*
|
||||||
|
* Include the routes for both ends of point-to-point interfaces
|
||||||
|
* since the other side presumably knows them as well as we do.
|
||||||
*/
|
*/
|
||||||
pref = metric = RT->rt_metric + ws.metric;
|
if (RT->rt_ifp == ws.ifp && ws.ifp != 0
|
||||||
if (metric >= HOPCNT_INFINITY) {
|
&& !(ws.state & WS_ST_QUERY)
|
||||||
metric = HOPCNT_INFINITY;
|
&& (ws.state & WS_ST_TO_ON_NET)
|
||||||
pref = ((RT->rt_hold_down > now.tv_sec)
|
&& (!(RT->rt_state & RS_IF)
|
||||||
? RT->rt_hold_metric
|
|| ws.ifp->int_if_flags & IFF_POINTOPOINT)) {
|
||||||
: metric);
|
ags |= AGS_SPLIT_HZ;
|
||||||
|
ags &= ~(AGS_PROMOTE | AGS_SUPPRESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Advertise the next hop if this is not a route for one
|
ag_check(dst, RT->rt_mask, 0, nhop, metric, pref,
|
||||||
* of our interfaces and the next hop is on the same
|
|
||||||
* network as the target.
|
|
||||||
*/
|
|
||||||
if ((ws.state & WS_ST_RIP2_SAFE)
|
|
||||||
&& !(RT->rt_state & RS_IF)
|
|
||||||
&& ((ws.state & WS_ST_QUERY)
|
|
||||||
|| (on_net(RT->rt_gate, ws.ifp->int_net, ws.ifp->int_mask)
|
|
||||||
&& RT->rt_gate != ws.ifp->int_addr))) {
|
|
||||||
gate = RT->rt_gate;
|
|
||||||
} else {
|
|
||||||
gate = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
ag_check(dst, RT->rt_mask, gate, metric, pref,
|
|
||||||
RT->rt_seqno, RT->rt_tag, ags, supply_out);
|
RT->rt_seqno, RT->rt_tag, ags, supply_out);
|
||||||
return 0;
|
return 0;
|
||||||
#undef RT
|
#undef RT
|
||||||
@ -466,7 +536,6 @@ supply(struct sockaddr_in *dst,
|
|||||||
{
|
{
|
||||||
static int init = 1;
|
static int init = 1;
|
||||||
struct rt_entry *rt;
|
struct rt_entry *rt;
|
||||||
int metric;
|
|
||||||
|
|
||||||
|
|
||||||
ws.state = 0;
|
ws.state = 0;
|
||||||
@ -482,7 +551,7 @@ supply(struct sockaddr_in *dst,
|
|||||||
ws.state |= WS_ST_TO_ON_NET;
|
ws.state |= WS_ST_TO_ON_NET;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
ws.to_mask = ripv1_mask_net(ws.to.sin_addr.s_addr, 0, 0);
|
ws.to_mask = ripv1_mask_net(ws.to.sin_addr.s_addr, 0);
|
||||||
ws.to_net = ntohl(ws.to.sin_addr.s_addr) & ws.to_mask;
|
ws.to_net = ntohl(ws.to.sin_addr.s_addr) & ws.to_mask;
|
||||||
rt = rtfind(dst->sin_addr.s_addr);
|
rt = rtfind(dst->sin_addr.s_addr);
|
||||||
if (rt)
|
if (rt)
|
||||||
@ -496,45 +565,69 @@ supply(struct sockaddr_in *dst,
|
|||||||
ws.state |= WS_ST_QUERY;
|
ws.state |= WS_ST_QUERY;
|
||||||
|
|
||||||
if ((ws.ifp = ifp) == 0) {
|
if ((ws.ifp = ifp) == 0) {
|
||||||
ws.metric = 0;
|
ws.metric = 1;
|
||||||
} else {
|
} else {
|
||||||
/* Adjust the advertised metric by the outgoing interface
|
/* Adjust the advertised metric by the outgoing interface
|
||||||
* metric, but reduced by 1 to avoid counting this hop
|
* metric.
|
||||||
* twice.
|
|
||||||
*/
|
*/
|
||||||
ws.metric = ifp->int_metric;
|
ws.metric = ifp->int_metric+1;
|
||||||
if (ws.metric > 0)
|
|
||||||
ws.metric--;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (init) {
|
if (init) {
|
||||||
init = 0;
|
init = 0;
|
||||||
|
|
||||||
bzero(&ripv2_buf, sizeof(ripv2_buf));
|
bzero(&ripv12_buf, sizeof(ripv12_buf));
|
||||||
ripv2_buf.rip.rip_cmd = RIPCMD_RESPONSE;
|
ripv12_buf.rip.rip_cmd = RIPCMD_RESPONSE;
|
||||||
ws.v2.buf = &ripv2_buf.rip;
|
ws.v12.buf = &ripv12_buf.rip;
|
||||||
|
ws.v12.base = &ws.v12.buf->rip_nets[0];
|
||||||
|
ws.v12.lim = ws.v12.base + NETS_LEN;
|
||||||
|
|
||||||
|
bzero(&rip_v2_buf, sizeof(rip_v2_buf));
|
||||||
|
rip_v2_buf.rip.rip_cmd = RIPCMD_RESPONSE;
|
||||||
|
rip_v2_buf.rip.rip_vers = RIPv2;
|
||||||
|
ws.v2.buf = &rip_v2_buf.rip;
|
||||||
ws.v2.base = &ws.v2.buf->rip_nets[0];
|
ws.v2.base = &ws.v2.buf->rip_nets[0];
|
||||||
ws.v2.lim = ws.v2.base + NETS_LEN;
|
ws.v2.lim = ws.v2.base + NETS_LEN;
|
||||||
|
|
||||||
bzero(&rip_mcast_buf, sizeof(rip_mcast_buf));
|
|
||||||
rip_mcast_buf.rip.rip_cmd = RIPCMD_RESPONSE;
|
|
||||||
rip_mcast_buf.rip.rip_vers = RIPv2;
|
|
||||||
ws.mcast.buf = &rip_mcast_buf.rip;
|
|
||||||
ws.mcast.base = &ws.mcast.buf->rip_nets[0];
|
|
||||||
ws.mcast.lim = ws.mcast.base + NETS_LEN;
|
|
||||||
}
|
}
|
||||||
ripv2_buf.rip.rip_vers = vers;
|
ripv12_buf.rip.rip_vers = vers;
|
||||||
|
|
||||||
ws.v2.type = type;
|
ws.v12.n = ws.v12.base;
|
||||||
|
set_auth(&ws.v12);
|
||||||
ws.v2.n = ws.v2.base;
|
ws.v2.n = ws.v2.base;
|
||||||
set_auth(&ws.v2);
|
set_auth(&ws.v2);
|
||||||
|
|
||||||
ws.mcast.type = (type == OUT_BROADCAST) ? OUT_MULTICAST : type;
|
switch (type) {
|
||||||
ws.mcast.n = ws.mcast.base;
|
case OUT_BROADCAST:
|
||||||
set_auth(&ws.mcast);
|
ws.v2.type = ((ws.ifp != 0
|
||||||
|
&& (ws.ifp->int_if_flags & IFF_MULTICAST))
|
||||||
|
? OUT_MULTICAST
|
||||||
|
: NO_OUT_MULTICAST);
|
||||||
|
ws.v12.type = OUT_BROADCAST;
|
||||||
|
break;
|
||||||
|
case OUT_MULTICAST:
|
||||||
|
ws.v2.type = ((ws.ifp != 0
|
||||||
|
&& (ws.ifp->int_if_flags & IFF_MULTICAST))
|
||||||
|
? OUT_MULTICAST
|
||||||
|
: NO_OUT_MULTICAST);
|
||||||
|
ws.v12.type = OUT_BROADCAST;
|
||||||
|
break;
|
||||||
|
case OUT_UNICAST:
|
||||||
|
case OUT_QUERY:
|
||||||
|
ws.v2.type = (vers == RIPv2) ? type : NO_OUT_RIPV2;
|
||||||
|
ws.v12.type = type;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
ws.v2.type = type;
|
||||||
|
ws.v12.type = type;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
if (vers == RIPv2) {
|
if (vers == RIPv2) {
|
||||||
|
/* if asked to send RIPv2, send at least that which can
|
||||||
|
* be safely heard by RIPv1 listeners.
|
||||||
|
*/
|
||||||
ws.state |= WS_ST_RIP2_SAFE;
|
ws.state |= WS_ST_RIP2_SAFE;
|
||||||
|
|
||||||
/* 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;
|
||||||
@ -547,43 +640,51 @@ supply(struct sockaddr_in *dst,
|
|||||||
|| !(ws.ifp->int_state & IS_NO_SUPER_AG)))
|
|| !(ws.ifp->int_state & IS_NO_SUPER_AG)))
|
||||||
ws.state |= WS_ST_SUPER_AG;
|
ws.state |= WS_ST_SUPER_AG;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} else if (ws.ifp == 0 || !(ws.ifp->int_state & IS_NO_AG)) {
|
||||||
|
ws.state |= WS_ST_SUB_AG;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* send the routes
|
if (supplier) {
|
||||||
*/
|
/* Fake a default route if asked, and if there is not
|
||||||
if ((metric = ifp->int_d_metric) != 0) {
|
* a better, real default route.
|
||||||
/* Fake a default route if asked */
|
|
||||||
ws.state |= WS_ST_DEFAULT;
|
|
||||||
|
|
||||||
/* Use the metric of a real default, if there is one.
|
|
||||||
*/
|
*/
|
||||||
rt = rtget(RIP_DEFAULT, 0);
|
if (ifp->int_d_metric != 0
|
||||||
if (rt != 0
|
&& (0 == (rt = rtget(RIP_DEFAULT, 0))
|
||||||
&& rt->rt_metric+ws.metric < metric)
|
|| rt->rt_metric+ws.metric >= ifp->int_d_metric)) {
|
||||||
metric = rt->rt_metric+ws.metric;
|
ws.state |= WS_ST_DEFAULT;
|
||||||
|
ag_check(0, 0, 0, 0,
|
||||||
if (metric < HOPCNT_INFINITY)
|
ifp->int_d_metric,ifp->int_d_metric,
|
||||||
ag_check(0, 0, 0, metric,metric, 0, 0, 0, supply_out);
|
0, 0, 0, supply_out);
|
||||||
|
}
|
||||||
|
if ((ws.state & WS_ST_RIP2_ALL)
|
||||||
|
&& (ifp->int_state & IS_PM_RDISC)) {
|
||||||
|
ws.state |= WS_ST_PM_RDISC;
|
||||||
|
ripv12_buf.rip.rip_vers = RIPv1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
(void)rn_walktree(rhead, walk_supply, 0);
|
(void)rn_walktree(rhead, walk_supply, 0);
|
||||||
ag_flush(0,0,supply_out);
|
ag_flush(0,0,supply_out);
|
||||||
|
|
||||||
/* Flush the packet buffers */
|
/* Flush the packet buffers, provided they are not empty and
|
||||||
|
* do not contain only the password.
|
||||||
|
*/
|
||||||
|
if (ws.v12.n != ws.v12.base
|
||||||
|
&& (ws.v12.n > ws.v12.base+1
|
||||||
|
|| ws.v12.n->n_family != RIP_AF_AUTH))
|
||||||
|
supply_write(&ws.v12);
|
||||||
if (ws.v2.n != ws.v2.base
|
if (ws.v2.n != ws.v2.base
|
||||||
&& (ws.v2.n > ws.v2.base+1
|
&& (ws.v2.n > ws.v2.base+1
|
||||||
|| ws.v2.n->n_family != RIP_AF_AUTH))
|
|| ws.v2.n->n_family != RIP_AF_AUTH))
|
||||||
supply_write(&ws.v2);
|
supply_write(&ws.v2);
|
||||||
if (ws.mcast.n != ws.mcast.base
|
|
||||||
&& (ws.mcast.n > ws.mcast.base+1
|
|
||||||
|| ws.mcast.n->n_family != RIP_AF_AUTH))
|
|
||||||
supply_write(&ws.mcast);
|
|
||||||
|
|
||||||
/* If we sent nothing and this is an answer to a query, send
|
/* If we sent nothing and this is an answer to a query, send
|
||||||
* an empty buffer.
|
* an empty buffer.
|
||||||
*/
|
*/
|
||||||
if (ws.npackets == 0
|
if (ws.npackets == 0
|
||||||
&& (ws.state & WS_ST_QUERY))
|
&& (ws.state & WS_ST_QUERY))
|
||||||
supply_write(&ws.v2);
|
supply_write(&ws.v12);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -611,7 +712,7 @@ rip_bcast(int flash)
|
|||||||
if (rip_sock < 0)
|
if (rip_sock < 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
trace_msg("send %s and inhibit dynamic updates for %.3f sec\n",
|
trace_act("send %s and inhibit dynamic updates for %.3f sec\n",
|
||||||
flash ? "dynamic update" : "all routes",
|
flash ? "dynamic update" : "all routes",
|
||||||
rtime.tv_sec + ((float)rtime.tv_usec)/1000000.0);
|
rtime.tv_sec + ((float)rtime.tv_usec)/1000000.0);
|
||||||
|
|
||||||
@ -620,18 +721,16 @@ rip_bcast(int flash)
|
|||||||
* and aliases. Do try broken interfaces to see
|
* and aliases. Do try broken interfaces to see
|
||||||
* if they have healed.
|
* if they have healed.
|
||||||
*/
|
*/
|
||||||
if (0 != (ifp->int_state & (IS_PASSIVE
|
if (0 != (ifp->int_state & (IS_PASSIVE | IS_ALIAS)))
|
||||||
| IS_ALIAS)))
|
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* skip turned off interfaces */
|
/* skip turned off interfaces */
|
||||||
if (!iff_alive(ifp->int_if_flags))
|
if (!iff_alive(ifp->int_if_flags))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* Prefer RIPv1 announcements unless RIPv2 is on and
|
/* default to RIPv1 output */
|
||||||
* RIPv2 is off.
|
|
||||||
*/
|
|
||||||
if (ifp->int_state & IS_NO_RIPV1_OUT) {
|
if (ifp->int_state & IS_NO_RIPV1_OUT) {
|
||||||
|
/* Say nothing if this interface is turned off */
|
||||||
if (ifp->int_state & IS_NO_RIPV2_OUT)
|
if (ifp->int_state & IS_NO_RIPV2_OUT)
|
||||||
continue;
|
continue;
|
||||||
vers = RIPv2;
|
vers = RIPv2;
|
||||||
@ -645,10 +744,11 @@ rip_bcast(int flash)
|
|||||||
/* if RIPv1 is not turned off, then broadcast so
|
/* if RIPv1 is not turned off, then broadcast so
|
||||||
* that RIPv1 listeners can hear.
|
* that RIPv1 listeners can hear.
|
||||||
*/
|
*/
|
||||||
if (!(ifp->int_state & IS_NO_RIPV1_OUT)) {
|
if (vers == RIPv2
|
||||||
type = OUT_BROADCAST;
|
&& (ifp->int_state & IS_NO_RIPV1_OUT)) {
|
||||||
} else {
|
|
||||||
type = OUT_MULTICAST;
|
type = OUT_MULTICAST;
|
||||||
|
} else {
|
||||||
|
type = OUT_BROADCAST;
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if (ifp->int_if_flags & IFF_POINTOPOINT) {
|
} else if (ifp->int_if_flags & IFF_POINTOPOINT) {
|
||||||
@ -697,16 +797,16 @@ rip_query(void)
|
|||||||
* if they have healed.
|
* if they have healed.
|
||||||
*/
|
*/
|
||||||
if (0 != (ifp->int_state & (IS_RIP_QUERIED
|
if (0 != (ifp->int_state & (IS_RIP_QUERIED
|
||||||
| IS_PASSIVE
|
| IS_PASSIVE | IS_ALIAS)))
|
||||||
| IS_ALIAS)))
|
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* skip turned off interfaces */
|
/* skip turned off interfaces */
|
||||||
if (!iff_alive(ifp->int_if_flags))
|
if (!iff_alive(ifp->int_if_flags))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* prefer RIPv2 queries */
|
/* default to RIPv1 output */
|
||||||
if (ifp->int_state & IS_NO_RIPV2_OUT) {
|
if (ifp->int_state & IS_NO_RIPV2_OUT) {
|
||||||
|
/* Say nothing if this interface is turned off */
|
||||||
if (ifp->int_state & IS_NO_RIPV1_OUT)
|
if (ifp->int_state & IS_NO_RIPV1_OUT)
|
||||||
continue;
|
continue;
|
||||||
buf.rip_vers = RIPv1;
|
buf.rip_vers = RIPv1;
|
||||||
@ -724,10 +824,11 @@ rip_query(void)
|
|||||||
/* if RIPv1 is not turned off, then broadcast so
|
/* if RIPv1 is not turned off, then broadcast so
|
||||||
* that RIPv1 listeners can hear.
|
* that RIPv1 listeners can hear.
|
||||||
*/
|
*/
|
||||||
if (!(ifp->int_state & IS_NO_RIPV1_OUT)) {
|
if (buf.rip_vers == RIPv2
|
||||||
type = OUT_BROADCAST;
|
&& (ifp->int_state & IS_NO_RIPV1_OUT)) {
|
||||||
} else {
|
|
||||||
type = OUT_MULTICAST;
|
type = OUT_MULTICAST;
|
||||||
|
} else {
|
||||||
|
type = OUT_BROADCAST;
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if (ifp->int_if_flags & IFF_POINTOPOINT) {
|
} else if (ifp->int_if_flags & IFF_POINTOPOINT) {
|
||||||
@ -743,6 +844,6 @@ rip_query(void)
|
|||||||
|
|
||||||
ifp->int_state |= IS_RIP_QUERIED;
|
ifp->int_state |= IS_RIP_QUERIED;
|
||||||
if (output(type, &dst, ifp, &buf, sizeof(buf)) < 0)
|
if (output(type, &dst, ifp, &buf, sizeof(buf)) < 0)
|
||||||
ifbad(ifp,0);
|
if_sick(ifp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -31,11 +31,11 @@
|
|||||||
* SUCH DAMAGE.
|
* SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef lint
|
#if !defined(lint) && !defined(sgi)
|
||||||
static char sccsid[] = "@(#)if.c 8.1 (Berkeley) 6/5/93";
|
static char sccsid[] = "@(#)if.c 8.1 (Berkeley) 6/5/93";
|
||||||
#endif /* not lint */
|
#endif /* not lint */
|
||||||
|
|
||||||
#ident "$Revision: 1.1 $"
|
#ident "$Revision: 1.7 $"
|
||||||
|
|
||||||
#include "defs.h"
|
#include "defs.h"
|
||||||
#include "pathnames.h"
|
#include "pathnames.h"
|
||||||
@ -45,177 +45,6 @@ struct parm *parms;
|
|||||||
struct intnet *intnets;
|
struct intnet *intnets;
|
||||||
|
|
||||||
|
|
||||||
/* parse a set of parameters for an interface
|
|
||||||
*/
|
|
||||||
char * /* error message */
|
|
||||||
parse_parms(char *line)
|
|
||||||
{
|
|
||||||
#define PARS(str) (0 == (tgt = str, strcasecmp(tok, tgt)))
|
|
||||||
#define PARSE(str) (0 == (tgt = str, strncasecmp(tok, str "=", sizeof(str))))
|
|
||||||
#define CKF(g,b) {if (0 != (parm.parm_int_state & ((g) & ~(b)))) break; \
|
|
||||||
parm.parm_int_state |= (b);}
|
|
||||||
#define DELIMS " ,\t\n"
|
|
||||||
struct parm parm, *parmp;
|
|
||||||
struct intnet *intnetp;
|
|
||||||
char *tok, *tgt, *p;
|
|
||||||
|
|
||||||
|
|
||||||
/* "subnet=x.y.z.u/mask" must be alone on the line */
|
|
||||||
if (!strncasecmp("subnet=",line,7)) {
|
|
||||||
intnetp = (struct intnet*)malloc(sizeof(*intnetp));
|
|
||||||
if (!getnet(&line[7], &intnetp->intnet_addr,
|
|
||||||
&intnetp->intnet_mask)) {
|
|
||||||
free(intnetp);
|
|
||||||
return line;
|
|
||||||
}
|
|
||||||
HTONL(intnetp->intnet_addr);
|
|
||||||
intnetp->intnet_next = intnets;
|
|
||||||
intnets = intnetp;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
bzero(&parm, sizeof(parm));
|
|
||||||
|
|
||||||
tgt = "null";
|
|
||||||
for (tok = strtok(line, DELIMS);
|
|
||||||
tok != 0 && tok[0] != '\0';
|
|
||||||
tgt = 0, tok = strtok(0,DELIMS)) {
|
|
||||||
if (PARSE("if")) {
|
|
||||||
if (parm.parm_name[0] != '\0'
|
|
||||||
|| tok[3] == '\0'
|
|
||||||
|| strlen(tok) > IFNAMSIZ+3)
|
|
||||||
break;
|
|
||||||
strcpy(parm.parm_name, tok+3);
|
|
||||||
|
|
||||||
} else if (PARSE("passwd")) {
|
|
||||||
if (tok[7] == '\0'
|
|
||||||
|| strlen(tok) > RIP_AUTH_PW_LEN+7)
|
|
||||||
break;
|
|
||||||
strcpy(parm.parm_passwd, tok+7);
|
|
||||||
|
|
||||||
} else if (PARS("no_ag")) {
|
|
||||||
parm.parm_int_state |= IS_NO_AG;
|
|
||||||
|
|
||||||
} else if (PARS("no_super_ag")) {
|
|
||||||
parm.parm_int_state |= IS_NO_SUPER_AG;
|
|
||||||
|
|
||||||
} else if (PARS("no_rip")) {
|
|
||||||
parm.parm_int_state |= (IS_NO_RIPV1_IN
|
|
||||||
| IS_NO_RIPV2_IN
|
|
||||||
| IS_NO_RIPV1_OUT
|
|
||||||
| IS_NO_RIPV2_OUT);
|
|
||||||
|
|
||||||
} else if (PARS("no_ripv1_in")) {
|
|
||||||
parm.parm_int_state |= IS_NO_RIPV1_IN;
|
|
||||||
|
|
||||||
} else if (PARS("no_ripv2_in")) {
|
|
||||||
parm.parm_int_state |= IS_NO_RIPV2_IN;
|
|
||||||
|
|
||||||
} else if (PARS("no_ripv2_out")) {
|
|
||||||
parm.parm_int_state |= IS_NO_RIPV2_OUT;
|
|
||||||
|
|
||||||
} else if (PARS("ripv2_out")) {
|
|
||||||
if (parm.parm_int_state & IS_NO_RIPV2_OUT)
|
|
||||||
break;
|
|
||||||
parm.parm_int_state |= IS_NO_RIPV1_OUT;
|
|
||||||
|
|
||||||
} else if (PARS("no_rdisc")) {
|
|
||||||
CKF((GROUP_IS_SOL|GROUP_IS_ADV),
|
|
||||||
IS_NO_ADV_IN | IS_NO_SOL_OUT | IS_NO_ADV_OUT);
|
|
||||||
|
|
||||||
} else if (PARS("no_solicit")) {
|
|
||||||
CKF(GROUP_IS_SOL, IS_NO_SOL_OUT);
|
|
||||||
|
|
||||||
} else if (PARS("send_solicit")) {
|
|
||||||
CKF(GROUP_IS_SOL, IS_SOL_OUT);
|
|
||||||
|
|
||||||
} else if (PARS("no_rdisc_adv")) {
|
|
||||||
CKF(GROUP_IS_ADV, IS_NO_ADV_OUT);
|
|
||||||
|
|
||||||
} else if (PARS("rdisc_adv")) {
|
|
||||||
CKF(GROUP_IS_ADV, IS_ADV_OUT);
|
|
||||||
|
|
||||||
} else if (PARS("bcast_rdisc")) {
|
|
||||||
parm.parm_int_state |= IS_BCAST_RDISC;
|
|
||||||
|
|
||||||
} else if (PARSE("rdisc_pref")) {
|
|
||||||
if (parm.parm_rdisc_pref != 0
|
|
||||||
|| tok[11] == '\0'
|
|
||||||
|| (parm.parm_rdisc_pref = (int)strtol(&tok[11],
|
|
||||||
&p,0),
|
|
||||||
*p != '\0'))
|
|
||||||
break;
|
|
||||||
|
|
||||||
} else if (PARSE("rdisc_interval")) {
|
|
||||||
if (parm.parm_rdisc_int != 0
|
|
||||||
|| tok[15] == '\0'
|
|
||||||
|| (parm.parm_rdisc_int = (int)strtol(&tok[15],
|
|
||||||
&p,0),
|
|
||||||
*p != '\0')
|
|
||||||
|| parm.parm_rdisc_int < MinMaxAdvertiseInterval
|
|
||||||
|| parm.parm_rdisc_int > MaxMaxAdvertiseInterval)
|
|
||||||
break;
|
|
||||||
|
|
||||||
} else if (PARSE("fake_default")) {
|
|
||||||
if (parm.parm_d_metric != 0
|
|
||||||
|| tok[13] == '\0'
|
|
||||||
|| (parm.parm_d_metric=(int)strtol(&tok[13],&p,0),
|
|
||||||
*p != '\0')
|
|
||||||
|| parm.parm_d_metric >= HOPCNT_INFINITY-2)
|
|
||||||
break;
|
|
||||||
|
|
||||||
} else {
|
|
||||||
tgt = tok;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (tgt != 0)
|
|
||||||
return tgt;
|
|
||||||
|
|
||||||
if (parm.parm_int_state & IS_NO_ADV_IN)
|
|
||||||
parm.parm_int_state |= IS_NO_SOL_OUT;
|
|
||||||
|
|
||||||
/* check for duplicate specification */
|
|
||||||
for (parmp = parms; parmp != 0; parmp = parmp->parm_next) {
|
|
||||||
if (strcmp(parm.parm_name, parmp->parm_name))
|
|
||||||
continue;
|
|
||||||
if (parmp->parm_a_h != (parm.parm_a_h & parmp->parm_m)
|
|
||||||
&& parm.parm_a_h != (parmp->parm_a_h & parm.parm_m))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (strcmp(parmp->parm_passwd, parm.parm_passwd)
|
|
||||||
|| (0 != (parm.parm_int_state & GROUP_IS_SOL)
|
|
||||||
&& 0 != (parmp->parm_int_state & GROUP_IS_SOL)
|
|
||||||
&& 0 != ((parm.parm_int_state ^ parmp->parm_int_state)
|
|
||||||
&& GROUP_IS_SOL))
|
|
||||||
|| (0 != (parm.parm_int_state & GROUP_IS_ADV)
|
|
||||||
&& 0 != (parmp->parm_int_state & GROUP_IS_ADV)
|
|
||||||
&& 0 != ((parm.parm_int_state ^ parmp->parm_int_state)
|
|
||||||
&& GROUP_IS_ADV))
|
|
||||||
|| (parm.parm_rdisc_pref != 0
|
|
||||||
&& parmp->parm_rdisc_pref != 0
|
|
||||||
&& parm.parm_rdisc_pref != parmp->parm_rdisc_pref)
|
|
||||||
|| (parm.parm_rdisc_int != 0
|
|
||||||
&& parmp->parm_rdisc_int != 0
|
|
||||||
&& parm.parm_rdisc_int != parmp->parm_rdisc_int)
|
|
||||||
|| (parm.parm_d_metric != 0
|
|
||||||
&& parmp->parm_d_metric != 0
|
|
||||||
&& parm.parm_d_metric != parmp->parm_d_metric))
|
|
||||||
return "duplicate";
|
|
||||||
}
|
|
||||||
|
|
||||||
parmp = (struct parm*)malloc(sizeof(*parmp));
|
|
||||||
bcopy(&parm, parmp, sizeof(*parmp));
|
|
||||||
parmp->parm_next = parms;
|
|
||||||
parms = parmp;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
#undef DELIMS
|
|
||||||
#undef PARS
|
|
||||||
#undef PARSE
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* use configured parameters
|
/* use configured parameters
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
@ -223,51 +52,66 @@ get_parms(struct interface *ifp)
|
|||||||
{
|
{
|
||||||
struct parm *parmp;
|
struct parm *parmp;
|
||||||
|
|
||||||
|
/* get all relevant parameters
|
||||||
|
*/
|
||||||
for (parmp = parms; parmp != 0; parmp = parmp->parm_next) {
|
for (parmp = parms; parmp != 0; parmp = parmp->parm_next) {
|
||||||
if ((parmp->parm_a_h == (ntohl(ifp->int_addr)
|
if ((parmp->parm_name[0] == '\0'
|
||||||
& parmp->parm_m)
|
&& on_net(ifp->int_addr,
|
||||||
&& parmp->parm_name[0] == '\0')
|
parmp->parm_addr_h, parmp->parm_mask))
|
||||||
|| (parmp->parm_name[0] != '\0'
|
|| (parmp->parm_name[0] != '\0'
|
||||||
&& !strcmp(ifp->int_name, parmp->parm_name))) {
|
&& !strcmp(ifp->int_name, parmp->parm_name))) {
|
||||||
|
/* this group of parameters is relevant,
|
||||||
|
* so get its settings
|
||||||
|
*/
|
||||||
ifp->int_state |= parmp->parm_int_state;
|
ifp->int_state |= parmp->parm_int_state;
|
||||||
bcopy(parmp->parm_passwd, ifp->int_passwd,
|
if (parmp->parm_passwd[0] != '\0')
|
||||||
sizeof(ifp->int_passwd));
|
bcopy(parmp->parm_passwd, ifp->int_passwd,
|
||||||
ifp->int_rdisc_pref = parmp->parm_rdisc_pref;
|
sizeof(ifp->int_passwd));
|
||||||
ifp->int_rdisc_int = parmp->parm_rdisc_int;
|
if (parmp->parm_rdisc_pref != 0)
|
||||||
ifp->int_d_metric = parmp->parm_d_metric;
|
ifp->int_rdisc_pref = parmp->parm_rdisc_pref;
|
||||||
}
|
if (parmp->parm_rdisc_int != 0)
|
||||||
|
ifp->int_rdisc_int = parmp->parm_rdisc_int;
|
||||||
|
if (parmp->parm_d_metric != 0)
|
||||||
|
ifp->int_d_metric = parmp->parm_d_metric;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
/* default poor-man's router discovery to a metric that will
|
||||||
|
* be heard by old versions of routed.
|
||||||
|
*/
|
||||||
|
if ((ifp->int_state & IS_PM_RDISC)
|
||||||
|
&& ifp->int_d_metric == 0)
|
||||||
|
ifp->int_d_metric = HOPCNT_INFINITY-2;
|
||||||
|
|
||||||
if ((ifp->int_state & IS_NO_RIP_IN) == IS_NO_RIP_IN)
|
if (IS_RIP_IN_OFF(ifp->int_state))
|
||||||
ifp->int_state |= IS_NO_RIP_OUT;
|
ifp->int_state |= IS_NO_RIP_OUT;
|
||||||
|
|
||||||
if (ifp->int_rdisc_int == 0)
|
if (ifp->int_rdisc_int == 0)
|
||||||
ifp->int_rdisc_int = DefMaxAdvertiseInterval;
|
ifp->int_rdisc_int = DefMaxAdvertiseInterval;
|
||||||
|
|
||||||
if ((ifp->int_state & IS_PASSIVE)
|
if (!(ifp->int_if_flags & IFF_MULTICAST)
|
||||||
|| (ifp->int_state & IS_REMOTE))
|
&& !(ifp->int_if_flags & IFF_POINTOPOINT))
|
||||||
ifp->int_state |= IS_NO_ADV_IN|IS_NO_SOL_OUT|IS_NO_ADV_OUT;
|
ifp->int_state |= IS_NO_RIPV2_OUT;
|
||||||
|
|
||||||
|
|
||||||
if (!(ifp->int_state & IS_PASSIVE)) {
|
|
||||||
if (!(ifp->int_if_flags & IFF_MULTICAST)
|
|
||||||
&& !(ifp->int_if_flags & IFF_POINTOPOINT))
|
|
||||||
ifp->int_state |= IS_NO_RIPV2_OUT;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!(ifp->int_if_flags & IFF_MULTICAST))
|
if (!(ifp->int_if_flags & IFF_MULTICAST))
|
||||||
ifp->int_state |= IS_BCAST_RDISC;
|
ifp->int_state |= IS_BCAST_RDISC;
|
||||||
|
|
||||||
if (ifp->int_if_flags & IFF_POINTOPOINT) {
|
if (ifp->int_if_flags & IFF_POINTOPOINT) {
|
||||||
ifp->int_state |= IS_BCAST_RDISC;
|
ifp->int_state |= IS_BCAST_RDISC;
|
||||||
/* point-to-point links should be passive for the sake
|
/* By default, point-to-point links should be passive
|
||||||
* 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))
|
||||||
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))
|
||||||
ifp->int_state |= IS_NO_ADV_OUT;
|
ifp->int_state |= IS_NO_ADV_OUT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (0 != (ifp->int_state & (IS_PASSIVE | IS_REMOTE)))
|
||||||
|
ifp->int_state |= IS_NO_RDISC;
|
||||||
|
if (ifp->int_state & IS_PASSIVE)
|
||||||
|
ifp->int_state |= (IS_NO_RIP | IS_NO_RDISC);
|
||||||
|
if (ifp->int_state&(IS_NO_RIP|IS_NO_RDISC) == (IS_NO_RIP|IS_NO_RDISC))
|
||||||
|
ifp->int_state |= IS_PASSIVE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -314,53 +158,62 @@ gwkludge(void)
|
|||||||
if (*lptr == '\n' /* ignore null and comment lines */
|
if (*lptr == '\n' /* ignore null and comment lines */
|
||||||
|| *lptr == '#')
|
|| *lptr == '#')
|
||||||
continue;
|
continue;
|
||||||
|
p = lptr+strlen(lptr)-1;
|
||||||
|
while (*p == '\n'
|
||||||
|
|| *p == ' ')
|
||||||
|
*p-- = '\0';
|
||||||
|
|
||||||
/* notice 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);
|
p = parse_parms(lptr);
|
||||||
if (p != 0)
|
if (p != 0) {
|
||||||
msglog("bad \"%s\" in "_PATH_GATEWAYS
|
if (strcmp(p,lptr))
|
||||||
" entry %s", lptr, p);
|
msglog("bad \"%s\" in "_PATH_GATEWAYS
|
||||||
|
" entry \"%s\"", lptr, p);
|
||||||
|
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 */
|
||||||
n = sscanf(lptr, "%4s %129[^ ] gateway"
|
n = sscanf(lptr, "%4s %129[^ \t] gateway"
|
||||||
" %64[^ / ] metric %d %8s\n",
|
" %64[^ / \t] metric %d %8s\n",
|
||||||
net_host, dname, gname, &metric, qual);
|
net_host, dname, gname, &metric, qual);
|
||||||
if (n != 5) {
|
if (n != 5) {
|
||||||
msglog("bad "_PATH_GATEWAYS" entry %s", lptr);
|
msglog("bad "_PATH_GATEWAYS" entry \"%s\"", lptr);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (metric < 0 || metric >= HOPCNT_INFINITY) {
|
if (metric < 0 || metric >= HOPCNT_INFINITY) {
|
||||||
msglog("bad metric in "_PATH_GATEWAYS" entry %s",
|
msglog("bad metric in "_PATH_GATEWAYS" entry \"%s\"",
|
||||||
lptr);
|
lptr);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (!strcmp(net_host, "host")) {
|
if (!strcmp(net_host, "host")) {
|
||||||
if (!gethost(dname, &dst)) {
|
if (!gethost(dname, &dst)) {
|
||||||
msglog("bad host %s in "_PATH_GATEWAYS
|
msglog("bad host \"%s\" in "_PATH_GATEWAYS
|
||||||
" entry %s", dname, lptr);
|
" entry \"%s\"", dname, lptr);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
netmask = HOST_MASK;
|
netmask = HOST_MASK;
|
||||||
} else if (!strcmp(net_host, "net")) {
|
} else if (!strcmp(net_host, "net")) {
|
||||||
if (!getnet(dname, &dst, &netmask)) {
|
if (!getnet(dname, &dst, &netmask)) {
|
||||||
msglog("bad net %s in "_PATH_GATEWAYS
|
msglog("bad net \"%s\" in "_PATH_GATEWAYS
|
||||||
" entry %s", dname, lptr);
|
" entry \"%s\"", dname, lptr);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
HTONL(dst);
|
|
||||||
} else {
|
} else {
|
||||||
msglog("bad \"%s\" in "_PATH_GATEWAYS
|
msglog("bad \"%s\" in "_PATH_GATEWAYS
|
||||||
" entry %s", lptr);
|
" entry \"%s\"", lptr);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!gethost(gname, &gate)) {
|
if (!gethost(gname, &gate)) {
|
||||||
msglog("bad gateway %s in "_PATH_GATEWAYS
|
msglog("bad gateway \"%s\" in "_PATH_GATEWAYS
|
||||||
" entry %s", gname, lptr);
|
" entry \"%s\"", gname, lptr);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -403,34 +256,29 @@ gwkludge(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
msglog("bad "_PATH_GATEWAYS" entry %s", lptr);
|
msglog("bad "_PATH_GATEWAYS" entry \"%s\"", lptr);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(state & IS_EXTERNAL)) {
|
/* Remember to advertise the corresponding logical network.
|
||||||
/* If we are going to send packets to the gateway,
|
*/
|
||||||
* it must be reachable using our physical interfaces
|
if (!(state & IS_EXTERNAL)
|
||||||
*/
|
&& netmask != std_mask(dst))
|
||||||
if (!rtfind(gate)) {
|
state |= IS_SUBNET;
|
||||||
msglog("unreachable gateway %s in "
|
|
||||||
_PATH_GATEWAYS" entry %s",
|
|
||||||
gname, lptr);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Remember to advertise the corresponding logical
|
if (0 != (state & (IS_PASSIVE | IS_REMOTE)))
|
||||||
* network.
|
state |= IS_NO_RDISC;
|
||||||
*/
|
if (state & IS_PASSIVE)
|
||||||
if (netmask != std_mask(dst))
|
state |= (IS_NO_RIP | IS_NO_RDISC);
|
||||||
state |= IS_SUBNET;
|
if (state & (IS_NO_RIP|IS_NO_RDISC) == (IS_NO_RIP|IS_NO_RDISC))
|
||||||
}
|
state |= IS_PASSIVE;
|
||||||
|
|
||||||
parmp = (struct parm*)malloc(sizeof(*parmp));
|
parmp = (struct parm*)malloc(sizeof(*parmp));
|
||||||
bzero(parmp, sizeof(*parmp));
|
bzero(parmp, sizeof(*parmp));
|
||||||
parmp->parm_next = parms;
|
parmp->parm_next = parms;
|
||||||
parms = parmp;
|
parms = parmp;
|
||||||
parmp->parm_a_h = ntohl(dst);
|
parmp->parm_addr_h = ntohl(dst);
|
||||||
parmp->parm_m = -1;
|
parmp->parm_mask = -1;
|
||||||
parmp->parm_d_metric = 0;
|
parmp->parm_d_metric = 0;
|
||||||
parmp->parm_int_state = state;
|
parmp->parm_int_state = state;
|
||||||
|
|
||||||
@ -438,8 +286,11 @@ gwkludge(void)
|
|||||||
* interface.
|
* interface.
|
||||||
*/
|
*/
|
||||||
for (ifp = ifnet; 0 != ifp; ifp = ifp->int_next) {
|
for (ifp = ifnet; 0 != ifp; ifp = ifp->int_next) {
|
||||||
if (ifp->int_addr == dst
|
if (ifp->int_mask == netmask
|
||||||
&& ifp->int_mask == netmask)
|
&& ((ifp->int_addr == dst
|
||||||
|
&& netmask != HOST_MASK)
|
||||||
|
|| (ifp->int_dstaddr == dst
|
||||||
|
&& netmask == HOST_MASK)))
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (ifp != 0) {
|
if (ifp != 0) {
|
||||||
@ -478,22 +329,218 @@ gwkludge(void)
|
|||||||
|
|
||||||
get_parms(ifp);
|
get_parms(ifp);
|
||||||
|
|
||||||
if (TRACEACTIONS)
|
trace_if("Add", ifp);
|
||||||
trace_if("Add", ifp);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* parse a set of parameters for an interface
|
||||||
|
*/
|
||||||
|
char * /* 0 or error message */
|
||||||
|
parse_parms(char *line)
|
||||||
|
{
|
||||||
|
#define PARS(str) (0 == (tgt = str, strcasecmp(tok, tgt)))
|
||||||
|
#define PARSE(str) (0 == (tgt = str, strncasecmp(tok, str "=", sizeof(str))))
|
||||||
|
#define CKF(g,b) {if (0 != (parm.parm_int_state & ((g) & ~(b)))) break; \
|
||||||
|
parm.parm_int_state |= (b);}
|
||||||
|
#define DELIMS " ,\t\n"
|
||||||
|
struct parm parm;
|
||||||
|
struct intnet *intnetp;
|
||||||
|
char *tok, *tgt, *p;
|
||||||
|
|
||||||
|
|
||||||
|
/* "subnet=x.y.z.u/mask" must be alone on the line */
|
||||||
|
if (!strncasecmp("subnet=",line,7)) {
|
||||||
|
intnetp = (struct intnet*)malloc(sizeof(*intnetp));
|
||||||
|
intnetp->intnet_metric = 1;
|
||||||
|
if (p = strrchr(line,',')) {
|
||||||
|
*p++ = '\0';
|
||||||
|
intnetp->intnet_metric = (int)strtol(p,&p,0);
|
||||||
|
if (*p != '\0'
|
||||||
|
|| intnetp->intnet_metric <= 0
|
||||||
|
|| intnetp->intnet_metric >= HOPCNT_INFINITY)
|
||||||
|
return line;
|
||||||
|
}
|
||||||
|
if (!getnet(&line[7], &intnetp->intnet_addr,
|
||||||
|
&intnetp->intnet_mask)
|
||||||
|
|| intnetp->intnet_mask == HOST_MASK
|
||||||
|
|| intnetp->intnet_addr == RIP_DEFAULT) {
|
||||||
|
free(intnetp);
|
||||||
|
return line;
|
||||||
|
}
|
||||||
|
intnetp->intnet_next = intnets;
|
||||||
|
intnets = intnetp;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bzero(&parm, sizeof(parm));
|
||||||
|
|
||||||
|
tgt = "null";
|
||||||
|
for (tok = strtok(line, DELIMS);
|
||||||
|
tok != 0 && tok[0] != '\0';
|
||||||
|
tgt = 0, tok = strtok(0,DELIMS)) {
|
||||||
|
if (PARSE("if")) {
|
||||||
|
if (parm.parm_name[0] != '\0'
|
||||||
|
|| tok[3] == '\0'
|
||||||
|
|| strlen(tok) > IFNAMSIZ+3)
|
||||||
|
break;
|
||||||
|
strcpy(parm.parm_name, tok+3);
|
||||||
|
|
||||||
|
} else if (PARSE("passwd")) {
|
||||||
|
if (tok[7] == '\0'
|
||||||
|
|| strlen(tok) > RIP_AUTH_PW_LEN+7)
|
||||||
|
break;
|
||||||
|
strcpy(parm.parm_passwd, tok+7);
|
||||||
|
|
||||||
|
} else if (PARS("no_ag")) {
|
||||||
|
parm.parm_int_state |= (IS_NO_AG | IS_NO_SUPER_AG);
|
||||||
|
|
||||||
|
} else if (PARS("no_super_ag")) {
|
||||||
|
parm.parm_int_state |= IS_NO_SUPER_AG;
|
||||||
|
|
||||||
|
} else if (PARS("no_ripv1_in")) {
|
||||||
|
parm.parm_int_state |= IS_NO_RIPV1_IN;
|
||||||
|
|
||||||
|
} else if (PARS("no_ripv2_in")) {
|
||||||
|
parm.parm_int_state |= IS_NO_RIPV2_IN;
|
||||||
|
|
||||||
|
} else if (PARS("ripv2_out")) {
|
||||||
|
if (parm.parm_int_state & IS_NO_RIPV2_OUT)
|
||||||
|
break;
|
||||||
|
parm.parm_int_state |= IS_NO_RIPV1_OUT;
|
||||||
|
|
||||||
|
} else if (PARS("no_rip")) {
|
||||||
|
parm.parm_int_state |= IS_NO_RIP;
|
||||||
|
|
||||||
|
} else if (PARS("no_rdisc")) {
|
||||||
|
CKF((GROUP_IS_SOL|GROUP_IS_ADV), IS_NO_RDISC);
|
||||||
|
|
||||||
|
} else if (PARS("no_solicit")) {
|
||||||
|
CKF(GROUP_IS_SOL, IS_NO_SOL_OUT);
|
||||||
|
|
||||||
|
} else if (PARS("send_solicit")) {
|
||||||
|
CKF(GROUP_IS_SOL, IS_SOL_OUT);
|
||||||
|
|
||||||
|
} else if (PARS("no_rdisc_adv")) {
|
||||||
|
CKF(GROUP_IS_ADV, IS_NO_ADV_OUT);
|
||||||
|
|
||||||
|
} else if (PARS("rdisc_adv")) {
|
||||||
|
CKF(GROUP_IS_ADV, IS_ADV_OUT);
|
||||||
|
|
||||||
|
} else if (PARS("bcast_rdisc")) {
|
||||||
|
parm.parm_int_state |= IS_BCAST_RDISC;
|
||||||
|
|
||||||
|
} else if (PARS("passive")) {
|
||||||
|
CKF((GROUP_IS_SOL|GROUP_IS_ADV), IS_NO_RDISC);
|
||||||
|
parm.parm_int_state |= IS_NO_RIP;
|
||||||
|
|
||||||
|
} else if (PARSE("rdisc_pref")) {
|
||||||
|
if (parm.parm_rdisc_pref != 0
|
||||||
|
|| tok[11] == '\0'
|
||||||
|
|| (parm.parm_rdisc_pref = (int)strtol(&tok[11],
|
||||||
|
&p,0),
|
||||||
|
*p != '\0'))
|
||||||
|
break;
|
||||||
|
|
||||||
|
} else if (PARS("pm_rdisc")) {
|
||||||
|
parm.parm_int_state |= IS_PM_RDISC;
|
||||||
|
|
||||||
|
} else if (PARSE("rdisc_interval")) {
|
||||||
|
if (parm.parm_rdisc_int != 0
|
||||||
|
|| tok[15] == '\0'
|
||||||
|
|| (parm.parm_rdisc_int = (int)strtol(&tok[15],
|
||||||
|
&p,0),
|
||||||
|
*p != '\0')
|
||||||
|
|| parm.parm_rdisc_int < MinMaxAdvertiseInterval
|
||||||
|
|| parm.parm_rdisc_int > MaxMaxAdvertiseInterval)
|
||||||
|
break;
|
||||||
|
|
||||||
|
} else if (PARSE("fake_default")) {
|
||||||
|
if (parm.parm_d_metric != 0
|
||||||
|
|| tok[13] == '\0'
|
||||||
|
|| (parm.parm_d_metric=(int)strtol(&tok[13],&p,0),
|
||||||
|
*p != '\0')
|
||||||
|
|| parm.parm_d_metric > HOPCNT_INFINITY-1)
|
||||||
|
break;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
tgt = tok;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (tgt != 0)
|
||||||
|
return tgt;
|
||||||
|
|
||||||
|
if (parm.parm_int_state & IS_NO_ADV_IN)
|
||||||
|
parm.parm_int_state |= IS_NO_SOL_OUT;
|
||||||
|
|
||||||
|
if ((parm.parm_int_state & (IS_NO_RIP | IS_NO_RDISC))
|
||||||
|
== (IS_NO_RIP | IS_NO_RDISC))
|
||||||
|
parm.parm_int_state |= IS_PASSIVE;
|
||||||
|
|
||||||
|
return check_parms(&parm);
|
||||||
|
#undef DELIMS
|
||||||
|
#undef PARS
|
||||||
|
#undef PARSE
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* check for duplicate parameter specifications */
|
||||||
|
char * /* 0 or error message */
|
||||||
|
check_parms(struct parm *new)
|
||||||
|
{
|
||||||
|
struct parm *parmp;
|
||||||
|
|
||||||
|
|
||||||
|
for (parmp = parms; parmp != 0; parmp = parmp->parm_next) {
|
||||||
|
if (strcmp(new->parm_name, parmp->parm_name))
|
||||||
|
continue;
|
||||||
|
if (!on_net(htonl(parmp->parm_addr_h),
|
||||||
|
new->parm_addr_h, new->parm_mask)
|
||||||
|
&& !on_net(htonl(new->parm_addr_h),
|
||||||
|
parmp->parm_addr_h, parmp->parm_mask))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (strcmp(parmp->parm_passwd, new->parm_passwd)
|
||||||
|
|| (0 != (new->parm_int_state & GROUP_IS_SOL)
|
||||||
|
&& 0 != (parmp->parm_int_state & GROUP_IS_SOL)
|
||||||
|
&& 0 != ((new->parm_int_state ^ parmp->parm_int_state)
|
||||||
|
&& GROUP_IS_SOL))
|
||||||
|
|| (0 != (new->parm_int_state & GROUP_IS_ADV)
|
||||||
|
&& 0 != (parmp->parm_int_state & GROUP_IS_ADV)
|
||||||
|
&& 0 != ((new->parm_int_state ^ parmp->parm_int_state)
|
||||||
|
&& GROUP_IS_ADV))
|
||||||
|
|| (new->parm_rdisc_pref != 0
|
||||||
|
&& parmp->parm_rdisc_pref != 0
|
||||||
|
&& new->parm_rdisc_pref != parmp->parm_rdisc_pref)
|
||||||
|
|| (new->parm_rdisc_int != 0
|
||||||
|
&& parmp->parm_rdisc_int != 0
|
||||||
|
&& new->parm_rdisc_int != parmp->parm_rdisc_int)
|
||||||
|
|| (new->parm_d_metric != 0
|
||||||
|
&& parmp->parm_d_metric != 0
|
||||||
|
&& new->parm_d_metric != parmp->parm_d_metric))
|
||||||
|
return "duplicate";
|
||||||
|
}
|
||||||
|
|
||||||
|
parmp = (struct parm*)malloc(sizeof(*parmp));
|
||||||
|
bcopy(new, parmp, sizeof(*parmp));
|
||||||
|
parmp->parm_next = parms;
|
||||||
|
parms = parmp;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* get a network number as a name or a number, with an optional "/xx"
|
/* get a network number as a name or a number, with an optional "/xx"
|
||||||
* netmask.
|
* netmask.
|
||||||
*/
|
*/
|
||||||
int /* 0=bad */
|
int /* 0=bad */
|
||||||
getnet(char *name,
|
getnet(char *name,
|
||||||
naddr *addr_hp,
|
naddr *addrp, /* host byte order */
|
||||||
naddr *maskp)
|
naddr *maskp)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
struct netent *nentp;
|
struct netent *np;
|
||||||
naddr mask;
|
naddr mask;
|
||||||
struct in_addr in;
|
struct in_addr in;
|
||||||
char hname[MAXHOSTNAMELEN+1];
|
char hname[MAXHOSTNAMELEN+1];
|
||||||
@ -512,25 +559,34 @@ getnet(char *name,
|
|||||||
name = hname;
|
name = hname;
|
||||||
}
|
}
|
||||||
|
|
||||||
nentp = getnetbyname(name);
|
np = getnetbyname(name);
|
||||||
if (nentp != 0) {
|
if (np != 0) {
|
||||||
in.s_addr = (naddr)nentp->n_net;
|
in.s_addr = (naddr)np->n_net;
|
||||||
} else if (inet_aton(name, &in) == 1) {
|
} else if (inet_aton(name, &in) == 1) {
|
||||||
NTOHL(in.s_addr);
|
HTONL(in.s_addr);
|
||||||
} else {
|
} else {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mname == 0) {
|
if (mname == 0) {
|
||||||
|
/* we cannot use the interfaces here because we have not
|
||||||
|
* looked at them yet.
|
||||||
|
*/
|
||||||
mask = std_mask(in.s_addr);
|
mask = std_mask(in.s_addr);
|
||||||
|
if ((~mask & ntohl(in.s_addr)) != 0)
|
||||||
|
mask = HOST_MASK;
|
||||||
} else {
|
} else {
|
||||||
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);
|
mask = HOST_MASK << (32-mask);
|
||||||
}
|
}
|
||||||
|
if (mask != 0 && in.s_addr == RIP_DEFAULT)
|
||||||
|
return 0;
|
||||||
|
if ((~mask & ntohl(in.s_addr)) != 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
*addr_hp = in.s_addr;
|
*addrp = in.s_addr;
|
||||||
*maskp = mask;
|
*maskp = mask;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -37,7 +37,9 @@
|
|||||||
|
|
||||||
#define _PATH_GATEWAYS "/etc/gateways"
|
#define _PATH_GATEWAYS "/etc/gateways"
|
||||||
|
|
||||||
/* all remotely requested trace files must either start with this prefix
|
/* All remotely requested trace files must either start with this prefix
|
||||||
* or be the same as the tracefile specified when the daemon was started.
|
* or be the same as the tracefile specified when the daemon was started.
|
||||||
|
* If this is a directory, routed will create log files in it. That
|
||||||
|
* might be a security problem.
|
||||||
*/
|
*/
|
||||||
#define _PATH_TRACE "/tmp"
|
#define _PATH_TRACE "/tmp/routed.log"
|
||||||
|
@ -31,11 +31,11 @@
|
|||||||
* SUCH DAMAGE.
|
* SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef lint
|
#if !defined(lint) && !defined(sgi)
|
||||||
static char sccsid[] = "@(#)rdisc.c 8.1 (Berkeley) x/y/95";
|
static char sccsid[] = "@(#)rdisc.c 8.1 (Berkeley) x/y/95";
|
||||||
#endif /* not lint */
|
#endif /* not lint */
|
||||||
|
|
||||||
#ident "$Revision: 1.1 $"
|
#ident "$Revision: 1.14 $"
|
||||||
|
|
||||||
#include "defs.h"
|
#include "defs.h"
|
||||||
#include <netinet/in_systm.h>
|
#include <netinet/in_systm.h>
|
||||||
@ -89,8 +89,8 @@ struct dr { /* accumulated advertisements */
|
|||||||
} *cur_drp, drs[MAX_ADS];
|
} *cur_drp, drs[MAX_ADS];
|
||||||
|
|
||||||
/* adjust preference by interface metric without driving it to infinity */
|
/* adjust preference by interface metric without driving it to infinity */
|
||||||
#define PREF(p, ifp) ((p) < (ifp)->int_metric ? ((p) != 0 ? 1 : 0) \
|
#define PREF(p, ifp) ((p) <= (ifp)->int_metric ? ((p) != 0 ? 1 : 0) \
|
||||||
: (p) - ((ifp)->int_metric-1))
|
: (p) - ((ifp)->int_metric))
|
||||||
|
|
||||||
static void rdisc_sort(void);
|
static void rdisc_sort(void);
|
||||||
|
|
||||||
@ -109,7 +109,7 @@ trace_rdisc(char *act,
|
|||||||
n_long *wp, *lim;
|
n_long *wp, *lim;
|
||||||
|
|
||||||
|
|
||||||
if (ftrace == 0)
|
if (!TRACEPACKETS || ftrace == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
lastlog();
|
lastlog();
|
||||||
@ -119,7 +119,7 @@ trace_rdisc(char *act,
|
|||||||
" from %s to %s via %s life=%d\n",
|
" from %s to %s via %s life=%d\n",
|
||||||
act, naddr_ntoa(from), naddr_ntoa(to),
|
act, naddr_ntoa(from), naddr_ntoa(to),
|
||||||
ifp ? ifp->int_name : "?",
|
ifp ? ifp->int_name : "?",
|
||||||
p->ad.icmp_ad_life);
|
ntohs(p->ad.icmp_ad_life));
|
||||||
if (!TRACECONTENTS)
|
if (!TRACECONTENTS)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@ -133,7 +133,7 @@ trace_rdisc(char *act,
|
|||||||
(void)fputc('\n',ftrace);
|
(void)fputc('\n',ftrace);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
trace_msg("%s Router Solic. from %s to %s via %s"
|
trace_act("%s Router Solic. from %s to %s via %s"
|
||||||
" value=%#x\n",
|
" value=%#x\n",
|
||||||
act, naddr_ntoa(from), naddr_ntoa(to),
|
act, naddr_ntoa(from), naddr_ntoa(to),
|
||||||
ifp ? ifp->int_name : "?",
|
ifp ? ifp->int_name : "?",
|
||||||
@ -173,7 +173,7 @@ set_rdisc_mg(struct interface *ifp,
|
|||||||
if (setsockopt(rdisc_sock, IPPROTO_IP,
|
if (setsockopt(rdisc_sock, IPPROTO_IP,
|
||||||
IP_DROP_MEMBERSHIP,
|
IP_DROP_MEMBERSHIP,
|
||||||
&m, sizeof(m)) < 0)
|
&m, sizeof(m)) < 0)
|
||||||
DBGERR(1,"IP_DROP_MEMBERSHIP ALLHOSTS");
|
LOGERR("IP_DROP_MEMBERSHIP ALLHOSTS");
|
||||||
ifp->int_state &= ~IS_ALL_HOSTS;
|
ifp->int_state &= ~IS_ALL_HOSTS;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -181,9 +181,11 @@ set_rdisc_mg(struct interface *ifp,
|
|||||||
/* start listening to advertisements */
|
/* start listening to advertisements */
|
||||||
m.imr_multiaddr.s_addr = htonl(INADDR_ALLHOSTS_GROUP);
|
m.imr_multiaddr.s_addr = htonl(INADDR_ALLHOSTS_GROUP);
|
||||||
if (setsockopt(rdisc_sock, IPPROTO_IP, IP_ADD_MEMBERSHIP,
|
if (setsockopt(rdisc_sock, IPPROTO_IP, IP_ADD_MEMBERSHIP,
|
||||||
&m, sizeof(m)) < 0)
|
&m, sizeof(m)) < 0) {
|
||||||
DBGERR(1,"IP_ADD_MEMBERSHIP ALLHOSTS");
|
LOGERR("IP_ADD_MEMBERSHIP ALLHOSTS");
|
||||||
ifp->int_state |= IS_ALL_HOSTS;
|
} else {
|
||||||
|
ifp->int_state |= IS_ALL_HOSTS;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!supplier
|
if (!supplier
|
||||||
@ -195,7 +197,7 @@ set_rdisc_mg(struct interface *ifp,
|
|||||||
if (setsockopt(rdisc_sock, IPPROTO_IP,
|
if (setsockopt(rdisc_sock, IPPROTO_IP,
|
||||||
IP_DROP_MEMBERSHIP,
|
IP_DROP_MEMBERSHIP,
|
||||||
&m, sizeof(m)) < 0)
|
&m, sizeof(m)) < 0)
|
||||||
DBGERR(1,"IP_DROP_MEMBERSHIP ALLROUTERS");
|
LOGERR("IP_DROP_MEMBERSHIP ALLROUTERS");
|
||||||
ifp->int_state &= ~IS_ALL_ROUTERS;
|
ifp->int_state &= ~IS_ALL_ROUTERS;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -203,9 +205,11 @@ set_rdisc_mg(struct interface *ifp,
|
|||||||
/* start hearing solicitations */
|
/* start hearing solicitations */
|
||||||
m.imr_multiaddr.s_addr=htonl(INADDR_ALLROUTERS_GROUP);
|
m.imr_multiaddr.s_addr=htonl(INADDR_ALLROUTERS_GROUP);
|
||||||
if (setsockopt(rdisc_sock, IPPROTO_IP, IP_ADD_MEMBERSHIP,
|
if (setsockopt(rdisc_sock, IPPROTO_IP, IP_ADD_MEMBERSHIP,
|
||||||
&m, sizeof(m)) < 0)
|
&m, sizeof(m)) < 0) {
|
||||||
DBGERR(1,"IP_ADD_MEMBERSHIP ALLROUTERS");
|
LOGERR("IP_ADD_MEMBERSHIP ALLROUTERS");
|
||||||
ifp->int_state |= IS_ALL_ROUTERS;
|
} else {
|
||||||
|
ifp->int_state |= IS_ALL_ROUTERS;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -221,7 +225,7 @@ set_supplier(void)
|
|||||||
if (supplier_set)
|
if (supplier_set)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
trace_msg("start suppying routes\n");
|
trace_act("start suppying routes\n");
|
||||||
|
|
||||||
/* Forget discovered routes.
|
/* Forget discovered routes.
|
||||||
*/
|
*/
|
||||||
@ -248,6 +252,9 @@ set_supplier(void)
|
|||||||
ifp->int_rdisc_timer.tv_sec = now.tv_sec+MIN_WAITTIME;
|
ifp->int_rdisc_timer.tv_sec = now.tv_sec+MIN_WAITTIME;
|
||||||
set_rdisc_mg(ifp, 1);
|
set_rdisc_mg(ifp, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* get rid of any redirects */
|
||||||
|
del_redirects(0,0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -260,8 +267,13 @@ rdisc_age(naddr bad_gate)
|
|||||||
struct dr *drp;
|
struct dr *drp;
|
||||||
|
|
||||||
|
|
||||||
|
/* If only adverising, then do only that. */
|
||||||
if (supplier) {
|
if (supplier) {
|
||||||
/* If only adverising, then do only that. */
|
/* if switching from client to server, get rid of old
|
||||||
|
* default routes.
|
||||||
|
*/
|
||||||
|
if (cur_drp != 0)
|
||||||
|
rdisc_sort();
|
||||||
rdisc_adv();
|
rdisc_adv();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -287,7 +299,7 @@ rdisc_age(naddr bad_gate)
|
|||||||
sec = (now.tv_sec - drp->dr_life
|
sec = (now.tv_sec - drp->dr_life
|
||||||
+ SUPPLY_INTERVAL);
|
+ SUPPLY_INTERVAL);
|
||||||
if (drp->dr_ts > sec) {
|
if (drp->dr_ts > sec) {
|
||||||
trace_msg("age 0.0.0.0 --> %s"
|
trace_act("age 0.0.0.0 --> %s"
|
||||||
" via %s\n",
|
" via %s\n",
|
||||||
naddr_ntoa(drp->dr_gate),
|
naddr_ntoa(drp->dr_gate),
|
||||||
drp->dr_ifp->int_name);
|
drp->dr_ifp->int_name);
|
||||||
@ -309,10 +321,11 @@ rdisc_age(naddr bad_gate)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* zap all routes discovered via an interface that has gone bad
|
/* Zap all routes discovered via an interface that has gone bad
|
||||||
|
* This should only be called when !(ifp->int_state & IS_ALIAS)
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
ifbad_rdisc(struct interface *ifp)
|
if_bad_rdisc(struct interface *ifp)
|
||||||
{
|
{
|
||||||
struct dr *drp;
|
struct dr *drp;
|
||||||
|
|
||||||
@ -330,7 +343,7 @@ ifbad_rdisc(struct interface *ifp)
|
|||||||
/* mark an interface ok for router discovering.
|
/* mark an interface ok for router discovering.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
ifok_rdisc(struct interface *ifp)
|
if_ok_rdisc(struct interface *ifp)
|
||||||
{
|
{
|
||||||
set_rdisc_mg(ifp, 1);
|
set_rdisc_mg(ifp, 1);
|
||||||
|
|
||||||
@ -373,7 +386,8 @@ del_rdisc(struct dr *drp)
|
|||||||
*/
|
*/
|
||||||
if (i == 0
|
if (i == 0
|
||||||
&& ifp->int_rdisc_cnt >= MAX_SOLICITATIONS) {
|
&& ifp->int_rdisc_cnt >= MAX_SOLICITATIONS) {
|
||||||
trace_msg("re-solicit routers via %s\n", ifp->int_name);
|
trace_act("discovered route is bad"
|
||||||
|
"--re-solicit routers via %s\n", 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();
|
||||||
@ -390,10 +404,11 @@ rdisc_sort(void)
|
|||||||
struct dr *drp, *new_drp;
|
struct dr *drp, *new_drp;
|
||||||
struct rt_entry *rt;
|
struct rt_entry *rt;
|
||||||
struct interface *ifp;
|
struct interface *ifp;
|
||||||
time_t sec;
|
u_int new_st;
|
||||||
|
n_long new_pref;
|
||||||
|
|
||||||
|
|
||||||
/* find the best discovered route
|
/* Find the best discovered route.
|
||||||
*/
|
*/
|
||||||
new_drp = 0;
|
new_drp = 0;
|
||||||
for (drp = drs; drp < &drs[MAX_ADS]; drp++) {
|
for (drp = drs; drp < &drs[MAX_ADS]; drp++) {
|
||||||
@ -401,33 +416,14 @@ rdisc_sort(void)
|
|||||||
continue;
|
continue;
|
||||||
ifp = drp->dr_ifp;
|
ifp = drp->dr_ifp;
|
||||||
|
|
||||||
/* Get rid of expired discovered routes.
|
/* Get rid of expired discovered routers.
|
||||||
* Routes received over PPP links do not die until
|
|
||||||
* the link has been active long enough to be certain
|
|
||||||
* we should have heard from the router.
|
|
||||||
*/
|
*/
|
||||||
if (drp->dr_ts + drp->dr_life <= now.tv_sec) {
|
if (drp->dr_ts + drp->dr_life <= now.tv_sec) {
|
||||||
if (drp->dr_recv_pref == 0
|
del_rdisc(drp);
|
||||||
|| !ppp_noage
|
continue;
|
||||||
|| !(ifp->int_if_flags & IFF_POINTOPOINT)
|
|
||||||
|| !(ifp->int_state & IS_QUIET)
|
|
||||||
|| (ifp->int_quiet_time
|
|
||||||
+ (sec = MIN(MaxMaxAdvertiseInterval,
|
|
||||||
drp->dr_life)) <= now.tv_sec)) {
|
|
||||||
del_rdisc(drp);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* If the PPP link is quiet, keep checking
|
|
||||||
* in case the link becomes active.
|
|
||||||
* After the link is active, the timer on the
|
|
||||||
* discovered route might force its deletion.
|
|
||||||
*/
|
|
||||||
sec += now.tv_sec+1;
|
|
||||||
} else {
|
|
||||||
sec = drp->dr_ts+drp->dr_life+1;
|
|
||||||
}
|
}
|
||||||
LIM_SEC(rdisc_timer, sec);
|
|
||||||
|
LIM_SEC(rdisc_timer, drp->dr_ts+drp->dr_life+1);
|
||||||
|
|
||||||
/* Update preference with possibly changed interface
|
/* Update preference with possibly changed interface
|
||||||
* metric.
|
* metric.
|
||||||
@ -437,14 +433,21 @@ rdisc_sort(void)
|
|||||||
/* Prefer the current route to prevent thrashing.
|
/* Prefer the current route to prevent thrashing.
|
||||||
* Prefer shorter lifetimes to speed the detection of
|
* Prefer shorter lifetimes to speed the detection of
|
||||||
* bad routers.
|
* bad routers.
|
||||||
|
* Avoid sick interfaces.
|
||||||
*/
|
*/
|
||||||
if (new_drp == 0
|
if (new_drp == 0
|
||||||
|| new_drp->dr_pref < drp->dr_pref
|
|| (!((new_st ^ drp->dr_ifp->int_state) & IS_SICK)
|
||||||
|| (new_drp->dr_pref == drp->dr_pref
|
&& (new_pref < drp->dr_pref
|
||||||
&& (drp == cur_drp
|
|| (new_pref == drp->dr_pref
|
||||||
|| (new_drp != cur_drp
|
&& (drp == cur_drp
|
||||||
&& new_drp->dr_life > drp->dr_life))))
|
|| (new_drp != cur_drp
|
||||||
new_drp = drp;
|
&& new_drp->dr_life > drp->dr_life)))))
|
||||||
|
|| ((new_st & IS_SICK)
|
||||||
|
&& !(drp->dr_ifp->int_state & IS_SICK))) {
|
||||||
|
new_drp = drp;
|
||||||
|
new_st = drp->dr_ifp->int_state;
|
||||||
|
new_pref = drp->dr_pref;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* switch to a better default route
|
/* switch to a better default route
|
||||||
@ -455,12 +458,12 @@ rdisc_sort(void)
|
|||||||
/* Stop using discovered routes if they are all bad
|
/* Stop using discovered routes if they are all bad
|
||||||
*/
|
*/
|
||||||
if (new_drp == 0) {
|
if (new_drp == 0) {
|
||||||
trace_msg("turn off Router Discovery\n");
|
trace_act("turn off Router Discovery client\n");
|
||||||
rdisc_ok = 0;
|
rdisc_ok = 0;
|
||||||
|
|
||||||
if (rt != 0
|
if (rt != 0
|
||||||
&& (rt->rt_state & RS_RDISC)) {
|
&& (rt->rt_state & RS_RDISC)) {
|
||||||
rtchange(rt, rt->rt_state,
|
rtchange(rt, rt->rt_state & ~RS_RDISC,
|
||||||
rt->rt_gate, rt->rt_router,
|
rt->rt_gate, rt->rt_router,
|
||||||
HOPCNT_INFINITY, 0, rt->rt_ifp,
|
HOPCNT_INFINITY, 0, rt->rt_ifp,
|
||||||
now.tv_sec - GARBAGE_TIME, 0);
|
now.tv_sec - GARBAGE_TIME, 0);
|
||||||
@ -472,16 +475,15 @@ rdisc_sort(void)
|
|||||||
|
|
||||||
} else {
|
} else {
|
||||||
if (cur_drp == 0) {
|
if (cur_drp == 0) {
|
||||||
trace_msg("turn on Router Discovery using"
|
trace_act("turn on Router Discovery client"
|
||||||
" %s via %s\n",
|
" using %s via %s\n",
|
||||||
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;
|
||||||
rip_off();
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
trace_msg("switch Router Discovery from"
|
trace_act("switch Router Discovery from"
|
||||||
" %s via %s to %s via %s\n",
|
" %s via %s to %s via %s\n",
|
||||||
naddr_ntoa(cur_drp->dr_gate),
|
naddr_ntoa(cur_drp->dr_gate),
|
||||||
cur_drp->dr_ifp->int_name,
|
cur_drp->dr_ifp->int_name,
|
||||||
@ -499,6 +501,12 @@ rdisc_sort(void)
|
|||||||
new_drp->dr_gate, new_drp->dr_gate,
|
new_drp->dr_gate, new_drp->dr_gate,
|
||||||
0, 0, RS_RDISC, new_drp->dr_ifp);
|
0, 0, RS_RDISC, new_drp->dr_ifp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Now turn off RIP and delete RIP routes,
|
||||||
|
* which might otherwise include the default
|
||||||
|
* we just modified.
|
||||||
|
*/
|
||||||
|
rip_off();
|
||||||
}
|
}
|
||||||
|
|
||||||
cur_drp = new_drp;
|
cur_drp = new_drp;
|
||||||
@ -512,14 +520,13 @@ static void
|
|||||||
parse_ad(naddr from,
|
parse_ad(naddr from,
|
||||||
naddr gate,
|
naddr gate,
|
||||||
n_long pref,
|
n_long pref,
|
||||||
int life,
|
u_short life,
|
||||||
struct interface *ifp)
|
struct interface *ifp)
|
||||||
{
|
{
|
||||||
static naddr bad_gate;
|
static naddr bad_gate;
|
||||||
struct dr *drp, *new_drp;
|
struct dr *drp, *new_drp;
|
||||||
|
|
||||||
|
|
||||||
NTOHL(gate);
|
|
||||||
if (gate == RIP_DEFAULT
|
if (gate == RIP_DEFAULT
|
||||||
|| !check_dst(gate)) {
|
|| !check_dst(gate)) {
|
||||||
if (bad_gate != from) {
|
if (bad_gate != from) {
|
||||||
@ -534,55 +541,79 @@ parse_ad(naddr from,
|
|||||||
/* ignore pointers to ourself and routes via unreachable networks
|
/* ignore pointers to ourself and routes via unreachable networks
|
||||||
*/
|
*/
|
||||||
if (ifwithaddr(gate, 1, 0) != 0) {
|
if (ifwithaddr(gate, 1, 0) != 0) {
|
||||||
if (TRACEPACKETS)
|
trace_pkt("\tdiscard our own Router Discovery Ad\n");
|
||||||
trace_msg("discard our own packet\n");
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!on_net(gate, ifp->int_net, ifp->int_mask)) {
|
if (!on_net(gate, ifp->int_net, ifp->int_mask)) {
|
||||||
if (TRACEPACKETS)
|
trace_pkt("\tdiscard Router Discovery Ad"
|
||||||
trace_msg("discard packet from unreachable net\n");
|
" from unreachable net\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Convert preference to an unsigned value
|
/* Convert preference to an unsigned value
|
||||||
* and bias it by the metric of the interface.
|
* and later bias it by the metric of the interface.
|
||||||
*/
|
*/
|
||||||
pref = ntohl(pref) ^ MIN_PreferenceLevel;
|
pref = ntohl(pref) ^ MIN_PreferenceLevel;
|
||||||
|
|
||||||
|
if (pref == 0 || life == 0) {
|
||||||
|
pref = 0;
|
||||||
|
life = 0;
|
||||||
|
}
|
||||||
|
|
||||||
for (new_drp = drs, drp = drs; drp < &drs[MAX_ADS]; drp++) {
|
for (new_drp = 0, drp = drs; drp < &drs[MAX_ADS]; drp++) {
|
||||||
if (drp->dr_ts == 0) {
|
/* accept new info for a familiar entry
|
||||||
new_drp = drp;
|
*/
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (drp->dr_gate == gate) {
|
if (drp->dr_gate == gate) {
|
||||||
/* Zap an entry we are being told is kaput */
|
|
||||||
if (pref == 0 || life == 0) {
|
|
||||||
drp->dr_recv_pref = 0;
|
|
||||||
drp->dr_life = 0;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
new_drp = drp;
|
new_drp = drp;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* look for least valueable entry */
|
if (life == 0)
|
||||||
if (new_drp->dr_pref > drp->dr_pref)
|
continue; /* do not worry about dead ads */
|
||||||
new_drp = drp;
|
|
||||||
|
if (drp->dr_ts == 0) {
|
||||||
|
new_drp = drp; /* use unused entry */
|
||||||
|
|
||||||
|
} else if (new_drp == 0) {
|
||||||
|
/* look for an entry worse than the new one to
|
||||||
|
* reuse.
|
||||||
|
*/
|
||||||
|
if ((!(ifp->int_state & IS_SICK)
|
||||||
|
&& (drp->dr_ifp->int_state & IS_SICK))
|
||||||
|
|| (pref > drp->dr_pref
|
||||||
|
&& !((ifp->int_state ^ drp->dr_ifp->int_state)
|
||||||
|
& IS_SICK)))
|
||||||
|
new_drp = drp;
|
||||||
|
|
||||||
|
} else if (new_drp->dr_ts != 0) {
|
||||||
|
/* look for the least valueable entry to reuse
|
||||||
|
*/
|
||||||
|
if ((!(new_drp->dr_ifp->int_state & IS_SICK)
|
||||||
|
&& (drp->dr_ifp->int_state & IS_SICK))
|
||||||
|
|| (new_drp->dr_pref > drp->dr_pref
|
||||||
|
&& !((new_drp->dr_ifp->int_state
|
||||||
|
^ drp->dr_ifp->int_state)
|
||||||
|
& IS_SICK)))
|
||||||
|
new_drp = drp;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ignore zap of an entry we do not know about. */
|
/* forget it if all of the current entries are better */
|
||||||
if (pref == 0 || life == 0)
|
if (new_drp == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
new_drp->dr_ifp = ifp;
|
new_drp->dr_ifp = ifp;
|
||||||
new_drp->dr_gate = gate;
|
new_drp->dr_gate = gate;
|
||||||
new_drp->dr_ts = now.tv_sec;
|
new_drp->dr_ts = now.tv_sec;
|
||||||
new_drp->dr_life = ntohl(life);
|
new_drp->dr_life = ntohs(life);
|
||||||
new_drp->dr_recv_pref = pref;
|
new_drp->dr_recv_pref = pref;
|
||||||
|
/* bias functional preference by metric of the interface */
|
||||||
new_drp->dr_pref = PREF(pref,ifp);
|
new_drp->dr_pref = PREF(pref,ifp);
|
||||||
|
|
||||||
ifp->int_rdisc_cnt = MAX_SOLICITATIONS;
|
/* after hearing a good advertisement, stop asking
|
||||||
|
*/
|
||||||
|
if (!(ifp->int_state & IS_SICK))
|
||||||
|
ifp->int_rdisc_cnt = MAX_SOLICITATIONS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -638,13 +669,19 @@ send_rdisc(union ad_u *p,
|
|||||||
msg = "Send pt-to-pt";
|
msg = "Send pt-to-pt";
|
||||||
sin.sin_addr.s_addr = ifp->int_dstaddr;
|
sin.sin_addr.s_addr = ifp->int_dstaddr;
|
||||||
} else {
|
} else {
|
||||||
msg = "Broadcast";
|
msg = "Send broadcast";
|
||||||
sin.sin_addr.s_addr = ifp->int_brdaddr;
|
sin.sin_addr.s_addr = ifp->int_brdaddr;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 2: /* multicast */
|
case 2: /* multicast */
|
||||||
msg = "Multicast";
|
msg = "Send multicast";
|
||||||
|
if (ifp->int_state & IS_DUP) {
|
||||||
|
trace_act("abort multicast output via %s"
|
||||||
|
" with duplicate address\n",
|
||||||
|
ifp->int_name);
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (rdisc_sock_mcast != ifp) {
|
if (rdisc_sock_mcast != ifp) {
|
||||||
/* select the right interface. */
|
/* select the right interface. */
|
||||||
#ifdef MCAST_PPP_BUG
|
#ifdef MCAST_PPP_BUG
|
||||||
@ -660,11 +697,12 @@ send_rdisc(union ad_u *p,
|
|||||||
} else
|
} else
|
||||||
#endif
|
#endif
|
||||||
tgt_mcast = ifp->int_addr;
|
tgt_mcast = ifp->int_addr;
|
||||||
if (setsockopt(rdisc_sock,
|
if (0 > setsockopt(rdisc_sock,
|
||||||
IPPROTO_IP, IP_MULTICAST_IF,
|
IPPROTO_IP, IP_MULTICAST_IF,
|
||||||
&tgt_mcast, sizeof(tgt_mcast))) {
|
&tgt_mcast, sizeof(tgt_mcast))) {
|
||||||
DBGERR(1,"setsockopt(rdisc_sock,"
|
LOGERR("setsockopt(rdisc_sock,"
|
||||||
"IP_MULTICAST_IF)");
|
"IP_MULTICAST_IF)");
|
||||||
|
rdisc_sock_mcast = 0;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
rdisc_sock_mcast = ifp;
|
rdisc_sock_mcast = ifp;
|
||||||
@ -673,19 +711,19 @@ send_rdisc(union ad_u *p,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (TRACEPACKETS)
|
trace_rdisc(msg, ifp->int_addr, sin.sin_addr.s_addr, ifp,
|
||||||
trace_rdisc(msg, ifp->int_addr, sin.sin_addr.s_addr, ifp,
|
p, p_size);
|
||||||
p, p_size);
|
|
||||||
|
|
||||||
if (0 > sendto(rdisc_sock, p, p_size, flags,
|
if (0 > sendto(rdisc_sock, p, p_size, flags,
|
||||||
(struct sockaddr *)&sin, sizeof(sin))) {
|
(struct sockaddr *)&sin, sizeof(sin))) {
|
||||||
msglog("sendto(%s%s%s): %s",
|
if (ifp == 0 || !(ifp->int_state & IS_BROKE))
|
||||||
ifp != 0 ? ifp->int_name : "",
|
msglog("sendto(%s%s%s): %s",
|
||||||
ifp != 0 ? ", " : "",
|
ifp != 0 ? ifp->int_name : "",
|
||||||
inet_ntoa(sin.sin_addr),
|
ifp != 0 ? ", " : "",
|
||||||
strerror(errno));
|
inet_ntoa(sin.sin_addr),
|
||||||
|
strerror(errno));
|
||||||
if (ifp != 0)
|
if (ifp != 0)
|
||||||
ifbad(ifp, 0);
|
if_sick(ifp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -707,9 +745,7 @@ send_adv(struct interface *ifp,
|
|||||||
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 : htonl(ifp->int_rdisc_int*3);
|
u.ad.icmp_ad_life = stopint ? 0 : htons(ifp->int_rdisc_int*3);
|
||||||
|
|
||||||
u.ad.icmp_ad_life = stopint ? 0 : htonl(ifp->int_rdisc_int*3);
|
|
||||||
pref = ifp->int_rdisc_pref ^ MIN_PreferenceLevel;
|
pref = ifp->int_rdisc_pref ^ MIN_PreferenceLevel;
|
||||||
pref = PREF(pref, ifp) ^ MIN_PreferenceLevel;
|
pref = PREF(pref, ifp) ^ MIN_PreferenceLevel;
|
||||||
u.ad.icmp_ad_info[0].icmp_ad_pref = htonl(pref);
|
u.ad.icmp_ad_info[0].icmp_ad_pref = htonl(pref);
|
||||||
@ -741,8 +777,8 @@ rdisc_adv(void)
|
|||||||
|
|
||||||
if (!timercmp(&ifp->int_rdisc_timer, &now, >)
|
if (!timercmp(&ifp->int_rdisc_timer, &now, >)
|
||||||
|| stopint) {
|
|| stopint) {
|
||||||
send_adv(ifp, INADDR_ALLHOSTS_GROUP,
|
send_adv(ifp, htonl(INADDR_ALLHOSTS_GROUP),
|
||||||
(ifp->int_if_flags&IS_BCAST_RDISC) ? 1 : 2);
|
(ifp->int_state&IS_BCAST_RDISC) ? 1 : 2);
|
||||||
ifp->int_rdisc_cnt++;
|
ifp->int_rdisc_cnt++;
|
||||||
|
|
||||||
intvl_random(&ifp->int_rdisc_timer,
|
intvl_random(&ifp->int_rdisc_timer,
|
||||||
@ -788,9 +824,8 @@ rdisc_sol(void)
|
|||||||
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));
|
||||||
send_rdisc(&u, sizeof(u.so), ifp,
|
send_rdisc(&u, sizeof(u.so), ifp,
|
||||||
INADDR_ALLROUTERS_GROUP,
|
htonl(INADDR_ALLROUTERS_GROUP),
|
||||||
((ifp->int_if_flags & IS_BCAST_RDISC)
|
((ifp->int_state&IS_BCAST_RDISC) ? 1 : 2));
|
||||||
? 1 : 2));
|
|
||||||
|
|
||||||
if (++ifp->int_rdisc_cnt >= MAX_SOLICITATIONS)
|
if (++ifp->int_rdisc_cnt >= MAX_SOLICITATIONS)
|
||||||
continue;
|
continue;
|
||||||
@ -833,21 +868,19 @@ ck_icmp(char *act,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (p->icmp.icmp_code != 0) {
|
if (p->icmp.icmp_code != 0) {
|
||||||
if (TRACEPACKETS)
|
trace_pkt("unrecognized ICMP Router"
|
||||||
msglog("unrecognized ICMP Router"
|
" %s code=%d from %s to %s\n",
|
||||||
" %s code=%d from %s to %s\n",
|
type, p->icmp.icmp_code,
|
||||||
type, p->icmp.icmp_code,
|
naddr_ntoa(from), naddr_ntoa(to));
|
||||||
naddr_ntoa(from), naddr_ntoa(to));
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (TRACEPACKETS)
|
trace_rdisc(act, from, to, ifp, p, len);
|
||||||
trace_rdisc(act, from, to, ifp, p, len);
|
|
||||||
|
|
||||||
if (ifp == 0 && TRACEPACKETS)
|
if (ifp == 0)
|
||||||
msglog("unknown interface for router-discovery %s"
|
trace_pkt("unknown interface for router-discovery %s"
|
||||||
" from %s to %s",
|
" from %s to %s",
|
||||||
type, naddr_ntoa(from), naddr_ntoa(to));
|
type, naddr_ntoa(from), naddr_ntoa(to));
|
||||||
|
|
||||||
return ifp;
|
return ifp;
|
||||||
}
|
}
|
||||||
@ -897,7 +930,7 @@ read_d(void)
|
|||||||
if (ifp == 0)
|
if (ifp == 0)
|
||||||
continue;
|
continue;
|
||||||
if (ifwithaddr(from.sin_addr.s_addr, 0, 0)) {
|
if (ifwithaddr(from.sin_addr.s_addr, 0, 0)) {
|
||||||
trace_msg("\tdiscard our own packet\n");
|
trace_pkt("\tdiscard our own Router Discovery msg\n");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -914,8 +947,7 @@ read_d(void)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (p->ad.icmp_ad_num == 0) {
|
if (p->ad.icmp_ad_num == 0) {
|
||||||
if (TRACEPACKETS)
|
trace_pkt("\tempty?\n");
|
||||||
trace_msg("\tempty?\n");
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (cc != (sizeof(p->ad) - sizeof(p->ad.icmp_ad_info)
|
if (cc != (sizeof(p->ad) - sizeof(p->ad.icmp_ad_info)
|
||||||
@ -938,7 +970,7 @@ read_d(void)
|
|||||||
for (n = 0; n < p->ad.icmp_ad_num; n++) {
|
for (n = 0; n < p->ad.icmp_ad_num; n++) {
|
||||||
parse_ad(from.sin_addr.s_addr,
|
parse_ad(from.sin_addr.s_addr,
|
||||||
wp[0], wp[1],
|
wp[0], wp[1],
|
||||||
p->ad.icmp_ad_life,
|
ntohs(p->ad.icmp_ad_life),
|
||||||
ifp);
|
ifp);
|
||||||
wp += p->ad.icmp_ad_asize;
|
wp += p->ad.icmp_ad_asize;
|
||||||
}
|
}
|
||||||
|
@ -31,12 +31,12 @@
|
|||||||
.\"
|
.\"
|
||||||
.\" @(#)routed.8 8.2 (Berkeley) 12/11/93
|
.\" @(#)routed.8 8.2 (Berkeley) 12/11/93
|
||||||
.\"
|
.\"
|
||||||
.Dd March 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
|
||||||
.Nd network routing daemon
|
.Nd network RIP and router discovery routing daemon
|
||||||
.Sh SYNOPSIS
|
.Sh SYNOPSIS
|
||||||
.Nm
|
.Nm
|
||||||
.Op Fl sqdghmpAt
|
.Op Fl sqdghmpAt
|
||||||
@ -54,8 +54,7 @@ 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 version of the RIPv1 protocol implemented
|
The RIPv1 protocol is based on the reference 4.3BSD daemon.
|
||||||
is based on the RIPv1 protocol implemented in the reference 4.3BSD daemon.
|
|
||||||
.Pp
|
.Pp
|
||||||
It listens on the
|
It listens on the
|
||||||
.Xr udp 4
|
.Xr udp 4
|
||||||
@ -65,7 +64,7 @@ service (see
|
|||||||
.Xr services 5 )
|
.Xr services 5 )
|
||||||
for Routing Information Protocol packets.
|
for Routing Information Protocol packets.
|
||||||
It also sends and receives multicast Router Discovery ICMP messages.
|
It also sends and receives multicast Router Discovery ICMP messages.
|
||||||
If the host is an router,
|
If the host is a router,
|
||||||
.Nm
|
.Nm
|
||||||
periodically supplies copies
|
periodically supplies copies
|
||||||
of its routing tables to any directly connected hosts and networks.
|
of its routing tables to any directly connected hosts and networks.
|
||||||
@ -116,8 +115,8 @@ 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 resquesting
|
Responses do not contain routes with a first hop on the requesting
|
||||||
network to implement
|
network to implement in part
|
||||||
.Em split-horizon .
|
.Em split-horizon .
|
||||||
Requests from query programs
|
Requests from query programs
|
||||||
such as
|
such as
|
||||||
@ -157,7 +156,7 @@ This is a form of
|
|||||||
.Em poison reverse .
|
.Em poison reverse .
|
||||||
.Pp
|
.Pp
|
||||||
Routes in the kernel table that are added or changed as a result
|
Routes in the kernel table that are added or changed as a result
|
||||||
of ICMP Redirect messages are deleted after a while to minimze
|
of ICMP Redirect messages are deleted after a while to minimize
|
||||||
.Em black-holes .
|
.Em black-holes .
|
||||||
When a TCP connection suffers a timeout,
|
When a TCP connection suffers a timeout,
|
||||||
the kernel tells
|
the kernel tells
|
||||||
@ -170,7 +169,7 @@ age of any relevant Router Discovery Protocol default routes.
|
|||||||
Hosts acting as internetwork routers gratuitously supply their
|
Hosts acting as internetwork routers gratuitously supply their
|
||||||
routing tables every 30 seconds to all directly connected hosts
|
routing tables every 30 seconds to all directly connected hosts
|
||||||
and networks.
|
and networks.
|
||||||
The response is sent to the broadcast address on nets that support
|
These RIP responses are sent to the broadcast address on nets that support
|
||||||
broadcasting,
|
broadcasting,
|
||||||
to the destination address on point-to-point links, and to the router's
|
to the destination address on point-to-point links, and to the router's
|
||||||
own address on other networks.
|
own address on other networks.
|
||||||
@ -198,6 +197,37 @@ 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.
|
||||||
|
.Pp
|
||||||
|
While using Router Discovery (which happens by default when
|
||||||
|
the system has a single network interface and a Router Discover Advertisement
|
||||||
|
is received), there is a single default route and a variable number of
|
||||||
|
redirected host routes in the kernel table.
|
||||||
|
.Pp
|
||||||
|
The Router Discover standard requires that advertisements
|
||||||
|
have a default "lifetime" of 30 minutes. That means should
|
||||||
|
something happen, a client can be without a good route for
|
||||||
|
30 minutes. It is a good idea to reduce the default to 45
|
||||||
|
seconds using
|
||||||
|
.Fl P Cm rdisc_interval=45
|
||||||
|
on the command line or
|
||||||
|
.Cm rdisc_interval=45
|
||||||
|
in the
|
||||||
|
.Pa /etc/gateways
|
||||||
|
file.
|
||||||
|
.Pp
|
||||||
|
While using Router Discovery (which happens by default when
|
||||||
|
the system has a single network interface and a Router Discover Advertisement
|
||||||
|
is received), there is a single default route and a variable number of
|
||||||
|
redirected host routes in the kernel table.
|
||||||
|
.Pp
|
||||||
|
See the
|
||||||
|
.Cm pm_rdisc
|
||||||
|
facility described below to support "legacy" systems
|
||||||
|
that can handle neither RIPv2 nor Router Discovery.
|
||||||
|
.Pp
|
||||||
|
By default, neither Router Discovery advertisements nor solicications
|
||||||
|
are sent over point to point links (e.g. PPP).
|
||||||
|
|
||||||
.Pp
|
.Pp
|
||||||
Options supported by
|
Options supported by
|
||||||
.Nm routed :
|
.Nm routed :
|
||||||
@ -219,9 +249,25 @@ This option is meant for interactive use.
|
|||||||
.It Fl g
|
.It Fl g
|
||||||
This flag is used on internetwork routers to offer a route
|
This flag is used on internetwork routers to offer a route
|
||||||
to the "default" destination.
|
to the "default" destination.
|
||||||
|
It is equivalent to
|
||||||
|
.Fl F
|
||||||
|
.Cm 0/0,1
|
||||||
|
and is present mostly for historical reasons.
|
||||||
|
A better choice is
|
||||||
|
.Fl P Cm pm_rdisc
|
||||||
|
on the command line or
|
||||||
|
.CM pm_rdisc in the
|
||||||
|
.Pa /etc/gateways
|
||||||
|
file.
|
||||||
|
since a larger metric
|
||||||
|
will be used, reducing the spread of the potentially dangerous
|
||||||
|
default route.
|
||||||
This is typically used on a gateway to the Internet,
|
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
|
||||||
|
dangerous. It is more commonly accidently used to create chaos with routing
|
||||||
|
loop than to solve problems.
|
||||||
.It Fl h
|
.It Fl h
|
||||||
This causes host or point-to-point routes to not be advertised,
|
This causes 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.
|
||||||
@ -242,20 +288,16 @@ The
|
|||||||
option overrides the
|
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 p
|
|
||||||
causes routes received over point-to-point links to not be timed
|
|
||||||
out while the link is idle.
|
|
||||||
This is handy for "demand dialed" PPP links that filter routing packets.
|
|
||||||
.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 wiht RFC 1723,
|
This option is required for conformance with RFC 1723.
|
||||||
but it makes little 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
|
.It Fl T Ar tracefile
|
||||||
increases the debugging level to at least 1 and
|
increases the debugging level to at least 1 and
|
||||||
causes debugging information to be appended to the file.
|
causes debugging information to be appended to the trace file.
|
||||||
.It Fl t
|
.It Fl t
|
||||||
increases the debugging level, which causes more information to be logged
|
increases the debugging level, which causes more information to be logged
|
||||||
on the tracefile specified with
|
on the tracefile specified with
|
||||||
@ -266,9 +308,11 @@ with the
|
|||||||
.Em SIGUSR1
|
.Em SIGUSR1
|
||||||
or
|
or
|
||||||
.Em SIGUSR2
|
.Em SIGUSR2
|
||||||
signals.
|
signals or with the
|
||||||
|
.Cm rtquery
|
||||||
|
command.
|
||||||
.It Fl F Ar net[/mask][,metric]
|
.It Fl F Ar net[/mask][,metric]
|
||||||
minimize routes in transmissions to network
|
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 .
|
||||||
@ -279,6 +323,13 @@ 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
|
||||||
|
loops.
|
||||||
|
Notice also that more than one interface can match the specified network
|
||||||
|
number and mask.
|
||||||
|
See also
|
||||||
|
.Fl g .
|
||||||
.It Fl P Ar parms
|
.It Fl P Ar parms
|
||||||
is equivalent to adding the parameter
|
is equivalent to adding the parameter
|
||||||
line
|
line
|
||||||
@ -327,8 +378,8 @@ Distant active gateways are treated like network interfaces.
|
|||||||
RIP responses are sent
|
RIP responses are sent
|
||||||
to the distant
|
to the distant
|
||||||
.Em active
|
.Em active
|
||||||
gateway and if no responses are received
|
gateway.
|
||||||
in turn for a period of the time, the associated route deleted from
|
If no responses are received, the associated route is deleted from
|
||||||
the kernel table and RIP responses advertised via other interfaces.
|
the kernel table and RIP responses advertised via other interfaces.
|
||||||
If the distant gateway resumes sending RIP responses, the associated
|
If the distant gateway resumes sending RIP responses, the associated
|
||||||
route is restored.
|
route is restored.
|
||||||
@ -419,49 +470,68 @@ One of the keywords
|
|||||||
or
|
or
|
||||||
.Cm external
|
.Cm external
|
||||||
must be present to indicate whether the gateway should be treated as
|
must be present to indicate whether the gateway should be treated as
|
||||||
.Em passive
|
.Cm passive
|
||||||
or
|
or
|
||||||
.Em active
|
.Cm active
|
||||||
(as described above),
|
(as described above),
|
||||||
or whether the gateway is
|
or whether the gateway is
|
||||||
.Em external
|
.Cm external
|
||||||
to the scope of the RIP protocol.
|
to the scope of the RIP protocol.
|
||||||
.Pp
|
.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:
|
or more of the following parameter settings, separated by commas or
|
||||||
|
blanks:
|
||||||
.Bl -tag -width Ds
|
.Bl -tag -width Ds
|
||||||
.It Cm if Ns \&= Ns Ar ifname
|
.It Cm if Ns \&= Ns Ar ifname
|
||||||
indicates that the other parameters on the line apply to the interface
|
indicates that the other parameters on the line apply to the interface
|
||||||
name
|
name
|
||||||
.Ar ifname .
|
.Ar ifname .
|
||||||
.It Cm subnet Ns \&= Ns Ar nname[/mask]
|
.It Cm subnet Ns \&= Ns Ar nname[/mask][,metric]
|
||||||
causes other routes to be aggregated as if a compatible route to
|
advertises a route to network
|
||||||
Ar nname/mask
|
.AR nname
|
||||||
had been received.
|
with mask
|
||||||
|
.AR mask
|
||||||
|
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.
|
||||||
|
.Pp
|
||||||
|
Do not use this feature unless necessary. It is dangerous.
|
||||||
.It Cm passwd Ns \&= Ns Ar XXX
|
.It Cm passwd Ns \&= Ns Ar XXX
|
||||||
specifies a RIPv2 password that will be included on all RIPv2
|
specifies a RIPv2 password that will be included on all RIPv2
|
||||||
responses sent and checked on all RIPv2 responses received.
|
responses sent and checked on all RIPv2 responses received.
|
||||||
|
The password must not contain any blanks, tab characters, commas
|
||||||
|
or '#' characters.
|
||||||
.It Cm no_ag
|
.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
|
||||||
turns off aggregation of networks into supernets in RIPv2 responses.
|
turns off aggregation of networks into supernets in RIPv2 responses.
|
||||||
|
.It Cm passive
|
||||||
|
is equivalent
|
||||||
|
.Cm no_rip Cm no_rdisc .
|
||||||
.It Cm no_rip
|
.It Cm no_rip
|
||||||
disables all RIP processing on the specified interface.
|
disables all RIP processing on the specified interface.
|
||||||
If no interfaces are allowed to process RIP packets,
|
If no interfaces are allowed to process RIP packets,
|
||||||
.Nm
|
.Nm
|
||||||
acts purely as a router discovery daemon.
|
acts purely as a router discovery daemon.
|
||||||
.Ar " No_rip "
|
.Cm No_rip
|
||||||
is equivalent to
|
is equivalent to
|
||||||
.Ar " no_ripv1_in no_ripv2_in no_ripv1_out no_ripv2_out ."
|
.Cm no_ripv1_in no_ripv2_in no_ripv1_out no_ripv2_out .
|
||||||
|
|
||||||
|
Note that turning off RIP without explicitly turning on router
|
||||||
|
discovery advertisements with
|
||||||
|
.Cm rdisc_adv
|
||||||
|
or
|
||||||
|
.Fl s
|
||||||
|
causes
|
||||||
|
.Nm routed
|
||||||
|
to act as a client router discovery daemon, not adveritising.
|
||||||
.It Cm no_ripv1_in
|
.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
|
||||||
disables the RIPv2 responses that are otherwise multicast containing
|
turns off RIPv1 output and causes RIPv2 advertisements to be
|
||||||
information that cannot be sent in RIPv2 packets.
|
multicast when possible.
|
||||||
.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
|
||||||
@ -488,9 +558,24 @@ are transmitted to N seconds and their lifetime to 3*N.
|
|||||||
.It Cm fake_default Ns \&= Ns Ar metric
|
.It Cm fake_default Ns \&= Ns Ar metric
|
||||||
has an identical effect to
|
has an identical effect to
|
||||||
.Fl F Ar net[/mask][,metric]
|
.Fl F Ar net[/mask][,metric]
|
||||||
with the network and mask coming from the affected interface.
|
with the network and mask coming from the sepcified interface.
|
||||||
|
.It Cm pm_rdisc
|
||||||
|
is similar to
|
||||||
|
.Cm fake_default .
|
||||||
|
When RIPv2 routes are multicast, so that RIPv1 listeners cannot
|
||||||
|
receive them, this feature causes a RIPv1 default route to be
|
||||||
|
broadcast to RIPv1 listeners.
|
||||||
|
Unless modified with
|
||||||
|
.Cm fake_default ,
|
||||||
|
the default route is broadcast with a metric of 14.
|
||||||
|
That serves as a "poor man's router discovery" protocol.
|
||||||
.El
|
.El
|
||||||
.Pp
|
.Pp
|
||||||
|
Note that the netmask associated with point-to-point links (such as SLIP
|
||||||
|
or PPP, with the IFF_POINTOPOINT flag) is used by
|
||||||
|
.Nm routed
|
||||||
|
to infer the netmask used by the remote system when RIPv1 is used.
|
||||||
|
.Pp
|
||||||
.Sh FILES
|
.Sh FILES
|
||||||
.Bl -tag -width /etc/gateways -compact
|
.Bl -tag -width /etc/gateways -compact
|
||||||
.It Pa /etc/gateways
|
.It Pa /etc/gateways
|
||||||
|
@ -3,4 +3,5 @@
|
|||||||
PROG= rtquery
|
PROG= rtquery
|
||||||
MAN8= rtquery.8
|
MAN8= rtquery.8
|
||||||
|
|
||||||
|
.include "../../Makefile.inc"
|
||||||
.include <bsd.prog.mk>
|
.include <bsd.prog.mk>
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
.Dd April 9, 1996
|
.Dd June 1, 1996
|
||||||
.Dt RTQUERY 8
|
.Dt RTQUERY 8
|
||||||
.Os BSD 4.4
|
.Os BSD 4.4
|
||||||
.Sh NAME
|
.Sh NAME
|
||||||
@ -7,7 +7,7 @@
|
|||||||
.Sh SYNOPSIS
|
.Sh SYNOPSIS
|
||||||
.Nm
|
.Nm
|
||||||
.Op Fl np1
|
.Op Fl np1
|
||||||
.Op Fl 1 Ar timeout
|
.Op Fl w Ar timeout
|
||||||
.Op Fl r Ar addr
|
.Op Fl r Ar addr
|
||||||
.Ar host ...
|
.Ar host ...
|
||||||
.Sh DESCRIPTION
|
.Sh DESCRIPTION
|
||||||
@ -29,22 +29,26 @@ by default uses the
|
|||||||
.Em request
|
.Em request
|
||||||
command.
|
command.
|
||||||
When the
|
When the
|
||||||
.B \-p
|
.Ar -p
|
||||||
option is specified,
|
option is specified,
|
||||||
.Nm rtquery
|
.Nm rtquery
|
||||||
uses the
|
uses the
|
||||||
.Em poll
|
.Em poll
|
||||||
command, which is an
|
command, an
|
||||||
undocumented extension to the RIP specification supported by
|
undocumented extension to the RIP protocol supported by
|
||||||
.IR gated (1M).
|
.Xr gated 8 .
|
||||||
When querying
|
When querying gated, the
|
||||||
.IR gated (1M),
|
.Em poll
|
||||||
the
|
|
||||||
.I poll
|
|
||||||
command is preferred over the
|
command is preferred over the
|
||||||
.I request
|
.I 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
|
||||||
Poisioned Reverse.
|
Poisoned Reverse, and because some versions of gated do not answer
|
||||||
|
the Request command. Routed does not answer the Poll command, but
|
||||||
|
recognizes Requests coming from rtquery and so answers completely.
|
||||||
|
.Pp
|
||||||
|
.Em Rtquery
|
||||||
|
is also used to turn tracing on or off in
|
||||||
|
.Em routed .
|
||||||
.Pp
|
.Pp
|
||||||
Options supported by
|
Options supported by
|
||||||
.Nm rtquery :
|
.Nm rtquery :
|
||||||
@ -57,10 +61,10 @@ The
|
|||||||
option displays only the numeric network and host numbers.
|
option displays only the numeric network and host numbers.
|
||||||
.It Fl p
|
.It Fl p
|
||||||
Uses 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 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.
|
query using RIP version 1 instead of RIP version 2.
|
||||||
@ -69,10 +73,28 @@ 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
|
ask about the route to destination
|
||||||
.Em parms
|
.Em addr .
|
||||||
|
.It Fl t Ar op
|
||||||
|
change tracing, where
|
||||||
|
.Em op
|
||||||
|
is one of the following.
|
||||||
|
Requests from processes not running with UID 0 or on distant networks
|
||||||
|
are generally ignored.
|
||||||
|
.El
|
||||||
|
.Bl -tag -width Ds -offset indent-two
|
||||||
|
.It Em on=filename
|
||||||
|
turn tracing on into the specified file. That file must usually
|
||||||
|
have been specified when the daemon was started or be the same
|
||||||
|
as a fixed name, often
|
||||||
|
.Pa /tmp/routed.log .
|
||||||
|
.It Em more
|
||||||
|
increases the debugging level.
|
||||||
|
.It Em off
|
||||||
|
turns off tracing.
|
||||||
|
.El
|
||||||
.Sh SEE ALSO
|
.Sh SEE ALSO
|
||||||
.Xr routed 8,
|
.Xr routed 8 ,
|
||||||
.Xr gated 8,
|
.Xr gated 8 .
|
||||||
.br
|
.br
|
||||||
RFC\ 1058 - Routing Information Protocol, RIPv1
|
RFC\ 1058 - Routing Information Protocol, RIPv1
|
||||||
.br
|
.br
|
||||||
|
@ -31,13 +31,11 @@
|
|||||||
* SUCH DAMAGE.
|
* SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef lint
|
char copyright[] =
|
||||||
static 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 !defined(lint) && !defined(sgi)
|
||||||
static char sccsid[] = "@(#)query.c 8.1 (Berkeley) 6/5/93";
|
static char sccsid[] = "@(#)query.c 8.1 (Berkeley) 6/5/93";
|
||||||
#endif /* not lint */
|
#endif /* not lint */
|
||||||
|
|
||||||
@ -71,24 +69,33 @@ int s;
|
|||||||
|
|
||||||
char *pgmname;
|
char *pgmname;
|
||||||
|
|
||||||
union pkt_buf {
|
union {
|
||||||
char packet[MAXPACKETSIZE+4096];
|
struct rip rip;
|
||||||
|
char packet[MAXPACKETSIZE+MAXPATHLEN];
|
||||||
|
} omsg_buf;
|
||||||
|
#define OMSG omsg_buf.rip
|
||||||
|
int omsg_len = sizeof(struct rip);
|
||||||
|
|
||||||
|
union {
|
||||||
struct rip rip;
|
struct rip rip;
|
||||||
} msg_buf;
|
char packet[MAXPACKETSIZE+1024];
|
||||||
#define MSG msg_buf.rip
|
} imsg_buf;
|
||||||
#define MSG_LIM ((struct rip*)(&msg_buf.packet[MAXPACKETSIZE \
|
#define IMSG imsg_buf.rip
|
||||||
- sizeof(struct netinfo)]))
|
|
||||||
|
|
||||||
int nflag; /* numbers, no names */
|
int nflag; /* numbers, no names */
|
||||||
int pflag; /* play the `gated` game */
|
int pflag; /* play the `gated` game */
|
||||||
int ripv2 = 1; /* use RIP version 2 */
|
int ripv2 = 1; /* use RIP version 2 */
|
||||||
int wtime = WTIME;
|
int wtime = WTIME;
|
||||||
int rflag; /* 1=ask about a particular route */
|
int rflag; /* 1=ask about a particular route */
|
||||||
|
int trace;
|
||||||
|
int not_trace;
|
||||||
|
|
||||||
struct timeval start; /* when query sent */
|
struct timeval sent; /* when query sent */
|
||||||
|
|
||||||
static void rip_input(struct sockaddr_in*, int);
|
static void rip_input(struct sockaddr_in*, int);
|
||||||
static int query(char *, struct netinfo *);
|
static int out(char *);
|
||||||
|
static void trace_loop(char *argv[]);
|
||||||
|
static void query_loop(char *argv[], int);
|
||||||
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);
|
||||||
|
|
||||||
@ -97,67 +104,120 @@ int
|
|||||||
main(int argc,
|
main(int argc,
|
||||||
char *argv[])
|
char *argv[])
|
||||||
{
|
{
|
||||||
char *p;
|
int ch, bsize;
|
||||||
struct seen {
|
char *p, *options, *value;
|
||||||
struct seen *next;
|
|
||||||
struct in_addr addr;
|
|
||||||
} *seen, *sp;
|
|
||||||
int answered = 0;
|
|
||||||
int ch, cc, bsize;
|
|
||||||
fd_set bits;
|
|
||||||
struct timeval now, delay;
|
|
||||||
struct sockaddr_in from;
|
|
||||||
int fromlen;
|
|
||||||
struct netinfo rt;
|
|
||||||
|
|
||||||
|
OMSG.rip_nets[0].n_dst = RIP_DEFAULT;
|
||||||
bzero(&rt, sizeof(rt));
|
OMSG.rip_nets[0].n_family = RIP_AF_UNSPEC;
|
||||||
|
OMSG.rip_nets[0].n_metric = htonl(HOPCNT_INFINITY);
|
||||||
|
|
||||||
pgmname = argv[0];
|
pgmname = argv[0];
|
||||||
while ((ch = getopt(argc, argv, "np1w:r:")) != EOF)
|
while ((ch = getopt(argc, argv, "np1w:r:t:")) != EOF)
|
||||||
switch (ch) {
|
switch (ch) {
|
||||||
case 'n':
|
case 'n':
|
||||||
|
not_trace = 1;
|
||||||
nflag = 1;
|
nflag = 1;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'p':
|
case 'p':
|
||||||
|
not_trace = 1;
|
||||||
pflag = 1;
|
pflag = 1;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case '1':
|
case '1':
|
||||||
ripv2 = 0;
|
ripv2 = 0;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'w':
|
case 'w':
|
||||||
|
not_trace = 1;
|
||||||
wtime = (int)strtoul(optarg, &p, 0);
|
wtime = (int)strtoul(optarg, &p, 0);
|
||||||
if (*p != '\0'
|
if (*p != '\0'
|
||||||
|| wtime <= 0)
|
|| wtime <= 0)
|
||||||
goto usage;
|
goto usage;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'r':
|
case 'r':
|
||||||
|
not_trace = 1;
|
||||||
if (rflag)
|
if (rflag)
|
||||||
goto usage;
|
goto usage;
|
||||||
rflag = getnet(optarg, &rt);
|
rflag = getnet(optarg, &OMSG.rip_nets[0]);
|
||||||
|
if (!rflag) {
|
||||||
|
struct hostent *hp = gethostbyname(optarg);
|
||||||
|
if (hp == 0) {
|
||||||
|
fprintf(stderr, "%s: %s:",
|
||||||
|
pgmname, optarg);
|
||||||
|
herror(0);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
bcopy(hp->h_addr, &OMSG.rip_nets[0].n_dst,
|
||||||
|
sizeof(OMSG.rip_nets[0].n_dst));
|
||||||
|
OMSG.rip_nets[0].n_family = AF_INET;
|
||||||
|
OMSG.rip_nets[0].n_mask = -1;
|
||||||
|
rflag = 1;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case '?':
|
|
||||||
|
case 't':
|
||||||
|
trace = 1;
|
||||||
|
options = optarg;
|
||||||
|
while (*options != '\0') {
|
||||||
|
char *traceopts[] = {
|
||||||
|
# define TRACE_ON 0
|
||||||
|
"on",
|
||||||
|
# define TRACE_MORE 1
|
||||||
|
"more",
|
||||||
|
# define TRACE_OFF 2
|
||||||
|
"off",
|
||||||
|
0
|
||||||
|
};
|
||||||
|
switch (getsubopt(&options,traceopts,&value)) {
|
||||||
|
case TRACE_ON:
|
||||||
|
OMSG.rip_cmd = RIPCMD_TRACEON;
|
||||||
|
if (!value
|
||||||
|
|| strlen(value) > MAXPATHLEN)
|
||||||
|
goto usage;
|
||||||
|
strcpy(OMSG.rip_tracefile, value);
|
||||||
|
omsg_len += (strlen(value)
|
||||||
|
- sizeof(OMSG.ripun));
|
||||||
|
break;
|
||||||
|
case TRACE_MORE:
|
||||||
|
if (value)
|
||||||
|
goto usage;
|
||||||
|
OMSG.rip_cmd = RIPCMD_TRACEON;
|
||||||
|
OMSG.rip_tracefile[0] = '\0';
|
||||||
|
break;
|
||||||
|
case TRACE_OFF:
|
||||||
|
if (value)
|
||||||
|
goto usage;
|
||||||
|
OMSG.rip_cmd = RIPCMD_TRACEOFF;
|
||||||
|
OMSG.rip_tracefile[0] = '\0';
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
goto usage;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
goto usage;
|
goto usage;
|
||||||
}
|
}
|
||||||
argv += optind;
|
argv += optind;
|
||||||
argc -= optind;
|
argc -= optind;
|
||||||
if (argc == 0) {
|
if ((not_trace && trace) || argc == 0) {
|
||||||
usage: printf("usage: query [-np1v] [-w wtime] host1 [host2 ...]\n");
|
usage: fprintf(stderr, "%s: [-np1v] [-r tgt_rt] [-w wtime]"
|
||||||
|
" host1 [host2 ...]\n"
|
||||||
|
"or\t-t {on=filename|more|off} host1 host2 ...\n",
|
||||||
|
pgmname);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!rflag) {
|
|
||||||
rt.n_dst = RIP_DEFAULT;
|
|
||||||
rt.n_family = RIP_AF_UNSPEC;
|
|
||||||
rt.n_metric = htonl(HOPCNT_INFINITY);
|
|
||||||
}
|
|
||||||
|
|
||||||
s = socket(AF_INET, SOCK_DGRAM, 0);
|
s = socket(AF_INET, SOCK_DGRAM, 0);
|
||||||
if (s < 0) {
|
if (s < 0) {
|
||||||
perror("socket");
|
perror("socket");
|
||||||
exit(2);
|
exit(2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 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(s, SOL_SOCKET, SO_RCVBUF,
|
||||||
&bsize, sizeof(bsize)) == 0)
|
&bsize, sizeof(bsize)) == 0)
|
||||||
@ -168,10 +228,89 @@ usage: printf("usage: query [-np1v] [-w wtime] host1 [host2 ...]\n");
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ask the first host */
|
if (trace)
|
||||||
|
trace_loop(argv);
|
||||||
|
else
|
||||||
|
query_loop(argv, argc);
|
||||||
|
/* NOTREACHED */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* tell the target hosts about tracing
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
trace_loop(char *argv[])
|
||||||
|
{
|
||||||
|
struct sockaddr_in myaddr;
|
||||||
|
int res;
|
||||||
|
|
||||||
|
if (geteuid() != 0) {
|
||||||
|
(void)fprintf(stderr, "-t requires UID 0\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ripv2) {
|
||||||
|
OMSG.rip_vers = RIPv2;
|
||||||
|
} else {
|
||||||
|
OMSG.rip_vers = RIPv1;
|
||||||
|
}
|
||||||
|
|
||||||
|
bzero(&myaddr, sizeof(myaddr));
|
||||||
|
myaddr.sin_family = AF_INET;
|
||||||
|
#ifdef _HAVE_SIN_LEN
|
||||||
|
myaddr.sin_len = sizeof(myaddr);
|
||||||
|
#endif
|
||||||
|
myaddr.sin_port = htons(IPPORT_RESERVED-1);
|
||||||
|
while (bind(s, (struct sockaddr *)&myaddr, sizeof(myaddr)) < 0) {
|
||||||
|
if (errno != EADDRINUSE
|
||||||
|
|| myaddr.sin_port == 0) {
|
||||||
|
perror("bind");
|
||||||
|
exit(2);
|
||||||
|
}
|
||||||
|
myaddr.sin_port = htons(ntohs(myaddr.sin_port)-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
res = 1;
|
||||||
|
while (*argv != 0) {
|
||||||
|
if (out(*argv++) <= 0)
|
||||||
|
res = 0;
|
||||||
|
}
|
||||||
|
exit(res);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* query all of the listed hosts
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
query_loop(char *argv[], int argc)
|
||||||
|
{
|
||||||
|
struct seen {
|
||||||
|
struct seen *next;
|
||||||
|
struct in_addr addr;
|
||||||
|
} *seen, *sp;
|
||||||
|
int answered = 0;
|
||||||
|
int cc;
|
||||||
|
fd_set bits;
|
||||||
|
struct timeval now, delay;
|
||||||
|
struct sockaddr_in from;
|
||||||
|
int fromlen;
|
||||||
|
|
||||||
|
|
||||||
|
OMSG.rip_cmd = (pflag) ? RIPCMD_POLL : RIPCMD_REQUEST;
|
||||||
|
if (ripv2) {
|
||||||
|
OMSG.rip_vers = RIPv2;
|
||||||
|
} else {
|
||||||
|
OMSG.rip_vers = RIPv1;
|
||||||
|
OMSG.rip_nets[0].n_mask = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ask the first (valid) host */
|
||||||
seen = 0;
|
seen = 0;
|
||||||
while (0 > query(*argv++, &rt) && *argv != 0)
|
while (0 > out(*argv++)) {
|
||||||
|
if (*argv == 0)
|
||||||
|
exit(-1);
|
||||||
answered++;
|
answered++;
|
||||||
|
}
|
||||||
|
|
||||||
FD_ZERO(&bits);
|
FD_ZERO(&bits);
|
||||||
for (;;) {
|
for (;;) {
|
||||||
@ -181,8 +320,8 @@ usage: printf("usage: query [-np1v] [-w wtime] host1 [host2 ...]\n");
|
|||||||
cc = select(s+1, &bits, 0,0, &delay);
|
cc = select(s+1, &bits, 0,0, &delay);
|
||||||
if (cc > 0) {
|
if (cc > 0) {
|
||||||
fromlen = sizeof(from);
|
fromlen = sizeof(from);
|
||||||
cc = recvfrom(s, msg_buf.packet,
|
cc = recvfrom(s, imsg_buf.packet,
|
||||||
sizeof(msg_buf.packet), 0,
|
sizeof(imsg_buf.packet), 0,
|
||||||
(struct sockaddr *)&from, &fromlen);
|
(struct sockaddr *)&from, &fromlen);
|
||||||
if (cc < 0) {
|
if (cc < 0) {
|
||||||
perror("recvfrom");
|
perror("recvfrom");
|
||||||
@ -220,7 +359,7 @@ usage: printf("usage: query [-np1v] [-w wtime] host1 [host2 ...]\n");
|
|||||||
/* After a pause in responses, probe another host.
|
/* After a pause in responses, probe another host.
|
||||||
* This reduces the intermingling of answers.
|
* This reduces the intermingling of answers.
|
||||||
*/
|
*/
|
||||||
while (*argv != 0 && 0 > query(*argv++, &rt))
|
while (*argv != 0 && 0 > out(*argv++))
|
||||||
answered++;
|
answered++;
|
||||||
|
|
||||||
/* continue until no more packets arrive
|
/* continue until no more packets arrive
|
||||||
@ -235,28 +374,25 @@ usage: printf("usage: query [-np1v] [-w wtime] host1 [host2 ...]\n");
|
|||||||
perror("gettimeofday(now)");
|
perror("gettimeofday(now)");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
if (start.tv_sec + wtime <= now.tv_sec)
|
if (sent.tv_sec + wtime <= now.tv_sec)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* fail if there was no answer */
|
/* fail if there was no answer */
|
||||||
exit (answered >= argc ? 0 : 1);
|
exit (answered >= argc ? 0 : 1);
|
||||||
/* NOTREACHED */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/* sent do one host
|
||||||
* Poll one host.
|
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
query(char *host,
|
out(char *host)
|
||||||
struct netinfo *rt)
|
|
||||||
{
|
{
|
||||||
struct sockaddr_in router;
|
struct sockaddr_in router;
|
||||||
struct hostent *hp;
|
struct hostent *hp;
|
||||||
|
|
||||||
if (gettimeofday(&start, 0) < 0) {
|
if (gettimeofday(&sent, 0) < 0) {
|
||||||
perror("gettimeofday(start)");
|
perror("gettimeofday(sent)");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -265,29 +401,17 @@ query(char *host,
|
|||||||
#ifdef _HAVE_SIN_LEN
|
#ifdef _HAVE_SIN_LEN
|
||||||
router.sin_len = sizeof(router);
|
router.sin_len = sizeof(router);
|
||||||
#endif
|
#endif
|
||||||
router.sin_addr.s_addr = inet_addr(host);
|
if (!inet_aton(host, &router.sin_addr)) {
|
||||||
if (router.sin_addr.s_addr == -1) {
|
|
||||||
hp = gethostbyname(host);
|
hp = gethostbyname(host);
|
||||||
if (hp == 0) {
|
if (hp == 0) {
|
||||||
fprintf(stderr,"%s: %s:", pgmname, host);
|
herror(host);
|
||||||
herror(0);
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
bcopy(hp->h_addr, &router.sin_addr, hp->h_length);
|
bcopy(hp->h_addr, &router.sin_addr, sizeof(router.sin_addr));
|
||||||
}
|
}
|
||||||
|
|
||||||
router.sin_port = htons(RIP_PORT);
|
router.sin_port = htons(RIP_PORT);
|
||||||
|
|
||||||
MSG.rip_cmd = (pflag)? RIPCMD_POLL : RIPCMD_REQUEST;
|
if (sendto(s, &omsg_buf, omsg_len, 0,
|
||||||
MSG.rip_nets[0] = *rt;
|
|
||||||
if (ripv2) {
|
|
||||||
MSG.rip_vers = RIPv2;
|
|
||||||
} else {
|
|
||||||
MSG.rip_vers = RIPv1;
|
|
||||||
MSG.rip_nets[0].n_mask = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sendto(s, msg_buf.packet, sizeof(struct rip), 0,
|
|
||||||
(struct sockaddr *)&router, sizeof(router)) < 0) {
|
(struct sockaddr *)&router, sizeof(router)) < 0) {
|
||||||
perror(host);
|
perror(host);
|
||||||
return -1;
|
return -1;
|
||||||
@ -329,18 +453,18 @@ rip_input(struct sockaddr_in *from,
|
|||||||
inet_ntoa(from->sin_addr));
|
inet_ntoa(from->sin_addr));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (MSG.rip_cmd != RIPCMD_RESPONSE) {
|
if (IMSG.rip_cmd != RIPCMD_RESPONSE) {
|
||||||
printf("\n unexpected response type %d\n", MSG.rip_cmd);
|
printf("\n unexpected response type %d\n", IMSG.rip_cmd);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
printf(" RIPv%d%s %d bytes\n", MSG.rip_vers,
|
printf(" RIPv%d%s %d bytes\n", IMSG.rip_vers,
|
||||||
(MSG.rip_vers != RIPv1 && MSG.rip_vers != RIPv2) ? " ?" : "",
|
(IMSG.rip_vers != RIPv1 && IMSG.rip_vers != RIPv2) ? " ?" : "",
|
||||||
size);
|
size);
|
||||||
if (size > MAXPACKETSIZE) {
|
if (size > MAXPACKETSIZE) {
|
||||||
if (size > sizeof(msg_buf) - sizeof(*n)) {
|
if (size > sizeof(imsg_buf) - sizeof(*n)) {
|
||||||
printf(" at least %d bytes too long\n",
|
printf(" at least %d bytes too long\n",
|
||||||
size-MAXPACKETSIZE);
|
size-MAXPACKETSIZE);
|
||||||
size = sizeof(msg_buf) - sizeof(*n);
|
size = sizeof(imsg_buf) - sizeof(*n);
|
||||||
} else {
|
} else {
|
||||||
printf(" %d bytes too long\n",
|
printf(" %d bytes too long\n",
|
||||||
size-MAXPACKETSIZE);
|
size-MAXPACKETSIZE);
|
||||||
@ -349,7 +473,7 @@ rip_input(struct sockaddr_in *from,
|
|||||||
printf(" response of bad length=%d\n", size);
|
printf(" response of bad length=%d\n", size);
|
||||||
}
|
}
|
||||||
|
|
||||||
n = MSG.rip_nets;
|
n = IMSG.rip_nets;
|
||||||
lim = (struct netinfo *)((char*)n + size) - 1;
|
lim = (struct netinfo *)((char*)n + size) - 1;
|
||||||
for (; n <= lim; n++) {
|
for (; n <= lim; n++) {
|
||||||
name = "";
|
name = "";
|
||||||
@ -361,7 +485,7 @@ rip_input(struct sockaddr_in *from,
|
|||||||
dmask = mask & -mask;
|
dmask = mask & -mask;
|
||||||
if (mask != 0) {
|
if (mask != 0) {
|
||||||
sp = &net_buf[strlen(net_buf)];
|
sp = &net_buf[strlen(net_buf)];
|
||||||
if (MSG.rip_vers == RIPv1) {
|
if (IMSG.rip_vers == RIPv1) {
|
||||||
(void)sprintf(sp," mask=%#x ? ",mask);
|
(void)sprintf(sp," mask=%#x ? ",mask);
|
||||||
mask = 0;
|
mask = 0;
|
||||||
} else if (mask + dmask == 0) {
|
} else if (mask + dmask == 0) {
|
||||||
@ -391,14 +515,16 @@ rip_input(struct sockaddr_in *from,
|
|||||||
* good guess.
|
* good guess.
|
||||||
*/
|
*/
|
||||||
if ((in.s_addr & ~mask) == 0) {
|
if ((in.s_addr & ~mask) == 0) {
|
||||||
np = getnetbyaddr(in.s_addr, AF_INET);
|
np = getnetbyaddr((long)in.s_addr,
|
||||||
|
AF_INET);
|
||||||
if (np != 0)
|
if (np != 0)
|
||||||
name = np->n_name;
|
name = np->n_name;
|
||||||
else if (in.s_addr == 0)
|
else if (in.s_addr == 0)
|
||||||
name = "default";
|
name = "default";
|
||||||
}
|
}
|
||||||
if (name[0] == '\0'
|
if (name[0] == '\0'
|
||||||
&& (in.s_addr & ~mask) != 0) {
|
&& ((in.s_addr & ~mask) != 0
|
||||||
|
|| mask == 0xffffffff)) {
|
||||||
hp = gethostbyaddr((char*)&in,
|
hp = gethostbyaddr((char*)&in,
|
||||||
sizeof(in),
|
sizeof(in),
|
||||||
AF_INET);
|
AF_INET);
|
||||||
@ -425,7 +551,7 @@ rip_input(struct sockaddr_in *from,
|
|||||||
(char)n->n_dst);
|
(char)n->n_dst);
|
||||||
}
|
}
|
||||||
|
|
||||||
(void)printf(" %-18s metric %2d %8s",
|
(void)printf(" %-18s metric %2d %-10s",
|
||||||
net_buf, ntohl(n->n_metric), name);
|
net_buf, ntohl(n->n_metric), name);
|
||||||
|
|
||||||
if (n->n_nhop != 0) {
|
if (n->n_nhop != 0) {
|
||||||
@ -435,13 +561,13 @@ rip_input(struct sockaddr_in *from,
|
|||||||
else
|
else
|
||||||
hp = gethostbyaddr((char*)&in, sizeof(in),
|
hp = gethostbyaddr((char*)&in, sizeof(in),
|
||||||
AF_INET);
|
AF_INET);
|
||||||
(void)printf(" nhop=%-15s%s",
|
(void)printf(" nhop=%-15s%s",
|
||||||
(hp != 0) ? hp->h_name : inet_ntoa(in),
|
(hp != 0) ? hp->h_name : inet_ntoa(in),
|
||||||
(MSG.rip_vers == RIPv1) ? " ?" : "");
|
(IMSG.rip_vers == RIPv1) ? " ?" : "");
|
||||||
}
|
}
|
||||||
if (n->n_tag != 0)
|
if (n->n_tag != 0)
|
||||||
(void)printf(" tag=%#x%s", n->n_tag,
|
(void)printf(" tag=%#x%s", n->n_tag,
|
||||||
(MSG.rip_vers == RIPv1) ? " ?" : "");
|
(IMSG.rip_vers == RIPv1) ? " ?" : "");
|
||||||
putc('\n', stdout);
|
putc('\n', stdout);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -31,11 +31,11 @@
|
|||||||
* SUCH DAMAGE.
|
* SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef lint
|
#if !defined(lint) && !defined(sgi)
|
||||||
static char sccsid[] = "@(#)trace.c 8.1 (Berkeley) 6/5/93";
|
static char sccsid[] = "@(#)trace.c 8.1 (Berkeley) 6/5/93";
|
||||||
#endif /* not lint */
|
#endif /* not lint */
|
||||||
|
|
||||||
#ident "$Revision: 1.1 $"
|
#ident "$Revision: 1.8 $"
|
||||||
|
|
||||||
#define RIPCMDS
|
#define RIPCMDS
|
||||||
#include "defs.h"
|
#include "defs.h"
|
||||||
@ -54,11 +54,13 @@ static char sccsid[] = "@(#)trace.c 8.1 (Berkeley) 6/5/93";
|
|||||||
|
|
||||||
u_int tracelevel, new_tracelevel;
|
u_int tracelevel, new_tracelevel;
|
||||||
FILE *ftrace = stdout; /* output trace file */
|
FILE *ftrace = stdout; /* output trace file */
|
||||||
char *tracelevel_msg = "";
|
static char *tracelevel_pat = "%s\n";
|
||||||
|
|
||||||
char savetracename[MAXPATHLEN+1];
|
char savetracename[MAXPATHLEN+1];
|
||||||
|
|
||||||
|
|
||||||
|
/* convert IP address to a string, but not into a single buffer
|
||||||
|
*/
|
||||||
char *
|
char *
|
||||||
naddr_ntoa(naddr a)
|
naddr_ntoa(naddr a)
|
||||||
{
|
{
|
||||||
@ -110,42 +112,43 @@ lastlog(void)
|
|||||||
|
|
||||||
if (last.tv_sec != now.tv_sec
|
if (last.tv_sec != now.tv_sec
|
||||||
|| last.tv_usec != now.tv_usec) {
|
|| last.tv_usec != now.tv_usec) {
|
||||||
(void)fprintf(ftrace, "--- %s ---\n", ts(now.tv_sec));
|
(void)fprintf(ftrace, "-- %s --\n", ts(now.tv_sec));
|
||||||
last = now;
|
last = now;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
tmsg(char *msg1, char* msg2)
|
tmsg(char *p, ...)
|
||||||
{
|
{
|
||||||
|
va_list args;
|
||||||
|
|
||||||
if (ftrace != 0) {
|
if (ftrace != 0) {
|
||||||
lastlog();
|
lastlog();
|
||||||
(void)fprintf(ftrace, "%s%s\n", msg1,msg2);
|
va_start(args, p);
|
||||||
|
vfprintf(ftrace, p, args);
|
||||||
|
fflush(ftrace);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
trace_close(char *msg1, char *msg2)
|
trace_close(void)
|
||||||
{
|
{
|
||||||
int fd;
|
int fd;
|
||||||
|
|
||||||
|
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
fflush(stderr);
|
fflush(stderr);
|
||||||
|
|
||||||
if (ftrace != 0) {
|
if (ftrace != 0
|
||||||
tmsg(msg1,msg2);
|
&& savetracename[0] != '\0') {
|
||||||
fflush(ftrace);
|
fd = open(_PATH_DEVNULL, O_RDWR);
|
||||||
|
(void)dup2(fd, STDOUT_FILENO);
|
||||||
if (savetracename[0] != '\0') {
|
(void)dup2(fd, STDERR_FILENO);
|
||||||
fd = open(_PATH_DEVNULL, O_RDWR);
|
(void)close(fd);
|
||||||
(void)dup2(fd, STDOUT_FILENO);
|
fclose(ftrace);
|
||||||
(void)dup2(fd, STDERR_FILENO);
|
ftrace = 0;
|
||||||
(void)close(fd);
|
|
||||||
fclose(ftrace);
|
|
||||||
ftrace = 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -162,9 +165,18 @@ trace_flush(void)
|
|||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
trace_off(char *msg1, char *msg2)
|
trace_off(char *p, ...)
|
||||||
{
|
{
|
||||||
trace_close(msg1, msg2);
|
va_list args;
|
||||||
|
|
||||||
|
|
||||||
|
if (ftrace != 0) {
|
||||||
|
lastlog();
|
||||||
|
va_start(args, p);
|
||||||
|
vfprintf(ftrace, p, args);
|
||||||
|
fflush(ftrace);
|
||||||
|
}
|
||||||
|
trace_close();
|
||||||
|
|
||||||
new_tracelevel = tracelevel = 0;
|
new_tracelevel = tracelevel = 0;
|
||||||
}
|
}
|
||||||
@ -178,26 +190,48 @@ trace_on(char *filename,
|
|||||||
FILE *n_ftrace;
|
FILE *n_ftrace;
|
||||||
|
|
||||||
|
|
||||||
if (stat(filename, &stbuf) >= 0 &&
|
/* Given a null filename when tracing is already on, increase the
|
||||||
(stbuf.st_mode & S_IFMT) != S_IFREG) {
|
* debugging level and re-open the file in case it has been unlinked.
|
||||||
msglog("wrong type (%#x) of trace file \"%s\"",
|
*/
|
||||||
stbuf.st_mode, filename);
|
if (filename[0] == '\0') {
|
||||||
return;
|
if (tracelevel != 0) {
|
||||||
}
|
new_tracelevel++;
|
||||||
if (!trusted
|
tracelevel_pat = "trace command: %s\n";
|
||||||
&& strcmp(filename, savetracename)
|
} else if (savetracename[0] == '\0') {
|
||||||
&& strncmp(filename, _PATH_TRACE, sizeof(_PATH_TRACE)-1)) {
|
msglog("missing trace file name");
|
||||||
msglog("wrong directory for trace file %s", filename);
|
return;
|
||||||
return;
|
}
|
||||||
|
filename = savetracename;
|
||||||
|
|
||||||
|
} else if (stat(filename, &stbuf) >= 0) {
|
||||||
|
if (!trusted) {
|
||||||
|
msglog("trace file \"%s\" already exists");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if ((stbuf.st_mode & S_IFMT) != S_IFREG) {
|
||||||
|
msglog("wrong type (%#x) of trace file \"%s\"",
|
||||||
|
stbuf.st_mode, filename);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!trusted
|
||||||
|
&& strcmp(filename, savetracename)
|
||||||
|
&& strncmp(filename, _PATH_TRACE, sizeof(_PATH_TRACE)-1)) {
|
||||||
|
msglog("wrong directory for trace file: \"%s\"",
|
||||||
|
filename);
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
n_ftrace = fopen(filename, "a");
|
n_ftrace = fopen(filename, "a");
|
||||||
if (n_ftrace == 0) {
|
if (n_ftrace == 0) {
|
||||||
msglog("failed to open trace file \"%s\": %s",
|
msglog("failed to open trace file \"%s\" %s",
|
||||||
filename, strerror(errno));
|
filename, strerror(errno));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
trace_close("switch to trace file ", filename);
|
tmsg("switch to trace file %s\n", filename);
|
||||||
|
trace_close();
|
||||||
if (filename != savetracename)
|
if (filename != savetracename)
|
||||||
strncpy(savetracename, filename, sizeof(savetracename)-1);
|
strncpy(savetracename, filename, sizeof(savetracename)-1);
|
||||||
ftrace = n_ftrace;
|
ftrace = n_ftrace;
|
||||||
@ -207,12 +241,9 @@ trace_on(char *filename,
|
|||||||
dup2(fileno(ftrace), STDOUT_FILENO);
|
dup2(fileno(ftrace), STDOUT_FILENO);
|
||||||
dup2(fileno(ftrace), STDERR_FILENO);
|
dup2(fileno(ftrace), STDERR_FILENO);
|
||||||
|
|
||||||
if (new_tracelevel == 0) {
|
if (new_tracelevel == 0)
|
||||||
tracelevel_msg = "trace command: ";
|
|
||||||
new_tracelevel = 1;
|
new_tracelevel = 1;
|
||||||
} else {
|
set_tracelevel();
|
||||||
tmsg("trace command","");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -221,7 +252,7 @@ void
|
|||||||
sigtrace_on(int s)
|
sigtrace_on(int s)
|
||||||
{
|
{
|
||||||
new_tracelevel++;
|
new_tracelevel++;
|
||||||
tracelevel_msg = "SIGUSR1: ";
|
tracelevel_pat = "SIGUSR1: %s\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -230,7 +261,7 @@ void
|
|||||||
sigtrace_off(int s)
|
sigtrace_off(int s)
|
||||||
{
|
{
|
||||||
new_tracelevel--;
|
new_tracelevel--;
|
||||||
tracelevel_msg = "SIGUSR2: ";
|
tracelevel_pat = "SIGUSR2: %s\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -255,14 +286,19 @@ set_tracelevel(void)
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
if (new_tracelevel > MAX_TRACELEVEL)
|
if (new_tracelevel > MAX_TRACELEVEL) {
|
||||||
new_tracelevel = MAX_TRACELEVEL;
|
new_tracelevel = MAX_TRACELEVEL;
|
||||||
|
if (new_tracelevel == tracelevel) {
|
||||||
|
tmsg(tracelevel_pat, on_msgs[tracelevel-1]);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
while (new_tracelevel != tracelevel) {
|
while (new_tracelevel != tracelevel) {
|
||||||
if (new_tracelevel < tracelevel) {
|
if (new_tracelevel < tracelevel) {
|
||||||
if (--tracelevel == 0)
|
if (--tracelevel == 0)
|
||||||
trace_off(tracelevel_msg, off_msgs[0]);
|
trace_off(tracelevel_pat, off_msgs[0]);
|
||||||
else
|
else
|
||||||
tmsg(tracelevel_msg, off_msgs[tracelevel]);
|
tmsg(tracelevel_pat, off_msgs[tracelevel]);
|
||||||
} else {
|
} else {
|
||||||
if (ftrace == 0) {
|
if (ftrace == 0) {
|
||||||
if (savetracename[0] != '\0')
|
if (savetracename[0] != '\0')
|
||||||
@ -270,9 +306,10 @@ set_tracelevel(void)
|
|||||||
else
|
else
|
||||||
ftrace = stdout;
|
ftrace = stdout;
|
||||||
}
|
}
|
||||||
tmsg(tracelevel_msg, on_msgs[tracelevel++]);
|
tmsg(tracelevel_pat, on_msgs[tracelevel++]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
tracelevel_pat = "%s\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -312,106 +349,132 @@ addrname(naddr addr, /* in network byte order */
|
|||||||
*/
|
*/
|
||||||
struct bits {
|
struct bits {
|
||||||
int bits_mask;
|
int bits_mask;
|
||||||
|
int bits_clear;
|
||||||
char *bits_name;
|
char *bits_name;
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct bits if_bits[] = {
|
static struct bits if_bits[] = {
|
||||||
{ IFF_UP, "" },
|
{ IFF_LOOPBACK, 0, "LOOPBACK" },
|
||||||
{ IFF_BROADCAST, "" },
|
{ IFF_POINTOPOINT, 0, "PT-TO-PT" },
|
||||||
{ IFF_LOOPBACK, "LOOPBACK" },
|
{ 0, 0, 0}
|
||||||
{ IFF_POINTOPOINT, "PT-TO-PT" },
|
|
||||||
{ IFF_RUNNING, "" },
|
|
||||||
{ IFF_MULTICAST, "" },
|
|
||||||
{ -1, ""},
|
|
||||||
{ 0 }
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct bits is_bits[] = {
|
static struct bits is_bits[] = {
|
||||||
{ IS_SUBNET, "" },
|
{ IS_SUBNET, 0, "" },
|
||||||
{ IS_REMOTE, "REMOTE" },
|
{ IS_REMOTE, 0, "REMOTE" },
|
||||||
{ IS_PASSIVE, "PASSIVE" },
|
{ IS_PASSIVE, (IS_NO_RDISC
|
||||||
{ IS_EXTERNAL, "EXTERNAL" },
|
| IS_BCAST_RDISC
|
||||||
{ IS_CHECKED, "" },
|
| IS_NO_RIP
|
||||||
{ IS_ALL_HOSTS, "" },
|
| IS_NO_SUPER_AG
|
||||||
{ IS_ALL_ROUTERS, "" },
|
| IS_PM_RDISC
|
||||||
{ IS_RIP_QUERIED, "" },
|
| IS_NO_AG), "PASSIVE" },
|
||||||
{ IS_BROKE, "BROKE" },
|
{ IS_EXTERNAL, 0, "EXTERNAL" },
|
||||||
{ IS_ACTIVE, "ACTIVE" },
|
{ IS_CHECKED, 0, "" },
|
||||||
{ IS_QUIET, "QUIET" },
|
{ IS_ALL_HOSTS, 0, "" },
|
||||||
{ IS_NEED_NET_SUB, "" },
|
{ IS_ALL_ROUTERS, 0, "" },
|
||||||
{ IS_NO_AG, "NO_AG" },
|
{ IS_RIP_QUERIED, 0, "" },
|
||||||
{ IS_NO_SUPER_AG, "NO_SUPER_AG" },
|
{ IS_BROKE, IS_SICK, "BROKEN" },
|
||||||
|
{ IS_SICK, 0, "SICK" },
|
||||||
|
{ IS_ACTIVE, 0, "ACTIVE" },
|
||||||
|
{ IS_NEED_NET_SYN, 0, "" },
|
||||||
|
{ IS_NO_AG, IS_NO_SUPER_AG, "NO_AG" },
|
||||||
|
{ IS_NO_SUPER_AG, 0, "NO_SUPER_AG" },
|
||||||
{ (IS_NO_RIPV1_IN
|
{ (IS_NO_RIPV1_IN
|
||||||
| IS_NO_RIPV2_IN
|
| IS_NO_RIPV2_IN
|
||||||
| IS_NO_RIPV1_OUT
|
| IS_NO_RIPV1_OUT
|
||||||
| IS_NO_RIPV2_OUT), "NO_RIP" },
|
| IS_NO_RIPV2_OUT), 0, "NO_RIP" },
|
||||||
{ IS_NO_RIPV1_IN, "NO_RIPV1_IN" },
|
{ (IS_NO_RIPV1_IN
|
||||||
{ IS_NO_RIPV2_IN, "NO_RIPV2_IN" },
|
| IS_NO_RIPV1_OUT), 0, "RIPV2" },
|
||||||
{ IS_NO_RIPV1_OUT, "NO_RIPV1_OUT" },
|
{ IS_NO_RIPV1_IN, 0, "NO_RIPV1_IN" },
|
||||||
{ IS_NO_RIPV2_OUT, "NO_RIPV2_OUT" },
|
{ IS_NO_RIPV2_IN, 0, "NO_RIPV2_IN" },
|
||||||
|
{ IS_NO_RIPV1_OUT, 0, "NO_RIPV1_OUT" },
|
||||||
|
{ IS_NO_RIPV2_OUT, 0, "NO_RIPV2_OUT" },
|
||||||
{ (IS_NO_ADV_IN
|
{ (IS_NO_ADV_IN
|
||||||
| IS_NO_SOL_OUT
|
| IS_NO_SOL_OUT
|
||||||
| IS_NO_ADV_OUT), "NO_RDISC" },
|
| IS_NO_ADV_OUT), IS_BCAST_RDISC, "NO_RDISC" },
|
||||||
{ IS_NO_SOL_OUT, "NO_SOLICIT" },
|
{ IS_NO_SOL_OUT, 0, "NO_SOLICIT" },
|
||||||
{ IS_SOL_OUT, "SEND_SOLICIT" },
|
{ IS_SOL_OUT, 0, "SEND_SOLICIT" },
|
||||||
{ IS_NO_ADV_OUT, "NO_RDISC_ADV" },
|
{ IS_NO_ADV_OUT, IS_BCAST_RDISC, "NO_RDISC_ADV" },
|
||||||
{ IS_ADV_OUT, "RDISC_ADV" },
|
{ IS_ADV_OUT, 0, "RDISC_ADV" },
|
||||||
{ IS_BCAST_RDISC, "BCAST_RDISC" },
|
{ IS_BCAST_RDISC, 0, "BCAST_RDISC" },
|
||||||
{ 0 }
|
{ IS_PM_RDISC, 0, "PM_RDISC" },
|
||||||
|
{ 0, 0, "%#x"}
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct bits rs_bits[] = {
|
static struct bits rs_bits[] = {
|
||||||
{ RS_IF, "IF" },
|
{ RS_IF, 0, "IF" },
|
||||||
{ RS_NET_SUB, "NET_SUB" },
|
{ RS_NET_INT, RS_NET_SYN, "NET_INT" },
|
||||||
{ RS_NET_HOST, "NET_HOST" },
|
{ RS_NET_SYN, 0, "NET_SYN" },
|
||||||
{ RS_NET_INT, "NET_INT" },
|
{ RS_SUBNET, 0, "" },
|
||||||
{ RS_SUBNET, "" },
|
{ RS_LOCAL, 0, "LOCAL" },
|
||||||
{ RS_LOCAL, "LOCAL" },
|
{ RS_MHOME, 0, "MHOME" },
|
||||||
{ RS_MHOME, "MHOME" },
|
{ RS_STATIC, 0, "STATIC" },
|
||||||
{ RS_GW, "GW" },
|
{ RS_RDISC, 0, "RDISC" },
|
||||||
{ RS_STATIC, "STATIC" },
|
{ 0, 0, "%#x"}
|
||||||
{ RS_RDISC, "RDISC" },
|
|
||||||
{ 0 }
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
trace_bits(struct bits *tbl,
|
trace_bits(struct bits *tbl,
|
||||||
u_int field)
|
u_int field,
|
||||||
|
int force)
|
||||||
{
|
{
|
||||||
int first = 1;
|
|
||||||
int b;
|
int b;
|
||||||
|
char c;
|
||||||
|
|
||||||
|
if (force) {
|
||||||
|
(void)putc('<', ftrace);
|
||||||
|
c = 0;
|
||||||
|
} else {
|
||||||
|
c = '<';
|
||||||
|
}
|
||||||
|
|
||||||
while (field != 0) {
|
while (field != 0
|
||||||
b = tbl->bits_mask;
|
&& (b = tbl->bits_mask) != 0) {
|
||||||
if (b == 0)
|
if ((b & field) == b) {
|
||||||
break;
|
if (tbl->bits_name[0] != '\0') {
|
||||||
if ((b & field) == b
|
if (c)
|
||||||
&& tbl->bits_name[0] != '\0') {
|
(void)putc(c, ftrace);
|
||||||
(void)fprintf(ftrace, first ? "<%s" : "|%s",
|
(void)fprintf(ftrace, "%s", tbl->bits_name);
|
||||||
tbl->bits_name);
|
c = '|';
|
||||||
first = 0;
|
}
|
||||||
|
if (0 == (field &= ~(b | tbl->bits_clear)))
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
field &= ~b;
|
|
||||||
tbl++;
|
tbl++;
|
||||||
}
|
}
|
||||||
if (field != 0) {
|
if (field != 0 && tbl->bits_name != 0) {
|
||||||
(void)fputc(first ? '<' : '|', ftrace);
|
if (c)
|
||||||
(void)fprintf(ftrace, "%#x", field);
|
(void)putc(c, ftrace);
|
||||||
first = 0;
|
(void)fprintf(ftrace, tbl->bits_name, field);
|
||||||
|
c = '|';
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!first)
|
if (c || force)
|
||||||
(void)fputs("> ", ftrace);
|
(void)fputs("> ", ftrace);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static char *
|
||||||
|
trace_pair(naddr dst,
|
||||||
|
naddr mask,
|
||||||
|
char *gate)
|
||||||
|
{
|
||||||
|
static char buf[3*4+3+1+2+3 /* "xxx.xxx.xxx.xxx/xx-->" */
|
||||||
|
+3*4+3+1]; /* "xxx.xxx.xxx.xxx" */
|
||||||
|
int i;
|
||||||
|
|
||||||
|
i = sprintf(buf, "%-16s-->", addrname(dst, mask, 0));
|
||||||
|
(void)sprintf(&buf[i], "%-*s", 15+20-MAX(20,i), gate);
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
trace_if(char *act,
|
trace_if(char *act,
|
||||||
struct interface *ifp)
|
struct interface *ifp)
|
||||||
{
|
{
|
||||||
if (ftrace == 0)
|
if (!TRACEACTIONS || ftrace == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
lastlog();
|
lastlog();
|
||||||
@ -422,8 +485,8 @@ trace_if(char *act,
|
|||||||
? naddr_ntoa(ifp->int_dstaddr)
|
? naddr_ntoa(ifp->int_dstaddr)
|
||||||
: addrname(htonl(ifp->int_net), ifp->int_mask, 0)));
|
: addrname(htonl(ifp->int_net), ifp->int_mask, 0)));
|
||||||
(void)fprintf(ftrace, "metric=%d ", ifp->int_metric);
|
(void)fprintf(ftrace, "metric=%d ", ifp->int_metric);
|
||||||
trace_bits(if_bits, ifp->int_if_flags);
|
trace_bits(if_bits, ifp->int_if_flags, 0);
|
||||||
trace_bits(is_bits, ifp->int_state);
|
trace_bits(is_bits, ifp->int_state, 0);
|
||||||
(void)fputc('\n',ftrace);
|
(void)fputc('\n',ftrace);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -438,7 +501,7 @@ trace_upslot(struct rt_entry *rt,
|
|||||||
u_short tag,
|
u_short tag,
|
||||||
time_t new_time)
|
time_t new_time)
|
||||||
{
|
{
|
||||||
if (ftrace == 0)
|
if (!TRACEACTIONS || ftrace == 0)
|
||||||
return;
|
return;
|
||||||
if (rts->rts_gate == gate
|
if (rts->rts_gate == gate
|
||||||
&& rts->rts_router == router
|
&& rts->rts_router == router
|
||||||
@ -448,11 +511,10 @@ trace_upslot(struct rt_entry *rt,
|
|||||||
|
|
||||||
lastlog();
|
lastlog();
|
||||||
if (rts->rts_gate != RIP_DEFAULT) {
|
if (rts->rts_gate != RIP_DEFAULT) {
|
||||||
(void)fprintf(ftrace, "Chg #%d %-16s--> ",
|
(void)fprintf(ftrace, "Chg #%d %-35s ",
|
||||||
rts - rt->rt_spares,
|
rts - rt->rt_spares,
|
||||||
addrname(rt->rt_dst, rt->rt_mask, 0));
|
trace_pair(rt->rt_dst, rt->rt_mask,
|
||||||
(void)fprintf(ftrace, "%-15s ",
|
naddr_ntoa(rts->rts_gate)));
|
||||||
naddr_ntoa(rts->rts_gate));
|
|
||||||
if (rts->rts_gate != rts->rts_gate)
|
if (rts->rts_gate != rts->rts_gate)
|
||||||
(void)fprintf(ftrace, "router=%s ",
|
(void)fprintf(ftrace, "router=%s ",
|
||||||
naddr_ntoa(rts->rts_gate));
|
naddr_ntoa(rts->rts_gate));
|
||||||
@ -464,9 +526,8 @@ trace_upslot(struct rt_entry *rt,
|
|||||||
rts->rts_ifp->int_name);
|
rts->rts_ifp->int_name);
|
||||||
(void)fprintf(ftrace, "%s\n", ts(rts->rts_time));
|
(void)fprintf(ftrace, "%s\n", ts(rts->rts_time));
|
||||||
|
|
||||||
(void)fprintf(ftrace, " %-16s--> ",
|
(void)fprintf(ftrace, " %19s%-16s ",
|
||||||
addrname(rt->rt_dst, rt->rt_mask, 0));
|
"",
|
||||||
(void)fprintf(ftrace, "%-15s ",
|
|
||||||
gate != rts->rts_gate ? naddr_ntoa(gate) : "");
|
gate != rts->rts_gate ? naddr_ntoa(gate) : "");
|
||||||
if (gate != router)
|
if (gate != router)
|
||||||
(void)fprintf(ftrace,"router=%s ",naddr_ntoa(router));
|
(void)fprintf(ftrace,"router=%s ",naddr_ntoa(router));
|
||||||
@ -480,10 +541,10 @@ trace_upslot(struct rt_entry *rt,
|
|||||||
new_time != rts->rts_time ? ts(new_time) : "");
|
new_time != rts->rts_time ? ts(new_time) : "");
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
(void)fprintf(ftrace, "Add #%d %-16s--> ",
|
(void)fprintf(ftrace, "Add #%d %-35s ",
|
||||||
rts - rt->rt_spares,
|
rts - rt->rt_spares,
|
||||||
addrname(rt->rt_dst, rt->rt_mask, 0));
|
trace_pair(rt->rt_dst, rt->rt_mask,
|
||||||
(void)fprintf(ftrace, "%-15s ", naddr_ntoa(gate));
|
naddr_ntoa(gate)));
|
||||||
if (gate != router)
|
if (gate != router)
|
||||||
(void)fprintf(ftrace, "router=%s ", naddr_ntoa(gate));
|
(void)fprintf(ftrace, "router=%s ", naddr_ntoa(gate));
|
||||||
if (tag != 0)
|
if (tag != 0)
|
||||||
@ -496,8 +557,10 @@ trace_upslot(struct rt_entry *rt,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* display a message if tracing actions
|
||||||
|
*/
|
||||||
void
|
void
|
||||||
trace_msg(char *p, ...)
|
trace_act(char *p, ...)
|
||||||
{
|
{
|
||||||
va_list args;
|
va_list args;
|
||||||
|
|
||||||
@ -510,6 +573,22 @@ trace_msg(char *p, ...)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* display a message if tracing packets
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
trace_pkt(char *p, ...)
|
||||||
|
{
|
||||||
|
va_list args;
|
||||||
|
|
||||||
|
if (!TRACEPACKETS || ftrace == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
lastlog();
|
||||||
|
va_start(args, p);
|
||||||
|
vfprintf(ftrace, p, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
trace_change(struct rt_entry *rt,
|
trace_change(struct rt_entry *rt,
|
||||||
u_int state,
|
u_int state,
|
||||||
@ -532,25 +611,25 @@ trace_change(struct rt_entry *rt,
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
lastlog();
|
lastlog();
|
||||||
(void)fprintf(ftrace, "%s %-16s--> %-15s metric=%-2d ",
|
(void)fprintf(ftrace, "%s %-35s metric=%-2d ",
|
||||||
label,
|
label,
|
||||||
addrname(rt->rt_dst, rt->rt_mask, 0),
|
trace_pair(rt->rt_dst, rt->rt_mask,
|
||||||
naddr_ntoa(rt->rt_gate), rt->rt_metric);
|
naddr_ntoa(rt->rt_gate)),
|
||||||
|
rt->rt_metric);
|
||||||
if (rt->rt_router != rt->rt_gate)
|
if (rt->rt_router != rt->rt_gate)
|
||||||
(void)fprintf(ftrace, "router=%s ",
|
(void)fprintf(ftrace, "router=%s ",
|
||||||
naddr_ntoa(rt->rt_router));
|
naddr_ntoa(rt->rt_router));
|
||||||
if (rt->rt_tag != 0)
|
if (rt->rt_tag != 0)
|
||||||
(void)fprintf(ftrace, "tag=%#x ", rt->rt_tag);
|
(void)fprintf(ftrace, "tag=%#x ", rt->rt_tag);
|
||||||
trace_bits(rs_bits, rt->rt_state);
|
trace_bits(rs_bits, rt->rt_state, rt->rt_state != state);
|
||||||
(void)fprintf(ftrace, "%s ",
|
(void)fprintf(ftrace, "%s ",
|
||||||
rt->rt_ifp == 0 ? "-" : rt->rt_ifp->int_name);
|
rt->rt_ifp == 0 ? "?" : rt->rt_ifp->int_name);
|
||||||
(void)fprintf(ftrace, "%s\n",
|
(void)fprintf(ftrace, "%s\n",
|
||||||
AGE_RT(rt, rt->rt_ifp) ? ts(rt->rt_time) : "");
|
AGE_RT(rt, rt->rt_ifp) ? ts(rt->rt_time) : "");
|
||||||
|
|
||||||
(void)fprintf(ftrace, "%*s %-16s--> %-15s ",
|
(void)fprintf(ftrace, "%*s %19s%-16s ",
|
||||||
strlen(label), "",
|
strlen(label), "", "",
|
||||||
addrname(rt->rt_dst, rt->rt_mask, 0),
|
rt->rt_gate != gate ? naddr_ntoa(gate) : "");
|
||||||
(rt->rt_gate != gate) ? naddr_ntoa(gate) : "");
|
|
||||||
if (rt->rt_metric != metric)
|
if (rt->rt_metric != metric)
|
||||||
(void)fprintf(ftrace, "metric=%-2d ", metric);
|
(void)fprintf(ftrace, "metric=%-2d ", metric);
|
||||||
if (router != gate)
|
if (router != gate)
|
||||||
@ -558,13 +637,10 @@ trace_change(struct rt_entry *rt,
|
|||||||
if (rt->rt_tag != tag)
|
if (rt->rt_tag != tag)
|
||||||
(void)fprintf(ftrace, "tag=%#x ", tag);
|
(void)fprintf(ftrace, "tag=%#x ", tag);
|
||||||
if (rt->rt_state != state)
|
if (rt->rt_state != state)
|
||||||
trace_bits(rs_bits, state);
|
trace_bits(rs_bits, state, 1);
|
||||||
if (rt->rt_ifp != ifp)
|
if (rt->rt_ifp != ifp)
|
||||||
(void)fprintf(ftrace, "%s ",
|
(void)fprintf(ftrace, "%s ",
|
||||||
ifp != 0 ? ifp->int_name : "-");
|
ifp != 0 ? ifp->int_name : "?");
|
||||||
if (rt->rt_hold_down > now.tv_sec)
|
|
||||||
(void)fprintf(ftrace, "hold-down=%d ",
|
|
||||||
rt->rt_hold_down - now.tv_sec);
|
|
||||||
(void)fprintf(ftrace, "%s\n",
|
(void)fprintf(ftrace, "%s\n",
|
||||||
((rt->rt_time == new_time || !AGE_RT(rt, ifp))
|
((rt->rt_time == new_time || !AGE_RT(rt, ifp))
|
||||||
? "" : ts(new_time)));
|
? "" : ts(new_time)));
|
||||||
@ -580,16 +656,17 @@ trace_add_del(char * action, struct rt_entry *rt)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
lastlog();
|
lastlog();
|
||||||
(void)fprintf(ftrace, "%s %-16s--> %-15s metric=%-2d ",
|
(void)fprintf(ftrace, "%s %-35s metric=%-2d ",
|
||||||
action,
|
action,
|
||||||
addrname(rt->rt_dst, rt->rt_mask, 0),
|
trace_pair(rt->rt_dst, rt->rt_mask,
|
||||||
naddr_ntoa(rt->rt_gate), rt->rt_metric);
|
naddr_ntoa(rt->rt_gate)),
|
||||||
|
rt->rt_metric);
|
||||||
if (rt->rt_router != rt->rt_gate)
|
if (rt->rt_router != rt->rt_gate)
|
||||||
(void)fprintf(ftrace, "router=%s ",
|
(void)fprintf(ftrace, "router=%s ",
|
||||||
naddr_ntoa(rt->rt_router));
|
naddr_ntoa(rt->rt_router));
|
||||||
if (rt->rt_tag != 0)
|
if (rt->rt_tag != 0)
|
||||||
(void)fprintf(ftrace, "tag=%#x ", rt->rt_tag);
|
(void)fprintf(ftrace, "tag=%#x ", rt->rt_tag);
|
||||||
trace_bits(rs_bits, state);
|
trace_bits(rs_bits, state, 0);
|
||||||
if (rt->rt_ifp != 0)
|
if (rt->rt_ifp != 0)
|
||||||
(void)fprintf(ftrace, "%s ", rt->rt_ifp->int_name);
|
(void)fprintf(ftrace, "%s ", rt->rt_ifp->int_name);
|
||||||
(void)fprintf(ftrace, "%s\n", ts(rt->rt_time));
|
(void)fprintf(ftrace, "%s\n", ts(rt->rt_time));
|
||||||
@ -607,7 +684,7 @@ trace_rip(char *dir1, char *dir2,
|
|||||||
struct netauth *a;
|
struct netauth *a;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if (ftrace == 0)
|
if (!TRACEPACKETS || ftrace == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
lastlog();
|
lastlog();
|
||||||
|
Loading…
Reference in New Issue
Block a user