/*
 * A tool to check checksum integrity and gather simple traffic statistics.
 *
 * James Bulpin, October 2004.
 *
 * (C) University of Cambridge 2004.
 *
 * $Id: headers.h,v 1.1 2004/11/09 16:15:47 jrb44 Exp $
 *
 * $Log: headers.h,v $
 * Revision 1.1  2004/11/09 16:15:47  jrb44
 * Initial revision
 *
 *
 */

#ifndef HEADERS_H
#define HEADERS_H

/*****************************************************************************
 * Link layer
 */
typedef struct ethernet_t_struct
{
    uint8_t  dst[6];
    uint8_t  src[6];
    uint16_t proto;
} __attribute__((packed)) ethernet_t;

#ifndef ETHERTYPE_8021Q
#define ETHERTYPE_8021Q         0x8100
#endif
#ifndef ETHERTYPE_IP
#define ETHERTYPE_IP            0x0800  /* IP protocol */
#endif

typedef struct vlan_t_struct
{
    uint16_t vlan;
    uint16_t proto;
} __attribute__((packed)) vlan_t;

/*****************************************************************************
 * Basic details about header format.
 */
#define IPVERSION 0x4
#define BASE_HEADER_LENGTH sizeof(ipheader_t)

/*****************************************************************************
 * Protocol numbers.
 */
#define PROTOCOL_TCP  6
#define PROTOCOL_UDP  17
#define PROTOCOL_ICMP 1

/*
ip      0       IP              # internet protocol, pseudo protocol number
icmp    1       ICMP            # internet control message protocol
igmp    2       IGMP            # Internet Group Management
ggp     3       GGP             # gateway-gateway protocol
ipencap 4       IP-ENCAP        # IP encapsulated in IP (officially ``IP'')
st      5       ST              # ST datagram mode
tcp     6       TCP             # transmission control protocol
egp     8       EGP             # exterior gateway protocol
pup     12      PUP             # PARC universal packet protocol
udp     17      UDP             # user datagram protocol
hmp     20      HMP             # host monitoring protocol
xns-idp 22      XNS-IDP         # Xerox NS IDP
rdp     27      RDP             # "reliable datagram" protocol
iso-tp4 29      ISO-TP4         # ISO Transport Protocol class 4
*/

/*****************************************************************************
 * Fragmentation details.
 */
#define IP_CE           0x8000          /* Flag: "Congestion"           */
#define IP_DF           0x4000          /* Flag: "Don't Fragment"       */
#define IP_MF           0x2000          /* Flag: "More Fragments"       */
#define IP_OFFSET       0x1FFF          /* "Fragment Offset" part       */

/*****************************************************************************
 * The type of an IP address.
 */
typedef uint32_t addr_t;
#define MAKEADDR_NE(_a, _b, _c, _d) ((_a)|((_b)<<8)|((_c)<<16)|((_d)<<24))
#define ADDR_PRINTF_LIST(_ane) (unsigned int)((_ane)&0xff), \
    (unsigned int)(((_ane)>>8)&0xff), \
    (unsigned int)(((_ane)>>16)&0xff), \
    (unsigned int)(((_ane)>>24)&0xff)

/*****************************************************************************
 * The format of an IP header.
 */
typedef struct ipheader_t_struct
{
    uint8_t  vers_hlen;
    uint8_t  tos;
    uint16_t total_length;
    uint16_t ident;
    uint16_t flags_frag;
    uint8_t  ttl;
    uint8_t  protocol;
    uint16_t hdr_chksum;
    addr_t   src;
    addr_t   dst;
} __attribute__((packed)) ipheader_t;
#define IP_HDR_LEN(_ip) ((((_ip)->vers_hlen)&0xf)<<2)
#define IP_HDR_VER(_ip) (((_ip)->vers_hlen)>>4)

#define IP_HDR_ECN(_ip) (((_ip)->tos)>>6)

#define IP_OPTION(_class, _number) (((_class)<<5)|(_number))
#define IP_OPTION_EOL  IP_OPTION(0, 0)
#define IP_OPTION_NOP  IP_OPTION(0, 1)
#define IP_OPTION_REST IP_OPTION(0, 2)
#define IP_OPTION_LSR  IP_OPTION(0, 3)
#define IP_OPTION_RR   IP_OPTION(0, 7)
#define IP_OPTION_SID  IP_OPTION(0, 8)
#define IP_OPTION_SSR  IP_OPTION(0, 9)
#define IP_OPTION_MTUP IP_OPTION(0, 11)
#define IP_OPTION_MTUR IP_OPTION(0, 12)
#define IP_OPTION_RA   IP_OPTION(0, 20)
#define IP_OPTION_TS   IP_OPTION(2, 4)
#define IP_OPTION_TR   IP_OPTION(2, 18)

#define IS_MULTICAST(_addr) ((ntohl(_addr)&0xf0000000)==0xe0000000)

/*****************************************************************************
 * TCP Header format.
 */
typedef struct tcp_t_struct
{
    uint16_t src_port;
    uint16_t dst_port;
    uint32_t seq_no;
    uint32_t ack_no;
    uint16_t hlen_code;
    uint16_t window;
    uint16_t checksum;
    uint16_t urgent;
} __attribute__((packed)) tcp_t;
#define TCP_HDR_LEN(_tcp) ((((_tcp)->hlen_code>>4)&0xf)<<2)

#define TCP_OPTION_EOL    0x00
#define TCP_OPTION_NOP    0x01
#define TCP_OPTION_MSS    0x02
#define TCP_OPTION_WS     0x03 //Window scale
#define TCP_OPTION_SACKOK 0x04
#define TCP_OPTION_SACK   0x05
#define TCP_OPTION_ECHO   0x06
#define TCP_OPTION_REPLY  0x07
#define TCP_OPTION_TS     0x08
#define TCP_OPTION_PO_OK  0x09
#define TCP_OPTION_PO_PR  0x0a
#define TCP_OPTION_CC     0x0b
#define TCP_OPTION_CCNEW  0x0c
#define TCP_OPTION_CCECHO 0x0d
#define TCP_OPTION_ALTCHK 0x0e
#define TCP_OPTION_ACDAT  0x0f
#define TCP_OPTION_SKEET  0x10
#define TCP_OPTION_BUBBA  0x11
#define TCP_OPTION_TRLCHK 0x12
#define TCP_OPTION_MD5    0x13
#define TCP_OPTION_SCPS   0x14
#define TCP_OPTION_SNACK  0x15
#define TCP_OPTION_RBND   0x16
#define TCP_OPTION_CRPT   0x17
#define TCP_OPTION_SNAP   0x18
#define TCP_OPTION_X      0x19
#define TCP_OPTION_COMP   0x1a

#define TCP_ALTCHK_TCP        0x00
#define TCP_ALTCHK_FLETCHER8  0x01
#define TCP_ALTCHK_FLETCHER16 0x02

/*****************************************************************************
 * TCP flags.
 */
#define TCP_URG 0x20
#define TCP_ACK 0x10
#define TCP_PSH 0x80
#define TCP_RST 0x40
#define TCP_SYN 0x20
#define TCP_FIN 0x10

/*****************************************************************************
 * UDP Header format.
 */
typedef struct udp_t_struct
{
    uint16_t src_port;
    uint16_t dst_port;
    uint16_t msg_len;
    uint16_t checksum;
} __attribute__((packed)) udp_t;

/*****************************************************************************
 * ICMP
 */
typedef struct icmp_common_t_struct
{
    uint8_t  type;
    uint8_t  code;
    uint16_t checksum;
} __attribute__((packed)) icmp_common_t;

typedef struct icmp_ud_t_struct
{
    icmp_common_t c;
    uint32_t      unused;
    ipheader_t    ip; 
} __attribute__((packed)) icmp_ud_t;

#define ICMP_ECHO_REPLY 0
#define ICMP_DEST_UR    3
#define ICMP_SQ         4
#define ICMP_REDIRECT   5
#define ICMP_ECHO_REQ   8
#define ICMP_RTR_AD     9
#define ICMP_RTR_SOL    10
#define ICMP_TE         11
#define ICMP_PP         12
#define ICMP_TS_REQ     13
#define ICMP_TS_REPLY   14
#define ICMP_INF_REQ    15
#define ICMP_INF_REPLY  16
#define ICMP_MASK_REQ   17
#define ICMP_MASK_REPLY 18

#define ICMP_UR_NET         0
#define ICMP_UR_HOST        1
#define ICMP_UR_PROTO       2
#define ICMP_UR_PORT        3
#define ICMP_UR_FRAG        4
#define ICMP_UR_SR_FAIL     5
#define ICMP_UR_NET_UNK     6
#define ICMP_UR_HOST_UNK    7
#define ICMP_UR_SRC_ISOL    8
#define ICMP_UR_NET_PROHIB  9
#define ICMP_UR_HOST_PROHIB 10
#define ICMP_UR_NET_TOS     11
#define ICMP_UR_HOST_TOS    12
#define ICMP_UR_PKT_FILT    13      /* Packet filtered */
#define ICMP_PREC_VIOLATION 14      /* Precedence violation */
#define ICMP_PREC_CUTOFF    15      /* Precedence cut off */

/*****************************************************************************
 * Checksum computation - From Linux 2.6.7
 */
static inline unsigned short ip_fast_csum(unsigned char * iph,
                                          unsigned int ihl)
{
    unsigned int sum;
        
    __asm__ __volatile__("movl (%1), %0      ;\n"
                         "subl $4, %2        ;\n"
                         "jbe 2f             ;\n"
                         "addl 4(%1), %0     ;\n"
                         "adcl 8(%1), %0     ;\n"
                         "adcl 12(%1), %0    ;\n"
                         "1:         adcl 16(%1), %0     ;\n"
                         "lea 4(%1), %1      ;\n"
                         "decl %2            ;\n"
                         "jne 1b             ;\n"
                         "adcl $0, %0        ;\n"
                         "movl %0, %2        ;\n"
                         "shrl $16, %0       ;\n"
                         "addw %w2, %w0      ;\n"
                         "adcl $0, %0        ;\n"
                         "notl %0            ;\n"
                         "2:                             ;\n"
                         /* Since the input registers which are loaded with
                            iph and ipl are modified, we must also specify
                            them as outputs, or gcc will assume they contain
                            their original values. */
                         : "=r" (sum), "=r" (iph), "=r" (ihl)
                         : "1" (iph), "2" (ihl)
                         : "memory");
    return(sum);
}

#endif /* HEADERS_H */

/* End of $RCSfile: headers.h,v $ */
