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