1/* 2 * Copyright (c) 1992, 1993, 1994, 1995, 1996, 1997 3 * The Regents of the University of California. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that: (1) source code distributions 7 * retain the above copyright notice and this paragraph in its entirety, (2) 8 * distributions including binary code include the above copyright notice and 9 * this paragraph in its entirety in the documentation or other materials 10 * provided with the distribution, and (3) all advertising materials mentioning 11 * features or use of this software display the following acknowledgement: 12 * ``This product includes software developed by the University of California, 13 * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of 14 * the University nor the names of its contributors may be used to endorse 15 * or promote products derived from this software without specific prior 16 * written permission. 17 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED 18 * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF 19 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 20 */ 21 22#define NETDISSECT_REWORKED 23#ifdef HAVE_CONFIG_H 24#include "config.h" 25#endif 26 27#include <tcpdump-stdinc.h> 28 29struct mbuf; 30struct rtentry; 31 32#ifdef HAVE_NETDNET_DNETDB_H 33#include <netdnet/dnetdb.h> 34#endif 35 36#include <stdio.h> 37#include <stdlib.h> 38#include <string.h> 39 40#include "extract.h" 41#include "interface.h" 42#include "addrtoname.h" 43 44static const char tstr[] = "[|decnet]"; 45 46#ifndef WIN32 47typedef uint8_t byte[1]; /* single byte field */ 48#else 49/* 50 * the keyword 'byte' generates conflicts in Windows 51 */ 52typedef unsigned char Byte[1]; /* single byte field */ 53#define byte Byte 54#endif /* WIN32 */ 55typedef uint8_t word[2]; /* 2 byte field */ 56typedef uint8_t longword[4]; /* 4 bytes field */ 57 58/* 59 * Definitions for DECNET Phase IV protocol headers 60 */ 61union etheraddress { 62 uint8_t dne_addr[6]; /* full ethernet address */ 63 struct { 64 uint8_t dne_hiord[4]; /* DECnet HIORD prefix */ 65 uint8_t dne_nodeaddr[2]; /* DECnet node address */ 66 } dne_remote; 67}; 68 69typedef union etheraddress etheraddr; /* Ethernet address */ 70 71#define HIORD 0x000400aa /* high 32-bits of address (swapped) */ 72 73#define AREAMASK 0176000 /* mask for area field */ 74#define AREASHIFT 10 /* bit-offset for area field */ 75#define NODEMASK 01777 /* mask for node address field */ 76 77#define DN_MAXADDL 20 /* max size of DECnet address */ 78struct dn_naddr { 79 uint16_t a_len; /* length of address */ 80 uint8_t a_addr[DN_MAXADDL]; /* address as bytes */ 81}; 82 83/* 84 * Define long and short header formats. 85 */ 86struct shorthdr 87 { 88 byte sh_flags; /* route flags */ 89 word sh_dst; /* destination node address */ 90 word sh_src; /* source node address */ 91 byte sh_visits; /* visit count */ 92 }; 93 94struct longhdr 95 { 96 byte lg_flags; /* route flags */ 97 byte lg_darea; /* destination area (reserved) */ 98 byte lg_dsarea; /* destination subarea (reserved) */ 99 etheraddr lg_dst; /* destination id */ 100 byte lg_sarea; /* source area (reserved) */ 101 byte lg_ssarea; /* source subarea (reserved) */ 102 etheraddr lg_src; /* source id */ 103 byte lg_nextl2; /* next level 2 router (reserved) */ 104 byte lg_visits; /* visit count */ 105 byte lg_service; /* service class (reserved) */ 106 byte lg_pt; /* protocol type (reserved) */ 107 }; 108 109union routehdr 110 { 111 struct shorthdr rh_short; /* short route header */ 112 struct longhdr rh_long; /* long route header */ 113 }; 114 115/* 116 * Define the values of various fields in the protocol messages. 117 * 118 * 1. Data packet formats. 119 */ 120#define RMF_MASK 7 /* mask for message type */ 121#define RMF_SHORT 2 /* short message format */ 122#define RMF_LONG 6 /* long message format */ 123#ifndef RMF_RQR 124#define RMF_RQR 010 /* request return to sender */ 125#define RMF_RTS 020 /* returning to sender */ 126#define RMF_IE 040 /* intra-ethernet packet */ 127#endif /* RMR_RQR */ 128#define RMF_FVER 0100 /* future version flag */ 129#define RMF_PAD 0200 /* pad field */ 130#define RMF_PADMASK 0177 /* pad field mask */ 131 132#define VIS_MASK 077 /* visit field mask */ 133 134/* 135 * 2. Control packet formats. 136 */ 137#define RMF_CTLMASK 017 /* mask for message type */ 138#define RMF_CTLMSG 01 /* control message indicator */ 139#define RMF_INIT 01 /* initialization message */ 140#define RMF_VER 03 /* verification message */ 141#define RMF_TEST 05 /* hello and test message */ 142#define RMF_L1ROUT 07 /* level 1 routing message */ 143#define RMF_L2ROUT 011 /* level 2 routing message */ 144#define RMF_RHELLO 013 /* router hello message */ 145#define RMF_EHELLO 015 /* endnode hello message */ 146 147#define TI_L2ROUT 01 /* level 2 router */ 148#define TI_L1ROUT 02 /* level 1 router */ 149#define TI_ENDNODE 03 /* endnode */ 150#define TI_VERIF 04 /* verification required */ 151#define TI_BLOCK 010 /* blocking requested */ 152 153#define VE_VERS 2 /* version number (2) */ 154#define VE_ECO 0 /* ECO number */ 155#define VE_UECO 0 /* user ECO number (0) */ 156 157#define P3_VERS 1 /* phase III version number (1) */ 158#define P3_ECO 3 /* ECO number (3) */ 159#define P3_UECO 0 /* user ECO number (0) */ 160 161#define II_L2ROUT 01 /* level 2 router */ 162#define II_L1ROUT 02 /* level 1 router */ 163#define II_ENDNODE 03 /* endnode */ 164#define II_VERIF 04 /* verification required */ 165#define II_NOMCAST 040 /* no multicast traffic accepted */ 166#define II_BLOCK 0100 /* blocking requested */ 167#define II_TYPEMASK 03 /* mask for node type */ 168 169#define TESTDATA 0252 /* test data bytes */ 170#define TESTLEN 1 /* length of transmitted test data */ 171 172/* 173 * Define control message formats. 174 */ 175struct initmsgIII /* phase III initialization message */ 176 { 177 byte inIII_flags; /* route flags */ 178 word inIII_src; /* source node address */ 179 byte inIII_info; /* routing layer information */ 180 word inIII_blksize; /* maximum data link block size */ 181 byte inIII_vers; /* version number */ 182 byte inIII_eco; /* ECO number */ 183 byte inIII_ueco; /* user ECO number */ 184 byte inIII_rsvd; /* reserved image field */ 185 }; 186 187struct initmsg /* initialization message */ 188 { 189 byte in_flags; /* route flags */ 190 word in_src; /* source node address */ 191 byte in_info; /* routing layer information */ 192 word in_blksize; /* maximum data link block size */ 193 byte in_vers; /* version number */ 194 byte in_eco; /* ECO number */ 195 byte in_ueco; /* user ECO number */ 196 word in_hello; /* hello timer */ 197 byte in_rsvd; /* reserved image field */ 198 }; 199 200struct verifmsg /* verification message */ 201 { 202 byte ve_flags; /* route flags */ 203 word ve_src; /* source node address */ 204 byte ve_fcnval; /* function value image field */ 205 }; 206 207struct testmsg /* hello and test message */ 208 { 209 byte te_flags; /* route flags */ 210 word te_src; /* source node address */ 211 byte te_data; /* test data image field */ 212 }; 213 214struct l1rout /* level 1 routing message */ 215 { 216 byte r1_flags; /* route flags */ 217 word r1_src; /* source node address */ 218 byte r1_rsvd; /* reserved field */ 219 }; 220 221struct l2rout /* level 2 routing message */ 222 { 223 byte r2_flags; /* route flags */ 224 word r2_src; /* source node address */ 225 byte r2_rsvd; /* reserved field */ 226 }; 227 228struct rhellomsg /* router hello message */ 229 { 230 byte rh_flags; /* route flags */ 231 byte rh_vers; /* version number */ 232 byte rh_eco; /* ECO number */ 233 byte rh_ueco; /* user ECO number */ 234 etheraddr rh_src; /* source id */ 235 byte rh_info; /* routing layer information */ 236 word rh_blksize; /* maximum data link block size */ 237 byte rh_priority; /* router's priority */ 238 byte rh_area; /* reserved */ 239 word rh_hello; /* hello timer */ 240 byte rh_mpd; /* reserved */ 241 }; 242 243struct ehellomsg /* endnode hello message */ 244 { 245 byte eh_flags; /* route flags */ 246 byte eh_vers; /* version number */ 247 byte eh_eco; /* ECO number */ 248 byte eh_ueco; /* user ECO number */ 249 etheraddr eh_src; /* source id */ 250 byte eh_info; /* routing layer information */ 251 word eh_blksize; /* maximum data link block size */ 252 byte eh_area; /* area (reserved) */ 253 byte eh_seed[8]; /* verification seed */ 254 etheraddr eh_router; /* designated router */ 255 word eh_hello; /* hello timer */ 256 byte eh_mpd; /* (reserved) */ 257 byte eh_data; /* test data image field */ 258 }; 259 260union controlmsg 261 { 262 struct initmsg cm_init; /* initialization message */ 263 struct verifmsg cm_ver; /* verification message */ 264 struct testmsg cm_test; /* hello and test message */ 265 struct l1rout cm_l1rou; /* level 1 routing message */ 266 struct l2rout cm_l2rout; /* level 2 routing message */ 267 struct rhellomsg cm_rhello; /* router hello message */ 268 struct ehellomsg cm_ehello; /* endnode hello message */ 269 }; 270 271/* Macros for decoding routing-info fields */ 272#define RI_COST(x) ((x)&0777) 273#define RI_HOPS(x) (((x)>>10)&037) 274 275/* 276 * NSP protocol fields and values. 277 */ 278 279#define NSP_TYPEMASK 014 /* mask to isolate type code */ 280#define NSP_SUBMASK 0160 /* mask to isolate subtype code */ 281#define NSP_SUBSHFT 4 /* shift to move subtype code */ 282 283#define MFT_DATA 0 /* data message */ 284#define MFT_ACK 04 /* acknowledgement message */ 285#define MFT_CTL 010 /* control message */ 286 287#define MFS_ILS 020 /* data or I/LS indicator */ 288#define MFS_BOM 040 /* beginning of message (data) */ 289#define MFS_MOM 0 /* middle of message (data) */ 290#define MFS_EOM 0100 /* end of message (data) */ 291#define MFS_INT 040 /* interrupt message */ 292 293#define MFS_DACK 0 /* data acknowledgement */ 294#define MFS_IACK 020 /* I/LS acknowledgement */ 295#define MFS_CACK 040 /* connect acknowledgement */ 296 297#define MFS_NOP 0 /* no operation */ 298#define MFS_CI 020 /* connect initiate */ 299#define MFS_CC 040 /* connect confirm */ 300#define MFS_DI 060 /* disconnect initiate */ 301#define MFS_DC 0100 /* disconnect confirm */ 302#define MFS_RCI 0140 /* retransmitted connect initiate */ 303 304#define SGQ_ACK 0100000 /* ack */ 305#define SGQ_NAK 0110000 /* negative ack */ 306#define SGQ_OACK 0120000 /* other channel ack */ 307#define SGQ_ONAK 0130000 /* other channel negative ack */ 308#define SGQ_MASK 07777 /* mask to isolate seq # */ 309#define SGQ_OTHER 020000 /* other channel qualifier */ 310#define SGQ_DELAY 010000 /* ack delay flag */ 311 312#define SGQ_EOM 0100000 /* pseudo flag for end-of-message */ 313 314#define LSM_MASK 03 /* mask for modifier field */ 315#define LSM_NOCHANGE 0 /* no change */ 316#define LSM_DONOTSEND 1 /* do not send data */ 317#define LSM_SEND 2 /* send data */ 318 319#define LSI_MASK 014 /* mask for interpretation field */ 320#define LSI_DATA 0 /* data segment or message count */ 321#define LSI_INTR 4 /* interrupt request count */ 322#define LSI_INTM 0377 /* funny marker for int. message */ 323 324#define COS_MASK 014 /* mask for flow control field */ 325#define COS_NONE 0 /* no flow control */ 326#define COS_SEGMENT 04 /* segment flow control */ 327#define COS_MESSAGE 010 /* message flow control */ 328#define COS_CRYPTSER 020 /* cryptographic services requested */ 329#define COS_DEFAULT 1 /* default value for field */ 330 331#define COI_MASK 3 /* mask for version field */ 332#define COI_32 0 /* version 3.2 */ 333#define COI_31 1 /* version 3.1 */ 334#define COI_40 2 /* version 4.0 */ 335#define COI_41 3 /* version 4.1 */ 336 337#define MNU_MASK 140 /* mask for session control version */ 338#define MNU_10 000 /* session V1.0 */ 339#define MNU_20 040 /* session V2.0 */ 340#define MNU_ACCESS 1 /* access control present */ 341#define MNU_USRDATA 2 /* user data field present */ 342#define MNU_INVKPROXY 4 /* invoke proxy field present */ 343#define MNU_UICPROXY 8 /* use uic-based proxy */ 344 345#define DC_NORESOURCES 1 /* no resource reason code */ 346#define DC_NOLINK 41 /* no link terminate reason code */ 347#define DC_COMPLETE 42 /* disconnect complete reason code */ 348 349#define DI_NOERROR 0 /* user disconnect */ 350#define DI_SHUT 3 /* node is shutting down */ 351#define DI_NOUSER 4 /* destination end user does not exist */ 352#define DI_INVDEST 5 /* invalid end user destination */ 353#define DI_REMRESRC 6 /* insufficient remote resources */ 354#define DI_TPA 8 /* third party abort */ 355#define DI_PROTOCOL 7 /* protocol error discovered */ 356#define DI_ABORT 9 /* user abort */ 357#define DI_LOCALRESRC 32 /* insufficient local resources */ 358#define DI_REMUSERRESRC 33 /* insufficient remote user resources */ 359#define DI_BADACCESS 34 /* bad access control information */ 360#define DI_BADACCNT 36 /* bad ACCOUNT information */ 361#define DI_CONNECTABORT 38 /* connect request cancelled */ 362#define DI_TIMEDOUT 38 /* remote node or user crashed */ 363#define DI_UNREACHABLE 39 /* local timers expired due to ... */ 364#define DI_BADIMAGE 43 /* bad image data in connect */ 365#define DI_SERVMISMATCH 54 /* cryptographic service mismatch */ 366 367#define UC_OBJREJECT 0 /* object rejected connect */ 368#define UC_USERDISCONNECT 0 /* user disconnect */ 369#define UC_RESOURCES 1 /* insufficient resources (local or remote) */ 370#define UC_NOSUCHNODE 2 /* unrecognized node name */ 371#define UC_REMOTESHUT 3 /* remote node shutting down */ 372#define UC_NOSUCHOBJ 4 /* unrecognized object */ 373#define UC_INVOBJFORMAT 5 /* invalid object name format */ 374#define UC_OBJTOOBUSY 6 /* object too busy */ 375#define UC_NETWORKABORT 8 /* network abort */ 376#define UC_USERABORT 9 /* user abort */ 377#define UC_INVNODEFORMAT 10 /* invalid node name format */ 378#define UC_LOCALSHUT 11 /* local node shutting down */ 379#define UC_ACCESSREJECT 34 /* invalid access control information */ 380#define UC_NORESPONSE 38 /* no response from object */ 381#define UC_UNREACHABLE 39 /* node unreachable */ 382 383/* 384 * NSP message formats. 385 */ 386struct nsphdr /* general nsp header */ 387 { 388 byte nh_flags; /* message flags */ 389 word nh_dst; /* destination link address */ 390 word nh_src; /* source link address */ 391 }; 392 393struct seghdr /* data segment header */ 394 { 395 byte sh_flags; /* message flags */ 396 word sh_dst; /* destination link address */ 397 word sh_src; /* source link address */ 398 word sh_seq[3]; /* sequence numbers */ 399 }; 400 401struct minseghdr /* minimum data segment header */ 402 { 403 byte ms_flags; /* message flags */ 404 word ms_dst; /* destination link address */ 405 word ms_src; /* source link address */ 406 word ms_seq; /* sequence number */ 407 }; 408 409struct lsmsg /* link service message (after hdr) */ 410 { 411 byte ls_lsflags; /* link service flags */ 412 byte ls_fcval; /* flow control value */ 413 }; 414 415struct ackmsg /* acknowledgement message */ 416 { 417 byte ak_flags; /* message flags */ 418 word ak_dst; /* destination link address */ 419 word ak_src; /* source link address */ 420 word ak_acknum[2]; /* acknowledgement numbers */ 421 }; 422 423struct minackmsg /* minimum acknowledgement message */ 424 { 425 byte mk_flags; /* message flags */ 426 word mk_dst; /* destination link address */ 427 word mk_src; /* source link address */ 428 word mk_acknum; /* acknowledgement number */ 429 }; 430 431struct ciackmsg /* connect acknowledgement message */ 432 { 433 byte ck_flags; /* message flags */ 434 word ck_dst; /* destination link address */ 435 }; 436 437struct cimsg /* connect initiate message */ 438 { 439 byte ci_flags; /* message flags */ 440 word ci_dst; /* destination link address (0) */ 441 word ci_src; /* source link address */ 442 byte ci_services; /* requested services */ 443 byte ci_info; /* information */ 444 word ci_segsize; /* maximum segment size */ 445 }; 446 447struct ccmsg /* connect confirm message */ 448 { 449 byte cc_flags; /* message flags */ 450 word cc_dst; /* destination link address */ 451 word cc_src; /* source link address */ 452 byte cc_services; /* requested services */ 453 byte cc_info; /* information */ 454 word cc_segsize; /* maximum segment size */ 455 byte cc_optlen; /* optional data length */ 456 }; 457 458struct cnmsg /* generic connect message */ 459 { 460 byte cn_flags; /* message flags */ 461 word cn_dst; /* destination link address */ 462 word cn_src; /* source link address */ 463 byte cn_services; /* requested services */ 464 byte cn_info; /* information */ 465 word cn_segsize; /* maximum segment size */ 466 }; 467 468struct dimsg /* disconnect initiate message */ 469 { 470 byte di_flags; /* message flags */ 471 word di_dst; /* destination link address */ 472 word di_src; /* source link address */ 473 word di_reason; /* reason code */ 474 byte di_optlen; /* optional data length */ 475 }; 476 477struct dcmsg /* disconnect confirm message */ 478 { 479 byte dc_flags; /* message flags */ 480 word dc_dst; /* destination link address */ 481 word dc_src; /* source link address */ 482 word dc_reason; /* reason code */ 483 }; 484 485/* Forwards */ 486static int print_decnet_ctlmsg(netdissect_options *, const union routehdr *, u_int, u_int); 487static void print_t_info(netdissect_options *, int); 488static int print_l1_routes(netdissect_options *, const char *, u_int); 489static int print_l2_routes(netdissect_options *, const char *, u_int); 490static void print_i_info(netdissect_options *, int); 491static int print_elist(const char *, u_int); 492static int print_nsp(netdissect_options *, const u_char *, u_int); 493static void print_reason(netdissect_options *, int); 494#ifdef PRINT_NSPDATA 495static void pdata(netdissect_options *, u_char *, u_int); 496#endif 497 498#ifndef HAVE_NETDNET_DNETDB_H_DNET_HTOA 499extern char *dnet_htoa(struct dn_naddr *); 500#endif 501 502void 503decnet_print(netdissect_options *ndo, 504 register const u_char *ap, register u_int length, 505 register u_int caplen) 506{ 507 register const union routehdr *rhp; 508 register int mflags; 509 int dst, src, hops; 510 u_int nsplen, pktlen; 511 const u_char *nspp; 512 513 if (length < sizeof(struct shorthdr)) { 514 ND_PRINT((ndo, "%s", tstr)); 515 return; 516 } 517 518 ND_TCHECK2(*ap, sizeof(short)); 519 pktlen = EXTRACT_LE_16BITS(ap); 520 if (pktlen < sizeof(struct shorthdr)) { 521 ND_PRINT((ndo, "%s", tstr)); 522 return; 523 } 524 if (pktlen > length) { 525 ND_PRINT((ndo, "%s", tstr)); 526 return; 527 } 528 length = pktlen; 529 530 rhp = (const union routehdr *)&(ap[sizeof(short)]); 531 ND_TCHECK(rhp->rh_short.sh_flags); 532 mflags = EXTRACT_LE_8BITS(rhp->rh_short.sh_flags); 533 534 if (mflags & RMF_PAD) { 535 /* pad bytes of some sort in front of message */ 536 u_int padlen = mflags & RMF_PADMASK; 537 if (ndo->ndo_vflag) 538 ND_PRINT((ndo, "[pad:%d] ", padlen)); 539 if (length < padlen + 2) { 540 ND_PRINT((ndo, "%s", tstr)); 541 return; 542 } 543 ND_TCHECK2(ap[sizeof(short)], padlen); 544 ap += padlen; 545 length -= padlen; 546 caplen -= padlen; 547 rhp = (const union routehdr *)&(ap[sizeof(short)]); 548 mflags = EXTRACT_LE_8BITS(rhp->rh_short.sh_flags); 549 } 550 551 if (mflags & RMF_FVER) { 552 ND_PRINT((ndo, "future-version-decnet")); 553 ND_DEFAULTPRINT(ap, min(length, caplen)); 554 return; 555 } 556 557 /* is it a control message? */ 558 if (mflags & RMF_CTLMSG) { 559 if (!print_decnet_ctlmsg(ndo, rhp, length, caplen)) 560 goto trunc; 561 return; 562 } 563 564 switch (mflags & RMF_MASK) { 565 case RMF_LONG: 566 if (length < sizeof(struct longhdr)) { 567 ND_PRINT((ndo, "%s", tstr)); 568 return; 569 } 570 ND_TCHECK(rhp->rh_long); 571 dst = 572 EXTRACT_LE_16BITS(rhp->rh_long.lg_dst.dne_remote.dne_nodeaddr); 573 src = 574 EXTRACT_LE_16BITS(rhp->rh_long.lg_src.dne_remote.dne_nodeaddr); 575 hops = EXTRACT_LE_8BITS(rhp->rh_long.lg_visits); 576 nspp = &(ap[sizeof(short) + sizeof(struct longhdr)]); 577 nsplen = length - sizeof(struct longhdr); 578 break; 579 case RMF_SHORT: 580 ND_TCHECK(rhp->rh_short); 581 dst = EXTRACT_LE_16BITS(rhp->rh_short.sh_dst); 582 src = EXTRACT_LE_16BITS(rhp->rh_short.sh_src); 583 hops = (EXTRACT_LE_8BITS(rhp->rh_short.sh_visits) & VIS_MASK)+1; 584 nspp = &(ap[sizeof(short) + sizeof(struct shorthdr)]); 585 nsplen = length - sizeof(struct shorthdr); 586 break; 587 default: 588 ND_PRINT((ndo, "unknown message flags under mask")); 589 ND_DEFAULTPRINT((u_char *)ap, min(length, caplen)); 590 return; 591 } 592 593 ND_PRINT((ndo, "%s > %s %d ", 594 dnaddr_string(ndo, src), dnaddr_string(ndo, dst), pktlen)); 595 if (ndo->ndo_vflag) { 596 if (mflags & RMF_RQR) 597 ND_PRINT((ndo, "RQR ")); 598 if (mflags & RMF_RTS) 599 ND_PRINT((ndo, "RTS ")); 600 if (mflags & RMF_IE) 601 ND_PRINT((ndo, "IE ")); 602 ND_PRINT((ndo, "%d hops ", hops)); 603 } 604 605 if (!print_nsp(ndo, nspp, nsplen)) 606 goto trunc; 607 return; 608 609trunc: 610 ND_PRINT((ndo, "%s", tstr)); 611 return; 612} 613 614static int 615print_decnet_ctlmsg(netdissect_options *ndo, 616 register const union routehdr *rhp, u_int length, 617 u_int caplen) 618{ 619 int mflags = EXTRACT_LE_8BITS(rhp->rh_short.sh_flags); 620 register union controlmsg *cmp = (union controlmsg *)rhp; 621 int src, dst, info, blksize, eco, ueco, hello, other, vers; 622 etheraddr srcea, rtea; 623 int priority; 624 char *rhpx = (char *)rhp; 625 int ret; 626 627 switch (mflags & RMF_CTLMASK) { 628 case RMF_INIT: 629 ND_PRINT((ndo, "init ")); 630 if (length < sizeof(struct initmsg)) 631 goto trunc; 632 ND_TCHECK(cmp->cm_init); 633 src = EXTRACT_LE_16BITS(cmp->cm_init.in_src); 634 info = EXTRACT_LE_8BITS(cmp->cm_init.in_info); 635 blksize = EXTRACT_LE_16BITS(cmp->cm_init.in_blksize); 636 vers = EXTRACT_LE_8BITS(cmp->cm_init.in_vers); 637 eco = EXTRACT_LE_8BITS(cmp->cm_init.in_eco); 638 ueco = EXTRACT_LE_8BITS(cmp->cm_init.in_ueco); 639 hello = EXTRACT_LE_16BITS(cmp->cm_init.in_hello); 640 print_t_info(ndo, info); 641 ND_PRINT((ndo, 642 "src %sblksize %d vers %d eco %d ueco %d hello %d", 643 dnaddr_string(ndo, src), blksize, vers, eco, ueco, 644 hello)); 645 ret = 1; 646 break; 647 case RMF_VER: 648 ND_PRINT((ndo, "verification ")); 649 if (length < sizeof(struct verifmsg)) 650 goto trunc; 651 ND_TCHECK(cmp->cm_ver); 652 src = EXTRACT_LE_16BITS(cmp->cm_ver.ve_src); 653 other = EXTRACT_LE_8BITS(cmp->cm_ver.ve_fcnval); 654 ND_PRINT((ndo, "src %s fcnval %o", dnaddr_string(ndo, src), other)); 655 ret = 1; 656 break; 657 case RMF_TEST: 658 ND_PRINT((ndo, "test ")); 659 if (length < sizeof(struct testmsg)) 660 goto trunc; 661 ND_TCHECK(cmp->cm_test); 662 src = EXTRACT_LE_16BITS(cmp->cm_test.te_src); 663 other = EXTRACT_LE_8BITS(cmp->cm_test.te_data); 664 ND_PRINT((ndo, "src %s data %o", dnaddr_string(ndo, src), other)); 665 ret = 1; 666 break; 667 case RMF_L1ROUT: 668 ND_PRINT((ndo, "lev-1-routing ")); 669 if (length < sizeof(struct l1rout)) 670 goto trunc; 671 ND_TCHECK(cmp->cm_l1rou); 672 src = EXTRACT_LE_16BITS(cmp->cm_l1rou.r1_src); 673 ND_PRINT((ndo, "src %s ", dnaddr_string(ndo, src))); 674 ret = print_l1_routes(ndo, &(rhpx[sizeof(struct l1rout)]), 675 length - sizeof(struct l1rout)); 676 break; 677 case RMF_L2ROUT: 678 ND_PRINT((ndo, "lev-2-routing ")); 679 if (length < sizeof(struct l2rout)) 680 goto trunc; 681 ND_TCHECK(cmp->cm_l2rout); 682 src = EXTRACT_LE_16BITS(cmp->cm_l2rout.r2_src); 683 ND_PRINT((ndo, "src %s ", dnaddr_string(ndo, src))); 684 ret = print_l2_routes(ndo, &(rhpx[sizeof(struct l2rout)]), 685 length - sizeof(struct l2rout)); 686 break; 687 case RMF_RHELLO: 688 ND_PRINT((ndo, "router-hello ")); 689 if (length < sizeof(struct rhellomsg)) 690 goto trunc; 691 ND_TCHECK(cmp->cm_rhello); 692 vers = EXTRACT_LE_8BITS(cmp->cm_rhello.rh_vers); 693 eco = EXTRACT_LE_8BITS(cmp->cm_rhello.rh_eco); 694 ueco = EXTRACT_LE_8BITS(cmp->cm_rhello.rh_ueco); 695 memcpy((char *)&srcea, (char *)&(cmp->cm_rhello.rh_src), 696 sizeof(srcea)); 697 src = EXTRACT_LE_16BITS(srcea.dne_remote.dne_nodeaddr); 698 info = EXTRACT_LE_8BITS(cmp->cm_rhello.rh_info); 699 blksize = EXTRACT_LE_16BITS(cmp->cm_rhello.rh_blksize); 700 priority = EXTRACT_LE_8BITS(cmp->cm_rhello.rh_priority); 701 hello = EXTRACT_LE_16BITS(cmp->cm_rhello.rh_hello); 702 print_i_info(ndo, info); 703 ND_PRINT((ndo, 704 "vers %d eco %d ueco %d src %s blksize %d pri %d hello %d", 705 vers, eco, ueco, dnaddr_string(ndo, src), 706 blksize, priority, hello)); 707 ret = print_elist(&(rhpx[sizeof(struct rhellomsg)]), 708 length - sizeof(struct rhellomsg)); 709 break; 710 case RMF_EHELLO: 711 ND_PRINT((ndo, "endnode-hello ")); 712 if (length < sizeof(struct ehellomsg)) 713 goto trunc; 714 ND_TCHECK(cmp->cm_ehello); 715 vers = EXTRACT_LE_8BITS(cmp->cm_ehello.eh_vers); 716 eco = EXTRACT_LE_8BITS(cmp->cm_ehello.eh_eco); 717 ueco = EXTRACT_LE_8BITS(cmp->cm_ehello.eh_ueco); 718 memcpy((char *)&srcea, (char *)&(cmp->cm_ehello.eh_src), 719 sizeof(srcea)); 720 src = EXTRACT_LE_16BITS(srcea.dne_remote.dne_nodeaddr); 721 info = EXTRACT_LE_8BITS(cmp->cm_ehello.eh_info); 722 blksize = EXTRACT_LE_16BITS(cmp->cm_ehello.eh_blksize); 723 /*seed*/ 724 memcpy((char *)&rtea, (char *)&(cmp->cm_ehello.eh_router), 725 sizeof(rtea)); 726 dst = EXTRACT_LE_16BITS(rtea.dne_remote.dne_nodeaddr); 727 hello = EXTRACT_LE_16BITS(cmp->cm_ehello.eh_hello); 728 other = EXTRACT_LE_8BITS(cmp->cm_ehello.eh_data); 729 print_i_info(ndo, info); 730 ND_PRINT((ndo, 731 "vers %d eco %d ueco %d src %s blksize %d rtr %s hello %d data %o", 732 vers, eco, ueco, dnaddr_string(ndo, src), 733 blksize, dnaddr_string(ndo, dst), hello, other)); 734 ret = 1; 735 break; 736 737 default: 738 ND_PRINT((ndo, "unknown control message")); 739 ND_DEFAULTPRINT((u_char *)rhp, min(length, caplen)); 740 ret = 1; 741 break; 742 } 743 return (ret); 744 745trunc: 746 return (0); 747} 748 749static void 750print_t_info(netdissect_options *ndo, 751 int info) 752{ 753 int ntype = info & 3; 754 switch (ntype) { 755 case 0: ND_PRINT((ndo, "reserved-ntype? ")); break; 756 case TI_L2ROUT: ND_PRINT((ndo, "l2rout ")); break; 757 case TI_L1ROUT: ND_PRINT((ndo, "l1rout ")); break; 758 case TI_ENDNODE: ND_PRINT((ndo, "endnode ")); break; 759 } 760 if (info & TI_VERIF) 761 ND_PRINT((ndo, "verif ")); 762 if (info & TI_BLOCK) 763 ND_PRINT((ndo, "blo ")); 764} 765 766static int 767print_l1_routes(netdissect_options *ndo, 768 const char *rp, u_int len) 769{ 770 int count; 771 int id; 772 int info; 773 774 /* The last short is a checksum */ 775 while (len > (3 * sizeof(short))) { 776 ND_TCHECK2(*rp, 3 * sizeof(short)); 777 count = EXTRACT_LE_16BITS(rp); 778 if (count > 1024) 779 return (1); /* seems to be bogus from here on */ 780 rp += sizeof(short); 781 len -= sizeof(short); 782 id = EXTRACT_LE_16BITS(rp); 783 rp += sizeof(short); 784 len -= sizeof(short); 785 info = EXTRACT_LE_16BITS(rp); 786 rp += sizeof(short); 787 len -= sizeof(short); 788 ND_PRINT((ndo, "{ids %d-%d cost %d hops %d} ", id, id + count, 789 RI_COST(info), RI_HOPS(info))); 790 } 791 return (1); 792 793trunc: 794 return (0); 795} 796 797static int 798print_l2_routes(netdissect_options *ndo, 799 const char *rp, u_int len) 800{ 801 int count; 802 int area; 803 int info; 804 805 /* The last short is a checksum */ 806 while (len > (3 * sizeof(short))) { 807 ND_TCHECK2(*rp, 3 * sizeof(short)); 808 count = EXTRACT_LE_16BITS(rp); 809 if (count > 1024) 810 return (1); /* seems to be bogus from here on */ 811 rp += sizeof(short); 812 len -= sizeof(short); 813 area = EXTRACT_LE_16BITS(rp); 814 rp += sizeof(short); 815 len -= sizeof(short); 816 info = EXTRACT_LE_16BITS(rp); 817 rp += sizeof(short); 818 len -= sizeof(short); 819 ND_PRINT((ndo, "{areas %d-%d cost %d hops %d} ", area, area + count, 820 RI_COST(info), RI_HOPS(info))); 821 } 822 return (1); 823 824trunc: 825 return (0); 826} 827 828static void 829print_i_info(netdissect_options *ndo, 830 int info) 831{ 832 int ntype = info & II_TYPEMASK; 833 switch (ntype) { 834 case 0: ND_PRINT((ndo, "reserved-ntype? ")); break; 835 case II_L2ROUT: ND_PRINT((ndo, "l2rout ")); break; 836 case II_L1ROUT: ND_PRINT((ndo, "l1rout ")); break; 837 case II_ENDNODE: ND_PRINT((ndo, "endnode ")); break; 838 } 839 if (info & II_VERIF) 840 ND_PRINT((ndo, "verif ")); 841 if (info & II_NOMCAST) 842 ND_PRINT((ndo, "nomcast ")); 843 if (info & II_BLOCK) 844 ND_PRINT((ndo, "blo ")); 845} 846 847static int 848print_elist(const char *elp _U_, u_int len _U_) 849{ 850 /* Not enough examples available for me to debug this */ 851 return (1); 852} 853 854static int 855print_nsp(netdissect_options *ndo, 856 const u_char *nspp, u_int nsplen) 857{ 858 const struct nsphdr *nsphp = (struct nsphdr *)nspp; 859 int dst, src, flags; 860 861 if (nsplen < sizeof(struct nsphdr)) 862 goto trunc; 863 ND_TCHECK(*nsphp); 864 flags = EXTRACT_LE_8BITS(nsphp->nh_flags); 865 dst = EXTRACT_LE_16BITS(nsphp->nh_dst); 866 src = EXTRACT_LE_16BITS(nsphp->nh_src); 867 868 switch (flags & NSP_TYPEMASK) { 869 case MFT_DATA: 870 switch (flags & NSP_SUBMASK) { 871 case MFS_BOM: 872 case MFS_MOM: 873 case MFS_EOM: 874 case MFS_BOM+MFS_EOM: 875 ND_PRINT((ndo, "data %d>%d ", src, dst)); 876 { 877 struct seghdr *shp = (struct seghdr *)nspp; 878 int ack; 879#ifdef PRINT_NSPDATA 880 u_char *dp; 881#endif 882 u_int data_off = sizeof(struct minseghdr); 883 884 if (nsplen < data_off) 885 goto trunc; 886 ND_TCHECK(shp->sh_seq[0]); 887 ack = EXTRACT_LE_16BITS(shp->sh_seq[0]); 888 if (ack & SGQ_ACK) { /* acknum field */ 889 if ((ack & SGQ_NAK) == SGQ_NAK) 890 ND_PRINT((ndo, "nak %d ", ack & SGQ_MASK)); 891 else 892 ND_PRINT((ndo, "ack %d ", ack & SGQ_MASK)); 893 data_off += sizeof(short); 894 if (nsplen < data_off) 895 goto trunc; 896 ND_TCHECK(shp->sh_seq[1]); 897 ack = EXTRACT_LE_16BITS(shp->sh_seq[1]); 898 if (ack & SGQ_OACK) { /* ackoth field */ 899 if ((ack & SGQ_ONAK) == SGQ_ONAK) 900 ND_PRINT((ndo, "onak %d ", ack & SGQ_MASK)); 901 else 902 ND_PRINT((ndo, "oack %d ", ack & SGQ_MASK)); 903 data_off += sizeof(short); 904 if (nsplen < data_off) 905 goto trunc; 906 ND_TCHECK(shp->sh_seq[2]); 907 ack = EXTRACT_LE_16BITS(shp->sh_seq[2]); 908 } 909 } 910 ND_PRINT((ndo, "seg %d ", ack & SGQ_MASK)); 911#ifdef PRINT_NSPDATA 912 if (nsplen > data_off) { 913 dp = &(nspp[data_off]); 914 ND_TCHECK2(*dp, nsplen - data_off); 915 pdata(ndo, dp, nsplen - data_off); 916 } 917#endif 918 } 919 break; 920 case MFS_ILS+MFS_INT: 921 ND_PRINT((ndo, "intr ")); 922 { 923 struct seghdr *shp = (struct seghdr *)nspp; 924 int ack; 925#ifdef PRINT_NSPDATA 926 u_char *dp; 927#endif 928 u_int data_off = sizeof(struct minseghdr); 929 930 if (nsplen < data_off) 931 goto trunc; 932 ND_TCHECK(shp->sh_seq[0]); 933 ack = EXTRACT_LE_16BITS(shp->sh_seq[0]); 934 if (ack & SGQ_ACK) { /* acknum field */ 935 if ((ack & SGQ_NAK) == SGQ_NAK) 936 ND_PRINT((ndo, "nak %d ", ack & SGQ_MASK)); 937 else 938 ND_PRINT((ndo, "ack %d ", ack & SGQ_MASK)); 939 data_off += sizeof(short); 940 if (nsplen < data_off) 941 goto trunc; 942 ND_TCHECK(shp->sh_seq[1]); 943 ack = EXTRACT_LE_16BITS(shp->sh_seq[1]); 944 if (ack & SGQ_OACK) { /* ackdat field */ 945 if ((ack & SGQ_ONAK) == SGQ_ONAK) 946 ND_PRINT((ndo, "nakdat %d ", ack & SGQ_MASK)); 947 else 948 ND_PRINT((ndo, "ackdat %d ", ack & SGQ_MASK)); 949 data_off += sizeof(short); 950 if (nsplen < data_off) 951 goto trunc; 952 ND_TCHECK(shp->sh_seq[2]); 953 ack = EXTRACT_LE_16BITS(shp->sh_seq[2]); 954 } 955 } 956 ND_PRINT((ndo, "seg %d ", ack & SGQ_MASK)); 957#ifdef PRINT_NSPDATA 958 if (nsplen > data_off) { 959 dp = &(nspp[data_off]); 960 ND_TCHECK2(*dp, nsplen - data_off); 961 pdata(ndo, dp, nsplen - data_off); 962 } 963#endif 964 } 965 break; 966 case MFS_ILS: 967 ND_PRINT((ndo, "link-service %d>%d ", src, dst)); 968 { 969 struct seghdr *shp = (struct seghdr *)nspp; 970 struct lsmsg *lsmp = 971 (struct lsmsg *)&(nspp[sizeof(struct seghdr)]); 972 int ack; 973 int lsflags, fcval; 974 975 if (nsplen < sizeof(struct seghdr) + sizeof(struct lsmsg)) 976 goto trunc; 977 ND_TCHECK(shp->sh_seq[0]); 978 ack = EXTRACT_LE_16BITS(shp->sh_seq[0]); 979 if (ack & SGQ_ACK) { /* acknum field */ 980 if ((ack & SGQ_NAK) == SGQ_NAK) 981 ND_PRINT((ndo, "nak %d ", ack & SGQ_MASK)); 982 else 983 ND_PRINT((ndo, "ack %d ", ack & SGQ_MASK)); 984 ND_TCHECK(shp->sh_seq[1]); 985 ack = EXTRACT_LE_16BITS(shp->sh_seq[1]); 986 if (ack & SGQ_OACK) { /* ackdat field */ 987 if ((ack & SGQ_ONAK) == SGQ_ONAK) 988 ND_PRINT((ndo, "nakdat %d ", ack & SGQ_MASK)); 989 else 990 ND_PRINT((ndo, "ackdat %d ", ack & SGQ_MASK)); 991 ND_TCHECK(shp->sh_seq[2]); 992 ack = EXTRACT_LE_16BITS(shp->sh_seq[2]); 993 } 994 } 995 ND_PRINT((ndo, "seg %d ", ack & SGQ_MASK)); 996 ND_TCHECK(*lsmp); 997 lsflags = EXTRACT_LE_8BITS(lsmp->ls_lsflags); 998 fcval = EXTRACT_LE_8BITS(lsmp->ls_fcval); 999 switch (lsflags & LSI_MASK) { 1000 case LSI_DATA: 1001 ND_PRINT((ndo, "dat seg count %d ", fcval)); 1002 switch (lsflags & LSM_MASK) { 1003 case LSM_NOCHANGE: 1004 break; 1005 case LSM_DONOTSEND: 1006 ND_PRINT((ndo, "donotsend-data ")); 1007 break; 1008 case LSM_SEND: 1009 ND_PRINT((ndo, "send-data ")); 1010 break; 1011 default: 1012 ND_PRINT((ndo, "reserved-fcmod? %x", lsflags)); 1013 break; 1014 } 1015 break; 1016 case LSI_INTR: 1017 ND_PRINT((ndo, "intr req count %d ", fcval)); 1018 break; 1019 default: 1020 ND_PRINT((ndo, "reserved-fcval-int? %x", lsflags)); 1021 break; 1022 } 1023 } 1024 break; 1025 default: 1026 ND_PRINT((ndo, "reserved-subtype? %x %d > %d", flags, src, dst)); 1027 break; 1028 } 1029 break; 1030 case MFT_ACK: 1031 switch (flags & NSP_SUBMASK) { 1032 case MFS_DACK: 1033 ND_PRINT((ndo, "data-ack %d>%d ", src, dst)); 1034 { 1035 struct ackmsg *amp = (struct ackmsg *)nspp; 1036 int ack; 1037 1038 if (nsplen < sizeof(struct ackmsg)) 1039 goto trunc; 1040 ND_TCHECK(*amp); 1041 ack = EXTRACT_LE_16BITS(amp->ak_acknum[0]); 1042 if (ack & SGQ_ACK) { /* acknum field */ 1043 if ((ack & SGQ_NAK) == SGQ_NAK) 1044 ND_PRINT((ndo, "nak %d ", ack & SGQ_MASK)); 1045 else 1046 ND_PRINT((ndo, "ack %d ", ack & SGQ_MASK)); 1047 ack = EXTRACT_LE_16BITS(amp->ak_acknum[1]); 1048 if (ack & SGQ_OACK) { /* ackoth field */ 1049 if ((ack & SGQ_ONAK) == SGQ_ONAK) 1050 ND_PRINT((ndo, "onak %d ", ack & SGQ_MASK)); 1051 else 1052 ND_PRINT((ndo, "oack %d ", ack & SGQ_MASK)); 1053 } 1054 } 1055 } 1056 break; 1057 case MFS_IACK: 1058 ND_PRINT((ndo, "ils-ack %d>%d ", src, dst)); 1059 { 1060 struct ackmsg *amp = (struct ackmsg *)nspp; 1061 int ack; 1062 1063 if (nsplen < sizeof(struct ackmsg)) 1064 goto trunc; 1065 ND_TCHECK(*amp); 1066 ack = EXTRACT_LE_16BITS(amp->ak_acknum[0]); 1067 if (ack & SGQ_ACK) { /* acknum field */ 1068 if ((ack & SGQ_NAK) == SGQ_NAK) 1069 ND_PRINT((ndo, "nak %d ", ack & SGQ_MASK)); 1070 else 1071 ND_PRINT((ndo, "ack %d ", ack & SGQ_MASK)); 1072 ND_TCHECK(amp->ak_acknum[1]); 1073 ack = EXTRACT_LE_16BITS(amp->ak_acknum[1]); 1074 if (ack & SGQ_OACK) { /* ackdat field */ 1075 if ((ack & SGQ_ONAK) == SGQ_ONAK) 1076 ND_PRINT((ndo, "nakdat %d ", ack & SGQ_MASK)); 1077 else 1078 ND_PRINT((ndo, "ackdat %d ", ack & SGQ_MASK)); 1079 } 1080 } 1081 } 1082 break; 1083 case MFS_CACK: 1084 ND_PRINT((ndo, "conn-ack %d", dst)); 1085 break; 1086 default: 1087 ND_PRINT((ndo, "reserved-acktype? %x %d > %d", flags, src, dst)); 1088 break; 1089 } 1090 break; 1091 case MFT_CTL: 1092 switch (flags & NSP_SUBMASK) { 1093 case MFS_CI: 1094 case MFS_RCI: 1095 if ((flags & NSP_SUBMASK) == MFS_CI) 1096 ND_PRINT((ndo, "conn-initiate ")); 1097 else 1098 ND_PRINT((ndo, "retrans-conn-initiate ")); 1099 ND_PRINT((ndo, "%d>%d ", src, dst)); 1100 { 1101 struct cimsg *cimp = (struct cimsg *)nspp; 1102 int services, info, segsize; 1103#ifdef PRINT_NSPDATA 1104 u_char *dp; 1105#endif 1106 1107 if (nsplen < sizeof(struct cimsg)) 1108 goto trunc; 1109 ND_TCHECK(*cimp); 1110 services = EXTRACT_LE_8BITS(cimp->ci_services); 1111 info = EXTRACT_LE_8BITS(cimp->ci_info); 1112 segsize = EXTRACT_LE_16BITS(cimp->ci_segsize); 1113 1114 switch (services & COS_MASK) { 1115 case COS_NONE: 1116 break; 1117 case COS_SEGMENT: 1118 ND_PRINT((ndo, "seg ")); 1119 break; 1120 case COS_MESSAGE: 1121 ND_PRINT((ndo, "msg ")); 1122 break; 1123 case COS_CRYPTSER: 1124 ND_PRINT((ndo, "crypt ")); 1125 break; 1126 } 1127 switch (info & COI_MASK) { 1128 case COI_32: 1129 ND_PRINT((ndo, "ver 3.2 ")); 1130 break; 1131 case COI_31: 1132 ND_PRINT((ndo, "ver 3.1 ")); 1133 break; 1134 case COI_40: 1135 ND_PRINT((ndo, "ver 4.0 ")); 1136 break; 1137 case COI_41: 1138 ND_PRINT((ndo, "ver 4.1 ")); 1139 break; 1140 } 1141 ND_PRINT((ndo, "segsize %d ", segsize)); 1142#ifdef PRINT_NSPDATA 1143 if (nsplen > sizeof(struct cimsg)) { 1144 dp = &(nspp[sizeof(struct cimsg)]); 1145 ND_TCHECK2(*dp, nsplen - sizeof(struct cimsg)); 1146 pdata(ndo, dp, nsplen - sizeof(struct cimsg)); 1147 } 1148#endif 1149 } 1150 break; 1151 case MFS_CC: 1152 ND_PRINT((ndo, "conn-confirm %d>%d ", src, dst)); 1153 { 1154 struct ccmsg *ccmp = (struct ccmsg *)nspp; 1155 int services, info; 1156 u_int segsize, optlen; 1157#ifdef PRINT_NSPDATA 1158 u_char *dp; 1159#endif 1160 1161 if (nsplen < sizeof(struct ccmsg)) 1162 goto trunc; 1163 ND_TCHECK(*ccmp); 1164 services = EXTRACT_LE_8BITS(ccmp->cc_services); 1165 info = EXTRACT_LE_8BITS(ccmp->cc_info); 1166 segsize = EXTRACT_LE_16BITS(ccmp->cc_segsize); 1167 optlen = EXTRACT_LE_8BITS(ccmp->cc_optlen); 1168 1169 switch (services & COS_MASK) { 1170 case COS_NONE: 1171 break; 1172 case COS_SEGMENT: 1173 ND_PRINT((ndo, "seg ")); 1174 break; 1175 case COS_MESSAGE: 1176 ND_PRINT((ndo, "msg ")); 1177 break; 1178 case COS_CRYPTSER: 1179 ND_PRINT((ndo, "crypt ")); 1180 break; 1181 } 1182 switch (info & COI_MASK) { 1183 case COI_32: 1184 ND_PRINT((ndo, "ver 3.2 ")); 1185 break; 1186 case COI_31: 1187 ND_PRINT((ndo, "ver 3.1 ")); 1188 break; 1189 case COI_40: 1190 ND_PRINT((ndo, "ver 4.0 ")); 1191 break; 1192 case COI_41: 1193 ND_PRINT((ndo, "ver 4.1 ")); 1194 break; 1195 } 1196 ND_PRINT((ndo, "segsize %d ", segsize)); 1197 if (optlen) { 1198 ND_PRINT((ndo, "optlen %d ", optlen)); 1199#ifdef PRINT_NSPDATA 1200 if (optlen > nsplen - sizeof(struct ccmsg)) 1201 goto trunc; 1202 dp = &(nspp[sizeof(struct ccmsg)]); 1203 ND_TCHECK2(*dp, optlen); 1204 pdata(ndo, dp, optlen); 1205#endif 1206 } 1207 } 1208 break; 1209 case MFS_DI: 1210 ND_PRINT((ndo, "disconn-initiate %d>%d ", src, dst)); 1211 { 1212 struct dimsg *dimp = (struct dimsg *)nspp; 1213 int reason; 1214 u_int optlen; 1215#ifdef PRINT_NSPDATA 1216 u_char *dp; 1217#endif 1218 1219 if (nsplen < sizeof(struct dimsg)) 1220 goto trunc; 1221 ND_TCHECK(*dimp); 1222 reason = EXTRACT_LE_16BITS(dimp->di_reason); 1223 optlen = EXTRACT_LE_8BITS(dimp->di_optlen); 1224 1225 print_reason(ndo, reason); 1226 if (optlen) { 1227 ND_PRINT((ndo, "optlen %d ", optlen)); 1228#ifdef PRINT_NSPDATA 1229 if (optlen > nsplen - sizeof(struct dimsg)) 1230 goto trunc; 1231 dp = &(nspp[sizeof(struct dimsg)]); 1232 ND_TCHECK2(*dp, optlen); 1233 pdata(ndo, dp, optlen); 1234#endif 1235 } 1236 } 1237 break; 1238 case MFS_DC: 1239 ND_PRINT((ndo, "disconn-confirm %d>%d ", src, dst)); 1240 { 1241 struct dcmsg *dcmp = (struct dcmsg *)nspp; 1242 int reason; 1243 1244 ND_TCHECK(*dcmp); 1245 reason = EXTRACT_LE_16BITS(dcmp->dc_reason); 1246 1247 print_reason(ndo, reason); 1248 } 1249 break; 1250 default: 1251 ND_PRINT((ndo, "reserved-ctltype? %x %d > %d", flags, src, dst)); 1252 break; 1253 } 1254 break; 1255 default: 1256 ND_PRINT((ndo, "reserved-type? %x %d > %d", flags, src, dst)); 1257 break; 1258 } 1259 return (1); 1260 1261trunc: 1262 return (0); 1263} 1264 1265static const struct tok reason2str[] = { 1266 { UC_OBJREJECT, "object rejected connect" }, 1267 { UC_RESOURCES, "insufficient resources" }, 1268 { UC_NOSUCHNODE, "unrecognized node name" }, 1269 { DI_SHUT, "node is shutting down" }, 1270 { UC_NOSUCHOBJ, "unrecognized object" }, 1271 { UC_INVOBJFORMAT, "invalid object name format" }, 1272 { UC_OBJTOOBUSY, "object too busy" }, 1273 { DI_PROTOCOL, "protocol error discovered" }, 1274 { DI_TPA, "third party abort" }, 1275 { UC_USERABORT, "user abort" }, 1276 { UC_INVNODEFORMAT, "invalid node name format" }, 1277 { UC_LOCALSHUT, "local node shutting down" }, 1278 { DI_LOCALRESRC, "insufficient local resources" }, 1279 { DI_REMUSERRESRC, "insufficient remote user resources" }, 1280 { UC_ACCESSREJECT, "invalid access control information" }, 1281 { DI_BADACCNT, "bad ACCOUNT information" }, 1282 { UC_NORESPONSE, "no response from object" }, 1283 { UC_UNREACHABLE, "node unreachable" }, 1284 { DC_NOLINK, "no link terminate" }, 1285 { DC_COMPLETE, "disconnect complete" }, 1286 { DI_BADIMAGE, "bad image data in connect" }, 1287 { DI_SERVMISMATCH, "cryptographic service mismatch" }, 1288 { 0, NULL } 1289}; 1290 1291static void 1292print_reason(netdissect_options *ndo, 1293 register int reason) 1294{ 1295 ND_PRINT((ndo, "%s ", tok2str(reason2str, "reason-%d", reason))); 1296} 1297 1298const char * 1299dnnum_string(u_short dnaddr) 1300{ 1301 char *str; 1302 size_t siz; 1303 int area = (u_short)(dnaddr & AREAMASK) >> AREASHIFT; 1304 int node = dnaddr & NODEMASK; 1305 1306 str = (char *)malloc(siz = sizeof("00.0000")); 1307 if (str == NULL) 1308 error("dnnum_string: malloc"); 1309 snprintf(str, siz, "%d.%d", area, node); 1310 return(str); 1311} 1312 1313const char * 1314dnname_string(u_short dnaddr) 1315{ 1316#ifdef HAVE_DNET_HTOA 1317 struct dn_naddr dna; 1318 char *dnname; 1319 1320 dna.a_len = sizeof(short); 1321 memcpy((char *)dna.a_addr, (char *)&dnaddr, sizeof(short)); 1322 dnname = dnet_htoa(&dna); 1323 if(dnname != NULL) 1324 return (strdup(dnname)); 1325 else 1326 return(dnnum_string(dnaddr)); 1327#else 1328 return(dnnum_string(dnaddr)); /* punt */ 1329#endif 1330} 1331 1332#ifdef PRINT_NSPDATA 1333static void 1334pdata(netdissect_options *ndo, 1335 u_char *dp, u_int maxlen) 1336{ 1337 char c; 1338 u_int x = maxlen; 1339 1340 while (x-- > 0) { 1341 c = *dp++; 1342 safeputchar(ndo, c); 1343 } 1344} 1345#endif 1346