Merge the 980602 RIPv2/Router Discovery routed. Fixes floods of host routes
generated when one of the interfaces on the network does not support broadcast (e.g. HIPPI or ATM). From Vern Schryver <vjs@rhyolite.com>
This commit is contained in:
parent
c296923d2f
commit
6d8ef4df7c
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: defs.h,v 1.15 1997/09/15 10:38:11 lukem Exp $ */
|
||||
/* $NetBSD: defs.h,v 1.16 1998/06/02 18:02:55 thorpej Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1983, 1988, 1993
|
||||
@ -80,6 +80,7 @@
|
||||
#include <sys/sysctl.h>
|
||||
#include <sys/socket.h>
|
||||
#ifdef sgi
|
||||
#define _USER_ROUTE_TREE
|
||||
#include <net/radix.h>
|
||||
#else
|
||||
#include "radix.h"
|
||||
@ -167,6 +168,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.
|
||||
@ -197,19 +201,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)
|
||||
@ -258,7 +264,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) */
|
||||
@ -294,7 +300,8 @@ struct interface {
|
||||
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;
|
||||
@ -327,23 +334,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 */
|
||||
@ -361,7 +364,7 @@ struct ag_info {
|
||||
u_short ag_tag;
|
||||
u_short ag_state;
|
||||
#define AGS_SUPPRESS 0x001 /* combine with coaser mask */
|
||||
#define AGS_PROMOTE 0x002 /* synthesize combined routes */
|
||||
#define AGS_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)) \
|
||||
@ -376,37 +379,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 internval */
|
||||
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,
|
||||
@ -435,8 +451,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 adverising it */
|
||||
@ -453,7 +469,7 @@ extern struct timeval next_bcast; /* next general broadcast */
|
||||
extern struct timeval age_timer; /* next check of old routes */
|
||||
extern struct timeval no_flash; /* inhibit flash update until then */
|
||||
extern struct timeval rdisc_timer; /* next advert. or solicitation */
|
||||
extern int rdisc_ok; /* using solicited route */
|
||||
extern int rdisc_ok; /* using solicted route */
|
||||
|
||||
extern struct timeval ifinit_timer; /* time to check interfaces */
|
||||
|
||||
@ -531,21 +547,21 @@ extern char *check_parms(struct parm *);
|
||||
extern void get_parms(struct interface *);
|
||||
|
||||
extern void lastlog(void);
|
||||
extern void trace_close(int);
|
||||
extern void set_tracefile(char *, char *, int);
|
||||
extern void tracelevel_msg(char *, int);
|
||||
extern void trace_off(char*, ...);
|
||||
extern void set_tracelevel(void);
|
||||
extern void trace_flush(void);
|
||||
extern void trace_kernel(char *, ...);
|
||||
extern void trace_misc(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_change(struct rt_entry *, u_int, struct rt_spare *,
|
||||
char *);
|
||||
extern void trace_if(char *, struct interface *);
|
||||
extern void trace_upslot(struct rt_entry *, struct rt_spare *,
|
||||
naddr, naddr,
|
||||
struct interface *, int, u_short, time_t);
|
||||
struct rt_spare *);
|
||||
extern void trace_rip(char*, char*, struct sockaddr_in *,
|
||||
struct interface *, struct rip *, int);
|
||||
extern char *addrname(naddr, naddr, int);
|
||||
@ -574,15 +590,13 @@ 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 *);
|
||||
|
166
sbin/routed/if.c
166
sbin/routed/if.c
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: if.c,v 1.13 1997/09/15 11:51:54 lukem Exp $ */
|
||||
/* $NetBSD: if.c,v 1.14 1998/06/02 18:02:55 thorpej Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1983, 1993
|
||||
@ -37,7 +37,7 @@
|
||||
static char sccsid[] = "@(#)if.c 8.1 (Berkeley) 6/5/93";
|
||||
#elif defined(__NetBSD__)
|
||||
#include <sys/cdefs.h>
|
||||
__RCSID("$NetBSD: if.c,v 1.13 1997/09/15 11:51:54 lukem Exp $");
|
||||
__RCSID("$NetBSD: if.c,v 1.14 1998/06/02 18:02:55 thorpej Exp $");
|
||||
#endif
|
||||
|
||||
#include "defs.h"
|
||||
@ -71,9 +71,13 @@ 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;
|
||||
@ -201,8 +205,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();
|
||||
}
|
||||
@ -225,8 +228,7 @@ ifwithindex(u_short index,
|
||||
* new interface. So just once look for new interfaces.
|
||||
*/
|
||||
if (!rescan_ok
|
||||
|| (last_ifinit.tv_sec == now.tv_sec
|
||||
&& last_ifinit.tv_usec == now.tv_usec))
|
||||
|| IF_RESCAN_DELAY())
|
||||
return 0;
|
||||
ifinit();
|
||||
}
|
||||
@ -265,8 +267,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
|
||||
@ -302,12 +303,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.
|
||||
*/
|
||||
@ -323,15 +325,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)
|
||||
r1p->r1net_mask = mask;
|
||||
}
|
||||
|
||||
/* Otherwise, make the classic A/B/C guess.
|
||||
*/
|
||||
if (mask == 0)
|
||||
mask = std_mask(addr);
|
||||
}
|
||||
|
||||
return mask;
|
||||
}
|
||||
@ -386,7 +399,7 @@ 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
|
||||
@ -507,8 +520,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);
|
||||
|
||||
@ -551,7 +564,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);
|
||||
|
||||
@ -704,14 +717,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);
|
||||
@ -761,10 +776,10 @@ ifinit(void)
|
||||
* Do not output RIP or Router-Discovery packets via aliases.
|
||||
*/
|
||||
memmove(&ifs, &ifs0, sizeof(ifs));
|
||||
ifs0.int_state |= (IS_ALIAS | IS_NO_RIP | IS_NO_RDISC);
|
||||
ifs0.int_state |= (IS_ALIAS | IS_NO_RIP_OUT | IS_NO_RDISC);
|
||||
|
||||
if (INFO_IFA(&info) == 0) {
|
||||
if (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);
|
||||
@ -773,7 +788,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);
|
||||
@ -786,7 +801,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);
|
||||
@ -805,12 +820,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",
|
||||
@ -822,7 +839,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",
|
||||
@ -838,7 +855,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);
|
||||
@ -856,7 +873,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"
|
||||
@ -893,7 +910,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);
|
||||
@ -942,19 +959,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"
|
||||
" %d 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, "");
|
||||
}
|
||||
|
||||
@ -1036,7 +1060,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,
|
||||
@ -1085,7 +1109,7 @@ ifinit(void)
|
||||
|
||||
/* It is new and ok. Add it to the list of interfaces
|
||||
*/
|
||||
ifp = (struct interface *)rtmalloc(sizeof(*ifp), "ifinit");
|
||||
ifp = (struct interface *)rtmalloc(sizeof(*ifp), "ifinit ifp");
|
||||
memmove(ifp, &ifs, sizeof(*ifp));
|
||||
get_parms(ifp);
|
||||
if_link(ifp);
|
||||
@ -1156,14 +1180,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) {
|
||||
@ -1208,7 +1236,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);
|
||||
@ -1221,14 +1249,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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1242,10 +1273,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;
|
||||
@ -1256,6 +1289,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
|
||||
@ -1272,10 +1306,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;
|
||||
@ -1298,7 +1336,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
|
||||
@ -1312,11 +1351,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
|
||||
*/
|
||||
@ -1329,7 +1373,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
|
||||
@ -1342,8 +1386,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) {
|
||||
@ -1351,8 +1394,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;
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: input.c,v 1.21 1997/09/15 11:51:56 lukem Exp $ */
|
||||
/* $NetBSD: input.c,v 1.22 1998/06/02 18:02:55 thorpej Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1983, 1988, 1993
|
||||
@ -37,15 +37,14 @@
|
||||
static char sccsid[] = "@(#)input.c 8.1 (Berkeley) 6/5/93";
|
||||
#elif defined(__NetBSD__)
|
||||
#include <sys/cdefs.h>
|
||||
__RCSID("$NetBSD: input.c,v 1.21 1997/09/15 11:51:56 lukem Exp $");
|
||||
__RCSID("$NetBSD: input.c,v 1.22 1998/06/02 18:02:55 thorpej Exp $");
|
||||
#endif
|
||||
|
||||
#include "defs.h"
|
||||
|
||||
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 *);
|
||||
|
||||
@ -142,14 +141,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 = 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
|
||||
*/
|
||||
@ -284,10 +286,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;
|
||||
@ -299,11 +301,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");
|
||||
@ -315,8 +313,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;
|
||||
@ -328,8 +354,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));
|
||||
@ -513,7 +539,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;
|
||||
}
|
||||
@ -523,7 +549,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) {
|
||||
@ -624,6 +650,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.
|
||||
@ -665,13 +705,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;
|
||||
@ -680,10 +719,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);
|
||||
}
|
||||
@ -697,18 +743,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.
|
||||
@ -732,7 +775,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 */
|
||||
@ -744,8 +787,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;
|
||||
}
|
||||
|
||||
@ -770,7 +812,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.
|
||||
@ -780,40 +822,51 @@ 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;
|
||||
}
|
||||
|
||||
/* This is an update for a spare route.
|
||||
* Finished if the route is unchanged.
|
||||
* Forget it if it has gone bad.
|
||||
*/
|
||||
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;
|
||||
} else if (n->n_metric == HOPCNT_INFINITY) {
|
||||
}
|
||||
/* Forget it if it has gone bad.
|
||||
*/
|
||||
if (new->rts_metric == HOPCNT_INFINITY) {
|
||||
rts_delete(rt, rts);
|
||||
return;
|
||||
}
|
||||
@ -828,6 +881,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
|
||||
@ -835,19 +889,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);
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: main.c,v 1.17 1997/09/15 10:38:15 lukem Exp $ */
|
||||
/* $NetBSD: main.c,v 1.18 1998/06/02 18:02:55 thorpej Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1983, 1988, 1993
|
||||
@ -40,7 +40,7 @@ char copyright[] =
|
||||
static char sccsid[] = "@(#)main.c 8.1 (Berkeley) 6/5/93";
|
||||
#elif defined(__NetBSD__)
|
||||
#include <sys/cdefs.h>
|
||||
__RCSID("$NetBSD: main.c,v 1.17 1997/09/15 10:38:15 lukem Exp $");
|
||||
__RCSID("$NetBSD: main.c,v 1.18 1998/06/02 18:02:55 thorpej Exp $");
|
||||
#endif
|
||||
|
||||
#include "defs.h"
|
||||
@ -51,12 +51,20 @@ __RCSID("$NetBSD: main.c,v 1.17 1997/09/15 10:38:15 lukem Exp $");
|
||||
#include <signal.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/file.h>
|
||||
#if defined(sgi) && !defined(PRE_KUDZU)
|
||||
#include <cap_net.h>
|
||||
#else
|
||||
#define cap_socket socket
|
||||
#define cap_bind bind
|
||||
#endif
|
||||
|
||||
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 */
|
||||
@ -78,6 +86,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 */
|
||||
@ -126,7 +136,7 @@ main(int argc,
|
||||
(void)gethostname(myname, sizeof(myname)-1);
|
||||
(void)gethost(myname, &myaddr);
|
||||
|
||||
while ((n = getopt(argc, argv, "sqdghmpAtT:F:P:")) != -1) {
|
||||
while ((n = getopt(argc, argv, "sqdghmpAtvT:F:P:")) != -1) {
|
||||
switch (n) {
|
||||
case 's':
|
||||
supplier = 1;
|
||||
@ -200,16 +210,19 @@ main(int argc,
|
||||
break;
|
||||
|
||||
case 'P':
|
||||
/* handle arbirary, (usually) per-interface
|
||||
* parameters.
|
||||
/* handle arbitrary parameters.
|
||||
*/
|
||||
p = parse_parms(optarg, 0);
|
||||
if (p != 0) {
|
||||
if (strcasecmp(p,optarg))
|
||||
msglog("%s in \"%s\"", p, optarg);
|
||||
else
|
||||
msglog("bad \"-P %s\"", optarg);
|
||||
}
|
||||
q = strdup(optarg);
|
||||
p = parse_parms(q, 0);
|
||||
if (p != 0)
|
||||
msglog("%s in \"-P %s\"", p, optarg);
|
||||
free(q);
|
||||
break;
|
||||
|
||||
case 'v':
|
||||
/* display version */
|
||||
verbose++;
|
||||
msglog("version 2.10");
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -227,11 +240,14 @@ main(int argc,
|
||||
goto usage;
|
||||
if (argc != 0) {
|
||||
usage:
|
||||
logbad(0, "usage: routed [-sqdghmpAt] [-T tracefile]"
|
||||
logbad(0, "usage: routed [-sqdghmpAtv] [-T tracefile]"
|
||||
" [-F net[,metric]] [-P parms]");
|
||||
}
|
||||
if (geteuid() != 0)
|
||||
if (geteuid() != 0) {
|
||||
if (verbose)
|
||||
exit(0);
|
||||
logbad(0, "requires UID 0");
|
||||
}
|
||||
|
||||
mib[0] = CTL_NET;
|
||||
mib[1] = PF_INET;
|
||||
@ -272,12 +288,10 @@ usage:
|
||||
/* get into the background */
|
||||
#ifdef sgi
|
||||
if (0 > _daemonize(background ? 0 : (_DF_NOCHDIR|_DF_NOFORK),
|
||||
new_tracelevel == 0 ? -1 : STDOUT_FILENO,
|
||||
new_tracelevel == 0 ? -1 : STDERR_FILENO,
|
||||
-1))
|
||||
STDIN_FILENO, STDOUT_FILENO, STDERR_FILENO))
|
||||
BADERR(0, "_daemonize()");
|
||||
#else
|
||||
if (background && daemon(0, new_tracelevel) < 0)
|
||||
if (background && daemon(0, 1) < 0)
|
||||
BADERR(0,"daemon()");
|
||||
#endif
|
||||
|
||||
@ -286,7 +300,7 @@ usage:
|
||||
|
||||
/* prepare socket connected to the kernel.
|
||||
*/
|
||||
rt_sock = socket(AF_ROUTE, SOCK_RAW, 0);
|
||||
rt_sock = cap_socket(AF_ROUTE, SOCK_RAW, 0);
|
||||
if (rt_sock < 0)
|
||||
BADERR(1,"rt_sock = socket()");
|
||||
if (fcntl(rt_sock, F_SETFL, O_NONBLOCK) == -1)
|
||||
@ -299,8 +313,6 @@ usage:
|
||||
fix_select();
|
||||
|
||||
|
||||
if (background && new_tracelevel == 0)
|
||||
ftrace = 0;
|
||||
if (tracename != 0) {
|
||||
strncpy(inittracename, tracename, sizeof(inittracename)-1);
|
||||
set_tracefile(inittracename, "%s", -1);
|
||||
@ -331,12 +343,15 @@ usage:
|
||||
*/
|
||||
gwkludge();
|
||||
ifinit();
|
||||
flush_kern();
|
||||
|
||||
/* Ask for routes */
|
||||
rip_query();
|
||||
rdisc_sol();
|
||||
|
||||
/* Now turn off stdio if not tracing */
|
||||
if (new_tracelevel == 0)
|
||||
trace_close(background);
|
||||
|
||||
/* Loop forever, listening and broadcasting.
|
||||
*/
|
||||
for (;;) {
|
||||
@ -378,6 +393,19 @@ usage:
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Check the kernel table occassionally for mysteriously
|
||||
* evaporated routes
|
||||
*/
|
||||
timevalsub(&t2, &flush_kern_timer, &now);
|
||||
if (t2.tv_sec <= 0) {
|
||||
flush_kern();
|
||||
flush_kern_timer.tv_sec = (now.tv_sec
|
||||
+ CHECK_QUIET_INTERVAL);
|
||||
continue;
|
||||
}
|
||||
if (timercmp(&t2, &wtime, <))
|
||||
wtime = t2;
|
||||
|
||||
/* If it is time, then broadcast our routes.
|
||||
*/
|
||||
if (supplier || advertise_mhome) {
|
||||
@ -448,7 +476,7 @@ usage:
|
||||
wtime = t2;
|
||||
|
||||
/* take care of router discovery,
|
||||
* but do it to the millisecond
|
||||
* but do it in the correct the millisecond
|
||||
*/
|
||||
if (!timercmp(&rdisc_timer, &now, >)) {
|
||||
rdisc_age(0);
|
||||
@ -612,7 +640,7 @@ get_rip_sock(naddr addr,
|
||||
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 (cap_bind(s, (struct sockaddr *)&sin, sizeof(sin)) < 0) {
|
||||
if (serious)
|
||||
BADERR(errno != EADDRINUSE, "bind(rip_sock)");
|
||||
return -1;
|
||||
@ -702,8 +730,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
|
||||
@ -753,7 +783,7 @@ rtmalloc(size_t size,
|
||||
{
|
||||
void *p = malloc(size);
|
||||
if (p == 0)
|
||||
logbad(1,"malloc() failed in %s", msg);
|
||||
logbad(1,"malloc(%d) failed in %s", size, msg);
|
||||
return p;
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: output.c,v 1.14 1997/09/15 11:51:57 lukem Exp $ */
|
||||
/* $NetBSD: output.c,v 1.15 1998/06/02 18:02:55 thorpej Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1983, 1988, 1993
|
||||
@ -37,7 +37,7 @@
|
||||
static char sccsid[] = "@(#)output.c 8.1 (Berkeley) 6/5/93";
|
||||
#elif defined(__NetBSD__)
|
||||
#include <sys/cdefs.h>
|
||||
__RCSID("$NetBSD: output.c,v 1.14 1997/09/15 11:51:57 lukem Exp $");
|
||||
__RCSID("$NetBSD: output.c,v 1.15 1998/06/02 18:02:55 thorpej Exp $");
|
||||
#endif
|
||||
|
||||
#include "defs.h"
|
||||
@ -64,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 */
|
||||
@ -357,11 +356,6 @@ supply_out(struct ag_info *ag)
|
||||
&& (ws.state & WS_ST_FLASH))
|
||||
return;
|
||||
|
||||
/* Skip this route if required by split-horizon.
|
||||
*/
|
||||
if (ag->ag_state & AGS_SPLIT_HZ)
|
||||
return;
|
||||
|
||||
dst_h = ag->ag_dst_h;
|
||||
mask = ag->ag_mask;
|
||||
v1_mask = ripv1_mask_host(htonl(dst_h),
|
||||
@ -397,13 +391,14 @@ supply_out(struct ag_info *ag)
|
||||
/* Punt if we would have to generate an
|
||||
* unreasonable number of routes.
|
||||
*/
|
||||
#ifdef DEBUG
|
||||
msglog("sending %s to %s as 1 instead"
|
||||
" of %d routes",
|
||||
addrname(htonl(dst_h),mask,1),
|
||||
naddr_ntoa(ws.to.sin_addr.s_addr),
|
||||
i+1);
|
||||
#endif
|
||||
if (TRACECONTENTS)
|
||||
trace_misc("sending %s-->%s as 1"
|
||||
" instead of %d routes",
|
||||
addrname(htonl(dst_h), mask,
|
||||
1),
|
||||
naddr_ntoa(ws.to.sin_addr
|
||||
.s_addr),
|
||||
i+1);
|
||||
i = 0;
|
||||
|
||||
} else {
|
||||
@ -495,7 +490,7 @@ walk_supply(struct radix_node *rn, struct walkarg *argp)
|
||||
|
||||
} else {
|
||||
/* Do not send automatic synthetic network routes
|
||||
* if they are not needed becaus no RIPv1 listeners
|
||||
* if they are not needed because no RIPv1 listeners
|
||||
* can hear them.
|
||||
*/
|
||||
if (ws.state & WS_ST_RIP2_ALL)
|
||||
@ -514,6 +509,7 @@ walk_supply(struct radix_node *rn, struct walkarg *argp)
|
||||
/* 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
|
||||
@ -531,23 +527,30 @@ walk_supply(struct radix_node *rn, struct walkarg *argp)
|
||||
;
|
||||
|
||||
} 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;
|
||||
|
||||
@ -556,10 +559,10 @@ walk_supply(struct radix_node *rn, struct walkarg *argp)
|
||||
* 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
|
||||
@ -567,11 +570,9 @@ walk_supply(struct radix_node *rn, struct walkarg *argp)
|
||||
*/
|
||||
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
|
||||
@ -580,8 +581,7 @@ walk_supply(struct radix_node *rn, struct walkarg *argp)
|
||||
* 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
|
||||
@ -596,11 +596,10 @@ walk_supply(struct radix_node *rn, struct walkarg *argp)
|
||||
&& (!(RT->rt_state & RS_IF)
|
||||
|| ws.ifp->int_if_flags & IFF_POINTOPOINT)) {
|
||||
for (rts = RT->rt_spares, i = NUM_SPARES; i != 0; i--, rts++) {
|
||||
if (rts->rts_ifp == ws.ifp
|
||||
&& rts->rts_metric <= metric)
|
||||
break;
|
||||
}
|
||||
if (i != 0) {
|
||||
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.
|
||||
@ -619,9 +618,10 @@ walk_supply(struct radix_node *rn, struct walkarg *argp)
|
||||
|| RT->rt_poison_metric >= metric
|
||||
|| RT->rt_spares[1].rts_gate == 0) {
|
||||
ags |= AGS_SPLIT_HZ;
|
||||
ags &= ~(AGS_PROMOTE | AGS_SUPPRESS);
|
||||
ags &= ~AGS_SUPPRESS;
|
||||
}
|
||||
metric = HOPCNT_INFINITY;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -701,8 +701,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;
|
||||
@ -716,44 +714,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;
|
||||
@ -849,7 +845,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;
|
||||
@ -858,11 +854,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;
|
||||
@ -924,7 +917,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;
|
||||
@ -932,14 +925,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;
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: parms.c,v 1.10 1998/03/30 02:15:27 mrg Exp $ */
|
||||
/* $NetBSD: parms.c,v 1.11 1998/06/02 18:02:55 thorpej Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1983, 1993
|
||||
@ -37,7 +37,7 @@
|
||||
static char sccsid[] = "@(#)if.c 8.1 (Berkeley) 6/5/93";
|
||||
#elif defined(__NetBSD__)
|
||||
#include <sys/cdefs.h>
|
||||
__RCSID("$NetBSD: parms.c,v 1.10 1998/03/30 02:15:27 mrg Exp $");
|
||||
__RCSID("$NetBSD: parms.c,v 1.11 1998/06/02 18:02:55 thorpej Exp $");
|
||||
#endif
|
||||
|
||||
#include "defs.h"
|
||||
@ -47,6 +47,7 @@ __RCSID("$NetBSD: parms.c,v 1.10 1998/03/30 02:15:27 mrg Exp $");
|
||||
|
||||
struct parm *parms;
|
||||
struct intnet *intnets;
|
||||
struct r1net *r1nets;
|
||||
struct tgate *tgates;
|
||||
|
||||
|
||||
@ -111,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;
|
||||
}
|
||||
|
||||
@ -165,10 +166,11 @@ gwkludge(void)
|
||||
{
|
||||
FILE *fp;
|
||||
char *p, *lptr;
|
||||
char lbuf[200], net_host[5], dname[64+1+64+1], gname[64+1], qual[9];
|
||||
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;
|
||||
@ -184,18 +186,19 @@ gwkludge(void)
|
||||
return;
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
for (lnum = 1; ; lnum++) {
|
||||
if (0 == fgets(lbuf, sizeof(lbuf)-1, 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
|
||||
*/
|
||||
@ -204,19 +207,15 @@ gwkludge(void)
|
||||
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);
|
||||
}
|
||||
if (p != 0)
|
||||
msglog("%s in line %d of "_PATH_GATEWAYS,
|
||||
p, 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);
|
||||
@ -243,6 +242,12 @@ 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
|
||||
@ -313,14 +318,14 @@ gwkludge(void)
|
||||
continue;
|
||||
}
|
||||
|
||||
ifp = (struct interface *)malloc(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;
|
||||
@ -357,14 +362,14 @@ 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 */
|
||||
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 = '\0';
|
||||
char *pc, *p;
|
||||
@ -411,10 +416,10 @@ exit:
|
||||
if (lim == 0)
|
||||
return -1;
|
||||
|
||||
*buf = '\0';
|
||||
*buf = '\0'; /* terminate copy of token */
|
||||
if (delimp != 0)
|
||||
*delimp = c;
|
||||
*linep = pc-1;
|
||||
*delimp = c; /* return delimiter */
|
||||
*linep = pc-1; /* say where we ended */
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -539,6 +544,16 @@ get_passwd(char *tgt,
|
||||
}
|
||||
|
||||
|
||||
static char *
|
||||
bad_str(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 */
|
||||
@ -551,30 +566,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 = NULL, *tgt, *val, *p;
|
||||
char buf[64];
|
||||
char delim, *val0, *tgt, *val, *p;
|
||||
char buf[BUFSIZ], buf2[BUFSIZ];
|
||||
int i;
|
||||
|
||||
val0 = NULL; /* XXX gcc -Wuninitialized */
|
||||
|
||||
/* "subnet=x.y.z.u/mask,metric" must be alone on the line */
|
||||
/* "subnet=x.y.z.u/mask[,metric]" must be alone on the line */
|
||||
if (!strncasecmp(line, "subnet=", sizeof("subnet=")-1)
|
||||
&& *(val = &line[sizeof("subnet=")]) != '\0') {
|
||||
intnetp = (struct intnet*)malloc(sizeof(*intnetp));
|
||||
&& *(val = &line[sizeof("subnet=")-1]) != '\0') {
|
||||
if (0 > parse_quote(&val, ",", &delim, buf, sizeof(buf)))
|
||||
return bad_str(line);
|
||||
intnetp = (struct intnet*)rtmalloc(sizeof(*intnetp),
|
||||
"parse_parms subnet");
|
||||
intnetp->intnet_metric = 1;
|
||||
if ((p = strrchr(val,','))) {
|
||||
*p++ = '\0';
|
||||
intnetp->intnet_metric = (int)strtol(p,&p,0);
|
||||
if (delim == ',') {
|
||||
intnetp->intnet_metric = (int)strtol(val+1,&p,0);
|
||||
if (*p != '\0'
|
||||
|| intnetp->intnet_metric <= 0
|
||||
|| intnetp->intnet_metric >= HOPCNT_INFINITY)
|
||||
return line;
|
||||
return bad_str(line);
|
||||
}
|
||||
if (!getnet(val, &intnetp->intnet_addr, &intnetp->intnet_mask)
|
||||
if (!getnet(buf, &intnetp->intnet_addr, &intnetp->intnet_mask)
|
||||
|| intnetp->intnet_mask == HOST_MASK
|
||||
|| intnetp->intnet_addr == RIP_DEFAULT) {
|
||||
free(intnetp);
|
||||
return line;
|
||||
return bad_str(line);
|
||||
}
|
||||
HTONL(intnetp->intnet_addr);
|
||||
intnetp->intnet_next = intnets;
|
||||
@ -582,29 +602,60 @@ parse_parms(char *line,
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* "ripv1_mask=x.y.z.u/mask,mask" must be alone on the line */
|
||||
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")) {
|
||||
@ -616,7 +667,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';
|
||||
@ -628,14 +679,14 @@ parse_parms(char *line,
|
||||
tgt = get_passwd(tgt,val0,&parm,RIP_AUTH_PW,1);
|
||||
if (tgt) {
|
||||
*val0 = '\0';
|
||||
return tgt;
|
||||
return bad_str(tgt);
|
||||
}
|
||||
|
||||
} else if (PARSEQ("md5_passwd")) {
|
||||
tgt = get_passwd(tgt,val0,&parm,RIP_AUTH_MD5,safe);
|
||||
if (tgt) {
|
||||
*val0 = '\0';
|
||||
return tgt;
|
||||
return bad_str(tgt);
|
||||
}
|
||||
|
||||
} else if (PARS("no_ag")) {
|
||||
@ -652,50 +703,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")) {
|
||||
@ -704,7 +758,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
|
||||
@ -712,14 +766,35 @@ parse_parms(char *line,
|
||||
|| (parm.parm_d_metric = (int)strtoul(buf,&p,0),
|
||||
*p != '\0')
|
||||
|| parm.parm_d_metric > HOPCNT_INFINITY-1)
|
||||
return tgt;
|
||||
return bad_str(tgt);
|
||||
|
||||
} else if (PARSEQ("trust_gateway")) {
|
||||
if (!gethost(buf,&addr))
|
||||
return tgt;
|
||||
tg = (struct tgate *)malloc(sizeof(*tg));
|
||||
tg->tgate_next = tgates;
|
||||
/* look for trust_gateway=x.y.z|net/mask|...) */
|
||||
p = buf;
|
||||
if (0 > parse_quote(&p, "|", &delim,
|
||||
buf2, sizeof(buf2))
|
||||
|| !gethost(buf2,&addr))
|
||||
return bad_str(tgt);
|
||||
tg = (struct tgate *)rtmalloc(sizeof(*tg),
|
||||
"parse_parms"
|
||||
"trust_gateway");
|
||||
bzero(tg, 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 +802,7 @@ parse_parms(char *line,
|
||||
parm.parm_int_state |= IS_REDIRECT_OK;
|
||||
|
||||
} else {
|
||||
return tgt; /* error */
|
||||
return bad_str(tgt); /* error */
|
||||
}
|
||||
}
|
||||
|
||||
@ -748,6 +823,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 +851,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)
|
||||
@ -804,7 +881,7 @@ check_parms(struct parm *new)
|
||||
/* link new entry on the so that when the entries are scanned,
|
||||
* they affect the result in the order the operator specified.
|
||||
*/
|
||||
parmp = (struct parm*)malloc(sizeof(*parmp));
|
||||
parmp = (struct parm*)rtmalloc(sizeof(*parmp), "check_parms");
|
||||
memmove(parmp, new, sizeof(*parmp));
|
||||
*parmpp = parmp;
|
||||
|
||||
@ -817,7 +894,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;
|
||||
@ -843,6 +920,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")) {
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: rdisc.c,v 1.6 1997/09/15 10:38:19 lukem Exp $ */
|
||||
/* $NetBSD: rdisc.c,v 1.7 1998/06/02 18:02:56 thorpej Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1995
|
||||
@ -37,13 +37,18 @@
|
||||
static char sccsid[] = "@(#)rdisc.c 8.1 (Berkeley) x/y/95";
|
||||
#elif defined(__NetBSD__)
|
||||
#include <sys/cdefs.h>
|
||||
__RCSID("$NetBSD: rdisc.c,v 1.6 1997/09/15 10:38:19 lukem Exp $");
|
||||
__RCSID("$NetBSD: rdisc.c,v 1.7 1998/06/02 18:02:56 thorpej Exp $");
|
||||
#endif
|
||||
|
||||
#include "defs.h"
|
||||
#include <netinet/in_systm.h>
|
||||
#include <netinet/ip.h>
|
||||
#include <netinet/ip_icmp.h>
|
||||
#if defined(sgi) && !defined(PRE_KUDZU)
|
||||
#include <cap_net.h>
|
||||
#else
|
||||
#define cap_socket socket
|
||||
#endif
|
||||
|
||||
/* router advertisement ICMP packet */
|
||||
struct icmp_ad {
|
||||
@ -78,10 +83,10 @@ int rdisc_sock = -1; /* router-discovery raw socket */
|
||||
struct interface *rdisc_sock_mcast; /* current multicast interface */
|
||||
|
||||
struct timeval rdisc_timer;
|
||||
int rdisc_ok; /* using solicited route */
|
||||
int rdisc_ok; /* using solicted 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 */
|
||||
@ -91,7 +96,12 @@ 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 */
|
||||
/* 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) ((p) <= (ifp)->int_metric ? ((p) != 0 ? 1 : 0) \
|
||||
: (p) - ((ifp)->int_metric))
|
||||
|
||||
@ -149,7 +159,7 @@ static void
|
||||
get_rdisc_sock(void)
|
||||
{
|
||||
if (rdisc_sock < 0) {
|
||||
rdisc_sock = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
|
||||
rdisc_sock = cap_socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
|
||||
if (rdisc_sock < 0)
|
||||
BADERR(1,"rdisc_sock = socket()");
|
||||
fix_sock(rdisc_sock,"rdisc_sock");
|
||||
@ -298,7 +308,7 @@ rdisc_age(naddr bad_gate)
|
||||
|
||||
/* If only adverising, 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)
|
||||
@ -338,14 +348,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);
|
||||
}
|
||||
|
||||
|
||||
@ -361,10 +374,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;
|
||||
}
|
||||
|
||||
|
||||
@ -390,10 +405,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;
|
||||
|
||||
@ -412,13 +428,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);
|
||||
}
|
||||
}
|
||||
|
||||
@ -431,6 +455,7 @@ 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;
|
||||
@ -493,23 +518,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 {
|
||||
@ -521,27 +543,28 @@ rdisc_sort(void)
|
||||
new_drp->dr_ifp->int_name);
|
||||
}
|
||||
|
||||
bzero(&new, 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();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -550,7 +573,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)
|
||||
{
|
||||
@ -581,9 +604,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;
|
||||
}
|
||||
@ -782,9 +805,13 @@ send_adv(struct interface *ifp,
|
||||
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;
|
||||
|
||||
@ -1030,6 +1057,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,4 +1,4 @@
|
||||
.\" $NetBSD: routed.8,v 1.19 1998/04/29 09:49:14 fair Exp $
|
||||
.\" $NetBSD: routed.8,v 1.20 1998/06/02 18:02:56 thorpej Exp $
|
||||
.\"
|
||||
.\" Copyright (c) 1983, 1991, 1993
|
||||
.\" The Regents of the University of California. All rights reserved.
|
||||
@ -42,7 +42,7 @@
|
||||
.Nd network RIP and router discovery routing daemon
|
||||
.Sh SYNOPSIS
|
||||
.Nm
|
||||
.Op Fl sqdghmpAt
|
||||
.Op Fl sqdghmpAtv
|
||||
.Op Fl T Ar tracefile
|
||||
.Oo
|
||||
.Fl F
|
||||
@ -120,7 +120,7 @@ Advertised metrics reflect the metric associated with interface
|
||||
so setting the metric on an interface
|
||||
is an effective way to steer traffic.
|
||||
.Pp
|
||||
Responses do not contain routes with a first hop on the requesting
|
||||
Responses do not include routes with a first hop on the requesting
|
||||
network to implement in part
|
||||
.Em split-horizon .
|
||||
Requests from query programs
|
||||
@ -193,25 +193,17 @@ The
|
||||
is handled similarly.
|
||||
When the daemon is supplying RIP routes, it also listens for
|
||||
Router Discovery Solicitations and sends Advertisements.
|
||||
When it is quiet and only listening to other RIP routers, it
|
||||
When it is quiet and listening to other RIP routers, it
|
||||
sends Solicitations and listens for Advertisements.
|
||||
If it receives
|
||||
a good Advertisement, it stops listening for broadcast or multicast
|
||||
RIP responses.
|
||||
a good Advertisement and it is not multi-homed,
|
||||
it stops listening for broadcast or multicast RIP responses.
|
||||
It tracks several advertising routers to speed recovery when the
|
||||
currently chosen router dies.
|
||||
If all discovered routers disappear,
|
||||
the daemon resumes listening to RIP responses.
|
||||
.Pp
|
||||
While using Router Discovery (which happens by default when
|
||||
the system has a single network interface and a Router Discovery Advertisement
|
||||
is received), there is a single default route and a variable number of
|
||||
redirected host routes in the kernel table.
|
||||
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 \f3\-q\f1 might need
|
||||
.Cm no_rdisc
|
||||
described below.
|
||||
It continues listen 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
|
||||
@ -304,12 +296,6 @@ This option is required for conformance with RFC 1723.
|
||||
However, it makes no sense and breaks using RIP as a discovery protocol
|
||||
to ignore all RIPv2 packets that carry authentication when this machine
|
||||
does not care about authentication.
|
||||
.It Fl T Ar tracefile
|
||||
increases the debugging level to at least 1 and
|
||||
causes debugging information to be appended to the trace file.
|
||||
Note that because of security concerns, it is wisest to not run
|
||||
.Nm
|
||||
routinely with tracing directed to a file.
|
||||
.It Fl t
|
||||
increases the debugging level, which causes more information to be logged
|
||||
on the tracefile specified with
|
||||
@ -323,6 +309,14 @@ 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 routed
|
||||
routinely with tracing directed to a file.
|
||||
.It Fl v
|
||||
displays and logs the version of daemon.
|
||||
.It Fl F Ar net[/mask][,metric]
|
||||
minimize routes in transmissions via interfaces with addresses that match
|
||||
.Em net/mask ,
|
||||
@ -402,6 +396,8 @@ One can list all RIP routers reachable on the 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
|
||||
@ -419,7 +415,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
|
||||
@ -489,6 +486,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 psuedo-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:
|
||||
@ -505,14 +511,19 @@ 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/28 instead of 192.0.2.0/24.
|
||||
.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
|
||||
@ -537,7 +548,7 @@ be valid within 24 hours, or that was valid within 24 hours.
|
||||
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 XXX1|KeyID[start|stop]
|
||||
.It Cm md5_passwd Ns \&= Ns Ar XXX|KeyID[start|stop]
|
||||
specifes a RIPv2 MD5 password.
|
||||
Except that a
|
||||
.Cm KeyID
|
||||
@ -563,6 +574,8 @@ 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
|
||||
@ -593,8 +606,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 +629,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
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: rtquery.c,v 1.7 1998/06/02 10:48:49 kleink Exp $ */
|
||||
/* $NetBSD: rtquery.c,v 1.8 1998/06/02 18:02:56 thorpej Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1982, 1986, 1993
|
||||
@ -41,7 +41,7 @@ char copyright[] =
|
||||
static char sccsid[] = "@(#)query.c 8.1 (Berkeley) 6/5/93";
|
||||
#elif defined(__NetBSD__)
|
||||
#include <sys/cdefs.h>
|
||||
__RCSID("$NetBSD: rtquery.c,v 1.7 1998/06/02 10:48:49 kleink Exp $");
|
||||
__RCSID("$NetBSD: rtquery.c,v 1.8 1998/06/02 18:02:56 thorpej Exp $");
|
||||
#endif
|
||||
|
||||
#include <sys/param.h>
|
||||
@ -110,6 +110,8 @@ u_long keyid;
|
||||
|
||||
struct timeval sent; /* when query sent */
|
||||
|
||||
static char *default_argv[2] = {"localhost", 0};
|
||||
|
||||
static void rip_input(struct sockaddr_in*, int);
|
||||
static int out(char *);
|
||||
static void trace_loop(char *argv[]) __attribute((__noreturn__));
|
||||
@ -254,7 +256,7 @@ main(int argc,
|
||||
}
|
||||
argv += optind;
|
||||
argc -= optind;
|
||||
if ((not_trace && trace) || argc == 0) {
|
||||
if (not_trace && trace) {
|
||||
usage: fprintf(stderr, "%s: [-np1] [-r tgt_rt] [-w wtime]"
|
||||
" [-a type=passwd] host1 [host2 ...]\n"
|
||||
"or\t-t {on=filename|more|off|dump}"
|
||||
@ -262,6 +264,10 @@ usage: fprintf(stderr, "%s: [-np1] [-r tgt_rt] [-w wtime]"
|
||||
pgmname);
|
||||
exit(1);
|
||||
}
|
||||
if (argc == 0) {
|
||||
argc = 1;
|
||||
argv = default_argv;
|
||||
}
|
||||
|
||||
s = socket(AF_INET, SOCK_DGRAM, 0);
|
||||
if (s < 0) {
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: table.c,v 1.6 1997/09/16 08:37:15 mrg Exp $ */
|
||||
/* $NetBSD: table.c,v 1.7 1998/06/02 18:02:56 thorpej Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1983, 1988, 1993
|
||||
@ -37,13 +37,13 @@
|
||||
static char sccsid[] = "@(#)tables.c 8.1 (Berkeley) 6/5/93";
|
||||
#elif defined(__NetBSD__)
|
||||
#include <sys/cdefs.h>
|
||||
__RCSID("$NetBSD: table.c,v 1.6 1997/09/16 08:37:15 mrg Exp $");
|
||||
__RCSID("$NetBSD: table.c,v 1.7 1998/06/02 18:02:56 thorpej Exp $");
|
||||
#endif
|
||||
|
||||
#include "defs.h"
|
||||
|
||||
static struct rt_spare *rts_better(struct rt_entry *);
|
||||
static struct rt_spare rts_empty = {0,0,0,HOPCNT_INFINITY,0,0};
|
||||
static struct rt_spare rts_empty = {0,0,0,HOPCNT_INFINITY,0,0,0};
|
||||
|
||||
void set_need_flash(void);
|
||||
#ifdef _HAVE_SIN_LEN
|
||||
@ -126,6 +126,10 @@ ag_out(struct ag_info *ag,
|
||||
naddr bit;
|
||||
|
||||
|
||||
/* Forget it if this route should not be output for split-horizon. */
|
||||
if (ag->ag_state & AGS_SPLIT_HZ)
|
||||
return;
|
||||
|
||||
/* If we output both the even and odd twins, then the immediate parent,
|
||||
* if it is present, is redundant, unless the parent manages to
|
||||
* aggregate into something coarser.
|
||||
@ -151,12 +155,14 @@ ag_out(struct ag_info *ag,
|
||||
*/
|
||||
if (ag->ag_state & AGS_REDUN0) {
|
||||
if (ag->ag_state & AGS_REDUN1)
|
||||
return;
|
||||
return; /* quit if fully redundant */
|
||||
/* make it finer if it is half-redundant */
|
||||
bit = (-ag->ag_mask) >> 1;
|
||||
ag->ag_dst_h |= bit;
|
||||
ag->ag_mask |= bit;
|
||||
|
||||
} else if (ag->ag_state & AGS_REDUN1) {
|
||||
/* make it finer if it is half-redundant */
|
||||
bit = (-ag->ag_mask) >> 1;
|
||||
ag->ag_mask |= bit;
|
||||
}
|
||||
@ -243,6 +249,8 @@ ag_flush(naddr lim_dst_h, /* flush routes to here */
|
||||
|
||||
/* If the coarse route has a good enough
|
||||
* metric, it suppresses the target.
|
||||
* If the suppressed target was redundant,
|
||||
* then mark the suppressor redundant.
|
||||
*/
|
||||
if (ag_cors->ag_pref <= ag->ag_pref) {
|
||||
if (ag_cors->ag_seqno > ag->ag_seqno)
|
||||
@ -340,6 +348,9 @@ ag_check(naddr dst,
|
||||
|| (ag_cors->ag_state & AGS_CORS_GATE))) {
|
||||
if (ag_cors->ag_seqno > ag->ag_seqno)
|
||||
ag_cors->ag_seqno = ag->ag_seqno;
|
||||
/* If the suppressed target was redundant,
|
||||
* then mark the suppressor redundant.
|
||||
*/
|
||||
if (AG_IS_REDUN(ag->ag_state)
|
||||
&& ag_cors->ag_mask==ag->ag_mask<<1) {
|
||||
if (ag_cors->ag_dst_h == dst)
|
||||
@ -382,11 +393,11 @@ ag_check(naddr dst,
|
||||
* Routes are encountered in lexical order, so a
|
||||
* route is never promoted until the parent route is
|
||||
* already present. So we know that the new route is
|
||||
* a promoted pair and the route already in the slot
|
||||
* is the explicit route.
|
||||
* a promoted (or aggregated) pair and the route
|
||||
* already in the slot is the explicit route.
|
||||
*
|
||||
* Prefer the best route if their metrics differ,
|
||||
* or the promoted one if not, following a sort
|
||||
* or the aggregated one if not, following a sort
|
||||
* of longest-match rule.
|
||||
*/
|
||||
if (pref <= ag->ag_pref) {
|
||||
@ -406,9 +417,13 @@ ag_check(naddr dst,
|
||||
if (ag->ag_seqno > seqno)
|
||||
ag->ag_seqno = seqno;
|
||||
|
||||
/* some bits are set if they are set on either route */
|
||||
ag->ag_state |= (state & (AGS_PROMOTE_EITHER
|
||||
| AGS_REDUN0 | AGS_REDUN1));
|
||||
/* Some bits are set if they are set on either route,
|
||||
* except when the route is for an interface.
|
||||
*/
|
||||
if (!(ag->ag_state & AGS_IF))
|
||||
ag->ag_state |= (state & (AGS_AGGREGATE_EITHER
|
||||
| AGS_REDUN0
|
||||
| AGS_REDUN1));
|
||||
return;
|
||||
}
|
||||
|
||||
@ -416,12 +431,12 @@ ag_check(naddr dst,
|
||||
* be suppressed, it may be possible to combine them or
|
||||
* worthwhile to promote one.
|
||||
*
|
||||
* Note that any route that can be promoted is always
|
||||
* Any route that can be promoted is always
|
||||
* marked to be eligible to be suppressed.
|
||||
*/
|
||||
if (!((state & AGS_PROMOTE)
|
||||
if (!((state & AGS_AGGREGATE)
|
||||
&& (ag->ag_state & AGS_SUPPRESS))
|
||||
&& !((ag->ag_state & AGS_PROMOTE)
|
||||
&& !((ag->ag_state & AGS_AGGREGATE)
|
||||
&& (state & AGS_SUPPRESS)))
|
||||
break;
|
||||
|
||||
@ -433,13 +448,13 @@ ag_check(naddr dst,
|
||||
|| AG_IS_REDUN(state)
|
||||
|| (ag->ag_gate == gate
|
||||
&& ag->ag_pref == pref
|
||||
&& (state & ag->ag_state & AGS_PROMOTE) != 0)) {
|
||||
&& (state & ag->ag_state & AGS_AGGREGATE) != 0)) {
|
||||
|
||||
/* We have both the even and odd pairs.
|
||||
* Since the routes are encountered in order,
|
||||
* the route in the slot must be the even twin.
|
||||
*
|
||||
* Combine and promote the pair of routes.
|
||||
* Combine and promote (aggregate) the pair of routes.
|
||||
*/
|
||||
if (seqno > ag->ag_seqno)
|
||||
seqno = ag->ag_seqno;
|
||||
@ -449,7 +464,7 @@ ag_check(naddr dst,
|
||||
state |= AGS_REDUN0;
|
||||
else
|
||||
state &= ~AGS_REDUN0;
|
||||
state |= (ag->ag_state & AGS_PROMOTE_EITHER);
|
||||
state |= (ag->ag_state & AGS_AGGREGATE_EITHER);
|
||||
if (ag->ag_tag != tag)
|
||||
tag = 0;
|
||||
if (ag->ag_nhop != nhop)
|
||||
@ -461,7 +476,7 @@ ag_check(naddr dst,
|
||||
ag_del(ag);
|
||||
|
||||
} else if (ag->ag_pref >= pref
|
||||
&& (ag->ag_state & AGS_PROMOTE)) {
|
||||
&& (ag->ag_state & AGS_AGGREGATE)) {
|
||||
/* If we cannot combine the pair, maybe the route
|
||||
* with the worse metric can be promoted.
|
||||
*
|
||||
@ -482,11 +497,17 @@ ag_check(naddr dst,
|
||||
ag->ag_tag = tag;
|
||||
tag = x;
|
||||
|
||||
/* The promoted route is even-redundant only if the
|
||||
* even twin was fully redundant. It is not
|
||||
* odd-redundant because the odd-twin will still be
|
||||
* in the table.
|
||||
*/
|
||||
x = ag->ag_state;
|
||||
if (!AG_IS_REDUN(x))
|
||||
x &= ~AGS_REDUN0;
|
||||
x &= ~AGS_REDUN1;
|
||||
ag->ag_state = state;
|
||||
state = x;
|
||||
if (!AG_IS_REDUN(state))
|
||||
state &= ~AGS_REDUN0;
|
||||
|
||||
x = ag->ag_metric;
|
||||
ag->ag_metric = metric;
|
||||
@ -496,24 +517,30 @@ ag_check(naddr dst,
|
||||
ag->ag_pref = pref;
|
||||
pref = x;
|
||||
|
||||
/* take the newest sequence number */
|
||||
if (seqno >= ag->ag_seqno)
|
||||
seqno = ag->ag_seqno;
|
||||
else
|
||||
ag->ag_seqno = seqno;
|
||||
|
||||
} else {
|
||||
if (!(state & AGS_PROMOTE))
|
||||
if (!(state & AGS_AGGREGATE))
|
||||
break; /* cannot promote either twin */
|
||||
|
||||
/* promote the new, odd twin by shaving its
|
||||
/* Promote the new, odd twin by shaving its
|
||||
* mask and address.
|
||||
* The promoted route is odd-redundant only if the
|
||||
* odd twin was fully redundant. It is not
|
||||
* even-redundant because the even twin is still in
|
||||
* the table.
|
||||
*/
|
||||
if (!AG_IS_REDUN(state))
|
||||
state &= ~AGS_REDUN1;
|
||||
state &= ~AGS_REDUN0;
|
||||
if (seqno > ag->ag_seqno)
|
||||
seqno = ag->ag_seqno;
|
||||
else
|
||||
ag->ag_seqno = seqno;
|
||||
if (!AG_IS_REDUN(state))
|
||||
state &= ~AGS_REDUN1;
|
||||
}
|
||||
|
||||
mask <<= 1;
|
||||
@ -678,7 +705,7 @@ again:
|
||||
w.w_rtm.rtm_flags = flags;
|
||||
w.w_rtm.rtm_seq = ++rt_sock_seqno;
|
||||
w.w_rtm.rtm_addrs = RTA_DST|RTA_GATEWAY;
|
||||
if (metric != 0) {
|
||||
if (metric != 0 || action == RTM_CHANGE) {
|
||||
w.w_rtm.rtm_rmx.rmx_hopcount = metric;
|
||||
w.w_rtm.rtm_inits |= RTV_HOPCOUNT;
|
||||
}
|
||||
@ -716,7 +743,7 @@ again:
|
||||
}
|
||||
return;
|
||||
}
|
||||
msglog("write(rt_sock)" PAT ": ", ARGS, strerror(errno));
|
||||
msglog("write(rt_sock)" PAT ": %s", ARGS, strerror(errno));
|
||||
return;
|
||||
} else if (cc != w.w_rtm.rtm_msglen) {
|
||||
msglog("write(rt_sock) wrote %d instead of %d for" PAT,
|
||||
@ -725,7 +752,7 @@ again:
|
||||
}
|
||||
#endif
|
||||
if (TRACEKERNEL)
|
||||
trace_kernel("write kernel" PAT, ARGS);
|
||||
trace_misc("write kernel" PAT, ARGS);
|
||||
#undef PAT
|
||||
#undef ARGS
|
||||
}
|
||||
@ -741,14 +768,15 @@ static struct khash {
|
||||
short k_metric;
|
||||
u_short k_state;
|
||||
#define KS_NEW 0x001
|
||||
#define KS_DELETE 0x002
|
||||
#define KS_DELETE 0x002 /* need to delete the route */
|
||||
#define KS_ADD 0x004 /* add to the kernel */
|
||||
#define KS_CHANGE 0x008 /* tell kernel to change the route */
|
||||
#define KS_DEL_ADD 0x010 /* delete & add to change the kernel */
|
||||
#define KS_STATIC 0x020 /* Static flag in kernel */
|
||||
#define KS_GATEWAY 0x040 /* G flag in kernel */
|
||||
#define KS_DYNAMIC 0x080 /* result of redirect */
|
||||
#define KS_DELETED 0x100 /* already deleted */
|
||||
#define KS_DELETED 0x100 /* already deleted from kernel */
|
||||
#define KS_CHECK 0x200
|
||||
time_t k_keep;
|
||||
#define K_KEEP_LIM 30
|
||||
time_t k_redirect_time; /* when redirected route 1st seen */
|
||||
@ -779,7 +807,7 @@ kern_add(naddr dst, naddr mask)
|
||||
if (k != 0)
|
||||
return k;
|
||||
|
||||
k = (struct khash *)malloc(sizeof(*k));
|
||||
k = (struct khash *)rtmalloc(sizeof(*k), "kern_add");
|
||||
|
||||
memset(k, 0, sizeof(*k));
|
||||
k->k_dst = dst;
|
||||
@ -800,22 +828,24 @@ kern_check_static(struct khash *k,
|
||||
struct interface *ifp)
|
||||
{
|
||||
struct rt_entry *rt;
|
||||
naddr int_addr;
|
||||
struct rt_spare new;
|
||||
|
||||
if (k->k_metric == 0)
|
||||
return;
|
||||
|
||||
int_addr = (ifp != 0) ? ifp->int_addr : loopaddr;
|
||||
bzero(&new, sizeof(new));
|
||||
new.rts_ifp = ifp;
|
||||
new.rts_gate = k->k_gate;
|
||||
new.rts_router = (ifp != 0) ? ifp->int_addr : loopaddr;
|
||||
new.rts_metric = k->k_metric;
|
||||
new.rts_time = now.tv_sec;
|
||||
|
||||
rt = rtget(k->k_dst, k->k_mask);
|
||||
if (rt != 0) {
|
||||
if (!(rt->rt_state & RS_STATIC))
|
||||
rtchange(rt, rt->rt_state | RS_STATIC,
|
||||
k->k_gate, int_addr,
|
||||
k->k_metric, 0, ifp, now.tv_sec, 0);
|
||||
rtchange(rt, rt->rt_state | RS_STATIC, &new, 0);
|
||||
} else {
|
||||
rtadd(k->k_dst, k->k_mask, k->k_gate, int_addr,
|
||||
k->k_metric, 0, RS_STATIC, ifp);
|
||||
rtadd(k->k_dst, k->k_mask, RS_STATIC, &new);
|
||||
}
|
||||
}
|
||||
|
||||
@ -871,23 +901,29 @@ rtm_add(struct rt_msghdr *rtm,
|
||||
return;
|
||||
}
|
||||
|
||||
if (INFO_GATE(info) == 0
|
||||
|| INFO_GATE(info)->sa_family != AF_INET) {
|
||||
msglog("ignore %s without gateway",
|
||||
rtm_type_name(rtm->rtm_type));
|
||||
return;
|
||||
}
|
||||
|
||||
k = kern_add(S_ADDR(INFO_DST(info)), mask);
|
||||
if (k->k_state & KS_NEW)
|
||||
k->k_keep = now.tv_sec+keep;
|
||||
k->k_gate = S_ADDR(INFO_GATE(info));
|
||||
k->k_metric = rtm->rtm_rmx.rmx_hopcount;
|
||||
if (k->k_metric < 0)
|
||||
k->k_metric = 0;
|
||||
else if (k->k_metric > HOPCNT_INFINITY)
|
||||
k->k_metric = HOPCNT_INFINITY;
|
||||
k->k_state &= ~(KS_DELETED | KS_GATEWAY | KS_STATIC | KS_NEW);
|
||||
if (INFO_GATE(info) == 0) {
|
||||
trace_act("note %s without gateway",
|
||||
rtm_type_name(rtm->rtm_type));
|
||||
k->k_metric = HOPCNT_INFINITY;
|
||||
} else if (INFO_GATE(info)->sa_family != AF_INET) {
|
||||
trace_act("note %s with gateway AF=%d",
|
||||
rtm_type_name(rtm->rtm_type),
|
||||
INFO_GATE(info)->sa_family);
|
||||
k->k_metric = HOPCNT_INFINITY;
|
||||
} else {
|
||||
k->k_gate = S_ADDR(INFO_GATE(info));
|
||||
k->k_metric = rtm->rtm_rmx.rmx_hopcount;
|
||||
if (k->k_metric < 0)
|
||||
k->k_metric = 0;
|
||||
else if (k->k_metric > HOPCNT_INFINITY-1)
|
||||
k->k_metric = HOPCNT_INFINITY-1;
|
||||
}
|
||||
k->k_state &= ~(KS_DELETE | KS_ADD | KS_CHANGE | KS_DEL_ADD
|
||||
| KS_DELETED | KS_GATEWAY | KS_STATIC
|
||||
| KS_NEW | KS_CHECK);
|
||||
if (rtm->rtm_flags & RTF_GATEWAY)
|
||||
k->k_state |= KS_GATEWAY;
|
||||
if (rtm->rtm_flags & RTF_STATIC)
|
||||
@ -961,44 +997,104 @@ rtm_lose(struct rt_msghdr *rtm,
|
||||
return;
|
||||
}
|
||||
|
||||
if (!supplier)
|
||||
if (rdisc_ok)
|
||||
rdisc_age(S_ADDR(INFO_GATE(info)));
|
||||
|
||||
age(S_ADDR(INFO_GATE(info)));
|
||||
}
|
||||
|
||||
|
||||
/* Make the gateway slot of an info structure point to something
|
||||
* useful. If it is not already useful, but it specifies an interface,
|
||||
* then fill in the sockaddr_in provided and point it there.
|
||||
*/
|
||||
static int
|
||||
get_info_gate(struct sockaddr **sap,
|
||||
struct sockaddr_in *sin)
|
||||
{
|
||||
struct sockaddr_dl *sdl = (struct sockaddr_dl *)*sap;
|
||||
struct interface *ifp;
|
||||
|
||||
if (sdl == 0)
|
||||
return 0;
|
||||
if ((sdl)->sdl_family == AF_INET)
|
||||
return 1;
|
||||
if ((sdl)->sdl_family != AF_LINK)
|
||||
return 0;
|
||||
|
||||
ifp = ifwithindex(sdl->sdl_index, 1);
|
||||
if (ifp == 0)
|
||||
return 0;
|
||||
|
||||
sin->sin_addr.s_addr = ifp->int_addr;
|
||||
#ifdef _HAVE_SA_LEN
|
||||
sin->sin_len = sizeof(*sin);
|
||||
#endif
|
||||
sin->sin_family = AF_INET;
|
||||
*sap = (struct sockaddr*)sin;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/* Clean the kernel table by copying it to the daemon image.
|
||||
* Eventually the daemon will delete any extra routes.
|
||||
*/
|
||||
void
|
||||
flush_kern(void)
|
||||
{
|
||||
static char *sysctl_buf;
|
||||
static size_t sysctl_buf_size = 0;
|
||||
size_t needed;
|
||||
int mib[6];
|
||||
char *buf, *next, *lim;
|
||||
char *next, *lim;
|
||||
struct rt_msghdr *rtm;
|
||||
struct interface *ifp;
|
||||
static struct sockaddr_in gate_sa;
|
||||
struct sockaddr_in gate_sin;
|
||||
struct rt_addrinfo info;
|
||||
int i;
|
||||
struct khash *k;
|
||||
|
||||
|
||||
for (i = 0; i < KHASH_SIZE; i++) {
|
||||
for (k = khash_bins[i]; k != 0; k = k->k_next) {
|
||||
k->k_state |= KS_CHECK;
|
||||
}
|
||||
}
|
||||
|
||||
mib[0] = CTL_NET;
|
||||
mib[1] = PF_ROUTE;
|
||||
mib[2] = 0; /* protocol */
|
||||
mib[3] = 0; /* wildcard address family */
|
||||
mib[4] = NET_RT_DUMP;
|
||||
mib[5] = 0; /* no flags */
|
||||
if (sysctl(mib, 6, 0, &needed, 0, 0) < 0) {
|
||||
DBGERR(1,"RT_DUMP-sysctl-estimate");
|
||||
return;
|
||||
for (;;) {
|
||||
if ((needed = sysctl_buf_size) != 0) {
|
||||
if (sysctl(mib, 6, sysctl_buf,&needed, 0, 0) >= 0)
|
||||
break;
|
||||
if (errno != ENOMEM && errno != EFAULT)
|
||||
BADERR(1,"flush_kern: sysctl(RT_DUMP)");
|
||||
free(sysctl_buf);
|
||||
needed = 0;
|
||||
}
|
||||
if (sysctl(mib, 6, 0, &needed, 0, 0) < 0)
|
||||
BADERR(1,"flush_kern: sysctl(RT_DUMP) estimate");
|
||||
/* Kludge around the habit of some systems, such as
|
||||
* BSD/OS 3.1, to not admit how many routes are in the
|
||||
* kernel, or at least to be quite wrong.
|
||||
*/
|
||||
needed += 50*(sizeof(*rtm)+5*sizeof(struct sockaddr));
|
||||
sysctl_buf = rtmalloc(sysctl_buf_size = needed,
|
||||
"flush_kern sysctl(RT_DUMP)");
|
||||
}
|
||||
buf = malloc(needed);
|
||||
if (sysctl(mib, 6, buf, &needed, 0, 0) < 0)
|
||||
BADERR(1,"RT_DUMP");
|
||||
lim = buf + needed;
|
||||
for (next = buf; next < lim; next += rtm->rtm_msglen) {
|
||||
|
||||
lim = sysctl_buf + needed;
|
||||
for (next = sysctl_buf; next < lim; next += rtm->rtm_msglen) {
|
||||
rtm = (struct rt_msghdr *)next;
|
||||
if (rtm->rtm_msglen == 0) {
|
||||
msglog("zero length kernel route at "
|
||||
" %#x in buffer %#x before %#x",
|
||||
rtm, sysctl_buf, lim);
|
||||
break;
|
||||
}
|
||||
|
||||
rt_xaddrs(&info,
|
||||
(struct sockaddr *)(rtm+1),
|
||||
@ -1015,32 +1111,14 @@ flush_kern(void)
|
||||
if (rtm->rtm_flags & RTF_LLINFO)
|
||||
continue;
|
||||
|
||||
if (INFO_GATE(&info) == 0)
|
||||
continue;
|
||||
if (INFO_GATE(&info)->sa_family != AF_INET) {
|
||||
if (INFO_GATE(&info)->sa_family != AF_LINK)
|
||||
continue;
|
||||
ifp = ifwithindex(((struct sockaddr_dl *)
|
||||
INFO_GATE(&info))->sdl_index, 0);
|
||||
if (ifp == 0)
|
||||
continue;
|
||||
if ((ifp->int_if_flags & IFF_POINTOPOINT)
|
||||
|| S_ADDR(INFO_DST(&info)) == ifp->int_addr)
|
||||
gate_sa.sin_addr.s_addr = ifp->int_addr;
|
||||
else
|
||||
gate_sa.sin_addr.s_addr = htonl(ifp->int_net);
|
||||
#ifdef _HAVE_SA_LEN
|
||||
gate_sa.sin_len = sizeof(gate_sa);
|
||||
#endif
|
||||
gate_sa.sin_family = AF_INET;
|
||||
INFO_GATE(&info) = (struct sockaddr *)&gate_sa;
|
||||
}
|
||||
|
||||
/* ignore multicast addresses
|
||||
*/
|
||||
if (IN_MULTICAST(ntohl(S_ADDR(INFO_DST(&info)))))
|
||||
continue;
|
||||
|
||||
if (!get_info_gate(&INFO_GATE(&info), &gate_sin))
|
||||
continue;
|
||||
|
||||
/* Note static routes and interface routes, and also
|
||||
* preload the image of the kernel table so that
|
||||
* we can later clean it, as well as avoid making
|
||||
@ -1050,7 +1128,17 @@ flush_kern(void)
|
||||
*/
|
||||
rtm_add(rtm,&info,MIN_WAITTIME);
|
||||
}
|
||||
free(buf);
|
||||
|
||||
for (i = 0; i < KHASH_SIZE; i++) {
|
||||
for (k = khash_bins[i]; k != 0; k = k->k_next) {
|
||||
if (k->k_state & KS_CHECK) {
|
||||
msglog("%s --> %s disappeared from kernel",
|
||||
addrname(k->k_dst, k->k_mask, 0),
|
||||
naddr_ntoa(k->k_gate));
|
||||
del_static(k->k_dst, k->k_mask, k->k_gate, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1061,7 +1149,8 @@ read_rt(void)
|
||||
{
|
||||
long cc;
|
||||
struct interface *ifp;
|
||||
naddr mask;
|
||||
struct sockaddr_in gate_sin;
|
||||
naddr mask, gate;
|
||||
union {
|
||||
struct {
|
||||
struct rt_msghdr rtm;
|
||||
@ -1106,7 +1195,7 @@ read_rt(void)
|
||||
m.r.rtm.rtm_type != RTM_DELADDR);
|
||||
if (ifp == 0)
|
||||
trace_act("note %s with flags %#x"
|
||||
" for interface index #%d",
|
||||
" for unknown interface index #%d",
|
||||
rtm_type_name(m.r.rtm.rtm_type),
|
||||
m.ifm.ifm_flags,
|
||||
m.ifm.ifm_index);
|
||||
@ -1125,7 +1214,7 @@ read_rt(void)
|
||||
if (ifinit_timer.tv_sec-now.tv_sec>=CHECK_BAD_INTERVAL
|
||||
|| ifp == 0
|
||||
|| ((ifp->int_if_flags ^ m.ifm.ifm_flags)
|
||||
& IFF_UP_RUNNING) != 0)
|
||||
& IFF_UP) != 0)
|
||||
ifinit_timer.tv_sec = now.tv_sec;
|
||||
continue;
|
||||
}
|
||||
@ -1162,11 +1251,18 @@ read_rt(void)
|
||||
trace_act("ignore multicast %s", str);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (m.r.rtm.rtm_flags & RTF_LLINFO) {
|
||||
trace_act("ignore ARP %s", str);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (INFO_GATE(&info) != 0
|
||||
&& INFO_GATE(&info)->sa_family == AF_INET)
|
||||
strp += sprintf(strp, " --> %s",
|
||||
saddr_ntoa(INFO_GATE(&info)));
|
||||
if (get_info_gate(&INFO_GATE(&info), &gate_sin)) {
|
||||
gate = S_ADDR(INFO_GATE(&info));
|
||||
strp += sprintf(strp, " --> %s", naddr_ntoa(gate));
|
||||
} else {
|
||||
gate = 0;
|
||||
}
|
||||
|
||||
if (INFO_AUTHOR(&info) != 0)
|
||||
strp += sprintf(strp, " by authority of %s",
|
||||
@ -1186,12 +1282,14 @@ read_rt(void)
|
||||
break;
|
||||
|
||||
case RTM_DELETE:
|
||||
if (m.r.rtm.rtm_errno != 0) {
|
||||
if (m.r.rtm.rtm_errno != 0
|
||||
&& m.r.rtm.rtm_errno != ESRCH) {
|
||||
trace_act("ignore %s with \"%s\" error",
|
||||
str, strerror(m.r.rtm.rtm_errno));
|
||||
} else {
|
||||
trace_act("%s", str);
|
||||
del_static(S_ADDR(INFO_DST(&info)), mask, 1);
|
||||
del_static(S_ADDR(INFO_DST(&info)), mask,
|
||||
gate, 1);
|
||||
}
|
||||
break;
|
||||
|
||||
@ -1244,12 +1342,20 @@ kern_out(struct ag_info *ag)
|
||||
/* modify existing kernel entry if necessary */
|
||||
if (k->k_gate != ag->ag_gate
|
||||
|| k->k_metric != ag->ag_metric) {
|
||||
/* Must delete bad interface routes etc. to change them. */
|
||||
if (k->k_metric == HOPCNT_INFINITY)
|
||||
k->k_state |= KS_DEL_ADD;
|
||||
k->k_gate = ag->ag_gate;
|
||||
k->k_metric = ag->ag_metric;
|
||||
k->k_state |= KS_CHANGE;
|
||||
}
|
||||
|
||||
if (k->k_state & KS_DYNAMIC) {
|
||||
/* If the daemon thinks the route should exist, forget
|
||||
* about any redirections.
|
||||
* If the daemon thinks the route should exist, eventually
|
||||
* override manual intervention by the operator.
|
||||
*/
|
||||
if ((k->k_state & (KS_DYNAMIC | KS_DELETED)) != 0) {
|
||||
k->k_state &= ~KS_DYNAMIC;
|
||||
k->k_state |= (KS_ADD | KS_DEL_ADD);
|
||||
}
|
||||
@ -1291,15 +1397,33 @@ walk_kern(struct radix_node *rn, struct walkarg *argp)
|
||||
return 0;
|
||||
|
||||
if (!(RT->rt_state & RS_IF)) {
|
||||
ags |= (AGS_GATEWAY | AGS_SUPPRESS | AGS_PROMOTE);
|
||||
/* This is an ordinary route, not for an interface.
|
||||
*/
|
||||
|
||||
/* aggregate, ordinary good routes without regard to
|
||||
* their metric
|
||||
*/
|
||||
pref = 1;
|
||||
ags |= (AGS_GATEWAY | AGS_SUPPRESS | AGS_AGGREGATE);
|
||||
|
||||
/* Do not install host routes directly to hosts, to avoid
|
||||
* interfering with ARP entries in the kernel table.
|
||||
*/
|
||||
if (RT_ISHOST(RT)
|
||||
&& ntohl(RT->rt_dst) == RT->rt_gate)
|
||||
return 0;
|
||||
|
||||
} else {
|
||||
/* Do not install routes for "external" remote interfaces.
|
||||
/* This is an interface route.
|
||||
* Do not install routes for "external" remote interfaces.
|
||||
*/
|
||||
if (RT->rt_ifp != 0 && (RT->rt_ifp->int_state & IS_EXTERNAL))
|
||||
return 0;
|
||||
|
||||
ags |= AGS_IF;
|
||||
/* Interfaces should override received routes.
|
||||
*/
|
||||
pref = 0;
|
||||
ags |= (AGS_IF | AGS_CORS_GATE);
|
||||
|
||||
/* If it is not an interface, or an alias for an interface,
|
||||
* it must be a "gateway."
|
||||
@ -1309,19 +1433,23 @@ walk_kern(struct radix_node *rn, struct walkarg *argp)
|
||||
*/
|
||||
if (RT->rt_ifp == 0
|
||||
|| (RT->rt_ifp->int_state & IS_REMOTE))
|
||||
ags |= (AGS_GATEWAY | AGS_SUPPRESS | AGS_PROMOTE);
|
||||
ags |= (AGS_GATEWAY | AGS_SUPPRESS | AGS_AGGREGATE);
|
||||
}
|
||||
|
||||
if (RT->rt_state & RS_RDISC)
|
||||
/* If RIP is off and IRDP is on, let the route to the discovered
|
||||
* route suppress any RIP routes. Eventually the RIP routes
|
||||
* will time-out and be deleted. This reaches the steady-state
|
||||
* quicker.
|
||||
*/
|
||||
if ((RT->rt_state & RS_RDISC) && rip_sock < 0)
|
||||
ags |= AGS_CORS_GATE;
|
||||
|
||||
/* aggregate good routes without regard to their metric */
|
||||
pref = 1;
|
||||
metric = RT->rt_metric;
|
||||
if (metric == HOPCNT_INFINITY) {
|
||||
/* if the route is dead, so try hard to aggregate. */
|
||||
pref = HOPCNT_INFINITY;
|
||||
ags |= (AGS_FINE_GATE | AGS_SUPPRESS);
|
||||
ags &= ~(AGS_IF | AGS_CORS_GATE);
|
||||
}
|
||||
|
||||
ag_check(RT->rt_dst, RT->rt_mask, RT->rt_gate, 0,
|
||||
@ -1358,7 +1486,9 @@ fix_kern(void)
|
||||
|
||||
/* check hold on routes deleted by the operator */
|
||||
if (k->k_keep > now.tv_sec) {
|
||||
/* ensure we check when the hold is over */
|
||||
LIM_SEC(need_kern, k->k_keep);
|
||||
/* mark for the next cycle */
|
||||
k->k_state |= KS_DELETE;
|
||||
pk = &k->k_next;
|
||||
continue;
|
||||
@ -1406,6 +1536,7 @@ fix_kern(void)
|
||||
void
|
||||
del_static(naddr dst,
|
||||
naddr mask,
|
||||
naddr gate,
|
||||
int gone)
|
||||
{
|
||||
struct khash *k;
|
||||
@ -1419,8 +1550,8 @@ del_static(naddr dst,
|
||||
* and add a replacement.
|
||||
*/
|
||||
k = kern_find(dst, mask, 0);
|
||||
if (k != 0) {
|
||||
k->k_state &= ~(KS_STATIC | KS_DYNAMIC);
|
||||
if (k != 0 && (gate == 0 || k->k_gate == gate)) {
|
||||
k->k_state &= ~(KS_STATIC | KS_DYNAMIC | KS_CHECK);
|
||||
k->k_state |= KS_DELETE;
|
||||
if (gone) {
|
||||
k->k_state |= KS_DELETED;
|
||||
@ -1547,12 +1678,8 @@ rtfind(naddr dst)
|
||||
void
|
||||
rtadd(naddr dst,
|
||||
naddr mask,
|
||||
naddr gate, /* forward packets here */
|
||||
naddr router, /* on the authority of this router */
|
||||
int metric,
|
||||
u_short tag,
|
||||
u_int state, /* rs_state for the entry */
|
||||
struct interface *ifp)
|
||||
u_int state, /* rt_state for the entry */
|
||||
struct rt_spare *new)
|
||||
{
|
||||
struct rt_entry *rt;
|
||||
naddr smask;
|
||||
@ -1579,13 +1706,9 @@ rtadd(naddr dst,
|
||||
masktrim(&mask_sock);
|
||||
rt->rt_mask = mask;
|
||||
rt->rt_state = state;
|
||||
rt->rt_gate = gate;
|
||||
rt->rt_router = router;
|
||||
rt->rt_spares[0] = *new;
|
||||
rt->rt_time = now.tv_sec;
|
||||
rt->rt_metric = metric;
|
||||
rt->rt_poison_metric = HOPCNT_INFINITY;
|
||||
rt->rt_tag = tag;
|
||||
rt->rt_ifp = ifp;
|
||||
rt->rt_seqno = update_seqno;
|
||||
|
||||
if (++total_routes == MAX_ROUTES)
|
||||
@ -1609,29 +1732,24 @@ rtadd(naddr dst,
|
||||
void
|
||||
rtchange(struct rt_entry *rt,
|
||||
u_int state, /* new state bits */
|
||||
naddr gate, /* now forward packets here */
|
||||
naddr router, /* on the authority of this router */
|
||||
int metric, /* new metric */
|
||||
u_short tag,
|
||||
struct interface *ifp,
|
||||
time_t new_time,
|
||||
struct rt_spare *new,
|
||||
char *label)
|
||||
{
|
||||
if (rt->rt_metric != metric) {
|
||||
if (rt->rt_metric != new->rts_metric) {
|
||||
/* Fix the kernel immediately if it seems the route
|
||||
* has gone bad, since there may be a working route that
|
||||
* aggregates this route.
|
||||
*/
|
||||
if (metric == HOPCNT_INFINITY) {
|
||||
if (new->rts_metric == HOPCNT_INFINITY) {
|
||||
need_kern.tv_sec = now.tv_sec;
|
||||
if (new_time >= now.tv_sec - EXPIRE_TIME)
|
||||
new_time = now.tv_sec - EXPIRE_TIME;
|
||||
if (new->rts_time >= now.tv_sec - EXPIRE_TIME)
|
||||
new->rts_time = now.tv_sec - EXPIRE_TIME;
|
||||
}
|
||||
rt->rt_seqno = update_seqno;
|
||||
set_need_flash();
|
||||
}
|
||||
|
||||
if (rt->rt_gate != gate) {
|
||||
if (rt->rt_gate != new->rts_gate) {
|
||||
need_kern.tv_sec = now.tv_sec;
|
||||
rt->rt_seqno = update_seqno;
|
||||
set_need_flash();
|
||||
@ -1641,21 +1759,15 @@ rtchange(struct rt_entry *rt,
|
||||
|
||||
/* Keep various things from deciding ageless routes are stale.
|
||||
*/
|
||||
if (!AGE_RT(state, ifp))
|
||||
new_time = now.tv_sec;
|
||||
if (!AGE_RT(state, new->rts_ifp))
|
||||
new->rts_time = now.tv_sec;
|
||||
|
||||
if (TRACEACTIONS)
|
||||
trace_change(rt, state, gate, router, metric, tag, ifp,
|
||||
new_time,
|
||||
trace_change(rt, state, new,
|
||||
label ? label : "Chg ");
|
||||
|
||||
rt->rt_state = state;
|
||||
rt->rt_gate = gate;
|
||||
rt->rt_router = router;
|
||||
rt->rt_metric = metric;
|
||||
rt->rt_tag = tag;
|
||||
rt->rt_ifp = ifp;
|
||||
rt->rt_time = new_time;
|
||||
rt->rt_spares[0] = *new;
|
||||
}
|
||||
|
||||
|
||||
@ -1704,9 +1816,7 @@ rtswitch(struct rt_entry *rt,
|
||||
|
||||
swap = rt->rt_spares[0];
|
||||
(void)sprintf(label, "Use #%d", (int)(rts - rt->rt_spares));
|
||||
rtchange(rt, rt->rt_state & ~(RS_NET_SYN | RS_RDISC),
|
||||
rts->rts_gate, rts->rts_router, rts->rts_metric,
|
||||
rts->rts_tag, rts->rts_ifp, rts->rts_time, label);
|
||||
rtchange(rt, rt->rt_state & ~(RS_NET_SYN | RS_RDISC), rts, label);
|
||||
if (swap.rts_metric == HOPCNT_INFINITY) {
|
||||
*rts = rts_empty;
|
||||
} else {
|
||||
@ -1747,7 +1857,7 @@ void
|
||||
rts_delete(struct rt_entry *rt,
|
||||
struct rt_spare *rts)
|
||||
{
|
||||
trace_upslot(rt, rts, 0, 0, 0, HOPCNT_INFINITY, 0, 0);
|
||||
trace_upslot(rt, rts, &rts_empty);
|
||||
*rts = rts_empty;
|
||||
}
|
||||
|
||||
@ -1757,11 +1867,12 @@ rts_delete(struct rt_entry *rt,
|
||||
void
|
||||
rtbad(struct rt_entry *rt)
|
||||
{
|
||||
/* Poison the route */
|
||||
rtchange(rt, rt->rt_state & ~(RS_IF | RS_LOCAL | RS_STATIC),
|
||||
rt->rt_gate, rt->rt_router, HOPCNT_INFINITY, rt->rt_tag,
|
||||
0, rt->rt_time, 0);
|
||||
struct rt_spare new;
|
||||
|
||||
/* Poison the route */
|
||||
new = rt->rt_spares[0];
|
||||
new.rts_metric = HOPCNT_INFINITY;
|
||||
rtchange(rt, rt->rt_state & ~(RS_IF | RS_LOCAL | RS_STATIC), &new, 0);
|
||||
rtswitch(rt, 0);
|
||||
}
|
||||
|
||||
@ -1826,10 +1937,10 @@ rtbad_sub(struct rt_entry *rt)
|
||||
}
|
||||
|
||||
if (ifp1 != 0 || (state & RS_NET_SYN)) {
|
||||
rtchange(rt, ((rt->rt_state & ~(RS_NET_SYN | RS_LOCAL))
|
||||
| state),
|
||||
rt->rt_gate, rt->rt_router, rt->rt_metric,
|
||||
rt->rt_tag, ifp1, rt->rt_time, 0);
|
||||
struct rt_spare new = rt->rt_spares[0];
|
||||
new.rts_ifp = ifp1;
|
||||
rtchange(rt, ((rt->rt_state & ~(RS_NET_SYN|RS_LOCAL)) | state),
|
||||
&new, 0);
|
||||
} else {
|
||||
rtbad(rt);
|
||||
}
|
||||
@ -1924,7 +2035,8 @@ walk_age(struct radix_node *rn, struct walkarg *argp)
|
||||
|
||||
/* trash the spare routes when they go bad */
|
||||
if (rts->rts_metric < HOPCNT_INFINITY
|
||||
&& now_garbage > rts->rts_time)
|
||||
&& now_garbage > rts->rts_time
|
||||
&& i != NUM_SPARES)
|
||||
rts_delete(RT, rts);
|
||||
}
|
||||
|
||||
@ -1943,10 +2055,11 @@ walk_age(struct radix_node *rn, struct walkarg *argp)
|
||||
}
|
||||
|
||||
/* Start poisoning a bad route before deleting it. */
|
||||
if (now.tv_sec - RT->rt_time > EXPIRE_TIME)
|
||||
rtchange(RT, RT->rt_state, RT->rt_gate, RT->rt_router,
|
||||
HOPCNT_INFINITY, RT->rt_tag, RT->rt_ifp,
|
||||
RT->rt_time, 0);
|
||||
if (now.tv_sec - RT->rt_time > EXPIRE_TIME) {
|
||||
struct rt_spare new = RT->rt_spares[0];
|
||||
new.rts_metric = HOPCNT_INFINITY;
|
||||
rtchange(RT, RT->rt_state, &new, 0);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1975,6 +2088,7 @@ age(naddr bad_gate)
|
||||
/* ignore unreachable remote interfaces */
|
||||
if (!check_remote(ifp))
|
||||
continue;
|
||||
|
||||
/* Restore remote interface that has become reachable
|
||||
*/
|
||||
if (ifp->int_state & IS_BROKE)
|
||||
@ -2004,6 +2118,11 @@ age(naddr bad_gate)
|
||||
age_bad_gate = bad_gate;
|
||||
(void)rn_walktree(rhead, walk_age, 0);
|
||||
|
||||
/* delete old redirected routes to keep the kernel table small
|
||||
* and prevent blackholes
|
||||
*/
|
||||
del_redirects(bad_gate, now.tv_sec-STALE_TIME);
|
||||
|
||||
/* Update the kernel routing table. */
|
||||
fix_kern();
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: trace.c,v 1.20 1997/10/19 18:23:55 mycroft Exp $ */
|
||||
/* $NetBSD: trace.c,v 1.21 1998/06/02 18:02:56 thorpej Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1983, 1988, 1993
|
||||
@ -37,7 +37,7 @@
|
||||
static char sccsid[] = "@(#)trace.c 8.1 (Berkeley) 6/5/93";
|
||||
#elif defined(__NetBSD__)
|
||||
#include <sys/cdefs.h>
|
||||
__RCSID("$NetBSD: trace.c,v 1.20 1997/10/19 18:23:55 mycroft Exp $");
|
||||
__RCSID("$NetBSD: trace.c,v 1.21 1998/06/02 18:02:56 thorpej Exp $");
|
||||
#endif
|
||||
|
||||
#define RIPCMDS
|
||||
@ -193,8 +193,8 @@ tmsg(char *p, ...)
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
trace_close(void)
|
||||
void
|
||||
trace_close(int zap_stdio)
|
||||
{
|
||||
int fd;
|
||||
|
||||
@ -202,14 +202,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;
|
||||
@ -239,7 +242,7 @@ trace_off(char *p, ...)
|
||||
vfprintf(ftrace, p, args);
|
||||
(void)fputc('\n',ftrace);
|
||||
}
|
||||
trace_close();
|
||||
trace_close(file_trace);
|
||||
|
||||
new_tracelevel = tracelevel = 0;
|
||||
}
|
||||
@ -361,8 +364,7 @@ set_tracefile(char *filename,
|
||||
|
||||
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);
|
||||
@ -597,6 +599,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)
|
||||
@ -610,8 +615,13 @@ 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; (1 << i) <= rts->rts_de_ag; i++)
|
||||
continue;
|
||||
(void)fprintf(ftrace, "de_ag=%d ", i);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@ -644,78 +654,69 @@ 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 (gate == 0) {
|
||||
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(&new, 0,0,0,0,
|
||||
rts != rt->rt_spares || AGE_RT(rt->rt_state,ifp));
|
||||
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 ",
|
||||
(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 ",
|
||||
(int)(rts - rt->rt_spares),
|
||||
rtname(rt->rt_dst, rt->rt_mask, gate));
|
||||
print_rts(&new, 0,0,0,0,
|
||||
rts != rt->rt_spares || AGE_RT(rt->rt_state,ifp));
|
||||
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(char *p, ...)
|
||||
{
|
||||
va_list args;
|
||||
|
||||
if (!TRACEKERNEL || ftrace == 0)
|
||||
if (ftrace == 0)
|
||||
return;
|
||||
|
||||
lastlog();
|
||||
@ -762,31 +763,19 @@ 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,
|
||||
struct rt_spare *new,
|
||||
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 ",
|
||||
@ -798,13 +787,15 @@ trace_change(struct rt_entry *rt,
|
||||
|
||||
(void)fprintf(ftrace, "\n%*s %19s%-16s ",
|
||||
(int)strlen(label), "", "",
|
||||
rt->rt_gate != gate ? naddr_ntoa(gate) : "");
|
||||
print_rts(&new,
|
||||
-(metric == rt->rt_metric),
|
||||
-(ifp == rt->rt_ifp),
|
||||
(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);
|
||||
|
Loading…
Reference in New Issue
Block a user