/* * Copyright (c) 2009 Lukas Mejdrech * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * - The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /** @addtogroup libnet * @{ */ /** @file * IP header and options definitions. * Based on the RFC 791. */ #ifndef LIBNET_IP_HEADER_H_ #define LIBNET_IP_HEADER_H_ #include #include /** Returns the fragment offest high bits. * @param[in] length The prefixed data total length. */ #define IP_COMPUTE_FRAGMENT_OFFSET_HIGH(length) \ ((((length) / 8U) & 0x1f00) >> 8) /** Returns the fragment offest low bits. * @param[in] length The prefixed data total length. */ #define IP_COMPUTE_FRAGMENT_OFFSET_LOW(length) \ (((length) / 8U) & 0xff) /** Returns the IP header length. * @param[in] length The IP header length in bytes. */ #define IP_COMPUTE_HEADER_LENGTH(length) \ ((uint8_t) ((length) / 4U)) /** Returns the fragment offest. * @param[in] header The IP packet header. */ #define IP_FRAGMENT_OFFSET(header) \ ((((header)->fragment_offset_high << 8) + \ (header)->fragment_offset_low) * 8U) /** Returns the IP packet header checksum. * @param[in] header The IP packet header. */ #define IP_HEADER_CHECKSUM(header) \ (htons(ip_checksum((uint8_t *) (header), IP_HEADER_LENGTH(header)))) /** Returns the actual IP packet data length. * @param[in] header The IP packet header. */ #define IP_HEADER_DATA_LENGTH(header) \ (IP_TOTAL_LENGTH(header) - IP_HEADER_LENGTH(header)) /** Returns the actual IP header length in bytes. * @param[in] header The IP packet header. */ #define IP_HEADER_LENGTH(header) \ ((header)->header_length * 4U) /** Returns the actual IP packet total length. * @param[in] header The IP packet header. */ #define IP_TOTAL_LENGTH(header) \ ntohs((header)->total_length) /** @name IP flags definitions */ /*@{*/ /** Fragment flag field shift. */ #define IPFLAG_FRAGMENT_SHIFT 1 /** Fragmented flag field shift. */ #define IPFLAG_FRAGMENTED_SHIFT 0 /** Don't fragment flag value. * Permits the packet fragmentation. */ #define IPFLAG_DONT_FRAGMENT (0x1 << IPFLAG_FRAGMENT_SHIFT) /** Last fragment flag value. * Indicates the last packet fragment. */ #define IPFLAG_LAST_FRAGMENT (0x0 << IPFLAG_FRAGMENTED_SHIFT) /** May fragment flag value. * Allows the packet fragmentation. */ #define IPFLAG_MAY_FRAGMENT (0x0 << IPFLAG_FRAGMENT_SHIFT) /** More fragments flag value. * Indicates that more packet fragments follow. */ #define IPFLAG_MORE_FRAGMENTS (0x1 << IPFLAG_FRAGMENTED_SHIFT) /*@}*/ /** Type definition of the internet header. * @see ip_header */ typedef struct ip_header ip_header_t; /** Type definition of the internet option header. * @see ip_header */ typedef struct ip_option ip_option_t; /** Type definition of the internet version 4 pseudo header. * @see ipv4_pseudo_header */ typedef struct ipv4_pseudo_header ipv4_pseudo_header_t; /** Internet header. * * The variable options should be included after the header itself and * indicated by the increased header length value. */ struct ip_header { #ifdef ARCH_IS_BIG_ENDIAN uint8_t version : 4; uint8_t header_length : 4; #else uint8_t header_length : 4; uint8_t version : 4; #endif uint8_t tos; uint16_t total_length; uint16_t identification; #ifdef ARCH_IS_BIG_ENDIAN uint8_t flags : 3; uint8_t fragment_offset_high : 5; #else uint8_t fragment_offset_high : 5; uint8_t flags : 3; #endif uint8_t fragment_offset_low; uint8_t ttl; uint8_t protocol; uint16_t header_checksum; uint32_t source_address; uint32_t destination_address; } __attribute__ ((packed)); /** Internet option header. * * Only type field is always valid. * Other fields' validity depends on the option type. */ struct ip_option { uint8_t type; uint8_t length; uint8_t pointer; #ifdef ARCH_IS_BIG_ENDIAN uint8_t overflow : 4; uint8_t flags : 4; #else uint8_t flags : 4; uint8_t overflow : 4; #endif } __attribute__ ((packed)); /** Internet version 4 pseudo header. */ struct ipv4_pseudo_header { uint32_t source_address; uint32_t destination_address; uint8_t reserved; uint8_t protocol; uint16_t data_length; } __attribute__ ((packed)); #endif /** @} */