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