1186 lines
34 KiB
C
1186 lines
34 KiB
C
/*
|
|
* CENTER FOR THEORY AND SIMULATION IN SCIENCE AND ENGINEERING
|
|
* CORNELL UNIVERSITY
|
|
*
|
|
* Portions of this software may fall under the following
|
|
* copyrights:
|
|
*
|
|
* Copyright (c) 1983 Regents of the University of California.
|
|
* All rights reserved. The Berkeley software License Agreement
|
|
* specifies the terms and conditions for redistribution.
|
|
*
|
|
* GATED - based on Kirton's EGP, UC Berkeley's routing daemon (routed),
|
|
* and DCN's HELLO routing Protocol.
|
|
*/
|
|
|
|
#ifndef lint
|
|
static char *rcsid = "$Header: /proj/irix6.5.7m/isms/eoe/cmd/bsd/gated/RCS/trace.c,v 1.2 1990/09/10 13:06:28 arc Exp $";
|
|
#endif not lint
|
|
|
|
/* trace_egp.c
|
|
*
|
|
* Tracing functions for route changes, received packets and EGP messages.
|
|
*
|
|
* Functions: traceaction (modified from routed/trace.c), tracercv, traceegp
|
|
*/
|
|
|
|
#include "include.h"
|
|
#ifndef vax11c
|
|
#include <sys/stat.h>
|
|
#endif vax11c
|
|
#if defined(AGENT_SNMP) || defined(AGENT_SGMP)
|
|
#include <snmp.h>
|
|
#endif defined(AGENT_SNMP) || defined(AGENT_SGMP)
|
|
|
|
extern FILE *conf_open();
|
|
|
|
/*
|
|
* traceaction() traces changes to the routing tables
|
|
*/
|
|
traceaction(fd, action, rt)
|
|
FILE *fd; /* trace logfile */
|
|
char *action;
|
|
struct rt_entry *rt;
|
|
{
|
|
struct sockaddr_in *dst, *gate;
|
|
register struct bits *p;
|
|
register int first;
|
|
char *cp;
|
|
|
|
if (fd == NULL)
|
|
return;
|
|
fprintf(fd, "%-8s ", action);
|
|
dst = (struct sockaddr_in *)&rt->rt_dst;
|
|
gate = (struct sockaddr_in *)&rt->rt_router;
|
|
fprintf(fd, "%4s %-15s ", (rt->rt_state & RTS_HOSTROUTE ? "host" : "net" ), inet_ntoa(dst->sin_addr));
|
|
fprintf(fd, "gw %-15s metric %5d proto ", inet_ntoa(gate->sin_addr), rt->rt_metric);
|
|
cp = "%s";
|
|
for (first = 1, p = protobits; p->t_bits; p++) {
|
|
if ((rt->rt_proto & p->t_bits) == 0)
|
|
continue;
|
|
fprintf(fd, cp, p->t_name);
|
|
if (first) {
|
|
cp = "|%s";
|
|
first = 0;
|
|
}
|
|
}
|
|
fprintf(fd, " flags");
|
|
cp = " %s";
|
|
for (first = 1, p = flagbits; p->t_bits; p++) {
|
|
if ((rt->rt_flags & p->t_bits) == 0)
|
|
continue;
|
|
fprintf(fd, cp, p->t_name);
|
|
if (first) {
|
|
cp = "|%s";
|
|
first = 0;
|
|
}
|
|
}
|
|
fprintf(fd, " state");
|
|
cp = " %s";
|
|
for (first = 1, p = statebits; p->t_bits; p++) {
|
|
if ((rt->rt_state & p->t_bits) == 0)
|
|
continue;
|
|
fprintf(fd, cp, p->t_name);
|
|
if (first) {
|
|
cp = "|%s";
|
|
first = 0;
|
|
}
|
|
}
|
|
#ifndef NSS
|
|
if (rt->rt_proto & RTPROTO_HELLO) {
|
|
printf(" hwin_min %d ", rt->rt_hwindow.h_min);
|
|
}
|
|
#endif NSS
|
|
if ( rt->rt_fromproto != rt->rt_proto) {
|
|
printf(" fromproto ");
|
|
cp = "%s";
|
|
for (first = 1, p = protobits; p->t_bits; p++) {
|
|
if ((rt->rt_fromproto & p->t_bits) == 0)
|
|
continue;
|
|
fprintf(fd, cp, p->t_name);
|
|
if (first) {
|
|
cp = "|%s";
|
|
first = 0;
|
|
}
|
|
}
|
|
}
|
|
if ( rt->rt_state & RTS_EXTERIOR ) {
|
|
printf(" extmetric %d", rt->rt_metric_exterior);
|
|
}
|
|
if ( rt->rt_as != mysystem ) {
|
|
printf(" as %d", rt->rt_as);
|
|
}
|
|
(void) fprintf(fd, "\n");
|
|
|
|
#ifdef notdef
|
|
if ((rt->rt_announcelist != NULL) && (tracing & TR_INT)) {
|
|
dst = (struct sockaddr_in *)&rt->rt_announcelist->rdst;
|
|
fprintf(fd, "ANNOUNCE net %s, ", inet_ntoa(dst->sin_addr));
|
|
fprintf(fd, "metric %d, proto %d\n",rt->rt_announcelist->regpmetric, rt->rt_announcelist->rproto);
|
|
}
|
|
if ((rt->rt_noannouncelist != NULL) && (tracing & TR_INT)) {
|
|
dst = (struct sockaddr_in *)&rt->rt_noannouncelist->rdst;
|
|
fprintf(fd, "NOANNOUNCE net %s, ", inet_ntoa(dst->sin_addr));
|
|
fprintf(fd, "metric %d, proto %d\n",rt->rt_noannouncelist->regpmetric, rt->rt_noannouncelist->rproto);
|
|
}
|
|
#endif notdef
|
|
}
|
|
|
|
|
|
/*
|
|
* Turn off tracing.
|
|
*/
|
|
traceoff(tracetype)
|
|
int tracetype;
|
|
{
|
|
int tracedel = 0;
|
|
|
|
#ifndef NSS
|
|
if (tracetype & RIP_TRACE) {
|
|
tracedel |= (TR_UPDATE|TR_RIP);
|
|
}
|
|
if (tracetype & HELLO_TRACE) {
|
|
tracedel |= (TR_UPDATE|TR_HELLO);
|
|
}
|
|
#endif NSS
|
|
if (!tracing) {
|
|
return;
|
|
}
|
|
tracing &= ~tracedel; /* unflag added tracing options */
|
|
if ((ftrace != NULL) && (tracetype & GEN_TRACE)) {
|
|
TRACE_TRC("Tracing to %s suspended at %s", logfile, strtime);
|
|
tracing = 0;
|
|
#ifdef notdef
|
|
(void) fflush(ftrace);
|
|
(void) fflush(stdout);
|
|
(void) fflush(stderr);
|
|
#endif notdef
|
|
(void) fclose(ftrace);
|
|
(void) fclose(stdout);
|
|
(void) fclose(stderr);
|
|
ftrace = NULL;
|
|
syslog(LOG_ERR, "tracing to %s suspended", logfile);
|
|
}
|
|
return;
|
|
}
|
|
|
|
/*
|
|
* Turn on tracing.
|
|
*/
|
|
traceon(file, tracetype)
|
|
char *file;
|
|
int tracetype;
|
|
{
|
|
#ifndef vax11c
|
|
struct stat stbuf;
|
|
#endif vax11c
|
|
int traceadd = 0;
|
|
|
|
switch (tracetype) {
|
|
#ifndef NSS
|
|
case RIP_TRACE:
|
|
traceadd |= (TR_UPDATE|TR_RIP);
|
|
break;
|
|
case HELLO_TRACE:
|
|
traceadd |= (TR_UPDATE|TR_HELLO);
|
|
break;
|
|
#endif NSS
|
|
case GEN_TRACE:
|
|
traceadd |= savetrace;
|
|
break;
|
|
}
|
|
|
|
if ((ftrace == NULL) && (file != NULL)) {
|
|
#ifndef vax11c
|
|
if ((stat(file, &stbuf) >= 0) && ((stbuf.st_mode & S_IFMT) != S_IFREG)) {
|
|
return;
|
|
}
|
|
#endif vax11c
|
|
if ((ftrace = fopen(file, "a")) == NULL) {
|
|
syslog(LOG_ERR, "error opening %s: %m", file);
|
|
return;
|
|
}
|
|
#ifndef vax11c
|
|
setlinebuf(ftrace);
|
|
#endif vax11c
|
|
if ( freopen(file, "a", stdout) == NULL ) {
|
|
syslog(LOG_ERR, "error opening %s: %m", file);
|
|
return;
|
|
}
|
|
#ifndef vax11c
|
|
setlinebuf(stdout);
|
|
#endif vax11c
|
|
if ( freopen(file, "a", stderr) == NULL ) {
|
|
syslog(LOG_ERR, "error opening %s: %m", file);
|
|
return;
|
|
}
|
|
#ifndef vax11c
|
|
setlinebuf(stderr);
|
|
#endif vax11c
|
|
syslog(LOG_ERR, "tracing to %s started", file);
|
|
printf("\fTracing to %s started at %s", file, strtime);
|
|
}
|
|
tracing |= traceadd;
|
|
tracedisplay(tracing);
|
|
}
|
|
|
|
|
|
/*
|
|
* Read tracing information from conf file
|
|
*/
|
|
traceflags()
|
|
{
|
|
FILE *fd;
|
|
int more_flags, new_flags, trace_flags = 0;
|
|
char c, keyword[MAXHOSTNAMELENGTH+1];
|
|
struct bits *flag_ptr;
|
|
char line[256], *lp;
|
|
|
|
if ( (fd = conf_open()) == NULL) {
|
|
return(trace_flags);
|
|
}
|
|
while (fgets(line, sizeof(line), fd) != NULL) {
|
|
if ( (*line == '\n') || (*line == '#') ) {
|
|
continue;
|
|
}
|
|
lp = line;
|
|
(void) sscanf(lp, "%s", keyword);
|
|
lp += strlen(keyword);
|
|
if (strcasecmp(keyword, "traceflags") != 0) {
|
|
continue;
|
|
}
|
|
more_flags = TRUE;
|
|
while (more_flags) {
|
|
switch (c= *lp++) {
|
|
case '\n':
|
|
*--lp = c;
|
|
case '\0':
|
|
case '#':
|
|
more_flags = FALSE;
|
|
break;
|
|
case ' ':
|
|
case '\t':
|
|
break;
|
|
default:
|
|
*--lp = c;
|
|
(void) sscanf(lp, "%s", keyword);
|
|
lp += strlen(keyword);
|
|
new_flags = 0;
|
|
for ( flag_ptr = trace_types; flag_ptr->t_name; flag_ptr++ ) {
|
|
if ( strcasecmp(keyword, flag_ptr->t_name) == 0 ) {
|
|
new_flags = flag_ptr->t_bits;
|
|
break;
|
|
}
|
|
}
|
|
if ( new_flags == 0 ) {
|
|
TRACE_INT("traceflags: invalid trace flag '%s' ignored\n", keyword);
|
|
syslog(LOG_ERR, "traceflags: invalid trace flag '%s' ignored\n", keyword);
|
|
}
|
|
trace_flags |= new_flags;
|
|
}
|
|
}
|
|
}
|
|
(void) fclose(fd);
|
|
|
|
return(trace_flags);
|
|
}
|
|
|
|
|
|
/*
|
|
* Display trace options enabled
|
|
*/
|
|
tracedisplay(trace_flags)
|
|
int trace_flags;
|
|
{
|
|
struct bits *flag_ptr, *last_ptr;
|
|
|
|
printf("\nTracing flags enabled: ");
|
|
if ( trace_flags ) {
|
|
last_ptr = &trace_types[1];
|
|
for ( flag_ptr = trace_types; flag_ptr->t_name; last_ptr = flag_ptr++ ) {
|
|
if ( ((trace_flags & flag_ptr->t_bits) == flag_ptr->t_bits) &&
|
|
(flag_ptr->t_bits != last_ptr->t_bits) ) {
|
|
printf("%s ", flag_ptr->t_name);
|
|
}
|
|
}
|
|
printf("\n\n");
|
|
} else {
|
|
printf("none\n\n");
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
* trace packets received
|
|
*
|
|
* Only trace data part - EGP packets include IP header but ICMP packets do
|
|
* not (but on 4.3BSD they DO, well it is passed to the RAW ICMP socket.
|
|
*/
|
|
tracercv(sock, protocol, packet, length, frompt)
|
|
int sock, protocol, length;
|
|
struct sockaddr_in *frompt;
|
|
char *packet;
|
|
{
|
|
struct sockaddr_in sockname;
|
|
int socklen = sizeof (sockname), i;
|
|
struct ip *pkt;
|
|
int hlen;
|
|
|
|
pkt = (struct ip *)packet;
|
|
switch (protocol) {
|
|
case IPPROTO_EGP:
|
|
hlen = pkt->ip_hl;
|
|
hlen <<= 2; /* IP header length in octets */
|
|
TRACE_EGPPKT(EGP RECV, pkt->ip_src, pkt->ip_dst,
|
|
(struct egppkt *)(packet+hlen), pkt->ip_len);
|
|
break;
|
|
#ifndef sgi
|
|
case IMPLINK_IP: /* not implemented */
|
|
#endif
|
|
case IPPROTO_ICMP: /* IP header not passed with ICMP messages */
|
|
if (getsockname (sock, (char *)&sockname, &socklen))
|
|
p_error ("tracercv: getsockname");
|
|
printf("\nPacket received at time %s", strtime);
|
|
printf("protocol %d, from addr %s",protocol,inet_ntoa(frompt->sin_addr));
|
|
printf(", on interface addr %s\n", inet_ntoa(sockname.sin_addr));
|
|
printf("Data octets (decimal):\n");
|
|
for (i = 0; i < length; i++)
|
|
printf ("%d ", packet[i]);
|
|
printf ("\n");
|
|
break;
|
|
}
|
|
return;
|
|
}
|
|
|
|
/*
|
|
* Trace EGP packet
|
|
*/
|
|
traceegp(comment, src, dst, egp, length)
|
|
char *comment;
|
|
struct in_addr src, dst;
|
|
struct egppkt *egp;
|
|
int length;
|
|
{
|
|
struct egppkt *ep;
|
|
int reason;
|
|
char *type, *code, *status;
|
|
static char *no_codes[1] = { "0" };
|
|
static struct {
|
|
char *et_type;
|
|
short et_ncodes;
|
|
char **et_codes;
|
|
char et_nstatus;
|
|
char **et_status;
|
|
} egp_types[9] = {
|
|
"Invalid", -1, (char **) 0, -1, (char **)0, /* 0 - Error */
|
|
"UPDATE", 0, no_codes, 3, egp_nr_status, /* 1 - Nets Reachable */
|
|
"POLL", 0, no_codes, 3, egp_nr_status, /* 2 - Poll */
|
|
"ACQUIRE", 5, egp_acq_codes, 7, egp_acq_status, /* 3 - Neighbor Aquisition */
|
|
"Invalid", -1, (char **) 0, -1, (char **)0, /* 4 - Error */
|
|
"NEIGHBOR", 2, egp_reach_codes, 3, egp_nr_status, /* 5 - Neighbor Reachability */
|
|
"Invalid", -1, (char **) 0, -1, (char **)0, /* 6 - Error */
|
|
"Invalid", -1, (char **) 0, -1, (char **)0, /* 7 - Error */
|
|
"ERROR", -1, (char **) 0, 3, egp_nr_status}; /* 8 - Error packet */
|
|
|
|
printf("%s", comment);
|
|
if (src.s_addr != INADDR_ANY)
|
|
printf(" %s", inet_ntoa(src));
|
|
printf(" -> %s length %d at %s", inet_ntoa(dst), length, strtime);
|
|
|
|
if ( egp->egp_type <= EGPERR ) {
|
|
type = egp_types[egp->egp_type].et_type;
|
|
if ( (short)(egp->egp_code % UNSOLICITED) <= egp_types[egp->egp_type].et_ncodes ) {
|
|
code = egp_types[egp->egp_type].et_codes[(egp->egp_code % UNSOLICITED)];
|
|
} else {
|
|
if ( (egp->egp_code % UNSOLICITED) == 0 ) {
|
|
code = "";
|
|
} else {
|
|
code = "Invalid";
|
|
}
|
|
}
|
|
if ( egp->egp_status <= egp_types[egp->egp_type].et_nstatus ) {
|
|
status = egp_types[egp->egp_type].et_status[egp->egp_status];
|
|
} else {
|
|
status = "Invalid";
|
|
}
|
|
} else {
|
|
type = "Invalid";
|
|
}
|
|
printf("%s vers %d, type %s(%d), code %s(%d), status %s(%d)%s, AS# %d, id %d",
|
|
comment,
|
|
egp->egp_ver,
|
|
type, egp->egp_type,
|
|
code, egp->egp_code,
|
|
status, egp->egp_status,
|
|
egp->egp_code & UNSOLICITED ? " UNSOLICITED" : "",
|
|
ntohs(egp->egp_system), ntohs(egp->egp_id));
|
|
if (length > sizeof( struct egppkt))
|
|
switch (egp->egp_type) {
|
|
case EGPACQ:
|
|
printf(", hello int %d, poll int %d",
|
|
ntohs(((struct egpacq *)egp)->ea_hint),
|
|
ntohs(((struct egpacq *)egp)->ea_pint));
|
|
break;
|
|
case EGPPOLL:
|
|
printf(", src net %s", inet_ntoa(((struct egppoll *)egp)->ep_net));
|
|
break;
|
|
case EGPNR:
|
|
printf(", src net %s, #int %d, #ext %d\n",
|
|
inet_ntoa(((struct egpnr *)egp)->en_net),
|
|
((struct egpnr *)egp)->en_igw,
|
|
((struct egpnr *)egp)->en_egw);
|
|
if (length > sizeof(struct egpnr) && ( tracing & TR_UPDATE) ) {
|
|
#ifdef EGP_UPDATE_FORMAT
|
|
NR_format((struct egpnr *)egp, length);
|
|
#else EGP_UPDATE_FORMAT
|
|
register u_char *data, *dataf;
|
|
|
|
data = (u_char *)egp + sizeof(struct egpnr);
|
|
dataf = (u_char *)egp + length;
|
|
for ( ; data < dataf; data++)
|
|
printf( "%d ", *data);
|
|
printf("\n");
|
|
#endif EGP_UPDATE_FORMAT
|
|
}
|
|
break;
|
|
case EGPERR:
|
|
reason = ntohs(((struct egperr *)egp)->ee_rsn);
|
|
if ( reason > 7 ) {
|
|
printf(", error %d (invalid)\nreturned header: ",
|
|
reason);
|
|
} else {
|
|
printf(", error: %s\nreturned header: ",
|
|
egp_reasons[reason]);
|
|
}
|
|
ep = (struct egppkt *)((struct egperr*)egp)->ee_egphd;
|
|
printf("vers %d, typ %d, code %d, status %d, AS# %d,",
|
|
ep->egp_ver, ep->egp_type, ep->egp_code,
|
|
ep->egp_status, ntohs(ep->egp_system));
|
|
printf(" id %d, %d, %d", ntohs(ep->egp_id),
|
|
((struct egperr *)egp)->ee_egphd[10],
|
|
((struct egperr *)egp)->ee_egphd[11]);
|
|
break;
|
|
}
|
|
printf("\n\n");
|
|
return;
|
|
}
|
|
|
|
#ifndef NSS
|
|
tracerip(dir, who, cp, size)
|
|
struct sockaddr_in *who; /* should be sockaddr */
|
|
char *dir, *cp;
|
|
register int size;
|
|
{
|
|
register struct rip *rpmsg = (struct rip *)cp;
|
|
register struct netinfo *n;
|
|
register char *cmd = "Invalid";
|
|
|
|
if (rpmsg->rip_cmd && rpmsg->rip_cmd < RIPCMD_MAX) {
|
|
cmd = ripcmds[rpmsg->rip_cmd];
|
|
}
|
|
printf("RIP %s %s.%d vers %d, cmd %s, length %d",
|
|
dir,
|
|
inet_ntoa(who->sin_addr),
|
|
ntohs(who->sin_port),
|
|
rpmsg->rip_vers,
|
|
cmd, size);
|
|
switch (rpmsg->rip_cmd) {
|
|
#ifdef RIPCMD_POLL
|
|
case RIPCMD_POLL:
|
|
#endif RIPCMD_POLL
|
|
case RIPCMD_REQUEST:
|
|
case RIPCMD_RESPONSE:
|
|
printf(" at %s", strtime);
|
|
if (tracing & TR_UPDATE) {
|
|
size -= 4 * sizeof (char);
|
|
n = rpmsg->rip_nets;
|
|
for (; size > 0; n++, size -= sizeof (struct netinfo)) {
|
|
if (size < sizeof (struct netinfo)) {
|
|
break;
|
|
}
|
|
printf("\tnet %-15s metric %2d size %d\n", inet_ntoa(sock_inaddr(&n->rip_dst)),
|
|
ntohl((u_long)n->rip_metric), size);
|
|
}
|
|
}
|
|
break;
|
|
case RIPCMD_TRACEON:
|
|
printf(", file %*s at %s", size, rpmsg->rip_tracefile, strtime);
|
|
break;
|
|
#ifdef RIPCMD_POLLENTRY
|
|
case RIPCMD_POLLENTRY:
|
|
n = rpmsg->rip_nets;
|
|
printf(", net %s at %s",
|
|
inet_ntoa(sock_inaddr(&n->rip_dst)),
|
|
strtime);
|
|
break;
|
|
#endif RIPCMD_POLLENTRY
|
|
default:
|
|
printf(" at %s", strtime);
|
|
break;
|
|
}
|
|
printf("\n");
|
|
}
|
|
|
|
/* ARGSUSED */
|
|
tracehello(comment, src, dst, hello, length, nets)
|
|
char *comment;
|
|
struct in_addr src, dst;
|
|
char *hello;
|
|
int length, nets;
|
|
{
|
|
printf("%s %s -> ", comment, inet_ntoa(src));
|
|
printf("%s length %d", inet_ntoa(dst), length);
|
|
if (nets < 0) {
|
|
printf(", %d nets", nets);
|
|
}
|
|
printf(" at %s\n", strtime);
|
|
}
|
|
#endif NSS
|
|
|
|
#if defined(AGENT_SNMP) || defined(AGENT_SGMP)
|
|
tracesnmp(comment, dst, packet, length)
|
|
char *comment;
|
|
struct sockaddr_in *dst;
|
|
char *packet;
|
|
int length;
|
|
{
|
|
int size, integer;
|
|
char *cp;
|
|
char *pkt = packet;
|
|
register struct bits *p;
|
|
#ifdef AGENT_SNMP
|
|
struct in_addr ipaddr;
|
|
#endif AGENT_SNMP
|
|
|
|
cp = "Unknown";
|
|
for (p = snmp_types; p->t_bits > (u_int)0; p++) {
|
|
if ( p->t_bits == *pkt ) {
|
|
cp = p->t_name;
|
|
break;
|
|
}
|
|
}
|
|
|
|
printf("%s %s.%d type %s(%d) length %d at %s",
|
|
comment,
|
|
inet_ntoa(dst->sin_addr),
|
|
ntohs(dst->sin_port),
|
|
cp, *pkt++, length,
|
|
strtime);
|
|
|
|
if (tracing & TR_UPDATE) {
|
|
if ((pkt-packet) <= length) {
|
|
switch (*packet) {
|
|
case AGENT_RSP:
|
|
while ((pkt-packet) <= length-1) {
|
|
switch (*pkt++) {
|
|
case INT:
|
|
size = *pkt++;
|
|
bcopy(pkt, (char *) &integer, size);
|
|
pkt += size;
|
|
printf("%s\tinteger length %d value: %d 0x%x\n", comment, size, integer, integer);
|
|
break;
|
|
case STR:
|
|
size = *pkt++;
|
|
printf("%s\tstring length %d value: ", comment, size);
|
|
for (; size; size--) {
|
|
printf("%c", *pkt++);
|
|
}
|
|
printf("\n");
|
|
break;
|
|
#ifdef AGENT_SNMP
|
|
case IPADD:
|
|
size = *pkt++;
|
|
bcopy(pkt, (char *) &ipaddr.s_addr, size);
|
|
pkt += size;
|
|
printf("%s\tIP address length %d value: %s 0x%x\n", comment, size, inet_ntoa(ipaddr), ipaddr.s_addr);
|
|
break;
|
|
case CNTR:
|
|
size = *pkt++;
|
|
bcopy(pkt, (char *) &integer, size);
|
|
pkt += size;
|
|
printf("%s\tcounter length %d value: %u 0x%x\n", comment, size, integer, integer);
|
|
break;
|
|
case GAUGE:
|
|
size = *pkt++;
|
|
bcopy(pkt, (char *) &integer, size);
|
|
pkt += size;
|
|
printf("%s\tgauge length %d value: %u 0x%x\n", comment, size, integer, integer);
|
|
break;
|
|
case TIME:
|
|
size = *pkt++;
|
|
bcopy(pkt, (char *) &integer, size);
|
|
pkt += size;
|
|
printf("%s\ttimer length %d value: %u 0x%x\n", comment, size, integer, integer);
|
|
break;
|
|
#endif AGENT_SNMP
|
|
}
|
|
}
|
|
break;
|
|
case AGENT_ERR:
|
|
break;
|
|
case AGENT_REQ:
|
|
case AGENT_REG:
|
|
while ((pkt-packet) <= length-1) {
|
|
size = *pkt++;
|
|
printf("%s\tlength %d variable: ", comment, size);
|
|
for (; size; size--) {
|
|
printf("%02x", *pkt++ & 0xff);
|
|
}
|
|
printf("\n");
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
} else {
|
|
printf("\n");
|
|
}
|
|
}
|
|
#endif defined(AGENT_SNMP) || defined(AGENT_SGMP)
|
|
|
|
dumpinfo()
|
|
{
|
|
FILE *fd;
|
|
register struct interface *ifp;
|
|
|
|
#define HELLO_REPORT 8 /* how far back we will report */
|
|
|
|
register struct bits *p;
|
|
register int first;
|
|
char *cp, *ch;
|
|
struct rthash *rh;
|
|
struct active_gw *agp;
|
|
struct rthash *base = hosthash;
|
|
struct rt_entry *rt;
|
|
int doinghost = 1, cnt, ind, cntr;
|
|
struct in_addr tmpos;
|
|
struct advlist *mptr;
|
|
struct egpngh *ngp;
|
|
|
|
if ((fd = fopen(DUMPFILE, "a")) <= (FILE *)0) {
|
|
p_error("dumpinfo: ");
|
|
return;
|
|
}
|
|
#ifndef vax11c
|
|
setlinebuf(fd);
|
|
#endif vax11c
|
|
syslog(LOG_NOTICE, "dumpinfo: processing dump to %s", DUMPFILE);
|
|
TRACE_TRC("dumpinfo: processing dump to %s at %s", DUMPFILE, strtime);
|
|
fprintf(fd, "\f\n\t%s[%d] version %s memory dump on %s at %s\n", my_name, my_pid, version, my_hostname, strtime);
|
|
if (version_kernel) {
|
|
fprintf(fd, "\t\t%s\n\n", version_kernel);
|
|
}
|
|
/*
|
|
* Print out all of the interface stuff.
|
|
*/
|
|
fprintf(fd, "Interface Stats:\n\n");
|
|
for (ifp = ifnet; ifp; ifp = ifp->int_next) {
|
|
fprintf(fd, "\tInterface: %s\t\t\tMetric: %d\n", ifp->int_name, ifp->int_metric);
|
|
fprintf(fd, "\tAddress: %s\n", inet_ntoa(sock_inaddr(&ifp->int_addr)));
|
|
fprintf(fd, "\tUp-down transitions: %u\n", ifp->int_transitions);
|
|
if (ifp->int_flags & IFF_BROADCAST) {
|
|
fprintf(fd, "\tBroadcast Address: %s\n", inet_ntoa(sock_inaddr(&ifp->int_broadaddr)));
|
|
}
|
|
if (ifp->int_flags & IFF_POINTOPOINT) {
|
|
fprintf(fd, "\tDestination Address: %s\n", inet_ntoa(sock_inaddr(&ifp->int_dstaddr)));
|
|
}
|
|
#ifdef NSS
|
|
fprintf(fd, "\tIntra-NSS Address: %s\n", inet_ntoa(ifp->intra_nss_int.sin_addr));
|
|
#endif NSS
|
|
tmpos.s_addr = ntohl(ifp->int_net);
|
|
fprintf(fd, "\tNet Number: %s\t\tNet Mask: %lx\n",
|
|
inet_ntoa(tmpos),
|
|
ifp->int_netmask);
|
|
tmpos.s_addr = ntohl(ifp->int_subnet);
|
|
fprintf(fd, "\tSubnet Number: %s\t\tSubnet Mask: %lx\n",
|
|
inet_ntoa(tmpos),
|
|
ifp->int_subnetmask);
|
|
fprintf(fd, "\tFlags: <");
|
|
cp = "%s";
|
|
for (first = 1, p = intfbits; p->t_bits > (u_int)0; p++) {
|
|
if ((ifp->int_flags & p->t_bits) == 0)
|
|
continue;
|
|
fprintf(fd, cp, p->t_name);
|
|
if (first) {
|
|
cp = "|%s";
|
|
first = 0;
|
|
}
|
|
}
|
|
fprintf(fd, ">\n");
|
|
#ifndef NSS
|
|
fprintf(fd, "\tFixed Metrics:\n");
|
|
fprintf(fd, "\t\t\tRIP:\t");
|
|
if (ifp->int_flags & IFF_RIPFIXEDMETRIC) {
|
|
fprintf(fd, "%d\n", ifp->int_ripfixedmetric);
|
|
} else {
|
|
fprintf(fd, "NONE\n");
|
|
}
|
|
fprintf(fd, "\t\t\tHELLO:\t");
|
|
if (ifp->int_flags & IFF_HELLOFIXEDMETRIC) {
|
|
fprintf(fd, "%d\n", ifp->int_hellofixedmetric);
|
|
} else {
|
|
fprintf(fd, "NONE\n");
|
|
}
|
|
#endif NSS
|
|
fprintf(fd, "\tActive gateways on interface:");
|
|
if (ifp->int_active_gw == NULL) {
|
|
fprintf(fd, "\tNONE\n");
|
|
} else {
|
|
fprintf(fd, "\n");
|
|
for (agp = ifp->int_active_gw; agp; agp = agp->next) {
|
|
tmpos.s_addr = agp->addr;
|
|
fprintf(fd, "\t\t\t%s\t<", inet_ntoa(tmpos));
|
|
cp = "%s";
|
|
for (first = 1, p = protobits; p->t_bits > (u_int)0; p++) {
|
|
if ((agp->proto & p->t_bits) == 0)
|
|
continue;
|
|
fprintf(fd, cp, p->t_name);
|
|
if (first) {
|
|
cp = "|%s";
|
|
first = 0;
|
|
}
|
|
}
|
|
fprintf(fd, ">\t%d\n", agp->timer);
|
|
}
|
|
}
|
|
fprintf(fd, "\n");
|
|
}
|
|
/*
|
|
* EGP neighbor status
|
|
*/
|
|
if ( doing_egp ) {
|
|
struct tm *tmp;
|
|
fprintf(fd, "EGP status:\n\tN_remote_nets: %d\t\tdefaultegpmetric: %d\n", n_remote_nets, conv_factor);
|
|
fprintf(fd, "\tAutonomous System: %d\t\tacquired: %d/%d\n", mysystem, n_acquired, maxacq);
|
|
fprintf(fd, "\tMaxage: %d\t\t\tMaxpollint: %d\n", rt_maxage, maxpollint);
|
|
fprintf(fd, "\tPackets In: %d\t\t\tErrors In: %d\n", egp_stats.inmsgs, egp_stats.inerrors);
|
|
fprintf(fd, "\tPackets Out: %d\t\t\tErrors Out: %d\n", egp_stats.outmsgs, egp_stats.outerrors);
|
|
fprintf(fd, "\t\t\t\t\tTotal Errors: %d\n", egp_stats.outerrors+egp_stats.inerrors);
|
|
for (ngp = egpngh; ngp != NULL; ngp = ngp->ng_next) {
|
|
fprintf(fd, "\n\tNeighbor: %s",inet_ntoa(ngp->ng_addr));
|
|
fprintf(fd, "\t\tInterface: %s\n", inet_ntoa(ngp->ng_myaddr));
|
|
tmp = localtime(&ngp->ng_htime);
|
|
fprintf(fd, "\tHello time: %2d:%02d:%02d\t\tHello interval: %d\n",
|
|
tmp->tm_hour, tmp->tm_min, tmp->tm_sec, ngp->ng_hint);
|
|
tmp = localtime(&ngp->ng_stime);
|
|
fprintf(fd, "\tPoll time: %2d:%02d:%02d\t\tPoll interval: %d\n",
|
|
tmp->tm_hour, tmp->tm_min, tmp->tm_sec, ngp->ng_spint);
|
|
fprintf(fd, "\tState: <");
|
|
for (p = egp_states; p->t_bits != (u_int) -1; p++) {
|
|
if ( p->t_bits == ngp->ng_state ) {
|
|
fprintf(fd, p->t_name);
|
|
break;
|
|
}
|
|
}
|
|
fprintf(fd, ">\t\tReachability: <%s|%s>\n",
|
|
(ngp->ng_reach & NG_DOWN) ? "NG_DOWN" : "NG_UP",
|
|
(ngp->ng_reach & ME_DOWN) ? "ME_DOWN" : "ME_UP");
|
|
fprintf(fd, "\tLast poll received: %s", inet_ntoa(ngp->ng_paddr));
|
|
fprintf(fd, "\tNet to poll: %s\n", inet_ntoa(ngp->ng_saddr));
|
|
fprintf(fd, "\tFlags: %X <", ngp->ng_flags);
|
|
cp = "%s";
|
|
for (first = 1, p = egp_flags; p->t_bits > (u_int)0; p++) {
|
|
if ((ngp->ng_flags & p->t_bits)) {
|
|
fprintf(fd, cp, p->t_name);
|
|
if (first) {
|
|
cp = "|%s";
|
|
first = 0;
|
|
}
|
|
}
|
|
}
|
|
fprintf(fd, ">\n");
|
|
fprintf(fd, "\tMetricOut: ");
|
|
if ( (ngp->ng_flags & NG_METRICOUT) ) {
|
|
fprintf(fd, "%d", ngp->ng_metricout);
|
|
} else {
|
|
fprintf(fd, "N/A");
|
|
}
|
|
fprintf(fd, "\t\t\tMetricIn: ");
|
|
if ( (ngp->ng_flags & NG_METRICIN) ) {
|
|
fprintf(fd, "%d", ngp->ng_metricin);
|
|
} else {
|
|
fprintf(fd, "N/A");
|
|
}
|
|
fprintf(fd, "\n\tASout: ");
|
|
if ( (ngp->ng_flags & NG_ASOUT) ) {
|
|
fprintf(fd, "%d", ngp->ng_asout);
|
|
} else {
|
|
fprintf(fd, "N/A");
|
|
}
|
|
fprintf(fd, "\t\t\tASin: ");
|
|
if ((ngp->ng_flags & NG_ASIN) || ngp->ng_asin) {
|
|
fprintf(fd, "%d", ngp->ng_asin);
|
|
} else {
|
|
fprintf(fd, "N/A");
|
|
}
|
|
fprintf(fd, "\n\tAS: ");
|
|
if ((ngp->ng_flags & NG_AS) || ngp->ng_as) {
|
|
fprintf(fd, "%d", ngp->ng_as);
|
|
}
|
|
fprintf(fd, "\n\tDefaultMetric: ");
|
|
if ( (ngp->ng_flags & NG_DEFAULTOUT) ) {
|
|
fprintf(fd, "%d", ngp->ng_defaultmetric);
|
|
} else {
|
|
fprintf(fd, "N/A");
|
|
}
|
|
fprintf(fd, "\t\tGateway: ");
|
|
if ( (ngp->ng_flags & NG_GATEWAY) ) {
|
|
fprintf(fd, "%s", inet_ntoa(ngp->ng_gateway));
|
|
} else {
|
|
fprintf(fd, "N/A");
|
|
}
|
|
fprintf(fd, "\n");
|
|
}
|
|
fprintf(fd, "\n");
|
|
}
|
|
/*
|
|
* List all of the {no,}annoucetoAS clauses
|
|
*/
|
|
if (sendas) {
|
|
struct as_list *tmp_list;
|
|
struct as_entry *tmp_entry;
|
|
|
|
fprintf(fd, "AS restriction lists:\n");
|
|
for (tmp_list = sendas; tmp_list; tmp_list = tmp_list->next) {
|
|
fprintf(fd, "\tAS %d %s AS(s):",
|
|
tmp_list->as,
|
|
tmp_list->flags & AS_DONOTSEND ? "Does not receive" : "receives");
|
|
for (tmp_entry = tmp_list->as_ptr; tmp_entry; tmp_entry = tmp_entry->next) {
|
|
fprintf(fd, " %d", tmp_entry->as);
|
|
}
|
|
if (tmp_list == my_aslist) {
|
|
fprintf(fd, "*\n");
|
|
} else {
|
|
fprintf(fd, "\n");
|
|
}
|
|
}
|
|
fprintf(fd, "\n");
|
|
}
|
|
/*
|
|
* Dump the validAS list
|
|
*/
|
|
if (validas) {
|
|
struct as_valid *tmp_valid;
|
|
|
|
fprintf(fd, "AS validation:\n");
|
|
for (tmp_valid = validas; tmp_valid; tmp_valid = tmp_valid->next) {
|
|
fprintf(fd, "\tvalidAS %s AS %d metric %d\n",
|
|
inet_ntoa(tmp_valid->dst), tmp_valid->as, tmp_valid->metric);
|
|
}
|
|
fprintf(fd, "\n");
|
|
}
|
|
/*
|
|
* Dump the list of martian networks
|
|
*/
|
|
fprintf(fd, "Martian networks:\n\t");
|
|
cnt = 0;
|
|
for (mptr = martians; mptr; mptr = mptr->next) {
|
|
cp = inet_ntoa(mptr->destnet);
|
|
if ( (cnt+strlen(cp)+1) > 64 ) {
|
|
fprintf(fd, "\n\t");
|
|
cnt = 0;
|
|
}
|
|
cnt += strlen(cp) + 1;
|
|
fprintf(fd, "%s ", cp);
|
|
}
|
|
fprintf(fd, "\n");
|
|
#ifdef notdef
|
|
fprintf(fd, "\n-----------------------------------------------------------\n");
|
|
#endif notdef
|
|
/*
|
|
* Dump all the routing information
|
|
*/
|
|
fprintf(fd, "\n\nRouting Tables:\nEntries:\t%d\n", n_routes);
|
|
#ifndef NSS
|
|
fprintf(fd, "\tUnits:\n\t\tInternal metric:\tmilliseconds\n\t\tAge:\t\t\tseconds\n\n");
|
|
#else NSS
|
|
fprintf(fd, "\tUnits:\n\t\tInternal metric:\treachability\n\t\tAge:\tseconds\n\n");
|
|
#endif NSS
|
|
onemoretime:
|
|
for (rh = base; rh < &base[ROUTEHASHSIZ]; rh++) {
|
|
for (rt = rh->rt_forw; rt != (struct rt_entry *)rh; rt = rt->rt_forw) {
|
|
fprintf(fd,"\tDestination: %s\n", inet_ntoa(sock_inaddr(&rt->rt_dst)));
|
|
if (rt->rt_as != mysystem) {
|
|
fprintf(fd,"\tAutonomous System: %d\n", rt->rt_as);
|
|
}
|
|
fprintf(fd,"\tGateway: %s\n", inet_ntoa(sock_inaddr(&rt->rt_router)));
|
|
#ifndef NSS
|
|
fprintf(fd,"\tInterface: %s\n", rt->rt_ifp->int_name);
|
|
#endif NSS
|
|
fprintf(fd,"\tAge: %d\n", rt->rt_timer);
|
|
ch = "Unknown";
|
|
for (p = protobits; p->t_bits > (u_int)0; p++) {
|
|
if ( (rt->rt_proto == p->t_bits) ) {
|
|
ch = p->t_name;
|
|
break;
|
|
}
|
|
}
|
|
fprintf(fd, "\tProtocol: %s\n", ch);
|
|
fprintf(fd, "\tMetric: %d\n", rt->rt_metric);
|
|
if ( rt->rt_state & RTS_EXTERIOR ) {
|
|
fprintf(fd, "\tExterior Metric: %d\n", rt->rt_metric_exterior);
|
|
}
|
|
fprintf(fd, "\tFlags: <");
|
|
cp = "%s";
|
|
for (first = 1, p = flagbits; p->t_bits > (u_int)0; p++) {
|
|
if ((rt->rt_flags & p->t_bits) == 0)
|
|
continue;
|
|
fprintf(fd, cp, p->t_name);
|
|
if (first) {
|
|
cp = "|%s";
|
|
first = 0;
|
|
}
|
|
}
|
|
fprintf(fd, ">\n");
|
|
fprintf(fd, "\tState: <");
|
|
cp = "%s";
|
|
for (first = 1, p = statebits; p->t_bits > (u_int)0; p++) {
|
|
if ((rt->rt_state & p->t_bits) == 0)
|
|
continue;
|
|
fprintf(fd, cp, p->t_name);
|
|
if (first) {
|
|
cp = "|%s";
|
|
first = 0;
|
|
}
|
|
}
|
|
fprintf(fd, ">\n");
|
|
fprintf(fd, "\tFrom Protocol: <");
|
|
cp = "%s";
|
|
for (first = 1, p = protobits; p->t_bits > (u_int)0; p++) {
|
|
if ((rt->rt_fromproto & p->t_bits) == 0)
|
|
continue;
|
|
fprintf(fd, cp, p->t_name);
|
|
if (first) {
|
|
cp = "|%s";
|
|
first = 0;
|
|
}
|
|
}
|
|
fprintf(fd, ">\n");
|
|
if (rt->rt_proto & RTPROTO_HELLO) {
|
|
fprintf(fd, "\tMinimum HELLO time delay in last %d updates: %d\n",
|
|
HWINSIZE, rt->rt_hwindow.h_min);
|
|
fprintf(fd, "\tLast %d HELLO time delays:\n\t\t", HELLO_REPORT);
|
|
cnt = 0;
|
|
ind = rt->rt_hwindow.h_index;
|
|
while (cnt < HELLO_REPORT) {
|
|
fprintf(fd, "%d ", rt->rt_hwindow.h_win[ind]);
|
|
cnt++;
|
|
ind++;
|
|
if (ind >= HWINSIZE)
|
|
ind = 0;
|
|
}
|
|
fprintf(fd, "\n");
|
|
}
|
|
if (rt->rt_announcelist || rt->rt_noannouncelist || rt->rt_listenlist || rt->rt_srclisten ) {
|
|
fprintf(fd, "\tRestrictions:\n");
|
|
if (rt->rt_announcelist != NULL) {
|
|
fprintf(fd, "\t\tANNOUNCED via <");
|
|
cp = "%s";
|
|
for (first = 1, p = protobits; p->t_bits > (u_int)0; p++) {
|
|
if ((rt->rt_announcelist->rproto & p->t_bits) == 0) {
|
|
continue;
|
|
}
|
|
fprintf(fd, cp, p->t_name);
|
|
if (first) {
|
|
cp = "|%s";
|
|
first = 0;
|
|
}
|
|
}
|
|
fprintf(fd, "> ");
|
|
if (rt->rt_announcelist->rproto & RTPROTO_EGP) {
|
|
fprintf(fd, "EGP metric %d ", rt->rt_announcelist->regpmetric);
|
|
}
|
|
cntr = 0;
|
|
if (rt->rt_announcelist->rintf[cntr] == 0) {
|
|
fprintf(fd, "OUT ALL INTERFACES\n");
|
|
} else {
|
|
fprintf(fd, "OUT INTERFACES:\n");
|
|
while ((rt->rt_announcelist->rintf[cntr] != 0) || (cntr >= MAXINTERFACE)) {
|
|
fprintf(fd, "\t\t\t\t");
|
|
tmpos.s_addr = rt->rt_announcelist->rintf[cntr];
|
|
fprintf(fd, "%s\n", inet_ntoa(tmpos));
|
|
cntr++;
|
|
}
|
|
}
|
|
}
|
|
if (rt->rt_noannouncelist != NULL) {
|
|
fprintf(fd, "\t\tNOT ANNOUNCED via <");
|
|
cp = "%s";
|
|
for (first = 1, p = protobits; p->t_bits > (u_int)0; p++) {
|
|
if ((rt->rt_noannouncelist->rproto & p->t_bits) == 0) {
|
|
continue;
|
|
}
|
|
fprintf(fd, cp, p->t_name);
|
|
if (first) {
|
|
cp = "|%s";
|
|
first = 0;
|
|
}
|
|
}
|
|
fprintf(fd, "> ");
|
|
if (rt->rt_noannouncelist->rproto & RTPROTO_EGP) {
|
|
fprintf(fd, "EGP metric %d ", rt->rt_noannouncelist->regpmetric);
|
|
}
|
|
cntr = 0;
|
|
if (rt->rt_noannouncelist->rintf[cntr] == 0) {
|
|
fprintf(fd, "OUT ALL INTERFACES\n");
|
|
} else {
|
|
fprintf(fd, "OUT INTERFACES:\n");
|
|
while ((rt->rt_noannouncelist->rintf[cntr] != 0) || (cntr >= MAXINTERFACE)) {
|
|
fprintf(fd, "\t\t\t\t");
|
|
tmpos.s_addr = rt->rt_noannouncelist->rintf[cntr];
|
|
fprintf(fd, "%s\n", inet_ntoa(tmpos));
|
|
cntr++;
|
|
}
|
|
}
|
|
}
|
|
if (rt->rt_listenlist != NULL) {
|
|
fprintf(fd, "\t\tNOTLISTENEDTO via <");
|
|
cp = "%s";
|
|
for (first = 1, p = protobits; p->t_bits > (u_int)0; p++) {
|
|
if ((rt->rt_listenlist->rproto & p->t_bits) == 0) {
|
|
continue;
|
|
}
|
|
fprintf(fd, cp, p->t_name);
|
|
if (first) {
|
|
cp = "|%s";
|
|
first = 0;
|
|
}
|
|
}
|
|
fprintf(fd, "> ");
|
|
if (rt->rt_listenlist->rproto & RTPROTO_EGP) {
|
|
fprintf(fd, "EGP metric %d ", rt->rt_listenlist->regpmetric);
|
|
}
|
|
cntr = 0;
|
|
if (rt->rt_listenlist->rintf[cntr] == 0) {
|
|
fprintf(fd, "FROM ALL INTERFACES\n");
|
|
} else {
|
|
fprintf(fd, "FROM INTERFACES:\n");
|
|
while ((rt->rt_listenlist->rintf[cntr] != 0) || (cntr >= MAXINTERFACE)) {
|
|
fprintf(fd, "\t\t\t\t");
|
|
tmpos.s_addr = rt->rt_listenlist->rintf[cntr];
|
|
fprintf(fd, "%s\n", inet_ntoa(tmpos));
|
|
cntr++;
|
|
}
|
|
}
|
|
}
|
|
if (rt->rt_srclisten != NULL) {
|
|
fprintf(fd, "\t\tLISTENEDTO via <");
|
|
cp = "%s";
|
|
for (first = 1, p = protobits; p->t_bits > (u_int)0; p++) {
|
|
if ((rt->rt_srclisten->rproto & p->t_bits) == 0) {
|
|
continue;
|
|
}
|
|
fprintf(fd, cp, p->t_name);
|
|
if (first) {
|
|
cp = "|%s";
|
|
first = 0;
|
|
}
|
|
}
|
|
fprintf(fd, "> ");
|
|
if (rt->rt_srclisten->rproto & RTPROTO_EGP) {
|
|
fprintf(fd, "EGP metric %d ", rt->rt_srclisten->regpmetric);
|
|
}
|
|
cntr = 0;
|
|
if (rt->rt_srclisten->rintf[cntr] == 0) {
|
|
fprintf(fd, "FROM ALL GATEWAYS\n");
|
|
} else {
|
|
fprintf(fd, "FROM GATEWAYS:\n");
|
|
while ((rt->rt_srclisten->rintf[cntr] != 0) || (cntr >= MAXINTERFACE)) {
|
|
fprintf(fd, "\t\t\t\t");
|
|
tmpos.s_addr = rt->rt_srclisten->rintf[cntr];
|
|
fprintf(fd, "%s\n", inet_ntoa(tmpos));
|
|
cntr++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
fprintf(fd, "\n");
|
|
}
|
|
}
|
|
if (doinghost) {
|
|
base = nethash;
|
|
doinghost = 0;
|
|
goto onemoretime;
|
|
}
|
|
(void) fflush(fd);
|
|
(void) fclose(fd);
|
|
syslog(LOG_NOTICE, "dumpinfo: dump completed to %s", DUMPFILE);
|
|
TRACE_TRC("dumpinfo: dump completed to %s at %s", DUMPFILE, strtime);
|
|
}
|
|
|
|
|
|
#ifdef NSS
|
|
gated_trace(sock, pkt, size, src, dst)
|
|
int sock;
|
|
char *pkt;
|
|
int size;
|
|
struct sockaddr_in src, dst;
|
|
{
|
|
if (tracing & TR_EGP) {
|
|
tracercv(sock, IPPROTO_EGP, pkt, size, &src);
|
|
}
|
|
}
|
|
#endif NSS
|
|
|
|
|
|
#ifdef EGP_UPDATE_FORMAT
|
|
/*
|
|
* Format an EGP network update packet
|
|
*/
|
|
|
|
NR_format(nr, nr_length)
|
|
struct egpnr *nr;
|
|
int nr_length;
|
|
{
|
|
int gateways, distances, networks;
|
|
int distance, t_gateways;
|
|
int shared_net_class, net_class;
|
|
char class;
|
|
u_char *nr_ptr, *nr_end;
|
|
struct in_addr gateway, network;
|
|
|
|
shared_net_class = gd_inet_class((u_char *)&nr->en_net);
|
|
bcopy((char *) &nr->en_net, (char *)&gateway, shared_net_class);
|
|
nr_ptr = (u_char *)nr + sizeof(struct egpnr);
|
|
nr_end = (u_char *)nr + nr_length;
|
|
printf("net %s (%c) - %d interior gateways, %d exterior gateways\n",
|
|
inet_ntoa(nr->en_net), 'A' - 1 + shared_net_class,
|
|
nr->en_igw, nr->en_egw);
|
|
t_gateways = nr->en_igw + nr->en_egw;
|
|
for ( gateways = 0; gateways < t_gateways; gateways++) {
|
|
bcopy((char *)nr_ptr, (char *)&gateway + shared_net_class, 4 - shared_net_class);
|
|
nr_ptr += 4 - shared_net_class;
|
|
distances = (u_char) *nr_ptr;
|
|
nr_ptr++;
|
|
printf("\t%s gateway %s, %d distances\n",
|
|
gateways < nr->en_igw ? "interior" : "exterior",
|
|
inet_ntoa(gateway), distances);
|
|
for ( ; distances; distances-- ) {
|
|
distance = (u_char) *nr_ptr;
|
|
nr_ptr++;
|
|
networks = (u_char) *nr_ptr;
|
|
nr_ptr++;
|
|
printf("\t\tdistance %d, %d networks\n",
|
|
distance, networks);
|
|
for ( ; networks; networks-- ) {
|
|
bzero((char *)&network, sizeof(struct in_addr));
|
|
if ( (net_class = gd_inet_class(nr_ptr)) == 0 ) {
|
|
net_class = CLAC;
|
|
class = '?';
|
|
} else {
|
|
class = 'A' - 1 + net_class;
|
|
}
|
|
bcopy((char *)nr_ptr, (char *)&network, net_class);
|
|
nr_ptr += net_class;
|
|
printf("\t\t\t(%c) %s\n",
|
|
class, inet_ntoa(network));
|
|
if ( nr_ptr > nr_end ) {
|
|
printf("\tpacket smashed\n");
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
#endif EGP_UPDATE_FORMAT
|