diff -Nur racoon2-20070817cvs/lib/if_pfkeyv2.c racoon2-patched/lib/if_pfkeyv2.c --- racoon2-20070817cvs/lib/if_pfkeyv2.c 2007-08-17 10:57:42.000000000 +0900 +++ racoon2-patched/lib/if_pfkeyv2.c 2007-08-17 11:52:12.000000000 +0900 @@ -1894,12 +1894,11 @@ struct sadb_x_packet *pkt; struct ip6_hdr *ip; struct ip6_ext *ep; - struct ip6_opt *op; - struct ip6_opt_home_address *hao = NULL; + struct ip6_mh_opt_altcoa *altcoa=NULL; struct ip6_mh *mh = NULL; struct ip6_mh_binding_update *hrbu = NULL; struct sockaddr_in6 *src6; - int len, nxt, l; + int len, nxt, l=0; #endif /* ignore this message in the case of the local test mode. */ @@ -1959,19 +1958,18 @@ * Decode the triggering packet for the case it is * a MIPv6 home registration binding update. */ -#define HRBU_MIN_LEN (40 + 24 + 12) if (mhp[SADB_X_EXT_PACKET] == 0) goto skippa; pkt = (struct sadb_x_packet *)mhp[SADB_X_EXT_PACKET]; ip = (struct ip6_hdr *)(pkt + 1); ep = (struct ip6_ext *)(ip + 1); - if (pkt->sadb_x_packet_copylen < HRBU_MIN_LEN) + if (pkt->sadb_x_packet_copylen < sizeof( struct ip6_hdr)) goto skippa; if ((ip->ip6_vfc & IPV6_VERSION_MASK) != IPV6_VERSION) goto skippa; - /* chasing for HOA and HRBU */ + /* chasing for HRBU */ len = ntohs(ip->ip6_plen) + sizeof(*ip); if (len > pkt->sadb_x_packet_copylen) @@ -1983,6 +1981,7 @@ case IPPROTO_HOPOPTS: case IPPROTO_ROUTING: case IPPROTO_FRAGMENT: + case IPPROTO_DSTOPTS: l = (ep->ip6e_len + 1) << 3; skip: nxt = ep->ip6e_nxt; @@ -2000,31 +1999,6 @@ default: goto skippa; - case IPPROTO_DSTOPTS: - l = (ep->ip6e_len + 1) << 3; - if (l > len) - goto skippa; - op = (struct ip6_opt *)(ep + 1); - l -= sizeof(*ep); - while (l > 0) - switch (op->ip6o_type) { - case IP6OPT_PAD1: - l -= 1; - op = (struct ip6_opt *)((caddr_t)op + 1); - break; - - case IP6OPT_HOME_ADDRESS: - hao = (struct ip6_opt_home_address *)op; - /* fall into */ - - case IP6OPT_PADN: - default: - l -= 2 + op->ip6o_len; - op = (struct ip6_opt *)((caddr_t)op + 2 + op->ip6o_len); - } - l = (ep->ip6e_len + 1) << 3; - goto skip; - case IPPROTO_MH: l = (ep->ip6e_len + 1) << 3; hrbu = (struct ip6_mh_binding_update *)ep; @@ -2034,28 +2008,54 @@ if (mh->ip6mh_type != IP6_MH_TYPE_BU || (hrbu->ip6mhbu_flags & IP6_MH_BU_HOME) == 0) { hrbu = NULL; - goto skip; + goto skippa; } + altcoa = (struct ip6_mh_opt_altcoa *)(hrbu + 1); + /* force exit */ len = 0; } - /* found? */ - - if (hao == NULL || hrbu == NULL) - goto skippa; - if (hao->ip6oh_len < 16) + /* found mobility header? */ + if (! altcoa) goto skippa; - - /* cache the right address to use in src2 */ - rc->sa2_src = (struct sockaddr *)&rc->sa2_src_storage; - src6 = (struct sockaddr_in6 *)rc->sa2_src; - bzero(src6, sizeof(struct sockaddr_in6)); - src6->sin6_family = AF_INET6; -#ifdef HAVE_SA_LEN - src6->sin6_len = sizeof(*src6); -#endif - memcpy(&src6->sin6_addr, hao->ip6oh_addr, sizeof(hao->ip6oh_addr)); + + len = l - sizeof(*hrbu); + + /* Parse the MH options -- we are looking for ALTCOA */ + while (len > 0) + switch (altcoa->ip6moa_type){ + case IP6_MHOPT_PAD1: + len -= 1; + altcoa = (struct ip6_mh_opt_altcoa *)((caddr_t)altcoa + 1); + break; + + case IP6_MHOPT_PADN: + len -= 2 + altcoa->ip6moa_len; + altcoa = (struct ip6_mh_opt_altcoa *)((caddr_t)altcoa + 2 + altcoa->ip6moa_len); + break; + + case IP6_MHOPT_ALTCOA: + /* This is what we were looking for. We save CoA in sa2_src */ + if (len < sizeof (*altcoa)) + goto skippa; + + /* cache the right address to use in src2 */ + rc->sa2_src = (struct sockaddr *)&rc->sa2_src_storage; + src6 = (struct sockaddr_in6 *)rc->sa2_src; + bzero(src6, sizeof(struct sockaddr_in6)); + src6->sin6_family = AF_INET6; + #ifdef HAVE_SA_LEN + src6->sin6_len = sizeof(*src6); + #endif + + memcpy(&src6->sin6_addr, &altcoa->ip6moa_addr, sizeof(altcoa->ip6moa_addr)); + goto skippa; /* we are done here */ + + default: + /* not implemented yet */ + goto skippa; + } skippa: #endif diff -Nur racoon2-20070817cvs/lib/mipv6aux.h racoon2-patched/lib/mipv6aux.h --- racoon2-20070817cvs/lib/mipv6aux.h 2007-08-17 10:57:42.000000000 +0900 +++ racoon2-patched/lib/mipv6aux.h 2007-08-17 11:52:12.000000000 +0900 @@ -103,6 +103,26 @@ /* followed by mobility options */ } __attribute__((__packed__)); -#define IP6_MH_BU_HOME 0x4000 /* home registration */ +/* ip6mhbu_flags */ +#if BYTE_ORDER == BIG_ENDIAN +#define IP6_MH_BU_HOME 0x4000 /* Home Registration */ +#else /* BYTE_ORDER == LITTLE_ENDIAN */ +#define IP6_MH_BU_HOME 0x0040 /* Home Registration */ +#endif + +#define IP6_MHOPT_PAD1 0x00 /* PAD1 */ +#define IP6_MHOPT_PADN 0x01 /* PADN */ +#define IP6_MHOPT_BREFRESH 0x02 /* Binding Refresh */ +#define IP6_MHOPT_ALTCOA 0x03 /* Alternate COA */ +#define IP6_MHOPT_NONCEID 0x04 /* Nonce Index */ +#define IP6_MHOPT_BAUTH 0x05 /* Binding Auth Data */ +#define IP6_MHOPT_MOB_NET_PRFX 0x06 /* Mobile Network Prefix */ + +struct ip6_mh_opt_altcoa { + uint8_t ip6moa_type; + uint8_t ip6moa_len; + struct in6_addr ip6moa_addr; /* Alternate Care-of Address */ +} __attribute__ ((packed)); + #endif