1 /* $OpenBSD: ip_gre.c,v 1.59 2016/03/04 22:38:23 sashan 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, u_char); 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, u_char proto) 94 { 95 struct greip *gip; 96 struct niqueue *ifq; 97 struct gre_softc *sc; 98 u_short flags; 99 u_int af; 100 101 if ((sc = gre_lookup(m, proto)) == NULL) { 102 /* No matching tunnel or tunnel is down. */ 103 return (0); 104 } 105 106 if (m->m_len < sizeof(*gip)) { 107 m = m_pullup(m, sizeof(*gip)); 108 if (m == NULL) 109 return (ENOBUFS); 110 } 111 gip = mtod(m, struct greip *); 112 113 m->m_pkthdr.ph_ifidx = sc->sc_if.if_index; 114 m->m_pkthdr.ph_rtableid = sc->sc_if.if_rdomain; 115 116 sc->sc_if.if_ipackets++; 117 sc->sc_if.if_ibytes += m->m_pkthdr.len; 118 119 switch (proto) { 120 case IPPROTO_GRE: 121 hlen += sizeof (struct gre_h); 122 123 /* process GRE flags as packet can be of variable len */ 124 flags = ntohs(gip->gi_flags); 125 126 /* Checksum & Offset are present */ 127 if ((flags & GRE_CP) | (flags & GRE_RP)) 128 hlen += 4; 129 130 /* We don't support routing fields (variable length) */ 131 if (flags & GRE_RP) 132 return (0); 133 134 if (flags & GRE_KP) 135 hlen += 4; 136 137 if (flags & GRE_SP) 138 hlen += 4; 139 140 switch (ntohs(gip->gi_ptype)) { /* ethertypes */ 141 case GREPROTO_WCCP: 142 /* WCCP/GRE: 143 * So far as I can see (and test) it seems that Cisco's WCCP 144 * GRE tunnel is precisely a IP-in-GRE tunnel that differs 145 * only in its protocol number. At least, it works for me. 146 * 147 * The Internet Drafts can be found if you look for 148 * the following: 149 * draft-forster-wrec-wccp-v1-00.txt 150 * draft-wilson-wrec-wccp-v2-01.txt 151 * 152 * So yes, we're doing a fall-through (unless, of course, 153 * net.inet.gre.wccp is 0). 154 */ 155 if (!gre_wccp) 156 return (0); 157 /* 158 * For WCCPv2, additionally skip the 4 byte 159 * redirect header. 160 */ 161 if (gre_wccp == 2) 162 hlen += 4; 163 case ETHERTYPE_IP: /* shouldn't need a schednetisr(), as */ 164 ifq = &ipintrq; /* we are in ip_input */ 165 af = AF_INET; 166 break; 167 #ifdef INET6 168 case ETHERTYPE_IPV6: 169 ifq = &ip6intrq; 170 af = AF_INET6; 171 break; 172 #endif 173 case 0: 174 /* keepalive reply, retrigger hold timer */ 175 gre_recv_keepalive(sc); 176 m_freem(m); 177 return (1); 178 #ifdef MPLS 179 case ETHERTYPE_MPLS: 180 case ETHERTYPE_MPLS_MCAST: 181 mpls_input(m); 182 return (1); 183 #endif 184 default: /* others not yet supported */ 185 return (0); 186 } 187 break; 188 default: 189 /* others not yet supported */ 190 return (0); 191 } 192 193 if (hlen > m->m_pkthdr.len) { 194 m_freem(m); 195 return (EINVAL); 196 } 197 m_adj(m, hlen); 198 199 #if NBPFILTER > 0 200 if (sc->sc_if.if_bpf) 201 bpf_mtap_af(sc->sc_if.if_bpf, af, m, BPF_DIRECTION_IN); 202 #endif 203 204 #if NPF > 0 205 pf_pkt_addr_changed(m); 206 #endif 207 208 niq_enqueue(ifq, m); 209 210 return (1); /* packet is done, no further processing needed */ 211 } 212 213 /* 214 * Decapsulate a packet and feed it back through ip_input (this 215 * routine is called whenever IP gets a packet with proto type 216 * IPPROTO_GRE and a local destination address). 217 */ 218 void 219 gre_input(struct mbuf *m, ...) 220 { 221 int hlen, ret; 222 va_list ap; 223 224 va_start(ap, m); 225 hlen = va_arg(ap, int); 226 va_end(ap); 227 228 if (!gre_allow) { 229 m_freem(m); 230 return; 231 } 232 233 #ifdef PIPEX 234 if (pipex_enable) { 235 struct pipex_session *session; 236 237 if ((session = pipex_pptp_lookup_session(m)) != NULL) { 238 if (pipex_pptp_input(m, session) == NULL) 239 return; 240 } 241 } 242 #endif 243 244 ret = gre_input2(m, hlen, IPPROTO_GRE); 245 /* 246 * ret == 0: packet not processed, but input from here 247 * means no matching tunnel that is up is found. 248 * we inject it to raw ip socket to see if anyone picks it up. 249 * possible that we received a WCCPv1-style GRE packet 250 * but we're not set to accept them. 251 */ 252 if (!ret) 253 rip_input(m, hlen, IPPROTO_GRE); 254 } 255 256 /* 257 * Input routine for IPPROTO_MOBILE. 258 * This is a little bit different from the other modes, as the 259 * encapsulating header was not prepended, but instead inserted 260 * between IP header and payload. 261 */ 262 263 void 264 gre_mobile_input(struct mbuf *m, ...) 265 { 266 struct ip *ip; 267 struct mobip_h *mip; 268 struct gre_softc *sc; 269 int hlen; 270 va_list ap; 271 u_char osrc = 0; 272 int msiz; 273 274 va_start(ap, m); 275 hlen = va_arg(ap, int); 276 va_end(ap); 277 278 if (!ip_mobile_allow) { 279 m_freem(m); 280 return; 281 } 282 283 if ((sc = gre_lookup(m, IPPROTO_MOBILE)) == NULL) { 284 /* No matching tunnel or tunnel is down. */ 285 m_freem(m); 286 return; 287 } 288 289 if (m->m_len < sizeof(*mip)) { 290 m = m_pullup(m, sizeof(*mip)); 291 if (m == NULL) 292 return; 293 } 294 ip = mtod(m, struct ip *); 295 mip = mtod(m, struct mobip_h *); 296 297 m->m_pkthdr.ph_ifidx = sc->sc_if.if_index; 298 299 sc->sc_if.if_ipackets++; 300 sc->sc_if.if_ibytes += m->m_pkthdr.len; 301 302 if (ntohs(mip->mh.proto) & MOB_H_SBIT) { 303 osrc = 1; 304 msiz = MOB_H_SIZ_L; 305 mip->mi.ip_src.s_addr = mip->mh.osrc; 306 } else 307 msiz = MOB_H_SIZ_S; 308 309 if (m->m_len < (ip->ip_hl << 2) + msiz) { 310 m = m_pullup(m, (ip->ip_hl << 2) + msiz); 311 if (m == NULL) 312 return; 313 ip = mtod(m, struct ip *); 314 mip = mtod(m, struct mobip_h *); 315 } 316 317 mip->mi.ip_dst.s_addr = mip->mh.odst; 318 mip->mi.ip_p = (ntohs(mip->mh.proto) >> 8); 319 320 if (gre_in_cksum((u_short *) &mip->mh, msiz) != 0) { 321 m_freem(m); 322 return; 323 } 324 325 memmove(ip + (ip->ip_hl << 2), ip + (ip->ip_hl << 2) + msiz, 326 m->m_len - msiz - (ip->ip_hl << 2)); 327 328 m->m_len -= msiz; 329 ip->ip_len = htons(ntohs(ip->ip_len) - msiz); 330 m->m_pkthdr.len -= msiz; 331 332 ip->ip_sum = 0; 333 ip->ip_sum = in_cksum(m,(ip->ip_hl << 2)); 334 335 #if NBPFILTER > 0 336 if (sc->sc_if.if_bpf) 337 bpf_mtap_af(sc->sc_if.if_bpf, AF_INET, m, BPF_DIRECTION_IN); 338 #endif 339 340 #if NPF > 0 341 pf_pkt_addr_changed(m); 342 #endif 343 344 niq_enqueue(&ipintrq, m); 345 } 346 347 /* 348 * Find the gre interface associated with our src/dst/proto set. 349 */ 350 struct gre_softc * 351 gre_lookup(struct mbuf *m, u_int8_t proto) 352 { 353 struct ip *ip = mtod(m, struct ip *); 354 struct gre_softc *sc; 355 356 LIST_FOREACH(sc, &gre_softc_list, sc_list) { 357 if ((sc->g_dst.s_addr == ip->ip_src.s_addr) && 358 (sc->g_src.s_addr == ip->ip_dst.s_addr) && 359 (sc->g_proto == proto) && 360 (rtable_l2(sc->g_rtableid) == 361 rtable_l2(m->m_pkthdr.ph_rtableid)) && 362 ((sc->sc_if.if_flags & IFF_UP) != 0)) 363 return (sc); 364 } 365 366 return (NULL); 367 } 368 369 int 370 gre_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp, 371 size_t newlen) 372 { 373 /* All sysctl names at this level are terminal. */ 374 if (namelen != 1) 375 return (ENOTDIR); 376 377 switch (name[0]) { 378 case GRECTL_ALLOW: 379 return (sysctl_int(oldp, oldlenp, newp, newlen, &gre_allow)); 380 case GRECTL_WCCP: 381 return (sysctl_int(oldp, oldlenp, newp, newlen, &gre_wccp)); 382 default: 383 return (ENOPROTOOPT); 384 } 385 /* NOTREACHED */ 386 } 387 388 int 389 ipmobile_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, 390 void *newp, size_t newlen) 391 { 392 /* All sysctl names at this level are terminal. */ 393 if (namelen != 1) 394 return (ENOTDIR); 395 396 switch (name[0]) { 397 case MOBILEIPCTL_ALLOW: 398 return (sysctl_int(oldp, oldlenp, newp, newlen, 399 &ip_mobile_allow)); 400 default: 401 return (ENOPROTOOPT); 402 } 403 /* NOTREACHED */ 404 } 405 406 int 407 gre_usrreq(struct socket *so, int req, struct mbuf *m, struct mbuf *nam, 408 struct mbuf *control, struct proc *p) 409 { 410 #ifdef PIPEX 411 struct inpcb *inp = sotoinpcb(so); 412 413 if (inp != NULL && inp->inp_pipex && req == PRU_SEND) { 414 int s; 415 struct sockaddr_in *sin4; 416 struct in_addr *ina_dst; 417 struct pipex_session *session; 418 419 s = splsoftnet(); 420 ina_dst = NULL; 421 if ((so->so_state & SS_ISCONNECTED) != 0) { 422 inp = sotoinpcb(so); 423 if (inp) 424 ina_dst = &inp->inp_laddr; 425 } else if (nam) { 426 sin4 = mtod(nam, struct sockaddr_in *); 427 if (nam->m_len == sizeof(struct sockaddr_in) && 428 sin4->sin_family == AF_INET) 429 ina_dst = &sin4->sin_addr; 430 } 431 if (ina_dst != NULL && 432 (session = pipex_pptp_userland_lookup_session_ipv4(m, 433 *ina_dst))) 434 m = pipex_pptp_userland_output(m, session); 435 splx(s); 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