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