diff options
Diffstat (limited to 'sys/netinet/in_gif.c')
-rw-r--r-- | sys/netinet/in_gif.c | 118 |
1 files changed, 89 insertions, 29 deletions
diff --git a/sys/netinet/in_gif.c b/sys/netinet/in_gif.c index ffd877b..d6508d5 100644 --- a/sys/netinet/in_gif.c +++ b/sys/netinet/in_gif.c @@ -42,6 +42,7 @@ #include <sys/errno.h> #include <sys/kernel.h> #include <sys/sysctl.h> +#include <sys/protosw.h> #include <sys/malloc.h> @@ -69,6 +70,18 @@ #include <net/net_osdep.h> +static int gif_validate4(const struct ip *, struct gif_softc *, + struct ifnet *); + +extern struct domain inetdomain; +struct protosw in_gif_protosw = +{ SOCK_RAW, &inetdomain, 0/*IPPROTO_IPV[46]*/, PR_ATOMIC|PR_ADDR, + in_gif_input, (pr_output_t*)rip_output, 0, rip_ctloutput, + 0, + 0, 0, 0, 0, + &rip_usrreqs +}; + static int ip_gif_ttl = GIF_TTL; SYSCTL_INT(_net_inet_ip, IPCTL_GIF_TTL, gifttl, CTLFLAG_RW, &ip_gif_ttl, 0, ""); @@ -277,43 +290,29 @@ in_gif_input(m, off) } /* - * we know that we are in IFF_UP, outer address available, and outer family - * matched the physical addr family. see gif_encapcheck(). + * validate outer address. */ -int -gif_encapcheck4(m, off, proto, arg) - const struct mbuf *m; - int off; - int proto; - void *arg; -{ - struct ip ip; +static int +gif_validate4(ip, sc, ifp) + const struct ip *ip; struct gif_softc *sc; + struct ifnet *ifp; +{ struct sockaddr_in *src, *dst; - int addrmatch; struct in_ifaddr *ia4; - /* sanity check done in caller */ - sc = (struct gif_softc *)arg; src = (struct sockaddr_in *)sc->gif_psrc; dst = (struct sockaddr_in *)sc->gif_pdst; - /* LINTED const cast */ - m_copydata(m, 0, sizeof(ip), (caddr_t)&ip); - /* check for address match */ - addrmatch = 0; - if (src->sin_addr.s_addr == ip.ip_dst.s_addr) - addrmatch |= 1; - if (dst->sin_addr.s_addr == ip.ip_src.s_addr) - addrmatch |= 2; - if (addrmatch != 3) + if (src->sin_addr.s_addr != ip->ip_dst.s_addr || + dst->sin_addr.s_addr != ip->ip_src.s_addr) return 0; /* martian filters on outer source - NOT done in ip_input! */ - if (IN_MULTICAST(ntohl(ip.ip_src.s_addr))) + if (IN_MULTICAST(ntohl(ip->ip_src.s_addr))) return 0; - switch ((ntohl(ip.ip_src.s_addr) & 0xff000000) >> 24) { + switch ((ntohl(ip->ip_src.s_addr) & 0xff000000) >> 24) { case 0: case 127: case 255: return 0; } @@ -322,22 +321,21 @@ gif_encapcheck4(m, off, proto, arg) { if ((ia4->ia_ifa.ifa_ifp->if_flags & IFF_BROADCAST) == 0) continue; - if (ip.ip_src.s_addr == ia4->ia_broadaddr.sin_addr.s_addr) + if (ip->ip_src.s_addr == ia4->ia_broadaddr.sin_addr.s_addr) return 0; } /* ingress filters on outer source */ - if ((sc->gif_if.if_flags & IFF_LINK2) == 0 && - (m->m_flags & M_PKTHDR) != 0 && m->m_pkthdr.rcvif) { + if ((sc->gif_if.if_flags & IFF_LINK2) == 0 && ifp) { struct sockaddr_in sin; struct rtentry *rt; bzero(&sin, sizeof(sin)); sin.sin_family = AF_INET; sin.sin_len = sizeof(struct sockaddr_in); - sin.sin_addr = ip.ip_src; + sin.sin_addr = ip->ip_src; rt = rtalloc1((struct sockaddr *)&sin, 0, 0UL); - if (!rt || rt->rt_ifp != m->m_pkthdr.rcvif) { + if (!rt || rt->rt_ifp != ifp) { #if 0 log(LOG_WARNING, "%s: packet from 0x%x dropped " "due to ingress filter\n", if_name(&sc->gif_if), @@ -352,3 +350,65 @@ gif_encapcheck4(m, off, proto, arg) return 32 * 2; } + +/* + * we know that we are in IFF_UP, outer address available, and outer family + * matched the physical addr family. see gif_encapcheck(). + */ +int +gif_encapcheck4(m, off, proto, arg) + const struct mbuf *m; + int off; + int proto; + void *arg; +{ + struct ip ip; + struct gif_softc *sc; + struct ifnet *ifp; + + /* sanity check done in caller */ + sc = (struct gif_softc *)arg; + + /* LINTED const cast */ + m_copydata(m, 0, sizeof(ip), (caddr_t)&ip); + ifp = ((m->m_flags & M_PKTHDR) != 0) ? m->m_pkthdr.rcvif : NULL; + + return gif_validate4(&ip, sc, ifp); +} + +int +in_gif_attach(sc) + struct gif_softc *sc; +{ +#ifndef USE_ENCAPCHECK + struct sockaddr_in mask4; + + bzero(&mask4, sizeof(mask4)); + mask4.sin_len = sizeof(struct sockaddr_in); + mask4.sin_addr.s_addr = ~0; + + if (!sc->gif_psrc || !sc->gif_pdst) + return EINVAL; + sc->encap_cookie4 = encap_attach(AF_INET, -1, sc->gif_psrc, + (struct sockaddr *)&mask4, sc->gif_pdst, (struct sockaddr *)&mask4, + (struct protosw *)&in_gif_protosw, sc); +#else + sc->encap_cookie4 = encap_attach_func(AF_INET, -1, gif_encapcheck, + &in_gif_protosw, sc); +#endif + if (sc->encap_cookie4 == NULL) + return EEXIST; + return 0; +} + +int +in_gif_detach(sc) + struct gif_softc *sc; +{ + int error; + + error = encap_detach(sc->encap_cookie4); + if (error == 0) + sc->encap_cookie4 = NULL; + return error; +} |