1 /* 2 * Copyright (c) 1985 Regents of the University of California. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms are permitted 6 * provided that the above copyright notice and this paragraph are 7 * duplicated in all such forms and that any documentation, 8 * advertising materials, and other materials related to such 9 * distribution and use acknowledge that the software was developed 10 * by the University of California, Berkeley. The name of the 11 * University may not be used to endorse or promote products derived 12 * from this software without specific prior written permission. 13 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 14 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 15 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 16 */ 17 18 #ifndef lint 19 char copyright[] = 20 "@(#) Copyright (c) 1985 Regents of the University of California.\n\ 21 All rights reserved.\n"; 22 #endif /* not lint */ 23 24 #ifndef lint 25 static char sccsid[] = "@(#)trsp.c 6.3 (Berkeley) 09/20/88"; 26 #endif /* not lint */ 27 28 #include <sys/param.h> 29 #include <sys/socket.h> 30 #include <sys/socketvar.h> 31 #define PRUREQUESTS 32 #include <sys/protosw.h> 33 34 #include <net/route.h> 35 #include <net/if.h> 36 37 #define TCPSTATES 38 #include <netinet/tcp_fsm.h> 39 #define TCPTIMERS 40 #include <netinet/tcp_timer.h> 41 42 #include <netns/ns.h> 43 #include <netns/ns_pcb.h> 44 #include <netns/idp.h> 45 #include <netns/idp_var.h> 46 #include <netns/sp.h> 47 #include <netns/spidp.h> 48 #include <netns/spp_timer.h> 49 #include <netns/spp_var.h> 50 #define SANAMES 51 #include <netns/spp_debug.h> 52 53 #include <stdio.h> 54 #include <errno.h> 55 #include <nlist.h> 56 57 unsigned long ntime; 58 int sflag; 59 int tflag; 60 int jflag; 61 int aflag; 62 int zflag; 63 int numeric(); 64 struct nlist nl[] = { 65 { "_spp_debug" }, 66 { "_spp_debx" }, 67 0 68 }; 69 struct spp_debug spp_debug[SPP_NDEBUG]; 70 caddr_t spp_pcbs[SPP_NDEBUG]; 71 int spp_debx; 72 73 main(argc, argv) 74 int argc; 75 char **argv; 76 { 77 int i, mask = 0, npcbs = 0; 78 char *system = "/vmunix", *core = "/dev/kmem"; 79 80 argc--, argv++; 81 again: 82 if (argc > 0 && !strcmp(*argv, "-a")) { 83 aflag++, argc--, argv++; 84 goto again; 85 } 86 if (argc > 0 && !strcmp(*argv, "-z")) { 87 zflag++, argc--, argv++; 88 goto again; 89 } 90 if (argc > 0 && !strcmp(*argv, "-s")) { 91 sflag++, argc--, argv++; 92 goto again; 93 } 94 if (argc > 0 && !strcmp(*argv, "-t")) { 95 tflag++, argc--, argv++; 96 goto again; 97 } 98 if (argc > 0 && !strcmp(*argv, "-j")) { 99 jflag++, argc--, argv++; 100 goto again; 101 } 102 if (argc > 0 && !strcmp(*argv, "-p")) { 103 argc--, argv++; 104 if (argc < 1) { 105 fprintf(stderr, "-p: missing sppcb address\n"); 106 exit(1); 107 } 108 if (npcbs >= SPP_NDEBUG) { 109 fprintf(stderr, "-p: too many pcb's specified\n"); 110 exit(1); 111 } 112 sscanf(*argv, "%x", &spp_pcbs[npcbs++]); 113 argc--, argv++; 114 goto again; 115 } 116 if (argc > 0) { 117 system = *argv; 118 argc--, argv++; 119 mask++; 120 } 121 if (argc > 0) { 122 core = *argv; 123 argc--, argv++; 124 mask++; 125 } 126 (void) nlist(system, nl); 127 if (nl[0].n_value == 0) { 128 fprintf(stderr, "trsp: %s: no namelist\n", system); 129 exit(1); 130 } 131 (void) close(0); 132 if (open(core, 0) < 0) { 133 fprintf(stderr, "trsp: "); perror(core); 134 exit(2); 135 } 136 if (mask) { 137 nl[0].n_value &= 0x7fffffff; 138 nl[1].n_value &= 0x7fffffff; 139 } 140 (void) lseek(0, nl[1].n_value, 0); 141 if (read(0, &spp_debx, sizeof (spp_debx)) != sizeof (spp_debx)) { 142 fprintf(stderr, "trsp: "); perror("spp_debx"); 143 exit(3); 144 } 145 printf("spp_debx=%d\n", spp_debx); 146 (void) lseek(0, nl[0].n_value, 0); 147 if (read(0, spp_debug, sizeof (spp_debug)) != sizeof (spp_debug)) { 148 fprintf(stderr, "trsp: "); perror("spp_debug"); 149 exit(3); 150 } 151 /* 152 * Here, we just want to clear out the old trace data and start over. 153 */ 154 if (zflag) { 155 char *cp = (char *) spp_debug, 156 *cplim = cp + sizeof(spp_debug); 157 (void) close(0); 158 if (open(core, 2) < 0) { 159 fprintf(stderr, "trsp: "); perror(core); 160 exit(2); 161 } 162 while(cp < cplim) *cp++ = 0; 163 (void) lseek(0, nl[0].n_value, 0); 164 if (write(0, spp_debug, sizeof (spp_debug)) != sizeof (spp_debug)) { 165 fprintf(stderr, "trsp: "); perror("spp_debug"); 166 exit(3); 167 } 168 (void) lseek(0, nl[1].n_value, 0); 169 spp_debx = 0; 170 if (write(0, &spp_debx, sizeof (spp_debx)) != sizeof (spp_debx)) { 171 fprintf(stderr, "trsp: "); perror("spp_debx"); 172 exit(3); 173 } 174 exit(0); 175 } 176 /* 177 * If no control blocks have been specified, figure 178 * out how many distinct one we have and summarize 179 * them in spp_pcbs for sorting the trace records 180 * below. 181 */ 182 if (npcbs == 0) { 183 for (i = 0; i < SPP_NDEBUG; i++) { 184 register int j; 185 register struct spp_debug *sd = &spp_debug[i]; 186 187 if (sd->sd_cb == 0) 188 continue; 189 for (j = 0; j < npcbs; j++) 190 if (spp_pcbs[j] == sd->sd_cb) 191 break; 192 if (j >= npcbs) 193 spp_pcbs[npcbs++] = sd->sd_cb; 194 } 195 } 196 qsort(spp_pcbs, npcbs, sizeof (caddr_t), numeric); 197 if (jflag) { 198 char *cp = ""; 199 200 for (i = 0; i < npcbs; i++) { 201 printf("%s%x", cp, spp_pcbs[i]); 202 cp = ", "; 203 } 204 if (*cp) 205 putchar('\n'); 206 exit(0); 207 } 208 for (i = 0; i < npcbs; i++) { 209 printf("\n%x:\n", spp_pcbs[i]); 210 dotrace(spp_pcbs[i]); 211 } 212 exit(0); 213 } 214 215 dotrace(sppcb) 216 register caddr_t sppcb; 217 { 218 register int i; 219 register struct spp_debug *sd; 220 221 for (i = spp_debx % SPP_NDEBUG; i < SPP_NDEBUG; i++) { 222 sd = &spp_debug[i]; 223 if (sppcb && sd->sd_cb != sppcb) 224 continue; 225 ntime = ntohl(sd->sd_time); 226 spp_trace(sd->sd_act, sd->sd_ostate, sd->sd_cb, &sd->sd_sp, 227 &sd->sd_si, sd->sd_req); 228 } 229 for (i = 0; i < spp_debx % SPP_NDEBUG; i++) { 230 sd = &spp_debug[i]; 231 if (sppcb && sd->sd_cb != sppcb) 232 continue; 233 ntime = ntohl(sd->sd_time); 234 spp_trace(sd->sd_act, sd->sd_ostate, sd->sd_cb, &sd->sd_sp, 235 &sd->sd_si, sd->sd_req); 236 } 237 } 238 239 ptime(ms) 240 int ms; 241 { 242 243 printf("%03d ", (ms/10) % 1000); 244 } 245 246 numeric(c1, c2) 247 caddr_t *c1, *c2; 248 { 249 250 return (*c1 - *c2); 251 } 252 253 spp_trace(act, ostate, asp, sp, si, req) 254 short act, ostate; 255 struct sppcb *asp, *sp; 256 struct spidp *si; 257 int req; 258 { 259 u_short seq, ack, len, alo; 260 int flags, timer; 261 char *cp; 262 263 if(ostate >= TCP_NSTATES) ostate = 0; 264 if(act > SA_DROP) act = SA_DROP; 265 printf("\n"); 266 ptime(ntime); 267 printf("%s:%s", tcpstates[ostate], sanames[act]); 268 269 if (si != 0) { 270 seq = si->si_seq; 271 ack = si->si_ack; 272 alo = si->si_alo; 273 len = si->si_len; 274 switch (act) { 275 case SA_RESPOND: 276 case SA_OUTPUT: 277 seq = ntohs(seq); 278 ack = ntohs(ack); 279 alo = ntohs(alo); 280 len = ntohs(len); 281 case SA_INPUT: 282 case SA_DROP: 283 if (aflag) { 284 printf("\n\tsna="); 285 ns_printhost(&si->si_sna); 286 printf("\tdna="); 287 ns_printhost(&si->si_dna); 288 } 289 printf("\n\t"); 290 #define p1(f) { printf("%s = %x, ", "f", f); } 291 p1(seq); p1(ack); p1(alo); p1(len); 292 flags = si->si_cc; 293 printf("flags=%x", flags); 294 if (flags) { 295 char *cp = "<"; 296 #define pf(f) { if (flags&SP_/**/f) { printf("%s%s", cp, "f"); cp = ","; } } 297 pf(SP); pf(SA); pf(OB); pf(EM); 298 printf(">"); 299 } 300 printf(", "); 301 #define p2(f) { printf("%s = %x, ", "f", si->si_/**/f); } 302 p2(sid);p2(did);p2(dt); 303 printf("\n\tsna="); 304 ns_printhost(&si->si_sna); 305 printf("\tdna="); 306 ns_printhost(&si->si_dna); 307 } 308 } 309 if(act == SA_USER) { 310 printf("\treq=%s", prurequests[req&0xff]); 311 if ((req & 0xff) == PRU_SLOWTIMO) 312 printf("<%s>", tcptimers[req>>8]); 313 } 314 printf(" -> %s", tcpstates[sp->s_state]); 315 316 /* print out internal state of sp !?! */ 317 printf("\n"); 318 if (sp == 0) 319 return; 320 #define p3(f) { printf("%s = %x, ", "f", sp->s_/**/f); } 321 if(sflag) { 322 printf("\t"); p3(rack); p3(ralo); p3(smax); p3(snxt); p3(flags); 323 #undef pf 324 #define pf(f) { if (flags&SF_/**/f) { printf("%s%s", cp, "f"); cp = ","; } } 325 flags = sp->s_flags; 326 if (flags || sp->s_oobflags) { 327 char *cp = "<"; 328 pf(ACKNOW); pf(DELACK); pf(HI); pf(HO); 329 pf(PI); pf(WIN); pf(RXT); pf(RVD); 330 flags = sp->s_oobflags; 331 pf(SOOB); pf(IOOB); 332 printf(">"); 333 } 334 335 } 336 /* print out timers? */ 337 if (tflag) { 338 char *cp = "\t"; 339 register int i; 340 341 printf("\n\tTIMERS: "); 342 p3(idle); p3(force); p3(rtseq); 343 for (i = 0; i < TCPT_NTIMERS; i++) { 344 if (sp->s_timer[i] == 0) 345 continue; 346 printf("%s%s=%d", cp, tcptimers[i], sp->s_timer[i]); 347 if (i == TCPT_REXMT) 348 printf(" (s_rxtshft=%d)", sp->s_rxtshift); 349 cp = ", "; 350 } 351 if (*cp != '\t') 352 putchar('\n'); 353 } 354 } 355 356 ns_printhost(p) 357 register struct ns_addr *p; 358 { 359 360 printf("<net:%x%x,host:%4.4x%4.4x%4.4x,port:%x>", 361 p->x_net.s_net[0], 362 p->x_net.s_net[1], 363 p->x_host.s_host[0], 364 p->x_host.s_host[1], 365 p->x_host.s_host[2], 366 p->x_port); 367 368 } 369 370