esp.c
Go to the documentation of this file.
1 /**
2  * @file esp.c
3  * @brief ESP (IP Encapsulating Security Payload)
4  *
5  * @section License
6  *
7  * SPDX-License-Identifier: GPL-2.0-or-later
8  *
9  * Copyright (C) 2022-2026 Oryx Embedded SARL. All rights reserved.
10  *
11  * This file is part of CycloneIPSEC Open.
12  *
13  * This program is free software; you can redistribute it and/or
14  * modify it under the terms of the GNU General Public License
15  * as published by the Free Software Foundation; either version 2
16  * of the License, or (at your option) any later version.
17  *
18  * This program is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21  * GNU General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public License
24  * along with this program; if not, write to the Free Software Foundation,
25  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
26  *
27  * @author Oryx Embedded SARL (www.oryx-embedded.com)
28  * @version 2.6.6
29  **/
30 
31 //Switch to the appropriate trace level
32 #define TRACE_LEVEL ESP_TRACE_LEVEL
33 
34 //Dependencies
35 #include "ipsec/ipsec.h"
36 #include "ipsec/ipsec_inbound.h"
37 #include "ipsec/ipsec_outbound.h"
39 #include "ipsec/ipsec_misc.h"
40 #include "esp/esp.h"
41 #include "esp/esp_packet_encrypt.h"
42 #include "esp/esp_packet_decrypt.h"
43 #include "core/tcp_fsm.h"
44 #include "core/raw_socket.h"
45 #include "ipv4/icmp.h"
46 #include "debug.h"
47 
48 //Check IPsec library configuration
49 #if (ESP_SUPPORT == ENABLED)
50 
51 
52 /**
53  * @brief Protect an outbound IPv4 packet using ESP
54  * @param[in] context Pointer to the IPsec context
55  * @param[in] sa Pointer to the security association
56  * @param[in] interface Underlying network interface
57  * @param[in] pseudoHeader IPv4 pseudo header
58  * @param[in] fragId Fragment identification field
59  * @param[in] buffer Multi-part buffer containing the payload
60  * @param[in] offset Offset to the first byte of the payload
61  * @param[in] ancillary Additional options passed to the stack along with
62  * the packet
63  * @return Error code
64  **/
65 
67  NetInterface *interface, const Ipv4PseudoHeader *pseudoHeader,
68  uint16_t fragId, NetBuffer *buffer, size_t offset,
69  NetTxAncillary *ancillary)
70 {
71  error_t error;
72  size_t n;
73  size_t length;
74  size_t offset2;
75  NetBuffer *buffer2;
76  Ipv4PseudoHeader pseudoHeader2;
77  EspHeader *espHeader;
78 
79  //Retrieve the length of the data
80  length = netBufferGetLength(buffer) - offset;
81 
82  //The sender may add 0 to 255 bytes of padding
84  //Calculate the overhead caused by ESP encryption
85  n += sizeof(EspHeader) + sizeof(EspTrailer) + sa->ivLen + sa->icvLen;
86 
87 #if (ESP_UDP_ENCAPS_SUPPORT == ENABLED)
88  //UDP encapsulation of IPsec ESP packets?
89  if(sa->udpEncapsulation)
90  {
91  //Calculate the overhead caused by UDP encapsulation
92  n += sizeof(UdpHeader);
93  }
94 #endif
95 
96  //Check the length of the resulting ESP packet
97  if((length + n) > ESP_BUFFER_SIZE)
98  return ERROR_FAILURE;
99 
100 #if (ESP_UDP_ENCAPS_SUPPORT == ENABLED)
101  //UDP encapsulation of IPsec ESP packets?
102  if(sa->udpEncapsulation)
103  {
104  //The ESP header is inserted after the UDP header and before the next
105  //layer protocol header (transport mode) or before an encapsulated IP
106  //header (tunnel mode)
107  espHeader = (EspHeader *) (context->buffer + sizeof(UdpHeader));
108  }
109  else
110 #endif
111  {
112  //The ESP header is inserted after the IP header and before the next
113  //layer protocol header (transport mode) or before an encapsulated IP
114  //header (tunnel mode)
115  espHeader = (EspHeader *) context->buffer;
116  }
117 
118  //The sender increments the sequence number counter for this SA and inserts
119  //the low-order 32 bits of the value into the Sequence Number field (refer
120  //to RFC 4303, section 3.3.3)
121  sa->seqNum++;
122 
123  //Format ESP header
124  espHeader->spi = htonl(sa->spi);
125  espHeader->seqNum = htonl(sa->seqNum);
126 
127  //Debug message
128  TRACE_INFO("ESP Header:\r\n");
129  //Dump ESP header contents for debugging purpose
130  espDumpHeader(espHeader);
131 
132  //Copy the payload data to be encrypted
133  netBufferRead(espHeader->payloadData + sa->ivLen, buffer, offset, length);
134 
135  //The encryption algorithm employed to protect the ESP packet is specified
136  //by the SA via which the packet is transmitted
137  error = espEncryptPacket(context, sa, espHeader, espHeader->payloadData,
138  &length, pseudoHeader->protocol);
139  //Any error to report?
140  if(error)
141  return error;
142 
143  //Calculate the length of the resulting ESP packet
144  length += sizeof(EspHeader);
145 
146 #if (ESP_UDP_ENCAPS_SUPPORT == ENABLED)
147  //UDP encapsulation of IPsec ESP packets?
148  if(sa->udpEncapsulation)
149  {
150  UdpHeader *udpHeader;
151 
152  //An 8-byte UDP header is inserted between the IP header and the ESP
153  //header of the ESP packet
154  length += sizeof(UdpHeader);
155 
156  //Point to the UDP header
157  udpHeader = (UdpHeader *) context->buffer;
158 
159  //Format the UDP header
160  udpHeader->srcPort = HTONS(IPSEC_NAT_PORT);
161  udpHeader->destPort = HTONS(IPSEC_NAT_PORT);
162  udpHeader->length = htons(length);
163 
164  //IPv4 UDP Checksum should be transmitted as a zero value
165  udpHeader->checksum = HTONS(0);
166 
167  //Debug message
168  TRACE_INFO("UDP Header:\r\n");
169  //Dump UDP header contents for debugging purpose
170  udpDumpHeader(udpHeader);
171  }
172 #endif
173 
174  //Allocate a buffer to hold the ESP packet
175  buffer2 = ipAllocBuffer(length, &offset2);
176  //Failed to allocate memory?
177  if(buffer2 == NULL)
178  return ERROR_OUT_OF_MEMORY;
179 
180  //Copy the resulting ESP packet
181  netBufferWrite(buffer2, offset2, context->buffer, length);
182 
183  //Fix the pseudo header
184  pseudoHeader2 = *pseudoHeader;
185  pseudoHeader2.length = htonl(length);
186 
187 #if (ESP_UDP_ENCAPS_SUPPORT == ENABLED)
188  //UDP encapsulation of IPsec ESP packets?
189  if(sa->udpEncapsulation)
190  {
191  //The outer IPv4 protocol header that immediately precedes the UDP header
192  //shall contain the value 17 in its Protocol field
193  pseudoHeader2.protocol = IPV4_PROTOCOL_UDP;
194  }
195  else
196 #endif
197  {
198  //The outer IPv4 protocol header that immediately precedes the ESP header
199  //shall contain the value 50 in its Protocol field (refer to RFC 4303,
200  //section 2)
201  pseudoHeader2.protocol = IPV4_PROTOCOL_ESP;
202  }
203 
204  //Send ESP packet
205  error = ipsecSendIpv4Packet(interface, &pseudoHeader2, fragId, buffer2,
206  offset2, ancillary);
207 
208  //Free previously allocated memory
209  netBufferFree(buffer2);
210 
211  //Return status code
212  return error;
213 }
214 
215 
216 /**
217  * @brief Process ESP protected packet
218  * @param[in] interface Underlying network interface
219  * @param[in] ipv4Header Pointer to the IPv4 header
220  * @param[in] buffer Multi-part buffer containing the ESP protected packet
221  * @param[in] offset Offset to the first byte of the ESP header
222  * @param[in] ancillary Additional options passed to the stack along with
223  * the packet
224  * @param[in] udpEncapsulation UDP-encapsulated ESP packet
225  * @return Error code
226  **/
227 
229  const Ipv4Header *ipv4Header, const NetBuffer *buffer, size_t offset,
230  NetRxAncillary *ancillary, bool_t udpEncapsulation)
231 {
232  error_t error;
233  size_t length;
234  uint64_t seq;
235  uint8_t nextHeader;
236  size_t offset2;
237  NetBuffer *buffer2;
238  IpsecContext *context;
239  IpsecSadEntry *sa;
240  EspHeader *espHeader;
241  IpsecSelector selector;
242  IpPseudoHeader pseudoHeader;
243 
244  //Point to the IPsec context
245  context = interface->netContext->ipsecContext;
246  //Sanity check
247  if(context == NULL)
248  return ERROR_FAILURE;
249 
250  //Retrieve the length of the packet
251  length = netBufferGetLength(buffer) - offset;
252 
253 #if (ESP_UDP_ENCAPS_SUPPORT == ENABLED)
254  //UDP-encapsulated ESP packet?
255  if(udpEncapsulation)
256  {
257  const UdpHeader *udpHeader;
258 
259  //Point to the UDP header
260  udpHeader = netBufferAt(buffer, offset, sizeof(UdpHeader));
261  //Malformed UDP datagram?
262  if(udpHeader == NULL)
263  return ERROR_FAILURE;
264 
265  //Debug message
266  TRACE_INFO("Parsing UDP header...\r\n");
267  //Dump UDP header contents for debugging purpose
268  udpDumpHeader(udpHeader);
269 
270  //Make sure the length field is correct
271  if(ntohs(udpHeader->length) < sizeof(UdpHeader) ||
272  ntohs(udpHeader->length) > length)
273  {
274  return ERROR_INVALID_HEADER;
275  }
276 
277  //Convert the length field from network byte order
278  length = ntohs(udpHeader->length);
279 
280  //Point to the payload data
281  offset += sizeof(UdpHeader);
282  length -= sizeof(UdpHeader);
283  }
284 #endif
285 
286  //Malformed ESP packet?
287  if(length < sizeof(EspHeader))
288  return ERROR_INVALID_HEADER;
289 
290  //Point to the ESP header
291  espHeader = netBufferAt(buffer, offset, sizeof(EspHeader));
292  //Malformed ESP packet?
293  if(espHeader == NULL)
294  return ERROR_FAILURE;
295 
296  //Debug message
297  TRACE_INFO("Parsing ESP header...\r\n");
298  //Dump ESP header contents for debugging purpose
299  espDumpHeader(espHeader);
300 
301  //Upon receipt of a packet containing an ESP Header, the receiver determines
302  //the appropriate (unidirectional) SA via lookup in the SAD (refer to
303  //RFC 4303, section 3.4.2)
305  ntohl(espHeader->spi));
306 
307  //If no valid Security Association exists for this packet the receiver
308  //must discard the packet. This is an auditable event
309  if(sa == NULL)
310  {
311  //Debug message
312  TRACE_WARNING("ESP: No matching SA found!\r\n");
313  //Report an error
314  return ERROR_POLICY_FAILURE;
315  }
316 
317  //Check IPsec mode
318  if(sa->mode == IPSEC_MODE_TRANSPORT)
319  {
320  //Transport mode ESP is applied only to whole IP datagrams (not to IP
321  //fragments)
322  if((ntohs(ipv4Header->fragmentOffset) & IPV4_OFFSET_MASK) != 0 ||
323  (ntohs(ipv4Header->fragmentOffset) & IPV4_FLAG_MF) != 0)
324  {
325  return ERROR_INVALID_HEADER;
326  }
327  }
328  else
329  {
330  //In tunnel mode, ESP is applied to an IP packet, which may be a fragment
331  //of an IP datagram
332  }
333 
334  //Because only the low-order 32 bits are transmitted with the packet, the
335  //receiver must deduce and track the sequence number subspace into which
336  //each packet falls
337  seq = ipsecGetSeqNum(sa, ntohl(espHeader->seqNum));
338 
339  //For each received packet, the receiver must verify that the packet
340  //contains a Sequence Number that does not duplicate the Sequence Number of
341  //any other packets received during the life of this SA. This should be the
342  //first ESP check applied to a packet after it has been matched to an SA, to
343  //speed rejection of duplicate packets (refer to RFC 4303, section 3.4.3)
344  error = ipsecCheckReplayWindow(sa, seq);
345 
346  //Duplicate packets are rejected
347  if(error)
348  {
349  //Debug message
350  TRACE_WARNING("ESP: Invalid sequence number!\r\n");
351  //Report an error
353  }
354 
355  //Point to the payload data
356  offset += sizeof(EspHeader);
357  length -= sizeof(EspHeader);
358 
359  //Check the length of the payload data
360  if(length > ESP_BUFFER_SIZE)
361  return ERROR_INVALID_LENGTH;
362 
363  //Copy the payload data to be decrypted
364  netBufferRead(context->buffer, buffer, offset, length);
365 
366  //if a separate integrity algorithm is employed, then the receiver proceeds
367  //to integrity verification, then decryption. If a combined mode algorithm
368  //is employed, the integrity check is performed along with decryption
369  error = espDecryptPacket(context, sa, espHeader, context->buffer, &length,
370  &nextHeader);
371 
372  //If the integrity check fails, the receiver must discard the received IP
373  //datagram as invalid. This is an auditable event
374  if(error)
375  {
376  //Debug message
377  TRACE_WARNING("ESP: ICV validation failed!\r\n");
378  //Report an error
380  }
381 
382  //The receive window is updated only if the ICV verification succeeds
383  ipsecUpdateReplayWindow(sa, seq);
384 
385  //Allocate a buffer to hold the decrypted payload
386  buffer2 = ipAllocBuffer(length, &offset2);
387  //Failed to allocate memory?
388  if(buffer2 == NULL)
389  return ERROR_OUT_OF_MEMORY;
390 
391  //Copy the resulting data
392  netBufferWrite(buffer2, offset2, context->buffer, length);
393 
394  //Retrieve packet's selector
395  error = ipsecGetInboundIpv4PacketSelector(ipv4Header, nextHeader, buffer2,
396  offset2, &selector);
397 
398  //Check status code
399  if(!error)
400  {
401  //Match the packet against the inbound selectors identified by the SAD
402  //entry to verify that the received packet is appropriate for the SA via
403  //which it was received (refer to RFC 4301, section 5.2)
404  if(ipsecIsSubsetSelector(&selector, &sa->selector))
405  {
406  //Form the IPv4 pseudo header
407  pseudoHeader.length = sizeof(Ipv4PseudoHeader);
408  pseudoHeader.ipv4Data.srcAddr = ipv4Header->srcAddr;
409  pseudoHeader.ipv4Data.destAddr = ipv4Header->destAddr;
410  pseudoHeader.ipv4Data.reserved = 0;
411  pseudoHeader.ipv4Data.protocol = nextHeader;
412  pseudoHeader.ipv4Data.length = htons(length);
413 
414 #if (ESP_UDP_ENCAPS_SUPPORT == ENABLED)
415  //When a transport mode has been used to transmit packets, contained
416  //TCP or UDP headers will have incorrect checksums due to the change
417  //of parts of the IP header during transit (refer to RFC 3948,
418  //section 3.1.2)
419  if(udpEncapsulation && sa->mode == IPSEC_MODE_TRANSPORT)
420  {
421  ancillary->ignoreTcpChecksum = TRUE;
422  ancillary->ignoreUdpChecksum = TRUE;
423  }
424 #endif
425  //If the computed and received ICVs match, then the datagram is valid,
426  //and it is accepted (refer to RFC 4303, section 3.4.4.1)
427  error = ipv4DispatchDatagram(interface, &pseudoHeader, buffer2, offset2,
428  ancillary);
429  }
430  else
431  {
432  //If an IPsec system receives an inbound packet on an SA and the
433  //packet's header fields are not consistent with the selectors for
434  //the SA, it must discard the packet. This is an auditable event
435  error = ERROR_POLICY_FAILURE;
436  }
437  }
438 
439  //Free previously allocated memory
440  netBufferFree(buffer2);
441 
442  //Return status code
443  return error;
444 }
445 
446 
447 /**
448  * @brief Determine if a packet uses UDP-encapsulated ESP format
449  * @param[in] buffer Multi-part buffer containing the UDP packet
450  * @param[in] offset Offset to the first byte of the UDP header
451  **/
452 
453 bool_t espIsUdpEncapsulatedPacket(const NetBuffer *buffer, size_t offset)
454 {
455 #if (ESP_UDP_ENCAPS_SUPPORT == ENABLED)
456  const UdpHeader *udpHeader;
457  const EspHeader *espHeader;
458 
459  //Point to the UDP header
460  udpHeader = netBufferAt(buffer, offset, sizeof(UdpHeader));
461  //Malformed UDP datagram?
462  if(udpHeader == NULL)
463  return FALSE;
464 
465  //The destination port must be the same as that used by IKE traffic (refer
466  //to RFC 3948, section 2.1)
467  if(ntohs(udpHeader->destPort) != IPSEC_NAT_PORT)
468  return FALSE;
469 
470  //Point to the ESP header
471  espHeader = netBufferAt(buffer, offset + sizeof(UdpHeader),
472  sizeof(EspHeader));
473  //Malformed ESP packet?
474  if(espHeader == NULL)
475  return FALSE;
476 
477  //The SPI field in the ESP header must not be a zero value (refer to
478  //RFC 3948, section 2.1)
479  if(espHeader->spi == 0)
480  return FALSE;
481 
482  //Valid UDP-encapsulated ESP packet
483  return TRUE;
484 #else
485  //Not implemented
486  return FALSE;
487 #endif
488 }
489 
490 
491 /**
492  * @brief Dump ESP header for debugging purpose
493  * @param[in] espHeader Pointer to the ESP header
494  **/
495 
496 void espDumpHeader(const EspHeader *espHeader)
497 {
498  //Dump ESP header contents
499  TRACE_DEBUG(" SPI = 0x%08" PRIX32 "\r\n", ntohl(espHeader->spi));
500  TRACE_DEBUG(" Sequence Number = 0x%08" PRIX32 "\r\n", ntohl(espHeader->seqNum));
501 }
502 
503 #endif
error_t espEncryptPacket(IpsecContext *context, IpsecSadEntry *sa, const EspHeader *espHeader, uint8_t *payload, size_t *payloadLen, uint8_t nextHeader)
Encrypt an outgoing ESP packet.
#define htons(value)
Definition: cpu_endian.h:413
NetBuffer * ipAllocBuffer(size_t length, size_t *offset)
Allocate a buffer to hold an IP packet.
Definition: ip.c:716
int bool_t
Definition: compiler_port.h:63
#define Ipv4Header
Definition: ipv4.h:36
@ IPV4_OFFSET_MASK
Definition: ipv4.h:265
@ ERROR_WRONG_SEQUENCE_NUMBER
Definition: error.h:183
IPsec selector.
Definition: ipsec.h:309
size_t netBufferRead(void *dest, const NetBuffer *src, size_t srcOffset, size_t length)
Read data from a multi-part buffer.
Definition: net_mem.c:690
error_t espProtectOutboundIpv4Packet(IpsecContext *context, IpsecSadEntry *sa, NetInterface *interface, const Ipv4PseudoHeader *pseudoHeader, uint16_t fragId, NetBuffer *buffer, size_t offset, NetTxAncillary *ancillary)
Protect an outbound IPv4 packet using ESP.
Definition: esp.c:66
IPsec processing of outbound IP traffic.
Structure describing a buffer that spans multiple chunks.
Definition: net_mem.h:89
#define TRUE
Definition: os_port.h:50
@ ERROR_INVALID_HEADER
Definition: error.h:87
ESP packet decryption.
@ ERROR_OUT_OF_MEMORY
Definition: error.h:63
#define ESP_BUFFER_SIZE
Definition: esp.h:277
bool_t espIsUdpEncapsulatedPacket(const NetBuffer *buffer, size_t offset)
Determine if a packet uses UDP-encapsulated ESP format.
Definition: esp.c:453
error_t ipsecCheckReplayWindow(const IpsecSadEntry *sa, uint64_t seqNum)
Perform replay detection.
#define IPSEC_NAT_PORT
Definition: ipsec.h:142
@ IPSEC_PROTOCOL_ESP
Definition: ipsec.h:200
uint64_t ipsecGetSeqNum(IpsecSadEntry *sa, uint32_t seql)
Determine the higher-order bits of the sequence number.
ESP (IP Encapsulating Security Payload)
#define FALSE
Definition: os_port.h:46
#define htonl(value)
Definition: cpu_endian.h:414
ICMP (Internet Control Message Protocol)
@ IPSEC_MODE_TRANSPORT
Definition: ipsec.h:212
error_t
Error codes.
Definition: error.h:43
error_t ipsecSendIpv4Packet(NetInterface *interface, const Ipv4PseudoHeader *pseudoHeader, uint16_t fragId, NetBuffer *buffer, size_t offset, NetTxAncillary *ancillary)
Send an IPv4 packet.
TCP finite state machine.
@ ERROR_FAILURE
Generic error code.
Definition: error.h:45
@ IPV4_FLAG_MF
Definition: ipv4.h:264
size_t espComputePadLength(IpsecSadEntry *sa, size_t length)
Compute the number of padding bytes.
Helper routines for IPsec.
bool_t ipsecIsSubsetSelector(const IpsecSelector *selector1, const IpsecSelector *selector2)
Test if a selector is a subset of another selector.
Definition: ipsec_misc.c:373
#define NetRxAncillary
Definition: net_misc.h:40
#define NetInterface
Definition: net.h:40
void netBufferFree(NetBuffer *buffer)
Dispose a multi-part buffer.
Definition: net_mem.c:282
@ ERROR_INVALID_LENGTH
Definition: error.h:111
EspTrailer
Definition: esp.h:327
uint8_t nextHeader
Definition: ipv6.h:304
ESP packet encryption.
#define NetTxAncillary
Definition: net_misc.h:36
#define Ipv4PseudoHeader
Definition: ipv4.h:40
#define TRACE_INFO(...)
Definition: debug.h:105
uint8_t length
Definition: tcp.h:375
size_t netBufferGetLength(const NetBuffer *buffer)
Get the actual length of a multi-part buffer.
Definition: net_mem.c:297
IPsec processing of inbound IP traffic.
IpsecSadEntry * ipsecFindInboundSadEntry(IpsecContext *context, IpsecProtocol protocol, uint32_t spi)
Search the SAD database for a matching inbound entry.
Definition: ipsec_misc.c:145
Anti-replay mechanism.
#define IpsecSadEntry
Definition: ipsec.h:36
UdpHeader
Definition: udp.h:85
TCP/IP raw sockets.
EspHeader
Definition: esp.h:315
#define ntohs(value)
Definition: cpu_endian.h:421
#define TRACE_WARNING(...)
Definition: debug.h:93
#define TRACE_DEBUG(...)
Definition: debug.h:119
IPsec (IP security)
#define HTONS(value)
Definition: cpu_endian.h:410
uint8_t n
#define IpPseudoHeader
Definition: ip.h:36
@ IPV4_PROTOCOL_UDP
Definition: ipv4.h:279
@ ERROR_AUTHENTICATION_FAILED
Definition: error.h:69
@ IPV4_PROTOCOL_ESP
Definition: ipv4.h:281
error_t espDecryptPacket(IpsecContext *context, IpsecSadEntry *sa, const EspHeader *espHeader, uint8_t *payload, size_t *payloadLen, uint8_t *nextHeader)
Decrypt an incoming ESP packet.
size_t netBufferWrite(NetBuffer *dest, size_t destOffset, const void *src, size_t length)
Write data to a multi-part buffer.
Definition: net_mem.c:637
#define IpsecContext
Definition: ipsec.h:40
error_t espProcessInboundIpv4Packet(NetInterface *interface, const Ipv4Header *ipv4Header, const NetBuffer *buffer, size_t offset, NetRxAncillary *ancillary, bool_t udpEncapsulation)
Process ESP protected packet.
Definition: esp.c:228
void * netBufferAt(const NetBuffer *buffer, size_t offset, size_t length)
Returns a pointer to a data segment.
Definition: net_mem.c:418
error_t ipsecGetInboundIpv4PacketSelector(const Ipv4Header *ipv4Header, uint8_t nextHeader, const NetBuffer *buffer, size_t offset, IpsecSelector *selector)
Extract packet's selector from inbound IPv4 packet.
void udpDumpHeader(const UdpHeader *datagram)
Dump UDP header for debugging purpose.
Definition: udp.c:1201
void ipsecUpdateReplayWindow(IpsecSadEntry *sa, uint64_t seqNum)
Update sliding window.
void espDumpHeader(const EspHeader *espHeader)
Dump ESP header for debugging purpose.
Definition: esp.c:496
@ ERROR_POLICY_FAILURE
Definition: error.h:300
#define ntohl(value)
Definition: cpu_endian.h:422
Debugging facilities.
error_t ipv4DispatchDatagram(NetInterface *interface, const IpPseudoHeader *pseudoHeader, const NetBuffer *buffer, size_t offset, const NetRxAncillary *ancillary)
Dispatch incoming IPv4 datagram.
Definition: ipv4.c:972