14edb46e9SPaul Traina /* 2699fc314SBill Fenner * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997 34edb46e9SPaul Traina * The Regents of the University of California. All rights reserved. 44edb46e9SPaul Traina * 54edb46e9SPaul Traina * Redistribution and use in source and binary forms, with or without 64edb46e9SPaul Traina * modification, are permitted provided that: (1) source code distributions 74edb46e9SPaul Traina * retain the above copyright notice and this paragraph in its entirety, (2) 84edb46e9SPaul Traina * distributions including binary code include the above copyright notice and 94edb46e9SPaul Traina * this paragraph in its entirety in the documentation or other materials 104edb46e9SPaul Traina * provided with the distribution, and (3) all advertising materials mentioning 114edb46e9SPaul Traina * features or use of this software display the following acknowledgement: 124edb46e9SPaul Traina * ``This product includes software developed by the University of California, 134edb46e9SPaul Traina * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of 144edb46e9SPaul Traina * the University nor the names of its contributors may be used to endorse 154edb46e9SPaul Traina * or promote products derived from this software without specific prior 164edb46e9SPaul Traina * written permission. 174edb46e9SPaul Traina * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED 184edb46e9SPaul Traina * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF 194edb46e9SPaul Traina * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 20a88113a8SBill Fenner * 21a88113a8SBill Fenner * $FreeBSD$ 224edb46e9SPaul Traina */ 234edb46e9SPaul Traina 244edb46e9SPaul Traina #ifndef lint 252ebf6c05SBill Fenner static const char rcsid[] = 26a1c2090eSBill Fenner "@(#) $Header: /tcpdump/master/tcpdump/print-arp.c,v 1.51 2001/09/17 21:57:54 fenner Exp $ (LBL)"; 27a88113a8SBill Fenner #endif 28a88113a8SBill Fenner 29a88113a8SBill Fenner #ifdef HAVE_CONFIG_H 30a88113a8SBill Fenner #include "config.h" 314edb46e9SPaul Traina #endif 324edb46e9SPaul Traina 334edb46e9SPaul Traina #include <sys/param.h> 344edb46e9SPaul Traina #include <sys/time.h> 354edb46e9SPaul Traina 364edb46e9SPaul Traina #include <netinet/in.h> 374edb46e9SPaul Traina 384edb46e9SPaul Traina #include <stdio.h> 394edb46e9SPaul Traina #include <string.h> 404edb46e9SPaul Traina 414edb46e9SPaul Traina #include "interface.h" 424edb46e9SPaul Traina #include "addrtoname.h" 43943ee2b1SBill Fenner #include "ether.h" 444edb46e9SPaul Traina #include "ethertype.h" 454edb46e9SPaul Traina #include "extract.h" /* must come after interface.h */ 464edb46e9SPaul Traina 47943ee2b1SBill Fenner /* 48943ee2b1SBill Fenner * Address Resolution Protocol. 49943ee2b1SBill Fenner * 50943ee2b1SBill Fenner * See RFC 826 for protocol description. ARP packets are variable 51943ee2b1SBill Fenner * in size; the arphdr structure defines the fixed-length portion. 52943ee2b1SBill Fenner * Protocol type values are the same as those for 10 Mb/s Ethernet. 53943ee2b1SBill Fenner * It is followed by the variable-sized fields ar_sha, arp_spa, 54943ee2b1SBill Fenner * arp_tha and arp_tpa in that order, according to the lengths 55943ee2b1SBill Fenner * specified. Field names used correspond to RFC 826. 56943ee2b1SBill Fenner */ 57943ee2b1SBill Fenner struct arphdr { 58943ee2b1SBill Fenner u_short ar_hrd; /* format of hardware address */ 59943ee2b1SBill Fenner #define ARPHRD_ETHER 1 /* ethernet hardware format */ 60943ee2b1SBill Fenner #define ARPHRD_IEEE802 6 /* token-ring hardware format */ 61a1c2090eSBill Fenner #define ARPHRD_ARCNET 7 /* arcnet hardware format */ 62943ee2b1SBill Fenner #define ARPHRD_FRELAY 15 /* frame relay hardware format */ 63a1c2090eSBill Fenner #define ARPHRD_STRIP 23 /* Ricochet Starmode Radio hardware format */ 64a1c2090eSBill Fenner #define ARPHRD_IEEE1394 24 /* IEEE 1394 (FireWire) hardware format */ 65943ee2b1SBill Fenner u_short ar_pro; /* format of protocol address */ 66943ee2b1SBill Fenner u_char ar_hln; /* length of hardware address */ 67943ee2b1SBill Fenner u_char ar_pln; /* length of protocol address */ 68943ee2b1SBill Fenner u_short ar_op; /* one of: */ 69943ee2b1SBill Fenner #define ARPOP_REQUEST 1 /* request to resolve address */ 70943ee2b1SBill Fenner #define ARPOP_REPLY 2 /* response to previous request */ 71943ee2b1SBill Fenner #define ARPOP_REVREQUEST 3 /* request protocol address given hardware */ 72943ee2b1SBill Fenner #define ARPOP_REVREPLY 4 /* response giving protocol address */ 73943ee2b1SBill Fenner #define ARPOP_INVREQUEST 8 /* request to identify peer */ 74943ee2b1SBill Fenner #define ARPOP_INVREPLY 9 /* response identifying peer */ 75943ee2b1SBill Fenner /* 76943ee2b1SBill Fenner * The remaining fields are variable in size, 77943ee2b1SBill Fenner * according to the sizes above. 78943ee2b1SBill Fenner */ 79943ee2b1SBill Fenner #ifdef COMMENT_ONLY 80943ee2b1SBill Fenner u_char ar_sha[]; /* sender hardware address */ 81943ee2b1SBill Fenner u_char ar_spa[]; /* sender protocol address */ 82943ee2b1SBill Fenner u_char ar_tha[]; /* target hardware address */ 83943ee2b1SBill Fenner u_char ar_tpa[]; /* target protocol address */ 84943ee2b1SBill Fenner #endif 85a1c2090eSBill Fenner #define ar_sha(ap) (((const caddr_t)((ap)+1))+0) 86a1c2090eSBill Fenner #define ar_spa(ap) (((const caddr_t)((ap)+1))+ (ap)->ar_hln) 87a1c2090eSBill Fenner #define ar_tha(ap) (((const caddr_t)((ap)+1))+ (ap)->ar_hln+(ap)->ar_pln) 88a1c2090eSBill Fenner #define ar_tpa(ap) (((const caddr_t)((ap)+1))+2*(ap)->ar_hln+(ap)->ar_pln) 89943ee2b1SBill Fenner }; 90943ee2b1SBill Fenner 91943ee2b1SBill Fenner #define ARP_HDRLEN 8 92943ee2b1SBill Fenner 93a1c2090eSBill Fenner #define HRD(ap) ((ap)->ar_hrd) 94a1c2090eSBill Fenner #define HLN(ap) ((ap)->ar_hln) 95a1c2090eSBill Fenner #define PLN(ap) ((ap)->ar_pln) 96a1c2090eSBill Fenner #define OP(ap) ((ap)->ar_op) 97a1c2090eSBill Fenner #define PRO(ap) ((ap)->ar_pro) 98a1c2090eSBill Fenner #define SHA(ap) (ar_sha(ap)) 99a1c2090eSBill Fenner #define SPA(ap) (ar_spa(ap)) 100a1c2090eSBill Fenner #define THA(ap) (ar_tha(ap)) 101a1c2090eSBill Fenner #define TPA(ap) (ar_tpa(ap)) 1024edb46e9SPaul Traina 1034edb46e9SPaul Traina static u_char ezero[6]; 1044edb46e9SPaul Traina 1054edb46e9SPaul Traina void 106a1c2090eSBill Fenner arp_print(const u_char *bp, u_int length, u_int caplen) 1074edb46e9SPaul Traina { 108a1c2090eSBill Fenner const struct arphdr *ap; 109a1c2090eSBill Fenner u_short pro, hrd, op; 1104edb46e9SPaul Traina 111a1c2090eSBill Fenner ap = (const struct arphdr *)bp; 112a1c2090eSBill Fenner TCHECK(*ap); 113a1c2090eSBill Fenner if ((const u_char *)(ar_tpa(ap) + PLN(ap)) > snapend) { 1144edb46e9SPaul Traina (void)printf("truncated-arp"); 115a1c2090eSBill Fenner default_print((const u_char *)ap, length); 1164edb46e9SPaul Traina return; 1174edb46e9SPaul Traina } 1184edb46e9SPaul Traina 119a1c2090eSBill Fenner pro = EXTRACT_16BITS(&PRO(ap)); 120a1c2090eSBill Fenner hrd = EXTRACT_16BITS(&HRD(ap)); 121a1c2090eSBill Fenner op = EXTRACT_16BITS(&OP(ap)); 1224edb46e9SPaul Traina 123a1c2090eSBill Fenner if (pro != ETHERTYPE_IP && pro != ETHERTYPE_TRAIL) { 1244edb46e9SPaul Traina (void)printf("arp-#%d for proto #%d (%d) hardware #%d (%d)", 125a1c2090eSBill Fenner op, pro, PLN(ap), hrd, HLN(ap)); 1264edb46e9SPaul Traina return; 1274edb46e9SPaul Traina } 1284edb46e9SPaul Traina if (pro == ETHERTYPE_TRAIL) 1294edb46e9SPaul Traina (void)printf("trailer-"); 1304edb46e9SPaul Traina switch (op) { 1314edb46e9SPaul Traina 1324edb46e9SPaul Traina case ARPOP_REQUEST: 1334edb46e9SPaul Traina (void)printf("arp who-has %s", ipaddr_string(TPA(ap))); 134a1c2090eSBill Fenner if (memcmp((const char *)ezero, (const char *)THA(ap), HLN(ap)) != 0) 135a1c2090eSBill Fenner (void)printf(" (%s)", 136a1c2090eSBill Fenner linkaddr_string(THA(ap), HLN(ap))); 1374edb46e9SPaul Traina (void)printf(" tell %s", ipaddr_string(SPA(ap))); 1384edb46e9SPaul Traina break; 1394edb46e9SPaul Traina 1404edb46e9SPaul Traina case ARPOP_REPLY: 1414edb46e9SPaul Traina (void)printf("arp reply %s", ipaddr_string(SPA(ap))); 142a1c2090eSBill Fenner (void)printf(" is-at %s", linkaddr_string(SHA(ap), HLN(ap))); 1434edb46e9SPaul Traina break; 1444edb46e9SPaul Traina 145a1c2090eSBill Fenner case ARPOP_REVREQUEST: 1464edb46e9SPaul Traina (void)printf("rarp who-is %s tell %s", 147a1c2090eSBill Fenner linkaddr_string(THA(ap), HLN(ap)), 148a1c2090eSBill Fenner linkaddr_string(SHA(ap), HLN(ap))); 1494edb46e9SPaul Traina break; 1504edb46e9SPaul Traina 151a1c2090eSBill Fenner case ARPOP_REVREPLY: 1524edb46e9SPaul Traina (void)printf("rarp reply %s at %s", 153a1c2090eSBill Fenner linkaddr_string(THA(ap), HLN(ap)), 1544edb46e9SPaul Traina ipaddr_string(TPA(ap))); 1554edb46e9SPaul Traina break; 1564edb46e9SPaul Traina 1574edb46e9SPaul Traina default: 1584edb46e9SPaul Traina (void)printf("arp-#%d", op); 159a1c2090eSBill Fenner default_print((const u_char *)ap, caplen); 1604edb46e9SPaul Traina return; 1614edb46e9SPaul Traina } 1624edb46e9SPaul Traina if (hrd != ARPHRD_ETHER) 1632ebf6c05SBill Fenner printf(" hardware #%d", hrd); 164a1c2090eSBill Fenner return; 165a1c2090eSBill Fenner trunc: 166a1c2090eSBill Fenner (void)printf("[|arp]"); 1674edb46e9SPaul Traina } 168