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