trace.c revision 15248
1/* 2 * Copyright (c) 1985, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * Copyright (c) 1995 John Hay. All rights reserved. 6 * 7 * This file includes significant work done at Cornell University by 8 * Bill Nesheim. That work included by permission. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. All advertising materials mentioning features or use of this software 19 * must display the following acknowledgement: 20 * This product includes software developed by the University of 21 * California, Berkeley and its contributors. 22 * 4. Neither the name of the University nor the names of its contributors 23 * may be used to endorse or promote products derived from this software 24 * without specific prior written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 29 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 36 * SUCH DAMAGE. 37 * 38 * $Id: trace.c,v 1.1 1995/10/26 21:28:29 julian Exp $ 39 */ 40 41#ifndef lint 42static char sccsid[] = "@(#)trace.c 8.1 (Berkeley) 6/5/93"; 43#endif /* not lint */ 44 45/* 46 * Routing Table Management Daemon 47 */ 48#define RIPCMDS 49#define SAPCMDS 50#include <stdlib.h> 51#include <unistd.h> 52#include <sys/types.h> 53#include <time.h> 54#include "defs.h" 55 56#define NRECORDS 50 /* size of circular trace buffer */ 57#ifdef DEBUG 58FILE *ftrace = stdout; 59int tracing = 1; 60#else DEBUG 61FILE *ftrace = NULL; 62int tracing = 0; 63#endif 64 65void dumpif(FILE *fd, struct interface *ifp); 66void dumptrace(FILE *fd, char *dir, struct ifdebug *ifd); 67 68void 69traceinit(ifp) 70 register struct interface *ifp; 71{ 72 static int iftraceinit(); 73 74 if (iftraceinit(ifp, &ifp->int_input) && 75 iftraceinit(ifp, &ifp->int_output)) 76 return; 77 tracing = 0; 78 syslog(LOG_ERR, "traceinit: can't init %s\n", ifp->int_name); 79} 80 81static int 82iftraceinit(ifp, ifd) 83 struct interface *ifp; 84 register struct ifdebug *ifd; 85{ 86 register struct iftrace *t; 87 88 ifd->ifd_records = 89 (struct iftrace *)malloc(NRECORDS * sizeof (struct iftrace)); 90 if (ifd->ifd_records == 0) 91 return (0); 92 ifd->ifd_front = ifd->ifd_records; 93 ifd->ifd_count = 0; 94 for (t = ifd->ifd_records; t < ifd->ifd_records + NRECORDS; t++) { 95 t->ift_size = 0; 96 t->ift_packet = 0; 97 } 98 ifd->ifd_if = ifp; 99 return (1); 100} 101 102void 103traceon(file) 104 char *file; 105{ 106 107 if (ftrace != NULL) 108 return; 109 ftrace = fopen(file, "a"); 110 if (ftrace == NULL) 111 return; 112 dup2(fileno(ftrace), 1); 113 dup2(fileno(ftrace), 2); 114 tracing = 1; 115} 116 117void 118traceoff(void) 119{ 120 if (!tracing) 121 return; 122 if (ftrace != NULL) 123 fclose(ftrace); 124 ftrace = NULL; 125 tracing = 0; 126} 127 128void 129trace(ifd, who, p, len, m) 130 register struct ifdebug *ifd; 131 struct sockaddr *who; 132 char *p; 133 int len, m; 134{ 135 register struct iftrace *t; 136 137 if (ifd->ifd_records == 0) 138 return; 139 t = ifd->ifd_front++; 140 if (ifd->ifd_front >= ifd->ifd_records + NRECORDS) 141 ifd->ifd_front = ifd->ifd_records; 142 if (ifd->ifd_count < NRECORDS) 143 ifd->ifd_count++; 144 if (t->ift_size > 0 && t->ift_packet) 145 free(t->ift_packet); 146 t->ift_packet = 0; 147 t->ift_stamp = time(0); 148 t->ift_who = *who; 149 if (len > 0) { 150 t->ift_packet = malloc(len); 151 if (t->ift_packet) 152 bcopy(p, t->ift_packet, len); 153 else 154 len = 0; 155 } 156 t->ift_size = len; 157 t->ift_metric = m; 158} 159 160void 161traceaction(fd, action, rt) 162 FILE *fd; 163 char *action; 164 struct rt_entry *rt; 165{ 166 struct sockaddr_ipx *dst, *gate; 167 static struct bits { 168 int t_bits; 169 char *t_name; 170 } flagbits[] = { 171 { RTF_UP, "UP" }, 172 { RTF_GATEWAY, "GATEWAY" }, 173 { RTF_HOST, "HOST" }, 174 { 0 } 175 }, statebits[] = { 176 { RTS_PASSIVE, "PASSIVE" }, 177 { RTS_REMOTE, "REMOTE" }, 178 { RTS_INTERFACE,"INTERFACE" }, 179 { RTS_CHANGED, "CHANGED" }, 180 { 0 } 181 }; 182 register struct bits *p; 183 register int first; 184 char *cp; 185 186 if (fd == NULL) 187 return; 188 fprintf(fd, "%s ", action); 189 dst = (struct sockaddr_ipx *)&rt->rt_dst; 190 gate = (struct sockaddr_ipx *)&rt->rt_router; 191 fprintf(fd, "dst %s, ", ipxdp_ntoa(&dst->sipx_addr)); 192 fprintf(fd, "router %s, metric %d, ticks %d, flags", 193 ipxdp_ntoa(&gate->sipx_addr), rt->rt_metric, rt->rt_ticks); 194 cp = " %s"; 195 for (first = 1, p = flagbits; p->t_bits > 0; p++) { 196 if ((rt->rt_flags & p->t_bits) == 0) 197 continue; 198 fprintf(fd, cp, p->t_name); 199 if (first) { 200 cp = "|%s"; 201 first = 0; 202 } 203 } 204 fprintf(fd, " state"); 205 cp = " %s"; 206 for (first = 1, p = statebits; p->t_bits > 0; p++) { 207 if ((rt->rt_state & p->t_bits) == 0) 208 continue; 209 fprintf(fd, cp, p->t_name); 210 if (first) { 211 cp = "|%s"; 212 first = 0; 213 } 214 } 215 putc('\n', fd); 216 if (!tracepackets && (rt->rt_state & RTS_PASSIVE) == 0 && rt->rt_ifp) 217 dumpif(fd, rt->rt_ifp); 218 fflush(fd); 219} 220 221void 222dumpif(fd, ifp) 223 register struct interface *ifp; 224 FILE *fd; 225{ 226 if (ifp->int_input.ifd_count || ifp->int_output.ifd_count) { 227 fprintf(fd, "*** Packet history for interface %s ***\n", 228 ifp->int_name); 229 dumptrace(fd, "to", &ifp->int_output); 230 dumptrace(fd, "from", &ifp->int_input); 231 fprintf(fd, "*** end packet history ***\n"); 232 } 233} 234 235void 236dumptrace(fd, dir, ifd) 237 FILE *fd; 238 char *dir; 239 register struct ifdebug *ifd; 240{ 241 register struct iftrace *t; 242 char *cp = !strcmp(dir, "to") ? "Output" : "Input"; 243 244 if (ifd->ifd_front == ifd->ifd_records && 245 ifd->ifd_front->ift_size == 0) { 246 fprintf(fd, "%s: no packets.\n", cp); 247 return; 248 } 249 fprintf(fd, "%s trace:\n", cp); 250 t = ifd->ifd_front - ifd->ifd_count; 251 if (t < ifd->ifd_records) 252 t += NRECORDS; 253 for ( ; ifd->ifd_count; ifd->ifd_count--, t++) { 254 if (t >= ifd->ifd_records + NRECORDS) 255 t = ifd->ifd_records; 256 if (t->ift_size == 0) 257 continue; 258 fprintf(fd, "%.24s: metric=%d\n", ctime(&t->ift_stamp), 259 t->ift_metric); 260 dumppacket(fd, dir, &t->ift_who, t->ift_packet, t->ift_size); 261 } 262} 263 264void 265dumppacket(fd, dir, source, cp, size) 266 FILE *fd; 267 char *dir; 268 struct sockaddr *source; 269 char *cp; 270 register int size; 271{ 272 register struct rip *msg = (struct rip *)cp; 273 register struct netinfo *n; 274 struct sockaddr_ipx *who = (struct sockaddr_ipx *)source; 275 276 if (msg->rip_cmd && ntohs(msg->rip_cmd) < RIPCMD_MAX) 277 fprintf(fd, "%s %s %s#%x", ripcmds[ntohs(msg->rip_cmd)], 278 dir, ipxdp_ntoa(&who->sipx_addr), 279 ntohs(who->sipx_addr.x_port)); 280 else { 281 fprintf(fd, "Bad cmd 0x%x %s %s#%x\n", ntohs(msg->rip_cmd), 282 dir, ipxdp_ntoa(&who->sipx_addr), 283 ntohs(who->sipx_addr.x_port)); 284 fprintf(fd, "size=%d cp=%x packet=%x\n", size, 285 (u_int)cp, (u_int)packet); 286 return; 287 } 288 switch (ntohs(msg->rip_cmd)) { 289 290 case RIPCMD_REQUEST: 291 case RIPCMD_RESPONSE: 292 fprintf(fd, ":\n"); 293 size -= sizeof (u_short); 294 n = msg->rip_nets; 295 for (; size > 0; n++, size -= sizeof (struct netinfo)) { 296 if (size < sizeof (struct netinfo)) 297 break; 298 fprintf(fd, "\tnet %s metric %d ticks %d\n", 299 ipxdp_nettoa(n->rip_dst), 300 ntohs(n->rip_metric), 301 ntohs(n->rip_ticks)); 302 } 303 break; 304 305 } 306} 307 308void 309dumpsappacket(fd, dir, source, cp, size) 310 FILE *fd; 311 char *dir; 312 struct sockaddr *source; 313 char *cp; 314 register int size; 315{ 316 register struct sap_packet *msg = (struct sap_packet *)cp; 317 register struct sap_info *n; 318 struct sockaddr_ipx *who = (struct sockaddr_ipx *)source; 319 320 if (msg->sap_cmd && ntohs(msg->sap_cmd) < SAPCMD_MAX) 321 fprintf(fd, "%s %s %s#%x", sapcmds[ntohs(msg->sap_cmd)], 322 dir, ipxdp_ntoa(&who->sipx_addr), 323 ntohs(who->sipx_addr.x_port)); 324 else { 325 fprintf(fd, "Bad cmd 0x%x %s %s#%x\n", ntohs(msg->sap_cmd), 326 dir, ipxdp_ntoa(&who->sipx_addr), 327 ntohs(who->sipx_addr.x_port)); 328 fprintf(fd, "size=%d cp=%x packet=%x\n", size, 329 (u_int)cp, (u_int)packet); 330 return; 331 } 332 switch (ntohs(msg->sap_cmd)) { 333 334 case SAP_REQ: 335 case SAP_RESP: 336 case SAP_REQ_NEAR: 337 case SAP_RESP_NEAR: 338 fprintf(fd, ":\n"); 339 size -= sizeof (u_short); 340 n = msg->sap; 341 for (; size > 0; n++, size -= sizeof (struct sap_info)) { 342 if (size < sizeof (struct sap_info)) 343 break; 344 fprintf(fd, " service %04X %-20.20s " 345 "addr %s.%04X metric %d\n", 346 ntohs(n->ServType), 347 n->ServName, 348 ipxdp_ntoa(&n->ipx), 349 ntohs(n->ipx.x_port), 350 ntohs(n->hops)); 351 } 352 break; 353 354 } 355} 356 357void 358dumpsaptable(fd, sh) 359 FILE *fd; 360 struct sap_hash *sh; 361{ 362 register struct sap_entry *sap; 363 struct sap_hash *hash; 364 int x = 0; 365 366 fprintf(fd, "------- SAP table dump. -------\n"); 367 for (hash = sh; hash < &sh[SAPHASHSIZ]; hash++, x++) { 368 fprintf(fd, "HASH %d\n", x); 369 sap = hash->forw; 370 for (; sap != (struct sap_entry *)hash; sap = sap->forw) { 371 fprintf(fd, " service %04X %-20.20s " 372 "addr %s.%04X %c metric %d\n", 373 ntohs(sap->sap.ServType), 374 sap->sap.ServName, 375 ipxdp_ntoa(&sap->sap.ipx), 376 ntohs(sap->sap.ipx.x_port), 377 (sap->clone ? 'C' : ' '), 378 ntohs(sap->sap.hops)); 379 } 380 } 381 fprintf(fd, "\n"); 382} 383 384void 385dumpriptable(fd) 386 FILE *fd; 387{ 388 register struct rt_entry *rip; 389 struct rthash *hash; 390 int x; 391 struct rthash *rh = nethash; 392 393 fprintf(fd, "------- RIP table dump. -------\n"); 394 x = 0; 395 fprintf(fd, "Network table.\n"); 396 397 for (hash = rh; hash < &rh[ROUTEHASHSIZ]; hash++, x++) { 398 fprintf(fd, "HASH %d\n", x); 399 rip = hash->rt_forw; 400 for (; rip != (struct rt_entry *)hash; rip = rip->rt_forw) { 401 fprintf(fd, " dest %s\t", 402 ipxdp_ntoa(&satoipx_addr(rip->rt_dst))); 403 fprintf(fd, "%s metric %d, ticks %d\n", 404 ipxdp_ntoa(&satoipx_addr(rip->rt_router)), 405 rip->rt_metric, 406 rip->rt_ticks); 407 } 408 } 409 fprintf(fd, "\n"); 410} 411 412union ipx_net_u net; 413 414char * 415ipxdp_nettoa(val) 416union ipx_net val; 417{ 418 static char buf[100]; 419 net.net_e = val; 420 (void)sprintf(buf, "%lx", ntohl(net.long_e)); 421 return (buf); 422} 423 424 425char * 426ipxdp_ntoa(addr) 427struct ipx_addr *addr; 428{ 429 static char buf[100]; 430 431 (void)sprintf(buf, "%s#%x:%x:%x:%x:%x:%x", 432 ipxdp_nettoa(addr->x_net), 433 addr->x_host.c_host[0], addr->x_host.c_host[1], 434 addr->x_host.c_host[2], addr->x_host.c_host[3], 435 addr->x_host.c_host[4], addr->x_host.c_host[5]); 436 437 return(buf); 438} 439