141c99275SPeter Avalos /*
241c99275SPeter Avalos * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997
341c99275SPeter Avalos * The Regents of the University of California. All rights reserved.
441c99275SPeter Avalos *
541c99275SPeter Avalos * Redistribution and use in source and binary forms, with or without
641c99275SPeter Avalos * modification, are permitted provided that: (1) source code distributions
741c99275SPeter Avalos * retain the above copyright notice and this paragraph in its entirety, (2)
841c99275SPeter Avalos * distributions including binary code include the above copyright notice and
941c99275SPeter Avalos * this paragraph in its entirety in the documentation or other materials
1041c99275SPeter Avalos * provided with the distribution, and (3) all advertising materials mentioning
1141c99275SPeter Avalos * features or use of this software display the following acknowledgement:
1241c99275SPeter Avalos * ``This product includes software developed by the University of California,
1341c99275SPeter Avalos * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
1441c99275SPeter Avalos * the University nor the names of its contributors may be used to endorse
1541c99275SPeter Avalos * or promote products derived from this software without specific prior
1641c99275SPeter Avalos * written permission.
1741c99275SPeter Avalos * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
1841c99275SPeter Avalos * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
1941c99275SPeter Avalos * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
2041c99275SPeter Avalos */
2141c99275SPeter Avalos
22411677aeSAaron LI /* \summary: AppleTalk printer */
2341c99275SPeter Avalos
2441c99275SPeter Avalos #ifdef HAVE_CONFIG_H
25*ed775ee7SAntonio Huete Jimenez #include <config.h>
2641c99275SPeter Avalos #endif
2741c99275SPeter Avalos
28*ed775ee7SAntonio Huete Jimenez #include "netdissect-stdinc.h"
2941c99275SPeter Avalos
3041c99275SPeter Avalos #include <stdio.h>
3141c99275SPeter Avalos #include <string.h>
3241c99275SPeter Avalos
33411677aeSAaron LI #include "netdissect.h"
3441c99275SPeter Avalos #include "addrtoname.h"
3541c99275SPeter Avalos #include "ethertype.h"
36411677aeSAaron LI #include "extract.h"
3741c99275SPeter Avalos #include "appletalk.h"
3841c99275SPeter Avalos
39411677aeSAaron LI
40411677aeSAaron LI static const struct tok type2str[] = {
4141c99275SPeter Avalos { ddpRTMP, "rtmp" },
4241c99275SPeter Avalos { ddpRTMPrequest, "rtmpReq" },
4341c99275SPeter Avalos { ddpECHO, "echo" },
4441c99275SPeter Avalos { ddpIP, "IP" },
4541c99275SPeter Avalos { ddpARP, "ARP" },
4641c99275SPeter Avalos { ddpKLAP, "KLAP" },
4741c99275SPeter Avalos { 0, NULL }
4841c99275SPeter Avalos };
4941c99275SPeter Avalos
5041c99275SPeter Avalos struct aarp {
51*ed775ee7SAntonio Huete Jimenez nd_uint16_t htype, ptype;
52*ed775ee7SAntonio Huete Jimenez nd_uint8_t halen, palen;
53*ed775ee7SAntonio Huete Jimenez nd_uint16_t op;
54*ed775ee7SAntonio Huete Jimenez nd_mac_addr hsaddr;
55411677aeSAaron LI uint8_t psaddr[4];
56*ed775ee7SAntonio Huete Jimenez nd_mac_addr hdaddr;
57411677aeSAaron LI uint8_t pdaddr[4];
5841c99275SPeter Avalos };
5941c99275SPeter Avalos
60411677aeSAaron LI static void atp_print(netdissect_options *, const struct atATP *, u_int);
61411677aeSAaron LI static void atp_bitmap_print(netdissect_options *, u_char);
62411677aeSAaron LI static void nbp_print(netdissect_options *, const struct atNBP *, u_int, u_short, u_char, u_char);
63411677aeSAaron LI static const struct atNBPtuple *nbp_tuple_print(netdissect_options *ndo, const struct atNBPtuple *,
6441c99275SPeter Avalos const u_char *,
6541c99275SPeter Avalos u_short, u_char, u_char);
66411677aeSAaron LI static const struct atNBPtuple *nbp_name_print(netdissect_options *, const struct atNBPtuple *,
6741c99275SPeter Avalos const u_char *);
68411677aeSAaron LI static const char *ataddr_string(netdissect_options *, u_short, u_char);
69*ed775ee7SAntonio Huete Jimenez static void ddp_print(netdissect_options *, const u_char *, u_int, u_int, u_short, u_char, u_char);
70*ed775ee7SAntonio Huete Jimenez static const char *ddpskt_string(netdissect_options *, u_int);
7141c99275SPeter Avalos
7241c99275SPeter Avalos /*
7341c99275SPeter Avalos * Print LLAP packets received on a physical LocalTalk interface.
7441c99275SPeter Avalos */
75*ed775ee7SAntonio Huete Jimenez void
ltalk_if_print(netdissect_options * ndo,const struct pcap_pkthdr * h,const u_char * p)76411677aeSAaron LI ltalk_if_print(netdissect_options *ndo,
77411677aeSAaron LI const struct pcap_pkthdr *h, const u_char *p)
7841c99275SPeter Avalos {
79411677aeSAaron LI u_int hdrlen;
80411677aeSAaron LI
81*ed775ee7SAntonio Huete Jimenez ndo->ndo_protocol = "ltalk";
82411677aeSAaron LI hdrlen = llap_print(ndo, p, h->len);
83411677aeSAaron LI if (hdrlen == 0) {
84411677aeSAaron LI /* Cut short by the snapshot length. */
85*ed775ee7SAntonio Huete Jimenez ndo->ndo_ll_hdr_len += h->caplen;
86*ed775ee7SAntonio Huete Jimenez return;
87411677aeSAaron LI }
88*ed775ee7SAntonio Huete Jimenez ndo->ndo_ll_hdr_len += hdrlen;
8941c99275SPeter Avalos }
9041c99275SPeter Avalos
9141c99275SPeter Avalos /*
9241c99275SPeter Avalos * Print AppleTalk LLAP packets.
9341c99275SPeter Avalos */
9441c99275SPeter Avalos u_int
llap_print(netdissect_options * ndo,const u_char * bp,u_int length)95411677aeSAaron LI llap_print(netdissect_options *ndo,
96*ed775ee7SAntonio Huete Jimenez const u_char *bp, u_int length)
9741c99275SPeter Avalos {
98*ed775ee7SAntonio Huete Jimenez const struct LAP *lp;
99*ed775ee7SAntonio Huete Jimenez const struct atDDP *dp;
100*ed775ee7SAntonio Huete Jimenez const struct atShortDDP *sdp;
10141c99275SPeter Avalos u_short snet;
10241c99275SPeter Avalos u_int hdrlen;
10341c99275SPeter Avalos
104*ed775ee7SAntonio Huete Jimenez ndo->ndo_protocol = "llap";
10527bfbee1SPeter Avalos if (length < sizeof(*lp)) {
106*ed775ee7SAntonio Huete Jimenez ND_PRINT(" [|llap %u]", length);
10727bfbee1SPeter Avalos return (length);
10827bfbee1SPeter Avalos }
109*ed775ee7SAntonio Huete Jimenez if (!ND_TTEST_LEN(bp, sizeof(*lp))) {
110*ed775ee7SAntonio Huete Jimenez nd_print_trunc(ndo);
111411677aeSAaron LI return (0); /* cut short by the snapshot length */
112411677aeSAaron LI }
11341c99275SPeter Avalos lp = (const struct LAP *)bp;
11441c99275SPeter Avalos bp += sizeof(*lp);
11541c99275SPeter Avalos length -= sizeof(*lp);
11641c99275SPeter Avalos hdrlen = sizeof(*lp);
117*ed775ee7SAntonio Huete Jimenez switch (GET_U_1(lp->type)) {
11841c99275SPeter Avalos
11941c99275SPeter Avalos case lapShortDDP:
12041c99275SPeter Avalos if (length < ddpSSize) {
121*ed775ee7SAntonio Huete Jimenez ND_PRINT(" [|sddp %u]", length);
12241c99275SPeter Avalos return (length);
12341c99275SPeter Avalos }
124*ed775ee7SAntonio Huete Jimenez if (!ND_TTEST_LEN(bp, ddpSSize)) {
125*ed775ee7SAntonio Huete Jimenez ND_PRINT(" [|sddp]");
126411677aeSAaron LI return (0); /* cut short by the snapshot length */
127411677aeSAaron LI }
12841c99275SPeter Avalos sdp = (const struct atShortDDP *)bp;
129*ed775ee7SAntonio Huete Jimenez ND_PRINT("%s.%s",
130*ed775ee7SAntonio Huete Jimenez ataddr_string(ndo, 0, GET_U_1(lp->src)),
131*ed775ee7SAntonio Huete Jimenez ddpskt_string(ndo, GET_U_1(sdp->srcSkt)));
132*ed775ee7SAntonio Huete Jimenez ND_PRINT(" > %s.%s:",
133*ed775ee7SAntonio Huete Jimenez ataddr_string(ndo, 0, GET_U_1(lp->dst)),
134*ed775ee7SAntonio Huete Jimenez ddpskt_string(ndo, GET_U_1(sdp->dstSkt)));
13541c99275SPeter Avalos bp += ddpSSize;
13641c99275SPeter Avalos length -= ddpSSize;
13741c99275SPeter Avalos hdrlen += ddpSSize;
138*ed775ee7SAntonio Huete Jimenez ddp_print(ndo, bp, length, GET_U_1(sdp->type), 0,
139*ed775ee7SAntonio Huete Jimenez GET_U_1(lp->src), GET_U_1(sdp->srcSkt));
14041c99275SPeter Avalos break;
14141c99275SPeter Avalos
14241c99275SPeter Avalos case lapDDP:
14341c99275SPeter Avalos if (length < ddpSize) {
144*ed775ee7SAntonio Huete Jimenez ND_PRINT(" [|ddp %u]", length);
14541c99275SPeter Avalos return (length);
14641c99275SPeter Avalos }
147*ed775ee7SAntonio Huete Jimenez if (!ND_TTEST_LEN(bp, ddpSize)) {
148*ed775ee7SAntonio Huete Jimenez ND_PRINT(" [|ddp]");
149411677aeSAaron LI return (0); /* cut short by the snapshot length */
150411677aeSAaron LI }
15141c99275SPeter Avalos dp = (const struct atDDP *)bp;
152*ed775ee7SAntonio Huete Jimenez snet = GET_BE_U_2(dp->srcNet);
153*ed775ee7SAntonio Huete Jimenez ND_PRINT("%s.%s",
154*ed775ee7SAntonio Huete Jimenez ataddr_string(ndo, snet, GET_U_1(dp->srcNode)),
155*ed775ee7SAntonio Huete Jimenez ddpskt_string(ndo, GET_U_1(dp->srcSkt)));
156*ed775ee7SAntonio Huete Jimenez ND_PRINT(" > %s.%s:",
157*ed775ee7SAntonio Huete Jimenez ataddr_string(ndo, GET_BE_U_2(dp->dstNet), GET_U_1(dp->dstNode)),
158*ed775ee7SAntonio Huete Jimenez ddpskt_string(ndo, GET_U_1(dp->dstSkt)));
15941c99275SPeter Avalos bp += ddpSize;
16041c99275SPeter Avalos length -= ddpSize;
16141c99275SPeter Avalos hdrlen += ddpSize;
162*ed775ee7SAntonio Huete Jimenez ddp_print(ndo, bp, length, GET_U_1(dp->type), snet,
163*ed775ee7SAntonio Huete Jimenez GET_U_1(dp->srcNode), GET_U_1(dp->srcSkt));
16441c99275SPeter Avalos break;
16541c99275SPeter Avalos
16641c99275SPeter Avalos #ifdef notdef
16741c99275SPeter Avalos case lapKLAP:
16841c99275SPeter Avalos klap_print(bp, length);
16941c99275SPeter Avalos break;
17041c99275SPeter Avalos #endif
17141c99275SPeter Avalos
17241c99275SPeter Avalos default:
173*ed775ee7SAntonio Huete Jimenez ND_PRINT("%u > %u at-lap#%u %u",
174*ed775ee7SAntonio Huete Jimenez GET_U_1(lp->src), GET_U_1(lp->dst), GET_U_1(lp->type),
175*ed775ee7SAntonio Huete Jimenez length);
17641c99275SPeter Avalos break;
17741c99275SPeter Avalos }
17841c99275SPeter Avalos return (hdrlen);
17941c99275SPeter Avalos }
18041c99275SPeter Avalos
18141c99275SPeter Avalos /*
18241c99275SPeter Avalos * Print EtherTalk/TokenTalk packets (or FDDITalk, or whatever it's called
18341c99275SPeter Avalos * when it runs over FDDI; yes, I've seen FDDI captures with AppleTalk
18441c99275SPeter Avalos * packets in them).
18541c99275SPeter Avalos */
18641c99275SPeter Avalos void
atalk_print(netdissect_options * ndo,const u_char * bp,u_int length)187411677aeSAaron LI atalk_print(netdissect_options *ndo,
188*ed775ee7SAntonio Huete Jimenez const u_char *bp, u_int length)
18941c99275SPeter Avalos {
190*ed775ee7SAntonio Huete Jimenez const struct atDDP *dp;
19141c99275SPeter Avalos u_short snet;
19241c99275SPeter Avalos
193*ed775ee7SAntonio Huete Jimenez ndo->ndo_protocol = "atalk";
194411677aeSAaron LI if(!ndo->ndo_eflag)
195*ed775ee7SAntonio Huete Jimenez ND_PRINT("AT ");
19641c99275SPeter Avalos
19741c99275SPeter Avalos if (length < ddpSize) {
198*ed775ee7SAntonio Huete Jimenez ND_PRINT(" [|ddp %u]", length);
199411677aeSAaron LI return;
200411677aeSAaron LI }
201*ed775ee7SAntonio Huete Jimenez if (!ND_TTEST_LEN(bp, ddpSize)) {
202*ed775ee7SAntonio Huete Jimenez ND_PRINT(" [|ddp]");
20341c99275SPeter Avalos return;
20441c99275SPeter Avalos }
20541c99275SPeter Avalos dp = (const struct atDDP *)bp;
206*ed775ee7SAntonio Huete Jimenez snet = GET_BE_U_2(dp->srcNet);
207*ed775ee7SAntonio Huete Jimenez ND_PRINT("%s.%s", ataddr_string(ndo, snet, GET_U_1(dp->srcNode)),
208*ed775ee7SAntonio Huete Jimenez ddpskt_string(ndo, GET_U_1(dp->srcSkt)));
209*ed775ee7SAntonio Huete Jimenez ND_PRINT(" > %s.%s: ",
210*ed775ee7SAntonio Huete Jimenez ataddr_string(ndo, GET_BE_U_2(dp->dstNet), GET_U_1(dp->dstNode)),
211*ed775ee7SAntonio Huete Jimenez ddpskt_string(ndo, GET_U_1(dp->dstSkt)));
21241c99275SPeter Avalos bp += ddpSize;
21341c99275SPeter Avalos length -= ddpSize;
214*ed775ee7SAntonio Huete Jimenez ddp_print(ndo, bp, length, GET_U_1(dp->type), snet,
215*ed775ee7SAntonio Huete Jimenez GET_U_1(dp->srcNode), GET_U_1(dp->srcSkt));
21641c99275SPeter Avalos }
21741c99275SPeter Avalos
21841c99275SPeter Avalos /* XXX should probably pass in the snap header and do checks like arp_print() */
21941c99275SPeter Avalos void
aarp_print(netdissect_options * ndo,const u_char * bp,u_int length)220411677aeSAaron LI aarp_print(netdissect_options *ndo,
221*ed775ee7SAntonio Huete Jimenez const u_char *bp, u_int length)
22241c99275SPeter Avalos {
223*ed775ee7SAntonio Huete Jimenez const struct aarp *ap;
22441c99275SPeter Avalos
225411677aeSAaron LI #define AT(member) ataddr_string(ndo, (ap->member[1]<<8)|ap->member[2],ap->member[3])
22641c99275SPeter Avalos
227*ed775ee7SAntonio Huete Jimenez ndo->ndo_protocol = "aarp";
228*ed775ee7SAntonio Huete Jimenez ND_PRINT("aarp ");
22941c99275SPeter Avalos ap = (const struct aarp *)bp;
230*ed775ee7SAntonio Huete Jimenez if (!ND_TTEST_SIZE(ap)) {
231411677aeSAaron LI /* Just bail if we don't have the whole chunk. */
232*ed775ee7SAntonio Huete Jimenez nd_print_trunc(ndo);
233411677aeSAaron LI return;
234411677aeSAaron LI }
235411677aeSAaron LI if (length < sizeof(*ap)) {
236*ed775ee7SAntonio Huete Jimenez ND_PRINT(" [|aarp %u]", length);
237411677aeSAaron LI return;
238411677aeSAaron LI }
239*ed775ee7SAntonio Huete Jimenez if (GET_BE_U_2(ap->htype) == 1 &&
240*ed775ee7SAntonio Huete Jimenez GET_BE_U_2(ap->ptype) == ETHERTYPE_ATALK &&
241*ed775ee7SAntonio Huete Jimenez GET_U_1(ap->halen) == MAC_ADDR_LEN && GET_U_1(ap->palen) == 4)
242*ed775ee7SAntonio Huete Jimenez switch (GET_BE_U_2(ap->op)) {
24341c99275SPeter Avalos
24441c99275SPeter Avalos case 1: /* request */
245*ed775ee7SAntonio Huete Jimenez ND_PRINT("who-has %s tell %s", AT(pdaddr), AT(psaddr));
24641c99275SPeter Avalos return;
24741c99275SPeter Avalos
24841c99275SPeter Avalos case 2: /* response */
249*ed775ee7SAntonio Huete Jimenez ND_PRINT("reply %s is-at %s", AT(psaddr), GET_ETHERADDR_STRING(ap->hsaddr));
25041c99275SPeter Avalos return;
25141c99275SPeter Avalos
25241c99275SPeter Avalos case 3: /* probe (oy!) */
253*ed775ee7SAntonio Huete Jimenez ND_PRINT("probe %s tell %s", AT(pdaddr), AT(psaddr));
25441c99275SPeter Avalos return;
25541c99275SPeter Avalos }
256*ed775ee7SAntonio Huete Jimenez ND_PRINT("len %u op %u htype %u ptype %#x halen %u palen %u",
257*ed775ee7SAntonio Huete Jimenez length, GET_BE_U_2(ap->op), GET_BE_U_2(ap->htype),
258*ed775ee7SAntonio Huete Jimenez GET_BE_U_2(ap->ptype), GET_U_1(ap->halen), GET_U_1(ap->palen));
25941c99275SPeter Avalos }
26041c99275SPeter Avalos
26141c99275SPeter Avalos /*
26241c99275SPeter Avalos * Print AppleTalk Datagram Delivery Protocol packets.
26341c99275SPeter Avalos */
26441c99275SPeter Avalos static void
ddp_print(netdissect_options * ndo,const u_char * bp,u_int length,u_int t,u_short snet,u_char snode,u_char skt)265411677aeSAaron LI ddp_print(netdissect_options *ndo,
266*ed775ee7SAntonio Huete Jimenez const u_char *bp, u_int length, u_int t,
267*ed775ee7SAntonio Huete Jimenez u_short snet, u_char snode, u_char skt)
26841c99275SPeter Avalos {
26941c99275SPeter Avalos
27041c99275SPeter Avalos switch (t) {
27141c99275SPeter Avalos
27241c99275SPeter Avalos case ddpNBP:
273411677aeSAaron LI nbp_print(ndo, (const struct atNBP *)bp, length, snet, snode, skt);
27441c99275SPeter Avalos break;
27541c99275SPeter Avalos
27641c99275SPeter Avalos case ddpATP:
277411677aeSAaron LI atp_print(ndo, (const struct atATP *)bp, length);
27841c99275SPeter Avalos break;
27941c99275SPeter Avalos
28041c99275SPeter Avalos case ddpEIGRP:
281411677aeSAaron LI eigrp_print(ndo, bp, length);
28241c99275SPeter Avalos break;
28341c99275SPeter Avalos
28441c99275SPeter Avalos default:
285*ed775ee7SAntonio Huete Jimenez ND_PRINT(" at-%s %u", tok2str(type2str, NULL, t), length);
28641c99275SPeter Avalos break;
28741c99275SPeter Avalos }
28841c99275SPeter Avalos }
28941c99275SPeter Avalos
29041c99275SPeter Avalos static void
atp_print(netdissect_options * ndo,const struct atATP * ap,u_int length)291411677aeSAaron LI atp_print(netdissect_options *ndo,
292*ed775ee7SAntonio Huete Jimenez const struct atATP *ap, u_int length)
29341c99275SPeter Avalos {
294*ed775ee7SAntonio Huete Jimenez uint8_t control;
295411677aeSAaron LI uint32_t data;
29641c99275SPeter Avalos
297411677aeSAaron LI if ((const u_char *)(ap + 1) > ndo->ndo_snapend) {
29841c99275SPeter Avalos /* Just bail if we don't have the whole chunk. */
299*ed775ee7SAntonio Huete Jimenez nd_print_trunc(ndo);
30041c99275SPeter Avalos return;
30141c99275SPeter Avalos }
30227bfbee1SPeter Avalos if (length < sizeof(*ap)) {
303*ed775ee7SAntonio Huete Jimenez ND_PRINT(" [|atp %u]", length);
30427bfbee1SPeter Avalos return;
30527bfbee1SPeter Avalos }
30641c99275SPeter Avalos length -= sizeof(*ap);
307*ed775ee7SAntonio Huete Jimenez control = GET_U_1(ap->control);
308*ed775ee7SAntonio Huete Jimenez switch (control & 0xc0) {
30941c99275SPeter Avalos
31041c99275SPeter Avalos case atpReqCode:
311*ed775ee7SAntonio Huete Jimenez ND_PRINT(" atp-req%s %u",
312*ed775ee7SAntonio Huete Jimenez control & atpXO? " " : "*",
313*ed775ee7SAntonio Huete Jimenez GET_BE_U_2(ap->transID));
31441c99275SPeter Avalos
315*ed775ee7SAntonio Huete Jimenez atp_bitmap_print(ndo, GET_U_1(ap->bitmap));
31641c99275SPeter Avalos
31741c99275SPeter Avalos if (length != 0)
318*ed775ee7SAntonio Huete Jimenez ND_PRINT(" [len=%u]", length);
31941c99275SPeter Avalos
320*ed775ee7SAntonio Huete Jimenez switch (control & (atpEOM|atpSTS)) {
32141c99275SPeter Avalos case atpEOM:
322*ed775ee7SAntonio Huete Jimenez ND_PRINT(" [EOM]");
32341c99275SPeter Avalos break;
32441c99275SPeter Avalos case atpSTS:
325*ed775ee7SAntonio Huete Jimenez ND_PRINT(" [STS]");
32641c99275SPeter Avalos break;
32741c99275SPeter Avalos case atpEOM|atpSTS:
328*ed775ee7SAntonio Huete Jimenez ND_PRINT(" [EOM,STS]");
32941c99275SPeter Avalos break;
33041c99275SPeter Avalos }
33141c99275SPeter Avalos break;
33241c99275SPeter Avalos
33341c99275SPeter Avalos case atpRspCode:
334*ed775ee7SAntonio Huete Jimenez ND_PRINT(" atp-resp%s%u:%u (%u)",
335*ed775ee7SAntonio Huete Jimenez control & atpEOM? "*" : " ",
336*ed775ee7SAntonio Huete Jimenez GET_BE_U_2(ap->transID), GET_U_1(ap->bitmap),
337*ed775ee7SAntonio Huete Jimenez length);
338*ed775ee7SAntonio Huete Jimenez switch (control & (atpXO|atpSTS)) {
33941c99275SPeter Avalos case atpXO:
340*ed775ee7SAntonio Huete Jimenez ND_PRINT(" [XO]");
34141c99275SPeter Avalos break;
34241c99275SPeter Avalos case atpSTS:
343*ed775ee7SAntonio Huete Jimenez ND_PRINT(" [STS]");
34441c99275SPeter Avalos break;
34541c99275SPeter Avalos case atpXO|atpSTS:
346*ed775ee7SAntonio Huete Jimenez ND_PRINT(" [XO,STS]");
34741c99275SPeter Avalos break;
34841c99275SPeter Avalos }
34941c99275SPeter Avalos break;
35041c99275SPeter Avalos
35141c99275SPeter Avalos case atpRelCode:
352*ed775ee7SAntonio Huete Jimenez ND_PRINT(" atp-rel %u", GET_BE_U_2(ap->transID));
35341c99275SPeter Avalos
354*ed775ee7SAntonio Huete Jimenez atp_bitmap_print(ndo, GET_U_1(ap->bitmap));
35541c99275SPeter Avalos
35641c99275SPeter Avalos /* length should be zero */
35741c99275SPeter Avalos if (length)
358*ed775ee7SAntonio Huete Jimenez ND_PRINT(" [len=%u]", length);
35941c99275SPeter Avalos
36041c99275SPeter Avalos /* there shouldn't be any control flags */
361*ed775ee7SAntonio Huete Jimenez if (control & (atpXO|atpEOM|atpSTS)) {
362*ed775ee7SAntonio Huete Jimenez char c = '[';
363*ed775ee7SAntonio Huete Jimenez if (control & atpXO) {
364*ed775ee7SAntonio Huete Jimenez ND_PRINT("%cXO", c);
36541c99275SPeter Avalos c = ',';
36641c99275SPeter Avalos }
367*ed775ee7SAntonio Huete Jimenez if (control & atpEOM) {
368*ed775ee7SAntonio Huete Jimenez ND_PRINT("%cEOM", c);
36941c99275SPeter Avalos c = ',';
37041c99275SPeter Avalos }
371*ed775ee7SAntonio Huete Jimenez if (control & atpSTS) {
372*ed775ee7SAntonio Huete Jimenez ND_PRINT("%cSTS", c);
37341c99275SPeter Avalos }
374*ed775ee7SAntonio Huete Jimenez ND_PRINT("]");
37541c99275SPeter Avalos }
37641c99275SPeter Avalos break;
37741c99275SPeter Avalos
37841c99275SPeter Avalos default:
379*ed775ee7SAntonio Huete Jimenez ND_PRINT(" atp-0x%x %u (%u)", control,
380*ed775ee7SAntonio Huete Jimenez GET_BE_U_2(ap->transID), length);
38141c99275SPeter Avalos break;
38241c99275SPeter Avalos }
383*ed775ee7SAntonio Huete Jimenez data = GET_BE_U_4(ap->userData);
38441c99275SPeter Avalos if (data != 0)
385*ed775ee7SAntonio Huete Jimenez ND_PRINT(" 0x%x", data);
38641c99275SPeter Avalos }
38741c99275SPeter Avalos
38841c99275SPeter Avalos static void
atp_bitmap_print(netdissect_options * ndo,u_char bm)389411677aeSAaron LI atp_bitmap_print(netdissect_options *ndo,
390*ed775ee7SAntonio Huete Jimenez u_char bm)
39141c99275SPeter Avalos {
392*ed775ee7SAntonio Huete Jimenez u_int i;
39341c99275SPeter Avalos
39441c99275SPeter Avalos /*
39541c99275SPeter Avalos * The '& 0xff' below is needed for compilers that want to sign
39641c99275SPeter Avalos * extend a u_char, which is the case with the Ultrix compiler.
39741c99275SPeter Avalos * (gcc is smart enough to eliminate it, at least on the Sparc).
39841c99275SPeter Avalos */
39941c99275SPeter Avalos if ((bm + 1) & (bm & 0xff)) {
400*ed775ee7SAntonio Huete Jimenez char c = '<';
40141c99275SPeter Avalos for (i = 0; bm; ++i) {
40241c99275SPeter Avalos if (bm & 1) {
403*ed775ee7SAntonio Huete Jimenez ND_PRINT("%c%u", c, i);
40441c99275SPeter Avalos c = ',';
40541c99275SPeter Avalos }
40641c99275SPeter Avalos bm >>= 1;
40741c99275SPeter Avalos }
408*ed775ee7SAntonio Huete Jimenez ND_PRINT(">");
40941c99275SPeter Avalos } else {
41041c99275SPeter Avalos for (i = 0; bm; ++i)
41141c99275SPeter Avalos bm >>= 1;
41241c99275SPeter Avalos if (i > 1)
413*ed775ee7SAntonio Huete Jimenez ND_PRINT("<0-%u>", i - 1);
41441c99275SPeter Avalos else
415*ed775ee7SAntonio Huete Jimenez ND_PRINT("<0>");
41641c99275SPeter Avalos }
41741c99275SPeter Avalos }
41841c99275SPeter Avalos
41941c99275SPeter Avalos static void
nbp_print(netdissect_options * ndo,const struct atNBP * np,u_int length,u_short snet,u_char snode,u_char skt)420411677aeSAaron LI nbp_print(netdissect_options *ndo,
421*ed775ee7SAntonio Huete Jimenez const struct atNBP *np, u_int length, u_short snet,
422*ed775ee7SAntonio Huete Jimenez u_char snode, u_char skt)
42341c99275SPeter Avalos {
424*ed775ee7SAntonio Huete Jimenez const struct atNBPtuple *tp =
425411677aeSAaron LI (const struct atNBPtuple *)((const u_char *)np + nbpHeaderSize);
426*ed775ee7SAntonio Huete Jimenez uint8_t control;
427*ed775ee7SAntonio Huete Jimenez u_int i;
42841c99275SPeter Avalos const u_char *ep;
42941c99275SPeter Avalos
43041c99275SPeter Avalos if (length < nbpHeaderSize) {
431*ed775ee7SAntonio Huete Jimenez ND_PRINT(" truncated-nbp %u", length);
43241c99275SPeter Avalos return;
43341c99275SPeter Avalos }
43441c99275SPeter Avalos
43541c99275SPeter Avalos length -= nbpHeaderSize;
43641c99275SPeter Avalos if (length < 8) {
43741c99275SPeter Avalos /* must be room for at least one tuple */
438*ed775ee7SAntonio Huete Jimenez ND_PRINT(" truncated-nbp %u", length + nbpHeaderSize);
43941c99275SPeter Avalos return;
44041c99275SPeter Avalos }
44141c99275SPeter Avalos /* ep points to end of available data */
442411677aeSAaron LI ep = ndo->ndo_snapend;
44341c99275SPeter Avalos if ((const u_char *)tp > ep) {
444*ed775ee7SAntonio Huete Jimenez nd_print_trunc(ndo);
44541c99275SPeter Avalos return;
44641c99275SPeter Avalos }
447*ed775ee7SAntonio Huete Jimenez control = GET_U_1(np->control);
448*ed775ee7SAntonio Huete Jimenez switch (i = (control & 0xf0)) {
44941c99275SPeter Avalos
45041c99275SPeter Avalos case nbpBrRq:
45141c99275SPeter Avalos case nbpLkUp:
452*ed775ee7SAntonio Huete Jimenez ND_PRINT(i == nbpLkUp? " nbp-lkup %u:":" nbp-brRq %u:",
453*ed775ee7SAntonio Huete Jimenez GET_U_1(np->id));
45441c99275SPeter Avalos if ((const u_char *)(tp + 1) > ep) {
455*ed775ee7SAntonio Huete Jimenez nd_print_trunc(ndo);
45641c99275SPeter Avalos return;
45741c99275SPeter Avalos }
458411677aeSAaron LI (void)nbp_name_print(ndo, tp, ep);
45941c99275SPeter Avalos /*
46041c99275SPeter Avalos * look for anomalies: the spec says there can only
46141c99275SPeter Avalos * be one tuple, the address must match the source
46241c99275SPeter Avalos * address and the enumerator should be zero.
46341c99275SPeter Avalos */
464*ed775ee7SAntonio Huete Jimenez if ((control & 0xf) != 1)
465*ed775ee7SAntonio Huete Jimenez ND_PRINT(" [ntup=%u]", control & 0xf);
466*ed775ee7SAntonio Huete Jimenez if (GET_U_1(tp->enumerator))
467*ed775ee7SAntonio Huete Jimenez ND_PRINT(" [enum=%u]", GET_U_1(tp->enumerator));
468*ed775ee7SAntonio Huete Jimenez if (GET_BE_U_2(tp->net) != snet ||
469*ed775ee7SAntonio Huete Jimenez GET_U_1(tp->node) != snode ||
470*ed775ee7SAntonio Huete Jimenez GET_U_1(tp->skt) != skt)
471*ed775ee7SAntonio Huete Jimenez ND_PRINT(" [addr=%s.%u]",
472*ed775ee7SAntonio Huete Jimenez ataddr_string(ndo, GET_BE_U_2(tp->net),
473*ed775ee7SAntonio Huete Jimenez GET_U_1(tp->node)),
474*ed775ee7SAntonio Huete Jimenez GET_U_1(tp->skt));
47541c99275SPeter Avalos break;
47641c99275SPeter Avalos
47741c99275SPeter Avalos case nbpLkUpReply:
478*ed775ee7SAntonio Huete Jimenez ND_PRINT(" nbp-reply %u:", GET_U_1(np->id));
47941c99275SPeter Avalos
48041c99275SPeter Avalos /* print each of the tuples in the reply */
481*ed775ee7SAntonio Huete Jimenez for (i = control & 0xf; i != 0 && tp; i--)
482411677aeSAaron LI tp = nbp_tuple_print(ndo, tp, ep, snet, snode, skt);
48341c99275SPeter Avalos break;
48441c99275SPeter Avalos
48541c99275SPeter Avalos default:
486*ed775ee7SAntonio Huete Jimenez ND_PRINT(" nbp-0x%x %u (%u)", control, GET_U_1(np->id),
487*ed775ee7SAntonio Huete Jimenez length);
48841c99275SPeter Avalos break;
48941c99275SPeter Avalos }
49041c99275SPeter Avalos }
49141c99275SPeter Avalos
49241c99275SPeter Avalos /* print a counted string */
493*ed775ee7SAntonio Huete Jimenez static const u_char *
print_cstring(netdissect_options * ndo,const u_char * cp,const u_char * ep)494411677aeSAaron LI print_cstring(netdissect_options *ndo,
495*ed775ee7SAntonio Huete Jimenez const u_char *cp, const u_char *ep)
49641c99275SPeter Avalos {
497*ed775ee7SAntonio Huete Jimenez u_int length;
49841c99275SPeter Avalos
499*ed775ee7SAntonio Huete Jimenez if (cp >= ep) {
500*ed775ee7SAntonio Huete Jimenez nd_print_trunc(ndo);
50141c99275SPeter Avalos return (0);
50241c99275SPeter Avalos }
503*ed775ee7SAntonio Huete Jimenez length = GET_U_1(cp);
504*ed775ee7SAntonio Huete Jimenez cp++;
50541c99275SPeter Avalos
50641c99275SPeter Avalos /* Spec says string can be at most 32 bytes long */
50741c99275SPeter Avalos if (length > 32) {
508*ed775ee7SAntonio Huete Jimenez ND_PRINT("[len=%u]", length);
50941c99275SPeter Avalos return (0);
51041c99275SPeter Avalos }
511*ed775ee7SAntonio Huete Jimenez while (length != 0) {
512*ed775ee7SAntonio Huete Jimenez if (cp >= ep) {
513*ed775ee7SAntonio Huete Jimenez nd_print_trunc(ndo);
51441c99275SPeter Avalos return (0);
51541c99275SPeter Avalos }
516*ed775ee7SAntonio Huete Jimenez fn_print_char(ndo, GET_U_1(cp));
517*ed775ee7SAntonio Huete Jimenez cp++;
518*ed775ee7SAntonio Huete Jimenez length--;
51941c99275SPeter Avalos }
52041c99275SPeter Avalos return (cp);
52141c99275SPeter Avalos }
52241c99275SPeter Avalos
52341c99275SPeter Avalos static const struct atNBPtuple *
nbp_tuple_print(netdissect_options * ndo,const struct atNBPtuple * tp,const u_char * ep,u_short snet,u_char snode,u_char skt)524411677aeSAaron LI nbp_tuple_print(netdissect_options *ndo,
525*ed775ee7SAntonio Huete Jimenez const struct atNBPtuple *tp, const u_char *ep,
526*ed775ee7SAntonio Huete Jimenez u_short snet, u_char snode, u_char skt)
52741c99275SPeter Avalos {
528*ed775ee7SAntonio Huete Jimenez const struct atNBPtuple *tpn;
52941c99275SPeter Avalos
53041c99275SPeter Avalos if ((const u_char *)(tp + 1) > ep) {
531*ed775ee7SAntonio Huete Jimenez nd_print_trunc(ndo);
53241c99275SPeter Avalos return 0;
53341c99275SPeter Avalos }
534411677aeSAaron LI tpn = nbp_name_print(ndo, tp, ep);
53541c99275SPeter Avalos
53641c99275SPeter Avalos /* if the enumerator isn't 1, print it */
537*ed775ee7SAntonio Huete Jimenez if (GET_U_1(tp->enumerator) != 1)
538*ed775ee7SAntonio Huete Jimenez ND_PRINT("(%u)", GET_U_1(tp->enumerator));
53941c99275SPeter Avalos
54041c99275SPeter Avalos /* if the socket doesn't match the src socket, print it */
541*ed775ee7SAntonio Huete Jimenez if (GET_U_1(tp->skt) != skt)
542*ed775ee7SAntonio Huete Jimenez ND_PRINT(" %u", GET_U_1(tp->skt));
54341c99275SPeter Avalos
54441c99275SPeter Avalos /* if the address doesn't match the src address, it's an anomaly */
545*ed775ee7SAntonio Huete Jimenez if (GET_BE_U_2(tp->net) != snet ||
546*ed775ee7SAntonio Huete Jimenez GET_U_1(tp->node) != snode)
547*ed775ee7SAntonio Huete Jimenez ND_PRINT(" [addr=%s]",
548*ed775ee7SAntonio Huete Jimenez ataddr_string(ndo, GET_BE_U_2(tp->net), GET_U_1(tp->node)));
54941c99275SPeter Avalos
55041c99275SPeter Avalos return (tpn);
55141c99275SPeter Avalos }
55241c99275SPeter Avalos
55341c99275SPeter Avalos static const struct atNBPtuple *
nbp_name_print(netdissect_options * ndo,const struct atNBPtuple * tp,const u_char * ep)554411677aeSAaron LI nbp_name_print(netdissect_options *ndo,
555*ed775ee7SAntonio Huete Jimenez const struct atNBPtuple *tp, const u_char *ep)
55641c99275SPeter Avalos {
557*ed775ee7SAntonio Huete Jimenez const u_char *cp = (const u_char *)tp + nbpTupleSize;
55841c99275SPeter Avalos
559*ed775ee7SAntonio Huete Jimenez ND_PRINT(" ");
56041c99275SPeter Avalos
56141c99275SPeter Avalos /* Object */
562*ed775ee7SAntonio Huete Jimenez ND_PRINT("\"");
563411677aeSAaron LI if ((cp = print_cstring(ndo, cp, ep)) != NULL) {
56441c99275SPeter Avalos /* Type */
565*ed775ee7SAntonio Huete Jimenez ND_PRINT(":");
566411677aeSAaron LI if ((cp = print_cstring(ndo, cp, ep)) != NULL) {
56741c99275SPeter Avalos /* Zone */
568*ed775ee7SAntonio Huete Jimenez ND_PRINT("@");
569411677aeSAaron LI if ((cp = print_cstring(ndo, cp, ep)) != NULL)
570*ed775ee7SAntonio Huete Jimenez ND_PRINT("\"");
57141c99275SPeter Avalos }
57241c99275SPeter Avalos }
57341c99275SPeter Avalos return ((const struct atNBPtuple *)cp);
57441c99275SPeter Avalos }
57541c99275SPeter Avalos
57641c99275SPeter Avalos
57741c99275SPeter Avalos #define HASHNAMESIZE 4096
57841c99275SPeter Avalos
57941c99275SPeter Avalos struct hnamemem {
580*ed775ee7SAntonio Huete Jimenez u_int addr;
58141c99275SPeter Avalos char *name;
58241c99275SPeter Avalos struct hnamemem *nxt;
58341c99275SPeter Avalos };
58441c99275SPeter Avalos
58541c99275SPeter Avalos static struct hnamemem hnametable[HASHNAMESIZE];
58641c99275SPeter Avalos
58741c99275SPeter Avalos static const char *
ataddr_string(netdissect_options * ndo,u_short atnet,u_char athost)588411677aeSAaron LI ataddr_string(netdissect_options *ndo,
589411677aeSAaron LI u_short atnet, u_char athost)
59041c99275SPeter Avalos {
591*ed775ee7SAntonio Huete Jimenez struct hnamemem *tp, *tp2;
592*ed775ee7SAntonio Huete Jimenez u_int i = (atnet << 8) | athost;
593411677aeSAaron LI char nambuf[256+1];
59441c99275SPeter Avalos static int first = 1;
59541c99275SPeter Avalos FILE *fp;
59641c99275SPeter Avalos
59741c99275SPeter Avalos /*
598*ed775ee7SAntonio Huete Jimenez * Are we doing address to name resolution?
59941c99275SPeter Avalos */
600*ed775ee7SAntonio Huete Jimenez if (!ndo->ndo_nflag) {
601*ed775ee7SAntonio Huete Jimenez /*
602*ed775ee7SAntonio Huete Jimenez * Yes. Have we tried to open and read an AppleTalk
603*ed775ee7SAntonio Huete Jimenez * number to name map file?
604*ed775ee7SAntonio Huete Jimenez */
605*ed775ee7SAntonio Huete Jimenez if (!first) {
606*ed775ee7SAntonio Huete Jimenez /*
607*ed775ee7SAntonio Huete Jimenez * No; try to do so.
608*ed775ee7SAntonio Huete Jimenez */
609*ed775ee7SAntonio Huete Jimenez first = 0;
610*ed775ee7SAntonio Huete Jimenez fp = fopen("/etc/atalk.names", "r");
611*ed775ee7SAntonio Huete Jimenez if (fp != NULL) {
61241c99275SPeter Avalos char line[256];
613*ed775ee7SAntonio Huete Jimenez u_int i1, i2;
61441c99275SPeter Avalos
61541c99275SPeter Avalos while (fgets(line, sizeof(line), fp)) {
616*ed775ee7SAntonio Huete Jimenez if (line[0] == '\n' || line[0] == 0 ||
617*ed775ee7SAntonio Huete Jimenez line[0] == '#')
61841c99275SPeter Avalos continue;
619*ed775ee7SAntonio Huete Jimenez if (sscanf(line, "%u.%u %256s", &i1,
620*ed775ee7SAntonio Huete Jimenez &i2, nambuf) == 3)
62141c99275SPeter Avalos /* got a hostname. */
62227bfbee1SPeter Avalos i2 |= (i1 << 8);
623*ed775ee7SAntonio Huete Jimenez else if (sscanf(line, "%u %256s", &i1,
624*ed775ee7SAntonio Huete Jimenez nambuf) == 2)
62541c99275SPeter Avalos /* got a net name */
62627bfbee1SPeter Avalos i2 = (i1 << 8) | 255;
62741c99275SPeter Avalos else
62841c99275SPeter Avalos continue;
62941c99275SPeter Avalos
63027bfbee1SPeter Avalos for (tp = &hnametable[i2 & (HASHNAMESIZE-1)];
63141c99275SPeter Avalos tp->nxt; tp = tp->nxt)
63241c99275SPeter Avalos ;
63327bfbee1SPeter Avalos tp->addr = i2;
634411677aeSAaron LI tp->nxt = newhnamemem(ndo);
63541c99275SPeter Avalos tp->name = strdup(nambuf);
636411677aeSAaron LI if (tp->name == NULL)
637411677aeSAaron LI (*ndo->ndo_error)(ndo,
638*ed775ee7SAntonio Huete Jimenez S_ERR_ND_MEM_ALLOC,
639*ed775ee7SAntonio Huete Jimenez "%s: strdup(nambuf)", __func__);
64041c99275SPeter Avalos }
64141c99275SPeter Avalos fclose(fp);
64241c99275SPeter Avalos }
643*ed775ee7SAntonio Huete Jimenez }
644*ed775ee7SAntonio Huete Jimenez }
64541c99275SPeter Avalos
646*ed775ee7SAntonio Huete Jimenez /*
647*ed775ee7SAntonio Huete Jimenez * Now try to look up the address in the table.
648*ed775ee7SAntonio Huete Jimenez */
64941c99275SPeter Avalos for (tp = &hnametable[i & (HASHNAMESIZE-1)]; tp->nxt; tp = tp->nxt)
65041c99275SPeter Avalos if (tp->addr == i)
65141c99275SPeter Avalos return (tp->name);
65241c99275SPeter Avalos
65341c99275SPeter Avalos /* didn't have the node name -- see if we've got the net name */
65441c99275SPeter Avalos i |= 255;
65541c99275SPeter Avalos for (tp2 = &hnametable[i & (HASHNAMESIZE-1)]; tp2->nxt; tp2 = tp2->nxt)
65641c99275SPeter Avalos if (tp2->addr == i) {
65741c99275SPeter Avalos tp->addr = (atnet << 8) | athost;
658411677aeSAaron LI tp->nxt = newhnamemem(ndo);
659*ed775ee7SAntonio Huete Jimenez (void)snprintf(nambuf, sizeof(nambuf), "%s.%u",
66041c99275SPeter Avalos tp2->name, athost);
66141c99275SPeter Avalos tp->name = strdup(nambuf);
662411677aeSAaron LI if (tp->name == NULL)
663*ed775ee7SAntonio Huete Jimenez (*ndo->ndo_error)(ndo, S_ERR_ND_MEM_ALLOC,
664*ed775ee7SAntonio Huete Jimenez "%s: strdup(nambuf)", __func__);
66541c99275SPeter Avalos return (tp->name);
66641c99275SPeter Avalos }
66741c99275SPeter Avalos
66841c99275SPeter Avalos tp->addr = (atnet << 8) | athost;
669411677aeSAaron LI tp->nxt = newhnamemem(ndo);
67041c99275SPeter Avalos if (athost != 255)
671*ed775ee7SAntonio Huete Jimenez (void)snprintf(nambuf, sizeof(nambuf), "%u.%u", atnet, athost);
67241c99275SPeter Avalos else
673*ed775ee7SAntonio Huete Jimenez (void)snprintf(nambuf, sizeof(nambuf), "%u", atnet);
67441c99275SPeter Avalos tp->name = strdup(nambuf);
675411677aeSAaron LI if (tp->name == NULL)
676*ed775ee7SAntonio Huete Jimenez (*ndo->ndo_error)(ndo, S_ERR_ND_MEM_ALLOC,
677*ed775ee7SAntonio Huete Jimenez "%s: strdup(nambuf)", __func__);
67841c99275SPeter Avalos
67941c99275SPeter Avalos return (tp->name);
68041c99275SPeter Avalos }
68141c99275SPeter Avalos
682411677aeSAaron LI static const struct tok skt2str[] = {
68341c99275SPeter Avalos { rtmpSkt, "rtmp" }, /* routing table maintenance */
68441c99275SPeter Avalos { nbpSkt, "nis" }, /* name info socket */
68541c99275SPeter Avalos { echoSkt, "echo" }, /* AppleTalk echo protocol */
68641c99275SPeter Avalos { zipSkt, "zip" }, /* zone info protocol */
68741c99275SPeter Avalos { 0, NULL }
68841c99275SPeter Avalos };
68941c99275SPeter Avalos
69041c99275SPeter Avalos static const char *
ddpskt_string(netdissect_options * ndo,u_int skt)691411677aeSAaron LI ddpskt_string(netdissect_options *ndo,
692*ed775ee7SAntonio Huete Jimenez u_int skt)
69341c99275SPeter Avalos {
69441c99275SPeter Avalos static char buf[8];
69541c99275SPeter Avalos
696411677aeSAaron LI if (ndo->ndo_nflag) {
697*ed775ee7SAntonio Huete Jimenez (void)snprintf(buf, sizeof(buf), "%u", skt);
69841c99275SPeter Avalos return (buf);
69941c99275SPeter Avalos }
700*ed775ee7SAntonio Huete Jimenez return (tok2str(skt2str, "%u", skt));
70141c99275SPeter Avalos }
702