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