2017-03-17 19:13:44 +03:00
|
|
|
/* $NetBSD: route.c,v 1.155 2017/03/17 16:13:44 roy Exp $ */
|
1995-03-18 17:54:19 +03:00
|
|
|
|
1993-03-21 12:45:37 +03:00
|
|
|
/*
|
1994-05-13 12:02:16 +04:00
|
|
|
* Copyright (c) 1983, 1989, 1991, 1993
|
|
|
|
* The Regents of the University of California. All rights reserved.
|
1993-03-21 12:45:37 +03:00
|
|
|
*
|
|
|
|
* 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.
|
2003-08-07 14:04:22 +04:00
|
|
|
* 3. Neither the name of the University nor the names of its contributors
|
1993-03-21 12:45:37 +03:00
|
|
|
* 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.
|
|
|
|
*/
|
|
|
|
|
1997-09-15 13:15:26 +04:00
|
|
|
#include <sys/cdefs.h>
|
1993-03-21 12:45:37 +03:00
|
|
|
#ifndef lint
|
2008-07-20 05:20:21 +04:00
|
|
|
__COPYRIGHT("@(#) Copyright (c) 1983, 1989, 1991, 1993\
|
|
|
|
The Regents of the University of California. All rights reserved.");
|
1993-03-21 12:45:37 +03:00
|
|
|
#endif /* not lint */
|
|
|
|
|
|
|
|
#ifndef lint
|
1995-03-18 17:54:19 +03:00
|
|
|
#if 0
|
1997-09-16 11:04:17 +04:00
|
|
|
static char sccsid[] = "@(#)route.c 8.6 (Berkeley) 4/28/95";
|
1995-03-18 17:54:19 +03:00
|
|
|
#else
|
2017-03-17 19:13:44 +03:00
|
|
|
__RCSID("$NetBSD: route.c,v 1.155 2017/03/17 16:13:44 roy Exp $");
|
1995-03-18 17:54:19 +03:00
|
|
|
#endif
|
1993-03-21 12:45:37 +03:00
|
|
|
#endif /* not lint */
|
|
|
|
|
|
|
|
#include <sys/param.h>
|
|
|
|
#include <sys/file.h>
|
|
|
|
#include <sys/socket.h>
|
|
|
|
#include <sys/ioctl.h>
|
1994-05-13 12:02:16 +04:00
|
|
|
#include <sys/sysctl.h>
|
1993-03-21 12:45:37 +03:00
|
|
|
|
1994-05-13 12:02:16 +04:00
|
|
|
#include <net/if.h>
|
1993-03-21 12:45:37 +03:00
|
|
|
#include <net/route.h>
|
|
|
|
#include <net/if_dl.h>
|
2005-06-25 10:38:35 +04:00
|
|
|
#include <net80211/ieee80211_netbsd.h>
|
1993-03-21 12:45:37 +03:00
|
|
|
#include <netinet/in.h>
|
1997-04-03 06:35:46 +04:00
|
|
|
#include <netatalk/at.h>
|
2010-06-26 18:29:36 +04:00
|
|
|
#include <netmpls/mpls.h>
|
1993-03-21 12:45:37 +03:00
|
|
|
#include <arpa/inet.h>
|
|
|
|
#include <netdb.h>
|
|
|
|
|
|
|
|
#include <errno.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <ctype.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
1998-04-01 19:14:25 +04:00
|
|
|
#include <time.h>
|
1993-03-21 12:45:37 +03:00
|
|
|
#include <paths.h>
|
1997-11-16 20:03:11 +03:00
|
|
|
#include <err.h>
|
1993-03-21 12:45:37 +03:00
|
|
|
|
|
|
|
#include "keywords.h"
|
1997-04-03 06:35:46 +04:00
|
|
|
#include "extern.h"
|
2010-12-13 20:39:47 +03:00
|
|
|
#include "prog_ops.h"
|
2014-11-07 00:29:32 +03:00
|
|
|
#include "rtutil.h"
|
1997-04-03 06:35:46 +04:00
|
|
|
|
2008-09-10 05:56:22 +04:00
|
|
|
union sockunion {
|
|
|
|
struct sockaddr sa;
|
|
|
|
struct sockaddr_in sin;
|
|
|
|
#ifdef INET6
|
|
|
|
struct sockaddr_in6 sin6;
|
|
|
|
#endif
|
|
|
|
struct sockaddr_at sat;
|
|
|
|
struct sockaddr_dl sdl;
|
|
|
|
#ifndef SMALL
|
2010-06-26 18:29:36 +04:00
|
|
|
struct sockaddr_mpls smpls;
|
2008-09-10 05:56:22 +04:00
|
|
|
#endif /* SMALL */
|
2011-02-01 04:39:19 +03:00
|
|
|
struct sockaddr_storage sstorage;
|
2008-09-10 05:56:22 +04:00
|
|
|
};
|
|
|
|
|
1997-04-03 06:35:46 +04:00
|
|
|
typedef union sockunion *sup;
|
|
|
|
|
2008-09-10 05:56:22 +04:00
|
|
|
struct sou {
|
2011-06-21 18:33:14 +04:00
|
|
|
union sockunion *so_dst, *so_gate, *so_mask, *so_genmask, *so_ifa,
|
|
|
|
*so_ifp, *so_mpls;
|
2008-09-10 05:56:22 +04:00
|
|
|
};
|
|
|
|
|
2005-08-13 01:23:06 +04:00
|
|
|
static const char *route_strerror(int);
|
2008-09-10 05:00:02 +04:00
|
|
|
static void set_metric(const char *, int);
|
2008-09-10 05:06:58 +04:00
|
|
|
static int newroute(int, char *const *);
|
2008-09-10 05:56:22 +04:00
|
|
|
static void inet_makenetandmask(u_int32_t, struct sockaddr_in *, struct sou *);
|
2000-04-20 16:08:50 +04:00
|
|
|
#ifdef INET6
|
2008-09-10 05:56:22 +04:00
|
|
|
static int inet6_makenetandmask(const struct sockaddr_in6 *, struct sou *);
|
2000-04-20 16:08:50 +04:00
|
|
|
#endif
|
2008-09-10 05:56:22 +04:00
|
|
|
static int getaddr(int, const char *, struct hostent **, struct sou *);
|
2008-09-10 05:06:58 +04:00
|
|
|
static int flushroutes(int, char *const [], int);
|
2014-11-07 00:29:32 +03:00
|
|
|
static char *netmask_string(const struct sockaddr *, int, int);
|
2008-09-10 05:56:22 +04:00
|
|
|
static int prefixlen(const char *, struct sou *);
|
2005-08-31 06:58:30 +04:00
|
|
|
#ifndef SMALL
|
2005-02-05 17:05:23 +03:00
|
|
|
static void interfaces(void);
|
2011-08-29 18:34:58 +04:00
|
|
|
__dead static void monitor(void);
|
2008-09-10 05:56:22 +04:00
|
|
|
static int print_getmsg(struct rt_msghdr *, int, struct sou *);
|
2005-02-05 17:05:23 +03:00
|
|
|
static const char *linkstate(struct if_msghdr *);
|
2011-06-21 18:33:14 +04:00
|
|
|
static sup readtag(sup, const char *);
|
|
|
|
static void addtag(sup, const char *, int);
|
2002-02-21 18:44:25 +03:00
|
|
|
#endif /* SMALL */
|
2008-09-10 05:56:22 +04:00
|
|
|
static int rtmsg(int, int, struct sou *);
|
|
|
|
static void mask_addr(struct sou *);
|
2005-02-05 17:05:23 +03:00
|
|
|
static void print_rtmsg(struct rt_msghdr *, int);
|
|
|
|
static void pmsg_common(struct rt_msghdr *);
|
2008-09-09 20:55:28 +04:00
|
|
|
static void pmsg_addrs(const char *, int);
|
2006-01-25 19:19:50 +03:00
|
|
|
static void bprintf(FILE *, int, const char *);
|
2005-06-27 01:28:15 +04:00
|
|
|
static void sodump(sup, const char *);
|
2008-09-10 04:57:57 +04:00
|
|
|
static void sockaddr(const char *, struct sockaddr *);
|
1993-03-21 12:45:37 +03:00
|
|
|
|
1997-02-23 00:22:24 +03:00
|
|
|
int pid, rtm_addrs;
|
2001-11-02 06:51:48 +03:00
|
|
|
int sock;
|
2014-11-12 06:34:08 +03:00
|
|
|
int forcehost, forcenet, doflush, af;
|
|
|
|
int iflag, Lflag, nflag, qflag, tflag, Sflag, Tflag;
|
|
|
|
int verbose, aflen = sizeof(struct sockaddr_in), rtag;
|
2005-08-13 01:23:06 +04:00
|
|
|
int locking, lockrest, debugonly, shortoutput;
|
1993-03-21 12:45:37 +03:00
|
|
|
struct rt_metrics rt_metrics;
|
2011-02-01 04:39:19 +03:00
|
|
|
int rtm_inits;
|
2001-02-05 00:09:07 +03:00
|
|
|
short ns_nullh[] = {0,0,0};
|
|
|
|
short ns_bh[] = {-1,-1,-1};
|
|
|
|
|
2014-11-12 06:34:08 +03:00
|
|
|
static const char opts[] = "dfLnqSsTtv";
|
1997-04-03 06:35:46 +04:00
|
|
|
|
2005-08-10 01:25:42 +04:00
|
|
|
void
|
2005-06-27 01:28:15 +04:00
|
|
|
usage(const char *cp)
|
1993-03-21 12:45:37 +03:00
|
|
|
{
|
2001-02-20 01:48:57 +03:00
|
|
|
|
1993-03-21 12:45:37 +03:00
|
|
|
if (cp)
|
1997-11-16 20:03:11 +03:00
|
|
|
warnx("botched keyword: %s", cp);
|
2005-08-09 23:43:24 +04:00
|
|
|
(void)fprintf(stderr,
|
2014-11-07 17:57:08 +03:00
|
|
|
"Usage: %s [-%s] cmd [[-<qualifers>] args]\n", getprogname(), opts);
|
1993-03-21 12:45:37 +03:00
|
|
|
exit(1);
|
|
|
|
/* NOTREACHED */
|
|
|
|
}
|
|
|
|
|
2005-06-25 10:38:35 +04:00
|
|
|
#define PRIETHER "02x:%02x:%02x:%02x:%02x:%02x"
|
|
|
|
#define PRIETHER_ARGS(__enaddr) (__enaddr)[0], (__enaddr)[1], (__enaddr)[2], \
|
|
|
|
(__enaddr)[3], (__enaddr)[4], (__enaddr)[5]
|
1993-03-21 12:45:37 +03:00
|
|
|
|
1994-05-13 12:02:16 +04:00
|
|
|
int
|
2008-09-10 05:06:58 +04:00
|
|
|
main(int argc, char * const *argv)
|
1993-03-21 12:45:37 +03:00
|
|
|
{
|
2010-11-05 02:38:18 +03:00
|
|
|
int ch;
|
2010-11-05 02:36:10 +03:00
|
|
|
|
1993-03-21 12:45:37 +03:00
|
|
|
if (argc < 2)
|
1997-11-16 20:03:11 +03:00
|
|
|
usage(NULL);
|
1993-03-21 12:45:37 +03:00
|
|
|
|
2014-11-07 17:57:08 +03:00
|
|
|
while ((ch = getopt(argc, argv, opts)) != -1)
|
2005-07-21 01:12:40 +04:00
|
|
|
switch (ch) {
|
|
|
|
case 'd':
|
|
|
|
debugonly = 1;
|
|
|
|
break;
|
1998-10-23 09:36:42 +04:00
|
|
|
case 'f':
|
|
|
|
doflush = 1;
|
|
|
|
break;
|
2014-11-12 06:34:08 +03:00
|
|
|
case 'L':
|
|
|
|
Lflag = RT_LFLAG;
|
|
|
|
break;
|
1993-03-21 12:45:37 +03:00
|
|
|
case 'n':
|
2014-11-07 00:29:32 +03:00
|
|
|
nflag = RT_NFLAG;
|
1993-03-21 12:45:37 +03:00
|
|
|
break;
|
|
|
|
case 'q':
|
|
|
|
qflag = 1;
|
|
|
|
break;
|
2006-01-25 19:29:10 +03:00
|
|
|
case 'S':
|
|
|
|
Sflag = 1;
|
|
|
|
break;
|
2006-01-30 01:11:10 +03:00
|
|
|
case 's':
|
|
|
|
shortoutput = 1;
|
|
|
|
break;
|
2014-11-07 17:57:08 +03:00
|
|
|
case 'T':
|
|
|
|
Tflag = RT_TFLAG;
|
|
|
|
break;
|
1993-03-21 12:45:37 +03:00
|
|
|
case 't':
|
|
|
|
tflag = 1;
|
|
|
|
break;
|
2005-07-21 01:12:40 +04:00
|
|
|
case 'v':
|
2014-11-07 17:57:08 +03:00
|
|
|
verbose = RT_VFLAG;
|
2001-10-24 22:40:16 +04:00
|
|
|
break;
|
1993-03-21 12:45:37 +03:00
|
|
|
case '?':
|
|
|
|
default:
|
1997-11-16 20:03:11 +03:00
|
|
|
usage(NULL);
|
2001-11-16 00:25:08 +03:00
|
|
|
/*NOTREACHED*/
|
1993-03-21 12:45:37 +03:00
|
|
|
}
|
|
|
|
argc -= optind;
|
|
|
|
argv += optind;
|
|
|
|
|
2010-12-13 20:39:47 +03:00
|
|
|
if (prog_init && prog_init() == -1)
|
|
|
|
err(1, "init failed");
|
|
|
|
|
|
|
|
pid = prog_getpid();
|
1993-03-21 12:45:37 +03:00
|
|
|
if (tflag)
|
2010-12-13 20:39:47 +03:00
|
|
|
sock = prog_open("/dev/null", O_WRONLY, 0);
|
1993-03-21 12:45:37 +03:00
|
|
|
else
|
2010-12-13 20:39:47 +03:00
|
|
|
sock = prog_socket(PF_ROUTE, SOCK_RAW, 0);
|
2001-11-02 06:51:48 +03:00
|
|
|
if (sock < 0)
|
2006-08-06 21:47:17 +04:00
|
|
|
err(EXIT_FAILURE, "socket");
|
1996-11-15 21:01:36 +03:00
|
|
|
|
1998-10-23 09:36:42 +04:00
|
|
|
if (*argv == NULL) {
|
|
|
|
if (doflush)
|
|
|
|
ch = K_FLUSH;
|
|
|
|
else
|
|
|
|
goto no_cmd;
|
|
|
|
} else
|
|
|
|
ch = keyword(*argv);
|
|
|
|
|
|
|
|
switch (ch) {
|
1996-11-15 21:01:36 +03:00
|
|
|
#ifndef SMALL
|
|
|
|
case K_GET:
|
|
|
|
#endif /* SMALL */
|
|
|
|
case K_CHANGE:
|
|
|
|
case K_ADD:
|
|
|
|
case K_DELETE:
|
1998-10-23 09:36:42 +04:00
|
|
|
if (doflush)
|
2003-07-19 05:36:47 +04:00
|
|
|
(void)flushroutes(1, argv, 0);
|
2001-11-16 00:25:08 +03:00
|
|
|
return newroute(argc, argv);
|
1996-11-15 21:01:36 +03:00
|
|
|
|
|
|
|
case K_SHOW:
|
2014-11-12 06:34:08 +03:00
|
|
|
show(argc, argv, Lflag|nflag|Tflag|verbose);
|
2001-11-16 00:25:08 +03:00
|
|
|
return 0;
|
1996-11-15 21:01:36 +03:00
|
|
|
|
|
|
|
#ifndef SMALL
|
|
|
|
case K_MONITOR:
|
|
|
|
monitor();
|
2001-11-16 00:25:08 +03:00
|
|
|
return 0;
|
1996-11-15 21:01:36 +03:00
|
|
|
|
1998-10-23 09:36:42 +04:00
|
|
|
#endif /* SMALL */
|
1996-11-15 21:01:36 +03:00
|
|
|
case K_FLUSH:
|
2003-07-19 05:36:47 +04:00
|
|
|
return flushroutes(argc, argv, 0);
|
1996-11-15 21:01:36 +03:00
|
|
|
|
2003-07-19 05:36:47 +04:00
|
|
|
case K_FLUSHALL:
|
|
|
|
return flushroutes(argc, argv, 1);
|
1996-11-15 21:01:36 +03:00
|
|
|
no_cmd:
|
|
|
|
default:
|
|
|
|
usage(*argv);
|
2001-11-16 00:25:08 +03:00
|
|
|
/*NOTREACHED*/
|
1996-11-15 21:01:36 +03:00
|
|
|
}
|
1993-03-21 12:45:37 +03:00
|
|
|
}
|
|
|
|
|
2014-11-07 00:29:32 +03:00
|
|
|
static char *
|
|
|
|
netmask_string(const struct sockaddr *mask, int len, int family)
|
|
|
|
{
|
|
|
|
static char smask[INET6_ADDRSTRLEN];
|
|
|
|
struct sockaddr_in nsin;
|
|
|
|
struct sockaddr_in6 nsin6;
|
|
|
|
|
|
|
|
if (len >= 0)
|
|
|
|
snprintf(smask, sizeof(smask), "%d", len);
|
|
|
|
else {
|
|
|
|
switch (family) {
|
|
|
|
case AF_INET:
|
|
|
|
memset(&nsin, 0, sizeof(nsin));
|
|
|
|
memcpy(&nsin, mask, mask->sa_len);
|
|
|
|
snprintf(smask, sizeof(smask), "%s",
|
|
|
|
inet_ntoa(nsin.sin_addr));
|
|
|
|
break;
|
|
|
|
case AF_INET6:
|
|
|
|
memset(&nsin6, 0, sizeof(nsin6));
|
|
|
|
memcpy(&nsin6, mask, mask->sa_len);
|
|
|
|
inet_ntop(family, &nsin6.sin6_addr, smask,
|
|
|
|
sizeof(smask));
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
snprintf(smask, sizeof(smask), "%s", any_ntoa(mask));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return smask;
|
|
|
|
}
|
1993-03-21 12:45:37 +03:00
|
|
|
/*
|
|
|
|
* Purge all entries in the routing tables not
|
|
|
|
* associated with network interfaces.
|
|
|
|
*/
|
2001-11-16 00:25:08 +03:00
|
|
|
static int
|
2008-09-10 05:06:58 +04:00
|
|
|
flushroutes(int argc, char * const argv[], int doall)
|
1993-03-21 12:45:37 +03:00
|
|
|
{
|
2006-09-24 02:41:25 +04:00
|
|
|
struct sockaddr *sa;
|
1994-05-13 12:02:16 +04:00
|
|
|
size_t needed;
|
2006-09-24 02:41:25 +04:00
|
|
|
int flags, mib[6], rlen, seqno;
|
1993-03-21 12:45:37 +03:00
|
|
|
char *buf, *next, *lim;
|
2006-09-24 02:41:25 +04:00
|
|
|
const char *afname;
|
1997-09-15 13:15:26 +04:00
|
|
|
struct rt_msghdr *rtm;
|
1993-03-21 12:45:37 +03:00
|
|
|
|
2006-09-24 02:41:25 +04:00
|
|
|
flags = 0;
|
2006-09-24 01:51:05 +04:00
|
|
|
af = AF_UNSPEC;
|
2010-12-13 20:39:47 +03:00
|
|
|
/* Don't want to read back our messages */
|
|
|
|
prog_shutdown(sock, SHUT_RD);
|
2008-09-09 20:18:17 +04:00
|
|
|
parse_show_opts(argc, argv, &af, &flags, &afname, false);
|
1994-05-13 12:02:16 +04:00
|
|
|
mib[0] = CTL_NET;
|
|
|
|
mib[1] = PF_ROUTE;
|
|
|
|
mib[2] = 0; /* protocol */
|
|
|
|
mib[3] = 0; /* wildcard address family */
|
|
|
|
mib[4] = NET_RT_DUMP;
|
|
|
|
mib[5] = 0; /* no flags */
|
2010-12-13 20:39:47 +03:00
|
|
|
if (prog_sysctl(mib, 6, NULL, &needed, NULL, 0) < 0)
|
2006-08-06 21:47:17 +04:00
|
|
|
err(EXIT_FAILURE, "route-sysctl-estimate");
|
2005-08-30 23:01:25 +04:00
|
|
|
buf = lim = NULL;
|
|
|
|
if (needed) {
|
|
|
|
if ((buf = malloc(needed)) == NULL)
|
2006-08-06 21:47:17 +04:00
|
|
|
err(EXIT_FAILURE, "malloc");
|
2010-12-13 20:39:47 +03:00
|
|
|
if (prog_sysctl(mib, 6, buf, &needed, NULL, 0) < 0)
|
2006-08-06 21:47:17 +04:00
|
|
|
err(EXIT_FAILURE, "actual retrieval of routing table");
|
2005-08-30 23:01:25 +04:00
|
|
|
lim = buf + needed;
|
|
|
|
}
|
1996-11-15 21:01:36 +03:00
|
|
|
if (verbose) {
|
2005-08-09 23:43:24 +04:00
|
|
|
(void)printf("Examining routing table from sysctl\n");
|
2006-09-24 01:51:05 +04:00
|
|
|
if (af != AF_UNSPEC)
|
2006-09-24 02:41:25 +04:00
|
|
|
printf("(address family %s)\n", afname);
|
1996-11-15 21:01:36 +03:00
|
|
|
}
|
2005-08-30 23:01:25 +04:00
|
|
|
if (needed == 0)
|
|
|
|
return 0;
|
1993-03-21 12:45:37 +03:00
|
|
|
seqno = 0; /* ??? */
|
|
|
|
for (next = buf; next < lim; next += rtm->rtm_msglen) {
|
|
|
|
rtm = (struct rt_msghdr *)next;
|
2006-09-24 02:41:25 +04:00
|
|
|
sa = (struct sockaddr *)(rtm + 1);
|
1994-05-13 12:02:16 +04:00
|
|
|
if (verbose)
|
|
|
|
print_rtmsg(rtm, rtm->rtm_msglen);
|
2006-09-24 02:41:25 +04:00
|
|
|
if ((rtm->rtm_flags & flags) != flags)
|
|
|
|
continue;
|
2016-04-04 10:37:07 +03:00
|
|
|
if (!(rtm->rtm_flags & (RTF_GATEWAY | RTF_STATIC)) && !doall)
|
1993-03-21 12:45:37 +03:00
|
|
|
continue;
|
2006-09-24 02:41:25 +04:00
|
|
|
if (af != AF_UNSPEC && sa->sa_family != af)
|
|
|
|
continue;
|
1994-05-13 12:02:16 +04:00
|
|
|
if (debugonly)
|
|
|
|
continue;
|
1993-03-21 12:45:37 +03:00
|
|
|
rtm->rtm_type = RTM_DELETE;
|
|
|
|
rtm->rtm_seq = seqno;
|
2010-12-13 20:39:47 +03:00
|
|
|
if ((rlen = prog_write(sock, next,
|
|
|
|
rtm->rtm_msglen)) < 0) {
|
2005-08-13 01:23:06 +04:00
|
|
|
warnx("writing to routing socket: %s",
|
|
|
|
route_strerror(errno));
|
|
|
|
return 1;
|
|
|
|
}
|
1993-03-21 12:45:37 +03:00
|
|
|
if (rlen < (int)rtm->rtm_msglen) {
|
2005-08-13 01:23:06 +04:00
|
|
|
warnx("write to routing socket, got %d for rlen", rlen);
|
2005-07-16 01:29:54 +04:00
|
|
|
return 1;
|
1993-03-21 12:45:37 +03:00
|
|
|
}
|
|
|
|
seqno++;
|
|
|
|
if (qflag)
|
|
|
|
continue;
|
|
|
|
if (verbose)
|
|
|
|
print_rtmsg(rtm, rlen);
|
|
|
|
else {
|
2014-11-07 00:29:32 +03:00
|
|
|
(void)printf("%-20.20s ", netname(sa, NULL, nflag));
|
2011-02-01 04:39:19 +03:00
|
|
|
sa = (struct sockaddr *)(RT_ROUNDUP(sa->sa_len) +
|
2006-09-24 02:41:25 +04:00
|
|
|
(char *)sa);
|
2014-11-07 00:29:32 +03:00
|
|
|
(void)printf("%-20.20s ", routename(sa, nflag));
|
2005-08-09 23:43:24 +04:00
|
|
|
(void)printf("done\n");
|
1993-03-21 12:45:37 +03:00
|
|
|
}
|
|
|
|
}
|
2005-08-30 23:01:25 +04:00
|
|
|
free(buf);
|
2001-11-16 00:25:08 +03:00
|
|
|
return 0;
|
1993-03-21 12:45:37 +03:00
|
|
|
}
|
1996-11-15 21:01:36 +03:00
|
|
|
|
2005-08-13 01:23:06 +04:00
|
|
|
static const char *
|
|
|
|
route_strerror(int error)
|
|
|
|
{
|
|
|
|
|
|
|
|
switch (error) {
|
|
|
|
case ESRCH:
|
|
|
|
return "not in table";
|
|
|
|
case EBUSY:
|
|
|
|
return "entry in use";
|
|
|
|
case ENOBUFS:
|
|
|
|
return "routing table overflow";
|
|
|
|
default:
|
|
|
|
return strerror(error);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1997-04-03 06:35:46 +04:00
|
|
|
static void
|
2008-09-10 05:00:02 +04:00
|
|
|
set_metric(const char *value, int key)
|
1993-03-21 12:45:37 +03:00
|
|
|
{
|
1994-05-13 12:02:16 +04:00
|
|
|
int flag = 0;
|
2011-02-01 04:39:19 +03:00
|
|
|
uint64_t noval, *valp = &noval;
|
1993-03-21 12:45:37 +03:00
|
|
|
|
|
|
|
switch (key) {
|
2011-02-01 04:39:19 +03:00
|
|
|
#define caseof(x, y, z) \
|
|
|
|
case x: valp = (uint64_t *)&rt_metrics.z; flag = y; break
|
1993-03-21 12:45:37 +03:00
|
|
|
caseof(K_MTU, RTV_MTU, rmx_mtu);
|
|
|
|
caseof(K_HOPCOUNT, RTV_HOPCOUNT, rmx_hopcount);
|
|
|
|
caseof(K_EXPIRE, RTV_EXPIRE, rmx_expire);
|
|
|
|
caseof(K_RECVPIPE, RTV_RPIPE, rmx_recvpipe);
|
|
|
|
caseof(K_SENDPIPE, RTV_SPIPE, rmx_sendpipe);
|
|
|
|
caseof(K_SSTHRESH, RTV_SSTHRESH, rmx_ssthresh);
|
|
|
|
caseof(K_RTT, RTV_RTT, rmx_rtt);
|
|
|
|
caseof(K_RTTVAR, RTV_RTTVAR, rmx_rttvar);
|
|
|
|
}
|
|
|
|
rtm_inits |= flag;
|
|
|
|
if (lockrest || locking)
|
|
|
|
rt_metrics.rmx_locks |= flag;
|
|
|
|
if (locking)
|
|
|
|
locking = 0;
|
2008-12-28 23:12:31 +03:00
|
|
|
*valp = strtoul(value, NULL, 0);
|
1993-03-21 12:45:37 +03:00
|
|
|
}
|
|
|
|
|
2001-11-16 00:25:08 +03:00
|
|
|
static int
|
2008-09-10 05:06:58 +04:00
|
|
|
newroute(int argc, char *const *argv)
|
1993-03-21 12:45:37 +03:00
|
|
|
{
|
2005-06-27 01:28:15 +04:00
|
|
|
const char *cmd, *dest = "", *gateway = "";
|
1994-05-13 12:02:16 +04:00
|
|
|
int ishost = 0, ret, attempts, oerrno, flags = RTF_STATIC;
|
1993-03-21 12:45:37 +03:00
|
|
|
int key;
|
|
|
|
struct hostent *hp = 0;
|
2008-09-10 05:56:22 +04:00
|
|
|
struct sou sou, *soup = &sou;
|
|
|
|
|
2011-06-21 18:33:14 +04:00
|
|
|
sou.so_dst = calloc(1, sizeof(union sockunion));
|
|
|
|
sou.so_gate = calloc(1, sizeof(union sockunion));
|
|
|
|
sou.so_mask = calloc(1, sizeof(union sockunion));
|
|
|
|
sou.so_genmask = calloc(1, sizeof(union sockunion));
|
|
|
|
sou.so_ifa = calloc(1, sizeof(union sockunion));
|
|
|
|
sou.so_ifp = calloc(1, sizeof(union sockunion));
|
|
|
|
sou.so_mpls = calloc(1, sizeof(union sockunion));
|
|
|
|
|
|
|
|
if (sou.so_dst == NULL || sou.so_gate == NULL || sou.so_mask == NULL ||
|
|
|
|
sou.so_genmask == NULL || sou.so_ifa == NULL || sou.so_ifp == NULL ||
|
|
|
|
sou.so_mpls == NULL)
|
|
|
|
errx(EXIT_FAILURE, "Cannot allocate memory");
|
1993-03-21 12:45:37 +03:00
|
|
|
|
|
|
|
cmd = argv[0];
|
2006-09-24 01:51:05 +04:00
|
|
|
af = AF_UNSPEC;
|
2010-12-13 20:39:47 +03:00
|
|
|
if (*cmd != 'g') {
|
|
|
|
/* Don't want to read back our messages */
|
|
|
|
prog_shutdown(sock, SHUT_RD);
|
|
|
|
}
|
1993-03-21 12:45:37 +03:00
|
|
|
while (--argc > 0) {
|
|
|
|
if (**(++argv)== '-') {
|
|
|
|
switch (key = keyword(1 + *argv)) {
|
1996-11-15 21:01:36 +03:00
|
|
|
|
|
|
|
case K_SA:
|
|
|
|
af = PF_ROUTE;
|
|
|
|
aflen = sizeof(union sockunion);
|
|
|
|
break;
|
|
|
|
|
2003-06-11 19:45:20 +04:00
|
|
|
#ifndef SMALL
|
1997-04-03 06:35:46 +04:00
|
|
|
case K_ATALK:
|
|
|
|
af = AF_APPLETALK;
|
|
|
|
aflen = sizeof(struct sockaddr_at);
|
|
|
|
break;
|
2003-06-11 19:45:20 +04:00
|
|
|
#endif
|
1997-04-03 06:35:46 +04:00
|
|
|
|
1996-11-15 21:01:36 +03:00
|
|
|
case K_INET:
|
|
|
|
af = AF_INET;
|
|
|
|
aflen = sizeof(struct sockaddr_in);
|
|
|
|
break;
|
|
|
|
|
1999-07-02 19:29:02 +04:00
|
|
|
#ifdef INET6
|
|
|
|
case K_INET6:
|
|
|
|
af = AF_INET6;
|
|
|
|
aflen = sizeof(struct sockaddr_in6);
|
|
|
|
break;
|
|
|
|
#endif
|
|
|
|
|
1993-03-21 12:45:37 +03:00
|
|
|
case K_LINK:
|
|
|
|
af = AF_LINK;
|
|
|
|
aflen = sizeof(struct sockaddr_dl);
|
|
|
|
break;
|
1996-11-15 21:01:36 +03:00
|
|
|
|
1998-10-23 09:36:42 +04:00
|
|
|
#ifndef SMALL
|
2010-06-26 18:29:36 +04:00
|
|
|
case K_MPLS:
|
|
|
|
af = AF_MPLS;
|
|
|
|
aflen = sizeof(struct sockaddr_mpls);
|
|
|
|
break;
|
|
|
|
case K_TAG:
|
|
|
|
if (!--argc)
|
|
|
|
usage(1+*argv);
|
2011-06-21 18:33:14 +04:00
|
|
|
af = AF_MPLS;
|
2010-06-26 18:29:36 +04:00
|
|
|
aflen = sizeof(struct sockaddr_mpls);
|
|
|
|
(void)getaddr(RTA_TAG, *++argv, 0, soup);
|
|
|
|
break;
|
1998-10-23 09:36:42 +04:00
|
|
|
#endif /* SMALL */
|
1996-11-15 21:01:36 +03:00
|
|
|
|
1993-03-21 12:45:37 +03:00
|
|
|
case K_IFACE:
|
|
|
|
case K_INTERFACE:
|
|
|
|
iflag++;
|
1995-04-21 00:52:46 +04:00
|
|
|
break;
|
1994-05-13 12:02:16 +04:00
|
|
|
case K_NOSTATIC:
|
|
|
|
flags &= ~RTF_STATIC;
|
1993-03-21 12:45:37 +03:00
|
|
|
break;
|
|
|
|
case K_LOCK:
|
|
|
|
locking = 1;
|
|
|
|
break;
|
|
|
|
case K_LOCKREST:
|
|
|
|
lockrest = 1;
|
|
|
|
break;
|
|
|
|
case K_HOST:
|
|
|
|
forcehost++;
|
|
|
|
break;
|
|
|
|
case K_REJECT:
|
|
|
|
flags |= RTF_REJECT;
|
|
|
|
break;
|
2010-05-12 21:56:13 +04:00
|
|
|
case K_NOREJECT:
|
|
|
|
flags &= ~RTF_REJECT;
|
|
|
|
break;
|
1994-05-13 12:02:16 +04:00
|
|
|
case K_BLACKHOLE:
|
|
|
|
flags |= RTF_BLACKHOLE;
|
|
|
|
break;
|
2010-05-12 21:56:13 +04:00
|
|
|
case K_NOBLACKHOLE:
|
|
|
|
flags &= ~RTF_BLACKHOLE;
|
|
|
|
break;
|
1993-03-21 12:45:37 +03:00
|
|
|
case K_PROTO1:
|
|
|
|
flags |= RTF_PROTO1;
|
|
|
|
break;
|
|
|
|
case K_PROTO2:
|
|
|
|
flags |= RTF_PROTO2;
|
|
|
|
break;
|
Move RTF_ANNOUNCE flag so that it no longer conflicts with RTF_PROTO2.
RTF_ANNOUNCE was defined as RTF_PROTO2. The flag is used to indicated
that host should act as a proxy for a link level arp or ndp request.
(If RTF_PROTO2 is used as an experimental flag (as advertised),
various problems can occur.)
This commit provides a first-class definition with its own bit for
RTF_ANNOUNCE, removes the old aliasing definitions, and adds support
for the new RTF_ANNOUNCE flag to netstat(8) and route(8).,
Also, remove unused RTF_ flags that collide with RTF_PROTO1:
netinet/icmp6.h defined RTF_PROBEMTU as RTF_PROTO1
netinet/if_inarp.h defined RTF_USETRAILERS as RTF_PROTO1
(Neither of these flags are used anywhere. Both have been removed
to reduce chances of collision with RTF_PROTO1.)
Figuring this out and the diff are the work of Beverly Schwartz of
BBN.
(Passed release build, boot in VM, with no apparently related atf
failures.)
Approved for Public Release, Distribution Unlimited
This material is based upon work supported by the Defense Advanced
Research Projects Agency and Space and Naval Warfare Systems Center,
Pacific, under Contract No. N66001-09-C-2073.
2011-11-11 19:09:32 +04:00
|
|
|
case K_PROXY:
|
|
|
|
flags |= RTF_ANNOUNCE;
|
|
|
|
break;
|
2016-04-04 10:37:07 +03:00
|
|
|
case K_CONNECTED:
|
|
|
|
flags |= RTF_CONNECTED;
|
2006-08-06 21:44:56 +04:00
|
|
|
break;
|
2016-04-04 10:37:07 +03:00
|
|
|
case K_NOCONNECTED:
|
|
|
|
flags &= ~RTF_CONNECTED;
|
1993-03-21 12:45:37 +03:00
|
|
|
break;
|
1994-05-13 12:02:16 +04:00
|
|
|
case K_STATIC:
|
|
|
|
flags |= RTF_STATIC;
|
|
|
|
break;
|
1993-03-21 12:45:37 +03:00
|
|
|
case K_IFA:
|
1997-04-27 20:58:22 +04:00
|
|
|
if (!--argc)
|
|
|
|
usage(1+*argv);
|
2008-09-10 05:56:22 +04:00
|
|
|
(void)getaddr(RTA_IFA, *++argv, 0, soup);
|
1993-03-21 12:45:37 +03:00
|
|
|
break;
|
|
|
|
case K_IFP:
|
1997-04-27 20:58:22 +04:00
|
|
|
if (!--argc)
|
|
|
|
usage(1+*argv);
|
2008-09-10 05:56:22 +04:00
|
|
|
(void)getaddr(RTA_IFP, *++argv, 0, soup);
|
1993-03-21 12:45:37 +03:00
|
|
|
break;
|
|
|
|
case K_GENMASK:
|
1997-04-27 20:58:22 +04:00
|
|
|
if (!--argc)
|
|
|
|
usage(1+*argv);
|
2008-09-10 05:56:22 +04:00
|
|
|
(void)getaddr(RTA_GENMASK, *++argv, 0, soup);
|
1993-03-21 12:45:37 +03:00
|
|
|
break;
|
|
|
|
case K_GATEWAY:
|
1997-04-27 20:58:22 +04:00
|
|
|
if (!--argc)
|
|
|
|
usage(1+*argv);
|
2008-09-10 05:56:22 +04:00
|
|
|
(void)getaddr(RTA_GATEWAY, *++argv, 0, soup);
|
1993-03-21 12:45:37 +03:00
|
|
|
break;
|
|
|
|
case K_DST:
|
1997-04-27 20:58:22 +04:00
|
|
|
if (!--argc)
|
|
|
|
usage(1+*argv);
|
2008-09-10 05:56:22 +04:00
|
|
|
ishost = getaddr(RTA_DST, *++argv, &hp, soup);
|
1993-03-21 12:45:37 +03:00
|
|
|
dest = *argv;
|
|
|
|
break;
|
|
|
|
case K_NETMASK:
|
1997-04-27 20:58:22 +04:00
|
|
|
if (!--argc)
|
|
|
|
usage(1+*argv);
|
2008-09-10 05:56:22 +04:00
|
|
|
(void)getaddr(RTA_NETMASK, *++argv, 0, soup);
|
1993-03-21 12:45:37 +03:00
|
|
|
/* FALLTHROUGH */
|
|
|
|
case K_NET:
|
|
|
|
forcenet++;
|
|
|
|
break;
|
1999-07-02 19:29:02 +04:00
|
|
|
case K_PREFIXLEN:
|
2002-10-18 04:16:25 +04:00
|
|
|
if (!--argc)
|
|
|
|
usage(1+*argv);
|
2008-09-10 05:56:22 +04:00
|
|
|
ishost = prefixlen(*++argv, soup);
|
1999-07-02 19:29:02 +04:00
|
|
|
break;
|
1993-03-21 12:45:37 +03:00
|
|
|
case K_MTU:
|
|
|
|
case K_HOPCOUNT:
|
|
|
|
case K_EXPIRE:
|
|
|
|
case K_RECVPIPE:
|
|
|
|
case K_SENDPIPE:
|
|
|
|
case K_SSTHRESH:
|
|
|
|
case K_RTT:
|
|
|
|
case K_RTTVAR:
|
1997-04-27 20:58:22 +04:00
|
|
|
if (!--argc)
|
|
|
|
usage(1+*argv);
|
1993-03-21 12:45:37 +03:00
|
|
|
set_metric(*++argv, key);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
usage(1+*argv);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if ((rtm_addrs & RTA_DST) == 0) {
|
|
|
|
dest = *argv;
|
2008-09-10 05:56:22 +04:00
|
|
|
ishost = getaddr(RTA_DST, *argv, &hp, soup);
|
1993-03-21 12:45:37 +03:00
|
|
|
} else if ((rtm_addrs & RTA_GATEWAY) == 0) {
|
|
|
|
gateway = *argv;
|
2008-09-10 05:56:22 +04:00
|
|
|
(void)getaddr(RTA_GATEWAY, *argv, &hp, soup);
|
1993-03-21 12:45:37 +03:00
|
|
|
} else {
|
2001-11-02 06:51:48 +03:00
|
|
|
ret = atoi(*argv);
|
1994-05-13 12:02:16 +04:00
|
|
|
|
1993-03-21 12:45:37 +03:00
|
|
|
if (ret == 0) {
|
2003-06-11 19:45:20 +04:00
|
|
|
if (strcmp(*argv, "0") == 0) {
|
|
|
|
if (!qflag) {
|
|
|
|
warnx("%s, %s",
|
|
|
|
"old usage of trailing 0",
|
|
|
|
"assuming route to if");
|
|
|
|
}
|
|
|
|
} else
|
2005-08-30 23:01:25 +04:00
|
|
|
usage(NULL);
|
1993-03-21 12:45:37 +03:00
|
|
|
iflag = 1;
|
|
|
|
continue;
|
|
|
|
} else if (ret > 0 && ret < 10) {
|
1996-01-07 03:07:23 +03:00
|
|
|
if (!qflag) {
|
2003-06-11 19:45:20 +04:00
|
|
|
warnx("%s, %s",
|
1997-11-16 20:03:11 +03:00
|
|
|
"old usage of trailing digit",
|
|
|
|
"assuming route via gateway");
|
1996-01-07 03:07:23 +03:00
|
|
|
}
|
1993-03-21 12:45:37 +03:00
|
|
|
iflag = 0;
|
|
|
|
continue;
|
|
|
|
}
|
2008-09-10 05:56:22 +04:00
|
|
|
(void)getaddr(RTA_NETMASK, *argv, 0, soup);
|
1993-03-21 12:45:37 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2012-03-17 06:13:44 +04:00
|
|
|
if ((rtm_addrs & RTA_DST) == 0)
|
|
|
|
errx(EXIT_FAILURE, "missing destination specification");
|
|
|
|
if (*cmd == 'a' && (rtm_addrs & RTA_GATEWAY) == 0)
|
|
|
|
errx(EXIT_FAILURE, "missing gateway specification");
|
2003-06-11 19:45:20 +04:00
|
|
|
if (forcehost && forcenet)
|
2006-08-06 21:47:17 +04:00
|
|
|
errx(EXIT_FAILURE, "-host and -net conflict");
|
2003-06-11 19:45:20 +04:00
|
|
|
else if (forcehost)
|
1993-03-21 12:45:37 +03:00
|
|
|
ishost = 1;
|
2003-06-11 19:45:20 +04:00
|
|
|
else if (forcenet)
|
1993-03-21 12:45:37 +03:00
|
|
|
ishost = 0;
|
|
|
|
flags |= RTF_UP;
|
|
|
|
if (ishost)
|
|
|
|
flags |= RTF_HOST;
|
|
|
|
if (iflag == 0)
|
|
|
|
flags |= RTF_GATEWAY;
|
|
|
|
for (attempts = 1; ; attempts++) {
|
|
|
|
errno = 0;
|
2008-09-10 05:56:22 +04:00
|
|
|
if ((ret = rtmsg(*cmd, flags, soup)) == 0)
|
1994-05-13 12:02:16 +04:00
|
|
|
break;
|
1993-03-21 12:45:37 +03:00
|
|
|
if (errno != ENETUNREACH && errno != ESRCH)
|
|
|
|
break;
|
1994-05-13 12:02:16 +04:00
|
|
|
if (af == AF_INET && *gateway && hp && hp->h_addr_list[1]) {
|
1993-03-21 12:45:37 +03:00
|
|
|
hp->h_addr_list++;
|
2011-06-21 18:33:14 +04:00
|
|
|
memmove(&soup->so_gate->sin.sin_addr, hp->h_addr_list[0],
|
1993-03-21 12:45:37 +03:00
|
|
|
hp->h_length);
|
|
|
|
} else
|
|
|
|
break;
|
|
|
|
}
|
2016-01-17 18:59:26 +03:00
|
|
|
if (*cmd == 'g' || qflag)
|
|
|
|
goto out;
|
|
|
|
|
|
|
|
oerrno = errno;
|
|
|
|
(void)printf("%s %s %s", cmd, ishost? "host" : "net", dest);
|
|
|
|
if (*gateway) {
|
|
|
|
(void)printf(": gateway %s", gateway);
|
|
|
|
if (attempts > 1 && ret == 0 && af == AF_INET)
|
|
|
|
(void)printf(" (%s)",
|
|
|
|
inet_ntoa(soup->so_gate->sin.sin_addr));
|
1993-03-21 12:45:37 +03:00
|
|
|
}
|
2016-01-17 18:59:26 +03:00
|
|
|
if (ret == 0)
|
|
|
|
(void)printf("\n");
|
|
|
|
else
|
|
|
|
(void)printf(": %s\n", route_strerror(oerrno));
|
|
|
|
out:
|
2011-06-21 18:33:14 +04:00
|
|
|
free(sou.so_dst);
|
|
|
|
free(sou.so_gate);
|
|
|
|
free(sou.so_mask);
|
|
|
|
free(sou.so_genmask);
|
|
|
|
free(sou.so_ifa);
|
|
|
|
free(sou.so_ifp);
|
|
|
|
free(sou.so_mpls);
|
|
|
|
|
2008-09-09 20:50:52 +04:00
|
|
|
return ret != 0;
|
1993-03-21 12:45:37 +03:00
|
|
|
}
|
|
|
|
|
1997-04-03 06:35:46 +04:00
|
|
|
static void
|
2008-09-10 05:56:22 +04:00
|
|
|
inet_makenetandmask(const u_int32_t net, struct sockaddr_in * const isin,
|
|
|
|
struct sou *soup)
|
1993-03-21 12:45:37 +03:00
|
|
|
{
|
2008-09-10 04:57:57 +04:00
|
|
|
struct sockaddr_in *sin;
|
1998-02-06 00:09:46 +03:00
|
|
|
u_int32_t addr, mask = 0;
|
1997-09-15 13:15:26 +04:00
|
|
|
char *cp;
|
1993-03-21 12:45:37 +03:00
|
|
|
|
|
|
|
rtm_addrs |= RTA_NETMASK;
|
|
|
|
if (net == 0)
|
|
|
|
mask = addr = 0;
|
|
|
|
else if (net < 128) {
|
|
|
|
addr = net << IN_CLASSA_NSHIFT;
|
|
|
|
mask = IN_CLASSA_NET;
|
2003-04-21 17:42:50 +04:00
|
|
|
} else if (net < 192) {
|
|
|
|
addr = net << IN_CLASSA_NSHIFT;
|
|
|
|
mask = IN_CLASSB_NET;
|
|
|
|
} else if (net < 224) {
|
|
|
|
addr = net << IN_CLASSA_NSHIFT;
|
|
|
|
mask = IN_CLASSC_NET;
|
|
|
|
} else if (net < 256) {
|
|
|
|
addr = net << IN_CLASSA_NSHIFT;
|
|
|
|
mask = IN_CLASSD_NET;
|
|
|
|
} else if (net < 49152) { /* 192 * 256 */
|
1993-03-21 12:45:37 +03:00
|
|
|
addr = net << IN_CLASSB_NSHIFT;
|
|
|
|
mask = IN_CLASSB_NET;
|
2003-04-21 17:42:50 +04:00
|
|
|
} else if (net < 57344) { /* 224 * 256 */
|
|
|
|
addr = net << IN_CLASSB_NSHIFT;
|
|
|
|
mask = IN_CLASSC_NET;
|
2003-09-16 13:34:48 +04:00
|
|
|
} else if (net < 65536) {
|
2003-04-21 17:42:50 +04:00
|
|
|
addr = net << IN_CLASSB_NSHIFT;
|
|
|
|
mask = IN_CLASSB_NET;
|
|
|
|
} else if (net < 14680064L) { /* 224 * 65536 */
|
1993-03-21 12:45:37 +03:00
|
|
|
addr = net << IN_CLASSC_NSHIFT;
|
|
|
|
mask = IN_CLASSC_NET;
|
2003-04-21 17:42:50 +04:00
|
|
|
} else if (net < 16777216L) {
|
|
|
|
addr = net << IN_CLASSC_NSHIFT;
|
|
|
|
mask = IN_CLASSD_NET;
|
1993-03-21 12:45:37 +03:00
|
|
|
} else {
|
|
|
|
addr = net;
|
|
|
|
if ((addr & IN_CLASSA_HOST) == 0)
|
|
|
|
mask = IN_CLASSA_NET;
|
|
|
|
else if ((addr & IN_CLASSB_HOST) == 0)
|
|
|
|
mask = IN_CLASSB_NET;
|
|
|
|
else if ((addr & IN_CLASSC_HOST) == 0)
|
|
|
|
mask = IN_CLASSC_NET;
|
|
|
|
else
|
|
|
|
mask = -1;
|
|
|
|
}
|
2001-11-02 06:51:48 +03:00
|
|
|
isin->sin_addr.s_addr = htonl(addr);
|
2011-06-21 18:33:14 +04:00
|
|
|
sin = &soup->so_mask->sin;
|
2008-09-10 04:57:57 +04:00
|
|
|
sin->sin_addr.s_addr = htonl(mask);
|
|
|
|
sin->sin_len = 0;
|
|
|
|
sin->sin_family = 0;
|
|
|
|
cp = (char *)(&sin->sin_addr + 1);
|
|
|
|
while (*--cp == 0 && cp > (char *)sin)
|
1993-03-21 12:45:37 +03:00
|
|
|
;
|
2008-09-10 04:57:57 +04:00
|
|
|
sin->sin_len = 1 + cp - (char *)sin;
|
|
|
|
sin->sin_family = AF_INET;
|
1993-03-21 12:45:37 +03:00
|
|
|
}
|
|
|
|
|
2000-04-20 16:08:50 +04:00
|
|
|
#ifdef INET6
|
|
|
|
/*
|
|
|
|
* XXX the function may need more improvement...
|
|
|
|
*/
|
2002-05-21 03:01:32 +04:00
|
|
|
static int
|
2008-09-10 05:56:22 +04:00
|
|
|
inet6_makenetandmask(const struct sockaddr_in6 * const sin6, struct sou *soup)
|
2000-04-20 16:08:50 +04:00
|
|
|
{
|
2005-06-27 01:28:15 +04:00
|
|
|
const char *plen;
|
2000-04-20 16:08:50 +04:00
|
|
|
struct in6_addr in6;
|
|
|
|
|
|
|
|
plen = NULL;
|
|
|
|
if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr) &&
|
|
|
|
sin6->sin6_scope_id == 0) {
|
|
|
|
plen = "0";
|
|
|
|
} else if ((sin6->sin6_addr.s6_addr[0] & 0xe0) == 0x20) {
|
|
|
|
/* aggregatable global unicast - RFC2374 */
|
|
|
|
memset(&in6, 0, sizeof(in6));
|
|
|
|
if (!memcmp(&sin6->sin6_addr.s6_addr[8], &in6.s6_addr[8], 8))
|
|
|
|
plen = "64";
|
|
|
|
}
|
|
|
|
|
2002-06-06 02:10:44 +04:00
|
|
|
if (!plen || strcmp(plen, "128") == 0)
|
|
|
|
return 1;
|
|
|
|
else {
|
2000-04-20 16:08:50 +04:00
|
|
|
rtm_addrs |= RTA_NETMASK;
|
2008-09-10 05:56:22 +04:00
|
|
|
(void)prefixlen(plen, soup);
|
2002-06-06 02:10:44 +04:00
|
|
|
return 0;
|
2000-04-20 16:08:50 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
1993-03-21 12:45:37 +03:00
|
|
|
/*
|
|
|
|
* Interpret an argument as a network address of some kind,
|
|
|
|
* returning 1 if a host address, 0 if a network address.
|
|
|
|
*/
|
1997-04-03 06:35:46 +04:00
|
|
|
static int
|
2008-09-10 05:56:22 +04:00
|
|
|
getaddr(int which, const char *s, struct hostent **hpp, struct sou *soup)
|
1993-03-21 12:45:37 +03:00
|
|
|
{
|
1997-09-15 13:15:26 +04:00
|
|
|
sup su;
|
1993-03-21 12:45:37 +03:00
|
|
|
struct hostent *hp;
|
|
|
|
struct netent *np;
|
1998-02-06 00:09:46 +03:00
|
|
|
u_int32_t val;
|
1997-04-03 06:35:46 +04:00
|
|
|
char *t;
|
1999-07-02 19:29:02 +04:00
|
|
|
int afamily; /* local copy of af so we can change it */
|
1993-03-21 12:45:37 +03:00
|
|
|
|
2006-09-24 01:51:05 +04:00
|
|
|
if (af == AF_UNSPEC) {
|
1993-03-21 12:45:37 +03:00
|
|
|
af = AF_INET;
|
|
|
|
aflen = sizeof(struct sockaddr_in);
|
|
|
|
}
|
1999-07-02 19:29:02 +04:00
|
|
|
afamily = af;
|
1993-03-21 12:45:37 +03:00
|
|
|
rtm_addrs |= which;
|
|
|
|
switch (which) {
|
1994-05-13 12:02:16 +04:00
|
|
|
case RTA_DST:
|
2011-06-21 18:33:14 +04:00
|
|
|
su = soup->so_dst;
|
1994-05-13 12:02:16 +04:00
|
|
|
break;
|
|
|
|
case RTA_GATEWAY:
|
2011-06-21 18:33:14 +04:00
|
|
|
su = soup->so_gate;
|
1994-05-13 12:02:16 +04:00
|
|
|
break;
|
|
|
|
case RTA_NETMASK:
|
2011-06-21 18:33:14 +04:00
|
|
|
su = soup->so_mask;
|
1994-05-13 12:02:16 +04:00
|
|
|
break;
|
|
|
|
case RTA_GENMASK:
|
2011-06-21 18:33:14 +04:00
|
|
|
su = soup->so_genmask;
|
1994-05-13 12:02:16 +04:00
|
|
|
break;
|
|
|
|
case RTA_IFP:
|
2011-06-21 18:33:14 +04:00
|
|
|
su = soup->so_ifp;
|
1999-07-02 19:29:02 +04:00
|
|
|
afamily = AF_LINK;
|
1994-05-13 12:02:16 +04:00
|
|
|
break;
|
|
|
|
case RTA_IFA:
|
2011-06-21 18:33:14 +04:00
|
|
|
su = soup->so_ifa;
|
1994-05-13 12:02:16 +04:00
|
|
|
su->sa.sa_family = af;
|
|
|
|
break;
|
2010-11-05 02:37:27 +03:00
|
|
|
#ifndef SMALL
|
2010-06-26 18:29:36 +04:00
|
|
|
case RTA_TAG:
|
2011-06-21 18:33:14 +04:00
|
|
|
su = soup->so_mpls;
|
2010-06-26 18:29:36 +04:00
|
|
|
afamily = AF_MPLS;
|
|
|
|
break;
|
2010-11-05 02:37:27 +03:00
|
|
|
#endif
|
1994-05-13 12:02:16 +04:00
|
|
|
default:
|
1997-04-03 06:35:46 +04:00
|
|
|
su = NULL;
|
1994-05-13 12:02:16 +04:00
|
|
|
usage("Internal Error");
|
|
|
|
/*NOTREACHED*/
|
1993-03-21 12:45:37 +03:00
|
|
|
}
|
|
|
|
su->sa.sa_len = aflen;
|
1999-07-02 19:29:02 +04:00
|
|
|
su->sa.sa_family = afamily; /* cases that don't want it have left already */
|
1993-03-21 12:45:37 +03:00
|
|
|
if (strcmp(s, "default") == 0) {
|
|
|
|
switch (which) {
|
|
|
|
case RTA_DST:
|
|
|
|
forcenet++;
|
2008-09-10 05:56:22 +04:00
|
|
|
(void)getaddr(RTA_NETMASK, s, 0, soup);
|
1993-03-21 12:45:37 +03:00
|
|
|
break;
|
|
|
|
case RTA_NETMASK:
|
|
|
|
case RTA_GENMASK:
|
|
|
|
su->sa.sa_len = 0;
|
|
|
|
}
|
2008-09-09 20:50:52 +04:00
|
|
|
return 0;
|
1994-05-13 12:02:16 +04:00
|
|
|
}
|
1999-07-02 19:29:02 +04:00
|
|
|
switch (afamily) {
|
|
|
|
#ifdef INET6
|
|
|
|
case AF_INET6:
|
2000-04-20 16:08:50 +04:00
|
|
|
{
|
|
|
|
struct addrinfo hints, *res;
|
2003-06-11 19:45:20 +04:00
|
|
|
char *slash = 0;
|
2000-04-20 16:08:50 +04:00
|
|
|
|
2003-06-11 19:45:20 +04:00
|
|
|
if (which == RTA_DST && (slash = (strrchr(s, '/'))) != 0)
|
|
|
|
*slash = '\0';
|
2000-04-20 16:08:50 +04:00
|
|
|
memset(&hints, 0, sizeof(hints));
|
|
|
|
hints.ai_family = afamily; /*AF_INET6*/
|
|
|
|
hints.ai_flags = AI_NUMERICHOST;
|
|
|
|
hints.ai_socktype = SOCK_DGRAM; /*dummy*/
|
2002-06-11 01:18:53 +04:00
|
|
|
if (getaddrinfo(s, "0", &hints, &res) != 0) {
|
|
|
|
hints.ai_flags = 0;
|
2003-06-11 19:45:20 +04:00
|
|
|
if (slash) {
|
|
|
|
*slash = '/';
|
|
|
|
slash = 0;
|
|
|
|
}
|
2005-05-13 01:10:49 +04:00
|
|
|
if (getaddrinfo(s, "0", &hints, &res) != 0)
|
2006-08-06 21:47:17 +04:00
|
|
|
errx(EXIT_FAILURE, "%s: bad value", s);
|
2002-06-11 01:18:53 +04:00
|
|
|
}
|
2003-06-11 19:45:20 +04:00
|
|
|
if (slash)
|
|
|
|
*slash = '/';
|
2005-05-13 01:10:49 +04:00
|
|
|
if (sizeof(su->sin6) != res->ai_addrlen)
|
2006-08-06 21:47:17 +04:00
|
|
|
errx(EXIT_FAILURE, "%s: bad value", s);
|
|
|
|
if (res->ai_next) {
|
|
|
|
errx(EXIT_FAILURE,
|
|
|
|
"%s: address resolved to multiple values", s);
|
|
|
|
}
|
2000-04-20 16:08:50 +04:00
|
|
|
memcpy(&su->sin6, res->ai_addr, sizeof(su->sin6));
|
2002-06-11 01:18:53 +04:00
|
|
|
freeaddrinfo(res);
|
2013-10-19 19:59:15 +04:00
|
|
|
inet6_putscopeid(&su->sin6, INET6_IS_ADDR_LINKLOCAL|
|
2013-10-19 19:50:26 +04:00
|
|
|
INET6_IS_ADDR_MC_LINKLOCAL);
|
2002-06-11 01:18:53 +04:00
|
|
|
if (hints.ai_flags == AI_NUMERICHOST) {
|
2003-06-11 19:45:20 +04:00
|
|
|
if (slash)
|
2008-09-10 05:56:22 +04:00
|
|
|
return prefixlen(slash + 1, soup);
|
2002-06-11 01:18:53 +04:00
|
|
|
if (which == RTA_DST)
|
2008-09-10 05:56:22 +04:00
|
|
|
return inet6_makenetandmask(&su->sin6, soup);
|
2008-09-09 20:50:52 +04:00
|
|
|
return 0;
|
2002-06-11 01:18:53 +04:00
|
|
|
} else
|
2008-09-09 20:50:52 +04:00
|
|
|
return 1;
|
2000-04-20 16:08:50 +04:00
|
|
|
}
|
1999-07-02 19:29:02 +04:00
|
|
|
#endif
|
|
|
|
|
1994-05-13 12:02:16 +04:00
|
|
|
case PF_ROUTE:
|
|
|
|
su->sa.sa_len = sizeof(*su);
|
|
|
|
sockaddr(s, &su->sa);
|
2008-09-09 20:50:52 +04:00
|
|
|
return 1;
|
1994-05-13 12:02:16 +04:00
|
|
|
|
2003-06-11 19:45:20 +04:00
|
|
|
#ifndef SMALL
|
1997-04-03 06:35:46 +04:00
|
|
|
case AF_APPLETALK:
|
|
|
|
t = strchr (s, '.');
|
|
|
|
if (!t) {
|
|
|
|
badataddr:
|
2006-08-06 21:47:17 +04:00
|
|
|
errx(EXIT_FAILURE, "bad address: %s", s);
|
1997-04-03 06:35:46 +04:00
|
|
|
}
|
|
|
|
val = atoi (s);
|
|
|
|
if (val > 65535)
|
|
|
|
goto badataddr;
|
|
|
|
su->sat.sat_addr.s_net = val;
|
|
|
|
val = atoi (t);
|
|
|
|
if (val > 256)
|
|
|
|
goto badataddr;
|
|
|
|
su->sat.sat_addr.s_node = val;
|
|
|
|
rtm_addrs |= RTA_NETMASK;
|
|
|
|
return(forcehost || su->sat.sat_addr.s_node != 0);
|
2010-06-26 18:29:36 +04:00
|
|
|
case AF_MPLS:
|
2011-06-21 18:33:14 +04:00
|
|
|
if (which == RTA_DST)
|
|
|
|
soup->so_dst = readtag(su, s);
|
|
|
|
else if (which == RTA_TAG)
|
|
|
|
soup->so_mpls = readtag(su, s);
|
|
|
|
else
|
|
|
|
errx(EXIT_FAILURE, "MPLS can be used only as "
|
|
|
|
"DST or TAG");
|
2010-06-26 18:29:36 +04:00
|
|
|
return 1;
|
2003-06-11 19:45:20 +04:00
|
|
|
#endif
|
1997-04-03 06:35:46 +04:00
|
|
|
|
1996-11-15 21:01:36 +03:00
|
|
|
case AF_LINK:
|
|
|
|
link_addr(s, &su->sdl);
|
2008-09-09 20:50:52 +04:00
|
|
|
return 1;
|
1996-11-15 21:01:36 +03:00
|
|
|
|
1994-05-13 12:02:16 +04:00
|
|
|
case AF_INET:
|
|
|
|
default:
|
|
|
|
break;
|
1993-03-21 12:45:37 +03:00
|
|
|
}
|
1994-05-13 12:02:16 +04:00
|
|
|
|
1993-03-21 12:45:37 +03:00
|
|
|
if (hpp == NULL)
|
|
|
|
hpp = &hp;
|
|
|
|
*hpp = NULL;
|
2003-06-03 08:41:42 +04:00
|
|
|
|
|
|
|
if ((t = strchr(s, '/')) != NULL && which == RTA_DST) {
|
|
|
|
*t = '\0';
|
2005-05-13 01:10:49 +04:00
|
|
|
if (forcenet == 0) {
|
|
|
|
if ((val = inet_addr(s)) != INADDR_NONE) {
|
2008-09-10 05:56:22 +04:00
|
|
|
inet_makenetandmask(htonl(val), &su->sin, soup);
|
|
|
|
return prefixlen(&t[1], soup);
|
2005-05-13 01:10:49 +04:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if ((val = inet_network(s)) != INADDR_NONE) {
|
2008-09-10 05:56:22 +04:00
|
|
|
inet_makenetandmask(val, &su->sin, soup);
|
|
|
|
return prefixlen(&t[1], soup);
|
2005-05-13 01:10:49 +04:00
|
|
|
}
|
2003-06-03 08:41:42 +04:00
|
|
|
}
|
|
|
|
*t = '/';
|
|
|
|
}
|
2005-05-19 19:05:11 +04:00
|
|
|
if (inet_aton(s, &su->sin.sin_addr) &&
|
1993-03-21 12:45:37 +03:00
|
|
|
(which != RTA_DST || forcenet == 0)) {
|
2005-05-19 19:05:11 +04:00
|
|
|
val = su->sin.sin_addr.s_addr;
|
1993-03-21 12:45:37 +03:00
|
|
|
if (inet_lnaof(su->sin.sin_addr) != INADDR_ANY)
|
2008-09-09 20:50:52 +04:00
|
|
|
return 1;
|
1993-03-21 12:45:37 +03:00
|
|
|
else {
|
|
|
|
val = ntohl(val);
|
1994-05-13 12:02:16 +04:00
|
|
|
goto netdone;
|
1993-03-21 12:45:37 +03:00
|
|
|
}
|
|
|
|
}
|
1996-04-15 22:27:05 +04:00
|
|
|
if ((val = inet_network(s)) != INADDR_NONE ||
|
1994-05-13 12:02:16 +04:00
|
|
|
((np = getnetbyname(s)) != NULL && (val = np->n_net) != 0)) {
|
|
|
|
netdone:
|
|
|
|
if (which == RTA_DST)
|
2008-09-10 05:56:22 +04:00
|
|
|
inet_makenetandmask(val, &su->sin, soup);
|
2008-09-09 20:50:52 +04:00
|
|
|
return 0;
|
1993-03-21 12:45:37 +03:00
|
|
|
}
|
|
|
|
hp = gethostbyname(s);
|
|
|
|
if (hp) {
|
|
|
|
*hpp = hp;
|
|
|
|
su->sin.sin_family = hp->h_addrtype;
|
1997-09-16 11:04:17 +04:00
|
|
|
memmove(&su->sin.sin_addr, hp->h_addr, hp->h_length);
|
2008-09-09 20:50:52 +04:00
|
|
|
return 1;
|
1993-03-21 12:45:37 +03:00
|
|
|
}
|
2006-08-06 21:47:17 +04:00
|
|
|
errx(EXIT_FAILURE, "%s: bad value", s);
|
2005-08-13 01:23:06 +04:00
|
|
|
/*NOTREACHED*/
|
1994-05-13 12:02:16 +04:00
|
|
|
}
|
|
|
|
|
2011-06-22 08:57:28 +04:00
|
|
|
#ifndef SMALL
|
2011-06-21 18:33:14 +04:00
|
|
|
static sup
|
|
|
|
readtag(sup su, const char *s)
|
|
|
|
{
|
|
|
|
char *p, *n, *norig;
|
|
|
|
int mplssize = 0;
|
|
|
|
sup retsu = su;
|
|
|
|
|
2011-10-07 13:56:15 +04:00
|
|
|
n = strdup(s);
|
2011-06-21 18:33:14 +04:00
|
|
|
if (n == NULL)
|
|
|
|
errx(EXIT_FAILURE, "%s: Cannot allocate memory", s);
|
|
|
|
norig = n;
|
|
|
|
for (uint i = 0; i < strlen(n); i++)
|
|
|
|
if(n[i] == ',')
|
|
|
|
mplssize++;
|
|
|
|
|
|
|
|
#define MPLS_NEW_SIZE (sizeof(struct sockaddr_mpls) + \
|
|
|
|
mplssize * sizeof(union mpls_shim))
|
|
|
|
|
|
|
|
if (mplssize != 0 && sizeof(union sockunion) < MPLS_NEW_SIZE) {
|
|
|
|
free(su);
|
|
|
|
retsu = malloc(MPLS_NEW_SIZE);
|
|
|
|
retsu->smpls.smpls_family = AF_MPLS;
|
|
|
|
}
|
|
|
|
retsu->smpls.smpls_len = MPLS_NEW_SIZE;
|
|
|
|
mplssize = 0;
|
|
|
|
while ((p = strchr(n, ',')) != NULL) {
|
|
|
|
p[0] = '\0';
|
|
|
|
addtag(retsu, n, mplssize);
|
|
|
|
n = p + 1;
|
|
|
|
mplssize++;
|
|
|
|
}
|
|
|
|
addtag(retsu, n, mplssize);
|
|
|
|
|
|
|
|
free(norig);
|
|
|
|
return retsu;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
addtag(sup su, const char *s, int where)
|
|
|
|
{
|
|
|
|
union mpls_shim *ms = &su->smpls.smpls_addr;
|
|
|
|
|
|
|
|
if (atoi(s) < 0 || atoi(s) >= (1 << 20))
|
|
|
|
errx(EXIT_FAILURE, "%s: Bad tag", s);
|
|
|
|
ms[where].s_addr = 0;
|
|
|
|
ms[where].shim.label = atoi(s);
|
|
|
|
ms[where].s_addr = htonl(ms[where].s_addr);
|
|
|
|
}
|
2011-06-22 08:57:28 +04:00
|
|
|
#endif /* SMALL */
|
2011-06-21 18:33:14 +04:00
|
|
|
|
1999-07-02 19:29:02 +04:00
|
|
|
int
|
2008-09-10 05:56:22 +04:00
|
|
|
prefixlen(const char *s, struct sou *soup)
|
1999-07-02 19:29:02 +04:00
|
|
|
{
|
2014-12-20 16:15:48 +03:00
|
|
|
int max, len = atoi(s);
|
|
|
|
#ifdef INET6
|
|
|
|
int q, r;
|
|
|
|
#endif
|
2001-07-20 12:28:25 +04:00
|
|
|
|
|
|
|
switch (af) {
|
|
|
|
case AF_INET:
|
|
|
|
max = sizeof(struct in_addr) * 8;
|
|
|
|
break;
|
|
|
|
#ifdef INET6
|
|
|
|
case AF_INET6:
|
|
|
|
max = sizeof(struct in6_addr) * 8;
|
|
|
|
break;
|
|
|
|
#endif
|
|
|
|
default:
|
2006-08-06 21:47:17 +04:00
|
|
|
errx(EXIT_FAILURE, "prefixlen is not supported with af %d", af);
|
2005-08-30 23:01:25 +04:00
|
|
|
/*NOTREACHED*/
|
2001-07-20 12:28:25 +04:00
|
|
|
}
|
1999-07-02 19:29:02 +04:00
|
|
|
|
|
|
|
rtm_addrs |= RTA_NETMASK;
|
2005-05-13 01:10:49 +04:00
|
|
|
if (len < -1 || len > max)
|
2006-08-06 21:47:17 +04:00
|
|
|
errx(EXIT_FAILURE, "%s: bad value", s);
|
1999-07-02 19:29:02 +04:00
|
|
|
|
2014-12-20 16:15:48 +03:00
|
|
|
#ifdef INET6
|
1999-07-02 19:29:02 +04:00
|
|
|
q = len >> 3;
|
|
|
|
r = len & 7;
|
2014-12-20 16:15:48 +03:00
|
|
|
#endif
|
2001-07-20 12:28:25 +04:00
|
|
|
switch (af) {
|
|
|
|
case AF_INET:
|
2011-07-01 06:46:24 +04:00
|
|
|
memset(soup->so_mask, 0, sizeof(*soup->so_mask));
|
2011-06-21 18:33:14 +04:00
|
|
|
soup->so_mask->sin.sin_family = AF_INET;
|
|
|
|
soup->so_mask->sin.sin_len = sizeof(struct sockaddr_in);
|
|
|
|
soup->so_mask->sin.sin_addr.s_addr = (len == 0 ? 0
|
2006-11-12 00:50:19 +03:00
|
|
|
: htonl(0xffffffff << (32 - len)));
|
2001-07-20 12:28:25 +04:00
|
|
|
break;
|
|
|
|
#ifdef INET6
|
|
|
|
case AF_INET6:
|
2011-06-21 18:33:14 +04:00
|
|
|
soup->so_mask->sin6.sin6_family = AF_INET6;
|
|
|
|
soup->so_mask->sin6.sin6_len = sizeof(struct sockaddr_in6);
|
|
|
|
memset(&soup->so_mask->sin6.sin6_addr, 0,
|
|
|
|
sizeof(soup->so_mask->sin6.sin6_addr));
|
2001-07-20 12:28:25 +04:00
|
|
|
if (q > 0)
|
2011-06-21 18:33:14 +04:00
|
|
|
memset(&soup->so_mask->sin6.sin6_addr, 0xff, q);
|
2001-07-20 12:28:25 +04:00
|
|
|
if (r > 0)
|
2011-06-21 18:33:14 +04:00
|
|
|
*((u_char *)&soup->so_mask->sin6.sin6_addr + q) =
|
2001-07-20 12:28:25 +04:00
|
|
|
(0xff00 >> r) & 0xff;
|
|
|
|
break;
|
|
|
|
#endif
|
|
|
|
}
|
2008-09-09 20:50:52 +04:00
|
|
|
return len == max;
|
1999-07-02 19:29:02 +04:00
|
|
|
}
|
|
|
|
|
2000-05-04 22:29:34 +04:00
|
|
|
#ifndef SMALL
|
1997-04-03 06:35:46 +04:00
|
|
|
static void
|
2005-02-05 17:05:23 +03:00
|
|
|
interfaces(void)
|
1994-05-13 12:02:16 +04:00
|
|
|
{
|
|
|
|
size_t needed;
|
|
|
|
int mib[6];
|
|
|
|
char *buf, *lim, *next;
|
1997-09-15 13:15:26 +04:00
|
|
|
struct rt_msghdr *rtm;
|
1994-05-13 12:02:16 +04:00
|
|
|
|
|
|
|
mib[0] = CTL_NET;
|
|
|
|
mib[1] = PF_ROUTE;
|
|
|
|
mib[2] = 0; /* protocol */
|
|
|
|
mib[3] = 0; /* wildcard address family */
|
|
|
|
mib[4] = NET_RT_IFLIST;
|
|
|
|
mib[5] = 0; /* no flags */
|
2010-12-13 20:39:47 +03:00
|
|
|
if (prog_sysctl(mib, 6, NULL, &needed, NULL, 0) < 0)
|
2006-08-06 21:47:17 +04:00
|
|
|
err(EXIT_FAILURE, "route-sysctl-estimate");
|
2005-08-30 23:01:25 +04:00
|
|
|
if (needed) {
|
|
|
|
if ((buf = malloc(needed)) == NULL)
|
2006-08-06 21:47:17 +04:00
|
|
|
err(EXIT_FAILURE, "malloc");
|
2010-12-13 20:39:47 +03:00
|
|
|
if (prog_sysctl(mib, 6, buf, &needed, NULL, 0) < 0) {
|
2006-08-06 21:47:17 +04:00
|
|
|
err(EXIT_FAILURE,
|
|
|
|
"actual retrieval of interface table");
|
|
|
|
}
|
2005-08-30 23:01:25 +04:00
|
|
|
lim = buf + needed;
|
|
|
|
for (next = buf; next < lim; next += rtm->rtm_msglen) {
|
|
|
|
rtm = (struct rt_msghdr *)next;
|
|
|
|
print_rtmsg(rtm, rtm->rtm_msglen);
|
|
|
|
}
|
|
|
|
free(buf);
|
1994-05-13 12:02:16 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1997-04-03 06:35:46 +04:00
|
|
|
static void
|
2005-02-05 17:05:23 +03:00
|
|
|
monitor(void)
|
1993-03-21 12:45:37 +03:00
|
|
|
{
|
|
|
|
int n;
|
2008-09-09 20:23:33 +04:00
|
|
|
union {
|
|
|
|
char msg[2048];
|
|
|
|
struct rt_msghdr hdr;
|
|
|
|
} u;
|
1993-03-21 12:45:37 +03:00
|
|
|
|
|
|
|
verbose = 1;
|
1994-05-13 12:02:16 +04:00
|
|
|
if (debugonly) {
|
|
|
|
interfaces();
|
|
|
|
exit(0);
|
|
|
|
}
|
1993-03-21 12:45:37 +03:00
|
|
|
for(;;) {
|
1999-07-07 03:15:48 +04:00
|
|
|
time_t now;
|
2010-12-13 20:39:47 +03:00
|
|
|
n = prog_read(sock, &u, sizeof(u));
|
1999-07-02 19:29:02 +04:00
|
|
|
now = time(NULL);
|
2005-08-09 23:43:24 +04:00
|
|
|
(void)printf("got message of size %d on %s", n, ctime(&now));
|
2008-09-09 20:23:33 +04:00
|
|
|
print_rtmsg(&u.hdr, n);
|
1993-03-21 12:45:37 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1996-11-15 21:01:36 +03:00
|
|
|
#endif /* SMALL */
|
|
|
|
|
|
|
|
|
1993-03-21 12:45:37 +03:00
|
|
|
struct {
|
|
|
|
struct rt_msghdr m_rtm;
|
|
|
|
char m_space[512];
|
|
|
|
} m_rtmsg;
|
|
|
|
|
1997-04-03 06:35:46 +04:00
|
|
|
static int
|
2008-09-10 05:56:22 +04:00
|
|
|
rtmsg(int cmd, int flags, struct sou *soup)
|
1993-03-21 12:45:37 +03:00
|
|
|
{
|
|
|
|
static int seq;
|
|
|
|
int rlen;
|
1997-09-15 13:15:26 +04:00
|
|
|
char *cp = m_rtmsg.m_space;
|
|
|
|
int l;
|
1993-03-21 12:45:37 +03:00
|
|
|
|
|
|
|
#define NEXTADDR(w, u) \
|
|
|
|
if (rtm_addrs & (w)) {\
|
2011-06-21 18:33:14 +04:00
|
|
|
l = RT_ROUNDUP(u->sa.sa_len); memmove(cp, u, l); cp += l;\
|
|
|
|
if (verbose && ! shortoutput) sodump(u,#u);\
|
1993-03-21 12:45:37 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
errno = 0;
|
1994-09-23 18:26:58 +04:00
|
|
|
memset(&m_rtmsg, 0, sizeof(m_rtmsg));
|
1993-03-21 12:45:37 +03:00
|
|
|
if (cmd == 'a')
|
|
|
|
cmd = RTM_ADD;
|
|
|
|
else if (cmd == 'c')
|
|
|
|
cmd = RTM_CHANGE;
|
1994-05-13 12:02:16 +04:00
|
|
|
else if (cmd == 'g') {
|
1996-11-15 21:01:36 +03:00
|
|
|
#ifdef SMALL
|
2008-09-09 20:50:52 +04:00
|
|
|
return -1;
|
1996-11-15 21:01:36 +03:00
|
|
|
#else /* SMALL */
|
1993-03-21 12:45:37 +03:00
|
|
|
cmd = RTM_GET;
|
2011-06-21 18:33:14 +04:00
|
|
|
if (soup->so_ifp->sa.sa_family == AF_UNSPEC) {
|
|
|
|
soup->so_ifp->sa.sa_family = AF_LINK;
|
|
|
|
soup->so_ifp->sa.sa_len = sizeof(struct sockaddr_dl);
|
1994-05-13 12:02:16 +04:00
|
|
|
rtm_addrs |= RTA_IFP;
|
|
|
|
}
|
1996-11-15 21:01:36 +03:00
|
|
|
#endif /* SMALL */
|
1994-05-13 12:02:16 +04:00
|
|
|
} else
|
1993-03-21 12:45:37 +03:00
|
|
|
cmd = RTM_DELETE;
|
|
|
|
#define rtm m_rtmsg.m_rtm
|
|
|
|
rtm.rtm_type = cmd;
|
|
|
|
rtm.rtm_flags = flags;
|
|
|
|
rtm.rtm_version = RTM_VERSION;
|
|
|
|
rtm.rtm_seq = ++seq;
|
|
|
|
rtm.rtm_addrs = rtm_addrs;
|
|
|
|
rtm.rtm_rmx = rt_metrics;
|
|
|
|
rtm.rtm_inits = rtm_inits;
|
|
|
|
|
|
|
|
if (rtm_addrs & RTA_NETMASK)
|
2008-09-10 05:56:22 +04:00
|
|
|
mask_addr(soup);
|
|
|
|
NEXTADDR(RTA_DST, soup->so_dst);
|
|
|
|
NEXTADDR(RTA_GATEWAY, soup->so_gate);
|
|
|
|
NEXTADDR(RTA_NETMASK, soup->so_mask);
|
|
|
|
NEXTADDR(RTA_GENMASK, soup->so_genmask);
|
|
|
|
NEXTADDR(RTA_IFP, soup->so_ifp);
|
|
|
|
NEXTADDR(RTA_IFA, soup->so_ifa);
|
2010-11-05 02:37:27 +03:00
|
|
|
#ifndef SMALL
|
2010-06-26 18:29:36 +04:00
|
|
|
NEXTADDR(RTA_TAG, soup->so_mpls);
|
2010-11-05 02:37:27 +03:00
|
|
|
#endif
|
1993-03-21 12:45:37 +03:00
|
|
|
rtm.rtm_msglen = l = cp - (char *)&m_rtmsg;
|
2005-08-13 01:23:06 +04:00
|
|
|
if (verbose && ! shortoutput) {
|
|
|
|
if (rtm_addrs)
|
|
|
|
putchar('\n');
|
1993-03-21 12:45:37 +03:00
|
|
|
print_rtmsg(&rtm, l);
|
2005-08-13 01:23:06 +04:00
|
|
|
}
|
1993-03-21 12:45:37 +03:00
|
|
|
if (debugonly)
|
2008-09-09 20:50:52 +04:00
|
|
|
return 0;
|
2010-12-13 20:39:47 +03:00
|
|
|
if ((rlen = prog_write(sock, (char *)&m_rtmsg, l)) < 0) {
|
2005-08-13 01:23:06 +04:00
|
|
|
warnx("writing to routing socket: %s", route_strerror(errno));
|
2008-09-09 20:50:52 +04:00
|
|
|
return -1;
|
1993-03-21 12:45:37 +03:00
|
|
|
}
|
2005-08-13 01:23:06 +04:00
|
|
|
if (rlen < l) {
|
|
|
|
warnx("write to routing socket, got %d for rlen", rlen);
|
|
|
|
return 1;
|
|
|
|
}
|
1996-11-15 21:01:36 +03:00
|
|
|
#ifndef SMALL
|
1993-03-21 12:45:37 +03:00
|
|
|
if (cmd == RTM_GET) {
|
|
|
|
do {
|
2010-12-13 20:39:47 +03:00
|
|
|
l = prog_read(sock,
|
|
|
|
(char *)&m_rtmsg, sizeof(m_rtmsg));
|
1993-03-21 12:45:37 +03:00
|
|
|
} while (l > 0 && (rtm.rtm_seq != seq || rtm.rtm_pid != pid));
|
|
|
|
if (l < 0)
|
2006-08-06 21:47:17 +04:00
|
|
|
err(EXIT_FAILURE, "read from routing socket");
|
1993-03-21 12:45:37 +03:00
|
|
|
else
|
2008-09-10 05:56:22 +04:00
|
|
|
return print_getmsg(&rtm, l, soup);
|
1993-03-21 12:45:37 +03:00
|
|
|
}
|
1996-11-15 21:01:36 +03:00
|
|
|
#endif /* SMALL */
|
1993-03-21 12:45:37 +03:00
|
|
|
#undef rtm
|
2008-09-09 20:50:52 +04:00
|
|
|
return 0;
|
1993-03-21 12:45:37 +03:00
|
|
|
}
|
|
|
|
|
1997-04-03 06:35:46 +04:00
|
|
|
static void
|
2008-09-10 05:56:22 +04:00
|
|
|
mask_addr(struct sou *soup)
|
1994-05-13 12:02:16 +04:00
|
|
|
{
|
2011-06-21 18:33:14 +04:00
|
|
|
int olen = soup->so_mask->sa.sa_len;
|
2012-10-04 04:01:48 +04:00
|
|
|
char *cp1 = olen + (char *)soup->so_mask, *cp2;
|
1993-03-21 12:45:37 +03:00
|
|
|
|
2012-10-04 04:01:48 +04:00
|
|
|
for (soup->so_mask->sa.sa_len = 0; cp1 > (char *)soup->so_mask; )
|
1994-05-13 12:02:16 +04:00
|
|
|
if (*--cp1 != 0) {
|
2012-10-04 04:01:48 +04:00
|
|
|
soup->so_mask->sa.sa_len = 1 + cp1 - (char *)soup->so_mask;
|
1994-05-13 12:02:16 +04:00
|
|
|
break;
|
|
|
|
}
|
1993-03-21 12:45:37 +03:00
|
|
|
if ((rtm_addrs & RTA_DST) == 0)
|
|
|
|
return;
|
2011-06-21 18:33:14 +04:00
|
|
|
switch (soup->so_dst->sa.sa_family) {
|
1994-05-13 12:02:16 +04:00
|
|
|
case AF_INET:
|
1999-07-02 19:29:02 +04:00
|
|
|
#ifdef INET6
|
|
|
|
case AF_INET6:
|
|
|
|
#endif
|
1998-10-23 09:36:42 +04:00
|
|
|
#ifndef SMALL
|
2003-06-11 19:45:20 +04:00
|
|
|
case AF_APPLETALK:
|
1998-10-23 09:36:42 +04:00
|
|
|
#endif /* SMALL */
|
1994-05-13 12:02:16 +04:00
|
|
|
case 0:
|
1993-03-21 12:45:37 +03:00
|
|
|
return;
|
|
|
|
}
|
2012-10-04 04:01:48 +04:00
|
|
|
cp1 = soup->so_mask->sa.sa_len + 1 + (char *)soup->so_dst;
|
|
|
|
cp2 = soup->so_dst->sa.sa_len + 1 + (char *)soup->so_dst;
|
1993-03-21 12:45:37 +03:00
|
|
|
while (cp2 > cp1)
|
|
|
|
*--cp2 = 0;
|
2012-10-04 04:01:48 +04:00
|
|
|
cp2 = soup->so_mask->sa.sa_len + 1 + (char *)soup->so_mask;
|
2011-06-21 18:33:14 +04:00
|
|
|
while (cp1 > soup->so_dst->sa.sa_data)
|
1993-03-21 12:45:37 +03:00
|
|
|
*--cp1 &= *--cp2;
|
|
|
|
}
|
|
|
|
|
2011-02-01 04:39:19 +03:00
|
|
|
const char * const msgtypes[] = {
|
|
|
|
[RTM_ADD] = "RTM_ADD: Add Route",
|
|
|
|
[RTM_DELETE] = "RTM_DELETE: Delete Route",
|
2014-12-17 13:56:09 +03:00
|
|
|
[RTM_CHANGE] = "RTM_CHANGE: Change Metrics, Flags or Gateway",
|
2011-02-01 04:39:19 +03:00
|
|
|
[RTM_GET] = "RTM_GET: Report Metrics",
|
|
|
|
[RTM_LOSING] = "RTM_LOSING: Kernel Suspects Partitioning",
|
|
|
|
[RTM_REDIRECT] = "RTM_REDIRECT: Told to use different route",
|
|
|
|
[RTM_MISS] = "RTM_MISS: Lookup failed on this address",
|
|
|
|
[RTM_LOCK] = "RTM_LOCK: fix specified metrics",
|
|
|
|
[RTM_OLDADD] = "RTM_OLDADD: caused by SIOCADDRT",
|
|
|
|
[RTM_OLDDEL] = "RTM_OLDDEL: caused by SIOCDELRT",
|
|
|
|
[RTM_NEWADDR] = "RTM_NEWADDR: address being added to iface",
|
|
|
|
[RTM_DELADDR] = "RTM_DELADDR: address being removed from iface",
|
|
|
|
[RTM_OOIFINFO] = "RTM_OOIFINFO: iface status change (pre-1.5)",
|
|
|
|
[RTM_OIFINFO] = "RTM_OIFINFO: iface status change (pre-64bit time)",
|
|
|
|
[RTM_IFANNOUNCE] = "RTM_IFANNOUNCE: iface arrival/departure",
|
|
|
|
[RTM_IEEE80211] = "RTM_IEEE80211: IEEE80211 wireless event",
|
|
|
|
[RTM_IFINFO] = "RTM_IFINFO: iface status change",
|
|
|
|
[RTM_CHGADDR] = "RTM_CHGADDR: address being changed on iface",
|
1993-03-21 12:45:37 +03:00
|
|
|
};
|
|
|
|
|
2006-01-25 19:19:50 +03:00
|
|
|
const char metricnames[] =
|
1994-05-13 12:02:16 +04:00
|
|
|
"\011pksent\010rttvar\7rtt\6ssthresh\5sendpipe\4recvpipe\3expire\2hopcount\1mtu";
|
2006-01-25 19:19:50 +03:00
|
|
|
const char routeflags[] =
|
2016-04-04 10:37:07 +03:00
|
|
|
"\1UP\2GATEWAY\3HOST\4REJECT\5DYNAMIC\6MODIFIED\7DONE\010MASK_PRESENT\011CONNECTED\012XRESOLVE\013LLINFO\014STATIC\015BLACKHOLE\016CLONED\017PROTO2\020PROTO1\023LOCAL\024BROADCAST";
|
2006-01-25 19:19:50 +03:00
|
|
|
const char ifnetflags[] =
|
1994-05-13 12:02:16 +04:00
|
|
|
"\1UP\2BROADCAST\3DEBUG\4LOOPBACK\5PTP\6NOTRAILERS\7RUNNING\010NOARP\011PPROMISC\012ALLMULTI\013OACTIVE\014SIMPLEX\015LINK0\016LINK1\017LINK2\020MULTICAST";
|
2006-01-25 19:19:50 +03:00
|
|
|
const char addrnames[] =
|
2010-06-26 18:29:36 +04:00
|
|
|
"\1DST\2GATEWAY\3NETMASK\4GENMASK\5IFP\6IFA\7AUTHOR\010BRD\011TAG";
|
1993-03-21 12:45:37 +03:00
|
|
|
|
2002-02-21 18:44:25 +03:00
|
|
|
|
|
|
|
#ifndef SMALL
|
|
|
|
static const char *
|
2005-02-05 17:05:23 +03:00
|
|
|
linkstate(struct if_msghdr *ifm)
|
2002-02-21 18:44:25 +03:00
|
|
|
{
|
|
|
|
static char buf[64];
|
|
|
|
|
|
|
|
switch (ifm->ifm_data.ifi_link_state) {
|
|
|
|
case LINK_STATE_UNKNOWN:
|
|
|
|
return "carrier: unknown";
|
|
|
|
case LINK_STATE_DOWN:
|
|
|
|
return "carrier: no carrier";
|
|
|
|
case LINK_STATE_UP:
|
|
|
|
return "carrier: active";
|
|
|
|
default:
|
|
|
|
(void)snprintf(buf, sizeof(buf), "carrier: 0x%x",
|
|
|
|
ifm->ifm_data.ifi_link_state);
|
|
|
|
return buf;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif /* SMALL */
|
|
|
|
|
1997-04-03 06:35:46 +04:00
|
|
|
static void
|
2005-02-05 17:05:23 +03:00
|
|
|
print_rtmsg(struct rt_msghdr *rtm, int msglen)
|
1993-03-21 12:45:37 +03:00
|
|
|
{
|
1994-05-13 12:02:16 +04:00
|
|
|
struct if_msghdr *ifm;
|
|
|
|
struct ifa_msghdr *ifam;
|
2000-10-10 13:35:05 +04:00
|
|
|
struct if_announcemsghdr *ifan;
|
2005-06-25 10:38:35 +04:00
|
|
|
union {
|
|
|
|
struct ieee80211_join_event join;
|
|
|
|
struct ieee80211_leave_event leave;
|
|
|
|
struct ieee80211_replay_event replay;
|
|
|
|
struct ieee80211_michael_event michael;
|
|
|
|
} ev;
|
|
|
|
size_t evlen = 0;
|
1994-05-13 12:02:16 +04:00
|
|
|
|
1993-03-21 12:45:37 +03:00
|
|
|
if (verbose == 0)
|
|
|
|
return;
|
|
|
|
if (rtm->rtm_version != RTM_VERSION) {
|
2005-08-09 23:43:24 +04:00
|
|
|
(void)printf("routing message version %d not understood\n",
|
1993-03-21 12:45:37 +03:00
|
|
|
rtm->rtm_version);
|
|
|
|
return;
|
|
|
|
}
|
2000-10-10 13:35:05 +04:00
|
|
|
if (msgtypes[rtm->rtm_type])
|
|
|
|
(void)printf("%s: ", msgtypes[rtm->rtm_type]);
|
|
|
|
else
|
|
|
|
(void)printf("#%d: ", rtm->rtm_type);
|
|
|
|
(void)printf("len %d, ", rtm->rtm_msglen);
|
1994-05-13 12:02:16 +04:00
|
|
|
switch (rtm->rtm_type) {
|
|
|
|
case RTM_IFINFO:
|
|
|
|
ifm = (struct if_msghdr *)rtm;
|
2005-08-15 23:28:08 +04:00
|
|
|
(void)printf("if# %d, %s, flags: ", ifm->ifm_index,
|
2002-02-21 18:44:25 +03:00
|
|
|
#ifdef SMALL
|
|
|
|
""
|
|
|
|
#else
|
|
|
|
linkstate(ifm)
|
|
|
|
#endif /* SMALL */
|
|
|
|
);
|
1994-05-13 12:02:16 +04:00
|
|
|
bprintf(stdout, ifm->ifm_flags, ifnetflags);
|
|
|
|
pmsg_addrs((char *)(ifm + 1), ifm->ifm_addrs);
|
|
|
|
break;
|
|
|
|
case RTM_NEWADDR:
|
|
|
|
case RTM_DELADDR:
|
2010-11-12 19:32:18 +03:00
|
|
|
case RTM_CHGADDR:
|
1994-05-13 12:02:16 +04:00
|
|
|
ifam = (struct ifa_msghdr *)rtm;
|
2017-03-17 19:13:44 +03:00
|
|
|
(void)printf("pid %d, metric %d, flags: ",
|
|
|
|
ifam->ifam_pid, ifam->ifam_metric);
|
1994-05-13 12:02:16 +04:00
|
|
|
bprintf(stdout, ifam->ifam_flags, routeflags);
|
|
|
|
pmsg_addrs((char *)(ifam + 1), ifam->ifam_addrs);
|
|
|
|
break;
|
2005-06-25 10:38:35 +04:00
|
|
|
case RTM_IEEE80211:
|
|
|
|
ifan = (struct if_announcemsghdr *)rtm;
|
2005-08-09 23:43:24 +04:00
|
|
|
(void)printf("if# %d, what: ", ifan->ifan_index);
|
2005-06-25 10:38:35 +04:00
|
|
|
switch (ifan->ifan_what) {
|
|
|
|
case RTM_IEEE80211_ASSOC:
|
|
|
|
printf("associate");
|
|
|
|
break;
|
|
|
|
case RTM_IEEE80211_REASSOC:
|
|
|
|
printf("re-associate");
|
|
|
|
break;
|
|
|
|
case RTM_IEEE80211_DISASSOC:
|
|
|
|
printf("disassociate");
|
|
|
|
break;
|
|
|
|
case RTM_IEEE80211_SCAN:
|
|
|
|
printf("scan complete");
|
|
|
|
break;
|
|
|
|
case RTM_IEEE80211_JOIN:
|
|
|
|
evlen = sizeof(ev.join);
|
|
|
|
printf("join");
|
|
|
|
break;
|
|
|
|
case RTM_IEEE80211_LEAVE:
|
|
|
|
evlen = sizeof(ev.leave);
|
|
|
|
printf("leave");
|
|
|
|
break;
|
|
|
|
case RTM_IEEE80211_MICHAEL:
|
|
|
|
evlen = sizeof(ev.michael);
|
|
|
|
printf("michael");
|
|
|
|
break;
|
|
|
|
case RTM_IEEE80211_REPLAY:
|
|
|
|
evlen = sizeof(ev.replay);
|
|
|
|
printf("replay");
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
evlen = 0;
|
|
|
|
printf("#%d", ifan->ifan_what);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (sizeof(*ifan) + evlen > ifan->ifan_msglen) {
|
|
|
|
printf(" (truncated)\n");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
(void)memcpy(&ev, (ifan + 1), evlen);
|
|
|
|
switch (ifan->ifan_what) {
|
|
|
|
case RTM_IEEE80211_JOIN:
|
|
|
|
case RTM_IEEE80211_LEAVE:
|
|
|
|
printf(" mac %" PRIETHER,
|
|
|
|
PRIETHER_ARGS(ev.join.iev_addr));
|
|
|
|
break;
|
|
|
|
case RTM_IEEE80211_REPLAY:
|
|
|
|
case RTM_IEEE80211_MICHAEL:
|
|
|
|
printf(" src %" PRIETHER " dst %" PRIETHER
|
|
|
|
" cipher %" PRIu8 " keyix %" PRIu8,
|
|
|
|
PRIETHER_ARGS(ev.replay.iev_src),
|
|
|
|
PRIETHER_ARGS(ev.replay.iev_dst),
|
|
|
|
ev.replay.iev_cipher,
|
|
|
|
ev.replay.iev_keyix);
|
|
|
|
if (ifan->ifan_what == RTM_IEEE80211_REPLAY) {
|
|
|
|
printf(" key rsc %#" PRIx64
|
|
|
|
" frame rsc %#" PRIx64,
|
|
|
|
ev.replay.iev_keyrsc, ev.replay.iev_rsc);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
printf("\n");
|
|
|
|
break;
|
2000-10-10 13:35:05 +04:00
|
|
|
case RTM_IFANNOUNCE:
|
|
|
|
ifan = (struct if_announcemsghdr *)rtm;
|
2005-08-09 23:43:24 +04:00
|
|
|
(void)printf("if# %d, what: ", ifan->ifan_index);
|
2000-10-10 13:35:05 +04:00
|
|
|
switch (ifan->ifan_what) {
|
|
|
|
case IFAN_ARRIVAL:
|
|
|
|
printf("arrival");
|
|
|
|
break;
|
|
|
|
case IFAN_DEPARTURE:
|
|
|
|
printf("departure");
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
printf("#%d", ifan->ifan_what);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
printf("\n");
|
|
|
|
break;
|
1994-05-13 12:02:16 +04:00
|
|
|
default:
|
2005-08-15 23:28:08 +04:00
|
|
|
(void)printf("pid %d, seq %d, errno %d, flags: ",
|
1994-05-13 12:02:16 +04:00
|
|
|
rtm->rtm_pid, rtm->rtm_seq, rtm->rtm_errno);
|
|
|
|
bprintf(stdout, rtm->rtm_flags, routeflags);
|
|
|
|
pmsg_common(rtm);
|
|
|
|
}
|
1993-03-21 12:45:37 +03:00
|
|
|
}
|
|
|
|
|
1996-11-15 21:01:36 +03:00
|
|
|
#ifndef SMALL
|
2005-08-13 01:23:06 +04:00
|
|
|
static int
|
2008-09-10 05:56:22 +04:00
|
|
|
print_getmsg(struct rt_msghdr *rtm, int msglen, struct sou *soup)
|
1993-03-21 12:45:37 +03:00
|
|
|
{
|
2010-06-26 18:29:36 +04:00
|
|
|
struct sockaddr *dst = NULL, *gate = NULL, *mask = NULL, *ifa = NULL, *mpls = NULL;
|
1994-05-13 12:02:16 +04:00
|
|
|
struct sockaddr_dl *ifp = NULL;
|
1997-09-15 13:15:26 +04:00
|
|
|
struct sockaddr *sa;
|
|
|
|
char *cp;
|
|
|
|
int i;
|
1994-05-13 12:02:16 +04:00
|
|
|
|
2011-02-01 04:39:19 +03:00
|
|
|
if (! shortoutput) {
|
2005-08-09 23:43:24 +04:00
|
|
|
(void)printf(" route to: %s\n",
|
2014-11-07 00:29:32 +03:00
|
|
|
routename(&soup->so_dst->sa, nflag));
|
2011-02-01 04:39:19 +03:00
|
|
|
}
|
1993-03-21 12:45:37 +03:00
|
|
|
if (rtm->rtm_version != RTM_VERSION) {
|
1997-11-16 20:03:11 +03:00
|
|
|
warnx("routing message version %d not understood",
|
1993-03-21 12:45:37 +03:00
|
|
|
rtm->rtm_version);
|
2005-08-13 01:23:06 +04:00
|
|
|
return 1;
|
1993-03-21 12:45:37 +03:00
|
|
|
}
|
|
|
|
if (rtm->rtm_msglen > msglen) {
|
2002-07-20 12:36:17 +04:00
|
|
|
warnx("message length mismatch, in packet %d, returned %d",
|
1993-03-21 12:45:37 +03:00
|
|
|
rtm->rtm_msglen, msglen);
|
|
|
|
}
|
1994-05-13 12:02:16 +04:00
|
|
|
if (rtm->rtm_errno) {
|
2005-08-13 01:23:06 +04:00
|
|
|
warnx("RTM_GET: %s (errno %d)",
|
|
|
|
strerror(rtm->rtm_errno), rtm->rtm_errno);
|
|
|
|
return 1;
|
1994-05-13 12:02:16 +04:00
|
|
|
}
|
|
|
|
cp = ((char *)(rtm + 1));
|
|
|
|
if (rtm->rtm_addrs)
|
|
|
|
for (i = 1; i; i <<= 1)
|
|
|
|
if (i & rtm->rtm_addrs) {
|
|
|
|
sa = (struct sockaddr *)cp;
|
|
|
|
switch (i) {
|
|
|
|
case RTA_DST:
|
|
|
|
dst = sa;
|
|
|
|
break;
|
|
|
|
case RTA_GATEWAY:
|
|
|
|
gate = sa;
|
|
|
|
break;
|
|
|
|
case RTA_NETMASK:
|
|
|
|
mask = sa;
|
|
|
|
break;
|
|
|
|
case RTA_IFP:
|
|
|
|
if (sa->sa_family == AF_LINK &&
|
|
|
|
((struct sockaddr_dl *)sa)->sdl_nlen)
|
|
|
|
ifp = (struct sockaddr_dl *)sa;
|
|
|
|
break;
|
1999-11-01 16:32:38 +03:00
|
|
|
case RTA_IFA:
|
|
|
|
ifa = sa;
|
|
|
|
break;
|
2010-06-26 18:29:36 +04:00
|
|
|
case RTA_TAG:
|
|
|
|
mpls = sa;
|
|
|
|
break;
|
1994-05-13 12:02:16 +04:00
|
|
|
}
|
2011-02-01 04:39:19 +03:00
|
|
|
RT_ADVANCE(cp, sa);
|
1994-05-13 12:02:16 +04:00
|
|
|
}
|
|
|
|
if (dst && mask)
|
|
|
|
mask->sa_family = dst->sa_family; /* XXX */
|
2001-10-24 22:40:16 +04:00
|
|
|
if (dst && ! shortoutput)
|
2001-10-24 20:05:06 +04:00
|
|
|
(void)printf("destination: %s\n",
|
2014-11-07 00:29:32 +03:00
|
|
|
routename(dst, nflag));
|
2001-10-24 22:40:16 +04:00
|
|
|
if (mask && ! shortoutput) {
|
1994-05-13 12:02:16 +04:00
|
|
|
int savenflag = nflag;
|
|
|
|
|
2014-11-07 00:29:32 +03:00
|
|
|
nflag = RT_NFLAG;
|
2001-10-24 20:05:06 +04:00
|
|
|
(void)printf(" mask: %s\n",
|
2014-11-07 00:29:32 +03:00
|
|
|
routename(mask, nflag));
|
1994-05-13 12:02:16 +04:00
|
|
|
nflag = savenflag;
|
|
|
|
}
|
2005-08-13 01:23:06 +04:00
|
|
|
if (gate && rtm->rtm_flags & RTF_GATEWAY) {
|
|
|
|
const char *name;
|
|
|
|
|
2014-11-07 00:29:32 +03:00
|
|
|
name = routename(gate, nflag);
|
2005-08-13 01:23:06 +04:00
|
|
|
if (shortoutput) {
|
|
|
|
if (*name == '\0')
|
2008-09-09 20:50:52 +04:00
|
|
|
return 1;
|
2005-08-13 01:23:06 +04:00
|
|
|
(void)printf("%s\n", name);
|
|
|
|
} else
|
|
|
|
(void)printf(" gateway: %s\n", name);
|
|
|
|
}
|
2010-06-26 18:29:36 +04:00
|
|
|
if (mpls) {
|
|
|
|
const char *name;
|
2014-11-07 00:29:32 +03:00
|
|
|
name = routename(mpls, nflag);
|
2010-06-26 18:29:36 +04:00
|
|
|
if(shortoutput) {
|
|
|
|
if (*name == '\0')
|
|
|
|
return 1;
|
|
|
|
printf("%s\n", name);
|
|
|
|
} else
|
|
|
|
printf(" Tag: %s\n", name);
|
|
|
|
}
|
|
|
|
|
2001-10-24 22:40:16 +04:00
|
|
|
if (ifa && ! shortoutput)
|
2001-10-24 20:05:06 +04:00
|
|
|
(void)printf(" local addr: %s\n",
|
2014-11-07 00:29:32 +03:00
|
|
|
routename(ifa, nflag));
|
2001-10-24 22:40:16 +04:00
|
|
|
if (ifp && ! shortoutput)
|
1994-05-13 12:02:16 +04:00
|
|
|
(void)printf(" interface: %.*s\n",
|
|
|
|
ifp->sdl_nlen, ifp->sdl_data);
|
2001-10-24 22:40:16 +04:00
|
|
|
if (! shortoutput) {
|
|
|
|
(void)printf(" flags: ");
|
|
|
|
bprintf(stdout, rtm->rtm_flags, routeflags);
|
|
|
|
}
|
1994-05-13 12:02:16 +04:00
|
|
|
|
|
|
|
#define lock(f) ((rtm->rtm_rmx.rmx_locks & __CONCAT(RTV_,f)) ? 'L' : ' ')
|
|
|
|
#define msec(u) (((u) + 500) / 1000) /* usec to msec */
|
|
|
|
|
2001-10-24 22:40:16 +04:00
|
|
|
if (! shortoutput) {
|
2005-08-09 23:43:24 +04:00
|
|
|
(void)printf("\n%s\n", "\
|
1994-05-13 12:02:16 +04:00
|
|
|
recvpipe sendpipe ssthresh rtt,msec rttvar hopcount mtu expire");
|
2011-02-01 04:39:19 +03:00
|
|
|
printf("%8"PRId64"%c ", rtm->rtm_rmx.rmx_recvpipe, lock(RPIPE));
|
|
|
|
printf("%8"PRId64"%c ", rtm->rtm_rmx.rmx_sendpipe, lock(SPIPE));
|
|
|
|
printf("%8"PRId64"%c ", rtm->rtm_rmx.rmx_ssthresh, lock(SSTHRESH));
|
|
|
|
printf("%8"PRId64"%c ", msec(rtm->rtm_rmx.rmx_rtt), lock(RTT));
|
|
|
|
printf("%8"PRId64"%c ", msec(rtm->rtm_rmx.rmx_rttvar), lock(RTTVAR));
|
|
|
|
printf("%8"PRId64"%c ", rtm->rtm_rmx.rmx_hopcount, lock(HOPCOUNT));
|
|
|
|
printf("%8"PRId64"%c ", rtm->rtm_rmx.rmx_mtu, lock(MTU));
|
2001-10-24 22:40:16 +04:00
|
|
|
if (rtm->rtm_rmx.rmx_expire)
|
|
|
|
rtm->rtm_rmx.rmx_expire -= time(0);
|
2011-02-01 04:39:19 +03:00
|
|
|
printf("%8"PRId64"%c\n", rtm->rtm_rmx.rmx_expire, lock(EXPIRE));
|
2001-10-24 22:40:16 +04:00
|
|
|
}
|
1994-05-13 12:02:16 +04:00
|
|
|
#undef lock
|
|
|
|
#undef msec
|
|
|
|
#define RTA_IGN (RTA_DST|RTA_GATEWAY|RTA_NETMASK|RTA_IFP|RTA_IFA|RTA_BRD)
|
2001-10-24 22:40:16 +04:00
|
|
|
|
|
|
|
if (shortoutput)
|
2008-09-09 20:50:52 +04:00
|
|
|
return (rtm->rtm_addrs & RTF_GATEWAY) == 0;
|
2001-10-24 22:40:16 +04:00
|
|
|
else if (verbose)
|
1994-05-13 12:02:16 +04:00
|
|
|
pmsg_common(rtm);
|
|
|
|
else if (rtm->rtm_addrs &~ RTA_IGN) {
|
2005-08-09 23:43:24 +04:00
|
|
|
(void)printf("sockaddrs: ");
|
1994-05-13 12:02:16 +04:00
|
|
|
bprintf(stdout, rtm->rtm_addrs, addrnames);
|
|
|
|
putchar('\n');
|
|
|
|
}
|
2005-08-13 01:23:06 +04:00
|
|
|
return 0;
|
1994-05-13 12:02:16 +04:00
|
|
|
#undef RTA_IGN
|
1993-03-21 12:45:37 +03:00
|
|
|
}
|
1996-11-15 21:01:36 +03:00
|
|
|
#endif /* SMALL */
|
1993-03-21 12:45:37 +03:00
|
|
|
|
|
|
|
void
|
2005-02-05 17:05:23 +03:00
|
|
|
pmsg_common(struct rt_msghdr *rtm)
|
1993-03-21 12:45:37 +03:00
|
|
|
{
|
2005-08-09 23:43:24 +04:00
|
|
|
(void)printf("\nlocks: ");
|
1993-03-21 12:45:37 +03:00
|
|
|
bprintf(stdout, rtm->rtm_rmx.rmx_locks, metricnames);
|
2005-08-09 23:43:24 +04:00
|
|
|
(void)printf(" inits: ");
|
1993-03-21 12:45:37 +03:00
|
|
|
bprintf(stdout, rtm->rtm_inits, metricnames);
|
2008-09-09 20:50:52 +04:00
|
|
|
pmsg_addrs((char *)(rtm + 1), rtm->rtm_addrs);
|
1994-05-13 12:02:16 +04:00
|
|
|
}
|
|
|
|
|
2008-09-09 23:58:46 +04:00
|
|
|
static void
|
|
|
|
extract_addrs(const char *cp, int addrs, const struct sockaddr *sa[], int *nmfp)
|
|
|
|
{
|
|
|
|
int i, nmf = -1;
|
|
|
|
|
|
|
|
for (i = 0; i < RTAX_MAX; i++) {
|
|
|
|
if ((1 << i) & addrs) {
|
|
|
|
sa[i] = (const struct sockaddr *)cp;
|
|
|
|
if ((i == RTAX_DST || i == RTAX_IFA) &&
|
|
|
|
nmf == -1)
|
|
|
|
nmf = sa[i]->sa_family;
|
2011-02-01 04:39:19 +03:00
|
|
|
RT_ADVANCE(cp, sa[i]);
|
2008-09-09 23:58:46 +04:00
|
|
|
} else
|
|
|
|
sa[i] = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (nmfp != NULL)
|
|
|
|
*nmfp = nmf;
|
|
|
|
}
|
|
|
|
|
1997-04-03 06:35:46 +04:00
|
|
|
static void
|
2008-09-09 20:55:28 +04:00
|
|
|
pmsg_addrs(const char *cp, int addrs)
|
1994-05-13 12:02:16 +04:00
|
|
|
{
|
2008-09-09 20:50:52 +04:00
|
|
|
const struct sockaddr *sa[RTAX_MAX];
|
2005-08-15 23:28:08 +04:00
|
|
|
int i, nmf;
|
1994-05-13 12:02:16 +04:00
|
|
|
|
2001-07-16 21:22:07 +04:00
|
|
|
if (addrs != 0) {
|
2005-08-09 23:43:24 +04:00
|
|
|
(void)printf("\nsockaddrs: ");
|
2001-07-16 21:22:07 +04:00
|
|
|
bprintf(stdout, addrs, addrnames);
|
2005-08-09 23:43:24 +04:00
|
|
|
(void)putchar('\n');
|
2008-09-09 23:58:46 +04:00
|
|
|
extract_addrs(cp, addrs, sa, &nmf);
|
2005-08-15 23:28:08 +04:00
|
|
|
for (i = 0; i < RTAX_MAX; i++) {
|
2008-09-09 20:50:52 +04:00
|
|
|
if (sa[i] == NULL)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (i == RTAX_NETMASK && sa[i]->sa_len)
|
|
|
|
(void)printf(" %s",
|
|
|
|
netmask_string(sa[i], -1, nmf));
|
|
|
|
else
|
|
|
|
(void)printf(" %s",
|
2014-11-07 00:29:32 +03:00
|
|
|
routename(sa[i], nflag));
|
2005-08-15 23:28:08 +04:00
|
|
|
}
|
2001-07-16 21:22:07 +04:00
|
|
|
}
|
2005-08-09 23:43:24 +04:00
|
|
|
(void)putchar('\n');
|
|
|
|
(void)fflush(stdout);
|
1993-03-21 12:45:37 +03:00
|
|
|
}
|
|
|
|
|
1997-04-03 06:35:46 +04:00
|
|
|
static void
|
2006-01-25 19:19:50 +03:00
|
|
|
bprintf(FILE *fp, int b, const char *f)
|
1993-03-21 12:45:37 +03:00
|
|
|
{
|
1997-09-15 13:15:26 +04:00
|
|
|
int i;
|
1993-03-21 12:45:37 +03:00
|
|
|
int gotsome = 0;
|
2006-01-25 19:19:50 +03:00
|
|
|
const uint8_t *s = (const uint8_t *)f;
|
1993-03-21 12:45:37 +03:00
|
|
|
|
2011-02-01 04:39:19 +03:00
|
|
|
if (b == 0) {
|
|
|
|
fputs("none", fp);
|
1993-03-21 12:45:37 +03:00
|
|
|
return;
|
2011-02-01 04:39:19 +03:00
|
|
|
}
|
1997-04-03 06:35:46 +04:00
|
|
|
while ((i = *s++) != 0) {
|
1993-03-21 12:45:37 +03:00
|
|
|
if (b & (1 << (i-1))) {
|
|
|
|
if (gotsome == 0)
|
|
|
|
i = '<';
|
|
|
|
else
|
|
|
|
i = ',';
|
2005-08-09 23:43:24 +04:00
|
|
|
(void)putc(i, fp);
|
1993-03-21 12:45:37 +03:00
|
|
|
gotsome = 1;
|
|
|
|
for (; (i = *s) > 32; s++)
|
2005-08-09 23:43:24 +04:00
|
|
|
(void)putc(i, fp);
|
1993-03-21 12:45:37 +03:00
|
|
|
} else
|
|
|
|
while (*s > 32)
|
|
|
|
s++;
|
|
|
|
}
|
|
|
|
if (gotsome)
|
2005-08-09 23:43:24 +04:00
|
|
|
(void)putc('>', fp);
|
1993-03-21 12:45:37 +03:00
|
|
|
}
|
|
|
|
|
2005-08-10 01:25:42 +04:00
|
|
|
int
|
2008-09-09 20:55:28 +04:00
|
|
|
keyword(const char *cp)
|
1993-03-21 12:45:37 +03:00
|
|
|
{
|
1997-09-15 13:15:26 +04:00
|
|
|
struct keytab *kt = keywords;
|
1993-03-21 12:45:37 +03:00
|
|
|
|
|
|
|
while (kt->kt_cp && strcmp(kt->kt_cp, cp))
|
|
|
|
kt++;
|
|
|
|
return kt->kt_i;
|
|
|
|
}
|
|
|
|
|
1997-04-03 06:35:46 +04:00
|
|
|
static void
|
2005-06-27 01:28:15 +04:00
|
|
|
sodump(sup su, const char *which)
|
1993-03-21 12:45:37 +03:00
|
|
|
{
|
1999-12-03 08:43:00 +03:00
|
|
|
#ifdef INET6
|
|
|
|
char ntop_buf[NI_MAXHOST];
|
|
|
|
#endif
|
|
|
|
|
1993-03-21 12:45:37 +03:00
|
|
|
switch (su->sa.sa_family) {
|
1996-11-15 21:01:36 +03:00
|
|
|
case AF_INET:
|
2005-08-09 23:43:24 +04:00
|
|
|
(void)printf("%s: inet %s; ",
|
1996-11-15 21:01:36 +03:00
|
|
|
which, inet_ntoa(su->sin.sin_addr));
|
|
|
|
break;
|
2003-06-11 19:45:20 +04:00
|
|
|
#ifndef SMALL
|
1997-04-03 06:35:46 +04:00
|
|
|
case AF_APPLETALK:
|
2005-08-09 23:43:24 +04:00
|
|
|
(void)printf("%s: atalk %d.%d; ",
|
1997-04-03 06:35:46 +04:00
|
|
|
which, su->sat.sat_addr.s_net, su->sat.sat_addr.s_node);
|
|
|
|
break;
|
2003-06-11 19:45:20 +04:00
|
|
|
#endif
|
1993-03-21 12:45:37 +03:00
|
|
|
case AF_LINK:
|
2005-08-09 23:43:24 +04:00
|
|
|
(void)printf("%s: link %s; ",
|
1993-03-21 12:45:37 +03:00
|
|
|
which, link_ntoa(&su->sdl));
|
|
|
|
break;
|
1999-07-02 19:29:02 +04:00
|
|
|
#ifdef INET6
|
|
|
|
case AF_INET6:
|
2005-08-09 23:43:24 +04:00
|
|
|
(void)printf("%s: inet6 %s; ",
|
1999-07-02 19:29:02 +04:00
|
|
|
which, inet_ntop(AF_INET6, &su->sin6.sin6_addr,
|
|
|
|
ntop_buf, sizeof(ntop_buf)));
|
|
|
|
break;
|
|
|
|
#endif
|
2005-08-31 06:58:30 +04:00
|
|
|
#ifndef SMALL
|
2010-06-26 18:29:36 +04:00
|
|
|
case AF_MPLS:
|
2011-06-21 18:33:14 +04:00
|
|
|
{
|
2010-06-26 18:29:36 +04:00
|
|
|
union mpls_shim ms;
|
2011-06-21 18:33:14 +04:00
|
|
|
const union mpls_shim *pms;
|
|
|
|
int psize = sizeof(struct sockaddr_mpls);
|
|
|
|
|
2010-06-26 18:29:36 +04:00
|
|
|
ms.s_addr = ntohl(su->smpls.smpls_addr.s_addr);
|
|
|
|
printf("%s: mpls %u; ",
|
|
|
|
which, ms.shim.label);
|
2011-06-21 18:33:14 +04:00
|
|
|
|
|
|
|
pms = &su->smpls.smpls_addr;
|
|
|
|
while(psize < su->smpls.smpls_len) {
|
|
|
|
pms++;
|
|
|
|
ms.s_addr = ntohl(pms->s_addr);
|
|
|
|
printf("%u; ", ms.shim.label);
|
|
|
|
psize += sizeof(ms);
|
2010-06-26 18:29:36 +04:00
|
|
|
}
|
|
|
|
break;
|
2011-06-21 18:33:14 +04:00
|
|
|
}
|
1996-11-15 21:01:36 +03:00
|
|
|
#endif /* SMALL */
|
|
|
|
default:
|
2005-08-10 01:25:42 +04:00
|
|
|
(void)printf("%s: (%d) %s; ",
|
|
|
|
which, su->sa.sa_family, any_ntoa(&su->sa));
|
1993-03-21 12:45:37 +03:00
|
|
|
}
|
2005-08-09 23:43:24 +04:00
|
|
|
(void)fflush(stdout);
|
1993-03-21 12:45:37 +03:00
|
|
|
}
|
1994-05-13 12:02:16 +04:00
|
|
|
|
1993-03-21 12:45:37 +03:00
|
|
|
/* States*/
|
|
|
|
#define VIRGIN 0
|
|
|
|
#define GOTONE 1
|
|
|
|
#define GOTTWO 2
|
|
|
|
/* Inputs */
|
|
|
|
#define DIGIT (4*0)
|
|
|
|
#define END (4*1)
|
|
|
|
#define DELIM (4*2)
|
|
|
|
|
1997-04-03 06:35:46 +04:00
|
|
|
static void
|
2008-09-10 04:57:57 +04:00
|
|
|
sockaddr(const char *addr, struct sockaddr *sa)
|
1993-03-21 12:45:37 +03:00
|
|
|
{
|
1997-09-15 13:15:26 +04:00
|
|
|
char *cp = (char *)sa;
|
1993-03-21 12:45:37 +03:00
|
|
|
int size = sa->sa_len;
|
|
|
|
char *cplim = cp + size;
|
1997-09-15 13:15:26 +04:00
|
|
|
int byte = 0, state = VIRGIN, new = 0;
|
1993-03-21 12:45:37 +03:00
|
|
|
|
2005-08-09 23:43:24 +04:00
|
|
|
(void)memset(cp, 0, size);
|
1994-05-13 12:02:16 +04:00
|
|
|
cp++;
|
1993-03-21 12:45:37 +03:00
|
|
|
do {
|
|
|
|
if ((*addr >= '0') && (*addr <= '9')) {
|
|
|
|
new = *addr - '0';
|
|
|
|
} else if ((*addr >= 'a') && (*addr <= 'f')) {
|
|
|
|
new = *addr - 'a' + 10;
|
|
|
|
} else if ((*addr >= 'A') && (*addr <= 'F')) {
|
|
|
|
new = *addr - 'A' + 10;
|
1994-05-13 12:02:16 +04:00
|
|
|
} else if (*addr == 0)
|
1993-03-21 12:45:37 +03:00
|
|
|
state |= END;
|
|
|
|
else
|
|
|
|
state |= DELIM;
|
|
|
|
addr++;
|
|
|
|
switch (state /* | INPUT */) {
|
|
|
|
case GOTTWO | DIGIT:
|
|
|
|
*cp++ = byte; /*FALLTHROUGH*/
|
|
|
|
case VIRGIN | DIGIT:
|
|
|
|
state = GOTONE; byte = new; continue;
|
|
|
|
case GOTONE | DIGIT:
|
|
|
|
state = GOTTWO; byte = new + (byte << 4); continue;
|
|
|
|
default: /* | DELIM */
|
|
|
|
state = VIRGIN; *cp++ = byte; byte = 0; continue;
|
|
|
|
case GOTONE | END:
|
|
|
|
case GOTTWO | END:
|
|
|
|
*cp++ = byte; /* FALLTHROUGH */
|
|
|
|
case VIRGIN | END:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
1994-05-13 12:02:16 +04:00
|
|
|
} while (cp < cplim);
|
1993-03-21 12:45:37 +03:00
|
|
|
sa->sa_len = cp - (char *)sa;
|
|
|
|
}
|