xref: /openbsd-src/sys/net/if_gif.c (revision 91f110e064cd7c194e59e019b83bb7496c1c84d4)
1 /*	$OpenBSD: if_gif.c,v 1.64 2013/10/19 14:46:30 mpi Exp $	*/
2 /*	$KAME: if_gif.c,v 1.43 2001/02/20 08:51:07 itojun Exp $	*/
3 
4 /*
5  * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  * 3. Neither the name of the project nor the names of its contributors
17  *    may be used to endorse or promote products derived from this software
18  *    without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
21  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23  * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
24  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30  * SUCH DAMAGE.
31  */
32 
33 #include <sys/param.h>
34 #include <sys/systm.h>
35 #include <sys/kernel.h>
36 #include <sys/mbuf.h>
37 #include <sys/socket.h>
38 #include <sys/sockio.h>
39 #include <sys/syslog.h>
40 
41 #include <net/if.h>
42 #include <net/if_types.h>
43 #include <net/route.h>
44 #include <net/bpf.h>
45 
46 #ifdef	INET
47 #include <netinet/in.h>
48 #include <netinet/in_systm.h>
49 #include <netinet/in_var.h>
50 #include <netinet/in_gif.h>
51 #include <netinet/ip.h>
52 #include <netinet/ip_ether.h>
53 #include <netinet/ip_var.h>
54 #endif	/* INET */
55 
56 #ifdef INET6
57 #ifndef INET
58 #include <netinet/in.h>
59 #endif
60 #include <netinet6/in6_var.h>
61 #include <netinet/ip6.h>
62 #include <netinet6/ip6_var.h>
63 #include <netinet6/in6_gif.h>
64 #endif /* INET6 */
65 
66 #include <net/if_gif.h>
67 
68 #include "bpfilter.h"
69 #include "bridge.h"
70 
71 void	gifattach(int);
72 int	gif_clone_create(struct if_clone *, int);
73 int	gif_clone_destroy(struct ifnet *);
74 int	gif_checkloop(struct ifnet *, struct mbuf *);
75 
76 /*
77  * gif global variable definitions
78  */
79 struct gif_softc_head gif_softc_list;
80 struct if_clone gif_cloner =
81     IF_CLONE_INITIALIZER("gif", gif_clone_create, gif_clone_destroy);
82 
83 /* ARGSUSED */
84 void
85 gifattach(int count)
86 {
87 	LIST_INIT(&gif_softc_list);
88 	if_clone_attach(&gif_cloner);
89 }
90 
91 int
92 gif_clone_create(struct if_clone *ifc, int unit)
93 {
94 	struct gif_softc *sc;
95 	int s;
96 
97 	sc = malloc(sizeof(*sc), M_DEVBUF, M_NOWAIT|M_ZERO);
98 	if (!sc)
99 		return (ENOMEM);
100 
101 	snprintf(sc->gif_if.if_xname, sizeof sc->gif_if.if_xname,
102 	     "%s%d", ifc->ifc_name, unit);
103 	sc->gif_if.if_mtu    = GIF_MTU;
104 	sc->gif_if.if_flags  = IFF_POINTOPOINT | IFF_MULTICAST;
105 	sc->gif_if.if_ioctl  = gif_ioctl;
106 	sc->gif_if.if_start  = gif_start;
107 	sc->gif_if.if_output = gif_output;
108 	sc->gif_if.if_type   = IFT_GIF;
109 	IFQ_SET_MAXLEN(&sc->gif_if.if_snd, IFQ_MAXLEN);
110 	IFQ_SET_READY(&sc->gif_if.if_snd);
111 	sc->gif_if.if_softc = sc;
112 	if_attach(&sc->gif_if);
113 	if_alloc_sadl(&sc->gif_if);
114 
115 #if NBPFILTER > 0
116 	bpfattach(&sc->gif_if.if_bpf, &sc->gif_if, DLT_LOOP, sizeof(u_int32_t));
117 #endif
118 	s = splnet();
119 	LIST_INSERT_HEAD(&gif_softc_list, sc, gif_list);
120 	splx(s);
121 
122 	return (0);
123 }
124 
125 int
126 gif_clone_destroy(struct ifnet *ifp)
127 {
128 	struct gif_softc *sc = ifp->if_softc;
129 	int s;
130 
131 	s = splnet();
132 	LIST_REMOVE(sc, gif_list);
133 	splx(s);
134 
135 	if_detach(ifp);
136 
137 	if (sc->gif_psrc)
138 		free((caddr_t)sc->gif_psrc, M_IFADDR);
139 	sc->gif_psrc = NULL;
140 	if (sc->gif_pdst)
141 		free((caddr_t)sc->gif_pdst, M_IFADDR);
142 	sc->gif_pdst = NULL;
143 	free(sc, M_DEVBUF);
144 	return (0);
145 }
146 
147 void
148 gif_start(struct ifnet *ifp)
149 {
150 	struct gif_softc *sc = (struct gif_softc*)ifp;
151 	struct mbuf *m;
152 	int s;
153 
154 	while (1) {
155 		s = splnet();
156 		IFQ_DEQUEUE(&ifp->if_snd, m);
157 		splx(s);
158 
159 		if (m == NULL)
160 			break;
161 
162 		/* is interface up and usable? */
163 		if ((ifp->if_flags & (IFF_OACTIVE | IFF_UP)) != IFF_UP ||
164 		    sc->gif_psrc == NULL || sc->gif_pdst == NULL ||
165 		    sc->gif_psrc->sa_family != sc->gif_pdst->sa_family) {
166 			m_freem(m);
167 			continue;
168 		}
169 
170 		/*
171 		 * Check if the packet is coming via bridge and needs
172 		 * etherip encapsulation or not. bridge(4) directly calls
173 		 * the start function and bypasses the if_output function
174 		 * so we need to do the encap here.
175 		 */
176 		if (ifp->if_bridgeport && (m->m_flags & M_PROTO1)) {
177 			int error = 0;
178 			/*
179 			 * Remove multicast and broadcast flags or encapsulated
180 			 * packet ends up as multicast or broadcast packet.
181 			 */
182 			m->m_flags &= ~(M_BCAST|M_MCAST);
183 			switch (sc->gif_psrc->sa_family) {
184 #ifdef INET
185 			case AF_INET:
186 				error = in_gif_output(ifp, AF_LINK, &m);
187 				break;
188 #endif
189 #ifdef INET6
190 			case AF_INET6:
191 				error = in6_gif_output(ifp, AF_LINK, &m);
192 				break;
193 #endif
194 			default:
195 				error = EAFNOSUPPORT;
196 				m_freem(m);
197 				break;
198 			}
199 			if (error)
200 				continue;
201 			if (gif_checkloop(ifp, m))
202 				continue;
203 		}
204 
205 #if NBPFILTER > 0
206 		if (ifp->if_bpf) {
207 			int offset;
208 			sa_family_t family;
209 			u_int8_t proto;
210 
211 			/* must decapsulate outer header for bpf */
212 			switch (sc->gif_psrc->sa_family) {
213 #ifdef INET
214 			case AF_INET:
215 				offset = sizeof(struct ip);
216 				proto = mtod(m, struct ip *)->ip_p;
217 				break;
218 #endif
219 #ifdef INET6
220 			case AF_INET6:
221 				offset = sizeof(struct ip6_hdr);
222 				proto = mtod(m, struct ip6_hdr *)->ip6_nxt;
223 				break;
224 #endif
225 			default:
226 				proto = 0;
227 				break;
228 			}
229 			switch (proto) {
230 			case IPPROTO_IPV4:
231 				family = AF_INET;
232 				break;
233 			case IPPROTO_IPV6:
234 				family = AF_INET6;
235 				break;
236 			case IPPROTO_ETHERIP:
237 				family = AF_LINK;
238 				offset += sizeof(struct etherip_header);
239 				break;
240 			case IPPROTO_MPLS:
241 				family = AF_MPLS;
242 				break;
243 			default:
244 				offset = 0;
245 				family = sc->gif_psrc->sa_family;
246 				break;
247 			}
248 			m->m_data += offset;
249 			m->m_len -= offset;
250 			m->m_pkthdr.len -= offset;
251 			bpf_mtap_af(ifp->if_bpf, family, m, BPF_DIRECTION_OUT);
252 			m->m_data -= offset;
253 			m->m_len += offset;
254 			m->m_pkthdr.len += offset;
255 		}
256 #endif
257 		ifp->if_opackets++;
258 
259 		/* XXX we should cache the outgoing route */
260 
261 		switch (sc->gif_psrc->sa_family) {
262 #ifdef INET
263 		case AF_INET:
264 			ip_output(m, (void *)NULL, (void *)NULL, 0,
265 			    (void *)NULL, (void *)NULL);
266 			break;
267 #endif
268 #ifdef INET6
269 		case AF_INET6:
270 			/*
271 			 * force fragmentation to minimum MTU, to avoid path
272 			 * MTU discovery. It is too painful to ask for resend
273 			 * of inner packet, to achieve path MTU discovery for
274 			 * encapsulated packets.
275 			 */
276 			ip6_output(m, 0, NULL, IPV6_MINMTU, 0, NULL,
277 			     NULL);
278 			break;
279 #endif
280 		default:
281 			m_freem(m);
282 			break;
283 		}
284 	}
285 }
286 
287 int
288 gif_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst,
289     struct rtentry *rt)
290 {
291 	struct gif_softc *sc = (struct gif_softc*)ifp;
292 	int error = 0;
293 	int s;
294 
295 	if (!(ifp->if_flags & IFF_UP) ||
296 	    sc->gif_psrc == NULL || sc->gif_pdst == NULL ||
297 	    sc->gif_psrc->sa_family != sc->gif_pdst->sa_family) {
298 		m_freem(m);
299 		error = ENETDOWN;
300 		goto end;
301 	}
302 
303 	/*
304 	 * Remove multicast and broadcast flags or encapsulated packet
305 	 * ends up as multicast or broadcast packet.
306 	 */
307 	m->m_flags &= ~(M_BCAST|M_MCAST);
308 
309 	/*
310 	 * Encapsulate packet. Add IP or IP6 header depending on tunnel AF.
311 	 */
312 	switch (sc->gif_psrc->sa_family) {
313 #ifdef INET
314 	case AF_INET:
315 		error = in_gif_output(ifp, dst->sa_family, &m);
316 		break;
317 #endif
318 #ifdef INET6
319 	case AF_INET6:
320 		error = in6_gif_output(ifp, dst->sa_family, &m);
321 		break;
322 #endif
323 	default:
324 		m_freem(m);
325 		error = EAFNOSUPPORT;
326 		break;
327 	}
328 
329 	if (error)
330 		goto end;
331 
332 	if ((error = gif_checkloop(ifp, m)))
333 		goto end;
334 
335 	/*
336 	 * Queue message on interface, and start output.
337 	 */
338 	s = splnet();
339 	IFQ_ENQUEUE(&ifp->if_snd, m, NULL, error);
340 	if (error) {
341 		/* mbuf is already freed */
342 		splx(s);
343 		goto end;
344 	}
345 	ifp->if_obytes += m->m_pkthdr.len;
346 	if_start(ifp);
347 	splx(s);
348 
349 end:
350 	if (error)
351 		ifp->if_oerrors++;
352 	return (error);
353 }
354 
355 int
356 gif_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
357 {
358 	struct gif_softc *sc  = (struct gif_softc*)ifp;
359 	struct ifreq     *ifr = (struct ifreq*)data;
360 	int error = 0, size;
361 	struct sockaddr *dst, *src;
362 	struct sockaddr *sa;
363 	int s;
364 	struct gif_softc *sc2;
365 
366 	switch (cmd) {
367 	case SIOCSIFADDR:
368 		break;
369 
370 	case SIOCSIFDSTADDR:
371 		break;
372 
373 	case SIOCADDMULTI:
374 	case SIOCDELMULTI:
375 		break;
376 
377 	case SIOCSIFPHYADDR:
378 #ifdef INET6
379 	case SIOCSIFPHYADDR_IN6:
380 #endif /* INET6 */
381 	case SIOCSLIFPHYADDR:
382 		switch (cmd) {
383 #ifdef INET
384 		case SIOCSIFPHYADDR:
385 			src = (struct sockaddr *)
386 				&(((struct in_aliasreq *)data)->ifra_addr);
387 			dst = (struct sockaddr *)
388 				&(((struct in_aliasreq *)data)->ifra_dstaddr);
389 			break;
390 #endif
391 #ifdef INET6
392 		case SIOCSIFPHYADDR_IN6:
393 			src = (struct sockaddr *)
394 				&(((struct in6_aliasreq *)data)->ifra_addr);
395 			dst = (struct sockaddr *)
396 				&(((struct in6_aliasreq *)data)->ifra_dstaddr);
397 			break;
398 #endif
399 		case SIOCSLIFPHYADDR:
400 			src = (struct sockaddr *)
401 				&(((struct if_laddrreq *)data)->addr);
402 			dst = (struct sockaddr *)
403 				&(((struct if_laddrreq *)data)->dstaddr);
404 			break;
405 		default:
406 			return (EINVAL);
407 		}
408 
409 		/* sa_family must be equal */
410 		if (src->sa_family != dst->sa_family)
411 			return (EINVAL);
412 
413 		/* validate sa_len */
414 		switch (src->sa_family) {
415 #ifdef INET
416 		case AF_INET:
417 			if (src->sa_len != sizeof(struct sockaddr_in))
418 				return (EINVAL);
419 			break;
420 #endif
421 #ifdef INET6
422 		case AF_INET6:
423 			if (src->sa_len != sizeof(struct sockaddr_in6))
424 				return (EINVAL);
425 			break;
426 #endif
427 		default:
428 			return (EAFNOSUPPORT);
429 		}
430 		switch (dst->sa_family) {
431 #ifdef INET
432 		case AF_INET:
433 			if (dst->sa_len != sizeof(struct sockaddr_in))
434 				return (EINVAL);
435 			break;
436 #endif
437 #ifdef INET6
438 		case AF_INET6:
439 			if (dst->sa_len != sizeof(struct sockaddr_in6))
440 				return (EINVAL);
441 			break;
442 #endif
443 		default:
444 			return (EAFNOSUPPORT);
445 		}
446 
447 		/* check sa_family looks sane for the cmd */
448 		switch (cmd) {
449 		case SIOCSIFPHYADDR:
450 			if (src->sa_family == AF_INET)
451 				break;
452 			return (EAFNOSUPPORT);
453 #ifdef INET6
454 		case SIOCSIFPHYADDR_IN6:
455 			if (src->sa_family == AF_INET6)
456 				break;
457 			return (EAFNOSUPPORT);
458 #endif /* INET6 */
459 		case SIOCSLIFPHYADDR:
460 			/* checks done in the above */
461 			break;
462 		}
463 
464 		LIST_FOREACH(sc2, &gif_softc_list, gif_list) {
465 			if (sc2 == sc)
466 				continue;
467 			if (!sc2->gif_pdst || !sc2->gif_psrc)
468 				continue;
469 			if (sc2->gif_pdst->sa_family != dst->sa_family ||
470 			    sc2->gif_pdst->sa_len != dst->sa_len ||
471 			    sc2->gif_psrc->sa_family != src->sa_family ||
472 			    sc2->gif_psrc->sa_len != src->sa_len)
473 				continue;
474 			/* can't configure same pair of address onto two gifs */
475 			if (bcmp(sc2->gif_pdst, dst, dst->sa_len) == 0 &&
476 			    bcmp(sc2->gif_psrc, src, src->sa_len) == 0) {
477 				error = EADDRNOTAVAIL;
478 				goto bad;
479 			}
480 
481 			/* can't configure multiple multi-dest interfaces */
482 #define multidest(x) \
483 	(((struct sockaddr_in *)(x))->sin_addr.s_addr == INADDR_ANY)
484 #ifdef INET6
485 #define multidest6(x) \
486 	(IN6_IS_ADDR_UNSPECIFIED(&((struct sockaddr_in6 *)(x))->sin6_addr))
487 #endif
488 			if (dst->sa_family == AF_INET &&
489 			    multidest(dst) && multidest(sc2->gif_pdst)) {
490 				error = EADDRNOTAVAIL;
491 				goto bad;
492 			}
493 #ifdef INET6
494 			if (dst->sa_family == AF_INET6 &&
495 			    multidest6(dst) && multidest6(sc2->gif_pdst)) {
496 				error = EADDRNOTAVAIL;
497 				goto bad;
498 			}
499 #endif
500 		}
501 
502 		if (sc->gif_psrc)
503 			free((caddr_t)sc->gif_psrc, M_IFADDR);
504 		sa = malloc(src->sa_len, M_IFADDR, M_WAITOK);
505 		bcopy((caddr_t)src, (caddr_t)sa, src->sa_len);
506 		sc->gif_psrc = sa;
507 
508 		if (sc->gif_pdst)
509 			free((caddr_t)sc->gif_pdst, M_IFADDR);
510 		sa = malloc(dst->sa_len, M_IFADDR, M_WAITOK);
511 		bcopy((caddr_t)dst, (caddr_t)sa, dst->sa_len);
512 		sc->gif_pdst = sa;
513 
514 		s = splnet();
515 		ifp->if_flags |= IFF_RUNNING;
516 		if_up(ifp);		/* send up RTM_IFINFO */
517 		splx(s);
518 
519 		error = 0;
520 		break;
521 
522 #ifdef SIOCDIFPHYADDR
523 	case SIOCDIFPHYADDR:
524 		if (sc->gif_psrc) {
525 			free((caddr_t)sc->gif_psrc, M_IFADDR);
526 			sc->gif_psrc = NULL;
527 		}
528 		if (sc->gif_pdst) {
529 			free((caddr_t)sc->gif_pdst, M_IFADDR);
530 			sc->gif_pdst = NULL;
531 		}
532 		/* change the IFF_{UP, RUNNING} flag as well? */
533 		break;
534 #endif
535 
536 	case SIOCGIFPSRCADDR:
537 #ifdef INET6
538 	case SIOCGIFPSRCADDR_IN6:
539 #endif /* INET6 */
540 		if (sc->gif_psrc == NULL) {
541 			error = EADDRNOTAVAIL;
542 			goto bad;
543 		}
544 		src = sc->gif_psrc;
545 		switch (cmd) {
546 #ifdef INET
547 		case SIOCGIFPSRCADDR:
548 			dst = &ifr->ifr_addr;
549 			size = sizeof(ifr->ifr_addr);
550 			break;
551 #endif /* INET */
552 #ifdef INET6
553 		case SIOCGIFPSRCADDR_IN6:
554 			dst = (struct sockaddr *)
555 				&(((struct in6_ifreq *)data)->ifr_addr);
556 			size = sizeof(((struct in6_ifreq *)data)->ifr_addr);
557 			break;
558 #endif /* INET6 */
559 		default:
560 			error = EADDRNOTAVAIL;
561 			goto bad;
562 		}
563 		if (src->sa_len > size)
564 			return (EINVAL);
565 		bcopy((caddr_t)src, (caddr_t)dst, src->sa_len);
566 		break;
567 
568 	case SIOCGIFPDSTADDR:
569 #ifdef INET6
570 	case SIOCGIFPDSTADDR_IN6:
571 #endif /* INET6 */
572 		if (sc->gif_pdst == NULL) {
573 			error = EADDRNOTAVAIL;
574 			goto bad;
575 		}
576 		src = sc->gif_pdst;
577 		switch (cmd) {
578 #ifdef INET
579 		case SIOCGIFPDSTADDR:
580 			dst = &ifr->ifr_addr;
581 			size = sizeof(ifr->ifr_addr);
582 			break;
583 #endif /* INET */
584 #ifdef INET6
585 		case SIOCGIFPDSTADDR_IN6:
586 			dst = (struct sockaddr *)
587 				&(((struct in6_ifreq *)data)->ifr_addr);
588 			size = sizeof(((struct in6_ifreq *)data)->ifr_addr);
589 			break;
590 #endif /* INET6 */
591 		default:
592 			error = EADDRNOTAVAIL;
593 			goto bad;
594 		}
595 		if (src->sa_len > size)
596 			return (EINVAL);
597 		bcopy((caddr_t)src, (caddr_t)dst, src->sa_len);
598 		break;
599 
600 	case SIOCGLIFPHYADDR:
601 		if (sc->gif_psrc == NULL || sc->gif_pdst == NULL) {
602 			error = EADDRNOTAVAIL;
603 			goto bad;
604 		}
605 
606 		/* copy src */
607 		src = sc->gif_psrc;
608 		dst = (struct sockaddr *)
609 			&(((struct if_laddrreq *)data)->addr);
610 		size = sizeof(((struct if_laddrreq *)data)->addr);
611 		if (src->sa_len > size)
612 			return (EINVAL);
613 		bcopy((caddr_t)src, (caddr_t)dst, src->sa_len);
614 
615 		/* copy dst */
616 		src = sc->gif_pdst;
617 		dst = (struct sockaddr *)
618 			&(((struct if_laddrreq *)data)->dstaddr);
619 		size = sizeof(((struct if_laddrreq *)data)->dstaddr);
620 		if (src->sa_len > size)
621 			return (EINVAL);
622 		bcopy((caddr_t)src, (caddr_t)dst, src->sa_len);
623 		break;
624 
625 	case SIOCSIFFLAGS:
626 		/* if_ioctl() takes care of it */
627 		break;
628 
629 	case SIOCSIFMTU:
630 		if (ifr->ifr_mtu < GIF_MTU_MIN || ifr->ifr_mtu > GIF_MTU_MAX)
631 			error = EINVAL;
632 		else
633 			ifp->if_mtu = ifr->ifr_mtu;
634 		break;
635 
636 	case SIOCSLIFPHYRTABLE:
637 		if (ifr->ifr_rdomainid < 0 ||
638 		    ifr->ifr_rdomainid > RT_TABLEID_MAX ||
639 		    !rtable_exists(ifr->ifr_rdomainid)) {
640 			error = EINVAL;
641 			break;
642 		}
643 		sc->gif_rtableid = ifr->ifr_rdomainid;
644 		break;
645 	case SIOCGLIFPHYRTABLE:
646 		ifr->ifr_rdomainid = sc->gif_rtableid;
647 		break;
648 	default:
649 		error = ENOTTY;
650 		break;
651 	}
652  bad:
653 	return (error);
654 }
655 
656 int
657 gif_checkloop(struct ifnet *ifp, struct mbuf *m)
658 {
659 	struct m_tag *mtag;
660 
661 	/*
662 	 * gif may cause infinite recursion calls when misconfigured.
663 	 * We'll prevent this by detecting loops.
664 	 */
665 	for (mtag = m_tag_find(m, PACKET_TAG_GIF, NULL); mtag;
666 	    mtag = m_tag_find(m, PACKET_TAG_GIF, mtag)) {
667 		if (*(struct ifnet **)(mtag + 1) == ifp) {
668 			log(LOG_NOTICE, "gif_output: "
669 			    "recursively called too many times\n");
670 			m_freem(m);
671 			return ENETUNREACH;
672 		}
673 	}
674 
675 	mtag = m_tag_get(PACKET_TAG_GIF, sizeof(struct ifnet *), M_NOWAIT);
676 	if (mtag == NULL) {
677 		m_freem(m);
678 		return ENOMEM;
679 	}
680 	*(struct ifnet **)(mtag + 1) = ifp;
681 	m_tag_prepend(m, mtag);
682 	return 0;
683 }
684