- Finished up merge.

- Add some prototypes and definitions for types as necessary,
  wrapped in __NetBSD__ to maintain portability.

- Explicit size types in structures that go out the wire.

- RCS id police.
This commit is contained in:
thorpej 1996-08-10 01:28:58 +00:00
parent b1e0bd39e1
commit fc1a524603
30 changed files with 4969 additions and 3988 deletions

View File

@ -1,10 +1,9 @@
# $NetBSD: Makefile,v 1.14 1995/06/20 22:25:51 christos Exp $
# @(#)Makefile 8.1 (Berkeley) 6/19/93
# $NetBSD: Makefile,v 1.15 1996/08/10 01:28:58 thorpej Exp $
# from: @(#)Makefile 8.1 (Berkeley) 6/19/93
PROG= routed
SRCS= af.c if.c input.c main.c output.c startup.c tables.c timer.c \
trace.c inet.c
SRCS= if.c input.c main.c output.c parms.c radix.c rdisc.c table.c trace.c
MAN= routed.8
#SUBDIR= query trace
SUBDIR= rtquery
.include <bsd.prog.mk>

View File

@ -1,253 +0,0 @@
/* $NetBSD: af.c,v 1.12 1995/07/24 13:03:25 ws Exp $ */
/*
* Copyright (c) 1983, 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
#if 0
static char sccsid[] = "@(#)af.c 8.1 (Berkeley) 6/5/93";
#else
static char rcsid[] = "$NetBSD: af.c,v 1.12 1995/07/24 13:03:25 ws Exp $";
#endif
#endif /* not lint */
#include "defs.h"
/*
* Address family support routines
*/
static void inet_canon __P((struct sockaddr *));
static int inet_checkhost __P((struct sockaddr *));
static char *inet_format __P((struct sockaddr *, char *buf, size_t sz));
static void inet_hash __P((struct sockaddr *, struct afhash *));
static int inet_netmatch __P((struct sockaddr *, struct sockaddr *));
static int inet_portcheck __P((struct sockaddr *));
static int inet_portmatch __P((struct sockaddr *));
static void inet_output __P((int, int, struct sockaddr *, int));
static int inet_get __P((int, void *, struct sockaddr *));
static void inet_put __P((void *, struct sockaddr *));
#define NIL { 0 }
#define INET \
{ inet_hash, inet_netmatch, inet_output, \
inet_portmatch, inet_portcheck, inet_checkhost, \
inet_rtflags, inet_sendroute, inet_canon, \
inet_format, inet_get, inet_put \
}
struct afswitch afswitch[AF_MAX] = {
NIL, /* 0- unused */
NIL, /* 1- Unix domain, unused */
INET, /* Internet */
};
int af_max = sizeof(afswitch) / sizeof(afswitch[0]);
struct sockaddr_in inet_default = {
#ifdef RTM_ADD
sizeof (inet_default),
#endif
AF_INET, INADDR_ANY };
static void
inet_hash(sa, hp)
struct sockaddr *sa;
struct afhash *hp;
{
struct sockaddr_in *sin = (struct sockaddr_in *) sa;
register u_long n;
n = inet_netof_subnet(sin->sin_addr);
if (n)
while ((n & 0xff) == 0)
n >>= 8;
hp->afh_nethash = n;
hp->afh_hosthash = ntohl(sin->sin_addr.s_addr);
hp->afh_hosthash &= 0x7fffffff;
}
static int
inet_netmatch(sa1, sa2)
struct sockaddr *sa1, *sa2;
{
struct sockaddr_in *sin1 = (struct sockaddr_in *) sa1;
struct sockaddr_in *sin2 = (struct sockaddr_in *) sa2;
return (inet_netof_subnet(sin1->sin_addr) ==
inet_netof_subnet(sin2->sin_addr));
}
/*
* Verify the message is from the right port.
*/
static int
inet_portmatch(sa)
struct sockaddr *sa;
{
struct sockaddr_in *sin = (struct sockaddr_in *) sa;
return (sin->sin_port == sp->s_port);
}
/*
* Verify the message is from a "trusted" port.
*/
static int
inet_portcheck(sa)
struct sockaddr *sa;
{
struct sockaddr_in *sin = (struct sockaddr_in *) sa;
return (ntohs(sin->sin_port) <= IPPORT_RESERVED);
}
/*
* Internet output routine.
*/
static void
inet_output(s, flags, sa, size)
int s, flags;
struct sockaddr *sa;
int size;
{
struct sockaddr_in *sin = (struct sockaddr_in *) sa;
struct sockaddr_in dst;
dst = *sin;
sin = &dst;
if (sin->sin_port == 0)
sin->sin_port = sp->s_port;
if (sin->sin_len == 0)
sin->sin_len = sizeof (*sin);
if (sendto(s, packet, size, flags,
(struct sockaddr *)sin, sizeof (*sin)) < 0)
perror("sendto");
}
/*
* Return 1 if the address is believed
* for an Internet host -- THIS IS A KLUDGE.
*/
static int
inet_checkhost(sa)
struct sockaddr *sa;
{
struct sockaddr_in *sin = (struct sockaddr_in *) sa;
u_long i = ntohl(sin->sin_addr.s_addr);
#ifndef IN_EXPERIMENTAL
#define IN_EXPERIMENTAL(i) (((long) (i) & 0xe0000000) == 0xe0000000)
#endif
if (IN_EXPERIMENTAL(i) || sin->sin_port != 0)
return (0);
if (i != 0 && (i & 0xff000000) == 0)
return (0);
for (i = 0; i < sizeof(sin->sin_zero)/sizeof(sin->sin_zero[0]); i++)
if (sin->sin_zero[i])
return (0);
return (1);
}
static void
inet_canon(sa)
struct sockaddr *sa;
{
struct sockaddr_in *sin = (struct sockaddr_in *) sa;
sin->sin_port = 0;
sin->sin_len = sizeof(*sin);
}
static char *
inet_format(sa, buf, sz)
struct sockaddr *sa;
char *buf; size_t sz;
{
struct sockaddr_in *sin = (struct sockaddr_in *) sa;
strncpy(buf, inet_ntoa(sin->sin_addr), sz);
buf[sz - 1] = '\0';
return buf;
}
static int
inet_get(what, pck, sa)
int what;
void *pck;
struct sockaddr *sa;
{
struct sockaddr_in *sin = (struct sockaddr_in *) sa;
struct netinfo *n = pck;
/* XXX: Internet only */
memset(sin, 0, sizeof(*sin));
switch (what) {
case DESTINATION:
sin->sin_addr.s_addr = n->rip_dst;
break;
case NETMASK:
if (n->rip_netmask == 0)
return 0;
sin->sin_addr.s_addr = n->rip_netmask;
break;
case GATEWAY:
if (n->rip_router == 0)
return 0;
sin->sin_addr.s_addr = n->rip_router;
break;
default:
abort();
break;
}
sin->sin_family = n->rip_family;
#if BSD >= 198810
sin->sin_len = sizeof(*sin);
#endif
return 1;
}
static void
inet_put(pck, sa)
void *pck;
struct sockaddr *sa;
{
struct netinfo *n = pck;
struct sockaddr_in *sin = (struct sockaddr_in *) sa;
#if BSD >= 198810
n->rip_family = htons(sin->sin_family);
#else
n->rip_family = sin->sin_family;
#endif
n->rip_dst = sin->sin_addr.s_addr;
}

View File

@ -1,84 +0,0 @@
/* $NetBSD: af.h,v 1.8 1995/06/20 22:26:45 christos Exp $ */
/*
* Copyright (c) 1983, 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.
*
* @(#)af.h 8.1 (Berkeley) 6/5/93
*/
/*
* Routing table management daemon.
*/
/*
* Structure returned by af_hash routines.
*/
struct afhash {
u_int afh_hosthash; /* host based hash */
u_int afh_nethash; /* network based hash */
};
/*
* Per address family routines.
*/
struct afswitch {
/* returns keys based on address */
void (*af_hash) __P((struct sockaddr *, struct afhash *));
/* verifies net # matching */
int (*af_netmatch) __P((struct sockaddr *, struct sockaddr *));
/* interprets address for sending */
void (*af_output) __P((int, int, struct sockaddr *, int));
/* packet from some other router? */
int (*af_portmatch) __P((struct sockaddr *));
/* packet from privileged peer? */
int (*af_portcheck) __P((struct sockaddr *));
/* tells if address is valid */
int (*af_checkhost) __P((struct sockaddr *));
/* get flags for route (host or net) */
int (*af_rtflags) __P((struct sockaddr *));
/* check bounds of subnet broadcast */
int (*af_sendroute) __P((struct rt_entry *, struct sockaddr *));
/* canonicalize address for compares */
void (*af_canon) __P((struct sockaddr *));
/* convert address to string */
char *(*af_format) __P((struct sockaddr *, char *, size_t));
/* get address from packet */
#define DESTINATION 0
#define GATEWAY 1
#define NETMASK 2
int (*af_get) __P((int, void *, struct sockaddr *));
/* put address to packet */
void (*af_put) __P((void *, struct sockaddr *));
};
extern struct afswitch afswitch[]; /* table proper */
extern int af_max; /* number of entries in table */

View File

@ -1,4 +1,4 @@
/* $NetBSD: defs.h,v 1.11 1995/06/20 22:26:57 christos Exp $ */
/* $NetBSD: defs.h,v 1.12 1996/08/10 01:29:09 thorpej Exp $ */
/*
* Copyright (c) 1983, 1988, 1993
@ -35,104 +35,548 @@
* @(#)defs.h 8.1 (Berkeley) 6/5/93
*/
/*
* Internal data structure definitions for
* user routing process. Based on Xerox NS
* protocol specs with mods relevant to more
* general addressing scheme.
/* Definitions for RIPv2 routing process.
*
* This code is based on the 4.4BSD `routed` daemon, with extensions to
* support:
* RIPv2, including variable length subnet masks.
* Router Discovery
* aggregate routes in the kernel tables.
* aggregate advertised routes.
* maintain spare routes for faster selection of another gateway
* when the current gateway dies.
* timers on routes with second granularity so that selection
* of a new route does not wait 30-60 seconds.
* tolerance of static routes.
* tell the kernel hop counts
* do not advertise if ipforwarding=0
*
* The vestigual support for other protocols has been removed. There
* is no likelihood that IETF RIPv1 or RIPv2 will ever be used with
* other protocols. The result is far smaller, faster, cleaner, and
* perhaps understandable.
*
* The accumulation of special flags and kludges added over the many
* years have been simplified and integrated.
*/
#include <sys/param.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <net/route.h>
#include <netinet/in.h>
#include <protocols/routed.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <signal.h>
#include <stdio.h>
#include <netdb.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#ifdef sgi
#include <strings.h>
#include <bstring.h>
#endif
#include <stdarg.h>
#include <syslog.h>
#include <time.h>
#include <sys/types.h>
#include <sys/param.h>
#include <sys/ioctl.h>
#include <sys/sysctl.h>
#include <sys/socket.h>
#include <net/if.h>
#include <net/route.h>
#include <net/radix.h>
#ifndef sgi
struct walkarg;
#endif
#include <net/if_dl.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#define RIPVERSION RIPv2
#include <protocols/routed.h>
#include "table.h"
#include "trace.h"
#include "interface.h"
#include "af.h"
#if defined(__NetBSD__)
/*
* When we find any interfaces marked down we rescan the
* kernel every CHECK_INTERVAL seconds to see if they've
* come up.
* Prototypes for the radix functions.
*/
#define CHECK_INTERVAL (1*60)
void rn_init __P((void));
int rn_inithead __P((void **, int));
int rn_refines __P((void *, void *));
int rn_walktree __P((struct radix_node_head *,
int (*)(struct radix_node *, void *), void *));
#define equal(a1, a2) \
(memcmp((a1), (a2), sizeof (struct sockaddr)) == 0)
struct radix_node
*rn_addmask __P((void *, int, int)),
*rn_addroute __P((void *, void *, struct radix_node_head *,
struct radix_node [2])),
*rn_delete __P((void *, void *, struct radix_node_head *)),
*rn_insert __P((void *, struct radix_node_head *, int *,
struct radix_node [2])),
*rn_lookup __P((void *, void *, struct radix_node_head *)),
*rn_match __P((void *, struct radix_node_head *)),
*rn_newpair __P((void *, int, struct radix_node[2])),
*rn_search __P((void *, struct radix_node *)),
*rn_search_m __P((void *, struct radix_node *, void *));
#endif /* __NetBSD__ */
struct sockaddr_in addr; /* address of daemon's socket */
/* Type of an IP address.
* Some systems do not like to pass structures, so do not use in_addr.
* Some systems think a long has 64 bits, which would be a gross waste.
* So define it here so it can be changed for the target system.
* It should be defined somewhere netinet/in.h, but it is not.
*/
#ifdef sgi
#define naddr __uint32_t
#elif defined (__NetBSD__)
#define naddr u_int32_t
#define _HAVE_SA_LEN
#define _HAVE_SIN_LEN
#else
#define naddr u_long
#define _HAVE_SA_LEN
#define _HAVE_SIN_LEN
#endif
int s; /* source and sink of all data */
int r; /* routing socket */
pid_t pid; /* process id for identifying messages */
uid_t uid; /* user id for identifying messages */
int seqno; /* sequence number for identifying messages */
int kmem;
int supplier; /* process should supply updates */
int install; /* if 1 call kernel */
int lookforinterfaces; /* if 1 probe kernel for new up interfaces */
int performnlist; /* if 1 check if /vmunix has changed */
int externalinterfaces; /* # of remote and local interfaces */
struct timeval now; /* current idea of time */
struct timeval lastbcast; /* last time all/changes broadcast */
struct timeval lastfullupdate; /* last time full table broadcast */
struct timeval nextbcast; /* time to wait before changes broadcast */
int needupdate; /* true if we need update at nextbcast */
/* Turn on if IP_DROP_MEMBERSHIP and IP_ADD_MEMBERSHIP do not look at
* the dstaddr of point-to-point interfaces.
*/
/* #define MCAST_PPP_BUG */
char packet[MAXPACKETSIZE+1];
struct rip *msg;
#define NEVER (24*60*60) /* a long time */
#define EPOCH NEVER /* bias time by this to avoid <0 */
char **argv0;
struct servent *sp;
/* Scan the kernel regularly to see if any interfaces have appeared or been
* turned off. These must be less than STALE_TIME.
*/
#define CHECK_BAD_INTERVAL 5 /* when an interface is known bad */
#define CHECK_ACT_INTERVAL 30 /* when advertising */
#define CHECK_QUIET_INTERVAL 300 /* when not */
/* inet.c */
struct in_addr inet_makeaddr __P((u_long, u_long ));
u_long inet_netof_subnet __P((struct in_addr));
u_long inet_lnaof_subnet __P((struct in_addr));
int inet_maskof __P((u_long));
int inet_rtflags __P((struct sockaddr *));
int inet_sendroute __P((struct rt_entry *, struct sockaddr *));
#define LIM_SEC(s,l) ((s).tv_sec = MIN((s).tv_sec, (l)))
/* input.c */
void rip_input __P((struct sockaddr *, struct rip *, int));
/* main.c */
int main __P((int, char *[]));
void process __P((int));
int getsocket __P((int, int , struct sockaddr_in *));
/* Router Discovery parameters */
#ifndef sgi
#define INADDR_ALLROUTERS_GROUP 0xe0000002 /* 224.0.0.2 */
#endif
#define MaxMaxAdvertiseInterval 1800
#define MinMaxAdvertiseInterval 4
#define DefMaxAdvertiseInterval 600
#define DEF_PreferenceLevel 0
#define MIN_PreferenceLevel 0x80000000
/* output.c */
void toall __P((void (*)(struct sockaddr *, int, struct interface *, int),
int, struct interface *));
void sndmsg __P((struct sockaddr *, int, struct interface *, int));
void supply __P((struct sockaddr *, int, struct interface *, int));
#define MAX_INITIAL_ADVERT_INTERVAL 16
#define MAX_INITIAL_ADVERTS 3
#define MAX_RESPONSE_DELAY 2
/* startup.c */
void quit __P((char *));
void rt_xaddrs __P((caddr_t, caddr_t , struct rt_addrinfo *));
void ifinit __P((void));
void addrouteforif __P((struct interface *));
void add_ptopt_localrt __P((struct interface *));
void gwkludge __P((void));
int getnetorhostname __P((char *, char *, struct sockaddr_in *));
int gethostnameornumber __P((char *, struct sockaddr_in *));
#define MAX_SOLICITATION_DELAY 1
#define SOLICITATION_INTERVAL 3
#define MAX_SOLICITATIONS 3
/* timer.c */
void timer __P((int));
void hup __P((int));
#define ADD 1
#define DELETE 2
#define CHANGE 3
/* typical packet buffers */
union pkt_buf {
char packet[MAXPACKETSIZE+1];
struct rip rip;
};
/* Main, daemon routing table structure
*/
struct rt_entry {
struct radix_node rt_nodes[2]; /* radix tree glue */
u_int rt_state;
# define RS_IF 0x001 /* for network interface */
# define RS_NET_INT 0x002 /* authority route */
# define RS_NET_SYN 0x004 /* fake net route for subnet */
# define RS_NO_NET_SYN (RS_LOCAL | RS_LOCAL | RS_IF)
# define RS_SUBNET 0x008 /* subnet route from any source */
# define RS_LOCAL 0x010 /* loopback for pt-to-pt */
# 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 {
struct interface *rts_ifp;
naddr rts_gate; /* forward packets here */
naddr rts_router; /* on the authority of this router */
char rts_metric;
u_short rts_tag;
time_t rts_time; /* timer to junk stale routes */
#define NUM_SPARES 4
} rt_spares[NUM_SPARES];
u_int rt_seqno; /* when last changed */
char rt_poison_metric; /* to notice maximum recently */
time_t rt_poison_time; /* advertised metric */
};
#define rt_dst rt_dst_sock.sin_addr.s_addr
#define rt_ifp rt_spares[0].rts_ifp
#define rt_gate rt_spares[0].rts_gate
#define rt_router rt_spares[0].rts_router
#define rt_metric rt_spares[0].rts_metric
#define rt_tag rt_spares[0].rts_tag
#define rt_time rt_spares[0].rts_time
#define HOST_MASK 0xffffffff
#define RT_ISHOST(rt) ((rt)->rt_mask == HOST_MASK)
/* age all routes that
* are not from -g, -m, or static routes from the kernel
* not unbroken interface routes
* but not broken interfaces
* 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))))
/* true if A is better than B
* Better if
* - A is not a poisoned route
* - and A is not stale
* - and A has a shorter path
* - or is the router speaking for itself
* - or the current route is equal but stale
* - or it is a host route advertised by a system for itself
*/
#define BETTER_LINK(rt,A,B) ((A)->rts_metric < HOPCNT_INFINITY \
&& now_stale <= (A)->rts_time \
&& ((A)->rts_metric < (B)->rts_metric \
|| ((A)->rts_gate == (A)->rts_router \
&& (B)->rts_gate != (B)->rts_router) \
|| ((A)->rts_metric == (B)->rts_metric \
&& now_stale > (B)->rts_time) \
|| (RT_ISHOST(rt) \
&& (rt)->rt_dst == (A)->rts_router \
&& (A)->rts_metric == (B)->rts_metric)))
/* An "interface" is similar to a kernel ifnet structure, except it also
* handles "logical" or "IS_REMOTE" interfaces (remote gateways).
*/
struct interface {
struct interface *int_next, *int_prev;
char int_name[IFNAMSIZ+15+1]; /* big enough for IS_REMOTE */
u_short int_index;
naddr int_addr; /* address on this host (net order) */
naddr int_brdaddr; /* broadcast address (n) */
naddr int_dstaddr; /* other end of pt-to-pt link (n) */
naddr int_net; /* working network # (host order)*/
naddr int_mask; /* working net mask (host order) */
naddr int_ripv1_mask; /* for inferring a mask (n) */
naddr int_std_addr; /* class A/B/C address (n) */
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 */
u_int int_state;
time_t int_act_time; /* last thought healthy */
u_short int_transitions; /* times gone up-down */
char int_metric;
char int_d_metric; /* for faked default route */
struct int_data {
u_int ipackets; /* previous network stats */
u_int ierrors;
u_int opackets;
u_int oerrors;
#ifdef sgi
u_int odrops;
#endif
time_t ts; /* timestamp on network stats */
} int_data;
char int_passwd[RIP_AUTH_PW_LEN]; /* RIPv2 password */
int int_rdisc_pref; /* advertised rdisc preference */
int int_rdisc_int; /* MaxAdvertiseInterval */
int int_rdisc_cnt;
struct timeval int_rdisc_timer;
};
#define IS_ALIAS 0x0000001 /* interface alias */
#define IS_SUBNET 0x0000002 /* interface on subnetted network */
#define IS_REMOTE 0x0000004 /* interface is not on this machine */
#define IS_PASSIVE 0x0000008 /* remote and does not do RIP */
#define IS_EXTERNAL 0x0000010 /* handled by EGP or something */
#define IS_CHECKED 0x0000020 /* still exists */
#define IS_ALL_HOSTS 0x0000040 /* in INADDR_ALLHOSTS_GROUP */
#define IS_ALL_ROUTERS 0x0000080 /* in INADDR_ALLROUTERS_GROUP */
#define IS_RIP_QUERIED 0x0000100 /* query broadcast */
#define IS_BROKE 0x0000200 /* seems to be broken */
#define IS_SICK 0x0000400 /* seems to be broken */
#define IS_DUP 0x0000800 /* has a duplicate address */
#define IS_ACTIVE 0x0001000 /* heard from it at least once */
#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 */
#define IS_NO_RIPV1_IN 0x0010000 /* no RIPv1 input at all */
#define IS_NO_RIPV2_IN 0x0020000 /* no RIPv2 input at all */
#define IS_NO_RIP_IN (IS_NO_RIPV1_IN | IS_NO_RIPV2_IN)
#define IS_RIP_IN_OFF(s) (((s) & IS_NO_RIP_IN) == IS_NO_RIP_IN)
#define IS_NO_RIPV1_OUT 0x0040000 /* no RIPv1 output at all */
#define IS_NO_RIPV2_OUT 0x0080000 /* no RIPv2 output at all */
#define IS_NO_RIP_OUT (IS_NO_RIPV1_OUT | IS_NO_RIPV2_OUT)
#define IS_NO_RIP (IS_NO_RIP_OUT | IS_NO_RIP_IN)
#define IS_RIP_OUT_OFF(s) (((s) & IS_NO_RIP_OUT) == IS_NO_RIP_OUT)
#define IS_RIP_OFF(s) (((s) & IS_NO_RIP) == IS_NO_RIP)
#define IS_NO_ADV_IN 0x0100000
#define IS_NO_SOL_OUT 0x0200000 /* no solicitations */
#define IS_SOL_OUT 0x0400000 /* send solicitations */
#define GROUP_IS_SOL (IS_NO_ADV_IN|IS_NO_SOL_OUT)
#define IS_NO_ADV_OUT 0x0800000 /* do not advertise rdisc */
#define IS_ADV_OUT 0x1000000 /* advertise rdisc */
#define GROUP_IS_ADV (IS_NO_ADV_OUT|IS_ADV_OUT)
#define IS_BCAST_RDISC 0x2000000 /* broadcast instead of multicast */
#define IS_NO_RDISC (IS_NO_ADV_IN | IS_NO_SOL_OUT | IS_NO_ADV_OUT)
#define IS_PM_RDISC 0x4000000 /* poor-man's router discovery */
#ifdef sgi
#define IFF_UP_RUNNING (IFF_RUNNING|IFF_UP)
#else
#define IFF_UP_RUNNING IFF_UP
#endif
#define iff_alive(f) (((f) & IFF_UP_RUNNING) == IFF_UP_RUNNING)
/* Information for aggregating routes */
#define NUM_AG_SLOTS 32
struct ag_info {
struct ag_info *ag_fine; /* slot with finer netmask */
struct ag_info *ag_cors; /* more coarse netmask */
naddr ag_dst_h; /* destination in host byte order */
naddr ag_mask;
naddr ag_gate;
naddr ag_nhop;
char ag_metric; /* metric to be advertised */
char ag_pref; /* aggregate based on this */
u_int ag_seqno;
u_short ag_tag;
u_short ag_state;
#define AGS_SUPPRESS 0x001 /* combine with coaser mask */
#define AGS_PROMOTE 0x002 /* synthesize combined routes */
#define AGS_REDUN0 0x004 /* redundant, finer routes output */
#define AGS_REDUN1 0x008
#define AG_IS_REDUN(state) (((state) & (AGS_REDUN0 | AGS_REDUN1)) \
== (AGS_REDUN0 | AGS_REDUN1))
#define AGS_GATEWAY 0x010 /* tell kernel RTF_GATEWAY */
#define AGS_IF 0x020 /* for an interface */
#define AGS_RIPV2 0x040 /* send only as RIPv2 */
#define AGS_FINE_GATE 0x080 /* ignore differing ag_gate when this
* has the finer netmask */
#define AGS_CORS_GATE 0x100 /* ignore differing gate when this
* has the coarser netmaks */
#define AGS_SPLIT_HZ 0x200 /* suppress for split horizon */
/* some bits are set if they are set on either route */
#define AGS_PROMOTE_EITHER (AGS_RIPV2 | AGS_GATEWAY | \
AGS_SUPPRESS | AGS_CORS_GATE)
};
/* parameters for interfaces */
extern struct parm {
struct parm *parm_next;
char parm_name[IFNAMSIZ+1];
naddr parm_addr_h;
naddr parm_mask;
char parm_d_metric;
u_int parm_int_state;
int parm_rdisc_pref;
int parm_rdisc_int;
char parm_passwd[RIP_AUTH_PW_LEN+1];
} *parms;
/* authority for internal networks */
extern struct intnet {
struct intnet *intnet_next;
naddr intnet_addr;
naddr intnet_mask;
char intnet_metric;
} *intnets;
extern pid_t mypid;
extern naddr myaddr; /* main address of this system */
extern int stopint; /* !=0 to stop */
extern int sock_max;
extern int rip_sock; /* RIP socket */
extern struct interface *rip_sock_mcast; /* current multicast interface */
extern int rt_sock; /* routing socket */
extern int rt_sock_seqno;
extern int rdisc_sock; /* router-discovery raw socket */
extern int seqno; /* sequence number for messages */
extern int supplier; /* process should supply updates */
extern int lookforinterfaces; /* 1=probe for new up interfaces */
extern int supplier_set; /* -s or -q requested */
extern int ridhosts; /* 1=reduce host routes */
extern int mhome; /* 1=want multi-homed host route */
extern int advertise_mhome; /* 1=must continue adverising it */
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_garbage;
extern struct timeval next_bcast; /* next general broadcast */
extern struct timeval age_timer; /* next check of old routes */
extern struct timeval no_flash; /* inhibit flash update until then */
extern struct timeval rdisc_timer; /* next advert. or solicitation */
extern int rdisc_ok; /* using solicited route */
extern struct timeval ifinit_timer; /* time to check interfaces */
extern naddr loopaddr; /* our address on loopback */
extern int tot_interfaces; /* # of remote and local interfaces */
extern int rip_interfaces; /* # of interfaces doing RIP */
extern struct interface *ifnet; /* all interfaces */
extern int have_ripv1_out; /* have a RIPv1 interface */
extern int have_ripv1_in;
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;
#define MAX_TRACELEVEL 3
#define TRACECONTENTS (tracelevel >= 3) /* display packet contents */
#define TRACEPACKETS (tracelevel >= 2) /* note packets */
#define TRACEACTIONS (tracelevel != 0)
extern FILE *ftrace; /* output trace file */
extern struct radix_node_head *rhead;
#ifdef sgi
/* Fix conflicts */
#define dup2(x,y) BSDdup2(x,y)
#endif /* sgi */
extern void fix_sock(int, char *);
extern void fix_select(void);
extern void rip_off(void);
extern void rip_on(struct interface *);
enum output_type {OUT_QUERY, OUT_UNICAST, OUT_BROADCAST, OUT_MULTICAST,
NO_OUT_MULTICAST, NO_OUT_RIPV2};
extern int output(enum output_type, struct sockaddr_in *,
struct interface *, struct rip *, int);
extern void rip_query(void);
extern void rip_bcast(int);
extern void supply(struct sockaddr_in *, struct interface *,
enum output_type, int, int);
extern void msglog(char *, ...);
#define LOGERR(msg) msglog(msg ": %s", strerror(errno))
extern void logbad(int, char *, ...);
#define BADERR(dump,msg) logbad(dump,msg ": %s", strerror(errno))
#ifdef DEBUG
#define DBGERR(dump,msg) BADERR(dump,msg)
#else
#define DBGERR(dump,msg) LOGERR(msg)
#endif
#ifdef MCAST_PPP_BUG
extern void mcasterr(struct interface *, int, char *);
#define MCASTERR(ifp,dump,msg) mcasterr(ifp, dump, "setsockopt(IP_"msg")")
#else
#define MCASTERR(ifp, dump,msg) DBGERR(dump,"setsockopt(IP_" msg ")")
#endif
extern char *naddr_ntoa(naddr);
extern char *saddr_ntoa(struct sockaddr *);
extern void timevaladd(struct timeval *, struct timeval *);
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 *check_parms(struct parm *);
extern void get_parms(struct interface *);
extern void lastlog(void);
extern void trace_on(char *, int);
extern void trace_off(char*, ...);
extern void trace_flush(void);
extern void set_tracelevel(void);
extern void trace_act(char *, ...);
extern void trace_pkt(char *, ...);
extern void trace_add_del(char *, struct rt_entry *);
extern void trace_change(struct rt_entry *, u_int, naddr, naddr, int,
u_short, struct interface *, time_t, char *);
extern void trace_if(char *, struct interface *);
extern void trace_upslot(struct rt_entry *, struct rt_spare *,
naddr, naddr,
struct interface *, int, u_short, time_t);
extern void trace_rip(char*, char*, struct sockaddr_in *,
struct interface *, struct rip *, int);
extern char *addrname(naddr, naddr, int);
extern void rdisc_age(naddr);
extern void set_rdisc_mg(struct interface *, int);
extern void set_supplier(void);
extern void if_bad_rdisc(struct interface *);
extern void if_ok_rdisc(struct interface *);
extern void read_rip(int, struct interface *);
extern void read_rt(void);
extern void read_d(void);
extern void rdisc_adv(void);
extern void rdisc_sol(void);
extern void sigalrm(int);
extern void sigterm(int);
extern void sigtrace_on(int);
extern void sigtrace_off(int);
extern void flush_kern(void);
extern void age(naddr);
extern void ag_flush(naddr, naddr, void (*)(struct ag_info *));
extern void ag_check(naddr, naddr, naddr, naddr, char, char, u_int,
u_short, u_short, void (*)(struct ag_info *));
extern void del_static(naddr, naddr, int);
extern void del_redirects(naddr, time_t);
extern struct rt_entry *rtget(naddr, naddr);
extern struct rt_entry *rtfind(naddr);
extern void rtinit(void);
extern void rtadd(naddr, naddr, naddr, naddr,
int, u_short, u_int, struct interface *);
extern void rtchange(struct rt_entry *, u_int, naddr,naddr, int, u_short,
struct interface *ifp, time_t, char *);
extern void rtdelete(struct rt_entry *);
extern void rtbad_sub(struct rt_entry *);
extern void rtswitch(struct rt_entry *, struct rt_spare *);
extern void rtbad(struct rt_entry *);
#define S_ADDR(x) (((struct sockaddr_in *)(x))->sin_addr.s_addr)
#define INFO_DST(I) ((I)->rti_info[RTAX_DST])
#define INFO_GATE(I) ((I)->rti_info[RTAX_GATEWAY])
#define INFO_MASK(I) ((I)->rti_info[RTAX_NETMASK])
#define INFO_IFA(I) ((I)->rti_info[RTAX_IFA])
#define INFO_IFP(I) ((I)->rti_info[RTAX_IFP])
#define INFO_AUTHOR(I) ((I)->rti_info[RTAX_AUTHOR])
#define INFO_BRD(I) ((I)->rti_info[RTAX_BRD])
void rt_xaddrs(struct rt_addrinfo *, struct sockaddr *, struct sockaddr *,
int);
extern naddr std_mask(naddr);
extern naddr ripv1_mask_net(naddr, struct interface *);
extern naddr ripv1_mask_host(naddr,struct interface *);
#define on_net(a,net,mask) (((ntohl(a) ^ (net)) & (mask)) == 0)
extern int check_dst(naddr);
#ifdef sgi
extern int sysctl(int *, u_int, void *, size_t *, void *, size_t);
#endif
extern void addrouteforif(register struct interface *);
extern void ifinit(void);
extern int walk_bad(struct radix_node *, void *);
extern int if_ok(struct interface *, char *);
extern void if_sick(struct interface *);
extern void if_bad(struct interface *);
extern struct interface *ifwithaddr(naddr, int, int);
extern struct interface *ifwithname(char *, naddr);
extern struct interface *ifwithindex(u_short);
extern struct interface *iflookup(naddr);

File diff suppressed because it is too large Load Diff

View File

@ -1,259 +0,0 @@
/* $NetBSD: inet.c,v 1.9 1995/06/20 22:27:40 christos Exp $ */
/*
* Copyright (c) 1983, 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
#if 0
static char sccsid[] = "@(#)inet.c 8.2 (Berkeley) 8/14/93";
#else
static char rcsid[] = "$NetBSD: inet.c,v 1.9 1995/06/20 22:27:40 christos Exp $";
#endif
#endif /* not lint */
/*
* Temporarily, copy these routines from the kernel,
* as we need to know about subnets.
*/
#include "defs.h"
extern struct interface *ifnet;
/*
* Formulate an Internet address from network + host.
*/
struct in_addr
inet_makeaddr(net, host)
u_long net, host;
{
register struct interface *ifp;
register u_long mask;
u_long addr;
if (IN_CLASSA(net))
mask = IN_CLASSA_HOST;
else if (IN_CLASSB(net))
mask = IN_CLASSB_HOST;
else
mask = IN_CLASSC_HOST;
for (ifp = ifnet; ifp; ifp = ifp->int_next)
if ((ifp->int_netmask & net) == ifp->int_net) {
mask = ~ifp->int_subnetmask;
break;
}
addr = net | (host & mask);
addr = htonl(addr);
return (*(struct in_addr *)&addr);
}
/*
* Return the network number from an internet address.
*/
u_long
inet_netof_subnet(in)
struct in_addr in;
{
register u_long i = ntohl(in.s_addr);
register u_long net;
register struct interface *ifp;
if (IN_CLASSA(i))
net = i & IN_CLASSA_NET;
else if (IN_CLASSB(i))
net = i & IN_CLASSB_NET;
else
net = i & IN_CLASSC_NET;
/*
* Check whether network is a subnet;
* if so, return subnet number.
*/
for (ifp = ifnet; ifp; ifp = ifp->int_next)
if ((ifp->int_netmask & net) == ifp->int_net)
return (i & ifp->int_subnetmask);
return (net);
}
#ifdef notdef
/*
* Return the host portion of an internet address.
* XXX THIS FUNCTION UNUSED.
*/
u_long
inet_lnaof_subnet(in)
struct in_addr in;
{
register u_long i = ntohl(in.s_addr);
register u_long net, host;
register struct interface *ifp;
if (IN_CLASSA(i)) {
net = i & IN_CLASSA_NET;
host = i & IN_CLASSA_HOST;
} else if (IN_CLASSB(i)) {
net = i & IN_CLASSB_NET;
host = i & IN_CLASSB_HOST;
} else {
net = i & IN_CLASSC_NET;
host = i & IN_CLASSC_HOST;
}
/*
* Check whether network is a subnet;
* if so, use the modified interpretation of `host'.
*/
for (ifp = ifnet; ifp; ifp = ifp->int_next)
if ((ifp->int_netmask & net) == ifp->int_net)
return (host &~ ifp->int_subnetmask);
return (host);
}
#endif
/*
* Return the netmask pertaining to an internet address.
*/
int
inet_maskof(inaddr)
u_long inaddr;
{
register u_long i = ntohl(inaddr);
register u_long mask;
register struct interface *ifp;
if (i == 0) {
mask = 0;
} else if (IN_CLASSA(i)) {
mask = IN_CLASSA_NET;
} else if (IN_CLASSB(i)) {
mask = IN_CLASSB_NET;
} else
mask = IN_CLASSC_NET;
/*
* Check whether network is a subnet;
* if so, use the modified interpretation of `host'.
*/
for (ifp = ifnet; ifp; ifp = ifp->int_next)
if ((ifp->int_netmask & i) == ifp->int_net)
mask = ifp->int_subnetmask;
return (htonl(mask));
}
/*
* Return RTF_HOST if the address is
* for an Internet host, RTF_SUBNET for a subnet,
* 0 for a network.
*/
int
inet_rtflags(sa)
struct sockaddr *sa;
{
struct sockaddr_in *sin = (struct sockaddr_in *) sa;
register u_long i = ntohl(sin->sin_addr.s_addr);
register u_long net, host;
register struct interface *ifp;
if (IN_CLASSA(i)) {
net = i & IN_CLASSA_NET;
host = i & IN_CLASSA_HOST;
} else if (IN_CLASSB(i)) {
net = i & IN_CLASSB_NET;
host = i & IN_CLASSB_HOST;
} else {
net = i & IN_CLASSC_NET;
host = i & IN_CLASSC_HOST;
}
/*
* Check whether this network is subnetted;
* if so, check whether this is a subnet or a host.
*/
for (ifp = ifnet; ifp; ifp = ifp->int_next)
if (net == ifp->int_net) {
if (host &~ ifp->int_subnetmask)
return (RTF_HOST);
else if (ifp->int_subnetmask != ifp->int_netmask)
return (RTF_SUBNET);
else
return (0); /* network */
}
if (host == 0)
return (0); /* network */
else
return (RTF_HOST);
}
/*
* Return true if a route to subnet/host of route rt should be sent to dst.
* Send it only if dst is on the same logical network if not "internal",
* otherwise only if the route is the "internal" route for the logical net.
*/
int
inet_sendroute(rt, sa)
struct rt_entry *rt;
struct sockaddr *sa;
{
struct sockaddr_in *dst = (struct sockaddr_in *) sa;
register u_long r =
ntohl(((struct sockaddr_in *)&rt->rt_dst)->sin_addr.s_addr);
register u_long d = ntohl(dst->sin_addr.s_addr);
if (IN_CLASSA(r)) {
if ((r & IN_CLASSA_NET) == (d & IN_CLASSA_NET)) {
if ((r & IN_CLASSA_HOST) == 0)
return ((rt->rt_state & RTS_INTERNAL) == 0);
return (1);
}
if (r & IN_CLASSA_HOST)
return (0);
return ((rt->rt_state & RTS_INTERNAL) != 0);
} else if (IN_CLASSB(r)) {
if ((r & IN_CLASSB_NET) == (d & IN_CLASSB_NET)) {
if ((r & IN_CLASSB_HOST) == 0)
return ((rt->rt_state & RTS_INTERNAL) == 0);
return (1);
}
if (r & IN_CLASSB_HOST)
return (0);
return ((rt->rt_state & RTS_INTERNAL) != 0);
} else {
if ((r & IN_CLASSC_NET) == (d & IN_CLASSC_NET)) {
if ((r & IN_CLASSC_HOST) == 0)
return ((rt->rt_state & RTS_INTERNAL) == 0);
return (1);
}
if (r & IN_CLASSC_HOST)
return (0);
return ((rt->rt_state & RTS_INTERNAL) != 0);
}
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: input.c,v 1.16 1995/07/13 23:20:10 christos Exp $ */
/* $NetBSD: input.c,v 1.17 1996/08/10 01:29:17 thorpej Exp $ */
/*
* Copyright (c) 1983, 1988, 1993
@ -33,363 +33,675 @@
* SUCH DAMAGE.
*/
#ifndef lint
#if !defined(lint) && !defined(sgi)
#if 0
static char sccsid[] = "@(#)input.c 8.1 (Berkeley) 6/5/93";
#else
static char rcsid[] = "$NetBSD: input.c,v 1.16 1995/07/13 23:20:10 christos Exp $";
static char rcsid[] = "$NetBSD: input.c,v 1.17 1996/08/10 01:29:17 thorpej Exp $";
#endif
#endif /* not lint */
/*
* Routing Table Management Daemon
*/
#include "defs.h"
#include <syslog.h>
static void input(struct sockaddr_in *, struct interface*, struct rip *, int);
static void input_route(struct interface *, naddr,
naddr, naddr, naddr, struct netinfo *);
/*
* "Authenticate" router from which message originated.
* We accept routing packets from routers directly connected
* via broadcast or point-to-point networks,
* and from those listed in /etc/gateways.
/* process RIP input
*/
static struct interface *
rip_verify(from)
struct sockaddr *from;
void
read_rip(int sock,
struct interface *ifp)
{
struct interface *ifp;
char buf[256];
struct sockaddr_in from;
int fromlen, cc;
union pkt_buf inbuf;
if ((ifp = if_iflookup(from)) == 0) {
syslog(LOG_ERR, "trace command from unknown router, %s",
(*afswitch[from->sa_family].af_format)(from, buf,
sizeof(buf)));
return NULL;
for (;;) {
fromlen = sizeof(from);
cc = recvfrom(sock, &inbuf, sizeof(inbuf), 0,
(struct sockaddr*)&from, &fromlen);
if (cc <= 0) {
if (cc < 0 && errno != EWOULDBLOCK)
LOGERR("recvfrom(rip)");
break;
}
if (fromlen != sizeof(struct sockaddr_in))
logbad(1,"impossible recvfrom(rip) fromlen=%d",
fromlen);
input(&from,
(ifp != 0) ? ifp : iflookup(from.sin_addr.s_addr),
&inbuf.rip, cc);
}
if ((ifp->int_flags &
(IFF_BROADCAST|IFF_POINTOPOINT|IFF_REMOTE)) == 0) {
syslog(LOG_ERR,
"trace command from router %s, with bad flags %x",
(*afswitch[from->sa_family].af_format)(from, buf,
sizeof(buf)),
ifp->int_flags);
return NULL;
}
if ((ifp->int_flags & IFF_PASSIVE) != 0) {
syslog(LOG_ERR,
"trace command from %s on an active interface",
(*afswitch[from->sa_family].af_format)(from, buf,
sizeof(buf)));
return NULL;
}
return ifp;
}
/*
* Process a newly received packet.
/* Process a RIP packet
*/
void
rip_input(from, rip, size)
struct sockaddr *from;
register struct rip *rip;
int size;
static void
input(struct sockaddr_in *from, /* received from this IP address */
struct interface *ifp,
struct rip *rip,
int size)
{
register struct rt_entry *rt;
register struct netinfo *n;
register struct interface *ifp;
struct sockaddr dst, gateway, netmask;
int count, changes = 0;
register struct afswitch *afp;
static struct sockaddr badfrom;
char buf1[256], buf2[256];
# define FROM_NADDR from->sin_addr.s_addr
static naddr use_auth, bad_len, bad_mask;
static naddr unk_router, bad_router, bad_nhop;
ifp = 0;
TRACE_INPUT(ifp, from, (char *)rip, size);
if (from->sa_family >= af_max ||
(afp = &afswitch[from->sa_family])->af_hash == NULL) {
syslog(LOG_INFO,
"\"from\" address in unsupported address family (%d), cmd %d\n",
from->sa_family, rip->rip_cmd);
struct rt_entry *rt;
struct netinfo *n, *lim;
struct interface *ifp1;
naddr gate, mask, v1_mask, dst, ddst_h;
int i;
if (ifp != 0)
ifp->int_state |= IS_ACTIVE;
trace_rip("Recv", "from", from, ifp, rip, size);
if (rip->rip_vers == 0) {
if (from->sin_addr.s_addr != bad_router)
msglog("RIP version 0, cmd %d, packet received"
" from %s",
rip->rip_cmd, naddr_ntoa(FROM_NADDR));
bad_router = from->sin_addr.s_addr;
return;
}
if (rip->rip_vers == 0) {
syslog(LOG_ERR,
"RIP version 0 packet received from %s! (cmd %d)",
(*afswitch[from->sa_family].af_format)(from, buf1,
sizeof(buf1)),
rip->rip_cmd);
if (size > MAXPACKETSIZE) {
if (from->sin_addr.s_addr != bad_router)
msglog("packet at least %d bytes too long received"
" from %s",
size-MAXPACKETSIZE, naddr_ntoa(FROM_NADDR));
bad_router = from->sin_addr.s_addr;
return;
}
n = rip->rip_nets;
lim = (struct netinfo *)((char*)rip + size);
/* Notice authentication.
* As required by section 4.2 in RFC 1723, discard authenticated
* RIPv2 messages, but only if configured for that silliness.
*
* RIPv2 authentication is lame, since snooping on the wire makes
* its simple passwords evident. Also, why authenticate queries?
* Why should a RIPv2 implementation with authentication disabled
* not be able to listen to RIPv2 packets with authenication, while
* RIPv1 systems will listen? Crazy!
*/
if (!auth_ok
&& 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"
" from %s discarded",
naddr_ntoa(FROM_NADDR));
use_auth = from->sin_addr.s_addr;
trace_pkt("discard authenticated RIPv2 message\n");
return;
}
switch (rip->rip_cmd) {
case RIPCMD_REQUEST:
n = rip->rip_nets;
count = size - ((char *)n - (char *)rip);
if (count < sizeof (struct netinfo))
return;
for (; count > 0; n++) {
if (count < sizeof (struct netinfo))
break;
count -= sizeof (struct netinfo);
n->rip_metric = ntohl(n->rip_metric);
n->rip_family = ntohs(n->rip_family);
/*
* A single entry with sa_family == AF_UNSPEC and
* metric ``infinity'' means ``all routes''.
* We respond to routers only if we are acting
* as a supplier, or to anyone other than a router
* (eg, query).
/* did the request come from a router?
*/
if (from->sin_port == htons(RIP_PORT)) {
/* yes, ignore it if RIP is off so that it does not
* depend on us.
*/
if (n->rip_family == AF_UNSPEC &&
n->rip_metric == HOPCNT_INFINITY && count == 0) {
if (supplier || (*afp->af_portmatch)(from) == 0)
supply(from, 0, 0, 0);
if (rip_sock < 0) {
trace_pkt("ignore request while RIP off\n");
return;
}
if (n->rip_family < af_max &&
afswitch[n->rip_family].af_hash) {
if (!(*afswitch[n->rip_family].af_get)(
DESTINATION, n, &dst))
return;
rt = rtlookup(&dst);
/* Ignore the request if we talking to ourself
* (and not a remote gateway).
*/
if (ifwithaddr(FROM_NADDR, 0, 0) != 0) {
trace_pkt("discard our own RIP request\n");
return;
}
else
rt = 0;
#define min(a, b) (a < b ? a : b)
n->rip_metric = rt == 0 ? HOPCNT_INFINITY :
min(rt->rt_metric + 1, HOPCNT_INFINITY);
n->rip_metric = htonl(n->rip_metric);
}
/* According to RFC 1723, we should ignore unathenticated
* queries. That is too silly to bother with. Sheesh!
* Are forwarding tables supposed to be secret? When
* a bad guy can infer them with test traffic?
* Maybe on firewalls you'd care, but not enough to
* give up the diagnostic facilities of remote probing.
*/
if (n >= lim
|| size%sizeof(*n) != sizeof(struct rip)%sizeof(*n)) {
if (from->sin_addr.s_addr != bad_len)
msglog("request of bad length (%d) from %s",
size, naddr_ntoa(FROM_NADDR));
bad_len = from->sin_addr.s_addr;
}
for (; n < lim; n++) {
n->n_metric = ntohl(n->n_metric);
/* A single entry with family RIP_AF_UNSPEC and
* metric HOPCNT_INFINITY means "all routes".
* 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 */
supply(from, ifp,
OUT_QUERY, 0, rip->rip_vers);
} else if (supplier) {
supply(from, ifp,
OUT_UNICAST, 0, rip->rip_vers);
}
return;
}
if (n->n_family != RIP_AF_INET) {
if (from->sin_addr.s_addr != bad_router)
msglog("request from %s"
" for unsupported (af %d) %s",
naddr_ntoa(FROM_NADDR),
ntohs(n->n_family),
naddr_ntoa(n->n_dst));
bad_router = from->sin_addr.s_addr;
return;
}
dst = n->n_dst;
if (!check_dst(dst)) {
if (from->sin_addr.s_addr != bad_router)
msglog("bad queried destination"
" %s from %s",
naddr_ntoa(dst),
naddr_ntoa(FROM_NADDR));
bad_router = from->sin_addr.s_addr;
return;
}
if (rip->rip_vers == RIPv1
|| 0 == (mask = ntohl(n->n_mask))
|| 0 != (ntohl(dst) & ~mask))
mask = ripv1_mask_host(dst,ifp);
rt = rtget(dst, mask);
if (!rt && dst != RIP_DEFAULT)
rt = rtfind(n->n_dst);
n->n_tag = 0;
n->n_nhop = 0;
if (rip->rip_vers == RIPv1) {
n->n_mask = 0;
} else {
n->n_mask = mask;
}
if (rt == 0) {
n->n_metric = HOPCNT_INFINITY;
} else {
n->n_metric = rt->rt_metric+1;
n->n_metric += (ifp!=0) ? ifp->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
&& on_net(rt->rt_gate,
ifp->int_net,
ifp->int_mask)
&& rt->rt_gate != ifp->int_addr)
n->n_nhop = rt->rt_gate;
}
}
HTONL(n->n_metric);
}
/* Answer about specific routes.
* Only answer a router if we are a supplier
* to keep an unwary host that is just starting
* from picking us an a router.
*/
rip->rip_cmd = RIPCMD_RESPONSE;
memcpy(packet, rip, size);
(*afp->af_output)(s, 0, from, size);
rip->rip_res1 = 0;
if (rip->rip_vers != RIPv1)
rip->rip_vers = RIPv2;
if (from->sin_port != htons(RIP_PORT)) {
/* query */
(void)output(OUT_QUERY, from, ifp, rip, size);
} else if (supplier) {
(void)output(OUT_UNICAST, from, ifp, rip, size);
}
return;
case RIPCMD_TRACEON:
case RIPCMD_TRACEOFF:
/* verify message came from a privileged port */
if ((*afp->af_portcheck)(from) == 0)
if (ntohs(from->sin_port) > IPPORT_RESERVED) {
msglog("trace command from untrusted port on %s",
naddr_ntoa(FROM_NADDR));
return;
if ((ifp = rip_verify(from)) == NULL)
}
if (ifp == 0) {
msglog("trace command from unknown router %s",
naddr_ntoa(FROM_NADDR));
return;
((char *)rip)[size] = '\0';
if (rip->rip_cmd == RIPCMD_TRACEON)
traceon(rip->rip_tracefile);
else
traceoff();
}
if (rip->rip_cmd == RIPCMD_TRACEON) {
rip->rip_tracefile[size-4] = '\0';
trace_on(rip->rip_tracefile, 0);
} else {
trace_off("tracing turned off by %s\n",
naddr_ntoa(FROM_NADDR));
}
return;
case RIPCMD_RESPONSE:
if (size%sizeof(*n) != sizeof(struct rip)%sizeof(*n)) {
if (from->sin_addr.s_addr != bad_len)
msglog("response of bad length (%d) from %s",
size, naddr_ntoa(FROM_NADDR));
bad_len = from->sin_addr.s_addr;
}
/* verify message came from a router */
if ((*afp->af_portmatch)(from) == 0)
return;
(*afp->af_canon)(from);
/* are we talking to ourselves? */
ifp = if_ifwithaddr(from);
if (ifp) {
if (ifp->int_flags & IFF_PASSIVE) {
syslog(LOG_ERR,
"bogus input (from passive interface, %s)",
(*afswitch[from->sa_family].af_format)(from,
buf1, sizeof(buf1)));
return;
}
rt = rtfind(from);
if (rt == 0 || (((rt->rt_state & RTS_INTERFACE) == 0) &&
rt->rt_metric >= ifp->int_metric))
addrouteforif(ifp);
else
rt->rt_timer = 0;
if (from->sin_port != ntohs(RIP_PORT)) {
trace_pkt("discard RIP response from unknown port\n");
return;
}
/*
* Update timer for interface on which the packet arrived.
* If from other end of a point-to-point link that isn't
* in the routing tables, (re-)add the route.
*/
if ((rt = rtfind(from)) &&
(rt->rt_state & (RTS_INTERFACE | RTS_REMOTE)))
rt->rt_timer = 0;
else if ((ifp = if_ifwithdstaddr(from)) &&
(rt == 0 || rt->rt_metric >= ifp->int_metric))
addrouteforif(ifp);
if ((ifp = rip_verify(from)) == NULL)
if (rip_sock < 0) {
trace_pkt("discard response while RIP off\n");
return;
}
size -= 4 * sizeof (char);
n = rip->rip_nets;
for (; size > 0; size -= sizeof (struct netinfo), n++) {
if (size < sizeof (struct netinfo))
break;
n->rip_metric = ntohl(n->rip_metric);
n->rip_family = ntohs(n->rip_family);
if (!(*afswitch[n->rip_family].af_get)(DESTINATION, n,
&dst))
continue;
if (!(*afswitch[n->rip_family].af_get)(NETMASK,
n, &netmask))
memset(&netmask, 0, sizeof(netmask));
if (!(*afswitch[n->rip_family].af_get)(GATEWAY,
n, &gateway))
memcpy(&gateway, from, sizeof(gateway));
if (dst.sa_family >= af_max ||
(afp = &afswitch[dst.sa_family])->af_hash == NULL) {
syslog(LOG_INFO,
"route in unsupported address family (%d), from %s (af %d)\n",
dst.sa_family,
(*afswitch[from->sa_family].af_format)(from,
buf1, sizeof(buf1)),
from->sa_family);
continue;
}
if (((*afp->af_checkhost)(&dst)) == 0) {
syslog(LOG_DEBUG,
"bad host %s in route from %s (af %d)\n",
(*afswitch[dst.sa_family].af_format)(
&dst, buf1, sizeof(buf1)),
(*afswitch[from->sa_family].af_format)(from,
buf2, sizeof(buf2)),
from->sa_family);
continue;
}
if (n->rip_metric == 0 ||
(unsigned) n->rip_metric > HOPCNT_INFINITY) {
if (memcmp(from, &badfrom,
sizeof(badfrom)) != 0) {
syslog(LOG_ERR,
"bad metric (%d) from %s\n",
n->rip_metric,
(*afswitch[from->sa_family].af_format)(from,
buf1, sizeof(buf1)));
badfrom = *from;
/* Are we talking to ourself or a remote gateway?
*/
ifp1 = ifwithaddr(FROM_NADDR, 0, 1);
if (ifp1) {
if (ifp1->int_state & IS_REMOTE) {
if (ifp1->int_state & IS_PASSIVE) {
msglog("bogus input from %s on"
" supposedly passive %s",
naddr_ntoa(FROM_NADDR),
ifp1->int_name);
} else {
ifp1->int_act_time = now.tv_sec;
if (if_ok(ifp1, "remote "))
addrouteforif(ifp1);
}
} else {
trace_pkt("discard our own RIP response\n");
}
return;
}
/* Check the router from which message originated. We accept
* routing packets from routers directly connected via
* broadcast or point-to-point networks, and from
* those listed in /etc/gateways.
*/
if (!ifp) {
if (from->sin_addr.s_addr != unk_router)
msglog("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",
naddr_ntoa(FROM_NADDR),
ifp->int_name);
return;
}
/* Check required version
*/
if (((ifp->int_state & IS_NO_RIPV1_IN)
&& rip->rip_vers == RIPv1)
|| ((ifp->int_state & IS_NO_RIPV2_IN)
&& rip->rip_vers != RIPv1)) {
trace_pkt("discard RIPv%d response\n",
rip->rip_vers);
return;
}
/* Ignore routes via dead interface.
*/
if (ifp->int_state & IS_BROKE) {
trace_pkt("discard response via broken interface %s\n",
ifp->int_name);
return;
}
/* Authenticate the packet.
*/
if (ifp->int_passwd[0] != '\0') {
if ((n < lim) &&
(((struct netauth*)n)->a_type == RIP_AUTH_PW) &&
(bcmp(((struct netauth*)n)->au.au_pw,
ifp->int_passwd, sizeof(ifp->int_passwd)) == 0))
goto auth_ok;
/*
* Authentication failed.
*/
if (from->sin_addr.s_addr != use_auth)
msglog("missing authentication from %s",
naddr_ntoa(FROM_NADDR));
use_auth = from->sin_addr.s_addr;
return;
}
auth_ok:
for (; n < lim; n++) {
if (n->n_family == RIP_AF_AUTH)
continue;
NTOHL(n->n_metric);
dst = n->n_dst;
if (n->n_family != RIP_AF_INET
&& (n->n_family != RIP_AF_UNSPEC
|| dst != RIP_DEFAULT)) {
if (from->sin_addr.s_addr != bad_router)
msglog("route from %s to unsupported"
" address family %d,"
" destination %s",
naddr_ntoa(FROM_NADDR),
n->n_family,
naddr_ntoa(dst));
bad_router = from->sin_addr.s_addr;
continue;
}
/*
* Adjust metric according to incoming interface.
if (!check_dst(dst)) {
if (from->sin_addr.s_addr != bad_router)
msglog("bad destination %s from %s",
naddr_ntoa(dst),
naddr_ntoa(FROM_NADDR));
bad_router = from->sin_addr.s_addr;
return;
}
if (n->n_metric == 0
|| n->n_metric > HOPCNT_INFINITY) {
if (from->sin_addr.s_addr != bad_router)
msglog("bad metric %d from %s"
" for destination %s",
n->n_metric,
naddr_ntoa(FROM_NADDR),
naddr_ntoa(dst));
bad_router = from->sin_addr.s_addr;
return;
}
/* Notice the next-hop.
*/
if ((unsigned) n->rip_metric < HOPCNT_INFINITY)
n->rip_metric += ifp->int_metric;
if ((unsigned) n->rip_metric > HOPCNT_INFINITY)
n->rip_metric = HOPCNT_INFINITY;
rt = rtlookup(&dst);
if (rt == 0 ||
(rt->rt_state & (RTS_INTERNAL|RTS_INTERFACE)) ==
(RTS_INTERNAL|RTS_INTERFACE)) {
/*
* If we're hearing a logical network route
* back from a peer to which we sent it,
* ignore it.
*/
if (rt && rt->rt_state & RTS_SUBNET &&
(*afp->af_sendroute)(rt, from))
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;
if ((unsigned)n->rip_metric < HOPCNT_INFINITY) {
/*
* Look for an equivalent route that
* includes this one before adding
* this route.
*/
rt = rtfind(&dst);
if (rt && equal(&gateway, &rt->rt_router))
continue;
rtadd(&dst, &gateway, &netmask,
n->rip_metric, 0);
changes++;
/* 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;
} 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));
bad_nhop = from->sin_addr.s_addr;
}
}
if (rip->rip_vers == RIPv1
|| 0 == (mask = ntohl(n->n_mask))) {
mask = ripv1_mask_host(dst,ifp);
} else if ((ntohl(dst) & ~mask) != 0) {
if (bad_mask != from->sin_addr.s_addr) {
msglog("router %s sent bad netmask"
" %#x with %s",
naddr_ntoa(FROM_NADDR),
mask,
naddr_ntoa(dst));
bad_mask = from->sin_addr.s_addr;
}
continue;
}
if (rip->rip_vers == RIPv1)
n->n_tag = 0;
/*
* Update if from gateway and different,
* shorter, or equivalent but old route
* is getting stale.
/* Adjust metric according to incoming interface..
*/
if (equal(&gateway, &rt->rt_router)) {
if (n->rip_metric != rt->rt_metric) {
rtchange(rt, &gateway,
&netmask, n->rip_metric);
changes++;
rt->rt_timer = 0;
if (rt->rt_metric >= HOPCNT_INFINITY)
rt->rt_timer =
GARBAGE_TIME - EXPIRE_TIME;
} else if (rt->rt_metric < HOPCNT_INFINITY)
rt->rt_timer = 0;
} else if ((unsigned) n->rip_metric < rt->rt_metric ||
(rt->rt_metric == n->rip_metric &&
rt->rt_timer > (EXPIRE_TIME/2) &&
(unsigned) n->rip_metric < HOPCNT_INFINITY)) {
rtchange(rt, &gateway, &netmask, n->rip_metric);
changes++;
rt->rt_timer = 0;
n->n_metric += ifp->int_metric;
if (n->n_metric > HOPCNT_INFINITY)
n->n_metric = HOPCNT_INFINITY;
/* Recognize and ignore a default route we faked
* which is being sent back to us by a machine with
* broken split-horizon.
* Be a little more paranoid than that, and reject
* default routes with the same metric we advertised.
*/
if (ifp->int_d_metric != 0
&& dst == RIP_DEFAULT
&& n->n_metric >= ifp->int_d_metric)
continue;
/* We can receive aggregated RIPv2 routes that must
* be broken down before they are transmitted by
* RIPv1 via an interface on a subnet.
* We might also receive the same routes aggregated
* via other RIPv2 interfaces.
* This could cause duplicate routes to be sent on
* the RIPv1 interfaces. "Longest matching variable
* length netmasks" lets RIPv2 listeners understand,
* but breaking down the aggregated routes for RIPv1
* listeners can produce duplicate routes.
*
* Breaking down aggregated routes here bloats
* the daemon table, but does not hurt the kernel
* table, since routes are always aggregated for
* the kernel.
*
* Notice that this does not break down network
* routes corresponding to subnets. This is part
* of the defense against RS_NET_SYN.
*/
if (have_ripv1_out
&& (v1_mask = ripv1_mask_net(dst,0)) > mask
&& (((rt = rtget(dst,mask)) == 0
|| !(rt->rt_state & RS_NET_SYN)))) {
ddst_h = v1_mask & -v1_mask;
i = (v1_mask & ~mask)/ddst_h;
if (i >= 1024) {
/* Punt if we would have to generate
* an unreasonable number of routes.
*/
#ifdef DEBUG
msglog("accept %s from %s as-is"
" instead of as %d routes",
addrname(dst,mask,0),
naddr_ntoa(FROM_NADDR), i);
#endif
i = 0;
} else {
mask = v1_mask;
}
} else {
i = 0;
}
for (;;) {
input_route(ifp, FROM_NADDR,
dst, mask, gate, n);
if (i-- == 0)
break;
dst = htonl(ntohl(dst) + ddst_h);
}
}
break;
}
/*
* If changes have occurred, and if we have not sent a broadcast
* recently, send a dynamic update. This update is sent only
* on interfaces other than the one on which we received notice
* of the change. If we are within MIN_WAITTIME of a full update,
* don't bother sending; if we just sent a dynamic update
* and set a timer (nextbcast), delay until that time.
* If we just sent a full update, delay the dynamic update.
* Set a timer for a randomized value to suppress additional
* dynamic updates until it expires; if we delayed sending
* the current changes, set needupdate.
*/
if (changes && supplier &&
now.tv_sec - lastfullupdate.tv_sec < SUPPLY_INTERVAL-MAX_WAITTIME) {
u_long delay;
if (now.tv_sec - lastbcast.tv_sec >= MIN_WAITTIME &&
timercmp(&nextbcast, &now, <)) {
if (traceactions)
fprintf(ftrace, "send dynamic update\n");
toall(supply, RTS_CHANGED, ifp);
lastbcast = now;
needupdate = 0;
nextbcast.tv_sec = 0;
} else {
needupdate++;
if (traceactions)
fprintf(ftrace, "delay dynamic update\n");
}
#define RANDOMDELAY() (MIN_WAITTIME * 1000000 + \
(u_long)random() % ((MAX_WAITTIME - MIN_WAITTIME) * 1000000))
if (nextbcast.tv_sec == 0) {
delay = RANDOMDELAY();
if (traceactions)
fprintf(ftrace,
"inhibit dynamic update for %d usec\n",
delay);
nextbcast.tv_sec = delay / 1000000;
nextbcast.tv_usec = delay % 1000000;
timeradd(&nextbcast, &now, &nextbcast);
/*
* If the next possibly dynamic update
* is within MIN_WAITTIME of the next full update,
* force the delay past the full update,
* or we might send a dynamic update just before
* the full update.
*/
if (nextbcast.tv_sec > lastfullupdate.tv_sec +
SUPPLY_INTERVAL - MIN_WAITTIME)
nextbcast.tv_sec = lastfullupdate.tv_sec +
SUPPLY_INTERVAL + 1;
}
}
}
/* Process a single input route.
*/
static void
input_route(struct interface *ifp,
naddr from,
naddr dst,
naddr mask,
naddr gate,
struct netinfo *n)
{
int i;
struct rt_entry *rt;
struct rt_spare *rts, *rts0;
struct interface *ifp1;
time_t new_time;
/* See if the other guy is telling us to send our packets to him.
* Sometimes network routes arrive over a point-to-point link for
* the network containing the address(es) of the link.
*
* If our interface is broken, switch to using the other guy.
*/
ifp1 = ifwithaddr(dst, 1, 1);
if (ifp1 != 0
&& !(ifp1->int_state & IS_BROKE))
return;
/* Look for the route in our table.
*/
rt = rtget(dst, mask);
/* Consider adding the route if we do not already have it.
*/
if (rt == 0) {
/* Ignore unknown routes being poisoned.
*/
if (n->n_metric == HOPCNT_INFINITY)
return;
rtadd(dst, mask, gate, from, n->n_metric, n->n_tag, 0, ifp);
return;
}
/* We already know about the route. Consider this update.
*
* If (rt->rt_state & RS_NET_SYN), then this route
* is the same as a network route we have inferred
* for subnets we know, in order to tell RIPv1 routers
* about the subnets.
*
* It is impossible to tell if the route is coming
* from a distant RIPv2 router with the standard
* netmask because that router knows about the entire
* network, or if it is a round-about echo of a
* 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
* around as long as the interface exists.
*/
rts0 = rt->rt_spares;
for (rts = rts0, i = NUM_SPARES; i != 0; i--, rts++) {
if (rts->rts_router == from)
break;
/* Note the worst slot to reuse,
* other than the current slot.
*/
if (rts0 == rt->rt_spares
|| BETTER_LINK(rt, rts0, rts))
rts0 = rts;
}
if (i != 0) {
/* Found the router
*/
int old_metric = rts->rts_metric;
/* Keep poisoned routes around only long
* enough to pass the poison on.
*/
if (old_metric < HOPCNT_INFINITY)
new_time = now.tv_sec;
/* If this is an update for the router we currently prefer,
* then note it.
*/
if (i == NUM_SPARES) {
rtchange(rt,rt->rt_state, gate,rt->rt_router,
n->n_metric, n->n_tag, ifp, new_time, 0);
/* If the route got worse, check for something better.
*/
if (n->n_metric > old_metric)
rtswitch(rt, 0);
return;
}
/* This is an update for a spare route.
* Finished if the route is unchanged.
*/
if (rts->rts_gate == gate
&& old_metric == n->n_metric
&& rts->rts_tag == n->n_tag) {
rts->rts_time = new_time;
return;
}
} else {
/* The update is for a route we know about,
* but not from a familiar router.
*/
rts = rts0;
/* Save the route as a spare only if it has
* a better metric than our worst spare.
* This also ignores poisoned routes (those
* received with metric HOPCNT_INFINITY).
*/
if (n->n_metric >= rts->rts_metric)
return;
new_time = now.tv_sec;
}
trace_upslot(rt, rts, gate, from, ifp, n->n_metric,n->n_tag, new_time);
rts->rts_gate = gate;
rts->rts_router = from;
rts->rts_metric = n->n_metric;
rts->rts_tag = n->n_tag;
rts->rts_time = new_time;
rts->rts_ifp = ifp;
/* try to switch to a better route */
rtswitch(rt, rts);
}

View File

@ -1,92 +0,0 @@
/* $NetBSD: interface.h,v 1.8 1995/06/20 22:27:52 christos Exp $ */
/*
* Copyright (c) 1983, 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.
*
* @(#)interface.h 8.1 (Berkeley) 6/5/93
*/
/*
* Routing table management daemon.
*/
/*
* An ``interface'' is similar to an ifnet structure,
* except it doesn't contain q'ing info, and it also
* handles ``logical'' interfaces (remote gateways
* that we want to keep polling even if they go down).
* The list of interfaces which we maintain is used
* in supplying the gratuitous routing table updates.
*/
struct interface {
struct interface *int_next;
struct sockaddr int_addr; /* address on this host */
union {
struct sockaddr intu_broadaddr;
struct sockaddr intu_dstaddr;
} int_intu;
#define int_broadaddr int_intu.intu_broadaddr /* broadcast address */
#define int_dstaddr int_intu.intu_dstaddr /* other end of p-to-p link */
int int_metric; /* init's routing entry */
int int_flags; /* see below */
/* START INTERNET SPECIFIC */
u_long int_net; /* network # */
u_long int_netmask; /* net mask for addr */
u_long int_subnet; /* subnet # */
u_long int_subnetmask; /* subnet mask for addr */
/* END INTERNET SPECIFIC */
struct ifdebug int_input, int_output; /* packet tracing stuff */
int int_ipackets; /* input packets received */
int int_opackets; /* output packets sent */
char *int_name; /* from kernel if structure */
u_short int_transitions; /* times gone up-down */
};
/*
* 0x1 to 0x10 are reused from the kernel's ifnet definitions,
* the others agree with the RTS_ flags defined elsewhere.
*/
#define IFF_UP 0x1 /* interface is up */
#define IFF_BROADCAST 0x2 /* broadcast address valid */
#define IFF_DEBUG 0x4 /* turn on debugging */
#define IFF_LOOPBACK 0x8 /* software loopback net */
#define IFF_POINTOPOINT 0x10 /* interface is point-to-point link */
#define IFF_SUBNET 0x100000 /* interface on subnetted network */
#define IFF_PASSIVE 0x200000 /* can't tell if up/down */
#define IFF_INTERFACE 0x400000 /* hardware interface */
#define IFF_REMOTE 0x800000 /* interface isn't on this machine */
struct interface *if_ifwithaddr __P((struct sockaddr *));
struct interface *if_ifwithdstaddr __P((struct sockaddr *));
struct interface *if_ifwithnet __P((struct sockaddr *));
struct interface *if_iflookup __P((struct sockaddr *));

File diff suppressed because it is too large Load Diff

View File

@ -1,4 +1,4 @@
/* $NetBSD: output.c,v 1.9 1995/06/20 22:27:54 christos Exp $ */
/* $NetBSD: output.c,v 1.10 1996/08/10 01:29:26 thorpej Exp $ */
/*
* Copyright (c) 1983, 1988, 1993
@ -33,144 +33,827 @@
* SUCH DAMAGE.
*/
#ifndef lint
#if !defined(lint) && !defined(sgi)
#if 0
static char sccsid[] = "@(#)output.c 8.1 (Berkeley) 6/5/93";
#else
static char rcsid[] = "$NetBSD: output.c,v 1.9 1995/06/20 22:27:54 christos Exp $";
static char rcsid[] = "$NetBSD: output.c,v 1.10 1996/08/10 01:29:26 thorpej Exp $";
#endif
#endif /* not lint */
/*
* Routing Table Management Daemon
*/
#include "defs.h"
/*
* Apply the function "f" to all non-passive
* interfaces. If the interface supports the
* use of broadcasting use it, otherwise address
* the output to the known router.
*/
void
toall(f, rtstate, skipif)
void (*f) __P((struct sockaddr *, int, struct interface *, int));
int rtstate;
struct interface *skipif;
{
register struct interface *ifp;
register struct sockaddr *dst;
register int flags;
extern struct interface *ifnet;
for (ifp = ifnet; ifp; ifp = ifp->int_next) {
if (ifp->int_flags & IFF_PASSIVE || ifp == skipif)
continue;
dst = ifp->int_flags & IFF_BROADCAST ? &ifp->int_broadaddr :
ifp->int_flags & IFF_POINTOPOINT ? &ifp->int_dstaddr :
&ifp->int_addr;
flags = ifp->int_flags & IFF_INTERFACE ? MSG_DONTROUTE : 0;
(*f)(dst, flags, ifp, rtstate);
int update_seqno;
/* walk the tree of routes with this for output
*/
struct {
struct sockaddr_in to;
naddr to_mask;
naddr to_net;
naddr to_std_mask;
naddr to_std_net;
struct interface *ifp; /* usually output interface */
struct ws_buf { /* info for each buffer */
struct rip *buf;
struct netinfo *n;
struct netinfo *base;
struct netinfo *lim;
enum output_type type;
} v12, v2;
char metric; /* adjust metrics by interface */
int npackets;
u_int state;
#define WS_ST_FLASH 0x001 /* send only changed routes */
#define WS_ST_RIP2_SAFE 0x002 /* send RIPv2 safe for RIPv1 */
#define WS_ST_RIP2_ALL 0x004 /* send full featured RIPv2 */
#define WS_ST_AG 0x008 /* ok to aggregate subnets */
#define WS_ST_SUPER_AG 0x010 /* ok to aggregate networks */
#define WS_ST_SUB_AG 0x020 /* aggregate subnets in odd case */
#define WS_ST_QUERY 0x040 /* responding to a query */
#define WS_ST_TO_ON_NET 0x080 /* sending onto one of our nets */
#define WS_ST_DEFAULT 0x100 /* faking a default */
#define WS_ST_PM_RDISC 0x200 /* poor-man's router discovery */
} ws;
/* A buffer for what can be heard by both RIPv1 and RIPv2 listeners */
union pkt_buf ripv12_buf;
/* Another for only RIPv2 listeners */
union pkt_buf rip_v2_buf;
/* Send the contents of the global buffer via the non-multicast socket
*/
int /* <0 on failure */
output(enum output_type type,
struct sockaddr_in *dst, /* send to here */
struct interface *ifp,
struct rip *buf,
int size) /* this many bytes */
{
struct sockaddr_in sin;
int flags;
char *msg;
int res;
naddr tgt_mcast;
int soc;
int serrno;
sin = *dst;
if (sin.sin_port == 0)
sin.sin_port = htons(RIP_PORT);
#ifdef _HAVE_SIN_LEN
if (sin.sin_len == 0)
sin.sin_len = sizeof(sin);
#endif
soc = rip_sock;
flags = 0;
switch (type) {
case OUT_QUERY:
msg = "Answer Query";
if (soc < 0)
soc = ifp->int_rip_sock;
break;
case OUT_UNICAST:
msg = "Send";
if (soc < 0)
soc = ifp->int_rip_sock;
flags = MSG_DONTROUTE;
break;
case OUT_BROADCAST:
if (ifp->int_if_flags & IFF_POINTOPOINT) {
msg = "Send";
} else {
msg = "Send bcast";
}
flags = MSG_DONTROUTE;
break;
case OUT_MULTICAST:
if (ifp->int_if_flags & IFF_POINTOPOINT) {
msg = "Send pt-to-pt";
} else if (ifp->int_state & IS_DUP) {
trace_act("abort multicast output via %s"
" with duplicate address\n",
ifp->int_name);
return 0;
} else {
msg = "Send mcast";
if (rip_sock_mcast != ifp) {
#ifdef MCAST_PPP_BUG
/* Do not specifiy the primary interface
* explicitly if we have the multicast
* point-to-point kernel bug, since the
* kernel will do the wrong thing if the
* local address of a point-to-point link
* is the same as the address of an ordinary
* interface.
*/
if (ifp->int_addr == myaddr) {
tgt_mcast = 0;
} else
#endif
tgt_mcast = ifp->int_addr;
if (0 > setsockopt(rip_sock,
IPPROTO_IP, IP_MULTICAST_IF,
&tgt_mcast,
sizeof(tgt_mcast))) {
serrno = errno;
LOGERR("setsockopt(rip_sock,"
"IP_MULTICAST_IF)");
errno = serrno;
ifp = 0;
return -1;
}
rip_sock_mcast = ifp;
}
sin.sin_addr.s_addr = htonl(INADDR_RIP_GROUP);
}
break;
default:
/* Nothing; keep compilers happy. */
}
trace_rip(msg, "to", &sin, ifp, buf, size);
res = sendto(soc, buf, size, flags,
(struct sockaddr *)&sin, sizeof(sin));
if (res < 0
&& (ifp == 0 || !(ifp->int_state & IS_BROKE))) {
serrno = errno;
msglog("%s sendto(%s%s%s.%d): %s", msg,
ifp != 0 ? ifp->int_name : "",
ifp != 0 ? ", " : "",
inet_ntoa(sin.sin_addr),
ntohs(sin.sin_port),
strerror(errno));
errno = serrno;
}
return res;
}
/* install authentication if appropriate
*/
static void
set_auth(struct ws_buf *w)
{
if (ws.ifp != 0
&& ws.ifp->int_passwd[0] != '\0'
&& (ws.state & WS_ST_RIP2_SAFE)) {
w->n->n_family = RIP_AF_AUTH;
((struct netauth*)w->n)->a_type = RIP_AUTH_PW;
bcopy(ws.ifp->int_passwd, ((struct netauth*)w->n)->au.au_pw,
sizeof(((struct netauth*)w->n)->au.au_pw));
w->n++;
}
}
/*
* Output a preformed packet.
*/
/*ARGSUSED*/
void
sndmsg(dst, flags, ifp, rtstate)
struct sockaddr *dst;
int flags;
struct interface *ifp;
int rtstate;
{
(*afswitch[dst->sa_family].af_output)(s, flags,
dst, sizeof (struct rip));
TRACE_OUTPUT(ifp, dst, sizeof (struct rip));
/* Send the buffer
*/
static void
supply_write(struct ws_buf *wb)
{
/* Output multicast only if legal.
* If we would multcast and it would be illegal, then discard the
* packet.
*/
switch (wb->type) {
case NO_OUT_MULTICAST:
trace_pkt("skip multicast to %s because impossible\n",
naddr_ntoa(ws.to.sin_addr.s_addr));
break;
case NO_OUT_RIPV2:
break;
default:
if (output(wb->type, &ws.to, ws.ifp, wb->buf,
((char *)wb->n - (char*)wb->buf)) < 0
&& ws.ifp != 0)
if_sick(ws.ifp);
ws.npackets++;
break;
}
bzero(wb->n = wb->base, sizeof(*wb->n)*NETS_LEN);
if (wb->buf->rip_vers == RIPv2)
set_auth(wb);
}
/*
* Supply dst with the contents of the routing tables.
/* put an entry into the packet
*/
static void
supply_out(struct ag_info *ag)
{
int i;
naddr mask, v1_mask, s_mask, dst_h, ddst_h;
struct ws_buf *wb;
/* Skip this route if doing a flash update and it and the routes
* it aggregates have not changed recently.
*/
if (ag->ag_seqno < update_seqno
&& (ws.state & WS_ST_FLASH))
return;
/* Skip this route if required by split-horizon
*/
if (ag->ag_state & AGS_SPLIT_HZ)
return;
dst_h = ag->ag_dst_h;
mask = ag->ag_mask;
v1_mask = ripv1_mask_host(htonl(dst_h),
(ws.state & WS_ST_TO_ON_NET) ? ws.ifp : 0);
s_mask = std_mask(htonl(dst_h));
i = 0;
/* If we are sending RIPv2 packets that cannot (or must not) be
* heard by RIPv1 listeners, do not worry about sub- or supernets.
* Subnets (from other networks) can only be sent via multicast.
* A pair of subnet routes might have been promoted so that they
* are legal to send by RIPv1.
* If RIPv1 is off, use the multicast buffer, unless this is the
* fake default route and it is acting as a poor-man's router-
* discovery mechanism.
*/
if (((ws.state & WS_ST_RIP2_ALL)
&& (dst_h != RIP_DEFAULT || !(ws.state & WS_ST_PM_RDISC)))
|| ((ag->ag_state & AGS_RIPV2) && v1_mask != mask)) {
/* use the RIPv2-only buffer */
wb = &ws.v2;
} else {
/* use the RIPv1-or-RIPv2 buffer */
wb = &ws.v12;
/* Convert supernet route into corresponding set of network
* routes for RIPv1, but leave non-contiguous netmasks
* to ag_check().
*/
if (v1_mask > mask
&& mask + (mask & -mask) == 0) {
ddst_h = v1_mask & -v1_mask;
i = (v1_mask & ~mask)/ddst_h;
if (i >= 1024) {
/* Punt if we would have to generate an
* unreasonable number of routes.
*/
#ifdef DEBUG
msglog("sending %s to %s as-is instead"
" of as %d routes",
addrname(htonl(dst_h),mask,0),
naddr_ntoa(ws.to.sin_addr.s_addr), i);
#endif
i = 0;
} else {
mask = v1_mask;
}
}
}
do {
wb->n->n_family = RIP_AF_INET;
wb->n->n_dst = htonl(dst_h);
/* If the route is from router-discovery or we are
* shutting down, admit only a bad metric.
*/
wb->n->n_metric = ((stopint || ag->ag_metric < 1)
? HOPCNT_INFINITY
: ag->ag_metric);
HTONL(wb->n->n_metric);
if (wb->buf->rip_vers == RIPv2) {
if (ag->ag_nhop != 0
&& (ws.state & WS_ST_RIP2_SAFE)
&& ((ws.state & WS_ST_QUERY)
|| (ag->ag_nhop != ws.ifp->int_addr
&& on_net(ag->ag_nhop,
ws.ifp->int_net,
ws.ifp->int_mask))))
wb->n->n_nhop = ag->ag_nhop;
if ((ws.state & WS_ST_RIP2_ALL)
|| mask != s_mask)
wb->n->n_mask = htonl(mask);
wb->n->n_tag = ag->ag_tag;
}
dst_h += ddst_h;
if (++wb->n >= wb->lim)
supply_write(wb);
} while (i-- != 0);
}
/* supply one route from the table
*/
/* ARGSUSED */
static int
walk_supply(struct radix_node *rn, void *argp)
{
#define RT ((struct rt_entry *)rn)
#if 0
struct walkarg *w = argp; /* not used */
#endif
u_short ags = 0;
char metric, pref;
naddr dst, nhop;
/* Do not advertise the loopback interface
* or external remote interfaces
*/
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))
return 0;
/* If being quiet about our ability to forward, then
* do not say anything unless responding to a query.
*/
if (!supplier && !(ws.state & WS_ST_QUERY))
return 0;
dst = RT->rt_dst;
/* do not collide with the fake default route */
if (dst == RIP_DEFAULT
&& (ws.state & WS_ST_DEFAULT))
return 0;
if (RT->rt_state & RS_NET_SYN) {
if (RT->rt_state & RS_NET_INT) {
/* Do not send manual synthetic network routes
* into the subnet.
*/
if (on_net(ws.to.sin_addr.s_addr,
ntohl(dst), RT->rt_mask))
return 0;
} else {
/* Do not send automatic synthetic network routes
* if they are not needed becaus no RIPv1 listeners
* can hear them.
*/
if (ws.state & WS_ST_RIP2_ALL)
return 0;
/* Do not send automatic synthetic network routes to
* the real subnet.
*/
if (on_net(ws.to.sin_addr.s_addr,
ntohl(dst), RT->rt_mask))
return 0;
}
nhop = 0;
} else {
/* Advertise the next hop if this is not a route for one
* of our interfaces and the next hop is on the same
* network as the target.
*/
if (!(RT->rt_state & RS_IF)
&& RT->rt_gate != myaddr
&& RT->rt_gate != loopaddr)
nhop = RT->rt_gate;
else
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;
}
if (RT->rt_state & RS_MHOME) {
/* retain host route of multi-homed servers */
;
} else if (RT_ISHOST(RT)) {
/* We should always aggregate the host routes
* for the local end of our point-to-point links.
* If we are suppressing host routes in general, then do so.
* Avoid advertising host routes onto their own network,
* where they should be handled by proxy-ARP.
*/
if ((RT->rt_state & RS_LOCAL)
|| ridhosts
|| (ws.state & WS_ST_SUPER_AG)
|| on_net(dst, ws.to_net, ws.to_mask))
ags |= AGS_SUPPRESS;
if (ws.state & WS_ST_SUPER_AG)
ags |= AGS_PROMOTE;
} else if (ws.state & WS_ST_AG) {
/* Aggregate network routes, if we are allowed.
*/
ags |= AGS_SUPPRESS;
/* Generate supernets if allowed.
* If we can be heard by RIPv1 systems, we will
* later convert back to ordinary nets.
* This unifies dealing with received supernets.
*/
if ((RT->rt_state & RS_SUBNET)
|| (ws.state & WS_ST_SUPER_AG))
ags |= AGS_PROMOTE;
}
/* Do not send RIPv1 advertisements of subnets to other
* networks. If possible, multicast them by RIPv2.
*/
if ((RT->rt_state & RS_SUBNET)
&& !(ws.state & WS_ST_RIP2_ALL)
&& !on_net(dst, ws.to_std_net, ws.to_std_mask)) {
ags |= AGS_RIPV2 | AGS_PROMOTE;
if (ws.state & WS_ST_SUB_AG)
ags |= AGS_SUPPRESS;
}
/* Do not send a route back to where it came from, except in
* response to a query. This is "split-horizon". That means not
* advertising back to the same network and so via the same interface.
*
* We want to suppress routes that might have been fragmented
* from this route by a RIPv1 router and sent back to us, and so we
* cannot forget this route here. Let the split-horizon route
* aggregate (suppress) the fragmented routes and then itself be
* forgotten.
*
* Include the routes for both ends of point-to-point interfaces
* since the other side presumably knows them as well as we do.
*/
if (RT->rt_ifp == ws.ifp && ws.ifp != 0
&& !(ws.state & WS_ST_QUERY)
&& (ws.state & WS_ST_TO_ON_NET)
&& (!(RT->rt_state & RS_IF)
|| ws.ifp->int_if_flags & IFF_POINTOPOINT)) {
ags |= AGS_SPLIT_HZ;
ags &= ~(AGS_PROMOTE | AGS_SUPPRESS);
}
ag_check(dst, RT->rt_mask, 0, nhop, metric, pref,
RT->rt_seqno, RT->rt_tag, ags, supply_out);
return 0;
#undef RT
}
/* Supply dst with the contents of the routing tables.
* If this won't fit in one packet, chop it up into several.
*/
void
supply(dst, flags, ifp, rtstate)
struct sockaddr *dst;
int flags;
struct interface *ifp;
int rtstate;
supply(struct sockaddr_in *dst,
struct interface *ifp, /* output interface */
enum output_type type,
int flash, /* 1=flash update */
int vers) /* RIP version */
{
register struct rt_entry *rt;
register struct netinfo *n = msg->rip_nets;
register struct rthash *rh;
struct rthash *base = hosthash;
int doinghost = 1, size;
void (*output) __P((int, int, struct sockaddr *, int)) =
afswitch[dst->sa_family].af_output;
int (*sendroute) __P((struct rt_entry *, struct sockaddr *)) =
afswitch[dst->sa_family].af_sendroute;
int npackets = 0;
static int init = 1;
struct rt_entry *rt;
msg->rip_cmd = RIPCMD_RESPONSE;
msg->rip_vers = RIP_VERSION_1;
memset(msg->rip_res1, 0, sizeof(msg->rip_res1));
again:
for (rh = base; rh < &base[ROUTEHASHSIZ]; rh++)
for (rt = rh->cqh_first; rt != (void *) rh; rt = rt->rt_entry.cqe_next) {
/*
* Don't resend the information on the network
* from which it was received (unless sending
* in response to a query).
ws.state = 0;
ws.to = *dst;
ws.to_std_mask = std_mask(ws.to.sin_addr.s_addr);
ws.to_std_net = ntohl(ws.to.sin_addr.s_addr) & ws.to_std_mask;
if (ifp != 0) {
ws.to_mask = ifp->int_mask;
ws.to_net = ifp->int_net;
if (on_net(ws.to.sin_addr.s_addr, ws.to_net, ws.to_mask))
ws.state |= WS_ST_TO_ON_NET;
} else {
ws.to_mask = ripv1_mask_net(ws.to.sin_addr.s_addr, 0);
ws.to_net = ntohl(ws.to.sin_addr.s_addr) & ws.to_mask;
rt = rtfind(dst->sin_addr.s_addr);
if (rt)
ifp = rt->rt_ifp;
}
ws.npackets = 0;
if (flash)
ws.state |= WS_ST_FLASH;
if (type == OUT_QUERY)
ws.state |= WS_ST_QUERY;
if ((ws.ifp = ifp) == 0) {
ws.metric = 1;
} else {
/* Adjust the advertised metric by the outgoing interface
* metric.
*/
if (ifp && rt->rt_ifp == ifp &&
(rt->rt_state & RTS_INTERFACE) == 0)
continue;
if (rt->rt_state & RTS_EXTERNAL)
continue;
/*
* For dynamic updates, limit update to routes
* with the specified state.
ws.metric = ifp->int_metric+1;
}
if (init) {
init = 0;
bzero(&ripv12_buf, sizeof(ripv12_buf));
ripv12_buf.rip.rip_cmd = RIPCMD_RESPONSE;
ws.v12.buf = &ripv12_buf.rip;
ws.v12.base = &ws.v12.buf->rip_nets[0];
ws.v12.lim = ws.v12.base + NETS_LEN;
bzero(&rip_v2_buf, sizeof(rip_v2_buf));
rip_v2_buf.rip.rip_cmd = RIPCMD_RESPONSE;
rip_v2_buf.rip.rip_vers = RIPv2;
ws.v2.buf = &rip_v2_buf.rip;
ws.v2.base = &ws.v2.buf->rip_nets[0];
ws.v2.lim = ws.v2.base + NETS_LEN;
}
ripv12_buf.rip.rip_vers = vers;
ws.v12.n = ws.v12.base;
set_auth(&ws.v12);
ws.v2.n = ws.v2.base;
set_auth(&ws.v2);
switch (type) {
case OUT_BROADCAST:
ws.v2.type = ((ws.ifp != 0
&& (ws.ifp->int_if_flags & IFF_MULTICAST))
? OUT_MULTICAST
: NO_OUT_MULTICAST);
ws.v12.type = OUT_BROADCAST;
break;
case OUT_MULTICAST:
ws.v2.type = ((ws.ifp != 0
&& (ws.ifp->int_if_flags & IFF_MULTICAST))
? OUT_MULTICAST
: NO_OUT_MULTICAST);
ws.v12.type = OUT_BROADCAST;
break;
case OUT_UNICAST:
case OUT_QUERY:
ws.v2.type = (vers == RIPv2) ? type : NO_OUT_RIPV2;
ws.v12.type = type;
break;
default:
ws.v2.type = type;
ws.v12.type = type;
break;
}
if (vers == RIPv2) {
/* if asked to send RIPv2, send at least that which can
* be safely heard by RIPv1 listeners.
*/
if (rtstate && (rt->rt_state & rtstate) == 0)
continue;
/*
* Limit the spread of subnet information
* to those who are interested.
*/
if (doinghost == 0 && rt->rt_state & RTS_SUBNET) {
if (rt->rt_dst.sa_family != dst->sa_family)
continue;
if ((*sendroute)(rt, dst) == 0)
continue;
ws.state |= WS_ST_RIP2_SAFE;
/* full RIPv2 only if cannot be heard by RIPv1 listeners */
if (type != OUT_BROADCAST)
ws.state |= WS_ST_RIP2_ALL;
if (!(ws.state & WS_ST_TO_ON_NET)) {
ws.state |= (WS_ST_AG | WS_ST_SUPER_AG);
} else if (ws.ifp == 0 || !(ws.ifp->int_state & IS_NO_AG)) {
ws.state |= WS_ST_AG;
if (type != OUT_BROADCAST
&& (ws.ifp == 0
|| !(ws.ifp->int_state & IS_NO_SUPER_AG)))
ws.state |= WS_ST_SUPER_AG;
}
size = (char *)n - packet;
if (size > MAXPACKETSIZE - sizeof (struct netinfo)) {
TRACE_OUTPUT(ifp, dst, size);
(*output)(s, flags, dst, size);
/*
* If only sending to ourselves,
* one packet is enough to monitor interface.
} else if (ws.ifp == 0 || !(ws.ifp->int_state & IS_NO_AG)) {
ws.state |= WS_ST_SUB_AG;
}
if (supplier) {
/* Fake a default route if asked, and if there is not
* a better, real default route.
*/
if (ifp->int_d_metric != 0
&& (0 == (rt = rtget(RIP_DEFAULT, 0))
|| rt->rt_metric+ws.metric >= ifp->int_d_metric)) {
ws.state |= WS_ST_DEFAULT;
ag_check(0, 0, 0, 0,
ifp->int_d_metric,ifp->int_d_metric,
0, 0, 0, supply_out);
}
if ((ws.state & WS_ST_RIP2_ALL)
&& (ifp->int_state & IS_PM_RDISC)) {
ws.state |= WS_ST_PM_RDISC;
ripv12_buf.rip.rip_vers = RIPv1;
}
}
(void)rn_walktree(rhead, walk_supply, 0);
ag_flush(0,0,supply_out);
/* Flush the packet buffers, provided they are not empty and
* do not contain only the password.
*/
if (ws.v12.n != ws.v12.base
&& (ws.v12.n > ws.v12.base+1
|| ws.v12.n->n_family != RIP_AF_AUTH))
supply_write(&ws.v12);
if (ws.v2.n != ws.v2.base
&& (ws.v2.n > ws.v2.base+1
|| ws.v2.n->n_family != RIP_AF_AUTH))
supply_write(&ws.v2);
/* If we sent nothing and this is an answer to a query, send
* an empty buffer.
*/
if (ws.npackets == 0
&& (ws.state & WS_ST_QUERY))
supply_write(&ws.v12);
}
/* send all of the routing table or just do a flash update
*/
void
rip_bcast(int flash)
{
#ifdef _HAVE_SIN_LEN
static struct sockaddr_in dst = {sizeof(dst), AF_INET};
#else
static struct sockaddr_in dst = {AF_INET};
#endif
struct interface *ifp;
enum output_type type;
int vers;
struct timeval rtime;
need_flash = 0;
intvl_random(&rtime, MIN_WAITTIME, MAX_WAITTIME);
no_flash = rtime;
timevaladd(&no_flash, &now);
if (rip_sock < 0)
return;
trace_act("send %s and inhibit dynamic updates for %.3f sec\n",
flash ? "dynamic update" : "all routes",
rtime.tv_sec + ((float)rtime.tv_usec)/1000000.0);
for (ifp = ifnet; ifp != 0; ifp = ifp->int_next) {
/* skip interfaces not doing RIP, those already queried,
* and aliases. Do try broken interfaces to see
* if they have healed.
*/
if (0 != (ifp->int_state & (IS_PASSIVE | IS_ALIAS)))
continue;
/* skip turned off interfaces */
if (!iff_alive(ifp->int_if_flags))
continue;
/* default to RIPv1 output */
if (ifp->int_state & IS_NO_RIPV1_OUT) {
/* Say nothing if this interface is turned off */
if (ifp->int_state & IS_NO_RIPV2_OUT)
continue;
vers = RIPv2;
} else {
vers = RIPv1;
}
if (ifp->int_if_flags & IFF_BROADCAST) {
/* ordinary, hardware interface */
dst.sin_addr.s_addr = ifp->int_brdaddr;
/* if RIPv1 is not turned off, then broadcast so
* that RIPv1 listeners can hear.
*/
if (ifp && (ifp->int_flags &
(IFF_BROADCAST | IFF_POINTOPOINT | IFF_REMOTE)) == 0)
return;
n = msg->rip_nets;
npackets++;
if (vers == RIPv2
&& (ifp->int_state & IS_NO_RIPV1_OUT)) {
type = OUT_MULTICAST;
} else {
type = OUT_BROADCAST;
}
} else if (ifp->int_if_flags & IFF_POINTOPOINT) {
/* point-to-point hardware interface */
dst.sin_addr.s_addr = ifp->int_dstaddr;
type = OUT_UNICAST;
} else {
/* remote interface */
dst.sin_addr.s_addr = ifp->int_addr;
type = OUT_UNICAST;
}
(*afswitch[rt->rt_dst.sa_family].af_put)(n, &rt->rt_dst);
n->rip_metric = htonl(rt->rt_metric);
n++;
supply(&dst, ifp, type, flash, vers);
}
if (doinghost) {
doinghost = 0;
base = nethash;
goto again;
}
if (n != msg->rip_nets || (npackets == 0 && rtstate == 0)) {
size = (char *)n - packet;
TRACE_OUTPUT(ifp, dst, size);
(*output)(s, flags, dst, size);
update_seqno++; /* all routes are up to date */
}
/* Ask for routes
* Do it only once to an interface, and not even after the interface
* was broken and recovered.
*/
void
rip_query(void)
{
#ifdef _HAVE_SIN_LEN
static struct sockaddr_in dst = {sizeof(dst), AF_INET};
#else
static struct sockaddr_in dst = {AF_INET};
#endif
struct interface *ifp;
struct rip buf;
enum output_type type;
if (rip_sock < 0)
return;
bzero(&buf, sizeof(buf));
for (ifp = ifnet; ifp; ifp = ifp->int_next) {
/* skip interfaces not doing RIP, those already queried,
* and aliases. Do try broken interfaces to see
* if they have healed.
*/
if (0 != (ifp->int_state & (IS_RIP_QUERIED
| IS_PASSIVE | IS_ALIAS)))
continue;
/* skip turned off interfaces */
if (!iff_alive(ifp->int_if_flags))
continue;
/* default to RIPv1 output */
if (ifp->int_state & IS_NO_RIPV2_OUT) {
/* Say nothing if this interface is turned off */
if (ifp->int_state & IS_NO_RIPV1_OUT)
continue;
buf.rip_vers = RIPv1;
} else {
buf.rip_vers = RIPv2;
}
buf.rip_cmd = RIPCMD_REQUEST;
buf.rip_nets[0].n_family = RIP_AF_UNSPEC;
buf.rip_nets[0].n_metric = htonl(HOPCNT_INFINITY);
if (ifp->int_if_flags & IFF_BROADCAST) {
/* ordinary, hardware interface */
dst.sin_addr.s_addr = ifp->int_brdaddr;
/* if RIPv1 is not turned off, then broadcast so
* that RIPv1 listeners can hear.
*/
if (buf.rip_vers == RIPv2
&& (ifp->int_state & IS_NO_RIPV1_OUT)) {
type = OUT_MULTICAST;
} else {
type = OUT_BROADCAST;
}
} else if (ifp->int_if_flags & IFF_POINTOPOINT) {
/* point-to-point hardware interface */
dst.sin_addr.s_addr = ifp->int_dstaddr;
type = OUT_UNICAST;
} else {
/* remote interface */
dst.sin_addr.s_addr = ifp->int_addr;
type = OUT_UNICAST;
}
ifp->int_state |= IS_RIP_QUERIED;
if (output(type, &dst, ifp, &buf, sizeof(buf)) < 0)
if_sick(ifp);
}
}

View File

@ -1,3 +1,5 @@
/* $NetBSD: parms.c,v 1.2 1996/08/10 01:29:30 thorpej Exp $ */
/*
* Copyright (c) 1983, 1993
* The Regents of the University of California. All rights reserved.
@ -32,11 +34,13 @@
*/
#if !defined(lint) && !defined(sgi)
#if 0
static char sccsid[] = "@(#)if.c 8.1 (Berkeley) 6/5/93";
#else
static char rcsid[] = "$NetBSD: parms.c,v 1.2 1996/08/10 01:29:30 thorpej Exp $";
#endif
#endif /* not lint */
#ident "$Revision: 1.1.1.1 $"
#include "defs.h"
#include "pathnames.h"
@ -110,7 +114,7 @@ get_parms(struct interface *ifp)
ifp->int_state |= IS_NO_RDISC;
if (ifp->int_state & IS_PASSIVE)
ifp->int_state |= (IS_NO_RIP | IS_NO_RDISC);
if (ifp->int_state&(IS_NO_RIP|IS_NO_RDISC) == (IS_NO_RIP|IS_NO_RDISC))
if ((ifp->int_state&(IS_NO_RIP|IS_NO_RDISC)) == (IS_NO_RIP|IS_NO_RDISC))
ifp->int_state |= IS_PASSIVE;
}
@ -270,7 +274,8 @@ gwkludge(void)
state |= IS_NO_RDISC;
if (state & IS_PASSIVE)
state |= (IS_NO_RIP | IS_NO_RDISC);
if (state & (IS_NO_RIP|IS_NO_RDISC) == (IS_NO_RIP|IS_NO_RDISC))
if ((state & (IS_NO_RIP|IS_NO_RDISC)) ==
(IS_NO_RIP|IS_NO_RDISC))
state |= IS_PASSIVE;
parmp = (struct parm*)malloc(sizeof(*parmp));
@ -353,7 +358,7 @@ parse_parms(char *line)
if (!strncasecmp("subnet=",line,7)) {
intnetp = (struct intnet*)malloc(sizeof(*intnetp));
intnetp->intnet_metric = 1;
if (p = strrchr(line,',')) {
if ((p = strrchr(line,','))) {
*p++ = '\0';
intnetp->intnet_metric = (int)strtol(p,&p,0);
if (*p != '\0'

View File

@ -1,4 +1,4 @@
/* $NetBSD: pathnames.h,v 1.6 1995/03/18 15:00:37 cgd Exp $ */
/* $NetBSD: pathnames.h,v 1.7 1996/08/10 01:29:34 thorpej Exp $ */
/*
* Copyright (c) 1989, 1993
@ -38,3 +38,10 @@
#include <paths.h>
#define _PATH_GATEWAYS "/etc/gateways"
/* All remotely requested trace files must either start with this prefix
* 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.
*/
#define _PATH_TRACE "/tmp/routed.log"

View File

@ -1,8 +0,0 @@
# $NetBSD: Makefile,v 1.6 1995/03/18 15:00:51 cgd Exp $
# @(#)Makefile 8.1 (Berkeley) 6/5/93
PROG= query
NOMAN= noman
.include "../../Makefile.inc"
.include <bsd.prog.mk>

View File

@ -1,299 +0,0 @@
/* $NetBSD: query.c,v 1.10 1995/06/20 22:28:08 christos Exp $ */
/*-
* Copyright (c) 1982, 1986, 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) 1982, 1986, 1993\n\
The Regents of the University of California. All rights reserved.\n";
#endif /* not lint */
#ifndef lint
#if 0
static char sccsid[] = "@(#)query.c 8.1 (Berkeley) 6/5/93";
#else
static char rcsid[] = "$NetBSD: query.c,v 1.10 1995/06/20 22:28:08 christos Exp $";
#endif
#endif /* not lint */
#include <sys/param.h>
#include <sys/protosw.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <signal.h>
#include <netinet/in.h>
#include <protocols/routed.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <errno.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define WTIME 5 /* Time to wait for all responses */
#define STIME 500000 /* usec to wait for another response */
int s;
int timedout;
void timeout();
char packet[MAXPACKETSIZE];
int nflag;
main(argc, argv)
int argc;
char *argv[];
{
extern char *optarg;
extern int optind;
int ch, cc, count, bits;
struct sockaddr from;
struct sigaction sigact;
int fromlen = sizeof(from), size = 32*1024;
struct timeval shorttime;
while ((ch = getopt(argc, argv, "n")) != EOF)
switch (ch) {
case 'n':
nflag++;
break;
case '?':
default:
goto usage;
}
argv += optind;
if (!*argv) {
usage: printf("usage: query [-n] hosts...\n");
exit(1);
}
s = socket(AF_INET, SOCK_DGRAM, 0);
if (s < 0) {
perror("socket");
exit(2);
}
if (setsockopt(s, SOL_SOCKET, SO_RCVBUF, &size, sizeof(size)) < 0)
perror("setsockopt SO_RCVBUF");
while (*argv) {
query(*argv++);
count++;
}
/*
* Listen for returning packets;
* may be more than one packet per host.
*/
bits = 1 << s;
memset(&shorttime, 0, sizeof(shorttime));
shorttime.tv_usec = STIME;
memset(&sigact, 0, sizeof(sigact));
sigact.sa_handler = timeout;
/*sigact.sa_flags = 0; /* no restart */
if (sigaction(SIGALRM, &sigact, (struct sigaction *)NULL) == -1)
perror("sigaction");
alarm(WTIME);
while ((count > 0 && !timedout) ||
select(20, (fd_set *)&bits, NULL, NULL, &shorttime) > 0) {
cc = recvfrom(s, packet, sizeof (packet), 0,
&from, &fromlen);
if (cc <= 0) {
if (cc < 0) {
if (errno == EINTR)
continue;
perror("recvfrom");
(void) close(s);
exit(1);
}
continue;
}
rip_input(&from, cc);
count--;
}
exit (count > 0 ? count : 0);
}
query(host)
char *host;
{
struct sockaddr_in router;
register struct rip *msg = (struct rip *)packet;
struct hostent *hp;
struct servent *sp;
memset(&router, 0, sizeof (router));
router.sin_family = AF_INET;
if (inet_aton(host, &router.sin_addr) == 0) {
hp = gethostbyname(host);
if (hp == NULL) {
fprintf(stderr, "query: %s: ", host);
herror((char *)NULL);
exit(1);
}
memcpy(&router.sin_addr, hp->h_addr, hp->h_length);
}
sp = getservbyname("router", "udp");
if (sp == 0) {
printf("udp/router: service unknown\n");
exit(1);
}
router.sin_port = sp->s_port;
msg->rip_cmd = RIPCMD_REQUEST;
msg->rip_vers = RIP_VERSION_1;
msg->rip_nets[0].rip_dst.sa_family = htons(AF_UNSPEC);
msg->rip_nets[0].rip_metric = htonl(HOPCNT_INFINITY);
if (sendto(s, packet, sizeof (struct rip), 0,
(struct sockaddr *)&router, sizeof(router)) < 0)
perror(host);
}
/*
* Handle an incoming routing packet.
*/
rip_input(from, size)
struct sockaddr_in *from;
int size;
{
register struct rip *msg = (struct rip *)packet;
register struct netinfo *n;
char *name;
int lna, net, subnet;
struct hostent *hp;
struct netent *np;
if (msg->rip_cmd != RIPCMD_RESPONSE)
return;
printf("%d bytes from ", size);
if (nflag)
printf("%s:\n", inet_ntoa(from->sin_addr));
else {
hp = gethostbyaddr((char *)&from->sin_addr,
sizeof (struct in_addr), AF_INET);
name = hp == 0 ? "???" : hp->h_name;
printf("%s(%s):\n", name, inet_ntoa(from->sin_addr));
}
size -= sizeof (int);
n = msg->rip_nets;
while (size > 0) {
if (size < sizeof (struct netinfo))
break;
if (msg->rip_vers > 0) {
n->rip_dst.sa_family =
ntohs(n->rip_dst.sa_family);
n->rip_metric = ntohl(n->rip_metric);
}
switch (n->rip_dst.sa_family) {
case AF_INET:
{ register struct sockaddr_in *sin;
sin = (struct sockaddr_in *)&n->rip_dst;
net = inet_netof(sin->sin_addr);
subnet = inet_subnetof(sin->sin_addr);
lna = inet_lnaof(sin->sin_addr);
name = "???";
if (!nflag) {
if (sin->sin_addr.s_addr == 0)
name = "default";
else if (lna == INADDR_ANY) {
np = getnetbyaddr(net, AF_INET);
if (np)
name = np->n_name;
else if (net == 0)
name = "default";
} else if ((lna & 0xff) == 0 &&
(np = getnetbyaddr(subnet, AF_INET))) {
struct in_addr subnaddr, inet_makeaddr();
subnaddr = inet_makeaddr(subnet, INADDR_ANY);
if (memcmp(&sin->sin_addr, &subnaddr,
sizeof(subnaddr)) == 0)
name = np->n_name;
else
goto host;
} else {
host:
hp = gethostbyaddr((char *)&sin->sin_addr,
sizeof (struct in_addr), AF_INET);
if (hp)
name = hp->h_name;
}
printf("\t%-17s metric %2d name %s\n",
inet_ntoa(sin->sin_addr), n->rip_metric, name);
} else
printf("\t%-17s metric %2d\n",
inet_ntoa(sin->sin_addr), n->rip_metric);
break;
}
default:
{ u_short *p = (u_short *)n->rip_dst.sa_data;
printf("\t(af %d) %x %x %x %x %x %x %x, metric %d\n",
p[0], p[1], p[2], p[3], p[4], p[5], p[6],
n->rip_dst.sa_family,
n->rip_metric);
break;
}
}
size -= sizeof (struct netinfo), n++;
}
}
void
timeout()
{
timedout = 1;
}
/*
* Return the possible subnetwork number from an internet address.
* SHOULD FIND OUT WHETHER THIS IS A LOCAL NETWORK BEFORE LOOKING
* INSIDE OF THE HOST PART. We can only believe this if we have other
* information (e.g., we can find a name for this number).
*/
inet_subnetof(in)
struct in_addr in;
{
register u_long i = ntohl(in.s_addr);
if (IN_CLASSA(i))
return ((i & IN_CLASSB_NET) >> IN_CLASSB_NSHIFT);
else if (IN_CLASSB(i))
return ((i & IN_CLASSC_NET) >> IN_CLASSC_NSHIFT);
else
return ((i & 0xffffffc0) >> 28);
}

View File

@ -1,3 +1,5 @@
/* $NetBSD: radix.c,v 1.2 1996/08/10 01:29:39 thorpej Exp $ */
/*
* Copyright (c) 1988, 1989, 1993
* The Regents of the University of California. All rights reserved.
@ -41,7 +43,11 @@
#include <sys/domain.h>
#include <sys/syslog.h>
#include <net/radix.h>
#include <stdio.h>
#include <stdlib.h>
#include "defs.h"
#define min(a,b) (((a)<(b))?(a):(b))
#define log(x, msg) syslog(x, msg)
#define panic(s) {log(LOG_ERR,s); exit(1);}
@ -272,7 +278,7 @@ on1:
do {
register struct radix_mask *m;
t = t->rn_p;
if (m = t->rn_mklist) {
if ((m = t->rn_mklist)) {
/*
* If non-contiguous masks ever become important
* we can restore the masking and open coding of
@ -291,7 +297,7 @@ on1:
if (x && rn_satsifies_leaf(v, x, off))
return x;
}
} while (m = m->rm_mklist);
} while ((m = m->rm_mklist));
}
} while (t != top);
return 0;
@ -587,14 +593,14 @@ rn_addroute(v_arg, n_arg, head, treenodes)
if (x->rn_b < 0) {
for (mp = &t->rn_mklist; x; x = x->rn_dupedkey)
if (x->rn_mask && (x->rn_b >= b_leaf) && x->rn_mklist == 0) {
if (*mp = m = rn_new_radix_mask(x, 0))
if ((*mp = m = rn_new_radix_mask(x, 0)))
mp = &m->rm_mklist;
}
} else if (x->rn_mklist) {
/*
* Skip over masks whose index is > that of new node
*/
for (mp = &x->rn_mklist; m = *mp; mp = &m->rm_mklist)
for (mp = &x->rn_mklist; (m = *mp); mp = &m->rm_mklist)
if (m->rm_b >= b_leaf)
break;
t->rn_mklist = m; *mp = 0;
@ -614,7 +620,7 @@ on2:
* Need same criteria as when sorting dupedkeys to avoid
* double loop on deletion.
*/
for (mp = &x->rn_mklist; m = *mp; mp = &m->rm_mklist) {
for (mp = &x->rn_mklist; (m = *mp); mp = &m->rm_mklist) {
if (m->rm_b < b_leaf)
continue;
if (m->rm_b > b_leaf)
@ -696,7 +702,7 @@ rn_delete(v_arg, netmask_arg, head)
x = t;
t = t->rn_p;
} while (b <= t->rn_b && x != top);
for (mp = &x->rn_mklist; m = *mp; mp = &m->rm_mklist)
for (mp = &x->rn_mklist; (m = *mp); mp = &m->rm_mklist)
if (m == saved_m) {
*mp = m->rm_mklist;
MKFree(m);
@ -719,7 +725,7 @@ on1:
if (t) t->rn_ybro = tt->rn_ybro;
#endif
t = tt->rn_p;
if (dupedkey = saved_tt->rn_dupedkey) {
if ((dupedkey = saved_tt->rn_dupedkey)) {
if (tt == saved_tt) {
x = dupedkey; x->rn_p = t;
if (t->rn_l == tt) t->rn_l = x; else t->rn_r = x;
@ -750,7 +756,7 @@ on1:
*/
if (t->rn_mklist) {
if (x->rn_b >= 0) {
for (mp = &x->rn_mklist; m = *mp;)
for (mp = &x->rn_mklist; (m = *mp);)
mp = &m->rm_mklist;
*mp = t->rn_mklist;
} else {
@ -767,11 +773,13 @@ on1:
}
if (m)
#ifdef _KERNEL
printf("%s %x at %x\n",
"rn_delete: Orphaned Mask", m, x);
printf("%s %lx at %lx\n",
"rn_delete: Orphaned Mask",
(unsigned long)m, (unsigned long)x);
#else
syslog(LOG_ERR, "%s %x at %x\n",
"rn_delete: Orphaned Mask", m, x);
syslog(LOG_ERR, "%s %lx at %lx\n",
"rn_delete: Orphaned Mask",
(unsigned long)m, (unsigned long)x);
#endif
}
}
@ -822,7 +830,7 @@ rn_walktree(h, f, w)
rn = rn->rn_l;
next = rn;
/* Process leaves */
while (rn = base) {
while ((rn = base)) {
base = rn->rn_dupedkey;
if (!(rn->rn_flags & RNF_ROOT) && (error = (*f)(rn, w)))
return (error);

View File

@ -1,3 +1,5 @@
/* $NetBSD: rdisc.c,v 1.2 1996/08/10 01:29:43 thorpej Exp $ */
/*
* Copyright (c) 1995
* The Regents of the University of California. All rights reserved.
@ -32,11 +34,13 @@
*/
#if !defined(lint) && !defined(sgi)
#if 0
static char sccsid[] = "@(#)rdisc.c 8.1 (Berkeley) x/y/95";
#else
static char rcsid[] = "$NetBSD: rdisc.c,v 1.2 1996/08/10 01:29:43 thorpej Exp $";
#endif
#endif /* not lint */
#ident "$Revision: 1.1.1.1 $"
#include "defs.h"
#include <netinet/in_systm.h>
#include <netinet/ip.h>
@ -44,12 +48,12 @@ static char sccsid[] = "@(#)rdisc.c 8.1 (Berkeley) x/y/95";
/* router advertisement ICMP packet */
struct icmp_ad {
u_char icmp_type; /* type of message */
u_char icmp_code; /* type sub code */
u_short icmp_cksum; /* ones complement cksum of struct */
u_char icmp_ad_num; /* # of following router addresses */
u_char icmp_ad_asize; /* 2--words in each advertisement */
u_short icmp_ad_life; /* seconds of validity */
u_int8_t icmp_type; /* type of message */
u_int8_t icmp_code; /* type sub code */
u_int16_t icmp_cksum; /* ones complement cksum of struct */
u_int8_t icmp_ad_num; /* # of following router addresses */
u_int8_t icmp_ad_asize; /* 2--words in each advertisement */
u_int16_t icmp_ad_life; /* seconds of validity */
struct icmp_ad_info {
n_long icmp_ad_addr;
n_long icmp_ad_pref;
@ -58,9 +62,9 @@ struct icmp_ad {
/* router solicitation ICMP packet */
struct icmp_so {
u_char icmp_type; /* type of message */
u_char icmp_code; /* type sub code */
u_short icmp_cksum; /* ones complement cksum of struct */
u_int8_t icmp_type; /* type of message */
u_int8_t icmp_code; /* type sub code */
u_int16_t icmp_cksum; /* ones complement cksum of struct */
n_long icmp_so_rsvd;
};

View File

@ -1,4 +1,4 @@
.\" $NetBSD: routed.8,v 1.7 1996/02/06 20:34:28 scottr Exp $
.\" $NetBSD: routed.8,v 1.8 1996/08/10 01:29:47 thorpej Exp $
.\"
.\" Copyright (c) 1983, 1991, 1993
.\" The Regents of the University of California. All rights reserved.
@ -31,326 +31,570 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
.\" @(#)routed.8 8.2 (Berkeley) 12/11/93
.\" @(#)routed.8 8.2 (Berkeley) 12/11/93
.\"
.Dd December 11, 1993
.Dd June 1, 1996
.Dt ROUTED 8
.Os BSD 4.2
.Os BSD 4.4
.Sh NAME
.Nm routed
.Nd network routing daemon
.Nd network RIP and router discovery routing daemon
.Sh SYNOPSIS
.Nm routed
.Op Fl d
.Op Fl g
.Op Fl q
.Op Fl s
.Op Fl t
.Op Ar logfile
.Nm
.Op Fl sqdghmpAt
.Op Fl T Ar tracefile
.Oo
.Fl F
.Ar net Ns Op /mask Ns Op ,metric
.Oc
.OP Fl P Ar parms
.Sh DESCRIPTION
.Nm Routed
is invoked at boot time to manage the network routing tables.
The routing daemon uses a variant of the Xerox NS Routing
Information Protocol in maintaining up to date kernel routing
table entries.
It used a generalized protocol capable of use with multiple
address types, but is currently used only for Internet routing
within a cluster of networks.
is a dameon invoked at boot time to manage the network
routing tables.
It uses Routing Information Protocol, RIPv1 (RFC\ 1058),
RIPv2 (RFC\ 1723),
and Internet Router Discovery Protocol (RFC 1256)
to maintain the kernel routing table.
The RIPv1 protocol is based on the reference 4.3BSD daemon.
.Pp
In normal operation
.Nm routed
listens on the
It listens on the
.Xr udp 4
socket for the
.Xr route 8
service (see
.Xr services 5 )
for routing information packets. If the host is an
internetwork router, it periodically supplies copies
of its routing tables to any directly connected hosts
and networks.
for Routing Information Protocol packets.
It also sends and receives multicast Router Discovery ICMP messages.
If the host is a router,
.Nm
periodically supplies copies
of its routing tables to any directly connected hosts and networks.
It also advertise or solicits default routes using Router Discovery
ICMP messages.
.Pp
When
.Nm routed
is started, it uses the
.Dv SIOCGIFCONF
.Xr ioctl 2
to find those
When started (or when a network interface is later turned on),
.Nm
uses an AF_ROUTE address family facility to find those
directly connected interfaces configured into the
system and marked ``up'' (the software loopback interface
is ignored). If multiple interfaces
are present, it is assumed that the host will forward packets
between networks.
.Nm Routed
then transmits a
.Em request
packet on each interface (using a broadcast packet if
the interface supports it) and enters a loop, listening
for
system and marked "up".
It adds necessary routes for the interfaces
to the kernel routing table.
Soon after being first started, and provided there is at least one
interface on which RIP has not been disabled,
.Nm
deletes all pre-existing
non-static routes in kernel table.
Static routes in the kernel table are preserved and
included in RIP responses if they have a valid RIP metric
(see
.Xr route 8 ).
.Pp
If more than one interface is present (not counting the loopback interface),
it is assumed that the host should forward packets among the
connected networks.
After transmitting a RIP
.Em request
and
.Em response
packets from other hosts.
Router Discovery Advertisements or Solicitations on a new interface,
the daemon enters a loop, listening for
RIP request and response and Router Discover packets from other hosts.
.Pp
When a
.Em request
packet is received,
.Nm routed
.Nm
formulates a reply based on the information maintained in its
internal tables. The
internal tables.
The
.Em response
packet generated contains a list of known routes, each marked
with a ``hop count'' metric (a count of 16, or greater, is
considered ``infinite''). The metric associated with each
route returned provides a metric
.Em relative to the sender .
with a "hop count" metric (a count of 16 or greater is
considered "infinite").
Advertised metrics reflect the metric associated with interface
(see
.Xr ifconfig 8 ),
so setting the metric on an interface
is an effective way to steer traffic.
.Pp
.Em Response
packets received by
.Nm routed
are used to update the routing tables if one of the following
conditions is satisfied:
.Bl -enum
.It
No routing table entry exists for the destination network
or host, and the metric indicates the destination is ``reachable''
(i.e. the hop count is not infinite).
.It
The source host of the packet is the same as the router in the
existing routing table entry. That is, updated information is
being received from the very internetwork router through which
packets for the destination are being routed.
.It
The existing entry in the routing table has not been updated for
some time (defined to be 90 seconds) and the route is at least
as cost effective as the current route.
.It
The new route describes a shorter route to the destination than
the one currently stored in the routing tables; the metric of
the new route is compared against the one stored in the table
to decide this.
.El
Responses do not contain routes with a first hop on the requesting
network to implement in part
.Em split-horizon .
Requests from query programs
such as
.Xr rtquery 8
are answered with the complete table.
.Pp
The routing table maintained by the daemon
includes space for several gateways for each destination
to speed recovery from a failing router.
RIP
.Em response
packets received are used to update the routing tables provided they are
from one of the several currently recognized gateways or
advertise a better metric than at least one of the existing
gateways.
.Pp
When an update is applied,
.Nm routed
records the change in its internal tables and updates the kernel
routing table.
The change is reflected in the next
.Nm
records the change in its own tables and updates the kernel routing table
if the best route to the destination changes.
The change in the kernel routing tableis reflected in the next batch of
.Em response
packet sent.
packets sent.
If the next response is not scheduled for a while, a
.Em flash update
response containing only recently changed routes is sent.
.Pp
In addition to processing incoming packets,
.Nm routed
.Nm
also periodically checks the routing table entries.
If an entry has not been updated for 3 minutes, the entry's metric
is set to infinity and marked for deletion. Deletions are delayed
an additional 60 seconds to insure the invalidation is propagated
throughout the local internet.
is set to infinity and marked for deletion.
Deletions are delayed until the route has been advertised with
an infinite metric to insure the invalidation
is propagated throughout the local internet.
This is a form of
.Em poison reverse .
.Pp
Routes in the kernel table that are added or changed as a result
of ICMP Redirect messages are deleted after a while to minimize
.Em black-holes .
When a TCP connection suffers a timeout,
the kernel tells
.Nm routed ,
which deletes all redirected routes
through the gateway involved, advances the age of all RIP routes through
the gateway to allow an alternate to be chosen, and advances of the
age of any relevant Router Discovery Protocol default routes.
.Pp
Hosts acting as internetwork routers gratuitously supply their
routing tables every 30 seconds to all directly connected hosts
and networks.
The response is sent to the broadcast address on nets capable of that function,
These RIP responses are sent to the broadcast address on nets that support
broadcasting,
to the destination address on point-to-point links, and to the router's
own address on other networks.
The normal routing tables are bypassed when sending gratuitous responses.
The reception of responses on each network is used to determine that the
network and interface are functioning correctly.
If no response is received on an interface, another route may be chosen
to route around the interface, or the route may be dropped if no alternative
is available.
If RIPv2 is enabled, multicast packets are sent on interfaces that
support multicasting.
.Pp
If no response is received on a remote interface, if there are errors
while sending responses,
or if there are more errors than input or output (see
.Xr netstat 8 ),
then the cable or some other part of the interface is assumed to be
disconnected or broken, and routes are adjusted appropriately.
.Pp
The
.Em Internet Router Discovery Protocol
is handled similarly.
When the daemon is supplying RIP routes, it also listens for
Router Discovery Solicitations and sends Advertisements.
When it is quiet and only listening to other RIP routers, it
sends Solicitations and listens for Advertisements.
If it receives
a good Advertisement, it stops listening for broadcast or multicast
RIP responses.
It tracks several advertising routers to speed recovery when the
currently chosen router dies.
If all discovered routers disappear,
the daemon resumes listening to RIP responses.
.Pp
While using Router Discovery (which happens by default when
the system has a single network interface and a Router Discover Advertisement
is received), there is a single default route and a variable number of
redirected host routes in the kernel table.
.Pp
The Router Discover standard requires that advertisements
have a default "lifetime" of 30 minutes. That means should
something happen, a client can be without a good route for
30 minutes. It is a good idea to reduce the default to 45
seconds using
.Fl P Cm rdisc_interval=45
on the command line or
.Cm rdisc_interval=45
in the
.Pa /etc/gateways
file.
.Pp
While using Router Discovery (which happens by default when
the system has a single network interface and a Router Discover Advertisement
is received), there is a single default route and a variable number of
redirected host routes in the kernel table.
.Pp
See the
.Cm pm_rdisc
facility described below to support "legacy" systems
that can handle neither RIPv2 nor Router Discovery.
.Pp
By default, neither Router Discovery advertisements nor solicications
are sent over point to point links (e.g. PPP).
.Pp
Options supported by
.Nm routed :
.Bl -tag -width Ds
.It Fl d
Enable additional debugging information to be logged,
such as bad packets received.
.It Fl g
This flag is used on internetwork routers to offer a route
to the ``default'' destination.
This is typically used on a gateway to the Internet,
or on a gateway that uses another routing protocol whose routes
are not reported to other local routers.
.It Fl s
Supplying this
option forces
.Nm routed
to supply routing information whether it is acting as an internetwork
router or not.
This is the default if multiple network interfaces are present,
or if a point-to-point link is in use.
this option forces
.Nm
to supply routing information.
This is the default if multiple network interfaces are present on which
RIP or Router Discovery have not been disabled, and if the kernel switch
ipforwarding=1.
.It Fl q
This
is the opposite of the
.Fl s
option.
.It Fl d
Do not run in the background.
This option is meant for interactive use.
.It Fl g
This flag is used on internetwork routers to offer a route
to the "default" destination.
It is equivalent to
.Fl F
.Cm 0/0,1
and is present mostly for historical reasons.
A better choice is
.Fl P Cm pm_rdisc
on the command line or
.CM pm_rdisc in the
.Pa /etc/gateways
file.
since a larger metric
will be used, reducing the spread of the potentially dangerous
default route.
This is typically used on a gateway to the Internet,
or on a gateway that uses another routing protocol whose routes
are not reported to other local routers.
Notice that because a metric of 1 is used, this feature is
dangerous. It is more commonly accidently used to create chaos with routing
loop than to solve problems.
.It Fl h
This causes host or point-to-point routes to not be advertised,
provided there is a network route going the same direction.
That is a limited kind of aggregation.
This option is useful on gateways to ethernets that have other gateway
machines connected with point-to-point links such as SLIP.
.It Fl m
This causes the machine to advertise a host or point-to-point route to
its primary interface.
It is useful on multi-homed machines such as NFS servers.
This option should not be used except when the cost of
the host routes it generates is justified by the popularity of
the server.
It is effective only when the machine is supplying
routing information, because there is more than one interface.
The
.Fl m
option overrides the
.Fl q
option to the limited extent of advertising the host route.
.It Fl A
do not ignore RIPv2 authentication if we do not care about RIPv2
authentication.
This option is required for conformance with RFC 1723.
However, it makes no sense and breaks using RIP as a discovery protocol
to ignore all RIPv2 packets that carry authentication when this machine
does not care about authentication.
.It Fl T Ar tracefile
increases the debugging level to at least 1 and
causes debugging information to be appended to the trace file.
.It Fl t
If the
.Fl t
option is specified, all packets sent or received are
printed on the standard output. In addition,
.Nm routed
will not divorce itself from the controlling terminal
so that interrupts from the keyboard will kill the process.
increases the debugging level, which causes more information to be logged
on the tracefile specified with
.Fl T
or standard out.
The debugging level can be increased or decreased
with the
.Em SIGUSR1
or
.Em SIGUSR2
signals or with the
.Cm rtquery
command.
.It Fl F Ar net[/mask][,metric]
minimize routes in transmissions via interfaces with addresses that match
.Em net/mask ,
and synthesizes a default route to this machine with the
.Em metric .
The intent is to reduce RIP traffic on slow, point-to-point links
such as PPP links by replacing many large UDP packets of RIP information
with a single, small packet containing a "fake" default route.
If
.Em metric
is absent, a value of 14 is assumed to limit
the spread of the "fake" default route.
This is a dangerous feature that when used carelessly can cause routing
loops.
Notice also that more than one interface can match the specified network
number and mask.
See also
.Fl g .
.It Fl P Ar parms
is equivalent to adding the parameter
line
.Em parms
to the
.Pa /etc/gateways
file.
.El
.Pp
Any other argument supplied is interpreted as the name
of file in which
.Nm routed Ns \'s
actions should be logged. This log contains information
about any changes to the routing tables and, if not tracing all packets,
a history of recent messages sent and received which are related to
the changed route.
of a file in which the actions of
.Nm
should be logged.
It is better to use
.Fl T
instead of
appending the name of the trace file to the command.
.Pp
In addition to the facilities described above,
.Nm routed
supports the notion of ``distant''
.Nm
also supports the notion of
"distant"
.Em passive
and
or
.Em active
gateways. When
.Nm routed
is started up, it reads the file
gateways.
When
.Nm
is started, it reads the file
.Pa /etc/gateways
to find gateways which may not be located using
only information from the
.Dv SIOGIFCONF
.Xr ioctl 2 .
to find such distant gateways which may not be located using
only information from a routing socket, to discover if some
of the local gateways are
.Em passive ,
and to obtain other parameters.
Gateways specified in this manner should be marked passive
if they are not expected to exchange routing information,
while gateways marked active
should be willing to exchange routing information (i.e.
they should have a
.Nm routed
process running on the machine).
Routes through passive gateways are installed in the
kernel's routing tables once upon startup.
Such routes are not included in
any routing information transmitted.
Active gateways are treated equally to network
interfaces. Routing information is distributed
to the gateway and if no routing information is
received for a period of time, the associated
route is deleted.
should be willing to exchange RIP packets.
Routes through
.Em passive
gateways are installed in the
kernel's routing tables once upon startup and are not included in
transmitted RIP responses.
.Pp
Distant active gateways are treated like network interfaces.
RIP responses are sent
to the distant
.Em active
gateway.
If no responses are received, the associated route is deleted from
the kernel table and RIP responses advertised via other interfaces.
If the distant gateway resumes sending RIP responses, the associated
route is restored.
.Pp
Such gateways can be useful on media that do not support broadcasts
or multicasts but otherwise act like classic shared media like
Ethernets such as some ATM networks.
One can list all RIP routers reachable on the ATM network in
.Pa /etc/gateways
with a series of
"host" lines.
.Pp
Gateways marked
.Em external
are also passive, but are not placed in the kernel
routing table nor are they included in routing updates.
The function of external entries is to inform
.Nm routed
The function of external entries is to indicate
that another routing process
will install such a route, and that alternate routes to that destination
should not be installed.
will install such a route if ncessary,
and that alternate routes to that destination should not be installed
by
.Nm routed .
Such entries are only required when both routers may learn of routes
to the same destination.
.Pp
The
.Pa /etc/gateways
file is composed of a series of lines, each in
the following format:
.Em /etc/gateways
file is comprised of a series of lines, each in
one of the following formats or consist of parameters described below:
.Pp
.Bd -ragged
.Pf < Cm net No \&|
.Cm host Ns >
.Ar name1
.Cm net
.Ar Nname[/mask]
.Cm gateway
.Ar name2
.Ar Gname
.Cm metric
.Ar value
.Pf < Cm passive No \&|
.Cm active No \&|
.Cm external Ns >
.Cm extern Ns >
.Ed
.Bd -ragged
.Cm host
.Ar Hname
.Cm gateway
.Ar Gname
.Cm metric
.Ar value
.Pf < Cm passive No \&|
.Cm active No \&|
.Cm extern Ns >
.Ed
.Pp
The
.Cm net
.Ar Nname
or
.Cm host
keyword indicates if the route is to a network or specific host.
.Pp
.Ar Name1
is the name of the destination network or host. This may be a
symbolic name located in
.Ar Hname
is the name of the destination network or host.
It may be a symbolic network name or an Internet address
specified in "dot" notation (see
.Xr inet 3 ).
(If it is a name, then it must either be defined in
.Pa /etc/networks
or
.Pa /etc/hosts
(or, if started after
.Pa /etc/hosts ,
or
.Xr named 8 ,
known to the name server),
or an Internet address specified in ``dot'' notation; see
.Xr inet 3 .
must have been started before
.Xr routed Ns .)
.Pp
.Ar Name2
is the name or address of the gateway to which messages should
.Ar mask
is an optional number between 1 and 32 indicating the netmask associated
with
.Ar Nname .
.Pp
.Ar Gname
is the name or address of the gateway to which RIP responses should
be forwarded.
.Pp
.Ar Value
is a metric indicating the hop count to the destination host
or network.
is the hop count to the destination host or network.
.Ar " host hname "
is equivalent to
.Ar " net nname/32 ".
.Pp
One of the keywords
.Cm passive ,
.Cm active
or
.Cm external
indicates if the gateway should be treated as
.Em passive
must be present to indicate whether the gateway should be treated as
.Cm passive
or
.Em active
.Cm active
(as described above),
or whether the gateway is
.Em external
to the scope of the
.Nm routed
protocol.
.Cm external
to the scope of the RIP protocol.
.Pp
Lines that start with neither "net" nor "host" must consist of one
or more of the following parameter settings, separated by commas or
blanks:
.Bl -tag -width Ds
.It Cm if Ns \&= Ns Ar ifname
indicates that the other parameters on the line apply to the interface
name
.Ar ifname .
.It Cm subnet Ns \&= Ns Ar nname[/mask][,metric]
advertises a route to network
.AR nname
with mask
.AR mask
and the supplied metric (default 1).
This is useful for filling "holes" in CIDR allocations.
This parameter must appear by itself on a line.
.Pp
Do not use this feature unless necessary. It is dangerous.
.It Cm passwd Ns \&= Ns Ar XXX
specifies a RIPv2 password that will be included on all RIPv2
responses sent and checked on all RIPv2 responses received.
The password must not contain any blanks, tab characters, commas
or '#' characters.
.It Cm no_ag
turns off aggregation of subnets in RIPv1 and RIPv2 responses.
.It Cm no_super_ag
turns off aggregation of networks into supernets in RIPv2 responses.
.It Cm passive
is equivalent
.Cm no_rip Cm no_rdisc .
.It Cm no_rip
disables all RIP processing on the specified interface.
If no interfaces are allowed to process RIP packets,
.Nm
acts purely as a router discovery daemon.
.Cm No_rip
is equivalent to
.Cm no_ripv1_in no_ripv2_in no_ripv1_out no_ripv2_out .
Note that turning off RIP without explicitly turning on router
discovery advertisements with
.Cm rdisc_adv
or
.Fl s
causes
.Nm routed
to act as a client router discovery daemon, not adveritising.
.It Cm no_ripv1_in
causes RIPv1 received responses to be ignored.
.It Cm no_ripv2_in
causes RIPv2 received responses to be ignored.
.It Cm ripv2_out
turns off RIPv1 output and causes RIPv2 advertisements to be
multicast when possible.
.It Cm no_rdisc
disables the Internet Router Discovery Protocol.
.It Cm no_solicit
disables the tranmission of Router Discovery Solicitations.
.It Cm send_solicit
specifies that Router Discovery solicitations should be sent,
even on point-to-point links,
which by default only listen to Router Discovery messages.
.It Cm no_rdisc_adv
disables the transmission of Router Discovery Advertisements
.It Cm rdisc_adv
specifies that Router Discovery advertisements should be sent,
even on point-to-point links,
which by default only listen to Router Discovery messages
.It Cm bcast_rdisc
specifies that Router Discovery packets should be broadcast instead of
multicast.
.It Cm rdisc_pref Ns \&= Ns Ar N
sets the preference in Router Discovery Advertisements to the integer
.Ar N .
.It Cm rdisc_interval Ns \&= Ns Ar N
sets the nominal interval with which Router Discovery Advertisements
are transmitted to N seconds and their lifetime to 3*N.
.It Cm fake_default Ns \&= Ns Ar metric
has an identical effect to
.Fl F Ar net[/mask][,metric]
with the network and mask coming from the sepcified interface.
.It Cm pm_rdisc
is similar to
.Cm fake_default .
When RIPv2 routes are multicast, so that RIPv1 listeners cannot
receive them, this feature causes a RIPv1 default route to be
broadcast to RIPv1 listeners.
Unless modified with
.Cm fake_default ,
the default route is broadcast with a metric of 14.
That serves as a "poor man's router discovery" protocol.
.El
.Pp
Note that the netmask associated with point-to-point links (such as SLIP
or PPP, with the IFF_POINTOPOINT flag) is used by
.Nm routed
to infer the netmask used by the remote system when RIPv1 is used.
.Pp
Internetwork routers that are directly attached to the Arpanet or Milnet
should use the Exterior Gateway Protocol
.Pq Tn EGP
to gather routing information
rather then using a static routing table of passive gateways.
.Tn EGP
is required in order to provide routes for local networks to the rest
of the Internet system.
.Sh FILES
.Bl -tag -width /etc/gateways -compact
.It Pa /etc/gateways
for distant gateways
.El
.Sh SEE ALSO
.Xr gated 8 ,
.Xr udp 4 ,
.Xr icmp 4 ,
.Xr XNSrouted 8 ,
.Xr htable 8
.Xr htable 8 ,
.Xr rtquery 8 .
.Rs
.%T Internet Transport Protocols
.%R XSIS 028112
.%Q Xerox System Integration Standard
.Re
.Sh BUGS
The kernel's routing tables may not correspond to those of
.Nm routed
when redirects change or add routes.
.Nm Routed
should note any redirects received by reading
the
.Tn ICMP
packets received via a raw socket.
.Pp
.Nm Routed
should incorporate other routing protocols,
such as Xerox
.Tn \&NS
.Pq Xr XNSrouted 8
and
.Tn EGP .
Using separate processes for each requires configuration options
to avoid redundant or competing routes.
.Pp
.Nm Routed
should listen to intelligent interfaces, such as an
.Tn IMP ,
to gather more information.
It does not always detect unidirectional failures in network interfaces
(e.g., when the output side fails).
.Sh HISTORY

View File

@ -1,3 +1,5 @@
/* $NetBSD: routed.h,v 1.2 1996/08/10 01:29:51 thorpej Exp $ */
/*-
* Copyright (c) 1983, 1989, 1993
* The Regents of the University of California. All rights reserved.
@ -38,7 +40,6 @@
#ifdef __cplusplus
extern "C" {
#endif
#ident "$Revision: 1.1.1.1 $"
/*
* Routing Information Protocol
@ -48,8 +49,12 @@ extern "C" {
* padding stuff to 32-bit boundaries.
*/
#define RIPv1 1
#define RIPv2 2
#define RIP_VERSION_0 0
#define RIP_VERSION_1 1
#define RIP_VERSION_2 2
#define RIPv1 RIP_VERSION_1
#define RIPv2 RIP_VERSION_2
#ifndef RIPVERSION
#define RIPVERSION RIPv1
#endif
@ -57,46 +62,44 @@ extern "C" {
#define RIP_PORT 520
#if RIPVERSION == 1
/* Note that this so called sockaddr has a 2-byte sa_family and no sa_len.
* It is not a UNIX sockaddr, but the shape of an address as defined
* in RIPv1.
*/
struct netinfo {
struct sockaddr rip_dst; /* destination net/host */
int rip_metric; /* cost of route */
u_int16_t rip_family;
u_int16_t rip_tag;
u_int32_t rip_dst; /* destination net/host */
u_int32_t rip_metric; /* cost of route */
};
#else
struct netinfo {
u_short n_family;
u_int16_t n_family;
#define RIP_AF_INET htons(AF_INET)
#define RIP_AF_UNSPEC 0
#define RIP_AF_AUTH 0xffff
u_short n_tag; /* optional in RIPv2 */
u_int n_dst; /* destination net or host */
u_int16_t n_tag; /* optional in RIPv2 */
u_int16_t n_dst; /* destination net or host */
#define RIP_DEFAULT 0
u_int n_mask; /* netmask in RIPv2 */
u_int n_nhop; /* optional next hop in RIPv2 */
u_int n_metric; /* cost of route */
u_int32_t n_mask; /* netmask in RIPv2 */
u_int32_t n_nhop; /* optional next hop in RIPv2 */
u_int32_t n_metric; /* cost of route */
};
#endif
/* RIPv2 authentication */
struct netauth {
u_short a_type;
u_int16_t a_type;
#define RIP_AUTH_PW htons(2) /* password type */
union {
#define RIP_AUTH_PW_LEN 16
char au_pw[RIP_AUTH_PW_LEN];
int8_t au_pw[RIP_AUTH_PW_LEN];
} au;
};
struct rip {
u_char rip_cmd; /* request/response */
u_char rip_vers; /* protocol version # */
u_short rip_res1; /* pad to 32-bit boundary */
u_int8_t rip_cmd; /* request/response */
u_int8_t rip_vers; /* protocol version # */
u_int16_t rip_res1; /* pad to 32-bit boundary */
union { /* variable length... */
struct netinfo ru_nets[1];
char ru_tracefile[1];
int8_t ru_tracefile[1];
struct netauth ru_auth[1];
} ripun;
#define rip_nets ripun.ru_nets
@ -129,7 +132,7 @@ char *ripcmds[RIPCMD_MAX] = {
#define NETS_LEN ((MAXPACKETSIZE-sizeof(struct rip)) \
/ sizeof(struct netinfo) +1)
#define INADDR_RIP_GROUP (u_long)0xe0000009 /* 224.0.0.9 */
#define INADDR_RIP_GROUP (u_int32_t)0xe0000009 /* 224.0.0.9 */
/* Timer values used in managing the routing table.

View File

@ -1,8 +1,8 @@
# @(#)Makefile 8.1 (Berkeley) 6/5/93
# $NetBSD: Makefile,v 1.2 1996/08/10 01:30:28 thorpej Exp $
# from: @(#)Makefile 8.1 (Berkeley) 6/5/93
PROG= rtquery
MAN8= rtquery.0
#COPTS= -g -DDEBUG
MAN= rtquery.8
.include "../../Makefile.inc"
.include <bsd.prog.mk>

View File

@ -1,3 +1,5 @@
.\" $NetBSD: rtquery.8,v 1.2 1996/08/10 01:30:31 thorpej Exp $
.\"
.Dd June 1, 1996
.Dt RTQUERY 8
.Os BSD 4.4

View File

@ -1,3 +1,5 @@
/* $NetBSD: rtquery.c,v 1.2 1996/08/10 01:30:36 thorpej Exp $ */
/*-
* Copyright (c) 1982, 1986, 1993
* The Regents of the University of California. All rights reserved.
@ -36,7 +38,11 @@ char copyright[] =
The Regents of the University of California. All rights reserved.\n";
#if !defined(lint) && !defined(sgi)
#if 0
static char sccsid[] = "@(#)query.c 8.1 (Berkeley) 6/5/93";
#else
static char rcsid[] = "$NetBSD: rtquery.c,v 1.2 1996/08/10 01:30:36 thorpej Exp $";
#endif
#endif /* not lint */
#include <sys/param.h>

View File

@ -1,530 +0,0 @@
/* $NetBSD: startup.c,v 1.14 1995/06/20 22:27:56 christos Exp $ */
/*
* 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
#if 0
static char sccsid[] = "@(#)startup.c 8.1 (Berkeley) 6/5/93";
#else
/*###40 [cc] warning: `rcsid' defined but not used%%%*/
static char rcsid[] = "$NetBSD: startup.c,v 1.14 1995/06/20 22:27:56 christos Exp $";
#endif
#endif /* not lint */
/*
* Routing Table Management Daemon
*/
#include "defs.h"
#include <sys/ioctl.h>
#include <sys/sysctl.h>
#include <net/if.h>
#include <net/if_dl.h>
#include <syslog.h>
#include "pathnames.h"
struct interface *ifnet;
struct interface **ifnext = &ifnet;
int lookforinterfaces = 1;
int externalinterfaces = 0; /* # of remote and local interfaces */
int foundloopback; /* valid flag for loopaddr */
struct sockaddr loopaddr; /* our address on loopback */
void add_ptopt_localrt __P((struct interface *));
int getnetorhostname __P((char *, char *, struct sockaddr_in *));
int gethostnameornumber __P((char *, struct sockaddr_in *));
void
quit(s)
char *s;
{
extern int errno;
int sverrno = errno;
(void) fprintf(stderr, "route: ");
if (s)
(void) fprintf(stderr, "%s: ", s);
(void) fprintf(stderr, "%s\n", strerror(sverrno));
exit(1);
/* NOTREACHED */
}
struct rt_addrinfo info;
/* Sleazy use of local variables throughout file, warning!!!! */
#define netmask info.rti_info[RTAX_NETMASK]
#define ifaaddr info.rti_info[RTAX_IFA]
#define brdaddr info.rti_info[RTAX_BRD]
#define ROUNDUP(a) \
((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
#define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len))
void
rt_xaddrs(cp, cplim, rtinfo)
register caddr_t cp, cplim;
register struct rt_addrinfo *rtinfo;
{
register struct sockaddr *sa;
register int i;
memset(rtinfo->rti_info, 0, sizeof(rtinfo->rti_info));
for (i = 0; (i < RTAX_MAX) && (cp < cplim); i++) {
if ((rtinfo->rti_addrs & (1 << i)) == 0)
continue;
rtinfo->rti_info[i] = sa = (struct sockaddr *)cp;
ADVANCE(cp, sa);
}
}
/*
* Find the network interfaces which have configured themselves.
* If the interface is present but not yet up (for example an
* ARPANET IMP), set the lookforinterfaces flag so we'll
* come back later and look again.
*/
void
ifinit()
{
struct interface ifs, *ifp;
size_t needed;
int mib[6], no_ipaddr = 0, flags = 0;
char *buf, *cplim, *cp;
register struct if_msghdr *ifm;
register struct ifa_msghdr *ifam;
struct sockaddr_dl *sdl = NULL;
struct sockaddr_in *sin;
u_long i;
mib[0] = CTL_NET;
mib[1] = PF_ROUTE;
mib[2] = 0;
mib[3] = AF_INET;
mib[4] = NET_RT_IFLIST;
mib[5] = 0;
if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0)
quit("route-sysctl-estimate");
if ((buf = malloc(needed)) == NULL)
quit("malloc");
if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0)
quit("actual retrieval of interface table");
lookforinterfaces = 0;
cplim = buf + needed;
for (cp = buf; cp < cplim; cp += ifm->ifm_msglen) {
ifm = (struct if_msghdr *)cp;
if (ifm->ifm_type == RTM_IFINFO) {
memset(&ifs, 0, sizeof(ifs));
ifs.int_flags = flags = (0xffff & ifm->ifm_flags) | IFF_INTERFACE;
if ((flags & IFF_UP) == 0 || no_ipaddr)
lookforinterfaces = 1;
sdl = (struct sockaddr_dl *) (ifm + 1);
sdl->sdl_data[sdl->sdl_nlen] = 0;
no_ipaddr = 1;
continue;
}
if (ifm->ifm_type != RTM_NEWADDR)
quit("ifinit: out of sync");
if ((flags & IFF_UP) == 0) {
lookforinterfaces = 1;
continue;
}
ifam = (struct ifa_msghdr *)ifm;
info.rti_addrs = ifam->ifam_addrs;
rt_xaddrs((char *)(ifam + 1), cp + ifam->ifam_msglen, &info);
if (ifaaddr == 0) {
syslog(LOG_ERR, "%s: (get addr)", sdl->sdl_data);
continue;
}
ifs.int_addr = *ifaaddr;
if (ifs.int_addr.sa_family != AF_INET)
continue;
no_ipaddr = 0;
if (ifs.int_flags & IFF_POINTOPOINT) {
if (brdaddr == 0) {
syslog(LOG_ERR, "%s: (get dstaddr)",
sdl->sdl_data);
continue;
}
if (brdaddr->sa_family == AF_UNSPEC) {
lookforinterfaces = 1;
continue;
}
ifs.int_dstaddr = *brdaddr;
}
/*
* already known to us?
* This allows multiple point-to-point links
* to share a source address (possibly with one
* other link), but assumes that there will not be
* multiple links with the same destination address.
*/
if (ifs.int_flags & IFF_POINTOPOINT) {
if (if_ifwithdstaddr(&ifs.int_dstaddr))
continue;
} else if (if_ifwithaddr(&ifs.int_addr))
continue;
if (ifs.int_flags & IFF_LOOPBACK) {
ifs.int_flags |= IFF_PASSIVE;
foundloopback = 1;
loopaddr = ifs.int_addr;
for (ifp = ifnet; ifp; ifp = ifp->int_next)
if (ifp->int_flags & IFF_POINTOPOINT)
add_ptopt_localrt(ifp);
}
if (ifs.int_flags & IFF_BROADCAST) {
if (brdaddr == 0) {
syslog(LOG_ERR, "%s: (get broadaddr)",
sdl->sdl_data);
continue;
}
ifs.int_dstaddr = *brdaddr;
}
/*
* Use a minimum metric of one;
* treat the interface metric (default 0)
* as an increment to the hop count of one.
*/
ifs.int_metric = ifam->ifam_metric + 1;
if (netmask == 0) {
syslog(LOG_ERR, "%s: (get netmask)",
sdl->sdl_data);
continue;
}
sin = (struct sockaddr_in *)netmask;
ifs.int_subnetmask = ntohl(sin->sin_addr.s_addr);
sin = (struct sockaddr_in *)&ifs.int_addr;
i = ntohl(sin->sin_addr.s_addr);
if (IN_CLASSA(i))
ifs.int_netmask = IN_CLASSA_NET;
else if (IN_CLASSB(i))
ifs.int_netmask = IN_CLASSB_NET;
else
ifs.int_netmask = IN_CLASSC_NET;
ifs.int_net = i & ifs.int_netmask;
ifs.int_subnet = i & ifs.int_subnetmask;
if (ifs.int_subnetmask != ifs.int_netmask)
ifs.int_flags |= IFF_SUBNET;
ifp = (struct interface *)
malloc(sdl->sdl_nlen + 1 + sizeof(ifs));
if (ifp == 0) {
printf("routed: out of memory\n");
lookforinterfaces = 1;
break;
}
*ifp = ifs;
/*
* Count the # of directly connected networks
* and point to point links which aren't looped
* back to ourself. This is used below to
* decide if we should be a routing ``supplier''.
*/
if ((ifs.int_flags & IFF_LOOPBACK) == 0 &&
((ifs.int_flags & IFF_POINTOPOINT) == 0 ||
if_ifwithaddr(&ifs.int_dstaddr) == 0))
externalinterfaces++;
/*
* If we have a point-to-point link, we want to act
* as a supplier even if it's our only interface,
* as that's the only way our peer on the other end
* can tell that the link is up.
*/
if ((ifs.int_flags & IFF_POINTOPOINT) && supplier < 0)
supplier = 1;
ifp->int_name = (char *)(ifp + 1);
strcpy(ifp->int_name, sdl->sdl_data);
*ifnext = ifp;
ifnext = &ifp->int_next;
traceinit(ifp);
addrouteforif(ifp);
}
if (externalinterfaces > 1 && supplier < 0)
supplier = 1;
free(buf);
}
/*
* Add route for interface if not currently installed.
* Create route to other end if a point-to-point link,
* otherwise a route to this (sub)network.
* INTERNET SPECIFIC.
*/
void
addrouteforif(ifp)
register struct interface *ifp;
{
struct sockaddr_in net;
struct sockaddr *dst;
int state;
register struct rt_entry *rt;
struct sockaddr mask;
memset(&mask, 0, sizeof(mask));
if (ifp->int_flags & IFF_POINTOPOINT)
dst = &ifp->int_dstaddr;
else {
memset(&net, 0, sizeof (net));
net.sin_family = AF_INET;
net.sin_addr = inet_makeaddr(ifp->int_subnet, INADDR_ANY);
dst = (struct sockaddr *)&net;
}
rt = rtfind(dst);
if (rt &&
(rt->rt_state & (RTS_INTERFACE | RTS_INTERNAL)) == RTS_INTERFACE)
return;
if (rt)
rtdelete(rt);
/*
* If interface on subnetted network,
* install route to network as well.
* This is meant for external viewers.
*/
if ((ifp->int_flags & (IFF_SUBNET|IFF_POINTOPOINT)) == IFF_SUBNET) {
struct in_addr subnet;
subnet = net.sin_addr;
net.sin_addr = inet_makeaddr(ifp->int_net, INADDR_ANY);
rt = rtfind(dst);
if (rt == 0)
rtadd(dst, &ifp->int_addr, &mask, ifp->int_metric,
((ifp->int_flags & (IFF_INTERFACE|IFF_REMOTE)) |
RTS_PASSIVE | RTS_INTERNAL | RTS_SUBNET));
else if ((rt->rt_state & (RTS_INTERNAL|RTS_SUBNET)) ==
(RTS_INTERNAL|RTS_SUBNET) &&
ifp->int_metric < rt->rt_metric)
rtchange(rt, &rt->rt_router, &mask, ifp->int_metric);
net.sin_addr = subnet;
}
if (ifp->int_transitions++ > 0)
syslog(LOG_ERR, "re-installing interface %s", ifp->int_name);
state = ifp->int_flags &
(IFF_INTERFACE | IFF_PASSIVE | IFF_REMOTE | IFF_SUBNET);
if (ifp->int_flags & IFF_POINTOPOINT &&
(ntohl(((struct sockaddr_in *)&ifp->int_dstaddr)->sin_addr.s_addr) &
ifp->int_netmask) != ifp->int_net)
state &= ~RTS_SUBNET;
if (ifp->int_flags & IFF_LOOPBACK)
state |= RTS_EXTERNAL;
rtadd(dst, &ifp->int_addr, &mask, ifp->int_metric, state);
if (ifp->int_flags & IFF_POINTOPOINT && foundloopback)
add_ptopt_localrt(ifp);
}
/*
* Add route to local end of point-to-point using loopback.
* If a route to this network is being sent to neighbors on other nets,
* mark this route as subnet so we don't have to propagate it too.
*/
void
add_ptopt_localrt(ifp)
register struct interface *ifp;
{
struct rt_entry *rt;
struct sockaddr *dst;
struct sockaddr_in net;
int state;
struct sockaddr mask;
memset(&mask, 0, sizeof(mask));
state = RTS_INTERFACE | RTS_PASSIVE;
/* look for route to logical network */
memset(&net, 0, sizeof (net));
net.sin_family = AF_INET;
net.sin_addr = inet_makeaddr(ifp->int_net, INADDR_ANY);
dst = (struct sockaddr *)&net;
rt = rtfind(dst);
if (rt && rt->rt_state & RTS_INTERNAL)
state |= RTS_SUBNET;
dst = &ifp->int_addr;
if ((rt = rtfind(dst)) != NULL) {
if (rt && rt->rt_state & RTS_INTERFACE)
return;
rtdelete(rt);
}
rtadd(dst, &loopaddr, &mask, 1, state);
}
/*
* As a concession to the ARPANET we read a list of gateways
* from /etc/gateways and add them to our tables. This file
* exists at each ARPANET gateway and indicates a set of ``remote''
* gateways (i.e. a gateway which we can't immediately determine
* if it's present or not as we can do for those directly connected
* at the hardware level). If a gateway is marked ``passive''
* in the file, then we assume it doesn't have a routing process
* of our design and simply assume it's always present. Those
* not marked passive are treated as if they were directly
* connected -- they're added into the interface list so we'll
* send them routing updates.
*
* PASSIVE ENTRIES AREN'T NEEDED OR USED ON GATEWAYS RUNNING EGP.
*/
void
gwkludge()
{
struct sockaddr_in dst, gate;
FILE *fp;
char *type, *dname, *gname, *qual, buf[BUFSIZ];
struct interface *ifp;
int metric, n;
struct rt_entry route;
struct sockaddr mask;
memset(&mask, 0, sizeof(mask));
fp = fopen(_PATH_GATEWAYS, "r");
if (fp == NULL)
return;
qual = buf;
dname = buf + 64;
gname = buf + ((BUFSIZ - 64) / 3);
type = buf + (((BUFSIZ - 64) * 2) / 3);
memset(&dst, 0, sizeof (dst));
memset(&gate, 0, sizeof (gate));
memset(&route, 0, sizeof(route));
/* format: {net | host} XX gateway XX metric DD [passive | external]\n */
#define readentry(fp) \
fscanf((fp), "%s %s gateway %s metric %d %s\n", \
type, dname, gname, &metric, qual)
for (;;) {
if ((n = readentry(fp)) == EOF)
break;
if (!getnetorhostname(type, dname, &dst))
continue;
if (!gethostnameornumber(gname, &gate))
continue;
if (metric == 0) /* XXX */
metric = 1;
if (strcmp(qual, "passive") == 0) {
/*
* Passive entries aren't placed in our tables,
* only the kernel's, so we don't copy all of the
* external routing information within a net.
* Internal machines should use the default
* route to a suitable gateway (like us).
*/
route.rt_dst = *(struct sockaddr *) &dst;
route.rt_router = *(struct sockaddr *) &gate;
route.rt_flags = RTF_UP;
if (strcmp(type, "host") == 0)
route.rt_flags |= RTF_HOST;
if (metric)
route.rt_flags |= RTF_GATEWAY;
(void) rtioctl(ADD, &route.rt_rt);
continue;
}
if (strcmp(qual, "external") == 0) {
/*
* Entries marked external are handled
* by other means, e.g. EGP,
* and are placed in our tables only
* to prevent overriding them
* with something else.
*/
rtadd((struct sockaddr *)&dst,
(struct sockaddr *)&gate, &mask, metric,
RTS_EXTERNAL|RTS_PASSIVE);
continue;
}
/* assume no duplicate entries */
externalinterfaces++;
ifp = (struct interface *)malloc(sizeof (*ifp));
memset(ifp, 0, sizeof (*ifp));
ifp->int_flags = IFF_REMOTE;
/* can't identify broadcast capability */
ifp->int_net = inet_netof_subnet(dst.sin_addr);
if (strcmp(type, "host") == 0) {
ifp->int_flags |= IFF_POINTOPOINT;
ifp->int_dstaddr = *((struct sockaddr *)&dst);
}
ifp->int_addr = *((struct sockaddr *)&gate);
ifp->int_metric = metric;
ifp->int_next = ifnet;
ifnet = ifp;
addrouteforif(ifp);
}
fclose(fp);
}
int
getnetorhostname(type, name, sin)
char *type, *name;
struct sockaddr_in *sin;
{
if (strcmp(type, "net") == 0) {
struct netent *np = getnetbyname(name);
int n;
if (np == 0)
n = inet_network(name);
else {
if (np->n_addrtype != AF_INET)
return (0);
n = np->n_net;
/*
* getnetbyname returns right-adjusted value.
*/
if (n < 128)
n <<= IN_CLASSA_NSHIFT;
else if (n < 65536)
n <<= IN_CLASSB_NSHIFT;
else
n <<= IN_CLASSC_NSHIFT;
}
sin->sin_family = AF_INET;
sin->sin_addr = inet_makeaddr(n, INADDR_ANY);
return (1);
}
if (strcmp(type, "host") == 0)
return (gethostnameornumber(name, sin));
return (0);
}
int
gethostnameornumber(name, sin)
char *name;
struct sockaddr_in *sin;
{
struct hostent *hp;
if (inet_aton(name, &sin->sin_addr) == 0) {
hp = gethostbyname(name);
if (hp == 0)
return (0);
memcpy(&sin->sin_addr, hp->h_addr, hp->h_length);
sin->sin_family = hp->h_addrtype;
} else
sin->sin_family = AF_INET;
return (1);
}

View File

@ -1,3 +1,5 @@
/* $NetBSD: table.c,v 1.2 1996/08/10 01:29:59 thorpej Exp $ */
/*
* Copyright (c) 1983, 1988, 1993
* The Regents of the University of California. All rights reserved.
@ -32,11 +34,13 @@
*/
#if !defined(lint) && !defined(sgi)
#if 0
static char sccsid[] = "@(#)tables.c 8.1 (Berkeley) 6/5/93";
#else
static char rcsid[] = "$NetBSD: table.c,v 1.2 1996/08/10 01:29:59 thorpej Exp $";
#endif
#endif /* not lint */
#ident "$Revision: 1.1.1.1 $"
#include "defs.h"
static struct rt_spare *rts_better(struct rt_entry *);
@ -1222,10 +1226,12 @@ kern_out(struct ag_info *ag)
/* ARGSUSED */
static int
walk_kern(struct radix_node *rn,
struct walkarg *w)
walk_kern(struct radix_node *rn, void *argp)
{
#define RT ((struct rt_entry *)rn)
#if 0
struct walkarg *w = argp;
#endif
char metric, pref;
u_int ags = 0;
@ -1771,10 +1777,12 @@ rtbad_sub(struct rt_entry *rt)
*/
/* ARGSUSED */
int
walk_bad(struct radix_node *rn,
struct walkarg *w)
walk_bad(struct radix_node *rn, void *argp)
{
#define RT ((struct rt_entry *)rn)
#if 0
struct walkarg *w = argp; /* not used */
#endif
struct rt_spare *rts;
int i;
time_t new_time;
@ -1825,10 +1833,12 @@ walk_bad(struct radix_node *rn,
*/
/* ARGSUSED */
static int
walk_age(struct radix_node *rn,
struct walkarg *w)
walk_age(struct radix_node *rn, void *argp)
{
#define RT ((struct rt_entry *)rn)
#if 0
struct walkarg *w = argp; /* not used */
#endif
struct interface *ifp;
struct rt_spare *rts;
int i;

View File

@ -1,120 +0,0 @@
/* $NetBSD: table.h,v 1.7 1995/06/20 22:27:58 christos Exp $ */
/*
* Copyright (c) 1983, 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.
*
* @(#)table.h 8.1 (Berkeley) 6/5/93
*/
/*
* Routing table management daemon.
*/
#include <sys/queue.h>
/*
* Routing table structure; differs a bit from kernel tables.
*
* Note: the union below must agree in the first 4 members
* so the ioctl's will work.
*/
#ifdef RTM_ADD
#define rtentry ortentry
#endif
struct rt_entry {
CIRCLEQ_ENTRY(rt_entry) rt_entry;
union {
struct rtentry rtu_rt;
struct rtuentry {
u_long rtu_hash;
struct sockaddr rtu_dst;
struct sockaddr rtu_router;
struct sockaddr rtu_netmask;
short rtu_rtflags; /* used by rtioctl */
short rtu_wasted[5];
int rtu_flags;
int rtu_state;
int rtu_timer;
int rtu_metric;
int rtu_ifmetric;
struct interface *rtu_ifp;
} rtu_entry;
} rt_rtu;
};
#define rt_rt rt_rtu.rtu_entry /* pass to ioctl */
#define rt_hash rt_rtu.rtu_entry.rtu_hash /* for net or host */
#define rt_dst rt_rtu.rtu_entry.rtu_dst /* match value */
#define rt_router rt_rtu.rtu_entry.rtu_router /* who to forward to */
#define rt_netmask rt_rtu.rtu_entry.rtu_netmask /* mask for the route */
#define rt_flags rt_rtu.rtu_entry.rtu_flags /* kernel flags */
#define rt_timer rt_rtu.rtu_entry.rtu_timer /* for invalidation */
#define rt_state rt_rtu.rtu_entry.rtu_state /* see below */
#define rt_metric rt_rtu.rtu_entry.rtu_metric /* cost of route */
#define rt_ifmetric rt_rtu.rtu_entry.rtu_ifmetric /* cost of route if */
#define rt_ifp rt_rtu.rtu_entry.rtu_ifp /* interface to take */
#define ROUTEHASHSIZ 32 /* must be a power of 2 */
#define ROUTEHASHMASK (ROUTEHASHSIZ - 1)
/*
* "State" of routing table entry.
*/
#define RTS_CHANGED 0x1 /* route has been altered recently */
#define RTS_EXTERNAL 0x2 /* extern info, not installed or sent */
#define RTS_INTERNAL 0x4 /* internal route, not installed */
#define RTS_PASSIVE IFF_PASSIVE /* don't time out route */
#define RTS_INTERFACE IFF_INTERFACE /* route is for network interface */
#define RTS_REMOTE IFF_REMOTE /* route is for ``remote'' entity */
#define RTS_SUBNET IFF_SUBNET /* route is for network subnet */
/*
* Flags are same as kernel, with this addition for af_rtflags:
*/
#define RTF_SUBNET 0x80000 /* pseudo: route to subnet */
CIRCLEQ_HEAD(rthash, rt_entry);
struct rthash nethash[ROUTEHASHSIZ];
struct rthash hosthash[ROUTEHASHSIZ];
struct rt_entry *rtlookup __P((struct sockaddr *));
struct rt_entry *rtfind __P((struct sockaddr *));
struct rthash *rthead __P((struct sockaddr *, u_int *, int *));
void rtadd __P((struct sockaddr *, struct sockaddr *, struct sockaddr *,
int, int ));
void rtchange __P((struct rt_entry *, struct sockaddr *, struct sockaddr *,
int));
void rtdelete __P((struct rt_entry *));
void rtdeleteall __P((int));
void rtdefault __P((void));
void rtinit __P((void));
int rtioctl __P((int, struct rtuentry *));

View File

@ -1,495 +0,0 @@
/* $NetBSD: tables.c,v 1.15 1995/06/20 22:27:59 christos Exp $ */
/*
* 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
#if 0
static char sccsid[] = "@(#)tables.c 8.1 (Berkeley) 6/5/93";
#else
static char rcsid[] = "$NetBSD: tables.c,v 1.15 1995/06/20 22:27:59 christos Exp $";
#endif
#endif /* not lint */
/*
* Routing Table Management Daemon
*/
#include "defs.h"
#include <sys/ioctl.h>
#include <syslog.h>
#include <errno.h>
#include <search.h>
#ifndef DEBUG
#define DEBUG 0
#endif
#ifdef RTM_ADD
#define FIXLEN(s) {if ((s)->sa_len == 0) (s)->sa_len = sizeof *(s);}
#else
#define FIXLEN(s) { }
#endif
int install = !DEBUG; /* if 1 call kernel */
/*
* Lookup dst in the tables for an exact match.
*/
struct rt_entry *
rtlookup(dst)
struct sockaddr *dst;
{
register struct rt_entry *rt;
register struct rthash *rh;
register u_int hash;
struct afhash h;
int doinghost = 1;
if (dst->sa_family >= af_max)
return (0);
(*afswitch[dst->sa_family].af_hash)(dst, &h);
hash = h.afh_hosthash;
rh = &hosthash[hash & ROUTEHASHMASK];
again:
for (rt = rh->cqh_first; rt != (void *)rh; rt = rt->rt_entry.cqe_next) {
if (rt->rt_hash != hash)
continue;
if (equal(&rt->rt_dst, dst))
return (rt);
}
if (doinghost) {
doinghost = 0;
hash = h.afh_nethash;
rh = &nethash[hash & ROUTEHASHMASK];
goto again;
}
return (0);
}
struct sockaddr wildcard; /* zero valued cookie for wildcard searches */
/*
* Find a route to dst as the kernel would.
*/
struct rt_entry *
rtfind(dst)
struct sockaddr *dst;
{
register struct rt_entry *rt;
register struct rthash *rh;
register u_int hash;
struct afhash h;
int af = dst->sa_family;
int doinghost = 1,
(*match) __P((struct sockaddr *, struct sockaddr *)) = NULL;
if (af >= af_max)
return (0);
(*afswitch[af].af_hash)(dst, &h);
hash = h.afh_hosthash;
rh = &hosthash[hash & ROUTEHASHMASK];
again:
for (rt = rh->cqh_first; rt != (void *)rh; rt = rt->rt_entry.cqe_next) {
if (rt->rt_hash != hash)
continue;
if (doinghost) {
if (equal(&rt->rt_dst, dst))
return (rt);
} else {
if (rt->rt_dst.sa_family == af && match &&
(*match)(&rt->rt_dst, dst))
return (rt);
}
}
if (doinghost) {
doinghost = 0;
hash = h.afh_nethash;
rh = &nethash[hash & ROUTEHASHMASK];
match = afswitch[af].af_netmatch;
goto again;
}
#ifdef notyet
/*
* Check for wildcard gateway, by convention network 0.
*/
if (dst != &wildcard) {
dst = &wildcard, hash = 0;
goto again;
}
#endif
return (0);
}
struct rthash *
rthead(dst, hashp, flagsp)
struct sockaddr *dst;
u_int *hashp;
int *flagsp;
{
struct afhash h;
int af = dst->sa_family;
if (af >= af_max)
return NULL;
(*afswitch[af].af_hash)(dst, &h);
*flagsp = (*afswitch[af].af_rtflags)(dst);
if (*flagsp & RTF_HOST) {
*hashp = h.afh_hosthash;
return &hosthash[*hashp & ROUTEHASHMASK];
} else {
*hashp = h.afh_nethash;
return &nethash[*hashp & ROUTEHASHMASK];
}
}
void
rtadd(dst, gate, netmask, metric, state)
struct sockaddr *dst, *gate, *netmask;
int metric, state;
{
register struct rt_entry *rt;
struct rthash *rh;
int flags;
u_int hash;
char buf1[256], buf2[256];
/*
* Subnet flag isn't visible to kernel, move to state. XXX
*/
FIXLEN(dst);
FIXLEN(gate);
rh = rthead(dst, &hash, &flags);
if (rh == NULL) {
syslog(LOG_ERR, "rtadd: Internal error finding route\n");
return;
}
if (flags & RTF_SUBNET) {
state |= RTS_SUBNET;
flags &= ~RTF_SUBNET;
}
rt = (struct rt_entry *)malloc(sizeof (*rt));
if (rt == 0)
return;
rt->rt_hash = hash;
rt->rt_dst = *dst;
rt->rt_router = *gate;
rt->rt_netmask = *netmask;
rt->rt_timer = 0;
rt->rt_flags = RTF_UP | flags;
rt->rt_state = state | RTS_CHANGED;
rt->rt_ifp = if_ifwithdstaddr(&rt->rt_dst);
if (rt->rt_ifp == 0)
rt->rt_ifp = if_ifwithnet(&rt->rt_router);
if ((state & RTS_INTERFACE) == 0)
rt->rt_flags |= RTF_GATEWAY;
rt->rt_metric = metric;
CIRCLEQ_INSERT_HEAD(rh, rt, rt_entry);
TRACE_ACTION("ADD", rt);
/*
* If the ioctl fails because the gateway is unreachable
* from this host, discard the entry. This should only
* occur because of an incorrect entry in /etc/gateways.
*/
if ((rt->rt_state & (RTS_INTERNAL | RTS_EXTERNAL)) == 0 &&
rtioctl(ADD, &rt->rt_rt) < 0) {
if (errno != EEXIST && gate->sa_family < af_max)
syslog(LOG_ERR,
"adding route to net/host %s through gateway %s: %m\n",
(*afswitch[dst->sa_family].af_format)(dst, buf1,
sizeof(buf1)),
(*afswitch[gate->sa_family].af_format)(gate, buf2,
sizeof(buf2)));
perror("ADD ROUTE");
if (errno == ENETUNREACH) {
TRACE_ACTION("DELETE", rt);
CIRCLEQ_REMOVE(rh, rt, rt_entry);
free((char *)rt);
}
}
}
void
rtchange(rt, gate, netmask, metric)
struct rt_entry *rt;
struct sockaddr *gate;
struct sockaddr *netmask;
short metric;
{
int add = 0, delete = 0, newgateway = 0;
struct rtuentry oldroute;
FIXLEN(gate);
FIXLEN(netmask);
FIXLEN(&(rt->rt_router));
FIXLEN(&(rt->rt_dst));
if (!equal(&rt->rt_router, gate)) {
newgateway++;
TRACE_ACTION("CHANGE FROM ", rt);
} else if (metric != rt->rt_metric)
TRACE_NEWMETRIC(rt, metric);
if ((rt->rt_state & RTS_INTERNAL) == 0) {
/*
* If changing to different router, we need to add
* new route and delete old one if in the kernel.
* If the router is the same, we need to delete
* the route if has become unreachable, or re-add
* it if it had been unreachable.
*/
if (newgateway) {
add++;
if (rt->rt_metric != HOPCNT_INFINITY)
delete++;
} else if (metric == HOPCNT_INFINITY)
delete++;
else if (rt->rt_metric == HOPCNT_INFINITY)
add++;
}
if (delete)
oldroute = rt->rt_rt;
if ((rt->rt_state & RTS_INTERFACE) && delete) {
rt->rt_state &= ~RTS_INTERFACE;
rt->rt_flags |= RTF_GATEWAY;
if (metric > rt->rt_metric && delete)
syslog(LOG_ERR, "%s route to interface %s (timed out)",
add? "changing" : "deleting",
rt->rt_ifp ? rt->rt_ifp->int_name : "?");
}
if (add) {
rt->rt_router = *gate;
rt->rt_ifp = if_ifwithdstaddr(&rt->rt_router);
if (rt->rt_ifp == 0)
rt->rt_ifp = if_ifwithnet(&rt->rt_router);
}
rt->rt_netmask = *netmask;
rt->rt_metric = metric;
rt->rt_state |= RTS_CHANGED;
if (newgateway)
TRACE_ACTION("CHANGE TO ", rt);
#ifndef RTM_ADD
if (add && rtioctl(ADD, &rt->rt_rt) < 0)
perror("ADD ROUTE");
if (delete && rtioctl(DELETE, &oldroute) < 0)
perror("DELETE ROUTE");
#else
if (delete && !add) {
if (rtioctl(DELETE, &oldroute) < 0)
perror("DELETE ROUTE");
} else if (!delete && add) {
if (rtioctl(ADD, &rt->rt_rt) < 0)
perror("ADD ROUTE");
} else if (delete && add) {
if (rtioctl(CHANGE, &rt->rt_rt) < 0)
perror("CHANGE ROUTE");
}
#endif
}
void
rtdelete(rt)
struct rt_entry *rt;
{
u_int hash;
int flags;
struct rthash *rh = rthead(&rt->rt_dst, &hash, &flags);
if (rh == NULL) {
syslog(LOG_ERR, "rtdelete: Internal error finding route\n");
return;
}
TRACE_ACTION("DELETE", rt);
FIXLEN(&(rt->rt_router));
FIXLEN(&(rt->rt_dst));
if (rt->rt_metric < HOPCNT_INFINITY) {
if ((rt->rt_state & (RTS_INTERFACE|RTS_INTERNAL)) == RTS_INTERFACE)
syslog(LOG_ERR,
"deleting route to interface %s? (timed out?)",
rt->rt_ifp->int_name);
if ((rt->rt_state & (RTS_INTERNAL | RTS_EXTERNAL)) == 0 &&
rtioctl(DELETE, &rt->rt_rt) < 0)
perror("rtdelete");
}
CIRCLEQ_REMOVE(rh, rt, rt_entry);
free((char *)rt);
}
void
rtdeleteall(sig)
int sig;
{
register struct rthash *rh;
register struct rt_entry *rt;
struct rthash *base = hosthash;
int doinghost = 1;
again:
for (rh = base; rh < &base[ROUTEHASHSIZ]; rh++) {
rt = rh->cqh_first;
for (; rt != (void *)rh; rt = rt->rt_entry.cqe_next) {
if (rt->rt_state & RTS_INTERFACE ||
rt->rt_metric >= HOPCNT_INFINITY)
continue;
TRACE_ACTION("DELETE", rt);
if ((rt->rt_state & (RTS_INTERNAL|RTS_EXTERNAL)) == 0 &&
rtioctl(DELETE, &rt->rt_rt) < 0)
perror("rtdeleteall");
}
}
if (doinghost) {
doinghost = 0;
base = nethash;
goto again;
}
exit(sig);
}
/*
* If we have an interface to the wide, wide world,
* add an entry for an Internet default route (wildcard) to the internal
* tables and advertise it. This route is not added to the kernel routes,
* but this entry prevents us from listening to other people's defaults
* and installing them in the kernel here.
*/
void
rtdefault()
{
extern struct sockaddr inet_default;
rtadd(&inet_default, &inet_default, &inet_default, 1,
RTS_CHANGED | RTS_PASSIVE | RTS_INTERNAL);
}
void
rtinit()
{
register struct rthash *rh;
for (rh = nethash; rh < &nethash[ROUTEHASHSIZ]; rh++)
CIRCLEQ_INIT(rh);
for (rh = hosthash; rh < &hosthash[ROUTEHASHSIZ]; rh++)
CIRCLEQ_INIT(rh);
}
int
rtioctl(action, ort)
int action;
struct rtuentry *ort;
{
#ifndef RTM_ADD
if (install == 0)
return (errno = 0);
ort->rtu_rtflags = ort->rtu_flags;
switch (action) {
case ADD:
return (ioctl(s, SIOCADDRT, (char *)ort));
case DELETE:
return (ioctl(s, SIOCDELRT, (char *)ort));
default:
return (-1);
}
#else /* RTM_ADD */
struct {
struct rt_msghdr w_rtm;
struct sockaddr_in w_dst;
struct sockaddr w_gate;
struct sockaddr_in w_netmask;
} w;
#define rtm w.w_rtm
memset(&w, 0, sizeof(w));
rtm.rtm_msglen = sizeof(w);
rtm.rtm_version = RTM_VERSION;
rtm.rtm_type = (action == ADD ? RTM_ADD :
(action == DELETE ? RTM_DELETE : RTM_CHANGE));
#undef rt_dst
rtm.rtm_flags = ort->rtu_flags;
rtm.rtm_seq = ++seqno;
rtm.rtm_addrs = RTA_DST|RTA_GATEWAY;
memcpy(&w.w_dst, &ort->rtu_dst, sizeof(w.w_dst));
memcpy(&w.w_gate, &ort->rtu_router, sizeof(w.w_gate));
memcpy(&w.w_netmask, &ort->rtu_netmask, sizeof(w.w_netmask));
w.w_dst.sin_family = AF_INET;
w.w_dst.sin_len = sizeof(w.w_dst);
w.w_gate.sa_family = AF_INET;
w.w_gate.sa_len = sizeof(w.w_gate);
if (rtm.rtm_flags & RTF_HOST) {
rtm.rtm_msglen -= sizeof(w.w_netmask);
} else {
register char *cp;
int len;
rtm.rtm_addrs |= RTA_NETMASK;
/*
* Check if we had a version 2 rip packet that sets the
* netmask, and otherwise set it to the default for
* the destination of the interface.
*/
if (w.w_netmask.sin_family == AF_UNSPEC) {
w.w_netmask.sin_addr.s_addr =
inet_maskof(w.w_dst.sin_addr.s_addr);
}
for (cp = (char *)(1 + &w.w_netmask.sin_addr);
--cp > (char *) &w.w_netmask; )
if (*cp)
break;
len = cp - (char *)&w.w_netmask;
if (len) {
len++;
w.w_netmask.sin_len = len;
len = 1 + ((len - 1) | (sizeof(long) - 1));
} else
len = sizeof(long);
rtm.rtm_msglen -= (sizeof(w.w_netmask) - len);
}
#if 0
fprintf(stderr, "%s ", action == ADD ? "add" : (action == DELETE ? "delete" : "change"));
fprintf(stderr, "dst = %s, ", inet_ntoa(w.w_dst.sin_addr));
fprintf(stderr, "gate = %s, ", inet_ntoa(((struct sockaddr_in *) &w.w_gate)->sin_addr));
fprintf(stderr, "mask = %s\n", inet_ntoa(w.w_netmask.sin_addr));
#endif
errno = 0;
return (install ? write(r, (char *)&w, rtm.rtm_msglen) : (errno = 0));
#endif /* RTM_ADD */
}

View File

@ -1,136 +0,0 @@
/* $NetBSD: timer.c,v 1.8 1995/06/20 22:28:02 christos Exp $ */
/*
* 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
#if 0
static char sccsid[] = "@(#)timer.c 8.1 (Berkeley) 6/5/93";
#else
static char rcsid[] = "$NetBSD: timer.c,v 1.8 1995/06/20 22:28:02 christos Exp $";
#endif
#endif /* not lint */
/*
* Routing Table Management Daemon
*/
#include "defs.h"
int faketime;
/*
* Timer routine. Performs routing information supply
* duties and manages timers on routing table entries.
* Management of the RTS_CHANGED bit assumes that we broadcast
* each time called.
*/
void
timer(sig)
int sig;
{
register struct rthash *rh;
register struct rt_entry *rt;
struct rthash *base = hosthash;
int doinghost = 1, timetobroadcast;
(void) gettimeofday(&now, NULL);
faketime += TIMER_RATE;
if (lookforinterfaces && (faketime % CHECK_INTERVAL) == 0)
ifinit();
timetobroadcast = supplier && (faketime % SUPPLY_INTERVAL) == 0;
again:
for (rh = base; rh < &base[ROUTEHASHSIZ]; rh++) {
rt = rh->cqh_first;
for (; rt != (void *)rh; rt = rt->rt_entry.cqe_next) {
/*
* We don't advance time on a routing entry for
* a passive gateway, or any interface if we're
* not acting as supplier.
*/
if (!(rt->rt_state & RTS_PASSIVE) &&
(supplier || !(rt->rt_state & RTS_INTERFACE)))
rt->rt_timer += TIMER_RATE;
if (rt->rt_timer >= GARBAGE_TIME) {
rt = rt->rt_entry.cqe_prev;
rtdelete(rt->rt_entry.cqe_next);
continue;
}
if (rt->rt_timer >= EXPIRE_TIME &&
rt->rt_metric < HOPCNT_INFINITY)
rtchange(rt, &rt->rt_router,
&rt->rt_netmask, HOPCNT_INFINITY);
rt->rt_state &= ~RTS_CHANGED;
}
}
if (doinghost) {
doinghost = 0;
base = nethash;
goto again;
}
if (timetobroadcast) {
toall(supply, 0, NULL);
lastbcast = now;
lastfullupdate = now;
needupdate = 0; /* cancel any pending dynamic update */
nextbcast.tv_sec = 0;
}
}
/*
* On hangup, let everyone know we're going away.
*/
void
hup(sig)
int sig;
{
register struct rthash *rh;
register struct rt_entry *rt;
struct rthash *base = hosthash;
int doinghost = 1;
if (supplier) {
again:
for (rh = base; rh < &base[ROUTEHASHSIZ]; rh++) {
rt = rh->cqh_first;
for (; rt != (void *)rh; rt = rt->rt_entry.cqe_next)
rt->rt_metric = HOPCNT_INFINITY;
}
if (doinghost) {
doinghost = 0;
base = nethash;
goto again;
}
toall(supply, 0, NULL);
}
exit(1);
}

File diff suppressed because it is too large Load Diff

View File

@ -1,114 +0,0 @@
/* $NetBSD: trace.h,v 1.8 1995/06/20 22:28:04 christos Exp $ */
/*
* 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.
*
* @(#)trace.h 8.1 (Berkeley) 6/5/93
*/
/*
* Routing table management daemon.
*/
/*
* Trace record format.
*/
struct iftrace {
struct timeval ift_stamp; /* time stamp */
struct sockaddr ift_who; /* from/to */
char *ift_packet; /* pointer to packet */
short ift_size; /* size of packet */
short ift_metric; /* metric on associated metric */
};
/*
* Per interface packet tracing buffers. An incoming and
* outgoing circular buffer of packets is maintained, per
* interface, for debugging. Buffers are dumped whenever
* an interface is marked down.
*/
struct ifdebug {
struct iftrace *ifd_records; /* array of trace records */
struct iftrace *ifd_front; /* next empty trace record */
int ifd_count; /* number of unprinted records */
struct interface *ifd_if; /* for locating stuff */
};
/*
* Packet tracing stuff.
*/
int tracepackets; /* watch packets as they go by */
int tracecontents; /* watch packet contents as they go by */
int traceactions; /* on/off */
int tracehistory; /* on/off */
FILE *ftrace; /* output trace file */
#define TRACE_ACTION(action, route) { \
if (traceactions) \
traceaction(ftrace, action, route); \
}
#define TRACE_NEWMETRIC(route, newmetric) { \
if (traceactions) \
tracenewmetric(ftrace, route, newmetric); \
}
#define TRACE_INPUT(ifp, src, pack, size) { \
if (tracehistory) { \
ifp = if_iflookup(src); \
if (ifp) \
trace(&ifp->int_input, src, pack, size, \
ntohl(ifp->int_metric)); \
} \
if (tracepackets) \
dumppacket(ftrace, "from", (struct sockaddr_in *)src, pack, \
size, &now); \
}
#define TRACE_OUTPUT(ifp, dst, size) { \
if (tracehistory && ifp) \
trace(&ifp->int_output, dst, packet, size, ifp->int_metric); \
if (tracepackets) \
dumppacket(ftrace, "to", (struct sockaddr_in *)dst, packet, \
size, &now); \
}
/* trace.c */
void traceinit __P((struct interface *));
void traceon __P((char *));
void traceoff __P((void));
void sigtrace __P((int));
void bumploglevel __P((void));
void trace __P((struct ifdebug *, struct sockaddr *, char *, int, int ));
void traceaction __P((FILE *, char *, struct rt_entry *));
void tracenewmetric __P((FILE *, struct rt_entry *, int));
void dumpif __P((FILE *, struct interface *));
void dumptrace __P((FILE *, char *, struct ifdebug *));
void dumppacket __P((FILE *, char *, struct sockaddr_in *, char *, int, struct timeval *));

View File

@ -1,8 +0,0 @@
# $NetBSD: Makefile,v 1.6 1995/03/18 15:00:54 cgd Exp $
# @(#)Makefile 8.1 (Berkeley) 6/5/93
PROG= trace
NOMAN= noman
.include "../../Makefile.inc"
.include <bsd.prog.mk>

View File

@ -1,130 +0,0 @@
/* $NetBSD: trace.c,v 1.9 1995/06/20 22:28:11 christos Exp $ */
/*-
* 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
#if 0
static char sccsid[] = "@(#)trace.c 8.1 (Berkeley) 6/5/93";
#else
static char rcsid[] = "$NetBSD: trace.c,v 1.9 1995/06/20 22:28:11 christos Exp $";
#endif
#endif /* not lint */
#include <sys/param.h>
#include <sys/protosw.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <protocols/routed.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct sockaddr_in myaddr;
char packet[MAXPACKETSIZE];
main(argc, argv)
int argc;
char **argv;
{
int size, s;
struct sockaddr from;
struct sockaddr_in router;
register struct rip *msg = (struct rip *)packet;
struct hostent *hp;
struct servent *sp;
if (argc < 3) {
usage:
printf("usage: trace cmd machines,\n");
printf("cmd either \"on filename\", or \"off\"\n");
exit(1);
}
s = socket(AF_INET, SOCK_DGRAM, 0);
if (s < 0) {
perror("socket");
exit(2);
}
myaddr.sin_family = AF_INET;
myaddr.sin_port = htons(IPPORT_RESERVED-1);
if (bind(s, (struct sockaddr *)&myaddr, sizeof(myaddr)) < 0) {
perror("bind");
exit(2);
}
argv++, argc--;
msg->rip_cmd = strcmp(*argv, "on") == 0 ?
RIPCMD_TRACEON : RIPCMD_TRACEOFF;
msg->rip_vers = RIP_VERSION_1;
argv++, argc--;
size = sizeof (int);
if (msg->rip_cmd == RIPCMD_TRACEON) {
strcpy(msg->rip_tracefile, *argv);
size += strlen(*argv);
argv++, argc--;
}
if (argc == 0)
goto usage;
memset(&router, 0, sizeof (router));
router.sin_family = AF_INET;
sp = getservbyname("router", "udp");
if (sp == 0) {
printf("udp/router: service unknown\n");
exit(1);
}
router.sin_port = sp->s_port;
while (argc > 0) {
router.sin_family = AF_INET;
if (inet_aton(*argv, &router.sin_addr) == 0) {
hp = gethostbyname(*argv);
if (hp == NULL) {
fprintf(stderr, "trace: %s: ", *argv);
herror((char *)NULL);
continue;
}
memcpy(&router.sin_addr, hp->h_addr, hp->h_length);
}
if (sendto(s, packet, size, 0,
(struct sockaddr *)&router, sizeof(router)) < 0)
perror(*argv);
argv++, argc--;
}
}