- uh->uh_dport == ntohs((u_short)esp_udp_encap_port)) {
- int payload_len = len - sizeof (struct udphdr) > 4 ? 4 :
- len - sizeof (struct udphdr);
-
- if (m->m_len < iphlen + sizeof (struct udphdr) + payload_len) {
- if ((m = m_pullup(m, iphlen + sizeof (struct udphdr) +
- payload_len)) == NULL) {
- udpstat.udps_hdrops++;
+ (uh->uh_dport == ntohs((u_short)esp_udp_encap_port) ||
+ uh->uh_sport == ntohs((u_short)esp_udp_encap_port))) {
+ /*
+ * Check if ESP or keepalive:
+ * 1. If the destination port of the incoming packet is 4500.
+ * 2. If the source port of the incoming packet is 4500,
+ * then check the SADB to match IP address and port.
+ */
+ bool check_esp = true;
+ if (uh->uh_dport != ntohs((u_short)esp_udp_encap_port)) {
+ check_esp = key_checksa_present(AF_INET, (caddr_t)&ip->ip_dst,
+ (caddr_t)&ip->ip_src, uh->uh_dport,
+ uh->uh_sport);
+ }
+
+ if (check_esp) {
+ int payload_len = len - sizeof(struct udphdr) > 4 ? 4 :
+ len - sizeof(struct udphdr);
+
+ if (m->m_len < iphlen + sizeof(struct udphdr) + payload_len) {
+ if ((m = m_pullup(m, iphlen + sizeof(struct udphdr) +
+ payload_len)) == NULL) {
+ udpstat.udps_hdrops++;
+ KERNEL_DEBUG(DBG_FNC_UDP_INPUT | DBG_FUNC_END,
+ 0, 0, 0, 0, 0);
+ return;
+ }
+ /*
+ * Expect 32-bit aligned data pointer on strict-align
+ * platforms.
+ */
+ MBUF_STRICT_DATA_ALIGNMENT_CHECK_32(m);
+
+ ip = mtod(m, struct ip *);
+ uh = (struct udphdr *)(void *)((caddr_t)ip + iphlen);
+ }
+ /* Check for NAT keepalive packet */
+ if (payload_len == 1 && *(u_int8_t *)
+ ((caddr_t)uh + sizeof(struct udphdr)) == 0xFF) {
+ m_freem(m);
+ KERNEL_DEBUG(DBG_FNC_UDP_INPUT | DBG_FUNC_END,
+ 0, 0, 0, 0, 0);
+ return;
+ } else if (payload_len == 4 && *(u_int32_t *)(void *)
+ ((caddr_t)uh + sizeof(struct udphdr)) != 0) {
+ /* UDP encapsulated IPsec packet to pass through NAT */