]> CyberLeo.Net >> Repos - FreeBSD/releng/8.1.git/blob - sys/net/if_gre.c
Copy stable/8 to releng/8.1 in preparation for 8.1-RC1.
[FreeBSD/releng/8.1.git] / sys / net / if_gre.c
1 /*      $NetBSD: if_gre.c,v 1.49 2003/12/11 00:22:29 itojun Exp $ */
2 /*       $FreeBSD$ */
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  * IPv6-over-GRE contributed by Gert Doering <gert@greenie.muc.de>
12  *
13  * Redistribution and use in source and binary forms, with or without
14  * modification, are permitted provided that the following conditions
15  * are met:
16  * 1. Redistributions of source code must retain the above copyright
17  *    notice, this list of conditions and the following disclaimer.
18  * 2. Redistributions in binary form must reproduce the above copyright
19  *    notice, this list of conditions and the following disclaimer in the
20  *    documentation and/or other materials provided with the distribution.
21  * 3. All advertising materials mentioning features or use of this software
22  *    must display the following acknowledgement:
23  *        This product includes software developed by the NetBSD
24  *        Foundation, Inc. and its contributors.
25  * 4. Neither the name of The NetBSD Foundation nor the names of its
26  *    contributors may be used to endorse or promote products derived
27  *    from this software without specific prior written permission.
28  *
29  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
30  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
31  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
32  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
33  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
34  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
35  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
36  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
37  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
38  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
39  * POSSIBILITY OF SUCH DAMAGE.
40  */
41
42 /*
43  * Encapsulate L3 protocols into IP
44  * See RFC 2784 (successor of RFC 1701 and 1702) for more details.
45  * If_gre is compatible with Cisco GRE tunnels, so you can
46  * have a NetBSD box as the other end of a tunnel interface of a Cisco
47  * router. See gre(4) for more details.
48  * Also supported:  IP in IP encaps (proto 55) as of RFC 2004
49  */
50
51 #include "opt_atalk.h"
52 #include "opt_inet.h"
53 #include "opt_inet6.h"
54
55 #include <sys/param.h>
56 #include <sys/kernel.h>
57 #include <sys/malloc.h>
58 #include <sys/module.h>
59 #include <sys/mbuf.h>
60 #include <sys/priv.h>
61 #include <sys/proc.h>
62 #include <sys/protosw.h>
63 #include <sys/socket.h>
64 #include <sys/sockio.h>
65 #include <sys/sysctl.h>
66 #include <sys/systm.h>
67
68 #include <net/ethernet.h>
69 #include <net/if.h>
70 #include <net/if_clone.h>
71 #include <net/if_types.h>
72 #include <net/route.h>
73 #include <net/vnet.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_gre.h>
81 #include <netinet/ip_var.h>
82 #include <netinet/ip_encap.h>
83 #else
84 #error "Huh? if_gre without inet?"
85 #endif
86
87 #include <net/bpf.h>
88
89 #include <net/if_gre.h>
90
91 /*
92  * It is not easy to calculate the right value for a GRE MTU.
93  * We leave this task to the admin and use the same default that
94  * other vendors use.
95  */
96 #define GREMTU  1476
97
98 #define GRENAME "gre"
99
100 /*
101  * gre_mtx protects all global variables in if_gre.c.
102  * XXX: gre_softc data not protected yet.
103  */
104 struct mtx gre_mtx;
105 static MALLOC_DEFINE(M_GRE, GRENAME, "Generic Routing Encapsulation");
106
107 struct gre_softc_head gre_softc_list;
108
109 static int      gre_clone_create(struct if_clone *, int, caddr_t);
110 static void     gre_clone_destroy(struct ifnet *);
111 static int      gre_ioctl(struct ifnet *, u_long, caddr_t);
112 static int      gre_output(struct ifnet *, struct mbuf *, struct sockaddr *,
113                     struct route *ro);
114
115 IFC_SIMPLE_DECLARE(gre, 0);
116
117 static int gre_compute_route(struct gre_softc *sc);
118
119 static void     greattach(void);
120
121 #ifdef INET
122 extern struct domain inetdomain;
123 static const struct protosw in_gre_protosw = {
124         .pr_type =              SOCK_RAW,
125         .pr_domain =            &inetdomain,
126         .pr_protocol =          IPPROTO_GRE,
127         .pr_flags =             PR_ATOMIC|PR_ADDR,
128         .pr_input =             gre_input,
129         .pr_output =            (pr_output_t *)rip_output,
130         .pr_ctlinput =          rip_ctlinput,
131         .pr_ctloutput =         rip_ctloutput,
132         .pr_usrreqs =           &rip_usrreqs
133 };
134 static const struct protosw in_mobile_protosw = {
135         .pr_type =              SOCK_RAW,
136         .pr_domain =            &inetdomain,
137         .pr_protocol =          IPPROTO_MOBILE,
138         .pr_flags =             PR_ATOMIC|PR_ADDR,
139         .pr_input =             gre_mobile_input,
140         .pr_output =            (pr_output_t *)rip_output,
141         .pr_ctlinput =          rip_ctlinput,
142         .pr_ctloutput =         rip_ctloutput,
143         .pr_usrreqs =           &rip_usrreqs
144 };
145 #endif
146
147 SYSCTL_DECL(_net_link);
148 SYSCTL_NODE(_net_link, IFT_TUNNEL, gre, CTLFLAG_RW, 0,
149     "Generic Routing Encapsulation");
150 #ifndef MAX_GRE_NEST
151 /*
152  * This macro controls the default upper limitation on nesting of gre tunnels.
153  * Since, setting a large value to this macro with a careless configuration
154  * may introduce system crash, we don't allow any nestings by default.
155  * If you need to configure nested gre tunnels, you can define this macro
156  * in your kernel configuration file.  However, if you do so, please be
157  * careful to configure the tunnels so that it won't make a loop.
158  */
159 #define MAX_GRE_NEST 1
160 #endif
161 static int max_gre_nesting = MAX_GRE_NEST;
162 SYSCTL_INT(_net_link_gre, OID_AUTO, max_nesting, CTLFLAG_RW,
163     &max_gre_nesting, 0, "Max nested tunnels");
164
165 /* ARGSUSED */
166 static void
167 greattach(void)
168 {
169
170         mtx_init(&gre_mtx, "gre_mtx", NULL, MTX_DEF);
171         LIST_INIT(&gre_softc_list);
172         if_clone_attach(&gre_cloner);
173 }
174
175 static int
176 gre_clone_create(ifc, unit, params)
177         struct if_clone *ifc;
178         int unit;
179         caddr_t params;
180 {
181         struct gre_softc *sc;
182
183         sc = malloc(sizeof(struct gre_softc), M_GRE, M_WAITOK | M_ZERO);
184
185         GRE2IFP(sc) = if_alloc(IFT_TUNNEL);
186         if (GRE2IFP(sc) == NULL) {
187                 free(sc, M_GRE);
188                 return (ENOSPC);
189         }
190
191         GRE2IFP(sc)->if_softc = sc;
192         if_initname(GRE2IFP(sc), ifc->ifc_name, unit);
193
194         GRE2IFP(sc)->if_snd.ifq_maxlen = IFQ_MAXLEN;
195         GRE2IFP(sc)->if_addrlen = 0;
196         GRE2IFP(sc)->if_hdrlen = 24; /* IP + GRE */
197         GRE2IFP(sc)->if_mtu = GREMTU;
198         GRE2IFP(sc)->if_flags = IFF_POINTOPOINT|IFF_MULTICAST;
199         GRE2IFP(sc)->if_output = gre_output;
200         GRE2IFP(sc)->if_ioctl = gre_ioctl;
201         sc->g_dst.s_addr = sc->g_src.s_addr = INADDR_ANY;
202         sc->g_proto = IPPROTO_GRE;
203         GRE2IFP(sc)->if_flags |= IFF_LINK0;
204         sc->encap = NULL;
205         sc->called = 0;
206         sc->gre_fibnum = curthread->td_proc->p_fibnum;
207         sc->wccp_ver = WCCP_V1;
208         sc->key = 0;
209         if_attach(GRE2IFP(sc));
210         bpfattach(GRE2IFP(sc), DLT_NULL, sizeof(u_int32_t));
211         mtx_lock(&gre_mtx);
212         LIST_INSERT_HEAD(&gre_softc_list, sc, sc_list);
213         mtx_unlock(&gre_mtx);
214         return (0);
215 }
216
217 static void
218 gre_clone_destroy(ifp)
219         struct ifnet *ifp;
220 {
221         struct gre_softc *sc = ifp->if_softc;
222
223         mtx_lock(&gre_mtx);
224         LIST_REMOVE(sc, sc_list);
225         mtx_unlock(&gre_mtx);
226
227 #ifdef INET
228         if (sc->encap != NULL)
229                 encap_detach(sc->encap);
230 #endif
231         bpfdetach(ifp);
232         if_detach(ifp);
233         if_free(ifp);
234         free(sc, M_GRE);
235 }
236
237 /*
238  * The output routine. Takes a packet and encapsulates it in the protocol
239  * given by sc->g_proto. See also RFC 1701 and RFC 2004
240  */
241 static int
242 gre_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst,
243            struct route *ro)
244 {
245         int error = 0;
246         struct gre_softc *sc = ifp->if_softc;
247         struct greip *gh;
248         struct ip *ip;
249         u_short gre_ip_id = 0;
250         uint8_t gre_ip_tos = 0;
251         u_int16_t etype = 0;
252         struct mobile_h mob_h;
253         u_int32_t af;
254         int extra = 0;
255
256         /*
257          * gre may cause infinite recursion calls when misconfigured.
258          * We'll prevent this by introducing upper limit.
259          */
260         if (++(sc->called) > max_gre_nesting) {
261                 printf("%s: gre_output: recursively called too many "
262                        "times(%d)\n", if_name(GRE2IFP(sc)), sc->called);
263                 m_freem(m);
264                 error = EIO;    /* is there better errno? */
265                 goto end;
266         }
267
268         if (!((ifp->if_flags & IFF_UP) &&
269             (ifp->if_drv_flags & IFF_DRV_RUNNING)) ||
270             sc->g_src.s_addr == INADDR_ANY || sc->g_dst.s_addr == INADDR_ANY) {
271                 m_freem(m);
272                 error = ENETDOWN;
273                 goto end;
274         }
275
276         gh = NULL;
277         ip = NULL;
278
279         /* BPF writes need to be handled specially. */
280         if (dst->sa_family == AF_UNSPEC) {
281                 bcopy(dst->sa_data, &af, sizeof(af));
282                 dst->sa_family = af;
283         }
284
285         if (bpf_peers_present(ifp->if_bpf)) {
286                 af = dst->sa_family;
287                 bpf_mtap2(ifp->if_bpf, &af, sizeof(af), m);
288         }
289
290         m->m_flags &= ~(M_BCAST|M_MCAST);
291
292         if (sc->g_proto == IPPROTO_MOBILE) {
293                 if (dst->sa_family == AF_INET) {
294                         struct mbuf *m0;
295                         int msiz;
296
297                         ip = mtod(m, struct ip *);
298
299                         /*
300                          * RFC2004 specifies that fragmented diagrams shouldn't
301                          * be encapsulated.
302                          */
303                         if (ip->ip_off & (IP_MF | IP_OFFMASK)) {
304                                 _IF_DROP(&ifp->if_snd);
305                                 m_freem(m);
306                                 error = EINVAL;    /* is there better errno? */
307                                 goto end;
308                         }
309                         memset(&mob_h, 0, MOB_H_SIZ_L);
310                         mob_h.proto = (ip->ip_p) << 8;
311                         mob_h.odst = ip->ip_dst.s_addr;
312                         ip->ip_dst.s_addr = sc->g_dst.s_addr;
313
314                         /*
315                          * If the packet comes from our host, we only change
316                          * the destination address in the IP header.
317                          * Else we also need to save and change the source
318                          */
319                         if (in_hosteq(ip->ip_src, sc->g_src)) {
320                                 msiz = MOB_H_SIZ_S;
321                         } else {
322                                 mob_h.proto |= MOB_H_SBIT;
323                                 mob_h.osrc = ip->ip_src.s_addr;
324                                 ip->ip_src.s_addr = sc->g_src.s_addr;
325                                 msiz = MOB_H_SIZ_L;
326                         }
327                         mob_h.proto = htons(mob_h.proto);
328                         mob_h.hcrc = gre_in_cksum((u_int16_t *)&mob_h, msiz);
329
330                         if ((m->m_data - msiz) < m->m_pktdat) {
331                                 /* need new mbuf */
332                                 MGETHDR(m0, M_DONTWAIT, MT_DATA);
333                                 if (m0 == NULL) {
334                                         _IF_DROP(&ifp->if_snd);
335                                         m_freem(m);
336                                         error = ENOBUFS;
337                                         goto end;
338                                 }
339                                 m0->m_next = m;
340                                 m->m_data += sizeof(struct ip);
341                                 m->m_len -= sizeof(struct ip);
342                                 m0->m_pkthdr.len = m->m_pkthdr.len + msiz;
343                                 m0->m_len = msiz + sizeof(struct ip);
344                                 m0->m_data += max_linkhdr;
345                                 memcpy(mtod(m0, caddr_t), (caddr_t)ip,
346                                        sizeof(struct ip));
347                                 m = m0;
348                         } else {  /* we have some space left in the old one */
349                                 m->m_data -= msiz;
350                                 m->m_len += msiz;
351                                 m->m_pkthdr.len += msiz;
352                                 bcopy(ip, mtod(m, caddr_t),
353                                         sizeof(struct ip));
354                         }
355                         ip = mtod(m, struct ip *);
356                         memcpy((caddr_t)(ip + 1), &mob_h, (unsigned)msiz);
357                         ip->ip_len = ntohs(ip->ip_len) + msiz;
358                 } else {  /* AF_INET */
359                         _IF_DROP(&ifp->if_snd);
360                         m_freem(m);
361                         error = EINVAL;
362                         goto end;
363                 }
364         } else if (sc->g_proto == IPPROTO_GRE) {
365                 switch (dst->sa_family) {
366                 case AF_INET:
367                         ip = mtod(m, struct ip *);
368                         gre_ip_tos = ip->ip_tos;
369                         gre_ip_id = ip->ip_id;
370                         if (sc->wccp_ver == WCCP_V2) {
371                                 extra = sizeof(uint32_t);
372                                 etype =  WCCP_PROTOCOL_TYPE;
373                         } else {
374                                 etype = ETHERTYPE_IP;
375                         }
376                         break;
377 #ifdef INET6
378                 case AF_INET6:
379                         gre_ip_id = ip_newid();
380                         etype = ETHERTYPE_IPV6;
381                         break;
382 #endif
383 #ifdef NETATALK
384                 case AF_APPLETALK:
385                         etype = ETHERTYPE_ATALK;
386                         break;
387 #endif
388                 default:
389                         _IF_DROP(&ifp->if_snd);
390                         m_freem(m);
391                         error = EAFNOSUPPORT;
392                         goto end;
393                 }
394                         
395                 /* Reserve space for GRE header + optional GRE key */
396                 int hdrlen = sizeof(struct greip) + extra;
397                 if (sc->key)
398                         hdrlen += sizeof(uint32_t);
399                 M_PREPEND(m, hdrlen, M_DONTWAIT);
400         } else {
401                 _IF_DROP(&ifp->if_snd);
402                 m_freem(m);
403                 error = EINVAL;
404                 goto end;
405         }
406
407         if (m == NULL) {        /* mbuf allocation failed */
408                 _IF_DROP(&ifp->if_snd);
409                 error = ENOBUFS;
410                 goto end;
411         }
412
413         M_SETFIB(m, sc->gre_fibnum); /* The envelope may use a different FIB */
414
415         gh = mtod(m, struct greip *);
416         if (sc->g_proto == IPPROTO_GRE) {
417                 uint32_t *options = gh->gi_options;
418
419                 memset((void *)gh, 0, sizeof(struct greip) + extra);
420                 gh->gi_ptype = htons(etype);
421                 gh->gi_flags = 0;
422
423                 /* Add key option */
424                 if (sc->key)
425                 {
426                         gh->gi_flags |= htons(GRE_KP);
427                         *(options++) = htonl(sc->key);
428                 }
429         }
430
431         gh->gi_pr = sc->g_proto;
432         if (sc->g_proto != IPPROTO_MOBILE) {
433                 gh->gi_src = sc->g_src;
434                 gh->gi_dst = sc->g_dst;
435                 ((struct ip*)gh)->ip_v = IPPROTO_IPV4;
436                 ((struct ip*)gh)->ip_hl = (sizeof(struct ip)) >> 2;
437                 ((struct ip*)gh)->ip_ttl = GRE_TTL;
438                 ((struct ip*)gh)->ip_tos = gre_ip_tos;
439                 ((struct ip*)gh)->ip_id = gre_ip_id;
440                 gh->gi_len = m->m_pkthdr.len;
441         }
442
443         ifp->if_opackets++;
444         ifp->if_obytes += m->m_pkthdr.len;
445         /*
446          * Send it off and with IP_FORWARD flag to prevent it from
447          * overwriting the ip_id again.  ip_id is already set to the
448          * ip_id of the encapsulated packet.
449          */
450         error = ip_output(m, NULL, &sc->route, IP_FORWARDING,
451             (struct ip_moptions *)NULL, (struct inpcb *)NULL);
452   end:
453         sc->called = 0;
454         if (error)
455                 ifp->if_oerrors++;
456         return (error);
457 }
458
459 static int
460 gre_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
461 {
462         struct ifreq *ifr = (struct ifreq *)data;
463         struct if_laddrreq *lifr = (struct if_laddrreq *)data;
464         struct in_aliasreq *aifr = (struct in_aliasreq *)data;
465         struct gre_softc *sc = ifp->if_softc;
466         int s;
467         struct sockaddr_in si;
468         struct sockaddr *sa = NULL;
469         int error, adj;
470         struct sockaddr_in sp, sm, dp, dm;
471         uint32_t key;
472
473         error = 0;
474         adj = 0;
475
476         s = splnet();
477         switch (cmd) {
478         case SIOCSIFADDR:
479                 ifp->if_flags |= IFF_UP;
480                 break;
481         case SIOCSIFDSTADDR:
482                 break;
483         case SIOCSIFFLAGS:
484                 /*
485                  * XXXRW: Isn't this priv_check() redundant to the ifnet
486                  * layer check?
487                  */
488                 if ((error = priv_check(curthread, PRIV_NET_SETIFFLAGS)) != 0)
489                         break;
490                 if ((ifr->ifr_flags & IFF_LINK0) != 0)
491                         sc->g_proto = IPPROTO_GRE;
492                 else
493                         sc->g_proto = IPPROTO_MOBILE;
494                 if ((ifr->ifr_flags & IFF_LINK2) != 0)
495                         sc->wccp_ver = WCCP_V2;
496                 else
497                         sc->wccp_ver = WCCP_V1;
498                 goto recompute;
499         case SIOCSIFMTU:
500                 /*
501                  * XXXRW: Isn't this priv_check() redundant to the ifnet
502                  * layer check?
503                  */
504                 if ((error = priv_check(curthread, PRIV_NET_SETIFMTU)) != 0)
505                         break;
506                 if (ifr->ifr_mtu < 576) {
507                         error = EINVAL;
508                         break;
509                 }
510                 ifp->if_mtu = ifr->ifr_mtu;
511                 break;
512         case SIOCGIFMTU:
513                 ifr->ifr_mtu = GRE2IFP(sc)->if_mtu;
514                 break;
515         case SIOCADDMULTI:
516                 /*
517                  * XXXRW: Isn't this priv_checkr() redundant to the ifnet
518                  * layer check?
519                  */
520                 if ((error = priv_check(curthread, PRIV_NET_ADDMULTI)) != 0)
521                         break;
522                 if (ifr == 0) {
523                         error = EAFNOSUPPORT;
524                         break;
525                 }
526                 switch (ifr->ifr_addr.sa_family) {
527 #ifdef INET
528                 case AF_INET:
529                         break;
530 #endif
531 #ifdef INET6
532                 case AF_INET6:
533                         break;
534 #endif
535                 default:
536                         error = EAFNOSUPPORT;
537                         break;
538                 }
539                 break;
540         case SIOCDELMULTI:
541                 /*
542                  * XXXRW: Isn't this priv_check() redundant to the ifnet
543                  * layer check?
544                  */
545                 if ((error = priv_check(curthread, PRIV_NET_DELIFGROUP)) != 0)
546                         break;
547                 if (ifr == 0) {
548                         error = EAFNOSUPPORT;
549                         break;
550                 }
551                 switch (ifr->ifr_addr.sa_family) {
552 #ifdef INET
553                 case AF_INET:
554                         break;
555 #endif
556 #ifdef INET6
557                 case AF_INET6:
558                         break;
559 #endif
560                 default:
561                         error = EAFNOSUPPORT;
562                         break;
563                 }
564                 break;
565         case GRESPROTO:
566                 /*
567                  * XXXRW: Isn't this priv_check() redundant to the ifnet
568                  * layer check?
569                  */
570                 if ((error = priv_check(curthread, PRIV_NET_GRE)) != 0)
571                         break;
572                 sc->g_proto = ifr->ifr_flags;
573                 switch (sc->g_proto) {
574                 case IPPROTO_GRE:
575                         ifp->if_flags |= IFF_LINK0;
576                         break;
577                 case IPPROTO_MOBILE:
578                         ifp->if_flags &= ~IFF_LINK0;
579                         break;
580                 default:
581                         error = EPROTONOSUPPORT;
582                         break;
583                 }
584                 goto recompute;
585         case GREGPROTO:
586                 ifr->ifr_flags = sc->g_proto;
587                 break;
588         case GRESADDRS:
589         case GRESADDRD:
590                 error = priv_check(curthread, PRIV_NET_GRE);
591                 if (error)
592                         return (error);
593                 /*
594                  * set tunnel endpoints, compute a less specific route
595                  * to the remote end and mark if as up
596                  */
597                 sa = &ifr->ifr_addr;
598                 if (cmd == GRESADDRS)
599                         sc->g_src = (satosin(sa))->sin_addr;
600                 if (cmd == GRESADDRD)
601                         sc->g_dst = (satosin(sa))->sin_addr;
602         recompute:
603 #ifdef INET
604                 if (sc->encap != NULL) {
605                         encap_detach(sc->encap);
606                         sc->encap = NULL;
607                 }
608 #endif
609                 if ((sc->g_src.s_addr != INADDR_ANY) &&
610                     (sc->g_dst.s_addr != INADDR_ANY)) {
611                         bzero(&sp, sizeof(sp));
612                         bzero(&sm, sizeof(sm));
613                         bzero(&dp, sizeof(dp));
614                         bzero(&dm, sizeof(dm));
615                         sp.sin_len = sm.sin_len = dp.sin_len = dm.sin_len =
616                             sizeof(struct sockaddr_in);
617                         sp.sin_family = sm.sin_family = dp.sin_family =
618                             dm.sin_family = AF_INET;
619                         sp.sin_addr = sc->g_src;
620                         dp.sin_addr = sc->g_dst;
621                         sm.sin_addr.s_addr = dm.sin_addr.s_addr =
622                             INADDR_BROADCAST;
623 #ifdef INET
624                         sc->encap = encap_attach(AF_INET, sc->g_proto,
625                             sintosa(&sp), sintosa(&sm), sintosa(&dp),
626                             sintosa(&dm), (sc->g_proto == IPPROTO_GRE) ?
627                                 &in_gre_protosw : &in_mobile_protosw, sc);
628                         if (sc->encap == NULL)
629                                 printf("%s: unable to attach encap\n",
630                                     if_name(GRE2IFP(sc)));
631 #endif
632                         if (sc->route.ro_rt != 0) /* free old route */
633                                 RTFREE(sc->route.ro_rt);
634                         if (gre_compute_route(sc) == 0)
635                                 ifp->if_drv_flags |= IFF_DRV_RUNNING;
636                         else
637                                 ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
638                 }
639                 break;
640         case GREGADDRS:
641                 memset(&si, 0, sizeof(si));
642                 si.sin_family = AF_INET;
643                 si.sin_len = sizeof(struct sockaddr_in);
644                 si.sin_addr.s_addr = sc->g_src.s_addr;
645                 sa = sintosa(&si);
646                 ifr->ifr_addr = *sa;
647                 break;
648         case GREGADDRD:
649                 memset(&si, 0, sizeof(si));
650                 si.sin_family = AF_INET;
651                 si.sin_len = sizeof(struct sockaddr_in);
652                 si.sin_addr.s_addr = sc->g_dst.s_addr;
653                 sa = sintosa(&si);
654                 ifr->ifr_addr = *sa;
655                 break;
656         case SIOCSIFPHYADDR:
657                 /*
658                  * XXXRW: Isn't this priv_check() redundant to the ifnet
659                  * layer check?
660                  */
661                 if ((error = priv_check(curthread, PRIV_NET_SETIFPHYS)) != 0)
662                         break;
663                 if (aifr->ifra_addr.sin_family != AF_INET ||
664                     aifr->ifra_dstaddr.sin_family != AF_INET) {
665                         error = EAFNOSUPPORT;
666                         break;
667                 }
668                 if (aifr->ifra_addr.sin_len != sizeof(si) ||
669                     aifr->ifra_dstaddr.sin_len != sizeof(si)) {
670                         error = EINVAL;
671                         break;
672                 }
673                 sc->g_src = aifr->ifra_addr.sin_addr;
674                 sc->g_dst = aifr->ifra_dstaddr.sin_addr;
675                 goto recompute;
676         case SIOCSLIFPHYADDR:
677                 /*
678                  * XXXRW: Isn't this priv_check() redundant to the ifnet
679                  * layer check?
680                  */
681                 if ((error = priv_check(curthread, PRIV_NET_SETIFPHYS)) != 0)
682                         break;
683                 if (lifr->addr.ss_family != AF_INET ||
684                     lifr->dstaddr.ss_family != AF_INET) {
685                         error = EAFNOSUPPORT;
686                         break;
687                 }
688                 if (lifr->addr.ss_len != sizeof(si) ||
689                     lifr->dstaddr.ss_len != sizeof(si)) {
690                         error = EINVAL;
691                         break;
692                 }
693                 sc->g_src = (satosin(&lifr->addr))->sin_addr;
694                 sc->g_dst =
695                     (satosin(&lifr->dstaddr))->sin_addr;
696                 goto recompute;
697         case SIOCDIFPHYADDR:
698                 /*
699                  * XXXRW: Isn't this priv_check() redundant to the ifnet
700                  * layer check?
701                  */
702                 if ((error = priv_check(curthread, PRIV_NET_SETIFPHYS)) != 0)
703                         break;
704                 sc->g_src.s_addr = INADDR_ANY;
705                 sc->g_dst.s_addr = INADDR_ANY;
706                 goto recompute;
707         case SIOCGLIFPHYADDR:
708                 if (sc->g_src.s_addr == INADDR_ANY ||
709                     sc->g_dst.s_addr == INADDR_ANY) {
710                         error = EADDRNOTAVAIL;
711                         break;
712                 }
713                 memset(&si, 0, sizeof(si));
714                 si.sin_family = AF_INET;
715                 si.sin_len = sizeof(struct sockaddr_in);
716                 si.sin_addr.s_addr = sc->g_src.s_addr;
717                 memcpy(&lifr->addr, &si, sizeof(si));
718                 si.sin_addr.s_addr = sc->g_dst.s_addr;
719                 memcpy(&lifr->dstaddr, &si, sizeof(si));
720                 break;
721         case SIOCGIFPSRCADDR:
722 #ifdef INET6
723         case SIOCGIFPSRCADDR_IN6:
724 #endif
725                 if (sc->g_src.s_addr == INADDR_ANY) {
726                         error = EADDRNOTAVAIL;
727                         break;
728                 }
729                 memset(&si, 0, sizeof(si));
730                 si.sin_family = AF_INET;
731                 si.sin_len = sizeof(struct sockaddr_in);
732                 si.sin_addr.s_addr = sc->g_src.s_addr;
733                 bcopy(&si, &ifr->ifr_addr, sizeof(ifr->ifr_addr));
734                 break;
735         case SIOCGIFPDSTADDR:
736 #ifdef INET6
737         case SIOCGIFPDSTADDR_IN6:
738 #endif
739                 if (sc->g_dst.s_addr == INADDR_ANY) {
740                         error = EADDRNOTAVAIL;
741                         break;
742                 }
743                 memset(&si, 0, sizeof(si));
744                 si.sin_family = AF_INET;
745                 si.sin_len = sizeof(struct sockaddr_in);
746                 si.sin_addr.s_addr = sc->g_dst.s_addr;
747                 bcopy(&si, &ifr->ifr_addr, sizeof(ifr->ifr_addr));
748                 break;
749         case GRESKEY:
750                 error = priv_check(curthread, PRIV_NET_GRE);
751                 if (error)
752                         break;
753                 error = copyin(ifr->ifr_data, &key, sizeof(key));
754                 if (error)
755                         break;
756                 /* adjust MTU for option header */
757                 if (key == 0 && sc->key != 0)           /* clear */
758                         adj += sizeof(key);
759                 else if (key != 0 && sc->key == 0)      /* set */
760                         adj -= sizeof(key);
761
762                 if (ifp->if_mtu + adj < 576) {
763                         error = EINVAL;
764                         break;
765                 }
766                 ifp->if_mtu += adj;
767                 sc->key = key;
768                 break;
769         case GREGKEY:
770                 error = copyout(&sc->key, ifr->ifr_data, sizeof(sc->key));
771                 break;
772
773         default:
774                 error = EINVAL;
775                 break;
776         }
777
778         splx(s);
779         return (error);
780 }
781
782 /*
783  * computes a route to our destination that is not the one
784  * which would be taken by ip_output(), as this one will loop back to
785  * us. If the interface is p2p as  a--->b, then a routing entry exists
786  * If we now send a packet to b (e.g. ping b), this will come down here
787  * gets src=a, dst=b tacked on and would from ip_output() sent back to
788  * if_gre.
789  * Goal here is to compute a route to b that is less specific than
790  * a-->b. We know that this one exists as in normal operation we have
791  * at least a default route which matches.
792  */
793 static int
794 gre_compute_route(struct gre_softc *sc)
795 {
796         struct route *ro;
797
798         ro = &sc->route;
799
800         memset(ro, 0, sizeof(struct route));
801         ((struct sockaddr_in *)&ro->ro_dst)->sin_addr = sc->g_dst;
802         ro->ro_dst.sa_family = AF_INET;
803         ro->ro_dst.sa_len = sizeof(ro->ro_dst);
804
805         /*
806          * toggle last bit, so our interface is not found, but a less
807          * specific route. I'd rather like to specify a shorter mask,
808          * but this is not possible. Should work though. XXX
809          * XXX MRT Use a different FIB for the tunnel to solve this problem.
810          */
811         if ((GRE2IFP(sc)->if_flags & IFF_LINK1) == 0) {
812                 ((struct sockaddr_in *)&ro->ro_dst)->sin_addr.s_addr ^=
813                     htonl(0x01);
814         }
815
816 #ifdef DIAGNOSTIC
817         printf("%s: searching for a route to %s", if_name(GRE2IFP(sc)),
818             inet_ntoa(((struct sockaddr_in *)&ro->ro_dst)->sin_addr));
819 #endif
820
821         rtalloc_fib(ro, sc->gre_fibnum);
822
823         /*
824          * check if this returned a route at all and this route is no
825          * recursion to ourself
826          */
827         if (ro->ro_rt == NULL || ro->ro_rt->rt_ifp->if_softc == sc) {
828 #ifdef DIAGNOSTIC
829                 if (ro->ro_rt == NULL)
830                         printf(" - no route found!\n");
831                 else
832                         printf(" - route loops back to ourself!\n");
833 #endif
834                 return EADDRNOTAVAIL;
835         }
836
837         /*
838          * now change it back - else ip_output will just drop
839          * the route and search one to this interface ...
840          */
841         if ((GRE2IFP(sc)->if_flags & IFF_LINK1) == 0)
842                 ((struct sockaddr_in *)&ro->ro_dst)->sin_addr = sc->g_dst;
843
844 #ifdef DIAGNOSTIC
845         printf(", choosing %s with gateway %s", if_name(ro->ro_rt->rt_ifp),
846             inet_ntoa(((struct sockaddr_in *)(ro->ro_rt->rt_gateway))->sin_addr));
847         printf("\n");
848 #endif
849
850         return 0;
851 }
852
853 /*
854  * do a checksum of a buffer - much like in_cksum, which operates on
855  * mbufs.
856  */
857 u_int16_t
858 gre_in_cksum(u_int16_t *p, u_int len)
859 {
860         u_int32_t sum = 0;
861         int nwords = len >> 1;
862
863         while (nwords-- != 0)
864                 sum += *p++;
865
866         if (len & 1) {
867                 union {
868                         u_short w;
869                         u_char c[2];
870                 } u;
871                 u.c[0] = *(u_char *)p;
872                 u.c[1] = 0;
873                 sum += u.w;
874         }
875
876         /* end-around-carry */
877         sum = (sum >> 16) + (sum & 0xffff);
878         sum += (sum >> 16);
879         return (~sum);
880 }
881
882 static int
883 gremodevent(module_t mod, int type, void *data)
884 {
885
886         switch (type) {
887         case MOD_LOAD:
888                 greattach();
889                 break;
890         case MOD_UNLOAD:
891                 if_clone_detach(&gre_cloner);
892                 mtx_destroy(&gre_mtx);
893                 break;
894         default:
895                 return EOPNOTSUPP;
896         }
897         return 0;
898 }
899
900 static moduledata_t gre_mod = {
901         "if_gre",
902         gremodevent,
903         0
904 };
905
906 DECLARE_MODULE(if_gre, gre_mod, SI_SUB_PSEUDO, SI_ORDER_ANY);
907 MODULE_VERSION(if_gre, 1);