1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * CDDL HEADER START 3*7c478bd9Sstevel@tonic-gate * 4*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*7c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*7c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*7c478bd9Sstevel@tonic-gate * with the License. 8*7c478bd9Sstevel@tonic-gate * 9*7c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*7c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*7c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 12*7c478bd9Sstevel@tonic-gate * and limitations under the License. 13*7c478bd9Sstevel@tonic-gate * 14*7c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*7c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*7c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*7c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*7c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*7c478bd9Sstevel@tonic-gate * 20*7c478bd9Sstevel@tonic-gate * CDDL HEADER END 21*7c478bd9Sstevel@tonic-gate */ 22*7c478bd9Sstevel@tonic-gate /* 23*7c478bd9Sstevel@tonic-gate * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 24*7c478bd9Sstevel@tonic-gate * Use is subject to license terms. 25*7c478bd9Sstevel@tonic-gate */ 26*7c478bd9Sstevel@tonic-gate 27*7c478bd9Sstevel@tonic-gate /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */ 28*7c478bd9Sstevel@tonic-gate /* All Rights Reserved */ 29*7c478bd9Sstevel@tonic-gate 30*7c478bd9Sstevel@tonic-gate /* 31*7c478bd9Sstevel@tonic-gate * Portions of this source code were derived from Berkeley 4.3 BSD 32*7c478bd9Sstevel@tonic-gate * under license from the Regents of the University of California. 33*7c478bd9Sstevel@tonic-gate */ 34*7c478bd9Sstevel@tonic-gate 35*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" /* SVr4.0 1.1 */ 36*7c478bd9Sstevel@tonic-gate 37*7c478bd9Sstevel@tonic-gate /* 38*7c478bd9Sstevel@tonic-gate * Routing Table Management Daemon 39*7c478bd9Sstevel@tonic-gate */ 40*7c478bd9Sstevel@tonic-gate #include "defs.h" 41*7c478bd9Sstevel@tonic-gate 42*7c478bd9Sstevel@tonic-gate #define NRECORDS 50 /* size of circular trace buffer */ 43*7c478bd9Sstevel@tonic-gate 44*7c478bd9Sstevel@tonic-gate boolean_t tracepackets; /* watch packets as they go by */ 45*7c478bd9Sstevel@tonic-gate int tracing; /* bitmask: */ 46*7c478bd9Sstevel@tonic-gate FILE *ftrace; /* output trace file */ 47*7c478bd9Sstevel@tonic-gate 48*7c478bd9Sstevel@tonic-gate static int iftraceinit(struct interface *ifp, struct ifdebug *ifd); 49*7c478bd9Sstevel@tonic-gate static void dumpif(FILE *fp, struct interface *ifp); 50*7c478bd9Sstevel@tonic-gate static void dumptrace(FILE *fp, char *dir, struct ifdebug *ifd); 51*7c478bd9Sstevel@tonic-gate 52*7c478bd9Sstevel@tonic-gate void 53*7c478bd9Sstevel@tonic-gate traceinit(struct interface *ifp) 54*7c478bd9Sstevel@tonic-gate { 55*7c478bd9Sstevel@tonic-gate if (iftraceinit(ifp, &ifp->int_input) && 56*7c478bd9Sstevel@tonic-gate iftraceinit(ifp, &ifp->int_output)) 57*7c478bd9Sstevel@tonic-gate return; 58*7c478bd9Sstevel@tonic-gate tracing = 0; 59*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "traceinit: can't init %s\n", 60*7c478bd9Sstevel@tonic-gate (ifp->int_name != NULL) ? ifp->int_name : "(noname)"); 61*7c478bd9Sstevel@tonic-gate } 62*7c478bd9Sstevel@tonic-gate 63*7c478bd9Sstevel@tonic-gate static int 64*7c478bd9Sstevel@tonic-gate iftraceinit(struct interface *ifp, struct ifdebug *ifd) 65*7c478bd9Sstevel@tonic-gate { 66*7c478bd9Sstevel@tonic-gate struct iftrace *t; 67*7c478bd9Sstevel@tonic-gate 68*7c478bd9Sstevel@tonic-gate ifd->ifd_records = (struct iftrace *) 69*7c478bd9Sstevel@tonic-gate malloc((size_t)NRECORDS * sizeof (struct iftrace)); 70*7c478bd9Sstevel@tonic-gate if (ifd->ifd_records == NULL) 71*7c478bd9Sstevel@tonic-gate return (0); 72*7c478bd9Sstevel@tonic-gate ifd->ifd_front = ifd->ifd_records; 73*7c478bd9Sstevel@tonic-gate ifd->ifd_count = 0; 74*7c478bd9Sstevel@tonic-gate for (t = ifd->ifd_records; t < ifd->ifd_records + NRECORDS; t++) { 75*7c478bd9Sstevel@tonic-gate t->ift_size = 0; 76*7c478bd9Sstevel@tonic-gate t->ift_packet = NULL; 77*7c478bd9Sstevel@tonic-gate } 78*7c478bd9Sstevel@tonic-gate ifd->ifd_if = ifp; 79*7c478bd9Sstevel@tonic-gate return (1); 80*7c478bd9Sstevel@tonic-gate } 81*7c478bd9Sstevel@tonic-gate 82*7c478bd9Sstevel@tonic-gate void 83*7c478bd9Sstevel@tonic-gate traceon(char *file) 84*7c478bd9Sstevel@tonic-gate { 85*7c478bd9Sstevel@tonic-gate struct stat stbuf; 86*7c478bd9Sstevel@tonic-gate 87*7c478bd9Sstevel@tonic-gate if (ftrace != NULL) 88*7c478bd9Sstevel@tonic-gate return; 89*7c478bd9Sstevel@tonic-gate if (stat(file, &stbuf) >= 0 && (stbuf.st_mode & S_IFMT) != S_IFREG) 90*7c478bd9Sstevel@tonic-gate return; 91*7c478bd9Sstevel@tonic-gate ftrace = fopen(file, "a"); 92*7c478bd9Sstevel@tonic-gate if (ftrace == NULL) 93*7c478bd9Sstevel@tonic-gate return; 94*7c478bd9Sstevel@tonic-gate (void) dup2(fileno(ftrace), 1); 95*7c478bd9Sstevel@tonic-gate (void) dup2(fileno(ftrace), 2); 96*7c478bd9Sstevel@tonic-gate } 97*7c478bd9Sstevel@tonic-gate 98*7c478bd9Sstevel@tonic-gate void 99*7c478bd9Sstevel@tonic-gate traceonfp(FILE *fp) 100*7c478bd9Sstevel@tonic-gate { 101*7c478bd9Sstevel@tonic-gate if (ftrace != NULL) 102*7c478bd9Sstevel@tonic-gate return; 103*7c478bd9Sstevel@tonic-gate ftrace = fp; 104*7c478bd9Sstevel@tonic-gate if (ftrace == NULL) 105*7c478bd9Sstevel@tonic-gate return; 106*7c478bd9Sstevel@tonic-gate (void) dup2(fileno(ftrace), 1); 107*7c478bd9Sstevel@tonic-gate (void) dup2(fileno(ftrace), 2); 108*7c478bd9Sstevel@tonic-gate } 109*7c478bd9Sstevel@tonic-gate 110*7c478bd9Sstevel@tonic-gate void 111*7c478bd9Sstevel@tonic-gate trace(struct ifdebug *ifd, struct sockaddr_in6 *who, char *p, int len, int m) 112*7c478bd9Sstevel@tonic-gate { 113*7c478bd9Sstevel@tonic-gate struct iftrace *t; 114*7c478bd9Sstevel@tonic-gate 115*7c478bd9Sstevel@tonic-gate if (ifd->ifd_records == 0) 116*7c478bd9Sstevel@tonic-gate return; 117*7c478bd9Sstevel@tonic-gate t = ifd->ifd_front++; 118*7c478bd9Sstevel@tonic-gate if (ifd->ifd_front >= ifd->ifd_records + NRECORDS) 119*7c478bd9Sstevel@tonic-gate ifd->ifd_front = ifd->ifd_records; 120*7c478bd9Sstevel@tonic-gate if (ifd->ifd_count < NRECORDS) 121*7c478bd9Sstevel@tonic-gate ifd->ifd_count++; 122*7c478bd9Sstevel@tonic-gate if (t->ift_size > 0 && t->ift_size < len && t->ift_packet != NULL) { 123*7c478bd9Sstevel@tonic-gate free(t->ift_packet); 124*7c478bd9Sstevel@tonic-gate t->ift_packet = NULL; 125*7c478bd9Sstevel@tonic-gate } 126*7c478bd9Sstevel@tonic-gate (void) time(&t->ift_stamp); 127*7c478bd9Sstevel@tonic-gate t->ift_who = *who; 128*7c478bd9Sstevel@tonic-gate if (len > 0 && t->ift_packet == NULL) { 129*7c478bd9Sstevel@tonic-gate t->ift_packet = (char *)malloc((size_t)len); 130*7c478bd9Sstevel@tonic-gate if (t->ift_packet == NULL) 131*7c478bd9Sstevel@tonic-gate len = 0; 132*7c478bd9Sstevel@tonic-gate } 133*7c478bd9Sstevel@tonic-gate if (len > 0) 134*7c478bd9Sstevel@tonic-gate bcopy(p, t->ift_packet, len); 135*7c478bd9Sstevel@tonic-gate t->ift_size = len; 136*7c478bd9Sstevel@tonic-gate t->ift_metric = m; 137*7c478bd9Sstevel@tonic-gate } 138*7c478bd9Sstevel@tonic-gate 139*7c478bd9Sstevel@tonic-gate void 140*7c478bd9Sstevel@tonic-gate traceaction(FILE *fp, char *action, struct rt_entry *rt) 141*7c478bd9Sstevel@tonic-gate { 142*7c478bd9Sstevel@tonic-gate static struct bits { 143*7c478bd9Sstevel@tonic-gate ulong_t t_bits; 144*7c478bd9Sstevel@tonic-gate char *t_name; 145*7c478bd9Sstevel@tonic-gate } flagbits[] = { 146*7c478bd9Sstevel@tonic-gate /* BEGIN CSTYLED */ 147*7c478bd9Sstevel@tonic-gate { RTF_UP, "UP" }, 148*7c478bd9Sstevel@tonic-gate { RTF_GATEWAY, "GATEWAY" }, 149*7c478bd9Sstevel@tonic-gate { RTF_HOST, "HOST" }, 150*7c478bd9Sstevel@tonic-gate { 0, NULL } 151*7c478bd9Sstevel@tonic-gate /* END CSTYLED */ 152*7c478bd9Sstevel@tonic-gate }, statebits[] = { 153*7c478bd9Sstevel@tonic-gate /* BEGIN CSTYLED */ 154*7c478bd9Sstevel@tonic-gate { RTS_INTERFACE, "INTERFACE" }, 155*7c478bd9Sstevel@tonic-gate { RTS_CHANGED, "CHANGED" }, 156*7c478bd9Sstevel@tonic-gate { RTS_PRIVATE, "PRIVATE" }, 157*7c478bd9Sstevel@tonic-gate { 0, NULL } 158*7c478bd9Sstevel@tonic-gate /* END CSTYLED */ 159*7c478bd9Sstevel@tonic-gate }; 160*7c478bd9Sstevel@tonic-gate struct bits *p; 161*7c478bd9Sstevel@tonic-gate boolean_t first; 162*7c478bd9Sstevel@tonic-gate char c; 163*7c478bd9Sstevel@tonic-gate time_t t; 164*7c478bd9Sstevel@tonic-gate 165*7c478bd9Sstevel@tonic-gate if (fp == NULL) 166*7c478bd9Sstevel@tonic-gate return; 167*7c478bd9Sstevel@tonic-gate (void) time(&t); 168*7c478bd9Sstevel@tonic-gate (void) fprintf(fp, "%.15s %s ", ctime(&t) + 4, action); 169*7c478bd9Sstevel@tonic-gate if (rt != NULL) { 170*7c478bd9Sstevel@tonic-gate char buf1[INET6_ADDRSTRLEN]; 171*7c478bd9Sstevel@tonic-gate 172*7c478bd9Sstevel@tonic-gate (void) fprintf(fp, "prefix %s/%d ", 173*7c478bd9Sstevel@tonic-gate inet_ntop(AF_INET6, (void *)&rt->rt_dst, buf1, 174*7c478bd9Sstevel@tonic-gate sizeof (buf1)), 175*7c478bd9Sstevel@tonic-gate rt->rt_prefix_length); 176*7c478bd9Sstevel@tonic-gate (void) fprintf(fp, "via %s metric %d", 177*7c478bd9Sstevel@tonic-gate inet_ntop(AF_INET6, (void *)&rt->rt_router, buf1, 178*7c478bd9Sstevel@tonic-gate sizeof (buf1)), 179*7c478bd9Sstevel@tonic-gate rt->rt_metric); 180*7c478bd9Sstevel@tonic-gate if (rt->rt_ifp != NULL) { 181*7c478bd9Sstevel@tonic-gate (void) fprintf(fp, " if %s", 182*7c478bd9Sstevel@tonic-gate (rt->rt_ifp->int_name != NULL) ? 183*7c478bd9Sstevel@tonic-gate rt->rt_ifp->int_name : "(noname)"); 184*7c478bd9Sstevel@tonic-gate } 185*7c478bd9Sstevel@tonic-gate (void) fprintf(fp, " state"); 186*7c478bd9Sstevel@tonic-gate c = ' '; 187*7c478bd9Sstevel@tonic-gate for (first = _B_TRUE, p = statebits; p->t_bits > 0; p++) { 188*7c478bd9Sstevel@tonic-gate if ((rt->rt_state & p->t_bits) == 0) 189*7c478bd9Sstevel@tonic-gate continue; 190*7c478bd9Sstevel@tonic-gate (void) fprintf(fp, "%c%s", c, p->t_name); 191*7c478bd9Sstevel@tonic-gate if (first) { 192*7c478bd9Sstevel@tonic-gate c = '|'; 193*7c478bd9Sstevel@tonic-gate first = _B_FALSE; 194*7c478bd9Sstevel@tonic-gate } 195*7c478bd9Sstevel@tonic-gate } 196*7c478bd9Sstevel@tonic-gate if (first) 197*7c478bd9Sstevel@tonic-gate (void) fprintf(fp, " 0"); 198*7c478bd9Sstevel@tonic-gate if (rt->rt_flags & (RTF_UP | RTF_GATEWAY)) { 199*7c478bd9Sstevel@tonic-gate c = ' '; 200*7c478bd9Sstevel@tonic-gate for (first = _B_TRUE, p = flagbits; p->t_bits > 0; 201*7c478bd9Sstevel@tonic-gate p++) { 202*7c478bd9Sstevel@tonic-gate if ((rt->rt_flags & p->t_bits) == 0) 203*7c478bd9Sstevel@tonic-gate continue; 204*7c478bd9Sstevel@tonic-gate (void) fprintf(fp, "%c%s", c, p->t_name); 205*7c478bd9Sstevel@tonic-gate if (first) { 206*7c478bd9Sstevel@tonic-gate c = '|'; 207*7c478bd9Sstevel@tonic-gate first = _B_FALSE; 208*7c478bd9Sstevel@tonic-gate } 209*7c478bd9Sstevel@tonic-gate } 210*7c478bd9Sstevel@tonic-gate } 211*7c478bd9Sstevel@tonic-gate } 212*7c478bd9Sstevel@tonic-gate (void) putc('\n', fp); 213*7c478bd9Sstevel@tonic-gate if (!tracepackets && rt != NULL && rt->rt_ifp != NULL) 214*7c478bd9Sstevel@tonic-gate dumpif(fp, rt->rt_ifp); 215*7c478bd9Sstevel@tonic-gate (void) fflush(fp); 216*7c478bd9Sstevel@tonic-gate } 217*7c478bd9Sstevel@tonic-gate 218*7c478bd9Sstevel@tonic-gate static void 219*7c478bd9Sstevel@tonic-gate dumpif(FILE *fp, struct interface *ifp) 220*7c478bd9Sstevel@tonic-gate { 221*7c478bd9Sstevel@tonic-gate if (ifp->int_input.ifd_count != 0 || ifp->int_output.ifd_count != 0) { 222*7c478bd9Sstevel@tonic-gate (void) fprintf(fp, "*** Packet history for interface %s ***\n", 223*7c478bd9Sstevel@tonic-gate (ifp->int_name != NULL) ? ifp->int_name : "(noname)"); 224*7c478bd9Sstevel@tonic-gate dumptrace(fp, "to", &ifp->int_output); 225*7c478bd9Sstevel@tonic-gate dumptrace(fp, "from", &ifp->int_input); 226*7c478bd9Sstevel@tonic-gate (void) fprintf(fp, "*** end packet history ***\n"); 227*7c478bd9Sstevel@tonic-gate } 228*7c478bd9Sstevel@tonic-gate (void) fflush(fp); 229*7c478bd9Sstevel@tonic-gate } 230*7c478bd9Sstevel@tonic-gate 231*7c478bd9Sstevel@tonic-gate static void 232*7c478bd9Sstevel@tonic-gate dumptrace(FILE *fp, char *dir, struct ifdebug *ifd) 233*7c478bd9Sstevel@tonic-gate { 234*7c478bd9Sstevel@tonic-gate struct iftrace *t; 235*7c478bd9Sstevel@tonic-gate char *cp = (strcmp(dir, "to") != 0) ? "Output" : "Input"; 236*7c478bd9Sstevel@tonic-gate 237*7c478bd9Sstevel@tonic-gate if (ifd->ifd_front == ifd->ifd_records && 238*7c478bd9Sstevel@tonic-gate ifd->ifd_front->ift_size == 0) { 239*7c478bd9Sstevel@tonic-gate (void) fprintf(fp, "%s: no packets.\n", cp); 240*7c478bd9Sstevel@tonic-gate (void) fflush(fp); 241*7c478bd9Sstevel@tonic-gate return; 242*7c478bd9Sstevel@tonic-gate } 243*7c478bd9Sstevel@tonic-gate (void) fprintf(fp, "%s trace:\n", cp); 244*7c478bd9Sstevel@tonic-gate t = ifd->ifd_front - ifd->ifd_count; 245*7c478bd9Sstevel@tonic-gate if (t < ifd->ifd_records) 246*7c478bd9Sstevel@tonic-gate t += NRECORDS; 247*7c478bd9Sstevel@tonic-gate for (; ifd->ifd_count; ifd->ifd_count--, t++) { 248*7c478bd9Sstevel@tonic-gate if (t >= ifd->ifd_records + NRECORDS) 249*7c478bd9Sstevel@tonic-gate t = ifd->ifd_records; 250*7c478bd9Sstevel@tonic-gate if (t->ift_size == 0) 251*7c478bd9Sstevel@tonic-gate continue; 252*7c478bd9Sstevel@tonic-gate (void) fprintf(fp, "%.24s: metric=%d\n", ctime(&t->ift_stamp), 253*7c478bd9Sstevel@tonic-gate t->ift_metric); 254*7c478bd9Sstevel@tonic-gate dumppacket(fp, dir, (struct sockaddr_in6 *)&t->ift_who, 255*7c478bd9Sstevel@tonic-gate t->ift_packet, t->ift_size); 256*7c478bd9Sstevel@tonic-gate } 257*7c478bd9Sstevel@tonic-gate } 258*7c478bd9Sstevel@tonic-gate 259*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 260*7c478bd9Sstevel@tonic-gate void 261*7c478bd9Sstevel@tonic-gate dumppacket(FILE *fp, char *dir, struct sockaddr_in6 *who, char *cp, int size) 262*7c478bd9Sstevel@tonic-gate { 263*7c478bd9Sstevel@tonic-gate /* XXX Output contents of the RIP packet */ 264*7c478bd9Sstevel@tonic-gate } 265