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.4 (Berkeley) 04/02/89"; 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 #include "pathnames.h" 57 58 unsigned long ntime; 59 int sflag; 60 int tflag; 61 int jflag; 62 int aflag; 63 int zflag; 64 int numeric(); 65 struct nlist nl[] = { 66 { "_spp_debug" }, 67 { "_spp_debx" }, 68 0 69 }; 70 struct spp_debug spp_debug[SPP_NDEBUG]; 71 caddr_t spp_pcbs[SPP_NDEBUG]; 72 int spp_debx; 73 74 main(argc, argv) 75 int argc; 76 char **argv; 77 { 78 int i, mask = 0, npcbs = 0; 79 char *system, *core; 80 81 system = _PATH_UNIX; 82 core = _PATH_KMEM; 83 84 argc--, argv++; 85 again: 86 if (argc > 0 && !strcmp(*argv, "-a")) { 87 aflag++, argc--, argv++; 88 goto again; 89 } 90 if (argc > 0 && !strcmp(*argv, "-z")) { 91 zflag++, argc--, argv++; 92 goto again; 93 } 94 if (argc > 0 && !strcmp(*argv, "-s")) { 95 sflag++, argc--, argv++; 96 goto again; 97 } 98 if (argc > 0 && !strcmp(*argv, "-t")) { 99 tflag++, argc--, argv++; 100 goto again; 101 } 102 if (argc > 0 && !strcmp(*argv, "-j")) { 103 jflag++, argc--, argv++; 104 goto again; 105 } 106 if (argc > 0 && !strcmp(*argv, "-p")) { 107 argc--, argv++; 108 if (argc < 1) { 109 fprintf(stderr, "-p: missing sppcb address\n"); 110 exit(1); 111 } 112 if (npcbs >= SPP_NDEBUG) { 113 fprintf(stderr, "-p: too many pcb's specified\n"); 114 exit(1); 115 } 116 sscanf(*argv, "%x", &spp_pcbs[npcbs++]); 117 argc--, argv++; 118 goto again; 119 } 120 if (argc > 0) { 121 system = *argv; 122 argc--, argv++; 123 mask++; 124 } 125 if (argc > 0) { 126 core = *argv; 127 argc--, argv++; 128 mask++; 129 } 130 (void) nlist(system, nl); 131 if (nl[0].n_value == 0) { 132 fprintf(stderr, "trsp: %s: no namelist\n", system); 133 exit(1); 134 } 135 (void) close(0); 136 if (open(core, 0) < 0) { 137 fprintf(stderr, "trsp: "); perror(core); 138 exit(2); 139 } 140 if (mask) { 141 nl[0].n_value &= 0x7fffffff; 142 nl[1].n_value &= 0x7fffffff; 143 } 144 (void) lseek(0, nl[1].n_value, 0); 145 if (read(0, &spp_debx, sizeof (spp_debx)) != sizeof (spp_debx)) { 146 fprintf(stderr, "trsp: "); perror("spp_debx"); 147 exit(3); 148 } 149 printf("spp_debx=%d\n", spp_debx); 150 (void) lseek(0, nl[0].n_value, 0); 151 if (read(0, spp_debug, sizeof (spp_debug)) != sizeof (spp_debug)) { 152 fprintf(stderr, "trsp: "); perror("spp_debug"); 153 exit(3); 154 } 155 /* 156 * Here, we just want to clear out the old trace data and start over. 157 */ 158 if (zflag) { 159 char *cp = (char *) spp_debug, 160 *cplim = cp + sizeof(spp_debug); 161 (void) close(0); 162 if (open(core, 2) < 0) { 163 fprintf(stderr, "trsp: "); perror(core); 164 exit(2); 165 } 166 while(cp < cplim) *cp++ = 0; 167 (void) lseek(0, nl[0].n_value, 0); 168 if (write(0, spp_debug, sizeof (spp_debug)) != sizeof (spp_debug)) { 169 fprintf(stderr, "trsp: "); perror("spp_debug"); 170 exit(3); 171 } 172 (void) lseek(0, nl[1].n_value, 0); 173 spp_debx = 0; 174 if (write(0, &spp_debx, sizeof (spp_debx)) != sizeof (spp_debx)) { 175 fprintf(stderr, "trsp: "); perror("spp_debx"); 176 exit(3); 177 } 178 exit(0); 179 } 180 /* 181 * If no control blocks have been specified, figure 182 * out how many distinct one we have and summarize 183 * them in spp_pcbs for sorting the trace records 184 * below. 185 */ 186 if (npcbs == 0) { 187 for (i = 0; i < SPP_NDEBUG; i++) { 188 register int j; 189 register struct spp_debug *sd = &spp_debug[i]; 190 191 if (sd->sd_cb == 0) 192 continue; 193 for (j = 0; j < npcbs; j++) 194 if (spp_pcbs[j] == sd->sd_cb) 195 break; 196 if (j >= npcbs) 197 spp_pcbs[npcbs++] = sd->sd_cb; 198 } 199 } 200 qsort(spp_pcbs, npcbs, sizeof (caddr_t), numeric); 201 if (jflag) { 202 char *cp = ""; 203 204 for (i = 0; i < npcbs; i++) { 205 printf("%s%x", cp, spp_pcbs[i]); 206 cp = ", "; 207 } 208 if (*cp) 209 putchar('\n'); 210 exit(0); 211 } 212 for (i = 0; i < npcbs; i++) { 213 printf("\n%x:\n", spp_pcbs[i]); 214 dotrace(spp_pcbs[i]); 215 } 216 exit(0); 217 } 218 219 dotrace(sppcb) 220 register caddr_t sppcb; 221 { 222 register int i; 223 register struct spp_debug *sd; 224 225 for (i = spp_debx % SPP_NDEBUG; i < SPP_NDEBUG; i++) { 226 sd = &spp_debug[i]; 227 if (sppcb && sd->sd_cb != sppcb) 228 continue; 229 ntime = ntohl(sd->sd_time); 230 spp_trace(sd->sd_act, sd->sd_ostate, sd->sd_cb, &sd->sd_sp, 231 &sd->sd_si, sd->sd_req); 232 } 233 for (i = 0; i < spp_debx % SPP_NDEBUG; i++) { 234 sd = &spp_debug[i]; 235 if (sppcb && sd->sd_cb != sppcb) 236 continue; 237 ntime = ntohl(sd->sd_time); 238 spp_trace(sd->sd_act, sd->sd_ostate, sd->sd_cb, &sd->sd_sp, 239 &sd->sd_si, sd->sd_req); 240 } 241 } 242 243 ptime(ms) 244 int ms; 245 { 246 247 printf("%03d ", (ms/10) % 1000); 248 } 249 250 numeric(c1, c2) 251 caddr_t *c1, *c2; 252 { 253 254 return (*c1 - *c2); 255 } 256 257 spp_trace(act, ostate, asp, sp, si, req) 258 short act, ostate; 259 struct sppcb *asp, *sp; 260 struct spidp *si; 261 int req; 262 { 263 u_short seq, ack, len, alo; 264 int flags, timer; 265 char *cp; 266 267 if(ostate >= TCP_NSTATES) ostate = 0; 268 if(act > SA_DROP) act = SA_DROP; 269 printf("\n"); 270 ptime(ntime); 271 printf("%s:%s", tcpstates[ostate], sanames[act]); 272 273 if (si != 0) { 274 seq = si->si_seq; 275 ack = si->si_ack; 276 alo = si->si_alo; 277 len = si->si_len; 278 switch (act) { 279 case SA_RESPOND: 280 case SA_OUTPUT: 281 seq = ntohs(seq); 282 ack = ntohs(ack); 283 alo = ntohs(alo); 284 len = ntohs(len); 285 case SA_INPUT: 286 case SA_DROP: 287 if (aflag) { 288 printf("\n\tsna="); 289 ns_printhost(&si->si_sna); 290 printf("\tdna="); 291 ns_printhost(&si->si_dna); 292 } 293 printf("\n\t"); 294 #define p1(f) { printf("%s = %x, ", "f", f); } 295 p1(seq); p1(ack); p1(alo); p1(len); 296 flags = si->si_cc; 297 printf("flags=%x", flags); 298 if (flags) { 299 char *cp = "<"; 300 #define pf(f) { if (flags&SP_/**/f) { printf("%s%s", cp, "f"); cp = ","; } } 301 pf(SP); pf(SA); pf(OB); pf(EM); 302 printf(">"); 303 } 304 printf(", "); 305 #define p2(f) { printf("%s = %x, ", "f", si->si_/**/f); } 306 p2(sid);p2(did);p2(dt); 307 printf("\n\tsna="); 308 ns_printhost(&si->si_sna); 309 printf("\tdna="); 310 ns_printhost(&si->si_dna); 311 } 312 } 313 if(act == SA_USER) { 314 printf("\treq=%s", prurequests[req&0xff]); 315 if ((req & 0xff) == PRU_SLOWTIMO) 316 printf("<%s>", tcptimers[req>>8]); 317 } 318 printf(" -> %s", tcpstates[sp->s_state]); 319 320 /* print out internal state of sp !?! */ 321 printf("\n"); 322 if (sp == 0) 323 return; 324 #define p3(f) { printf("%s = %x, ", "f", sp->s_/**/f); } 325 if(sflag) { 326 printf("\t"); p3(rack); p3(ralo); p3(smax); p3(snxt); p3(flags); 327 #undef pf 328 #define pf(f) { if (flags&SF_/**/f) { printf("%s%s", cp, "f"); cp = ","; } } 329 flags = sp->s_flags; 330 if (flags || sp->s_oobflags) { 331 char *cp = "<"; 332 pf(ACKNOW); pf(DELACK); pf(HI); pf(HO); 333 pf(PI); pf(WIN); pf(RXT); pf(RVD); 334 flags = sp->s_oobflags; 335 pf(SOOB); pf(IOOB); 336 printf(">"); 337 } 338 339 } 340 /* print out timers? */ 341 if (tflag) { 342 char *cp = "\t"; 343 register int i; 344 345 printf("\n\tTIMERS: "); 346 p3(idle); p3(force); p3(rtseq); 347 for (i = 0; i < TCPT_NTIMERS; i++) { 348 if (sp->s_timer[i] == 0) 349 continue; 350 printf("%s%s=%d", cp, tcptimers[i], sp->s_timer[i]); 351 if (i == TCPT_REXMT) 352 printf(" (s_rxtshft=%d)", sp->s_rxtshift); 353 cp = ", "; 354 } 355 if (*cp != '\t') 356 putchar('\n'); 357 } 358 } 359 360 ns_printhost(p) 361 register struct ns_addr *p; 362 { 363 364 printf("<net:%x%x,host:%4.4x%4.4x%4.4x,port:%x>", 365 p->x_net.s_net[0], 366 p->x_net.s_net[1], 367 p->x_host.s_host[0], 368 p->x_host.s_host[1], 369 p->x_host.s_host[2], 370 p->x_port); 371 372 } 373 374