1/*-
2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
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: if_gre.c,v 1.49 2003/12/11 00:22:29 itojun Exp $
35 */
36
37#include <sys/cdefs.h>
38__FBSDID("$FreeBSD$");
39
40#include "opt_inet.h"
41#include "opt_inet6.h"
42#include "opt_rss.h"
43
44#include <sys/param.h>
45#include <sys/kernel.h>
46#include <sys/lock.h>
47#include <sys/malloc.h>
48#include <sys/module.h>
49#include <sys/mbuf.h>
50#include <sys/priv.h>
51#include <sys/proc.h>
52#include <sys/socket.h>
53#include <sys/socketvar.h>
54#include <sys/sockio.h>
55#include <sys/sx.h>
56#include <sys/sysctl.h>
57#include <sys/syslog.h>
58#include <sys/systm.h>
59
60#include <net/ethernet.h>
61#include <net/if.h>
62#include <net/if_var.h>
63#include <net/if_clone.h>
64#include <net/if_types.h>
65#include <net/netisr.h>
66#include <net/vnet.h>
67#include <net/route.h>
68
69#include <netinet/in.h>
70#include <netinet/in_pcb.h>
71#ifdef INET
72#include <netinet/in_var.h>
73#include <netinet/ip.h>
74#include <netinet/ip_var.h>
75#ifdef RSS
76#include <netinet/in_rss.h>
77#endif
78#endif
79
80#ifdef INET6
81#include <netinet/ip6.h>
82#include <netinet6/in6_var.h>
83#include <netinet6/ip6_var.h>
84#ifdef RSS
85#include <netinet6/in6_rss.h>
86#endif
87#endif
88
89#include <netinet/ip_encap.h>
90#include <netinet/udp.h>
91#include <net/bpf.h>
92#include <net/if_gre.h>
93
94#include <machine/in_cksum.h>
95#include <security/mac/mac_framework.h>
96
97#define	GREMTU			1476
98
99static const char grename[] = "gre";
100MALLOC_DEFINE(M_GRE, grename, "Generic Routing Encapsulation");
101
102static struct sx gre_ioctl_sx;
103SX_SYSINIT(gre_ioctl_sx, &gre_ioctl_sx, "gre_ioctl");
104
105static int	gre_clone_create(struct if_clone *, int, caddr_t);
106static void	gre_clone_destroy(struct ifnet *);
107VNET_DEFINE_STATIC(struct if_clone *, gre_cloner);
108#define	V_gre_cloner	VNET(gre_cloner)
109
110#ifdef VIMAGE
111static void	gre_reassign(struct ifnet *, struct vnet *, char *);
112#endif
113static void	gre_qflush(struct ifnet *);
114static int	gre_transmit(struct ifnet *, struct mbuf *);
115static int	gre_ioctl(struct ifnet *, u_long, caddr_t);
116static int	gre_output(struct ifnet *, struct mbuf *,
117		    const struct sockaddr *, struct route *);
118static void	gre_delete_tunnel(struct gre_softc *);
119
120SYSCTL_DECL(_net_link);
121static SYSCTL_NODE(_net_link, IFT_TUNNEL, gre, CTLFLAG_RW | CTLFLAG_MPSAFE, 0,
122    "Generic Routing Encapsulation");
123#ifndef MAX_GRE_NEST
124/*
125 * This macro controls the default upper limitation on nesting of gre tunnels.
126 * Since, setting a large value to this macro with a careless configuration
127 * may introduce system crash, we don't allow any nestings by default.
128 * If you need to configure nested gre tunnels, you can define this macro
129 * in your kernel configuration file.  However, if you do so, please be
130 * careful to configure the tunnels so that it won't make a loop.
131 */
132#define MAX_GRE_NEST 1
133#endif
134
135VNET_DEFINE_STATIC(int, max_gre_nesting) = MAX_GRE_NEST;
136#define	V_max_gre_nesting	VNET(max_gre_nesting)
137SYSCTL_INT(_net_link_gre, OID_AUTO, max_nesting, CTLFLAG_RW | CTLFLAG_VNET,
138    &VNET_NAME(max_gre_nesting), 0, "Max nested tunnels");
139
140static void
141vnet_gre_init(const void *unused __unused)
142{
143
144	V_gre_cloner = if_clone_simple(grename, gre_clone_create,
145	    gre_clone_destroy, 0);
146#ifdef INET
147	in_gre_init();
148#endif
149#ifdef INET6
150	in6_gre_init();
151#endif
152}
153VNET_SYSINIT(vnet_gre_init, SI_SUB_PROTO_IFATTACHDOMAIN, SI_ORDER_ANY,
154    vnet_gre_init, NULL);
155
156static void
157vnet_gre_uninit(const void *unused __unused)
158{
159
160	if_clone_detach(V_gre_cloner);
161#ifdef INET
162	in_gre_uninit();
163#endif
164#ifdef INET6
165	in6_gre_uninit();
166#endif
167	/* XXX: epoch_call drain */
168}
169VNET_SYSUNINIT(vnet_gre_uninit, SI_SUB_PROTO_IFATTACHDOMAIN, SI_ORDER_ANY,
170    vnet_gre_uninit, NULL);
171
172static int
173gre_clone_create(struct if_clone *ifc, int unit, caddr_t params)
174{
175	struct gre_softc *sc;
176
177	sc = malloc(sizeof(struct gre_softc), M_GRE, M_WAITOK | M_ZERO);
178	sc->gre_fibnum = curthread->td_proc->p_fibnum;
179	GRE2IFP(sc) = if_alloc(IFT_TUNNEL);
180	GRE2IFP(sc)->if_softc = sc;
181	if_initname(GRE2IFP(sc), grename, unit);
182
183	GRE2IFP(sc)->if_mtu = GREMTU;
184	GRE2IFP(sc)->if_flags = IFF_POINTOPOINT|IFF_MULTICAST;
185	GRE2IFP(sc)->if_output = gre_output;
186	GRE2IFP(sc)->if_ioctl = gre_ioctl;
187	GRE2IFP(sc)->if_transmit = gre_transmit;
188	GRE2IFP(sc)->if_qflush = gre_qflush;
189#ifdef VIMAGE
190	GRE2IFP(sc)->if_reassign = gre_reassign;
191#endif
192	GRE2IFP(sc)->if_capabilities |= IFCAP_LINKSTATE;
193	GRE2IFP(sc)->if_capenable |= IFCAP_LINKSTATE;
194	if_attach(GRE2IFP(sc));
195	bpfattach(GRE2IFP(sc), DLT_NULL, sizeof(u_int32_t));
196	return (0);
197}
198
199#ifdef VIMAGE
200static void
201gre_reassign(struct ifnet *ifp, struct vnet *new_vnet __unused,
202    char *unused __unused)
203{
204	struct gre_softc *sc;
205
206	sx_xlock(&gre_ioctl_sx);
207	sc = ifp->if_softc;
208	if (sc != NULL)
209		gre_delete_tunnel(sc);
210	sx_xunlock(&gre_ioctl_sx);
211}
212#endif /* VIMAGE */
213
214static void
215gre_clone_destroy(struct ifnet *ifp)
216{
217	struct gre_softc *sc;
218
219	sx_xlock(&gre_ioctl_sx);
220	sc = ifp->if_softc;
221	gre_delete_tunnel(sc);
222	bpfdetach(ifp);
223	if_detach(ifp);
224	ifp->if_softc = NULL;
225	sx_xunlock(&gre_ioctl_sx);
226
227	GRE_WAIT();
228	if_free(ifp);
229	free(sc, M_GRE);
230}
231
232static int
233gre_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
234{
235	struct ifreq *ifr = (struct ifreq *)data;
236	struct gre_softc *sc;
237	uint32_t opt;
238	int error;
239
240	switch (cmd) {
241	case SIOCSIFMTU:
242		 /* XXX: */
243		if (ifr->ifr_mtu < 576)
244			return (EINVAL);
245		ifp->if_mtu = ifr->ifr_mtu;
246		return (0);
247	case SIOCSIFADDR:
248		ifp->if_flags |= IFF_UP;
249	case SIOCSIFFLAGS:
250	case SIOCADDMULTI:
251	case SIOCDELMULTI:
252		return (0);
253	case GRESADDRS:
254	case GRESADDRD:
255	case GREGADDRS:
256	case GREGADDRD:
257	case GRESPROTO:
258	case GREGPROTO:
259		return (EOPNOTSUPP);
260	}
261	sx_xlock(&gre_ioctl_sx);
262	sc = ifp->if_softc;
263	if (sc == NULL) {
264		error = ENXIO;
265		goto end;
266	}
267	error = 0;
268	switch (cmd) {
269	case SIOCDIFPHYADDR:
270		if (sc->gre_family == 0)
271			break;
272		gre_delete_tunnel(sc);
273		break;
274#ifdef INET
275	case SIOCSIFPHYADDR:
276	case SIOCGIFPSRCADDR:
277	case SIOCGIFPDSTADDR:
278		error = in_gre_ioctl(sc, cmd, data);
279		break;
280#endif
281#ifdef INET6
282	case SIOCSIFPHYADDR_IN6:
283	case SIOCGIFPSRCADDR_IN6:
284	case SIOCGIFPDSTADDR_IN6:
285		error = in6_gre_ioctl(sc, cmd, data);
286		break;
287#endif
288	case SIOCGTUNFIB:
289		ifr->ifr_fib = sc->gre_fibnum;
290		break;
291	case SIOCSTUNFIB:
292		if ((error = priv_check(curthread, PRIV_NET_GRE)) != 0)
293			break;
294		if (ifr->ifr_fib >= rt_numfibs)
295			error = EINVAL;
296		else
297			sc->gre_fibnum = ifr->ifr_fib;
298		break;
299	case GRESKEY:
300	case GRESOPTS:
301	case GRESPORT:
302		if ((error = priv_check(curthread, PRIV_NET_GRE)) != 0)
303			break;
304		if ((error = copyin(ifr_data_get_ptr(ifr), &opt,
305		    sizeof(opt))) != 0)
306			break;
307		if (cmd == GRESKEY) {
308			if (sc->gre_key == opt)
309				break;
310		} else if (cmd == GRESOPTS) {
311			if (opt & ~GRE_OPTMASK) {
312				error = EINVAL;
313				break;
314			}
315			if (sc->gre_options == opt)
316				break;
317		} else if (cmd == GRESPORT) {
318			if (opt != 0 && (opt < V_ipport_hifirstauto ||
319			    opt > V_ipport_hilastauto)) {
320				error = EINVAL;
321				break;
322			}
323			if (sc->gre_port == opt)
324				break;
325			if ((sc->gre_options & GRE_UDPENCAP) == 0) {
326				/*
327				 * UDP encapsulation is not enabled, thus
328				 * there is no need to reattach softc.
329				 */
330				sc->gre_port = opt;
331				break;
332			}
333		}
334		switch (sc->gre_family) {
335#ifdef INET
336		case AF_INET:
337			error = in_gre_setopts(sc, cmd, opt);
338			break;
339#endif
340#ifdef INET6
341		case AF_INET6:
342			error = in6_gre_setopts(sc, cmd, opt);
343			break;
344#endif
345		default:
346			/*
347			 * Tunnel is not yet configured.
348			 * We can just change any parameters.
349			 */
350			if (cmd == GRESKEY)
351				sc->gre_key = opt;
352			if (cmd == GRESOPTS)
353				sc->gre_options = opt;
354			if (cmd == GRESPORT)
355				sc->gre_port = opt;
356			break;
357		}
358		/*
359		 * XXX: Do we need to initiate change of interface
360		 * state here?
361		 */
362		break;
363	case GREGKEY:
364		error = copyout(&sc->gre_key, ifr_data_get_ptr(ifr),
365		    sizeof(sc->gre_key));
366		break;
367	case GREGOPTS:
368		error = copyout(&sc->gre_options, ifr_data_get_ptr(ifr),
369		    sizeof(sc->gre_options));
370		break;
371	case GREGPORT:
372		error = copyout(&sc->gre_port, ifr_data_get_ptr(ifr),
373		    sizeof(sc->gre_port));
374		break;
375	default:
376		error = EINVAL;
377		break;
378	}
379	if (error == 0 && sc->gre_family != 0) {
380		if (
381#ifdef INET
382		    cmd == SIOCSIFPHYADDR ||
383#endif
384#ifdef INET6
385		    cmd == SIOCSIFPHYADDR_IN6 ||
386#endif
387		    0) {
388			if_link_state_change(ifp, LINK_STATE_UP);
389		}
390	}
391end:
392	sx_xunlock(&gre_ioctl_sx);
393	return (error);
394}
395
396static void
397gre_delete_tunnel(struct gre_softc *sc)
398{
399	struct gre_socket *gs;
400
401	sx_assert(&gre_ioctl_sx, SA_XLOCKED);
402	if (sc->gre_family != 0) {
403		CK_LIST_REMOVE(sc, chain);
404		CK_LIST_REMOVE(sc, srchash);
405		GRE_WAIT();
406		free(sc->gre_hdr, M_GRE);
407		sc->gre_family = 0;
408	}
409	/*
410	 * If this Tunnel was the last one that could use UDP socket,
411	 * we should unlink socket from hash table and close it.
412	 */
413	if ((gs = sc->gre_so) != NULL && CK_LIST_EMPTY(&gs->list)) {
414		CK_LIST_REMOVE(gs, chain);
415		soclose(gs->so);
416		NET_EPOCH_CALL(gre_sofree, &gs->epoch_ctx);
417		sc->gre_so = NULL;
418	}
419	GRE2IFP(sc)->if_drv_flags &= ~IFF_DRV_RUNNING;
420	if_link_state_change(GRE2IFP(sc), LINK_STATE_DOWN);
421}
422
423struct gre_list *
424gre_hashinit(void)
425{
426	struct gre_list *hash;
427	int i;
428
429	hash = malloc(sizeof(struct gre_list) * GRE_HASH_SIZE,
430	    M_GRE, M_WAITOK);
431	for (i = 0; i < GRE_HASH_SIZE; i++)
432		CK_LIST_INIT(&hash[i]);
433
434	return (hash);
435}
436
437void
438gre_hashdestroy(struct gre_list *hash)
439{
440
441	free(hash, M_GRE);
442}
443
444void
445gre_sofree(epoch_context_t ctx)
446{
447	struct gre_socket *gs;
448
449	gs = __containerof(ctx, struct gre_socket, epoch_ctx);
450	free(gs, M_GRE);
451}
452
453static __inline uint16_t
454gre_cksum_add(uint16_t sum, uint16_t a)
455{
456	uint16_t res;
457
458	res = sum + a;
459	return (res + (res < a));
460}
461
462void
463gre_update_udphdr(struct gre_softc *sc, struct udphdr *udp, uint16_t csum)
464{
465
466	sx_assert(&gre_ioctl_sx, SA_XLOCKED);
467	MPASS(sc->gre_options & GRE_UDPENCAP);
468
469	udp->uh_dport = htons(GRE_UDPPORT);
470	udp->uh_sport = htons(sc->gre_port);
471	udp->uh_sum = csum;
472	udp->uh_ulen = 0;
473}
474
475void
476gre_update_hdr(struct gre_softc *sc, struct grehdr *gh)
477{
478	uint32_t *opts;
479	uint16_t flags;
480
481	sx_assert(&gre_ioctl_sx, SA_XLOCKED);
482
483	flags = 0;
484	opts = gh->gre_opts;
485	if (sc->gre_options & GRE_ENABLE_CSUM) {
486		flags |= GRE_FLAGS_CP;
487		sc->gre_hlen += 2 * sizeof(uint16_t);
488		*opts++ = 0;
489	}
490	if (sc->gre_key != 0) {
491		flags |= GRE_FLAGS_KP;
492		sc->gre_hlen += sizeof(uint32_t);
493		*opts++ = htonl(sc->gre_key);
494	}
495	if (sc->gre_options & GRE_ENABLE_SEQ) {
496		flags |= GRE_FLAGS_SP;
497		sc->gre_hlen += sizeof(uint32_t);
498		*opts++ = 0;
499	} else
500		sc->gre_oseq = 0;
501	gh->gre_flags = htons(flags);
502}
503
504int
505gre_input(struct mbuf *m, int off, int proto, void *arg)
506{
507	struct gre_softc *sc = arg;
508	struct grehdr *gh;
509	struct ifnet *ifp;
510	uint32_t *opts;
511#ifdef notyet
512	uint32_t key;
513#endif
514	uint16_t flags;
515	int hlen, isr, af;
516
517	ifp = GRE2IFP(sc);
518	hlen = off + sizeof(struct grehdr) + 4 * sizeof(uint32_t);
519	if (m->m_pkthdr.len < hlen)
520		goto drop;
521	if (m->m_len < hlen) {
522		m = m_pullup(m, hlen);
523		if (m == NULL)
524			goto drop;
525	}
526	gh = (struct grehdr *)mtodo(m, off);
527	flags = ntohs(gh->gre_flags);
528	if (flags & ~GRE_FLAGS_MASK)
529		goto drop;
530	opts = gh->gre_opts;
531	hlen = 2 * sizeof(uint16_t);
532	if (flags & GRE_FLAGS_CP) {
533		/* reserved1 field must be zero */
534		if (((uint16_t *)opts)[1] != 0)
535			goto drop;
536		if (in_cksum_skip(m, m->m_pkthdr.len, off) != 0)
537			goto drop;
538		hlen += 2 * sizeof(uint16_t);
539		opts++;
540	}
541	if (flags & GRE_FLAGS_KP) {
542#ifdef notyet
543        /*
544         * XXX: The current implementation uses the key only for outgoing
545         * packets. But we can check the key value here, or even in the
546         * encapcheck function.
547         */
548		key = ntohl(*opts);
549#endif
550		hlen += sizeof(uint32_t);
551		opts++;
552    }
553#ifdef notyet
554	} else
555		key = 0;
556
557	if (sc->gre_key != 0 && (key != sc->gre_key || key != 0))
558		goto drop;
559#endif
560	if (flags & GRE_FLAGS_SP) {
561#ifdef notyet
562		seq = ntohl(*opts);
563#endif
564		hlen += sizeof(uint32_t);
565	}
566	switch (ntohs(gh->gre_proto)) {
567	case ETHERTYPE_WCCP:
568		/*
569		 * For WCCP skip an additional 4 bytes if after GRE header
570		 * doesn't follow an IP header.
571		 */
572		if (flags == 0 && (*(uint8_t *)gh->gre_opts & 0xF0) != 0x40)
573			hlen += sizeof(uint32_t);
574		/* FALLTHROUGH */
575	case ETHERTYPE_IP:
576		isr = NETISR_IP;
577		af = AF_INET;
578		break;
579	case ETHERTYPE_IPV6:
580		isr = NETISR_IPV6;
581		af = AF_INET6;
582		break;
583	default:
584		goto drop;
585	}
586	m_adj(m, off + hlen);
587	m_clrprotoflags(m);
588	m->m_pkthdr.rcvif = ifp;
589	M_SETFIB(m, ifp->if_fib);
590#ifdef MAC
591	mac_ifnet_create_mbuf(ifp, m);
592#endif
593	BPF_MTAP2(ifp, &af, sizeof(af), m);
594	if_inc_counter(ifp, IFCOUNTER_IPACKETS, 1);
595	if_inc_counter(ifp, IFCOUNTER_IBYTES, m->m_pkthdr.len);
596	if ((ifp->if_flags & IFF_MONITOR) != 0)
597		m_freem(m);
598	else
599		netisr_dispatch(isr, m);
600	return (IPPROTO_DONE);
601drop:
602	if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
603	m_freem(m);
604	return (IPPROTO_DONE);
605}
606
607static int
608gre_output(struct ifnet *ifp, struct mbuf *m, const struct sockaddr *dst,
609   struct route *ro)
610{
611	uint32_t af;
612
613	if (dst->sa_family == AF_UNSPEC)
614		bcopy(dst->sa_data, &af, sizeof(af));
615	else
616		af = dst->sa_family;
617	/*
618	 * Now save the af in the inbound pkt csum data, this is a cheat since
619	 * we are using the inbound csum_data field to carry the af over to
620	 * the gre_transmit() routine, avoiding using yet another mtag.
621	 */
622	m->m_pkthdr.csum_data = af;
623	return (ifp->if_transmit(ifp, m));
624}
625
626static void
627gre_setseqn(struct grehdr *gh, uint32_t seq)
628{
629	uint32_t *opts;
630	uint16_t flags;
631
632	opts = gh->gre_opts;
633	flags = ntohs(gh->gre_flags);
634	KASSERT((flags & GRE_FLAGS_SP) != 0,
635	    ("gre_setseqn called, but GRE_FLAGS_SP isn't set "));
636	if (flags & GRE_FLAGS_CP)
637		opts++;
638	if (flags & GRE_FLAGS_KP)
639		opts++;
640	*opts = htonl(seq);
641}
642
643static uint32_t
644gre_flowid(struct gre_softc *sc, struct mbuf *m, uint32_t af)
645{
646	uint32_t flowid;
647
648	if ((sc->gre_options & GRE_UDPENCAP) == 0 || sc->gre_port != 0)
649		return (0);
650#ifndef RSS
651	switch (af) {
652#ifdef INET
653	case AF_INET:
654		flowid = mtod(m, struct ip *)->ip_src.s_addr ^
655		    mtod(m, struct ip *)->ip_dst.s_addr;
656		break;
657#endif
658#ifdef INET6
659	case AF_INET6:
660		flowid = mtod(m, struct ip6_hdr *)->ip6_src.s6_addr32[3] ^
661		    mtod(m, struct ip6_hdr *)->ip6_dst.s6_addr32[3];
662		break;
663#endif
664	default:
665		flowid = 0;
666	}
667#else /* RSS */
668	switch (af) {
669#ifdef INET
670	case AF_INET:
671		flowid = rss_hash_ip4_2tuple(mtod(m, struct ip *)->ip_src,
672		    mtod(m, struct ip *)->ip_dst);
673		break;
674#endif
675#ifdef INET6
676	case AF_INET6:
677		flowid = rss_hash_ip6_2tuple(
678		    &mtod(m, struct ip6_hdr *)->ip6_src,
679		    &mtod(m, struct ip6_hdr *)->ip6_dst);
680		break;
681#endif
682	default:
683		flowid = 0;
684	}
685#endif
686	return (flowid);
687}
688
689#define	MTAG_GRE	1307983903
690static int
691gre_transmit(struct ifnet *ifp, struct mbuf *m)
692{
693	GRE_RLOCK_TRACKER;
694	struct gre_softc *sc;
695	struct grehdr *gh;
696	struct udphdr *uh;
697	uint32_t af, flowid;
698	int error, len;
699	uint16_t proto;
700
701	len = 0;
702	GRE_RLOCK();
703#ifdef MAC
704	error = mac_ifnet_check_transmit(ifp, m);
705	if (error) {
706		m_freem(m);
707		goto drop;
708	}
709#endif
710	error = ENETDOWN;
711	sc = ifp->if_softc;
712	if ((ifp->if_flags & IFF_MONITOR) != 0 ||
713	    (ifp->if_flags & IFF_UP) == 0 ||
714	    (ifp->if_drv_flags & IFF_DRV_RUNNING) == 0 ||
715	    sc->gre_family == 0 ||
716	    (error = if_tunnel_check_nesting(ifp, m, MTAG_GRE,
717		V_max_gre_nesting)) != 0) {
718		m_freem(m);
719		goto drop;
720	}
721	af = m->m_pkthdr.csum_data;
722	BPF_MTAP2(ifp, &af, sizeof(af), m);
723	m->m_flags &= ~(M_BCAST|M_MCAST);
724	flowid = gre_flowid(sc, m, af);
725	M_SETFIB(m, sc->gre_fibnum);
726	M_PREPEND(m, sc->gre_hlen, M_NOWAIT);
727	if (m == NULL) {
728		error = ENOBUFS;
729		goto drop;
730	}
731	bcopy(sc->gre_hdr, mtod(m, void *), sc->gre_hlen);
732	/* Determine GRE proto */
733	switch (af) {
734#ifdef INET
735	case AF_INET:
736		proto = htons(ETHERTYPE_IP);
737		break;
738#endif
739#ifdef INET6
740	case AF_INET6:
741		proto = htons(ETHERTYPE_IPV6);
742		break;
743#endif
744	default:
745		m_freem(m);
746		error = ENETDOWN;
747		goto drop;
748	}
749	/* Determine offset of GRE header */
750	switch (sc->gre_family) {
751#ifdef INET
752	case AF_INET:
753		len = sizeof(struct ip);
754		break;
755#endif
756#ifdef INET6
757	case AF_INET6:
758		len = sizeof(struct ip6_hdr);
759		break;
760#endif
761	default:
762		m_freem(m);
763		error = ENETDOWN;
764		goto drop;
765	}
766	if (sc->gre_options & GRE_UDPENCAP) {
767		uh = (struct udphdr *)mtodo(m, len);
768		uh->uh_sport |= htons(V_ipport_hifirstauto) |
769		    (flowid >> 16) | (flowid & 0xFFFF);
770		uh->uh_sport = htons(ntohs(uh->uh_sport) %
771		    V_ipport_hilastauto);
772		uh->uh_ulen = htons(m->m_pkthdr.len - len);
773		uh->uh_sum = gre_cksum_add(uh->uh_sum,
774		    htons(m->m_pkthdr.len - len + IPPROTO_UDP));
775		m->m_pkthdr.csum_flags = sc->gre_csumflags;
776		m->m_pkthdr.csum_data = offsetof(struct udphdr, uh_sum);
777		len += sizeof(struct udphdr);
778	}
779	gh = (struct grehdr *)mtodo(m, len);
780	gh->gre_proto = proto;
781	if (sc->gre_options & GRE_ENABLE_SEQ)
782		gre_setseqn(gh, sc->gre_oseq++);
783	if (sc->gre_options & GRE_ENABLE_CSUM) {
784		*(uint16_t *)gh->gre_opts = in_cksum_skip(m,
785		    m->m_pkthdr.len, len);
786	}
787	len = m->m_pkthdr.len - len;
788	switch (sc->gre_family) {
789#ifdef INET
790	case AF_INET:
791		error = in_gre_output(m, af, sc->gre_hlen);
792		break;
793#endif
794#ifdef INET6
795	case AF_INET6:
796		error = in6_gre_output(m, af, sc->gre_hlen, flowid);
797		break;
798#endif
799	default:
800		m_freem(m);
801		error = ENETDOWN;
802	}
803drop:
804	if (error)
805		if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
806	else {
807		if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
808		if_inc_counter(ifp, IFCOUNTER_OBYTES, len);
809	}
810	GRE_RUNLOCK();
811	return (error);
812}
813
814static void
815gre_qflush(struct ifnet *ifp __unused)
816{
817
818}
819
820static int
821gremodevent(module_t mod, int type, void *data)
822{
823
824	switch (type) {
825	case MOD_LOAD:
826	case MOD_UNLOAD:
827		break;
828	default:
829		return (EOPNOTSUPP);
830	}
831	return (0);
832}
833
834static moduledata_t gre_mod = {
835	"if_gre",
836	gremodevent,
837	0
838};
839
840DECLARE_MODULE(if_gre, gre_mod, SI_SUB_PSEUDO, SI_ORDER_ANY);
841MODULE_VERSION(if_gre, 1);
842