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 /* 36 * Routing Table Management Daemon 37 */ 38 #include "defs.h" 39 40 #define NRECORDS 50 /* size of circular trace buffer */ 41 42 boolean_t tracepackets; /* watch packets as they go by */ 43 int tracing; /* bitmask: */ 44 FILE *ftrace; /* output trace file */ 45 46 static int iftraceinit(struct interface *ifp, struct ifdebug *ifd); 47 static void dumpif(FILE *fp, struct interface *ifp); 48 static void dumptrace(FILE *fp, char *dir, struct ifdebug *ifd); 49 50 void 51 traceinit(struct interface *ifp) 52 { 53 if (iftraceinit(ifp, &ifp->int_input) && 54 iftraceinit(ifp, &ifp->int_output)) 55 return; 56 tracing = 0; 57 (void) fprintf(stderr, "traceinit: can't init %s\n", 58 (ifp->int_name != NULL) ? ifp->int_name : "(noname)"); 59 } 60 61 static int 62 iftraceinit(struct interface *ifp, struct ifdebug *ifd) 63 { 64 struct iftrace *t; 65 66 ifd->ifd_records = (struct iftrace *) 67 malloc((size_t)NRECORDS * sizeof (struct iftrace)); 68 if (ifd->ifd_records == NULL) 69 return (0); 70 ifd->ifd_front = ifd->ifd_records; 71 ifd->ifd_count = 0; 72 for (t = ifd->ifd_records; t < ifd->ifd_records + NRECORDS; t++) { 73 t->ift_size = 0; 74 t->ift_packet = NULL; 75 } 76 ifd->ifd_if = ifp; 77 return (1); 78 } 79 80 void 81 traceon(char *file) 82 { 83 struct stat stbuf; 84 85 if (ftrace != NULL) 86 return; 87 if (stat(file, &stbuf) >= 0 && (stbuf.st_mode & S_IFMT) != S_IFREG) 88 return; 89 ftrace = fopen(file, "a"); 90 if (ftrace == NULL) 91 return; 92 (void) dup2(fileno(ftrace), 1); 93 (void) dup2(fileno(ftrace), 2); 94 } 95 96 void 97 traceonfp(FILE *fp) 98 { 99 if (ftrace != NULL) 100 return; 101 ftrace = fp; 102 if (ftrace == NULL) 103 return; 104 (void) dup2(fileno(ftrace), 1); 105 (void) dup2(fileno(ftrace), 2); 106 } 107 108 void 109 trace(struct ifdebug *ifd, struct sockaddr_in6 *who, char *p, int len, int m) 110 { 111 struct iftrace *t; 112 113 if (ifd->ifd_records == 0) 114 return; 115 t = ifd->ifd_front++; 116 if (ifd->ifd_front >= ifd->ifd_records + NRECORDS) 117 ifd->ifd_front = ifd->ifd_records; 118 if (ifd->ifd_count < NRECORDS) 119 ifd->ifd_count++; 120 if (t->ift_size > 0 && t->ift_size < len && t->ift_packet != NULL) { 121 free(t->ift_packet); 122 t->ift_packet = NULL; 123 } 124 (void) time(&t->ift_stamp); 125 t->ift_who = *who; 126 if (len > 0 && t->ift_packet == NULL) { 127 t->ift_packet = (char *)malloc((size_t)len); 128 if (t->ift_packet == NULL) 129 len = 0; 130 } 131 if (len > 0) 132 bcopy(p, t->ift_packet, len); 133 t->ift_size = len; 134 t->ift_metric = m; 135 } 136 137 void 138 traceaction(FILE *fp, char *action, struct rt_entry *rt) 139 { 140 static struct bits { 141 ulong_t t_bits; 142 char *t_name; 143 } flagbits[] = { 144 /* BEGIN CSTYLED */ 145 { RTF_UP, "UP" }, 146 { RTF_GATEWAY, "GATEWAY" }, 147 { RTF_HOST, "HOST" }, 148 { 0, NULL } 149 /* END CSTYLED */ 150 }, statebits[] = { 151 /* BEGIN CSTYLED */ 152 { RTS_INTERFACE, "INTERFACE" }, 153 { RTS_CHANGED, "CHANGED" }, 154 { RTS_PRIVATE, "PRIVATE" }, 155 { 0, NULL } 156 /* END CSTYLED */ 157 }; 158 struct bits *p; 159 boolean_t first; 160 char c; 161 time_t t; 162 163 if (fp == NULL) 164 return; 165 (void) time(&t); 166 (void) fprintf(fp, "%.15s %s ", ctime(&t) + 4, action); 167 if (rt != NULL) { 168 char buf1[INET6_ADDRSTRLEN]; 169 170 (void) fprintf(fp, "prefix %s/%d ", 171 inet_ntop(AF_INET6, (void *)&rt->rt_dst, buf1, 172 sizeof (buf1)), 173 rt->rt_prefix_length); 174 (void) fprintf(fp, "via %s metric %d", 175 inet_ntop(AF_INET6, (void *)&rt->rt_router, buf1, 176 sizeof (buf1)), 177 rt->rt_metric); 178 if (rt->rt_ifp != NULL) { 179 (void) fprintf(fp, " if %s", 180 (rt->rt_ifp->int_name != NULL) ? 181 rt->rt_ifp->int_name : "(noname)"); 182 } 183 (void) fprintf(fp, " state"); 184 c = ' '; 185 for (first = _B_TRUE, p = statebits; p->t_bits > 0; p++) { 186 if ((rt->rt_state & p->t_bits) == 0) 187 continue; 188 (void) fprintf(fp, "%c%s", c, p->t_name); 189 if (first) { 190 c = '|'; 191 first = _B_FALSE; 192 } 193 } 194 if (first) 195 (void) fprintf(fp, " 0"); 196 if (rt->rt_flags & (RTF_UP | RTF_GATEWAY)) { 197 c = ' '; 198 for (first = _B_TRUE, p = flagbits; p->t_bits > 0; 199 p++) { 200 if ((rt->rt_flags & p->t_bits) == 0) 201 continue; 202 (void) fprintf(fp, "%c%s", c, p->t_name); 203 if (first) { 204 c = '|'; 205 first = _B_FALSE; 206 } 207 } 208 } 209 } 210 (void) putc('\n', fp); 211 if (!tracepackets && rt != NULL && rt->rt_ifp != NULL) 212 dumpif(fp, rt->rt_ifp); 213 (void) fflush(fp); 214 } 215 216 static void 217 dumpif(FILE *fp, struct interface *ifp) 218 { 219 if (ifp->int_input.ifd_count != 0 || ifp->int_output.ifd_count != 0) { 220 (void) fprintf(fp, "*** Packet history for interface %s ***\n", 221 (ifp->int_name != NULL) ? ifp->int_name : "(noname)"); 222 dumptrace(fp, "to", &ifp->int_output); 223 dumptrace(fp, "from", &ifp->int_input); 224 (void) fprintf(fp, "*** end packet history ***\n"); 225 } 226 (void) fflush(fp); 227 } 228 229 static void 230 dumptrace(FILE *fp, char *dir, struct ifdebug *ifd) 231 { 232 struct iftrace *t; 233 char *cp = (strcmp(dir, "to") != 0) ? "Output" : "Input"; 234 235 if (ifd->ifd_front == ifd->ifd_records && 236 ifd->ifd_front->ift_size == 0) { 237 (void) fprintf(fp, "%s: no packets.\n", cp); 238 (void) fflush(fp); 239 return; 240 } 241 (void) fprintf(fp, "%s trace:\n", cp); 242 t = ifd->ifd_front - ifd->ifd_count; 243 if (t < ifd->ifd_records) 244 t += NRECORDS; 245 for (; ifd->ifd_count; ifd->ifd_count--, t++) { 246 if (t >= ifd->ifd_records + NRECORDS) 247 t = ifd->ifd_records; 248 if (t->ift_size == 0) 249 continue; 250 (void) fprintf(fp, "%.24s: metric=%d\n", ctime(&t->ift_stamp), 251 t->ift_metric); 252 dumppacket(fp, dir, (struct sockaddr_in6 *)&t->ift_who, 253 t->ift_packet, t->ift_size); 254 } 255 } 256 257 /*ARGSUSED*/ 258 void 259 dumppacket(FILE *fp, char *dir, struct sockaddr_in6 *who, char *cp, int size) 260 { 261 /* XXX Output contents of the RIP packet */ 262 } 263