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