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