1 /* 2 * Copyright (c) 1988, 1989, 1990, 1991, 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: AppleTalk 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 <string.h> 32 33 #include "netdissect.h" 34 #include "addrtoname.h" 35 #include "ethertype.h" 36 #include "extract.h" 37 #include "appletalk.h" 38 39 40 static const struct tok type2str[] = { 41 { ddpRTMP, "rtmp" }, 42 { ddpRTMPrequest, "rtmpReq" }, 43 { ddpECHO, "echo" }, 44 { ddpIP, "IP" }, 45 { ddpARP, "ARP" }, 46 { ddpKLAP, "KLAP" }, 47 { 0, NULL } 48 }; 49 50 struct aarp { 51 nd_uint16_t htype, ptype; 52 nd_uint8_t halen, palen; 53 nd_uint16_t op; 54 nd_mac_addr hsaddr; 55 uint8_t psaddr[4]; 56 nd_mac_addr hdaddr; 57 uint8_t pdaddr[4]; 58 }; 59 60 static void atp_print(netdissect_options *, const struct atATP *, u_int); 61 static void atp_bitmap_print(netdissect_options *, u_char); 62 static void nbp_print(netdissect_options *, const struct atNBP *, u_int, u_short, u_char, u_char); 63 static const struct atNBPtuple *nbp_tuple_print(netdissect_options *ndo, const struct atNBPtuple *, 64 const u_char *, 65 u_short, u_char, u_char); 66 static const struct atNBPtuple *nbp_name_print(netdissect_options *, const struct atNBPtuple *, 67 const u_char *); 68 static const char *ataddr_string(netdissect_options *, u_short, u_char); 69 static void ddp_print(netdissect_options *, const u_char *, u_int, u_int, u_short, u_char, u_char); 70 static const char *ddpskt_string(netdissect_options *, u_int); 71 72 /* 73 * Print LLAP packets received on a physical LocalTalk interface. 74 */ 75 void 76 ltalk_if_print(netdissect_options *ndo, 77 const struct pcap_pkthdr *h, const u_char *p) 78 { 79 u_int hdrlen; 80 81 ndo->ndo_protocol = "ltalk"; 82 hdrlen = llap_print(ndo, p, h->len); 83 if (hdrlen == 0) { 84 /* Cut short by the snapshot length. */ 85 ndo->ndo_ll_hdr_len += h->caplen; 86 return; 87 } 88 ndo->ndo_ll_hdr_len += hdrlen; 89 } 90 91 /* 92 * Print AppleTalk LLAP packets. 93 */ 94 u_int 95 llap_print(netdissect_options *ndo, 96 const u_char *bp, u_int length) 97 { 98 const struct LAP *lp; 99 const struct atDDP *dp; 100 const struct atShortDDP *sdp; 101 u_short snet; 102 u_int hdrlen; 103 104 ndo->ndo_protocol = "llap"; 105 if (length < sizeof(*lp)) { 106 ND_PRINT(" [|llap %u]", length); 107 return (length); 108 } 109 if (!ND_TTEST_LEN(bp, sizeof(*lp))) { 110 nd_print_trunc(ndo); 111 return (0); /* cut short by the snapshot length */ 112 } 113 lp = (const struct LAP *)bp; 114 bp += sizeof(*lp); 115 length -= sizeof(*lp); 116 hdrlen = sizeof(*lp); 117 switch (GET_U_1(lp->type)) { 118 119 case lapShortDDP: 120 if (length < ddpSSize) { 121 ND_PRINT(" [|sddp %u]", length); 122 return (length); 123 } 124 if (!ND_TTEST_LEN(bp, ddpSSize)) { 125 ND_PRINT(" [|sddp]"); 126 return (0); /* cut short by the snapshot length */ 127 } 128 sdp = (const struct atShortDDP *)bp; 129 ND_PRINT("%s.%s", 130 ataddr_string(ndo, 0, GET_U_1(lp->src)), 131 ddpskt_string(ndo, GET_U_1(sdp->srcSkt))); 132 ND_PRINT(" > %s.%s:", 133 ataddr_string(ndo, 0, GET_U_1(lp->dst)), 134 ddpskt_string(ndo, GET_U_1(sdp->dstSkt))); 135 bp += ddpSSize; 136 length -= ddpSSize; 137 hdrlen += ddpSSize; 138 ddp_print(ndo, bp, length, GET_U_1(sdp->type), 0, 139 GET_U_1(lp->src), GET_U_1(sdp->srcSkt)); 140 break; 141 142 case lapDDP: 143 if (length < ddpSize) { 144 ND_PRINT(" [|ddp %u]", length); 145 return (length); 146 } 147 if (!ND_TTEST_LEN(bp, ddpSize)) { 148 ND_PRINT(" [|ddp]"); 149 return (0); /* cut short by the snapshot length */ 150 } 151 dp = (const struct atDDP *)bp; 152 snet = GET_BE_U_2(dp->srcNet); 153 ND_PRINT("%s.%s", 154 ataddr_string(ndo, snet, GET_U_1(dp->srcNode)), 155 ddpskt_string(ndo, GET_U_1(dp->srcSkt))); 156 ND_PRINT(" > %s.%s:", 157 ataddr_string(ndo, GET_BE_U_2(dp->dstNet), GET_U_1(dp->dstNode)), 158 ddpskt_string(ndo, GET_U_1(dp->dstSkt))); 159 bp += ddpSize; 160 length -= ddpSize; 161 hdrlen += ddpSize; 162 ddp_print(ndo, bp, length, GET_U_1(dp->type), snet, 163 GET_U_1(dp->srcNode), GET_U_1(dp->srcSkt)); 164 break; 165 166 #ifdef notdef 167 case lapKLAP: 168 klap_print(bp, length); 169 break; 170 #endif 171 172 default: 173 ND_PRINT("%u > %u at-lap#%u %u", 174 GET_U_1(lp->src), GET_U_1(lp->dst), GET_U_1(lp->type), 175 length); 176 break; 177 } 178 return (hdrlen); 179 } 180 181 /* 182 * Print EtherTalk/TokenTalk packets (or FDDITalk, or whatever it's called 183 * when it runs over FDDI; yes, I've seen FDDI captures with AppleTalk 184 * packets in them). 185 */ 186 void 187 atalk_print(netdissect_options *ndo, 188 const u_char *bp, u_int length) 189 { 190 const struct atDDP *dp; 191 u_short snet; 192 193 ndo->ndo_protocol = "atalk"; 194 if(!ndo->ndo_eflag) 195 ND_PRINT("AT "); 196 197 if (length < ddpSize) { 198 ND_PRINT(" [|ddp %u]", length); 199 return; 200 } 201 if (!ND_TTEST_LEN(bp, ddpSize)) { 202 ND_PRINT(" [|ddp]"); 203 return; 204 } 205 dp = (const struct atDDP *)bp; 206 snet = GET_BE_U_2(dp->srcNet); 207 ND_PRINT("%s.%s", ataddr_string(ndo, snet, GET_U_1(dp->srcNode)), 208 ddpskt_string(ndo, GET_U_1(dp->srcSkt))); 209 ND_PRINT(" > %s.%s: ", 210 ataddr_string(ndo, GET_BE_U_2(dp->dstNet), GET_U_1(dp->dstNode)), 211 ddpskt_string(ndo, GET_U_1(dp->dstSkt))); 212 bp += ddpSize; 213 length -= ddpSize; 214 ddp_print(ndo, bp, length, GET_U_1(dp->type), snet, 215 GET_U_1(dp->srcNode), GET_U_1(dp->srcSkt)); 216 } 217 218 /* XXX should probably pass in the snap header and do checks like arp_print() */ 219 void 220 aarp_print(netdissect_options *ndo, 221 const u_char *bp, u_int length) 222 { 223 const struct aarp *ap; 224 225 #define AT(member) ataddr_string(ndo, (ap->member[1]<<8)|ap->member[2],ap->member[3]) 226 227 ndo->ndo_protocol = "aarp"; 228 ND_PRINT("aarp "); 229 ap = (const struct aarp *)bp; 230 if (!ND_TTEST_SIZE(ap)) { 231 /* Just bail if we don't have the whole chunk. */ 232 nd_print_trunc(ndo); 233 return; 234 } 235 if (length < sizeof(*ap)) { 236 ND_PRINT(" [|aarp %u]", length); 237 return; 238 } 239 if (GET_BE_U_2(ap->htype) == 1 && 240 GET_BE_U_2(ap->ptype) == ETHERTYPE_ATALK && 241 GET_U_1(ap->halen) == MAC_ADDR_LEN && GET_U_1(ap->palen) == 4) 242 switch (GET_BE_U_2(ap->op)) { 243 244 case 1: /* request */ 245 ND_PRINT("who-has %s tell %s", AT(pdaddr), AT(psaddr)); 246 return; 247 248 case 2: /* response */ 249 ND_PRINT("reply %s is-at %s", AT(psaddr), GET_ETHERADDR_STRING(ap->hsaddr)); 250 return; 251 252 case 3: /* probe (oy!) */ 253 ND_PRINT("probe %s tell %s", AT(pdaddr), AT(psaddr)); 254 return; 255 } 256 ND_PRINT("len %u op %u htype %u ptype %#x halen %u palen %u", 257 length, GET_BE_U_2(ap->op), GET_BE_U_2(ap->htype), 258 GET_BE_U_2(ap->ptype), GET_U_1(ap->halen), GET_U_1(ap->palen)); 259 } 260 261 /* 262 * Print AppleTalk Datagram Delivery Protocol packets. 263 */ 264 static void 265 ddp_print(netdissect_options *ndo, 266 const u_char *bp, u_int length, u_int t, 267 u_short snet, u_char snode, u_char skt) 268 { 269 270 switch (t) { 271 272 case ddpNBP: 273 nbp_print(ndo, (const struct atNBP *)bp, length, snet, snode, skt); 274 break; 275 276 case ddpATP: 277 atp_print(ndo, (const struct atATP *)bp, length); 278 break; 279 280 case ddpEIGRP: 281 eigrp_print(ndo, bp, length); 282 break; 283 284 default: 285 ND_PRINT(" at-%s %u", tok2str(type2str, NULL, t), length); 286 break; 287 } 288 } 289 290 static void 291 atp_print(netdissect_options *ndo, 292 const struct atATP *ap, u_int length) 293 { 294 uint8_t control; 295 uint32_t data; 296 297 if ((const u_char *)(ap + 1) > ndo->ndo_snapend) { 298 /* Just bail if we don't have the whole chunk. */ 299 nd_print_trunc(ndo); 300 return; 301 } 302 if (length < sizeof(*ap)) { 303 ND_PRINT(" [|atp %u]", length); 304 return; 305 } 306 length -= sizeof(*ap); 307 control = GET_U_1(ap->control); 308 switch (control & 0xc0) { 309 310 case atpReqCode: 311 ND_PRINT(" atp-req%s %u", 312 control & atpXO? " " : "*", 313 GET_BE_U_2(ap->transID)); 314 315 atp_bitmap_print(ndo, GET_U_1(ap->bitmap)); 316 317 if (length != 0) 318 ND_PRINT(" [len=%u]", length); 319 320 switch (control & (atpEOM|atpSTS)) { 321 case atpEOM: 322 ND_PRINT(" [EOM]"); 323 break; 324 case atpSTS: 325 ND_PRINT(" [STS]"); 326 break; 327 case atpEOM|atpSTS: 328 ND_PRINT(" [EOM,STS]"); 329 break; 330 } 331 break; 332 333 case atpRspCode: 334 ND_PRINT(" atp-resp%s%u:%u (%u)", 335 control & atpEOM? "*" : " ", 336 GET_BE_U_2(ap->transID), GET_U_1(ap->bitmap), 337 length); 338 switch (control & (atpXO|atpSTS)) { 339 case atpXO: 340 ND_PRINT(" [XO]"); 341 break; 342 case atpSTS: 343 ND_PRINT(" [STS]"); 344 break; 345 case atpXO|atpSTS: 346 ND_PRINT(" [XO,STS]"); 347 break; 348 } 349 break; 350 351 case atpRelCode: 352 ND_PRINT(" atp-rel %u", GET_BE_U_2(ap->transID)); 353 354 atp_bitmap_print(ndo, GET_U_1(ap->bitmap)); 355 356 /* length should be zero */ 357 if (length) 358 ND_PRINT(" [len=%u]", length); 359 360 /* there shouldn't be any control flags */ 361 if (control & (atpXO|atpEOM|atpSTS)) { 362 char c = '['; 363 if (control & atpXO) { 364 ND_PRINT("%cXO", c); 365 c = ','; 366 } 367 if (control & atpEOM) { 368 ND_PRINT("%cEOM", c); 369 c = ','; 370 } 371 if (control & atpSTS) { 372 ND_PRINT("%cSTS", c); 373 } 374 ND_PRINT("]"); 375 } 376 break; 377 378 default: 379 ND_PRINT(" atp-0x%x %u (%u)", control, 380 GET_BE_U_2(ap->transID), length); 381 break; 382 } 383 data = GET_BE_U_4(ap->userData); 384 if (data != 0) 385 ND_PRINT(" 0x%x", data); 386 } 387 388 static void 389 atp_bitmap_print(netdissect_options *ndo, 390 u_char bm) 391 { 392 u_int i; 393 394 /* 395 * The '& 0xff' below is needed for compilers that want to sign 396 * extend a u_char, which is the case with the Ultrix compiler. 397 * (gcc is smart enough to eliminate it, at least on the Sparc). 398 */ 399 if ((bm + 1) & (bm & 0xff)) { 400 char c = '<'; 401 for (i = 0; bm; ++i) { 402 if (bm & 1) { 403 ND_PRINT("%c%u", c, i); 404 c = ','; 405 } 406 bm >>= 1; 407 } 408 ND_PRINT(">"); 409 } else { 410 for (i = 0; bm; ++i) 411 bm >>= 1; 412 if (i > 1) 413 ND_PRINT("<0-%u>", i - 1); 414 else 415 ND_PRINT("<0>"); 416 } 417 } 418 419 static void 420 nbp_print(netdissect_options *ndo, 421 const struct atNBP *np, u_int length, u_short snet, 422 u_char snode, u_char skt) 423 { 424 const struct atNBPtuple *tp = 425 (const struct atNBPtuple *)((const u_char *)np + nbpHeaderSize); 426 uint8_t control; 427 u_int i; 428 const u_char *ep; 429 430 if (length < nbpHeaderSize) { 431 ND_PRINT(" truncated-nbp %u", length); 432 return; 433 } 434 435 length -= nbpHeaderSize; 436 if (length < 8) { 437 /* must be room for at least one tuple */ 438 ND_PRINT(" truncated-nbp %u", length + nbpHeaderSize); 439 return; 440 } 441 /* ep points to end of available data */ 442 ep = ndo->ndo_snapend; 443 if ((const u_char *)tp > ep) { 444 nd_print_trunc(ndo); 445 return; 446 } 447 control = GET_U_1(np->control); 448 switch (i = (control & 0xf0)) { 449 450 case nbpBrRq: 451 case nbpLkUp: 452 ND_PRINT(i == nbpLkUp? " nbp-lkup %u:":" nbp-brRq %u:", 453 GET_U_1(np->id)); 454 if ((const u_char *)(tp + 1) > ep) { 455 nd_print_trunc(ndo); 456 return; 457 } 458 (void)nbp_name_print(ndo, tp, ep); 459 /* 460 * look for anomalies: the spec says there can only 461 * be one tuple, the address must match the source 462 * address and the enumerator should be zero. 463 */ 464 if ((control & 0xf) != 1) 465 ND_PRINT(" [ntup=%u]", control & 0xf); 466 if (GET_U_1(tp->enumerator)) 467 ND_PRINT(" [enum=%u]", GET_U_1(tp->enumerator)); 468 if (GET_BE_U_2(tp->net) != snet || 469 GET_U_1(tp->node) != snode || 470 GET_U_1(tp->skt) != skt) 471 ND_PRINT(" [addr=%s.%u]", 472 ataddr_string(ndo, GET_BE_U_2(tp->net), 473 GET_U_1(tp->node)), 474 GET_U_1(tp->skt)); 475 break; 476 477 case nbpLkUpReply: 478 ND_PRINT(" nbp-reply %u:", GET_U_1(np->id)); 479 480 /* print each of the tuples in the reply */ 481 for (i = control & 0xf; i != 0 && tp; i--) 482 tp = nbp_tuple_print(ndo, tp, ep, snet, snode, skt); 483 break; 484 485 default: 486 ND_PRINT(" nbp-0x%x %u (%u)", control, GET_U_1(np->id), 487 length); 488 break; 489 } 490 } 491 492 /* print a counted string */ 493 static const u_char * 494 print_cstring(netdissect_options *ndo, 495 const u_char *cp, const u_char *ep) 496 { 497 u_int length; 498 499 if (cp >= ep) { 500 nd_print_trunc(ndo); 501 return (0); 502 } 503 length = GET_U_1(cp); 504 cp++; 505 506 /* Spec says string can be at most 32 bytes long */ 507 if (length > 32) { 508 ND_PRINT("[len=%u]", length); 509 return (0); 510 } 511 while (length != 0) { 512 if (cp >= ep) { 513 nd_print_trunc(ndo); 514 return (0); 515 } 516 fn_print_char(ndo, GET_U_1(cp)); 517 cp++; 518 length--; 519 } 520 return (cp); 521 } 522 523 static const struct atNBPtuple * 524 nbp_tuple_print(netdissect_options *ndo, 525 const struct atNBPtuple *tp, const u_char *ep, 526 u_short snet, u_char snode, u_char skt) 527 { 528 const struct atNBPtuple *tpn; 529 530 if ((const u_char *)(tp + 1) > ep) { 531 nd_print_trunc(ndo); 532 return 0; 533 } 534 tpn = nbp_name_print(ndo, tp, ep); 535 536 /* if the enumerator isn't 1, print it */ 537 if (GET_U_1(tp->enumerator) != 1) 538 ND_PRINT("(%u)", GET_U_1(tp->enumerator)); 539 540 /* if the socket doesn't match the src socket, print it */ 541 if (GET_U_1(tp->skt) != skt) 542 ND_PRINT(" %u", GET_U_1(tp->skt)); 543 544 /* if the address doesn't match the src address, it's an anomaly */ 545 if (GET_BE_U_2(tp->net) != snet || 546 GET_U_1(tp->node) != snode) 547 ND_PRINT(" [addr=%s]", 548 ataddr_string(ndo, GET_BE_U_2(tp->net), GET_U_1(tp->node))); 549 550 return (tpn); 551 } 552 553 static const struct atNBPtuple * 554 nbp_name_print(netdissect_options *ndo, 555 const struct atNBPtuple *tp, const u_char *ep) 556 { 557 const u_char *cp = (const u_char *)tp + nbpTupleSize; 558 559 ND_PRINT(" "); 560 561 /* Object */ 562 ND_PRINT("\""); 563 if ((cp = print_cstring(ndo, cp, ep)) != NULL) { 564 /* Type */ 565 ND_PRINT(":"); 566 if ((cp = print_cstring(ndo, cp, ep)) != NULL) { 567 /* Zone */ 568 ND_PRINT("@"); 569 if ((cp = print_cstring(ndo, cp, ep)) != NULL) 570 ND_PRINT("\""); 571 } 572 } 573 return ((const struct atNBPtuple *)cp); 574 } 575 576 577 #define HASHNAMESIZE 4096 578 579 struct hnamemem { 580 u_int addr; 581 char *name; 582 struct hnamemem *nxt; 583 }; 584 585 static struct hnamemem hnametable[HASHNAMESIZE]; 586 587 static const char * 588 ataddr_string(netdissect_options *ndo, 589 u_short atnet, u_char athost) 590 { 591 struct hnamemem *tp, *tp2; 592 u_int i = (atnet << 8) | athost; 593 char nambuf[256+1]; 594 static int first = 1; 595 FILE *fp; 596 597 /* 598 * Are we doing address to name resolution? 599 */ 600 if (!ndo->ndo_nflag) { 601 /* 602 * Yes. Have we tried to open and read an AppleTalk 603 * number to name map file? 604 */ 605 if (!first) { 606 /* 607 * No; try to do so. 608 */ 609 first = 0; 610 fp = fopen("/etc/atalk.names", "r"); 611 if (fp != NULL) { 612 char line[256]; 613 u_int i1, i2; 614 615 while (fgets(line, sizeof(line), fp)) { 616 if (line[0] == '\n' || line[0] == 0 || 617 line[0] == '#') 618 continue; 619 if (sscanf(line, "%u.%u %256s", &i1, 620 &i2, nambuf) == 3) 621 /* got a hostname. */ 622 i2 |= (i1 << 8); 623 else if (sscanf(line, "%u %256s", &i1, 624 nambuf) == 2) 625 /* got a net name */ 626 i2 = (i1 << 8) | 255; 627 else 628 continue; 629 630 for (tp = &hnametable[i2 & (HASHNAMESIZE-1)]; 631 tp->nxt; tp = tp->nxt) 632 ; 633 tp->addr = i2; 634 tp->nxt = newhnamemem(ndo); 635 tp->name = strdup(nambuf); 636 if (tp->name == NULL) 637 (*ndo->ndo_error)(ndo, 638 S_ERR_ND_MEM_ALLOC, 639 "%s: strdup(nambuf)", __func__); 640 } 641 fclose(fp); 642 } 643 } 644 } 645 646 /* 647 * Now try to look up the address in the table. 648 */ 649 for (tp = &hnametable[i & (HASHNAMESIZE-1)]; tp->nxt; tp = tp->nxt) 650 if (tp->addr == i) 651 return (tp->name); 652 653 /* didn't have the node name -- see if we've got the net name */ 654 i |= 255; 655 for (tp2 = &hnametable[i & (HASHNAMESIZE-1)]; tp2->nxt; tp2 = tp2->nxt) 656 if (tp2->addr == i) { 657 tp->addr = (atnet << 8) | athost; 658 tp->nxt = newhnamemem(ndo); 659 (void)snprintf(nambuf, sizeof(nambuf), "%s.%u", 660 tp2->name, athost); 661 tp->name = strdup(nambuf); 662 if (tp->name == NULL) 663 (*ndo->ndo_error)(ndo, S_ERR_ND_MEM_ALLOC, 664 "%s: strdup(nambuf)", __func__); 665 return (tp->name); 666 } 667 668 tp->addr = (atnet << 8) | athost; 669 tp->nxt = newhnamemem(ndo); 670 if (athost != 255) 671 (void)snprintf(nambuf, sizeof(nambuf), "%u.%u", atnet, athost); 672 else 673 (void)snprintf(nambuf, sizeof(nambuf), "%u", atnet); 674 tp->name = strdup(nambuf); 675 if (tp->name == NULL) 676 (*ndo->ndo_error)(ndo, S_ERR_ND_MEM_ALLOC, 677 "%s: strdup(nambuf)", __func__); 678 679 return (tp->name); 680 } 681 682 static const struct tok skt2str[] = { 683 { rtmpSkt, "rtmp" }, /* routing table maintenance */ 684 { nbpSkt, "nis" }, /* name info socket */ 685 { echoSkt, "echo" }, /* AppleTalk echo protocol */ 686 { zipSkt, "zip" }, /* zone info protocol */ 687 { 0, NULL } 688 }; 689 690 static const char * 691 ddpskt_string(netdissect_options *ndo, 692 u_int skt) 693 { 694 static char buf[8]; 695 696 if (ndo->ndo_nflag) { 697 (void)snprintf(buf, sizeof(buf), "%u", skt); 698 return (buf); 699 } 700 return (tok2str(skt2str, "%u", skt)); 701 } 702