/* This file is part of GNUnet. Copyright (C) 2010-2013 Christian Grothoff GNUnet is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. GNUnet 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 Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see . SPDX-License-Identifier: AGPL3.0-or-later */ /** * @author Philipp Toelke * @author Christian Grothoff * * @file * Standard TCP/IP network structs and IP checksum calculations for TUN * interaction * * @defgroup tun TUN library * Standard TCP/IP network structs and IP checksum calculations for TUN * interaction * @{ */ #ifndef GNUNET_TUN_LIB_H #define GNUNET_TUN_LIB_H #include "gnunet_common.h" #include "gnunet_crypto_lib.h" /* see http://www.iana.org/assignments/ethernet-numbers */ #ifndef ETH_P_IPV4 /** * Number for IPv4 */ #define ETH_P_IPV4 0x0800 #endif #ifndef ETH_P_IPV6 /** * Number for IPv6 */ #define ETH_P_IPV6 0x86DD #endif /** * Maximum regex string length for use with #GNUNET_TUN_ipv4toregexsearch. * * 8 bytes for IPv4, 4 bytes for port, 1 byte for "4", 2 bytes for "-", * one byte for 0-termination. */ #define GNUNET_TUN_IPV4_REGEXLEN 16 /** * Maximum regex string length for use with #GNUNET_TUN_ipv6toregexsearch * * 32 bytes for IPv4, 4 bytes for port, 1 byte for "4", 2 bytes for "-", * one byte for 0-termination. */ #define GNUNET_TUN_IPV6_REGEXLEN 40 GNUNET_NETWORK_STRUCT_BEGIN /** * Header from Linux TUN interface. */ struct GNUNET_TUN_Layer2PacketHeader { /** * Some flags (unused). */ uint16_t flags GNUNET_PACKED; /** * Here we get an ETH_P_-number. */ uint16_t proto GNUNET_PACKED; }; /** * Standard IPv4 header. */ struct GNUNET_TUN_IPv4Header { #if __BYTE_ORDER == __LITTLE_ENDIAN unsigned int header_length : 4 GNUNET_PACKED; unsigned int version : 4 GNUNET_PACKED; #elif __BYTE_ORDER == __BIG_ENDIAN unsigned int version : 4 GNUNET_PACKED; unsigned int header_length : 4 GNUNET_PACKED; #else #error byteorder undefined #endif uint8_t diff_serv; /** * Length of the packet, including this header. */ uint16_t total_length GNUNET_PACKED; /** * Unique random ID for matching up fragments. */ uint16_t identification GNUNET_PACKED; unsigned int flags : 3 GNUNET_PACKED; unsigned int fragmentation_offset : 13 GNUNET_PACKED; /** * How many more hops can this packet be forwarded? */ uint8_t ttl; /** * L4-protocol, for example, IPPROTO_UDP or IPPROTO_TCP. */ uint8_t protocol; /** * Checksum. */ uint16_t checksum GNUNET_PACKED; /** * Origin of the packet. */ struct in_addr source_address; /** * Destination of the packet. */ struct in_addr destination_address; } GNUNET_GCC_STRUCT_LAYOUT; /** * Standard IPv6 header. */ struct GNUNET_TUN_IPv6Header { #if __BYTE_ORDER == __LITTLE_ENDIAN unsigned int traffic_class_h : 4 GNUNET_PACKED; unsigned int version : 4 GNUNET_PACKED; unsigned int traffic_class_l : 4 GNUNET_PACKED; unsigned int flow_label : 20 GNUNET_PACKED; #elif __BYTE_ORDER == __BIG_ENDIAN unsigned int version : 4 GNUNET_PACKED; unsigned int traffic_class : 8 GNUNET_PACKED; unsigned int flow_label : 20 GNUNET_PACKED; #else #error byteorder undefined #endif /** * Length of the payload, excluding this header. */ uint16_t payload_length GNUNET_PACKED; /** * For example, IPPROTO_UDP or IPPROTO_TCP. */ uint8_t next_header; /** * How many more hops can this packet be forwarded? */ uint8_t hop_limit; /** * Origin of the packet. */ struct in6_addr source_address GNUNET_PACKED; /** * Destination of the packet. */ struct in6_addr destination_address GNUNET_PACKED; } GNUNET_GCC_STRUCT_LAYOUT; /** * TCP flags. */ #define GNUNET_TUN_TCP_FLAGS_FIN 1 #define GNUNET_TUN_TCP_FLAGS_SYN 2 #define GNUNET_TUN_TCP_FLAGS_RST 4 #define GNUNET_TUN_TCP_FLAGS_PSH 8 #define GNUNET_TUN_TCP_FLAGS_ACK 16 #define GNUNET_TUN_TCP_FLAGS_URG 32 #define GNUNET_TUN_TCP_FLAGS_ECE 64 #define GNUNET_TUN_TCP_FLAGS_CWR 128 /** * TCP packet header. */ struct GNUNET_TUN_TcpHeader { /** * Source port (in NBO). */ uint16_t source_port GNUNET_PACKED; /** * Destination port (in NBO). */ uint16_t destination_port GNUNET_PACKED; /** * Sequence number. */ uint32_t seq GNUNET_PACKED; /** * Acknowledgement number. */ uint32_t ack GNUNET_PACKED; #if __BYTE_ORDER == __LITTLE_ENDIAN /** * Reserved. Must be zero. */ unsigned int reserved : 4 GNUNET_PACKED; /** * Number of 32-bit words in TCP header. */ unsigned int off : 4 GNUNET_PACKED; #elif __BYTE_ORDER == __BIG_ENDIAN /** * Number of 32-bit words in TCP header. */ unsigned int off : 4 GNUNET_PACKED; /** * Reserved. Must be zero. */ unsigned int reserved : 4 GNUNET_PACKED; #else #error byteorder undefined #endif /** * Flags (SYN, FIN, ACK, etc.) */ uint8_t flags; /** * Window size. */ uint16_t window_size GNUNET_PACKED; /** * Checksum. */ uint16_t crc GNUNET_PACKED; /** * Urgent pointer. */ uint16_t urgent_pointer GNUNET_PACKED; } GNUNET_GCC_STRUCT_LAYOUT; /** * UDP packet header. */ struct GNUNET_TUN_UdpHeader { /** * Source port (in NBO). */ uint16_t source_port GNUNET_PACKED; /** * Destination port (in NBO). */ uint16_t destination_port GNUNET_PACKED; /** * Number of bytes of payload. */ uint16_t len GNUNET_PACKED; /** * Checksum. */ uint16_t crc GNUNET_PACKED; }; /** * A few common DNS classes (ok, only one is common, but I list a * couple more to make it clear what we're talking about here). */ #define GNUNET_TUN_DNS_CLASS_INTERNET 1 #define GNUNET_TUN_DNS_CLASS_CHAOS 3 #define GNUNET_TUN_DNS_CLASS_HESIOD 4 #define GNUNET_TUN_DNS_OPCODE_QUERY 0 #define GNUNET_TUN_DNS_OPCODE_INVERSE_QUERY 1 #define GNUNET_TUN_DNS_OPCODE_STATUS 2 /** * RFC 1035 codes. */ #define GNUNET_TUN_DNS_RETURN_CODE_NO_ERROR 0 #define GNUNET_TUN_DNS_RETURN_CODE_FORMAT_ERROR 1 #define GNUNET_TUN_DNS_RETURN_CODE_SERVER_FAILURE 2 #define GNUNET_TUN_DNS_RETURN_CODE_NAME_ERROR 3 #define GNUNET_TUN_DNS_RETURN_CODE_NOT_IMPLEMENTED 4 #define GNUNET_TUN_DNS_RETURN_CODE_REFUSED 5 /** * RFC 2136 codes */ #define GNUNET_TUN_DNS_RETURN_CODE_YXDOMAIN 6 #define GNUNET_TUN_DNS_RETURN_CODE_YXRRSET 7 #define GNUNET_TUN_DNS_RETURN_CODE_NXRRSET 8 #define GNUNET_TUN_DNS_RETURN_CODE_NOT_AUTH 9 #define GNUNET_TUN_DNS_RETURN_CODE_NOT_ZONE 10 /** * DNS flags (largely RFC 1035 / RFC 2136). */ struct GNUNET_TUN_DnsFlags { #if __BYTE_ORDER == __LITTLE_ENDIAN /** * Set to 1 if recursion is desired (client -> server) */ unsigned int recursion_desired : 1 GNUNET_PACKED; /** * Set to 1 if message is truncated */ unsigned int message_truncated : 1 GNUNET_PACKED; /** * Set to 1 if this is an authoritative answer */ unsigned int authoritative_answer : 1 GNUNET_PACKED; /** * See GNUNET_TUN_DNS_OPCODE_ defines. */ unsigned int opcode : 4 GNUNET_PACKED; /** * query:0, response:1 */ unsigned int query_or_response : 1 GNUNET_PACKED; /** * See GNUNET_TUN_DNS_RETURN_CODE_ defines. */ unsigned int return_code : 4 GNUNET_PACKED; /** * See RFC 4035. */ unsigned int checking_disabled : 1 GNUNET_PACKED; /** * Response has been cryptographically verified, RFC 4035. */ unsigned int authenticated_data : 1 GNUNET_PACKED; /** * Always zero. */ unsigned int zero : 1 GNUNET_PACKED; /** * Set to 1 if recursion is available (server -> client) */ unsigned int recursion_available : 1 GNUNET_PACKED; #elif __BYTE_ORDER == __BIG_ENDIAN /** * query:0, response:1 */ unsigned int query_or_response : 1 GNUNET_PACKED; /** * See GNUNET_TUN_DNS_OPCODE_ defines. */ unsigned int opcode : 4 GNUNET_PACKED; /** * Set to 1 if this is an authoritative answer */ unsigned int authoritative_answer : 1 GNUNET_PACKED; /** * Set to 1 if message is truncated */ unsigned int message_truncated : 1 GNUNET_PACKED; /** * Set to 1 if recursion is desired (client -> server) */ unsigned int recursion_desired : 1 GNUNET_PACKED; /** * Set to 1 if recursion is available (server -> client) */ unsigned int recursion_available : 1 GNUNET_PACKED; /** * Always zero. */ unsigned int zero : 1 GNUNET_PACKED; /** * Response has been cryptographically verified, RFC 4035. */ unsigned int authenticated_data : 1 GNUNET_PACKED; /** * See RFC 4035. */ unsigned int checking_disabled : 1 GNUNET_PACKED; /** * See GNUNET_TUN_DNS_RETURN_CODE_ defines. */ unsigned int return_code : 4 GNUNET_PACKED; #else #error byteorder undefined #endif } GNUNET_GCC_STRUCT_LAYOUT; /** * DNS header. */ struct GNUNET_TUN_DnsHeader { /** * Unique identifier for the request/response. */ uint16_t id GNUNET_PACKED; /** * Flags. */ struct GNUNET_TUN_DnsFlags flags; /** * Number of queries. */ uint16_t query_count GNUNET_PACKED; /** * Number of answers. */ uint16_t answer_rcount GNUNET_PACKED; /** * Number of authoritative answers. */ uint16_t authority_rcount GNUNET_PACKED; /** * Number of additional records. */ uint16_t additional_rcount GNUNET_PACKED; }; /** * Payload of DNS SOA record (header). */ struct GNUNET_TUN_DnsSoaRecord { /** * The version number of the original copy of the zone. (NBO) */ uint32_t serial GNUNET_PACKED; /** * Time interval before the zone should be refreshed. (NBO) */ uint32_t refresh GNUNET_PACKED; /** * Time interval that should elapse before a failed refresh should * be retried. (NBO) */ uint32_t retry GNUNET_PACKED; /** * Time value that specifies the upper limit on the time interval * that can elapse before the zone is no longer authoritative. (NBO) */ uint32_t expire GNUNET_PACKED; /** * The bit minimum TTL field that should be exported with any RR * from this zone. (NBO) */ uint32_t minimum GNUNET_PACKED; }; /** * Payload of DNS SRV record (header). */ struct GNUNET_TUN_DnsSrvRecord { /** * Preference for this entry (lower value is higher preference). Clients * will contact hosts from the lowest-priority group first and fall back * to higher priorities if the low-priority entries are unavailable. (NBO) */ uint16_t prio GNUNET_PACKED; /** * Relative weight for records with the same priority. Clients will use * the hosts of the same (lowest) priority with a probability proportional * to the weight given. (NBO) */ uint16_t weight GNUNET_PACKED; /** * TCP or UDP port of the service. (NBO) */ uint16_t port GNUNET_PACKED; /* followed by 'target' name */ }; /** * Payload of DNS CERT record. */ struct GNUNET_TUN_DnsCertRecord { /** * Certificate type */ uint16_t cert_type; /** * Certificate KeyTag */ uint16_t cert_tag; /** * Algorithm */ uint8_t algorithm; /* Followed by the certificate */ }; /** * Payload of DNSSEC TLSA record. * http://datatracker.ietf.org/doc/draft-ietf-dane-protocol/ */ struct GNUNET_TUN_DnsTlsaRecord { /** * Certificate usage * 0: CA cert * 1: Entity cert * 2: Trust anchor * 3: domain-issued cert */ uint8_t usage; /** * Selector * What part will be matched against the cert * presented by server * 0: Full cert (in binary) * 1: Full cert (in DER) */ uint8_t selector; /** * Matching type (of selected content) * 0: exact match * 1: SHA-256 hash * 2: SHA-512 hash */ uint8_t matching_type; /** * followed by certificate association data * The "certificate association data" to be matched. * These bytes are either raw data (that is, the full certificate or * its SubjectPublicKeyInfo, depending on the selector) for matching * type 0, or the hash of the raw data for matching types 1 and 2. * The data refers to the certificate in the association, not to the * TLS ASN.1 Certificate object. * * The data is represented as a string of hex chars */ }; /** * Payload of GNS VPN record */ struct GNUNET_TUN_GnsVpnRecord { /** * The peer to contact */ struct GNUNET_PeerIdentity peer; /** * The protocol to use */ uint16_t proto; /* followed by the servicename */ }; /** * DNS query prefix. */ struct GNUNET_TUN_DnsQueryLine { /** * Desired type (GNUNET_DNSPARSER_TYPE_XXX). (NBO) */ uint16_t type GNUNET_PACKED; /** * Desired class (usually GNUNET_TUN_DNS_CLASS_INTERNET). (NBO) */ uint16_t dns_traffic_class GNUNET_PACKED; }; /** * General DNS record prefix. */ struct GNUNET_TUN_DnsRecordLine { /** * Record type (GNUNET_DNSPARSER_TYPE_XXX). (NBO) */ uint16_t type GNUNET_PACKED; /** * Record class (usually GNUNET_TUN_DNS_CLASS_INTERNET). (NBO) */ uint16_t dns_traffic_class GNUNET_PACKED; /** * Expiration for the record (in seconds). (NBO) */ uint32_t ttl GNUNET_PACKED; /** * Number of bytes of data that follow. (NBO) */ uint16_t data_len GNUNET_PACKED; }; #define GNUNET_TUN_ICMPTYPE_ECHO_REPLY 0 #define GNUNET_TUN_ICMPTYPE_DESTINATION_UNREACHABLE 3 #define GNUNET_TUN_ICMPTYPE_SOURCE_QUENCH 4 #define GNUNET_TUN_ICMPTYPE_REDIRECT_MESSAGE 5 #define GNUNET_TUN_ICMPTYPE_ECHO_REQUEST 8 #define GNUNET_TUN_ICMPTYPE_ROUTER_ADVERTISEMENT 9 #define GNUNET_TUN_ICMPTYPE_ROUTER_SOLICITATION 10 #define GNUNET_TUN_ICMPTYPE_TIME_EXCEEDED 11 #define GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE 1 #define GNUNET_TUN_ICMPTYPE6_PACKET_TOO_BIG 2 #define GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED 3 #define GNUNET_TUN_ICMPTYPE6_PARAMETER_PROBLEM 4 #define GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST 128 #define GNUNET_TUN_ICMPTYPE6_ECHO_REPLY 129 /** * ICMP header. */ struct GNUNET_TUN_IcmpHeader { uint8_t type; uint8_t code; uint16_t crc GNUNET_PACKED; union { /** * ICMP Echo (request/reply) */ struct { uint16_t identifier GNUNET_PACKED; uint16_t sequence_number GNUNET_PACKED; } echo; /** * ICMP Destination Unreachable (RFC 1191) */ struct ih_pmtu { uint16_t empty GNUNET_PACKED; uint16_t next_hop_mtu GNUNET_PACKED; /* followed by original IP header + first 8 bytes of original IP datagram */ } destination_unreachable; /** * ICMP Redirect */ struct in_addr redirect_gateway_address; /** * MTU for packets that are too big (IPv6). */ uint32_t packet_too_big_mtu GNUNET_PACKED; } quench; }; GNUNET_NETWORK_STRUCT_END /** * Initialize an IPv4 header. * * @param ip header to initialize * @param protocol protocol to use (i.e. IPPROTO_UDP) * @param payload_length number of bytes of payload that follow (excluding IPv4 * header) * @param src source IP address to use * @param dst destination IP address to use */ void GNUNET_TUN_initialize_ipv4_header (struct GNUNET_TUN_IPv4Header *ip, uint8_t protocol, uint16_t payload_length, const struct in_addr *src, const struct in_addr *dst); /** * Initialize an IPv6 header. * * @param ip header to initialize * @param protocol protocol to use (i.e. IPPROTO_UDP) * @param payload_length number of bytes of payload that follow (excluding IPv4 * header) * @param src source IP address to use * @param dst destination IP address to use */ void GNUNET_TUN_initialize_ipv6_header (struct GNUNET_TUN_IPv6Header *ip, uint8_t protocol, uint16_t payload_length, const struct in6_addr *src, const struct in6_addr *dst); /** * Calculate IPv4 TCP checksum. * * @param ip ipv4 header fully initialized * @param tcp TCP header (initialized except for CRC) * @param payload the TCP payload * @param payload_length number of bytes of TCP @a payload */ void GNUNET_TUN_calculate_tcp4_checksum (const struct GNUNET_TUN_IPv4Header *ip, struct GNUNET_TUN_TcpHeader *tcp, const void *payload, uint16_t payload_length); /** * Calculate IPv6 TCP checksum. * * @param ip ipv6 header fully initialized * @param tcp TCP header (initialized except for CRC) * @param payload the TCP payload * @param payload_length number of bytes of TCP payload */ void GNUNET_TUN_calculate_tcp6_checksum (const struct GNUNET_TUN_IPv6Header *ip, struct GNUNET_TUN_TcpHeader *tcp, const void *payload, uint16_t payload_length); /** * Calculate IPv4 UDP checksum. * * @param ip ipv4 header fully initialized * @param udp UDP header (initialized except for CRC) * @param payload the UDP payload * @param payload_length number of bytes of UDP @a payload */ void GNUNET_TUN_calculate_udp4_checksum (const struct GNUNET_TUN_IPv4Header *ip, struct GNUNET_TUN_UdpHeader *udp, const void *payload, uint16_t payload_length); /** * Calculate IPv6 UDP checksum. * * @param ip ipv6 header fully initialized * @param udp UDP header (initialized except for CRC) * @param payload the UDP payload * @param payload_length number of bytes of @a payload */ void GNUNET_TUN_calculate_udp6_checksum (const struct GNUNET_TUN_IPv6Header *ip, struct GNUNET_TUN_UdpHeader *udp, const void *payload, uint16_t payload_length); /** * Calculate ICMP checksum. * * @param icmp IMCP header (initialized except for CRC) * @param payload the ICMP payload * @param payload_length number of bytes of @a payload */ void GNUNET_TUN_calculate_icmp_checksum (struct GNUNET_TUN_IcmpHeader *icmp, const void *payload, uint16_t payload_length); /** * Create a regex in @a rxstr from the given @a ip and @a port. * * @param ip IPv4 representation. * @param port destination port * @param rxstr generated regex, must be at least #GNUNET_TUN_IPV4_REGEXLEN * bytes long. */ void GNUNET_TUN_ipv4toregexsearch (const struct in_addr *ip, uint16_t port, char *rxstr); /** * Create a regex in @a rxstr from the given @a ipv6 and @a port. * * @param ipv6 IPv6 representation. * @param port destination port * @param rxstr generated regex, must be at least #GNUNET_TUN_IPV6_REGEXLEN * bytes long. */ void GNUNET_TUN_ipv6toregexsearch (const struct in6_addr *ipv6, uint16_t port, char *rxstr); /** * Convert an exit policy to a regular expression. The exit policy * specifies a set of subnets this peer is willing to serve as an * exit for; the resulting regular expression will match the * IPv6 address strings as returned by #GNUNET_TUN_ipv6toregexsearch. * * @param policy exit policy specification * @return regular expression, NULL on error */ char * GNUNET_TUN_ipv6policy2regex (const char *policy); /** * Convert an exit policy to a regular expression. The exit policy * specifies a set of subnets this peer is willing to serve as an * exit for; the resulting regular expression will match the * IPv4 address strings as returned by #GNUNET_TUN_ipv4toregexsearch. * * @param policy exit policy specification * @return regular expression, NULL on error */ char * GNUNET_TUN_ipv4policy2regex (const char *policy); /** * Hash the service name of a hosted service to the * hash code that is used to identify the service on * the network. * * @param service_name a string * @param[out] hc corresponding hash */ void GNUNET_TUN_service_name_to_hash (const char *service_name, struct GNUNET_HashCode *hc); /** * Check if two sockaddrs are equal. * * @param sa one address * @param sb another address * @param include_port also check ports * @return #GNUNET_YES if they are equal */ int GNUNET_TUN_sockaddr_cmp (const struct sockaddr *sa, const struct sockaddr *sb, int include_port); /** * Compute the CADET port given a service descriptor * (returned from #GNUNET_TUN_service_name_to_hash) and * a TCP/UDP port @a ip_port. * * @param desc service shared secret * @param ip_port TCP/UDP port, use 0 for ICMP * @param[out] cadet_port CADET port to use */ void GNUNET_TUN_compute_service_cadet_port (const struct GNUNET_HashCode *desc, uint16_t ip_port, struct GNUNET_HashCode *cadet_port); #endif /** @} */ /* end of group */