#include <sys/types.h>
#include <pcap.h>
#include "arch.h"

/* action codes  */
#define SEND_PACKET     1
#define RECV_PACKET     2
#define WAIT		3
#define	SHELL		4
#define NOT_SPEC        99
#define FINISH          100

/* Operation codes */
#define	NOP		0
#define	ADD		1
#define	SUB		2
#define	MUL		3
#define	DIV		4
#define AND		5
#define	OR		6
#define XOR		7

/* Argument codes */
#define	IMMEDIATE	1
#define THIS_PACKET	2
#define	STORED_PACKET	4
#define	RECEIVED_PACKET	8
#define	STD_CKSUM	16

struct field_off_bits{
  struct phinf  **pheaders; /* Previous headers information vector */
  u_int16_t     layer;  /* Layer */
  u_int8_t	swap;	/* Swap */
  u_int32_t     offset; /* Bits - relative value: from the beginning of the current header */
  u_int16_t     size;   /* Bits */
  u_int32_t     info;
};

struct pack_arg{
  u_int8_t			pnum;		/* Packet number 
						 * '0' for this packet
 						 * '#' for the stored packet number #
 						 * '#' for the received packet received by state #
 						 */
  struct field_off_bits         field;		/* The fields */
};

struct immediate_arg{
  u_int32_t			value;		/* The immediate */
};

struct cksum_arg{
  u_char			*header;	/* Header name */
};

struct but_args{
  u_int8_t			type;
  union {
    struct pack_arg		*p_arg;
    struct immediate_arg	*i_arg;
    struct cksum_arg		*c_arg;
  } arg_type;
#define	bp_arg	arg_type.p_arg
#define bi_arg	arg_type.i_arg
#define	bc_arg	arg_type.c_arg
};

struct but{
  struct field_off_bits		*field;		/* Field to change 	*/
  u_int8_t			operation;	/* Operation to apply 	*/
  struct but_args		**args;		/* Operation arguments	*/
};

struct send{
  u_int16_t	packet_id;		/* Packet to send ID 	*/
  u_int16_t     layer[MAX_LAYER];	/* Filled if but field is not NULL */
  u_int32_t     psize;			/* Packet to send size */
  u_char	*pack;			/* The packet to be sent*/
  u_int16_t	nobt;			/* Number of BuTs 	*/
  struct but	**but;			/* Fields to change	*/
  int32_t 	next_state;		/* Next packet		*/
};

struct phinf{		/* Previous header information about its size */
  u_int32_t	off;
  u_int32_t	size;
};

struct field_recv{
  u_int16_t			nof;            /* Number of fields to be checked */
  int32_t			next_state;     /* Next state - daaaa! */
  struct field_off_bits		*fld_vct;       /* Fields which satisfy the condition */
						/*   for joying this next state */
};

struct branch_recv{
  u_int16_t		nob;            /* Number of possible branches */
  struct field_recv	**fld_struct;   /* Field structure */
};

struct timeout {
  u_int32_t     time;
  u_int32_t     nxt;
};

struct recv{
  char			*bpf;		/* BPF expression	*/
  char			*iface;		/* Interface		*/
  struct timeout        to;		/* Pcap Timeout  	*/
  struct branch_recv    *brnch_struct;  /* Branch structure 	*/
  u_int32_t		plen;		/* Returned packet length*/
  u_char		*recvpack;	/* Returned packet 	*/
};

struct brch_in{				
  struct field_recv     info;		/* Used by the parser to deliver information */
  struct brch_in        *next;		/*    about the receive action  */
};					

struct but_in{
  struct but		*but;		/* Used by the parser to deliver information */
  struct but_in		*next;		/*  about the send action */
};

struct wait{
  unsigned long usec;
  int32_t	next_state;
};

struct shell{
  char		*command;
  int32_t	next_state;
};

struct base{
  u_int32_t state_id;
  char      *state_name;
  u_int16_t action;
  u_int8_t  *arg;
/*      This field depends on the action:
 *
 *              - SEND_PACKET:	struct send;
 *
 *              - RECV_PACKET:	struct recv;
 *
 *              - WAIT:		struct wait;
 *
 *              - SHELL:	struct shell;
 *
 */
  int32_t next; /* LOOK! the number of states must be known!!! */
};

struct hash{
  int pos;
  char *key;
};

struct yac_in {
  u_int16_t     action;
  union {
    struct send		snd;
    struct recv		rcv;
    struct wait		wt;
    struct shell 	sh;
  };
};
