diff options
author | mlaier <mlaier@FreeBSD.org> | 2005-06-16 14:55:58 +0000 |
---|---|---|
committer | mlaier <mlaier@FreeBSD.org> | 2005-06-16 14:55:58 +0000 |
commit | 702ab5eeef28a41f6e077de94fa304108b0f11e1 (patch) | |
tree | 41070e3dc757b861e5c7eaa98fe51fd3cbd7b73e /sys/netinet/ip_fw2.c | |
parent | 79dda5190c963b5c7a75279b19c176e33272925a (diff) | |
download | FreeBSD-src-702ab5eeef28a41f6e077de94fa304108b0f11e1.zip FreeBSD-src-702ab5eeef28a41f6e077de94fa304108b0f11e1.tar.gz |
In verify_rev_path6():
- do not use static memory as we are under a shared lock only
- properly rtfree routes allocated with rtalloc
- rename to verify_path6()
- implement the full functionality of the IPv4 version
Also make O_ANTISPOOF work with IPv6.
Reviewed by: gnn
Approved by: re (blanket)
Diffstat (limited to 'sys/netinet/ip_fw2.c')
-rw-r--r-- | sys/netinet/ip_fw2.c | 70 |
1 files changed, 52 insertions, 18 deletions
diff --git a/sys/netinet/ip_fw2.c b/sys/netinet/ip_fw2.c index c273791..3ad2932 100644 --- a/sys/netinet/ip_fw2.c +++ b/sys/netinet/ip_fw2.c @@ -605,24 +605,45 @@ search_ip6_addr_net (struct in6_addr * ip6_addr) } static int -verify_rev_path6(struct in6_addr *src, struct ifnet *ifp) +verify_path6(struct in6_addr *src, struct ifnet *ifp) { - static struct route_in6 ro; + struct route_in6 ro; struct sockaddr_in6 *dst; + bzero(&ro, sizeof(ro)); + dst = (struct sockaddr_in6 * )&(ro.ro_dst); + dst->sin6_family = AF_INET6; + dst->sin6_len = sizeof(*dst); + dst->sin6_addr = *src; + rtalloc_ign((struct route *)&ro, RTF_CLONING); + + if (ro.ro_rt == NULL) + return 0; - if ( !(IN6_ARE_ADDR_EQUAL (src, &dst->sin6_addr) )) { - bzero(dst, sizeof(*dst)); - dst->sin6_family = AF_INET6; - dst->sin6_len = sizeof(*dst); - dst->sin6_addr = *src; - rtalloc_ign((struct route *)&ro, RTF_CLONING); + /* if ifp is provided, check for equality with rtentry */ + if (ifp != NULL && ro.ro_rt->rt_ifp != ifp) { + RTFREE(ro.ro_rt); + return 0; } - if ((ro.ro_rt == NULL) || (ifp == NULL) || - (ro.ro_rt->rt_ifp->if_index != ifp->if_index)) + + /* if no ifp provided, check if rtentry is not default route */ + if (ifp == NULL && + IN6_IS_ADDR_UNSPECIFIED(&satosin6(rt_key(ro.ro_rt))->sin6_addr)) { + RTFREE(ro.ro_rt); + return 0; + } + + /* or if this is a blackhole/reject route */ + if (ifp == NULL && ro.ro_rt->rt_flags & (RTF_REJECT|RTF_BLACKHOLE)) { + RTFREE(ro.ro_rt); return 0; + } + + /* found valid route */ + RTFREE(ro.ro_rt); return 1; + } static __inline int hash_packet6(struct ipfw_flow_id *id) @@ -2591,13 +2612,12 @@ check_body: case O_VERREVPATH: /* Outgoing packets automatically pass/match */ - /* XXX BED: verify_path was verify_rev_path in the diff... */ match = ((oif != NULL) || (m->m_pkthdr.rcvif == NULL) || ( #ifdef INET6 is_ipv6 ? - verify_rev_path6(&(args->f_id.src_ip6), + verify_path6(&(args->f_id.src_ip6), m->m_pkthdr.rcvif) : #endif verify_path(src_ip, m->m_pkthdr.rcvif))); @@ -2605,18 +2625,32 @@ check_body: case O_VERSRCREACH: /* Outgoing packets automatically pass/match */ - /* XXX: IPv6 missing!?! */ match = (hlen > 0 && ((oif != NULL) || - (is_ipv4 && verify_path(src_ip, NULL)))); +#ifdef INET6 + is_ipv6 ? + verify_path6(&(args->f_id.src_ip6), + NULL) : +#endif + verify_path(src_ip, NULL))); break; case O_ANTISPOOF: /* Outgoing packets automatically pass/match */ - /* XXX: IPv6 missing!?! */ if (oif == NULL && hlen > 0 && - (is_ipv4 && in_localaddr(src_ip))) - match = verify_path(src_ip, - m->m_pkthdr.rcvif); + ( (is_ipv4 && in_localaddr(src_ip)) +#ifdef INET6 + || (is_ipv6 && + in6_localaddr(&(args->f_id.src_ip6))) +#endif + )) + match = +#ifdef INET6 + is_ipv6 ? verify_path6( + &(args->f_id.src_ip6), + m->m_pkthdr.rcvif) : +#endif + verify_path(src_ip, + m->m_pkthdr.rcvif); else match = 1; break; |