10f74e101Schristos /* 20f74e101Schristos * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997 30f74e101Schristos * The Regents of the University of California. All rights reserved. 40f74e101Schristos * 50f74e101Schristos * Redistribution and use in source and binary forms, with or without 60f74e101Schristos * modification, are permitted provided that: (1) source code distributions 70f74e101Schristos * retain the above copyright notice and this paragraph in its entirety, (2) 80f74e101Schristos * distributions including binary code include the above copyright notice and 90f74e101Schristos * this paragraph in its entirety in the documentation or other materials 100f74e101Schristos * provided with the distribution, and (3) all advertising materials mentioning 110f74e101Schristos * features or use of this software display the following acknowledgement: 120f74e101Schristos * ``This product includes software developed by the University of California, 130f74e101Schristos * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of 140f74e101Schristos * the University nor the names of its contributors may be used to endorse 150f74e101Schristos * or promote products derived from this software without specific prior 160f74e101Schristos * written permission. 170f74e101Schristos * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED 180f74e101Schristos * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF 190f74e101Schristos * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 200f74e101Schristos */ 210f74e101Schristos 2211b3aaa1Schristos #include <sys/cdefs.h> 230f74e101Schristos #ifndef lint 24*26ba0b50Schristos __RCSID("$NetBSD: print-arp.c,v 1.11 2024/09/02 16:15:30 christos Exp $"); 250f74e101Schristos #endif 260f74e101Schristos 27dc860a36Sspz /* \summary: Address Resolution Protocol (ARP) printer */ 28dc860a36Sspz 29c74ad251Schristos #include <config.h> 300f74e101Schristos 31c74ad251Schristos #include "netdissect-stdinc.h" 320f74e101Schristos 33c74ad251Schristos #define ND_LONGJMP_FROM_TCHECK 34fdccd7e4Schristos #include "netdissect.h" 350f74e101Schristos #include "addrtoname.h" 360f74e101Schristos #include "ethertype.h" 37fdccd7e4Schristos #include "extract.h" 380f74e101Schristos 39b3a00663Schristos 400f74e101Schristos /* 410f74e101Schristos * Address Resolution Protocol. 420f74e101Schristos * 430f74e101Schristos * See RFC 826 for protocol description. ARP packets are variable 440f74e101Schristos * in size; the arphdr structure defines the fixed-length portion. 450f74e101Schristos * Protocol type values are the same as those for 10 Mb/s Ethernet. 460f74e101Schristos * It is followed by the variable-sized fields ar_sha, arp_spa, 470f74e101Schristos * arp_tha and arp_tpa in that order, according to the lengths 480f74e101Schristos * specified. Field names used correspond to RFC 826. 490f74e101Schristos */ 500f74e101Schristos struct arp_pkthdr { 51c74ad251Schristos nd_uint16_t ar_hrd; /* format of hardware address */ 520f74e101Schristos #define ARPHRD_ETHER 1 /* ethernet hardware format */ 530f74e101Schristos #define ARPHRD_IEEE802 6 /* token-ring hardware format */ 540f74e101Schristos #define ARPHRD_ARCNET 7 /* arcnet hardware format */ 550f74e101Schristos #define ARPHRD_FRELAY 15 /* frame relay hardware format */ 560f74e101Schristos #define ARPHRD_ATM2225 19 /* ATM (RFC 2225) */ 570f74e101Schristos #define ARPHRD_STRIP 23 /* Ricochet Starmode Radio hardware format */ 580f74e101Schristos #define ARPHRD_IEEE1394 24 /* IEEE 1394 (FireWire) hardware format */ 59c74ad251Schristos #define ARPHRD_INFINIBAND 32 /* InfiniBand RFC 4391 */ 60c74ad251Schristos nd_uint16_t ar_pro; /* format of protocol address */ 61c74ad251Schristos nd_uint8_t ar_hln; /* length of hardware address */ 62c74ad251Schristos nd_uint8_t ar_pln; /* length of protocol address */ 63c74ad251Schristos nd_uint16_t ar_op; /* one of: */ 640f74e101Schristos #define ARPOP_REQUEST 1 /* request to resolve address */ 650f74e101Schristos #define ARPOP_REPLY 2 /* response to previous request */ 660f74e101Schristos #define ARPOP_REVREQUEST 3 /* request protocol address given hardware */ 670f74e101Schristos #define ARPOP_REVREPLY 4 /* response giving protocol address */ 680f74e101Schristos #define ARPOP_INVREQUEST 8 /* request to identify peer */ 690f74e101Schristos #define ARPOP_INVREPLY 9 /* response identifying peer */ 70c74ad251Schristos #define ARPOP_NAK 10 /* NAK - only valid for ATM ARP */ 710f74e101Schristos 720f74e101Schristos /* 730f74e101Schristos * The remaining fields are variable in size, 740f74e101Schristos * according to the sizes above. 750f74e101Schristos */ 760f74e101Schristos #ifdef COMMENT_ONLY 77c74ad251Schristos nd_byte ar_sha[]; /* sender hardware address */ 78c74ad251Schristos nd_byte ar_spa[]; /* sender protocol address */ 79c74ad251Schristos nd_byte ar_tha[]; /* target hardware address */ 80c74ad251Schristos nd_byte ar_tpa[]; /* target protocol address */ 810f74e101Schristos #endif 820f74e101Schristos #define ar_sha(ap) (((const u_char *)((ap)+1))+ 0) 83c74ad251Schristos #define ar_spa(ap) (((const u_char *)((ap)+1))+ GET_U_1((ap)->ar_hln)) 84c74ad251Schristos #define ar_tha(ap) (((const u_char *)((ap)+1))+ GET_U_1((ap)->ar_hln)+GET_U_1((ap)->ar_pln)) 85c74ad251Schristos #define ar_tpa(ap) (((const u_char *)((ap)+1))+2*GET_U_1((ap)->ar_hln)+GET_U_1((ap)->ar_pln)) 860f74e101Schristos }; 870f74e101Schristos 880f74e101Schristos #define ARP_HDRLEN 8 890f74e101Schristos 90c74ad251Schristos #define HRD(ap) GET_BE_U_2((ap)->ar_hrd) 91c74ad251Schristos #define HRD_LEN(ap) GET_U_1((ap)->ar_hln) 92c74ad251Schristos #define PROTO_LEN(ap) GET_U_1((ap)->ar_pln) 93c74ad251Schristos #define OP(ap) GET_BE_U_2((ap)->ar_op) 94c74ad251Schristos #define PRO(ap) GET_BE_U_2((ap)->ar_pro) 950f74e101Schristos #define SHA(ap) (ar_sha(ap)) 960f74e101Schristos #define SPA(ap) (ar_spa(ap)) 970f74e101Schristos #define THA(ap) (ar_tha(ap)) 980f74e101Schristos #define TPA(ap) (ar_tpa(ap)) 990f74e101Schristos 1000f74e101Schristos 101870189d2Schristos static const struct tok arpop_values[] = { 1020f74e101Schristos { ARPOP_REQUEST, "Request" }, 1030f74e101Schristos { ARPOP_REPLY, "Reply" }, 1040f74e101Schristos { ARPOP_REVREQUEST, "Reverse Request" }, 1050f74e101Schristos { ARPOP_REVREPLY, "Reverse Reply" }, 1060f74e101Schristos { ARPOP_INVREQUEST, "Inverse Request" }, 1070f74e101Schristos { ARPOP_INVREPLY, "Inverse Reply" }, 1080f74e101Schristos { ARPOP_NAK, "NACK Reply" }, 1090f74e101Schristos { 0, NULL } 1100f74e101Schristos }; 1110f74e101Schristos 112870189d2Schristos static const struct tok arphrd_values[] = { 1130f74e101Schristos { ARPHRD_ETHER, "Ethernet" }, 1140f74e101Schristos { ARPHRD_IEEE802, "TokenRing" }, 1150f74e101Schristos { ARPHRD_ARCNET, "ArcNet" }, 1160f74e101Schristos { ARPHRD_FRELAY, "FrameRelay" }, 1170f74e101Schristos { ARPHRD_STRIP, "Strip" }, 1180f74e101Schristos { ARPHRD_IEEE1394, "IEEE 1394" }, 1190f74e101Schristos { ARPHRD_ATM2225, "ATM" }, 120c74ad251Schristos { ARPHRD_INFINIBAND, "InfiniBand" }, 1210f74e101Schristos { 0, NULL } 1220f74e101Schristos }; 1230f74e101Schristos 1240f74e101Schristos /* 1250f74e101Schristos * ATM Address Resolution Protocol. 1260f74e101Schristos * 1270f74e101Schristos * See RFC 2225 for protocol description. ATMARP packets are similar 1280f74e101Schristos * to ARP packets, except that there are no length fields for the 1290f74e101Schristos * protocol address - instead, there are type/length fields for 1300f74e101Schristos * the ATM number and subaddress - and the hardware addresses consist 1310f74e101Schristos * of an ATM number and an ATM subaddress. 1320f74e101Schristos */ 1330f74e101Schristos struct atmarp_pkthdr { 134c74ad251Schristos nd_uint16_t aar_hrd; /* format of hardware address */ 135c74ad251Schristos nd_uint16_t aar_pro; /* format of protocol address */ 136c74ad251Schristos nd_uint8_t aar_shtl; /* length of source ATM number */ 137c74ad251Schristos nd_uint8_t aar_sstl; /* length of source ATM subaddress */ 1380f74e101Schristos #define ATMARP_IS_E164 0x40 /* bit in type/length for E.164 format */ 1390f74e101Schristos #define ATMARP_LEN_MASK 0x3F /* length of {sub}address in type/length */ 140c74ad251Schristos nd_uint16_t aar_op; /* same as regular ARP */ 141c74ad251Schristos nd_uint8_t aar_spln; /* length of source protocol address */ 142c74ad251Schristos nd_uint8_t aar_thtl; /* length of target ATM number */ 143c74ad251Schristos nd_uint8_t aar_tstl; /* length of target ATM subaddress */ 144c74ad251Schristos nd_uint8_t aar_tpln; /* length of target protocol address */ 1450f74e101Schristos /* 1460f74e101Schristos * The remaining fields are variable in size, 1470f74e101Schristos * according to the sizes above. 1480f74e101Schristos */ 1490f74e101Schristos #ifdef COMMENT_ONLY 150c74ad251Schristos nd_byte aar_sha[]; /* source ATM number */ 151c74ad251Schristos nd_byte aar_ssa[]; /* source ATM subaddress */ 152c74ad251Schristos nd_byte aar_spa[]; /* sender protocol address */ 153c74ad251Schristos nd_byte aar_tha[]; /* target ATM number */ 154c74ad251Schristos nd_byte aar_tsa[]; /* target ATM subaddress */ 155c74ad251Schristos nd_byte aar_tpa[]; /* target protocol address */ 1560f74e101Schristos #endif 1570f74e101Schristos 158c74ad251Schristos #define ATMHRD(ap) GET_BE_U_2((ap)->aar_hrd) 159c74ad251Schristos #define ATMSHRD_LEN(ap) (GET_U_1((ap)->aar_shtl) & ATMARP_LEN_MASK) 160c74ad251Schristos #define ATMSSLN(ap) (GET_U_1((ap)->aar_sstl) & ATMARP_LEN_MASK) 161c74ad251Schristos #define ATMSPROTO_LEN(ap) GET_U_1((ap)->aar_spln) 162c74ad251Schristos #define ATMOP(ap) GET_BE_U_2((ap)->aar_op) 163c74ad251Schristos #define ATMPRO(ap) GET_BE_U_2((ap)->aar_pro) 164c74ad251Schristos #define ATMTHRD_LEN(ap) (GET_U_1((ap)->aar_thtl) & ATMARP_LEN_MASK) 165c74ad251Schristos #define ATMTSLN(ap) (GET_U_1((ap)->aar_tstl) & ATMARP_LEN_MASK) 166c74ad251Schristos #define ATMTPROTO_LEN(ap) GET_U_1((ap)->aar_tpln) 1670f74e101Schristos #define aar_sha(ap) ((const u_char *)((ap)+1)) 1680f74e101Schristos #define aar_ssa(ap) (aar_sha(ap) + ATMSHRD_LEN(ap)) 1690f74e101Schristos #define aar_spa(ap) (aar_ssa(ap) + ATMSSLN(ap)) 1700f74e101Schristos #define aar_tha(ap) (aar_spa(ap) + ATMSPROTO_LEN(ap)) 1710f74e101Schristos #define aar_tsa(ap) (aar_tha(ap) + ATMTHRD_LEN(ap)) 1720f74e101Schristos #define aar_tpa(ap) (aar_tsa(ap) + ATMTSLN(ap)) 1730f74e101Schristos }; 1740f74e101Schristos 1750f74e101Schristos #define ATMSHA(ap) (aar_sha(ap)) 1760f74e101Schristos #define ATMSSA(ap) (aar_ssa(ap)) 1770f74e101Schristos #define ATMSPA(ap) (aar_spa(ap)) 1780f74e101Schristos #define ATMTHA(ap) (aar_tha(ap)) 1790f74e101Schristos #define ATMTSA(ap) (aar_tsa(ap)) 1800f74e101Schristos #define ATMTPA(ap) (aar_tpa(ap)) 1810f74e101Schristos 182dc860a36Sspz static int 183c74ad251Schristos isnonzero(netdissect_options *ndo, const u_char *a, size_t len) 184dc860a36Sspz { 185dc860a36Sspz while (len > 0) { 186c74ad251Schristos if (GET_U_1(a) != 0) 187dc860a36Sspz return (1); 188dc860a36Sspz a++; 189dc860a36Sspz len--; 190dc860a36Sspz } 191dc860a36Sspz return (0); 192dc860a36Sspz } 1930f74e101Schristos 1940f74e101Schristos static void 19572c96ff3Schristos tpaddr_print_ip(netdissect_options *ndo, 19672c96ff3Schristos const struct arp_pkthdr *ap, u_short pro) 19772c96ff3Schristos { 19872c96ff3Schristos if (pro != ETHERTYPE_IP && pro != ETHERTYPE_TRAIL) 199c74ad251Schristos ND_PRINT("<wrong proto type>"); 20072c96ff3Schristos else if (PROTO_LEN(ap) != 4) 201c74ad251Schristos ND_PRINT("<wrong len>"); 20272c96ff3Schristos else 203c74ad251Schristos ND_PRINT("%s", GET_IPADDR_STRING(TPA(ap))); 20472c96ff3Schristos } 20572c96ff3Schristos 20672c96ff3Schristos static void 20772c96ff3Schristos spaddr_print_ip(netdissect_options *ndo, 20872c96ff3Schristos const struct arp_pkthdr *ap, u_short pro) 20972c96ff3Schristos { 21072c96ff3Schristos if (pro != ETHERTYPE_IP && pro != ETHERTYPE_TRAIL) 211c74ad251Schristos ND_PRINT("<wrong proto type>"); 21272c96ff3Schristos else if (PROTO_LEN(ap) != 4) 213c74ad251Schristos ND_PRINT("<wrong len>"); 21472c96ff3Schristos else 215c74ad251Schristos ND_PRINT("%s", GET_IPADDR_STRING(SPA(ap))); 21672c96ff3Schristos } 21772c96ff3Schristos 21872c96ff3Schristos static void 2190f74e101Schristos atmarp_addr_print(netdissect_options *ndo, 2200f74e101Schristos const u_char *ha, u_int ha_len, const u_char *srca, 2210f74e101Schristos u_int srca_len) 2220f74e101Schristos { 2230f74e101Schristos if (ha_len == 0) 224c74ad251Schristos ND_PRINT("<No address>"); 2250f74e101Schristos else { 226c74ad251Schristos ND_PRINT("%s", GET_LINKADDR_STRING(ha, LINKADDR_ATM, ha_len)); 2270f74e101Schristos if (srca_len != 0) 228c74ad251Schristos ND_PRINT(",%s", 229c74ad251Schristos GET_LINKADDR_STRING(srca, LINKADDR_ATM, srca_len)); 2300f74e101Schristos } 2310f74e101Schristos } 2320f74e101Schristos 2330f74e101Schristos static void 23472c96ff3Schristos atmarp_tpaddr_print(netdissect_options *ndo, 23572c96ff3Schristos const struct atmarp_pkthdr *ap, u_short pro) 23672c96ff3Schristos { 23772c96ff3Schristos if (pro != ETHERTYPE_IP && pro != ETHERTYPE_TRAIL) 238c74ad251Schristos ND_PRINT("<wrong proto type>"); 23972c96ff3Schristos else if (ATMTPROTO_LEN(ap) != 4) 240c74ad251Schristos ND_PRINT("<wrong tplen>"); 24172c96ff3Schristos else 242c74ad251Schristos ND_PRINT("%s", GET_IPADDR_STRING(ATMTPA(ap))); 24372c96ff3Schristos } 24472c96ff3Schristos 24572c96ff3Schristos static void 24672c96ff3Schristos atmarp_spaddr_print(netdissect_options *ndo, 24772c96ff3Schristos const struct atmarp_pkthdr *ap, u_short pro) 24872c96ff3Schristos { 24972c96ff3Schristos if (pro != ETHERTYPE_IP && pro != ETHERTYPE_TRAIL) 250c74ad251Schristos ND_PRINT("<wrong proto type>"); 25172c96ff3Schristos else if (ATMSPROTO_LEN(ap) != 4) 252c74ad251Schristos ND_PRINT("<wrong splen>"); 25372c96ff3Schristos else 254c74ad251Schristos ND_PRINT("%s", GET_IPADDR_STRING(ATMSPA(ap))); 25572c96ff3Schristos } 25672c96ff3Schristos 25772c96ff3Schristos static void 2580f74e101Schristos atmarp_print(netdissect_options *ndo, 2590f74e101Schristos const u_char *bp, u_int length, u_int caplen) 2600f74e101Schristos { 2610f74e101Schristos const struct atmarp_pkthdr *ap; 2620f74e101Schristos u_short pro, hrd, op; 2630f74e101Schristos 2640f74e101Schristos ap = (const struct atmarp_pkthdr *)bp; 265c74ad251Schristos ND_TCHECK_SIZE(ap); 2660f74e101Schristos 2670f74e101Schristos hrd = ATMHRD(ap); 2680f74e101Schristos pro = ATMPRO(ap); 2690f74e101Schristos op = ATMOP(ap); 2700f74e101Schristos 271c74ad251Schristos ND_TCHECK_LEN(ATMTPA(ap), ATMTPROTO_LEN(ap)); 2720f74e101Schristos 2730f74e101Schristos if (!ndo->ndo_eflag) { 274c74ad251Schristos ND_PRINT("ARP, "); 2750f74e101Schristos } 2760f74e101Schristos 2770f74e101Schristos if ((pro != ETHERTYPE_IP && pro != ETHERTYPE_TRAIL) || 2780f74e101Schristos ATMSPROTO_LEN(ap) != 4 || 2790f74e101Schristos ATMTPROTO_LEN(ap) != 4 || 2800f74e101Schristos ndo->ndo_vflag) { 281c74ad251Schristos ND_PRINT("%s, %s (len %u/%u)", 2820f74e101Schristos tok2str(arphrd_values, "Unknown Hardware (%u)", hrd), 2830f74e101Schristos tok2str(ethertype_values, "Unknown Protocol (0x%04x)", pro), 2840f74e101Schristos ATMSPROTO_LEN(ap), 285c74ad251Schristos ATMTPROTO_LEN(ap)); 2860f74e101Schristos 287c74ad251Schristos /* don't know about the address formats */ 2880f74e101Schristos if (!ndo->ndo_vflag) { 2890f74e101Schristos goto out; 2900f74e101Schristos } 2910f74e101Schristos } 2920f74e101Schristos 2930f74e101Schristos /* print operation */ 294c74ad251Schristos ND_PRINT("%s%s ", 2950f74e101Schristos ndo->ndo_vflag ? ", " : "", 296c74ad251Schristos tok2str(arpop_values, "Unknown (%u)", op)); 2970f74e101Schristos 2980f74e101Schristos switch (op) { 2990f74e101Schristos 3000f74e101Schristos case ARPOP_REQUEST: 301c74ad251Schristos ND_PRINT("who-has "); 30272c96ff3Schristos atmarp_tpaddr_print(ndo, ap, pro); 3030f74e101Schristos if (ATMTHRD_LEN(ap) != 0) { 304c74ad251Schristos ND_PRINT(" ("); 3050f74e101Schristos atmarp_addr_print(ndo, ATMTHA(ap), ATMTHRD_LEN(ap), 3060f74e101Schristos ATMTSA(ap), ATMTSLN(ap)); 307c74ad251Schristos ND_PRINT(")"); 3080f74e101Schristos } 309c74ad251Schristos ND_PRINT(" tell "); 31072c96ff3Schristos atmarp_spaddr_print(ndo, ap, pro); 3110f74e101Schristos break; 3120f74e101Schristos 3130f74e101Schristos case ARPOP_REPLY: 31472c96ff3Schristos atmarp_spaddr_print(ndo, ap, pro); 315c74ad251Schristos ND_PRINT(" is-at "); 3160f74e101Schristos atmarp_addr_print(ndo, ATMSHA(ap), ATMSHRD_LEN(ap), ATMSSA(ap), 3170f74e101Schristos ATMSSLN(ap)); 3180f74e101Schristos break; 3190f74e101Schristos 3200f74e101Schristos case ARPOP_INVREQUEST: 321c74ad251Schristos ND_PRINT("who-is "); 3220f74e101Schristos atmarp_addr_print(ndo, ATMTHA(ap), ATMTHRD_LEN(ap), ATMTSA(ap), 3230f74e101Schristos ATMTSLN(ap)); 324c74ad251Schristos ND_PRINT(" tell "); 3250f74e101Schristos atmarp_addr_print(ndo, ATMSHA(ap), ATMSHRD_LEN(ap), ATMSSA(ap), 3260f74e101Schristos ATMSSLN(ap)); 3270f74e101Schristos break; 3280f74e101Schristos 3290f74e101Schristos case ARPOP_INVREPLY: 3300f74e101Schristos atmarp_addr_print(ndo, ATMSHA(ap), ATMSHRD_LEN(ap), ATMSSA(ap), 3310f74e101Schristos ATMSSLN(ap)); 332c74ad251Schristos ND_PRINT("at "); 33372c96ff3Schristos atmarp_spaddr_print(ndo, ap, pro); 3340f74e101Schristos break; 3350f74e101Schristos 3360f74e101Schristos case ARPOP_NAK: 337c74ad251Schristos ND_PRINT("for "); 33872c96ff3Schristos atmarp_spaddr_print(ndo, ap, pro); 3390f74e101Schristos break; 3400f74e101Schristos 3410f74e101Schristos default: 3420f74e101Schristos ND_DEFAULTPRINT((const u_char *)ap, caplen); 3430f74e101Schristos return; 3440f74e101Schristos } 3450f74e101Schristos 3460f74e101Schristos out: 347c74ad251Schristos ND_PRINT(", length %u", length); 3480f74e101Schristos } 3490f74e101Schristos 3500f74e101Schristos void 3510f74e101Schristos arp_print(netdissect_options *ndo, 3520f74e101Schristos const u_char *bp, u_int length, u_int caplen) 3530f74e101Schristos { 3540f74e101Schristos const struct arp_pkthdr *ap; 3550f74e101Schristos u_short pro, hrd, op, linkaddr; 3560f74e101Schristos 357c74ad251Schristos ndo->ndo_protocol = "arp"; 3580f74e101Schristos ap = (const struct arp_pkthdr *)bp; 359c74ad251Schristos ND_TCHECK_SIZE(ap); 3600f74e101Schristos 3610f74e101Schristos hrd = HRD(ap); 3620f74e101Schristos pro = PRO(ap); 3630f74e101Schristos op = OP(ap); 3640f74e101Schristos 3650f74e101Schristos 3660f74e101Schristos /* if its ATM then call the ATM ARP printer 3670f74e101Schristos for Frame-relay ARP most of the fields 3680f74e101Schristos are similar to Ethernet so overload the Ethernet Printer 369c74ad251Schristos and set the linkaddr type for GET_LINKADDR_STRING() accordingly */ 3700f74e101Schristos 3710f74e101Schristos switch(hrd) { 3720f74e101Schristos case ARPHRD_ATM2225: 3730f74e101Schristos atmarp_print(ndo, bp, length, caplen); 3740f74e101Schristos return; 3750f74e101Schristos case ARPHRD_FRELAY: 3760f74e101Schristos linkaddr = LINKADDR_FRELAY; 3770e9868baSchristos break; 3780f74e101Schristos default: 3790f74e101Schristos linkaddr = LINKADDR_ETHER; 3800f74e101Schristos break; 3810f74e101Schristos } 3820f74e101Schristos 383c74ad251Schristos ND_TCHECK_LEN(TPA(ap), PROTO_LEN(ap)); 3840f74e101Schristos 3850f74e101Schristos if (!ndo->ndo_eflag) { 386c74ad251Schristos ND_PRINT("ARP, "); 3870f74e101Schristos } 3880f74e101Schristos 3890f74e101Schristos /* print hardware type/len and proto type/len */ 3900f74e101Schristos if ((pro != ETHERTYPE_IP && pro != ETHERTYPE_TRAIL) || 3910f74e101Schristos PROTO_LEN(ap) != 4 || 3920f74e101Schristos HRD_LEN(ap) == 0 || 3930f74e101Schristos ndo->ndo_vflag) { 394c74ad251Schristos ND_PRINT("%s (len %u), %s (len %u)", 3950f74e101Schristos tok2str(arphrd_values, "Unknown Hardware (%u)", hrd), 3960f74e101Schristos HRD_LEN(ap), 3970f74e101Schristos tok2str(ethertype_values, "Unknown Protocol (0x%04x)", pro), 398c74ad251Schristos PROTO_LEN(ap)); 3990f74e101Schristos 400c74ad251Schristos /* don't know about the address formats */ 4010f74e101Schristos if (!ndo->ndo_vflag) { 4020f74e101Schristos goto out; 4030f74e101Schristos } 4040f74e101Schristos } 4050f74e101Schristos 4060f74e101Schristos /* print operation */ 407c74ad251Schristos ND_PRINT("%s%s ", 4080f74e101Schristos ndo->ndo_vflag ? ", " : "", 409c74ad251Schristos tok2str(arpop_values, "Unknown (%u)", op)); 4100f74e101Schristos 4110f74e101Schristos switch (op) { 4120f74e101Schristos 4130f74e101Schristos case ARPOP_REQUEST: 414c74ad251Schristos ND_PRINT("who-has "); 41572c96ff3Schristos tpaddr_print_ip(ndo, ap, pro); 416c74ad251Schristos if (isnonzero(ndo, (const u_char *)THA(ap), HRD_LEN(ap))) 417c74ad251Schristos ND_PRINT(" (%s)", 418c74ad251Schristos GET_LINKADDR_STRING(THA(ap), linkaddr, HRD_LEN(ap))); 419c74ad251Schristos ND_PRINT(" tell "); 42072c96ff3Schristos spaddr_print_ip(ndo, ap, pro); 4210f74e101Schristos break; 4220f74e101Schristos 4230f74e101Schristos case ARPOP_REPLY: 42472c96ff3Schristos spaddr_print_ip(ndo, ap, pro); 425c74ad251Schristos ND_PRINT(" is-at %s", 426c74ad251Schristos GET_LINKADDR_STRING(SHA(ap), linkaddr, HRD_LEN(ap))); 4270f74e101Schristos break; 4280f74e101Schristos 4290f74e101Schristos case ARPOP_REVREQUEST: 430c74ad251Schristos /* 431c74ad251Schristos * XXX - GET_LINKADDR_STRING() may return a pointer to 432c74ad251Schristos * a static buffer, so we only have one call to it per 433c74ad251Schristos * ND_PRINT() call. 434c74ad251Schristos * 435c74ad251Schristos * This should be done in a cleaner fashion. 436c74ad251Schristos */ 437c74ad251Schristos ND_PRINT("who-is %s", 438c74ad251Schristos GET_LINKADDR_STRING(THA(ap), linkaddr, HRD_LEN(ap))); 439c74ad251Schristos ND_PRINT(" tell %s", 440c74ad251Schristos GET_LINKADDR_STRING(SHA(ap), linkaddr, HRD_LEN(ap))); 4410f74e101Schristos break; 4420f74e101Schristos 4430f74e101Schristos case ARPOP_REVREPLY: 444c74ad251Schristos ND_PRINT("%s at ", 445c74ad251Schristos GET_LINKADDR_STRING(THA(ap), linkaddr, HRD_LEN(ap))); 44672c96ff3Schristos tpaddr_print_ip(ndo, ap, pro); 4470f74e101Schristos break; 4480f74e101Schristos 4490f74e101Schristos case ARPOP_INVREQUEST: 450c74ad251Schristos /* 451c74ad251Schristos * XXX - GET_LINKADDR_STRING() may return a pointer to 452c74ad251Schristos * a static buffer, so we only have one call to it per 453c74ad251Schristos * ND_PRINT() call. 454c74ad251Schristos * 455c74ad251Schristos * This should be done in a cleaner fashion. 456c74ad251Schristos */ 457c74ad251Schristos ND_PRINT("who-is %s", 458c74ad251Schristos GET_LINKADDR_STRING(THA(ap), linkaddr, HRD_LEN(ap))); 459c74ad251Schristos ND_PRINT(" tell %s", 460c74ad251Schristos GET_LINKADDR_STRING(SHA(ap), linkaddr, HRD_LEN(ap))); 4610f74e101Schristos break; 4620f74e101Schristos 4630f74e101Schristos case ARPOP_INVREPLY: 464c74ad251Schristos ND_PRINT("%s at ", 465c74ad251Schristos GET_LINKADDR_STRING(SHA(ap), linkaddr, HRD_LEN(ap))); 46672c96ff3Schristos spaddr_print_ip(ndo, ap, pro); 4670f74e101Schristos break; 4680f74e101Schristos 4690f74e101Schristos default: 4700f74e101Schristos ND_DEFAULTPRINT((const u_char *)ap, caplen); 4710f74e101Schristos return; 4720f74e101Schristos } 4730f74e101Schristos 4740f74e101Schristos out: 475c74ad251Schristos ND_PRINT(", length %u", length); 4760f74e101Schristos } 477