Index: head/sys/netinet6/in6.c =================================================================== --- head/sys/netinet6/in6.c (revision 245251) +++ head/sys/netinet6/in6.c (working copy) @@ -2055,6 +2055,10 @@ ip6_sprintf(char *ip6buf, const struct in6_addr *a return (ip6buf); } +/* + * Return 1 if an internet address is for a ``local'' host + * (one to which we have a connection). + */ int in6_localaddr(struct in6_addr *in6) { @@ -2096,7 +2100,32 @@ in6_localip(struct in6_addr *in6) return (0); } +/* + * Return 1 if an internet address is configured on the given interface. + */ int +in6_ifpwithaddr(struct ifnet *ifp, struct in6_addr *in6) +{ + struct in6_addr addr; + struct in6_ifaddr *ia; + + addr = *in6; + if (in6_setscope(&addr, ifp, NULL)) + return (0); + + IN6_IFADDR_RLOCK(); + LIST_FOREACH(ia, IN6ADDR_HASH(&addr), ia6_hash) { + if (IN6_ARE_ADDR_EQUAL(&addr, &ia->ia_addr.sin6_addr) && + ia->ia_ifp == ifp) { + IN6_IFADDR_RUNLOCK(); + return (1); + } + } + IN6_IFADDR_RUNLOCK(); + return (0); +} + +int in6_is_addr_deprecated(struct sockaddr_in6 *sa6) { struct in6_ifaddr *ia; Index: head/sys/netinet6/in6.h =================================================================== --- head/sys/netinet6/in6.h (revision 245251) +++ head/sys/netinet6/in6.h (working copy) @@ -638,6 +638,7 @@ int in6_cksum_pseudo(struct ip6_hdr *, uint32_t, u int in6_cksum(struct mbuf *, u_int8_t, u_int32_t, u_int32_t); int in6_localaddr(struct in6_addr *); int in6_localip(struct in6_addr *); +int in6_ifpwithaddr(struct ifnet *ifp, struct in6_addr *in6); int in6_addrscope(struct in6_addr *); struct in6_ifaddr *in6_ifawithifp(struct ifnet *, struct in6_addr *); extern void in6_if_up(struct ifnet *); Index: head/sys/netpfil/ipfw/ip_fw2.c =================================================================== --- head/sys/netpfil/ipfw/ip_fw2.c (revision 245251) +++ head/sys/netpfil/ipfw/ip_fw2.c (working copy) @@ -477,35 +477,7 @@ flow6id_match( int curr_flow, ipfw_insn_u32 *cmd ) return 0; } -/* support for IP6_*_ME opcodes */ static int -search_ip6_addr_net (struct in6_addr * ip6_addr) -{ - struct ifnet *mdc; - struct ifaddr *mdc2; - struct in6_ifaddr *fdm; - struct in6_addr copia; - - TAILQ_FOREACH(mdc, &V_ifnet, if_link) { - if_addr_rlock(mdc); - TAILQ_FOREACH(mdc2, &mdc->if_addrhead, ifa_link) { - if (mdc2->ifa_addr->sa_family == AF_INET6) { - fdm = (struct in6_ifaddr *)mdc2; - copia = fdm->ia_addr.sin6_addr; - /* need for leaving scope_id in the sock_addr */ - in6_clearscope(&copia); - if (IN6_ARE_ADDR_EQUAL(ip6_addr, &copia)) { - if_addr_runlock(mdc); - return 1; - } - } - } - if_addr_runlock(mdc); - } - return 0; -} - -static int verify_path6(struct in6_addr *src, struct ifnet *ifp, u_int fib) { struct route_in6 ro; @@ -1497,7 +1469,8 @@ do { \ #ifdef INET6 /* FALLTHROUGH */ case O_IP6_SRC_ME: - match= is_ipv6 && search_ip6_addr_net(&args->f_id.src_ip6); + match = is_ipv6 && oif && + in6_ifpwithaddr(oif, &args->f_id.src_ip6); #endif break; @@ -1536,7 +1509,9 @@ do { \ #ifdef INET6 /* FALLTHROUGH */ case O_IP6_DST_ME: - match= is_ipv6 && search_ip6_addr_net(&args->f_id.dst_ip6); + match = is_ipv6 && m->m_pkthdr.rcvif && + in6_ifpwithaddr(m->m_pkthdr.rcvif, + &args->f_id.dst_ip6); #endif break;