From 83f39a352fd47b026ef54bebe526949cf5b76367 Mon Sep 17 00:00:00 2001 From: wollman Date: Wed, 11 Dec 1996 20:59:33 +0000 Subject: New version of Vern's routed. This includes more byte-order fixes, some MD5 fixes, better tracing, configurable redirect processing, and a fix to split-horizon/poisoned-reverse treatment. Submitted by: Vernon J. Schryver --- sbin/routed/defs.h | 47 +++-- sbin/routed/if.c | 81 +++++--- sbin/routed/input.c | 102 +++++----- sbin/routed/main.c | 89 ++++++--- sbin/routed/md5.c | 2 +- sbin/routed/output.c | 88 ++++++--- sbin/routed/parms.c | 233 +++++++++++++--------- sbin/routed/rdisc.c | 5 +- sbin/routed/routed.8 | 26 ++- sbin/routed/routed.h | 2 +- sbin/routed/rtquery/md5.c | 2 +- sbin/routed/rtquery/rtquery.c | 2 +- sbin/routed/table.c | 48 ++--- sbin/routed/trace.c | 438 ++++++++++++++++++++++-------------------- 14 files changed, 668 insertions(+), 497 deletions(-) (limited to 'sbin') diff --git a/sbin/routed/defs.h b/sbin/routed/defs.h index 8057a90..3e52ab7 100644 --- a/sbin/routed/defs.h +++ b/sbin/routed/defs.h @@ -36,7 +36,7 @@ */ #ifndef __NetBSD__ -#ident "$Revision: 1.17 $" +#ident "$Revision: 1.19 $" #endif /* Definitions for RIPv2 routing process. @@ -123,7 +123,8 @@ */ /* #define MCAST_PPP_BUG */ -#define NEVER (24*60*60) /* a long time */ +#define DAY (24*60*60) +#define NEVER DAY /* a long time */ #define EPOCH NEVER /* bias time by this to avoid <0 */ /* Scan the kernel regularly to see if any interfaces have appeared or been @@ -292,15 +293,13 @@ struct interface { #endif time_t ts; /* timestamp on network stats */ } int_data; +# define MAX_AUTH_KEYS 5 struct auth { /* authentication info */ u_char type; -# define MAX_AUTH_KEYS 3 - struct auth_key { - u_char key[RIP_AUTH_PW_LEN]; - u_char keyid; - time_t start, end; - } keys[MAX_AUTH_KEYS]; - } int_auth; + u_char key[RIP_AUTH_PW_LEN]; + u_char keyid; + time_t start, end; + } int_auth[MAX_AUTH_KEYS]; int int_rdisc_pref; /* advertised rdisc preference */ int int_rdisc_int; /* MaxAdvertiseInterval */ int int_rdisc_cnt; @@ -317,10 +316,10 @@ struct interface { #define IS_ALL_HOSTS 0x0000040 /* in INADDR_ALLHOSTS_GROUP */ #define IS_ALL_ROUTERS 0x0000080 /* in INADDR_ALLROUTERS_GROUP */ #define IS_DISTRUST 0x0000100 /* ignore untrusted routers */ -#define IS_BROKE 0x0000200 /* seems to be broken */ -#define IS_SICK 0x0000400 /* seems to be broken */ -#define IS_DUP 0x0000800 /* has a duplicate address */ -/* 0x0001000 spare */ +#define IS_REDIRECT_OK 0x0000200 /* accept ICMP redirects */ +#define IS_BROKE 0x0000400 /* seems to be broken */ +#define IS_SICK 0x0000800 /* seems to be broken */ +#define IS_DUP 0x0001000 /* has a duplicate address */ #define IS_NEED_NET_SYN 0x0002000 /* need RS_NET_SYN route */ #define IS_NO_AG 0x0004000 /* do not aggregate subnets */ #define IS_NO_SUPER_AG 0x0008000 /* do not aggregate networks */ @@ -399,7 +398,7 @@ extern struct parm { u_int parm_int_state; int parm_rdisc_pref; int parm_rdisc_int; - struct auth parm_auth; + struct auth parm_auth[MAX_AUTH_KEYS]; } *parms; /* authority for internal networks */ @@ -475,13 +474,14 @@ extern int need_flash; /* flash update needed */ extern struct timeval need_kern; /* need to update kernel table */ extern int update_seqno; /* a route has changed */ -extern u_int tracelevel, new_tracelevel; +extern int tracelevel, new_tracelevel; #define MAX_TRACELEVEL 4 #define TRACEKERNEL (tracelevel >= 4) /* log kernel changes */ #define TRACECONTENTS (tracelevel >= 3) /* display packet contents */ #define TRACEPACKETS (tracelevel >= 2) /* note packets */ #define TRACEACTIONS (tracelevel != 0) extern FILE *ftrace; /* output trace file */ +extern char inittracename[MAXPATHLEN+1]; extern struct radix_node_head *rhead; @@ -499,7 +499,7 @@ extern void rip_on(struct interface *); extern void bufinit(void); extern int output(enum output_type, struct sockaddr_in *, struct interface *, struct rip *, int); -extern void clr_ws_buf(struct ws_buf *, struct auth_key *, struct interface *); +extern void clr_ws_buf(struct ws_buf *, struct auth *); extern void rip_query(void); extern void rip_bcast(int); extern void supply(struct sockaddr_in *, struct interface *, @@ -507,8 +507,12 @@ extern void supply(struct sockaddr_in *, struct interface *, extern void msglog(char *, ...); struct msg_limit { + time_t reuse; + struct msg_sub { naddr addr; time_t until; +# define MSG_SUBJECT_N 8 + } subs[MSG_SUBJECT_N]; }; extern void msglim(struct msg_limit *, naddr, char *, ...); #define LOGERR(msg) msglog(msg ": %s", strerror(errno)) @@ -528,15 +532,16 @@ extern void intvl_random(struct timeval *, u_long, u_long); extern int getnet(char *, naddr *, naddr *); extern int gethost(char *, naddr *); extern void gwkludge(void); -extern char *parse_parms(char *); +extern char *parse_parms(char *, int); extern char *check_parms(struct parm *); extern void get_parms(struct interface *); extern void lastlog(void); -extern void trace_on(char *, 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 set_tracelevel(int); extern void trace_kernel(char *, ...); extern void trace_act(char *, ...); extern void trace_pkt(char *, ...); @@ -619,8 +624,8 @@ extern struct interface *ifwithname(char *, naddr); extern struct interface *ifwithindex(u_short); extern struct interface *iflookup(naddr); -extern struct auth_key *find_auth(struct interface *); -extern void end_md5_auth(struct ws_buf *, struct auth_key *); +extern struct auth *find_auth(struct interface *); +extern void end_md5_auth(struct ws_buf *, struct auth *); #define MD5_DIGEST_LEN 16 typedef struct { diff --git a/sbin/routed/if.c b/sbin/routed/if.c index 3eea2df..8a42344 100644 --- a/sbin/routed/if.c +++ b/sbin/routed/if.c @@ -36,7 +36,7 @@ static char sccsid[] = "@(#)if.c 8.1 (Berkeley) 6/5/93"; #elif defined(__NetBSD__) static char rcsid[] = "$NetBSD$"; #endif -#ident "$Revision: 1.18 $" +#ident "$Revision: 1.21 $" #include "defs.h" #include "pathnames.h" @@ -208,42 +208,54 @@ ifwithindex(u_short index) /* Find an interface from which the specified address * should have come from. Used for figuring out which - * interface a packet came in on -- for tracing. + * interface a packet came in on. */ struct interface * iflookup(naddr addr) { struct interface *ifp, *maybe; + static struct timeval retried; maybe = 0; - for (ifp = ifnet; ifp; ifp = ifp->int_next) { - if (ifp->int_if_flags & IFF_POINTOPOINT) { - /* finished with a match */ - if (ifp->int_dstaddr == addr) - return ifp; + for (;;) { + for (ifp = ifnet; ifp; ifp = ifp->int_next) { + if (ifp->int_if_flags & IFF_POINTOPOINT) { + /* finished with a match */ + if (ifp->int_dstaddr == addr) + return ifp; - } else { - /* finished with an exact match */ - if (ifp->int_addr == addr) - return ifp; + } else { + /* finished with an exact match */ + if (ifp->int_addr == addr) + return ifp; - /* Look for the longest approximate match. - */ - if (on_net(addr, ifp->int_net, ifp->int_mask) - && (maybe == 0 - || ifp->int_mask > maybe->int_mask)) - maybe = ifp; + /* Look for the longest approximate match. + */ + if (on_net(addr, ifp->int_net, ifp->int_mask) + && (maybe == 0 + || ifp->int_mask > maybe->int_mask)) + maybe = ifp; + } } - } - return maybe; + if (maybe != 0 + || (retried.tv_sec == now.tv_sec + && retried.tv_usec == now.tv_usec)) + return maybe; + + /* If there is no known interface, maybe there is a + * new interface. So just once look for new interfaces. + */ + ifinit(); + retried = now; + } } /* Return the classical netmask for an IP address. */ -naddr -std_mask(naddr addr) /* in network order */ +naddr /* host byte order */ +std_mask(naddr addr) /* network byte order */ { NTOHL(addr); /* was a host, not a network */ @@ -338,9 +350,9 @@ check_dst(naddr addr) /* See a new interface duplicates an existing interface. */ struct interface * -check_dup(naddr addr, - naddr dstaddr, - naddr mask, +check_dup(naddr addr, /* IP address, so network byte order */ + naddr dstaddr, /* ditto */ + naddr mask, /* mask, so host byte order */ int if_flags) { struct interface *ifp; @@ -691,6 +703,7 @@ ifinit(void) ifs0.int_index = ifm->ifm_index; ifs0.int_if_flags = ifm->ifm_flags; ifs0.int_state = IS_CHECKED; + ifs0.int_query_time = NEVER; ifs0.int_act_time = now.tv_sec; ifs0.int_data.ts = now.tv_sec; ifs0.int_data.ipackets = ifm->ifm_data.ifi_ipackets; @@ -1006,10 +1019,20 @@ ifinit(void) if (ifp != 0) { if (!(prev_complaints & COMP_DUP)) { complaints |= COMP_DUP; - msglog("%s is duplicated by %s at %s to %s", - ifs.int_name, ifp->int_name, - naddr_ntoa(ifp->int_addr), - naddr_ntoa(ifp->int_dstaddr)); + msglog("%s (%s%s%s) is duplicated by" + " %s (%s%s%s)", + ifs.int_name, + addrname(ifs.int_addr,ifs.int_mask,1), + ((ifs.int_if_flags & IFF_POINTOPOINT) + ? "-->" : ""), + ((ifs.int_if_flags & IFF_POINTOPOINT) + ? naddr_ntoa(ifs.int_dstaddr) : ""), + ifp->int_name, + addrname(ifp->int_addr,ifp->int_mask,1), + ((ifp->int_if_flags & IFF_POINTOPOINT) + ? "-->" : ""), + ((ifp->int_if_flags & IFF_POINTOPOINT) + ? naddr_ntoa(ifp->int_dstaddr) : "")); } ifp->int_state |= IS_DUP; continue; @@ -1263,7 +1286,7 @@ addrouteforif(struct interface *ifp) * it must be reachable using our physical interfaces */ if ((ifp->int_state & IS_REMOTE) - && !(ifp->int_state && IS_EXTERNAL) + && !(ifp->int_state & IS_EXTERNAL) && !check_remote(ifp)) return 0; diff --git a/sbin/routed/input.c b/sbin/routed/input.c index 24a02b9..fb5dbf5 100644 --- a/sbin/routed/input.c +++ b/sbin/routed/input.c @@ -36,7 +36,7 @@ static char sccsid[] = "@(#)input.c 8.1 (Berkeley) 6/5/93"; #elif defined(__NetBSD__) static char rcsid[] = "$NetBSD$"; #endif -#ident "$Revision: 1.17 $" +#ident "$Revision: 1.19 $" #include "defs.h" @@ -54,16 +54,20 @@ void read_rip(int sock, struct interface *sifp) { - static struct msg_limit bad_name; struct sockaddr_in from; struct interface *aifp; int fromlen, cc; - struct { #ifdef USE_PASSIFNAME + static struct msg_limit bad_name; + struct { char ifname[IFNAMSIZ]; -#endif union pkt_buf pbuf; } inbuf; +#else + struct { + union pkt_buf pbuf; + } inbuf; +#endif for (;;) { @@ -148,7 +152,7 @@ input(struct sockaddr_in *from, /* received from this IP address */ struct netinfo *n, *lim; struct interface *ifp1; naddr gate, mask, v1_mask, dst, ddst_h; - struct auth_key *ap; + struct auth *ap; int i; /* Notice when we hear from a remote gateway @@ -262,17 +266,16 @@ input(struct sockaddr_in *from, /* received from this IP address */ * do not disclose our secret unless the other guy * already knows it. */ - if (aifp != 0 - && aifp->int_auth.type == RIP_AUTH_PW + ap = find_auth(aifp); + if (aifp == 0 && ap->type == RIP_AUTH_PW + && n->n_family == RIP_AF_AUTH && !ck_passwd(aifp,rip,lim,FROM_NADDR,&use_auth)) ap = 0; - else - ap = find_auth(aifp); } else { v12buf.buf->rip_vers = RIPv1; ap = 0; } - clr_ws_buf(&v12buf, ap, aifp); + clr_ws_buf(&v12buf, ap); do { NTOHL(n->n_metric); @@ -397,7 +400,7 @@ input(struct sockaddr_in *from, /* received from this IP address */ /* Send the answer about specific routes. */ - if (ap != 0 && aifp->int_auth.type == RIP_AUTH_MD5) + if (ap != 0 && ap->type == RIP_AUTH_MD5) end_md5_auth(&v12buf, ap); if (from->sin_port != htons(RIP_PORT)) { @@ -433,7 +436,8 @@ input(struct sockaddr_in *from, /* received from this IP address */ } if (rip->rip_cmd == RIPCMD_TRACEON) { rip->rip_tracefile[cc-4] = '\0'; - trace_on((char*)rip->rip_tracefile, 0); + set_tracefile((char*)rip->rip_tracefile, + "trace command: %s\n", 0); } else { trace_off("tracing turned off by %s\n", naddr_ntoa(FROM_NADDR)); @@ -519,8 +523,8 @@ input(struct sockaddr_in *from, /* received from this IP address */ } /* If the interface cares, ignore bad routers. - * Trace but do not log this problem because when it - * happens it happens a lot. + * Trace but do not log this problem, because where it + * happens, it happens frequently. */ if (aifp->int_state & IS_DISTRUST) { struct tgate *tg = tgates; @@ -536,14 +540,13 @@ input(struct sockaddr_in *from, /* received from this IP address */ } /* Authenticate the packet if we have a secret. - * If we do not, ignore the silliness in RFC 1723 - * and accept it regardless. + * If we do not have any secrets, ignore the error in + * RFC 1723 and accept it regardless. */ - if (aifp->int_auth.type != RIP_AUTH_NONE - && rip->rip_vers != RIPv1) { - if (!ck_passwd(aifp,rip,lim,FROM_NADDR,&use_auth)) - return; - } + if (aifp->int_auth[0].type != RIP_AUTH_NONE + && rip->rip_vers != RIPv1 + && !ck_passwd(aifp,rip,lim,FROM_NADDR,&use_auth)) + return; do { if (n->n_family == RIP_AF_AUTH) @@ -860,9 +863,8 @@ ck_passwd(struct interface *aifp, struct msg_limit *use_authp) { # define NA (rip->rip_auths) -# define DAY (24*60*60) struct netauth *na2; - struct auth_key *akp = aifp->int_auth.keys; + struct auth *ap; MD5_CTX md5_ctx; u_char hash[RIP_AUTH_PW_LEN]; int i; @@ -874,35 +876,24 @@ ck_passwd(struct interface *aifp, return 0; } - if (NA->a_type != aifp->int_auth.type) { - msglim(use_authp, from, "wrong type of password from %s", - naddr_ntoa(from)); - return 0; - } - - if (NA->a_type == RIP_AUTH_PW) { - /* accept any current cleartext password - */ - for (i = 0; i < MAX_AUTH_KEYS; i++, akp++) { - if ((u_long)akp->start-DAY > (u_long)clk.tv_sec - || (u_long)akp->end+DAY < (u_long)clk.tv_sec) - continue; - - if (!bcmp(NA->au.au_pw, akp->key, RIP_AUTH_PW_LEN)) + /* accept any current (+/- 24 hours) password + */ + for (ap = aifp->int_auth, i = 0; i < MAX_AUTH_KEYS; i++, ap++) { + if (ap->type != NA->a_type + || (u_long)ap->start > (u_long)clk.tv_sec+DAY + || (u_long)ap->end+DAY < (u_long)clk.tv_sec) + continue; + + if (NA->a_type == RIP_AUTH_PW) { + if (!bcmp(NA->au.au_pw, ap->key, RIP_AUTH_PW_LEN)) return 1; - } - } else { - /* accept any current MD5 secret with the right key ID - */ - for (i = 0; i < MAX_AUTH_KEYS; i++, akp++) { - if (NA->au.a_md5.md5_keyid == akp->keyid - && (u_long)akp->start-DAY <= (u_long)clk.tv_sec - && (u_long)akp->end+DAY >= (u_long)clk.tv_sec) - break; - } + } else { + /* accept MD5 secret with the right key ID + */ + if (NA->au.a_md5.md5_keyid != ap->keyid) + continue; - if (i < MAX_AUTH_KEYS) { na2 = (struct netauth *)((char *)(NA+1) + NA->au.a_md5.md5_pkt_len); if (NA->au.a_md5.md5_pkt_len % sizeof(*NA) != 0 @@ -917,13 +908,14 @@ ck_passwd(struct interface *aifp, MD5Update(&md5_ctx, (u_char *)NA, (char *)na2->au.au_pw - (char *)NA); MD5Update(&md5_ctx, - (u_char *)akp->key, sizeof(akp->key)); + (u_char *)ap->key, sizeof(ap->key)); MD5Final(hash, &md5_ctx); - if (na2->a_family == RIP_AF_AUTH - && na2->a_type == 1 - && NA->au.a_md5.md5_auth_len == RIP_AUTH_PW_LEN - && !bcmp(hash, na2->au.au_pw, sizeof(hash))) - return 1; + if (na2->a_family != RIP_AF_AUTH + || na2->a_type != 1 + || NA->au.a_md5.md5_auth_len != RIP_AUTH_PW_LEN + || bcmp(hash, na2->au.au_pw, sizeof(hash))) + return 0; + return 1; } } diff --git a/sbin/routed/main.c b/sbin/routed/main.c index dc0b1d8..58cce95 100644 --- a/sbin/routed/main.c +++ b/sbin/routed/main.c @@ -39,7 +39,7 @@ static char sccsid[] = "@(#)main.c 8.1 (Berkeley) 6/5/93"; #elif defined(__NetBSD__) static char rcsid[] = "$NetBSD$"; #endif -#ident "$Revision: 1.18 $" +#ident "$Revision: 1.20 $" #include "defs.h" #include "pathnames.h" @@ -201,10 +201,13 @@ main(int argc, /* handle arbirary, (usually) per-interface * parameters. */ - p = parse_parms(optarg); - if (p != 0) - msglog("bad \"%s\" in \"%s\"", - p, optarg); + p = parse_parms(optarg, 0); + if (p != 0) { + if (strcasecmp(p,optarg)) + msglog("%s in \"%s\"", p, optarg); + else + msglog("bad \"-P %s\"", optarg); + } break; default: @@ -218,9 +221,11 @@ main(int argc, tracename = *argv++; argc--; } + if (tracename != 0 && tracename[0] == '\0') + goto usage; if (argc != 0) { usage: - logbad(0, "usage: routed [-sqdghmpAt] [-T /tracefile]" + logbad(0, "usage: routed [-sqdghmpAt] [-T tracefile]" " [-F net[,metric]] [-P parms]"); } if (geteuid() != 0) @@ -263,18 +268,16 @@ usage: signal(SIGUSR2, sigtrace_off); /* get into the background */ - if (background) { #ifdef sgi - if (0 > _daemonize(_DF_NOCHDIR, - new_tracelevel == 0 ? -1 : STDOUT_FILENO, - new_tracelevel == 0 ? -1 : STDERR_FILENO, - -1)) - BADERR(0, "_daemonize()"); + if (0 > _daemonize(background ? 0 : (_DF_NOCHDIR|_DF_NOFORK), + new_tracelevel == 0 ? -1 : STDOUT_FILENO, + new_tracelevel == 0 ? -1 : STDERR_FILENO, + -1)) + BADERR(0, "_daemonize()"); #else - if (daemon(1, 1) < 0) - BADERR(0,"daemon()"); + if (background && daemon(0, new_tracelevel) < 0) + BADERR(0,"daemon()"); #endif - } mypid = getpid(); srandom((int)(clk.tv_sec ^ clk.tv_usec ^ mypid)); @@ -297,11 +300,11 @@ usage: if (background && new_tracelevel == 0) ftrace = 0; if (tracename != 0) { - trace_on(tracename, 1); - if (new_tracelevel == 0) /* use stdout if file is bad */ - new_tracelevel = 1; + strncpy(inittracename, tracename, sizeof(inittracename)-1); + set_tracefile(inittracename, "%s\n", -1); + } else { + tracelevel_msg("%s\n", -1); /* turn on tracing to stdio */ } - set_tracelevel(1); bufinit(); @@ -354,8 +357,8 @@ usage: now_expire = now.tv_sec - EXPIRE_TIME; now_garbage = now.tv_sec - GARBAGE_TIME; - /* deal with interrupts that should affect tracing */ - set_tracelevel(0); + /* deal with signals that should affect tracing */ + set_tracelevel(); if (stopint != 0) { rip_bcast(0); @@ -491,7 +494,7 @@ usage: /* ARGSUSED */ void -sigalrm(int sig) +sigalrm(int s) { /* Historically, SIGALRM would cause the daemon to check for * new and broken interfaces. @@ -816,20 +819,53 @@ msglog(char *p, ...) } -/* Put a message about a bad router into the system log if +/* Put a message about a bad system into the system log if * we have not complained about it recently. + * + * It is desirable to complain about all bad systems, but not too often. + * In the worst case, it is not practical to keep track of all bad systems. + * For example, there can be many systems with the wrong password. */ void msglim(struct msg_limit *lim, naddr addr, char *p, ...) { va_list args; + int i; + struct msg_sub *ms1, *ms; char *p1; va_start(args, p); - if ( lim->addr != addr || lim->until <= now.tv_sec) { - lim->addr = addr; - lim->until = now.tv_sec + 60*60; + /* look for the oldest slot in the table + * or the slot for the bad router. + */ + ms = ms1 = lim->subs; + for (i = MSG_SUBJECT_N; ; i--, ms1++) { + if (i == 0) { + /* Reuse a slot at most once every 10 minutes. + */ + if (lim->reuse > now.tv_sec) { + ms = 0; + } else { + ms = ms1; + lim->reuse = now.tv_sec + 10*60; + } + break; + } + if (ms->addr == addr) { + /* Repeat a complaint about a given system at + * most once an hour. + */ + if (ms->until > now.tv_sec) + ms = 0; + break; + } + if (ms->until < ms1->until) + ms = ms1; + } + if (ms != 0) { + ms->addr = addr; + ms->until = now.tv_sec + 60*60; /* 60 minutes */ trace_flush(); for (p1 = p; *p1 == ' '; p1++) @@ -837,6 +873,7 @@ msglim(struct msg_limit *lim, naddr addr, char *p, ...) vsyslog(LOG_ERR, p1, args); } + /* always display the message if tracing */ if (ftrace != 0) { (void)vfprintf(ftrace, p, args); (void)fputc('\n', ftrace); diff --git a/sbin/routed/md5.c b/sbin/routed/md5.c index a6fcf16..c24aa5a 100644 --- a/sbin/routed/md5.c +++ b/sbin/routed/md5.c @@ -22,7 +22,7 @@ * documentation and/or software. */ -#ident "$Revision: 1.2 $" +#ident "$Revision: 1.3 $" #ifdef sgi #include diff --git a/sbin/routed/output.c b/sbin/routed/output.c index 69f7da9..de8f97d 100644 --- a/sbin/routed/output.c +++ b/sbin/routed/output.c @@ -36,7 +36,7 @@ static char sccsid[] = "@(#)output.c 8.1 (Berkeley) 6/5/93"; #elif defined(__NetBSD__) static char rcsid[] = "$NetBSD$"; #endif -#ident "$Revision: 1.18 $" +#ident "$Revision: 1.21 $" #include "defs.h" @@ -53,7 +53,7 @@ struct { naddr to_std_mask; naddr to_std_net; struct interface *ifp; /* usually output interface */ - struct auth_key *a; + struct auth *a; char metric; /* adjust metrics by interface */ int npackets; int gen_limit; @@ -180,10 +180,15 @@ output(enum output_type type, } sin.sin_addr.s_addr = htonl(INADDR_RIP_GROUP); } + break; case NO_OUT_MULTICAST: case NO_OUT_RIPV2: - break; + default: +#ifdef DEBUG + abort(); +#endif + return -1; } trace_rip(msg, "to", &sin, ifp, buf, size); @@ -206,28 +211,42 @@ output(enum output_type type, } -/* Find the first key that has not expired, but settle for +/* Find the first key for a packet to send. + * Try for a key that is eligable and has not expired, but settle for * the last key if they have all expired. * If no key is ready yet, give up. */ -struct auth_key * +struct auth * find_auth(struct interface *ifp) { - struct auth_key *ap, *res; + struct auth *ap, *res; int i; - if (ifp == 0 || ifp->int_auth.type == RIP_AUTH_NONE) + if (ifp == 0) return 0; - + res = 0; - ap = ifp->int_auth.keys; + ap = ifp->int_auth; for (i = 0; i < MAX_AUTH_KEYS; i++, ap++) { - if ((u_long)ap->start <= (u_long)clk.tv_sec) { - if ((u_long)ap->end >= (u_long)clk.tv_sec) - return ap; - res = ap; + /* stop looking after the last key */ + if (ap->type == RIP_AUTH_NONE) + break; + + /* ignore keys that are not ready yet */ + if ((u_long)ap->start > (u_long)clk.tv_sec) + continue; + + if ((u_long)ap->end < (u_long)clk.tv_sec) { + /* note best expired password as a fall-back */ + if (res == 0 || (u_long)ap->end > (u_long)res->end) + res = ap; + continue; } + + /* note key with the best future */ + if (res == 0 || (u_long)res->end < (u_long)ap->end) + res = ap; } return res; } @@ -235,8 +254,7 @@ find_auth(struct interface *ifp) void clr_ws_buf(struct ws_buf *wb, - struct auth_key *ap, - struct interface *ifp) + struct auth *ap) { struct netauth *na; @@ -249,13 +267,13 @@ clr_ws_buf(struct ws_buf *wb, if (ap == 0) return; na = (struct netauth*)wb->n; - if (ifp->int_auth.type == RIP_AUTH_PW) { + if (ap->type == RIP_AUTH_PW) { na->a_family = RIP_AF_AUTH; na->a_type = RIP_AUTH_PW; bcopy(ap->key, na->au.au_pw, sizeof(na->au.au_pw)); wb->n++; - } else if (ifp->int_auth.type == RIP_AUTH_MD5) { + } else if (ap->type == RIP_AUTH_MD5) { na->a_family = RIP_AF_AUTH; na->a_type = RIP_AUTH_MD5; na->au.a_md5.md5_keyid = ap->keyid; @@ -269,7 +287,7 @@ clr_ws_buf(struct ws_buf *wb, void end_md5_auth(struct ws_buf *wb, - struct auth_key *ap) + struct auth *ap) { struct netauth *na, *na2; MD5_CTX md5_ctx; @@ -306,7 +324,7 @@ supply_write(struct ws_buf *wb) case NO_OUT_RIPV2: break; default: - if (ws.ifp->int_auth.type == RIP_AUTH_MD5) + if (ws.a != 0 && ws.a->type == RIP_AUTH_MD5) end_md5_auth(wb,ws.a); if (output(wb->type, &ws.to, ws.ifp, wb->buf, ((char *)wb->n - (char*)wb->buf)) < 0 @@ -316,7 +334,7 @@ supply_write(struct ws_buf *wb) break; } - clr_ws_buf(wb,ws.a,ws.ifp); + clr_ws_buf(wb,ws.a); } @@ -326,7 +344,7 @@ static void supply_out(struct ag_info *ag) { int i; - naddr mask, v1_mask, dst_h, ddst_h; + naddr mask, v1_mask, dst_h, ddst_h = 0; struct ws_buf *wb; @@ -563,25 +581,33 @@ walk_supply(struct radix_node *rn, * forgotten. * * Include the routes for both ends of point-to-point interfaces - * since the other side presumably knows them as well as we do. + * among those suppressed by split-horizon, since the other side + * should knows them as well as we do. */ if (RT->rt_ifp == ws.ifp && ws.ifp != 0 && !(ws.state & WS_ST_QUERY) && (ws.state & WS_ST_TO_ON_NET) && (!(RT->rt_state & RS_IF) || ws.ifp->int_if_flags & IFF_POINTOPOINT)) { - /* Poison-reverse the route instead of only not advertising it - * it is recently changed from some other route. + /* If we do not mark the route with AGS_SPLIT_HZ here, + * it will be poisoned-reverse, or advertised back toward + * its source with an infinite metric. If we have recently + * advertised the route with a better metric than we now + * have, then we should poison-reverse the route before + * suppressing it for split-horizon. + * * In almost all cases, if there is no spare for the route - * then it is either old or a brand new route, and if it - * is brand new, there is no need for poison-reverse. + * then it is either old and dead or a brand new route. + * If it is brand new, there is no need for poison-reverse. + * If it is old and dead, it is already poisoned. */ - metric = HOPCNT_INFINITY; if (RT->rt_poison_time < now_expire - || RT->rt_spares[1].rts_gate ==0) { + || RT->rt_poison_metric >= metric + || RT->rt_spares[1].rts_gate == 0) { ags |= AGS_SPLIT_HZ; ags &= ~(AGS_PROMOTE | AGS_SUPPRESS); } + metric = HOPCNT_INFINITY; } /* Adjust the outgoing metric by the cost of the link. @@ -716,10 +742,10 @@ supply(struct sockaddr_in *dst, } ws.a = (vers == RIPv2) ? find_auth(ifp) : 0; - if (ws.a != 0 && !passwd_ok && ifp->int_auth.type == RIP_AUTH_PW) + if (!passwd_ok && ws.a != 0 && ws.a->type == RIP_AUTH_PW) ws.a = 0; - clr_ws_buf(&v12buf,ws.a,ifp); - clr_ws_buf(&v2buf,ws.a,ifp); + clr_ws_buf(&v12buf,ws.a); + clr_ws_buf(&v2buf,ws.a); /* Fake a default route if asked and if there is not already * a better, real default route. diff --git a/sbin/routed/parms.c b/sbin/routed/parms.c index ab5c75e..87ca4a8 100644 --- a/sbin/routed/parms.c +++ b/sbin/routed/parms.c @@ -36,10 +36,11 @@ static char sccsid[] = "@(#)if.c 8.1 (Berkeley) 6/5/93"; #elif defined(__NetBSD__) static char rcsid[] = "$NetBSD$"; #endif -#ident "$Revision: 1.10 $" +#ident "$Revision: 1.12 $" #include "defs.h" #include "pathnames.h" +#include struct parm *parms; @@ -54,6 +55,7 @@ get_parms(struct interface *ifp) { static warned_auth_in, warned_auth_out; struct parm *parmp; + int i, num_passwds = 0; /* get all relevant parameters */ @@ -68,9 +70,14 @@ get_parms(struct interface *ifp) * so get its settings */ ifp->int_state |= parmp->parm_int_state; - if (parmp->parm_auth.type != RIP_AUTH_NONE) - bcopy(&parmp->parm_auth, &ifp->int_auth, - sizeof(ifp->int_auth)); + for (i = 0; i < MAX_AUTH_KEYS; i++) { + if (parmp->parm_auth[0].type == RIP_AUTH_NONE + || num_passwds >= MAX_AUTH_KEYS) + break; + bcopy(&parmp->parm_auth[i], + &ifp->int_auth[num_passwds++], + sizeof(ifp->int_auth[0])); + } if (parmp->parm_rdisc_pref != 0) ifp->int_rdisc_pref = parmp->parm_rdisc_pref; if (parmp->parm_rdisc_int != 0) @@ -114,7 +121,7 @@ get_parms(struct interface *ifp) ifp->int_state |= IS_NO_RIP; if (!IS_RIP_IN_OFF(ifp->int_state) - && ifp->int_auth.type != RIP_AUTH_NONE + && ifp->int_auth[0].type != RIP_AUTH_NONE && !(ifp->int_state & IS_NO_RIPV1_IN) && !warned_auth_in) { msglog("Warning: RIPv1 input via %s" @@ -123,14 +130,14 @@ get_parms(struct interface *ifp) warned_auth_in = 1; } if (!IS_RIP_OUT_OFF(ifp->int_state) - && ifp->int_auth.type != RIP_AUTH_NONE - && !(ifp->int_state & IS_NO_RIPV1_OUT) - && !warned_auth_out) { - msglog("Warning: RIPv1 output via %s" - " will be sent without authentication", - ifp->int_name); - warned_auth_out = 1; - ifp->int_auth.type = RIP_AUTH_NONE; + && ifp->int_auth[0].type != RIP_AUTH_NONE + && !(ifp->int_state & IS_NO_RIPV1_OUT)) { + if (!warned_auth_out) { + msglog("Warning: RIPv1 output via %s" + " will be sent without authentication", + ifp->int_name); + warned_auth_out = 1; + } } } @@ -160,6 +167,7 @@ gwkludge(void) struct interface *ifp; naddr dst, netmask, gate; int metric, n; + struct stat sb; u_int state; char *type; @@ -168,6 +176,12 @@ gwkludge(void) if (fp == 0) return; + if (0 > fstat(fileno(fp), &sb)) { + msglog("could not stat() "_PATH_GATEWAYS); + (void)fclose(fp); + return; + } + for (;;) { if (0 == fgets(lbuf, sizeof(lbuf)-1, fp)) break; @@ -185,10 +199,12 @@ gwkludge(void) */ if (strncasecmp("net", lptr, 3) && strncasecmp("host", lptr, 4)) { - p = parse_parms(lptr); + p = parse_parms(lptr, + (sb.st_uid == 0 + && !(sb.st_mode&(S_IRWXG|S_IRWXO)))); if (p != 0) { if (strcasecmp(p,lptr)) - msglog("bad %s in "_PATH_GATEWAYS + msglog("%s in "_PATH_GATEWAYS " entry \"%s\"", p, lptr); else msglog("bad \"%s\" in "_PATH_GATEWAYS, @@ -225,6 +241,7 @@ gwkludge(void) " entry \"%s\"", dname, lptr); continue; } + HTONL(dst); /* make network # into IP address */ } else { msglog("bad \"%s\" in "_PATH_GATEWAYS " entry \"%s\"", lptr); @@ -333,12 +350,14 @@ gwkludge(void) trace_if("Add", ifp); } + + (void)fclose(fp); } /* strtok(), but honoring backslash */ -static int /* -1=bad */ +static int /* 0=ok, -1=bad */ parse_quote(char **linep, char *delims, char *delimp, @@ -352,9 +371,7 @@ parse_quote(char **linep, if (*pc == '\0') return -1; - for (;;) { - if (lim == 0) - return -1; + while (lim != 0) { c = *pc++; if (c == '\0') break; @@ -388,11 +405,13 @@ parse_quote(char **linep, --lim; } exit: + if (lim == 0) + return -1; + + *buf = '\0'; if (delimp != 0) *delimp = c; *linep = pc-1; - if (lim != 0) - *buf = '\0'; return 0; } @@ -413,7 +432,7 @@ parse_ts(time_t *tp, buf,bufsize) || buf[bufsize-1] != '\0' || buf[bufsize-2] != '\0') { - sprintf(buf,"timestamp %.25s", val0); + sprintf(buf,"bad timestamp %.25s", val0); return buf; } strcat(buf,"\n"); @@ -421,14 +440,14 @@ parse_ts(time_t *tp, if (5 != sscanf(buf, "%u/%u/%u@%u:%u\n", &tm.tm_year, &tm.tm_mon, &tm.tm_mday, &tm.tm_hour, &tm.tm_min)) { - sprintf(buf,"timestamp %.25s", val0); + sprintf(buf,"bad timestamp %.25s", val0); return buf; } if (tm.tm_year <= 37) tm.tm_year += 100; if ((*tp = mktime(&tm)) == -1) { - sprintf(buf,"timestamp %.25s", val0); + sprintf(buf,"bad timestamp %.25s", val0); return buf; } @@ -436,92 +455,93 @@ parse_ts(time_t *tp, } -/* Get one or more password, key ID's, and expiration dates in - * the format - * passwd|keyID|year/mon/day@hour:min|year/mon/day@hour:min|passwd|... +/* Get a password, key ID, and expiration date in the format + * passwd|keyID|year/mon/day@hour:min|year/mon/day@hour:min */ static char * /* 0 or error message */ -get_passwds(char *tgt, - char *val, - struct parm *parmp, - u_char type) +get_passwd(char *tgt, + char *val, + struct parm *parmp, + u_char type, + int safe) /* 1=from secure file */ { static char buf[80]; char *val0, *p, delim; - struct auth_key *akp, *akp2; + struct auth k, *ap, *ap2; int i; u_long l; - if (parmp->parm_auth.type != RIP_AUTH_NONE) - return "duplicate authentication"; - parmp->parm_auth.type = type; + if (!safe) + return "unsafe password"; - bzero(buf, sizeof(buf)); + for (ap = parmp->parm_auth, i = 0; + ap->type != RIP_AUTH_NONE; i++, ap++) { + if (i >= MAX_AUTH_KEYS) + return "too many passwords"; + } - akp = parmp->parm_auth.keys; - for (i = 0; i < MAX_AUTH_KEYS; i++, val++, akp++) { - if ((delim = *val) == '\0') - break; - val0 = val; - if (0 > parse_quote(&val, "| ,\n\r", &delim, - (char *)akp->key, sizeof(akp->key))) - return tgt; + bzero(&k, sizeof(k)); + k.type = type; + k.end = -1-DAY; - akp->end = -1; + val0 = val; + if (0 > parse_quote(&val, "| ,\n\r", &delim, + (char *)k.key, sizeof(k.key))) + return tgt; - if (delim != '|') { - if (type == RIP_AUTH_MD5) - return "missing Keyid"; - break; - } + if (delim != '|') { + if (type == RIP_AUTH_MD5) + return "missing Keyid"; + } else { val0 = ++val; + buf[sizeof(buf)-1] = '\0'; if (0 > parse_quote(&val, "| ,\n\r", &delim, buf,sizeof(buf)) || buf[sizeof(buf)-1] != '\0' || (l = strtoul(buf,&p,0)) > 255 || *p != '\0') { - sprintf(buf,"KeyID \"%.20s\"", val0); + sprintf(buf,"bad KeyID \"%.20s\"", val0); return buf; } - for (akp2 = parmp->parm_auth.keys; akp2 < akp; akp2++) { - if (akp2->keyid == l) { - *val = '\0'; + for (ap2 = parmp->parm_auth; ap2 < ap; ap2++) { + if (ap2->keyid == l) { sprintf(buf,"duplicate KeyID \"%.20s\"", val0); return buf; } } - akp->keyid = (int)l; - - if (delim != '|') - break; - - val0 = ++val; - if (0 != (p = parse_ts(&akp->start,&val,val0,&delim, - buf,sizeof(buf)))) - return p; - if (delim != '|') - return "missing second timestamp"; - val0 = ++val; - if (0 != (p = parse_ts(&akp->end,&val,val0,&delim, - buf,sizeof(buf)))) - return p; - if ((u_long)akp->start > (u_long)akp->end) { - sprintf(buf,"out of order timestamp %.30s",val0); - return buf; + k.keyid = (int)l; + + if (delim == '|') { + val0 = ++val; + if (0 != (p = parse_ts(&k.start,&val,val0,&delim, + buf,sizeof(buf)))) + return p; + if (delim != '|') + return "missing second timestamp"; + val0 = ++val; + if (0 != (p = parse_ts(&k.end,&val,val0,&delim, + buf,sizeof(buf)))) + return p; + if ((u_long)k.start > (u_long)k.end) { + sprintf(buf,"out of order timestamp %.30s", + val0); + return buf; + } } - - if (delim != '|') - break; } + if (delim != '\0') + return tgt; - return (delim != '\0') ? tgt : 0; + bcopy(&k, ap, sizeof(*ap)); + return 0; } /* Parse a set of parameters for an interface. */ char * /* 0 or error message */ -parse_parms(char *line) +parse_parms(char *line, + int safe) /* 1=from secure file */ { #define PARS(str) (!strcasecmp(tgt, str)) #define PARSEQ(str) (!strncasecmp(tgt, str"=", sizeof(str))) @@ -554,6 +574,7 @@ parse_parms(char *line) free(intnetp); return line; } + HTONL(intnetp->intnet_addr); intnetp->intnet_next = intnets; intnets = intnetp; return 0; @@ -591,7 +612,7 @@ parse_parms(char *line) * The parm_net stuff is needed to allow several * -F settings. */ - if (!getnet(val, &addr, &mask) + if (!getnet(val0, &addr, &mask) || parm.parm_name[0] != '\0') return tgt; parm.parm_net = addr; @@ -599,14 +620,21 @@ parse_parms(char *line) parm.parm_name[0] = '\n'; } else if (PARSEQ("passwd")) { - tgt = get_passwds(tgt, val0, &parm, RIP_AUTH_PW); - if (tgt) + /* since cleartext passwords are so weak allow + * them anywhere + */ + tgt = get_passwd(tgt,val0,&parm,RIP_AUTH_PW,1); + if (tgt) { + *val0 = '\0'; return tgt; + } } else if (PARSEQ("md5_passwd")) { - tgt = get_passwds(tgt, val0, &parm, RIP_AUTH_MD5); - if (tgt) + tgt = get_passwd(tgt,val0,&parm,RIP_AUTH_MD5,safe); + if (tgt) { + *val0 = '\0'; return tgt; + } } else if (PARS("no_ag")) { parm.parm_int_state |= (IS_NO_AG | IS_NO_SUPER_AG); @@ -693,6 +721,9 @@ parse_parms(char *line) tgates = tg; parm.parm_int_state |= IS_DISTRUST; + } else if (PARS("redirect_ok")) { + parm.parm_int_state |= IS_REDIRECT_OK; + } else { return tgt; /* error */ } @@ -708,16 +739,24 @@ parse_parms(char *line) char * /* 0 or error message */ check_parms(struct parm *new) { - struct parm *parmp; + struct parm *parmp, **parmpp; + int i, num_passwds; /* set implicit values */ if (new->parm_int_state & IS_NO_ADV_IN) new->parm_int_state |= IS_NO_SOL_OUT; + for (i = num_passwds = 0; i < MAX_AUTH_KEYS; i++) { + if (new->parm_auth[i].type != RIP_AUTH_NONE) + num_passwds++; + } + /* compare with existing sets of parameters */ - for (parmp = parms; parmp != 0; parmp = parmp->parm_next) { + for (parmpp = &parms; + (parmp = *parmpp) != 0; + parmpp = &parmp->parm_next) { if (strcmp(new->parm_name, parmp->parm_name)) continue; if (!on_net(htonl(parmp->parm_net), @@ -726,12 +765,12 @@ check_parms(struct parm *new) parmp->parm_net, parmp->parm_mask)) continue; - if (parmp->parm_auth.type != RIP_AUTH_NONE - && new->parm_auth.type != RIP_AUTH_NONE - && bcmp(&parmp->parm_auth, &new->parm_auth, - sizeof(parmp->parm_auth))) { - return "conflicting, duplicate authentication"; + for (i = 0; i < MAX_AUTH_KEYS; i++) { + if (parmp->parm_auth[i].type != RIP_AUTH_NONE) + num_passwds++; } + 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) @@ -760,10 +799,12 @@ check_parms(struct parm *new) } } + /* link new entry on the so that when the entries are scanned, + * they affect the result in the order the operator specified. + */ parmp = (struct parm*)malloc(sizeof(*parmp)); bcopy(new, parmp, sizeof(*parmp)); - parmp->parm_next = parms; - parms = parmp; + *parmpp = parmp; return 0; } @@ -774,13 +815,13 @@ check_parms(struct parm *new) */ int /* 0=bad */ getnet(char *name, - naddr *netp, /* host byte order */ - naddr *maskp) + naddr *netp, /* a network so host byte order */ + naddr *maskp) /* masks are always in host order */ { int i; struct netent *np; - naddr mask; - struct in_addr in; + naddr mask; /* in host byte order */ + struct in_addr in; /* a network and so host byte order */ char hname[MAXHOSTNAMELEN+1]; char *mname, *p; @@ -812,7 +853,7 @@ getnet(char *name, /* we cannot use the interfaces here because we have not * looked at them yet. */ - mask = std_mask(in.s_addr); + mask = std_mask(htonl(in.s_addr)); if ((~mask & in.s_addr) != 0) mask = HOST_MASK; } else { diff --git a/sbin/routed/rdisc.c b/sbin/routed/rdisc.c index 7433b792..1e9f42d 100644 --- a/sbin/routed/rdisc.c +++ b/sbin/routed/rdisc.c @@ -36,7 +36,7 @@ static char sccsid[] = "@(#)rdisc.c 8.1 (Berkeley) x/y/95"; #elif defined(__NetBSD__) static char rcsid[] = "$NetBSD$"; #endif -#ident "$Revision: 1.17 $" +#ident "$Revision: 1.19 $" #include "defs.h" #include @@ -127,7 +127,7 @@ trace_rdisc(char *act, wp = &p->ad.icmp_ad_info[0].icmp_ad_addr; lim = &wp[(len - sizeof(p->ad)) / sizeof(*wp)]; for (i = 0; i < p->ad.icmp_ad_num && wp <= lim; i++) { - (void)fprintf(ftrace, "\t%s preference=%#x", + (void)fprintf(ftrace, "\t%s preference=%d", naddr_ntoa(wp[0]), (int)ntohl(wp[1])); wp += p->ad.icmp_ad_asize; } @@ -689,6 +689,7 @@ send_rdisc(union ad_u *p, switch (type) { case 0: /* unicast */ + default: msg = "Send"; break; diff --git a/sbin/routed/routed.8 b/sbin/routed/routed.8 index 3e7a6c9..424a851 100644 --- a/sbin/routed/routed.8 +++ b/sbin/routed/routed.8 @@ -514,11 +514,13 @@ 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]][XXX2...] -specifies one or more RIPv2 cleartext passwords that will be included on +.It Cm passwd Ns \&= Ns Ar XXX1[|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 '|' characters in the +Any blanks, tab characters, commas, or '#', '|', or NULL characters in the password must be escaped with a backslash (\\). +The common escape sequences \\n, \\r, \\t, \\b, and \\xxx have their +usual meanings. The .Cm KeyID must be unique but is ignored for cleartext passwords. @@ -528,15 +530,21 @@ and .Cm stop are timestamps in the form year/month/day@hour:minute. They specify when the password is valid. -The first valid password is used on output packets. +The valid password with the most future is used on output packets, unless +all passwords have expired, in which case the password that expired most +recently is used, or unless no passwords are valid yet, in which case +no password is output. Incoming packets can carry any password that is valid, will be valid within 24 hours, or that was valid within 24 hours. -.It Cm md5_passwd Ns \&= Ns Ar XXX1|KeyID[start|stop][XXX2...] -specifes one or more RIPv2 MD5 passwords. +.It Cm md5_passwd Ns \&= Ns Ar XXX1|KeyID[start|stop] +specifes a RIPv2 MD5 password. Except that a .Cm KeyID -is required, this keyword is the similar to +is required, this keyword is similar to .Cm passwd . +To protect the secrets, this parameter setting is valid only in the +.Em /etc/gateways +file and only when that file is readable only by UID 0. .It Cm no_ag turns off aggregation of subnets in RIPv1 and RIPv2 responses. .It Cm no_super_ag @@ -612,6 +620,10 @@ 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. +.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. .El .Pp .Sh FILES diff --git a/sbin/routed/routed.h b/sbin/routed/routed.h index 3981d99..5885ac5 100644 --- a/sbin/routed/routed.h +++ b/sbin/routed/routed.h @@ -40,7 +40,7 @@ #ifdef __cplusplus extern "C" { #endif -#ident "$Revision: 1.10 $" +#ident "$Revision: 1.11 $" /* * Routing Information Protocol diff --git a/sbin/routed/rtquery/md5.c b/sbin/routed/rtquery/md5.c index a6fcf16..c24aa5a 100644 --- a/sbin/routed/rtquery/md5.c +++ b/sbin/routed/rtquery/md5.c @@ -22,7 +22,7 @@ * documentation and/or software. */ -#ident "$Revision: 1.2 $" +#ident "$Revision: 1.3 $" #ifdef sgi #include diff --git a/sbin/routed/rtquery/rtquery.c b/sbin/routed/rtquery/rtquery.c index 0579141..5417d06 100644 --- a/sbin/routed/rtquery/rtquery.c +++ b/sbin/routed/rtquery/rtquery.c @@ -40,7 +40,7 @@ static char sccsid[] = "@(#)query.c 8.1 (Berkeley) 6/5/93"; #elif defined(__NetBSD__) static char rcsid[] = "$NetBSD$"; #endif -#ident "$Revision: 1.9 $" +#ident "$Revision: 1.10 $" #include #include diff --git a/sbin/routed/table.c b/sbin/routed/table.c index bad1da4..d00279e 100644 --- a/sbin/routed/table.c +++ b/sbin/routed/table.c @@ -36,7 +36,7 @@ static char sccsid[] = "@(#)tables.c 8.1 (Berkeley) 6/5/93"; #elif defined(__NetBSD__) static char rcsid[] = "$NetBSD$"; #endif -#ident "$Revision: 1.26 $" +#ident "$Revision: 1.28 $" #include "defs.h" @@ -746,7 +746,7 @@ static struct khash { #define KS_DELETED 0x100 /* already deleted */ time_t k_keep; #define K_KEEP_LIM 30 - time_t k_redirect_time; + time_t k_redirect_time; /* when redirected route 1st seen */ } *khash_bins[KHASH_SIZE]; @@ -832,8 +832,7 @@ rtm_add(struct rt_msghdr *rtm, } else if (INFO_MASK(info) != 0) { mask = ntohl(S_ADDR(INFO_MASK(info))); } else { - msglog("ignore %s without mask", - rtm_type_name(rtm->rtm_type)); + msglog("ignore %s without mask", rtm_type_name(rtm->rtm_type)); return; } @@ -860,20 +859,32 @@ rtm_add(struct rt_msghdr *rtm, k->k_state |= KS_STATIC; if (0 != (rtm->rtm_flags & (RTF_DYNAMIC | RTF_MODIFIED))) { - if (supplier) { + if (INFO_AUTHOR(info) != 0 + && INFO_AUTHOR(info)->sa_family == AF_INET) + ifp = iflookup(S_ADDR(INFO_AUTHOR(info))); + else + ifp = 0; + if (supplier + && (ifp == 0 || !(ifp->int_state & IS_REDIRECT_OK))) { /* Routers are not supposed to listen to redirects, - * so delete it. + * so delete it if it came via an unknown interface + * or the interface does not have special permission. */ k->k_state &= ~KS_DYNAMIC; k->k_state |= KS_DELETE; LIM_SEC(need_kern, 0); - trace_act("mark redirected %s --> %s for deletion" - " since this is a router", + trace_act("mark for deletion redirected %s --> %s" + " via %s", addrname(k->k_dst, k->k_mask, 0), - naddr_ntoa(k->k_gate)); + naddr_ntoa(k->k_gate), + ifp ? ifp->int_name : "unknown interface"); } else { k->k_state |= KS_DYNAMIC; k->k_redirect_time = now.tv_sec; + trace_act("accept redirected %s --> %s via %s", + addrname(k->k_dst, k->k_mask, 0), + naddr_ntoa(k->k_gate), + ifp ? ifp->int_name : "unknown interface"); } return; } @@ -893,17 +904,10 @@ rtm_add(struct rt_msghdr *rtm, * Find the interface toward the gateway. */ ifp = iflookup(k->k_gate); - if (ifp == 0) { - /* if there is no known interface, - * maybe there is a new interface - */ - ifinit(); - ifp = iflookup(k->k_gate); - if (ifp == 0) - msglog("static route %s --> %s impossibly lacks ifp", - addrname(S_ADDR(INFO_DST(info)), mask, 0), - naddr_ntoa(k->k_gate)); - } + if (ifp == 0) + msglog("static route %s --> %s impossibly lacks ifp", + addrname(S_ADDR(INFO_DST(info)), mask, 0), + naddr_ntoa(k->k_gate)); kern_check_static(k, ifp); } @@ -917,8 +921,8 @@ rtm_lose(struct rt_msghdr *rtm, { if (INFO_GATE(info) == 0 || INFO_GATE(info)->sa_family != AF_INET) { - msglog("ignore %s without gateway", - rtm_type_name(rtm->rtm_type)); + trace_act("ignore %s without gateway", + rtm_type_name(rtm->rtm_type)); return; } diff --git a/sbin/routed/trace.c b/sbin/routed/trace.c index dabf4d1..a171ce8 100644 --- a/sbin/routed/trace.c +++ b/sbin/routed/trace.c @@ -36,7 +36,7 @@ static char sccsid[] = "@(#)trace.c 8.1 (Berkeley) 6/5/93"; #elif defined(__NetBSD__) static char rcsid[] = "$NetBSD$"; #endif -#ident "$Revision: 1.14 $" +#ident "$Revision: 1.16 $" #define RIPCMDS #include "defs.h" @@ -53,11 +53,12 @@ static char rcsid[] = "$NetBSD$"; #define NRECORDS 50 /* size of circular trace buffer */ -u_int tracelevel, new_tracelevel; +int tracelevel, new_tracelevel; FILE *ftrace = stdout; /* output trace file */ -static char *tracelevel_pat = "%s\n"; - -char savetracename[MAXPATHLEN+1]; +static char *sigtrace_pat = "%s\n"; +static char savetracename[MAXPATHLEN+1]; +char inittracename[MAXPATHLEN+1]; +int file_trace; /* 1=tracing to file, not stdout */ static void trace_dump(void); @@ -162,15 +163,15 @@ ts(time_t secs) { * This assumes that 'now' is update once for each event, and * that at least now.tv_usec changes. */ +static struct timeval lastlog_time; + void lastlog(void) { - static struct timeval last; - - if (last.tv_sec != now.tv_sec - || last.tv_usec != now.tv_usec) { + if (lastlog_time.tv_sec != now.tv_sec + || lastlog_time.tv_usec != now.tv_usec) { (void)fprintf(ftrace, "-- %s --\n", ts(now.tv_sec)); - last = now; + lastlog_time = now; } } @@ -198,15 +199,17 @@ trace_close(void) fflush(stdout); fflush(stderr); - if (ftrace != 0 - && savetracename[0] != '\0') { + if (ftrace != 0 && file_trace) { + 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); (void)close(fd); - fclose(ftrace); - ftrace = 0; } + lastlog_time.tv_sec = 0; } @@ -231,7 +234,6 @@ trace_off(char *p, ...) lastlog(); va_start(args, p); vfprintf(ftrace, p, args); - fflush(ftrace); } trace_close(); @@ -239,33 +241,101 @@ trace_off(char *p, ...) } +/* log a change in tracing + */ void -trace_on(char *filename, - int initial) /* 1=setting from command line */ +tracelevel_msg(char *pat, + int dump) /* -1=no dump, 0=default, 1=force */ +{ + static char *off_msgs[MAX_TRACELEVEL] = { + "Tracing actions stopped", + "Tracing packets stopped", + "Tracing packet contents stopped", + "Tracing kernel changes stopped", + }; + static char *on_msgs[MAX_TRACELEVEL] = { + "Tracing actions started", + "Tracing packets started", + "Tracing packet contents started", + "Tracing kernel changes started", + }; + u_int old_tracelevel = tracelevel; + + + if (new_tracelevel < 0) + new_tracelevel = 0; + else if (new_tracelevel > MAX_TRACELEVEL) + new_tracelevel = MAX_TRACELEVEL; + + if (new_tracelevel < tracelevel) { + if (new_tracelevel <= 0) { + trace_off(pat, off_msgs[0]); + } else do { + tmsg(pat, off_msgs[tracelevel]); + } + while (--tracelevel != new_tracelevel); + + } else if (new_tracelevel > tracelevel) { + do { + tmsg(pat, on_msgs[tracelevel++]); + } while (tracelevel != new_tracelevel); + } + + if (dump > 0 + || (dump == 0 && old_tracelevel == 0 && tracelevel != 0)) + trace_dump(); +} + + +void +set_tracefile(char *filename, + char *pat, + int dump) /* -1=no dump, 0=default, 1=force */ { struct stat stbuf; FILE *n_ftrace; - u_int old_tracelevel; + char *fn; - /* Given a null filename when tracing is already on, increase the - * debugging level and re-open the file in case it has been unlinked. + /* Allow a null filename to increase the level if the trace file + * is already open or if coming from a trusted source, such as + * a signal or the command line. */ - if (filename[0] == '\0') { - if (tracelevel != 0) { - new_tracelevel++; - tracelevel_pat = "trace command: %s\n"; - } else if (savetracename[0] == '\0') { - msglog("missing trace file name"); - return; + if (filename == 0 || filename[0] == '\0') { + filename = 0; + if (ftrace == 0) { + if (inittracename[0] == '\0') { + msglog("missing trace file name"); + return; + } + fn = inittracename; + } else { + fn = 0; } - filename = savetracename; } else if (!strcmp(filename,"dump/../table")) { trace_dump(); return; } else { + /* Allow the file specified with "-T file" to be reopened, + * but require all other names specified over the net to + * match the official path. The path can specify a directory + * in which the file is to be created. + */ + if (strcmp(filename, inittracename) +#ifdef _PATH_TRACE + && (strncmp(filename, _PATH_TRACE, sizeof(_PATH_TRACE)-1) + || strstr(filename,"../") + || 0 > stat(_PATH_TRACE, &stbuf)) +#endif + ) { + msglog("wrong trace file \"%s\"", filename); + return; + } + + /* If the new tracefile exists, it must be a regular file. + */ if (stat(filename, &stbuf) >= 0 && (stbuf.st_mode & S_IFMT) != S_IFREG) { msglog("wrong type (%#x) of trace file \"%s\"", @@ -273,44 +343,37 @@ trace_on(char *filename, return; } - if (!initial -#ifdef _PATH_TRACE - && (strncmp(filename, _PATH_TRACE, sizeof(_PATH_TRACE)-1) - || strstr(filename,"../") - || 0 > stat(_PATH_TRACE, &stbuf)) -#endif - && strcmp(filename, savetracename)) { - msglog("wrong directory for trace file \"%s\"", - filename); + fn = filename; + } + + if (fn != 0) { + n_ftrace = fopen(fn, "a"); + if (n_ftrace == 0) { + msglog("failed to open trace file \"%s\" %s", + fn, strerror(errno)); + if (fn == inittracename) + inittracename[0] = '\0'; return; } - } - n_ftrace = fopen(filename, "a"); - if (n_ftrace == 0) { - msglog("failed to open trace file \"%s\" %s", - filename, strerror(errno)); - return; - } + tmsg("switch to trace file %s\n", fn); - tmsg("switch to trace file %s\n", filename); - trace_close(); - if (filename != savetracename) - strncpy(savetracename, filename, sizeof(savetracename)-1); - ftrace = n_ftrace; + file_trace = 1; + trace_close(); - fflush(stdout); - fflush(stderr); - dup2(fileno(ftrace), STDOUT_FILENO); - dup2(fileno(ftrace), STDERR_FILENO); + if (fn != savetracename) + strncpy(savetracename, fn, sizeof(savetracename)-1); + ftrace = n_ftrace; - if (new_tracelevel == 0) - new_tracelevel = 1; - old_tracelevel = tracelevel; - set_tracelevel(initial); + fflush(stdout); + fflush(stderr); + dup2(fileno(ftrace), STDOUT_FILENO); + dup2(fileno(ftrace), STDERR_FILENO); + } - if (!initial && old_tracelevel == 0) - trace_dump(); + if (new_tracelevel == 0 || filename == 0) + new_tracelevel++; + tracelevel_msg(pat, dump != 0 ? dump : (filename != 0)); } @@ -319,7 +382,7 @@ void sigtrace_on(int s) { new_tracelevel++; - tracelevel_pat = "SIGUSR1: %s\n"; + sigtrace_pat = "SIGUSR1: %s\n"; } @@ -328,59 +391,33 @@ void sigtrace_off(int s) { new_tracelevel--; - tracelevel_pat = "SIGUSR2: %s\n"; + sigtrace_pat = "SIGUSR2: %s\n"; } -/* Move to next higher level of tracing when -t option processed or - * SIGUSR1 is received. Successive levels are: - * actions - * actions + packets - * actions + packets + contents +/* Set tracing after a signal. */ void -set_tracelevel(int initial) +set_tracelevel(void) { - static char *off_msgs[MAX_TRACELEVEL] = { - "Tracing actions stopped", - "Tracing packets stopped", - "Tracing packet contents stopped", - "Tracing kernel changes stopped", - }; - static char *on_msgs[MAX_TRACELEVEL] = { - "Tracing actions started", - "Tracing packets started", - "Tracing packet contents started", - "Tracing kernel changes started", - }; - - - if (new_tracelevel > MAX_TRACELEVEL) { - new_tracelevel = MAX_TRACELEVEL; - if (new_tracelevel == tracelevel) { - tmsg(tracelevel_pat, on_msgs[tracelevel-1]); - return; - } - } + if (new_tracelevel == tracelevel) + return; - for (; new_tracelevel != tracelevel; tracelevel++) { - if (new_tracelevel < tracelevel) { - if (--tracelevel == 0) - trace_off(tracelevel_pat, off_msgs[0]); - else - tmsg(tracelevel_pat, off_msgs[tracelevel]); + /* If tracing entirely off, and there was no tracefile specified + * on the command line, then leave it off. + */ + if (new_tracelevel > tracelevel && ftrace == 0) { + if (savetracename[0] != '\0') { + set_tracefile(savetracename,sigtrace_pat,0); + } else if (inittracename[0] != '\0') { + set_tracefile(inittracename,sigtrace_pat,0); } else { - if (ftrace == 0) { - if (savetracename[0] != '\0') - trace_on(savetracename, 1); - else - ftrace = stdout; - } - if (!initial || tracelevel+1 == new_tracelevel) - tmsg(tracelevel_pat, on_msgs[tracelevel]); + new_tracelevel = 0; + return; } + } else { + tracelevel_msg(sigtrace_pat, 0); } - tracelevel_pat = "%s\n"; } @@ -454,6 +491,7 @@ static struct bits is_bits[] = { { IS_BROKE, IS_SICK, "BROKEN" }, { IS_SICK, 0, "SICK" }, { IS_DUP, 0, "DUPLICATE" }, + { IS_REDIRECT_OK, 0, "REDIRECT_OK" }, { IS_NEED_NET_SYN, 0, "" }, { IS_NO_AG, IS_NO_SUPER_AG, "NO_AG" }, { IS_NO_SUPER_AG, 0, "NO_SUPER_AG" }, @@ -548,6 +586,32 @@ trace_pair(naddr dst, } +static void +print_rts(struct rt_spare *rts, + int force_metric, /* -1=suppress, 0=default */ + int force_ifp, /* -1=suppress, 0=default */ + int force_router, /* -1=suppress, 0=default, 1=display */ + int force_tag, /* -1=suppress, 0=default, 1=display */ + int force_time) /* 0=suppress, 1=display */ +{ + if (force_metric >= 0) + (void)fprintf(ftrace, "metric=%-2d ", rts->rts_metric); + if (force_ifp >= 0) + (void)fprintf(ftrace, "%s ", (rts->rts_ifp == 0 ? + "if?" : rts->rts_ifp->int_name)); + if (force_router > 0 + || (force_router == 0 && rts->rts_router != rts->rts_gate)) + (void)fprintf(ftrace, "router=%s ", + naddr_ntoa(rts->rts_router)); + if (force_time > 0) + (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 trace_if(char *act, struct interface *ifp) @@ -584,13 +648,22 @@ trace_upslot(struct rt_entry *rt, u_short tag, time_t new_time) { + 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) return; + new.rts_ifp = ifp; + new.rts_gate = gate; + new.rts_router = router; + new.rts_metric = metric; + new.rts_time = new_time; + new.rts_tag = tag; lastlog(); if (rts->rts_gate != RIP_DEFAULT) { @@ -598,45 +671,32 @@ trace_upslot(struct rt_entry *rt, rts - rt->rt_spares, trace_pair(rt->rt_dst, rt->rt_mask, naddr_ntoa(rts->rts_gate))); - if (rts->rts_gate != rts->rts_gate) - (void)fprintf(ftrace, "router=%s ", - naddr_ntoa(rts->rts_gate)); - if (rts->rts_tag != 0) - (void)fprintf(ftrace, "tag=%#x ", ntohs(rts->rts_tag)); - (void)fprintf(ftrace, "metric=%-2d ", rts->rts_metric); - if (rts->rts_ifp != 0) - (void)fprintf(ftrace, "%s ", - rts->rts_ifp->int_name); - (void)fprintf(ftrace, "%s\n", ts(rts->rts_time)); + print_rts(rts, 0,0, + rts->rts_gate != gate, + rts->rts_tag != tag, + rts != rt->rt_spares || AGE_RT(rt->rt_state, + rt->rt_ifp)); - (void)fprintf(ftrace, " %19s%-16s ", - "", + (void)fprintf(ftrace, "\n %19s%-16s ", "", gate != rts->rts_gate ? naddr_ntoa(gate) : ""); - if (gate != router) - (void)fprintf(ftrace,"router=%s ",naddr_ntoa(router)); - if (tag != rts->rts_tag) - (void)fprintf(ftrace, "tag=%#x ", ntohs(tag)); - if (metric != rts->rts_metric) - (void)fprintf(ftrace, "metric=%-2d ", metric); - if (ifp != rts->rts_ifp && ifp != 0 ) - (void)fprintf(ftrace, "%s ", ifp->int_name); - (void)fprintf(ftrace, "%s\n", - new_time != rts->rts_time ? ts(new_time) : ""); + print_rts(&new, + -(metric == rts->rts_metric), + -(ifp == rts->rts_ifp), + 0, + rts->rts_tag != tag, + new_time != rts->rts_time && (rts != rt->rt_spares + || AGE_RT(rt->rt_state, + ifp))); } else { (void)fprintf(ftrace, "Add #%d %-35s ", rts - rt->rt_spares, trace_pair(rt->rt_dst, rt->rt_mask, naddr_ntoa(gate))); - if (gate != router) - (void)fprintf(ftrace, "router=%s ", naddr_ntoa(gate)); - if (tag != 0) - (void)fprintf(ftrace, "tag=%#x ", ntohs(tag)); - (void)fprintf(ftrace, "metric=%-2d ", metric); - if (ifp != 0) - (void)fprintf(ftrace, "%s ", ifp->int_name); - (void)fprintf(ftrace, "%s\n", ts(new_time)); + print_rts(&new, 0,0,0,0, + rts != rt->rt_spares || AGE_RT(rt->rt_state,ifp)); } + (void)fputc('\n',ftrace); } @@ -701,6 +761,8 @@ trace_change(struct rt_entry *rt, time_t new_time, char *label) { + struct rt_spare new; + if (ftrace == 0) return; @@ -710,67 +772,51 @@ trace_change(struct rt_entry *rt, && rt->rt_state == state && rt->rt_tag == tag) 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 metric=%-2d ", + (void)fprintf(ftrace, "%s %-35s ", label, trace_pair(rt->rt_dst, rt->rt_mask, - naddr_ntoa(rt->rt_gate)), - rt->rt_metric); - if (rt->rt_router != rt->rt_gate) - (void)fprintf(ftrace, "router=%s ", - naddr_ntoa(rt->rt_router)); - if (rt->rt_tag != 0) - (void)fprintf(ftrace, "tag=%#x ", ntohs(rt->rt_tag)); + naddr_ntoa(rt->rt_gate))); + print_rts(rt->rt_spares, + 0,0,0,0, AGE_RT(rt->rt_state, rt->rt_ifp)); trace_bits(rs_bits, rt->rt_state, rt->rt_state != state); - (void)fprintf(ftrace, "%s ", - rt->rt_ifp == 0 ? "?" : rt->rt_ifp->int_name); - (void)fprintf(ftrace, "%s\n", - AGE_RT(rt->rt_state, rt->rt_ifp) ? ts(rt->rt_time) : ""); - (void)fprintf(ftrace, "%*s %19s%-16s ", + (void)fprintf(ftrace, "\n%*s %19s%-16s ", strlen(label), "", "", rt->rt_gate != gate ? naddr_ntoa(gate) : ""); - if (rt->rt_metric != metric) - (void)fprintf(ftrace, "metric=%-2d ", metric); - if (router != gate) - (void)fprintf(ftrace, "router=%s ", naddr_ntoa(router)); - if (rt->rt_tag != tag) - (void)fprintf(ftrace, "tag=%#x ", ntohs(tag)); + print_rts(&new, + -(metric == rt->rt_metric), + -(ifp == rt->rt_ifp), + 0, + rt->rt_tag != tag, + rt->rt_time != new_time && AGE_RT(rt->rt_state,ifp)); if (rt->rt_state != state) trace_bits(rs_bits, state, 1); - if (rt->rt_ifp != ifp) - (void)fprintf(ftrace, "%s ", - ifp != 0 ? ifp->int_name : "?"); - (void)fprintf(ftrace, "%s\n", - ((rt->rt_time == new_time || !AGE_RT(rt->rt_state, ifp)) - ? "" : ts(new_time))); + (void)fputc('\n',ftrace); } void trace_add_del(char * action, struct rt_entry *rt) { - u_int state = rt->rt_state; - if (ftrace == 0) return; lastlog(); - (void)fprintf(ftrace, "%s %-35s metric=%-2d ", + (void)fprintf(ftrace, "%s %-35s ", action, trace_pair(rt->rt_dst, rt->rt_mask, - naddr_ntoa(rt->rt_gate)), - rt->rt_metric); - if (rt->rt_router != rt->rt_gate) - (void)fprintf(ftrace, "router=%s ", - naddr_ntoa(rt->rt_router)); - if (rt->rt_tag != 0) - (void)fprintf(ftrace, "tag=%#x ", ntohs(rt->rt_tag)); - trace_bits(rs_bits, state, 0); - (void)fprintf(ftrace, "%s ", - rt->rt_ifp != 0 ? rt->rt_ifp->int_name : "?"); - (void)fprintf(ftrace, "%s\n", ts(rt->rt_time)); + naddr_ntoa(rt->rt_gate))); + print_rts(rt->rt_spares, 0,0,0,0,AGE_RT(rt->rt_state,rt->rt_ifp)); + trace_bits(rs_bits, rt->rt_state, 0); + (void)fputc('\n',ftrace); } @@ -781,42 +827,24 @@ walk_trace(struct radix_node *rn, { #define RT ((struct rt_entry *)rn) struct rt_spare *rts; - int i, age; + int i, age = AGE_RT(RT->rt_state, RT->rt_ifp); - (void)fprintf(ftrace, " %-35s metric=%-2d ", - trace_pair(RT->rt_dst, RT->rt_mask, - naddr_ntoa(RT->rt_gate)), - RT->rt_metric); - if (RT->rt_router != RT->rt_gate) - (void)fprintf(ftrace, "router=%s ", - naddr_ntoa(RT->rt_router)); - if (RT->rt_tag != 0) - (void)fprintf(ftrace, "tag=%#x ", - ntohs(RT->rt_tag)); + (void)fprintf(ftrace, " %-35s ", trace_pair(RT->rt_dst, RT->rt_mask, + naddr_ntoa(RT->rt_gate))); + print_rts(&RT->rt_spares[0], 0,0,0,0,age); trace_bits(rs_bits, RT->rt_state, 0); - (void)fprintf(ftrace, "%s ", - RT->rt_ifp == 0 ? "?" : RT->rt_ifp->int_name); - age = AGE_RT(RT->rt_state, RT->rt_ifp); - if (age) - (void)fprintf(ftrace, "%s", ts(RT->rt_time)); + if (RT->rt_poison_time >= now_garbage + && RT->rt_poison_metric < RT->rt_metric) + (void)fprintf(ftrace, "pm=%d@%s", + RT->rt_poison_metric, + ts(RT->rt_poison_time)); rts = &RT->rt_spares[1]; for (i = 1; i < NUM_SPARES; i++, rts++) { - if (rts->rts_metric != HOPCNT_INFINITY) { - (void)fprintf(ftrace,"\n #%d%15s%-16s metric=%-2d ", - i, "", naddr_ntoa(rts->rts_gate), - rts->rts_metric); - if (rts->rts_router != rts->rts_gate) - (void)fprintf(ftrace, "router=%s ", - naddr_ntoa(rts->rts_router)); - if (rts->rts_tag != 0) - (void)fprintf(ftrace, "tag=%#x ", - ntohs(rts->rts_tag)); - (void)fprintf(ftrace, "%s ", - (rts->rts_ifp == 0 - ? "?" : rts->rts_ifp->int_name)); - if (age) - (void)fprintf(ftrace, "%s", ts(rts->rts_time)); + if (rts->rts_gate != RIP_DEFAULT) { + (void)fprintf(ftrace,"\n #%d%15s%-16s ", + i, "", naddr_ntoa(rts->rts_gate)); + print_rts(rts, 0,0,0,0,1); } } (void)fputc('\n',ftrace); @@ -834,6 +862,7 @@ trace_dump(void) return; lastlog(); + (void)fputs("current daemon state:\n", ftrace); for (ifp = ifnet; ifp != 0; ifp = ifp->int_next) trace_if("", ifp); (void)rn_walktree(rhead, walk_trace, 0); @@ -976,7 +1005,8 @@ trace_rip(char *dir1, char *dir2, break; case RIPCMD_TRACEON: - fprintf(ftrace, "\tfile=%*s\n", size-4, msg->rip_tracefile); + fprintf(ftrace, "\tfile=\"%.*s\"\n", size-4, + msg->rip_tracefile); break; case RIPCMD_TRACEOFF: -- cgit v1.1