794 lines
28 KiB
C
794 lines
28 KiB
C
/*
|
|
* ==================================================================================
|
|
* 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 */
|