- 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:
parent
b1e0bd39e1
commit
fc1a524603
|
@ -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>
|
||||
|
|
253
sbin/routed/af.c
253
sbin/routed/af.c
|
@ -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;
|
||||
}
|
|
@ -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 */
|
|
@ -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);
|
||||
|
|
1118
sbin/routed/if.c
1118
sbin/routed/if.c
File diff suppressed because it is too large
Load Diff
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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'
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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>
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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);
|
||||
}
|
|
@ -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;
|
||||
|
|
|
@ -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 *));
|
|
@ -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 */
|
||||
}
|
|
@ -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);
|
||||
}
|
1032
sbin/routed/trace.c
1032
sbin/routed/trace.c
File diff suppressed because it is too large
Load Diff
|
@ -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 *));
|
||||
|
|
@ -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>
|
|
@ -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--;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue