1 /* $OpenBSD: if_gre.c,v 1.28 2003/08/15 20:32:19 tedu Exp $ */ 2 /* $NetBSD: if_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 * 3. All advertising materials mentioning features or use of this software 20 * must display the following acknowledgement: 21 * This product includes software developed by the NetBSD 22 * Foundation, Inc. and its contributors. 23 * 4. Neither the name of The NetBSD Foundation nor the names of its 24 * contributors may be used to endorse or promote products derived 25 * from this software without specific prior written permission. 26 * 27 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 28 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 29 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 30 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 31 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 32 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 33 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 34 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 35 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 36 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 37 * POSSIBILITY OF SUCH DAMAGE. 38 */ 39 40 /* 41 * Encapsulate L3 protocols into IP, per RFC 1701 and 1702. 42 * See gre(4) for more details. 43 * Also supported: IP in IP encapsulation (proto 55) per RFC 2004. 44 */ 45 46 #include "gre.h" 47 #if NGRE > 0 48 49 #include "bpfilter.h" 50 51 #include <sys/param.h> 52 #include <sys/proc.h> 53 #include <sys/mbuf.h> 54 #include <sys/socket.h> 55 #include <sys/sockio.h> 56 #include <sys/kernel.h> 57 #include <sys/systm.h> 58 59 #include <net/if.h> 60 #include <net/if_types.h> 61 #include <net/netisr.h> 62 #include <net/route.h> 63 64 #ifdef INET 65 #include <netinet/in.h> 66 #include <netinet/in_systm.h> 67 #include <netinet/in_var.h> 68 #include <netinet/ip.h> 69 #include <netinet/ip_var.h> 70 #include <netinet/if_ether.h> 71 #else 72 #error "if_gre used without inet" 73 #endif 74 75 #ifdef NS 76 #include <netns/ns.h> 77 #include <netns/ns_if.h> 78 #endif 79 80 #ifdef NETATALK 81 #include <netatalk/at.h> 82 #include <netatalk/at_var.h> 83 #include <netatalk/at_extern.h> 84 #endif 85 86 #if NBPFILTER > 0 87 #include <net/bpf.h> 88 #endif 89 90 #include <net/if_gre.h> 91 92 #ifndef GRE_RECURSION_LIMIT 93 #define GRE_RECURSION_LIMIT 3 /* How many levels of recursion allowed */ 94 #endif /* GRE_RECURSION_LIMIT */ 95 96 #define GREMTU 1450 /* XXX this is below the standard MTU of 97 1500 Bytes, allowing for headers, 98 but we should possibly do path mtu discovery 99 before changing if state to up to find the 100 correct value */ 101 102 struct gre_softc *gre = 0; 103 104 int ngre = 0; 105 106 /* 107 * We can control the acceptance of GRE and MobileIP packets by 108 * altering the sysctl net.inet.gre.allow and net.inet.mobileip.allow values 109 * respectively. Zero means drop them, all else is acceptance. We can also 110 * control acceptance of WCCPv1-style GRE packets through the 111 * net.inet.gre.wccp value, but be aware it depends upon normal GRE being 112 * allowed as well. 113 * 114 */ 115 int gre_allow = 0; 116 int gre_wccp = 0; 117 int ip_mobile_allow = 0; 118 119 static void gre_compute_route(struct gre_softc *sc); 120 121 void 122 greattach(n) 123 int n; 124 { 125 struct gre_softc *sc; 126 int i; 127 128 ngre = n; 129 gre = sc = malloc(ngre * sizeof(struct gre_softc), M_DEVBUF, M_WAIT); 130 bzero(sc, ngre * sizeof(struct gre_softc)); 131 for (i = 0; i < ngre ; sc++) { 132 snprintf(sc->sc_if.if_xname, sizeof(sc->sc_if.if_xname), 133 "gre%d", i++); 134 sc->sc_if.if_softc = sc; 135 sc->sc_if.if_type = IFT_OTHER; 136 sc->sc_if.if_addrlen = 0; 137 sc->sc_if.if_hdrlen = 24; /* IP + GRE */ 138 sc->sc_if.if_mtu = GREMTU; 139 sc->sc_if.if_flags = IFF_POINTOPOINT|IFF_MULTICAST; 140 sc->sc_if.if_output = gre_output; 141 sc->sc_if.if_ioctl = gre_ioctl; 142 sc->sc_if.if_collisions = 0; 143 sc->sc_if.if_ierrors = 0; 144 sc->sc_if.if_oerrors = 0; 145 sc->sc_if.if_ipackets = 0; 146 sc->sc_if.if_opackets = 0; 147 sc->g_dst.s_addr = sc->g_src.s_addr = INADDR_ANY; 148 sc->g_proto = IPPROTO_GRE; 149 sc->sc_if.if_flags |= IFF_LINK0; 150 151 if_attach(&sc->sc_if); 152 if_alloc_sadl(&sc->sc_if); 153 154 #if NBPFILTER > 0 155 bpfattach(&sc->sc_if.if_bpf, &sc->sc_if, DLT_RAW, 156 sizeof(u_int32_t)); 157 #endif 158 } 159 } 160 161 /* 162 * The output routine. Takes a packet and encapsulates it in the protocol 163 * given by sc->g_proto. See also RFC 1701 and RFC 2004. 164 */ 165 166 int 167 gre_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst, 168 struct rtentry *rt) 169 { 170 int error = 0; 171 struct gre_softc *sc = (struct gre_softc *) (ifp->if_softc); 172 struct greip *gh = NULL; 173 struct ip *inp = NULL; 174 u_short etype = 0; 175 struct mobile_h mob_h; 176 struct m_tag *mtag; 177 178 if ((ifp->if_flags & IFF_UP) == 0 || 179 sc->g_src.s_addr == INADDR_ANY || sc->g_dst.s_addr == INADDR_ANY) { 180 m_freem(m); 181 error = ENETDOWN; 182 goto end; 183 } 184 185 /* Try to limit infinite recursion through misconfiguration. */ 186 for (mtag = m_tag_find(m, PACKET_TAG_GRE, NULL); mtag; 187 mtag = m_tag_find(m, PACKET_TAG_GRE, mtag)) { 188 if (!bcmp((caddr_t)(mtag + 1), &ifp, sizeof(struct ifnet *))) { 189 IF_DROP(&ifp->if_snd); 190 m_freem(m); 191 error = EIO; 192 goto end; 193 } 194 } 195 196 mtag = m_tag_get(PACKET_TAG_GRE, sizeof(struct ifnet *), M_NOWAIT); 197 if (mtag == NULL) { 198 IF_DROP(&ifp->if_snd); 199 m_freem(m); 200 error = ENOBUFS; 201 goto end; 202 } 203 bcopy(&ifp, (caddr_t)(mtag + 1), sizeof(struct ifnet *)); 204 m_tag_prepend(m, mtag); 205 206 #if NBPFILTER >0 207 if (ifp->if_bpf) 208 bpf_mtap(ifp->if_bpf, m); 209 #endif 210 211 if (sc->g_proto == IPPROTO_MOBILE) { 212 if (ip_mobile_allow == 0) { 213 IF_DROP(&ifp->if_snd); 214 m_freem(m); 215 error = EACCES; 216 goto end; 217 } 218 219 if (dst->sa_family == AF_INET) { 220 struct mbuf *m0; 221 int msiz; 222 223 /* 224 * Make sure the complete IP header (with options) 225 * is in the first mbuf. 226 */ 227 if (m->m_len < sizeof(struct ip)) { 228 m = m_pullup(m, sizeof(struct ip)); 229 if (m == NULL) { 230 IF_DROP(&ifp->if_snd); 231 error = ENOBUFS; 232 goto end; 233 } else 234 inp = mtod(m, struct ip *); 235 236 if (m->m_len < inp->ip_hl << 2) { 237 m = m_pullup(m, 238 sizeof(inp->ip_hl << 2)); 239 if (m == NULL) { 240 IF_DROP(&ifp->if_snd); 241 error = ENOBUFS; 242 goto end; 243 } 244 } 245 } 246 247 inp = mtod(m, struct ip *); 248 249 bzero(&mob_h, MOB_H_SIZ_L); 250 mob_h.proto = (inp->ip_p) << 8; 251 mob_h.odst = inp->ip_dst.s_addr; 252 inp->ip_dst.s_addr = sc->g_dst.s_addr; 253 254 /* 255 * If the packet comes from our host, we only change 256 * the destination address in the IP header. 257 * Otherwise we need to save and change the source. 258 */ 259 if (inp->ip_src.s_addr == sc->g_src.s_addr) { 260 msiz = MOB_H_SIZ_S; 261 } else { 262 mob_h.proto |= MOB_H_SBIT; 263 mob_h.osrc = inp->ip_src.s_addr; 264 inp->ip_src.s_addr = sc->g_src.s_addr; 265 msiz = MOB_H_SIZ_L; 266 } 267 268 HTONS(mob_h.proto); 269 mob_h.hcrc = gre_in_cksum((u_short *) &mob_h, msiz); 270 271 /* Squeeze in the mobility header */ 272 if ((m->m_data - msiz) < m->m_pktdat) { 273 /* Need new mbuf */ 274 MGETHDR(m0, M_DONTWAIT, MT_HEADER); 275 if (m0 == NULL) { 276 IF_DROP(&ifp->if_snd); 277 m_freem(m); 278 error = ENOBUFS; 279 goto end; 280 } 281 M_MOVE_HDR(m0, m); 282 283 m0->m_len = msiz + (inp->ip_hl << 2); 284 m0->m_data += max_linkhdr; 285 m0->m_pkthdr.len = m->m_pkthdr.len + msiz; 286 m->m_data += inp->ip_hl << 2; 287 m->m_len -= inp->ip_hl << 2; 288 289 bcopy((caddr_t) inp, mtod(m0, caddr_t), 290 sizeof(struct ip)); 291 292 m0->m_next = m; 293 m = m0; 294 } else { /* we have some space left in the old one */ 295 m->m_data -= msiz; 296 m->m_len += msiz; 297 m->m_pkthdr.len += msiz; 298 bcopy(inp, mtod(m, caddr_t), 299 inp->ip_hl << 2); 300 } 301 302 /* Copy Mobility header */ 303 inp = mtod(m, struct ip *); 304 bcopy(&mob_h, (caddr_t)(inp + 1), (unsigned) msiz); 305 inp->ip_len = htons(ntohs(inp->ip_len) + msiz); 306 } else { /* AF_INET */ 307 IF_DROP(&ifp->if_snd); 308 m_freem(m); 309 error = EINVAL; 310 goto end; 311 } 312 } else if (sc->g_proto == IPPROTO_GRE) { 313 if (gre_allow == 0) { 314 IF_DROP(&ifp->if_snd); 315 m_freem(m); 316 error = EACCES; 317 goto end; 318 } 319 320 switch(dst->sa_family) { 321 case AF_INET: 322 if (m->m_len < sizeof(struct ip)) { 323 m = m_pullup(m, sizeof(struct ip)); 324 if (m == NULL) { 325 IF_DROP(&ifp->if_snd); 326 error = ENOBUFS; 327 goto end; 328 } 329 } 330 331 inp = mtod(m, struct ip *); 332 etype = ETHERTYPE_IP; 333 break; 334 #ifdef NETATALK 335 case AF_APPLETALK: 336 etype = ETHERTYPE_AT; 337 break; 338 #endif 339 #ifdef NS 340 case AF_NS: 341 etype = ETHERTYPE_NS; 342 break; 343 #endif 344 default: 345 IF_DROP(&ifp->if_snd); 346 m_freem(m); 347 error = EAFNOSUPPORT; 348 goto end; 349 } 350 351 M_PREPEND(m, sizeof(struct greip), M_DONTWAIT); 352 } else { 353 IF_DROP(&ifp->if_snd); 354 m_freem(m); 355 error = EINVAL; 356 goto end; 357 } 358 359 if (m == NULL) { 360 IF_DROP(&ifp->if_snd); 361 error = ENOBUFS; 362 goto end; 363 } 364 365 gh = mtod(m, struct greip *); 366 if (sc->g_proto == IPPROTO_GRE) { 367 /* We don't support any GRE flags for now */ 368 369 bzero((void *) &gh->gi_g, sizeof(struct gre_h)); 370 gh->gi_ptype = htons(etype); 371 } 372 373 gh->gi_pr = sc->g_proto; 374 if (sc->g_proto != IPPROTO_MOBILE) { 375 gh->gi_src = sc->g_src; 376 gh->gi_dst = sc->g_dst; 377 ((struct ip *) gh)->ip_hl = (sizeof(struct ip)) >> 2; 378 ((struct ip *) gh)->ip_ttl = ip_defttl; 379 ((struct ip *) gh)->ip_tos = inp->ip_tos; 380 gh->gi_len = m->m_pkthdr.len; 381 } 382 383 ifp->if_opackets++; 384 ifp->if_obytes += m->m_pkthdr.len; 385 386 /* Send it off */ 387 error = ip_output(m, (void *)NULL, &sc->route, 0, (void *)NULL, (void *)NULL); 388 end: 389 if (error) 390 ifp->if_oerrors++; 391 return (error); 392 } 393 394 int 395 gre_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) 396 { 397 398 struct ifreq *ifr = (struct ifreq *) data; 399 struct if_laddrreq *lifr = (struct if_laddrreq *)data; 400 struct gre_softc *sc = ifp->if_softc; 401 int s; 402 struct sockaddr_in si; 403 struct sockaddr *sa = NULL; 404 int error = 0; 405 struct proc *prc = curproc; /* XXX */ 406 407 s = splimp(); 408 switch(cmd) { 409 case SIOCSIFADDR: 410 ifp->if_flags |= IFF_UP; 411 break; 412 case SIOCSIFDSTADDR: 413 break; 414 case SIOCSIFFLAGS: 415 if ((ifr->ifr_flags & IFF_LINK0) != 0) 416 sc->g_proto = IPPROTO_GRE; 417 else 418 sc->g_proto = IPPROTO_MOBILE; 419 break; 420 case SIOCADDMULTI: 421 case SIOCDELMULTI: 422 if (ifr == 0) { 423 error = EAFNOSUPPORT; 424 break; 425 } 426 switch (ifr->ifr_addr.sa_family) { 427 #ifdef INET 428 case AF_INET: 429 break; 430 #endif 431 default: 432 error = EAFNOSUPPORT; 433 break; 434 } 435 break; 436 case GRESPROTO: 437 /* Check for superuser */ 438 if ((error = suser(prc, 0)) != 0) 439 break; 440 441 sc->g_proto = ifr->ifr_flags; 442 switch (sc->g_proto) { 443 case IPPROTO_GRE: 444 ifp->if_flags |= IFF_LINK0; 445 break; 446 case IPPROTO_MOBILE: 447 ifp->if_flags &= ~IFF_LINK0; 448 break; 449 default: 450 error = EPROTONOSUPPORT; 451 break; 452 } 453 break; 454 case GREGPROTO: 455 ifr->ifr_flags = sc->g_proto; 456 break; 457 case GRESADDRS: 458 case GRESADDRD: 459 /* Check for superuser */ 460 if ((error = suser(prc, 0)) != 0) 461 break; 462 463 /* 464 * set tunnel endpoints, compute a less specific route 465 * to the remote end and mark if as up 466 */ 467 sa = &ifr->ifr_addr; 468 if (cmd == GRESADDRS ) 469 sc->g_src = (satosin(sa))->sin_addr; 470 if (cmd == GRESADDRD ) 471 sc->g_dst = (satosin(sa))->sin_addr; 472 recompute: 473 if ((sc->g_src.s_addr != INADDR_ANY) && 474 (sc->g_dst.s_addr != INADDR_ANY)) { 475 if (sc->route.ro_rt != 0) { 476 /* free old route */ 477 RTFREE(sc->route.ro_rt); 478 sc->route.ro_rt = (struct rtentry *) 0; 479 } 480 481 gre_compute_route(sc); 482 if (sc->route.ro_rt == 0) 483 { 484 sc->g_src.s_addr = INADDR_ANY; 485 sc->g_dst.s_addr = INADDR_ANY; 486 splx(s); 487 return EIO; /* Is this is good ? */ 488 } 489 ifp->if_flags |= IFF_UP; 490 } 491 break; 492 case GREGADDRS: 493 bzero(&si, sizeof(si)); 494 si.sin_family = AF_INET; 495 si.sin_len = sizeof(struct sockaddr_in); 496 si.sin_addr.s_addr = sc->g_src.s_addr; 497 sa = sintosa(&si); 498 ifr->ifr_addr = *sa; 499 break; 500 case GREGADDRD: 501 bzero(&si, sizeof(si)); 502 si.sin_family = AF_INET; 503 si.sin_len = sizeof(struct sockaddr_in); 504 si.sin_addr.s_addr = sc->g_dst.s_addr; 505 sa = sintosa(&si); 506 ifr->ifr_addr = *sa; 507 break; 508 case SIOCSLIFPHYADDR: 509 if ((error = suser(prc, 0)) != 0) 510 break; 511 if (lifr->addr.ss_family != AF_INET || 512 lifr->dstaddr.ss_family != AF_INET) { 513 error = EAFNOSUPPORT; 514 break; 515 } 516 if (lifr->addr.ss_len != sizeof(si) || 517 lifr->dstaddr.ss_len != sizeof(si)) { 518 error = EINVAL; 519 break; 520 } 521 sc->g_src = (satosin((struct sockadrr *)&lifr->addr))->sin_addr; 522 sc->g_dst = 523 (satosin((struct sockadrr *)&lifr->dstaddr))->sin_addr; 524 goto recompute; 525 case SIOCDIFPHYADDR: 526 if ((error = suser(prc, 0)) != 0) 527 break; 528 sc->g_src.s_addr = INADDR_ANY; 529 sc->g_dst.s_addr = INADDR_ANY; 530 break; 531 case SIOCGLIFPHYADDR: 532 if (sc->g_src.s_addr == INADDR_ANY || 533 sc->g_dst.s_addr == INADDR_ANY) { 534 error = EADDRNOTAVAIL; 535 break; 536 } 537 bzero(&si, sizeof(si)); 538 si.sin_family = AF_INET; 539 si.sin_len = sizeof(struct sockaddr_in); 540 si.sin_addr.s_addr = sc->g_src.s_addr; 541 memcpy(&lifr->addr, &si, sizeof(si)); 542 si.sin_addr.s_addr = sc->g_dst.s_addr; 543 memcpy(&lifr->dstaddr, &si, sizeof(si)); 544 break; 545 default: 546 error = EINVAL; 547 } 548 549 splx(s); 550 return (error); 551 } 552 553 /* 554 * computes a route to our destination that is not the one 555 * which would be taken by ip_output(), as this one will loop back to 556 * us. If the interface is p2p as a--->b, then a routing entry exists 557 * If we now send a packet to b (e.g. ping b), this will come down here 558 * gets src=a, dst=b tacked on and would from ip_output() sent back to 559 * if_gre. 560 * Goal here is to compute a route to b that is less specific than 561 * a-->b. We know that this one exists as in normal operation we have 562 * at least a default route which matches. 563 */ 564 565 static void 566 gre_compute_route(struct gre_softc *sc) 567 { 568 struct route *ro; 569 u_int32_t a, b, c; 570 571 ro = &sc->route; 572 573 bzero(ro, sizeof(struct route)); 574 ((struct sockaddr_in *) &ro->ro_dst)->sin_addr = sc->g_dst; 575 ro->ro_dst.sa_family = AF_INET; 576 ro->ro_dst.sa_len = sizeof(ro->ro_dst); 577 578 /* 579 * toggle last bit, so our interface is not found, but a less 580 * specific route. I'd rather like to specify a shorter mask, 581 * but this is not possible. Should work though. XXX 582 * there is a simpler way ... 583 */ 584 if ((sc->sc_if.if_flags & IFF_LINK1) == 0) { 585 a = ntohl(sc->g_dst.s_addr); 586 b = a & 0x01; 587 c = a & 0xfffffffe; 588 b = b ^ 0x01; 589 a = b | c; 590 ((struct sockaddr_in *) &ro->ro_dst)->sin_addr.s_addr = htonl(a); 591 } 592 593 rtalloc(ro); 594 if (ro->ro_rt == 0) 595 return; 596 597 /* 598 * Check whether we just created a loop. An even more paranoid 599 * check would be against all GRE interfaces, but that would 600 * not allow people to link GRE tunnels. 601 */ 602 if (ro->ro_rt->rt_ifp == &sc->sc_if) { 603 RTFREE(ro->ro_rt); 604 ro->ro_rt = (struct rtentry *) 0; 605 return; 606 } 607 608 /* 609 * now change it back - else ip_output will just drop 610 * the route and search one to this interface ... 611 */ 612 if ((sc->sc_if.if_flags & IFF_LINK1) == 0) 613 ((struct sockaddr_in *) &ro->ro_dst)->sin_addr = sc->g_dst; 614 } 615 616 /* 617 * do a checksum of a buffer - much like in_cksum, which operates on 618 * mbufs. 619 */ 620 u_short 621 gre_in_cksum(u_short *p, u_int len) 622 { 623 u_int sum = 0; 624 int nwords = len >> 1; 625 626 while (nwords-- != 0) 627 sum += *p++; 628 629 if (len & 1) { 630 union { 631 u_short w; 632 u_char c[2]; 633 } u; 634 u.c[0] = *(u_char *) p; 635 u.c[1] = 0; 636 sum += u.w; 637 } 638 639 /* end-around-carry */ 640 sum = (sum >> 16) + (sum & 0xffff); 641 sum += (sum >> 16); 642 return (~sum); 643 } 644 #endif 645