1686cdd19SJun-ichiro itojun Hagino /* $FreeBSD$ */ 233841545SHajimu UMEMOTO /* $KAME: in_gif.c,v 1.54 2001/05/14 14:02:16 itojun Exp $ */ 3686cdd19SJun-ichiro itojun Hagino 4cfa1ca9dSYoshinobu Inoue /* 5cfa1ca9dSYoshinobu Inoue * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. 6cfa1ca9dSYoshinobu Inoue * All rights reserved. 7cfa1ca9dSYoshinobu Inoue * 8cfa1ca9dSYoshinobu Inoue * Redistribution and use in source and binary forms, with or without 9cfa1ca9dSYoshinobu Inoue * modification, are permitted provided that the following conditions 10cfa1ca9dSYoshinobu Inoue * are met: 11cfa1ca9dSYoshinobu Inoue * 1. Redistributions of source code must retain the above copyright 12cfa1ca9dSYoshinobu Inoue * notice, this list of conditions and the following disclaimer. 13cfa1ca9dSYoshinobu Inoue * 2. Redistributions in binary form must reproduce the above copyright 14cfa1ca9dSYoshinobu Inoue * notice, this list of conditions and the following disclaimer in the 15cfa1ca9dSYoshinobu Inoue * documentation and/or other materials provided with the distribution. 16cfa1ca9dSYoshinobu Inoue * 3. Neither the name of the project nor the names of its contributors 17cfa1ca9dSYoshinobu Inoue * may be used to endorse or promote products derived from this software 18cfa1ca9dSYoshinobu Inoue * without specific prior written permission. 19cfa1ca9dSYoshinobu Inoue * 20cfa1ca9dSYoshinobu Inoue * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND 21cfa1ca9dSYoshinobu Inoue * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22cfa1ca9dSYoshinobu Inoue * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23cfa1ca9dSYoshinobu Inoue * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE 24cfa1ca9dSYoshinobu Inoue * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25cfa1ca9dSYoshinobu Inoue * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26cfa1ca9dSYoshinobu Inoue * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27cfa1ca9dSYoshinobu Inoue * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28cfa1ca9dSYoshinobu Inoue * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29cfa1ca9dSYoshinobu Inoue * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30cfa1ca9dSYoshinobu Inoue * SUCH DAMAGE. 31cfa1ca9dSYoshinobu Inoue */ 32cfa1ca9dSYoshinobu Inoue 33cfa1ca9dSYoshinobu Inoue #include "opt_mrouting.h" 34686cdd19SJun-ichiro itojun Hagino #include "opt_inet.h" 35cfa1ca9dSYoshinobu Inoue #include "opt_inet6.h" 36cfa1ca9dSYoshinobu Inoue 37cfa1ca9dSYoshinobu Inoue #include <sys/param.h> 38cfa1ca9dSYoshinobu Inoue #include <sys/systm.h> 39cfa1ca9dSYoshinobu Inoue #include <sys/socket.h> 40cfa1ca9dSYoshinobu Inoue #include <sys/sockio.h> 41cfa1ca9dSYoshinobu Inoue #include <sys/mbuf.h> 42cfa1ca9dSYoshinobu Inoue #include <sys/errno.h> 43cfa1ca9dSYoshinobu Inoue #include <sys/kernel.h> 44cfa1ca9dSYoshinobu Inoue #include <sys/sysctl.h> 459426aedfSHajimu UMEMOTO #include <sys/protosw.h> 46686cdd19SJun-ichiro itojun Hagino 47686cdd19SJun-ichiro itojun Hagino #include <sys/malloc.h> 48cfa1ca9dSYoshinobu Inoue 49cfa1ca9dSYoshinobu Inoue #include <net/if.h> 50cfa1ca9dSYoshinobu Inoue #include <net/route.h> 51cfa1ca9dSYoshinobu Inoue 52cfa1ca9dSYoshinobu Inoue #include <netinet/in.h> 53cfa1ca9dSYoshinobu Inoue #include <netinet/in_systm.h> 54cfa1ca9dSYoshinobu Inoue #include <netinet/ip.h> 556a800098SYoshinobu Inoue #include <netinet/ip_var.h> 566a800098SYoshinobu Inoue #include <netinet/in_gif.h> 57686cdd19SJun-ichiro itojun Hagino #include <netinet/in_var.h> 58686cdd19SJun-ichiro itojun Hagino #include <netinet/ip_encap.h> 596a800098SYoshinobu Inoue #include <netinet/ip_ecn.h> 60686cdd19SJun-ichiro itojun Hagino 616a800098SYoshinobu Inoue #ifdef INET6 62686cdd19SJun-ichiro itojun Hagino #include <netinet/ip6.h> 636a800098SYoshinobu Inoue #endif 64cfa1ca9dSYoshinobu Inoue 65cfa1ca9dSYoshinobu Inoue #ifdef MROUTING 66cfa1ca9dSYoshinobu Inoue #include <netinet/ip_mroute.h> 67cfa1ca9dSYoshinobu Inoue #endif /* MROUTING */ 68cfa1ca9dSYoshinobu Inoue 69cfa1ca9dSYoshinobu Inoue #include <net/if_gif.h> 70cfa1ca9dSYoshinobu Inoue 71cfa1ca9dSYoshinobu Inoue #include <net/net_osdep.h> 72cfa1ca9dSYoshinobu Inoue 739426aedfSHajimu UMEMOTO static int gif_validate4(const struct ip *, struct gif_softc *, 749426aedfSHajimu UMEMOTO struct ifnet *); 759426aedfSHajimu UMEMOTO 769426aedfSHajimu UMEMOTO extern struct domain inetdomain; 779426aedfSHajimu UMEMOTO struct protosw in_gif_protosw = 789426aedfSHajimu UMEMOTO { SOCK_RAW, &inetdomain, 0/* IPPROTO_IPV[46] */, PR_ATOMIC|PR_ADDR, 799426aedfSHajimu UMEMOTO in_gif_input, (pr_output_t*)rip_output, 0, rip_ctloutput, 809426aedfSHajimu UMEMOTO 0, 819426aedfSHajimu UMEMOTO 0, 0, 0, 0, 829426aedfSHajimu UMEMOTO &rip_usrreqs 839426aedfSHajimu UMEMOTO }; 849426aedfSHajimu UMEMOTO 85673623b3SBrooks Davis static int ip_gif_ttl = GIF_TTL; 86cfa1ca9dSYoshinobu Inoue SYSCTL_INT(_net_inet_ip, IPCTL_GIF_TTL, gifttl, CTLFLAG_RW, 87cfa1ca9dSYoshinobu Inoue &ip_gif_ttl, 0, ""); 88cfa1ca9dSYoshinobu Inoue 89cfa1ca9dSYoshinobu Inoue int 90b6e28453SHajimu UMEMOTO in_gif_output(ifp, family, m) 91cfa1ca9dSYoshinobu Inoue struct ifnet *ifp; 92cfa1ca9dSYoshinobu Inoue int family; 93cfa1ca9dSYoshinobu Inoue struct mbuf *m; 94cfa1ca9dSYoshinobu Inoue { 9533841545SHajimu UMEMOTO struct gif_softc *sc = (struct gif_softc*)ifp; 96cfa1ca9dSYoshinobu Inoue struct sockaddr_in *dst = (struct sockaddr_in *)&sc->gif_ro.ro_dst; 97cfa1ca9dSYoshinobu Inoue struct sockaddr_in *sin_src = (struct sockaddr_in *)sc->gif_psrc; 98cfa1ca9dSYoshinobu Inoue struct sockaddr_in *sin_dst = (struct sockaddr_in *)sc->gif_pdst; 99cfa1ca9dSYoshinobu Inoue struct ip iphdr; /* capsule IP header, host byte ordered */ 100cfa1ca9dSYoshinobu Inoue int proto, error; 101cfa1ca9dSYoshinobu Inoue u_int8_t tos; 102cfa1ca9dSYoshinobu Inoue 103cfa1ca9dSYoshinobu Inoue if (sin_src == NULL || sin_dst == NULL || 104cfa1ca9dSYoshinobu Inoue sin_src->sin_family != AF_INET || 105cfa1ca9dSYoshinobu Inoue sin_dst->sin_family != AF_INET) { 106cfa1ca9dSYoshinobu Inoue m_freem(m); 107cfa1ca9dSYoshinobu Inoue return EAFNOSUPPORT; 108cfa1ca9dSYoshinobu Inoue } 109cfa1ca9dSYoshinobu Inoue 110cfa1ca9dSYoshinobu Inoue switch (family) { 111686cdd19SJun-ichiro itojun Hagino #ifdef INET 112cfa1ca9dSYoshinobu Inoue case AF_INET: 113cfa1ca9dSYoshinobu Inoue { 114cfa1ca9dSYoshinobu Inoue struct ip *ip; 115cfa1ca9dSYoshinobu Inoue 116cfa1ca9dSYoshinobu Inoue proto = IPPROTO_IPV4; 117cfa1ca9dSYoshinobu Inoue if (m->m_len < sizeof(*ip)) { 118cfa1ca9dSYoshinobu Inoue m = m_pullup(m, sizeof(*ip)); 119cfa1ca9dSYoshinobu Inoue if (!m) 120cfa1ca9dSYoshinobu Inoue return ENOBUFS; 121cfa1ca9dSYoshinobu Inoue } 122cfa1ca9dSYoshinobu Inoue ip = mtod(m, struct ip *); 123cfa1ca9dSYoshinobu Inoue tos = ip->ip_tos; 124cfa1ca9dSYoshinobu Inoue break; 125cfa1ca9dSYoshinobu Inoue } 126686cdd19SJun-ichiro itojun Hagino #endif /* INET */ 127cfa1ca9dSYoshinobu Inoue #ifdef INET6 128cfa1ca9dSYoshinobu Inoue case AF_INET6: 129cfa1ca9dSYoshinobu Inoue { 130686cdd19SJun-ichiro itojun Hagino struct ip6_hdr *ip6; 131cfa1ca9dSYoshinobu Inoue proto = IPPROTO_IPV6; 132cfa1ca9dSYoshinobu Inoue if (m->m_len < sizeof(*ip6)) { 133cfa1ca9dSYoshinobu Inoue m = m_pullup(m, sizeof(*ip6)); 134cfa1ca9dSYoshinobu Inoue if (!m) 135cfa1ca9dSYoshinobu Inoue return ENOBUFS; 136cfa1ca9dSYoshinobu Inoue } 137cfa1ca9dSYoshinobu Inoue ip6 = mtod(m, struct ip6_hdr *); 138cfa1ca9dSYoshinobu Inoue tos = (ntohl(ip6->ip6_flow) >> 20) & 0xff; 139cfa1ca9dSYoshinobu Inoue break; 140cfa1ca9dSYoshinobu Inoue } 141cfa1ca9dSYoshinobu Inoue #endif /* INET6 */ 142cfa1ca9dSYoshinobu Inoue default: 143686cdd19SJun-ichiro itojun Hagino #ifdef DEBUG 144cfa1ca9dSYoshinobu Inoue printf("in_gif_output: warning: unknown family %d passed\n", 145cfa1ca9dSYoshinobu Inoue family); 146cfa1ca9dSYoshinobu Inoue #endif 147cfa1ca9dSYoshinobu Inoue m_freem(m); 148cfa1ca9dSYoshinobu Inoue return EAFNOSUPPORT; 149cfa1ca9dSYoshinobu Inoue } 150cfa1ca9dSYoshinobu Inoue 151cfa1ca9dSYoshinobu Inoue bzero(&iphdr, sizeof(iphdr)); 152cfa1ca9dSYoshinobu Inoue iphdr.ip_src = sin_src->sin_addr; 153cfa1ca9dSYoshinobu Inoue /* bidirectional configured tunnel mode */ 154cfa1ca9dSYoshinobu Inoue if (sin_dst->sin_addr.s_addr != INADDR_ANY) 155cfa1ca9dSYoshinobu Inoue iphdr.ip_dst = sin_dst->sin_addr; 156cfa1ca9dSYoshinobu Inoue else { 157cfa1ca9dSYoshinobu Inoue m_freem(m); 158cfa1ca9dSYoshinobu Inoue return ENETUNREACH; 159cfa1ca9dSYoshinobu Inoue } 160cfa1ca9dSYoshinobu Inoue iphdr.ip_p = proto; 161cfa1ca9dSYoshinobu Inoue /* version will be set in ip_output() */ 162cfa1ca9dSYoshinobu Inoue iphdr.ip_ttl = ip_gif_ttl; 163cfa1ca9dSYoshinobu Inoue iphdr.ip_len = m->m_pkthdr.len + sizeof(struct ip); 16459dfcba4SHajimu UMEMOTO ip_ecn_ingress((ifp->if_flags & IFF_LINK1) ? ECN_ALLOWED : ECN_NOCARE, 16559dfcba4SHajimu UMEMOTO &iphdr.ip_tos, &tos); 166cfa1ca9dSYoshinobu Inoue 167cfa1ca9dSYoshinobu Inoue /* prepend new IP header */ 168a163d034SWarner Losh M_PREPEND(m, sizeof(struct ip), M_DONTWAIT); 169cfa1ca9dSYoshinobu Inoue if (m && m->m_len < sizeof(struct ip)) 170cfa1ca9dSYoshinobu Inoue m = m_pullup(m, sizeof(struct ip)); 171cfa1ca9dSYoshinobu Inoue if (m == NULL) { 172cfa1ca9dSYoshinobu Inoue printf("ENOBUFS in in_gif_output %d\n", __LINE__); 173cfa1ca9dSYoshinobu Inoue return ENOBUFS; 174cfa1ca9dSYoshinobu Inoue } 175686cdd19SJun-ichiro itojun Hagino bcopy(&iphdr, mtod(m, struct ip *), sizeof(struct ip)); 176cfa1ca9dSYoshinobu Inoue 177cfa1ca9dSYoshinobu Inoue if (dst->sin_family != sin_dst->sin_family || 178cfa1ca9dSYoshinobu Inoue dst->sin_addr.s_addr != sin_dst->sin_addr.s_addr) { 179cfa1ca9dSYoshinobu Inoue /* cache route doesn't match */ 180cfa1ca9dSYoshinobu Inoue dst->sin_family = sin_dst->sin_family; 181cfa1ca9dSYoshinobu Inoue dst->sin_len = sizeof(struct sockaddr_in); 182cfa1ca9dSYoshinobu Inoue dst->sin_addr = sin_dst->sin_addr; 183cfa1ca9dSYoshinobu Inoue if (sc->gif_ro.ro_rt) { 184cfa1ca9dSYoshinobu Inoue RTFREE(sc->gif_ro.ro_rt); 185cfa1ca9dSYoshinobu Inoue sc->gif_ro.ro_rt = NULL; 186cfa1ca9dSYoshinobu Inoue } 187686cdd19SJun-ichiro itojun Hagino #if 0 188686cdd19SJun-ichiro itojun Hagino sc->gif_if.if_mtu = GIF_MTU; 189686cdd19SJun-ichiro itojun Hagino #endif 190cfa1ca9dSYoshinobu Inoue } 191cfa1ca9dSYoshinobu Inoue 192cfa1ca9dSYoshinobu Inoue if (sc->gif_ro.ro_rt == NULL) { 193cfa1ca9dSYoshinobu Inoue rtalloc(&sc->gif_ro); 194cfa1ca9dSYoshinobu Inoue if (sc->gif_ro.ro_rt == NULL) { 195cfa1ca9dSYoshinobu Inoue m_freem(m); 196cfa1ca9dSYoshinobu Inoue return ENETUNREACH; 197cfa1ca9dSYoshinobu Inoue } 198686cdd19SJun-ichiro itojun Hagino 199686cdd19SJun-ichiro itojun Hagino /* if it constitutes infinite encapsulation, punt. */ 200686cdd19SJun-ichiro itojun Hagino if (sc->gif_ro.ro_rt->rt_ifp == ifp) { 201686cdd19SJun-ichiro itojun Hagino m_freem(m); 202686cdd19SJun-ichiro itojun Hagino return ENETUNREACH; /* XXX */ 203686cdd19SJun-ichiro itojun Hagino } 204686cdd19SJun-ichiro itojun Hagino #if 0 205686cdd19SJun-ichiro itojun Hagino ifp->if_mtu = sc->gif_ro.ro_rt->rt_ifp->if_mtu 206686cdd19SJun-ichiro itojun Hagino - sizeof(struct ip); 207686cdd19SJun-ichiro itojun Hagino #endif 208cfa1ca9dSYoshinobu Inoue } 209cfa1ca9dSYoshinobu Inoue 2105d846453SSam Leffler error = ip_output(m, NULL, &sc->gif_ro, 0, NULL, NULL); 211cfa1ca9dSYoshinobu Inoue return (error); 212cfa1ca9dSYoshinobu Inoue } 213cfa1ca9dSYoshinobu Inoue 214cfa1ca9dSYoshinobu Inoue void 215f0ffb944SJulian Elischer in_gif_input(m, off) 216686cdd19SJun-ichiro itojun Hagino struct mbuf *m; 21753dab5feSBrooks Davis int off; 218cfa1ca9dSYoshinobu Inoue { 219cfa1ca9dSYoshinobu Inoue struct ifnet *gifp = NULL; 220cfa1ca9dSYoshinobu Inoue struct ip *ip; 221686cdd19SJun-ichiro itojun Hagino int af; 2226a800098SYoshinobu Inoue u_int8_t otos; 223f0ffb944SJulian Elischer int proto; 224cfa1ca9dSYoshinobu Inoue 225cfa1ca9dSYoshinobu Inoue ip = mtod(m, struct ip *); 226f0ffb944SJulian Elischer proto = ip->ip_p; 227cfa1ca9dSYoshinobu Inoue 228686cdd19SJun-ichiro itojun Hagino gifp = (struct ifnet *)encap_getarg(m); 229cfa1ca9dSYoshinobu Inoue 230686cdd19SJun-ichiro itojun Hagino if (gifp == NULL || (gifp->if_flags & IFF_UP) == 0) { 231cfa1ca9dSYoshinobu Inoue m_freem(m); 232cfa1ca9dSYoshinobu Inoue ipstat.ips_nogif++; 233cfa1ca9dSYoshinobu Inoue return; 234cfa1ca9dSYoshinobu Inoue } 235cfa1ca9dSYoshinobu Inoue 2366a800098SYoshinobu Inoue otos = ip->ip_tos; 237cfa1ca9dSYoshinobu Inoue m_adj(m, off); 238cfa1ca9dSYoshinobu Inoue 239cfa1ca9dSYoshinobu Inoue switch (proto) { 240686cdd19SJun-ichiro itojun Hagino #ifdef INET 241cfa1ca9dSYoshinobu Inoue case IPPROTO_IPV4: 242cfa1ca9dSYoshinobu Inoue { 243cfa1ca9dSYoshinobu Inoue struct ip *ip; 244cfa1ca9dSYoshinobu Inoue af = AF_INET; 245cfa1ca9dSYoshinobu Inoue if (m->m_len < sizeof(*ip)) { 246cfa1ca9dSYoshinobu Inoue m = m_pullup(m, sizeof(*ip)); 247cfa1ca9dSYoshinobu Inoue if (!m) 248cfa1ca9dSYoshinobu Inoue return; 249cfa1ca9dSYoshinobu Inoue } 250cfa1ca9dSYoshinobu Inoue ip = mtod(m, struct ip *); 25159dfcba4SHajimu UMEMOTO if (ip_ecn_egress((gifp->if_flags & IFF_LINK1) ? 25259dfcba4SHajimu UMEMOTO ECN_ALLOWED : ECN_NOCARE, 25359dfcba4SHajimu UMEMOTO &otos, &ip->ip_tos) == 0) { 25459dfcba4SHajimu UMEMOTO m_freem(m); 25559dfcba4SHajimu UMEMOTO return; 25659dfcba4SHajimu UMEMOTO } 257cfa1ca9dSYoshinobu Inoue break; 258cfa1ca9dSYoshinobu Inoue } 259686cdd19SJun-ichiro itojun Hagino #endif 260cfa1ca9dSYoshinobu Inoue #ifdef INET6 261cfa1ca9dSYoshinobu Inoue case IPPROTO_IPV6: 262cfa1ca9dSYoshinobu Inoue { 263cfa1ca9dSYoshinobu Inoue struct ip6_hdr *ip6; 26459dfcba4SHajimu UMEMOTO u_int8_t itos, oitos; 26559dfcba4SHajimu UMEMOTO 266cfa1ca9dSYoshinobu Inoue af = AF_INET6; 267cfa1ca9dSYoshinobu Inoue if (m->m_len < sizeof(*ip6)) { 268cfa1ca9dSYoshinobu Inoue m = m_pullup(m, sizeof(*ip6)); 269cfa1ca9dSYoshinobu Inoue if (!m) 270cfa1ca9dSYoshinobu Inoue return; 271cfa1ca9dSYoshinobu Inoue } 272cfa1ca9dSYoshinobu Inoue ip6 = mtod(m, struct ip6_hdr *); 27359dfcba4SHajimu UMEMOTO itos = oitos = (ntohl(ip6->ip6_flow) >> 20) & 0xff; 27459dfcba4SHajimu UMEMOTO if (ip_ecn_egress((gifp->if_flags & IFF_LINK1) ? 27559dfcba4SHajimu UMEMOTO ECN_ALLOWED : ECN_NOCARE, 27659dfcba4SHajimu UMEMOTO &otos, &itos) == 0) { 27759dfcba4SHajimu UMEMOTO m_freem(m); 27859dfcba4SHajimu UMEMOTO return; 27959dfcba4SHajimu UMEMOTO } 28059dfcba4SHajimu UMEMOTO if (itos != oitos) { 281cfa1ca9dSYoshinobu Inoue ip6->ip6_flow &= ~htonl(0xff << 20); 2826a800098SYoshinobu Inoue ip6->ip6_flow |= htonl((u_int32_t)itos << 20); 28359dfcba4SHajimu UMEMOTO } 284cfa1ca9dSYoshinobu Inoue break; 285cfa1ca9dSYoshinobu Inoue } 286cfa1ca9dSYoshinobu Inoue #endif /* INET6 */ 287cfa1ca9dSYoshinobu Inoue default: 288cfa1ca9dSYoshinobu Inoue ipstat.ips_nogif++; 289cfa1ca9dSYoshinobu Inoue m_freem(m); 290cfa1ca9dSYoshinobu Inoue return; 291cfa1ca9dSYoshinobu Inoue } 292cfa1ca9dSYoshinobu Inoue gif_input(m, af, gifp); 293cfa1ca9dSYoshinobu Inoue return; 294cfa1ca9dSYoshinobu Inoue } 295686cdd19SJun-ichiro itojun Hagino 296686cdd19SJun-ichiro itojun Hagino /* 2979426aedfSHajimu UMEMOTO * validate outer address. 298686cdd19SJun-ichiro itojun Hagino */ 2999426aedfSHajimu UMEMOTO static int 3009426aedfSHajimu UMEMOTO gif_validate4(ip, sc, ifp) 3019426aedfSHajimu UMEMOTO const struct ip *ip; 302686cdd19SJun-ichiro itojun Hagino struct gif_softc *sc; 3039426aedfSHajimu UMEMOTO struct ifnet *ifp; 3049426aedfSHajimu UMEMOTO { 305686cdd19SJun-ichiro itojun Hagino struct sockaddr_in *src, *dst; 306686cdd19SJun-ichiro itojun Hagino struct in_ifaddr *ia4; 307686cdd19SJun-ichiro itojun Hagino 308686cdd19SJun-ichiro itojun Hagino src = (struct sockaddr_in *)sc->gif_psrc; 309686cdd19SJun-ichiro itojun Hagino dst = (struct sockaddr_in *)sc->gif_pdst; 310686cdd19SJun-ichiro itojun Hagino 311686cdd19SJun-ichiro itojun Hagino /* check for address match */ 3129426aedfSHajimu UMEMOTO if (src->sin_addr.s_addr != ip->ip_dst.s_addr || 3139426aedfSHajimu UMEMOTO dst->sin_addr.s_addr != ip->ip_src.s_addr) 314686cdd19SJun-ichiro itojun Hagino return 0; 315686cdd19SJun-ichiro itojun Hagino 316686cdd19SJun-ichiro itojun Hagino /* martian filters on outer source - NOT done in ip_input! */ 3179426aedfSHajimu UMEMOTO if (IN_MULTICAST(ntohl(ip->ip_src.s_addr))) 318686cdd19SJun-ichiro itojun Hagino return 0; 3199426aedfSHajimu UMEMOTO switch ((ntohl(ip->ip_src.s_addr) & 0xff000000) >> 24) { 320686cdd19SJun-ichiro itojun Hagino case 0: case 127: case 255: 321686cdd19SJun-ichiro itojun Hagino return 0; 322686cdd19SJun-ichiro itojun Hagino } 323686cdd19SJun-ichiro itojun Hagino /* reject packets with broadcast on source */ 32406cd0a3fSHajimu UMEMOTO TAILQ_FOREACH(ia4, &in_ifaddrhead, ia_link) { 325686cdd19SJun-ichiro itojun Hagino if ((ia4->ia_ifa.ifa_ifp->if_flags & IFF_BROADCAST) == 0) 326686cdd19SJun-ichiro itojun Hagino continue; 3279426aedfSHajimu UMEMOTO if (ip->ip_src.s_addr == ia4->ia_broadaddr.sin_addr.s_addr) 328686cdd19SJun-ichiro itojun Hagino return 0; 329686cdd19SJun-ichiro itojun Hagino } 330686cdd19SJun-ichiro itojun Hagino 331686cdd19SJun-ichiro itojun Hagino /* ingress filters on outer source */ 3329426aedfSHajimu UMEMOTO if ((sc->gif_if.if_flags & IFF_LINK2) == 0 && ifp) { 333686cdd19SJun-ichiro itojun Hagino struct sockaddr_in sin; 334686cdd19SJun-ichiro itojun Hagino struct rtentry *rt; 335686cdd19SJun-ichiro itojun Hagino 336686cdd19SJun-ichiro itojun Hagino bzero(&sin, sizeof(sin)); 337686cdd19SJun-ichiro itojun Hagino sin.sin_family = AF_INET; 338686cdd19SJun-ichiro itojun Hagino sin.sin_len = sizeof(struct sockaddr_in); 3399426aedfSHajimu UMEMOTO sin.sin_addr = ip->ip_src; 340686cdd19SJun-ichiro itojun Hagino rt = rtalloc1((struct sockaddr *)&sin, 0, 0UL); 3419426aedfSHajimu UMEMOTO if (!rt || rt->rt_ifp != ifp) { 34233841545SHajimu UMEMOTO #if 0 34333841545SHajimu UMEMOTO log(LOG_WARNING, "%s: packet from 0x%x dropped " 34433841545SHajimu UMEMOTO "due to ingress filter\n", if_name(&sc->gif_if), 34533841545SHajimu UMEMOTO (u_int32_t)ntohl(sin.sin_addr.s_addr)); 34633841545SHajimu UMEMOTO #endif 34733841545SHajimu UMEMOTO if (rt) 348686cdd19SJun-ichiro itojun Hagino rtfree(rt); 349686cdd19SJun-ichiro itojun Hagino return 0; 350686cdd19SJun-ichiro itojun Hagino } 351686cdd19SJun-ichiro itojun Hagino rtfree(rt); 352686cdd19SJun-ichiro itojun Hagino } 353686cdd19SJun-ichiro itojun Hagino 35433841545SHajimu UMEMOTO return 32 * 2; 355686cdd19SJun-ichiro itojun Hagino } 3569426aedfSHajimu UMEMOTO 3579426aedfSHajimu UMEMOTO /* 3589426aedfSHajimu UMEMOTO * we know that we are in IFF_UP, outer address available, and outer family 3599426aedfSHajimu UMEMOTO * matched the physical addr family. see gif_encapcheck(). 3609426aedfSHajimu UMEMOTO */ 3619426aedfSHajimu UMEMOTO int 3629426aedfSHajimu UMEMOTO gif_encapcheck4(m, off, proto, arg) 3639426aedfSHajimu UMEMOTO const struct mbuf *m; 3649426aedfSHajimu UMEMOTO int off; 3659426aedfSHajimu UMEMOTO int proto; 3669426aedfSHajimu UMEMOTO void *arg; 3679426aedfSHajimu UMEMOTO { 3689426aedfSHajimu UMEMOTO struct ip ip; 3699426aedfSHajimu UMEMOTO struct gif_softc *sc; 3709426aedfSHajimu UMEMOTO struct ifnet *ifp; 3719426aedfSHajimu UMEMOTO 3729426aedfSHajimu UMEMOTO /* sanity check done in caller */ 3739426aedfSHajimu UMEMOTO sc = (struct gif_softc *)arg; 3749426aedfSHajimu UMEMOTO 3759426aedfSHajimu UMEMOTO /* LINTED const cast */ 3769426aedfSHajimu UMEMOTO m_copydata(m, 0, sizeof(ip), (caddr_t)&ip); 3779426aedfSHajimu UMEMOTO ifp = ((m->m_flags & M_PKTHDR) != 0) ? m->m_pkthdr.rcvif : NULL; 3789426aedfSHajimu UMEMOTO 3799426aedfSHajimu UMEMOTO return gif_validate4(&ip, sc, ifp); 3809426aedfSHajimu UMEMOTO } 3819426aedfSHajimu UMEMOTO 3829426aedfSHajimu UMEMOTO int 3839426aedfSHajimu UMEMOTO in_gif_attach(sc) 3849426aedfSHajimu UMEMOTO struct gif_softc *sc; 3859426aedfSHajimu UMEMOTO { 3869426aedfSHajimu UMEMOTO sc->encap_cookie4 = encap_attach_func(AF_INET, -1, gif_encapcheck, 3879426aedfSHajimu UMEMOTO &in_gif_protosw, sc); 3889426aedfSHajimu UMEMOTO if (sc->encap_cookie4 == NULL) 3899426aedfSHajimu UMEMOTO return EEXIST; 3909426aedfSHajimu UMEMOTO return 0; 3919426aedfSHajimu UMEMOTO } 3929426aedfSHajimu UMEMOTO 3939426aedfSHajimu UMEMOTO int 3949426aedfSHajimu UMEMOTO in_gif_detach(sc) 3959426aedfSHajimu UMEMOTO struct gif_softc *sc; 3969426aedfSHajimu UMEMOTO { 3979426aedfSHajimu UMEMOTO int error; 3989426aedfSHajimu UMEMOTO 3999426aedfSHajimu UMEMOTO error = encap_detach(sc->encap_cookie4); 4009426aedfSHajimu UMEMOTO if (error == 0) 4019426aedfSHajimu UMEMOTO sc->encap_cookie4 = NULL; 4029426aedfSHajimu UMEMOTO return error; 4039426aedfSHajimu UMEMOTO } 404