/** @file * IPRT - Network Protocols. */ /* * Copyright (C) 2008-2023 Oracle and/or its affiliates. * * This file is part of VirtualBox base platform packages, as * available from https://www.virtualbox.org. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation, in version 3 of the * License. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . * * The contents of this file may alternatively be used under the terms * of the Common Development and Distribution License Version 1.0 * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included * in the VirtualBox distribution, in which case the provisions of the * CDDL are applicable instead of those of the GPL. * * You may elect to license modified versions of this file under the * terms and conditions of either the GPL or the CDDL or both. * * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 */ #ifndef IPRT_INCLUDED_net_h #define IPRT_INCLUDED_net_h #ifndef RT_WITHOUT_PRAGMA_ONCE # pragma once #endif #include #include #include RT_C_DECLS_BEGIN /** @defgroup grp_rt_net RTNet - Network Protocols * @ingroup grp_rt * @{ */ /** * Converts an stringified Ethernet MAC address into the RTMAC representation. * * @todo This should be move to some generic part of the runtime. * * @returns VINF_SUCCESS on success, VERR_GETOPT_INVALID_ARGUMENT_FORMAT on * failure. * * @param pszAddr The address string to convert. * @param pMacAddr Where to store the result. */ RTDECL(int) RTNetStrToMacAddr(const char *pszAddr, PRTMAC pMacAddr); /** * IPv4 address. */ typedef RTUINT32U RTNETADDRIPV4; AssertCompileSize(RTNETADDRIPV4, 4); /** Pointer to a IPv4 address. */ typedef RTNETADDRIPV4 *PRTNETADDRIPV4; /** Pointer to a const IPv4 address. */ typedef RTNETADDRIPV4 const *PCRTNETADDRIPV4; /** * Tests if the given string is an IPv4 address. * * @returns boolean. * @param pcszAddr String which may be an IPv4 address. */ RTDECL(bool) RTNetIsIPv4AddrStr(const char *pcszAddr); /** * Tests if the given string is a wildcard IPv4 address. * * @returns boolean. * @param pcszAddr String which may be an IPv4 address. */ RTDECL(bool) RTNetStrIsIPv4AddrAny(const char *pcszAddr); /** * Parses dotted-decimal IPv4 address into RTNETADDRIPV4 representation. * * @returns VINF_SUCCESS on success, VERR_INVALID_PARAMETER on * failure. * * @param pcszAddr The value to convert. * @param ppszNext Where to store the pointer to the first char * following the address. (Optional) * @param pAddr Where to store the result. */ RTDECL(int) RTNetStrToIPv4AddrEx(const char *pcszAddr, PRTNETADDRIPV4 pAddr, char **ppszNext); /** * Parses dotted-decimal IPv4 address into RTNETADDRIPV4 representation. * Leading and trailing whitespace is ignored. * * @returns VINF_SUCCESS on success, VERR_INVALID_PARAMETER on * failure. * * @param pcszAddr The value to convert. * @param pAddr Where to store the result. */ RTDECL(int) RTNetStrToIPv4Addr(const char *pcszAddr, PRTNETADDRIPV4 pAddr); /** * Parses dotted-decimal IPv4 CIDR notation into RTNETADDRIPV4 * representation and prefix length. Missing prefix specification is * treated as exact address specification (prefix length 32). Leading * and trailing whitespace is ignored. * * @returns VINF_SUCCESS on success, VERR_INVALID_PARAMETER on * failure. * * @param pcszAddr The value to convert. * @param pAddr Where to store the address. * @param piPrefix Where to store the prefix length; */ RTDECL(int) RTNetStrToIPv4Cidr(const char *pcszAddr, PRTNETADDRIPV4 pAddr, int *piPrefix); /** * Verifies that RTNETADDRIPV4 is a valid contiguous netmask and * computes its prefix length. * * @returns VINF_SUCCESS on success, VERR_INVALID_PARAMETER on * failure. * * @param pMask The netmask to verify and convert. * @param piPrefix Where to store the prefix length. (Optional) */ RTDECL(int) RTNetMaskToPrefixIPv4(PCRTNETADDRIPV4 pMask, int *piPrefix); /** * Computes netmask corresponding to the prefix length. * * @returns VINF_SUCCESS on success, VERR_INVALID_PARAMETER on * failure. * * @param iPrefix The prefix to convert. * @param pMask Where to store the netmask. */ RTDECL(int) RTNetPrefixToMaskIPv4(int iPrefix, PRTNETADDRIPV4 pMask); /** * Initializes an IPv4 address from four octets. * * @returns The address (network endian). * @param b3 The 4th and the most significant address octet. * @param b2 The 3rd address octet. * @param b1 The 2nd address octet. * @param b0 The 1st and least significant address octet. */ DECLINLINE(RTNETADDRIPV4) RTNetIPv4AddrFromU8(uint8_t b3, uint8_t b2, uint8_t b1, uint8_t b0) { RTNETADDRIPV4 Ret; #ifdef RT_LITTLE_ENDIAN Ret.u = RT_MAKE_U32_FROM_U8( b3, b2, b1, b0); #else Ret.u = RT_MAKE_U32_FROM_MSB_U8(b3, b2, b1, b0); #endif return Ret; } /** * Initializes an IPv4 address from four octets, host endian version. * * @returns The address (host endian). * @param b3 The 4th and the most significant address octet. * @param b2 The 3rd address octet. * @param b1 The 2nd address octet. * @param b0 The 1st and least significant address octet. */ DECLINLINE(RTNETADDRIPV4) RTNetIPv4AddrHEFromU8(uint8_t b3, uint8_t b2, uint8_t b1, uint8_t b0) { RTNETADDRIPV4 Ret; Ret.u = RT_MAKE_U32_FROM_MSB_U8(b3, b2, b1, b0); return Ret; } #ifdef RTNET_INCL_IN_ADDR /** * Initializes an struct in_addr from four octets * * @returns The in_addr (network endian). * @param b3 The 4th and the most significant address octet. * @param b2 The 3rd address octet. * @param b1 The 2nd address octet. * @param b0 The 1st and least significant address octet. */ DECLINLINE(struct in_addr) RTNetInAddrFromU8(uint8_t b3, uint8_t b2, uint8_t b1, uint8_t b0) { struct in_addr Ret; # ifdef RT_LITTLE_ENDIAN Ret.s_addr = RT_MAKE_U32_FROM_U8( b3, b2, b1, b0); # else Ret.s_addr = RT_MAKE_U32_FROM_MSB_U8(b3, b2, b1, b0); # endif return Ret; } /** * Converts an IPv4 address to the struct in_addr format. * * @returns Converted address (network endian). * @param pAddr The IPv4 address to convert (network endian). */ DECLINLINE(struct in_addr) RTNetIPv4AddrToInAddr(PCRTNETADDRIPV4 pAddr) { struct in_addr Ret; Ret.s_addr = pAddr->u; return Ret; } # ifdef IPRT_INCLUDED_asm_h /* for ASMByteSwapU32 */ /** * Converts an IPv4 address to the struct in_addr format, host endian version. * * @returns Converted address (network endian). * @param pAddr The IPv4 address to convert - host endian. */ DECLINLINE(struct in_addr) RTNetIPv4AddrHEToInAddr(PCRTNETADDRIPV4 pAddr) { struct in_addr Ret; Ret.s_addr = RT_H2N_U32(pAddr->u); return Ret; } # endif /** * Converts an IPv4 address to the struct in_addr format. * * @returns Converted address (network endian). * @param pInAddr The in_addr to convert (network endian). */ DECLINLINE(RTNETADDRIPV4) RTNetIPv4AddrFromInAddr(struct in_addr const *pInAddr) { RTNETADDRIPV4 Ret; Ret.u = pInAddr->s_addr; return Ret; } # ifdef IPRT_INCLUDED_asm_h /* for ASMByteSwapU32 */ /** * Converts an IPv4 address to the struct in_addr format, host endian version. * * @returns Converted address (host endian). * @param pInAddr The in_addr to convert (network endian). */ DECLINLINE(RTNETADDRIPV4) RTNetIPv4AddrHEFromInAddr(struct in_addr const *pInAddr) { RTNETADDRIPV4 Ret; Ret.u = RT_N2H_U32(pInAddr->s_addr); return Ret; } # endif #endif /* RTNET_INCL_IN_ADDR */ /** * IPv6 address. */ typedef RTUINT128U RTNETADDRIPV6; AssertCompileSize(RTNETADDRIPV6, 16); /** Pointer to a IPv6 address. */ typedef RTNETADDRIPV6 *PRTNETADDRIPV6; /** Pointer to a const IPv6 address. */ typedef RTNETADDRIPV6 const *PCRTNETADDRIPV6; /** * Tests if the given string is a valid IPv6 address. * * @returns @c true if it is, @c false if not. * @param pszAddress String which may be an IPv6 address. */ RTDECL(bool) RTNetIsIPv6AddrStr(const char *pszAddress); /** * Tests if the given string is a wildcard IPv6 address. * * @returns @c true if it is, @c false if not. * @param pszAddress String which may be an IPv6 address. */ RTDECL(bool) RTNetStrIsIPv6AddrAny(const char *pszAddress); /** * Parses IPv6 address into RTNETADDRIPV6 representation. * * @returns VINF_SUCCESS on success, VERR_INVALID_PARAMETER on * failure. * * @param pcszAddr The value to convert. * @param ppszNext Where to store the pointer to the first char * following the address. (Optional) * @param pAddr Where to store the result. */ RTDECL(int) RTNetStrToIPv6AddrEx(const char *pcszAddr, PRTNETADDRIPV6 pAddr, char **ppszNext); /** * Parses IPv6 address into RTNETADDRIPV6 representation. * Leading and trailing whitespace is ignored. * * @returns VINF_SUCCESS on success, VERR_INVALID_PARAMETER on * failure. * * @param pcszAddr The value to convert. * @param ppszZone Where to store the pointer to the first char * of the zone id. NULL is stored if there is * no zone id. * @param pAddr Where to store the result. */ RTDECL(int) RTNetStrToIPv6Addr(const char *pcszAddr, PRTNETADDRIPV6 pAddr, char **ppszZone); /** * Verifies that RTNETADDRIPV6 is a valid contiguous netmask and * computes its prefix length. * * @returns VINF_SUCCESS on success, VERR_INVALID_PARAMETER on * failure. * * @param pMask The netmask to verify and convert. * @param piPrefix Where to store the prefix length. (Optional) */ RTDECL(int) RTNetMaskToPrefixIPv6(PCRTNETADDRIPV6 pMask, int *piPrefix); /** * Computes netmask corresponding to the prefix length. * * @returns VINF_SUCCESS on success, VERR_INVALID_PARAMETER on * failure. * * @param iPrefix The prefix to convert. * @param pMask Where to store the netmask. */ RTDECL(int) RTNetPrefixToMaskIPv6(int iPrefix, PRTNETADDRIPV6 pMask); /** * Parses IPv6 prefix notation into RTNETADDRIPV6 representation and * prefix length. Missing prefix specification is treated as exact * address specification (prefix length 128). Leading and trailing * whitespace is ignored. * * "CIDR" in the name is a misnomer as IPv6 doesn't have network * classes, but is parallel to the IPv4 name (and naming things is * hard). * * @returns VINF_SUCCESS on success, VERR_INVALID_PARAMETER on * failure. * * @param pcszAddr The value to convert. * @param pAddr Where to store the address. * @param piPrefix Where to store the prefix length; */ RTDECL(int) RTNetStrToIPv6Cidr(const char *pcszAddr, PRTNETADDRIPV6 pAddr, int *piPrefix); /** * IPX address. */ #pragma pack(1) typedef struct RTNETADDRIPX { /** The network ID. */ uint32_t Network; /** The node ID. (Defaults to the MAC address apparently.) */ RTMAC Node; } RTNETADDRIPX; #pragma pack() AssertCompileSize(RTNETADDRIPX, 4+6); /** Pointer to an IPX address. */ typedef RTNETADDRIPX *PRTNETADDRIPX; /** Pointer to a const IPX address. */ typedef RTNETADDRIPX const *PCRTNETADDRIPX; /** * Network address union. * * @remarks The size of this structure may change in the future. */ typedef union RTNETADDRU { /** 64-bit view. */ uint64_t au64[2]; /** 32-bit view. */ uint32_t au32[4]; /** 16-bit view. */ uint16_t au16[8]; /** 8-bit view. */ uint8_t au8[16]; /** IPv4 view. */ RTNETADDRIPV4 IPv4; #ifndef IPv6 /* Work around X11 and RDP defining IPv6 to 1. */ /** IPv6 view. */ RTNETADDRIPV6 IPv6; #endif /** IPX view. */ RTNETADDRIPX Ipx; /** MAC address view. */ RTMAC Mac; } RTNETADDRU; AssertCompileSize(RTNETADDRU, 16); /** Pointer to an address union. */ typedef RTNETADDRU *PRTNETADDRU; /** Pointer to a const address union. */ typedef RTNETADDRU const *PCRTNETADDRU; /** * Network address type. * * @remarks The value assignments may change in the future. */ typedef enum RTNETADDRTYPE { /** The invalid 0 entry. */ RTNETADDRTYPE_INVALID = 0, /** IP version 4. */ RTNETADDRTYPE_IPV4, /** IP version 6. */ RTNETADDRTYPE_IPV6, /** IPX. */ RTNETADDRTYPE_IPX, /** MAC address. */ RTNETADDRTYPE_MAC, /** The end of the valid values. */ RTNETADDRTYPE_END, /** The usual 32-bit hack. */ RTNETADDRTYPE_32_BIT_HACK = 0x7fffffff } RTNETADDRTYPE; /** Pointer to a network address type. */ typedef RTNETADDRTYPE *PRTNETADDRTYPE; /** Pointer to a const network address type. */ typedef RTNETADDRTYPE const *PCRTNETADDRTYPE; /** * Network address. * * @remarks The size and type values may change. */ typedef struct RTNETADDR { /** The address union. */ RTNETADDRU uAddr; /** Indicates which view of @a u that is valid. */ RTNETADDRTYPE enmType; /** The port number for IPv4 and IPv6 addresses. This is set to * RTNETADDR_NA_PORT if not applicable. */ uint32_t uPort; } RTNETADDR; /** Pointer to a network address. */ typedef RTNETADDR *PRTNETADDR; /** Pointer to a const network address. */ typedef RTNETADDR const *PCRTNETADDR; /** The not applicable value of RTNETADDR::uPort value use to inid. */ #define RTNETADDR_PORT_NA UINT32_MAX /** * Ethernet header. */ #pragma pack(1) typedef struct RTNETETHERHDR { RTMAC DstMac; RTMAC SrcMac; /** Ethernet frame type or frame size, depending on the kind of ethernet. * This is big endian on the wire. */ uint16_t EtherType; } RTNETETHERHDR; #pragma pack() AssertCompileSize(RTNETETHERHDR, 14); /** Pointer to an ethernet header. */ typedef RTNETETHERHDR *PRTNETETHERHDR; /** Pointer to a const ethernet header. */ typedef RTNETETHERHDR const *PCRTNETETHERHDR; /** @name EtherType (RTNETETHERHDR::EtherType) * @{ */ #define RTNET_ETHERTYPE_IPV4 UINT16_C(0x0800) #define RTNET_ETHERTYPE_ARP UINT16_C(0x0806) #define RTNET_ETHERTYPE_IPV6 UINT16_C(0x86dd) #define RTNET_ETHERTYPE_VLAN UINT16_C(0x8100) #define RTNET_ETHERTYPE_IPX_1 UINT16_C(0x8037) #define RTNET_ETHERTYPE_IPX_2 UINT16_C(0x8137) #define RTNET_ETHERTYPE_IPX_3 UINT16_C(0x8138) /** @} */ /** * IPv4 header. * All is bigendian on the wire. */ #pragma pack(1) typedef struct RTNETIPV4 { #ifdef RT_BIG_ENDIAN unsigned int ip_v : 4; unsigned int ip_hl : 4; unsigned int ip_tos : 8; unsigned int ip_len : 16; #else /** 00:0 - Header length given as a 32-bit word count. */ unsigned int ip_hl : 4; /** 00:4 - Header version. */ unsigned int ip_v : 4; /** 01 - Type of service. */ unsigned int ip_tos : 8; /** 02 - Total length (header + data). */ unsigned int ip_len : 16; #endif /** 04 - Packet idenficiation. */ uint16_t ip_id; /** 06 - Offset if fragmented. */ uint16_t ip_off; /** 08 - Time to live. */ uint8_t ip_ttl; /** 09 - Protocol. */ uint8_t ip_p; /** 0a - Header check sum. */ uint16_t ip_sum; /** 0c - Source address. */ RTNETADDRIPV4 ip_src; /** 10 - Destination address. */ RTNETADDRIPV4 ip_dst; /** 14 - Options (optional). */ uint32_t ip_options[1]; } RTNETIPV4; #pragma pack() AssertCompileSize(RTNETIPV4, 6 * 4); /** Pointer to a IPv4 header. */ typedef RTNETIPV4 *PRTNETIPV4; /** Pointer to a const IPv4 header. */ typedef RTNETIPV4 const *PCRTNETIPV4; /** The minimum IPv4 header length (in bytes). * Up to and including RTNETIPV4::ip_dst. */ #define RTNETIPV4_MIN_LEN (20) /** @name IPv4 Protocol Numbers * @{ */ /** IPv4: ICMP */ #define RTNETIPV4_PROT_ICMP (1) /** IPv4: TCP */ #define RTNETIPV4_PROT_TCP (6) /** IPv4: UDP */ #define RTNETIPV4_PROT_UDP (17) /** @} */ /** @name Common IPv4 Port Assignments * @{ */ /** Boostrap Protocol / DHCP) Server. */ #define RTNETIPV4_PORT_BOOTPS (67) /** Boostrap Protocol / DHCP) Client. */ #define RTNETIPV4_PORT_BOOTPC (68) /** @} */ /** @name IPv4 Flags * @{ */ /** IPv4: Don't fragment */ #define RTNETIPV4_FLAGS_DF (0x4000) /** IPv4: More fragments */ #define RTNETIPV4_FLAGS_MF (0x2000) /** @} */ RTDECL(uint16_t) RTNetIPv4HdrChecksum(PCRTNETIPV4 pIpHdr); RTDECL(bool) RTNetIPv4IsHdrValid(PCRTNETIPV4 pIpHdr, size_t cbHdrMax, size_t cbPktMax, bool fChecksum); RTDECL(uint32_t) RTNetIPv4PseudoChecksum(PCRTNETIPV4 pIpHdr); RTDECL(uint32_t) RTNetIPv4PseudoChecksumBits(RTNETADDRIPV4 SrcAddr, RTNETADDRIPV4 DstAddr, uint8_t bProtocol, uint16_t cbPkt); RTDECL(uint32_t) RTNetIPv4AddDataChecksum(void const *pvData, size_t cbData, uint32_t u32Sum, bool *pfOdd); RTDECL(uint16_t) RTNetIPv4FinalizeChecksum(uint32_t u32Sum); /** * IPv6 header. * All is bigendian on the wire. */ #pragma pack(1) typedef struct RTNETIPV6 { /** Version (4 bits), Traffic Class (8 bits) and Flow Lable (20 bits). * @todo this is probably mislabeled - ip6_flow vs. ip6_vfc, fix later. */ uint32_t ip6_vfc; /** 04 - Payload length, including extension headers. */ uint16_t ip6_plen; /** 06 - Next header type (RTNETIPV4_PROT_XXX). */ uint8_t ip6_nxt; /** 07 - Hop limit. */ uint8_t ip6_hlim; /** xx - Source address. */ RTNETADDRIPV6 ip6_src; /** xx - Destination address. */ RTNETADDRIPV6 ip6_dst; } RTNETIPV6; #pragma pack() AssertCompileSize(RTNETIPV6, 8 + 16 + 16); /** Pointer to a IPv6 header. */ typedef RTNETIPV6 *PRTNETIPV6; /** Pointer to a const IPv6 header. */ typedef RTNETIPV6 const *PCRTNETIPV6; /** The minimum IPv6 header length (in bytes). * Up to and including RTNETIPV6::ip6_dst. */ #define RTNETIPV6_MIN_LEN (40) #define RTNETIPV6_ICMPV6_ND_WITH_LLA_OPT_MIN_LEN (32) RTDECL(uint32_t) RTNetIPv6PseudoChecksum(PCRTNETIPV6 pIpHdr); RTDECL(uint32_t) RTNetIPv6PseudoChecksumEx(PCRTNETIPV6 pIpHdr, uint8_t bProtocol, uint16_t cbPkt); RTDECL(uint32_t) RTNetIPv6PseudoChecksumBits(PCRTNETADDRIPV6 pSrcAddr, PCRTNETADDRIPV6 pDstAddr, uint8_t bProtocol, uint16_t cbPkt); /** * UDP header. */ #pragma pack(1) typedef struct RTNETUDP { /** The source port. */ uint16_t uh_sport; /** The destination port. */ uint16_t uh_dport; /** The length of the UDP header and associated data. */ uint16_t uh_ulen; /** The checksum of the pseudo header, the UDP header and the data. */ uint16_t uh_sum; } RTNETUDP; #pragma pack() AssertCompileSize(RTNETUDP, 8); /** Pointer to an UDP header. */ typedef RTNETUDP *PRTNETUDP; /** Pointer to a const UDP header. */ typedef RTNETUDP const *PCRTNETUDP; /** The minimum UDP packet length (in bytes). (RTNETUDP::uh_ulen) */ #define RTNETUDP_MIN_LEN (8) RTDECL(uint16_t) RTNetUDPChecksum(uint32_t u32Sum, PCRTNETUDP pUdpHdr); RTDECL(uint32_t) RTNetIPv4AddUDPChecksum(PCRTNETUDP pUdpHdr, uint32_t u32Sum); RTDECL(uint16_t) RTNetIPv4UDPChecksum(PCRTNETIPV4 pIpHdr, PCRTNETUDP pUdpHdr, void const *pvData); RTDECL(bool) RTNetIPv4IsUDPSizeValid(PCRTNETIPV4 pIpHdr, PCRTNETUDP pUdpHdr, size_t cbPktMax); RTDECL(bool) RTNetIPv4IsUDPValid(PCRTNETIPV4 pIpHdr, PCRTNETUDP pUdpHdr, void const *pvData, size_t cbPktMax, bool fChecksum); /** * IPv4 BOOTP / DHCP packet. */ #pragma pack(1) typedef struct RTNETBOOTP { /** 00 - The packet opcode (RTNETBOOTP_OP_*). */ uint8_t bp_op; /** 01 - Hardware address type. Same as RTNETARPHDR::ar_htype. */ uint8_t bp_htype; /** 02 - Hardware address length. */ uint8_t bp_hlen; /** 03 - Gateway hops. */ uint8_t bp_hops; /** 04 - Transaction ID. */ uint32_t bp_xid; /** 08 - Seconds since boot started. */ uint16_t bp_secs; /** 0a - Unused (BOOTP) / Flags (DHCP) (RTNET_DHCP_FLAGS_*). */ uint16_t bp_flags; /** 0c - Client IPv4 address. */ RTNETADDRIPV4 bp_ciaddr; /** 10 - Your IPv4 address. */ RTNETADDRIPV4 bp_yiaddr; /** 14 - Server IPv4 address. */ RTNETADDRIPV4 bp_siaddr; /** 18 - Gateway IPv4 address. */ RTNETADDRIPV4 bp_giaddr; /** 1c - Client hardware address. */ union { uint8_t au8[16]; RTMAC Mac; } bp_chaddr; /** 2c - Server name. */ uint8_t bp_sname[64]; /** 6c - File name / more DHCP options. */ uint8_t bp_file[128]; /** ec - Vendor specific area (BOOTP) / Options (DHCP). * @remark This is really 312 bytes in the DHCP version. */ union { uint8_t au8[128]; struct DHCP { /** ec - The DHCP cookie (RTNET_DHCP_COOKIE). */ uint32_t dhcp_cookie; /** f0 - The DHCP options. */ uint8_t dhcp_opts[124]; } Dhcp; } bp_vend; } RTNETBOOTP; #pragma pack() AssertCompileSize(RTNETBOOTP, 0xec + 128); /** Pointer to a BOOTP / DHCP packet. */ typedef RTNETBOOTP *PRTNETBOOTP; /** Pointer to a const BOOTP / DHCP packet. */ typedef RTNETBOOTP const *PCRTNETBOOTP; /** Minimum BOOTP packet length. For quick validation, no standard thing really. */ #define RTNETBOOTP_MIN_LEN 0xec /** Minimum DHCP packet length. For quick validation, no standard thing really. */ #define RTNETBOOTP_DHCP_MIN_LEN 0xf1 /** The normal size of the a DHCP packet (i.e. a RTNETBOOTP). * Same as RTNET_DHCP_OPT_SIZE, just expressed differently. */ #define RTNET_DHCP_NORMAL_SIZE (0xec + 4 + RTNET_DHCP_OPT_SIZE) /** The normal size of RTNETBOOTP::bp_vend::Dhcp::dhcp_opts. */ #define RTNET_DHCP_OPT_SIZE (312 - 4) /** @name BOOTP packet opcode values * @{ */ #define RTNETBOOTP_OP_REQUEST 1 #define RTNETBOOTP_OP_REPLY 2 /** @} */ /** @name DHCP flags (RTNETBOOTP::bp_flags) * @{ */ #define RTNET_DHCP_FLAGS_NO_BROADCAST UINT16_C(0x8000) /** @todo check test!!! */ /** @} */ /** The DHCP cookie (network endian). */ #define RTNET_DHCP_COOKIE UINT32_C(0x63825363) /** * An IPv4 DHCP option header. */ typedef struct RTNETDHCPOPT { /** 00 - The DHCP option. */ uint8_t dhcp_opt; /** 01 - The data length (excluding this header). */ uint8_t dhcp_len; /* 02 - The option data follows here, optional and of variable length. */ } RTNETDHCPOPT; AssertCompileSize(RTNETDHCPOPT, 2); /** Pointer to a DHCP option header. */ typedef RTNETDHCPOPT *PRTNETDHCPOPT; /** Pointer to a const DHCP option header. */ typedef RTNETDHCPOPT const *PCRTNETDHCPOPT; /** @name DHCP options * @{ */ /** 1 byte padding, this has no dhcp_len field. */ #define RTNET_DHCP_OPT_PAD 0 /** The subnet mask. */ #define RTNET_DHCP_OPT_SUBNET_MASK 1 /** The time offset. */ #define RTNET_DHCP_OPT_TIME_OFFSET 2 /** The routers for the subnet. */ #define RTNET_DHCP_OPT_ROUTERS 3 /** Domain Name Server. */ #define RTNET_DHCP_OPT_DNS 6 /** Host name. */ #define RTNET_DHCP_OPT_HOST_NAME 12 /** Domain name. */ #define RTNET_DHCP_OPT_DOMAIN_NAME 15 /** The requested address. */ #define RTNET_DHCP_OPT_REQ_ADDR 50 /** The lease time in seconds. */ #define RTNET_DHCP_OPT_LEASE_TIME 51 /** Option overload. * Indicates that the bp_file and/or bp_sname holds contains DHCP options. */ #define RTNET_DHCP_OPT_OPTION_OVERLOAD 52 /** Have a 8-bit message type value as data, see RTNET_DHCP_MT_*. */ #define RTNET_DHCP_OPT_MSG_TYPE 53 /** Server ID. */ #define RTNET_DHCP_OPT_SERVER_ID 54 /** Parameter request list. */ #define RTNET_DHCP_OPT_PARAM_REQ_LIST 55 /** The maximum DHCP message size a client is willing to accept. */ #define RTNET_DHCP_OPT_MAX_DHCP_MSG_SIZE 57 /** Client ID. */ #define RTNET_DHCP_OPT_CLIENT_ID 61 /** TFTP server name. */ #define RTNET_DHCP_OPT_TFTP_SERVER_NAME 66 /** Bootfile name. */ #define RTNET_DHCP_OPT_BOOTFILE_NAME 67 /** Marks the end of the DHCP options, this has no dhcp_len field. */ #define RTNET_DHCP_OPT_END 255 /** @} */ /** @name DHCP Option overload flags (option 52) * @{ */ #define RTNET_DHCP_OPTION_OVERLOAD_FILE 1 #define RTNET_DHCP_OPTION_OVERLOAD_SNAME 2 #define RTNET_DHCP_OPTION_OVERLOAD_MASK 3 /** @} */ /** @name DHCP Message Types (option 53) * @{ */ #define RTNET_DHCP_MT_DISCOVER 1 #define RTNET_DHCP_MT_OFFER 2 #define RTNET_DHCP_MT_REQUEST 3 #define RTNET_DHCP_MT_DECLINE 4 #define RTNET_DHCP_MT_ACK 5 #define RTNET_DHCP_MT_NAC 6 #define RTNET_DHCP_MT_RELEASE 7 #define RTNET_DHCP_MT_INFORM 8 /** @} */ /** @name DHCP Flags * @{ */ #define RTNET_DHCP_FLAG_BROADCAST 0x8000 /** @} */ RTDECL(bool) RTNetIPv4IsDHCPValid(PCRTNETUDP pUdpHdr, PCRTNETBOOTP pDhcp, size_t cbDhcp, uint8_t *pMsgType); /** * IPv4 DHCP packet. * @deprecated Use RTNETBOOTP. */ #pragma pack(1) typedef struct RTNETDHCP { /** 00 - The packet opcode. */ uint8_t Op; /** Hardware address type. */ uint8_t HType; /** Hardware address length. */ uint8_t HLen; uint8_t Hops; uint32_t XID; uint16_t Secs; uint16_t Flags; /** Client IPv4 address. */ RTNETADDRIPV4 CIAddr; /** Your IPv4 address. */ RTNETADDRIPV4 YIAddr; /** Server IPv4 address. */ RTNETADDRIPV4 SIAddr; /** Gateway IPv4 address. */ RTNETADDRIPV4 GIAddr; /** Client hardware address. */ uint8_t CHAddr[16]; /** Server name. */ uint8_t SName[64]; uint8_t File[128]; uint8_t abMagic[4]; uint8_t DhcpOpt; uint8_t DhcpLen; /* 1 */ uint8_t DhcpReq; uint8_t abOptions[57]; } RTNETDHCP; #pragma pack() /** @todo AssertCompileSize(RTNETDHCP, ); */ /** Pointer to a DHCP packet. */ typedef RTNETDHCP *PRTNETDHCP; /** Pointer to a const DHCP packet. */ typedef RTNETDHCP const *PCRTNETDHCP; /** * TCP packet. */ #pragma pack(1) typedef struct RTNETTCP { /** 00 - The source port. */ uint16_t th_sport; /** 02 - The destination port. */ uint16_t th_dport; /** 04 - The sequence number. */ uint32_t th_seq; /** 08 - The acknowledgement number. */ uint32_t th_ack; #ifdef RT_BIG_ENDIAN unsigned int th_win : 16; unsigned int th_flags : 8; unsigned int th_off : 4; unsigned int th_x2 : 4; #else /** 0c:0 - Reserved. */ unsigned int th_x2 : 4; /** 0c:4 - The data offset given as a dword count from the start of this header. */ unsigned int th_off : 4; /** 0d - flags. */ unsigned int th_flags : 8; /** 0e - The window. */ unsigned int th_win : 16; #endif /** 10 - The checksum of the pseudo header, the TCP header and the data. */ uint16_t th_sum; /** 12 - The urgent pointer. */ uint16_t th_urp; /* (options follows here and then the data (aka text).) */ } RTNETTCP; #pragma pack() AssertCompileSize(RTNETTCP, 20); /** Pointer to a TCP packet. */ typedef RTNETTCP *PRTNETTCP; /** Pointer to a const TCP packet. */ typedef RTNETTCP const *PCRTNETTCP; /** The minimum TCP header length (in bytes). (RTNETTCP::th_off * 4) */ #define RTNETTCP_MIN_LEN (20) /** @name TCP flags (RTNETTCP::th_flags) * @{ */ #define RTNETTCP_F_FIN 0x01 #define RTNETTCP_F_SYN 0x02 #define RTNETTCP_F_RST 0x04 #define RTNETTCP_F_PSH 0x08 #define RTNETTCP_F_ACK 0x10 #define RTNETTCP_F_URG 0x20 #define RTNETTCP_F_ECE 0x40 #define RTNETTCP_F_CWR 0x80 /** @} */ RTDECL(uint16_t) RTNetTCPChecksum(uint32_t u32Sum, PCRTNETTCP pTcpHdr, void const *pvData, size_t cbData); RTDECL(uint32_t) RTNetIPv4AddTCPChecksum(PCRTNETTCP pTcpHdr, uint32_t u32Sum); RTDECL(uint16_t) RTNetIPv4TCPChecksum(PCRTNETIPV4 pIpHdr, PCRTNETTCP pTcpHdr, void const *pvData); RTDECL(bool) RTNetIPv4IsTCPSizeValid(PCRTNETIPV4 pIpHdr, PCRTNETTCP pTcpHdr, size_t cbHdrMax, size_t cbPktMax); RTDECL(bool) RTNetIPv4IsTCPValid(PCRTNETIPV4 pIpHdr, PCRTNETTCP pTcpHdr, size_t cbHdrMax, void const *pvData, size_t cbPktMax, bool fChecksum); /** * IPv4 ICMP packet header. */ #pragma pack(1) typedef struct RTNETICMPV4HDR { /** 00 - The ICMP message type. */ uint8_t icmp_type; /** 01 - Type specific code that further qualifies the message. */ uint8_t icmp_code; /** 02 - Checksum of the ICMP message. */ uint16_t icmp_cksum; } RTNETICMPV4HDR; #pragma pack() AssertCompileSize(RTNETICMPV4HDR, 4); /** Pointer to an ICMP packet header. */ typedef RTNETICMPV4HDR *PRTNETICMPV4HDR; /** Pointer to a const ICMP packet header. */ typedef RTNETICMPV4HDR const *PCRTNETICMPV4HDR; /** @name ICMP (v4) message types. * @{ */ #define RTNETICMPV4_TYPE_ECHO_REPLY 0 #define RTNETICMPV4_TYPE_ECHO_REQUEST 8 #define RTNETICMPV4_TYPE_TRACEROUTE 30 /** @} */ /** * IPv4 ICMP ECHO Reply & Request packet. */ #pragma pack(1) typedef struct RTNETICMPV4ECHO { /** 00 - The ICMP header. */ RTNETICMPV4HDR Hdr; /** 04 - The identifier to help the requestor match up the reply. * Can be 0. Typically fixed value. */ uint16_t icmp_id; /** 06 - The sequence number to help the requestor match up the reply. * Can be 0. Typically incrementing between requests. */ uint16_t icmp_seq; /** 08 - Variable length data that is to be returned unmodified in the reply. */ uint8_t icmp_data[1]; } RTNETICMPV4ECHO; #pragma pack() AssertCompileSize(RTNETICMPV4ECHO, 9); /** Pointer to an ICMP ECHO packet. */ typedef RTNETICMPV4ECHO *PRTNETICMPV4ECHO; /** Pointer to a const ICMP ECHO packet. */ typedef RTNETICMPV4ECHO const *PCRTNETICMPV4ECHO; /** * IPv4 ICMP TRACEROUTE packet. * This is an reply to an IP packet with the traceroute option set. */ #pragma pack(1) typedef struct RTNETICMPV4TRACEROUTE { /** 00 - The ICMP header. */ RTNETICMPV4HDR Hdr; /** 04 - Identifier copied from the traceroute option's ID number. */ uint16_t icmp_id; /** 06 - Unused. (Possibly an icmp_seq?) */ uint16_t icmp_void; /** 08 - Outbound hop count. From the IP packet causing this message. */ uint16_t icmp_ohc; /** 0a - Return hop count. From the IP packet causing this message. */ uint16_t icmp_rhc; /** 0c - Output link speed, 0 if not known. */ uint32_t icmp_speed; /** 10 - Output link MTU, 0 if not known. */ uint32_t icmp_mtu; } RTNETICMPV4TRACEROUTE; #pragma pack() AssertCompileSize(RTNETICMPV4TRACEROUTE, 20); /** Pointer to an ICMP TRACEROUTE packet. */ typedef RTNETICMPV4TRACEROUTE *PRTNETICMPV4TRACEROUTE; /** Pointer to a const ICMP TRACEROUTE packet. */ typedef RTNETICMPV4TRACEROUTE const *PCRTNETICMPV4TRACEROUTE; /** @todo add more ICMPv4 as needed. */ /** * IPv4 ICMP union packet. */ typedef union RTNETICMPV4 { RTNETICMPV4HDR Hdr; RTNETICMPV4ECHO Echo; RTNETICMPV4TRACEROUTE Traceroute; } RTNETICMPV4; /** Pointer to an ICMP union packet. */ typedef RTNETICMPV4 *PRTNETICMPV4; /** Pointer to a const ICMP union packet. */ typedef RTNETICMPV4 const *PCRTNETICMPV4; /** * IPv6 ICMP packet header. */ #pragma pack(1) typedef struct RTNETICMPV6HDR { /** 00 - The ICMPv6 message type. */ uint8_t icmp6_type; /** 01 - Type specific code that further qualifies the message. */ uint8_t icmp6_code; /** 02 - Checksum of the ICMPv6 message. */ uint16_t icmp6_cksum; } RTNETICMPV6HDR; #pragma pack() AssertCompileSize(RTNETICMPV6HDR, 4); /** Pointer to an ICMPv6 packet header. */ typedef RTNETICMPV6HDR *PRTNETICMPV6HDR; /** Pointer to a const ICMP packet header. */ typedef RTNETICMPV6HDR const *PCRTNETICMPV6HDR; #define RTNETIPV6_PROT_ICMPV6 (58) /** @name Internet Control Message Protocol version 6 (ICMPv6) message types. * @{ */ #define RTNETIPV6_ICMP_TYPE_RS 133 #define RTNETIPV6_ICMP_TYPE_RA 134 #define RTNETIPV6_ICMP_TYPE_NS 135 #define RTNETIPV6_ICMP_TYPE_NA 136 #define RTNETIPV6_ICMP_TYPE_RDR 137 /** @} */ /** @name Neighbor Discovery option types * @{ */ #define RTNETIPV6_ICMP_ND_SLLA_OPT (1) #define RTNETIPV6_ICMP_ND_TLLA_OPT (2) /** @} */ /** ICMPv6 ND Source/Target Link Layer Address option */ #pragma pack(1) typedef struct RTNETNDP_LLA_OPT { uint8_t type; uint8_t len; RTMAC lla; } RTNETNDP_LLA_OPT; #pragma pack() AssertCompileSize(RTNETNDP_LLA_OPT, 1+1+6); typedef RTNETNDP_LLA_OPT *PRTNETNDP_LLA_OPT; typedef RTNETNDP_LLA_OPT const *PCRTNETNDP_LLA_OPT; /** ICMPv6 ND Neighbor Sollicitation */ #pragma pack(1) typedef struct RTNETNDP { /** 00 - The ICMPv6 header. */ RTNETICMPV6HDR Hdr; /** 04 - reserved */ uint32_t reserved; /** 08 - target address */ RTNETADDRIPV6 target_address; } RTNETNDP; #pragma pack() AssertCompileSize(RTNETNDP, 4+4+16); /** Pointer to a NDP ND packet. */ typedef RTNETNDP *PRTNETNDP; /** Pointer to a const NDP NS packet. */ typedef RTNETNDP const *PCRTNETNDP; /** * Ethernet ARP header. */ #pragma pack(1) typedef struct RTNETARPHDR { /** The hardware type. */ uint16_t ar_htype; /** The protocol type (ethertype). */ uint16_t ar_ptype; /** The hardware address length. */ uint8_t ar_hlen; /** The protocol address length. */ uint8_t ar_plen; /** The operation. */ uint16_t ar_oper; } RTNETARPHDR; #pragma pack() AssertCompileSize(RTNETARPHDR, 8); /** Pointer to an ethernet ARP header. */ typedef RTNETARPHDR *PRTNETARPHDR; /** Pointer to a const ethernet ARP header. */ typedef RTNETARPHDR const *PCRTNETARPHDR; /** ARP hardware type - ethernet. */ #define RTNET_ARP_ETHER UINT16_C(1) /** @name ARP operations * @{ */ #define RTNET_ARPOP_REQUEST UINT16_C(1) /**< Request hardware address given a protocol address (ARP). */ #define RTNET_ARPOP_REPLY UINT16_C(2) #define RTNET_ARPOP_REVREQUEST UINT16_C(3) /**< Request protocol address given a hardware address (RARP). */ #define RTNET_ARPOP_REVREPLY UINT16_C(4) #define RTNET_ARPOP_INVREQUEST UINT16_C(8) /**< Inverse ARP. */ #define RTNET_ARPOP_INVREPLY UINT16_C(9) /** Check if an ARP operation is a request or not. */ #define RTNET_ARPOP_IS_REQUEST(Op) ((Op) & 1) /** Check if an ARP operation is a reply or not. */ #define RTNET_ARPOP_IS_REPLY(Op) (!RTNET_ARPOP_IS_REQUEST(Op)) /** @} */ /** * Ethernet IPv4 + 6-byte MAC ARP request packet. */ #pragma pack(1) typedef struct RTNETARPIPV4 { /** ARP header. */ RTNETARPHDR Hdr; /** The sender hardware address. */ RTMAC ar_sha; /** The sender protocol address. */ RTNETADDRIPV4 ar_spa; /** The target hardware address. */ RTMAC ar_tha; /** The target protocol address. */ RTNETADDRIPV4 ar_tpa; } RTNETARPIPV4; #pragma pack() AssertCompileSize(RTNETARPIPV4, 8+6+4+6+4); /** Pointer to an ethernet IPv4+MAC ARP request packet. */ typedef RTNETARPIPV4 *PRTNETARPIPV4; /** Pointer to a const ethernet IPv4+MAC ARP request packet. */ typedef RTNETARPIPV4 const *PCRTNETARPIPV4; /** @} */ RT_C_DECLS_END #endif /* !IPRT_INCLUDED_net_h */