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