1 /* $NetBSD: if_gre.c,v 1.15 2000/12/18 19:50:44 thorpej Exp $ */ 2 3 /* 4 * Copyright (c) 1998 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Heiko W.Rupp <hwr@pilhuhn.de> 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. All advertising materials mentioning features or use of this software 19 * must display the following acknowledgement: 20 * This product includes software developed by the NetBSD 21 * Foundation, Inc. and its contributors. 22 * 4. Neither the name of The NetBSD Foundation nor the names of its 23 * contributors may be used to endorse or promote products derived 24 * from this software without specific prior written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 27 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 28 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 29 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 30 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 36 * POSSIBILITY OF SUCH DAMAGE. 37 */ 38 39 /* 40 * Encapsulate L3 protocols into IP 41 * See RFC 1701 and 1702 for more details. 42 * If_gre is compatible with Cisco GRE tunnels, so you can 43 * have a NetBSD box as the other end of a tunnel interface of a Cisco 44 * router. See gre(4) for more details. 45 * Also supported: IP in IP encaps (proto 55) as of RFC 2004 46 */ 47 48 #include "gre.h" 49 #if NGRE > 0 50 51 #include "opt_inet.h" 52 #include "opt_ns.h" 53 #include "bpfilter.h" 54 55 #include <sys/param.h> 56 #include <sys/malloc.h> 57 #include <sys/mbuf.h> 58 #include <sys/proc.h> 59 #include <sys/protosw.h> 60 #include <sys/socket.h> 61 #include <sys/ioctl.h> 62 #include <sys/queue.h> 63 #if __NetBSD__ 64 #include <sys/systm.h> 65 #endif 66 67 #include <machine/cpu.h> 68 69 #include <net/ethertypes.h> 70 #include <net/if.h> 71 #include <net/if_types.h> 72 #include <net/netisr.h> 73 #include <net/route.h> 74 75 #ifdef INET 76 #include <netinet/in.h> 77 #include <netinet/in_systm.h> 78 #include <netinet/in_var.h> 79 #include <netinet/ip.h> 80 #include <netinet/ip_var.h> 81 #else 82 #error "Huh? if_gre without inet?" 83 #endif 84 85 #ifdef NS 86 #include <netns/ns.h> 87 #include <netns/ns_if.h> 88 #endif 89 90 #ifdef NETATALK 91 #include <netatalk/at.h> 92 #include <netatalk/at_var.h> 93 #include <netatalk/at_extern.h> 94 #endif 95 96 #if NBPFILTER > 0 97 #include <sys/time.h> 98 #include <net/bpf.h> 99 #endif 100 101 #include <net/if_gre.h> 102 103 #define GREMTU 1450 /* XXX this is below the standard MTU of 104 1500 Bytes, allowing for headers, 105 but we should possibly do path mtu discovery 106 before changing if state to up to find the 107 correct value */ 108 #define LINK_MASK (IFF_LINK0|IFF_LINK1|IFF_LINK2) 109 110 struct gre_softc_head gre_softc_list; 111 112 int gre_clone_create __P((struct if_clone *, int)); 113 void gre_clone_destroy __P((struct ifnet *)); 114 115 struct if_clone gre_cloner = 116 IF_CLONE_INITIALIZER("gre", gre_clone_create, gre_clone_destroy); 117 118 void gre_compute_route(struct gre_softc *sc); 119 #ifdef DIAGNOSTIC 120 void gre_inet_ntoa(struct in_addr in); 121 #endif 122 123 void greattach __P((int)); 124 125 /* ARGSUSED */ 126 void 127 greattach(count) 128 int count; 129 { 130 131 LIST_INIT(&gre_softc_list); 132 if_clone_attach(&gre_cloner); 133 } 134 135 int 136 gre_clone_create(ifc, unit) 137 struct if_clone *ifc; 138 int unit; 139 { 140 struct gre_softc *sc; 141 142 sc = malloc(sizeof(struct gre_softc), M_DEVBUF, M_WAITOK); 143 memset(sc, 0, sizeof(struct gre_softc)); 144 145 sprintf(sc->sc_if.if_xname, "%s%d", ifc->ifc_name, unit); 146 sc->sc_if.if_softc = sc; 147 sc->sc_if.if_type = IFT_OTHER; 148 sc->sc_if.if_addrlen = 4; 149 sc->sc_if.if_hdrlen = 24; /* IP + GRE */ 150 sc->sc_if.if_dlt = DLT_NULL; 151 sc->sc_if.if_mtu = GREMTU; 152 sc->sc_if.if_flags = IFF_POINTOPOINT|IFF_MULTICAST; 153 sc->sc_if.if_output = gre_output; 154 sc->sc_if.if_ioctl = gre_ioctl; 155 sc->g_dst.s_addr = sc->g_src.s_addr = INADDR_ANY; 156 sc->g_proto = IPPROTO_GRE; 157 if_attach(&sc->sc_if); 158 #if NBPFILTER > 0 159 bpfattach(&sc->sc_if, DLT_NULL, sizeof(u_int32_t)); 160 #endif 161 LIST_INSERT_HEAD(&gre_softc_list, sc, sc_list); 162 return (0); 163 } 164 165 void 166 gre_clone_destroy(ifp) 167 struct ifnet *ifp; 168 { 169 struct gre_softc *sc = ifp->if_softc; 170 171 LIST_REMOVE(sc, sc_list); 172 #if NBPFILTER > 0 173 bpfdetach(ifp); 174 #endif 175 if_detach(ifp); 176 free(sc, M_DEVBUF); 177 } 178 179 /* 180 * The output routine. Takes a packet and encapsulates it in the protocol 181 * given by sc->g_proto. See also RFC 1701 and RFC 2004 182 */ 183 184 #if 0 185 struct ip ip_h; 186 #endif 187 struct mobile_h mob_h; 188 189 int 190 gre_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst, 191 struct rtentry *rt) 192 { 193 int error = 0; 194 struct gre_softc *sc = ifp->if_softc; 195 struct greip *gh; 196 struct ip *inp; 197 u_char ttl, osrc; 198 u_short etype = 0; 199 200 201 gh = NULL; 202 inp = NULL; 203 osrc = 0; 204 205 #if NBPFILTER >0 206 if (ifp->if_bpf) { 207 /* see comment of other if_foo.c files */ 208 struct mbuf m0; 209 u_int af = dst->sa_family; 210 211 m0.m_next = m; 212 m0.m_len = 4; 213 m0.m_data = (char *)⁡ 214 215 bpf_mtap(ifp->if_bpf, &m0); 216 } 217 #endif 218 219 ttl = 255; 220 221 if (sc->g_proto == IPPROTO_MOBILE) { 222 if (dst->sa_family == AF_INET) { 223 struct mbuf *m0; 224 int msiz; 225 226 inp = mtod(m, struct ip *); 227 228 memset(&mob_h, 0, MOB_H_SIZ_L); 229 mob_h.proto = (inp->ip_p) << 8; 230 mob_h.odst = inp->ip_dst.s_addr; 231 inp->ip_dst.s_addr = sc->g_dst.s_addr; 232 233 /* 234 * If the packet comes from our host, we only change 235 * the destination address in the IP header. 236 * Else we also need to save and change the source 237 */ 238 if (in_hosteq(inp->ip_src, sc->g_src)) { 239 msiz = MOB_H_SIZ_S; 240 } else { 241 mob_h.proto |= MOB_H_SBIT; 242 mob_h.osrc = inp->ip_src.s_addr; 243 inp->ip_src.s_addr = sc->g_src.s_addr; 244 msiz = MOB_H_SIZ_L; 245 } 246 HTONS(mob_h.proto); 247 mob_h.hcrc = gre_in_cksum((u_short *)&mob_h, msiz); 248 249 if ((m->m_data - msiz) < m->m_pktdat) { 250 /* need new mbuf */ 251 MGETHDR(m0, M_DONTWAIT, MT_HEADER); 252 if (m0 == NULL) { 253 IF_DROP(&ifp->if_snd); 254 m_freem(m); 255 return (ENOBUFS); 256 } 257 m0->m_next = m; 258 m->m_data += sizeof(struct ip); 259 m->m_len -= sizeof(struct ip); 260 m0->m_pkthdr.len = m->m_pkthdr.len + msiz; 261 m0->m_len = msiz + sizeof(struct ip); 262 m0->m_data += max_linkhdr; 263 memcpy(mtod(m0, caddr_t), (caddr_t)inp, 264 sizeof(struct ip)); 265 m = m0; 266 } else { /* we have some spave left in the old one */ 267 m->m_data -= msiz; 268 m->m_len += msiz; 269 m->m_pkthdr.len += msiz; 270 memmove(mtod(m, caddr_t), inp, 271 sizeof(struct ip)); 272 } 273 inp=mtod(m, struct ip *); 274 memcpy((caddr_t)(inp + 1), &mob_h, (unsigned)msiz); 275 NTOHS(inp->ip_len); 276 inp->ip_len += msiz; 277 } else { /* AF_INET */ 278 IF_DROP(&ifp->if_snd); 279 m_freem(m); 280 return (EINVAL); 281 } 282 } else if (sc->g_proto == IPPROTO_GRE) { 283 switch(dst->sa_family) { 284 case AF_INET: 285 inp = mtod(m, struct ip *); 286 ttl = inp->ip_ttl; 287 etype = ETHERTYPE_IP; 288 break; 289 #ifdef NETATALK 290 case AF_APPLETALK: 291 etype = ETHERTYPE_ATALK; 292 break; 293 #endif 294 #ifdef NS 295 case AF_NS: 296 etype = ETHERTYPE_NS; 297 break; 298 #endif 299 default: 300 IF_DROP(&ifp->if_snd); 301 m_freem(m); 302 return (EAFNOSUPPORT); 303 } 304 M_PREPEND(m, sizeof(struct greip), M_DONTWAIT); 305 } else { 306 error = EINVAL; 307 IF_DROP(&ifp->if_snd); 308 m_freem(m); 309 return (error); 310 } 311 312 313 if (m == NULL) { 314 IF_DROP(&ifp->if_snd); 315 return (ENOBUFS); 316 } 317 318 gh = mtod(m, struct greip *); 319 if (sc->g_proto == IPPROTO_GRE) { 320 /* we don't have any GRE flags for now */ 321 322 memset((void *)&gh->gi_g, 0, sizeof(struct gre_h)); 323 gh->gi_ptype = htons(etype); 324 } 325 326 gh->gi_pr = sc->g_proto; 327 if (sc->g_proto != IPPROTO_MOBILE) { 328 gh->gi_src = sc->g_src; 329 gh->gi_dst = sc->g_dst; 330 ((struct ip*)gh)->ip_hl = (sizeof(struct ip)) >> 2; 331 ((struct ip*)gh)->ip_ttl = ttl; 332 ((struct ip*)gh)->ip_tos = inp->ip_tos; 333 gh->gi_len = m->m_pkthdr.len; 334 } 335 336 ifp->if_opackets++; 337 ifp->if_obytes += m->m_pkthdr.len; 338 /* send it off */ 339 error = ip_output(m, NULL, &sc->route, 0, NULL); 340 if (error) 341 ifp->if_oerrors++; 342 return (error); 343 344 } 345 346 int 347 gre_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) 348 { 349 struct proc *p = curproc; /* XXX */ 350 struct ifaddr *ifa = (struct ifaddr *)data; 351 struct ifreq *ifr = (struct ifreq *)data; 352 struct in_ifaddr *ia = (struct in_ifaddr *)data; 353 struct gre_softc *sc = ifp->if_softc; 354 int s; 355 struct sockaddr_in si; 356 struct sockaddr *sa = NULL; 357 int error; 358 359 error = 0; 360 361 s = splimp(); 362 switch(cmd) { 363 case SIOCSIFADDR: 364 case SIOCSIFDSTADDR: 365 if ((error = suser(p->p_ucred, &p->p_acflag)) != 0) 366 break; 367 /* 368 * set tunnel endpoints in case that we "only" 369 * have ip over ip encapsulation. This allows to 370 * set tunnel endpoints with ifconfig. 371 */ 372 if (ifa->ifa_addr->sa_family == AF_INET) { 373 sa = ifa->ifa_addr; 374 sc->g_src = (satosin(sa))->sin_addr; 375 sc->g_dst = ia->ia_dstaddr.sin_addr; 376 if ((sc->g_src.s_addr != INADDR_ANY) && 377 (sc->g_dst.s_addr != INADDR_ANY)) { 378 if (sc->route.ro_rt != 0) /* free old route */ 379 RTFREE(sc->route.ro_rt); 380 gre_compute_route(sc); 381 ifp->if_flags |= IFF_UP; 382 } 383 } 384 break; 385 case SIOCSIFFLAGS: 386 if ((error = suser(p->p_ucred, &p->p_acflag)) != 0) 387 break; 388 if ((sc->g_dst.s_addr == INADDR_ANY) || 389 (sc->g_src.s_addr == INADDR_ANY)) 390 ifp->if_flags &= ~IFF_UP; 391 392 switch(ifr->ifr_flags & LINK_MASK) { 393 case IFF_LINK0: 394 sc->g_proto = IPPROTO_GRE; 395 ifp->if_flags |= IFF_LINK0; 396 ifp->if_flags &= ~(IFF_LINK1|IFF_LINK2); 397 break; 398 case IFF_LINK2: 399 sc->g_proto = IPPROTO_MOBILE; 400 ifp->if_flags |= IFF_LINK2; 401 ifp->if_flags &= ~(IFF_LINK0|IFF_LINK1); 402 break; 403 } 404 break; 405 case SIOCSIFMTU: 406 if ((error = suser(p->p_ucred, &p->p_acflag)) != 0) 407 break; 408 if (ifr->ifr_mtu > GREMTU || ifr->ifr_mtu < 576) { 409 error = EINVAL; 410 break; 411 } 412 ifp->if_mtu = ifr->ifr_mtu; 413 break; 414 case SIOCGIFMTU: 415 ifr->ifr_mtu = sc->sc_if.if_mtu; 416 break; 417 case SIOCADDMULTI: 418 case SIOCDELMULTI: 419 if ((error = suser(p->p_ucred, &p->p_acflag)) != 0) 420 break; 421 if (ifr == 0) { 422 error = EAFNOSUPPORT; 423 break; 424 } 425 switch (ifr->ifr_addr.sa_family) { 426 #ifdef INET 427 case AF_INET: 428 break; 429 #endif 430 default: 431 error = EAFNOSUPPORT; 432 break; 433 } 434 break; 435 case GRESPROTO: 436 if ((error = suser(p->p_ucred, &p->p_acflag)) != 0) 437 break; 438 sc->g_proto = ifr->ifr_flags; 439 switch (sc->g_proto) { 440 case IPPROTO_GRE : 441 ifp->if_flags |= IFF_LINK0; 442 ifp->if_flags &= ~(IFF_LINK1|IFF_LINK2); 443 break; 444 case IPPROTO_MOBILE : 445 ifp->if_flags |= IFF_LINK2; 446 ifp->if_flags &= ~(IFF_LINK1|IFF_LINK2); 447 break; 448 default: 449 ifp->if_flags &= ~(IFF_LINK0|IFF_LINK1|IFF_LINK2); 450 } 451 break; 452 case GREGPROTO: 453 ifr->ifr_flags = sc->g_proto; 454 break; 455 case GRESADDRS: 456 case GRESADDRD: 457 if ((error = suser(p->p_ucred, &p->p_acflag)) != 0) 458 break; 459 /* 460 * set tunnel endpoints, compute a less specific route 461 * to the remote end and mark if as up 462 */ 463 sa = &ifr->ifr_addr; 464 if (cmd == GRESADDRS ) 465 sc->g_src = (satosin(sa))->sin_addr; 466 if (cmd == GRESADDRD ) 467 sc->g_dst = (satosin(sa))->sin_addr; 468 if ((sc->g_src.s_addr != INADDR_ANY) && 469 (sc->g_dst.s_addr != INADDR_ANY)) { 470 if (sc->route.ro_rt != 0) /* free old route */ 471 RTFREE(sc->route.ro_rt); 472 gre_compute_route(sc); 473 ifp->if_flags |= IFF_UP; 474 } 475 break; 476 case GREGADDRS: 477 si.sin_addr.s_addr = sc->g_src.s_addr; 478 sa = sintosa(&si); 479 ifr->ifr_addr = *sa; 480 break; 481 case GREGADDRD: 482 si.sin_addr.s_addr = sc->g_dst.s_addr; 483 sa = sintosa(&si); 484 ifr->ifr_addr = *sa; 485 break; 486 default: 487 error = EINVAL; 488 } 489 490 splx(s); 491 return (error); 492 } 493 494 /* 495 * computes a route to our destination that is not the one 496 * which would be taken by ip_output(), as this one will loop back to 497 * us. If the interface is p2p as a--->b, then a routing entry exists 498 * If we now send a packet to b (e.g. ping b), this will come down here 499 * gets src=a, dst=b tacked on and would from ip_ouput() sent back to 500 * if_gre. 501 * Goal here is to compute a route to b that is less specific than 502 * a-->b. We know that this one exists as in normal operation we have 503 * at least a default route which matches. 504 */ 505 506 void 507 gre_compute_route(struct gre_softc *sc) 508 { 509 struct route *ro; 510 u_int32_t a, b, c; 511 512 ro = &sc->route; 513 514 memset(ro, 0, sizeof(struct route)); 515 ((struct sockaddr_in *)&ro->ro_dst)->sin_addr = sc->g_dst; 516 ro->ro_dst.sa_family = AF_INET; 517 ro->ro_dst.sa_len = sizeof(ro->ro_dst); 518 519 /* 520 * toggle last bit, so our interface is not found, but a less 521 * specific route. I'd rather like to specify a shorter mask, 522 * but this is not possible. Should work though. XXX 523 * there is a simpler way ... 524 */ 525 if ((sc->sc_if.if_flags & IFF_LINK1) == 0) { 526 a = ntohl(sc->g_dst.s_addr); 527 b = a & 0x01; 528 c = a & 0xfffffffe; 529 b = b ^ 0x01; 530 a = b | c; 531 ((struct sockaddr_in *)&ro->ro_dst)->sin_addr.s_addr 532 = htonl(a); 533 } 534 535 #ifdef DIAGNOSTIC 536 printf("%s: searching a route to ", sc->sc_if.if_xname); 537 gre_inet_ntoa(((struct sockaddr_in *)&ro->ro_dst)->sin_addr); 538 #endif 539 540 rtalloc(ro); 541 542 /* 543 * now change it back - else ip_output will just drop 544 * the route and search one to this interface ... 545 */ 546 if ((sc->sc_if.if_flags & IFF_LINK1) == 0) 547 ((struct sockaddr_in *)&ro->ro_dst)->sin_addr = sc->g_dst; 548 549 #ifdef DIAGNOSTIC 550 printf(", choosing %s with gateway ",ro->ro_rt->rt_ifp->if_xname); 551 gre_inet_ntoa(((struct sockaddr_in *)(ro->ro_rt->rt_gateway))->sin_addr); 552 printf("\n"); 553 #endif 554 } 555 556 /* 557 * do a checksum of a buffer - much like in_cksum, which operates on 558 * mbufs. 559 */ 560 561 u_short 562 gre_in_cksum(u_short *p, u_int len) 563 { 564 u_int sum = 0; 565 int nwords = len >> 1; 566 567 while (nwords-- != 0) 568 sum += *p++; 569 570 if (len & 1) { 571 union { 572 u_short w; 573 u_char c[2]; 574 } u; 575 u.c[0] = *(u_char *)p; 576 u.c[1] = 0; 577 sum += u.w; 578 } 579 580 /* end-around-carry */ 581 sum = (sum >> 16) + (sum & 0xffff); 582 sum += (sum >> 16); 583 return (~sum); 584 } 585 586 587 /* while testing ... */ 588 #ifdef DIAGNOSTIC 589 void 590 gre_inet_ntoa(struct in_addr in) 591 { 592 char *p; 593 594 p = (char *)∈ 595 #define UC(b) (((int)b)&0xff) 596 printf("%d.%d.%d.%d", UC(p[0]), UC(p[1]), UC(p[2]), UC(p[3])); 597 } 598 599 #endif 600 #endif 601 602