Index: ossp-pkg/sa/sa.c RCS File: /v/ossp/cvs/ossp-pkg/sa/sa.c,v rcsdiff -q -kk '-r1.35' '-r1.36' -u '/v/ossp/cvs/ossp-pkg/sa/sa.c,v' 2>/dev/null --- sa.c 2001/10/24 11:43:28 1.35 +++ sa.c 2001/10/24 12:11:31 1.36 @@ -697,9 +697,12 @@ const unsigned char *ucp1, *ucp2; unsigned int uc1, uc2, mask; size_t l1, l2; - int nFamily; int nBytes; int nBits; +#ifdef AF_INET6 + int i; + const unsigned char *ucp0; +#endif /* argument sanity check(s) */ if (saa1 == NULL || saa2 == NULL || prefixlen < -1) @@ -709,13 +712,8 @@ if (prefixlen == 0) return SA_OK; - /* short circuiting handling different families */ - if (saa1->nFamily != saa2->nFamily) - return SA_ERR_MTC; - /* determine address representation pointer and size */ - nFamily = saa1->nFamily; - if (nFamily == AF_LOCAL) { + if (saa1->nFamily == AF_LOCAL) { ucp1 = (const unsigned char *)(((struct sockaddr_un *)saa1->saBuf)->sun_path); ucp2 = (const unsigned char *)(((struct sockaddr_un *)saa2->saBuf)->sun_path); l1 = strlen(((struct sockaddr_un *)saa1->saBuf)->sun_path) * 8; @@ -731,13 +729,38 @@ nBits = prefixlen; } } - else if (nFamily == AF_INET) { +#ifdef AF_INET6 + else if ( (saa1->nFamily == AF_INET && saa2->nFamily == AF_INET6) + || (saa1->nFamily == AF_INET6 && saa2->nFamily == AF_INET )) { + /* special case of comparing a regular IPv4 address (1.2.3.4) with an + "IPv4-mapped IPv6 address" (::ffff:1.2.3.4). For details see RFC 2373. */ + if (saa1->nFamily == AF_INET6) { + ucp1 = (const unsigned char *)&(((struct sockaddr_in6 *)saa1->saBuf)->sin6_addr); + ucp2 = (const unsigned char *)&(((struct sockaddr_in *)saa2->saBuf)->sin_addr); + ucp0 = ucp1; + ucp1 += 12; + } + else { + ucp1 = (const unsigned char *)&(((struct sockaddr_in *)saa1->saBuf)->sin_addr); + ucp2 = (const unsigned char *)&(((struct sockaddr_in6 *)saa2->saBuf)->sin6_addr); + ucp0 = ucp2; + ucp2 += 12; + } + for (i = 0; i < 10; i++) + if (ucp0[i] != 0x00) + return SA_ERR_MTC; + if (!(ucp0[10] == 0xFF && ucp0[11] == 0xFF)) + return SA_ERR_MTC; + nBits = 32; + } +#endif + else if (saa1->nFamily == AF_INET) { ucp1 = (const unsigned char *)&(((struct sockaddr_in *)saa1->saBuf)->sin_addr); ucp2 = (const unsigned char *)&(((struct sockaddr_in *)saa2->saBuf)->sin_addr); nBits = 32; } #ifdef AF_INET6 - else if (nFamily == AF_INET6) { + else if (saa1->nFamily == AF_INET6) { ucp1 = (const unsigned char *)&(((struct sockaddr_in6 *)saa1->saBuf)->sin6_addr); ucp2 = (const unsigned char *)&(((struct sockaddr_in6 *)saa2->saBuf)->sin6_addr); nBits = 128;