+ if ((pd->flags & tun_flags) == 0 && !is_tun) /* transport mode */
+ {
+ u8 udp_sz = (is_ip6 == 0 && pd->flags & IPSEC_SA_FLAG_UDP_ENCAP) ?
+ sizeof (udp_header_t) : 0;
+ u16 ip_hdr_sz = pd->hdr_sz - udp_sz;
+ u8 *old_ip = b[0]->data + pd->current_data - ip_hdr_sz - udp_sz;
+ u8 *ip = old_ip + adv + udp_sz;
+
+ if (is_ip6 && ip_hdr_sz > 64)
+ memmove (ip, old_ip, ip_hdr_sz);
+ else
+ clib_memcpy_le64 (ip, old_ip, ip_hdr_sz);
+
+ b[0]->current_data = pd->current_data + adv - ip_hdr_sz;
+ b[0]->current_length = pd->current_length + ip_hdr_sz - tail - adv;
+
+ if (is_ip6)
+ {
+ ip6_header_t *ip6 = (ip6_header_t *) ip;
+ u16 len = clib_net_to_host_u16 (ip6->payload_length);
+ len -= adv + tail;
+ ip6->payload_length = clib_host_to_net_u16 (len);
+ ip6->protocol = f->next_header;
+ next[0] = ESP_DECRYPT_NEXT_IP6_INPUT;
+ }
+ else
+ {
+ ip4_header_t *ip4 = (ip4_header_t *) ip;
+ ip_csum_t sum = ip4->checksum;
+ u16 len = clib_net_to_host_u16 (ip4->length);
+ len = clib_host_to_net_u16 (len - adv - tail - udp_sz);
+ sum = ip_csum_update (sum, ip4->protocol, f->next_header,
+ ip4_header_t, protocol);
+ sum = ip_csum_update (sum, ip4->length, len,
+ ip4_header_t, length);
+ ip4->checksum = ip_csum_fold (sum);
+ ip4->protocol = f->next_header;
+ ip4->length = len;
+ next[0] = ESP_DECRYPT_NEXT_IP4_INPUT;
+ }
+ }
+ else
+ {
+ if (PREDICT_TRUE (f->next_header == IP_PROTOCOL_IP_IN_IP))
+ {
+ next[0] = ESP_DECRYPT_NEXT_IP4_INPUT;
+ b[0]->current_data = pd->current_data + adv;
+ b[0]->current_length = pd->current_length - adv - tail;
+ }
+ else if (f->next_header == IP_PROTOCOL_IPV6)
+ {
+ next[0] = ESP_DECRYPT_NEXT_IP6_INPUT;
+ b[0]->current_data = pd->current_data + adv;
+ b[0]->current_length = pd->current_length - adv - tail;
+ }
+ else
+ {
+ next[0] = ESP_DECRYPT_NEXT_DROP;
+ b[0]->error = node->errors[ESP_DECRYPT_ERROR_DECRYPTION_FAILED];
+ goto trace;
+ }
+ if (is_tun)
+ {
+ if (ipsec_sa_is_set_IS_PROTECT (sa0))