/* * ================================================================================== * Network Interface Header - Raw Socket ICMP/ICMPv6 Operations * * ISA Project * Author: Roman Necas (xnecasr00) * Date: 13. October 2025 * * PURPOSE: * This header defines the network interface layer for the ICMP covert channel * file transfer application. It provides abstractions for raw socket operations, * supporting both IPv4 (ICMP) and IPv6 (ICMPv6) Echo-Request/Reply messages. * * RESPONSIBILITIES: * - Raw socket creation and management (requires root privileges) * - ICMP packet transmission and reception * - Address family abstraction (IPv4/IPv6) * - Timeout handling for reliable communication * - Network statistics tracking * - Checksum calculation for ICMPv4 packets * * PROTOCOL SUPPORT: * - IPv4: ICMP Echo-Request (type 8) / Echo-Reply (type 0) * - IPv6: ICMPv6 Echo-Request (type 128) / Echo-Reply (type 129) * * RAW SOCKET REQUIREMENTS: * - Requires CAP_NET_RAW capability or root privileges * - Uses IPPROTO_ICMP for IPv4, IPPROTO_ICMPV6 for IPv6 * - IPv4: Application must calculate ICMP checksum * - IPv6: Kernel automatically calculates ICMPv6 checksum (RFC 3542) * * KEY FEATURES: * - Dual-stack support (IPv4/IPv6) with automatic detection * - Hostname resolution via getaddrinfo() * - Configurable send/receive timeouts * - Non-blocking receive mode for server operation * - MTU discovery for optimal packet sizing * - Comprehensive error handling with detailed diagnostics * ================================================================================== */ #ifndef NETWORK_H #define NETWORK_H #include "common.h" /* * ================================================================================== * NETWORK INTERFACE STRUCTURE * ================================================================================== */ /* * network_interface_t - Network layer state management * * This structure encapsulates all state required for ICMP socket operations. * It abstracts the differences between IPv4 and IPv6, providing a unified * interface for packet transmission and reception. * * LIFECYCLE: * 1. Allocated by caller (typically on stack or in session structure) * 2. Initialized by network_init() - creates raw socket, resolves destination * 3. Configured by network_set_timeout() if custom timeouts needed * 4. Used for network_send_packet() and network_recv_packet() operations * 5. Cleaned up by network_cleanup() (closes socket) * * USAGE PATTERNS: * * Client mode: * network_interface_t net; * network_init(&net, "192.168.1.100"); * network_send_packet(&net, packet, packet_len); * network_recv_packet(&net, buffer, buffer_len, &src_addr, &src_addr_len); * network_cleanup(&net); * * Server mode: * network_interface_t net; * network_init(&net, NULL); // No destination for server * network_recv_packet_nonblocking(&net, buffer, buffer_len, &src_addr, &src_addr_len); * network_send_reply(&net, payload, payload_len, &src_addr, src_addr_len); * network_cleanup(&net); * * THREAD SAFETY: * This structure is NOT thread-safe. Each thread should have its own instance. * * SECURITY NOTES: * - Raw socket operations require elevated privileges * - Socket is bound to ICMP protocol only - cannot send arbitrary IP packets * - Timeouts prevent indefinite blocking on malicious/slow peers */ typedef struct { /* * sockfd - Primary raw ICMP socket file descriptor * * Client mode: Single socket (IPv4 or IPv6) based on destination address * - IPv4: socket(AF_INET, SOCK_RAW, IPPROTO_ICMP) * - IPv6: socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6) * * Server mode: IPv4 socket (used with sockfd_v6 for dual-stack) * - Always: socket(AF_INET, SOCK_RAW, IPPROTO_ICMP) * * Values: * - >= 0: Valid socket descriptor * - -1: Invalid/uninitialized socket * * Closed by network_cleanup() using SAFE_CLOSE macro. */ int sockfd; /* * sockfd_v6 - IPv6 socket file descriptor (server mode only) * * Client mode: Not used (always -1) * Server mode: IPv6 socket for dual-stack support * - socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6) * * This enables server to receive both IPv4 (ICMP) and IPv6 (ICMPv6) packets * simultaneously. The server uses select() to poll both sockfd and sockfd_v6. * * Values: * - >= 0: Valid IPv6 socket (server mode) * - -1: Not used (client mode) or uninitialized * * Closed by network_cleanup() using SAFE_CLOSE macro. */ int sockfd_v6; /* * dest_addr - Destination address storage (IPv4 or IPv6) * * This is a polymorphic structure capable of holding both sockaddr_in (IPv4) * and sockaddr_in6 (IPv6) addresses. The actual type is determined by the * addr_family field. * * Structure layout: * - sockaddr_storage is guaranteed to be large enough for any socket address * - Size: Typically 128 bytes (platform-dependent) * - Alignment: Suitable for casting to sockaddr_in or sockaddr_in6 * * Population: * - Client mode: Populated by network_init() via getaddrinfo() * - Server mode: Populated by network_recv_packet() from incoming packets * * Usage: * struct sockaddr_in *sin = (struct sockaddr_in *)&net->dest_addr; * sin->sin_port; // Access IPv4 fields * * struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)&net->dest_addr; * sin6->sin6_port; // Access IPv6 fields */ struct sockaddr_storage dest_addr; /* * dest_addr_len - Actual length of dest_addr structure * * This field specifies the actual size of the address stored in dest_addr. * It is required because dest_addr is a generic storage structure that can * hold addresses of different sizes. * * Typical values: * - IPv4: sizeof(struct sockaddr_in) = 16 bytes * - IPv6: sizeof(struct sockaddr_in6) = 28 bytes * * Used by: * - sendto() to specify destination address size * - recvfrom() to receive actual address size (pass as pointer) */ socklen_t dest_addr_len; /* * addr_family - Address family indicator * * Specifies whether this interface is operating in IPv4 or IPv6 mode. * This determines which socket protocol, address structures, and ICMP * message types are used. * * Values: * - AF_INET (2): IPv4 address family * * Uses IPPROTO_ICMP * * Uses struct sockaddr_in * * ICMP Echo-Request (type 8) / Echo-Reply (type 0) * * - AF_INET6 (10): IPv6 address family * * Uses IPPROTO_ICMPV6 * * Uses struct sockaddr_in6 * * ICMPv6 Echo-Request (type 128) / Echo-Reply (type 129) * * Determined automatically by network_init() based on getaddrinfo() results. */ int addr_family; /* * send_timeout - Send operation timeout in seconds * * Maximum time to wait for send operations to complete before returning error. * This timeout is set using setsockopt() with SO_SNDTIMEO option. * * Purpose: * - Prevents indefinite blocking if network is congested * - Allows application to retry or abort transfer * * Default: INITIAL_TIMEOUT (2 seconds) * Range: 1-300 seconds (validated by argument parser) * * Note: Send operations on raw sockets rarely block, as the kernel typically * queues outgoing packets. Timeout mainly protects against kernel buffer exhaustion. */ int send_timeout; /* * recv_timeout - Receive operation timeout in seconds * * Maximum time to wait for incoming packets before returning EAGAIN/EWOULDBLOCK. * This timeout is set using setsockopt() with SO_RCVTIMEO option. * * Purpose: * - Enables retry logic with exponential backoff * - Prevents infinite waiting for lost/dropped packets * - Critical for client mode when waiting for ACK responses * * Default: INITIAL_TIMEOUT (2 seconds) * Range: 1-300 seconds * * Client mode usage: * - Wait for ACK after sending DATA packet * - If timeout occurs, increment retry counter and resend * - Timeout value increases exponentially: 2s → 4s → 8s → 16s → 32s (capped at MAX_TIMEOUT) * * Server mode usage: * - Use non-blocking receive (network_recv_packet_nonblocking) * - Timeout is less critical as server waits indefinitely */ int recv_timeout; } network_interface_t; /* * ================================================================================== * NETWORK STATISTICS STRUCTURE * ================================================================================== */ /* * network_stats_t - Network performance and error metrics * * This structure tracks comprehensive statistics about network operations during * a file transfer session. It is used for: * - Debugging network issues * - Performance analysis * - Identifying reliability problems (high retransmissions, checksum errors) * - User feedback (display transfer progress) * * LIFECYCLE: * 1. Initialized by network_init_stats() (zeros all fields) * 2. Updated by network_update_stats() after each send/receive operation * 3. Displayed by network_print_stats() at end of transfer * * USAGE: * network_stats_t stats; * network_init_stats(&stats); * // ... perform transfers ... * network_update_stats(&stats, 1, packet_len, 0); // Sent packet * network_update_stats(&stats, 0, 0, 1); // Retransmission * network_print_stats(&stats); * * All counters are 64-bit to prevent overflow even for very large transfers * (e.g., 10 GB file = ~7.5 million 1400-byte packets). */ typedef struct { /* * packets_sent - Total number of packets transmitted * * Incremented for every successful call to network_send_packet() or * network_send_reply(). Includes both original transmissions and * retransmissions (counted separately in retransmissions field). * * Example values: * - 1 MB file: ~750 packets (1400-byte payload) * - 10 MB file: ~7500 packets */ uint64_t packets_sent; /* * packets_received - Total number of packets received * * Incremented for every successful call to network_recv_packet() or * network_recv_packet_nonblocking() that returns valid data. Includes * both valid and invalid packets (invalid counted in checksum_errors). * * Client mode: Primarily ACK responses from server * Server mode: DATA packets from client, END packet */ uint64_t packets_received; /* * bytes_sent - Total bytes transmitted at network layer * * Cumulative sum of all packet sizes sent, including: * - ICMP header (8 bytes) * - IFTP header (24 bytes) * - IFTP payload (0-1400 bytes) * * Does NOT include: * - IP header (added by kernel) * - Link layer headers (Ethernet, etc.) * * Used to calculate transfer throughput and verify file size. */ uint64_t bytes_sent; /* * bytes_received - Total bytes received at network layer * * Cumulative sum of all packet sizes received. Includes all received * packets, even those discarded due to checksum errors or protocol * violations. */ uint64_t bytes_received; /* * retransmissions - Number of packet retransmissions * * Incremented whenever a packet is sent more than once due to: * - Timeout waiting for ACK * - NACK response from peer * - Checksum error detection * * High retransmission count indicates: * - Network congestion or packet loss * - Peer overload (slow processing) * - Aggressive timeout settings * * Normal values: 0-5% of packets_sent * Problematic: >10% of packets_sent */ uint64_t retransmissions; /* * checksum_errors - Number of checksum validation failures * * Incremented when received packet has invalid CRC32 checksum in IFTP * header. Indicates: * - Network corruption (rare on wired networks) * - Software bugs in sender * - Malicious packet injection * * Should be 0 in normal operation. Any non-zero value requires investigation. */ uint64_t checksum_errors; /* * timeouts - Number of timeout events * * Incremented when network_recv_packet() returns timeout error (EAGAIN/ * EWOULDBLOCK) after waiting recv_timeout seconds. Indicates: * - Packet loss * - Peer failure or slowdown * - Network path issues * * Client mode: Timeout waiting for ACK triggers retransmission * Server mode: Timeout waiting for next DATA packet (logged but not critical) * * Normal values: Similar to retransmissions count */ uint64_t timeouts; } network_stats_t; /* * ================================================================================== * CORE NETWORK FUNCTIONS * ================================================================================== */ /* * network_init - Initialize network interface and create raw ICMP socket * * This function sets up the network interface for ICMP communication. It performs * the following operations: * * 1. Creates raw socket (requires root privileges): * - IPv4: socket(AF_INET, SOCK_RAW, IPPROTO_ICMP) * - IPv6: socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6) * * 2. Resolves destination address (client mode only): * - Accepts IPv4 addresses: "192.168.1.100" * - Accepts IPv6 addresses: "::1", "fe80::1" * - Accepts hostnames: "example.com" * - Uses getaddrinfo() for resolution * * 3. Sets default timeouts (2 seconds send, 2 seconds receive) * * 4. Initializes network_interface_t structure fields * * PRIVILEGE REQUIREMENTS: * Raw sockets require CAP_NET_RAW capability or effective UID 0 (root). * The application verifies root privileges in argument parser before calling * this function. * * ERROR HANDLING: * - Returns -1 and sets error context on failure * - Common errors: * * EPERM: Insufficient privileges for raw socket * * EPROTONOSUPPORT: ICMP protocol not supported by kernel * * EAI_*: getaddrinfo() resolution failures * * @param net: Network interface structure to initialize (output parameter) * @param dest_address: Destination IP address or hostname (NULL for server mode) * * @return: * 0: Success - socket created and destination resolved * -1: Failure - error details in error context */ int network_init(network_interface_t *net, const char *dest_address); /* * network_send_packet - Send ICMP packet to destination * * Transmits a complete ICMP packet to the destination address stored in the * network interface structure. The packet must already contain: * - ICMP header (8 bytes) with correct type, code, checksum * - IFTP header (24 bytes) with protocol fields * - Optional payload (0-1400 bytes) * * CHECKSUM HANDLING: * - IPv4: Caller MUST calculate ICMP checksum using network_calculate_icmp_checksum() * - IPv6: Checksum field MUST be 0, kernel calculates automatically (RFC 3542) * * SEND BEHAVIOR: * - Uses sendto() syscall with destination from net->dest_addr * - Blocks until packet is accepted by kernel (rarely blocks in practice) * - Respects SO_SNDTIMEO timeout if configured * - Returns number of bytes accepted by kernel (not necessarily transmitted) * * MTU CONSIDERATIONS: * This function does NOT perform fragmentation. Caller must ensure packet_len * does not exceed path MTU (typically 1500 bytes). Use network_get_mtu() to * query MTU if needed. * * ERROR HANDLING: * - EMSGSIZE: Packet too large for MTU (reduce payload size) * - ENETUNREACH: Network unreachable (routing problem) * - EHOSTUNREACH: Host unreachable (no route to destination) * - EAGAIN: Send buffer full (temporary, retry) * * @param net: Initialized network interface * @param packet: Complete ICMP packet with headers and payload * @param packet_len: Total packet length in bytes (ICMP + IFTP + payload) * * @return: * >0: Number of bytes sent (should equal packet_len) * -1: Error occurred (details in error context) */ int network_send_packet(network_interface_t *net, const void *packet, size_t packet_len); /* * network_recv_packet - Receive ICMP packet (blocking with timeout) * * Receives an ICMP packet from the network interface. This function blocks * until a packet arrives or the receive timeout expires (configured via * network_set_timeout() or defaults to INITIAL_TIMEOUT). * * RECEIVE BEHAVIOR: * - Uses recvfrom() syscall * - Blocks until packet arrives or timeout (SO_RCVTIMEO) * - Returns source address of sender (useful for server replies) * - May receive packets destined for other ICMP applications (filtering required) * * PACKET FILTERING: * This function returns ALL ICMP Echo-Request/Reply packets received by the * kernel, not just those for this application. Caller MUST: * 1. Verify ICMP type (Echo-Request/Reply) * 2. Verify IFTP magic number (0xDEADBEEF) * 3. Verify session ID matches expected session * 4. Verify CRC32 checksum * * IPv4 BEHAVIOR: * - Receives packets WITH IP header prepended (use IPPROTO_ICMP) * - Caller must skip IP header (typically 20 bytes) to access ICMP header * - IP header length varies (check IHL field) * * IPv6 BEHAVIOR: * - Receives packets WITHOUT IPv6 header (kernel strips it) * - First byte in buffer is ICMPv6 header * * TIMEOUT HANDLING: * - Returns -1 with errno = EAGAIN or EWOULDBLOCK on timeout * - Caller should check errno and retry if appropriate * - Client mode: Timeout waiting for ACK triggers retransmission * * @param net: Initialized network interface * @param buffer: Buffer to receive packet data (min MAX_BUFFER_SIZE = 2048 bytes) * @param buffer_len: Size of receive buffer * @param src_addr: Output parameter for source address of received packet (can be NULL) * @param src_addr_len: Input/output parameter for src_addr length (can be NULL) * * @return: * >0: Number of bytes received (total packet size including headers) * 0: Connection closed (rare for raw sockets) * -1: Error occurred (check errno for timeout vs. real error) */ int network_recv_packet(network_interface_t *net, void *buffer, size_t buffer_len, struct sockaddr_storage *src_addr, socklen_t *src_addr_len); /* * network_recv_packet_nonblocking - Receive ICMP packet (non-blocking) * * Same as network_recv_packet() but sets socket to non-blocking mode before * receiving. This function returns immediately if no packet is available. * * PURPOSE: * Used primarily in server mode where we want to: * - Poll for incoming packets without blocking forever * - Process multiple concurrent sessions * - Implement session timeouts * * BEHAVIOR: * 1. Sets socket to non-blocking mode (fcntl F_SETFL O_NONBLOCK) * 2. Calls recvfrom() which returns immediately * 3. Restores socket to blocking mode * * RETURN VALUES: * - >0: Packet received (length in bytes) * - -1 with errno = EAGAIN/EWOULDBLOCK: No packet available (NOT an error) * - -1 with other errno: Real error occurred * * @param net: Initialized network interface * @param buffer: Buffer to receive packet data * @param buffer_len: Size of receive buffer * @param src_addr: Output parameter for source address (can be NULL) * @param src_addr_len: Input/output parameter for src_addr length (can be NULL) * * @return: * >0: Number of bytes received * -1: No packet available (errno = EAGAIN) or error */ int network_recv_packet_nonblocking(network_interface_t *net, void *buffer, size_t buffer_len, struct sockaddr_storage *src_addr, socklen_t *src_addr_len); /* * network_send_reply - Send ICMP Echo Reply to specific address * * Convenience function for server mode to send ICMP Echo Reply packets back * to a client. This is used to send ACK/NACK responses after receiving DATA * packets. * * BEHAVIOR: * - Creates ICMP Echo Reply packet (type 0 for IPv4, type 129 for IPv6) * - Sets ICMP ID and sequence from original request (stored in payload) * - Calculates checksum (IPv4 only) * - Sends to specified destination address * * DIFFERENCE FROM network_send_packet(): * - network_send_packet(): Sends to net->dest_addr (client mode) * - network_send_reply(): Sends to specified address (server mode) * * @param net: Initialized network interface * @param payload: IFTP packet payload (contains ACK/NACK response) * @param payload_len: Length of payload * @param dest_addr: Destination address (client that sent the request) * @param dest_addr_len: Length of destination address * * @return: * >0: Number of bytes sent * -1: Error occurred */ int network_send_reply(network_interface_t *net, const void *payload, size_t payload_len, const struct sockaddr_storage *dest_addr, socklen_t dest_addr_len); /* * network_cleanup - Clean up network interface and close socket * * Releases all resources associated with the network interface. This function: * 1. Closes raw socket using SAFE_CLOSE macro * 2. Zeros network_interface_t structure * * SAFE TO CALL MULTIPLE TIMES: * Uses SAFE_CLOSE which sets sockfd = -1 after closing, making subsequent * calls safe no-ops. * * MUST BE CALLED: * Failure to call this function leaks a file descriptor. Always call in * cleanup paths, even on error. * * @param net: Network interface to clean up */ void network_cleanup(network_interface_t *net); /* * ================================================================================== * NETWORK UTILITY FUNCTIONS * ================================================================================== */ /* * network_set_timeout - Configure send and receive timeouts * * Updates the socket timeout values using setsockopt() with SO_SNDTIMEO and * SO_RCVTIMEO options. Timeouts are specified in seconds and converted to * struct timeval internally. * * TIMEOUT EFFECTS: * - Send timeout: Maximum time to wait for send buffer space * - Receive timeout: Maximum time to wait for incoming packet * * DEFAULT VALUES: * Both timeouts default to INITIAL_TIMEOUT (2 seconds) set by network_init(). * * EXPONENTIAL BACKOFF: * Client mode typically increases recv_timeout on each retry: * Attempt 1: 2 seconds * Attempt 2: 4 seconds * Attempt 3: 8 seconds * Attempt 4: 16 seconds * Attempt 5: 30 seconds (capped at MAX_TIMEOUT) * * @param net: Network interface to configure * @param send_timeout: Send timeout in seconds (1-300) * @param recv_timeout: Receive timeout in seconds (1-300) * * @return: * 0: Success * -1: Error setting socket options */ int network_set_timeout(network_interface_t *net, int send_timeout, int recv_timeout); /* * network_get_mtu - Query path MTU to destination * * Attempts to determine the Maximum Transmission Unit (MTU) for the path to * the destination address. This is useful for optimizing packet size to avoid * IP-level fragmentation. * * METHODS: * 1. Query IP_MTU socket option (Linux-specific) * 2. Parse /proc/sys/net/ipv4/route (fallback) * 3. Return default 1500 if unable to determine * * TYPICAL MTU VALUES: * - Ethernet: 1500 bytes * - PPPoE: 1492 bytes * - VPN: 1400 bytes * - Internet (safe minimum): 576 bytes * * USAGE: * This application uses fixed MAX_PAYLOAD_SIZE = 1400 bytes which is * conservative and should work on all networks. This function is provided * for future optimization but not currently used. * * @param net: Initialized network interface * @param dest_address: Destination IP address or hostname * * @return: * >0: Path MTU in bytes * -1: Unable to determine MTU */ int network_get_mtu(network_interface_t *net, const char *dest_address); /* * network_addr_to_string - Convert socket address to string representation * * Converts sockaddr_storage (IPv4 or IPv6) to human-readable string format * using inet_ntop(). * * OUTPUT FORMATS: * - IPv4: "192.168.1.100" * - IPv6: "fe80::1", "2001:db8::1" * * BUFFER SIZE: * Caller must provide buffer of at least INET6_ADDRSTRLEN (46) bytes to * accommodate longest possible IPv6 address string. * * @param addr: Socket address to convert * @param buffer: Output buffer for string representation * @param buffer_size: Size of output buffer (min INET6_ADDRSTRLEN) * * @return: * Pointer to buffer on success * NULL on error */ const char *network_addr_to_string(const struct sockaddr_storage *addr, char *buffer, size_t buffer_size); /* * network_compare_addresses - Compare two socket addresses for equality * * Compares two socket addresses to determine if they refer to the same host. * Handles both IPv4 and IPv6 addresses correctly. * * COMPARISON: * - Checks address family matches (AF_INET vs AF_INET6) * - Compares address bytes using memcmp() * - Ignores port numbers * - IPv6 scope ID is NOT compared * * USAGE: * Server mode uses this to verify that ACK responses come from the same * client that sent the original request (prevents hijacking). * * @param addr1: First address to compare * @param addr2: Second address to compare * * @return: * 0: Addresses are equal * -1: Addresses differ or comparison error */ int network_compare_addresses(const struct sockaddr_storage *addr1, const struct sockaddr_storage *addr2); /* * ================================================================================== * STATISTICS FUNCTIONS * ================================================================================== */ /* * network_init_stats - Initialize statistics structure to zero * * Zeros all fields in network_stats_t structure. Should be called once at * the beginning of a transfer session. * * @param stats: Statistics structure to initialize */ void network_init_stats(network_stats_t *stats); /* * network_update_stats - Update statistics after network operation * * Updates statistics counters based on the result of a network operation. * This function is called after each successful send or receive. * * @param stats: Statistics structure to update * @param sent: 1 if operation was a send, 0 if receive * @param bytes: Number of bytes sent or received * @param retransmit: 1 if this was a retransmission, 0 otherwise */ void network_update_stats(network_stats_t *stats, int sent, size_t bytes, int retransmit); /* * network_print_stats - Display statistics summary to stdout * * Prints a formatted summary of network statistics including: * - Total packets and bytes sent/received * - Retransmission count and percentage * - Checksum error count * - Timeout count * * OUTPUT EXAMPLE: * Network Statistics: * - Packets sent: 750 * - Packets received: 750 * - Bytes sent: 1050000 (1.00 MB) * - Bytes received: 18000 (0.02 MB) * - Retransmissions: 5 (0.67%) * - Checksum errors: 0 * - Timeouts: 5 * * @param stats: Statistics structure to display */ void network_print_stats(const network_stats_t *stats); /* * ================================================================================== * CHECKSUM FUNCTIONS * ================================================================================== */ /* * network_calculate_icmp_checksum - Calculate ICMPv4 checksum * * Computes the Internet Checksum (RFC 1071) for an ICMPv4 packet. This is * the standard 16-bit one's complement checksum used by IP, ICMP, UDP, TCP. * * ALGORITHM (RFC 1071): * 1. Set checksum field to 0 * 2. Sum all 16-bit words in the packet * 3. Add carry bits to the sum * 4. Take one's complement (~sum) * * USAGE: * IPv4 ICMP packets MUST have checksum calculated by application: * icmp_hdr->checksum = 0; * icmp_hdr->checksum = network_calculate_icmp_checksum(packet, packet_len); * * IPv6 ICMPv6 packets MUST NOT use this function - kernel calculates automatically. * * PADDING: * If packet length is odd, a zero byte is appended for checksum calculation * only (not transmitted). * * @param data: ICMP packet data (starting at ICMP header) * @param len: Length of packet in bytes * * @return: 16-bit checksum value (in network byte order, ready to use) */ uint16_t network_calculate_icmp_checksum(const void *data, size_t len); #endif /* NETWORK_H */