* Copyright (c) 1983, 1988 Regents of the University of California.
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
static char sccsid
[] = "@(#)trace.c 5.11 (Berkeley) 2/28/91";
* Routing Table Management Daemon
#define NRECORDS 50 /* size of circular trace buffer */
static struct timeval lastlog
;
static char *savetracename
;
register struct interface
*ifp
;
static int iftraceinit();
if (iftraceinit(ifp
, &ifp
->int_input
) &&
iftraceinit(ifp
, &ifp
->int_output
))
fprintf(stderr
, "traceinit: can't init %s\n", ifp
->int_name
);
register struct ifdebug
*ifd
;
register struct iftrace
*t
;
(struct iftrace
*)malloc(NRECORDS
* sizeof (struct iftrace
));
if (ifd
->ifd_records
== 0)
ifd
->ifd_front
= ifd
->ifd_records
;
for (t
= ifd
->ifd_records
; t
< ifd
->ifd_records
+ NRECORDS
; t
++) {
if (stat(file
, &stbuf
) >= 0 && (stbuf
.st_mode
& S_IFMT
) != S_IFREG
)
(void) gettimeofday(&now
, (struct timezone
*)NULL
);
ftrace
= fopen(file
, "a");
fprintf(ftrace
, "Tracing enabled %s\n", ctime((time_t *)&now
.tv_sec
));
int fd
= open(_PATH_DEVNULL
, O_RDWR
);
fprintf(ftrace
, "Tracing disabled %s\n",
ctime((time_t *)&now
.tv_sec
));
else if (ftrace
== NULL
&& savetracename
)
* Move to next higher level of tracing when -t option processed or
* SIGUSR1 is received. Successive levels are:
* traceactions + tracepackets
* traceactions + tracehistory (packets and contents after change)
* traceactions + tracepackets + tracecontents
(void) gettimeofday(&now
, (struct timezone
*)NULL
);
fprintf(ftrace
, "Tracing actions started %s\n",
ctime((time_t *)&now
.tv_sec
));
} else if (tracepackets
== 0) {
fprintf(ftrace
, "Tracing packets started %s\n",
ctime((time_t *)&now
.tv_sec
));
} else if (tracehistory
== 0) {
fprintf(ftrace
, "Tracing history started %s\n",
ctime((time_t *)&now
.tv_sec
));
fprintf(ftrace
, "Tracing packet contents started %s\n",
ctime((time_t *)&now
.tv_sec
));
trace(ifd
, who
, p
, len
, m
)
register struct ifdebug
*ifd
;
register struct iftrace
*t
;
if (ifd
->ifd_records
== 0)
if (ifd
->ifd_front
>= ifd
->ifd_records
+ NRECORDS
)
ifd
->ifd_front
= ifd
->ifd_records
;
if (ifd
->ifd_count
< NRECORDS
)
if (t
->ift_size
> 0 && t
->ift_size
< len
&& t
->ift_packet
) {
if (len
> 0 && t
->ift_packet
== 0) {
t
->ift_packet
= malloc(len
);
bcopy(p
, t
->ift_packet
, len
);
traceaction(fd
, action
, rt
)
struct sockaddr_in
*dst
, *gate
;
{ RTF_GATEWAY
, "GATEWAY" },
{ RTS_PASSIVE
, "PASSIVE" },
{ RTS_REMOTE
, "REMOTE" },
{ RTS_INTERFACE
,"INTERFACE" },
{ RTS_CHANGED
, "CHANGED" },
{ RTS_INTERNAL
, "INTERNAL" },
{ RTS_EXTERNAL
, "EXTERNAL" },
{ RTS_SUBNET
, "SUBNET" },
if (lastlog
.tv_sec
!= now
.tv_sec
|| lastlog
.tv_usec
!= now
.tv_usec
) {
fprintf(fd
, "\n%.19s:\n", ctime((time_t *)&now
.tv_sec
));
fprintf(fd
, "%s ", action
);
dst
= (struct sockaddr_in
*)&rt
->rt_dst
;
gate
= (struct sockaddr_in
*)&rt
->rt_router
;
fprintf(fd
, "dst %s, ", inet_ntoa(dst
->sin_addr
));
fprintf(fd
, "router %s, metric %d, flags",
inet_ntoa(gate
->sin_addr
), rt
->rt_metric
);
for (first
= 1, p
= flagbits
; p
->t_bits
> 0; p
++) {
if ((rt
->rt_flags
& p
->t_bits
) == 0)
fprintf(fd
, cp
, p
->t_name
);
for (first
= 1, p
= statebits
; p
->t_bits
> 0; p
++) {
if ((rt
->rt_state
& p
->t_bits
) == 0)
fprintf(fd
, cp
, p
->t_name
);
fprintf(fd
, " timer %d\n", rt
->rt_timer
);
if (tracehistory
&& !tracepackets
&&
(rt
->rt_state
& RTS_PASSIVE
) == 0 && rt
->rt_ifp
)
tracenewmetric(fd
, rt
, newmetric
)
struct sockaddr_in
*dst
, *gate
;
if (lastlog
.tv_sec
!= now
.tv_sec
|| lastlog
.tv_usec
!= now
.tv_usec
) {
fprintf(fd
, "\n%.19s:\n", ctime((time_t *)&now
.tv_sec
));
dst
= (struct sockaddr_in
*)&rt
->rt_dst
;
gate
= (struct sockaddr_in
*)&rt
->rt_router
;
fprintf(fd
, "CHANGE metric dst %s, ", inet_ntoa(dst
->sin_addr
));
fprintf(fd
, "router %s, from %d to %d\n",
inet_ntoa(gate
->sin_addr
), rt
->rt_metric
, newmetric
);
register struct interface
*ifp
;
if (ifp
->int_input
.ifd_count
|| ifp
->int_output
.ifd_count
) {
fprintf(fd
, "*** Packet history for interface %s ***\n",
dumptrace(fd
, "to", &ifp
->int_output
);
dumptrace(fd
, "from", &ifp
->int_input
);
fprintf(fd
, "*** end packet history ***\n");
register struct ifdebug
*ifd
;
register struct iftrace
*t
;
char *cp
= !strcmp(dir
, "to") ? "Output" : "Input";
if (ifd
->ifd_front
== ifd
->ifd_records
&&
ifd
->ifd_front
->ift_size
== 0) {
fprintf(fd
, "%s: no packets.\n", cp
);
fprintf(fd
, "%s trace:\n", cp
);
t
= ifd
->ifd_front
- ifd
->ifd_count
;
if (t
< ifd
->ifd_records
)
for ( ; ifd
->ifd_count
; ifd
->ifd_count
--, t
++) {
if (t
>= ifd
->ifd_records
+ NRECORDS
)
dumppacket(fd
, dir
, &t
->ift_who
, t
->ift_packet
, t
->ift_size
,
dumppacket(fd
, dir
, who
, cp
, size
, stamp
)
struct sockaddr_in
*who
; /* should be sockaddr */
register struct rip
*msg
= (struct rip
*)cp
;
register struct netinfo
*n
;
if (msg
->rip_cmd
&& msg
->rip_cmd
< RIPCMD_MAX
)
fprintf(fd
, "%s %s %s.%d %.19s:\n", ripcmds
[msg
->rip_cmd
],
dir
, inet_ntoa(who
->sin_addr
), ntohs(who
->sin_port
),
ctime((time_t *)&stamp
->tv_sec
));
fprintf(fd
, "Bad cmd 0x%x %s %x.%d %.19s\n", msg
->rip_cmd
,
dir
, inet_ntoa(who
->sin_addr
), ntohs(who
->sin_port
));
fprintf(fd
, "size=%d cp=%x packet=%x\n", size
, cp
, packet
,
ctime((time_t *)&stamp
->tv_sec
));
if (tracepackets
&& tracecontents
== 0) {
size
-= 4 * sizeof (char);
for (; size
> 0; n
++, size
-= sizeof (struct netinfo
)) {
if (size
< sizeof (struct netinfo
)) {
fprintf(fd
, "(truncated record, len %d)\n",
if (sizeof(n
->rip_dst
.sa_family
) > 1)
n
->rip_dst
.sa_family
= ntohs(n
->rip_dst
.sa_family
);
switch ((int)n
->rip_dst
.sa_family
) {
fprintf(fd
, "\tdst %s metric %d\n",
#define satosin(sa) ((struct sockaddr_in *)&sa)
inet_ntoa(satosin(n
->rip_dst
)->sin_addr
),
fprintf(fd
, "\taf %d? metric %d\n",
fprintf(fd
, "\tfile=%*s\n", size
, msg
->rip_tracefile
);