From a30febec0e1b05d4c0a1c9329cb2bd3467888172 Mon Sep 17 00:00:00 2001 From: Garrett Wollman Date: Wed, 11 Dec 1996 21:04:17 +0000 Subject: [PATCH] Merge from vendor branch. --- sbin/routed/defs.h | 47 ++++++++++--------- sbin/routed/main.c | 88 ++++++++++++++++++++++++----------- sbin/routed/routed.8 | 26 ++++++++--- sbin/routed/rtquery/rtquery.c | 1 - sbin/routed/table.c | 46 +++++++++--------- 5 files changed, 132 insertions(+), 76 deletions(-) diff --git a/sbin/routed/defs.h b/sbin/routed/defs.h index d87029d14560..1f8ec00d100b 100644 --- a/sbin/routed/defs.h +++ b/sbin/routed/defs.h @@ -31,7 +31,7 @@ * SUCH DAMAGE. * * @(#)defs.h 8.1 (Berkeley) 6/5/93 - * $Id: defs.h,v 1.3 1996/11/19 20:42:11 wollman Exp $ + * $Id: defs.h,v 1.4 1996/12/10 17:07:36 wollman Exp $ */ /* Definitions for RIPv2 routing process. @@ -119,7 +119,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 @@ -288,15 +289,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; @@ -313,10 +312,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 */ @@ -395,7 +394,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 */ @@ -471,13 +470,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; @@ -495,7 +495,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 *, @@ -503,8 +503,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)) @@ -524,15 +528,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 *, ...); @@ -615,7 +620,7 @@ 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 *); #include diff --git a/sbin/routed/main.c b/sbin/routed/main.c index dc0b1d88ab63..36399e999a70 100644 --- a/sbin/routed/main.c +++ b/sbin/routed/main.c @@ -39,7 +39,6 @@ static char sccsid[] = "@(#)main.c 8.1 (Berkeley) 6/5/93"; #elif defined(__NetBSD__) static char rcsid[] = "$NetBSD$"; #endif -#ident "$Revision: 1.18 $" #include "defs.h" #include "pathnames.h" @@ -201,10 +200,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 +220,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 +267,16 @@ main(int argc, 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 +299,11 @@ main(int argc, 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 +356,8 @@ main(int argc, 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 +493,7 @@ main(int argc, /* ARGSUSED */ void -sigalrm(int sig) +sigalrm(int s) { /* Historically, SIGALRM would cause the daemon to check for * new and broken interfaces. @@ -816,20 +818,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 +872,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/routed.8 b/sbin/routed/routed.8 index 5eaaff2be96f..8771654dfb0b 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/rtquery/rtquery.c b/sbin/routed/rtquery/rtquery.c index 42d4d6ee2099..f5421471e6ed 100644 --- a/sbin/routed/rtquery/rtquery.c +++ b/sbin/routed/rtquery/rtquery.c @@ -40,7 +40,6 @@ static char sccsid[] = "@(#)query.c 8.1 (Berkeley) 6/5/93"; #elif defined(__NetBSD__) static char rcsid[] = "$NetBSD$"; #endif -#ident "$Revision: 1.1.1.2 $" #include #include diff --git a/sbin/routed/table.c b/sbin/routed/table.c index dda559a295fe..a7c230339e8a 100644 --- a/sbin/routed/table.c +++ b/sbin/routed/table.c @@ -745,7 +745,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]; @@ -831,8 +831,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; } @@ -859,20 +858,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; } @@ -892,17 +903,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); } @@ -916,8 +920,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; }