print-gre.c 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422
  1. /* $OpenBSD: print-gre.c,v 1.6 2002/10/30 03:04:04 fgsch Exp $ */
  2. /*
  3. * Copyright (c) 2002 Jason L. Wright (jason@thought.net)
  4. * All rights reserved.
  5. *
  6. * Redistribution and use in source and binary forms, with or without
  7. * modification, are permitted provided that the following conditions
  8. * are met:
  9. * 1. Redistributions of source code must retain the above copyright
  10. * notice, this list of conditions and the following disclaimer.
  11. * 2. Redistributions in binary form must reproduce the above copyright
  12. * notice, this list of conditions and the following disclaimer in the
  13. * documentation and/or other materials provided with the distribution.
  14. * 3. All advertising materials mentioning features or use of this software
  15. * must display the following acknowledgement:
  16. * This product includes software developed by Jason L. Wright
  17. * 4. The name of the author may not be used to endorse or promote products
  18. * derived from this software without specific prior written permission.
  19. *
  20. * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  21. * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  22. * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  23. * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
  24. * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  25. * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  26. * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  27. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  28. * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
  29. * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  30. * POSSIBILITY OF SUCH DAMAGE.
  31. */
  32. /* \summary: Generic Routing Encapsulation (GRE) printer */
  33. /*
  34. * netdissect printer for GRE - Generic Routing Encapsulation
  35. * RFC1701 (GRE), RFC1702 (GRE IPv4), and RFC2637 (Enhanced GRE)
  36. */
  37. #ifdef HAVE_CONFIG_H
  38. #include "config.h"
  39. #endif
  40. #include <netdissect-stdinc.h>
  41. #include <string.h>
  42. #include "netdissect.h"
  43. #include "addrtostr.h"
  44. #include "extract.h"
  45. #include "ethertype.h"
  46. static const char tstr[] = "[|gre]";
  47. #define GRE_CP 0x8000 /* checksum present */
  48. #define GRE_RP 0x4000 /* routing present */
  49. #define GRE_KP 0x2000 /* key present */
  50. #define GRE_SP 0x1000 /* sequence# present */
  51. #define GRE_sP 0x0800 /* source routing */
  52. #define GRE_RECRS 0x0700 /* recursion count */
  53. #define GRE_AP 0x0080 /* acknowledgment# present */
  54. static const struct tok gre_flag_values[] = {
  55. { GRE_CP, "checksum present"},
  56. { GRE_RP, "routing present"},
  57. { GRE_KP, "key present"},
  58. { GRE_SP, "sequence# present"},
  59. { GRE_sP, "source routing present"},
  60. { GRE_RECRS, "recursion count"},
  61. { GRE_AP, "ack present"},
  62. { 0, NULL }
  63. };
  64. #define GRE_VERS_MASK 0x0007 /* protocol version */
  65. /* source route entry types */
  66. #define GRESRE_IP 0x0800 /* IP */
  67. #define GRESRE_ASN 0xfffe /* ASN */
  68. static void gre_print_0(netdissect_options *, const u_char *, u_int);
  69. static void gre_print_1(netdissect_options *, const u_char *, u_int);
  70. static int gre_sre_print(netdissect_options *, uint16_t, uint8_t, uint8_t, const u_char *, u_int);
  71. static int gre_sre_ip_print(netdissect_options *, uint8_t, uint8_t, const u_char *, u_int);
  72. static int gre_sre_asn_print(netdissect_options *, uint8_t, uint8_t, const u_char *, u_int);
  73. void
  74. gre_print(netdissect_options *ndo, const u_char *bp, u_int length)
  75. {
  76. u_int len = length, vers;
  77. ND_TCHECK2(*bp, 2);
  78. if (len < 2)
  79. goto trunc;
  80. vers = EXTRACT_16BITS(bp) & GRE_VERS_MASK;
  81. ND_PRINT((ndo, "GREv%u",vers));
  82. switch(vers) {
  83. case 0:
  84. gre_print_0(ndo, bp, len);
  85. break;
  86. case 1:
  87. gre_print_1(ndo, bp, len);
  88. break;
  89. default:
  90. ND_PRINT((ndo, " ERROR: unknown-version"));
  91. break;
  92. }
  93. return;
  94. trunc:
  95. ND_PRINT((ndo, "%s", tstr));
  96. return;
  97. }
  98. static void
  99. gre_print_0(netdissect_options *ndo, const u_char *bp, u_int length)
  100. {
  101. u_int len = length;
  102. uint16_t flags, prot;
  103. flags = EXTRACT_16BITS(bp);
  104. if (ndo->ndo_vflag)
  105. ND_PRINT((ndo, ", Flags [%s]",
  106. bittok2str(gre_flag_values,"none",flags)));
  107. len -= 2;
  108. bp += 2;
  109. ND_TCHECK2(*bp, 2);
  110. if (len < 2)
  111. goto trunc;
  112. prot = EXTRACT_16BITS(bp);
  113. len -= 2;
  114. bp += 2;
  115. if ((flags & GRE_CP) | (flags & GRE_RP)) {
  116. ND_TCHECK2(*bp, 2);
  117. if (len < 2)
  118. goto trunc;
  119. if (ndo->ndo_vflag)
  120. ND_PRINT((ndo, ", sum 0x%x", EXTRACT_16BITS(bp)));
  121. bp += 2;
  122. len -= 2;
  123. ND_TCHECK2(*bp, 2);
  124. if (len < 2)
  125. goto trunc;
  126. ND_PRINT((ndo, ", off 0x%x", EXTRACT_16BITS(bp)));
  127. bp += 2;
  128. len -= 2;
  129. }
  130. if (flags & GRE_KP) {
  131. ND_TCHECK2(*bp, 4);
  132. if (len < 4)
  133. goto trunc;
  134. ND_PRINT((ndo, ", key=0x%x", EXTRACT_32BITS(bp)));
  135. bp += 4;
  136. len -= 4;
  137. }
  138. if (flags & GRE_SP) {
  139. ND_TCHECK2(*bp, 4);
  140. if (len < 4)
  141. goto trunc;
  142. ND_PRINT((ndo, ", seq %u", EXTRACT_32BITS(bp)));
  143. bp += 4;
  144. len -= 4;
  145. }
  146. if (flags & GRE_RP) {
  147. for (;;) {
  148. uint16_t af;
  149. uint8_t sreoff;
  150. uint8_t srelen;
  151. ND_TCHECK2(*bp, 4);
  152. if (len < 4)
  153. goto trunc;
  154. af = EXTRACT_16BITS(bp);
  155. sreoff = *(bp + 2);
  156. srelen = *(bp + 3);
  157. bp += 4;
  158. len -= 4;
  159. if (af == 0 && srelen == 0)
  160. break;
  161. if (!gre_sre_print(ndo, af, sreoff, srelen, bp, len))
  162. goto trunc;
  163. if (len < srelen)
  164. goto trunc;
  165. bp += srelen;
  166. len -= srelen;
  167. }
  168. }
  169. if (ndo->ndo_eflag)
  170. ND_PRINT((ndo, ", proto %s (0x%04x)",
  171. tok2str(ethertype_values,"unknown",prot),
  172. prot));
  173. ND_PRINT((ndo, ", length %u",length));
  174. if (ndo->ndo_vflag < 1)
  175. ND_PRINT((ndo, ": ")); /* put in a colon as protocol demarc */
  176. else
  177. ND_PRINT((ndo, "\n\t")); /* if verbose go multiline */
  178. switch (prot) {
  179. case ETHERTYPE_IP:
  180. ip_print(ndo, bp, len);
  181. break;
  182. case ETHERTYPE_IPV6:
  183. ip6_print(ndo, bp, len);
  184. break;
  185. case ETHERTYPE_MPLS:
  186. mpls_print(ndo, bp, len);
  187. break;
  188. case ETHERTYPE_IPX:
  189. ipx_print(ndo, bp, len);
  190. break;
  191. case ETHERTYPE_ATALK:
  192. atalk_print(ndo, bp, len);
  193. break;
  194. case ETHERTYPE_GRE_ISO:
  195. isoclns_print(ndo, bp, len);
  196. break;
  197. case ETHERTYPE_TEB:
  198. ether_print(ndo, bp, len, ndo->ndo_snapend - bp, NULL, NULL);
  199. break;
  200. default:
  201. ND_PRINT((ndo, "gre-proto-0x%x", prot));
  202. }
  203. return;
  204. trunc:
  205. ND_PRINT((ndo, "%s", tstr));
  206. }
  207. static void
  208. gre_print_1(netdissect_options *ndo, const u_char *bp, u_int length)
  209. {
  210. u_int len = length;
  211. uint16_t flags, prot;
  212. flags = EXTRACT_16BITS(bp);
  213. len -= 2;
  214. bp += 2;
  215. if (ndo->ndo_vflag)
  216. ND_PRINT((ndo, ", Flags [%s]",
  217. bittok2str(gre_flag_values,"none",flags)));
  218. ND_TCHECK2(*bp, 2);
  219. if (len < 2)
  220. goto trunc;
  221. prot = EXTRACT_16BITS(bp);
  222. len -= 2;
  223. bp += 2;
  224. if (flags & GRE_KP) {
  225. uint32_t k;
  226. ND_TCHECK2(*bp, 4);
  227. if (len < 4)
  228. goto trunc;
  229. k = EXTRACT_32BITS(bp);
  230. ND_PRINT((ndo, ", call %d", k & 0xffff));
  231. len -= 4;
  232. bp += 4;
  233. }
  234. if (flags & GRE_SP) {
  235. ND_TCHECK2(*bp, 4);
  236. if (len < 4)
  237. goto trunc;
  238. ND_PRINT((ndo, ", seq %u", EXTRACT_32BITS(bp)));
  239. bp += 4;
  240. len -= 4;
  241. }
  242. if (flags & GRE_AP) {
  243. ND_TCHECK2(*bp, 4);
  244. if (len < 4)
  245. goto trunc;
  246. ND_PRINT((ndo, ", ack %u", EXTRACT_32BITS(bp)));
  247. bp += 4;
  248. len -= 4;
  249. }
  250. if ((flags & GRE_SP) == 0)
  251. ND_PRINT((ndo, ", no-payload"));
  252. if (ndo->ndo_eflag)
  253. ND_PRINT((ndo, ", proto %s (0x%04x)",
  254. tok2str(ethertype_values,"unknown",prot),
  255. prot));
  256. ND_PRINT((ndo, ", length %u",length));
  257. if ((flags & GRE_SP) == 0)
  258. return;
  259. if (ndo->ndo_vflag < 1)
  260. ND_PRINT((ndo, ": ")); /* put in a colon as protocol demarc */
  261. else
  262. ND_PRINT((ndo, "\n\t")); /* if verbose go multiline */
  263. switch (prot) {
  264. case ETHERTYPE_PPP:
  265. ppp_print(ndo, bp, len);
  266. break;
  267. default:
  268. ND_PRINT((ndo, "gre-proto-0x%x", prot));
  269. break;
  270. }
  271. return;
  272. trunc:
  273. ND_PRINT((ndo, "%s", tstr));
  274. }
  275. static int
  276. gre_sre_print(netdissect_options *ndo, uint16_t af, uint8_t sreoff,
  277. uint8_t srelen, const u_char *bp, u_int len)
  278. {
  279. int ret;
  280. switch (af) {
  281. case GRESRE_IP:
  282. ND_PRINT((ndo, ", (rtaf=ip"));
  283. ret = gre_sre_ip_print(ndo, sreoff, srelen, bp, len);
  284. ND_PRINT((ndo, ")"));
  285. break;
  286. case GRESRE_ASN:
  287. ND_PRINT((ndo, ", (rtaf=asn"));
  288. ret = gre_sre_asn_print(ndo, sreoff, srelen, bp, len);
  289. ND_PRINT((ndo, ")"));
  290. break;
  291. default:
  292. ND_PRINT((ndo, ", (rtaf=0x%x)", af));
  293. ret = 1;
  294. }
  295. return (ret);
  296. }
  297. static int
  298. gre_sre_ip_print(netdissect_options *ndo, uint8_t sreoff, uint8_t srelen,
  299. const u_char *bp, u_int len)
  300. {
  301. const u_char *up = bp;
  302. char buf[INET_ADDRSTRLEN];
  303. if (sreoff & 3) {
  304. ND_PRINT((ndo, ", badoffset=%u", sreoff));
  305. return (1);
  306. }
  307. if (srelen & 3) {
  308. ND_PRINT((ndo, ", badlength=%u", srelen));
  309. return (1);
  310. }
  311. if (sreoff >= srelen) {
  312. ND_PRINT((ndo, ", badoff/len=%u/%u", sreoff, srelen));
  313. return (1);
  314. }
  315. while (srelen != 0) {
  316. if (!ND_TTEST2(*bp, 4))
  317. return (0);
  318. if (len < 4)
  319. return (0);
  320. addrtostr(bp, buf, sizeof(buf));
  321. ND_PRINT((ndo, " %s%s",
  322. ((bp - up) == sreoff) ? "*" : "", buf));
  323. bp += 4;
  324. len -= 4;
  325. srelen -= 4;
  326. }
  327. return (1);
  328. }
  329. static int
  330. gre_sre_asn_print(netdissect_options *ndo, uint8_t sreoff, uint8_t srelen,
  331. const u_char *bp, u_int len)
  332. {
  333. const u_char *up = bp;
  334. if (sreoff & 1) {
  335. ND_PRINT((ndo, ", badoffset=%u", sreoff));
  336. return (1);
  337. }
  338. if (srelen & 1) {
  339. ND_PRINT((ndo, ", badlength=%u", srelen));
  340. return (1);
  341. }
  342. if (sreoff >= srelen) {
  343. ND_PRINT((ndo, ", badoff/len=%u/%u", sreoff, srelen));
  344. return (1);
  345. }
  346. while (srelen != 0) {
  347. if (!ND_TTEST2(*bp, 2))
  348. return (0);
  349. if (len < 2)
  350. return (0);
  351. ND_PRINT((ndo, " %s%x",
  352. ((bp - up) == sreoff) ? "*" : "",
  353. EXTRACT_16BITS(bp)));
  354. bp += 2;
  355. len -= 2;
  356. srelen -= 2;
  357. }
  358. return (1);
  359. }