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