print-arp.c revision 236192
16059Samurai/* 26059Samurai * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997 36059Samurai * The Regents of the University of California. All rights reserved. 46059Samurai * 56059Samurai * Redistribution and use in source and binary forms, with or without 66059Samurai * modification, are permitted provided that: (1) source code distributions 76059Samurai * retain the above copyright notice and this paragraph in its entirety, (2) 86059Samurai * distributions including binary code include the above copyright notice and 96059Samurai * this paragraph in its entirety in the documentation or other materials 106059Samurai * provided with the distribution, and (3) all advertising materials mentioning 116059Samurai * features or use of this software display the following acknowledgement: 126059Samurai * ``This product includes software developed by the University of California, 136059Samurai * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of 146059Samurai * the University nor the names of its contributors may be used to endorse 156059Samurai * or promote products derived from this software without specific prior 166059Samurai * written permission. 176059Samurai * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED 186059Samurai * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF 198857Srgrimes * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 2046686Sbrian * 218857Srgrimes * $FreeBSD: stable/9/contrib/tcpdump/print-arp.c 236192 2012-05-28 19:13:21Z delphij $ 226059Samurai */ 236059Samurai 246059Samurai#ifndef lint 256059Samuraistatic const char rcsid[] _U_ = 2643313Sbrian "@(#) $Header: /tcpdump/master/tcpdump/print-arp.c,v 1.66 2006-03-03 22:53:21 hannes Exp $ (LBL)"; 2746086Sbrian#endif 2831195Sbrian 2938174Sbrian#ifdef HAVE_CONFIG_H 3030715Sbrian#include "config.h" 316059Samurai#endif 326059Samurai 336059Samurai#include <tcpdump-stdinc.h> 346059Samurai 356059Samurai#include <stdio.h> 3613389Sphk#include <string.h> 3736285Sbrian 3830715Sbrian#include "netdissect.h" 3930092Sbrian#include "addrtoname.h" 4030715Sbrian#include "ether.h" 4130715Sbrian#include "ethertype.h" 4230715Sbrian#include "extract.h" /* must come after interface.h */ 4346686Sbrian 4430715Sbrian/* 4530715Sbrian * Address Resolution Protocol. 4646686Sbrian * 4746686Sbrian * See RFC 826 for protocol description. ARP packets are variable 4830715Sbrian * in size; the arphdr structure defines the fixed-length portion. 4930715Sbrian * Protocol type values are the same as those for 10 Mb/s Ethernet. 5030715Sbrian * It is followed by the variable-sized fields ar_sha, arp_spa, 5130715Sbrian * arp_tha and arp_tpa in that order, according to the lengths 5230715Sbrian * specified. Field names used correspond to RFC 826. 5336285Sbrian */ 5430715Sbrianstruct arp_pkthdr { 5536285Sbrian u_short ar_hrd; /* format of hardware address */ 5636285Sbrian#define ARPHRD_ETHER 1 /* ethernet hardware format */ 5736285Sbrian#define ARPHRD_IEEE802 6 /* token-ring hardware format */ 5836285Sbrian#define ARPHRD_ARCNET 7 /* arcnet hardware format */ 596059Samurai#define ARPHRD_FRELAY 15 /* frame relay hardware format */ 6036285Sbrian#define ARPHRD_ATM2225 19 /* ATM (RFC 2225) */ 6136285Sbrian#define ARPHRD_STRIP 23 /* Ricochet Starmode Radio hardware format */ 6236285Sbrian#define ARPHRD_IEEE1394 24 /* IEEE 1394 (FireWire) hardware format */ 6336285Sbrian u_short ar_pro; /* format of protocol address */ 6436285Sbrian u_char ar_hln; /* length of hardware address */ 6543313Sbrian u_char ar_pln; /* length of protocol address */ 6643313Sbrian u_short ar_op; /* one of: */ 6743313Sbrian#define ARPOP_REQUEST 1 /* request to resolve address */ 6836285Sbrian#define ARPOP_REPLY 2 /* response to previous request */ 6930715Sbrian#define ARPOP_REVREQUEST 3 /* request protocol address given hardware */ 7031195Sbrian#define ARPOP_REVREPLY 4 /* response giving protocol address */ 7130715Sbrian#define ARPOP_INVREQUEST 8 /* request to identify peer */ 726059Samurai#define ARPOP_INVREPLY 9 /* response identifying peer */ 7331343Sbrian#define ARPOP_NAK 10 /* NAK - only valif for ATM ARP */ 7428679Sbrian 7546223Sbrian/* 766059Samurai * The remaining fields are variable in size, 776059Samurai * according to the sizes above. 7813733Sdfr */ 796059Samurai#ifdef COMMENT_ONLY 8031343Sbrian u_char ar_sha[]; /* sender hardware address */ 816059Samurai u_char ar_spa[]; /* sender protocol address */ 826059Samurai u_char ar_tha[]; /* target hardware address */ 8328679Sbrian u_char ar_tpa[]; /* target protocol address */ 846059Samurai#endif 856059Samurai#define ar_sha(ap) (((const u_char *)((ap)+1))+0) 8628679Sbrian#define ar_spa(ap) (((const u_char *)((ap)+1))+ (ap)->ar_hln) 8728679Sbrian#define ar_tha(ap) (((const u_char *)((ap)+1))+ (ap)->ar_hln+(ap)->ar_pln) 886059Samurai#define ar_tpa(ap) (((const u_char *)((ap)+1))+2*(ap)->ar_hln+(ap)->ar_pln) 8928679Sbrian}; 906059Samurai 9128679Sbrian#define ARP_HDRLEN 8 926059Samurai 9328679Sbrian#define HRD(ap) EXTRACT_16BITS(&(ap)->ar_hrd) 946059Samurai#define HRD_LEN(ap) ((ap)->ar_hln) 956059Samurai#define PROTO_LEN(ap) ((ap)->ar_pln) 966059Samurai#define OP(ap) EXTRACT_16BITS(&(ap)->ar_op) 976059Samurai#define PRO(ap) EXTRACT_16BITS(&(ap)->ar_pro) 9846686Sbrian#define SHA(ap) (ar_sha(ap)) 996059Samurai#define SPA(ap) (ar_spa(ap)) 1006059Samurai#define THA(ap) (ar_tha(ap)) 10136285Sbrian#define TPA(ap) (ar_tpa(ap)) 1026059Samurai 10336285Sbrian 1046059Samuraistruct tok arpop_values[] = { 1056059Samurai { ARPOP_REQUEST, "Request" }, 1066059Samurai { ARPOP_REPLY, "Reply" }, 1076059Samurai { ARPOP_REVREQUEST, "Reverse Request" }, 1086059Samurai { ARPOP_REVREPLY, "Reverse Reply" }, 10936285Sbrian { ARPOP_INVREQUEST, "Inverse Request" }, 11036285Sbrian { ARPOP_INVREPLY, "Inverse Reply" }, 1116059Samurai { ARPOP_NAK, "NACK Reply" }, 1126059Samurai { 0, NULL } 11336285Sbrian}; 1146059Samurai 1156059Samuraistruct tok arphrd_values[] = { 1166059Samurai { ARPHRD_ETHER, "Ethernet" }, 11728679Sbrian { ARPHRD_IEEE802, "TokenRing" }, 11836285Sbrian { ARPHRD_ARCNET, "ArcNet" }, 11928679Sbrian { ARPHRD_FRELAY, "FrameRelay" }, 12036285Sbrian { ARPHRD_STRIP, "Strip" }, 12136285Sbrian { ARPHRD_IEEE1394, "IEEE 1394" }, 12236285Sbrian { ARPHRD_ATM2225, "ATM" }, 12336285Sbrian { 0, NULL } 12436285Sbrian}; 12531143Sbrian 12631143Sbrian/* 12731143Sbrian * ATM Address Resolution Protocol. 12831143Sbrian * 1296059Samurai * See RFC 2225 for protocol description. ATMARP packets are similar 1306059Samurai * to ARP packets, except that there are no length fields for the 13128679Sbrian * protocol address - instead, there are type/length fields for 1326059Samurai * the ATM number and subaddress - and the hardware addresses consist 1336059Samurai * of an ATM number and an ATM subaddress. 1346059Samurai */ 13528679Sbrianstruct atmarp_pkthdr { 13628679Sbrian u_short aar_hrd; /* format of hardware address */ 13728679Sbrian u_short aar_pro; /* format of protocol address */ 13836285Sbrian u_char aar_shtl; /* length of source ATM number */ 13936285Sbrian u_char aar_sstl; /* length of source ATM subaddress */ 14036285Sbrian#define ATMARP_IS_E164 0x40 /* bit in type/length for E.164 format */ 1416059Samurai#define ATMARP_LEN_MASK 0x3F /* length of {sub}address in type/length */ 1426059Samurai u_short aar_op; /* same as regular ARP */ 14336961Sbrian u_char aar_spln; /* length of source protocol address */ 14436961Sbrian u_char aar_thtl; /* length of target ATM number */ 14528679Sbrian u_char aar_tstl; /* length of target ATM subaddress */ 14628679Sbrian u_char aar_tpln; /* length of target protocol address */ 14728679Sbrian/* 14828679Sbrian * The remaining fields are variable in size, 14936285Sbrian * according to the sizes above. 15036285Sbrian */ 15136285Sbrian#ifdef COMMENT_ONLY 15236285Sbrian u_char aar_sha[]; /* source ATM number */ 1536059Samurai u_char aar_ssa[]; /* source ATM subaddress */ 1546059Samurai u_char aar_spa[]; /* sender protocol address */ 15528679Sbrian u_char aar_tha[]; /* target ATM number */ 15628679Sbrian u_char aar_tsa[]; /* target ATM subaddress */ 15728679Sbrian u_char aar_tpa[]; /* target protocol address */ 15828679Sbrian#endif 1596059Samurai 16036285Sbrian#define ATMHRD(ap) EXTRACT_16BITS(&(ap)->aar_hrd) 16136285Sbrian#define ATMSHRD_LEN(ap) ((ap)->aar_shtl & ATMARP_LEN_MASK) 16241044Sbrian#define ATMSSLN(ap) ((ap)->aar_sstl & ATMARP_LEN_MASK) 16341044Sbrian#define ATMSPROTO_LEN(ap) ((ap)->aar_spln) 16441044Sbrian#define ATMOP(ap) EXTRACT_16BITS(&(ap)->aar_op) 16541044Sbrian#define ATMPRO(ap) EXTRACT_16BITS(&(ap)->aar_pro) 16641044Sbrian#define ATMTHRD_LEN(ap) ((ap)->aar_thtl & ATMARP_LEN_MASK) 16741044Sbrian#define ATMTSLN(ap) ((ap)->aar_tstl & ATMARP_LEN_MASK) 16841044Sbrian#define ATMTPROTO_LEN(ap) ((ap)->aar_tpln) 16941044Sbrian#define aar_sha(ap) ((const u_char *)((ap)+1)) 1706059Samurai#define aar_ssa(ap) (aar_sha(ap) + ATMSHRD_LEN(ap)) 1716059Samurai#define aar_spa(ap) (aar_ssa(ap) + ATMSSLN(ap)) 17236285Sbrian#define aar_tha(ap) (aar_spa(ap) + ATMSPROTO_LEN(ap)) 1736059Samurai#define aar_tsa(ap) (aar_tha(ap) + ATMTHRD_LEN(ap)) 17436285Sbrian#define aar_tpa(ap) (aar_tsa(ap) + ATMTSLN(ap)) 17536285Sbrian}; 17636285Sbrian 17736285Sbrian#define ATMSHA(ap) (aar_sha(ap)) 17836285Sbrian#define ATMSSA(ap) (aar_ssa(ap)) 17936285Sbrian#define ATMSPA(ap) (aar_spa(ap)) 18036285Sbrian#define ATMTHA(ap) (aar_tha(ap)) 18136285Sbrian#define ATMTSA(ap) (aar_tsa(ap)) 18236285Sbrian#define ATMTPA(ap) (aar_tpa(ap)) 18336285Sbrian 1846059Samuraistatic u_char ezero[6]; 1856059Samurai 18636285Sbrianstatic void 18736285Sbrianatmarp_addr_print(netdissect_options *ndo, 18836285Sbrian const u_char *ha, u_int ha_len, const u_char *srca, 18936285Sbrian u_int srca_len) 19036285Sbrian{ 19136285Sbrian if (ha_len == 0) 19236285Sbrian ND_PRINT((ndo, "<No address>")); 19336285Sbrian else { 19436285Sbrian ND_PRINT((ndo, "%s", linkaddr_string(ha, LINKADDR_ATM, ha_len))); 19536285Sbrian if (srca_len != 0) 19636285Sbrian ND_PRINT((ndo, ",%s", 19736285Sbrian linkaddr_string(srca, LINKADDR_ATM, srca_len))); 19836285Sbrian } 19926516Sbrian} 20036285Sbrian 20136285Sbrianstatic void 20236285Sbrianatmarp_print(netdissect_options *ndo, 20336285Sbrian const u_char *bp, u_int length, u_int caplen) 20436285Sbrian{ 20536285Sbrian const struct atmarp_pkthdr *ap; 2066059Samurai u_short pro, hrd, op; 2076059Samurai 20836285Sbrian ap = (const struct atmarp_pkthdr *)bp; 2096059Samurai ND_TCHECK(*ap); 21036285Sbrian 21136285Sbrian hrd = ATMHRD(ap); 21236285Sbrian pro = ATMPRO(ap); 21336285Sbrian op = ATMOP(ap); 21428679Sbrian 2156059Samurai if (!ND_TTEST2(*aar_tpa(ap), ATMTPROTO_LEN(ap))) { 2166059Samurai ND_PRINT((ndo, "[|ARP]")); 2176059Samurai ND_DEFAULTPRINT((const u_char *)ap, length); 2186059Samurai return; 21936285Sbrian } 22036285Sbrian 22128679Sbrian if (!ndo->ndo_eflag) { 2226059Samurai ND_PRINT((ndo, "ARP, ")); 22336285Sbrian } 22436285Sbrian 2256059Samurai if ((pro != ETHERTYPE_IP && pro != ETHERTYPE_TRAIL) || 2266059Samurai ATMSPROTO_LEN(ap) != 4 || 2276059Samurai ATMTPROTO_LEN(ap) != 4 || 22828679Sbrian ndo->ndo_vflag) { 2296059Samurai ND_PRINT((ndo, "%s, %s (len %u/%u)", 23028679Sbrian tok2str(arphrd_values, "Unknown Hardware (%u)", hrd), 2316059Samurai tok2str(ethertype_values, "Unknown Protocol (0x%04x)", pro), 2326059Samurai ATMSPROTO_LEN(ap), 23336285Sbrian ATMTPROTO_LEN(ap))); 2346059Samurai 23528679Sbrian /* don't know know about the address formats */ 2366059Samurai if (!ndo->ndo_vflag) { 2376059Samurai goto out; 2386059Samurai } 2396059Samurai } 24036285Sbrian 24130715Sbrian /* print operation */ 24236285Sbrian printf("%s%s ", 24336285Sbrian ndo->ndo_vflag ? ", " : "", 2446059Samurai tok2str(arpop_values, "Unknown (%u)", op)); 24536285Sbrian 2466059Samurai switch (op) { 2476059Samurai 2486059Samurai case ARPOP_REQUEST: 2496059Samurai ND_PRINT((ndo, "who-has %s", ipaddr_string(ATMTPA(ap)))); 2506059Samurai if (ATMTHRD_LEN(ap) != 0) { 2516059Samurai ND_PRINT((ndo, " (")); 25236285Sbrian atmarp_addr_print(ndo, ATMTHA(ap), ATMTHRD_LEN(ap), 2536059Samurai ATMTSA(ap), ATMTSLN(ap)); 2546059Samurai ND_PRINT((ndo, ")")); 2556059Samurai } 2566059Samurai ND_PRINT((ndo, "tell %s", ipaddr_string(ATMSPA(ap)))); 2576059Samurai break; 2586059Samurai 2596059Samurai case ARPOP_REPLY: 2606059Samurai ND_PRINT((ndo, "%s is-at ", ipaddr_string(ATMSPA(ap)))); 26126692Sbrian atmarp_addr_print(ndo, ATMSHA(ap), ATMSHRD_LEN(ap), ATMSSA(ap), 26237010Sbrian ATMSSLN(ap)); 2636059Samurai break; 26436285Sbrian 26526692Sbrian case ARPOP_INVREQUEST: 2666059Samurai ND_PRINT((ndo, "who-is ")); 26728679Sbrian atmarp_addr_print(ndo, ATMTHA(ap), ATMTHRD_LEN(ap), ATMTSA(ap), 2688857Srgrimes ATMTSLN(ap)); 26926692Sbrian ND_PRINT((ndo, " tell ")); 27036285Sbrian atmarp_addr_print(ndo, ATMSHA(ap), ATMSHRD_LEN(ap), ATMSSA(ap), 27128679Sbrian ATMSSLN(ap)); 27226692Sbrian break; 2736059Samurai 2746059Samurai case ARPOP_INVREPLY: 2756059Samurai atmarp_addr_print(ndo, ATMSHA(ap), ATMSHRD_LEN(ap), ATMSSA(ap), 2766059Samurai ATMSSLN(ap)); 27726692Sbrian ND_PRINT((ndo, "at %s", ipaddr_string(ATMSPA(ap)))); 27828679Sbrian break; 27928679Sbrian 28028679Sbrian case ARPOP_NAK: 28128679Sbrian ND_PRINT((ndo, "for %s", ipaddr_string(ATMSPA(ap)))); 28228679Sbrian break; 28328679Sbrian 28428679Sbrian default: 2856059Samurai ND_DEFAULTPRINT((const u_char *)ap, caplen); 2866059Samurai return; 2876059Samurai } 28826692Sbrian 28928679Sbrian out: 29028679Sbrian ND_PRINT((ndo, ", length %u", length)); 29128679Sbrian return; 29228679Sbrian 29328679Sbriantrunc: 29428679Sbrian ND_PRINT((ndo, "[|ARP]")); 29528679Sbrian} 2966059Samurai 2976059Samuraivoid 29836961Sbrianarp_print(netdissect_options *ndo, 29936961Sbrian const u_char *bp, u_int length, u_int caplen) 30036961Sbrian{ 30136961Sbrian const struct arp_pkthdr *ap; 30236961Sbrian u_short pro, hrd, op, linkaddr; 30336961Sbrian 30436961Sbrian ap = (const struct arp_pkthdr *)bp; 30536961Sbrian ND_TCHECK(*ap); 30636961Sbrian 30736961Sbrian hrd = HRD(ap); 30836961Sbrian pro = PRO(ap); 30936961Sbrian op = OP(ap); 31036961Sbrian 31136961Sbrian 31236961Sbrian /* if its ATM then call the ATM ARP printer 31336961Sbrian for Frame-relay ARP most of the fields 31436961Sbrian are similar to Ethernet so overload the Ethernet Printer 31536961Sbrian and set the linkaddr type for linkaddr_string() accordingly */ 31636961Sbrian 31736961Sbrian switch(hrd) { 31836961Sbrian case ARPHRD_ATM2225: 31936961Sbrian atmarp_print(ndo, bp, length, caplen); 3206059Samurai return; 32128679Sbrian case ARPHRD_FRELAY: 3226059Samurai linkaddr = LINKADDR_FRELAY; 3236059Samurai break; 32413733Sdfr default: 3256059Samurai linkaddr = LINKADDR_ETHER; 32628679Sbrian break; 3276059Samurai } 32826692Sbrian 3296059Samurai if (!ND_TTEST2(*ar_tpa(ap), PROTO_LEN(ap))) { 33028679Sbrian ND_PRINT((ndo, "[|ARP]")); 33128679Sbrian ND_DEFAULTPRINT((const u_char *)ap, length); 33228679Sbrian return; 33328679Sbrian } 33428679Sbrian 33528679Sbrian if (!ndo->ndo_eflag) { 3366059Samurai ND_PRINT((ndo, "ARP, ")); 3376059Samurai } 33826692Sbrian 33928679Sbrian /* print hardware type/len and proto type/len */ 34028679Sbrian if ((pro != ETHERTYPE_IP && pro != ETHERTYPE_TRAIL) || 34128679Sbrian PROTO_LEN(ap) != 4 || 3426059Samurai HRD_LEN(ap) == 0 || 3436059Samurai ndo->ndo_vflag) { 34428679Sbrian ND_PRINT((ndo, "%s (len %u), %s (len %u)", 34537210Sbrian tok2str(arphrd_values, "Unknown Hardware (%u)", hrd), 34637210Sbrian HRD_LEN(ap), 34728679Sbrian tok2str(ethertype_values, "Unknown Protocol (0x%04x)", pro), 3486059Samurai PROTO_LEN(ap))); 34928679Sbrian 3506059Samurai /* don't know know about the address formats */ 3516059Samurai if (!ndo->ndo_vflag) { 35228679Sbrian goto out; 35326692Sbrian } 35428679Sbrian } 35528679Sbrian 35628679Sbrian /* print operation */ 35728679Sbrian printf("%s%s ", 3586059Samurai ndo->ndo_vflag ? ", " : "", 3596059Samurai tok2str(arpop_values, "Unknown (%u)", op)); 3606059Samurai 3616059Samurai switch (op) { 36226692Sbrian 36336285Sbrian case ARPOP_REQUEST: 36431142Sbrian ND_PRINT((ndo, "who-has %s", ipaddr_string(TPA(ap)))); 36536285Sbrian if (memcmp((const char *)ezero, (const char *)THA(ap), HRD_LEN(ap)) != 0) 36636285Sbrian ND_PRINT((ndo, " (%s)", 36728679Sbrian linkaddr_string(THA(ap), linkaddr, HRD_LEN(ap)))); 36828679Sbrian ND_PRINT((ndo, " tell %s", ipaddr_string(SPA(ap)))); 36936285Sbrian break; 37028679Sbrian 3716059Samurai case ARPOP_REPLY: 37236285Sbrian ND_PRINT((ndo, "%s is-at %s", 37336285Sbrian ipaddr_string(SPA(ap)), 37436285Sbrian linkaddr_string(SHA(ap), linkaddr, HRD_LEN(ap)))); 37536285Sbrian break; 37636285Sbrian 37736285Sbrian case ARPOP_REVREQUEST: 3786735Samurai ND_PRINT((ndo, "who-is %s tell %s", 37928679Sbrian linkaddr_string(THA(ap), linkaddr, HRD_LEN(ap)), 3806059Samurai linkaddr_string(SHA(ap), linkaddr, HRD_LEN(ap)))); 3816059Samurai break; 3826059Samurai 38346686Sbrian case ARPOP_REVREPLY: 38446686Sbrian ND_PRINT((ndo, "%s at %s", 38536285Sbrian linkaddr_string(THA(ap), linkaddr, HRD_LEN(ap)), 3866059Samurai ipaddr_string(TPA(ap)))); 38731343Sbrian break; 38846686Sbrian 3896059Samurai case ARPOP_INVREQUEST: 39046686Sbrian ND_PRINT((ndo, "who-is %s tell %s", 39146686Sbrian linkaddr_string(THA(ap), linkaddr, HRD_LEN(ap)), 39246686Sbrian linkaddr_string(SHA(ap), linkaddr, HRD_LEN(ap)))); 39346686Sbrian break; 3946059Samurai 3956059Samurai case ARPOP_INVREPLY: 39646686Sbrian ND_PRINT((ndo,"%s at %s", 39746686Sbrian linkaddr_string(THA(ap), linkaddr, HRD_LEN(ap)), 39846686Sbrian ipaddr_string(TPA(ap)))); 39926031Sbrian break; 40046686Sbrian 40146686Sbrian default: 40226031Sbrian ND_DEFAULTPRINT((const u_char *)ap, caplen); 40346686Sbrian return; 40446686Sbrian } 40546686Sbrian 40626031Sbrian out: 40746686Sbrian ND_PRINT((ndo, ", length %u", length)); 40836285Sbrian 40946686Sbrian return; 41046686Sbriantrunc: 41146686Sbrian ND_PRINT((ndo, "[|ARP]")); 41246686Sbrian} 41346686Sbrian 41446686Sbrian/* 41546686Sbrian * Local Variables: 41646686Sbrian * c-style: bsd 41736285Sbrian * End: 41846686Sbrian */ 4196059Samurai 4206059Samurai