/*
 * Copyright (c) 2017, Arnon Yaari
 * All rights reserved.
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

/* The kernel is always 64 bit but Python is usually compiled as a 32 bit
 * process. We're reading the kernel memory to get the network connections,
 * so we need the structs we read to be defined with 64 bit "pointers".
 * Here are the partial definitions of the structs we use, taken from the
 * header files, with data type sizes converted to their 64 bit counterparts,
 * and unused data truncated. */

#ifdef __64BIT__
/* In case we're in a 64 bit process after all */
#include <sys/socketvar.h>
#include <sys/protosw.h>
#include <sys/unpcb.h>
#include <sys/mbuf_base.h>
#include <sys/mbuf_macro.h>
#include <netinet/ip_var.h>
#include <netinet/tcp.h>
#include <netinet/tcpip.h>
#include <netinet/tcp_timer.h>
#include <netinet/tcp_var.h>
#define file64 file
#define socket64 socket
#define protosw64 protosw
#define inpcb64 inpcb
#define tcpcb64 tcpcb
#define unpcb64 unpcb
#define mbuf64 mbuf
#else       /* __64BIT__ */
  struct file64 {
    int f_flag;
    int f_count;
    int f_options;
    int f_type;
    u_longlong_t f_data;
 };

 struct socket64 {
    short   so_type;                 /* generic type, see socket.h */
    short   so_options;              /* from socket call, see socket.h */
    ushort  so_linger;               /* time to linger while closing */
    short   so_state;                /* internal state flags SS_*, below */
    u_longlong_t so_pcb;             /* protocol control block */
    u_longlong_t so_proto;           /* protocol handle */
 };

 struct protosw64 {
    short   pr_type;                 /* socket type used for */
    u_longlong_t pr_domain;          /* domain protocol a member of */
    short   pr_protocol;             /* protocol number */
    short   pr_flags;                /* see below */
 };

 struct inpcb64 {
    u_longlong_t inp_next,inp_prev;
                                     /* pointers to other pcb's */
    u_longlong_t inp_head;           /* pointer back to chain of inpcb's
                                       for this protocol */
    u_int32_t inp_iflowinfo;         /* input flow label */
    u_short inp_fport;               /* foreign port */
    u_int16_t inp_fatype;            /* foreign address type */
    union   in_addr_6 inp_faddr_6;   /* foreign host table entry */
    u_int32_t inp_oflowinfo;         /* output flow label */
    u_short inp_lport;               /* local port */
    u_int16_t inp_latype;            /* local address type */
    union   in_addr_6 inp_laddr_6;   /* local host table entry */
    u_longlong_t inp_socket;         /* back pointer to socket */
    u_longlong_t inp_ppcb;           /* pointer to per-protocol pcb */
    u_longlong_t space_rt;
    struct  sockaddr_in6 spare_dst;
    u_longlong_t inp_ifa;            /* interface address to use */
    int     inp_flags;               /* generic IP/datagram flags */
};

struct tcpcb64 {
    u_longlong_t seg__next;
    u_longlong_t seg__prev;
    short   t_state;                 /* state of this connection */
};

struct unpcb64 {
        u_longlong_t unp_socket;     /* pointer back to socket */
        u_longlong_t unp_vnode;      /* if associated with file */
        ino_t   unp_vno;             /* fake vnode number */
        u_longlong_t unp_conn;       /* control block of connected socket */
        u_longlong_t unp_refs;       /* referencing socket linked list */
        u_longlong_t unp_nextref;    /* link in unp_refs list */
        u_longlong_t unp_addr;       /* bound address of socket */
};

struct m_hdr64
{
    u_longlong_t mh_next;            /* next buffer in chain */
    u_longlong_t mh_nextpkt;         /* next chain in queue/record */
    long mh_len;                     /* amount of data in this mbuf */
    u_longlong_t mh_data;            /* location of data */
};

struct mbuf64
{
    struct m_hdr64 m_hdr;
};

#define m_len               m_hdr.mh_len

#endif      /* __64BIT__ */