1 /* $OpenBSD: ip_gre.c,v 1.65 2017/05/30 07:50:37 mpi Exp $ */ 2 /* $NetBSD: ip_gre.c,v 1.9 1999/10/25 19:18:11 drochner Exp $ */ 3 4 /* 5 * Copyright (c) 1998 The NetBSD Foundation, Inc. 6 * All rights reserved. 7 * 8 * This code is derived from software contributed to The NetBSD Foundation 9 * by Heiko W.Rupp <hwr@pilhuhn.de> 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 22 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 24 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 30 * POSSIBILITY OF SUCH DAMAGE. 31 */ 32 33 /* 34 * decapsulate tunneled packets and send them on 35 * output half is in net/if_gre.[ch] 36 * This currently handles IPPROTO_GRE, IPPROTO_MOBILE 37 */ 38 39 40 #include "gre.h" 41 #if NGRE > 0 42 43 #include <sys/param.h> 44 #include <sys/systm.h> 45 #include <sys/mbuf.h> 46 #include <sys/protosw.h> 47 #include <sys/socket.h> 48 #include <sys/socketvar.h> 49 #include <sys/sysctl.h> 50 #include <net/if.h> 51 #include <net/netisr.h> 52 #include <net/route.h> 53 #include <net/bpf.h> 54 55 #include <netinet/in.h> 56 #include <netinet/ip.h> 57 #include <netinet/ip_var.h> 58 #include <netinet/ip_gre.h> 59 #include <netinet/if_ether.h> 60 #include <netinet/in_pcb.h> 61 62 #ifdef MPLS 63 #include <netmpls/mpls.h> 64 #endif 65 66 #include "bpfilter.h" 67 #include "pf.h" 68 69 #if NPF > 0 70 #include <net/pfvar.h> 71 #endif 72 73 #ifdef PIPEX 74 #include <net/pipex.h> 75 #endif 76 77 /* Needs IP headers. */ 78 #include <net/if_gre.h> 79 80 struct gre_softc *gre_lookup(struct mbuf *, u_int8_t); 81 int gre_input2(struct mbuf *, int, int); 82 83 /* 84 * Decapsulate. 85 * Does the real work and is called from gre_input() (above) 86 * returns 0 if packet is not yet processed 87 * and 1 if it needs no further processing 88 * proto is the protocol number of the "calling" foo_input() 89 * routine. 90 */ 91 92 int 93 gre_input2(struct mbuf *m, int hlen, int proto) 94 { 95 struct greip *gip; 96 struct gre_softc *sc; 97 u_short flags; 98 u_int af; 99 100 if ((sc = gre_lookup(m, proto)) == NULL) { 101 /* No matching tunnel or tunnel is down. */ 102 return (0); 103 } 104 105 if (m->m_len < sizeof(*gip)) { 106 m = m_pullup(m, sizeof(*gip)); 107 if (m == NULL) 108 return (ENOBUFS); 109 } 110 gip = mtod(m, struct greip *); 111 112 m->m_pkthdr.ph_ifidx = sc->sc_if.if_index; 113 m->m_pkthdr.ph_rtableid = sc->sc_if.if_rdomain; 114 115 sc->sc_if.if_ipackets++; 116 sc->sc_if.if_ibytes += m->m_pkthdr.len; 117 118 switch (proto) { 119 case IPPROTO_GRE: 120 hlen += sizeof (struct gre_h); 121 122 /* process GRE flags as packet can be of variable len */ 123 flags = ntohs(gip->gi_flags); 124 125 /* Checksum & Offset are present */ 126 if ((flags & GRE_CP) | (flags & GRE_RP)) 127 hlen += 4; 128 129 /* We don't support routing fields (variable length) */ 130 if (flags & GRE_RP) 131 return (0); 132 133 if (flags & GRE_KP) 134 hlen += 4; 135 136 if (flags & GRE_SP) 137 hlen += 4; 138 139 switch (ntohs(gip->gi_ptype)) { /* ethertypes */ 140 case GREPROTO_WCCP: 141 /* WCCP/GRE: 142 * So far as I can see (and test) it seems that Cisco's WCCP 143 * GRE tunnel is precisely a IP-in-GRE tunnel that differs 144 * only in its protocol number. At least, it works for me. 145 * 146 * The Internet Drafts can be found if you look for 147 * the following: 148 * draft-forster-wrec-wccp-v1-00.txt 149 * draft-wilson-wrec-wccp-v2-01.txt 150 * 151 * So yes, we're doing a fall-through (unless, of course, 152 * net.inet.gre.wccp is 0). 153 */ 154 if (!gre_wccp) 155 return (0); 156 /* 157 * For WCCPv2, additionally skip the 4 byte 158 * redirect header. 159 */ 160 if (gre_wccp == 2) 161 hlen += 4; 162 case ETHERTYPE_IP: 163 af = AF_INET; 164 break; 165 #ifdef INET6 166 case ETHERTYPE_IPV6: 167 af = AF_INET6; 168 break; 169 #endif 170 case 0: 171 /* keepalive reply, retrigger hold timer */ 172 gre_recv_keepalive(sc); 173 m_freem(m); 174 return (1); 175 #ifdef MPLS 176 case ETHERTYPE_MPLS: 177 case ETHERTYPE_MPLS_MCAST: 178 mpls_input(m); 179 return (1); 180 #endif 181 default: /* others not yet supported */ 182 return (0); 183 } 184 break; 185 default: 186 /* others not yet supported */ 187 return (0); 188 } 189 190 if (hlen > m->m_pkthdr.len) { 191 m_freem(m); 192 return (EINVAL); 193 } 194 m_adj(m, hlen); 195 196 #if NBPFILTER > 0 197 if (sc->sc_if.if_bpf) 198 bpf_mtap_af(sc->sc_if.if_bpf, af, m, BPF_DIRECTION_IN); 199 #endif 200 201 #if NPF > 0 202 pf_pkt_addr_changed(m); 203 #endif 204 205 switch (af) { 206 case AF_INET: 207 ipv4_input(&sc->sc_if, m); 208 break; 209 #ifdef INET6 210 case AF_INET6: 211 ipv6_input(&sc->sc_if, m); 212 break; 213 #endif 214 default: 215 return (0); 216 } 217 218 219 return (1); /* packet is done, no further processing needed */ 220 } 221 222 /* 223 * Decapsulate a packet and feed it back through ip_input (this 224 * routine is called whenever IP gets a packet with proto type 225 * IPPROTO_GRE and a local destination address). 226 */ 227 int 228 gre_input(struct mbuf **mp, int *offp, int proto, int af) 229 { 230 struct mbuf *m = *mp; 231 int hlen = *offp; 232 int ret; 233 234 if (!gre_allow) { 235 m_freem(m); 236 return IPPROTO_DONE; 237 } 238 239 #ifdef PIPEX 240 if (pipex_enable) { 241 struct pipex_session *session; 242 243 if ((session = pipex_pptp_lookup_session(m)) != NULL) { 244 if (pipex_pptp_input(m, session) == NULL) 245 return IPPROTO_DONE; 246 } 247 } 248 #endif 249 250 ret = gre_input2(m, hlen, proto); 251 /* 252 * ret == 0: packet not processed, but input from here 253 * means no matching tunnel that is up is found. 254 * we inject it to raw ip socket to see if anyone picks it up. 255 * possible that we received a WCCPv1-style GRE packet 256 * but we're not set to accept them. 257 */ 258 if (!ret) 259 return rip_input(mp, offp, proto, af); 260 return IPPROTO_DONE; 261 } 262 263 /* 264 * Input routine for IPPROTO_MOBILE. 265 * This is a little bit different from the other modes, as the 266 * encapsulating header was not prepended, but instead inserted 267 * between IP header and payload. 268 */ 269 270 int 271 gre_mobile_input(struct mbuf **mp, int *offp, int proto, int af) 272 { 273 struct mbuf *m = *mp; 274 struct ip *ip; 275 struct mobip_h *mip; 276 struct gre_softc *sc; 277 u_char osrc = 0; 278 int msiz; 279 280 if (!ip_mobile_allow) { 281 m_freem(m); 282 return IPPROTO_DONE; 283 } 284 285 if ((sc = gre_lookup(m, proto)) == NULL) { 286 /* No matching tunnel or tunnel is down. */ 287 m_freem(m); 288 return IPPROTO_DONE; 289 } 290 291 if (m->m_len < sizeof(*mip)) { 292 m = *mp = m_pullup(m, sizeof(*mip)); 293 if (m == NULL) 294 return IPPROTO_DONE; 295 } 296 ip = mtod(m, struct ip *); 297 mip = mtod(m, struct mobip_h *); 298 299 m->m_pkthdr.ph_ifidx = sc->sc_if.if_index; 300 301 sc->sc_if.if_ipackets++; 302 sc->sc_if.if_ibytes += m->m_pkthdr.len; 303 304 if (ntohs(mip->mh.proto) & MOB_H_SBIT) { 305 osrc = 1; 306 msiz = MOB_H_SIZ_L; 307 mip->mi.ip_src.s_addr = mip->mh.osrc; 308 } else 309 msiz = MOB_H_SIZ_S; 310 311 if (m->m_len < (ip->ip_hl << 2) + msiz) { 312 m = *mp = m_pullup(m, (ip->ip_hl << 2) + msiz); 313 if (m == NULL) 314 return IPPROTO_DONE; 315 ip = mtod(m, struct ip *); 316 mip = mtod(m, struct mobip_h *); 317 } 318 319 mip->mi.ip_dst.s_addr = mip->mh.odst; 320 mip->mi.ip_p = (ntohs(mip->mh.proto) >> 8); 321 322 if (gre_in_cksum((u_short *) &mip->mh, msiz) != 0) { 323 m_freem(m); 324 return IPPROTO_DONE; 325 } 326 327 memmove(ip + (ip->ip_hl << 2), ip + (ip->ip_hl << 2) + msiz, 328 m->m_len - msiz - (ip->ip_hl << 2)); 329 330 m->m_len -= msiz; 331 ip->ip_len = htons(ntohs(ip->ip_len) - msiz); 332 m->m_pkthdr.len -= msiz; 333 334 ip->ip_sum = 0; 335 ip->ip_sum = in_cksum(m,(ip->ip_hl << 2)); 336 337 #if NBPFILTER > 0 338 if (sc->sc_if.if_bpf) 339 bpf_mtap_af(sc->sc_if.if_bpf, AF_INET, m, BPF_DIRECTION_IN); 340 #endif 341 342 #if NPF > 0 343 pf_pkt_addr_changed(m); 344 #endif 345 346 ipv4_input(&sc->sc_if, m); 347 return IPPROTO_DONE; 348 } 349 350 /* 351 * Find the gre interface associated with our src/dst/proto set. 352 */ 353 struct gre_softc * 354 gre_lookup(struct mbuf *m, u_int8_t proto) 355 { 356 struct ip *ip = mtod(m, struct ip *); 357 struct gre_softc *sc; 358 359 LIST_FOREACH(sc, &gre_softc_list, sc_list) { 360 if ((sc->g_dst.s_addr == ip->ip_src.s_addr) && 361 (sc->g_src.s_addr == ip->ip_dst.s_addr) && 362 (sc->g_proto == proto) && 363 (rtable_l2(sc->g_rtableid) == 364 rtable_l2(m->m_pkthdr.ph_rtableid)) && 365 ((sc->sc_if.if_flags & IFF_UP) != 0)) 366 return (sc); 367 } 368 369 return (NULL); 370 } 371 372 int 373 gre_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp, 374 size_t newlen) 375 { 376 /* All sysctl names at this level are terminal. */ 377 if (namelen != 1) 378 return (ENOTDIR); 379 380 switch (name[0]) { 381 case GRECTL_ALLOW: 382 return (sysctl_int(oldp, oldlenp, newp, newlen, &gre_allow)); 383 case GRECTL_WCCP: 384 return (sysctl_int(oldp, oldlenp, newp, newlen, &gre_wccp)); 385 default: 386 return (ENOPROTOOPT); 387 } 388 /* NOTREACHED */ 389 } 390 391 int 392 ipmobile_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, 393 void *newp, size_t newlen) 394 { 395 /* All sysctl names at this level are terminal. */ 396 if (namelen != 1) 397 return (ENOTDIR); 398 399 switch (name[0]) { 400 case MOBILEIPCTL_ALLOW: 401 return (sysctl_int(oldp, oldlenp, newp, newlen, 402 &ip_mobile_allow)); 403 default: 404 return (ENOPROTOOPT); 405 } 406 /* NOTREACHED */ 407 } 408 409 int 410 gre_usrreq(struct socket *so, int req, struct mbuf *m, struct mbuf *nam, 411 struct mbuf *control, struct proc *p) 412 { 413 #ifdef PIPEX 414 struct inpcb *inp = sotoinpcb(so); 415 416 if (inp != NULL && inp->inp_pipex && req == PRU_SEND) { 417 struct sockaddr_in *sin4; 418 struct in_addr *ina_dst; 419 struct pipex_session *session; 420 421 ina_dst = NULL; 422 if ((so->so_state & SS_ISCONNECTED) != 0) { 423 inp = sotoinpcb(so); 424 if (inp) 425 ina_dst = &inp->inp_laddr; 426 } else if (nam) { 427 sin4 = mtod(nam, struct sockaddr_in *); 428 if (nam->m_len == sizeof(struct sockaddr_in) && 429 sin4->sin_family == AF_INET) 430 ina_dst = &sin4->sin_addr; 431 } 432 if (ina_dst != NULL && 433 (session = pipex_pptp_userland_lookup_session_ipv4(m, 434 *ina_dst))) 435 m = pipex_pptp_userland_output(m, session); 436 437 if (m == NULL) 438 return (ENOMEM); 439 } 440 #endif 441 return rip_usrreq(so, req, m, nam, control, p); 442 } 443 #endif /* if NGRE > 0 */ 444