/*
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*
* Copyright (c) 1983, 1988, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgment:
* 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.
*
*/
#include "defs.h"
#include "pathnames.h"
#include <signal.h>
#include <strings.h>
#include <fcntl.h>
{"#0", "REQUEST", "RESPONSE", "TRACEON", "TRACEOFF", "POLL",
"POLLENTRY"};
static void tmsg(const char *, ...);
const char *
{
if (err == 0) {
cp = "success";
} else {
"unknown error %d", err);
}
}
return (cp);
}
/* convert IP address to a string, but not into a single buffer */
char *
{
static int bufno;
static struct {
char *s;
return (s);
}
const char *
{
}
static char *
{
static char s[20];
return (s);
}
static char *
{
static char s[32];
int len;
return (s);
}
/*
* On each event, display a time stamp.
* This assumes that 'now' is update once for each event, and
* that at least now.tv_usec changes.
*/
void
lastlog(void)
{
lastlog_time = now;
}
}
static void
tmsg(const char *p, ...)
{
lastlog();
}
}
void
{
int fd;
if (isatty(STDIN_FILENO))
if (isatty(STDOUT_FILENO))
if (isatty(STDERR_FILENO))
}
lastlog_time.tv_sec = 0;
}
void
trace_flush(void)
{
trace_off("tracing off: %s",
}
}
void
trace_off(const char *p, ...)
{
lastlog();
}
new_tracelevel = tracelevel = 0;
}
/* log a change in tracing */
void
int dump) /* -1=no dump, 0=default, 1=force */
{
"Tracing actions stopped",
"Tracing packets stopped",
"Tracing packet contents stopped",
"Tracing kernel changes stopped",
"Tracing routing socket messages stopped",
};
"Tracing actions started",
"Tracing packets started",
"Tracing packet contents started",
"Tracing kernel changes started",
"Tracing routing socket messages started",
};
if (new_tracelevel < 0)
new_tracelevel = 0;
else if (new_tracelevel > MAX_TRACELEVEL)
if (new_tracelevel < tracelevel) {
if (new_tracelevel <= 0) {
} else {
do {
} while (--tracelevel != new_tracelevel);
}
} else if (new_tracelevel > tracelevel) {
do {
} while (tracelevel != new_tracelevel);
}
if (dump > 0 ||
trace_dump();
}
void
const char *pat,
int dump) /* -1=no dump, 0=default, 1=force */
{
const char *fn;
int nfd;
/*
* main() calls this routine with "dump == -1". All others
* call it with 0, so we take dump == -1 to mean "can create
* the file."
*/
/*
* Allow a null filename to increase the level if the trace file
* is already open or if coming from a trusted source, such as
* a signal or the command line.
*/
if (inittracename[0] == '\0') {
msglog("missing trace file name");
return;
}
fn = inittracename;
} else {
goto set_tracelevel;
}
trace_dump();
return;
} else {
/*
* Allow the file specified with "-T file" to be reopened,
* but require all other names specified over the net to
* match the official path. The path can specify a directory
* in which the file is to be created.
*/
sizeof (PATH_TRACE)-1) != 0 ||
return;
}
fn = PATH_TRACE;
goto missing_file;
}
goto bad_file_type;
}
}
}
/* fn cannot be null here */
/* If the new tracefile exists, it must be a regular file. */
if (!allow_create)
goto missing_file;
goto missing_file;
}
} else {
goto bad_file_type;
}
if (fn == inittracename)
inittracename[0] = '\0';
if (nfd != -1)
return;
}
return;
}
if (fn != savetracename)
return;
return;
}
/* ARGSUSED */
void
sigtrace_more(int s)
{
sigtrace_pat = "SIGUSR1: %s";
}
/* ARGSUSED */
void
sigtrace_less(int s)
{
sigtrace_pat = "SIGUSR2: %s";
}
/* ARGSUSED */
void
sigtrace_dump(int s)
{
trace_dump();
}
/* Set tracing after a signal. */
void
set_tracelevel(void)
{
if (new_tracelevel == tracelevel)
return;
/*
* If tracing entirely off, and there was no tracefile specified
* on the command line, then leave it off.
*/
if (savetracename[0] != '\0') {
} else if (inittracename[0] != '\0') {
} else {
new_tracelevel = 0;
return;
}
} else {
}
}
/* display an address */
char *
int force) /* 0=show mask if nonstandard, */
{ /* 1=always show mask, 2=never */
static int bufno;
static struct {
/*
* this array can hold either of the following strings terminated
* by a null character:
* "xxx.xxx.xxx.xxx/xx"
* "xxx.xxx.xxx.xxx (mask xxx.xxx.xxx.xxx)"
*
*/
char *s, *sp;
int i, len;
} else {
}
}
return (s);
}
/* display a bit-field */
struct or_bits {
const char *origin_name;
};
{ RO_RIP, "RIP" },
{ RO_RDISC, "RDISC" },
{ RO_STATIC, "STATIC" },
{ RO_LOOPBCK, "LOOPBCK" },
{ RO_PTOPT, "PTOPT" },
{ RO_NET_SYN, "NET_SYN" },
{ RO_IF, "IF" },
{ RO_FILE, "FILE" },
{ RO_NONE, " " },
{ 0, NULL}
};
/* display a bit-field */
struct bits {
const char *bits_name;
};
{ IFF_BROADCAST, 0, "BROADCAST" },
{ IFF_DEBUG, 0, "DEBUG" },
{ IFF_LOOPBACK, 0, "LOOPBACK" },
{ IFF_POINTOPOINT, 0, "POINTOPOINT" },
{ IFF_NOTRAILERS, 0, "NOTRAILERS" },
{ IFF_RUNNING, 0, "RUNNING" },
{ IFF_NOARP, 0, "NOARP" },
{ IFF_PROMISC, 0, "PROMISC" },
{ IFF_ALLMULTI, 0, "ALLMULTI" },
{ IFF_INTELLIGENT, 0, "INTELLIGENT" },
{ IFF_MULTICAST, 0, "MULTICAST" },
{ IFF_MULTI_BCAST, 0, "MULTI_BCAST" },
{ IFF_UNNUMBERED, 0, "UNNUMBERED" },
{ IFF_DHCPRUNNING, 0, "DHCP" },
{ IFF_PRIVATE, 0, "PRIVATE" },
{ IFF_NOXMIT, 0, "NOXMIT" },
{ IFF_NOLOCAL, 0, "NOLOCAL" },
{ IFF_DEPRECATED, 0, "DEPRECATED" },
{ IFF_ADDRCONF, 0, "ADDRCONF" },
{ IFF_ROUTER, 0, "ROUTER" },
{ IFF_NONUD, 0, "NONUD" },
{ IFF_ANYCAST, 0, "ANYCAST" },
{ IFF_NORTEXCH, 0, "NORTEXCH" },
{ IFF_IPV4, 0, "IPv4" },
{ IFF_IPV6, 0, "IPv6" },
{ IFF_NOFAILOVER, 0, "NOFAILOVER" },
{ IFF_FAILED, 0, "FAILED" },
{ IFF_STANDBY, 0, "STANDBY" },
{ IFF_INACTIVE, 0, "INACTIVE" },
{ IFF_OFFLINE, 0, "OFFLINE" },
{ IFF_XRESOLV, 0, "XRESOLV" },
{ IFF_COS_ENABLED, 0, "CoS" },
{ IFF_PREFERRED, 0, "PREFERRED" },
{ IFF_TEMPORARY, 0, "TEMPORARY" },
{ IFF_FIXEDMTU, 0, "FIXEDMTU" },
{ IFF_VIRTUAL, 0, "VIRTUAL"},
{ IFF_IPMP, 0, "IPMP"},
{ 0, 0, NULL}
};
{ IS_ALIAS, 0, "ALIAS" },
{ IS_SUBNET, 0, "" },
{ IS_REMOTE, (IS_NO_RDISC |
IS_BCAST_RDISC), "REMOTE" },
{ IS_PASSIVE, (IS_NO_RDISC |
IS_NO_AG), "PASSIVE" },
{ IS_EXTERNAL, 0, "EXTERNAL" },
{ IS_CHECKED, 0, "" },
{ IS_ALL_HOSTS, 0, "" },
{ IS_ALL_ROUTERS, 0, "" },
{ IS_DISTRUST, 0, "DISTRUST" },
{ IS_SICK, 0, "SICK" },
{ IS_DUP, 0, "DUPLICATE" },
{ IS_REDIRECT_OK, 0, "REDIRECT_OK" },
{ IS_NEED_NET_SYN, 0, "" },
{ IS_NO_SUPER_AG, 0, "NO_SUPER_AG" },
{ (IS_NO_RIPV1_IN |
IS_NO_RIPV2_OUT), 0, "NO_RIP" },
{ (IS_NO_RIPV1_IN |
IS_NO_RIPV1_OUT), 0, "RIPV2" },
{ IS_NO_RIPV1_IN, 0, "NO_RIPV1_IN" },
{ IS_NO_RIPV2_IN, 0, "NO_RIPV2_IN" },
{ IS_NO_RIPV1_OUT, 0, "NO_RIPV1_OUT" },
{ IS_NO_RIPV2_OUT, 0, "NO_RIPV2_OUT" },
{ IS_NO_RIP_MCAST, 0, "NO_RIP_MCAST" },
{ (IS_NO_ADV_IN |
{ IS_NO_SOL_OUT, 0, "NO_SOLICIT" },
{ IS_SOL_OUT, 0, "SEND_SOLICIT" },
{ IS_ADV_OUT, 0, "RDISC_ADV" },
{ IS_BCAST_RDISC, 0, "BCAST_RDISC" },
{ IS_PM_RDISC, 0, "" },
{ IS_NO_HOST, 0, "NO_HOST" },
{ IS_SUPPRESS_RDISC, 0, "SUPPRESS_RDISC" },
{ IS_FLUSH_RDISC, 0, "FLUSH_RDISC" },
{ 0, 0, NULL}
};
{ RS_IF, 0, "IF" },
{ RS_NET_SYN, 0, "NET_SYN" },
{ RS_SUBNET, 0, "" },
{ RS_LOCAL, 0, "LOCAL" },
{ RS_MHOME, 0, "MHOME" },
{ RS_STATIC, 0, "STATIC" },
{ RS_NOPROPAGATE, 0, "NOPROP" },
{ RS_BADIF, 0, "BADIF" },
{ 0, 0, NULL}
};
{ KS_NEW, 0, "NEW" },
{ KS_DELETE, 0, "DELETE" },
{ KS_ADD, 0, "ADD" },
{ KS_CHANGE, 0, "CHANGE" },
{ KS_DEL_ADD, 0, "DEL_ADD" },
{ KS_STATIC, 0, "STATIC" },
{ KS_GATEWAY, 0, "GATEWAY" },
{ KS_DYNAMIC, 0, "DYNAMIC" },
{ KS_DELETED, 0, "DELETED" },
{ KS_PRIVATE, 0, "PRIVATE" },
{ KS_CHECK, 0, "CHECK" },
{ KS_IF, 0, "IF" },
{ KS_PASSIVE, 0, "PASSIVE" },
{ KS_DEPRE_IF, 0, "DEPRE_IF" },
{ KS_FILE, 0, "FILE" },
{ 0, 0, NULL}
};
static void
{
uint64_t b;
char c;
if (force) {
c = '\0';
} else {
c = '<';
}
while (field != 0 &&
if ((b & field) == b) {
if (c != '\0')
c = '|';
}
}
tbl++;
}
if (field != 0) {
if (c != '\0')
c = '|';
}
if (c != '<' || force)
}
static char *
{
/* minimum default string */
slen = sizeof ("<0x12345678>");
return (NULL);
if (force) {
*cp++ = '<';
chr = '\0';
} else {
chr = '<';
}
if (chr != '\0')
chr = '|';
}
}
tbl++;
}
if (field != 0) {
if (chr != '\0')
chr = '|';
}
*cp++ = '>';
*cp = '\0';
return (sbuf);
}
char *
{
}
char *
{
int i;
naddr_ntoa(gate));
return (buf);
}
static void
int force_metric, /* -1=suppress, 0=default */
int force_ifp, /* -1=suppress, 0=default */
int force_router, /* -1=suppress, 0=default, 1=display */
int force_tag, /* -1=suppress, 0=default, 1=display */
int force_time) /* 0=suppress, 1=display */
{
int i;
if (force_metric >= 0)
if (force_ifp >= 0)
if (force_router > 0 ||
if (force_time > 0)
if (force_tag > 0 ||
continue;
}
}
static void
{
if (tblentry == route_origin) {
}
tbl++;
}
}
void
{
return;
lastlog();
if (ifp->int_metric != 0)
ifp->int_d_metric != 0)
}
void
{
return;
lastlog();
else
}
void
{
return;
lastlog();
}
void
{
return;
return;
lastlog();
0,
} else {
}
}
/* miscellaneous message checked by the caller */
void
trace_misc(const char *p, ...)
{
return;
lastlog();
}
/* display a message if tracing actions */
void
trace_act(const char *p, ...)
{
return;
lastlog();
}
/* display a message if tracing packets */
void
trace_pkt(const char *p, ...)
{
return;
lastlog();
}
void
const char *label)
{
return;
return;
lastlog();
0,
}
}
void
{
return;
lastlog();
}
/* ARGSUSED */
static int
void *w)
{
int i;
}
}
return (0);
}
void
trace_dump(void)
{
return;
lastlog();
/*
* Warning: the rtquery.trace.* family of STC tests depend on
* the log file format here. If you need to change this next
* message, make sure that you change the TRACE_DUMP variable
* as well.
*/
kern_dump();
rdisc_dump();
}
void
struct sockaddr_in *who,
int size) /* total size of message */
{
int i, seen_route;
return;
lastlog();
" %s.%d size=%d\n",
size);
return;
}
if (!TRACECONTENTS)
return;
seen_route = 0;
case RIPCMD_REQUEST:
case RIPCMD_RESPONSE:
for (; n < lim; n++) {
if (!seen_route &&
n->n_family == RIP_AF_UNSPEC &&
(n+1 == lim ||
(n+2 == lim &&
if (n->n_dst != 0)
naddr_ntoa(n->n_dst));
if (n->n_mask != 0)
if (n->n_nhop != 0)
naddr_ntoa(n->n_nhop));
if (n->n_tag != 0)
continue;
}
if (n->n_family == RIP_AF_AUTH) {
" Authentication: \"%s\"\n",
continue;
}
"\tMD5 Auth"
" pkt_len=%d KeyID=%u"
" auth_len=%d"
" seqno=%#x"
" rsvd=%#hx,%#hx\n",
continue;
}
"\tAuthentication type %d: ",
i++)
continue;
}
seen_route = 1;
if (n->n_family != RIP_AF_INET) {
"\t(af %d) %-18s mask=%s ",
naddr_ntoa(n->n_dst),
} else {
n->n_mask == 0 ? 2 : 0));
}
if (n->n_nhop != 0)
naddr_ntoa(n->n_nhop));
if (n->n_tag != 0)
}
size);
break;
case RIPCMD_TRACEON:
msg->rip_tracefile);
break;
case RIPCMD_TRACEOFF:
break;
}
}