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