#ifndef __LINUX_IF_PACKET_H
#define __LINUX_IF_PACKET_H

#include <linux/types.h>

struct sockaddr_pkt
{
        unsigned short spkt_family;
        unsigned char spkt_device[14];
        __be16 spkt_protocol;
};

struct sockaddr_ll
{
        unsigned short        sll_family;
        __be16                sll_protocol;
        int                sll_ifindex;
        unsigned short        sll_hatype;
        unsigned char        sll_pkttype;
        unsigned char        sll_halen;
        unsigned char        sll_addr[8];
};

/* Packet types */

#define PACKET_HOST                0                /* To us                */
#define PACKET_BROADCAST        1                /* To all                */
#define PACKET_MULTICAST        2                /* To group                */
#define PACKET_OTHERHOST        3                /* To someone else         */
#define PACKET_OUTGOING                4                /* Outgoing of any type */
/* These ones are invisible by user level */
#define PACKET_LOOPBACK                5                /* MC/BRD frame looped back */
#define PACKET_FASTROUTE        6                /* Fastrouted frame        */

/* Packet socket options */

#define PACKET_ADD_MEMBERSHIP                1
#define PACKET_DROP_MEMBERSHIP                2
#define PACKET_RECV_OUTPUT                3
/* Value 4 is still used by obsolete turbo-packet. */
#define PACKET_RX_RING                        5
#define PACKET_STATISTICS                6
#define PACKET_COPY_THRESH                7
#define PACKET_AUXDATA                        8
#define PACKET_ORIGDEV                        9
#define PACKET_VERSION                        10
#define PACKET_HDRLEN                        11
#define PACKET_RESERVE                        12
#define PACKET_TX_RING                        13
#define PACKET_LOSS                        14

struct tpacket_stats
{
        unsigned int        tp_packets;
        unsigned int        tp_drops;
};

struct tpacket_auxdata
{
        __u32                tp_status;
        __u32                tp_len;
        __u32                tp_snaplen;
        __u16                tp_mac;
        __u16                tp_net;
        __u16                tp_vlan_tci;
#ifndef __GENKSYMS__
        __u16                tp_padding;
#endif
};

/* Rx ring - header status */
#define TP_STATUS_KERNEL        0x0
#define TP_STATUS_USER                0x1
#define TP_STATUS_COPY                0x2
#define TP_STATUS_LOSING        0x4
#define TP_STATUS_CSUMNOTREADY        0x8

/* Tx ring - header status */
#define TP_STATUS_AVAILABLE        0x0
#define TP_STATUS_SEND_REQUEST        0x1
#define TP_STATUS_SENDING        0x2
#define TP_STATUS_WRONG_FORMAT        0x4

struct tpacket_hdr
{
        unsigned long        tp_status;
        unsigned int        tp_len;
        unsigned int        tp_snaplen;
        unsigned short        tp_mac;
        unsigned short        tp_net;
        unsigned int        tp_sec;
        unsigned int        tp_usec;
};

#define TPACKET_ALIGNMENT        16
#define TPACKET_ALIGN(x)        (((x)+TPACKET_ALIGNMENT-1)&~(TPACKET_ALIGNMENT-1))
#define TPACKET_HDRLEN                (TPACKET_ALIGN(sizeof(struct tpacket_hdr)) + sizeof(struct sockaddr_ll))

struct tpacket2_hdr
{
        __u32                tp_status;
        __u32                tp_len;
        __u32                tp_snaplen;
        __u16                tp_mac;
        __u16                tp_net;
        __u32                tp_sec;
        __u32                tp_nsec;
        __u16                tp_vlan_tci;
#ifndef __GENKSYMS__
        __u16                tp_padding;
#endif
};

#define TPACKET2_HDRLEN                (TPACKET_ALIGN(sizeof(struct tpacket2_hdr)) + sizeof(struct sockaddr_ll))

enum tpacket_versions
{
        TPACKET_V1,
        TPACKET_V2,
};

/*
   Frame structure:

   - Start. Frame must be aligned to TPACKET_ALIGNMENT=16
   - struct tpacket_hdr
   - pad to TPACKET_ALIGNMENT=16
   - struct sockaddr_ll
   - Gap, chosen so that packet data (Start+tp_net) alignes to TPACKET_ALIGNMENT=16
   - Start+tp_mac: [ Optional MAC header ]
   - Start+tp_net: Packet data, aligned to TPACKET_ALIGNMENT=16.
   - Pad to align to TPACKET_ALIGNMENT=16
 */

struct tpacket_req
{
        unsigned int        tp_block_size;        /* Minimal size of contiguous block */
        unsigned int        tp_block_nr;        /* Number of blocks */
        unsigned int        tp_frame_size;        /* Size of frame */
        unsigned int        tp_frame_nr;        /* Total number of frames */
};

struct packet_mreq
{
        int                mr_ifindex;
        unsigned short        mr_type;
        unsigned short        mr_alen;
        unsigned char        mr_address[8];
};

#define PACKET_MR_MULTICAST        0
#define PACKET_MR_PROMISC        1
#define PACKET_MR_ALLMULTI        2
#define PACKET_MR_UNICAST        3

#endif