]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/netinet/ip_gre.c
jail: convert several functions from int to bool
[FreeBSD/FreeBSD.git] / sys / netinet / ip_gre.c
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause-NetBSD
3  *
4  * Copyright (c) 1998 The NetBSD Foundation, Inc.
5  * Copyright (c) 2014, 2018 Andrey V. Elsukov <ae@FreeBSD.org>
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  *
22  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
23  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
24  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
25  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
26  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
27  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
28  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
29  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
30  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
31  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32  * POSSIBILITY OF SUCH DAMAGE.
33  *
34  * $NetBSD: ip_gre.c,v 1.29 2003/09/05 23:02:43 itojun Exp $
35  */
36
37 #include <sys/cdefs.h>
38 __FBSDID("$FreeBSD$");
39
40 #include "opt_inet.h"
41 #include "opt_inet6.h"
42
43 #include <sys/param.h>
44 #include <sys/jail.h>
45 #include <sys/systm.h>
46 #include <sys/socket.h>
47 #include <sys/socketvar.h>
48 #include <sys/sockio.h>
49 #include <sys/mbuf.h>
50 #include <sys/errno.h>
51 #include <sys/kernel.h>
52 #include <sys/sysctl.h>
53 #include <sys/malloc.h>
54 #include <sys/proc.h>
55
56 #include <net/if.h>
57 #include <net/if_var.h>
58 #include <net/if_private.h>
59 #include <net/vnet.h>
60
61 #include <netinet/in.h>
62 #include <netinet/in_var.h>
63 #include <netinet/in_pcb.h>
64 #include <netinet/ip.h>
65 #include <netinet/ip_encap.h>
66 #include <netinet/ip_var.h>
67 #include <netinet/udp.h>
68 #include <netinet/udp_var.h>
69
70 #ifdef INET6
71 #include <netinet/ip6.h>
72 #endif
73
74 #include <net/if_gre.h>
75 #include <machine/in_cksum.h>
76
77 #define GRE_TTL                 30
78 VNET_DEFINE(int, ip_gre_ttl) = GRE_TTL;
79 #define V_ip_gre_ttl            VNET(ip_gre_ttl)
80 SYSCTL_INT(_net_inet_ip, OID_AUTO, grettl, CTLFLAG_VNET | CTLFLAG_RW,
81     &VNET_NAME(ip_gre_ttl), 0, "Default TTL value for encapsulated packets");
82
83 struct in_gre_socket {
84         struct gre_socket               base;
85         in_addr_t                       addr;
86 };
87 VNET_DEFINE_STATIC(struct gre_sockets *, ipv4_sockets) = NULL;
88 VNET_DEFINE_STATIC(struct gre_list *, ipv4_hashtbl) = NULL;
89 VNET_DEFINE_STATIC(struct gre_list *, ipv4_srchashtbl) = NULL;
90 #define V_ipv4_sockets          VNET(ipv4_sockets)
91 #define V_ipv4_hashtbl          VNET(ipv4_hashtbl)
92 #define V_ipv4_srchashtbl       VNET(ipv4_srchashtbl)
93 #define GRE_HASH(src, dst)      (V_ipv4_hashtbl[\
94     in_gre_hashval((src), (dst)) & (GRE_HASH_SIZE - 1)])
95 #define GRE_SRCHASH(src)        (V_ipv4_srchashtbl[\
96     fnv_32_buf(&(src), sizeof(src), FNV1_32_INIT) & (GRE_HASH_SIZE - 1)])
97 #define GRE_SOCKHASH(src)       (V_ipv4_sockets[\
98     fnv_32_buf(&(src), sizeof(src), FNV1_32_INIT) & (GRE_HASH_SIZE - 1)])
99 #define GRE_HASH_SC(sc)         GRE_HASH((sc)->gre_oip.ip_src.s_addr,\
100     (sc)->gre_oip.ip_dst.s_addr)
101
102 static uint32_t
103 in_gre_hashval(in_addr_t src, in_addr_t dst)
104 {
105         uint32_t ret;
106
107         ret = fnv_32_buf(&src, sizeof(src), FNV1_32_INIT);
108         return (fnv_32_buf(&dst, sizeof(dst), ret));
109 }
110
111 static struct gre_socket*
112 in_gre_lookup_socket(in_addr_t addr)
113 {
114         struct gre_socket *gs;
115         struct in_gre_socket *s;
116
117         CK_LIST_FOREACH(gs, &GRE_SOCKHASH(addr), chain) {
118                 s = __containerof(gs, struct in_gre_socket, base);
119                 if (s->addr == addr)
120                         break;
121         }
122         return (gs);
123 }
124
125 static int
126 in_gre_checkdup(const struct gre_softc *sc, in_addr_t src, in_addr_t dst,
127     uint32_t opts)
128 {
129         struct gre_list *head;
130         struct gre_softc *tmp;
131         struct gre_socket *gs;
132
133         if (sc->gre_family == AF_INET &&
134             sc->gre_oip.ip_src.s_addr == src &&
135             sc->gre_oip.ip_dst.s_addr == dst &&
136             (sc->gre_options & GRE_UDPENCAP) == (opts & GRE_UDPENCAP))
137                 return (EEXIST);
138
139         if (opts & GRE_UDPENCAP) {
140                 gs = in_gre_lookup_socket(src);
141                 if (gs == NULL)
142                         return (0);
143                 head = &gs->list;
144         } else
145                 head = &GRE_HASH(src, dst);
146
147         CK_LIST_FOREACH(tmp, head, chain) {
148                 if (tmp == sc)
149                         continue;
150                 if (tmp->gre_oip.ip_src.s_addr == src &&
151                     tmp->gre_oip.ip_dst.s_addr == dst)
152                         return (EADDRNOTAVAIL);
153         }
154         return (0);
155 }
156
157 static int
158 in_gre_lookup(const struct mbuf *m, int off, int proto, void **arg)
159 {
160         const struct ip *ip;
161         struct gre_softc *sc;
162
163         if (V_ipv4_hashtbl == NULL)
164                 return (0);
165
166         NET_EPOCH_ASSERT();
167         ip = mtod(m, const struct ip *);
168         CK_LIST_FOREACH(sc, &GRE_HASH(ip->ip_dst.s_addr,
169             ip->ip_src.s_addr), chain) {
170                 /*
171                  * This is an inbound packet, its ip_dst is source address
172                  * in softc.
173                  */
174                 if (sc->gre_oip.ip_src.s_addr == ip->ip_dst.s_addr &&
175                     sc->gre_oip.ip_dst.s_addr == ip->ip_src.s_addr) {
176                         if ((GRE2IFP(sc)->if_flags & IFF_UP) == 0)
177                                 return (0);
178                         *arg = sc;
179                         return (ENCAP_DRV_LOOKUP);
180                 }
181         }
182         return (0);
183 }
184
185 /*
186  * Check that ingress address belongs to local host.
187  */
188 static void
189 in_gre_set_running(struct gre_softc *sc)
190 {
191
192         if (in_localip(sc->gre_oip.ip_src))
193                 GRE2IFP(sc)->if_drv_flags |= IFF_DRV_RUNNING;
194         else
195                 GRE2IFP(sc)->if_drv_flags &= ~IFF_DRV_RUNNING;
196 }
197
198 /*
199  * ifaddr_event handler.
200  * Clear IFF_DRV_RUNNING flag when ingress address disappears to prevent
201  * source address spoofing.
202  */
203 static void
204 in_gre_srcaddr(void *arg __unused, const struct sockaddr *sa,
205     int event __unused)
206 {
207         const struct sockaddr_in *sin;
208         struct gre_softc *sc;
209
210         /* Check that VNET is ready */
211         if (V_ipv4_hashtbl == NULL)
212                 return;
213
214         NET_EPOCH_ASSERT();
215         sin = (const struct sockaddr_in *)sa;
216         CK_LIST_FOREACH(sc, &GRE_SRCHASH(sin->sin_addr.s_addr), srchash) {
217                 if (sc->gre_oip.ip_src.s_addr != sin->sin_addr.s_addr)
218                         continue;
219                 in_gre_set_running(sc);
220         }
221 }
222
223 static bool
224 in_gre_udp_input(struct mbuf *m, int off, struct inpcb *inp,
225     const struct sockaddr *sa, void *ctx)
226 {
227         struct gre_socket *gs;
228         struct gre_softc *sc;
229         in_addr_t dst;
230
231         NET_EPOCH_ASSERT();
232
233         gs = (struct gre_socket *)ctx;
234         dst = ((const struct sockaddr_in *)sa)->sin_addr.s_addr;
235         CK_LIST_FOREACH(sc, &gs->list, chain) {
236                 if (sc->gre_oip.ip_dst.s_addr == dst)
237                         break;
238         }
239         if (sc != NULL && (GRE2IFP(sc)->if_flags & IFF_UP) != 0){
240                 gre_input(m, off + sizeof(struct udphdr), IPPROTO_UDP, sc);
241                 return (true);
242         }
243         m_freem(m);
244
245         return (true);
246 }
247
248 static int
249 in_gre_setup_socket(struct gre_softc *sc)
250 {
251         struct sockopt sopt;
252         struct sockaddr_in sin;
253         struct in_gre_socket *s;
254         struct gre_socket *gs;
255         in_addr_t addr;
256         int error, value;
257
258         /*
259          * NOTE: we are protected with gre_ioctl_sx lock.
260          *
261          * First check that socket is already configured.
262          * If so, check that source address was not changed.
263          * If address is different, check that there are no other tunnels
264          * and close socket.
265          */
266         addr = sc->gre_oip.ip_src.s_addr;
267         gs = sc->gre_so;
268         if (gs != NULL) {
269                 s = __containerof(gs, struct in_gre_socket, base);
270                 if (s->addr != addr) {
271                         if (CK_LIST_EMPTY(&gs->list)) {
272                                 CK_LIST_REMOVE(gs, chain);
273                                 soclose(gs->so);
274                                 NET_EPOCH_CALL(gre_sofree, &gs->epoch_ctx);
275                         }
276                         gs = sc->gre_so = NULL;
277                 }
278         }
279
280         if (gs == NULL) {
281                 /*
282                  * Check that socket for given address is already
283                  * configured.
284                  */
285                 gs = in_gre_lookup_socket(addr);
286                 if (gs == NULL) {
287                         s = malloc(sizeof(*s), M_GRE, M_WAITOK | M_ZERO);
288                         s->addr = addr;
289                         gs = &s->base;
290
291                         error = socreate(sc->gre_family, &gs->so,
292                             SOCK_DGRAM, IPPROTO_UDP, curthread->td_ucred,
293                             curthread);
294                         if (error != 0) {
295                                 if_printf(GRE2IFP(sc),
296                                     "cannot create socket: %d\n", error);
297                                 free(s, M_GRE);
298                                 return (error);
299                         }
300
301                         error = udp_set_kernel_tunneling(gs->so,
302                             in_gre_udp_input, NULL, gs);
303                         if (error != 0) {
304                                 if_printf(GRE2IFP(sc),
305                                     "cannot set UDP tunneling: %d\n", error);
306                                 goto fail;
307                         }
308
309                         memset(&sopt, 0, sizeof(sopt));
310                         sopt.sopt_dir = SOPT_SET;
311                         sopt.sopt_level = IPPROTO_IP;
312                         sopt.sopt_name = IP_BINDANY;
313                         sopt.sopt_val = &value;
314                         sopt.sopt_valsize = sizeof(value);
315                         value = 1;
316                         error = sosetopt(gs->so, &sopt);
317                         if (error != 0) {
318                                 if_printf(GRE2IFP(sc),
319                                     "cannot set IP_BINDANY opt: %d\n", error);
320                                 goto fail;
321                         }
322
323                         memset(&sin, 0, sizeof(sin));
324                         sin.sin_family = AF_INET;
325                         sin.sin_len = sizeof(sin);
326                         sin.sin_addr.s_addr = addr;
327                         sin.sin_port = htons(GRE_UDPPORT);
328                         error = sobind(gs->so, (struct sockaddr *)&sin,
329                             curthread);
330                         if (error != 0) {
331                                 if_printf(GRE2IFP(sc),
332                                     "cannot bind socket: %d\n", error);
333                                 goto fail;
334                         }
335                         /* Add socket to the chain */
336                         CK_LIST_INSERT_HEAD(&GRE_SOCKHASH(addr), gs, chain);
337                 }
338         }
339
340         /* Add softc to the socket's list */
341         CK_LIST_INSERT_HEAD(&gs->list, sc, chain);
342         sc->gre_so = gs;
343         return (0);
344 fail:
345         soclose(gs->so);
346         free(s, M_GRE);
347         return (error);
348 }
349
350 static int
351 in_gre_attach(struct gre_softc *sc)
352 {
353         struct epoch_tracker et;
354         struct grehdr *gh;
355         int error;
356
357         if (sc->gre_options & GRE_UDPENCAP) {
358                 sc->gre_csumflags = CSUM_UDP;
359                 sc->gre_hlen = sizeof(struct greudp);
360                 sc->gre_oip.ip_p = IPPROTO_UDP;
361                 gh = &sc->gre_udphdr->gi_gre;
362                 gre_update_udphdr(sc, &sc->gre_udp,
363                     in_pseudo(sc->gre_oip.ip_src.s_addr,
364                     sc->gre_oip.ip_dst.s_addr, 0));
365         } else {
366                 sc->gre_hlen = sizeof(struct greip);
367                 sc->gre_oip.ip_p = IPPROTO_GRE;
368                 gh = &sc->gre_iphdr->gi_gre;
369         }
370         sc->gre_oip.ip_v = IPVERSION;
371         sc->gre_oip.ip_hl = sizeof(struct ip) >> 2;
372         gre_update_hdr(sc, gh);
373
374         /*
375          * If we return error, this means that sc is not linked,
376          * and caller should reset gre_family and free(sc->gre_hdr).
377          */
378         if (sc->gre_options & GRE_UDPENCAP) {
379                 error = in_gre_setup_socket(sc);
380                 if (error != 0)
381                         return (error);
382         } else
383                 CK_LIST_INSERT_HEAD(&GRE_HASH_SC(sc), sc, chain);
384         CK_LIST_INSERT_HEAD(&GRE_SRCHASH(sc->gre_oip.ip_src.s_addr),
385             sc, srchash);
386
387         /* Set IFF_DRV_RUNNING if interface is ready */
388         NET_EPOCH_ENTER(et);
389         in_gre_set_running(sc);
390         NET_EPOCH_EXIT(et);
391         return (0);
392 }
393
394 int
395 in_gre_setopts(struct gre_softc *sc, u_long cmd, uint32_t value)
396 {
397         int error;
398
399         /* NOTE: we are protected with gre_ioctl_sx lock */
400         MPASS(cmd == GRESKEY || cmd == GRESOPTS || cmd == GRESPORT);
401         MPASS(sc->gre_family == AF_INET);
402
403         /*
404          * If we are going to change encapsulation protocol, do check
405          * for duplicate tunnels. Return EEXIST here to do not confuse
406          * user.
407          */
408         if (cmd == GRESOPTS &&
409             (sc->gre_options & GRE_UDPENCAP) != (value & GRE_UDPENCAP) &&
410             in_gre_checkdup(sc, sc->gre_oip.ip_src.s_addr,
411                 sc->gre_oip.ip_dst.s_addr, value) == EADDRNOTAVAIL)
412                 return (EEXIST);
413
414         CK_LIST_REMOVE(sc, chain);
415         CK_LIST_REMOVE(sc, srchash);
416         GRE_WAIT();
417         switch (cmd) {
418         case GRESKEY:
419                 sc->gre_key = value;
420                 break;
421         case GRESOPTS:
422                 sc->gre_options = value;
423                 break;
424         case GRESPORT:
425                 sc->gre_port = value;
426                 break;
427         }
428         error = in_gre_attach(sc);
429         if (error != 0) {
430                 sc->gre_family = 0;
431                 free(sc->gre_hdr, M_GRE);
432         }
433         return (error);
434 }
435
436 int
437 in_gre_ioctl(struct gre_softc *sc, u_long cmd, caddr_t data)
438 {
439         struct ifreq *ifr = (struct ifreq *)data;
440         struct sockaddr_in *dst, *src;
441         struct ip *ip;
442         int error;
443
444         /* NOTE: we are protected with gre_ioctl_sx lock */
445         error = EINVAL;
446         switch (cmd) {
447         case SIOCSIFPHYADDR:
448                 src = &((struct in_aliasreq *)data)->ifra_addr;
449                 dst = &((struct in_aliasreq *)data)->ifra_dstaddr;
450
451                 /* sanity checks */
452                 if (src->sin_family != dst->sin_family ||
453                     src->sin_family != AF_INET ||
454                     src->sin_len != dst->sin_len ||
455                     src->sin_len != sizeof(*src))
456                         break;
457                 if (src->sin_addr.s_addr == INADDR_ANY ||
458                     dst->sin_addr.s_addr == INADDR_ANY) {
459                         error = EADDRNOTAVAIL;
460                         break;
461                 }
462                 if (V_ipv4_hashtbl == NULL) {
463                         V_ipv4_hashtbl = gre_hashinit();
464                         V_ipv4_srchashtbl = gre_hashinit();
465                         V_ipv4_sockets = (struct gre_sockets *)gre_hashinit();
466                 }
467                 error = in_gre_checkdup(sc, src->sin_addr.s_addr,
468                     dst->sin_addr.s_addr, sc->gre_options);
469                 if (error == EADDRNOTAVAIL)
470                         break;
471                 if (error == EEXIST) {
472                         /* Addresses are the same. Just return. */
473                         error = 0;
474                         break;
475                 }
476                 ip = malloc(sizeof(struct greudp) + 3 * sizeof(uint32_t),
477                     M_GRE, M_WAITOK | M_ZERO);
478                 ip->ip_src.s_addr = src->sin_addr.s_addr;
479                 ip->ip_dst.s_addr = dst->sin_addr.s_addr;
480                 if (sc->gre_family != 0) {
481                         /* Detach existing tunnel first */
482                         CK_LIST_REMOVE(sc, chain);
483                         CK_LIST_REMOVE(sc, srchash);
484                         GRE_WAIT();
485                         free(sc->gre_hdr, M_GRE);
486                         /* XXX: should we notify about link state change? */
487                 }
488                 sc->gre_family = AF_INET;
489                 sc->gre_hdr = ip;
490                 sc->gre_oseq = 0;
491                 sc->gre_iseq = UINT32_MAX;
492                 error = in_gre_attach(sc);
493                 if (error != 0) {
494                         sc->gre_family = 0;
495                         free(sc->gre_hdr, M_GRE);
496                 }
497                 break;
498         case SIOCGIFPSRCADDR:
499         case SIOCGIFPDSTADDR:
500                 if (sc->gre_family != AF_INET) {
501                         error = EADDRNOTAVAIL;
502                         break;
503                 }
504                 src = (struct sockaddr_in *)&ifr->ifr_addr;
505                 memset(src, 0, sizeof(*src));
506                 src->sin_family = AF_INET;
507                 src->sin_len = sizeof(*src);
508                 src->sin_addr = (cmd == SIOCGIFPSRCADDR) ?
509                     sc->gre_oip.ip_src: sc->gre_oip.ip_dst;
510                 error = prison_if(curthread->td_ucred, (struct sockaddr *)src);
511                 if (error != 0)
512                         memset(src, 0, sizeof(*src));
513                 break;
514         }
515         return (error);
516 }
517
518 int
519 in_gre_output(struct mbuf *m, int af, int hlen)
520 {
521         struct greip *gi;
522
523         gi = mtod(m, struct greip *);
524         switch (af) {
525         case AF_INET:
526                 /*
527                  * gre_transmit() has used M_PREPEND() that doesn't guarantee
528                  * m_data is contiguous more than hlen bytes. Use m_copydata()
529                  * here to avoid m_pullup().
530                  */
531                 m_copydata(m, hlen + offsetof(struct ip, ip_tos),
532                     sizeof(u_char), &gi->gi_ip.ip_tos);
533                 m_copydata(m, hlen + offsetof(struct ip, ip_id),
534                     sizeof(u_short), (caddr_t)&gi->gi_ip.ip_id);
535                 break;
536 #ifdef INET6
537         case AF_INET6:
538                 gi->gi_ip.ip_tos = 0; /* XXX */
539                 ip_fillid(&gi->gi_ip);
540                 break;
541 #endif
542         }
543         gi->gi_ip.ip_ttl = V_ip_gre_ttl;
544         gi->gi_ip.ip_len = htons(m->m_pkthdr.len);
545         return (ip_output(m, NULL, NULL, IP_FORWARDING, NULL, NULL));
546 }
547
548 static const struct srcaddrtab *ipv4_srcaddrtab = NULL;
549 static const struct encaptab *ecookie = NULL;
550 static const struct encap_config ipv4_encap_cfg = {
551         .proto = IPPROTO_GRE,
552         .min_length = sizeof(struct greip) + sizeof(struct ip),
553         .exact_match = ENCAP_DRV_LOOKUP,
554         .lookup = in_gre_lookup,
555         .input = gre_input
556 };
557
558 void
559 in_gre_init(void)
560 {
561
562         if (!IS_DEFAULT_VNET(curvnet))
563                 return;
564         ipv4_srcaddrtab = ip_encap_register_srcaddr(in_gre_srcaddr,
565             NULL, M_WAITOK);
566         ecookie = ip_encap_attach(&ipv4_encap_cfg, NULL, M_WAITOK);
567 }
568
569 void
570 in_gre_uninit(void)
571 {
572
573         if (IS_DEFAULT_VNET(curvnet)) {
574                 ip_encap_detach(ecookie);
575                 ip_encap_unregister_srcaddr(ipv4_srcaddrtab);
576         }
577         if (V_ipv4_hashtbl != NULL) {
578                 gre_hashdestroy(V_ipv4_hashtbl);
579                 V_ipv4_hashtbl = NULL;
580                 GRE_WAIT();
581                 gre_hashdestroy(V_ipv4_srchashtbl);
582                 gre_hashdestroy((struct gre_list *)V_ipv4_sockets);
583         }
584 }