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