print-mobility.c 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344
  1. /*
  2. * Copyright (C) 2002 WIDE Project.
  3. * All rights reserved.
  4. *
  5. * Redistribution and use in source and binary forms, with or without
  6. * modification, are permitted provided that the following conditions
  7. * are met:
  8. * 1. Redistributions of source code must retain the above copyright
  9. * notice, this list of conditions and the following disclaimer.
  10. * 2. Redistributions in binary form must reproduce the above copyright
  11. * notice, this list of conditions and the following disclaimer in the
  12. * documentation and/or other materials provided with the distribution.
  13. * 3. Neither the name of the project nor the names of its contributors
  14. * may be used to endorse or promote products derived from this software
  15. * without specific prior written permission.
  16. *
  17. * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
  18. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  19. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  20. * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
  21. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  22. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  23. * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  24. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  25. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  26. * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  27. * SUCH DAMAGE.
  28. */
  29. /* \summary: IPv6 mobility printer */
  30. /* RFC 3775 */
  31. #ifdef HAVE_CONFIG_H
  32. #include "config.h"
  33. #endif
  34. #include <netdissect-stdinc.h>
  35. #include "netdissect.h"
  36. #include "addrtoname.h"
  37. #include "extract.h"
  38. #include "ip6.h"
  39. static const char tstr[] = "[|MOBILITY]";
  40. /* Mobility header */
  41. struct ip6_mobility {
  42. uint8_t ip6m_pproto; /* following payload protocol (for PG) */
  43. uint8_t ip6m_len; /* length in units of 8 octets */
  44. uint8_t ip6m_type; /* message type */
  45. uint8_t reserved; /* reserved */
  46. uint16_t ip6m_cksum; /* sum of IPv6 pseudo-header and MH */
  47. union {
  48. uint16_t ip6m_un_data16[1]; /* type-specific field */
  49. uint8_t ip6m_un_data8[2]; /* type-specific field */
  50. } ip6m_dataun;
  51. };
  52. #define ip6m_data16 ip6m_dataun.ip6m_un_data16
  53. #define ip6m_data8 ip6m_dataun.ip6m_un_data8
  54. #define IP6M_MINLEN 8
  55. /* http://www.iana.org/assignments/mobility-parameters/mobility-parameters.xhtml */
  56. /* message type */
  57. #define IP6M_BINDING_REQUEST 0 /* Binding Refresh Request */
  58. #define IP6M_HOME_TEST_INIT 1 /* Home Test Init */
  59. #define IP6M_CAREOF_TEST_INIT 2 /* Care-of Test Init */
  60. #define IP6M_HOME_TEST 3 /* Home Test */
  61. #define IP6M_CAREOF_TEST 4 /* Care-of Test */
  62. #define IP6M_BINDING_UPDATE 5 /* Binding Update */
  63. #define IP6M_BINDING_ACK 6 /* Binding Acknowledgement */
  64. #define IP6M_BINDING_ERROR 7 /* Binding Error */
  65. #define IP6M_MAX 7
  66. static const struct tok ip6m_str[] = {
  67. { IP6M_BINDING_REQUEST, "BRR" },
  68. { IP6M_HOME_TEST_INIT, "HoTI" },
  69. { IP6M_CAREOF_TEST_INIT, "CoTI" },
  70. { IP6M_HOME_TEST, "HoT" },
  71. { IP6M_CAREOF_TEST, "CoT" },
  72. { IP6M_BINDING_UPDATE, "BU" },
  73. { IP6M_BINDING_ACK, "BA" },
  74. { IP6M_BINDING_ERROR, "BE" },
  75. { 0, NULL }
  76. };
  77. static const unsigned ip6m_hdrlen[IP6M_MAX + 1] = {
  78. IP6M_MINLEN, /* IP6M_BINDING_REQUEST */
  79. IP6M_MINLEN + 8, /* IP6M_HOME_TEST_INIT */
  80. IP6M_MINLEN + 8, /* IP6M_CAREOF_TEST_INIT */
  81. IP6M_MINLEN + 16, /* IP6M_HOME_TEST */
  82. IP6M_MINLEN + 16, /* IP6M_CAREOF_TEST */
  83. IP6M_MINLEN + 4, /* IP6M_BINDING_UPDATE */
  84. IP6M_MINLEN + 4, /* IP6M_BINDING_ACK */
  85. IP6M_MINLEN + 16, /* IP6M_BINDING_ERROR */
  86. };
  87. /* Mobility Header Options */
  88. #define IP6MOPT_MINLEN 2
  89. #define IP6MOPT_PAD1 0x0 /* Pad1 */
  90. #define IP6MOPT_PADN 0x1 /* PadN */
  91. #define IP6MOPT_REFRESH 0x2 /* Binding Refresh Advice */
  92. #define IP6MOPT_REFRESH_MINLEN 4
  93. #define IP6MOPT_ALTCOA 0x3 /* Alternate Care-of Address */
  94. #define IP6MOPT_ALTCOA_MINLEN 18
  95. #define IP6MOPT_NONCEID 0x4 /* Nonce Indices */
  96. #define IP6MOPT_NONCEID_MINLEN 6
  97. #define IP6MOPT_AUTH 0x5 /* Binding Authorization Data */
  98. #define IP6MOPT_AUTH_MINLEN 12
  99. static int
  100. mobility_opt_print(netdissect_options *ndo,
  101. const u_char *bp, const unsigned len)
  102. {
  103. unsigned i, optlen;
  104. for (i = 0; i < len; i += optlen) {
  105. ND_TCHECK(bp[i]);
  106. if (bp[i] == IP6MOPT_PAD1)
  107. optlen = 1;
  108. else {
  109. if (i + 1 < len) {
  110. ND_TCHECK(bp[i + 1]);
  111. optlen = bp[i + 1] + 2;
  112. }
  113. else
  114. goto trunc;
  115. }
  116. if (i + optlen > len)
  117. goto trunc;
  118. ND_TCHECK(bp[i + optlen]);
  119. switch (bp[i]) {
  120. case IP6MOPT_PAD1:
  121. ND_PRINT((ndo, "(pad1)"));
  122. break;
  123. case IP6MOPT_PADN:
  124. if (len - i < IP6MOPT_MINLEN) {
  125. ND_PRINT((ndo, "(padn: trunc)"));
  126. goto trunc;
  127. }
  128. ND_PRINT((ndo, "(padn)"));
  129. break;
  130. case IP6MOPT_REFRESH:
  131. if (len - i < IP6MOPT_REFRESH_MINLEN) {
  132. ND_PRINT((ndo, "(refresh: trunc)"));
  133. goto trunc;
  134. }
  135. /* units of 4 secs */
  136. ND_TCHECK_16BITS(&bp[i+2]);
  137. ND_PRINT((ndo, "(refresh: %u)",
  138. EXTRACT_16BITS(&bp[i+2]) << 2));
  139. break;
  140. case IP6MOPT_ALTCOA:
  141. if (len - i < IP6MOPT_ALTCOA_MINLEN) {
  142. ND_PRINT((ndo, "(altcoa: trunc)"));
  143. goto trunc;
  144. }
  145. ND_TCHECK_128BITS(&bp[i+2]);
  146. ND_PRINT((ndo, "(alt-CoA: %s)", ip6addr_string(ndo, &bp[i+2])));
  147. break;
  148. case IP6MOPT_NONCEID:
  149. if (len - i < IP6MOPT_NONCEID_MINLEN) {
  150. ND_PRINT((ndo, "(ni: trunc)"));
  151. goto trunc;
  152. }
  153. ND_TCHECK_16BITS(&bp[i+2]);
  154. ND_TCHECK_16BITS(&bp[i+4]);
  155. ND_PRINT((ndo, "(ni: ho=0x%04x co=0x%04x)",
  156. EXTRACT_16BITS(&bp[i+2]),
  157. EXTRACT_16BITS(&bp[i+4])));
  158. break;
  159. case IP6MOPT_AUTH:
  160. if (len - i < IP6MOPT_AUTH_MINLEN) {
  161. ND_PRINT((ndo, "(auth: trunc)"));
  162. goto trunc;
  163. }
  164. ND_PRINT((ndo, "(auth)"));
  165. break;
  166. default:
  167. if (len - i < IP6MOPT_MINLEN) {
  168. ND_PRINT((ndo, "(sopt_type %u: trunc)", bp[i]));
  169. goto trunc;
  170. }
  171. ND_PRINT((ndo, "(type-0x%02x: len=%u)", bp[i], bp[i + 1]));
  172. break;
  173. }
  174. }
  175. return 0;
  176. trunc:
  177. return 1;
  178. }
  179. /*
  180. * Mobility Header
  181. */
  182. int
  183. mobility_print(netdissect_options *ndo,
  184. const u_char *bp, const u_char *bp2 _U_)
  185. {
  186. const struct ip6_mobility *mh;
  187. const u_char *ep;
  188. unsigned mhlen, hlen;
  189. uint8_t type;
  190. mh = (const struct ip6_mobility *)bp;
  191. /* 'ep' points to the end of available data. */
  192. ep = ndo->ndo_snapend;
  193. if (!ND_TTEST(mh->ip6m_len)) {
  194. /*
  195. * There's not enough captured data to include the
  196. * mobility header length.
  197. *
  198. * Our caller expects us to return the length, however,
  199. * so return a value that will run to the end of the
  200. * captured data.
  201. *
  202. * XXX - "ip6_print()" doesn't do anything with the
  203. * returned length, however, as it breaks out of the
  204. * header-processing loop.
  205. */
  206. mhlen = ep - bp;
  207. goto trunc;
  208. }
  209. mhlen = (mh->ip6m_len + 1) << 3;
  210. /* XXX ip6m_cksum */
  211. ND_TCHECK(mh->ip6m_type);
  212. type = mh->ip6m_type;
  213. if (type <= IP6M_MAX && mhlen < ip6m_hdrlen[type]) {
  214. ND_PRINT((ndo, "(header length %u is too small for type %u)", mhlen, type));
  215. goto trunc;
  216. }
  217. ND_PRINT((ndo, "mobility: %s", tok2str(ip6m_str, "type-#%u", type)));
  218. switch (type) {
  219. case IP6M_BINDING_REQUEST:
  220. hlen = IP6M_MINLEN;
  221. break;
  222. case IP6M_HOME_TEST_INIT:
  223. case IP6M_CAREOF_TEST_INIT:
  224. hlen = IP6M_MINLEN;
  225. if (ndo->ndo_vflag) {
  226. ND_TCHECK_32BITS(&bp[hlen + 4]);
  227. ND_PRINT((ndo, " %s Init Cookie=%08x:%08x",
  228. type == IP6M_HOME_TEST_INIT ? "Home" : "Care-of",
  229. EXTRACT_32BITS(&bp[hlen]),
  230. EXTRACT_32BITS(&bp[hlen + 4])));
  231. }
  232. hlen += 8;
  233. break;
  234. case IP6M_HOME_TEST:
  235. case IP6M_CAREOF_TEST:
  236. ND_TCHECK(mh->ip6m_data16[0]);
  237. ND_PRINT((ndo, " nonce id=0x%x", EXTRACT_16BITS(&mh->ip6m_data16[0])));
  238. hlen = IP6M_MINLEN;
  239. if (ndo->ndo_vflag) {
  240. ND_TCHECK_32BITS(&bp[hlen + 4]);
  241. ND_PRINT((ndo, " %s Init Cookie=%08x:%08x",
  242. type == IP6M_HOME_TEST ? "Home" : "Care-of",
  243. EXTRACT_32BITS(&bp[hlen]),
  244. EXTRACT_32BITS(&bp[hlen + 4])));
  245. }
  246. hlen += 8;
  247. if (ndo->ndo_vflag) {
  248. ND_TCHECK_32BITS(&bp[hlen + 4]);
  249. ND_PRINT((ndo, " %s Keygen Token=%08x:%08x",
  250. type == IP6M_HOME_TEST ? "Home" : "Care-of",
  251. EXTRACT_32BITS(&bp[hlen]),
  252. EXTRACT_32BITS(&bp[hlen + 4])));
  253. }
  254. hlen += 8;
  255. break;
  256. case IP6M_BINDING_UPDATE:
  257. ND_TCHECK(mh->ip6m_data16[0]);
  258. ND_PRINT((ndo, " seq#=%u", EXTRACT_16BITS(&mh->ip6m_data16[0])));
  259. hlen = IP6M_MINLEN;
  260. ND_TCHECK_16BITS(&bp[hlen]);
  261. if (bp[hlen] & 0xf0) {
  262. ND_PRINT((ndo, " "));
  263. if (bp[hlen] & 0x80)
  264. ND_PRINT((ndo, "A"));
  265. if (bp[hlen] & 0x40)
  266. ND_PRINT((ndo, "H"));
  267. if (bp[hlen] & 0x20)
  268. ND_PRINT((ndo, "L"));
  269. if (bp[hlen] & 0x10)
  270. ND_PRINT((ndo, "K"));
  271. }
  272. /* Reserved (4bits) */
  273. hlen += 1;
  274. /* Reserved (8bits) */
  275. hlen += 1;
  276. ND_TCHECK_16BITS(&bp[hlen]);
  277. /* units of 4 secs */
  278. ND_PRINT((ndo, " lifetime=%u", EXTRACT_16BITS(&bp[hlen]) << 2));
  279. hlen += 2;
  280. break;
  281. case IP6M_BINDING_ACK:
  282. ND_TCHECK(mh->ip6m_data8[0]);
  283. ND_PRINT((ndo, " status=%u", mh->ip6m_data8[0]));
  284. ND_TCHECK(mh->ip6m_data8[1]);
  285. if (mh->ip6m_data8[1] & 0x80)
  286. ND_PRINT((ndo, " K"));
  287. /* Reserved (7bits) */
  288. hlen = IP6M_MINLEN;
  289. ND_TCHECK_16BITS(&bp[hlen]);
  290. ND_PRINT((ndo, " seq#=%u", EXTRACT_16BITS(&bp[hlen])));
  291. hlen += 2;
  292. ND_TCHECK_16BITS(&bp[hlen]);
  293. /* units of 4 secs */
  294. ND_PRINT((ndo, " lifetime=%u", EXTRACT_16BITS(&bp[hlen]) << 2));
  295. hlen += 2;
  296. break;
  297. case IP6M_BINDING_ERROR:
  298. ND_TCHECK(mh->ip6m_data8[0]);
  299. ND_PRINT((ndo, " status=%u", mh->ip6m_data8[0]));
  300. /* Reserved */
  301. hlen = IP6M_MINLEN;
  302. ND_TCHECK2(bp[hlen], 16);
  303. ND_PRINT((ndo, " homeaddr %s", ip6addr_string(ndo, &bp[hlen])));
  304. hlen += 16;
  305. break;
  306. default:
  307. ND_PRINT((ndo, " len=%u", mh->ip6m_len));
  308. return(mhlen);
  309. break;
  310. }
  311. if (ndo->ndo_vflag)
  312. if (mobility_opt_print(ndo, &bp[hlen], mhlen - hlen))
  313. goto trunc;;
  314. return(mhlen);
  315. trunc:
  316. ND_PRINT((ndo, "%s", tstr));
  317. return(-1);
  318. }