/*
- * Copyright (c) 2008-2018 Apple Inc. All rights reserved.
+ * Copyright (c) 2008-2020 Apple Inc. All rights reserved.
*
* @APPLE_OSREFERENCE_LICENSE_HEADER_START@
*
#include <sys/bitstring.h>
#include <libkern/OSAtomic.h>
+#include <libkern/sysctl.h>
#include <net/if.h>
#include <net/route.h>
#include <netinet/udp.h>
#include <netinet/udp_var.h>
#include <netinet/ip_ecn.h>
-#if INET6
#include <netinet6/ip6_ecn.h>
-#endif
#include <netinet/tcp.h>
#include <netinet/udp.h>
#include <netinet/ip6.h>
-#if INET6
#include <netinet6/ip6_var.h>
-#endif
#include <netinet/in_pcb.h>
-#if INET6
#include <netinet/icmp6.h>
-#endif
#include <netinet6/ipsec.h>
-#if INET6
#include <netinet6/ipsec6.h>
-#endif
#include <netinet6/ah.h>
-#if INET6
#include <netinet6/ah6.h>
-#endif
#if IPSEC_ESP
#include <netinet6/esp.h>
-#if INET6
#include <netinet6/esp6.h>
#endif
-#endif
#include <netkey/key.h>
#include <netkey/keydb.h>
#include <netkey/key_debug.h>
bool ipsec_save_wake_pkt = false;
SYSCTL_DECL(_net_inet_ipsec);
-#if INET6
SYSCTL_DECL(_net_inet6_ipsec6);
-#endif
/* net.inet.ipsec */
SYSCTL_STRUCT(_net_inet_ipsec, IPSECCTL_STATS,
stats, CTLFLAG_RD | CTLFLAG_LOCKED, &ipsecstat, ipsecstat, "");
SYSCTL_INT(_net_inet_ipsec, OID_AUTO, esp_port,
CTLFLAG_RW | CTLFLAG_LOCKED, &esp_udp_encap_port, 0, "");
-#if INET6
struct ipsecstat ipsec6stat;
int ip6_esp_trans_deflev = IPSEC_LEVEL_USE;
int ip6_esp_net_deflev = IPSEC_LEVEL_USE;
debug, CTLFLAG_RW | CTLFLAG_LOCKED, &ipsec_debug, 0, "");
SYSCTL_INT(_net_inet6_ipsec6, IPSECCTL_ESP_RANDPAD,
esp_randpad, CTLFLAG_RW | CTLFLAG_LOCKED, &ip6_esp_randpad, 0, "");
-#endif /* INET6 */
SYSCTL_DECL(_net_link_generic_system);
struct ipsec_wake_pkt_info ipsec_wake_pkt;
-static int ipsec_setspidx_interface(struct secpolicyindex *, u_int, struct mbuf *,
+static int ipsec_setspidx_interface(struct secpolicyindex *, u_int8_t, struct mbuf *,
int, int, int);
-static int ipsec_setspidx_mbuf(struct secpolicyindex *, u_int, u_int,
+static int ipsec_setspidx_mbuf(struct secpolicyindex *, u_int8_t, u_int,
struct mbuf *, int);
static int ipsec4_setspidx_inpcb(struct mbuf *, struct inpcb *pcb);
-#if INET6
static int ipsec6_setspidx_in6pcb(struct mbuf *, struct in6pcb *pcb);
-#endif
static int ipsec_setspidx(struct mbuf *, struct secpolicyindex *, int, int);
static void ipsec4_get_ulp(struct mbuf *m, struct secpolicyindex *, int);
static int ipsec4_setspidx_ipaddr(struct mbuf *, struct secpolicyindex *);
-#if INET6
static void ipsec6_get_ulp(struct mbuf *m, struct secpolicyindex *, int);
static int ipsec6_setspidx_ipaddr(struct mbuf *, struct secpolicyindex *);
-#endif
static struct inpcbpolicy *ipsec_newpcbpolicy(void);
static void ipsec_delpcbpolicy(struct inpcbpolicy *);
static struct secpolicy *ipsec_deepcopy_policy(struct secpolicy *src);
static int ipsec_set_policy(struct secpolicy **pcb_sp,
int optname, caddr_t request, size_t len, int priv);
-static void vshiftl(unsigned char *, int, int);
+static void vshiftl(unsigned char *, int, size_t);
static int ipsec_in_reject(struct secpolicy *, struct mbuf *);
-#if INET6
static int ipsec64_encapsulate(struct mbuf *, struct secasvar *);
static int ipsec6_update_routecache_and_output(struct ipsec_output_state *state, struct secasvar *sav);
static int ipsec46_encapsulate(struct ipsec_output_state *state, struct secasvar *sav);
-#endif
static struct ipsec_tag *ipsec_addaux(struct mbuf *);
static struct ipsec_tag *ipsec_findaux(struct mbuf *);
static void ipsec_optaux(struct mbuf *, struct ipsec_tag *);
bool ipsec_fill_offload_frame(ifnet_t ifp, struct secasvar *sav, struct ifnet_keepalive_offload_frame *frame, size_t frame_data_offset);
extern bool IOPMCopySleepWakeUUIDKey(char *, size_t);
-extern void *registerSleepWakeInterest(void *, void *, void *);
+
+typedef IOReturn (*IOServiceInterestHandler)( void * target, void * refCon,
+ UInt32 messageType, void * provider,
+ void * messageArgument, vm_size_t argSize );
+extern void *registerSleepWakeInterest(IOServiceInterestHandler, void *, void *);
static int
sysctl_def_policy SYSCTL_HANDLER_ARGS
*/
struct secpolicy *
ipsec4_getpolicybysock(struct mbuf *m,
- u_int dir,
+ u_int8_t dir,
struct socket *so,
int *error)
{
case PF_INET:
pcbsp = sotoinpcb(so)->inp_sp;
break;
-#if INET6
case PF_INET6:
pcbsp = sotoin6pcb(so)->in6p_sp;
break;
-#endif
}
if (!pcbsp) {
/* set spidx in pcb */
*error = ipsec4_setspidx_inpcb(m, sotoinpcb(so));
break;
-#if INET6
case PF_INET6:
/* set spidx in pcb */
*error = ipsec6_setspidx_in6pcb(m, sotoin6pcb(so));
break;
-#endif
default:
panic("ipsec4_getpolicybysock: unsupported address family\n");
}
*/
struct secpolicy *
ipsec4_getpolicybyaddr(struct mbuf *m,
- u_int dir,
+ u_int8_t dir,
int flag,
int *error)
{
*/
int
ipsec4_getpolicybyinterface(struct mbuf *m,
- u_int dir,
+ u_int8_t dir,
int *flags,
struct ip_out_args *ipoa,
struct secpolicy **sp)
}
-#if INET6
/*
* For OUTBOUND packet having a socket. Searching SPD for packet,
* and return a pointer to SP.
*/
struct secpolicy *
ipsec6_getpolicybysock(struct mbuf *m,
- u_int dir,
+ u_int8_t dir,
struct socket *so,
int *error)
{
struct secpolicy *
ipsec6_getpolicybyaddr(struct mbuf *m,
- u_int dir,
+ u_int8_t dir,
int flag,
int *error)
{
*/
int
ipsec6_getpolicybyinterface(struct mbuf *m,
- u_int dir,
+ u_int8_t dir,
int flag,
struct ip6_out_args *ip6oap,
int *noipsec,
return 0;
}
-#endif /* INET6 */
/*
* set IP address into spidx from mbuf.
static int
ipsec_setspidx_mbuf(
struct secpolicyindex *spidx,
- u_int dir,
+ u_int8_t dir,
__unused u_int family,
struct mbuf *m,
int needport)
static int
ipsec_setspidx_interface(
struct secpolicyindex *spidx,
- u_int dir,
+ u_int8_t dir,
struct mbuf *m,
int needport,
int ifindex,
return error;
}
-#if INET6
static int
ipsec6_setspidx_in6pcb(struct mbuf *m, struct in6pcb *pcb)
{
bzero(&pcb->in6p_sp->sp_out->spidx, sizeof(*spidx));
return error;
}
-#endif
/*
* configure security policy index (src/dst/proto/sport/dport)
}
ipsec4_get_ulp(m, spidx, needport);
return 0;
-#if INET6
case 6:
if (m->m_pkthdr.len < sizeof(struct ip6_hdr)) {
KEYDEBUG(KEYDEBUG_IPSEC_DUMP,
}
ipsec6_get_ulp(m, spidx, needport);
return 0;
-#endif
default:
KEYDEBUG(KEYDEBUG_IPSEC_DUMP,
printf("ipsec_setspidx: "
return 0;
}
-#if INET6
static void
ipsec6_get_ulp(struct mbuf *m,
struct secpolicyindex *spidx,
return;
}
+ VERIFY(nxt <= UINT8_MAX);
switch (nxt) {
case IPPROTO_TCP:
- spidx->ul_proto = nxt;
+ spidx->ul_proto = (u_int8_t)nxt;
if (!needport) {
break;
}
((struct sockaddr_in6 *)&spidx->dst)->sin6_port = th.th_dport;
break;
case IPPROTO_UDP:
- spidx->ul_proto = nxt;
+ spidx->ul_proto = (u_int8_t)nxt;
if (!needport) {
break;
}
case IPPROTO_ICMPV6:
default:
/* XXX intermediate headers??? */
- spidx->ul_proto = nxt;
+ spidx->ul_proto = (u_int8_t)nxt;
break;
}
}
return 0;
}
-#endif
static struct inpcbpolicy *
ipsec_newpcbpolicy(void)
return 0;
}
-#if INET6
int
ipsec6_set_policy(struct in6pcb *in6p,
int optname,
return 0;
}
-#endif
/*
* return current level.
/* set default level */
switch (((struct sockaddr *)&isr->sp->spidx.src)->sa_family) {
-#if INET
case AF_INET:
esp_trans_deflev = IPSEC_CHECK_DEFAULT(ip4_esp_trans_deflev);
esp_net_deflev = IPSEC_CHECK_DEFAULT(ip4_esp_net_deflev);
ah_trans_deflev = IPSEC_CHECK_DEFAULT(ip4_ah_trans_deflev);
ah_net_deflev = IPSEC_CHECK_DEFAULT(ip4_ah_net_deflev);
break;
-#endif
-#if INET6
case AF_INET6:
esp_trans_deflev = IPSEC_CHECK_DEFAULT(ip6_esp_trans_deflev);
esp_net_deflev = IPSEC_CHECK_DEFAULT(ip6_esp_net_deflev);
ah_trans_deflev = IPSEC_CHECK_DEFAULT(ip6_ah_trans_deflev);
ah_net_deflev = IPSEC_CHECK_DEFAULT(ip6_ah_net_deflev);
break;
-#endif /* INET6 */
default:
panic("key_get_reqlevel: Unknown family. %d\n",
((struct sockaddr *)&isr->sp->spidx.src)->sa_family);
return 0;
}
-#if INET6
/*
* Check AH/ESP integrity.
* This function is called from tcp6_input(), udp6_input(),
/* NOTREACHED */
return 0;
}
-#endif
/*
* compute the byte size to be occupied by IPsec header.
case AF_INET:
clen += sizeof(struct ip);
break;
-#if INET6
case AF_INET6:
clen += sizeof(struct ip6_hdr);
break;
-#endif
default:
ipseclog((LOG_ERR, "ipsec_hdrsiz: "
"unknown AF %d in IPsec tunnel SA\n",
/* This function is called from ip_forward() and ipsec4_hdrsize_tcp(). */
size_t
-ipsec4_hdrsiz(struct mbuf *m, u_int dir, struct inpcb *inp)
+ipsec4_hdrsiz(struct mbuf *m, u_int8_t dir, struct inpcb *inp)
{
struct secpolicy *sp = NULL;
int error;
return size;
}
-#if INET6
/* This function is called from ipsec6_hdrsize_tcp(),
* and maybe from ip6_forward.()
*/
size_t
-ipsec6_hdrsiz(struct mbuf *m, u_int dir, struct in6pcb *in6p)
+ipsec6_hdrsiz(struct mbuf *m, u_int8_t dir, struct in6pcb *in6p)
{
struct secpolicy *sp = NULL;
int error;
return size;
}
-#endif /*INET6*/
-#if INET
/*
* encapsulate for ipsec tunnel.
* ip->ip_src must be fixed later on.
{
struct ip *oip;
struct ip *ip;
- size_t hlen;
size_t plen;
+ u_int32_t hlen;
/* can't tunnel between different AFs */
if (((struct sockaddr *)&sav->sah->saidx.src)->sa_family
m_freem(m);
return EINVAL;
}
-#if 0
- /* XXX if the dst is myself, perform nothing. */
- if (key_ismyaddr((struct sockaddr *)&sav->sah->saidx.dst)) {
- m_freem(m);
- return EINVAL;
- }
-#endif
if (m->m_len < sizeof(*ip)) {
panic("ipsec4_encapsulate: assumption failed (first mbuf length)");
}
ip->ip_p = IPPROTO_IPIP;
if (plen + sizeof(struct ip) < IP_MAXPACKET) {
- ip->ip_len = htons(plen + sizeof(struct ip));
+ ip->ip_len = htons((u_int16_t)(plen + sizeof(struct ip)));
} else {
ipseclog((LOG_ERR, "IPv4 ipsec: size exceeds limit: "
"leave ip_len as is (invalid packet)\n"));
return 0;
}
-#endif /*INET*/
-#if INET6
int
ipsec6_encapsulate(struct mbuf *m, struct secasvar *sav)
{
m_freem(m);
return EINVAL;
}
-#if 0
- /* XXX if the dst is myself, perform nothing. */
- if (key_ismyaddr((struct sockaddr *)&sav->sah->saidx.dst)) {
- m_freem(m);
- return EINVAL;
- }
-#endif
plen = m->m_pkthdr.len;
/* ECN consideration. */
ip6_ecn_ingress(ip6_ipsec_ecn, &ip6->ip6_flow, &oip6->ip6_flow);
if (plen < IPV6_MAXPACKET - sizeof(struct ip6_hdr)) {
- ip6->ip6_plen = htons(plen);
+ ip6->ip6_plen = htons((u_int16_t)plen);
} else {
/* ip6->ip6_plen will be updated in ip6_output() */
}
m_freem(m);
return EINVAL;
}
-#if 0
- /* XXX if the dst is myself, perform nothing. */
- if (key_ismyaddr((struct sockaddr *)&sav->sah->saidx.dst)) {
- m_freem(m);
- return EINVAL;
- }
-#endif
plen = m->m_pkthdr.len;
ip6 = mtod(m, struct ip6_hdr *);
/* construct new IPv4 header. see RFC 2401 5.1.2.1 */
/* ECN consideration. */
- ip64_ecn_ingress(ip4_ipsec_ecn, &ip->ip_tos, &ip6->ip6_flow);
+ ip64_ecn_ingress(ip4_ipsec_ecn, &ip->ip_tos, &ip6i->ip6_flow);
if (plen + sizeof(struct ip) < IP_MAXPACKET) {
- ip->ip_len = htons(plen + sizeof(struct ip));
+ ip->ip_len = htons((u_int16_t)(plen + sizeof(struct ip)));
} else {
- ip->ip_len = htons(plen);
+ ip->ip_len = htons((u_int16_t)plen);
ipseclog((LOG_ERR, "IPv4 ipsec: size exceeds limit: "
"leave ip_len as is (invalid packet)\n"));
}
return error;
}
ip6 = mtod(state->m, struct ip6_hdr *);
- ip6->ip6_plen = htons(plen);
+ ip6->ip6_plen = htons((u_int16_t)plen);
ipsec_set_pkthdr_for_interface(sav->sah->ipsec_if, state->m, AF_INET6);
ipsec_set_ip6oa_for_interface(sav->sah->ipsec_if, &ip6oa);
/* Increment statistics */
- ifnet_stat_increment_out(sav->sah->ipsec_if, 1, mbuf_pkthdr_len(state->m), 0);
+ ifnet_stat_increment_out(sav->sah->ipsec_if, 1, (u_int32_t)mbuf_pkthdr_len(state->m), 0);
/* Send to ip6_output */
bzero(&ro6_new, sizeof(ro6_new));
struct ip6_hdr *ip6;
struct ip *oip;
struct ip *ip;
- size_t hlen;
size_t plen;
+ u_int32_t hlen;
m = state->m;
if (!m) {
m_freem(m);
return EINVAL;
}
-#if 0
- /* XXX if the dst is myself, perform nothing. */
- if (key_ismyaddr((struct sockaddr *)&sav->sah->saidx.dst)) {
- m_freem(m);
- return EINVAL;
- }
-#endif
if (m->m_len < sizeof(*ip)) {
panic("ipsec46_encapsulate: assumption failed (first mbuf length)");
/* construct new IPv6 header. see RFC 2401 5.1.2.2 */
/* ECN consideration. */
- ip46_ecn_ingress(ip6_ipsec_ecn, &ip6->ip6_flow, &ip->ip_tos);
+ ip46_ecn_ingress(ip6_ipsec_ecn, &ip6->ip6_flow, &oip->ip_tos);
if (plen < IPV6_MAXPACKET - sizeof(struct ip6_hdr)) {
- ip6->ip6_plen = htons(plen);
+ ip6->ip6_plen = htons((u_int16_t)plen);
} else {
/* ip6->ip6_plen will be updated in ip6_output() */
}
return 0;
}
-#endif /*INET6*/
-
/*
* Check the variable replay window.
* ipsec_chkreplay() performs replay check before ICV verification.
{
const struct secreplay *replay;
u_int32_t diff;
- int fr;
- u_int32_t wsizeb; /* constant: bits of window size */
- int frlast; /* constant: last frame */
+ size_t fr;
+ size_t wsizeb; /* constant: bits of window size */
+ size_t frlast; /* constant: last frame */
/* sanity check */
{
struct secreplay *replay;
u_int32_t diff;
- int fr;
- u_int32_t wsizeb; /* constant: bits of window size */
- int frlast; /* constant: last frame */
+ size_t fr;
+ size_t wsizeb; /* constant: bits of window size */
+ size_t frlast; /* constant: last frame */
/* sanity check */
if (sav == NULL) {
* wsize: buffer size (bytes).
*/
static void
-vshiftl(unsigned char *bitmap, int nbit, int wsize)
+vshiftl(unsigned char *bitmap, int nbit, size_t wsize)
{
- int s, j, i;
+ size_t i;
+ int s, j;
unsigned char over;
for (j = 0; j < nbit; j += 8) {
return buf;
}
-#if INET6
const char *
ipsec6_logpacketstr(struct ip6_hdr *ip6, u_int32_t spi)
{
return buf;
}
-#endif /*INET6*/
const char *
ipsec_logsastr(struct secasvar *sav)
snprintf(p, sizeof(buf) - (p - buf),
"src=%d.%d.%d.%d dst=%d.%d.%d.%d",
s[0], s[1], s[2], s[3], d[0], d[1], d[2], d[3]);
- }
-#if INET6
- else if (((struct sockaddr *)&saidx->src)->sa_family == AF_INET6) {
+ } else if (((struct sockaddr *)&saidx->src)->sa_family == AF_INET6) {
snprintf(p, sizeof(buf) - (p - buf),
"src=%s",
ip6_sprintf(&((struct sockaddr_in6 *)&saidx->src)->sin6_addr));
" dst=%s",
ip6_sprintf(&((struct sockaddr_in6 *)&saidx->dst)->sin6_addr));
}
-#endif
while (p && *p) {
p++;
}
isr->saidx.mode == IPSEC_MODE_TRANSPORT) {
if (ip->ip_p == IPPROTO_UDP) {
struct udphdr *udp;
- size_t hlen;
+ u_int32_t hlen;
#ifdef _IP_VHL
hlen = IP_VHL_HL(ip->ip_vhl) << 2;
#else
#endif
-#if INET6
/*
* IPsec output logic for IPv6, transport mode.
*/
struct mbuf *mprev)
{
struct ip6_hdr *ip6;
+ size_t plen;
int error = 0;
- int plen;
/* validity check */
if (sav == NULL || sav->sah == NULL) {
goto bad;
}
ip6 = mtod(state->m, struct ip6_hdr *);
- ip6->ip6_plen = htons(plen);
+ ip6->ip6_plen = htons((u_int16_t)plen);
return 0;
bad:
ipsec6_output_tunnel_internal(struct ipsec_output_state *state, struct secasvar *sav, int *must_be_last)
{
struct ip6_hdr *ip6;
- int error = 0;
- int plen;
struct sockaddr_in6* dst6;
struct route_in6 *ro6;
+ size_t plen;
+ int error = 0;
/* validity check */
if (sav == NULL || sav->sah == NULL || sav->sah->saidx.mode != IPSEC_MODE_TUNNEL) {
goto bad;
}
ip6 = mtod(state->m, struct ip6_hdr *);
- ip6->ip6_plen = htons(plen);
+ ip6->ip6_plen = htons((u_int16_t)plen);
done:
return 0;
state->m = NULL;
return error;
}
-#endif /*INET6*/
#if INET
/*
}
#endif
-#if INET6
struct mbuf *
ipsec6_splithdr(struct mbuf *m)
{
}
return m;
}
-#endif
/* validate inbound IPsec tunnel packet. */
int
return 1;
}
-#if INET6
/* validate inbound IPsec tunnel packet. */
int
ipsec6_tunnel_validate(
return 1;
}
-#endif
/*
* Make a mbuf chain for encryption.
bzero(m_mtod(m), m->m_len);
m->m_pkthdr.len = m->m_len;
- ip->ip_len = m->m_len;
- ip->ip_ttl = ip_defttl;
+ ip->ip_len = (u_short)m->m_len;
+ ip->ip_ttl = (u_char)ip_defttl;
ip->ip_p = IPPROTO_UDP;
if (sav->sah->dir != IPSEC_DIR_INBOUND) {
ip->ip_src = ((struct sockaddr_in*)&sav->sah->saidx.src)->sin_addr;
ip6->ip6_vfc &= ~IPV6_VERSION_MASK;
ip6->ip6_vfc |= IPV6_VERSION;
ip6->ip6_nxt = IPPROTO_UDP;
- ip6->ip6_hlim = ip6_defhlim;
+ ip6->ip6_hlim = (u_int8_t)ip6_defhlim;
ip6->ip6_plen = htons(sizeof(struct udphdr) + 1);
if (sav->sah->dir != IPSEC_DIR_INBOUND) {
ip6->ip6_src = ((struct sockaddr_in6 *)&sav->sah->saidx.src)->sin6_addr;
ip = (__typeof__(ip))(void *)(data + frame_data_offset);
uh = (__typeof__(uh))(void *)(data + frame_data_offset + sizeof(*ip));
- frame->length = frame_data_offset + sizeof(struct udpiphdr) + 1;
+ frame->length = (u_int8_t)(frame_data_offset + sizeof(struct udpiphdr) + 1);
frame->type = IFNET_KEEPALIVE_OFFLOAD_FRAME_IPSEC;
frame->ether_type = IFNET_KEEPALIVE_OFFLOAD_FRAME_ETHERTYPE_IPV4;
} else {
ip->ip_id = ip_randomid();
}
- ip->ip_ttl = ip_defttl;
+ ip->ip_ttl = (u_char)ip_defttl;
ip->ip_p = IPPROTO_UDP;
ip->ip_sum = 0;
if (sav->sah->dir != IPSEC_DIR_INBOUND) {
} else if (sav->natt_interval != 0) {
frame->interval = sav->natt_interval;
} else {
- frame->interval = natt_keepalive_interval;
+ frame->interval = (u_int16_t)natt_keepalive_interval;
}
return TRUE;
}
goto done;
}
- u_int16_t max_len = (wake_mbuf->m_pkthdr.len > IPSEC_MAX_WAKE_PKT_LEN) ? IPSEC_MAX_WAKE_PKT_LEN : wake_mbuf->m_pkthdr.len;
+ u_int16_t max_len = (wake_mbuf->m_pkthdr.len > IPSEC_MAX_WAKE_PKT_LEN) ? IPSEC_MAX_WAKE_PKT_LEN : (u_int16_t)wake_mbuf->m_pkthdr.len;
m_copydata(wake_mbuf, 0, max_len, (void *)ipsec_wake_pkt.wake_pkt);
ipsec_wake_pkt.wake_pkt_len = max_len;
ipsec_wake_pkt.wake_pkt_seq,
ipsec_wake_pkt.wake_pkt_len));
- struct kev_msg ev_msg = { 0 };
+ struct kev_msg ev_msg;
+ bzero(&ev_msg, sizeof(ev_msg));
+
ev_msg.vendor_code = KEV_VENDOR_APPLE;
ev_msg.kev_class = KEV_NETWORK_CLASS;
ev_msg.kev_subclass = KEV_IPSEC_SUBCLASS;
- ev_msg.kev_subclass = KEV_IPSEC_WAKE_PACKET;
+ ev_msg.event_code = KEV_IPSEC_WAKE_PACKET;
+
+ struct ipsec_wake_pkt_event_data event_data;
+ strlcpy(event_data.wake_uuid, ipsec_wake_pkt.wake_uuid, sizeof(event_data.wake_uuid));
+ ev_msg.dv[0].data_ptr = &event_data;
+ ev_msg.dv[0].data_length = sizeof(event_data);
+
int result = kev_post_msg(&ev_msg);
if (result != 0) {
os_log_error(OS_LOG_DEFAULT, "%s: kev_post_msg() failed with error %d for wake uuid %s",
#pragma unused(target, refCon, provider, messageArgument, argSize)
switch (messageType) {
case kIOMessageSystemWillSleep:
+ {
ipsec_get_local_ports();
+ ipsec_save_wake_pkt = false;
memset(&ipsec_wake_pkt, 0, sizeof(ipsec_wake_pkt));
IOPMCopySleepWakeUUIDKey(ipsec_wake_pkt.wake_uuid,
sizeof(ipsec_wake_pkt.wake_uuid));
ipseclog((LOG_NOTICE,
"ipsec: system will sleep, uuid: %s", ipsec_wake_pkt.wake_uuid));
break;
- case kIOMessageSystemWillPowerOn:
- ipsec_save_wake_pkt = true;
- ipseclog((LOG_NOTICE,
- "ipsec: system will powered on, uuid: %s", ipsec_wake_pkt.wake_uuid));
+ }
+ case kIOMessageSystemHasPoweredOn:
+ {
+ char wake_reason[128] = {0};
+ size_t size = sizeof(wake_reason);
+ if (kernel_sysctlbyname("kern.wakereason", wake_reason, &size, NULL, 0) == 0) {
+ if (strnstr(wake_reason, "wlan", size) == 0 ||
+ strnstr(wake_reason, "WL.OutboxNotEmpty", size) == 0 ||
+ strnstr(wake_reason, "baseband", size) == 0 ||
+ strnstr(wake_reason, "bluetooth", size) == 0 ||
+ strnstr(wake_reason, "BT.OutboxNotEmpty", size) == 0) {
+ ipsec_save_wake_pkt = true;
+ ipseclog((LOG_NOTICE,
+ "ipsec: system has powered on, uuid: %s reason %s", ipsec_wake_pkt.wake_uuid, wake_reason));
+ }
+ }
break;
+ }
default:
break;
}