1 /* 2 * Copyright (c) 1992, 1993, 1994, 1995, 1996, 1997 3 * The Regents of the University of California. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that: (1) source code distributions 7 * retain the above copyright notice and this paragraph in its entirety, (2) 8 * distributions including binary code include the above copyright notice and 9 * this paragraph in its entirety in the documentation or other materials 10 * provided with the distribution, and (3) all advertising materials mentioning 11 * features or use of this software display the following acknowledgement: 12 * ``This product includes software developed by the University of California, 13 * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of 14 * the University nor the names of its contributors may be used to endorse 15 * or promote products derived from this software without specific prior 16 * written permission. 17 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED 18 * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF 19 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 20 */ 21 22 #ifndef lint 23 static const char rcsid[] _U_ = 24 "@(#) $Header: /tcpdump/master/tcpdump/print-decnet.c,v 1.39 2005-05-06 02:16:26 guy Exp $ (LBL)"; 25 #endif 26 27 #ifdef HAVE_CONFIG_H 28 #include "config.h" 29 #endif 30 31 #include <tcpdump-stdinc.h> 32 33 struct mbuf; 34 struct rtentry; 35 36 #ifdef HAVE_NETDNET_DNETDB_H 37 #include <netdnet/dnetdb.h> 38 #endif 39 40 #include <stdio.h> 41 #include <stdlib.h> 42 #include <string.h> 43 44 #include "decnet.h" 45 #include "extract.h" 46 #include "interface.h" 47 #include "addrtoname.h" 48 49 /* Forwards */ 50 static int print_decnet_ctlmsg(const union routehdr *, u_int, u_int); 51 static void print_t_info(int); 52 static int print_l1_routes(const char *, u_int); 53 static int print_l2_routes(const char *, u_int); 54 static void print_i_info(int); 55 static int print_elist(const char *, u_int); 56 static int print_nsp(const u_char *, u_int); 57 static void print_reason(int); 58 #ifdef PRINT_NSPDATA 59 static void pdata(u_char *, int); 60 #endif 61 62 #ifndef HAVE_NETDNET_DNETDB_H_DNET_HTOA 63 extern char *dnet_htoa(struct dn_naddr *); 64 #endif 65 66 void 67 decnet_print(register const u_char *ap, register u_int length, 68 register u_int caplen) 69 { 70 register const union routehdr *rhp; 71 register int mflags; 72 int dst, src, hops; 73 u_int nsplen, pktlen; 74 const u_char *nspp; 75 76 if (length < sizeof(struct shorthdr)) { 77 (void)printf("[|decnet]"); 78 return; 79 } 80 81 TCHECK2(*ap, sizeof(short)); 82 pktlen = EXTRACT_LE_16BITS(ap); 83 if (pktlen < sizeof(struct shorthdr)) { 84 (void)printf("[|decnet]"); 85 return; 86 } 87 if (pktlen > length) { 88 (void)printf("[|decnet]"); 89 return; 90 } 91 length = pktlen; 92 93 rhp = (const union routehdr *)&(ap[sizeof(short)]); 94 TCHECK(rhp->rh_short.sh_flags); 95 mflags = EXTRACT_LE_8BITS(rhp->rh_short.sh_flags); 96 97 if (mflags & RMF_PAD) { 98 /* pad bytes of some sort in front of message */ 99 u_int padlen = mflags & RMF_PADMASK; 100 if (vflag) 101 (void) printf("[pad:%d] ", padlen); 102 if (length < padlen + 2) { 103 (void)printf("[|decnet]"); 104 return; 105 } 106 TCHECK2(ap[sizeof(short)], padlen); 107 ap += padlen; 108 length -= padlen; 109 caplen -= padlen; 110 rhp = (const union routehdr *)&(ap[sizeof(short)]); 111 mflags = EXTRACT_LE_8BITS(rhp->rh_short.sh_flags); 112 } 113 114 if (mflags & RMF_FVER) { 115 (void) printf("future-version-decnet"); 116 default_print(ap, min(length, caplen)); 117 return; 118 } 119 120 /* is it a control message? */ 121 if (mflags & RMF_CTLMSG) { 122 if (!print_decnet_ctlmsg(rhp, length, caplen)) 123 goto trunc; 124 return; 125 } 126 127 switch (mflags & RMF_MASK) { 128 case RMF_LONG: 129 if (length < sizeof(struct longhdr)) { 130 (void)printf("[|decnet]"); 131 return; 132 } 133 TCHECK(rhp->rh_long); 134 dst = 135 EXTRACT_LE_16BITS(rhp->rh_long.lg_dst.dne_remote.dne_nodeaddr); 136 src = 137 EXTRACT_LE_16BITS(rhp->rh_long.lg_src.dne_remote.dne_nodeaddr); 138 hops = EXTRACT_LE_8BITS(rhp->rh_long.lg_visits); 139 nspp = &(ap[sizeof(short) + sizeof(struct longhdr)]); 140 nsplen = length - sizeof(struct longhdr); 141 break; 142 case RMF_SHORT: 143 TCHECK(rhp->rh_short); 144 dst = EXTRACT_LE_16BITS(rhp->rh_short.sh_dst); 145 src = EXTRACT_LE_16BITS(rhp->rh_short.sh_src); 146 hops = (EXTRACT_LE_8BITS(rhp->rh_short.sh_visits) & VIS_MASK)+1; 147 nspp = &(ap[sizeof(short) + sizeof(struct shorthdr)]); 148 nsplen = length - sizeof(struct shorthdr); 149 break; 150 default: 151 (void) printf("unknown message flags under mask"); 152 default_print((u_char *)ap, min(length, caplen)); 153 return; 154 } 155 156 (void)printf("%s > %s %d ", 157 dnaddr_string(src), dnaddr_string(dst), pktlen); 158 if (vflag) { 159 if (mflags & RMF_RQR) 160 (void)printf("RQR "); 161 if (mflags & RMF_RTS) 162 (void)printf("RTS "); 163 if (mflags & RMF_IE) 164 (void)printf("IE "); 165 (void)printf("%d hops ", hops); 166 } 167 168 if (!print_nsp(nspp, nsplen)) 169 goto trunc; 170 return; 171 172 trunc: 173 (void)printf("[|decnet]"); 174 return; 175 } 176 177 static int 178 print_decnet_ctlmsg(register const union routehdr *rhp, u_int length, 179 u_int caplen) 180 { 181 int mflags = EXTRACT_LE_8BITS(rhp->rh_short.sh_flags); 182 register union controlmsg *cmp = (union controlmsg *)rhp; 183 int src, dst, info, blksize, eco, ueco, hello, other, vers; 184 etheraddr srcea, rtea; 185 int priority; 186 char *rhpx = (char *)rhp; 187 int ret; 188 189 switch (mflags & RMF_CTLMASK) { 190 case RMF_INIT: 191 (void)printf("init "); 192 if (length < sizeof(struct initmsg)) 193 goto trunc; 194 TCHECK(cmp->cm_init); 195 src = EXTRACT_LE_16BITS(cmp->cm_init.in_src); 196 info = EXTRACT_LE_8BITS(cmp->cm_init.in_info); 197 blksize = EXTRACT_LE_16BITS(cmp->cm_init.in_blksize); 198 vers = EXTRACT_LE_8BITS(cmp->cm_init.in_vers); 199 eco = EXTRACT_LE_8BITS(cmp->cm_init.in_eco); 200 ueco = EXTRACT_LE_8BITS(cmp->cm_init.in_ueco); 201 hello = EXTRACT_LE_16BITS(cmp->cm_init.in_hello); 202 print_t_info(info); 203 (void)printf( 204 "src %sblksize %d vers %d eco %d ueco %d hello %d", 205 dnaddr_string(src), blksize, vers, eco, ueco, 206 hello); 207 ret = 1; 208 break; 209 case RMF_VER: 210 (void)printf("verification "); 211 if (length < sizeof(struct verifmsg)) 212 goto trunc; 213 TCHECK(cmp->cm_ver); 214 src = EXTRACT_LE_16BITS(cmp->cm_ver.ve_src); 215 other = EXTRACT_LE_8BITS(cmp->cm_ver.ve_fcnval); 216 (void)printf("src %s fcnval %o", dnaddr_string(src), other); 217 ret = 1; 218 break; 219 case RMF_TEST: 220 (void)printf("test "); 221 if (length < sizeof(struct testmsg)) 222 goto trunc; 223 TCHECK(cmp->cm_test); 224 src = EXTRACT_LE_16BITS(cmp->cm_test.te_src); 225 other = EXTRACT_LE_8BITS(cmp->cm_test.te_data); 226 (void)printf("src %s data %o", dnaddr_string(src), other); 227 ret = 1; 228 break; 229 case RMF_L1ROUT: 230 (void)printf("lev-1-routing "); 231 if (length < sizeof(struct l1rout)) 232 goto trunc; 233 TCHECK(cmp->cm_l1rou); 234 src = EXTRACT_LE_16BITS(cmp->cm_l1rou.r1_src); 235 (void)printf("src %s ", dnaddr_string(src)); 236 ret = print_l1_routes(&(rhpx[sizeof(struct l1rout)]), 237 length - sizeof(struct l1rout)); 238 break; 239 case RMF_L2ROUT: 240 (void)printf("lev-2-routing "); 241 if (length < sizeof(struct l2rout)) 242 goto trunc; 243 TCHECK(cmp->cm_l2rout); 244 src = EXTRACT_LE_16BITS(cmp->cm_l2rout.r2_src); 245 (void)printf("src %s ", dnaddr_string(src)); 246 ret = print_l2_routes(&(rhpx[sizeof(struct l2rout)]), 247 length - sizeof(struct l2rout)); 248 break; 249 case RMF_RHELLO: 250 (void)printf("router-hello "); 251 if (length < sizeof(struct rhellomsg)) 252 goto trunc; 253 TCHECK(cmp->cm_rhello); 254 vers = EXTRACT_LE_8BITS(cmp->cm_rhello.rh_vers); 255 eco = EXTRACT_LE_8BITS(cmp->cm_rhello.rh_eco); 256 ueco = EXTRACT_LE_8BITS(cmp->cm_rhello.rh_ueco); 257 memcpy((char *)&srcea, (char *)&(cmp->cm_rhello.rh_src), 258 sizeof(srcea)); 259 src = EXTRACT_LE_16BITS(srcea.dne_remote.dne_nodeaddr); 260 info = EXTRACT_LE_8BITS(cmp->cm_rhello.rh_info); 261 blksize = EXTRACT_LE_16BITS(cmp->cm_rhello.rh_blksize); 262 priority = EXTRACT_LE_8BITS(cmp->cm_rhello.rh_priority); 263 hello = EXTRACT_LE_16BITS(cmp->cm_rhello.rh_hello); 264 print_i_info(info); 265 (void)printf( 266 "vers %d eco %d ueco %d src %s blksize %d pri %d hello %d", 267 vers, eco, ueco, dnaddr_string(src), 268 blksize, priority, hello); 269 ret = print_elist(&(rhpx[sizeof(struct rhellomsg)]), 270 length - sizeof(struct rhellomsg)); 271 break; 272 case RMF_EHELLO: 273 (void)printf("endnode-hello "); 274 if (length < sizeof(struct ehellomsg)) 275 goto trunc; 276 TCHECK(cmp->cm_ehello); 277 vers = EXTRACT_LE_8BITS(cmp->cm_ehello.eh_vers); 278 eco = EXTRACT_LE_8BITS(cmp->cm_ehello.eh_eco); 279 ueco = EXTRACT_LE_8BITS(cmp->cm_ehello.eh_ueco); 280 memcpy((char *)&srcea, (char *)&(cmp->cm_ehello.eh_src), 281 sizeof(srcea)); 282 src = EXTRACT_LE_16BITS(srcea.dne_remote.dne_nodeaddr); 283 info = EXTRACT_LE_8BITS(cmp->cm_ehello.eh_info); 284 blksize = EXTRACT_LE_16BITS(cmp->cm_ehello.eh_blksize); 285 /*seed*/ 286 memcpy((char *)&rtea, (char *)&(cmp->cm_ehello.eh_router), 287 sizeof(rtea)); 288 dst = EXTRACT_LE_16BITS(rtea.dne_remote.dne_nodeaddr); 289 hello = EXTRACT_LE_16BITS(cmp->cm_ehello.eh_hello); 290 other = EXTRACT_LE_8BITS(cmp->cm_ehello.eh_data); 291 print_i_info(info); 292 (void)printf( 293 "vers %d eco %d ueco %d src %s blksize %d rtr %s hello %d data %o", 294 vers, eco, ueco, dnaddr_string(src), 295 blksize, dnaddr_string(dst), hello, other); 296 ret = 1; 297 break; 298 299 default: 300 (void)printf("unknown control message"); 301 default_print((u_char *)rhp, min(length, caplen)); 302 ret = 1; 303 break; 304 } 305 return (ret); 306 307 trunc: 308 return (0); 309 } 310 311 static void 312 print_t_info(int info) 313 { 314 int ntype = info & 3; 315 switch (ntype) { 316 case 0: (void)printf("reserved-ntype? "); break; 317 case TI_L2ROUT: (void)printf("l2rout "); break; 318 case TI_L1ROUT: (void)printf("l1rout "); break; 319 case TI_ENDNODE: (void)printf("endnode "); break; 320 } 321 if (info & TI_VERIF) 322 (void)printf("verif "); 323 if (info & TI_BLOCK) 324 (void)printf("blo "); 325 } 326 327 static int 328 print_l1_routes(const char *rp, u_int len) 329 { 330 int count; 331 int id; 332 int info; 333 334 /* The last short is a checksum */ 335 while (len > (3 * sizeof(short))) { 336 TCHECK2(*rp, 3 * sizeof(short)); 337 count = EXTRACT_LE_16BITS(rp); 338 if (count > 1024) 339 return (1); /* seems to be bogus from here on */ 340 rp += sizeof(short); 341 len -= sizeof(short); 342 id = EXTRACT_LE_16BITS(rp); 343 rp += sizeof(short); 344 len -= sizeof(short); 345 info = EXTRACT_LE_16BITS(rp); 346 rp += sizeof(short); 347 len -= sizeof(short); 348 (void)printf("{ids %d-%d cost %d hops %d} ", id, id + count, 349 RI_COST(info), RI_HOPS(info)); 350 } 351 return (1); 352 353 trunc: 354 return (0); 355 } 356 357 static int 358 print_l2_routes(const char *rp, u_int len) 359 { 360 int count; 361 int area; 362 int info; 363 364 /* The last short is a checksum */ 365 while (len > (3 * sizeof(short))) { 366 TCHECK2(*rp, 3 * sizeof(short)); 367 count = EXTRACT_LE_16BITS(rp); 368 if (count > 1024) 369 return (1); /* seems to be bogus from here on */ 370 rp += sizeof(short); 371 len -= sizeof(short); 372 area = EXTRACT_LE_16BITS(rp); 373 rp += sizeof(short); 374 len -= sizeof(short); 375 info = EXTRACT_LE_16BITS(rp); 376 rp += sizeof(short); 377 len -= sizeof(short); 378 (void)printf("{areas %d-%d cost %d hops %d} ", area, area + count, 379 RI_COST(info), RI_HOPS(info)); 380 } 381 return (1); 382 383 trunc: 384 return (0); 385 } 386 387 static void 388 print_i_info(int info) 389 { 390 int ntype = info & II_TYPEMASK; 391 switch (ntype) { 392 case 0: (void)printf("reserved-ntype? "); break; 393 case II_L2ROUT: (void)printf("l2rout "); break; 394 case II_L1ROUT: (void)printf("l1rout "); break; 395 case II_ENDNODE: (void)printf("endnode "); break; 396 } 397 if (info & II_VERIF) 398 (void)printf("verif "); 399 if (info & II_NOMCAST) 400 (void)printf("nomcast "); 401 if (info & II_BLOCK) 402 (void)printf("blo "); 403 } 404 405 static int 406 print_elist(const char *elp _U_, u_int len _U_) 407 { 408 /* Not enough examples available for me to debug this */ 409 return (1); 410 } 411 412 static int 413 print_nsp(const u_char *nspp, u_int nsplen) 414 { 415 const struct nsphdr *nsphp = (struct nsphdr *)nspp; 416 int dst, src, flags; 417 418 if (nsplen < sizeof(struct nsphdr)) 419 goto trunc; 420 TCHECK(*nsphp); 421 flags = EXTRACT_LE_8BITS(nsphp->nh_flags); 422 dst = EXTRACT_LE_16BITS(nsphp->nh_dst); 423 src = EXTRACT_LE_16BITS(nsphp->nh_src); 424 425 switch (flags & NSP_TYPEMASK) { 426 case MFT_DATA: 427 switch (flags & NSP_SUBMASK) { 428 case MFS_BOM: 429 case MFS_MOM: 430 case MFS_EOM: 431 case MFS_BOM+MFS_EOM: 432 printf("data %d>%d ", src, dst); 433 { 434 struct seghdr *shp = (struct seghdr *)nspp; 435 int ack; 436 #ifdef PRINT_NSPDATA 437 u_char *dp; 438 #endif 439 u_int data_off = sizeof(struct minseghdr); 440 441 if (nsplen < data_off) 442 goto trunc; 443 TCHECK(shp->sh_seq[0]); 444 ack = EXTRACT_LE_16BITS(shp->sh_seq[0]); 445 if (ack & SGQ_ACK) { /* acknum field */ 446 if ((ack & SGQ_NAK) == SGQ_NAK) 447 (void)printf("nak %d ", ack & SGQ_MASK); 448 else 449 (void)printf("ack %d ", ack & SGQ_MASK); 450 data_off += sizeof(short); 451 if (nsplen < data_off) 452 goto trunc; 453 TCHECK(shp->sh_seq[1]); 454 ack = EXTRACT_LE_16BITS(shp->sh_seq[1]); 455 if (ack & SGQ_OACK) { /* ackoth field */ 456 if ((ack & SGQ_ONAK) == SGQ_ONAK) 457 (void)printf("onak %d ", ack & SGQ_MASK); 458 else 459 (void)printf("oack %d ", ack & SGQ_MASK); 460 data_off += sizeof(short); 461 if (nsplen < data_off) 462 goto trunc; 463 TCHECK(shp->sh_seq[2]); 464 ack = EXTRACT_LE_16BITS(shp->sh_seq[2]); 465 } 466 } 467 (void)printf("seg %d ", ack & SGQ_MASK); 468 #ifdef PRINT_NSPDATA 469 if (nsplen > data_off) { 470 dp = &(nspp[data_off]); 471 TCHECK2(*dp, nsplen - data_off); 472 pdata(dp, nsplen - data_off); 473 } 474 #endif 475 } 476 break; 477 case MFS_ILS+MFS_INT: 478 printf("intr "); 479 { 480 struct seghdr *shp = (struct seghdr *)nspp; 481 int ack; 482 #ifdef PRINT_NSPDATA 483 u_char *dp; 484 #endif 485 u_int data_off = sizeof(struct minseghdr); 486 487 if (nsplen < data_off) 488 goto trunc; 489 TCHECK(shp->sh_seq[0]); 490 ack = EXTRACT_LE_16BITS(shp->sh_seq[0]); 491 if (ack & SGQ_ACK) { /* acknum field */ 492 if ((ack & SGQ_NAK) == SGQ_NAK) 493 (void)printf("nak %d ", ack & SGQ_MASK); 494 else 495 (void)printf("ack %d ", ack & SGQ_MASK); 496 data_off += sizeof(short); 497 if (nsplen < data_off) 498 goto trunc; 499 TCHECK(shp->sh_seq[1]); 500 ack = EXTRACT_LE_16BITS(shp->sh_seq[1]); 501 if (ack & SGQ_OACK) { /* ackdat field */ 502 if ((ack & SGQ_ONAK) == SGQ_ONAK) 503 (void)printf("nakdat %d ", ack & SGQ_MASK); 504 else 505 (void)printf("ackdat %d ", ack & SGQ_MASK); 506 data_off += sizeof(short); 507 if (nsplen < data_off) 508 goto trunc; 509 TCHECK(shp->sh_seq[2]); 510 ack = EXTRACT_LE_16BITS(shp->sh_seq[2]); 511 } 512 } 513 (void)printf("seg %d ", ack & SGQ_MASK); 514 #ifdef PRINT_NSPDATA 515 if (nsplen > data_off) { 516 dp = &(nspp[data_off]); 517 TCHECK2(*dp, nsplen - data_off); 518 pdata(dp, nsplen - data_off); 519 } 520 #endif 521 } 522 break; 523 case MFS_ILS: 524 (void)printf("link-service %d>%d ", src, dst); 525 { 526 struct seghdr *shp = (struct seghdr *)nspp; 527 struct lsmsg *lsmp = 528 (struct lsmsg *)&(nspp[sizeof(struct seghdr)]); 529 int ack; 530 int lsflags, fcval; 531 532 if (nsplen < sizeof(struct seghdr) + sizeof(struct lsmsg)) 533 goto trunc; 534 TCHECK(shp->sh_seq[0]); 535 ack = EXTRACT_LE_16BITS(shp->sh_seq[0]); 536 if (ack & SGQ_ACK) { /* acknum field */ 537 if ((ack & SGQ_NAK) == SGQ_NAK) 538 (void)printf("nak %d ", ack & SGQ_MASK); 539 else 540 (void)printf("ack %d ", ack & SGQ_MASK); 541 TCHECK(shp->sh_seq[1]); 542 ack = EXTRACT_LE_16BITS(shp->sh_seq[1]); 543 if (ack & SGQ_OACK) { /* ackdat field */ 544 if ((ack & SGQ_ONAK) == SGQ_ONAK) 545 (void)printf("nakdat %d ", ack & SGQ_MASK); 546 else 547 (void)printf("ackdat %d ", ack & SGQ_MASK); 548 TCHECK(shp->sh_seq[2]); 549 ack = EXTRACT_LE_16BITS(shp->sh_seq[2]); 550 } 551 } 552 (void)printf("seg %d ", ack & SGQ_MASK); 553 TCHECK(*lsmp); 554 lsflags = EXTRACT_LE_8BITS(lsmp->ls_lsflags); 555 fcval = EXTRACT_LE_8BITS(lsmp->ls_fcval); 556 switch (lsflags & LSI_MASK) { 557 case LSI_DATA: 558 (void)printf("dat seg count %d ", fcval); 559 switch (lsflags & LSM_MASK) { 560 case LSM_NOCHANGE: 561 break; 562 case LSM_DONOTSEND: 563 (void)printf("donotsend-data "); 564 break; 565 case LSM_SEND: 566 (void)printf("send-data "); 567 break; 568 default: 569 (void)printf("reserved-fcmod? %x", lsflags); 570 break; 571 } 572 break; 573 case LSI_INTR: 574 (void)printf("intr req count %d ", fcval); 575 break; 576 default: 577 (void)printf("reserved-fcval-int? %x", lsflags); 578 break; 579 } 580 } 581 break; 582 default: 583 (void)printf("reserved-subtype? %x %d > %d", flags, src, dst); 584 break; 585 } 586 break; 587 case MFT_ACK: 588 switch (flags & NSP_SUBMASK) { 589 case MFS_DACK: 590 (void)printf("data-ack %d>%d ", src, dst); 591 { 592 struct ackmsg *amp = (struct ackmsg *)nspp; 593 int ack; 594 595 if (nsplen < sizeof(struct ackmsg)) 596 goto trunc; 597 TCHECK(*amp); 598 ack = EXTRACT_LE_16BITS(amp->ak_acknum[0]); 599 if (ack & SGQ_ACK) { /* acknum field */ 600 if ((ack & SGQ_NAK) == SGQ_NAK) 601 (void)printf("nak %d ", ack & SGQ_MASK); 602 else 603 (void)printf("ack %d ", ack & SGQ_MASK); 604 ack = EXTRACT_LE_16BITS(amp->ak_acknum[1]); 605 if (ack & SGQ_OACK) { /* ackoth field */ 606 if ((ack & SGQ_ONAK) == SGQ_ONAK) 607 (void)printf("onak %d ", ack & SGQ_MASK); 608 else 609 (void)printf("oack %d ", ack & SGQ_MASK); 610 } 611 } 612 } 613 break; 614 case MFS_IACK: 615 (void)printf("ils-ack %d>%d ", src, dst); 616 { 617 struct ackmsg *amp = (struct ackmsg *)nspp; 618 int ack; 619 620 if (nsplen < sizeof(struct ackmsg)) 621 goto trunc; 622 TCHECK(*amp); 623 ack = EXTRACT_LE_16BITS(amp->ak_acknum[0]); 624 if (ack & SGQ_ACK) { /* acknum field */ 625 if ((ack & SGQ_NAK) == SGQ_NAK) 626 (void)printf("nak %d ", ack & SGQ_MASK); 627 else 628 (void)printf("ack %d ", ack & SGQ_MASK); 629 TCHECK(amp->ak_acknum[1]); 630 ack = EXTRACT_LE_16BITS(amp->ak_acknum[1]); 631 if (ack & SGQ_OACK) { /* ackdat field */ 632 if ((ack & SGQ_ONAK) == SGQ_ONAK) 633 (void)printf("nakdat %d ", ack & SGQ_MASK); 634 else 635 (void)printf("ackdat %d ", ack & SGQ_MASK); 636 } 637 } 638 } 639 break; 640 case MFS_CACK: 641 (void)printf("conn-ack %d", dst); 642 break; 643 default: 644 (void)printf("reserved-acktype? %x %d > %d", flags, src, dst); 645 break; 646 } 647 break; 648 case MFT_CTL: 649 switch (flags & NSP_SUBMASK) { 650 case MFS_CI: 651 case MFS_RCI: 652 if ((flags & NSP_SUBMASK) == MFS_CI) 653 (void)printf("conn-initiate "); 654 else 655 (void)printf("retrans-conn-initiate "); 656 (void)printf("%d>%d ", src, dst); 657 { 658 struct cimsg *cimp = (struct cimsg *)nspp; 659 int services, info, segsize; 660 #ifdef PRINT_NSPDATA 661 u_char *dp; 662 #endif 663 664 if (nsplen < sizeof(struct cimsg)) 665 goto trunc; 666 TCHECK(*cimp); 667 services = EXTRACT_LE_8BITS(cimp->ci_services); 668 info = EXTRACT_LE_8BITS(cimp->ci_info); 669 segsize = EXTRACT_LE_16BITS(cimp->ci_segsize); 670 671 switch (services & COS_MASK) { 672 case COS_NONE: 673 break; 674 case COS_SEGMENT: 675 (void)printf("seg "); 676 break; 677 case COS_MESSAGE: 678 (void)printf("msg "); 679 break; 680 case COS_CRYPTSER: 681 (void)printf("crypt "); 682 break; 683 } 684 switch (info & COI_MASK) { 685 case COI_32: 686 (void)printf("ver 3.2 "); 687 break; 688 case COI_31: 689 (void)printf("ver 3.1 "); 690 break; 691 case COI_40: 692 (void)printf("ver 4.0 "); 693 break; 694 case COI_41: 695 (void)printf("ver 4.1 "); 696 break; 697 } 698 (void)printf("segsize %d ", segsize); 699 #ifdef PRINT_NSPDATA 700 if (nsplen > sizeof(struct cimsg)) { 701 dp = &(nspp[sizeof(struct cimsg)]); 702 TCHECK2(*dp, nsplen - sizeof(struct cimsg)); 703 pdata(dp, nsplen - sizeof(struct cimsg)); 704 } 705 #endif 706 } 707 break; 708 case MFS_CC: 709 (void)printf("conn-confirm %d>%d ", src, dst); 710 { 711 struct ccmsg *ccmp = (struct ccmsg *)nspp; 712 int services, info; 713 u_int segsize, optlen; 714 #ifdef PRINT_NSPDATA 715 u_char *dp; 716 #endif 717 718 if (nsplen < sizeof(struct ccmsg)) 719 goto trunc; 720 TCHECK(*ccmp); 721 services = EXTRACT_LE_8BITS(ccmp->cc_services); 722 info = EXTRACT_LE_8BITS(ccmp->cc_info); 723 segsize = EXTRACT_LE_16BITS(ccmp->cc_segsize); 724 optlen = EXTRACT_LE_8BITS(ccmp->cc_optlen); 725 726 switch (services & COS_MASK) { 727 case COS_NONE: 728 break; 729 case COS_SEGMENT: 730 (void)printf("seg "); 731 break; 732 case COS_MESSAGE: 733 (void)printf("msg "); 734 break; 735 case COS_CRYPTSER: 736 (void)printf("crypt "); 737 break; 738 } 739 switch (info & COI_MASK) { 740 case COI_32: 741 (void)printf("ver 3.2 "); 742 break; 743 case COI_31: 744 (void)printf("ver 3.1 "); 745 break; 746 case COI_40: 747 (void)printf("ver 4.0 "); 748 break; 749 case COI_41: 750 (void)printf("ver 4.1 "); 751 break; 752 } 753 (void)printf("segsize %d ", segsize); 754 if (optlen) { 755 (void)printf("optlen %d ", optlen); 756 #ifdef PRINT_NSPDATA 757 if (optlen > nsplen - sizeof(struct ccmsg)) 758 goto trunc; 759 dp = &(nspp[sizeof(struct ccmsg)]); 760 TCHECK2(*dp, optlen); 761 pdata(dp, optlen); 762 #endif 763 } 764 } 765 break; 766 case MFS_DI: 767 (void)printf("disconn-initiate %d>%d ", src, dst); 768 { 769 struct dimsg *dimp = (struct dimsg *)nspp; 770 int reason; 771 u_int optlen; 772 #ifdef PRINT_NSPDATA 773 u_char *dp; 774 #endif 775 776 if (nsplen < sizeof(struct dimsg)) 777 goto trunc; 778 TCHECK(*dimp); 779 reason = EXTRACT_LE_16BITS(dimp->di_reason); 780 optlen = EXTRACT_LE_8BITS(dimp->di_optlen); 781 782 print_reason(reason); 783 if (optlen) { 784 (void)printf("optlen %d ", optlen); 785 #ifdef PRINT_NSPDATA 786 if (optlen > nsplen - sizeof(struct dimsg)) 787 goto trunc; 788 dp = &(nspp[sizeof(struct dimsg)]); 789 TCHECK2(*dp, optlen); 790 pdata(dp, optlen); 791 #endif 792 } 793 } 794 break; 795 case MFS_DC: 796 (void)printf("disconn-confirm %d>%d ", src, dst); 797 { 798 struct dcmsg *dcmp = (struct dcmsg *)nspp; 799 int reason; 800 801 TCHECK(*dcmp); 802 reason = EXTRACT_LE_16BITS(dcmp->dc_reason); 803 804 print_reason(reason); 805 } 806 break; 807 default: 808 (void)printf("reserved-ctltype? %x %d > %d", flags, src, dst); 809 break; 810 } 811 break; 812 default: 813 (void)printf("reserved-type? %x %d > %d", flags, src, dst); 814 break; 815 } 816 return (1); 817 818 trunc: 819 return (0); 820 } 821 822 static const struct tok reason2str[] = { 823 { UC_OBJREJECT, "object rejected connect" }, 824 { UC_RESOURCES, "insufficient resources" }, 825 { UC_NOSUCHNODE, "unrecognized node name" }, 826 { DI_SHUT, "node is shutting down" }, 827 { UC_NOSUCHOBJ, "unrecognized object" }, 828 { UC_INVOBJFORMAT, "invalid object name format" }, 829 { UC_OBJTOOBUSY, "object too busy" }, 830 { DI_PROTOCOL, "protocol error discovered" }, 831 { DI_TPA, "third party abort" }, 832 { UC_USERABORT, "user abort" }, 833 { UC_INVNODEFORMAT, "invalid node name format" }, 834 { UC_LOCALSHUT, "local node shutting down" }, 835 { DI_LOCALRESRC, "insufficient local resources" }, 836 { DI_REMUSERRESRC, "insufficient remote user resources" }, 837 { UC_ACCESSREJECT, "invalid access control information" }, 838 { DI_BADACCNT, "bad ACCOUNT information" }, 839 { UC_NORESPONSE, "no response from object" }, 840 { UC_UNREACHABLE, "node unreachable" }, 841 { DC_NOLINK, "no link terminate" }, 842 { DC_COMPLETE, "disconnect complete" }, 843 { DI_BADIMAGE, "bad image data in connect" }, 844 { DI_SERVMISMATCH, "cryptographic service mismatch" }, 845 { 0, NULL } 846 }; 847 848 static void 849 print_reason(register int reason) 850 { 851 printf("%s ", tok2str(reason2str, "reason-%d", reason)); 852 } 853 854 const char * 855 dnnum_string(u_short dnaddr) 856 { 857 char *str; 858 size_t siz; 859 int area = (u_short)(dnaddr & AREAMASK) >> AREASHIFT; 860 int node = dnaddr & NODEMASK; 861 862 str = (char *)malloc(siz = sizeof("00.0000")); 863 if (str == NULL) 864 error("dnnum_string: malloc"); 865 snprintf(str, siz, "%d.%d", area, node); 866 return(str); 867 } 868 869 const char * 870 dnname_string(u_short dnaddr) 871 { 872 #ifdef HAVE_DNET_HTOA 873 struct dn_naddr dna; 874 875 dna.a_len = sizeof(short); 876 memcpy((char *)dna.a_addr, (char *)&dnaddr, sizeof(short)); 877 return (strdup(dnet_htoa(&dna))); 878 #else 879 return(dnnum_string(dnaddr)); /* punt */ 880 #endif 881 } 882 883 #ifdef PRINT_NSPDATA 884 static void 885 pdata(u_char *dp, u_int maxlen) 886 { 887 char c; 888 u_int x = maxlen; 889 890 while (x-- > 0) { 891 c = *dp++; 892 safeputchar(c); 893 } 894 } 895 #endif 896