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 mflags = EXTRACT_LE_8BITS(rhp->rh_short.sh_flags); 546 } 547 548 if (mflags & RMF_FVER) { 549 ND_PRINT((ndo, "future-version-decnet")); 550 ND_DEFAULTPRINT(ap, min(length, caplen)); 551 return; 552 } 553 554 /* is it a control message? */ 555 if (mflags & RMF_CTLMSG) { 556 if (!print_decnet_ctlmsg(ndo, rhp, length, caplen)) 557 goto trunc; 558 return; 559 } 560 561 switch (mflags & RMF_MASK) { 562 case RMF_LONG: 563 if (length < sizeof(struct longhdr)) { 564 ND_PRINT((ndo, "%s", tstr)); 565 return; 566 } 567 ND_TCHECK(rhp->rh_long); 568 dst = 569 EXTRACT_LE_16BITS(rhp->rh_long.lg_dst.dne_remote.dne_nodeaddr); 570 src = 571 EXTRACT_LE_16BITS(rhp->rh_long.lg_src.dne_remote.dne_nodeaddr); 572 hops = EXTRACT_LE_8BITS(rhp->rh_long.lg_visits); 573 nspp = &(ap[sizeof(short) + sizeof(struct longhdr)]); 574 nsplen = length - sizeof(struct longhdr); 575 break; 576 case RMF_SHORT: 577 ND_TCHECK(rhp->rh_short); 578 dst = EXTRACT_LE_16BITS(rhp->rh_short.sh_dst); 579 src = EXTRACT_LE_16BITS(rhp->rh_short.sh_src); 580 hops = (EXTRACT_LE_8BITS(rhp->rh_short.sh_visits) & VIS_MASK)+1; 581 nspp = &(ap[sizeof(short) + sizeof(struct shorthdr)]); 582 nsplen = length - sizeof(struct shorthdr); 583 break; 584 default: 585 ND_PRINT((ndo, "unknown message flags under mask")); 586 ND_DEFAULTPRINT((const u_char *)ap, min(length, caplen)); 587 return; 588 } 589 590 ND_PRINT((ndo, "%s > %s %d ", 591 dnaddr_string(ndo, src), dnaddr_string(ndo, dst), pktlen)); 592 if (ndo->ndo_vflag) { 593 if (mflags & RMF_RQR) 594 ND_PRINT((ndo, "RQR ")); 595 if (mflags & RMF_RTS) 596 ND_PRINT((ndo, "RTS ")); 597 if (mflags & RMF_IE) 598 ND_PRINT((ndo, "IE ")); 599 ND_PRINT((ndo, "%d hops ", hops)); 600 } 601 602 if (!print_nsp(ndo, nspp, nsplen)) 603 goto trunc; 604 return; 605 606 trunc: 607 ND_PRINT((ndo, "%s", tstr)); 608 return; 609 } 610 611 static int 612 print_decnet_ctlmsg(netdissect_options *ndo, 613 register const union routehdr *rhp, u_int length, 614 u_int caplen) 615 { 616 int mflags = EXTRACT_LE_8BITS(rhp->rh_short.sh_flags); 617 register const union controlmsg *cmp = (const union controlmsg *)rhp; 618 int src, dst, info, blksize, eco, ueco, hello, other, vers; 619 etheraddr srcea, rtea; 620 int priority; 621 const char *rhpx = (const char *)rhp; 622 int ret; 623 624 switch (mflags & RMF_CTLMASK) { 625 case RMF_INIT: 626 ND_PRINT((ndo, "init ")); 627 if (length < sizeof(struct initmsg)) 628 goto trunc; 629 ND_TCHECK(cmp->cm_init); 630 src = EXTRACT_LE_16BITS(cmp->cm_init.in_src); 631 info = EXTRACT_LE_8BITS(cmp->cm_init.in_info); 632 blksize = EXTRACT_LE_16BITS(cmp->cm_init.in_blksize); 633 vers = EXTRACT_LE_8BITS(cmp->cm_init.in_vers); 634 eco = EXTRACT_LE_8BITS(cmp->cm_init.in_eco); 635 ueco = EXTRACT_LE_8BITS(cmp->cm_init.in_ueco); 636 hello = EXTRACT_LE_16BITS(cmp->cm_init.in_hello); 637 print_t_info(ndo, info); 638 ND_PRINT((ndo, 639 "src %sblksize %d vers %d eco %d ueco %d hello %d", 640 dnaddr_string(ndo, src), blksize, vers, eco, ueco, 641 hello)); 642 ret = 1; 643 break; 644 case RMF_VER: 645 ND_PRINT((ndo, "verification ")); 646 if (length < sizeof(struct verifmsg)) 647 goto trunc; 648 ND_TCHECK(cmp->cm_ver); 649 src = EXTRACT_LE_16BITS(cmp->cm_ver.ve_src); 650 other = EXTRACT_LE_8BITS(cmp->cm_ver.ve_fcnval); 651 ND_PRINT((ndo, "src %s fcnval %o", dnaddr_string(ndo, src), other)); 652 ret = 1; 653 break; 654 case RMF_TEST: 655 ND_PRINT((ndo, "test ")); 656 if (length < sizeof(struct testmsg)) 657 goto trunc; 658 ND_TCHECK(cmp->cm_test); 659 src = EXTRACT_LE_16BITS(cmp->cm_test.te_src); 660 other = EXTRACT_LE_8BITS(cmp->cm_test.te_data); 661 ND_PRINT((ndo, "src %s data %o", dnaddr_string(ndo, src), other)); 662 ret = 1; 663 break; 664 case RMF_L1ROUT: 665 ND_PRINT((ndo, "lev-1-routing ")); 666 if (length < sizeof(struct l1rout)) 667 goto trunc; 668 ND_TCHECK(cmp->cm_l1rou); 669 src = EXTRACT_LE_16BITS(cmp->cm_l1rou.r1_src); 670 ND_PRINT((ndo, "src %s ", dnaddr_string(ndo, src))); 671 ret = print_l1_routes(ndo, &(rhpx[sizeof(struct l1rout)]), 672 length - sizeof(struct l1rout)); 673 break; 674 case RMF_L2ROUT: 675 ND_PRINT((ndo, "lev-2-routing ")); 676 if (length < sizeof(struct l2rout)) 677 goto trunc; 678 ND_TCHECK(cmp->cm_l2rout); 679 src = EXTRACT_LE_16BITS(cmp->cm_l2rout.r2_src); 680 ND_PRINT((ndo, "src %s ", dnaddr_string(ndo, src))); 681 ret = print_l2_routes(ndo, &(rhpx[sizeof(struct l2rout)]), 682 length - sizeof(struct l2rout)); 683 break; 684 case RMF_RHELLO: 685 ND_PRINT((ndo, "router-hello ")); 686 if (length < sizeof(struct rhellomsg)) 687 goto trunc; 688 ND_TCHECK(cmp->cm_rhello); 689 vers = EXTRACT_LE_8BITS(cmp->cm_rhello.rh_vers); 690 eco = EXTRACT_LE_8BITS(cmp->cm_rhello.rh_eco); 691 ueco = EXTRACT_LE_8BITS(cmp->cm_rhello.rh_ueco); 692 memcpy((char *)&srcea, (const char *)&(cmp->cm_rhello.rh_src), 693 sizeof(srcea)); 694 src = EXTRACT_LE_16BITS(srcea.dne_remote.dne_nodeaddr); 695 info = EXTRACT_LE_8BITS(cmp->cm_rhello.rh_info); 696 blksize = EXTRACT_LE_16BITS(cmp->cm_rhello.rh_blksize); 697 priority = EXTRACT_LE_8BITS(cmp->cm_rhello.rh_priority); 698 hello = EXTRACT_LE_16BITS(cmp->cm_rhello.rh_hello); 699 print_i_info(ndo, info); 700 ND_PRINT((ndo, 701 "vers %d eco %d ueco %d src %s blksize %d pri %d hello %d", 702 vers, eco, ueco, dnaddr_string(ndo, src), 703 blksize, priority, hello)); 704 ret = print_elist(&(rhpx[sizeof(struct rhellomsg)]), 705 length - sizeof(struct rhellomsg)); 706 break; 707 case RMF_EHELLO: 708 ND_PRINT((ndo, "endnode-hello ")); 709 if (length < sizeof(struct ehellomsg)) 710 goto trunc; 711 ND_TCHECK(cmp->cm_ehello); 712 vers = EXTRACT_LE_8BITS(cmp->cm_ehello.eh_vers); 713 eco = EXTRACT_LE_8BITS(cmp->cm_ehello.eh_eco); 714 ueco = EXTRACT_LE_8BITS(cmp->cm_ehello.eh_ueco); 715 memcpy((char *)&srcea, (const char *)&(cmp->cm_ehello.eh_src), 716 sizeof(srcea)); 717 src = EXTRACT_LE_16BITS(srcea.dne_remote.dne_nodeaddr); 718 info = EXTRACT_LE_8BITS(cmp->cm_ehello.eh_info); 719 blksize = EXTRACT_LE_16BITS(cmp->cm_ehello.eh_blksize); 720 /*seed*/ 721 memcpy((char *)&rtea, (const char *)&(cmp->cm_ehello.eh_router), 722 sizeof(rtea)); 723 dst = EXTRACT_LE_16BITS(rtea.dne_remote.dne_nodeaddr); 724 hello = EXTRACT_LE_16BITS(cmp->cm_ehello.eh_hello); 725 other = EXTRACT_LE_8BITS(cmp->cm_ehello.eh_data); 726 print_i_info(ndo, info); 727 ND_PRINT((ndo, 728 "vers %d eco %d ueco %d src %s blksize %d rtr %s hello %d data %o", 729 vers, eco, ueco, dnaddr_string(ndo, src), 730 blksize, dnaddr_string(ndo, dst), hello, other)); 731 ret = 1; 732 break; 733 734 default: 735 ND_PRINT((ndo, "unknown control message")); 736 ND_DEFAULTPRINT((const u_char *)rhp, min(length, caplen)); 737 ret = 1; 738 break; 739 } 740 return (ret); 741 742 trunc: 743 return (0); 744 } 745 746 static void 747 print_t_info(netdissect_options *ndo, 748 int info) 749 { 750 int ntype = info & 3; 751 switch (ntype) { 752 case 0: ND_PRINT((ndo, "reserved-ntype? ")); break; 753 case TI_L2ROUT: ND_PRINT((ndo, "l2rout ")); break; 754 case TI_L1ROUT: ND_PRINT((ndo, "l1rout ")); break; 755 case TI_ENDNODE: ND_PRINT((ndo, "endnode ")); break; 756 } 757 if (info & TI_VERIF) 758 ND_PRINT((ndo, "verif ")); 759 if (info & TI_BLOCK) 760 ND_PRINT((ndo, "blo ")); 761 } 762 763 static int 764 print_l1_routes(netdissect_options *ndo, 765 const char *rp, u_int len) 766 { 767 int count; 768 int id; 769 int info; 770 771 /* The last short is a checksum */ 772 while (len > (3 * sizeof(short))) { 773 ND_TCHECK2(*rp, 3 * sizeof(short)); 774 count = EXTRACT_LE_16BITS(rp); 775 if (count > 1024) 776 return (1); /* seems to be bogus from here on */ 777 rp += sizeof(short); 778 len -= sizeof(short); 779 id = EXTRACT_LE_16BITS(rp); 780 rp += sizeof(short); 781 len -= sizeof(short); 782 info = EXTRACT_LE_16BITS(rp); 783 rp += sizeof(short); 784 len -= sizeof(short); 785 ND_PRINT((ndo, "{ids %d-%d cost %d hops %d} ", id, id + count, 786 RI_COST(info), RI_HOPS(info))); 787 } 788 return (1); 789 790 trunc: 791 return (0); 792 } 793 794 static int 795 print_l2_routes(netdissect_options *ndo, 796 const char *rp, u_int len) 797 { 798 int count; 799 int area; 800 int info; 801 802 /* The last short is a checksum */ 803 while (len > (3 * sizeof(short))) { 804 ND_TCHECK2(*rp, 3 * sizeof(short)); 805 count = EXTRACT_LE_16BITS(rp); 806 if (count > 1024) 807 return (1); /* seems to be bogus from here on */ 808 rp += sizeof(short); 809 len -= sizeof(short); 810 area = EXTRACT_LE_16BITS(rp); 811 rp += sizeof(short); 812 len -= sizeof(short); 813 info = EXTRACT_LE_16BITS(rp); 814 rp += sizeof(short); 815 len -= sizeof(short); 816 ND_PRINT((ndo, "{areas %d-%d cost %d hops %d} ", area, area + count, 817 RI_COST(info), RI_HOPS(info))); 818 } 819 return (1); 820 821 trunc: 822 return (0); 823 } 824 825 static void 826 print_i_info(netdissect_options *ndo, 827 int info) 828 { 829 int ntype = info & II_TYPEMASK; 830 switch (ntype) { 831 case 0: ND_PRINT((ndo, "reserved-ntype? ")); break; 832 case II_L2ROUT: ND_PRINT((ndo, "l2rout ")); break; 833 case II_L1ROUT: ND_PRINT((ndo, "l1rout ")); break; 834 case II_ENDNODE: ND_PRINT((ndo, "endnode ")); break; 835 } 836 if (info & II_VERIF) 837 ND_PRINT((ndo, "verif ")); 838 if (info & II_NOMCAST) 839 ND_PRINT((ndo, "nomcast ")); 840 if (info & II_BLOCK) 841 ND_PRINT((ndo, "blo ")); 842 } 843 844 static int 845 print_elist(const char *elp _U_, u_int len _U_) 846 { 847 /* Not enough examples available for me to debug this */ 848 return (1); 849 } 850 851 static int 852 print_nsp(netdissect_options *ndo, 853 const u_char *nspp, u_int nsplen) 854 { 855 const struct nsphdr *nsphp = (const struct nsphdr *)nspp; 856 int dst, src, flags; 857 858 if (nsplen < sizeof(struct nsphdr)) 859 goto trunc; 860 ND_TCHECK(*nsphp); 861 flags = EXTRACT_LE_8BITS(nsphp->nh_flags); 862 dst = EXTRACT_LE_16BITS(nsphp->nh_dst); 863 src = EXTRACT_LE_16BITS(nsphp->nh_src); 864 865 switch (flags & NSP_TYPEMASK) { 866 case MFT_DATA: 867 switch (flags & NSP_SUBMASK) { 868 case MFS_BOM: 869 case MFS_MOM: 870 case MFS_EOM: 871 case MFS_BOM+MFS_EOM: 872 ND_PRINT((ndo, "data %d>%d ", src, dst)); 873 { 874 const struct seghdr *shp = (const struct seghdr *)nspp; 875 int ack; 876 u_int data_off = sizeof(struct minseghdr); 877 878 if (nsplen < data_off) 879 goto trunc; 880 ND_TCHECK(shp->sh_seq[0]); 881 ack = EXTRACT_LE_16BITS(shp->sh_seq[0]); 882 if (ack & SGQ_ACK) { /* acknum field */ 883 if ((ack & SGQ_NAK) == SGQ_NAK) 884 ND_PRINT((ndo, "nak %d ", ack & SGQ_MASK)); 885 else 886 ND_PRINT((ndo, "ack %d ", ack & SGQ_MASK)); 887 data_off += sizeof(short); 888 if (nsplen < data_off) 889 goto trunc; 890 ND_TCHECK(shp->sh_seq[1]); 891 ack = EXTRACT_LE_16BITS(shp->sh_seq[1]); 892 if (ack & SGQ_OACK) { /* ackoth field */ 893 if ((ack & SGQ_ONAK) == SGQ_ONAK) 894 ND_PRINT((ndo, "onak %d ", ack & SGQ_MASK)); 895 else 896 ND_PRINT((ndo, "oack %d ", ack & SGQ_MASK)); 897 data_off += sizeof(short); 898 if (nsplen < data_off) 899 goto trunc; 900 ND_TCHECK(shp->sh_seq[2]); 901 ack = EXTRACT_LE_16BITS(shp->sh_seq[2]); 902 } 903 } 904 ND_PRINT((ndo, "seg %d ", ack & SGQ_MASK)); 905 } 906 break; 907 case MFS_ILS+MFS_INT: 908 ND_PRINT((ndo, "intr ")); 909 { 910 const struct seghdr *shp = (const struct seghdr *)nspp; 911 int ack; 912 u_int data_off = sizeof(struct minseghdr); 913 914 if (nsplen < data_off) 915 goto trunc; 916 ND_TCHECK(shp->sh_seq[0]); 917 ack = EXTRACT_LE_16BITS(shp->sh_seq[0]); 918 if (ack & SGQ_ACK) { /* acknum field */ 919 if ((ack & SGQ_NAK) == SGQ_NAK) 920 ND_PRINT((ndo, "nak %d ", ack & SGQ_MASK)); 921 else 922 ND_PRINT((ndo, "ack %d ", ack & SGQ_MASK)); 923 data_off += sizeof(short); 924 if (nsplen < data_off) 925 goto trunc; 926 ND_TCHECK(shp->sh_seq[1]); 927 ack = EXTRACT_LE_16BITS(shp->sh_seq[1]); 928 if (ack & SGQ_OACK) { /* ackdat field */ 929 if ((ack & SGQ_ONAK) == SGQ_ONAK) 930 ND_PRINT((ndo, "nakdat %d ", ack & SGQ_MASK)); 931 else 932 ND_PRINT((ndo, "ackdat %d ", ack & SGQ_MASK)); 933 data_off += sizeof(short); 934 if (nsplen < data_off) 935 goto trunc; 936 ND_TCHECK(shp->sh_seq[2]); 937 ack = EXTRACT_LE_16BITS(shp->sh_seq[2]); 938 } 939 } 940 ND_PRINT((ndo, "seg %d ", ack & SGQ_MASK)); 941 } 942 break; 943 case MFS_ILS: 944 ND_PRINT((ndo, "link-service %d>%d ", src, dst)); 945 { 946 const struct seghdr *shp = (const struct seghdr *)nspp; 947 const struct lsmsg *lsmp = 948 (const struct lsmsg *)&(nspp[sizeof(struct seghdr)]); 949 int ack; 950 int lsflags, fcval; 951 952 if (nsplen < sizeof(struct seghdr) + sizeof(struct lsmsg)) 953 goto trunc; 954 ND_TCHECK(shp->sh_seq[0]); 955 ack = EXTRACT_LE_16BITS(shp->sh_seq[0]); 956 if (ack & SGQ_ACK) { /* acknum field */ 957 if ((ack & SGQ_NAK) == SGQ_NAK) 958 ND_PRINT((ndo, "nak %d ", ack & SGQ_MASK)); 959 else 960 ND_PRINT((ndo, "ack %d ", ack & SGQ_MASK)); 961 ND_TCHECK(shp->sh_seq[1]); 962 ack = EXTRACT_LE_16BITS(shp->sh_seq[1]); 963 if (ack & SGQ_OACK) { /* ackdat field */ 964 if ((ack & SGQ_ONAK) == SGQ_ONAK) 965 ND_PRINT((ndo, "nakdat %d ", ack & SGQ_MASK)); 966 else 967 ND_PRINT((ndo, "ackdat %d ", ack & SGQ_MASK)); 968 ND_TCHECK(shp->sh_seq[2]); 969 ack = EXTRACT_LE_16BITS(shp->sh_seq[2]); 970 } 971 } 972 ND_PRINT((ndo, "seg %d ", ack & SGQ_MASK)); 973 ND_TCHECK(*lsmp); 974 lsflags = EXTRACT_LE_8BITS(lsmp->ls_lsflags); 975 fcval = EXTRACT_LE_8BITS(lsmp->ls_fcval); 976 switch (lsflags & LSI_MASK) { 977 case LSI_DATA: 978 ND_PRINT((ndo, "dat seg count %d ", fcval)); 979 switch (lsflags & LSM_MASK) { 980 case LSM_NOCHANGE: 981 break; 982 case LSM_DONOTSEND: 983 ND_PRINT((ndo, "donotsend-data ")); 984 break; 985 case LSM_SEND: 986 ND_PRINT((ndo, "send-data ")); 987 break; 988 default: 989 ND_PRINT((ndo, "reserved-fcmod? %x", lsflags)); 990 break; 991 } 992 break; 993 case LSI_INTR: 994 ND_PRINT((ndo, "intr req count %d ", fcval)); 995 break; 996 default: 997 ND_PRINT((ndo, "reserved-fcval-int? %x", lsflags)); 998 break; 999 } 1000 } 1001 break; 1002 default: 1003 ND_PRINT((ndo, "reserved-subtype? %x %d > %d", flags, src, dst)); 1004 break; 1005 } 1006 break; 1007 case MFT_ACK: 1008 switch (flags & NSP_SUBMASK) { 1009 case MFS_DACK: 1010 ND_PRINT((ndo, "data-ack %d>%d ", src, dst)); 1011 { 1012 const struct ackmsg *amp = (const struct ackmsg *)nspp; 1013 int ack; 1014 1015 if (nsplen < sizeof(struct ackmsg)) 1016 goto trunc; 1017 ND_TCHECK(*amp); 1018 ack = EXTRACT_LE_16BITS(amp->ak_acknum[0]); 1019 if (ack & SGQ_ACK) { /* acknum field */ 1020 if ((ack & SGQ_NAK) == SGQ_NAK) 1021 ND_PRINT((ndo, "nak %d ", ack & SGQ_MASK)); 1022 else 1023 ND_PRINT((ndo, "ack %d ", ack & SGQ_MASK)); 1024 ack = EXTRACT_LE_16BITS(amp->ak_acknum[1]); 1025 if (ack & SGQ_OACK) { /* ackoth field */ 1026 if ((ack & SGQ_ONAK) == SGQ_ONAK) 1027 ND_PRINT((ndo, "onak %d ", ack & SGQ_MASK)); 1028 else 1029 ND_PRINT((ndo, "oack %d ", ack & SGQ_MASK)); 1030 } 1031 } 1032 } 1033 break; 1034 case MFS_IACK: 1035 ND_PRINT((ndo, "ils-ack %d>%d ", src, dst)); 1036 { 1037 const struct ackmsg *amp = (const struct ackmsg *)nspp; 1038 int ack; 1039 1040 if (nsplen < sizeof(struct ackmsg)) 1041 goto trunc; 1042 ND_TCHECK(*amp); 1043 ack = EXTRACT_LE_16BITS(amp->ak_acknum[0]); 1044 if (ack & SGQ_ACK) { /* acknum field */ 1045 if ((ack & SGQ_NAK) == SGQ_NAK) 1046 ND_PRINT((ndo, "nak %d ", ack & SGQ_MASK)); 1047 else 1048 ND_PRINT((ndo, "ack %d ", ack & SGQ_MASK)); 1049 ND_TCHECK(amp->ak_acknum[1]); 1050 ack = EXTRACT_LE_16BITS(amp->ak_acknum[1]); 1051 if (ack & SGQ_OACK) { /* ackdat field */ 1052 if ((ack & SGQ_ONAK) == SGQ_ONAK) 1053 ND_PRINT((ndo, "nakdat %d ", ack & SGQ_MASK)); 1054 else 1055 ND_PRINT((ndo, "ackdat %d ", ack & SGQ_MASK)); 1056 } 1057 } 1058 } 1059 break; 1060 case MFS_CACK: 1061 ND_PRINT((ndo, "conn-ack %d", dst)); 1062 break; 1063 default: 1064 ND_PRINT((ndo, "reserved-acktype? %x %d > %d", flags, src, dst)); 1065 break; 1066 } 1067 break; 1068 case MFT_CTL: 1069 switch (flags & NSP_SUBMASK) { 1070 case MFS_CI: 1071 case MFS_RCI: 1072 if ((flags & NSP_SUBMASK) == MFS_CI) 1073 ND_PRINT((ndo, "conn-initiate ")); 1074 else 1075 ND_PRINT((ndo, "retrans-conn-initiate ")); 1076 ND_PRINT((ndo, "%d>%d ", src, dst)); 1077 { 1078 const struct cimsg *cimp = (const struct cimsg *)nspp; 1079 int services, info, segsize; 1080 1081 if (nsplen < sizeof(struct cimsg)) 1082 goto trunc; 1083 ND_TCHECK(*cimp); 1084 services = EXTRACT_LE_8BITS(cimp->ci_services); 1085 info = EXTRACT_LE_8BITS(cimp->ci_info); 1086 segsize = EXTRACT_LE_16BITS(cimp->ci_segsize); 1087 1088 switch (services & COS_MASK) { 1089 case COS_NONE: 1090 break; 1091 case COS_SEGMENT: 1092 ND_PRINT((ndo, "seg ")); 1093 break; 1094 case COS_MESSAGE: 1095 ND_PRINT((ndo, "msg ")); 1096 break; 1097 } 1098 switch (info & COI_MASK) { 1099 case COI_32: 1100 ND_PRINT((ndo, "ver 3.2 ")); 1101 break; 1102 case COI_31: 1103 ND_PRINT((ndo, "ver 3.1 ")); 1104 break; 1105 case COI_40: 1106 ND_PRINT((ndo, "ver 4.0 ")); 1107 break; 1108 case COI_41: 1109 ND_PRINT((ndo, "ver 4.1 ")); 1110 break; 1111 } 1112 ND_PRINT((ndo, "segsize %d ", segsize)); 1113 } 1114 break; 1115 case MFS_CC: 1116 ND_PRINT((ndo, "conn-confirm %d>%d ", src, dst)); 1117 { 1118 const struct ccmsg *ccmp = (const struct ccmsg *)nspp; 1119 int services, info; 1120 u_int segsize, optlen; 1121 1122 if (nsplen < sizeof(struct ccmsg)) 1123 goto trunc; 1124 ND_TCHECK(*ccmp); 1125 services = EXTRACT_LE_8BITS(ccmp->cc_services); 1126 info = EXTRACT_LE_8BITS(ccmp->cc_info); 1127 segsize = EXTRACT_LE_16BITS(ccmp->cc_segsize); 1128 optlen = EXTRACT_LE_8BITS(ccmp->cc_optlen); 1129 1130 switch (services & COS_MASK) { 1131 case COS_NONE: 1132 break; 1133 case COS_SEGMENT: 1134 ND_PRINT((ndo, "seg ")); 1135 break; 1136 case COS_MESSAGE: 1137 ND_PRINT((ndo, "msg ")); 1138 break; 1139 } 1140 switch (info & COI_MASK) { 1141 case COI_32: 1142 ND_PRINT((ndo, "ver 3.2 ")); 1143 break; 1144 case COI_31: 1145 ND_PRINT((ndo, "ver 3.1 ")); 1146 break; 1147 case COI_40: 1148 ND_PRINT((ndo, "ver 4.0 ")); 1149 break; 1150 case COI_41: 1151 ND_PRINT((ndo, "ver 4.1 ")); 1152 break; 1153 } 1154 ND_PRINT((ndo, "segsize %d ", segsize)); 1155 if (optlen) { 1156 ND_PRINT((ndo, "optlen %d ", optlen)); 1157 } 1158 } 1159 break; 1160 case MFS_DI: 1161 ND_PRINT((ndo, "disconn-initiate %d>%d ", src, dst)); 1162 { 1163 const struct dimsg *dimp = (const struct dimsg *)nspp; 1164 int reason; 1165 u_int optlen; 1166 1167 if (nsplen < sizeof(struct dimsg)) 1168 goto trunc; 1169 ND_TCHECK(*dimp); 1170 reason = EXTRACT_LE_16BITS(dimp->di_reason); 1171 optlen = EXTRACT_LE_8BITS(dimp->di_optlen); 1172 1173 print_reason(ndo, reason); 1174 if (optlen) { 1175 ND_PRINT((ndo, "optlen %d ", optlen)); 1176 } 1177 } 1178 break; 1179 case MFS_DC: 1180 ND_PRINT((ndo, "disconn-confirm %d>%d ", src, dst)); 1181 { 1182 const struct dcmsg *dcmp = (const struct dcmsg *)nspp; 1183 int reason; 1184 1185 ND_TCHECK(*dcmp); 1186 reason = EXTRACT_LE_16BITS(dcmp->dc_reason); 1187 1188 print_reason(ndo, reason); 1189 } 1190 break; 1191 default: 1192 ND_PRINT((ndo, "reserved-ctltype? %x %d > %d", flags, src, dst)); 1193 break; 1194 } 1195 break; 1196 default: 1197 ND_PRINT((ndo, "reserved-type? %x %d > %d", flags, src, dst)); 1198 break; 1199 } 1200 return (1); 1201 1202 trunc: 1203 return (0); 1204 } 1205 1206 static const struct tok reason2str[] = { 1207 { UC_OBJREJECT, "object rejected connect" }, 1208 { UC_RESOURCES, "insufficient resources" }, 1209 { UC_NOSUCHNODE, "unrecognized node name" }, 1210 { DI_SHUT, "node is shutting down" }, 1211 { UC_NOSUCHOBJ, "unrecognized object" }, 1212 { UC_INVOBJFORMAT, "invalid object name format" }, 1213 { UC_OBJTOOBUSY, "object too busy" }, 1214 { DI_PROTOCOL, "protocol error discovered" }, 1215 { DI_TPA, "third party abort" }, 1216 { UC_USERABORT, "user abort" }, 1217 { UC_INVNODEFORMAT, "invalid node name format" }, 1218 { UC_LOCALSHUT, "local node shutting down" }, 1219 { DI_LOCALRESRC, "insufficient local resources" }, 1220 { DI_REMUSERRESRC, "insufficient remote user resources" }, 1221 { UC_ACCESSREJECT, "invalid access control information" }, 1222 { DI_BADACCNT, "bad ACCOUNT information" }, 1223 { UC_NORESPONSE, "no response from object" }, 1224 { UC_UNREACHABLE, "node unreachable" }, 1225 { DC_NOLINK, "no link terminate" }, 1226 { DC_COMPLETE, "disconnect complete" }, 1227 { DI_BADIMAGE, "bad image data in connect" }, 1228 { DI_SERVMISMATCH, "cryptographic service mismatch" }, 1229 { 0, NULL } 1230 }; 1231 1232 static void 1233 print_reason(netdissect_options *ndo, 1234 register int reason) 1235 { 1236 ND_PRINT((ndo, "%s ", tok2str(reason2str, "reason-%d", reason))); 1237 } 1238 1239 const char * 1240 dnnum_string(netdissect_options *ndo, u_short dnaddr) 1241 { 1242 char *str; 1243 size_t siz; 1244 int area = (u_short)(dnaddr & AREAMASK) >> AREASHIFT; 1245 int node = dnaddr & NODEMASK; 1246 1247 str = (char *)malloc(siz = sizeof("00.0000")); 1248 if (str == NULL) 1249 (*ndo->ndo_error)(ndo, "dnnum_string: malloc"); 1250 snprintf(str, siz, "%d.%d", area, node); 1251 return(str); 1252 } 1253 1254 const char * 1255 dnname_string(netdissect_options *ndo, u_short dnaddr) 1256 { 1257 #ifdef HAVE_DNET_HTOA 1258 struct dn_naddr dna; 1259 char *dnname; 1260 1261 dna.a_len = sizeof(short); 1262 memcpy((char *)dna.a_addr, (char *)&dnaddr, sizeof(short)); 1263 dnname = dnet_htoa(&dna); 1264 if(dnname != NULL) 1265 return (strdup(dnname)); 1266 else 1267 return(dnnum_string(ndo, dnaddr)); 1268 #else 1269 return(dnnum_string(ndo, dnaddr)); /* punt */ 1270 #endif 1271 } 1272