/*
 * SPDX-License-Identifier: GPL-2.0-or-later
 *
 * def.h - Definition header file for Bit-Twist project
 * Copyright (C) 2006 - 2024 Addy Yeow <ayeowch@gmail.com>
 *
 * 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.
 */

#ifndef _DEF_H_
#define _DEF_H_

#ifdef _WIN32
#define _WIN32_WINNT 0x0600 /* target Windows Vista and above*/
#endif                      /* _WIN32 */

#include <ctype.h>
#include <errno.h>
#include <inttypes.h>
#include <limits.h>
#include <signal.h>
#include <stdarg.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define __USE_XOPEN /* using strptime from time.h */
#include <time.h>
#include <unistd.h>
#define _NET_IF_ARP_H_ /* OpenBSD's if.h takes in if_arp.h */

#ifdef __BSD_VISIBLE /* Linux does not have net/if_dl.h */
#include <net/if_dl.h>
#endif /* __BSD_VISIBLE */

#include <pcap.h>

#ifdef _WIN32
#include "windows_utils.h"
#endif /* _WIN32 */

struct pcap_timeval
{
    bpf_int32 tv_sec; /* seconds (WARNING: will overflow by 2038-01-19 03:14:07 UTC) */
    /*
     * PCAP_MAGIC: 6-digit microseconds
     * NSEC_PCAP_MAGIC: 9-digit nanoseconds
     */
    bpf_int32 tv_usec;
};

struct pcap_sf_pkthdr
{
    struct pcap_timeval ts; /* timestamp */
    bpf_u_int32 caplen;     /* length of portion present */
    bpf_u_int32 len;        /* length this packet (off wire) */
};

#define BITTWIST_VERSION "4.7"
#define BITTWISTE_VERSION BITTWIST_VERSION

#define ETH_ADDR_LEN 6   /* Ethernet address length */
#define ETH_HDR_LEN 14   /* Ethernet header length */
#define VLAN_HDR_LEN 4   /* VLAN header length */
#define ETH_MAX_LEN 1514 /* max. frame length, excluding CRC */
#define ARP_HDR_LEN 28   /* Ethernet ARP header length */
#define IP_ADDR_LEN 4    /* IP address length */
#define IP_HDR_LEN 20    /* default IP header length */
#define IP6_HDR_LEN 40   /* default IPv6 header length */
#define ICMP_HDR_LEN 4   /* ICMP header length (up to checksum field only) */
#define ICMP6_HDR_LEN 4  /* ICMPv6 header length (up to checksum field only) */
#define TCP_HDR_LEN 20   /* default TCP header length */
#define UDP_HDR_LEN 8    /* UDP header length */

/* VLAN tag protocol identifier (TPID) */
#define ETH_TYPE_VLAN_CTAG 0x8100 /* 802.1Q VLAN TPID (802.1ad customer tag for Q-in-Q, C-Tag) */
#define ETH_TYPE_VLAN_STAG 0x88a8 /* 802.1ad service tag for Q-in-Q, S-Tag) */

#define ETH_TYPE_IP 0x0800   /* IP protocol */
#define ETH_TYPE_IPV6 0x86dd /* IPv6 protocol */
#define ETH_TYPE_ARP 0x0806  /* address resolution protocol */

#ifndef IPPROTO_ICMP
#define IPPROTO_ICMP 1 /* internet control message protocol */
#endif

#ifndef IPPROTO_TCP
#define IPPROTO_TCP 6 /* transmission control protocol */
#endif

#ifndef IPPROTO_UDP
#define IPPROTO_UDP 17 /* user datagram protocol */
#endif

#ifndef IPPROTO_ICMPV6
#define IPPROTO_ICMPV6 58 /* internet control message protocol version 6 */
#endif

/* bittwist */
#define LINERATE_MIN 0     /* Mbps (0 means no limit) */
#define LINERATE_MAX 10000 /* Mbps */
#define PKT_PAD 0x00       /* packet padding */
#define PPS_MAX 1000000    /* max. packets per second */
#define GAP_MAX 86400      /* arbitrary max. inter-packet gap in seconds */
#define JUMBO_MAX_LEN 9014 /* max. jumbo frame length, excluding CRC */

#ifdef _WIN32
#define SEND_QUEUE_MAX_PACKETS 15      /* max. packets in send queue */
#define JUMBO_SEND_QUEUE_MAX_PACKETS 2 /* max. packets in send queue for jumbo frames */
#endif                                 /* _WIN32 */

/* bittwiste */
#define PKT_MAX_LEN 65535      /* max. packet size in bytes (WARNING; larger than typical MTU) */
#define FIELD_SET 1            /* overwrite with new value */
#define FIELD_REPLACE 2        /* overwrite matching value with new value */
#define FIELD_SET_RAND 3       /* overwrite with random value */
#define FIELD_REPLACE_RAND 4   /* overwrite matching value with random value */
#define FIELD_SET_RANGE 5      /* overwrite with new value of random length within range */
#define FIELD_SET_RAND_RANGE 6 /* overwrite with random value of random length within range */
#define GAP_START 946684800    /* arbitrary start time when using custom inter-packet gap */

/* supported header specification (dummy values) */
#define ETH 1
#define VLAN 2
#define ARP 3
#define IP 4
#define IP6 40
#define ICMP 5
#define ICMP6 50
#define TCP 6
#define UDP 7

#define VLAN_MAX_DEPTH 4 /* max. nesting level for VLAN stacking (Q-in-Q) */
#define VLAN_ID_MAX 4095 /* max. value for 12-bit VLAN ID */
#define VLAN_PCP_MAX 7   /* max. value for 3-bit VLAN PCP */

#define IP_FO_MAX 7770             /* max. IP fragment offset (number of 64-bit segments) */
#define IP6_FLOW_LABEL_MAX 1048575 /* 20-bit flow label: 0x00000 to 0xfffff (1048575) */
#define DS_FIELD_MAX 63            /* 6-bit DS field */
#define ECN_FIELD_MAX 3            /* 2-bit ECN field */

#define PCAP_PREAMBLE_LEN 24       /* pcap file header length */
#define PCAP_HDR_LEN 16            /* pcap header length (pcap_sf_pkthdr) */
#define PCAP_MAGIC 0xa1b2c3d4      /* pcap magic number (timestamps in microsecond resolution)*/
#define NSEC_PCAP_MAGIC 0xa1b23c4d /* pcap magic number (timestamps in nanosecond resolution) */

#ifndef timespecisset
#define timespecisset(tsp) ((tsp)->tv_sec || (tsp)->tv_nsec)
#endif

#ifndef timespeccmp
#define timespeccmp(ctsp, ptsp, cmp)                                                               \
    (((ctsp)->tv_sec == (ptsp)->tv_sec) ? ((ctsp)->tv_nsec cmp(ptsp)->tv_nsec)                     \
                                        : ((ctsp)->tv_sec cmp(ptsp)->tv_sec))
#endif

#ifndef timespecsub
#define timespecsub(ctsp, ptsp, vtsp)                                                              \
    do                                                                                             \
    {                                                                                              \
        (vtsp)->tv_sec = (ctsp)->tv_sec - (ptsp)->tv_sec;                                          \
        (vtsp)->tv_nsec = (ctsp)->tv_nsec - (ptsp)->tv_nsec;                                       \
        if ((vtsp)->tv_nsec < 0)                                                                   \
        {                                                                                          \
            (vtsp)->tv_sec--;                                                                      \
            (vtsp)->tv_nsec += 1000000000L;                                                        \
        }                                                                                          \
    } while (0)
#endif

#define pcap_timeval_usadd(ts, us)                                                                 \
    do                                                                                             \
    {                                                                                              \
        uint64_t total_usec = (ts)->tv_usec + (us);                                                \
        (ts)->tv_sec += total_usec / 1000000;                                                      \
        (ts)->tv_usec = total_usec % 1000000;                                                      \
    } while (0)

#define pcap_timeval_nsadd(ts, ns)                                                                 \
    do                                                                                             \
    {                                                                                              \
        uint64_t total_usec = (ts)->tv_usec + (ns);                                                \
        (ts)->tv_sec += total_usec / 1000000000L;                                                  \
        (ts)->tv_usec = total_usec % 1000000000L;                                                  \
    } while (0)

/* Ethernet header */
struct ethhdr
{
    uint8_t eth_dhost[ETH_ADDR_LEN];
    uint8_t eth_shost[ETH_ADDR_LEN];
    uint16_t eth_type; /* if VLAN, set to 0x8100 */
};

/* VLAN header */
struct vlanhdr
{
    union
    {
        /*
        16-bit tag control information (TCI):
        000. .... .... .... = priority code point (PCP); ranges from 0 to 7
        ...0 .... .... .... = drop eligible indicator (DEI) or canonical format indicator (CFI)
        .... 0000 0000 0000 = VLAN ID; ranges from 0 to 4095
        */
        uint16_t vlan_tci;
        struct
        {
#if __BYTE_ORDER == __LITTLE_ENDIAN
            uint16_t vlan_id : 12; /* VLAN ID, bits 0-11 */
            uint16_t vlan_dei : 1; /* drop eligible indicator (DEI), bit 12 */
            uint16_t vlan_pcp : 3; /* priority code point (PCP), bits 13-15 */
#else
            uint16_t vlan_pcp : 3; /* priority code point (PCP), bits 15-13 */
            uint16_t vlan_dei : 1; /* drop eligible indicator (DEI), bit 12 */
            uint16_t vlan_id : 12; /* VLAN ID, bits 11-0 */
#endif
        } tci_fields;
    } tci_un;
    uint16_t eth_type; /* encapsulated protocol */
} __packed_vlanhdr;

#define vlan_tci tci_un.vlan_tci
#define vlan_id tci_un.tci_fields.vlan_id
#define vlan_dei tci_un.tci_fields.vlan_dei
#define vlan_pcp tci_un.tci_fields.vlan_pcp

#define VLAN_ID_MASK 0x0fff  /* mask for VLAN ID */
#define VLAN_DEI_MASK 0x1000 /* mask for DEI */
#define VLAN_PCP_MASK 0xe000 /* mask for PCP */

#define GET_VLAN_ID(tci) ((ntohs(tci) & VLAN_ID_MASK))
/* clear existing value in TCI then bitwise OR with new value */
#define SET_VLAN_ID(tci, vlan_id) (htons(((ntohs(tci) & ~VLAN_ID_MASK) | ((vlan_id)&VLAN_ID_MASK))))

#define GET_VLAN_DEI(tci) (((ntohs(tci) & VLAN_DEI_MASK) >> 12))
#define SET_VLAN_DEI(tci, dei) (htons(((ntohs(tci) & ~VLAN_DEI_MASK) | (((dei)&0x1) << 12))))

#define GET_VLAN_PCP(tci) ((ntohs(tci) & VLAN_PCP_MASK) >> 13)
#define SET_VLAN_PCP(tci, pcp) (htons(((ntohs(tci) & ~VLAN_PCP_MASK) | (((pcp)&0x7) << 13))))

/* Ethernet ARP header */
struct arphdr
{
    uint16_t ar_hrd;              /* format of hardware address */
#define ARPHRD_ETHER 1            /* ethernet hardware format */
#define ARPHRD_IEEE802 6          /* token-ring hardware format */
#define ARPHRD_ARCNET 7           /* arcnet hardware format */
#define ARPHRD_FRELAY 15          /* frame relay hardware format */
#define ARPHRD_IEEE1394 24        /* firewire hardware format */
    uint16_t ar_pro;              /* format of protocol address */
    uint8_t ar_hln;               /* length of hardware address */
    uint8_t ar_pln;               /* length of protocol address */
    uint16_t ar_op;               /* one of: */
#define ARPOP_REQUEST 1           /* request to resolve address */
#define ARPOP_REPLY 2             /* response to previous request */
#define ARPOP_REVREQUEST 3        /* request protocol address given hardware */
#define ARPOP_REVREPLY 4          /* response giving protocol address */
#define ARPOP_INVREQUEST 8        /* request to identify peer */
#define ARPOP_INVREPLY 9          /* response identifying peer */
    uint8_t ar_sha[ETH_ADDR_LEN]; /* sender hardware address */
    uint8_t ar_spa[IP_ADDR_LEN];  /* sender protocol address */
    uint8_t ar_tha[ETH_ADDR_LEN]; /* target hardware address */
    uint8_t ar_tpa[IP_ADDR_LEN];  /* target protocol address */
};

/* IPv4 header */
struct ip
{
#if __BYTE_ORDER == __LITTLE_ENDIAN
    uint8_t ip_hl : 4; /* header length */
    uint8_t ip_v : 4;  /* version */
#else
    uint8_t ip_v : 4;              /* version */
    uint8_t ip_hl : 4;             /* header length */
#endif
    uint8_t ip_tos;                /* type of service */
    uint16_t ip_len;               /* total length */
    uint16_t ip_id;                /* identification */
    uint16_t ip_off;               /* fragment offset field */
#define IP_RF 0x8000               /* reserved fragment flag */
#define IP_DF 0x4000               /* dont fragment flag */
#define IP_MF 0x2000               /* more fragments flag */
#define IP_OFFMASK 0x1fff          /* mask for fragmenting bits */
    uint8_t ip_ttl;                /* time to live */
    uint8_t ip_p;                  /* protocol */
    uint16_t ip_sum;               /* checksum */
    struct in_addr ip_src, ip_dst; /* source and destination address */
} __packed_ip;

/* IPv6 header */
struct ip6
{
    union
    {
        struct ip6_hdrctl
        {
            uint32_t ip6_un1_flow; /* 4-bit version, 8-bit traffic class, 20-bit flow label */
            uint16_t ip6_un1_plen; /* 16-bit payload length */
            uint8_t ip6_un1_nxt;   /* 8-bit next header */
            uint8_t ip6_un1_hlim;  /* 8-bit hop limit */
        } ip6_un1;
        uint8_t ip6_un2_vfc; /* 4-bit version, top 4-bit traffic class */
    } ip6_ctlun;
    struct in6_addr ip6_src; /* 128-bit source address */
    struct in6_addr ip6_dst; /* 128-bit destination address */
} __packed_ip6;

/*
Sample IPv6 packet showing how Wireshark decodes flow info (ip6_flow):

Frame 1: 86 bytes on wire (688 bits), 86 bytes captured (688 bits)
Ethernet II, Src: aa:aa:aa:aa:aa:aa (aa:aa:aa:aa:aa:aa), Dst: bb:bb:bb:bb:bb:bb (bb:bb:bb:bb:bb:bb)
Internet Protocol Version 6, Src: 2606:4700:4700::64, Dst: 2606:4700:4700::6400
    0110 ....                               = Version: 6
    .... 0000 0000 .... .... .... .... .... = Traffic Class: 0x00 (DSCP: CS0, ECN: Not-ECT)
    .... .... .... 0011 0101 0001 1011 0011 = Flow Label: 0x351b3
    Payload Length: 32
    Next Header: TCP (6)
    Hop Limit: 53
    Source Address: 2606:4700:4700::64
    Destination Address: 2606:4700:4700::6400
Transmission Control Protocol, Src Port: 30000, Dst Port: 60000, Seq: 1, Ack: 1, Len: 0
*/
#define ip6_flow ip6_ctlun.ip6_un1.ip6_un1_flow
#define ip6_plen ip6_ctlun.ip6_un1.ip6_un1_plen
#define ip6_nxt ip6_ctlun.ip6_un1.ip6_un1_nxt
#define ip6_hlim ip6_ctlun.ip6_un1.ip6_un1_hlim

#define IP6_FLOWLABEL_MASK (htonl(0x000fffff)) /* 20-bit flow label (network byte order) */

/* IPv4 pseudo header for computing TCP and UDP checksums */
struct ippseudo
{
    struct in_addr ippseudo_src; /* source address */
    struct in_addr ippseudo_dst; /* destination address */
    uint8_t ippseudo_pad;        /* pad, must be zero */
    uint8_t ippseudo_p;          /* protocol */
    uint16_t ippseudo_len;       /* protocol length */
};

/* IPv6 pseudo header for computing ICMPv6, TCP and UDP checksums */
struct ip6pseudo
{
    struct in6_addr ip6pseudo_src; /* 128-bit source address */
    struct in6_addr ip6pseudo_dst; /* 128-bit destination address */
    uint32_t ip6pseudo_len;        /* 32-bit upper-layer packet length */
    uint8_t ip6pseudo_zero[3];     /* 24-bit zeros */
    uint8_t ip6pseudo_nxt;         /* 8-bit next header */
};

/* ICMP header (up to checksum field only) */
struct icmphdr
{
    uint8_t icmp_type;   /* type field */
    uint8_t icmp_code;   /* code field */
    uint16_t icmp_cksum; /* checksum field */
};

/* ICMPv6 header (up to checksum field only) */
struct icmp6hdr
{
    uint8_t icmp6_type;   /* type field */
    uint8_t icmp6_code;   /* code field */
    uint16_t icmp6_cksum; /* checksum field */
};

/* TCP header */
struct tcphdr
{
    uint16_t th_sport; /* source port */
    uint16_t th_dport; /* destination port */
    uint32_t th_seq;   /* sequence number */
    uint32_t th_ack;   /* acknowledgment number */
#if __BYTE_ORDER == __LITTLE_ENDIAN
    uint8_t th_x2 : 4;  /* (unused) */
    uint8_t th_off : 4; /* data offset in number of 32-bit words */
#else
    uint8_t th_off : 4;            /* data offset in number of 32-bit words */
    uint8_t th_x2 : 4;             /* (unused) */
#endif
    uint8_t th_flags;
#define TH_FIN 0x01  /* no more data from sender */
#define TH_SYN 0x02  /* synchronize sequence numbers */
#define TH_RST 0x04  /* reset the connection */
#define TH_PUSH 0x08 /* push function */
#define TH_ACK 0x10  /* acknowledgment field is significant */
#define TH_URG 0x20  /* urgent pointer field is significant */
#define TH_ECE 0x40  /* explicit congestion notification echo */
#define TH_CWR 0x80  /* congestion window reduced */
#define TH_FLAGS (TH_FIN | TH_SYN | TH_RST | TH_PUSH | TH_ACK | TH_URG | TH_ECE | TH_CWR)
    uint16_t th_win; /* window */
    uint16_t th_sum; /* checksum */
    uint16_t th_urp; /* urgent pointer */
};

/* UDP header */
struct udphdr
{
    uint16_t uh_sport; /* source port */
    uint16_t uh_dport; /* destination port */
    uint16_t uh_ulen;  /* udp length */
    uint16_t uh_sum;   /* udp checksum */
};

/* Payload options */
struct payload_opt
{
    uint8_t *payload; /* payload in hex digits */
    uint16_t len;     /* final length of payload in bytes */
    uint16_t min_len; /* min.length of payload in bytes */
    uint16_t max_len; /* max. length of payload in bytes */
    uint8_t flag;

    /* pointer to function to update payload and len according to the specified options */
    void (*update_payload)(struct payload_opt *opt, uint16_t cur_len);
};

/*
 * Structures for bittwiste header specific options.
 */
struct eth_addr_opt
{
    uint8_t old[ETH_ADDR_LEN]; /* 48-bit Ethernet address */
    uint8_t new[ETH_ADDR_LEN];
    uint8_t flag;
};

struct ethopt
{
    struct eth_addr_opt dhost;
    struct eth_addr_opt shost;
    uint16_t old_eth_type;
    uint16_t new_eth_type;
    uint8_t eth_type_flag;
};

struct vlanopt
{
    uint16_t vlan_old_id; /* VLAN ID (0 to 4095) */
    uint16_t vlan_new_id;
    uint8_t vlan_id_flag;
    uint16_t vlan_old_dei; /* DEI (0 or 1) */
    uint16_t vlan_new_dei;
    uint8_t vlan_dei_flag;
    uint16_t vlan_old_pcp; /* PCP (0 to 7) */
    uint16_t vlan_new_pcp;
    uint8_t vlan_pcp_flag;
    uint16_t vlan_old_eth_type; /* encapsulated protocol */
    uint16_t vlan_new_eth_type;
    uint8_t vlan_eth_type_flag;
};

struct arpopt
{
    uint16_t ar_op; /* opcode */
    uint8_t ar_op_flag;
    struct eth_addr_opt sha;         /* sender hardware address */
    uint8_t ar_old_spa[IP_ADDR_LEN]; /* sender protocol address */
    uint8_t ar_new_spa[IP_ADDR_LEN];
    uint8_t ar_spa_flag;
    struct eth_addr_opt tha;         /* target hardware address */
    uint8_t ar_old_tpa[IP_ADDR_LEN]; /* target protocol address */
    uint8_t ar_new_tpa[IP_ADDR_LEN];
    uint8_t ar_tpa_flag;
};

struct in_addr_opt
{
    struct in_addr old; /* 32-bit IPv4 address */
    struct in_addr new;
    struct in_addr netmask; /* netmask to use when randomizing address */
    uint8_t rand_bits;      /* number of bits available to the right that can be randomized */
    uint8_t flag;
};

struct ipopt
{
    uint8_t ip_ds_field; /* 6-bit DS field (first 6-bit of 8-bit type of service field) */
    uint8_t ip_ds_field_flag;
    uint8_t ip_ecn_field; /* 2-bit ECN field (last 2-bit of 8-bit type of service field) */
    uint8_t ip_ecn_field_flag;
    uint16_t ip_old_id; /* identification */
    uint16_t ip_new_id;
    uint8_t ip_id_flag;
    uint8_t ip_flag_r; /* reserved bit */
    uint8_t ip_flag_d; /* don't fragment bit */
    uint8_t ip_flag_m; /* more fragment bit */
    uint8_t ip_flags_flag;
    uint16_t ip_fo; /* fragment offset in bytes */
    uint8_t ip_fo_flag;
    uint8_t ip_old_ttl; /* time to live */
    uint8_t ip_new_ttl;
    uint8_t ip_ttl_flag;
    uint8_t ip_old_p; /* protocol */
    uint8_t ip_new_p;
    uint8_t ip_p_flag;
    struct in_addr_opt ip_src; /* options for source address */
    struct in_addr_opt ip_dst; /* options for destination address */
};

struct in6_addr_opt
{
    struct in6_addr old; /* 128-bit IPv6 address */
    struct in6_addr new;
    struct in6_addr netmask; /* netmask to use when randomizing address */
    uint8_t rand_bits;       /* number of bits available to the right that can be randomized */
    uint8_t flag;
};

struct ip6opt
{
    uint8_t ip6_ds_field; /* 6-bit DS field (first 6-bit of 8-bit traffic class field) */
    uint8_t ip6_ds_field_flag;
    uint8_t ip6_ecn_field; /* 2-bit ECN field  (last 2-bit of 8-bit traffic class field) */
    uint8_t ip6_ecn_field_flag;
    uint32_t ip6_flow_label; /* 20-bit flow label */
    uint8_t ip6_flow_label_flag;
    uint8_t ip6_old_next_header; /* 8-bit next header */
    uint8_t ip6_new_next_header;
    uint8_t ip6_next_header_flag;
    uint8_t ip6_old_hop_limit; /* 8-bit hop limit */
    uint8_t ip6_new_hop_limit;
    uint8_t ip6_hop_limit_flag;
    struct in6_addr_opt ip6_src; /* options for source address */
    struct in6_addr_opt ip6_dst; /* options for destination address */
};

struct icmpopt
{
    uint8_t icmp_type; /* type of message */
    uint8_t icmp_type_flag;
    uint8_t icmp_code; /* type sub code */
    uint8_t icmp_code_flag;
};

struct icmp6opt
{
    uint8_t icmp6_type; /* type of message */
    uint8_t icmp6_type_flag;
    uint8_t icmp6_code; /* type sub code */
    uint8_t icmp6_code_flag;
};

struct tcpopt
{
    uint16_t th_old_sport; /* source port */
    uint16_t th_new_sport;
    uint8_t th_sport_flag;
    uint16_t th_old_dport; /* destination port */
    uint16_t th_new_dport;
    uint8_t th_dport_flag;
    uint32_t th_old_seq; /* sequence number */
    uint32_t th_new_seq;
    uint8_t th_seq_flag;
    uint32_t th_old_ack; /* acknowledgment number */
    uint32_t th_new_ack;
    uint8_t th_ack_flag;
    uint8_t th_flag_c; /* CWR */
    uint8_t th_flag_e; /* ECE */
    uint8_t th_flag_u; /* URG */
    uint8_t th_flag_a; /* ACK */
    uint8_t th_flag_p; /* PSH */
    uint8_t th_flag_r; /* RST */
    uint8_t th_flag_s; /* SYN */
    uint8_t th_flag_f; /* FIN */
    uint8_t th_flags_flag;
    uint16_t th_win; /* window */
    uint8_t th_win_flag;
    uint16_t th_urp; /* urgent pointer */
    uint8_t th_urp_flag;
};

struct udpopt
{
    uint16_t uh_old_sport; /* source port */
    uint16_t uh_new_sport;
    uint8_t uh_sport_flag;
    uint16_t uh_old_dport; /* destination port */
    uint16_t uh_new_dport;
    uint8_t uh_dport_flag;
};

#endif /* !_DEF_H_ */
