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