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