+ if (ip->ip_p == IPPROTO_UDP) {
+ // offset includes the outer ip and udp header lengths.
+ if (m->m_len < off) {
+ m = m_pullup(m, off);
+ if (!m) {
+ ipseclog((LOG_DEBUG,
+ "IPv4 ESP input: invalid udp encapsulated ESP packet length \n"));
+ IPSEC_STAT_INCREMENT(ipsecstat.in_inval);
+ goto bad;
+ }
+ }
+
+ // check the UDP encap header to detect changes in the source port, and then strip the header
+ off -= sizeof(struct udphdr); // off no longer includes the udphdr's size
+ // if peer is behind nat and this is the latest esp packet
+ if ((sav->flags & SADB_X_EXT_NATT_DETECTED_PEER) != 0 &&
+ (sav->flags & SADB_X_EXT_OLD) == 0 &&
+ seq && sav->replay &&
+ seq >= sav->replay->lastseq) {
+ struct udphdr *encap_uh = (__typeof__(encap_uh))(void *)((caddr_t)ip + off);
+ if (encap_uh->uh_sport &&
+ ntohs(encap_uh->uh_sport) != sav->remote_ike_port) {
+ sav->remote_ike_port = ntohs(encap_uh->uh_sport);
+ }
+ }
+ ip = esp4_input_strip_UDP_encap(m, off);
+ esp = (struct esp *)(void *)(((u_int8_t *)ip) + off);
+ }
+
+ if (sav->utun_is_keepalive_fn) {
+ if (sav->utun_is_keepalive_fn(sav->utun_pcb, &m, nxt, sav->flags, (off + esplen + ivlen))) {
+ if (m) {
+ // not really bad, we just wanna exit
+ IPSEC_STAT_INCREMENT(ipsecstat.in_success);
+ m = NULL;
+ }
+ goto bad;
+ }
+ }