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