/*
This file is part of GNUnet.
- (C) 2010, 2011, 2012 Christian Grothoff
+ (C) 2010-2013 Christian Grothoff
GNUnet is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published
#endif
+/**
+ * Maximum regex string length for use with GNUNET_TUN_ipv4toregexsearch
+ */
+#define GNUNET_TUN_IPV4_REGEXLEN 32 + 6
+
+
+/**
+ * Maximum regex string length for use with GNUNET_TUN_ipv6toregexsearch
+ */
+#define GNUNET_TUN_IPV6_REGEXLEN 128 + 6
+
+
GNUNET_NETWORK_STRUCT_BEGIN
/**
* Header from Linux TUN interface.
- */
+ */
struct GNUNET_TUN_Layer2PacketHeader
{
/**
* Some flags (unused).
- */
- uint16_t flags;
+ */
+ uint16_t flags GNUNET_PACKED;
/**
* Here we get an ETH_P_-number.
*/
- uint16_t proto;
+ uint16_t proto GNUNET_PACKED;
};
*/
struct GNUNET_TUN_IPv4Header
{
- unsigned header_length:4 GNUNET_PACKED;
- unsigned version:4 GNUNET_PACKED;
+#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 flags:3 GNUNET_PACKED;
- unsigned fragmentation_offset:13 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 GNUNET_PACKED;
+
+ /**
+ * Destination of the packet.
+ */
struct in_addr destination_address GNUNET_PACKED;
-};
+} GNUNET_GCC_STRUCT_LAYOUT;
/**
*/
struct GNUNET_TUN_IPv6Header
{
- unsigned traffic_class_h:4 GNUNET_PACKED;
- unsigned version:4 GNUNET_PACKED;
- unsigned traffic_class_l:4 GNUNET_PACKED;
- unsigned flow_label:20 GNUNET_PACKED;
+#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 packet header (FIXME: rename!)
+ * TCP packet header.
*/
struct GNUNET_TUN_TcpHeader
{
- unsigned spt:16 GNUNET_PACKED;
- unsigned dpt:16 GNUNET_PACKED;
- unsigned seq:32 GNUNET_PACKED;
- unsigned ack:32 GNUNET_PACKED;
- unsigned off:4 GNUNET_PACKED;
- unsigned rsv:4 GNUNET_PACKED;
- unsigned flg:8 GNUNET_PACKED;
- unsigned wsz:16 GNUNET_PACKED;
- unsigned crc:16 GNUNET_PACKED;
- unsigned urg:16 GNUNET_PACKED;
-};
+ /**
+ * 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 (FIXME: rename!)
+ * UDP packet header.
*/
struct GNUNET_TUN_UdpHeader
{
- uint16_t spt GNUNET_PACKED;
- uint16_t dpt GNUNET_PACKED;
+ /**
+ * 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;
- uint16_t flags GNUNET_PACKED;
- uint16_t qdcount GNUNET_PACKED;
- uint16_t ancount GNUNET_PACKED;
- uint16_t nscount GNUNET_PACKED;
- uint16_t arcount 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 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 GNUNET_PACKED;
+
+ /**
+ * MTU for packets that are too big (IPv6).
+ */
+ uint32_t packet_too_big_mtu GNUNET_PACKED;
+
+ } quench;
+
+};
+
+
GNUNET_NETWORK_STRUCT_END
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 ipv6 header fully initialized
- * @param tcp header (initialized except for CRC)
+ * @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
*/
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 UDP 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 ICMP 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 netmask.
+ *
+ * @param ip IPv4 representation.
+ * @param netmask netmask for the ip.
+ * @param rxstr generated regex, must be at least #GNUNET_TUN_IPV4_REGEXLEN
+ * bytes long.
+ */
+void
+GNUNET_TUN_ipv4toregexsearch (const struct in_addr *ip, const char *netmask,
+ char *rxstr);
+
+
+/**
+ * Create a regex in @a rxstr from the given @a ipv6 and @a prefixlen.
+ *
+ * @param ipv6 IPv6 representation.
+ * @param prefixlen length of the ipv6 prefix.
+ * @param rxstr generated regex, must be at least #GNUNET_TUN_IPV6_REGEXLEN
+ * bytes long.
+ */
+void
+GNUNET_TUN_ipv6toregexsearch (const struct in6_addr *ipv6,
+ unsigned int prefixlen, 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);
+
#endif