print-arcnet.c 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360
  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. * From: NetBSD: print-arcnet.c,v 1.2 2000/04/24 13:02:28 itojun Exp
  22. */
  23. /* \summary: Attached Resource Computer NETwork (ARCNET) printer */
  24. #ifdef HAVE_CONFIG_H
  25. #include "config.h"
  26. #endif
  27. #include <netdissect-stdinc.h>
  28. #include "netdissect.h"
  29. #include "extract.h"
  30. /*
  31. * from: NetBSD: if_arc.h,v 1.13 1999/11/19 20:41:19 thorpej Exp
  32. */
  33. /*
  34. * Structure of a 2.5MB/s Arcnet header on the BSDs,
  35. * as given to interface code.
  36. */
  37. struct arc_header {
  38. uint8_t arc_shost;
  39. uint8_t arc_dhost;
  40. uint8_t arc_type;
  41. /*
  42. * only present for newstyle encoding with LL fragmentation.
  43. * Don't use sizeof(anything), use ARC_HDR{,NEW}LEN instead.
  44. */
  45. uint8_t arc_flag;
  46. uint16_t arc_seqid;
  47. /*
  48. * only present in exception packets (arc_flag == 0xff)
  49. */
  50. uint8_t arc_type2; /* same as arc_type */
  51. uint8_t arc_flag2; /* real flag value */
  52. uint16_t arc_seqid2; /* real seqid value */
  53. };
  54. #define ARC_HDRLEN 3
  55. #define ARC_HDRNEWLEN 6
  56. #define ARC_HDRNEWLEN_EXC 10
  57. /* RFC 1051 */
  58. #define ARCTYPE_IP_OLD 240 /* IP protocol */
  59. #define ARCTYPE_ARP_OLD 241 /* address resolution protocol */
  60. /* RFC 1201 */
  61. #define ARCTYPE_IP 212 /* IP protocol */
  62. #define ARCTYPE_ARP 213 /* address resolution protocol */
  63. #define ARCTYPE_REVARP 214 /* reverse addr resolution protocol */
  64. #define ARCTYPE_ATALK 221 /* Appletalk */
  65. #define ARCTYPE_BANIAN 247 /* Banyan Vines */
  66. #define ARCTYPE_IPX 250 /* Novell IPX */
  67. #define ARCTYPE_INET6 0xc4 /* IPng */
  68. #define ARCTYPE_DIAGNOSE 0x80 /* as per ANSI/ATA 878.1 */
  69. /*
  70. * Structure of a 2.5MB/s Arcnet header on Linux. Linux has
  71. * an extra "offset" field when given to interface code, and
  72. * never presents packets that look like exception frames.
  73. */
  74. struct arc_linux_header {
  75. uint8_t arc_shost;
  76. uint8_t arc_dhost;
  77. uint16_t arc_offset;
  78. uint8_t arc_type;
  79. /*
  80. * only present for newstyle encoding with LL fragmentation.
  81. * Don't use sizeof(anything), use ARC_LINUX_HDR{,NEW}LEN
  82. * instead.
  83. */
  84. uint8_t arc_flag;
  85. uint16_t arc_seqid;
  86. };
  87. #define ARC_LINUX_HDRLEN 5
  88. #define ARC_LINUX_HDRNEWLEN 8
  89. static int arcnet_encap_print(netdissect_options *, u_char arctype, const u_char *p,
  90. u_int length, u_int caplen);
  91. static const struct tok arctypemap[] = {
  92. { ARCTYPE_IP_OLD, "oldip" },
  93. { ARCTYPE_ARP_OLD, "oldarp" },
  94. { ARCTYPE_IP, "ip" },
  95. { ARCTYPE_ARP, "arp" },
  96. { ARCTYPE_REVARP, "rarp" },
  97. { ARCTYPE_ATALK, "atalk" },
  98. { ARCTYPE_BANIAN, "banyan" },
  99. { ARCTYPE_IPX, "ipx" },
  100. { ARCTYPE_INET6, "ipv6" },
  101. { ARCTYPE_DIAGNOSE, "diag" },
  102. { 0, 0 }
  103. };
  104. static inline void
  105. arcnet_print(netdissect_options *ndo, const u_char *bp, u_int length, int phds,
  106. int flag, u_int seqid)
  107. {
  108. const struct arc_header *ap;
  109. const char *arctypename;
  110. ap = (const struct arc_header *)bp;
  111. if (ndo->ndo_qflag) {
  112. ND_PRINT((ndo, "%02x %02x %d: ",
  113. ap->arc_shost,
  114. ap->arc_dhost,
  115. length));
  116. return;
  117. }
  118. arctypename = tok2str(arctypemap, "%02x", ap->arc_type);
  119. if (!phds) {
  120. ND_PRINT((ndo, "%02x %02x %s %d: ",
  121. ap->arc_shost, ap->arc_dhost, arctypename,
  122. length));
  123. return;
  124. }
  125. if (flag == 0) {
  126. ND_PRINT((ndo, "%02x %02x %s seqid %04x %d: ",
  127. ap->arc_shost, ap->arc_dhost, arctypename, seqid,
  128. length));
  129. return;
  130. }
  131. if (flag & 1)
  132. ND_PRINT((ndo, "%02x %02x %s seqid %04x "
  133. "(first of %d fragments) %d: ",
  134. ap->arc_shost, ap->arc_dhost, arctypename, seqid,
  135. (flag + 3) / 2, length));
  136. else
  137. ND_PRINT((ndo, "%02x %02x %s seqid %04x "
  138. "(fragment %d) %d: ",
  139. ap->arc_shost, ap->arc_dhost, arctypename, seqid,
  140. flag/2 + 1, length));
  141. }
  142. /*
  143. * This is the top level routine of the printer. 'p' points
  144. * to the ARCNET header of the packet, 'h->ts' is the timestamp,
  145. * 'h->len' is the length of the packet off the wire, and 'h->caplen'
  146. * is the number of bytes actually captured.
  147. */
  148. u_int
  149. arcnet_if_print(netdissect_options *ndo, const struct pcap_pkthdr *h, const u_char *p)
  150. {
  151. u_int caplen = h->caplen;
  152. u_int length = h->len;
  153. const struct arc_header *ap;
  154. int phds, flag = 0, archdrlen = 0;
  155. u_int seqid = 0;
  156. u_char arc_type;
  157. if (caplen < ARC_HDRLEN || length < ARC_HDRLEN) {
  158. ND_PRINT((ndo, "[|arcnet]"));
  159. return (caplen);
  160. }
  161. ap = (const struct arc_header *)p;
  162. arc_type = ap->arc_type;
  163. switch (arc_type) {
  164. default:
  165. phds = 1;
  166. break;
  167. case ARCTYPE_IP_OLD:
  168. case ARCTYPE_ARP_OLD:
  169. case ARCTYPE_DIAGNOSE:
  170. phds = 0;
  171. archdrlen = ARC_HDRLEN;
  172. break;
  173. }
  174. if (phds) {
  175. if (caplen < ARC_HDRNEWLEN || length < ARC_HDRNEWLEN) {
  176. arcnet_print(ndo, p, length, 0, 0, 0);
  177. ND_PRINT((ndo, "[|phds]"));
  178. return (caplen);
  179. }
  180. if (ap->arc_flag == 0xff) {
  181. if (caplen < ARC_HDRNEWLEN_EXC || length < ARC_HDRNEWLEN_EXC) {
  182. arcnet_print(ndo, p, length, 0, 0, 0);
  183. ND_PRINT((ndo, "[|phds extended]"));
  184. return (caplen);
  185. }
  186. flag = ap->arc_flag2;
  187. seqid = EXTRACT_16BITS(&ap->arc_seqid2);
  188. archdrlen = ARC_HDRNEWLEN_EXC;
  189. } else {
  190. flag = ap->arc_flag;
  191. seqid = EXTRACT_16BITS(&ap->arc_seqid);
  192. archdrlen = ARC_HDRNEWLEN;
  193. }
  194. }
  195. if (ndo->ndo_eflag)
  196. arcnet_print(ndo, p, length, phds, flag, seqid);
  197. /*
  198. * Go past the ARCNET header.
  199. */
  200. length -= archdrlen;
  201. caplen -= archdrlen;
  202. p += archdrlen;
  203. if (phds && flag && (flag & 1) == 0) {
  204. /*
  205. * This is a middle fragment.
  206. */
  207. return (archdrlen);
  208. }
  209. if (!arcnet_encap_print(ndo, arc_type, p, length, caplen))
  210. ND_DEFAULTPRINT(p, caplen);
  211. return (archdrlen);
  212. }
  213. /*
  214. * This is the top level routine of the printer. 'p' points
  215. * to the ARCNET header of the packet, 'h->ts' is the timestamp,
  216. * 'h->len' is the length of the packet off the wire, and 'h->caplen'
  217. * is the number of bytes actually captured. It is quite similar
  218. * to the non-Linux style printer except that Linux doesn't ever
  219. * supply packets that look like exception frames, it always supplies
  220. * reassembled packets rather than raw frames, and headers have an
  221. * extra "offset" field between the src/dest and packet type.
  222. */
  223. u_int
  224. arcnet_linux_if_print(netdissect_options *ndo, const struct pcap_pkthdr *h, const u_char *p)
  225. {
  226. u_int caplen = h->caplen;
  227. u_int length = h->len;
  228. const struct arc_linux_header *ap;
  229. int archdrlen = 0;
  230. u_char arc_type;
  231. if (caplen < ARC_LINUX_HDRLEN || length < ARC_LINUX_HDRLEN) {
  232. ND_PRINT((ndo, "[|arcnet]"));
  233. return (caplen);
  234. }
  235. ap = (const struct arc_linux_header *)p;
  236. arc_type = ap->arc_type;
  237. switch (arc_type) {
  238. default:
  239. archdrlen = ARC_LINUX_HDRNEWLEN;
  240. if (caplen < ARC_LINUX_HDRNEWLEN || length < ARC_LINUX_HDRNEWLEN) {
  241. ND_PRINT((ndo, "[|arcnet]"));
  242. return (caplen);
  243. }
  244. break;
  245. case ARCTYPE_IP_OLD:
  246. case ARCTYPE_ARP_OLD:
  247. case ARCTYPE_DIAGNOSE:
  248. archdrlen = ARC_LINUX_HDRLEN;
  249. break;
  250. }
  251. if (ndo->ndo_eflag)
  252. arcnet_print(ndo, p, length, 0, 0, 0);
  253. /*
  254. * Go past the ARCNET header.
  255. */
  256. length -= archdrlen;
  257. caplen -= archdrlen;
  258. p += archdrlen;
  259. if (!arcnet_encap_print(ndo, arc_type, p, length, caplen))
  260. ND_DEFAULTPRINT(p, caplen);
  261. return (archdrlen);
  262. }
  263. /*
  264. * Prints the packet encapsulated in an ARCnet data field,
  265. * given the ARCnet system code.
  266. *
  267. * Returns non-zero if it can do so, zero if the system code is unknown.
  268. */
  269. static int
  270. arcnet_encap_print(netdissect_options *ndo, u_char arctype, const u_char *p,
  271. u_int length, u_int caplen)
  272. {
  273. switch (arctype) {
  274. case ARCTYPE_IP_OLD:
  275. case ARCTYPE_IP:
  276. ip_print(ndo, p, length);
  277. return (1);
  278. case ARCTYPE_INET6:
  279. ip6_print(ndo, p, length);
  280. return (1);
  281. case ARCTYPE_ARP_OLD:
  282. case ARCTYPE_ARP:
  283. case ARCTYPE_REVARP:
  284. arp_print(ndo, p, length, caplen);
  285. return (1);
  286. case ARCTYPE_ATALK: /* XXX was this ever used? */
  287. if (ndo->ndo_vflag)
  288. ND_PRINT((ndo, "et1 "));
  289. atalk_print(ndo, p, length);
  290. return (1);
  291. case ARCTYPE_IPX:
  292. ipx_print(ndo, p, length);
  293. return (1);
  294. default:
  295. return (0);
  296. }
  297. }
  298. /*
  299. * Local Variables:
  300. * c-style: bsd
  301. * End:
  302. */