route.c revision 7a23074e5a0337b4d20bc593de1aa7ad34701913
/*
* Copyright 2003 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
/* All Rights Reserved */
/* Copyright (c) 1990 Mentat Inc. */
/*
*
* Copyright (c) 1983, 1989, 1991, 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
* 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.
*
* @(#)route.c 8.6 (Berkeley) 4/28/95
* @(#)linkaddr.c 8.1 (Berkeley) 6/4/93
*/
#pragma ident "%Z%%M% %I% %E% SMI"
#include <sys/sysmacros.h>
#include <netdb.h>
#include <locale.h>
#include <errno.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stropts.h>
#include <fcntl.h>
#include <assert.h>
static struct keytab {
char *kt_cp;
int kt_i;
} keywords[] = {
#define K_ADD 1
{"add", K_ADD},
#define K_BLACKHOLE 2
{"blackhole", K_BLACKHOLE},
#define K_CHANGE 3
{"change", K_CHANGE},
#define K_CLONING 4
{"cloning", K_CLONING},
#define K_DELETE 5
{"delete", K_DELETE},
#define K_DST 6
{"dst", K_DST},
#define K_EXPIRE 7
{"expire", K_EXPIRE},
#define K_FLUSH 8
{"flush", K_FLUSH},
#define K_GATEWAY 9
{"gateway", K_GATEWAY},
#define K_GET 11
{"get", K_GET},
#define K_HOPCOUNT 12
{"hopcount", K_HOPCOUNT},
#define K_HOST 13
{"host", K_HOST},
#define K_IFA 14
{"ifa", K_IFA},
#define K_IFACE 15
{"iface", K_IFACE},
#define K_IFP 16
{"ifp", K_IFP},
#define K_INET 17
{"inet", K_INET},
#define K_INET6 18
{"inet6", K_INET6},
#define K_INTERFACE 19
{"interface", K_INTERFACE},
#define K_LINK 20
{"link", K_LINK},
#define K_LOCK 21
{"lock", K_LOCK},
#define K_LOCKREST 22
{"lockrest", K_LOCKREST},
#define K_MASK 23
{"mask", K_MASK},
#define K_MONITOR 24
{"monitor", K_MONITOR},
#define K_MTU 25
{"mtu", K_MTU},
#define K_NET 26
{"net", K_NET},
#define K_NETMASK 27
{"netmask", K_NETMASK},
#define K_NOSTATIC 28
{"nostatic", K_NOSTATIC},
#define K_PRIVATE 29
{"private", K_PRIVATE},
#define K_PROTO1 30
{"proto1", K_PROTO1},
#define K_PROTO2 31
{"proto2", K_PROTO2},
#define K_RECVPIPE 32
{"recvpipe", K_RECVPIPE},
#define K_REJECT 33
{"reject", K_REJECT},
#define K_RTT 34
{"rtt", K_RTT},
#define K_RTTVAR 35
{"rttvar", K_RTTVAR},
#define K_SA 36
{"sa", K_SA},
#define K_SENDPIPE 37
{"sendpipe", K_SENDPIPE},
#define K_SSTHRESH 38
{"ssthresh", K_SSTHRESH},
#define K_STATIC 39
{"static", K_STATIC},
#define K_XRESOLVE 40
{"xresolve", K_XRESOLVE},
#define K_MULTIRT 41
{"multirt", K_MULTIRT},
#define K_SETSRC 42
{"setsrc", K_SETSRC},
{0, 0}
};
static union sockunion {
struct sockaddr_in sin;
struct sockaddr_dl sdl;
struct sockaddr_in6 sin6;
typedef struct mib_item_s {
struct mib_item_s *next_item;
long group;
long mib_id;
long length;
} mib_item_t;
struct sockaddr_in *sin);
static int s;
static struct rt_metrics rt_metrics;
static int masklen;
static struct {
char m_space[512];
} m_rtmsg;
/*
* Sizes of data structures extracted from the base mib.
* This allows the size of the tables entries to grow while preserving
* binary compatibility.
*/
static int ipRouteEntrySize;
static int ipv6RouteEntrySize;
#define ROUNDUP_LONG(a) \
((a) > 0 ? (1 + (((a) - 1) | (sizeof (long) - 1))) : sizeof (long))
#define C(x) ((x) & 0xff)
/*
* return values from in_getprefixlen()
*/
void
{
cp);
gettext("usage: route [ -fnqv ] cmd [[ -<qualifers> ] args ]\n"));
exit(1);
/* NOTREACHED */
}
void
{
if (s != NULL)
/* NOTREACHED */
}
int
{
extern int optind;
int ch;
int key;
#if !defined(TEXT_DOMAIN)
#define TEXT_DOMAIN "SYS_TEST"
#endif
(void) textdomain(TEXT_DOMAIN);
if (argc < 2)
switch (ch) {
case 'n':
break;
case 'q':
break;
case 'v':
break;
case 't':
break;
case 'd':
break;
case 'f':
break;
case '?':
default:
/* NOTREACHED */
}
}
if (tflag)
else
if (s < 0)
if (fflag) {
/*
* Accept an address family keyword after the -f. Since the
* default address family is AF_INET, reassign af only for the
* other valid address families.
*/
case K_INET:
case K_INET6:
/* Skip over the address family parameter. */
argc--;
argv++;
break;
}
}
flushroutes(0, NULL);
}
case K_GET:
case K_CHANGE:
case K_ADD:
case K_DELETE:
case K_MONITOR:
/* NOTREACHED */
case K_FLUSH:
exit(0);
/* NOTREACHED */
}
}
if (!fflag)
return (0);
}
/*
* Purge all entries in the routing tables not
* associated with network interfaces.
*/
void
{
int seqno;
int sd; /* mib stream */
int oerrno;
int off = 0;
int on = 1;
sizeof (off)) < 0)
if (argc > 1) {
argv++;
/*
* The address family (preceded by a dash) may be used
* to flush the routes of that particular family.
*/
case K_INET:
break;
case K_LINK:
break;
case K_INET6:
break;
default:
/* NOTREACHED */
}
} else {
}
}
if (sd < 0) {
switch (errno) {
case EACCES:
gettext("route: flush: insufficient privileges\n"));
/* NOTREACHED */
default:
/* NOTREACHED */
}
}
if (verbose) {
(void) printf("Examining routing table from "
"T_SVR4_OPTMGMT_REQ\n");
}
seqno = 0; /* ??? */
switch (af) {
case AF_INET:
/* Extract ipRouteEntrySize */
continue;
sizeof (mib2_ipRouteEntry_t *)));
break;
}
}
if (ipRouteEntrySize == 0) {
gettext("ipRouteEntrySize can't be determined.\n"));
exit(1);
}
/*
* skip all the other trash that comes up the mib stream
*/
continue;
/* LINTED */
rp = (mib2_ipRouteEntry_t *)
((char *)rp + ipRouteEntrySize)) {
seqno++;
}
break;
}
break;
case AF_INET6:
/* Extract ipv6RouteEntrySize */
continue;
sizeof (mib2_ipv6RouteEntry_t *)));
break;
}
}
if (ipv6RouteEntrySize == 0) {
"ipv6RouteEntrySize cannot be determined.\n"));
exit(1);
}
/*
* skip all the other trash that comes up the mib stream
*/
continue;
/* LINTED */
rp6 = (mib2_ipv6RouteEntry_t *)
((char *)rp6 + ipv6RouteEntrySize)) {
seqno++;
}
break;
}
break;
}
sizeof (on)) < 0)
}
/*
* Given the contents of a mib_item_t of id type MIB2_IP_ROUTE or
* MIB2_IP6_ROUTE, construct and send an RTM_DELETE routing socket message in
* order to facilitate the flushing of RTF_GATEWAY routes.
*/
static void
{
char *cp;
int ire_type;
int rlen;
struct sockaddr_in sin;
struct sockaddr_in6 sin6;
int slen;
else
if (ire_type != IRE_DEFAULT &&
ire_type != IRE_PREFIX &&
return;
slen = sizeof (struct sockaddr_in);
} else {
slen = sizeof (struct sockaddr_in6);
}
if (debugonly) {
/*
* In debugonly mode, the routing socket message to delete the
* current entry is not actually sent. However if verbose is
* also set, the routing socket message that would have been
* is printed.
*/
if (verbose)
return;
}
if (rlen < 0) {
gettext("route: write to routing socket: %s\n"),
} else {
"routing socket got only %d for rlen\n"), rlen);
}
return;
}
if (qflag) {
/*
* In quiet mode, nothing is printed at all (unless the write()
* itself failed.
*/
return;
}
if (verbose) {
} else {
(void) printf("%-20.20s ",
/* LINTED */
(void) printf("done\n");
}
}
/*
* Return the name of the host whose address is given.
*/
char *
{
char *cp;
int error_num;
ushort_t *s;
if (first) {
else
domain[0] = 0;
}
return (line);
}
case AF_INET:
/* LINTED */
cp = "default";
AF_INET);
*cp = 0;
}
}
} else {
}
break;
case AF_LINK:
case AF_INET6:
/* LINTED */
if (IN6_IS_ADDR_UNSPECIFIED(&in6))
cp = "default";
*cp = 0;
}
}
} else {
}
break;
default:
while (++s < slim) /* start with sa->sa_data */
break;
}
return (line);
}
/*
* Return the name of the network whose address is given.
* The address is assumed to be that of a net or subnet, not a host.
*/
static char *
{
int subnetshift;
ushort_t *s;
case AF_INET:
/* LINTED */
cp = "default";
} else if (!nflag) {
subnetshift = 8;
subnetshift = 8;
} else {
subnetshift = 4;
}
/*
* If there are more bits than the standard mask
* would suggest, subnets must be in use.
* Guess at the subnet mask, assuming reasonable
* width subnet fields.
*/
while ((mask & 1) == 0)
}
} else {
}
break;
case AF_LINK:
case AF_INET6:
default:
/* LINTED */
while (s < slim)
break;
}
return (line);
}
void
{
int flag = 0;
switch (key) {
}
if (locking)
}
int
{
int key;
static char obuf[INET6_ADDRSTRLEN];
/* Don't want to read back our messages */
(void) shutdown(s, 0);
}
while (--argc > 0) {
} else if (**(argv) == '-') {
case K_LINK:
break;
case K_INET:
break;
case K_SA:
break;
case K_INET6:
break;
case K_IFACE:
case K_INTERFACE:
/* FALLTHROUGH */
case K_NOSTATIC:
flags &= ~RTF_STATIC;
break;
case K_LOCK:
break;
case K_LOCKREST:
break;
case K_HOST:
break;
case K_REJECT:
flags |= RTF_REJECT;
break;
case K_BLACKHOLE:
flags |= RTF_BLACKHOLE;
break;
case K_PROTO1:
flags |= RTF_PROTO1;
break;
case K_PROTO2:
flags |= RTF_PROTO2;
break;
case K_CLONING:
flags |= RTF_CLONING;
break;
case K_XRESOLVE:
flags |= RTF_XRESOLVE;
break;
case K_STATIC:
flags |= RTF_STATIC;
break;
case K_IFA:
argc--;
break;
case K_IFP:
argc--;
break;
case K_GATEWAY:
/*
* For the gateway parameter, retrieve the
* pointer to the struct hostent so that all
* possible addresses can be tried until one
* is successful.
*/
argc--;
break;
case K_DST:
argc--;
break;
case K_NETMASK:
argc--;
/* FALLTHROUGH */
case K_NET:
break;
case K_MTU:
case K_HOPCOUNT:
case K_EXPIRE:
case K_RECVPIPE:
case K_SENDPIPE:
case K_SSTHRESH:
case K_RTT:
case K_RTTVAR:
argc--;
break;
case K_PRIVATE:
flags |= RTF_PRIVATE;
break;
case K_MULTIRT:
flags |= RTF_MULTIRT;
break;
case K_SETSRC:
argc--;
flags |= RTF_SETSRC;
break;
default:
/* NOTREACHED */
}
} else {
} else if ((rtm_addrs & RTA_GATEWAY) == 0) {
/*
* For the gateway parameter, retrieve the
* pointer to the struct hostent so that all
* possible addresses can be tried until one
* is successful.
*/
} else {
/*
* Assume that a regular number is a metric.
* Needed for compatibility with old route
* command syntax.
*/
metric < 0x80000000ul) {
if (verbose) {
(void) printf("old usage of "
"trailing number, assuming "
"route %s\n", iflag ?
"to if" : "via gateway");
}
continue;
}
}
}
}
gettext("route: destination required following command\n"));
(rtm_addrs & RTA_GATEWAY) == 0) {
gettext("route: gateway required for add or delete "
"command\n"));
}
/*
* If the netmask has been specified use it to determine RTF_HOST.
* Otherwise rely on the "-net" and "-host" specifiers.
* Final fallback is whether ot not any bits were set in the address
* past the classful network component.
*/
if (rtm_addrs & RTA_NETMASK) {
else
}
if (forcehost)
if (forcenet)
if (ishost)
if (!iflag)
flags |= RTF_GATEWAY;
errno = 0;
break;
break;
switch (af) {
case AF_INET:
continue;
case AF_INET6:
continue;
}
}
break;
}
if (*cmd != 'g') {
if (*gateway != '\0') {
switch (af) {
case AF_INET:
if (nflag) {
(void) printf(": gateway %s",
(void) printf(": gateway %s (%s)",
} else {
}
break;
case AF_INET6:
INET6_ADDRSTRLEN) != NULL) {
if (nflag) {
(void) printf(": gateway %s",
obuf);
(void) printf(": gateway %s "
"(%s)",
}
break;
}
/* FALLTHROUGH */
default:
break;
}
}
if (ret == 0)
(void) printf("\n");
}
if (ret != 0) {
if (*cmd == 'g') {
if (nflag) {
switch (af) {
case AF_INET:
(void) printf(" %s",
break;
case AF_INET6:
break;
}
/* FALLTHROUGH */
default:
break;
}
} else {
}
}
switch (oerrno) {
case ESRCH:
err = "not in table";
break;
case EBUSY:
err = "entry in use";
break;
case ENOBUFS:
err = "routing table overflow";
break;
case EEXIST:
err = "entry exists";
break;
case EPERM:
err = "insufficient privileges";
break;
default:
break;
}
}
/*
* In the case of AF_INET6, one of the getipnodebyX() functions was used
* so free the allocated hostent.
*/
return (oerrno);
}
/*
* Convert a network number to the corresponding IP address.
* If the RTA_NETMASK hasn't been specified yet set it based
* on the class of address.
*/
static void
{
char *cp;
if (net == 0) {
} else if (net < 128) {
} else if (net < 65536) {
} else if (net < 16777216L) {
} else {
if ((addr & IN_CLASSA_HOST) == 0)
else if ((addr & IN_CLASSB_HOST) == 0)
else if ((addr & IN_CLASSC_HOST) == 0)
else {
else
mask = IP_HOST_MASK;
}
}
if (!(rtm_addrs & RTA_NETMASK)) {
rtm_addrs |= RTA_NETMASK;
;
}
}
static in_addr_t
{
int n;
struct sockaddr_in *sin;
char *buf;
int numifs;
int iosoc;
in_addr_t if_subnetmask = 0;
short if_flags;
if (mask == 0)
return (0);
/* Let's check to see if this is maybe a local subnet route. */
/* LINTED */
continue;
/* LINTED */
/*
* Don't trust pt-pt interfaces if there are
* other interfaces.
*/
if (if_flags & IFF_POINTOPOINT) {
continue;
}
/*
* Fine. Just assume the same net mask as the
* directly attached subnet interface is using.
*/
return (if_mask);
}
}
if (if_subnetmask != 0)
return (if_subnetmask);
return (mask);
}
/*
* Interpret an argument as a network address of some kind,
* returning B_TRUE if a host address, B_FALSE if a network address.
*
* If the address family is one looked up in getaddr() using one of the
* getipnodebyX() functions (currently only AF_INET6), then callers should
* freehostent() the returned "struct hostent" pointer if one was passed in.
*/
static boolean_t
{
if (s == NULL) {
gettext("route: argument required following keyword\n"));
}
switch (which) {
case RTA_DST:
break;
case RTA_GATEWAY:
break;
case RTA_NETMASK:
break;
case RTA_IFP:
gettext("route: %s: no such interface\n"),
s);
exit(1);
} else {
}
}
return (B_FALSE);
/*
* RTA_SRC has overloaded meaning. It can represent the
* src address of incoming or outgoing packets.
*/
case RTA_IFA:
break;
case RTA_SRC:
break;
default:
/* NOTREACHED */
/* NOTREACHED */
}
if (strcmp(s, "default") == 0) {
}
return (B_TRUE);
}
return (B_FALSE);
}
switch (af) {
case AF_LINK:
return (B_TRUE);
case PF_ROUTE:
return (B_TRUE);
case AF_INET6:
switch (which) {
case RTA_DST:
if (s[0] == '/') {
gettext("route: %s: unexpected '/'\n"), s);
exit(1);
}
switch (masklen) {
case NO_PREFIX:
/* Nothing there - ok */
return (ret);
case BAD_ADDR:
gettext("route: bad prefix length in %s\n"),
s);
exit(1);
/* NOTREACHED */
default:
gettext("route: bad prefix length: "
"%d\n"), masklen);
exit(1);
}
break;
}
rtm_addrs |= RTA_NETMASK;
return (ret);
case RTA_GATEWAY:
case RTA_IFA:
case RTA_SRC:
return (ret);
case RTA_NETMASK:
gettext("route: -netmask not supported for IPv6: "
"use <prefix>/<prefix-length> instead"));
exit(1);
/* NOTREACHED */
default:
/* NOTREACHED */
}
case AF_INET:
switch (which) {
case RTA_DST:
if (s[0] == '/') {
gettext("route: %s: unexpected '/'\n"), s);
exit(1);
}
switch (masklen) {
case NO_PREFIX:
/* Nothing there - ok */
return (ret);
case BAD_ADDR:
gettext("route: bad prefix length in %s\n"),
s);
exit(1);
/* NOTREACHED */
default:
gettext("route: bad prefix length: "
"%d\n"), masklen);
exit(1);
}
break;
}
rtm_addrs |= RTA_NETMASK;
return (ret);
case RTA_GATEWAY:
case RTA_IFA:
case RTA_NETMASK:
case RTA_SRC:
return (ret);
default:
/* NOTREACHED */
}
default:
/* NOTREACHED */
}
}
/*
* Interpret an argument as an IPv4 network address of some kind,
* returning B_TRUE if a host address, B_FALSE if a network address.
* Note that this *always* tries host interpretation before network
* interpretation.
*
* If the plenp argument is non-NULL, allow <addr>/<n> syntax and
* pass out <n> in *plenp.
* If <n> doesn't parse return BAD_ADDR as *plenp.
* If no /<n> is present return NO_PREFIX as *plenp.
*/
static boolean_t
{
/*
* Look for '/'<n> is plenp
*/
char *cp;
return (B_FALSE);
*cp = '\0';
str);
exit(1);
}
/*
* Note: only the route destination can be a network, so we treat
* all other addresses as though "-net" was not specified.
*/
return (B_TRUE);
return (B_FALSE);
}
return (B_FALSE);
}
return (B_TRUE);
}
return (B_FALSE);
}
exit(1);
/* NOTREACHED */
}
/*
* Interpret an argument as an IPv6 network address of some kind,
* returning B_TRUE if a host address, B_FALSE if a network address.
*
* If the last argument is non-NULL allow a <addr>/<n> syntax and
* pass out <n> in *plenp.
* If <n> doesn't parse return BAD_ADDR as *plenp.
* If no /<n> is present return NO_PREFIX as *plenp.
*/
static boolean_t
{
int error_num;
/*
* Look for '/'<n> is plenp
*/
char *cp;
return (B_FALSE);
*cp = '\0';
str);
exit(1);
}
return (B_TRUE);
}
"again later)\n"), s);
} else {
}
exit(1);
/* NOTREACHED */
}
/*
* If "slash" is zero this parses the whole string as
* an integer. With "slash" non zero it parses the tail part as an integer.
*
* If it is not a valid integer this returns BAD_ADDR.
* If there is /<n> present this returns NO_PREFIX.
*/
int
{
int prefixlen;
return (NO_PREFIX);
str++;
if (prefixlen < 0)
return (BAD_ADDR);
return (BAD_ADDR);
return (BAD_ADDR);
else
return (prefixlen);
}
/*
* Convert a prefix length to a mask.
* Returns B_TRUE if ok. B_FALSE otherwise.
* Assumes the mask array is zeroed by the caller.
*/
{
return (B_FALSE);
while (prefixlen > 0) {
if (prefixlen >= 8) {
*mask++ = 0xFF;
prefixlen -= 8;
continue;
}
prefixlen--;
}
return (B_TRUE);
}
void
{
int n;
if (tflag)
exit(0);
if (argc > 1) {
argv++;
case K_INET:
break;
case K_LINK:
break;
case K_INET6:
break;
default:
/* NOTREACHED */
}
} else {
}
(void) close(s);
if (s < 0)
}
for (;;) {
if (n <= 0)
(void) printf("got message of size %d\n", n);
}
}
int
{
static int seq;
int rlen;
int l;
errno = 0;
if (cmd == 'a') {
} else if (cmd == 'c') {
cmd = RTM_CHANGE;
} else if (cmd == 'g') {
}
} else {
cmd = RTM_DELETE;
}
#define NEXTADDR(w, u) \
if (rtm_addrs & (w)) { \
cp += l; \
if (verbose) \
sodump(&(u), #u); \
}
/*
* RTA_SRC has overloaded meaning. It can represent the
* src address of incoming or outgoing packets.
*/
if (verbose)
print_rtmsg(&rtm, l);
if (debugonly)
return (0);
switch (errno) {
case ESRCH:
case EBUSY:
case ENOBUFS:
case EEXIST:
case ENETUNREACH:
case EHOSTUNREACH:
case EPERM:
break;
default:
break;
}
return (-1);
gettext("route: write to routing socket got only %d for "
"len\n"), rlen);
return (-1);
}
do {
if (l < 0) {
gettext("route: read from routing socket: %s\n"),
} else {
print_getmsg(&rtm, l);
}
}
return (0);
}
static char *msgtypes[] = {
"",
"RTM_ADD: Add Route",
"RTM_DELETE: Delete Route",
"RTM_CHANGE: Change Metrics or flags",
"RTM_GET: Report Metrics",
"RTM_LOSING: Kernel Suspects Partitioning",
"RTM_REDIRECT: Told to use different route",
"RTM_MISS: Lookup failed on this address",
"RTM_LOCK: fix specified metrics",
"RTM_OLDADD: caused by SIOCADDRT",
"RTM_OLDDEL: caused by SIOCDELRT",
"RTM_RESOLVE: Route created by cloning",
"RTM_NEWADDR: address being added to iface",
"RTM_DELADDR: address being removed from iface",
"RTM_IFINFO: iface status change",
0,
};
static char metricnames[] =
"\011pksent\010rttvar\7rtt\6ssthresh\5sendpipe\4recvpipe\3expire\2hopcount"
"\1mtu";
static char routeflags[] =
"\1UP\2GATEWAY\3HOST\4REJECT\5DYNAMIC\6MODIFIED\7DONE\010MASK_PRESENT"
"\011CLONING\012XRESOLVE\013LLINFO\014STATIC\015BLACKHOLE"
"\016PRIVATE\017PROTO2\020PROTO1\021MULTIRT\022SETSRC";
static char ifnetflags[] =
"\1UP\2BROADCAST\3DEBUG\4LOOPBACK\5PTP\6NOTRAILERS\7RUNNING\010NOARP"
"\011PPROMISC\012ALLMULTI\013INTELLIGENT\014MULTICAST"
"\015MULTI_BCAST\016UNNUMBERED\017DHCP\020PRIVATE"
"\021NOXMIT\022NOLOCAL\023DEPRECATED\024ADDRCONF"
"\025ROUTER\026NONUD\027ANYCAST\030NORTEXCH\031IPv4\032IPv6"
"\033MIP\034NOFAILOVER\035FAILED\036STANDBY\037INACTIVE\040OFFLINE"
"\041XRESOLV\042COS\043PREFERRED\044TEMPORARY";
static char addrnames[] =
"\1DST\2GATEWAY\3NETMASK\4GENMASK\5IFP\6IFA\7AUTHOR\010BRD\011SRC";
void
{
struct ifa_msghdr *ifam;
if (!verbose)
return;
(void) printf("routing message version %d not understood\n",
rtm->rtm_version);
return;
}
(void) printf("message length mismatch, in packet %d, "
"returned %d\n",
}
/*
* Since rtm->rtm_type is unsigned, we'll just check the case of zero
* and the upper-bound of (NMSGTYPES - 1).
*/
(void) printf("routing message type %d not understood\n",
return;
}
case RTM_IFINFO:
break;
case RTM_NEWADDR:
case RTM_DELADDR:
break;
default:
(void) printf("pid: %ld, seq %d, errno %d, flags:",
}
}
void
{
char *cp;
int i;
gettext("routing message version %d not understood\n"),
rtm->rtm_version);
return;
}
gettext("message length mismatch, in packet %d, "
}
return;
}
for (i = 1; i != 0; i <<= 1) {
/* LINTED */
switch (i) {
case RTA_DST:
break;
case RTA_GATEWAY:
break;
case RTA_NETMASK:
break;
case RTA_IFP:
((struct sockaddr_dl *)sa)->
sdl_nlen != 0)
break;
case RTA_SRC:
break;
}
}
}
}
}
if (verbose) {
int i;
(void) printf(" interface: %.*s index %d address ",
i++) {
(void) printf("%02x ",
}
(void) printf("\n");
} else {
(void) printf(" interface: %.*s\n",
}
}
(void) printf(" flags: ");
"rttvar,ms hopcount mtu expire");
#define RTA_IGN \
if (verbose) {
(void) printf("sockaddrs: ");
(void) putchar('\n');
}
}
void
{
(void) printf("\nlocks: ");
(void) printf(" inits: ");
}
void
{
int i;
if (addrs == 0)
return;
(void) printf("\nsockaddrs: ");
(void) putchar('\n');
for (i = 1; i != 0; i <<= 1) {
if (i & addrs) {
/* LINTED */
}
}
(void) putchar('\n');
}
void
{
int i;
if (b == 0)
return;
while ((i = *s++) != 0) {
if (b & (1 << (i - 1))) {
if (!gotsome)
i = '<';
else
i = ',';
for (; (i = *s) > ' '; s++)
} else {
while (*s > ' ')
s++;
}
}
if (gotsome)
}
int
{
kt++;
}
void
{
static char obuf[INET6_ADDRSTRLEN];
case AF_LINK:
(void) printf("%s: link %s; ",
break;
case AF_INET:
(void) printf("%s: inet %s; ",
break;
case AF_INET6:
INET6_ADDRSTRLEN) != NULL) {
break;
}
/* FALLTHROUGH */
default:
/* NOTREACHED */
}
}
/* States */
#define VIRGIN 0
#define GOTONE 1
#define GOTTWO 2
#define RESET 3
/* Inputs */
#define DIGIT (4*0)
void
{
cp++;
do {
} else if (*addr == 0) {
} else {
}
addr++;
switch (state /* | INPUT */) {
/* FALLTHROUGH */
default: /* | DELIM */
/* FALLTHROUGH */
break;
}
break;
}
int
{
case AF_INET:
return (sizeof (struct sockaddr_in));
case AF_LINK:
return (sizeof (struct sockaddr_dl));
case AF_INET6:
return (sizeof (struct sockaddr_in6));
default:
return (sizeof (struct sockaddr));
}
}
void
{
do {
} else if (*addr == 0) {
} else {
}
addr++;
switch (state /* | INPUT */) {
continue;
continue;
/* FALLTHROUGH */
continue;
continue;
default: /* | DELIM */
byte = 0;
continue;
/* FALLTHROUGH */
break;
}
break;
}
static char hexlist[] = "0123456789abcdef";
char *
{
static char obuf[64];
int i;
*out++ = ':';
}
if (firsttime)
else
*out++ = '.';
i = *in++;
if (i > 0xf) {
i >>= 4;
out += 2;
} else {
}
}
*out = 0;
return (obuf);
}
static mib_item_t *
{
int flags;
int i, j, getcode;
flags = 0;
perror("mibget: putmsg (ctl)");
return (NULL);
}
/*
* each reply consists of a ctl part for one fixed structure
* or table, as defined in mib2.h. The format is a T_OPTMGMT_ACK,
* len is the size of the data part of the message.
*/
for (j = 1; ; j++) {
flags = 0;
if (getcode < 0) {
perror("mibget: getmsg (ctl)");
if (verbose) {
"# level name len\n");
i = 0;
(void) printf("%d %4ld %5ld %ld\n",
}
}
break;
}
if (getcode == 0 &&
if (verbose) {
(void) printf("mibget getmsg() %d returned EOD "
}
return (first_item); /* this is EOD msg */
}
"T_ERROR_ACK: TLI_error = 0x%lx, UNIX_error = "
break;
}
(void) printf("mibget getmsg(ctl) %d returned %d, "
"ctlbuf.len = %d, PRIM_type = %ld\n",
(void) printf("T_OPTMGMT_ACK: "
"MGMT_flags = 0x%lx, req->len = %ld\n",
}
break;
}
perror("mibget: malloc");
break;
}
else
first_item = temp;
if (verbose) {
(void) printf("msg %d: group = %4ld mib_id = %5ld "
"length = %ld\n",
}
flags = 0;
if (getcode < 0) {
perror("mibget: getmsg (data)");
break;
} else if (getcode != 0) {
(void) printf("mibget getmsg(data) returned %d, "
"databuf.maxlen = %d, databuf.len = %d\n",
break;
}
}
/*
* On error, free all the allocated mib_item_t objects.
*/
while (first_item != NULL) {
}
return (NULL);
}