Webserver+3d print

Dependents:   Nucleo

cyclone_tcp/ipv4/ipv4.h

Committer:
Sergunb
Date:
2017-02-04
Revision:
0:8918a71cdbe9

File content as of revision 0:8918a71cdbe9:

/**
 * @file ipv4.h
 * @brief IPv4 (Internet Protocol Version 4)
 *
 * @section License
 *
 * Copyright (C) 2010-2017 Oryx Embedded SARL. All rights reserved.
 *
 * This file is part of CycloneTCP Open.
 *
 * 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; either version 2
 * of the License, or (at your option) any later version.
 *
 * 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, write to the Free Software Foundation,
 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 *
 * @author Oryx Embedded SARL (www.oryx-embedded.com)
 * @version 1.7.6
 **/

#ifndef _IPV4_H
#define _IPV4_H

//Forward declaration of structures
struct _Ipv4Header;
#define Ipv4Header struct _Ipv4Header

struct _Ipv4PseudoHeader;
#define Ipv4PseudoHeader struct _Ipv4PseudoHeader

//Dependencies
#include <string.h>
#include "core/net.h"
#include "core/ethernet.h"
#include "ipv4/ipv4_frag.h"

//IPv4 support
#ifndef IPV4_SUPPORT
   #define IPV4_SUPPORT ENABLED
#elif (IPV4_SUPPORT != ENABLED && IPV4_SUPPORT != DISABLED)
   #error IPV4_SUPPORT parameter is not valid
#endif

//Default IPv4 time-to-live value
#ifndef IPV4_DEFAULT_TTL
   #define IPV4_DEFAULT_TTL 64
#elif (IPV4_DEFAULT_TTL < 1)
   #error IPV4_DEFAULT_TTL parameter is not valid
#endif

//Maximum number of DNS servers
#ifndef IPV4_DNS_SERVER_LIST_SIZE
   #define IPV4_DNS_SERVER_LIST_SIZE 2
#elif (IPV4_DNS_SERVER_LIST_SIZE < 1)
   #error IPV4_DNS_SERVER_LIST_SIZE parameter is not valid
#endif

//Size of the IPv4 multicast filter
#ifndef IPV4_MULTICAST_FILTER_SIZE
   #define IPV4_MULTICAST_FILTER_SIZE 4
#elif (IPV4_MULTICAST_FILTER_SIZE < 1)
   #error IPV4_MULTICAST_FILTER_SIZE parameter is not valid
#endif

//Version number for IPv4
#define IPV4_VERSION 4
//Minimum MTU
#define IPV4_MINIMUM_MTU 68
//Default MTU
#define IPV4_DEFAULT_MTU 576
//Minimum header length
#define IPV4_MIN_HEADER_LENGTH 20
//Maximum header length
#define IPV4_MAX_HEADER_LENGTH 60

//Shortcut to data field
#define IPV4_DATA(packet) PTR_OFFSET(packet, packet->headerLength * 4)

//Macro used for defining an IPv4 address
#ifdef _CPU_BIG_ENDIAN
   #define IPV4_ADDR(a, b, c, d) (((uint32_t) (a) << 24) | ((b) << 16) | ((c) << 8) | (d))
#else
   #define IPV4_ADDR(a, b, c, d) ((a) | ((b) << 8) | ((c) << 16) | ((uint32_t) (d) << 24))
#endif

//Unspecified IPv4 address
#define IPV4_UNSPECIFIED_ADDR IPV4_ADDR(0, 0, 0, 0)
//Broadcast IPV4 address
#define IPV4_BROADCAST_ADDR IPV4_ADDR(255, 255, 255, 255)

//Loopback IPv4 address
#define IPV4_LOOPBACK_ADDR IPV4_ADDR(127, 0, 0, 1)
#define IPV4_LOOPBACK_ADDR_PREFIX IPV4_ADDR(127, 0, 0, 0)
#define IPV4_LOOPBACK_ADDR_MASK IPV4_ADDR(255, 0, 0, 0)

//Link-local addresses
#define IPV4_LINK_LOCAL_PREFIX IPV4_ADDR(169, 254, 0, 0)
#define IPV4_LINK_LOCAL_MASK IPV4_ADDR(255, 255, 0, 0)

//Multicast addresses
#define IPV4_MULTICAST_PREFIX IPV4_ADDR(224, 0, 0, 0)
#define IPV4_MULTICAST_MASK IPV4_ADDR(240, 0, 0, 0)

//Local Network Control Block (RFC 5771)
#define IPV4_MULTICAST_LNCB_PREFIX IPV4_ADDR(224, 0, 0, 0)
#define IPV4_MULTICAST_LNCB_MASK IPV4_ADDR(255, 255, 255, 0)

//Internetwork Control Block (RFC 5771)
#define IPV4_MULTICAST_INCB_PREFIX IPV4_ADDR(224, 0, 1, 0)
#define IPV4_MULTICAST_INCB_MASK IPV4_ADDR(255, 255, 255, 0)

//IPv4 address classes
#define IPV4_CLASS_A_ADDR IPV4_ADDR(0, 0, 0, 0)
#define IPV4_CLASS_A_MASK IPV4_ADDR(128, 0, 0, 0)
#define IPV4_CLASS_B_ADDR IPV4_ADDR(128, 0, 0, 0)
#define IPV4_CLASS_B_MASK IPV4_ADDR(192, 0, 0, 0)
#define IPV4_CLASS_C_ADDR IPV4_ADDR(192, 0, 0, 0)
#define IPV4_CLASS_C_MASK IPV4_ADDR(224, 0, 0, 0)
#define IPV4_CLASS_D_ADDR IPV4_ADDR(224, 0, 0, 0)
#define IPV4_CLASS_D_MASK IPV4_ADDR(240, 0, 0, 0)
#define IPV4_CLASS_E_ADDR IPV4_ADDR(240, 0, 0, 0)
#define IPV4_CLASS_E_MASK IPV4_ADDR(240, 0, 0, 0)

//Copy IPv4 address
#define ipv4CopyAddr(destIpAddr, srcIpAddr) \
   memcpy(destIpAddr, srcIpAddr, sizeof(Ipv4Addr))

//Compare IPv4 addresses
#define ipv4CompAddr(ipAddr1, ipAddr2) \
   (!memcmp(ipAddr1, ipAddr2, sizeof(Ipv4Addr)))

//Determine whether an IPv4 address belongs to the local network
#define ipv4IsOnLocalSubnet(interface, ipAddr) \
   ((ipAddr & interface->ipv4Context.subnetMask) == \
   (interface->ipv4Context.addr & interface->ipv4Context.subnetMask))

//Determine whether an IPv4 address is a link-local address
#define ipv4IsLinkLocalAddr(ipAddr) \
   ((ipAddr & IPV4_LINK_LOCAL_MASK) == IPV4_LINK_LOCAL_PREFIX)

//Determine whether an IPv4 address is a multicast address
#define ipv4IsMulticastAddr(ipAddr) \
   ((ipAddr & IPV4_MULTICAST_MASK) == IPV4_MULTICAST_PREFIX)

//Check whether an IPv4 address is a tentative address
#define ipv4IsTentativeAddr(interface, ipAddr) \
   (interface->ipv4Context.addrState == IPV4_ADDR_STATE_TENTATIVE && \
   interface->ipv4Context.addr == ipAddr)


/**
 * @brief IPv4 address scopes
 **/

typedef enum
{
   IPV4_ADDR_SCOPE_INTERFACE_LOCAL = 1,
   IPV4_ADDR_SCOPE_LINK_LOCAL      = 2,
   IPV4_ADDR_SCOPE_GLOBAL          = 3
} Ipv4AddrScope;


/**
 * @brief IPv4 address state
 **/

typedef enum
{
   IPV4_ADDR_STATE_INVALID    = 0, ///<An address that is not assigned to any interface
   IPV4_ADDR_STATE_TENTATIVE  = 1, ///<An address whose uniqueness on a link is being verified
   IPV4_ADDR_STATE_VALID      = 2  ///<An address assigned to an interface whose use is unrestricted
} Ipv4AddrState;


/**
 * @brief IPv4 fragment offset field
 **/

typedef enum
{
   IPV4_FLAG_RES    = 0x8000,
   IPV4_FLAG_DF     = 0x4000,
   IPV4_FLAG_MF     = 0x2000,
   IPV4_OFFSET_MASK = 0x1FFF
} Ipv4FragmentOffset;


/**
 * @brief IPv4 protocol field
 **/

typedef enum
{
   IPV4_PROTOCOL_ICMP = 1,
   IPV4_PROTOCOL_IGMP = 2,
   IPV4_PROTOCOL_TCP  = 6,
   IPV4_PROTOCOL_UDP  = 17
} Ipv4Protocol;


/**
 * @brief IPv4 option types
 **/

typedef enum
{
   IPV4_OPTION_EEOL   = 0,
   IPV4_OPTION_NOP    = 1,
   IPV4_OPTION_RTRALT = 148
} Ipv4OptionType;


/**
 * @brief IPv4 network address
 **/

typedef uint32_t Ipv4Addr;


//CodeWarrior or Win32 compiler?
#if defined(__CWCC__) || defined(_WIN32)
   #pragma pack(push, 1)
#endif


/**
 * @brief IPv4 header
 **/

__start_packed struct _Ipv4Header
{
#ifdef _CPU_BIG_ENDIAN
   uint8_t version : 4;      //0
   uint8_t headerLength : 4;
#else
   uint8_t headerLength : 4; //0
   uint8_t version : 4;
#endif
   uint8_t typeOfService;    //1
   uint16_t totalLength;     //2-3
   uint16_t identification;  //4-5
   uint16_t fragmentOffset;  //6-7
   uint8_t timeToLive;       //8
   uint8_t protocol;         //9
   uint16_t headerChecksum;  //10-11
   Ipv4Addr srcAddr;         //12-15
   Ipv4Addr destAddr;        //16-19
   uint8_t options[];        //20
} __end_packed;


/**
 * @brief IPv4 pseudo header
 **/

__start_packed struct _Ipv4PseudoHeader
{
   Ipv4Addr srcAddr;  //0-3
   Ipv4Addr destAddr; //4-7
   uint8_t reserved;  //8
   uint8_t protocol;  //9
   uint16_t length;   //10-11
} __end_packed;


/**
 * @brief IPv4 option
 **/

typedef __start_packed struct
{
   uint8_t type;    //0
   uint8_t length;  //1
   uint8_t value[]; //2
} __end_packed Ipv4Option;


//CodeWarrior or Win32 compiler?
#if defined(__CWCC__) || defined(_WIN32)
   #pragma pack(pop)
#endif


/**
 * @brief IPv4 multicast filter entry
 **/

typedef struct
{
   Ipv4Addr addr;    ///<Multicast address
   uint_t refCount;  ///<Reference count for the current entry
   uint_t state;     ///<IGMP host state
   bool_t flag;      ///<IGMP flag
   systime_t timer;  ///<Delay timer
} Ipv4FilterEntry;


/**
 * @brief IPv4 context
 **/

typedef struct
{
   size_t linkMtu;                                              ///<Maximum transmission unit
   bool_t isRouter;                                             ///<A flag indicating whether routing is enabled on this interface
   uint16_t identification;                                     ///<IPv4 fragment identification field
   Ipv4Addr addr;                                               ///<Host address
   Ipv4AddrState addrState;                                     ///<State of the host address
   bool_t addrConflict;                                         ///<Address conflict detected
   Ipv4Addr subnetMask;                                         ///<Subnet mask
   Ipv4Addr defaultGateway;                                     ///<Default gateway
   Ipv4Addr dnsServerList[IPV4_DNS_SERVER_LIST_SIZE];           ///<DNS servers
   Ipv4FilterEntry multicastFilter[IPV4_MULTICAST_FILTER_SIZE]; ///<Multicast filter table
#if (IPV4_FRAG_SUPPORT == ENABLED)
   Ipv4FragDesc fragQueue[IPV4_MAX_FRAG_DATAGRAMS];             ///<IPv4 fragment reassembly queue
#endif
} Ipv4Context;


//IPv4 related functions
error_t ipv4Init(NetInterface *interface);

error_t ipv4SetHostAddr(NetInterface *interface, Ipv4Addr addr);
error_t ipv4GetHostAddr(NetInterface *interface, Ipv4Addr *addr);

error_t ipv4SetSubnetMask(NetInterface *interface, Ipv4Addr mask);
error_t ipv4GetSubnetMask(NetInterface *interface, Ipv4Addr *mask);

error_t ipv4SetDefaultGateway(NetInterface *interface, Ipv4Addr addr);
error_t ipv4GetDefaultGateway(NetInterface *interface, Ipv4Addr *addr);

error_t ipv4SetDnsServer(NetInterface *interface, uint_t index, Ipv4Addr addr);
error_t ipv4GetDnsServer(NetInterface *interface, uint_t index, Ipv4Addr *addr);

error_t ipv4GetBroadcastAddr(NetInterface *interface, Ipv4Addr *addr);

void ipv4LinkChangeEvent(NetInterface *interface);

void ipv4ProcessPacket(NetInterface *interface, Ipv4Header *packet, size_t length);
void ipv4ProcessDatagram(NetInterface *interface, const NetBuffer *buffer);

error_t ipv4SendDatagram(NetInterface *interface, Ipv4PseudoHeader *pseudoHeader,
   NetBuffer *buffer, size_t offset, uint8_t ttl);

error_t ipv4SendPacket(NetInterface *interface, Ipv4PseudoHeader *pseudoHeader,
   uint16_t fragId, size_t fragOffset, NetBuffer *buffer, size_t offset, uint8_t ttl);

error_t ipv4CheckSourceAddr(NetInterface *interface, Ipv4Addr ipAddr);
error_t ipv4CheckDestAddr(NetInterface *interface, Ipv4Addr ipAddr);

error_t ipv4SelectSourceAddr(NetInterface **interface,
   Ipv4Addr destAddr, Ipv4Addr *srcAddr);

bool_t ipv4IsBroadcastAddr(NetInterface *interface, Ipv4Addr ipAddr);

uint_t ipv4GetAddrScope(Ipv4Addr ipAddr);

error_t ipv4JoinMulticastGroup(NetInterface *interface, Ipv4Addr groupAddr);
error_t ipv4LeaveMulticastGroup(NetInterface *interface, Ipv4Addr groupAddr);

error_t ipv4MapMulticastAddrToMac(Ipv4Addr ipAddr, MacAddr *macAddr);

error_t ipv4StringToAddr(const char_t *str, Ipv4Addr *ipAddr);
char_t *ipv4AddrToString(Ipv4Addr ipAddr, char_t *str);

void ipv4DumpHeader(const Ipv4Header *ipHeader);

#endif