From 7b6ab19dde850fe54facf1dbc5b00466a0a12b53 Mon Sep 17 00:00:00 2001 From: Garrett Wollman Date: Mon, 16 Sep 1996 16:51:32 +0000 Subject: [PATCH] Virgin import of new BSD/SGI routed. This update contains a number of important bug fixes. Obtained from: Vernon J. Schryver --- {usr.sbin => sbin}/routed/Makefile | 0 {usr.sbin => sbin}/routed/defs.h | 22 ++- {usr.sbin => sbin}/routed/if.c | 49 ++++-- {usr.sbin => sbin}/routed/input.c | 173 +++++++++++--------- {usr.sbin => sbin}/routed/main.c | 24 ++- {usr.sbin => sbin}/routed/output.c | 80 +++++---- {usr.sbin => sbin}/routed/parms.c | 24 ++- {usr.sbin => sbin}/routed/pathnames.h | 5 +- {usr.sbin => sbin}/routed/radix.c | 0 {usr.sbin => sbin}/routed/radix.h | 0 {usr.sbin => sbin}/routed/rdisc.c | 0 {usr.sbin => sbin}/routed/routed.8 | 3 + {usr.sbin => sbin}/routed/routed.h | 0 {usr.sbin => sbin}/routed/rtquery/Makefile | 0 {usr.sbin => sbin}/routed/rtquery/rtquery.8 | 8 +- {usr.sbin => sbin}/routed/rtquery/rtquery.c | 19 ++- {usr.sbin => sbin}/routed/table.c | 36 ++-- {usr.sbin => sbin}/routed/trace.c | 111 +++++++++++-- usr.sbin/routed/Makefile.inc | 1 - usr.sbin/routed/rttrace/Makefile | 6 - usr.sbin/routed/rttrace/rttrace.c | 146 ----------------- 21 files changed, 377 insertions(+), 330 deletions(-) rename {usr.sbin => sbin}/routed/Makefile (100%) rename {usr.sbin => sbin}/routed/defs.h (97%) rename {usr.sbin => sbin}/routed/if.c (96%) rename {usr.sbin => sbin}/routed/input.c (84%) rename {usr.sbin => sbin}/routed/main.c (98%) rename {usr.sbin => sbin}/routed/output.c (96%) rename {usr.sbin => sbin}/routed/parms.c (97%) rename {usr.sbin => sbin}/routed/pathnames.h (92%) rename {usr.sbin => sbin}/routed/radix.c (100%) rename {usr.sbin => sbin}/routed/radix.h (100%) rename {usr.sbin => sbin}/routed/rdisc.c (100%) rename {usr.sbin => sbin}/routed/routed.8 (99%) rename {usr.sbin => sbin}/routed/routed.h (100%) rename {usr.sbin => sbin}/routed/rtquery/Makefile (100%) rename {usr.sbin => sbin}/routed/rtquery/rtquery.8 (92%) rename {usr.sbin => sbin}/routed/rtquery/rtquery.c (97%) rename {usr.sbin => sbin}/routed/table.c (98%) rename {usr.sbin => sbin}/routed/trace.c (88%) delete mode 100644 usr.sbin/routed/Makefile.inc delete mode 100644 usr.sbin/routed/rttrace/Makefile delete mode 100644 usr.sbin/routed/rttrace/rttrace.c diff --git a/usr.sbin/routed/Makefile b/sbin/routed/Makefile similarity index 100% rename from usr.sbin/routed/Makefile rename to sbin/routed/Makefile diff --git a/usr.sbin/routed/defs.h b/sbin/routed/defs.h similarity index 97% rename from usr.sbin/routed/defs.h rename to sbin/routed/defs.h index f64991222191..452b71aa067e 100644 --- a/usr.sbin/routed/defs.h +++ b/sbin/routed/defs.h @@ -36,7 +36,7 @@ */ #ifndef __NetBSD__ -#ident "$Revision: 1.13 $" +#ident "$Revision: 1.16 $" #endif /* Definitions for RIPv2 routing process. @@ -178,7 +178,6 @@ struct rt_entry { # define RS_MHOME 0x020 /* from -m */ # define RS_STATIC 0x040 /* from the kernel */ # define RS_RDISC 0x080 /* from router discovery */ -# define RS_PERMANENT (RS_MHOME | RS_STATIC | RS_NET_SYN | RS_RDISC) struct sockaddr_in rt_dst_sock; naddr rt_mask; struct rt_spare { @@ -212,11 +211,12 @@ struct rt_entry { * nor non-passive, remote interfaces that are not aliases * (i.e. remote & metric=0) */ -#define AGE_RT(rt,ifp) (0 == ((rt)->rt_state & RS_PERMANENT) \ - && (!((rt)->rt_state & RS_IF) \ - || (ifp) == 0 \ - || (((ifp)->int_state & IS_REMOTE) \ - && !((ifp)->int_state & IS_PASSIVE)))) +#define AGE_RT(rt_state,ifp) (0 == ((rt_state) & (RS_MHOME | RS_STATIC \ + | RS_NET_SYN | RS_RDISC)) \ + && (!((rt_state) & RS_IF) \ + || (ifp) == 0 \ + || (((ifp)->int_state & IS_REMOTE) \ + && !((ifp)->int_state & IS_PASSIVE)))) /* true if A is better than B * Better if @@ -256,7 +256,7 @@ struct interface { naddr int_std_net; /* class A/B/C network (h) */ naddr int_std_mask; /* class A/B/C netmask (h) */ int int_rip_sock; /* for queries */ - int int_if_flags; /* copied from kernel */ + int int_if_flags; /* some bits copied from kernel */ u_int int_state; time_t int_act_time; /* last thought healthy */ u_short int_transitions; /* times gone up-down */ @@ -279,6 +279,7 @@ struct interface { struct timeval int_rdisc_timer; }; +/* bits in int_state */ #define IS_ALIAS 0x0000001 /* interface alias */ #define IS_SUBNET 0x0000002 /* interface on subnetted network */ #define IS_REMOTE 0x0000004 /* interface is not on this machine */ @@ -407,6 +408,7 @@ extern int auth_ok; /* 1=ignore auth if we do not care */ extern struct timeval epoch; /* when started */ extern struct timeval now; /* current idea of time */ extern time_t now_stale; +extern time_t now_expire; extern time_t now_garbage; extern struct timeval next_bcast; /* next general broadcast */ @@ -428,7 +430,8 @@ extern struct timeval need_kern; /* need to update kernel table */ extern int update_seqno; /* a route has changed */ extern u_int tracelevel, new_tracelevel; -#define MAX_TRACELEVEL 3 +#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) @@ -483,6 +486,7 @@ extern void trace_on(char *, int); extern void trace_off(char*, ...); extern void trace_flush(void); extern void set_tracelevel(void); +extern void trace_kernel(char *, ...); extern void trace_act(char *, ...); extern void trace_pkt(char *, ...); extern void trace_add_del(char *, struct rt_entry *); diff --git a/usr.sbin/routed/if.c b/sbin/routed/if.c similarity index 96% rename from usr.sbin/routed/if.c rename to sbin/routed/if.c index 7143b319c54c..539b07323e3a 100644 --- a/usr.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.16 $" +#ident "$Revision: 1.17 $" #include "defs.h" #include "pathnames.h" @@ -454,12 +454,13 @@ ifinit(void) # define COMP_NOT_INET 0x001 # define COMP_WIERD 0x002 # define COMP_NOADDR 0x004 -# define COMP_NODST 0x008 -# define COMP_NOBADR 0x010 -# define COMP_NOMASK 0x020 -# define COMP_DUP 0x040 -# define COMP_BAD_METRIC 0x080 -# define COMP_NETMASK 0x100 +# define COMP_BADADDR 0x008 +# define COMP_NODST 0x010 +# define COMP_NOBADR 0x020 +# define COMP_NOMASK 0x040 +# define COMP_DUP 0x080 +# define COMP_BAD_METRIC 0x100 +# define COMP_NETMASK 0x200 struct interface ifs, ifs0, *ifp, *ifp1; struct rt_entry *rt; @@ -548,7 +549,7 @@ ifinit(void) if (INFO_IFA(&info) == 0) { if (iff_alive(ifs.int_if_flags)) { if (!(prev_complaints & COMP_NOADDR)) - msglog("%s has a bad address", + msglog("%s has no address", sdl->sdl_data); complaints |= COMP_NOADDR; } @@ -569,6 +570,17 @@ ifinit(void) ifs.int_addr = S_ADDR(INFO_IFA(&info)); + if (ntohl(ifs.int_addr)>>24 == 0 + || ntohl(ifs.int_addr)>>24 == 0xff) { + if (iff_alive(ifs.int_if_flags)) { + if (!(prev_complaints & COMP_BADADDR)) + msglog("%s has a bad address", + sdl->sdl_data); + complaints |= COMP_BADADDR; + } + continue; + } + if (ifs.int_if_flags & IFF_BROADCAST) { if (INFO_MASK(&info) == 0) { if (iff_alive(ifs.int_if_flags)) { @@ -612,6 +624,17 @@ ifinit(void) continue; } ifs.int_dstaddr = S_ADDR(INFO_BRD(&info)); + if (ntohl(ifs.int_dstaddr)>>24 == 0 + || ntohl(ifs.int_dstaddr)>>24 == 0xff) { + if (iff_alive(ifs.int_if_flags)) { + if (!(prev_complaints & COMP_NODST)) + msglog("%s has a bad" + " destination address", + sdl->sdl_data); + complaints |= COMP_NODST; + } + continue; + } ifs.int_mask = HOST_MASK; ifs.int_ripv1_mask = ntohl(S_ADDR(INFO_MASK(&info))); ifs.int_net = ntohl(ifs.int_dstaddr); @@ -949,12 +972,10 @@ ifinit(void) /* If we ever have a RIPv1 interface, assume we always will. * It might come back if it ever goes away. */ - if (!(ifp->int_if_flags & IFF_LOOPBACK)) { - if (!(ifp->int_state & IS_NO_RIPV1_OUT)) - have_ripv1_out = 1; - if (!(ifp->int_state & IS_NO_RIPV1_IN)) - have_ripv1_in = 1; - } + if (!(ifp->int_state & IS_NO_RIPV1_OUT) && supplier) + have_ripv1_out = 1; + if (!(ifp->int_state & IS_NO_RIPV1_IN)) + have_ripv1_in = 1; } for (ifp = ifnet; ifp != 0; ifp = ifp->int_next) { diff --git a/usr.sbin/routed/input.c b/sbin/routed/input.c similarity index 84% rename from usr.sbin/routed/input.c rename to sbin/routed/input.c index 6bbc572af577..a854c41914e4 100644 --- a/usr.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.13 $" +#ident "$Revision: 1.16 $" #include "defs.h" @@ -69,9 +69,7 @@ read_rip(int sock, logbad(1,"impossible recvfrom(rip) fromlen=%d", fromlen); - input(&from, - (ifp != 0) ? ifp : iflookup(from.sin_addr.s_addr), - &inbuf.rip, cc); + input(&from, ifp, &inbuf.rip, cc); } } @@ -80,7 +78,7 @@ read_rip(int sock, */ static void input(struct sockaddr_in *from, /* received from this IP address */ - struct interface *ifp, + struct interface *sifp, /* interface by which it arrived */ struct rip *rip, int size) { @@ -88,17 +86,21 @@ input(struct sockaddr_in *from, /* received from this IP address */ static naddr use_auth, bad_len, bad_mask; static naddr unk_router, bad_router, bad_nhop; + struct interface *aifp; /* interface if via 1 hop */ struct rt_entry *rt; struct netinfo *n, *lim; struct interface *ifp1; naddr gate, mask, v1_mask, dst, ddst_h; int i; + aifp = iflookup(from->sin_addr.s_addr); + if (sifp == 0) + sifp = aifp; - if (ifp != 0) - ifp->int_state |= IS_ACTIVE; + if (sifp != 0) + sifp->int_state |= IS_ACTIVE; - trace_rip("Recv", "from", from, ifp, rip, size); + trace_rip("Recv", "from", from, sifp, rip, size); if (rip->rip_vers == 0) { if (from->sin_addr.s_addr != bad_router) @@ -107,6 +109,8 @@ input(struct sockaddr_in *from, /* received from this IP address */ rip->rip_cmd, naddr_ntoa(FROM_NADDR)); bad_router = from->sin_addr.s_addr; return; + } else if (rip->rip_vers > RIPv2) { + rip->rip_vers = RIPv2; } if (size > MAXPACKETSIZE) { if (from->sin_addr.s_addr != bad_router) @@ -131,7 +135,7 @@ input(struct sockaddr_in *from, /* received from this IP address */ * RIPv1 systems will listen? Crazy! */ if (!auth_ok - && rip->rip_vers >= RIPv2 + && rip->rip_vers == RIPv2 && n < lim && n->n_family == RIP_AF_AUTH) { if (from->sin_addr.s_addr != use_auth) msglog("RIPv2 message with authentication" @@ -187,32 +191,42 @@ input(struct sockaddr_in *from, /* received from this IP address */ * We respond to routers only if we are acting * as a supplier, or to anyone other than a router * (i.e. a query). - * - * Answer a query from a stray program with all - * we know. Filter the answer to a query from a - * router in the about same way broadcasts are - * filtered. - * - * Only answer a router if we are a supplier - * to keep an unwary host that is just starting - * from picking us an a router. */ if (n->n_family == RIP_AF_UNSPEC && n->n_metric == HOPCNT_INFINITY && n == rip->rip_nets && n+1 == lim) { if (from->sin_port != htons(RIP_PORT)) { - /* query from `rtquery` or similar + /* Answer a query from a utility + * program with all we know. */ - supply(from, ifp, - OUT_QUERY, 0, rip->rip_vers); - } else if (supplier) { - /* a router trying to prime its - * tables. - */ - supply(from, ifp, - OUT_UNICAST, 0, rip->rip_vers); + supply(from, sifp, OUT_QUERY, 0, + rip->rip_vers); + return; } + /* A router trying to prime its tables. + * Filter the answer in the about same way + * broadcasts are filtered. + * + * Only answer a router if we are a supplier + * to keep an unwary host that is just starting + * from picking us as a router. Respond with + * RIPv1 instead of RIPv2 if that is what we + * are broadcasting on the interface to keep + * the remote router from getting the wrong + * initial idea of the routes we send. + */ + if (!supplier + || aifp == 0 + || (aifp->int_state & IS_PASSIVE) + || (aifp->int_state & IS_ALIAS) + || ((aifp->int_state & IS_NO_RIPV1_OUT) + && (aifp->int_state&IS_NO_RIPV2_OUT))) + return; + + supply(from, aifp, OUT_UNICAST, 0, + (aifp->int_state&IS_NO_RIPV1_OUT) + ? RIPv2 : RIPv1); return; } @@ -241,7 +255,7 @@ input(struct sockaddr_in *from, /* received from this IP address */ if (rip->rip_vers == RIPv1 || 0 == (mask = ntohl(n->n_mask)) || 0 != (ntohl(dst) & ~mask)) - mask = ripv1_mask_host(dst,ifp); + mask = ripv1_mask_host(dst,sifp); rt = rtget(dst, mask); if (!rt && dst != RIP_DEFAULT) @@ -258,16 +272,16 @@ input(struct sockaddr_in *from, /* received from this IP address */ n->n_metric = HOPCNT_INFINITY; } else { n->n_metric = rt->rt_metric+1; - n->n_metric += (ifp!=0) ? ifp->int_metric : 1; + n->n_metric += (sifp!=0)?sifp->int_metric : 1; if (n->n_metric > HOPCNT_INFINITY) n->n_metric = HOPCNT_INFINITY; if (rip->rip_vers != RIPv1) { n->n_tag = rt->rt_tag; - if (ifp != 0 + if (sifp != 0 && on_net(rt->rt_gate, - ifp->int_net, - ifp->int_mask) - && rt->rt_gate != ifp->int_addr) + sifp->int_net, + sifp->int_mask) + && rt->rt_gate != sifp->int_addr) n->n_nhop = rt->rt_gate; } } @@ -284,9 +298,9 @@ input(struct sockaddr_in *from, /* received from this IP address */ rip->rip_vers = RIPv2; if (from->sin_port != htons(RIP_PORT)) { /* query */ - (void)output(OUT_QUERY, from, ifp, rip, size); + (void)output(OUT_QUERY, from, sifp, rip, size); } else if (supplier) { - (void)output(OUT_UNICAST, from, ifp, rip, size); + (void)output(OUT_UNICAST, from, sifp, rip, size); } return; @@ -298,7 +312,7 @@ input(struct sockaddr_in *from, /* received from this IP address */ naddr_ntoa(FROM_NADDR)); return; } - if (ifp == 0) { + if (aifp == 0) { msglog("trace command from unknown router %s", naddr_ntoa(FROM_NADDR)); return; @@ -357,26 +371,27 @@ input(struct sockaddr_in *from, /* received from this IP address */ * broadcast or point-to-point networks, and from * those listed in /etc/gateways. */ - if (!ifp) { + if (!aifp) { if (from->sin_addr.s_addr != unk_router) - msglog("packet from unknown router %s" + msglog("discard packet from unknown router %s" " or via unidentified interface", naddr_ntoa(FROM_NADDR)); unk_router = from->sin_addr.s_addr; return; } - if (ifp->int_state & IS_PASSIVE) { - trace_act("packet from %s via passive interface %s\n", + if (aifp->int_state & IS_PASSIVE) { + trace_act("discard packet from %s" + " via passive interface %s\n", naddr_ntoa(FROM_NADDR), - ifp->int_name); + aifp->int_name); return; } /* Check required version */ - if (((ifp->int_state & IS_NO_RIPV1_IN) + if (((aifp->int_state & IS_NO_RIPV1_IN) && rip->rip_vers == RIPv1) - || ((ifp->int_state & IS_NO_RIPV2_IN) + || ((aifp->int_state & IS_NO_RIPV2_IN) && rip->rip_vers != RIPv1)) { trace_pkt("discard RIPv%d response\n", rip->rip_vers); @@ -385,15 +400,15 @@ input(struct sockaddr_in *from, /* received from this IP address */ /* Ignore routes via dead interface. */ - if (ifp->int_state & IS_BROKE) { + if (aifp->int_state & IS_BROKE) { trace_pkt("discard response via broken interface %s\n", - ifp->int_name); + aifp->int_name); return; } /* Authenticate the packet if we have a secret. */ - if (ifp->int_passwd[0] != '\0') { + if (aifp->int_passwd[0] != '\0') { if (n >= lim || n->n_family != RIP_AF_AUTH || ((struct netauth*)n)->a_type != RIP_AUTH_PW) { @@ -404,8 +419,8 @@ input(struct sockaddr_in *from, /* received from this IP address */ return; } else if (0 != bcmp(((struct netauth*)n)->au.au_pw, - ifp->int_passwd, - sizeof(ifp->int_passwd))) { + aifp->int_passwd, + sizeof(aifp->int_passwd))) { if (from->sin_addr.s_addr != use_auth) msglog("bad password from %s", naddr_ntoa(FROM_NADDR)); @@ -456,31 +471,31 @@ input(struct sockaddr_in *from, /* received from this IP address */ /* Notice the next-hop. */ gate = from->sin_addr.s_addr; - if (n->n_nhop != 0 - && rip->rip_vers == RIPv2) { - /* Ignore the route if it points to us */ - if (0 != ifwithaddr(n->n_nhop, 1, 0)) - continue; - - /* Use it only if it is valid. */ - if (on_net(n->n_nhop, - ifp->int_net, ifp->int_mask) - && check_dst(n->n_nhop)) { - gate = n->n_nhop; + if (n->n_nhop != 0) { + if (rip->rip_vers == RIPv2) { + n->n_nhop = 0; } else { + /* Use it only if it is valid. */ + if (on_net(n->n_nhop, + aifp->int_net, aifp->int_mask) + && check_dst(n->n_nhop)) { + gate = n->n_nhop; + } else { if (bad_nhop != from->sin_addr.s_addr) - msglog("router %s to %s has" - " bad next hop %s", - naddr_ntoa(FROM_NADDR), - naddr_ntoa(dst), - naddr_ntoa(n->n_nhop)); + msglog("router %s to %s has" + " bad next hop %s", + naddr_ntoa(FROM_NADDR), + naddr_ntoa(dst), + naddr_ntoa(n->n_nhop)); bad_nhop = from->sin_addr.s_addr; + n->n_nhop = 0; + } } } if (rip->rip_vers == RIPv1 || 0 == (mask = ntohl(n->n_mask))) { - mask = ripv1_mask_host(dst,ifp); + mask = ripv1_mask_host(dst,aifp); } else if ((ntohl(dst) & ~mask) != 0) { if (bad_mask != from->sin_addr.s_addr) { msglog("router %s sent bad netmask" @@ -497,7 +512,7 @@ input(struct sockaddr_in *from, /* received from this IP address */ /* Adjust metric according to incoming interface.. */ - n->n_metric += ifp->int_metric; + n->n_metric += aifp->int_metric; if (n->n_metric > HOPCNT_INFINITY) n->n_metric = HOPCNT_INFINITY; @@ -507,9 +522,9 @@ input(struct sockaddr_in *from, /* received from this IP address */ * Be a little more paranoid than that, and reject * default routes with the same metric we advertised. */ - if (ifp->int_d_metric != 0 + if (aifp->int_d_metric != 0 && dst == RIP_DEFAULT - && n->n_metric >= ifp->int_d_metric) + && n->n_metric >= aifp->int_d_metric) continue; /* We can receive aggregated RIPv2 routes that must @@ -558,7 +573,7 @@ input(struct sockaddr_in *from, /* received from this IP address */ } for (;;) { - input_route(ifp, FROM_NADDR, + input_route(aifp, FROM_NADDR, dst, mask, gate, n); if (i-- == 0) break; @@ -610,6 +625,14 @@ input_route(struct interface *ifp, if (n->n_metric == HOPCNT_INFINITY) return; + /* Ignore the route if it points to us */ + if (n->n_nhop != 0 + && 0 != ifwithaddr(n->n_nhop, 1, 0)) + return; + + /* If something has not gone crazy and tried to fill + * our memory, accept the new route. + */ if (total_routes < MAX_ROUTES) rtadd(dst, mask, gate, from, n->n_metric, n->n_tag, 0, ifp); @@ -630,10 +653,8 @@ input_route(struct interface *ifp, * synthetic, RIPv1 network route of our own. * The worst is that both kinds of routes might be * received, and the bad one might have the smaller - * metric. Partly solve this problem by faking the - * RIPv1 route with a metric that reflects the most - * distant part of the subnet. Also never - * aggregate into such a route. Also keep it + * metric. Partly solve this problem by never + * aggregating into such a route. Also keep it * around as long as the interface exists. */ @@ -686,7 +707,13 @@ input_route(struct interface *ifp, } else { /* The update is for a route we know about, * but not from a familiar router. + * + * Ignore the route if it points to us. */ + if (n->n_nhop != 0 + && 0 != ifwithaddr(n->n_nhop, 1, 0)) + return; + rts = rts0; /* Save the route as a spare only if it has diff --git a/usr.sbin/routed/main.c b/sbin/routed/main.c similarity index 98% rename from usr.sbin/routed/main.c rename to sbin/routed/main.c index 700762ed5dcb..84a7fac3dbe7 100644 --- a/usr.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.14 $" +#ident "$Revision: 1.17 $" #include "defs.h" #include "pathnames.h" @@ -70,6 +70,7 @@ struct timeval epoch; /* when started */ struct timeval clk, prev_clk; struct timeval now; /* current idea of time */ time_t now_stale; +time_t now_expire; time_t now_garbage; struct timeval next_bcast; /* next general broadcast */ @@ -111,6 +112,7 @@ main(int argc, epoch.tv_sec -= EPOCH; now.tv_sec = EPOCH; now_stale = EPOCH - STALE_TIME; + now_expire = EPOCH - EXPIRE_TIME; now_garbage = EPOCH - GARBAGE_TIME; wtime.tv_sec = 0; @@ -247,6 +249,16 @@ main(int argc, } + signal(SIGALRM, sigalrm); + if (!background) + signal(SIGHUP, sigterm); /* SIGHUP fatal during debugging */ + else + signal(SIGHUP, SIG_IGN); + signal(SIGTERM, sigterm); + signal(SIGINT, sigterm); + signal(SIGUSR1, sigtrace_on); + signal(SIGUSR2, sigtrace_off); + /* get into the background */ if (background) { #ifdef sgi @@ -275,7 +287,7 @@ main(int argc, if (setsockopt(rt_sock, SOL_SOCKET,SO_USELOOPBACK, &off,sizeof(off)) < 0) LOGERR("setsockopt(SO_USELOOPBACK,0)"); - + fix_select(); @@ -304,13 +316,6 @@ main(int argc, rdisc_timer = next_bcast; ifinit_timer.tv_usec = next_bcast.tv_usec; - signal(SIGALRM, sigalrm); - signal(SIGHUP, sigterm); - signal(SIGTERM, sigterm); - signal(SIGINT, sigterm); - signal(SIGUSR1, sigtrace_on); - signal(SIGUSR2, sigtrace_off); - /* Collect an initial view of the world by checking the interface * configuration and the kludge file. */ @@ -342,6 +347,7 @@ main(int argc, } timevalsub(&now, &clk, &epoch); now_stale = now.tv_sec - STALE_TIME; + now_expire = now.tv_sec - EXPIRE_TIME; now_garbage = now.tv_sec - GARBAGE_TIME; /* deal with interrupts that should affect tracing */ diff --git a/usr.sbin/routed/output.c b/sbin/routed/output.c similarity index 96% rename from usr.sbin/routed/output.c rename to sbin/routed/output.c index be30609743a7..eafcf31e7864 100644 --- a/usr.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.16 $" +#ident "$Revision: 1.17 $" #include "defs.h" @@ -263,7 +263,7 @@ supply_out(struct ag_info *ag) && (ws.state & WS_ST_FLASH)) return; - /* Skip this route if required by split-horizon + /* Skip this route if required by split-horizon. */ if (ag->ag_state & AGS_SPLIT_HZ) return; @@ -363,7 +363,7 @@ walk_supply(struct radix_node *rn, struct walkarg *w) { #define RT ((struct rt_entry *)rn) - u_short ags = 0; + u_short ags; char metric, pref; naddr dst, nhop; @@ -371,7 +371,8 @@ walk_supply(struct radix_node *rn, /* Do not advertise the loopback interface * or external remote interfaces */ - if (RT->rt_ifp != 0 + if ((RT->rt_state & RS_IF) + && RT->rt_ifp != 0 && ((RT->rt_ifp->int_if_flags & IFF_LOOPBACK) || (RT->rt_ifp->int_state & IS_EXTERNAL)) && !(RT->rt_state & RS_MHOME)) @@ -429,32 +430,8 @@ walk_supply(struct radix_node *rn, nhop = 0; } - /* Adjust the outgoing metric by the cost of the link. - */ - pref = metric = RT->rt_metric + ws.metric; - if (pref < HOPCNT_INFINITY) { - /* Keep track of the best metric with which the - * route has been advertised recently. - */ - if (RT->rt_poison_metric >= metric - || RT->rt_poison_time <= now_garbage) { - RT->rt_poison_time = now.tv_sec; - RT->rt_poison_metric = RT->rt_metric; - } - - } else { - /* Do not advertise stable routes that will be ignored, - * unless they are being held down and poisoned. If the - * route recently was advertised with a metric that would - * have been less than infinity through this interface, we - * need to continue to advertise it in order to poison it. - */ - pref = RT->rt_poison_metric + ws.metric; - if (pref >= HOPCNT_INFINITY) - return 0; - - metric = HOPCNT_INFINITY; - } + metric = RT->rt_metric; + ags = 0; if (RT->rt_state & RS_MHOME) { /* retain host route of multi-homed servers */ @@ -521,8 +498,47 @@ walk_supply(struct radix_node *rn, && (ws.state & WS_ST_TO_ON_NET) && (!(RT->rt_state & RS_IF) || ws.ifp->int_if_flags & IFF_POINTOPOINT)) { - ags |= AGS_SPLIT_HZ; - ags &= ~(AGS_PROMOTE | AGS_SUPPRESS); + /* Poison-reverse the route instead of only not advertising it + * it is recently changed from some other 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 + * is brand new, there is no need for poison-reverse. + */ + metric = HOPCNT_INFINITY; + if (RT->rt_poison_time < now_expire + || RT->rt_spares[1].rts_gate ==0) { + ags |= AGS_SPLIT_HZ; + ags &= ~(AGS_PROMOTE | AGS_SUPPRESS); + } + } + + /* Adjust the outgoing metric by the cost of the link. + */ + pref = metric + ws.metric; + if (pref < HOPCNT_INFINITY) { + /* Keep track of the best metric with which the + * route has been advertised recently. + */ + if (RT->rt_poison_metric >= metric + || RT->rt_poison_time < now_expire) { + RT->rt_poison_time = now.tv_sec; + RT->rt_poison_metric = metric; + } + metric = pref; + + } else { + /* Do not advertise stable routes that will be ignored, + * unless they are being held down and poisoned. If the + * route recently was advertised with a metric that would + * have been less than infinity through this interface, we + * need to continue to advertise it in order to poison it. + */ + pref = RT->rt_poison_metric + ws.metric; + if (pref >= HOPCNT_INFINITY + || RT->rt_poison_time < now_garbage ) + return 0; + + metric = HOPCNT_INFINITY; } ag_check(dst, RT->rt_mask, 0, nhop, metric, pref, diff --git a/usr.sbin/routed/parms.c b/sbin/routed/parms.c similarity index 97% rename from usr.sbin/routed/parms.c rename to sbin/routed/parms.c index fcd37a6b6c3a..0d178c3698bc 100644 --- a/usr.sbin/routed/parms.c +++ b/sbin/routed/parms.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.8 $" +#ident "$Revision: 1.9 $" #include "defs.h" #include "pathnames.h" @@ -474,13 +474,6 @@ parse_parms(char *line) if (tgt != 0) return tgt; - if (parm.parm_int_state & IS_NO_ADV_IN) - parm.parm_int_state |= IS_NO_SOL_OUT; - - if ((parm.parm_int_state & (IS_NO_RIP | IS_NO_RDISC)) - == (IS_NO_RIP | IS_NO_RDISC)) - parm.parm_int_state |= IS_PASSIVE; - return check_parms(&parm); #undef DELIMS #undef PARS @@ -495,6 +488,21 @@ check_parms(struct parm *new) struct parm *parmp; + /* set implicit values + */ + if (!supplier && supplier_set) + new->parm_int_state |= (IS_NO_RIPV1_OUT + | IS_NO_RIPV2_OUT + | IS_NO_ADV_OUT); + if (new->parm_int_state & IS_NO_ADV_IN) + new->parm_int_state |= IS_NO_SOL_OUT; + + if ((new->parm_int_state & (IS_NO_RIP | IS_NO_RDISC)) + == (IS_NO_RIP | IS_NO_RDISC)) + new->parm_int_state |= IS_PASSIVE; + + /* compare with existing sets of parameters + */ for (parmp = parms; parmp != 0; parmp = parmp->parm_next) { if (strcmp(new->parm_name, parmp->parm_name)) continue; diff --git a/usr.sbin/routed/pathnames.h b/sbin/routed/pathnames.h similarity index 92% rename from usr.sbin/routed/pathnames.h rename to sbin/routed/pathnames.h index e9e6c48c6392..14b721c2d473 100644 --- a/usr.sbin/routed/pathnames.h +++ b/sbin/routed/pathnames.h @@ -43,5 +43,8 @@ * or be the same as the tracefile specified when the daemon was started. * If this is a directory, routed will create log files in it. That * might be a security problem. + * + * Leave this undefined, and only the trace file originally specified + * when routed was started, if any, will be appended to. */ -#define _PATH_TRACE "/tmp/routed.log" +#define _PATH_TRACE "/etc/routed.trace" diff --git a/usr.sbin/routed/radix.c b/sbin/routed/radix.c similarity index 100% rename from usr.sbin/routed/radix.c rename to sbin/routed/radix.c diff --git a/usr.sbin/routed/radix.h b/sbin/routed/radix.h similarity index 100% rename from usr.sbin/routed/radix.h rename to sbin/routed/radix.h diff --git a/usr.sbin/routed/rdisc.c b/sbin/routed/rdisc.c similarity index 100% rename from usr.sbin/routed/rdisc.c rename to sbin/routed/rdisc.c diff --git a/usr.sbin/routed/routed.8 b/sbin/routed/routed.8 similarity index 99% rename from usr.sbin/routed/routed.8 rename to sbin/routed/routed.8 index 828bdd89fb1c..de3abf34e84e 100644 --- a/usr.sbin/routed/routed.8 +++ b/sbin/routed/routed.8 @@ -298,6 +298,9 @@ does not care about authentication. .It Fl T Ar tracefile increases the debugging level to at least 1 and causes debugging information to be appended to the trace file. +Note that because of security concerns, it is wisest to not run +.Nm routed +routinely with tracing directed to a file. .It Fl t increases the debugging level, which causes more information to be logged on the tracefile specified with diff --git a/usr.sbin/routed/routed.h b/sbin/routed/routed.h similarity index 100% rename from usr.sbin/routed/routed.h rename to sbin/routed/routed.h diff --git a/usr.sbin/routed/rtquery/Makefile b/sbin/routed/rtquery/Makefile similarity index 100% rename from usr.sbin/routed/rtquery/Makefile rename to sbin/routed/rtquery/Makefile diff --git a/usr.sbin/routed/rtquery/rtquery.8 b/sbin/routed/rtquery/rtquery.8 similarity index 92% rename from usr.sbin/routed/rtquery/rtquery.8 rename to sbin/routed/rtquery/rtquery.8 index 1afb8b9478be..d77ca30b9c8f 100644 --- a/usr.sbin/routed/rtquery/rtquery.8 +++ b/sbin/routed/rtquery/rtquery.8 @@ -79,18 +79,20 @@ change tracing, where .Em op is one of the following. Requests from processes not running with UID 0 or on distant networks -are generally ignored. +are generally ignored by the daemon except for a message in the system log. .El .Bl -tag -width Ds -offset indent-two -.It Em on=filename +.It Em on=tracefile turn tracing on into the specified file. That file must usually have been specified when the daemon was started or be the same as a fixed name, often -.Pa /tmp/routed.log . +.Pa /etc/routed.trace . .It Em more increases the debugging level. .It Em off turns off tracing. +.It Em dump +dumps the daemon's routing table to the current tracefile. .El .Sh SEE ALSO .Xr routed 8 , diff --git a/usr.sbin/routed/rtquery/rtquery.c b/sbin/routed/rtquery/rtquery.c similarity index 97% rename from usr.sbin/routed/rtquery/rtquery.c rename to sbin/routed/rtquery/rtquery.c index cc1be10ab228..7d6913a048d7 100644 --- a/usr.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.8 $" +#ident "$Revision: 1.9 $" #include #include @@ -171,6 +171,8 @@ main(int argc, "more", # define TRACE_OFF 2 "off", +# define TRACE_DUMP 3 + "dump", 0 }; switch (getsubopt(&options,traceopts,&value)) { @@ -179,25 +181,30 @@ main(int argc, if (!value || strlen(value) > MAXPATHLEN) goto usage; - strcpy((char*)OMSG.rip_tracefile,value); - omsg_len += (strlen(value) - - sizeof(OMSG.ripun)); break; case TRACE_MORE: if (value) goto usage; OMSG.rip_cmd = RIPCMD_TRACEON; - OMSG.rip_tracefile[0] = '\0'; + value = ""; break; case TRACE_OFF: if (value) goto usage; OMSG.rip_cmd = RIPCMD_TRACEOFF; - OMSG.rip_tracefile[0] = '\0'; + value = ""; + break; + case TRACE_DUMP: + if (value) + goto usage; + OMSG.rip_cmd = RIPCMD_TRACEON; + value = "dump/../table"; break; default: goto usage; } + strcpy((char*)OMSG.rip_tracefile, value); + omsg_len += strlen(value) - sizeof(OMSG.ripun); } break; diff --git a/usr.sbin/routed/table.c b/sbin/routed/table.c similarity index 98% rename from usr.sbin/routed/table.c rename to sbin/routed/table.c index b1566a3792a8..6ad97f0ada15 100644 --- a/usr.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.23 $" +#ident "$Revision: 1.25 $" #include "defs.h" @@ -690,6 +690,13 @@ rtioctl(int action, /* RTM_DELETE, etc */ w.w_rtm.rtm_msglen -= (sizeof(w.w_mask) - w.w_mask.sin_len); #endif } + + if (TRACEKERNEL) + trace_kernel("write kernel %s %s->%s metric=%d flags=%#x\n", + rtm_type_name(action), + addrname(dst, mask, 0), naddr_ntoa(gate), + metric, flags); + #ifndef NO_INSTALL cc = write(rt_sock, &w, w.w_rtm.rtm_msglen); if (cc == w.w_rtm.rtm_msglen) @@ -850,6 +857,7 @@ rtm_add(struct rt_msghdr *rtm, k->k_state |= KS_GATEWAY; if (rtm->rtm_flags & RTF_STATIC) k->k_state |= KS_STATIC; + if (0 != (rtm->rtm_flags & (RTF_DYNAMIC | RTF_MODIFIED))) { if (supplier) { /* Routers are not supposed to listen to redirects, @@ -857,6 +865,7 @@ rtm_add(struct rt_msghdr *rtm, */ 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\n", addrname(k->k_dst, k->k_mask, 0), @@ -865,6 +874,7 @@ rtm_add(struct rt_msghdr *rtm, k->k_state |= KS_DYNAMIC; k->k_redirect_time = now.tv_sec; } + return; } /* If it is not a static route, quit until the next comparison @@ -1584,8 +1594,11 @@ rtchange(struct rt_entry *rt, * has gone bad, since there may be a working route that * aggregates this route. */ - if (metric == HOPCNT_INFINITY) + if (metric == HOPCNT_INFINITY) { need_kern.tv_sec = now.tv_sec; + if (new_time >= now.tv_sec - EXPIRE_TIME) + new_time = now.tv_sec - EXPIRE_TIME; + } rt->rt_seqno = update_seqno; set_need_flash(); } @@ -1598,6 +1611,11 @@ rtchange(struct rt_entry *rt, state |= (rt->rt_state & RS_SUBNET); + /* Keep various things from deciding ageless routes are stale. + */ + if (!AGE_RT(state, ifp)) + new_time = now.tv_sec; + if (TRACEACTIONS) trace_change(rt, state, gate, router, metric, tag, ifp, new_time, @@ -1643,12 +1661,8 @@ rtswitch(struct rt_entry *rt, /* Do not change permanent routes */ - if (0 != (rt->rt_state & RS_PERMANENT)) - return; - - /* Do not discard synthetic routes until they go bad */ - if ((rt->rt_state & RS_NET_SYN) - && rt->rt_metric < HOPCNT_INFINITY) + if (0 != (rt->rt_state & (RS_MHOME | RS_STATIC | RS_RDISC + | RS_NET_SYN | RS_IF))) return; /* find the best alternative among the spares */ @@ -1803,6 +1817,7 @@ walk_bad(struct radix_node *rn, if (rts->rts_ifp != 0 && (rts->rts_ifp->int_state & IS_BROKE)) { + /* mark the spare route to be deleted immediately */ new_time = rts->rts_time; if (new_time >= now_garbage) new_time = now_garbage-1; @@ -1857,9 +1872,10 @@ walk_age(struct radix_node *rn, ifp = rts->rts_ifp; if (i == NUM_SPARES) { - if (!AGE_RT(RT, ifp)) { + if (!AGE_RT(RT->rt_state, ifp)) { /* Keep various things from deciding ageless - * routes are stale */ + * routes are stale + */ rts->rts_time = now.tv_sec; continue; } diff --git a/usr.sbin/routed/trace.c b/sbin/routed/trace.c similarity index 88% rename from usr.sbin/routed/trace.c rename to sbin/routed/trace.c index e9c1e03f05aa..8a0b59ccb023 100644 --- a/usr.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.11 $" +#ident "$Revision: 1.13 $" #define RIPCMDS #include "defs.h" @@ -59,6 +59,8 @@ static char *tracelevel_pat = "%s\n"; char savetracename[MAXPATHLEN+1]; +static void trace_dump(void); + /* convert IP address to a string, but not into a single buffer */ @@ -205,21 +207,26 @@ trace_on(char *filename, } filename = savetracename; - } else if (stat(filename, &stbuf) >= 0) { - if (!trusted) { - msglog("trace file \"%s\" already exists"); - return; - } - if ((stbuf.st_mode & S_IFMT) != S_IFREG) { + } 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 (!trusted - && strcmp(filename, savetracename) - && strncmp(filename, _PATH_TRACE, sizeof(_PATH_TRACE)-1)) { - msglog("wrong directory for trace file: \"%s\"", +#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; } @@ -280,11 +287,13 @@ set_tracelevel(void) "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", }; @@ -567,6 +576,22 @@ trace_upslot(struct rt_entry *rt, } +/* talk about a change made to the kernel table + */ +void +trace_kernel(char *p, ...) +{ + va_list args; + + if (!TRACEKERNEL || ftrace == 0) + return; + + lastlog(); + va_start(args, p); + vfprintf(ftrace, p, args); +} + + /* display a message if tracing actions */ void @@ -635,7 +660,7 @@ trace_change(struct rt_entry *rt, (void)fprintf(ftrace, "%s ", rt->rt_ifp == 0 ? "?" : rt->rt_ifp->int_name); (void)fprintf(ftrace, "%s\n", - AGE_RT(rt, rt->rt_ifp) ? ts(rt->rt_time) : ""); + AGE_RT(rt->rt_state, rt->rt_ifp) ? ts(rt->rt_time) : ""); (void)fprintf(ftrace, "%*s %19s%-16s ", strlen(label), "", "", @@ -652,7 +677,7 @@ trace_change(struct rt_entry *rt, (void)fprintf(ftrace, "%s ", ifp != 0 ? ifp->int_name : "?"); (void)fprintf(ftrace, "%s\n", - ((rt->rt_time == new_time || !AGE_RT(rt, ifp)) + ((rt->rt_time == new_time || !AGE_RT(rt->rt_state, ifp)) ? "" : ts(new_time))); } @@ -683,6 +708,68 @@ trace_add_del(char * action, struct rt_entry *rt) } +/* ARGSUSED */ +static int +walk_trace(struct radix_node *rn, + struct walkarg *w) +{ +#define RT ((struct rt_entry *)rn) + struct rt_spare *rts; + int i, age; + + (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)); + 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)); + + 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)); + } + } + (void)fputc('\n',ftrace); + + return 0; +} + + +static void +trace_dump(void) +{ + if (ftrace == 0) + return; + lastlog(); + + (void)rn_walktree(rhead, walk_trace, 0); +} + + void trace_rip(char *dir1, char *dir2, struct sockaddr_in *who, diff --git a/usr.sbin/routed/Makefile.inc b/usr.sbin/routed/Makefile.inc deleted file mode 100644 index 10fa13f1ed80..000000000000 --- a/usr.sbin/routed/Makefile.inc +++ /dev/null @@ -1 +0,0 @@ -.include "../../Makefile.inc" diff --git a/usr.sbin/routed/rttrace/Makefile b/usr.sbin/routed/rttrace/Makefile deleted file mode 100644 index df19d5c61b44..000000000000 --- a/usr.sbin/routed/rttrace/Makefile +++ /dev/null @@ -1,6 +0,0 @@ -# @(#)Makefile 8.1 (Berkeley) 6/5/93 - -PROG= rttrace -NOMAN= noman - -.include diff --git a/usr.sbin/routed/rttrace/rttrace.c b/usr.sbin/routed/rttrace/rttrace.c deleted file mode 100644 index 0d8ac6224ce7..000000000000 --- a/usr.sbin/routed/rttrace/rttrace.c +++ /dev/null @@ -1,146 +0,0 @@ -/*- - * Copyright (c) 1983, 1988, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifndef lint -static char copyright[] = -"@(#) Copyright (c) 1983, 1988, 1993\n\ - The Regents of the University of California. All rights reserved.\n"; -#endif /* not lint */ - -#ifndef lint -static char sccsid[] = "@(#)trace.c 8.1 (Berkeley) 6/5/93"; -#endif /* not lint */ - -#include -#include -#include -#include -#include -#include -#ifdef sgi -#include -#endif -#include -#include -#include -#include -#include -#include - -#ifndef sgi -#define _HAVE_SIN_LEN -#endif - -struct sockaddr_in myaddr; -char packet[MAXPACKETSIZE]; - -int -main(int argc, - char **argv) -{ - int size, s; - struct sockaddr_in router; - char *tgt; - register struct rip *msg = (struct rip *)packet; - struct hostent *hp; - - if (argc < 2) { -usage: - printf("usage: on filename host1 host2 ...\n" - " or: off host1 host2 ...\n"); - exit(1); - } - s = socket(AF_INET, SOCK_DGRAM, 0); - if (s < 0) { - perror("socket"); - exit(2); - } - myaddr.sin_family = AF_INET; -#ifdef _HAVE_SIN_LEN - myaddr.sin_len = sizeof(myaddr); -#endif - myaddr.sin_port = htons(IPPORT_RESERVED-1); - while (bind(s, (struct sockaddr *)&myaddr, sizeof(myaddr)) < 0) { - if (errno != EADDRINUSE - || myaddr.sin_port == 0) { - perror("bind"); - exit(2); - } - myaddr.sin_port = htons(ntohs(myaddr.sin_port)-1); - } - - msg->rip_vers = RIPVERSION; - size = sizeof(int); - - argv++, argc--; - if (!strcmp(*argv, "on")) { - msg->rip_cmd = RIPCMD_TRACEON; - if (--argc <= 1) - goto usage; - strcpy(msg->rip_tracefile, *++argv); - size += strlen(msg->rip_tracefile); - - } else if (!strcmp(*argv, "off")) { - msg->rip_cmd = RIPCMD_TRACEOFF; - - } else { - goto usage; - } - argv++, argc--; - - bzero(&router, sizeof(router)); - router.sin_family = AF_INET; -#ifdef _HAVE_SIN_LEN - router.sin_len = sizeof(router); -#endif - router.sin_port = htons(RIP_PORT); - - do { - tgt = argc > 0 ? *argv++ : "localhost"; - router.sin_family = AF_INET; - router.sin_addr.s_addr = inet_addr(tgt); - if (router.sin_addr.s_addr == -1) { - hp = gethostbyname(tgt); - if (hp == 0) { - herror(tgt); - continue; - } - bcopy(hp->h_addr, &router.sin_addr, hp->h_length); - } - if (sendto(s, packet, size, 0, - (struct sockaddr *)&router, sizeof(router)) < 0) - perror(*argv); - } while (--argc > 0); - - return 0; -}