/*en    Laurent Constantin's network library (lcrzo)
                 lcrzo_header module

  Functions herein allow to create and convert headers.
*/
/*fr    Bibliotheque reseau de Laurent Constantin (lcrzo)
                 Module lcrzo_header

  Les fonctions presentes dans ce module permettent de creer ou
  d'analyser des entetes de paquets.
*/

/*EN***************************************************************
 * Note about logical and physical headers :
 * Network packet contains for example :
 *   ethernet_header ip_header udp_header udp_data
 * Values used in these header are in the "Big Endian" format.
 * So, when we want to work on headers, we have to convert
 * from host to network (htonx) or from network to host (ntohx).
 *
 * To simplify lcrzo use, two types are purposed :
 *  - logical headers : they are in host format
 *  - physical headers : they are in network format
 * 
 * Logical headers are easier to use.
 * On the other hand, physical headers exactly reflect
 * what's on the wire.
 * 
 * All the functions in lcrzo use logical headers, which allow
 * easy use of headers.
 *
 * Below you can find functions to convert between both types,
 * to suit your needs.
 ****************************************************************/
/*FR***************************************************************
 * Note sur les entetes logiques et physiques :
 * Les paquets issus du reseau sont par exemple de la forme :
 *   entete_ethernet entete_ip entete_udp donnees_udp
 * Les valeurs stockees dans les differents entetes
 * sont au format "Big Endian". Lorsque l'on desire travailler
 * sur des entetes, il faut alors normalement convertir les
 * valeurs de "host to network" (htonx) ou "network to host" (ntohx).
 *
 * Afin de simplifier l'emploi de lcrzo, je propose deux types
 * d'entetes :
 *  - les entetes "logiques" : ce sont les entetes au format machine
 *  - les entetes "physiques" : ce sont les entetes au format reseau
 * 
 * Les entetes logiques sont beaucoup plus simples a utiliser.
 * D'un autre cote, les entetes physiques correspondent exactement
 * a ce qui transite sur le reseau.
 *
 * Toutes les fonctions de lcrzo ont pour interface des entetes
 * logiques, ce qui les rend simples d'emploi.
 *
 * Ci dessous, des entetes physiques sont aussi proposees, si vous
 * desirez pouvoir acceder directement a des paquets reseau, sans
 * utiliser des fonctions de lcrzo.
 ****************************************************************/

/*-------------------------------------------------------------*/
/*en definition of logical headers */
/*fr definition des entetes logiques */

/*en logical header for ethernet header*/
/*fr entete "logique" de paquet ethernet */
typedef struct
{ lcrzo_etha   dst;
  lcrzo_etha   src;
  lcrzo_uint16 type;
} lcrzo_hdrleth;

/*en logical header for IP header*/
/*fr entete "logique" de paquet IP */
typedef struct 
{ lcrzo_uint8  version;
  lcrzo_uint8  ihl;
  lcrzo_uint8  tos;
  lcrzo_uint16 totlen;
  lcrzo_uint16 id;
  lcrzo_bool   reserve;
  lcrzo_bool   dontfrag;
  lcrzo_bool   morefrag;
  lcrzo_uint16 offsetfrag;
  lcrzo_uint8  ttl;
  lcrzo_uint8  protocol;
  lcrzo_uint16 check;
  lcrzo_uint32 saddr;
  lcrzo_uint32 daddr;
} lcrzo_hdrlip;

/*en logical header for UDP header*/
/*fr entete "logique" de paquet UDP */
typedef struct
{ lcrzo_uint16 sport;
  lcrzo_uint16 dport;
  lcrzo_uint16 len;
  lcrzo_uint16 check;
} lcrzo_hdrludp;

/*en logical header for TCP header*/
/*fr entete "logique" de paquet TCP */
typedef struct
{
  lcrzo_uint16 sport;
  lcrzo_uint16 dport;
  lcrzo_uint32 seqnum;
  lcrzo_uint32 acknum;
  lcrzo_uint8  doff;
  lcrzo_uint8  reserve;
  lcrzo_bool   urg;
  lcrzo_bool   ack;
  lcrzo_bool   psh;
  lcrzo_bool   rst;
  lcrzo_bool   syn;
  lcrzo_bool   fin;
  lcrzo_uint16 window;
  lcrzo_uint16 check;
  lcrzo_uint16 urgptr;
} lcrzo_hdrltcp;

/*en logical header for ICMP header*/
/*fr entete "logique" de paquet ICMP */
typedef struct
{ lcrzo_uint8  type;
  lcrzo_uint8  code;
  lcrzo_uint16 check;
} lcrzo_hdrlicmp;

/*en logical header for ARP/RARP header (specific for ethernet<-->ip)) */
/*fr entete "logique" de paquet arp/rarp (specifique a ethernet<-->ip) */
typedef struct
{ lcrzo_uint16 hw_type;    /*1:ethernet 10/100Mbps*/
  lcrzo_uint16 prot_type;  /*0x0800:ip*/
  lcrzo_uint8  hw_size;    /*6*/
  lcrzo_uint8  prot_size;  /*4*/
  lcrzo_uint16 op;         /*1:arpreq,2:arpreply, 3:rarpreq,4:rarpreply*/
  lcrzo_etha   hw_src;
  lcrzo_ipa    prot_src;
  lcrzo_etha   hw_dst;
  lcrzo_ipa    prot_dst;
} lcrzo_hdrlarp;

/*-------------------------------------------------------------*/
/* Ethernet types */
/* types Ethernet */
#define LCRZO_HDRLETH_TYPE_IP   0x0800
#define LCRZO_HDRLETH_TYPE_ARP  0x0806
#define LCRZO_HDRLETH_TYPE_RARP 0x8035

/*-------------------------------------------------------------*/
/* IP protocols */
/* protocoles IP */
#define LCRZO_HDRLIP_PROTOCOL_ICMP  1
#define LCRZO_HDRLIP_PROTOCOL_TCP   6
#define LCRZO_HDRLIP_PROTOCOL_UDP  17

/*-------------------------------------------------------------*/
/*en initialize an Ethernet logical header */
/*fr initialise un entete logique Ethernet */
#define LCRZO_HDRLETH_TYPE_DEFVAL     0
int lcrzo_hdrleth_initdefault(lcrzo_hdrleth *phdrleth);

/*en initialize an IP logical header */
/*fr initialise un entete logique IP */
#define LCRZO_HDRLIP_TOTLEN_DEFVAL   20
#define LCRZO_HDRLIP_IHL_DEFVAL       5
#define LCRZO_HDRLIP_CHECK_DEFVAL     0
#define LCRZO_HDRLIP_PROTOCOL_DEFVAL  0
int lcrzo_hdrlip_initdefault(lcrzo_hdrlip *phdrlip);

/*en initialize an UDP logical header */
/*fr initialise un entete logique UDP */
#define LCRZO_HDRLUDP_LEN_DEFVAL      8
#define LCRZO_HDRLUDP_CHECK_DEFVAL    0 
int lcrzo_hdrludp_initdefault(lcrzo_hdrludp *phdrludp);

/*en initialize a TCP logical header */
/*fr initialise un entete logique TCP */
#define LCRZO_HDRLTCP_DOFF_DEFVAL     5
#define LCRZO_HDRLTCP_CHECK_DEFVAL    0
int lcrzo_hdrltcp_initdefault(lcrzo_hdrltcp *phdrltcp);

/*en initialize an ICMP logical header */
/*fr initialise un entete logique ICMP */
#define LCRZO_HDRLICMP_CHECK_DEFVAL   0
int lcrzo_hdrlicmp_initdefault(lcrzo_hdrlicmp *phdrlicmp);

/*en initialize an ARP/RARP logical header */
/*fr initialise un entete logique ARP/RARP */
int lcrzo_hdrlarp_initdefault(lcrzo_hdrlarp *phdrlarp);

/*-------------------------------------------------------------*/
/*en update fields of phdrxxx, with modified fields from fieldstomodify */
/*fr met a jour les champs de phdrxxx, avec les champs modifies
     de fieldstomodify */
int lcrzo_hdrleth_update(lcrzo_hdrleth fieldstomodify,
			 lcrzo_hdrleth *phdreth);
int lcrzo_hdrlip_update(lcrzo_hdrlip fieldstomodify,
			lcrzo_hdrlip *phdrip);
int lcrzo_hdrludp_update(lcrzo_hdrludp fieldstomodify,
			 lcrzo_hdrludp *phdrudp);
int lcrzo_hdrltcp_update(lcrzo_hdrltcp fieldstomodify,
			 lcrzo_hdrltcp *phdrtcp);
int lcrzo_hdrlicmp_update(lcrzo_hdrlicmp fieldstomodify,
			  lcrzo_hdrlicmp *phdricmp);
int lcrzo_hdrlarp_update(lcrzo_hdrlarp fieldstomodify,
			 lcrzo_hdrlarp *phdrarp);

/*-------------------------------------------------------------*/
/*en physical header for ethernet header*/
/*fr entete physique de paquet ethernet */
#define LCRZO_HDRPETH2_MAXBYTES 14
typedef lcrzo_uint8 lcrzo_hdrpeth2[LCRZO_HDRPETH2_MAXBYTES];
/*en convert from logical header to physical header */
/*fr conversion d'entete logique a physique */
int lcrzo_hdrpeth2_init_hdrleth(lcrzo_hdrleth hdrleth,
				lcrzo_hdrpeth2 hdrpeth);
/*en convert from physical header to logical header */
/*fr conversion d'entete physique a logique */
int lcrzo_hdrleth_init_hdrpeth2(lcrzo_hdrpeth2 hdrpeth,
				lcrzo_hdrleth *phdrleth);

/*-------------------------------------------------------------*/
/*en physical header for IP header*/
/*fr entete physique de paquet IP */
#define LCRZO_HDRPIP2_MAXBYTES 20
typedef lcrzo_uint8 lcrzo_hdrpip2[LCRZO_HDRPIP2_MAXBYTES];
/*en convert from logical header to physical header */
/*fr conversion d'entete logique a physique */
int lcrzo_hdrpip2_init_hdrlip(lcrzo_hdrlip hdrlip,
			      lcrzo_hdrpip2 hdrpip);
/*en convert from physical header to logical header */
/*fr conversion d'entete physique a logique */
int lcrzo_hdrlip_init_hdrpip2(lcrzo_hdrpip2 hdrpip,
			      lcrzo_hdrlip *phdrlip);

/*-------------------------------------------------------------*/
/*en physical header for UDP header*/
/*fr entete physique de paquet UDP */
#define LCRZO_HDRPUDP2_MAXBYTES 8
typedef lcrzo_uint8 lcrzo_hdrpudp2[LCRZO_HDRPUDP2_MAXBYTES];
/*en convert from logical header to physical header */
/*fr conversion d'entete logique a physique */
int lcrzo_hdrpudp2_init_hdrludp(lcrzo_hdrludp hdrludp,
				lcrzo_hdrpudp2 hdrpudp);
/*en convert from physical header to logical header */
/*fr conversion d'entete physique a logique */
int lcrzo_hdrludp_init_hdrpudp2(lcrzo_hdrpudp2 hdrpudp,
				lcrzo_hdrludp *phdrludp);

/*-------------------------------------------------------------*/
/*en physical header for TCP header*/
/*fr entete physique de paquet TCP */
#define LCRZO_HDRPTCP2_MAXBYTES 20
typedef lcrzo_uint8 lcrzo_hdrptcp2[LCRZO_HDRPTCP2_MAXBYTES];
/*en convert from logical header to physical header */
/*fr conversion d'entete logique a physique */
int lcrzo_hdrptcp2_init_hdrltcp(lcrzo_hdrltcp hdrltcp,
				lcrzo_hdrptcp2 hdrptcp);
/*en convert from physical header to logical header */
/*fr conversion d'entete physique a logique */
int lcrzo_hdrltcp_init_hdrptcp2(lcrzo_hdrptcp2 hdrptcp,
				lcrzo_hdrltcp *phdrltcp);

/*-------------------------------------------------------------*/
/*en physical header for ICMP header*/
/*fr entete physique de paquet ICMP */
#define LCRZO_HDRPICMP2_MAXBYTES 4
typedef lcrzo_uint8 lcrzo_hdrpicmp2[LCRZO_HDRPICMP2_MAXBYTES];
/*en convert from logical header to physical header */
/*fr conversion d'entete logique a physique */
int lcrzo_hdrpicmp2_init_hdrlicmp(lcrzo_hdrlicmp hdrlicmp,
				  lcrzo_hdrpicmp2 hdrpicmp);
/*en convert from physical header to logical header */
/*fr conversion d'entete physique a logique */
int lcrzo_hdrlicmp_init_hdrpicmp2(lcrzo_hdrpicmp2 hdrpicmp,
				  lcrzo_hdrlicmp *phdrlicmp);

/*-------------------------------------------------------------*/
/*en physical header for ARP/RARP header*/
/*fr entete physique de paquet ARP/RARP */
#define LCRZO_HDRPARP2_MAXBYTES 28
typedef lcrzo_uint8 lcrzo_hdrparp2[LCRZO_HDRPARP2_MAXBYTES];
/*en convert from logical header to physical header */
/*fr conversion d'entete logique a physique */
int lcrzo_hdrparp2_init_hdrlarp(lcrzo_hdrlarp hdrlarp,
				lcrzo_hdrparp2 hdrparp);
/*en convert from physical header to logical header */
/*fr conversion d'entete physique a logique */
int lcrzo_hdrlarp_init_hdrparp2(lcrzo_hdrparp2 hdrparp,
				lcrzo_hdrlarp *phdrlarp);

