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 <vjs@mica.denver.sgi.com>
This commit is contained in:
Garrett Wollman 1996-12-11 20:59:33 +00:00
parent c9c588ef9b
commit 71965874ee
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/vendor/SGI/dist_v_2_21/; revision=20339
svn path=/vendor/SGI/vjs_961211/; revision=20341; tag=vendor/SGI/vjs_961211
14 changed files with 697 additions and 526 deletions

View File

@ -36,7 +36,7 @@
*/ */
#ifndef __NetBSD__ #ifndef __NetBSD__
#ident "$Revision: 1.17 $" #ident "$Revision: 1.19 $"
#endif #endif
/* Definitions for RIPv2 routing process. /* Definitions for RIPv2 routing process.
@ -123,7 +123,8 @@
*/ */
/* #define MCAST_PPP_BUG */ /* #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 */ #define EPOCH NEVER /* bias time by this to avoid <0 */
/* Scan the kernel regularly to see if any interfaces have appeared or been /* Scan the kernel regularly to see if any interfaces have appeared or been
@ -292,15 +293,13 @@ struct interface {
#endif #endif
time_t ts; /* timestamp on network stats */ time_t ts; /* timestamp on network stats */
} int_data; } int_data;
# define MAX_AUTH_KEYS 5
struct auth { /* authentication info */ struct auth { /* authentication info */
u_char type; u_char type;
# define MAX_AUTH_KEYS 3 u_char key[RIP_AUTH_PW_LEN];
struct auth_key { u_char keyid;
u_char key[RIP_AUTH_PW_LEN]; time_t start, end;
u_char keyid; } int_auth[MAX_AUTH_KEYS];
time_t start, end;
} keys[MAX_AUTH_KEYS];
} int_auth;
int int_rdisc_pref; /* advertised rdisc preference */ int int_rdisc_pref; /* advertised rdisc preference */
int int_rdisc_int; /* MaxAdvertiseInterval */ int int_rdisc_int; /* MaxAdvertiseInterval */
int int_rdisc_cnt; int int_rdisc_cnt;
@ -317,10 +316,10 @@ struct interface {
#define IS_ALL_HOSTS 0x0000040 /* in INADDR_ALLHOSTS_GROUP */ #define IS_ALL_HOSTS 0x0000040 /* in INADDR_ALLHOSTS_GROUP */
#define IS_ALL_ROUTERS 0x0000080 /* in INADDR_ALLROUTERS_GROUP */ #define IS_ALL_ROUTERS 0x0000080 /* in INADDR_ALLROUTERS_GROUP */
#define IS_DISTRUST 0x0000100 /* ignore untrusted routers */ #define IS_DISTRUST 0x0000100 /* ignore untrusted routers */
#define IS_BROKE 0x0000200 /* seems to be broken */ #define IS_REDIRECT_OK 0x0000200 /* accept ICMP redirects */
#define IS_SICK 0x0000400 /* seems to be broken */ #define IS_BROKE 0x0000400 /* seems to be broken */
#define IS_DUP 0x0000800 /* has a duplicate address */ #define IS_SICK 0x0000800 /* seems to be broken */
/* 0x0001000 spare */ #define IS_DUP 0x0001000 /* has a duplicate address */
#define IS_NEED_NET_SYN 0x0002000 /* need RS_NET_SYN route */ #define IS_NEED_NET_SYN 0x0002000 /* need RS_NET_SYN route */
#define IS_NO_AG 0x0004000 /* do not aggregate subnets */ #define IS_NO_AG 0x0004000 /* do not aggregate subnets */
#define IS_NO_SUPER_AG 0x0008000 /* do not aggregate networks */ #define IS_NO_SUPER_AG 0x0008000 /* do not aggregate networks */
@ -399,7 +398,7 @@ extern struct parm {
u_int parm_int_state; u_int parm_int_state;
int parm_rdisc_pref; int parm_rdisc_pref;
int parm_rdisc_int; int parm_rdisc_int;
struct auth parm_auth; struct auth parm_auth[MAX_AUTH_KEYS];
} *parms; } *parms;
/* authority for internal networks */ /* 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 struct timeval need_kern; /* need to update kernel table */
extern int update_seqno; /* a route has changed */ extern int update_seqno; /* a route has changed */
extern u_int tracelevel, new_tracelevel; extern int tracelevel, new_tracelevel;
#define MAX_TRACELEVEL 4 #define MAX_TRACELEVEL 4
#define TRACEKERNEL (tracelevel >= 4) /* log kernel changes */ #define TRACEKERNEL (tracelevel >= 4) /* log kernel changes */
#define TRACECONTENTS (tracelevel >= 3) /* display packet contents */ #define TRACECONTENTS (tracelevel >= 3) /* display packet contents */
#define TRACEPACKETS (tracelevel >= 2) /* note packets */ #define TRACEPACKETS (tracelevel >= 2) /* note packets */
#define TRACEACTIONS (tracelevel != 0) #define TRACEACTIONS (tracelevel != 0)
extern FILE *ftrace; /* output trace file */ extern FILE *ftrace; /* output trace file */
extern char inittracename[MAXPATHLEN+1];
extern struct radix_node_head *rhead; extern struct radix_node_head *rhead;
@ -499,7 +499,7 @@ extern void rip_on(struct interface *);
extern void bufinit(void); extern void bufinit(void);
extern int output(enum output_type, struct sockaddr_in *, extern int output(enum output_type, struct sockaddr_in *,
struct interface *, struct rip *, int); struct interface *, struct rip *, int);
extern void 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_query(void);
extern void rip_bcast(int); extern void rip_bcast(int);
extern void supply(struct sockaddr_in *, struct interface *, extern void supply(struct sockaddr_in *, struct interface *,
@ -507,8 +507,12 @@ extern void supply(struct sockaddr_in *, struct interface *,
extern void msglog(char *, ...); extern void msglog(char *, ...);
struct msg_limit { struct msg_limit {
time_t reuse;
struct msg_sub {
naddr addr; naddr addr;
time_t until; time_t until;
# define MSG_SUBJECT_N 8
} subs[MSG_SUBJECT_N];
}; };
extern void msglim(struct msg_limit *, naddr, char *, ...); extern void msglim(struct msg_limit *, naddr, char *, ...);
#define LOGERR(msg) msglog(msg ": %s", strerror(errno)) #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 getnet(char *, naddr *, naddr *);
extern int gethost(char *, naddr *); extern int gethost(char *, naddr *);
extern void gwkludge(void); extern void gwkludge(void);
extern char *parse_parms(char *); extern char *parse_parms(char *, int);
extern char *check_parms(struct parm *); extern char *check_parms(struct parm *);
extern void get_parms(struct interface *); extern void get_parms(struct interface *);
extern void lastlog(void); extern void lastlog(void);
extern void trace_on(char *, int); extern void set_tracefile(char *, char *, int);
extern void tracelevel_msg(char *, int);
extern void trace_off(char*, ...); extern void trace_off(char*, ...);
extern void set_tracelevel(void);
extern void trace_flush(void); extern void trace_flush(void);
extern void set_tracelevel(int);
extern void trace_kernel(char *, ...); extern void trace_kernel(char *, ...);
extern void trace_act(char *, ...); extern void trace_act(char *, ...);
extern void trace_pkt(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 *ifwithindex(u_short);
extern struct interface *iflookup(naddr); extern struct interface *iflookup(naddr);
extern struct auth_key *find_auth(struct interface *); extern struct auth *find_auth(struct interface *);
extern void end_md5_auth(struct ws_buf *, struct auth_key *); extern void end_md5_auth(struct ws_buf *, struct auth *);
#define MD5_DIGEST_LEN 16 #define MD5_DIGEST_LEN 16
typedef struct { typedef struct {

View File

@ -36,7 +36,7 @@ static char sccsid[] = "@(#)if.c 8.1 (Berkeley) 6/5/93";
#elif defined(__NetBSD__) #elif defined(__NetBSD__)
static char rcsid[] = "$NetBSD$"; static char rcsid[] = "$NetBSD$";
#endif #endif
#ident "$Revision: 1.18 $" #ident "$Revision: 1.21 $"
#include "defs.h" #include "defs.h"
#include "pathnames.h" #include "pathnames.h"
@ -208,42 +208,54 @@ ifwithindex(u_short index)
/* Find an interface from which the specified address /* Find an interface from which the specified address
* should have come from. Used for figuring out which * 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 * struct interface *
iflookup(naddr addr) iflookup(naddr addr)
{ {
struct interface *ifp, *maybe; struct interface *ifp, *maybe;
static struct timeval retried;
maybe = 0; maybe = 0;
for (ifp = ifnet; ifp; ifp = ifp->int_next) { for (;;) {
if (ifp->int_if_flags & IFF_POINTOPOINT) { for (ifp = ifnet; ifp; ifp = ifp->int_next) {
/* finished with a match */ if (ifp->int_if_flags & IFF_POINTOPOINT) {
if (ifp->int_dstaddr == addr) /* finished with a match */
return ifp; if (ifp->int_dstaddr == addr)
return ifp;
} else { } else {
/* finished with an exact match */ /* finished with an exact match */
if (ifp->int_addr == addr) if (ifp->int_addr == addr)
return ifp; return ifp;
/* Look for the longest approximate match. /* Look for the longest approximate match.
*/ */
if (on_net(addr, ifp->int_net, ifp->int_mask) if (on_net(addr, ifp->int_net, ifp->int_mask)
&& (maybe == 0 && (maybe == 0
|| ifp->int_mask > maybe->int_mask)) || ifp->int_mask > maybe->int_mask))
maybe = ifp; 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. /* Return the classical netmask for an IP address.
*/ */
naddr naddr /* host byte order */
std_mask(naddr addr) /* in network order */ std_mask(naddr addr) /* network byte order */
{ {
NTOHL(addr); /* was a host, not a network */ NTOHL(addr); /* was a host, not a network */
@ -338,9 +350,9 @@ check_dst(naddr addr)
/* See a new interface duplicates an existing interface. /* See a new interface duplicates an existing interface.
*/ */
struct interface * struct interface *
check_dup(naddr addr, check_dup(naddr addr, /* IP address, so network byte order */
naddr dstaddr, naddr dstaddr, /* ditto */
naddr mask, naddr mask, /* mask, so host byte order */
int if_flags) int if_flags)
{ {
struct interface *ifp; struct interface *ifp;
@ -691,6 +703,7 @@ ifinit(void)
ifs0.int_index = ifm->ifm_index; ifs0.int_index = ifm->ifm_index;
ifs0.int_if_flags = ifm->ifm_flags; ifs0.int_if_flags = ifm->ifm_flags;
ifs0.int_state = IS_CHECKED; ifs0.int_state = IS_CHECKED;
ifs0.int_query_time = NEVER;
ifs0.int_act_time = now.tv_sec; ifs0.int_act_time = now.tv_sec;
ifs0.int_data.ts = now.tv_sec; ifs0.int_data.ts = now.tv_sec;
ifs0.int_data.ipackets = ifm->ifm_data.ifi_ipackets; ifs0.int_data.ipackets = ifm->ifm_data.ifi_ipackets;
@ -1006,10 +1019,20 @@ ifinit(void)
if (ifp != 0) { if (ifp != 0) {
if (!(prev_complaints & COMP_DUP)) { if (!(prev_complaints & COMP_DUP)) {
complaints |= COMP_DUP; complaints |= COMP_DUP;
msglog("%s is duplicated by %s at %s to %s", msglog("%s (%s%s%s) is duplicated by"
ifs.int_name, ifp->int_name, " %s (%s%s%s)",
naddr_ntoa(ifp->int_addr), ifs.int_name,
naddr_ntoa(ifp->int_dstaddr)); 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; ifp->int_state |= IS_DUP;
continue; continue;
@ -1263,7 +1286,7 @@ addrouteforif(struct interface *ifp)
* it must be reachable using our physical interfaces * it must be reachable using our physical interfaces
*/ */
if ((ifp->int_state & IS_REMOTE) if ((ifp->int_state & IS_REMOTE)
&& !(ifp->int_state && IS_EXTERNAL) && !(ifp->int_state & IS_EXTERNAL)
&& !check_remote(ifp)) && !check_remote(ifp))
return 0; return 0;

View File

@ -36,7 +36,7 @@ static char sccsid[] = "@(#)input.c 8.1 (Berkeley) 6/5/93";
#elif defined(__NetBSD__) #elif defined(__NetBSD__)
static char rcsid[] = "$NetBSD$"; static char rcsid[] = "$NetBSD$";
#endif #endif
#ident "$Revision: 1.17 $" #ident "$Revision: 1.19 $"
#include "defs.h" #include "defs.h"
@ -54,16 +54,20 @@ void
read_rip(int sock, read_rip(int sock,
struct interface *sifp) struct interface *sifp)
{ {
static struct msg_limit bad_name;
struct sockaddr_in from; struct sockaddr_in from;
struct interface *aifp; struct interface *aifp;
int fromlen, cc; int fromlen, cc;
struct {
#ifdef USE_PASSIFNAME #ifdef USE_PASSIFNAME
static struct msg_limit bad_name;
struct {
char ifname[IFNAMSIZ]; char ifname[IFNAMSIZ];
#endif
union pkt_buf pbuf; union pkt_buf pbuf;
} inbuf; } inbuf;
#else
struct {
union pkt_buf pbuf;
} inbuf;
#endif
for (;;) { for (;;) {
@ -148,7 +152,7 @@ input(struct sockaddr_in *from, /* received from this IP address */
struct netinfo *n, *lim; struct netinfo *n, *lim;
struct interface *ifp1; struct interface *ifp1;
naddr gate, mask, v1_mask, dst, ddst_h; naddr gate, mask, v1_mask, dst, ddst_h;
struct auth_key *ap; struct auth *ap;
int i; int i;
/* Notice when we hear from a remote gateway /* 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 * do not disclose our secret unless the other guy
* already knows it. * already knows it.
*/ */
if (aifp != 0 ap = find_auth(aifp);
&& aifp->int_auth.type == RIP_AUTH_PW if (aifp == 0 && ap->type == RIP_AUTH_PW
&& n->n_family == RIP_AF_AUTH
&& !ck_passwd(aifp,rip,lim,FROM_NADDR,&use_auth)) && !ck_passwd(aifp,rip,lim,FROM_NADDR,&use_auth))
ap = 0; ap = 0;
else
ap = find_auth(aifp);
} else { } else {
v12buf.buf->rip_vers = RIPv1; v12buf.buf->rip_vers = RIPv1;
ap = 0; ap = 0;
} }
clr_ws_buf(&v12buf, ap, aifp); clr_ws_buf(&v12buf, ap);
do { do {
NTOHL(n->n_metric); NTOHL(n->n_metric);
@ -397,7 +400,7 @@ input(struct sockaddr_in *from, /* received from this IP address */
/* Send the answer about specific routes. /* 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); end_md5_auth(&v12buf, ap);
if (from->sin_port != htons(RIP_PORT)) { 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) { if (rip->rip_cmd == RIPCMD_TRACEON) {
rip->rip_tracefile[cc-4] = '\0'; 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 { } else {
trace_off("tracing turned off by %s\n", trace_off("tracing turned off by %s\n",
naddr_ntoa(FROM_NADDR)); 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. /* If the interface cares, ignore bad routers.
* Trace but do not log this problem because when it * Trace but do not log this problem, because where it
* happens it happens a lot. * happens, it happens frequently.
*/ */
if (aifp->int_state & IS_DISTRUST) { if (aifp->int_state & IS_DISTRUST) {
struct tgate *tg = tgates; 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. /* Authenticate the packet if we have a secret.
* If we do not, ignore the silliness in RFC 1723 * If we do not have any secrets, ignore the error in
* and accept it regardless. * RFC 1723 and accept it regardless.
*/ */
if (aifp->int_auth.type != RIP_AUTH_NONE if (aifp->int_auth[0].type != RIP_AUTH_NONE
&& rip->rip_vers != RIPv1) { && rip->rip_vers != RIPv1
if (!ck_passwd(aifp,rip,lim,FROM_NADDR,&use_auth)) && !ck_passwd(aifp,rip,lim,FROM_NADDR,&use_auth))
return; return;
}
do { do {
if (n->n_family == RIP_AF_AUTH) if (n->n_family == RIP_AF_AUTH)
@ -860,9 +863,8 @@ ck_passwd(struct interface *aifp,
struct msg_limit *use_authp) struct msg_limit *use_authp)
{ {
# define NA (rip->rip_auths) # define NA (rip->rip_auths)
# define DAY (24*60*60)
struct netauth *na2; struct netauth *na2;
struct auth_key *akp = aifp->int_auth.keys; struct auth *ap;
MD5_CTX md5_ctx; MD5_CTX md5_ctx;
u_char hash[RIP_AUTH_PW_LEN]; u_char hash[RIP_AUTH_PW_LEN];
int i; int i;
@ -874,35 +876,24 @@ ck_passwd(struct interface *aifp,
return 0; return 0;
} }
if (NA->a_type != aifp->int_auth.type) { /* accept any current (+/- 24 hours) password
msglim(use_authp, from, "wrong type of password from %s", */
naddr_ntoa(from)); for (ap = aifp->int_auth, i = 0; i < MAX_AUTH_KEYS; i++, ap++) {
return 0; 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 (NA->a_type == RIP_AUTH_PW) {
/* accept any current cleartext password if (!bcmp(NA->au.au_pw, ap->key, RIP_AUTH_PW_LEN))
*/ return 1;
for (i = 0; i < MAX_AUTH_KEYS; i++, akp++) {
if ((u_long)akp->start-DAY > (u_long)clk.tv_sec } else {
|| (u_long)akp->end+DAY < (u_long)clk.tv_sec) /* accept MD5 secret with the right key ID
*/
if (NA->au.a_md5.md5_keyid != ap->keyid)
continue; continue;
if (!bcmp(NA->au.au_pw, akp->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;
}
if (i < MAX_AUTH_KEYS) {
na2 = (struct netauth *)((char *)(NA+1) na2 = (struct netauth *)((char *)(NA+1)
+ NA->au.a_md5.md5_pkt_len); + NA->au.a_md5.md5_pkt_len);
if (NA->au.a_md5.md5_pkt_len % sizeof(*NA) != 0 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, MD5Update(&md5_ctx, (u_char *)NA,
(char *)na2->au.au_pw - (char *)NA); (char *)na2->au.au_pw - (char *)NA);
MD5Update(&md5_ctx, MD5Update(&md5_ctx,
(u_char *)akp->key, sizeof(akp->key)); (u_char *)ap->key, sizeof(ap->key));
MD5Final(hash, &md5_ctx); MD5Final(hash, &md5_ctx);
if (na2->a_family == RIP_AF_AUTH if (na2->a_family != RIP_AF_AUTH
&& na2->a_type == 1 || na2->a_type != 1
&& NA->au.a_md5.md5_auth_len == RIP_AUTH_PW_LEN || NA->au.a_md5.md5_auth_len != RIP_AUTH_PW_LEN
&& !bcmp(hash, na2->au.au_pw, sizeof(hash))) || bcmp(hash, na2->au.au_pw, sizeof(hash)))
return 1; return 0;
return 1;
} }
} }

View File

@ -39,7 +39,7 @@ static char sccsid[] = "@(#)main.c 8.1 (Berkeley) 6/5/93";
#elif defined(__NetBSD__) #elif defined(__NetBSD__)
static char rcsid[] = "$NetBSD$"; static char rcsid[] = "$NetBSD$";
#endif #endif
#ident "$Revision: 1.18 $" #ident "$Revision: 1.20 $"
#include "defs.h" #include "defs.h"
#include "pathnames.h" #include "pathnames.h"
@ -201,10 +201,13 @@ main(int argc,
/* handle arbirary, (usually) per-interface /* handle arbirary, (usually) per-interface
* parameters. * parameters.
*/ */
p = parse_parms(optarg); p = parse_parms(optarg, 0);
if (p != 0) if (p != 0) {
msglog("bad \"%s\" in \"%s\"", if (strcasecmp(p,optarg))
p, optarg); msglog("%s in \"%s\"", p, optarg);
else
msglog("bad \"-P %s\"", optarg);
}
break; break;
default: default:
@ -218,9 +221,11 @@ main(int argc,
tracename = *argv++; tracename = *argv++;
argc--; argc--;
} }
if (tracename != 0 && tracename[0] == '\0')
goto usage;
if (argc != 0) { if (argc != 0) {
usage: usage:
logbad(0, "usage: routed [-sqdghmpAt] [-T /tracefile]" logbad(0, "usage: routed [-sqdghmpAt] [-T tracefile]"
" [-F net[,metric]] [-P parms]"); " [-F net[,metric]] [-P parms]");
} }
if (geteuid() != 0) if (geteuid() != 0)
@ -263,18 +268,16 @@ main(int argc,
signal(SIGUSR2, sigtrace_off); signal(SIGUSR2, sigtrace_off);
/* get into the background */ /* get into the background */
if (background) {
#ifdef sgi #ifdef sgi
if (0 > _daemonize(_DF_NOCHDIR, if (0 > _daemonize(background ? 0 : (_DF_NOCHDIR|_DF_NOFORK),
new_tracelevel == 0 ? -1 : STDOUT_FILENO, new_tracelevel == 0 ? -1 : STDOUT_FILENO,
new_tracelevel == 0 ? -1 : STDERR_FILENO, new_tracelevel == 0 ? -1 : STDERR_FILENO,
-1)) -1))
BADERR(0, "_daemonize()"); BADERR(0, "_daemonize()");
#else #else
if (daemon(1, 1) < 0) if (background && daemon(0, new_tracelevel) < 0)
BADERR(0,"daemon()"); BADERR(0,"daemon()");
#endif #endif
}
mypid = getpid(); mypid = getpid();
srandom((int)(clk.tv_sec ^ clk.tv_usec ^ mypid)); srandom((int)(clk.tv_sec ^ clk.tv_usec ^ mypid));
@ -297,11 +300,11 @@ main(int argc,
if (background && new_tracelevel == 0) if (background && new_tracelevel == 0)
ftrace = 0; ftrace = 0;
if (tracename != 0) { if (tracename != 0) {
trace_on(tracename, 1); strncpy(inittracename, tracename, sizeof(inittracename)-1);
if (new_tracelevel == 0) /* use stdout if file is bad */ set_tracefile(inittracename, "%s\n", -1);
new_tracelevel = 1; } else {
tracelevel_msg("%s\n", -1); /* turn on tracing to stdio */
} }
set_tracelevel(1);
bufinit(); bufinit();
@ -354,8 +357,8 @@ main(int argc,
now_expire = now.tv_sec - EXPIRE_TIME; now_expire = now.tv_sec - EXPIRE_TIME;
now_garbage = now.tv_sec - GARBAGE_TIME; now_garbage = now.tv_sec - GARBAGE_TIME;
/* deal with interrupts that should affect tracing */ /* deal with signals that should affect tracing */
set_tracelevel(0); set_tracelevel();
if (stopint != 0) { if (stopint != 0) {
rip_bcast(0); rip_bcast(0);
@ -491,7 +494,7 @@ main(int argc,
/* ARGSUSED */ /* ARGSUSED */
void void
sigalrm(int sig) sigalrm(int s)
{ {
/* Historically, SIGALRM would cause the daemon to check for /* Historically, SIGALRM would cause the daemon to check for
* new and broken interfaces. * new and broken interfaces.
@ -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. * 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 void
msglim(struct msg_limit *lim, naddr addr, char *p, ...) msglim(struct msg_limit *lim, naddr addr, char *p, ...)
{ {
va_list args; va_list args;
int i;
struct msg_sub *ms1, *ms;
char *p1; char *p1;
va_start(args, p); va_start(args, p);
if ( lim->addr != addr || lim->until <= now.tv_sec) { /* look for the oldest slot in the table
lim->addr = addr; * or the slot for the bad router.
lim->until = now.tv_sec + 60*60; */
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(); trace_flush();
for (p1 = p; *p1 == ' '; p1++) for (p1 = p; *p1 == ' '; p1++)
@ -837,6 +873,7 @@ msglim(struct msg_limit *lim, naddr addr, char *p, ...)
vsyslog(LOG_ERR, p1, args); vsyslog(LOG_ERR, p1, args);
} }
/* always display the message if tracing */
if (ftrace != 0) { if (ftrace != 0) {
(void)vfprintf(ftrace, p, args); (void)vfprintf(ftrace, p, args);
(void)fputc('\n', ftrace); (void)fputc('\n', ftrace);

View File

@ -22,7 +22,7 @@
* documentation and/or software. * documentation and/or software.
*/ */
#ident "$Revision: 1.2 $" #ident "$Revision: 1.3 $"
#ifdef sgi #ifdef sgi
#include <strings.h> #include <strings.h>

View File

@ -36,7 +36,7 @@ static char sccsid[] = "@(#)output.c 8.1 (Berkeley) 6/5/93";
#elif defined(__NetBSD__) #elif defined(__NetBSD__)
static char rcsid[] = "$NetBSD$"; static char rcsid[] = "$NetBSD$";
#endif #endif
#ident "$Revision: 1.18 $" #ident "$Revision: 1.21 $"
#include "defs.h" #include "defs.h"
@ -53,7 +53,7 @@ struct {
naddr to_std_mask; naddr to_std_mask;
naddr to_std_net; naddr to_std_net;
struct interface *ifp; /* usually output interface */ struct interface *ifp; /* usually output interface */
struct auth_key *a; struct auth *a;
char metric; /* adjust metrics by interface */ char metric; /* adjust metrics by interface */
int npackets; int npackets;
int gen_limit; int gen_limit;
@ -180,10 +180,15 @@ output(enum output_type type,
} }
sin.sin_addr.s_addr = htonl(INADDR_RIP_GROUP); sin.sin_addr.s_addr = htonl(INADDR_RIP_GROUP);
} }
break;
case NO_OUT_MULTICAST: case NO_OUT_MULTICAST:
case NO_OUT_RIPV2: case NO_OUT_RIPV2:
break; default:
#ifdef DEBUG
abort();
#endif
return -1;
} }
trace_rip(msg, "to", &sin, ifp, buf, size); 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. * the last key if they have all expired.
* If no key is ready yet, give up. * If no key is ready yet, give up.
*/ */
struct auth_key * struct auth *
find_auth(struct interface *ifp) find_auth(struct interface *ifp)
{ {
struct auth_key *ap, *res; struct auth *ap, *res;
int i; int i;
if (ifp == 0 || ifp->int_auth.type == RIP_AUTH_NONE) if (ifp == 0)
return 0; return 0;
res = 0; res = 0;
ap = ifp->int_auth.keys; ap = ifp->int_auth;
for (i = 0; i < MAX_AUTH_KEYS; i++, ap++) { for (i = 0; i < MAX_AUTH_KEYS; i++, ap++) {
if ((u_long)ap->start <= (u_long)clk.tv_sec) { /* stop looking after the last key */
if ((u_long)ap->end >= (u_long)clk.tv_sec) if (ap->type == RIP_AUTH_NONE)
return ap; break;
res = ap;
/* 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; return res;
} }
@ -235,8 +254,7 @@ find_auth(struct interface *ifp)
void void
clr_ws_buf(struct ws_buf *wb, clr_ws_buf(struct ws_buf *wb,
struct auth_key *ap, struct auth *ap)
struct interface *ifp)
{ {
struct netauth *na; struct netauth *na;
@ -249,13 +267,13 @@ clr_ws_buf(struct ws_buf *wb,
if (ap == 0) if (ap == 0)
return; return;
na = (struct netauth*)wb->n; 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_family = RIP_AF_AUTH;
na->a_type = RIP_AUTH_PW; na->a_type = RIP_AUTH_PW;
bcopy(ap->key, na->au.au_pw, sizeof(na->au.au_pw)); bcopy(ap->key, na->au.au_pw, sizeof(na->au.au_pw));
wb->n++; 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_family = RIP_AF_AUTH;
na->a_type = RIP_AUTH_MD5; na->a_type = RIP_AUTH_MD5;
na->au.a_md5.md5_keyid = ap->keyid; na->au.a_md5.md5_keyid = ap->keyid;
@ -269,7 +287,7 @@ clr_ws_buf(struct ws_buf *wb,
void void
end_md5_auth(struct ws_buf *wb, end_md5_auth(struct ws_buf *wb,
struct auth_key *ap) struct auth *ap)
{ {
struct netauth *na, *na2; struct netauth *na, *na2;
MD5_CTX md5_ctx; MD5_CTX md5_ctx;
@ -306,7 +324,7 @@ supply_write(struct ws_buf *wb)
case NO_OUT_RIPV2: case NO_OUT_RIPV2:
break; break;
default: 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); end_md5_auth(wb,ws.a);
if (output(wb->type, &ws.to, ws.ifp, wb->buf, if (output(wb->type, &ws.to, ws.ifp, wb->buf,
((char *)wb->n - (char*)wb->buf)) < 0 ((char *)wb->n - (char*)wb->buf)) < 0
@ -316,7 +334,7 @@ supply_write(struct ws_buf *wb)
break; 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) supply_out(struct ag_info *ag)
{ {
int i; int i;
naddr mask, v1_mask, dst_h, ddst_h; naddr mask, v1_mask, dst_h, ddst_h = 0;
struct ws_buf *wb; struct ws_buf *wb;
@ -563,25 +581,33 @@ walk_supply(struct radix_node *rn,
* forgotten. * forgotten.
* *
* Include the routes for both ends of point-to-point interfaces * 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 if (RT->rt_ifp == ws.ifp && ws.ifp != 0
&& !(ws.state & WS_ST_QUERY) && !(ws.state & WS_ST_QUERY)
&& (ws.state & WS_ST_TO_ON_NET) && (ws.state & WS_ST_TO_ON_NET)
&& (!(RT->rt_state & RS_IF) && (!(RT->rt_state & RS_IF)
|| ws.ifp->int_if_flags & IFF_POINTOPOINT)) { || ws.ifp->int_if_flags & IFF_POINTOPOINT)) {
/* Poison-reverse the route instead of only not advertising it /* If we do not mark the route with AGS_SPLIT_HZ here,
* it is recently changed from some other route. * 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 * 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 * then it is either old and dead or a brand new route.
* is brand new, there is no need for poison-reverse. * 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 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_SPLIT_HZ;
ags &= ~(AGS_PROMOTE | AGS_SUPPRESS); ags &= ~(AGS_PROMOTE | AGS_SUPPRESS);
} }
metric = HOPCNT_INFINITY;
} }
/* Adjust the outgoing metric by the cost of the link. /* 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; 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; ws.a = 0;
clr_ws_buf(&v12buf,ws.a,ifp); clr_ws_buf(&v12buf,ws.a);
clr_ws_buf(&v2buf,ws.a,ifp); clr_ws_buf(&v2buf,ws.a);
/* Fake a default route if asked and if there is not already /* Fake a default route if asked and if there is not already
* a better, real default route. * a better, real default route.

View File

@ -36,10 +36,11 @@ static char sccsid[] = "@(#)if.c 8.1 (Berkeley) 6/5/93";
#elif defined(__NetBSD__) #elif defined(__NetBSD__)
static char rcsid[] = "$NetBSD$"; static char rcsid[] = "$NetBSD$";
#endif #endif
#ident "$Revision: 1.10 $" #ident "$Revision: 1.12 $"
#include "defs.h" #include "defs.h"
#include "pathnames.h" #include "pathnames.h"
#include <sys/stat.h>
struct parm *parms; struct parm *parms;
@ -54,6 +55,7 @@ get_parms(struct interface *ifp)
{ {
static warned_auth_in, warned_auth_out; static warned_auth_in, warned_auth_out;
struct parm *parmp; struct parm *parmp;
int i, num_passwds = 0;
/* get all relevant parameters /* get all relevant parameters
*/ */
@ -68,9 +70,14 @@ get_parms(struct interface *ifp)
* so get its settings * so get its settings
*/ */
ifp->int_state |= parmp->parm_int_state; ifp->int_state |= parmp->parm_int_state;
if (parmp->parm_auth.type != RIP_AUTH_NONE) for (i = 0; i < MAX_AUTH_KEYS; i++) {
bcopy(&parmp->parm_auth, &ifp->int_auth, if (parmp->parm_auth[0].type == RIP_AUTH_NONE
sizeof(ifp->int_auth)); || 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) if (parmp->parm_rdisc_pref != 0)
ifp->int_rdisc_pref = parmp->parm_rdisc_pref; ifp->int_rdisc_pref = parmp->parm_rdisc_pref;
if (parmp->parm_rdisc_int != 0) if (parmp->parm_rdisc_int != 0)
@ -114,7 +121,7 @@ get_parms(struct interface *ifp)
ifp->int_state |= IS_NO_RIP; ifp->int_state |= IS_NO_RIP;
if (!IS_RIP_IN_OFF(ifp->int_state) 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) && !(ifp->int_state & IS_NO_RIPV1_IN)
&& !warned_auth_in) { && !warned_auth_in) {
msglog("Warning: RIPv1 input via %s" msglog("Warning: RIPv1 input via %s"
@ -123,14 +130,14 @@ get_parms(struct interface *ifp)
warned_auth_in = 1; warned_auth_in = 1;
} }
if (!IS_RIP_OUT_OFF(ifp->int_state) if (!IS_RIP_OUT_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_OUT) && !(ifp->int_state & IS_NO_RIPV1_OUT)) {
&& !warned_auth_out) { if (!warned_auth_out) {
msglog("Warning: RIPv1 output via %s" msglog("Warning: RIPv1 output via %s"
" will be sent without authentication", " will be sent without authentication",
ifp->int_name); ifp->int_name);
warned_auth_out = 1; warned_auth_out = 1;
ifp->int_auth.type = RIP_AUTH_NONE; }
} }
} }
@ -160,6 +167,7 @@ gwkludge(void)
struct interface *ifp; struct interface *ifp;
naddr dst, netmask, gate; naddr dst, netmask, gate;
int metric, n; int metric, n;
struct stat sb;
u_int state; u_int state;
char *type; char *type;
@ -168,6 +176,12 @@ gwkludge(void)
if (fp == 0) if (fp == 0)
return; return;
if (0 > fstat(fileno(fp), &sb)) {
msglog("could not stat() "_PATH_GATEWAYS);
(void)fclose(fp);
return;
}
for (;;) { for (;;) {
if (0 == fgets(lbuf, sizeof(lbuf)-1, fp)) if (0 == fgets(lbuf, sizeof(lbuf)-1, fp))
break; break;
@ -185,10 +199,12 @@ gwkludge(void)
*/ */
if (strncasecmp("net", lptr, 3) if (strncasecmp("net", lptr, 3)
&& strncasecmp("host", lptr, 4)) { && strncasecmp("host", lptr, 4)) {
p = parse_parms(lptr); p = parse_parms(lptr,
(sb.st_uid == 0
&& !(sb.st_mode&(S_IRWXG|S_IRWXO))));
if (p != 0) { if (p != 0) {
if (strcasecmp(p,lptr)) if (strcasecmp(p,lptr))
msglog("bad %s in "_PATH_GATEWAYS msglog("%s in "_PATH_GATEWAYS
" entry \"%s\"", p, lptr); " entry \"%s\"", p, lptr);
else else
msglog("bad \"%s\" in "_PATH_GATEWAYS, msglog("bad \"%s\" in "_PATH_GATEWAYS,
@ -225,6 +241,7 @@ gwkludge(void)
" entry \"%s\"", dname, lptr); " entry \"%s\"", dname, lptr);
continue; continue;
} }
HTONL(dst); /* make network # into IP address */
} else { } else {
msglog("bad \"%s\" in "_PATH_GATEWAYS msglog("bad \"%s\" in "_PATH_GATEWAYS
" entry \"%s\"", lptr); " entry \"%s\"", lptr);
@ -333,12 +350,14 @@ gwkludge(void)
trace_if("Add", ifp); trace_if("Add", ifp);
} }
(void)fclose(fp);
} }
/* strtok(), but honoring backslash /* strtok(), but honoring backslash
*/ */
static int /* -1=bad */ static int /* 0=ok, -1=bad */
parse_quote(char **linep, parse_quote(char **linep,
char *delims, char *delims,
char *delimp, char *delimp,
@ -352,9 +371,7 @@ parse_quote(char **linep,
if (*pc == '\0') if (*pc == '\0')
return -1; return -1;
for (;;) { while (lim != 0) {
if (lim == 0)
return -1;
c = *pc++; c = *pc++;
if (c == '\0') if (c == '\0')
break; break;
@ -388,11 +405,13 @@ parse_quote(char **linep,
--lim; --lim;
} }
exit: exit:
if (lim == 0)
return -1;
*buf = '\0';
if (delimp != 0) if (delimp != 0)
*delimp = c; *delimp = c;
*linep = pc-1; *linep = pc-1;
if (lim != 0)
*buf = '\0';
return 0; return 0;
} }
@ -413,7 +432,7 @@ parse_ts(time_t *tp,
buf,bufsize) buf,bufsize)
|| buf[bufsize-1] != '\0' || buf[bufsize-1] != '\0'
|| buf[bufsize-2] != '\0') { || buf[bufsize-2] != '\0') {
sprintf(buf,"timestamp %.25s", val0); sprintf(buf,"bad timestamp %.25s", val0);
return buf; return buf;
} }
strcat(buf,"\n"); strcat(buf,"\n");
@ -421,14 +440,14 @@ parse_ts(time_t *tp,
if (5 != sscanf(buf, "%u/%u/%u@%u:%u\n", if (5 != sscanf(buf, "%u/%u/%u@%u:%u\n",
&tm.tm_year, &tm.tm_mon, &tm.tm_mday, &tm.tm_year, &tm.tm_mon, &tm.tm_mday,
&tm.tm_hour, &tm.tm_min)) { &tm.tm_hour, &tm.tm_min)) {
sprintf(buf,"timestamp %.25s", val0); sprintf(buf,"bad timestamp %.25s", val0);
return buf; return buf;
} }
if (tm.tm_year <= 37) if (tm.tm_year <= 37)
tm.tm_year += 100; tm.tm_year += 100;
if ((*tp = mktime(&tm)) == -1) { if ((*tp = mktime(&tm)) == -1) {
sprintf(buf,"timestamp %.25s", val0); sprintf(buf,"bad timestamp %.25s", val0);
return buf; return buf;
} }
@ -436,92 +455,93 @@ parse_ts(time_t *tp,
} }
/* Get one or more password, key ID's, and expiration dates in /* Get a password, key ID, and expiration date in the format
* the format * passwd|keyID|year/mon/day@hour:min|year/mon/day@hour:min
* passwd|keyID|year/mon/day@hour:min|year/mon/day@hour:min|passwd|...
*/ */
static char * /* 0 or error message */ static char * /* 0 or error message */
get_passwds(char *tgt, get_passwd(char *tgt,
char *val, char *val,
struct parm *parmp, struct parm *parmp,
u_char type) u_char type,
int safe) /* 1=from secure file */
{ {
static char buf[80]; static char buf[80];
char *val0, *p, delim; char *val0, *p, delim;
struct auth_key *akp, *akp2; struct auth k, *ap, *ap2;
int i; int i;
u_long l; u_long l;
if (parmp->parm_auth.type != RIP_AUTH_NONE) if (!safe)
return "duplicate authentication"; return "unsafe password";
parmp->parm_auth.type = type;
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; bzero(&k, sizeof(k));
for (i = 0; i < MAX_AUTH_KEYS; i++, val++, akp++) { k.type = type;
if ((delim = *val) == '\0') k.end = -1-DAY;
break;
val0 = val;
if (0 > parse_quote(&val, "| ,\n\r", &delim,
(char *)akp->key, sizeof(akp->key)))
return tgt;
akp->end = -1; val0 = val;
if (0 > parse_quote(&val, "| ,\n\r", &delim,
(char *)k.key, sizeof(k.key)))
return tgt;
if (delim != '|') { if (delim != '|') {
if (type == RIP_AUTH_MD5) if (type == RIP_AUTH_MD5)
return "missing Keyid"; return "missing Keyid";
break; } else {
}
val0 = ++val; val0 = ++val;
buf[sizeof(buf)-1] = '\0';
if (0 > parse_quote(&val, "| ,\n\r", &delim, buf,sizeof(buf)) if (0 > parse_quote(&val, "| ,\n\r", &delim, buf,sizeof(buf))
|| buf[sizeof(buf)-1] != '\0' || buf[sizeof(buf)-1] != '\0'
|| (l = strtoul(buf,&p,0)) > 255 || (l = strtoul(buf,&p,0)) > 255
|| *p != '\0') { || *p != '\0') {
sprintf(buf,"KeyID \"%.20s\"", val0); sprintf(buf,"bad KeyID \"%.20s\"", val0);
return buf; return buf;
} }
for (akp2 = parmp->parm_auth.keys; akp2 < akp; akp2++) { for (ap2 = parmp->parm_auth; ap2 < ap; ap2++) {
if (akp2->keyid == l) { if (ap2->keyid == l) {
*val = '\0';
sprintf(buf,"duplicate KeyID \"%.20s\"", val0); sprintf(buf,"duplicate KeyID \"%.20s\"", val0);
return buf; return buf;
} }
} }
akp->keyid = (int)l; k.keyid = (int)l;
if (delim != '|') if (delim == '|') {
break; val0 = ++val;
if (0 != (p = parse_ts(&k.start,&val,val0,&delim,
val0 = ++val; buf,sizeof(buf))))
if (0 != (p = parse_ts(&akp->start,&val,val0,&delim, return p;
buf,sizeof(buf)))) if (delim != '|')
return p; return "missing second timestamp";
if (delim != '|') val0 = ++val;
return "missing second timestamp"; if (0 != (p = parse_ts(&k.end,&val,val0,&delim,
val0 = ++val; buf,sizeof(buf))))
if (0 != (p = parse_ts(&akp->end,&val,val0,&delim, return p;
buf,sizeof(buf)))) if ((u_long)k.start > (u_long)k.end) {
return p; sprintf(buf,"out of order timestamp %.30s",
if ((u_long)akp->start > (u_long)akp->end) { val0);
sprintf(buf,"out of order timestamp %.30s",val0); return buf;
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. /* Parse a set of parameters for an interface.
*/ */
char * /* 0 or error message */ 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 PARS(str) (!strcasecmp(tgt, str))
#define PARSEQ(str) (!strncasecmp(tgt, str"=", sizeof(str))) #define PARSEQ(str) (!strncasecmp(tgt, str"=", sizeof(str)))
@ -554,6 +574,7 @@ parse_parms(char *line)
free(intnetp); free(intnetp);
return line; return line;
} }
HTONL(intnetp->intnet_addr);
intnetp->intnet_next = intnets; intnetp->intnet_next = intnets;
intnets = intnetp; intnets = intnetp;
return 0; return 0;
@ -591,7 +612,7 @@ parse_parms(char *line)
* The parm_net stuff is needed to allow several * The parm_net stuff is needed to allow several
* -F settings. * -F settings.
*/ */
if (!getnet(val, &addr, &mask) if (!getnet(val0, &addr, &mask)
|| parm.parm_name[0] != '\0') || parm.parm_name[0] != '\0')
return tgt; return tgt;
parm.parm_net = addr; parm.parm_net = addr;
@ -599,14 +620,21 @@ parse_parms(char *line)
parm.parm_name[0] = '\n'; parm.parm_name[0] = '\n';
} else if (PARSEQ("passwd")) { } else if (PARSEQ("passwd")) {
tgt = get_passwds(tgt, val0, &parm, RIP_AUTH_PW); /* since cleartext passwords are so weak allow
if (tgt) * them anywhere
*/
tgt = get_passwd(tgt,val0,&parm,RIP_AUTH_PW,1);
if (tgt) {
*val0 = '\0';
return tgt; return tgt;
}
} else if (PARSEQ("md5_passwd")) { } else if (PARSEQ("md5_passwd")) {
tgt = get_passwds(tgt, val0, &parm, RIP_AUTH_MD5); tgt = get_passwd(tgt,val0,&parm,RIP_AUTH_MD5,safe);
if (tgt) if (tgt) {
*val0 = '\0';
return tgt; return tgt;
}
} else if (PARS("no_ag")) { } else if (PARS("no_ag")) {
parm.parm_int_state |= (IS_NO_AG | IS_NO_SUPER_AG); parm.parm_int_state |= (IS_NO_AG | IS_NO_SUPER_AG);
@ -693,6 +721,9 @@ parse_parms(char *line)
tgates = tg; tgates = tg;
parm.parm_int_state |= IS_DISTRUST; parm.parm_int_state |= IS_DISTRUST;
} else if (PARS("redirect_ok")) {
parm.parm_int_state |= IS_REDIRECT_OK;
} else { } else {
return tgt; /* error */ return tgt; /* error */
} }
@ -708,16 +739,24 @@ parse_parms(char *line)
char * /* 0 or error message */ char * /* 0 or error message */
check_parms(struct parm *new) check_parms(struct parm *new)
{ {
struct parm *parmp; struct parm *parmp, **parmpp;
int i, num_passwds;
/* set implicit values /* set implicit values
*/ */
if (new->parm_int_state & IS_NO_ADV_IN) if (new->parm_int_state & IS_NO_ADV_IN)
new->parm_int_state |= IS_NO_SOL_OUT; new->parm_int_state |= IS_NO_SOL_OUT;
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 /* 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)) if (strcmp(new->parm_name, parmp->parm_name))
continue; continue;
if (!on_net(htonl(parmp->parm_net), if (!on_net(htonl(parmp->parm_net),
@ -726,12 +765,12 @@ check_parms(struct parm *new)
parmp->parm_net, parmp->parm_mask)) parmp->parm_net, parmp->parm_mask))
continue; continue;
if (parmp->parm_auth.type != RIP_AUTH_NONE for (i = 0; i < MAX_AUTH_KEYS; i++) {
&& new->parm_auth.type != RIP_AUTH_NONE if (parmp->parm_auth[i].type != RIP_AUTH_NONE)
&& bcmp(&parmp->parm_auth, &new->parm_auth, num_passwds++;
sizeof(parmp->parm_auth))) {
return "conflicting, duplicate authentication";
} }
if (num_passwds > MAX_AUTH_KEYS)
return "too many conflicting passwords";
if ((0 != (new->parm_int_state & GROUP_IS_SOL) if ((0 != (new->parm_int_state & GROUP_IS_SOL)
&& 0 != (parmp->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)); parmp = (struct parm*)malloc(sizeof(*parmp));
bcopy(new, parmp, sizeof(*parmp)); bcopy(new, parmp, sizeof(*parmp));
parmp->parm_next = parms; *parmpp = parmp;
parms = parmp;
return 0; return 0;
} }
@ -774,13 +815,13 @@ check_parms(struct parm *new)
*/ */
int /* 0=bad */ int /* 0=bad */
getnet(char *name, getnet(char *name,
naddr *netp, /* host byte order */ naddr *netp, /* a network so host byte order */
naddr *maskp) naddr *maskp) /* masks are always in host order */
{ {
int i; int i;
struct netent *np; struct netent *np;
naddr mask; naddr mask; /* in host byte order */
struct in_addr in; struct in_addr in; /* a network and so host byte order */
char hname[MAXHOSTNAMELEN+1]; char hname[MAXHOSTNAMELEN+1];
char *mname, *p; char *mname, *p;
@ -812,7 +853,7 @@ getnet(char *name,
/* we cannot use the interfaces here because we have not /* we cannot use the interfaces here because we have not
* looked at them yet. * looked at them yet.
*/ */
mask = std_mask(in.s_addr); mask = std_mask(htonl(in.s_addr));
if ((~mask & in.s_addr) != 0) if ((~mask & in.s_addr) != 0)
mask = HOST_MASK; mask = HOST_MASK;
} else { } else {

View File

@ -36,7 +36,7 @@ static char sccsid[] = "@(#)rdisc.c 8.1 (Berkeley) x/y/95";
#elif defined(__NetBSD__) #elif defined(__NetBSD__)
static char rcsid[] = "$NetBSD$"; static char rcsid[] = "$NetBSD$";
#endif #endif
#ident "$Revision: 1.17 $" #ident "$Revision: 1.19 $"
#include "defs.h" #include "defs.h"
#include <netinet/in_systm.h> #include <netinet/in_systm.h>
@ -127,7 +127,7 @@ trace_rdisc(char *act,
wp = &p->ad.icmp_ad_info[0].icmp_ad_addr; wp = &p->ad.icmp_ad_info[0].icmp_ad_addr;
lim = &wp[(len - sizeof(p->ad)) / sizeof(*wp)]; lim = &wp[(len - sizeof(p->ad)) / sizeof(*wp)];
for (i = 0; i < p->ad.icmp_ad_num && wp <= lim; i++) { 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])); naddr_ntoa(wp[0]), (int)ntohl(wp[1]));
wp += p->ad.icmp_ad_asize; wp += p->ad.icmp_ad_asize;
} }
@ -689,6 +689,7 @@ send_rdisc(union ad_u *p,
switch (type) { switch (type) {
case 0: /* unicast */ case 0: /* unicast */
default:
msg = "Send"; msg = "Send";
break; break;

View File

@ -514,11 +514,13 @@ specifies a RIPv2 password that will be included on all RIPv2
responses sent and checked on all RIPv2 responses received. responses sent and checked on all RIPv2 responses received.
The password must not contain any blanks, tab characters, commas The password must not contain any blanks, tab characters, commas
or '#' characters. or '#' characters.
.It Cm passwd Ns \&= Ns Ar XXX1[|KeyID[start|stop]][XXX2...] .It Cm passwd Ns \&= Ns Ar XXX1[|KeyID[start|stop]]
specifies one or more RIPv2 cleartext passwords that will be included on specifies a RIPv2 cleartext password that will be included on
all RIPv2 responses sent, and checked on all RIPv2 responses received. all RIPv2 responses sent, and checked on all RIPv2 responses received.
Any blanks, tab characters, commas, or '#' or '|' characters in the Any blanks, tab characters, commas, or '#', '|', or NULL characters in the
password must be escaped with a backslash (\\). password must be escaped with a backslash (\\).
The common escape sequences \\n, \\r, \\t, \\b, and \\xxx have their
usual meanings.
The The
.Cm KeyID .Cm KeyID
must be unique but is ignored for cleartext passwords. must be unique but is ignored for cleartext passwords.
@ -528,15 +530,21 @@ and
.Cm stop .Cm stop
are timestamps in the form year/month/day@hour:minute. are timestamps in the form year/month/day@hour:minute.
They specify when the password is valid. 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 Incoming packets can carry any password that is valid, will
be valid within 24 hours, or that was valid within 24 hours. be valid within 24 hours, or that was valid within 24 hours.
.It Cm md5_passwd Ns \&= Ns Ar XXX1|KeyID[start|stop][XXX2...] .It Cm md5_passwd Ns \&= Ns Ar XXX1|KeyID[start|stop]
specifes one or more RIPv2 MD5 passwords. specifes a RIPv2 MD5 password.
Except that a Except that a
.Cm KeyID .Cm KeyID
is required, this keyword is the similar to is required, this keyword is similar to
.Cm passwd . .Cm passwd .
To protect the secrets, this parameter setting is valid only in the
.Em /etc/gateways
file and only when that file is readable only by UID 0.
.It Cm no_ag .It Cm no_ag
turns off aggregation of subnets in RIPv1 and RIPv2 responses. turns off aggregation of subnets in RIPv1 and RIPv2 responses.
.It Cm no_super_ag .It Cm no_super_ag
@ -612,6 +620,10 @@ causes RIP packets from that router and other routers named in
other other
.Cm trust_gateway .Cm trust_gateway
keywords to be accept, and packets from other routers to be ignored. keywords to be 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 .El
.Pp .Pp
.Sh FILES .Sh FILES

View File

@ -40,7 +40,7 @@
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
#ident "$Revision: 1.10 $" #ident "$Revision: 1.11 $"
/* /*
* Routing Information Protocol * Routing Information Protocol

View File

@ -22,7 +22,7 @@
* documentation and/or software. * documentation and/or software.
*/ */
#ident "$Revision: 1.2 $" #ident "$Revision: 1.3 $"
#ifdef sgi #ifdef sgi
#include <strings.h> #include <strings.h>

View File

@ -40,7 +40,7 @@ static char sccsid[] = "@(#)query.c 8.1 (Berkeley) 6/5/93";
#elif defined(__NetBSD__) #elif defined(__NetBSD__)
static char rcsid[] = "$NetBSD$"; static char rcsid[] = "$NetBSD$";
#endif #endif
#ident "$Revision: 1.9 $" #ident "$Revision: 1.10 $"
#include <sys/param.h> #include <sys/param.h>
#include <sys/protosw.h> #include <sys/protosw.h>

View File

@ -36,7 +36,7 @@ static char sccsid[] = "@(#)tables.c 8.1 (Berkeley) 6/5/93";
#elif defined(__NetBSD__) #elif defined(__NetBSD__)
static char rcsid[] = "$NetBSD$"; static char rcsid[] = "$NetBSD$";
#endif #endif
#ident "$Revision: 1.26 $" #ident "$Revision: 1.28 $"
#include "defs.h" #include "defs.h"
@ -746,7 +746,7 @@ static struct khash {
#define KS_DELETED 0x100 /* already deleted */ #define KS_DELETED 0x100 /* already deleted */
time_t k_keep; time_t k_keep;
#define K_KEEP_LIM 30 #define K_KEEP_LIM 30
time_t k_redirect_time; time_t k_redirect_time; /* when redirected route 1st seen */
} *khash_bins[KHASH_SIZE]; } *khash_bins[KHASH_SIZE];
@ -832,8 +832,7 @@ rtm_add(struct rt_msghdr *rtm,
} else if (INFO_MASK(info) != 0) { } else if (INFO_MASK(info) != 0) {
mask = ntohl(S_ADDR(INFO_MASK(info))); mask = ntohl(S_ADDR(INFO_MASK(info)));
} else { } else {
msglog("ignore %s without mask", msglog("ignore %s without mask", rtm_type_name(rtm->rtm_type));
rtm_type_name(rtm->rtm_type));
return; return;
} }
@ -860,20 +859,32 @@ rtm_add(struct rt_msghdr *rtm,
k->k_state |= KS_STATIC; k->k_state |= KS_STATIC;
if (0 != (rtm->rtm_flags & (RTF_DYNAMIC | RTF_MODIFIED))) { 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, /* 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_DYNAMIC;
k->k_state |= KS_DELETE; k->k_state |= KS_DELETE;
LIM_SEC(need_kern, 0); LIM_SEC(need_kern, 0);
trace_act("mark redirected %s --> %s for deletion" trace_act("mark for deletion redirected %s --> %s"
" since this is a router", " via %s",
addrname(k->k_dst, k->k_mask, 0), 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 { } else {
k->k_state |= KS_DYNAMIC; k->k_state |= KS_DYNAMIC;
k->k_redirect_time = now.tv_sec; 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; return;
} }
@ -893,17 +904,10 @@ rtm_add(struct rt_msghdr *rtm,
* Find the interface toward the gateway. * Find the interface toward the gateway.
*/ */
ifp = iflookup(k->k_gate); ifp = iflookup(k->k_gate);
if (ifp == 0) { if (ifp == 0)
/* if there is no known interface, msglog("static route %s --> %s impossibly lacks ifp",
* maybe there is a new interface addrname(S_ADDR(INFO_DST(info)), mask, 0),
*/ naddr_ntoa(k->k_gate));
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));
}
kern_check_static(k, ifp); kern_check_static(k, ifp);
} }
@ -917,8 +921,8 @@ rtm_lose(struct rt_msghdr *rtm,
{ {
if (INFO_GATE(info) == 0 if (INFO_GATE(info) == 0
|| INFO_GATE(info)->sa_family != AF_INET) { || INFO_GATE(info)->sa_family != AF_INET) {
msglog("ignore %s without gateway", trace_act("ignore %s without gateway",
rtm_type_name(rtm->rtm_type)); rtm_type_name(rtm->rtm_type));
return; return;
} }

View File

@ -36,7 +36,7 @@ static char sccsid[] = "@(#)trace.c 8.1 (Berkeley) 6/5/93";
#elif defined(__NetBSD__) #elif defined(__NetBSD__)
static char rcsid[] = "$NetBSD$"; static char rcsid[] = "$NetBSD$";
#endif #endif
#ident "$Revision: 1.14 $" #ident "$Revision: 1.16 $"
#define RIPCMDS #define RIPCMDS
#include "defs.h" #include "defs.h"
@ -53,11 +53,12 @@ static char rcsid[] = "$NetBSD$";
#define NRECORDS 50 /* size of circular trace buffer */ #define NRECORDS 50 /* size of circular trace buffer */
u_int tracelevel, new_tracelevel; int tracelevel, new_tracelevel;
FILE *ftrace = stdout; /* output trace file */ FILE *ftrace = stdout; /* output trace file */
static char *tracelevel_pat = "%s\n"; static char *sigtrace_pat = "%s\n";
static char savetracename[MAXPATHLEN+1];
char savetracename[MAXPATHLEN+1]; char inittracename[MAXPATHLEN+1];
int file_trace; /* 1=tracing to file, not stdout */
static void trace_dump(void); static void trace_dump(void);
@ -162,15 +163,15 @@ ts(time_t secs) {
* This assumes that 'now' is update once for each event, and * This assumes that 'now' is update once for each event, and
* that at least now.tv_usec changes. * that at least now.tv_usec changes.
*/ */
static struct timeval lastlog_time;
void void
lastlog(void) lastlog(void)
{ {
static struct timeval last; if (lastlog_time.tv_sec != now.tv_sec
|| lastlog_time.tv_usec != now.tv_usec) {
if (last.tv_sec != now.tv_sec
|| last.tv_usec != now.tv_usec) {
(void)fprintf(ftrace, "-- %s --\n", ts(now.tv_sec)); (void)fprintf(ftrace, "-- %s --\n", ts(now.tv_sec));
last = now; lastlog_time = now;
} }
} }
@ -198,15 +199,17 @@ trace_close(void)
fflush(stdout); fflush(stdout);
fflush(stderr); fflush(stderr);
if (ftrace != 0 if (ftrace != 0 && file_trace) {
&& savetracename[0] != '\0') { if (ftrace != stdout)
fclose(ftrace);
ftrace = 0;
fd = open(_PATH_DEVNULL, O_RDWR); fd = open(_PATH_DEVNULL, O_RDWR);
(void)dup2(fd, STDIN_FILENO);
(void)dup2(fd, STDOUT_FILENO); (void)dup2(fd, STDOUT_FILENO);
(void)dup2(fd, STDERR_FILENO); (void)dup2(fd, STDERR_FILENO);
(void)close(fd); (void)close(fd);
fclose(ftrace);
ftrace = 0;
} }
lastlog_time.tv_sec = 0;
} }
@ -231,7 +234,6 @@ trace_off(char *p, ...)
lastlog(); lastlog();
va_start(args, p); va_start(args, p);
vfprintf(ftrace, p, args); vfprintf(ftrace, p, args);
fflush(ftrace);
} }
trace_close(); trace_close();
@ -239,107 +241,11 @@ trace_off(char *p, ...)
} }
void /* log a change in tracing
trace_on(char *filename,
int initial) /* 1=setting from command line */
{
struct stat stbuf;
FILE *n_ftrace;
u_int old_tracelevel;
/* Given a null filename when tracing is already on, increase the
* debugging level and re-open the file in case it has been unlinked.
*/
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;
}
filename = savetracename;
} else if (!strcmp(filename,"dump/../table")) {
trace_dump();
return;
} else {
if (stat(filename, &stbuf) >= 0
&& (stbuf.st_mode & S_IFMT) != S_IFREG) {
msglog("wrong type (%#x) of trace file \"%s\"",
stbuf.st_mode, 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);
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", filename);
trace_close();
if (filename != savetracename)
strncpy(savetracename, filename, sizeof(savetracename)-1);
ftrace = n_ftrace;
fflush(stdout);
fflush(stderr);
dup2(fileno(ftrace), STDOUT_FILENO);
dup2(fileno(ftrace), STDERR_FILENO);
if (new_tracelevel == 0)
new_tracelevel = 1;
old_tracelevel = tracelevel;
set_tracelevel(initial);
if (!initial && old_tracelevel == 0)
trace_dump();
}
/* ARGSUSED */
void
sigtrace_on(int s)
{
new_tracelevel++;
tracelevel_pat = "SIGUSR1: %s\n";
}
/* ARGSUSED */
void
sigtrace_off(int s)
{
new_tracelevel--;
tracelevel_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
*/ */
void void
set_tracelevel(int initial) tracelevel_msg(char *pat,
int dump) /* -1=no dump, 0=default, 1=force */
{ {
static char *off_msgs[MAX_TRACELEVEL] = { static char *off_msgs[MAX_TRACELEVEL] = {
"Tracing actions stopped", "Tracing actions stopped",
@ -353,34 +259,165 @@ set_tracelevel(int initial)
"Tracing packet contents started", "Tracing packet contents started",
"Tracing kernel changes started", "Tracing kernel changes started",
}; };
u_int old_tracelevel = tracelevel;
if (new_tracelevel > MAX_TRACELEVEL) { if (new_tracelevel < 0)
new_tracelevel = 0;
else if (new_tracelevel > MAX_TRACELEVEL)
new_tracelevel = MAX_TRACELEVEL; new_tracelevel = MAX_TRACELEVEL;
if (new_tracelevel == tracelevel) {
tmsg(tracelevel_pat, on_msgs[tracelevel-1]); 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;
char *fn;
/* 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 || filename[0] == '\0') {
filename = 0;
if (ftrace == 0) {
if (inittracename[0] == '\0') {
msglog("missing trace file name");
return;
}
fn = inittracename;
} else {
fn = 0;
}
} 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; 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\"",
stbuf.st_mode, filename);
return;
}
fn = filename;
} }
for (; new_tracelevel != tracelevel; tracelevel++) { if (fn != 0) {
if (new_tracelevel < tracelevel) { n_ftrace = fopen(fn, "a");
if (--tracelevel == 0) if (n_ftrace == 0) {
trace_off(tracelevel_pat, off_msgs[0]); msglog("failed to open trace file \"%s\" %s",
else fn, strerror(errno));
tmsg(tracelevel_pat, off_msgs[tracelevel]); if (fn == inittracename)
} else { inittracename[0] = '\0';
if (ftrace == 0) { return;
if (savetracename[0] != '\0')
trace_on(savetracename, 1);
else
ftrace = stdout;
}
if (!initial || tracelevel+1 == new_tracelevel)
tmsg(tracelevel_pat, on_msgs[tracelevel]);
} }
tmsg("switch to trace file %s\n", fn);
file_trace = 1;
trace_close();
if (fn != savetracename)
strncpy(savetracename, fn, sizeof(savetracename)-1);
ftrace = n_ftrace;
fflush(stdout);
fflush(stderr);
dup2(fileno(ftrace), STDOUT_FILENO);
dup2(fileno(ftrace), STDERR_FILENO);
}
if (new_tracelevel == 0 || filename == 0)
new_tracelevel++;
tracelevel_msg(pat, dump != 0 ? dump : (filename != 0));
}
/* ARGSUSED */
void
sigtrace_on(int s)
{
new_tracelevel++;
sigtrace_pat = "SIGUSR1: %s\n";
}
/* ARGSUSED */
void
sigtrace_off(int s)
{
new_tracelevel--;
sigtrace_pat = "SIGUSR2: %s\n";
}
/* Set tracing after a signal.
*/
void
set_tracelevel(void)
{
if (new_tracelevel == tracelevel)
return;
/* 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 {
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_BROKE, IS_SICK, "BROKEN" },
{ IS_SICK, 0, "SICK" }, { IS_SICK, 0, "SICK" },
{ IS_DUP, 0, "DUPLICATE" }, { IS_DUP, 0, "DUPLICATE" },
{ IS_REDIRECT_OK, 0, "REDIRECT_OK" },
{ IS_NEED_NET_SYN, 0, "" }, { IS_NEED_NET_SYN, 0, "" },
{ IS_NO_AG, IS_NO_SUPER_AG, "NO_AG" }, { IS_NO_AG, IS_NO_SUPER_AG, "NO_AG" },
{ IS_NO_SUPER_AG, 0, "NO_SUPER_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 void
trace_if(char *act, trace_if(char *act,
struct interface *ifp) struct interface *ifp)
@ -584,13 +648,22 @@ trace_upslot(struct rt_entry *rt,
u_short tag, u_short tag,
time_t new_time) time_t new_time)
{ {
struct rt_spare new;
if (!TRACEACTIONS || ftrace == 0) if (!TRACEACTIONS || ftrace == 0)
return; return;
if (rts->rts_gate == gate if (rts->rts_gate == gate
&& rts->rts_router == router && rts->rts_router == router
&& rts->rts_metric == metric && rts->rts_metric == metric
&& rts->rts_tag == tag) && rts->rts_tag == tag)
return; return;
new.rts_ifp = ifp;
new.rts_gate = gate;
new.rts_router = router;
new.rts_metric = metric;
new.rts_time = new_time;
new.rts_tag = tag;
lastlog(); lastlog();
if (rts->rts_gate != RIP_DEFAULT) { if (rts->rts_gate != RIP_DEFAULT) {
@ -598,45 +671,32 @@ trace_upslot(struct rt_entry *rt,
rts - rt->rt_spares, rts - rt->rt_spares,
trace_pair(rt->rt_dst, rt->rt_mask, trace_pair(rt->rt_dst, rt->rt_mask,
naddr_ntoa(rts->rts_gate))); naddr_ntoa(rts->rts_gate)));
if (rts->rts_gate != rts->rts_gate) print_rts(rts, 0,0,
(void)fprintf(ftrace, "router=%s ", rts->rts_gate != gate,
naddr_ntoa(rts->rts_gate)); rts->rts_tag != tag,
if (rts->rts_tag != 0) rts != rt->rt_spares || AGE_RT(rt->rt_state,
(void)fprintf(ftrace, "tag=%#x ", ntohs(rts->rts_tag)); rt->rt_ifp));
(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));
(void)fprintf(ftrace, " %19s%-16s ", (void)fprintf(ftrace, "\n %19s%-16s ", "",
"",
gate != rts->rts_gate ? naddr_ntoa(gate) : ""); gate != rts->rts_gate ? naddr_ntoa(gate) : "");
if (gate != router) print_rts(&new,
(void)fprintf(ftrace,"router=%s ",naddr_ntoa(router)); -(metric == rts->rts_metric),
if (tag != rts->rts_tag) -(ifp == rts->rts_ifp),
(void)fprintf(ftrace, "tag=%#x ", ntohs(tag)); 0,
if (metric != rts->rts_metric) rts->rts_tag != tag,
(void)fprintf(ftrace, "metric=%-2d ", metric); new_time != rts->rts_time && (rts != rt->rt_spares
if (ifp != rts->rts_ifp && ifp != 0 ) || AGE_RT(rt->rt_state,
(void)fprintf(ftrace, "%s ", ifp->int_name); ifp)));
(void)fprintf(ftrace, "%s\n",
new_time != rts->rts_time ? ts(new_time) : "");
} else { } else {
(void)fprintf(ftrace, "Add #%d %-35s ", (void)fprintf(ftrace, "Add #%d %-35s ",
rts - rt->rt_spares, rts - rt->rt_spares,
trace_pair(rt->rt_dst, rt->rt_mask, trace_pair(rt->rt_dst, rt->rt_mask,
naddr_ntoa(gate))); naddr_ntoa(gate)));
if (gate != router) print_rts(&new, 0,0,0,0,
(void)fprintf(ftrace, "router=%s ", naddr_ntoa(gate)); rts != rt->rt_spares || AGE_RT(rt->rt_state,ifp));
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));
} }
(void)fputc('\n',ftrace);
} }
@ -701,6 +761,8 @@ trace_change(struct rt_entry *rt,
time_t new_time, time_t new_time,
char *label) char *label)
{ {
struct rt_spare new;
if (ftrace == 0) if (ftrace == 0)
return; return;
@ -710,67 +772,51 @@ trace_change(struct rt_entry *rt,
&& rt->rt_state == state && rt->rt_state == state
&& rt->rt_tag == tag) && rt->rt_tag == tag)
return; return;
new.rts_ifp = ifp;
new.rts_gate = gate;
new.rts_router = router;
new.rts_metric = metric;
new.rts_time = new_time;
new.rts_tag = tag;
lastlog(); lastlog();
(void)fprintf(ftrace, "%s %-35s metric=%-2d ", (void)fprintf(ftrace, "%s %-35s ",
label, label,
trace_pair(rt->rt_dst, rt->rt_mask, trace_pair(rt->rt_dst, rt->rt_mask,
naddr_ntoa(rt->rt_gate)), naddr_ntoa(rt->rt_gate)));
rt->rt_metric); print_rts(rt->rt_spares,
if (rt->rt_router != rt->rt_gate) 0,0,0,0, AGE_RT(rt->rt_state, rt->rt_ifp));
(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, rt->rt_state, rt->rt_state != state); 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), "", "", strlen(label), "", "",
rt->rt_gate != gate ? naddr_ntoa(gate) : ""); rt->rt_gate != gate ? naddr_ntoa(gate) : "");
if (rt->rt_metric != metric) print_rts(&new,
(void)fprintf(ftrace, "metric=%-2d ", metric); -(metric == rt->rt_metric),
if (router != gate) -(ifp == rt->rt_ifp),
(void)fprintf(ftrace, "router=%s ", naddr_ntoa(router)); 0,
if (rt->rt_tag != tag) rt->rt_tag != tag,
(void)fprintf(ftrace, "tag=%#x ", ntohs(tag)); rt->rt_time != new_time && AGE_RT(rt->rt_state,ifp));
if (rt->rt_state != state) if (rt->rt_state != state)
trace_bits(rs_bits, state, 1); trace_bits(rs_bits, state, 1);
if (rt->rt_ifp != ifp) (void)fputc('\n',ftrace);
(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 void
trace_add_del(char * action, struct rt_entry *rt) trace_add_del(char * action, struct rt_entry *rt)
{ {
u_int state = rt->rt_state;
if (ftrace == 0) if (ftrace == 0)
return; return;
lastlog(); lastlog();
(void)fprintf(ftrace, "%s %-35s metric=%-2d ", (void)fprintf(ftrace, "%s %-35s ",
action, action,
trace_pair(rt->rt_dst, rt->rt_mask, trace_pair(rt->rt_dst, rt->rt_mask,
naddr_ntoa(rt->rt_gate)), naddr_ntoa(rt->rt_gate)));
rt->rt_metric); print_rts(rt->rt_spares, 0,0,0,0,AGE_RT(rt->rt_state,rt->rt_ifp));
if (rt->rt_router != rt->rt_gate) trace_bits(rs_bits, rt->rt_state, 0);
(void)fprintf(ftrace, "router=%s ", (void)fputc('\n',ftrace);
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));
} }
@ -781,42 +827,24 @@ walk_trace(struct radix_node *rn,
{ {
#define RT ((struct rt_entry *)rn) #define RT ((struct rt_entry *)rn)
struct rt_spare *rts; struct rt_spare *rts;
int i, age; int i, age = AGE_RT(RT->rt_state, RT->rt_ifp);
(void)fprintf(ftrace, " %-35s metric=%-2d ", (void)fprintf(ftrace, " %-35s ", trace_pair(RT->rt_dst, RT->rt_mask,
trace_pair(RT->rt_dst, RT->rt_mask, naddr_ntoa(RT->rt_gate)));
naddr_ntoa(RT->rt_gate)), print_rts(&RT->rt_spares[0], 0,0,0,0,age);
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, RT->rt_state, 0); trace_bits(rs_bits, RT->rt_state, 0);
(void)fprintf(ftrace, "%s ", if (RT->rt_poison_time >= now_garbage
RT->rt_ifp == 0 ? "?" : RT->rt_ifp->int_name); && RT->rt_poison_metric < RT->rt_metric)
age = AGE_RT(RT->rt_state, RT->rt_ifp); (void)fprintf(ftrace, "pm=%d@%s",
if (age) RT->rt_poison_metric,
(void)fprintf(ftrace, "%s", ts(RT->rt_time)); ts(RT->rt_poison_time));
rts = &RT->rt_spares[1]; rts = &RT->rt_spares[1];
for (i = 1; i < NUM_SPARES; i++, rts++) { for (i = 1; i < NUM_SPARES; i++, rts++) {
if (rts->rts_metric != HOPCNT_INFINITY) { if (rts->rts_gate != RIP_DEFAULT) {
(void)fprintf(ftrace,"\n #%d%15s%-16s metric=%-2d ", (void)fprintf(ftrace,"\n #%d%15s%-16s ",
i, "", naddr_ntoa(rts->rts_gate), i, "", naddr_ntoa(rts->rts_gate));
rts->rts_metric); print_rts(rts, 0,0,0,0,1);
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));
} }
} }
(void)fputc('\n',ftrace); (void)fputc('\n',ftrace);
@ -834,6 +862,7 @@ trace_dump(void)
return; return;
lastlog(); lastlog();
(void)fputs("current daemon state:\n", ftrace);
for (ifp = ifnet; ifp != 0; ifp = ifp->int_next) for (ifp = ifnet; ifp != 0; ifp = ifp->int_next)
trace_if("", ifp); trace_if("", ifp);
(void)rn_walktree(rhead, walk_trace, 0); (void)rn_walktree(rhead, walk_trace, 0);
@ -976,7 +1005,8 @@ trace_rip(char *dir1, char *dir2,
break; break;
case RIPCMD_TRACEON: case RIPCMD_TRACEON:
fprintf(ftrace, "\tfile=%*s\n", size-4, msg->rip_tracefile); fprintf(ftrace, "\tfile=\"%.*s\"\n", size-4,
msg->rip_tracefile);
break; break;
case RIPCMD_TRACEOFF: case RIPCMD_TRACEOFF: