/*
- * Copyright (c) 2000-2018 Apple Inc. All rights reserved.
+ * Copyright (c) 2000-2020 Apple Inc. All rights reserved.
*
* @APPLE_OSREFERENCE_LICENSE_HEADER_START@
*
#include <netinet/ip_var.h>
#endif /* INET */
-#if INET6
#include <netinet6/in6_var.h>
#include <netinet/ip6.h>
#include <netinet6/ip6_var.h>
#include <netinet6/in6_gif.h>
#include <netinet6/ip6protosw.h>
-#endif /* INET6 */
#include <netinet/ip_encap.h>
#include <net/dlil.h>
#include <net/net_osdep.h>
-#if CONFIG_MACF_NET
-#include <security/mac_framework.h>
-#endif
-
#define GIFNAME "gif"
#define GIFDEV "if_gif"
.pr_unlock = rip_unlock,
};
#endif
-#if INET6
static struct ip6protosw in6_gif_protosw =
{
.pr_type = SOCK_RAW,
.pr_usrreqs = &rip6_usrreqs,
.pr_unlock = rip_unlock,
};
-#endif
static int gif_remove(struct ifnet *);
static int gif_clone_create(struct if_clone *, uint32_t, void *);
goto done;
}
#endif
-#if INET6
sc->encap_cookie6 = encap_attach_func(AF_INET6, -1,
gif_encapcheck, (struct protosw *)&in6_gif_protosw, sc);
if (sc->encap_cookie6 == NULL) {
error = ENOBUFS;
goto done;
}
-#endif
sc->gif_called = 0;
ifnet_set_mtu(sc->gif_if, GIF_MTU);
ifnet_set_flags(sc->gif_if, IFF_POINTOPOINT | IFF_MULTICAST, 0xffff);
-#if 0
- /* turn off ingress filter */
- sc->gif_if.if_flags |= IFF_LINK2;
-#endif
sc->gif_flags |= IFGIF_DETACHING;
error = ifnet_attach(sc->gif_if, NULL);
if (error != 0) {
if_clone_softc_deallocate(&gif_cloner, sc);
goto done;
}
-#if CONFIG_MACF_NET
- mac_ifnet_label_init(&sc->gif_if);
-#endif
bpfattach(sc->gif_if, DLT_NULL, sizeof(u_int));
sc->gif_flags &= ~IFGIF_DETACHING;
TAILQ_INSERT_TAIL(&gifs, sc, gif_link);
ngif--;
gif_delete_tunnel(sc);
-#ifdef INET6
encap_cookie6 = sc->encap_cookie6;
-#endif
#ifdef INET
encap_cookie4 = sc->encap_cookie4;
#endif
case IPPROTO_IPV4:
break;
#endif
-#if INET6
case IPPROTO_IPV6:
break;
-#endif
default:
goto done;
}
}
error = gif_encapcheck4(m, off, proto, arg);
#endif
-#if INET6
+ OS_FALLTHROUGH;
case 6:
if (sc->gif_psrc->sa_family != AF_INET6 ||
sc->gif_pdst->sa_family != AF_INET6) {
goto done;
}
error = gif_encapcheck6(m, off, proto, arg);
-#endif
+ OS_FALLTHROUGH;
default:
goto done;
}
/* XXX should we check if our outer source is legal? */
+ /*
+ * Save the length as m may be free by the output functions
+ * as they call m_pullup
+ */
+ u_int32_t bytes_out = m->m_pkthdr.len;
+
/* dispatch to output logic based on outer AF */
switch (sc->gif_psrc->sa_family) {
#if INET
error = in_gif_output(ifp, sc->gif_proto, m, NULL);
break;
#endif
-#if INET6
case AF_INET6:
error = in6_gif_output(ifp, sc->gif_proto, m, NULL);
break;
-#endif
default:
error = ENETDOWN;
break;
/* the mbuf was freed either by in_gif_output or in here */
ifnet_stat_increment_out(ifp, 0, 0, 1);
} else {
- ifnet_stat_increment_out(ifp, 1, m->m_pkthdr.len, 0);
+ ifnet_stat_increment_out(ifp, 1, bytes_out, 0);
}
if (error == 0) {
error = EJUSTRETURN; /* if no error, packet got sent already */
#endif /* SIOCSIFMTU */
case SIOCSIFPHYADDR:
-#if INET6
case SIOCSIFPHYADDR_IN6_32:
case SIOCSIFPHYADDR_IN6_64:
-#endif /* INET6 */
switch (cmd) {
#if INET
case SIOCSIFPHYADDR:
&(((struct in_aliasreq *)data)->ifra_dstaddr);
break;
#endif
-#if INET6
case SIOCSIFPHYADDR_IN6_32: {
struct in6_aliasreq_32 *ifra_32 =
(struct in6_aliasreq_32 *)data;
dst = (struct sockaddr *)&ifra_64->ifra_dstaddr;
break;
}
-#endif
}
/* sa_family must be equal */
}
break;
#endif
-#if INET6
case AF_INET6:
if (src->sa_len != sizeof(struct sockaddr_in6)) {
return EINVAL;
}
break;
-#endif
default:
return EAFNOSUPPORT;
}
}
break;
#endif
-#if INET6
case AF_INET6:
if (dst->sa_len != sizeof(struct sockaddr_in6)) {
return EINVAL;
}
break;
-#endif
default:
return EAFNOSUPPORT;
}
break;
}
return EAFNOSUPPORT;
-#if INET6
case SIOCSIFPHYADDR_IN6_32:
case SIOCSIFPHYADDR_IN6_64:
if (src->sa_family == AF_INET6) {
break;
}
return EAFNOSUPPORT;
-#endif /* INET6 */
}
#define GIF_ORDERED_LOCK(sc, sc2) \
/* can't configure multiple multi-dest interfaces */
#define multidest(x) \
(((struct sockaddr_in *)(void *)(x))->sin_addr.s_addr == INADDR_ANY)
-#if INET6
#define multidest6(x) \
(IN6_IS_ADDR_UNSPECIFIED(&((struct sockaddr_in6 *) \
(void *)(x))->sin6_addr))
-#endif
if (dst->sa_family == AF_INET &&
multidest(dst) && multidest(sc2->gif_pdst)) {
GIF_ORDERED_UNLOCK(sc, sc2);
ifnet_head_done();
goto bad;
}
-#if INET6
if (dst->sa_family == AF_INET6 &&
multidest6(dst) && multidest6(sc2->gif_pdst)) {
GIF_ORDERED_UNLOCK(sc, sc2);
ifnet_head_done();
goto bad;
}
-#endif
GIF_ORDERED_UNLOCK(sc, sc2);
}
ifnet_head_done();
#endif
case SIOCGIFPSRCADDR:
-#if INET6
case SIOCGIFPSRCADDR_IN6:
-#endif /* INET6 */
GIF_LOCK(sc);
if (sc->gif_psrc == NULL) {
GIF_UNLOCK(sc);
size = sizeof(ifr->ifr_addr);
break;
#endif /* INET */
-#if INET6
case SIOCGIFPSRCADDR_IN6:
dst = (struct sockaddr *)
&(((struct in6_ifreq *)data)->ifr_addr);
size = sizeof(((struct in6_ifreq *)data)->ifr_addr);
break;
-#endif /* INET6 */
default:
GIF_UNLOCK(sc);
error = EADDRNOTAVAIL;
break;
case SIOCGIFPDSTADDR:
-#if INET6
case SIOCGIFPDSTADDR_IN6:
-#endif /* INET6 */
GIF_LOCK(sc);
if (sc->gif_pdst == NULL) {
GIF_UNLOCK(sc);
size = sizeof(ifr->ifr_addr);
break;
#endif /* INET */
-#if INET6
case SIOCGIFPDSTADDR_IN6:
dst = (struct sockaddr *)
&(((struct in6_ifreq *)data)->ifr_addr);
size = sizeof(((struct in6_ifreq *)data)->ifr_addr);
break;
-#endif /* INET6 */
default:
error = EADDRNOTAVAIL;
GIF_UNLOCK(sc);