print-arp.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480
  1. /*
  2. * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997
  3. * The Regents of the University of California. All rights reserved.
  4. *
  5. * Redistribution and use in source and binary forms, with or without
  6. * modification, are permitted provided that: (1) source code distributions
  7. * retain the above copyright notice and this paragraph in its entirety, (2)
  8. * distributions including binary code include the above copyright notice and
  9. * this paragraph in its entirety in the documentation or other materials
  10. * provided with the distribution, and (3) all advertising materials mentioning
  11. * features or use of this software display the following acknowledgement:
  12. * ``This product includes software developed by the University of California,
  13. * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
  14. * the University nor the names of its contributors may be used to endorse
  15. * or promote products derived from this software without specific prior
  16. * written permission.
  17. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
  18. * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
  19. * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  20. */
  21. /* \summary: Address Resolution Protocol (ARP) printer */
  22. #ifdef HAVE_CONFIG_H
  23. #include "config.h"
  24. #endif
  25. #include <netdissect-stdinc.h>
  26. #include <string.h>
  27. #include "netdissect.h"
  28. #include "addrtoname.h"
  29. #include "ether.h"
  30. #include "ethertype.h"
  31. #include "extract.h"
  32. static const char tstr[] = "[|ARP]";
  33. /*
  34. * Address Resolution Protocol.
  35. *
  36. * See RFC 826 for protocol description. ARP packets are variable
  37. * in size; the arphdr structure defines the fixed-length portion.
  38. * Protocol type values are the same as those for 10 Mb/s Ethernet.
  39. * It is followed by the variable-sized fields ar_sha, arp_spa,
  40. * arp_tha and arp_tpa in that order, according to the lengths
  41. * specified. Field names used correspond to RFC 826.
  42. */
  43. struct arp_pkthdr {
  44. u_short ar_hrd; /* format of hardware address */
  45. #define ARPHRD_ETHER 1 /* ethernet hardware format */
  46. #define ARPHRD_IEEE802 6 /* token-ring hardware format */
  47. #define ARPHRD_ARCNET 7 /* arcnet hardware format */
  48. #define ARPHRD_FRELAY 15 /* frame relay hardware format */
  49. #define ARPHRD_ATM2225 19 /* ATM (RFC 2225) */
  50. #define ARPHRD_STRIP 23 /* Ricochet Starmode Radio hardware format */
  51. #define ARPHRD_IEEE1394 24 /* IEEE 1394 (FireWire) hardware format */
  52. u_short ar_pro; /* format of protocol address */
  53. u_char ar_hln; /* length of hardware address */
  54. u_char ar_pln; /* length of protocol address */
  55. u_short ar_op; /* one of: */
  56. #define ARPOP_REQUEST 1 /* request to resolve address */
  57. #define ARPOP_REPLY 2 /* response to previous request */
  58. #define ARPOP_REVREQUEST 3 /* request protocol address given hardware */
  59. #define ARPOP_REVREPLY 4 /* response giving protocol address */
  60. #define ARPOP_INVREQUEST 8 /* request to identify peer */
  61. #define ARPOP_INVREPLY 9 /* response identifying peer */
  62. #define ARPOP_NAK 10 /* NAK - only valif for ATM ARP */
  63. /*
  64. * The remaining fields are variable in size,
  65. * according to the sizes above.
  66. */
  67. #ifdef COMMENT_ONLY
  68. u_char ar_sha[]; /* sender hardware address */
  69. u_char ar_spa[]; /* sender protocol address */
  70. u_char ar_tha[]; /* target hardware address */
  71. u_char ar_tpa[]; /* target protocol address */
  72. #endif
  73. #define ar_sha(ap) (((const u_char *)((ap)+1))+ 0)
  74. #define ar_spa(ap) (((const u_char *)((ap)+1))+ (ap)->ar_hln)
  75. #define ar_tha(ap) (((const u_char *)((ap)+1))+ (ap)->ar_hln+(ap)->ar_pln)
  76. #define ar_tpa(ap) (((const u_char *)((ap)+1))+2*(ap)->ar_hln+(ap)->ar_pln)
  77. };
  78. #define ARP_HDRLEN 8
  79. #define HRD(ap) EXTRACT_16BITS(&(ap)->ar_hrd)
  80. #define HRD_LEN(ap) ((ap)->ar_hln)
  81. #define PROTO_LEN(ap) ((ap)->ar_pln)
  82. #define OP(ap) EXTRACT_16BITS(&(ap)->ar_op)
  83. #define PRO(ap) EXTRACT_16BITS(&(ap)->ar_pro)
  84. #define SHA(ap) (ar_sha(ap))
  85. #define SPA(ap) (ar_spa(ap))
  86. #define THA(ap) (ar_tha(ap))
  87. #define TPA(ap) (ar_tpa(ap))
  88. static const struct tok arpop_values[] = {
  89. { ARPOP_REQUEST, "Request" },
  90. { ARPOP_REPLY, "Reply" },
  91. { ARPOP_REVREQUEST, "Reverse Request" },
  92. { ARPOP_REVREPLY, "Reverse Reply" },
  93. { ARPOP_INVREQUEST, "Inverse Request" },
  94. { ARPOP_INVREPLY, "Inverse Reply" },
  95. { ARPOP_NAK, "NACK Reply" },
  96. { 0, NULL }
  97. };
  98. static const struct tok arphrd_values[] = {
  99. { ARPHRD_ETHER, "Ethernet" },
  100. { ARPHRD_IEEE802, "TokenRing" },
  101. { ARPHRD_ARCNET, "ArcNet" },
  102. { ARPHRD_FRELAY, "FrameRelay" },
  103. { ARPHRD_STRIP, "Strip" },
  104. { ARPHRD_IEEE1394, "IEEE 1394" },
  105. { ARPHRD_ATM2225, "ATM" },
  106. { 0, NULL }
  107. };
  108. /*
  109. * ATM Address Resolution Protocol.
  110. *
  111. * See RFC 2225 for protocol description. ATMARP packets are similar
  112. * to ARP packets, except that there are no length fields for the
  113. * protocol address - instead, there are type/length fields for
  114. * the ATM number and subaddress - and the hardware addresses consist
  115. * of an ATM number and an ATM subaddress.
  116. */
  117. struct atmarp_pkthdr {
  118. u_short aar_hrd; /* format of hardware address */
  119. u_short aar_pro; /* format of protocol address */
  120. u_char aar_shtl; /* length of source ATM number */
  121. u_char aar_sstl; /* length of source ATM subaddress */
  122. #define ATMARP_IS_E164 0x40 /* bit in type/length for E.164 format */
  123. #define ATMARP_LEN_MASK 0x3F /* length of {sub}address in type/length */
  124. u_short aar_op; /* same as regular ARP */
  125. u_char aar_spln; /* length of source protocol address */
  126. u_char aar_thtl; /* length of target ATM number */
  127. u_char aar_tstl; /* length of target ATM subaddress */
  128. u_char aar_tpln; /* length of target protocol address */
  129. /*
  130. * The remaining fields are variable in size,
  131. * according to the sizes above.
  132. */
  133. #ifdef COMMENT_ONLY
  134. u_char aar_sha[]; /* source ATM number */
  135. u_char aar_ssa[]; /* source ATM subaddress */
  136. u_char aar_spa[]; /* sender protocol address */
  137. u_char aar_tha[]; /* target ATM number */
  138. u_char aar_tsa[]; /* target ATM subaddress */
  139. u_char aar_tpa[]; /* target protocol address */
  140. #endif
  141. #define ATMHRD(ap) EXTRACT_16BITS(&(ap)->aar_hrd)
  142. #define ATMSHRD_LEN(ap) ((ap)->aar_shtl & ATMARP_LEN_MASK)
  143. #define ATMSSLN(ap) ((ap)->aar_sstl & ATMARP_LEN_MASK)
  144. #define ATMSPROTO_LEN(ap) ((ap)->aar_spln)
  145. #define ATMOP(ap) EXTRACT_16BITS(&(ap)->aar_op)
  146. #define ATMPRO(ap) EXTRACT_16BITS(&(ap)->aar_pro)
  147. #define ATMTHRD_LEN(ap) ((ap)->aar_thtl & ATMARP_LEN_MASK)
  148. #define ATMTSLN(ap) ((ap)->aar_tstl & ATMARP_LEN_MASK)
  149. #define ATMTPROTO_LEN(ap) ((ap)->aar_tpln)
  150. #define aar_sha(ap) ((const u_char *)((ap)+1))
  151. #define aar_ssa(ap) (aar_sha(ap) + ATMSHRD_LEN(ap))
  152. #define aar_spa(ap) (aar_ssa(ap) + ATMSSLN(ap))
  153. #define aar_tha(ap) (aar_spa(ap) + ATMSPROTO_LEN(ap))
  154. #define aar_tsa(ap) (aar_tha(ap) + ATMTHRD_LEN(ap))
  155. #define aar_tpa(ap) (aar_tsa(ap) + ATMTSLN(ap))
  156. };
  157. #define ATMSHA(ap) (aar_sha(ap))
  158. #define ATMSSA(ap) (aar_ssa(ap))
  159. #define ATMSPA(ap) (aar_spa(ap))
  160. #define ATMTHA(ap) (aar_tha(ap))
  161. #define ATMTSA(ap) (aar_tsa(ap))
  162. #define ATMTPA(ap) (aar_tpa(ap))
  163. static int
  164. isnonzero(const u_char *a, size_t len)
  165. {
  166. while (len > 0) {
  167. if (*a != 0)
  168. return (1);
  169. a++;
  170. len--;
  171. }
  172. return (0);
  173. }
  174. static void
  175. tpaddr_print_ip(netdissect_options *ndo,
  176. const struct arp_pkthdr *ap, u_short pro)
  177. {
  178. if (pro != ETHERTYPE_IP && pro != ETHERTYPE_TRAIL)
  179. ND_PRINT((ndo, "<wrong proto type>"));
  180. else if (PROTO_LEN(ap) != 4)
  181. ND_PRINT((ndo, "<wrong len>"));
  182. else
  183. ND_PRINT((ndo, "%s", ipaddr_string(ndo, TPA(ap))));
  184. }
  185. static void
  186. spaddr_print_ip(netdissect_options *ndo,
  187. const struct arp_pkthdr *ap, u_short pro)
  188. {
  189. if (pro != ETHERTYPE_IP && pro != ETHERTYPE_TRAIL)
  190. ND_PRINT((ndo, "<wrong proto type>"));
  191. else if (PROTO_LEN(ap) != 4)
  192. ND_PRINT((ndo, "<wrong len>"));
  193. else
  194. ND_PRINT((ndo, "%s", ipaddr_string(ndo, SPA(ap))));
  195. }
  196. static void
  197. atmarp_addr_print(netdissect_options *ndo,
  198. const u_char *ha, u_int ha_len, const u_char *srca,
  199. u_int srca_len)
  200. {
  201. if (ha_len == 0)
  202. ND_PRINT((ndo, "<No address>"));
  203. else {
  204. ND_PRINT((ndo, "%s", linkaddr_string(ndo, ha, LINKADDR_ATM, ha_len)));
  205. if (srca_len != 0)
  206. ND_PRINT((ndo, ",%s",
  207. linkaddr_string(ndo, srca, LINKADDR_ATM, srca_len)));
  208. }
  209. }
  210. static void
  211. atmarp_tpaddr_print(netdissect_options *ndo,
  212. const struct atmarp_pkthdr *ap, u_short pro)
  213. {
  214. if (pro != ETHERTYPE_IP && pro != ETHERTYPE_TRAIL)
  215. ND_PRINT((ndo, "<wrong proto type>"));
  216. else if (ATMTPROTO_LEN(ap) != 4)
  217. ND_PRINT((ndo, "<wrong tplen>"));
  218. else
  219. ND_PRINT((ndo, "%s", ipaddr_string(ndo, ATMTPA(ap))));
  220. }
  221. static void
  222. atmarp_spaddr_print(netdissect_options *ndo,
  223. const struct atmarp_pkthdr *ap, u_short pro)
  224. {
  225. if (pro != ETHERTYPE_IP && pro != ETHERTYPE_TRAIL)
  226. ND_PRINT((ndo, "<wrong proto type>"));
  227. else if (ATMSPROTO_LEN(ap) != 4)
  228. ND_PRINT((ndo, "<wrong splen>"));
  229. else
  230. ND_PRINT((ndo, "%s", ipaddr_string(ndo, ATMSPA(ap))));
  231. }
  232. static void
  233. atmarp_print(netdissect_options *ndo,
  234. const u_char *bp, u_int length, u_int caplen)
  235. {
  236. const struct atmarp_pkthdr *ap;
  237. u_short pro, hrd, op;
  238. ap = (const struct atmarp_pkthdr *)bp;
  239. ND_TCHECK(*ap);
  240. hrd = ATMHRD(ap);
  241. pro = ATMPRO(ap);
  242. op = ATMOP(ap);
  243. if (!ND_TTEST2(*aar_tpa(ap), ATMTPROTO_LEN(ap))) {
  244. ND_PRINT((ndo, "%s", tstr));
  245. ND_DEFAULTPRINT((const u_char *)ap, length);
  246. return;
  247. }
  248. if (!ndo->ndo_eflag) {
  249. ND_PRINT((ndo, "ARP, "));
  250. }
  251. if ((pro != ETHERTYPE_IP && pro != ETHERTYPE_TRAIL) ||
  252. ATMSPROTO_LEN(ap) != 4 ||
  253. ATMTPROTO_LEN(ap) != 4 ||
  254. ndo->ndo_vflag) {
  255. ND_PRINT((ndo, "%s, %s (len %u/%u)",
  256. tok2str(arphrd_values, "Unknown Hardware (%u)", hrd),
  257. tok2str(ethertype_values, "Unknown Protocol (0x%04x)", pro),
  258. ATMSPROTO_LEN(ap),
  259. ATMTPROTO_LEN(ap)));
  260. /* don't know know about the address formats */
  261. if (!ndo->ndo_vflag) {
  262. goto out;
  263. }
  264. }
  265. /* print operation */
  266. ND_PRINT((ndo, "%s%s ",
  267. ndo->ndo_vflag ? ", " : "",
  268. tok2str(arpop_values, "Unknown (%u)", op)));
  269. switch (op) {
  270. case ARPOP_REQUEST:
  271. ND_PRINT((ndo, "who-has "));
  272. atmarp_tpaddr_print(ndo, ap, pro);
  273. if (ATMTHRD_LEN(ap) != 0) {
  274. ND_PRINT((ndo, " ("));
  275. atmarp_addr_print(ndo, ATMTHA(ap), ATMTHRD_LEN(ap),
  276. ATMTSA(ap), ATMTSLN(ap));
  277. ND_PRINT((ndo, ")"));
  278. }
  279. ND_PRINT((ndo, " tell "));
  280. atmarp_spaddr_print(ndo, ap, pro);
  281. break;
  282. case ARPOP_REPLY:
  283. atmarp_spaddr_print(ndo, ap, pro);
  284. ND_PRINT((ndo, " is-at "));
  285. atmarp_addr_print(ndo, ATMSHA(ap), ATMSHRD_LEN(ap), ATMSSA(ap),
  286. ATMSSLN(ap));
  287. break;
  288. case ARPOP_INVREQUEST:
  289. ND_PRINT((ndo, "who-is "));
  290. atmarp_addr_print(ndo, ATMTHA(ap), ATMTHRD_LEN(ap), ATMTSA(ap),
  291. ATMTSLN(ap));
  292. ND_PRINT((ndo, " tell "));
  293. atmarp_addr_print(ndo, ATMSHA(ap), ATMSHRD_LEN(ap), ATMSSA(ap),
  294. ATMSSLN(ap));
  295. break;
  296. case ARPOP_INVREPLY:
  297. atmarp_addr_print(ndo, ATMSHA(ap), ATMSHRD_LEN(ap), ATMSSA(ap),
  298. ATMSSLN(ap));
  299. ND_PRINT((ndo, "at "));
  300. atmarp_spaddr_print(ndo, ap, pro);
  301. break;
  302. case ARPOP_NAK:
  303. ND_PRINT((ndo, "for "));
  304. atmarp_spaddr_print(ndo, ap, pro);
  305. break;
  306. default:
  307. ND_DEFAULTPRINT((const u_char *)ap, caplen);
  308. return;
  309. }
  310. out:
  311. ND_PRINT((ndo, ", length %u", length));
  312. return;
  313. trunc:
  314. ND_PRINT((ndo, "%s", tstr));
  315. }
  316. void
  317. arp_print(netdissect_options *ndo,
  318. const u_char *bp, u_int length, u_int caplen)
  319. {
  320. const struct arp_pkthdr *ap;
  321. u_short pro, hrd, op, linkaddr;
  322. ap = (const struct arp_pkthdr *)bp;
  323. ND_TCHECK(*ap);
  324. hrd = HRD(ap);
  325. pro = PRO(ap);
  326. op = OP(ap);
  327. /* if its ATM then call the ATM ARP printer
  328. for Frame-relay ARP most of the fields
  329. are similar to Ethernet so overload the Ethernet Printer
  330. and set the linkaddr type for linkaddr_string(ndo, ) accordingly */
  331. switch(hrd) {
  332. case ARPHRD_ATM2225:
  333. atmarp_print(ndo, bp, length, caplen);
  334. return;
  335. case ARPHRD_FRELAY:
  336. linkaddr = LINKADDR_FRELAY;
  337. break;
  338. default:
  339. linkaddr = LINKADDR_ETHER;
  340. break;
  341. }
  342. if (!ND_TTEST2(*TPA(ap), PROTO_LEN(ap))) {
  343. ND_PRINT((ndo, "%s", tstr));
  344. ND_DEFAULTPRINT((const u_char *)ap, length);
  345. return;
  346. }
  347. if (!ndo->ndo_eflag) {
  348. ND_PRINT((ndo, "ARP, "));
  349. }
  350. /* print hardware type/len and proto type/len */
  351. if ((pro != ETHERTYPE_IP && pro != ETHERTYPE_TRAIL) ||
  352. PROTO_LEN(ap) != 4 ||
  353. HRD_LEN(ap) == 0 ||
  354. ndo->ndo_vflag) {
  355. ND_PRINT((ndo, "%s (len %u), %s (len %u)",
  356. tok2str(arphrd_values, "Unknown Hardware (%u)", hrd),
  357. HRD_LEN(ap),
  358. tok2str(ethertype_values, "Unknown Protocol (0x%04x)", pro),
  359. PROTO_LEN(ap)));
  360. /* don't know know about the address formats */
  361. if (!ndo->ndo_vflag) {
  362. goto out;
  363. }
  364. }
  365. /* print operation */
  366. ND_PRINT((ndo, "%s%s ",
  367. ndo->ndo_vflag ? ", " : "",
  368. tok2str(arpop_values, "Unknown (%u)", op)));
  369. switch (op) {
  370. case ARPOP_REQUEST:
  371. ND_PRINT((ndo, "who-has "));
  372. tpaddr_print_ip(ndo, ap, pro);
  373. if (isnonzero((const u_char *)THA(ap), HRD_LEN(ap)))
  374. ND_PRINT((ndo, " (%s)",
  375. linkaddr_string(ndo, THA(ap), linkaddr, HRD_LEN(ap))));
  376. ND_PRINT((ndo, " tell "));
  377. spaddr_print_ip(ndo, ap, pro);
  378. break;
  379. case ARPOP_REPLY:
  380. spaddr_print_ip(ndo, ap, pro);
  381. ND_PRINT((ndo, " is-at %s",
  382. linkaddr_string(ndo, SHA(ap), linkaddr, HRD_LEN(ap))));
  383. break;
  384. case ARPOP_REVREQUEST:
  385. ND_PRINT((ndo, "who-is %s tell %s",
  386. linkaddr_string(ndo, THA(ap), linkaddr, HRD_LEN(ap)),
  387. linkaddr_string(ndo, SHA(ap), linkaddr, HRD_LEN(ap))));
  388. break;
  389. case ARPOP_REVREPLY:
  390. ND_PRINT((ndo, "%s at ",
  391. linkaddr_string(ndo, THA(ap), linkaddr, HRD_LEN(ap))));
  392. tpaddr_print_ip(ndo, ap, pro);
  393. break;
  394. case ARPOP_INVREQUEST:
  395. ND_PRINT((ndo, "who-is %s tell %s",
  396. linkaddr_string(ndo, THA(ap), linkaddr, HRD_LEN(ap)),
  397. linkaddr_string(ndo, SHA(ap), linkaddr, HRD_LEN(ap))));
  398. break;
  399. case ARPOP_INVREPLY:
  400. ND_PRINT((ndo,"%s at ",
  401. linkaddr_string(ndo, SHA(ap), linkaddr, HRD_LEN(ap))));
  402. spaddr_print_ip(ndo, ap, pro);
  403. break;
  404. default:
  405. ND_DEFAULTPRINT((const u_char *)ap, caplen);
  406. return;
  407. }
  408. out:
  409. ND_PRINT((ndo, ", length %u", length));
  410. return;
  411. trunc:
  412. ND_PRINT((ndo, "%s", tstr));
  413. }
  414. /*
  415. * Local Variables:
  416. * c-style: bsd
  417. * End:
  418. */