This is the mail archive of the gcc-bugs@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Re: gcc error: warning: pasting "syn" and ")" does not give a valid preprocessing token


Hi Neil;
The attachment is b.c . I have embbeded all the header files
except
those common to a unix system. The file now will compile but if
you
remove the space character as decribed in my earlier message,
the
preprocessor will not replace the 'state' string. The compiling
instruction:

> gcc -E b.c > junk


Thank you,
Regards,
Kiet


Neil Booth wrote:

> Kiet Tran wrote:-
>
> > #define TCP_EXTERN(state) \
> > extern pspec_t *##state##_rcv_rst(tcb_t *,pspec_t *), \
> > ....
> >
> > I removed the leading '##' pair and found that the
> > passing parameter of the macro was not replacing
> > 'state' word. The preprocessor replaced the 'state'
> > parameter after I insert a space between the '*' character
> > and 'state##' word. Is this a real bug in the preprocessor?
>
> Please provide a complete example.
>
> Neil.
#include <stdio.h>
#include <netinet/in.h>  /* for definition of caddr_t */

typedef struct ip_opt
  {
    unsigned char len;
    unsigned char srr;
    unsigned char rr;
    unsigned char ts;
    unsigned int is_strictroute:1; /* Strict source route		  */
    unsigned int srr_is_hit:1;	   /* Packet destination addr was our one */
    unsigned int is_changed:1;	   /* IP checksum more not valid	  */
    unsigned int rr_needaddr:1;	   /* Need to record addr of outgoing dev */
    unsigned int ts_needtime:1;	   /* Need to record timestamp		  */
    unsigned int ts_needaddr:1;	   /* Need to record addr of outgoing dev */
#if 0
    u_int8_t router_alert;
    u_int8_t __pad1;
    u_int8_t __pad2;
#ifdef __GNUC__
    u_int8_t __data[0];
#endif
#endif
  } ip_opt_t;

/*
 * Definitions for options.
 */
#define	IPOPT_COPY		0x80
#define	IPOPT_CLASS_MASK	0x60
#define	IPOPT_NUMBER_MASK	0x1f

#define	IPOPT_COPIED(o)		((o) & IPOPT_COPY)
#define	IPOPT_CLASS(o)		((o) & IPOPT_CLASS_MASK)
#define	IPOPT_NUMBER(o)		((o) & IPOPT_NUMBER_MASK)

#define	IPOPT_CONTROL		0x00
#define	IPOPT_RESERVED1		0x20
#define	IPOPT_DEBMEAS		0x40
#define	IPOPT_MEASUREMENT       IPOPT_DEBMEAS
#define	IPOPT_RESERVED2		0x60

#define	IPOPT_EOL		0		/* end of option list */
#define	IPOPT_END		IPOPT_EOL
#define	IPOPT_NOP		1		/* no operation */
#define	IPOPT_NOOP		IPOPT_NOP

#define	IPOPT_RR		7		/* record packet route */
#define	IPOPT_TS		68		/* timestamp */
#define	IPOPT_TIMESTAMP		IPOPT_TS
#define	IPOPT_SECURITY		130		/* provide s,c,h,tcc */
#define	IPOPT_SEC		IPOPT_SECURITY
#define	IPOPT_LSRR		131		/* loose source route */
#define	IPOPT_SATID		136		/* satnet id */
#define	IPOPT_SID		IPOPT_SATID
#define	IPOPT_SSRR		137		/* strict source route */
#define	IPOPT_RA		148		/* router alert */

/*
 * Offsets to fields in options other than EOL and NOP.
 */
#define	IPOPT_OPTVAL		0		/* option ID */
#define	IPOPT_OLEN		1		/* option length */
#define	IPOPT_OFFSET		2		/* offset within option */
#define	IPOPT_MINOFF		4		/* min value of above */

#define	MAX_IPOPTLEN		40

/* flag bits for ipt_flg */
#define	IPOPT_TS_TSONLY		0		/* timestamps only */
#define	IPOPT_TS_TSANDADDR	1		/* timestamps and addresses */
#define	IPOPT_TS_PRESPEC	3		/* specified modules only */

/* bits for security (not byte swapped) */
#define	IPOPT_SECUR_UNCLASS	0x0000
#define	IPOPT_SECUR_CONFID	0xf135
#define	IPOPT_SECUR_EFTO	0x789a
#define	IPOPT_SECUR_MMMM	0xbc4d
#define	IPOPT_SECUR_RESTR	0xaf13
#define	IPOPT_SECUR_SECRET	0xd788
#define	IPOPT_SECUR_TOPSECRET	0x6bc5

/*
 * List definitions.
 */
#define LIST_HEAD(name, type)						\
struct name {								\
	struct type *lh_first;	/* first element */			\
}

#define LIST_ENTRY(type)						\
struct {								\
	struct type *le_next;	/* next element */			\
	struct type **le_prev;	/* address of previous next element */	\
}

/*
 * List functions.
 */
#define	LIST_INIT(head) {						\
	(head)->lh_first = NULL;					\
}

#define LIST_INSERT_AFTER(listelm,elm,field) {			\
	if (((elm)->field.le_next = (listelm)->field.le_next) != NULL)	\
		(listelm)->field.le_next->field.le_prev =		\
		    &(elm)->field.le_next;				\
	(listelm)->field.le_next = (elm);				\
	(elm)->field.le_prev = &(listelm)->field.le_next;		\
}

#define LIST_INSERT_HEAD(head, elm, field) {				\
	if (((elm)->field.le_next = (head)->lh_first) != NULL)		\
		(head)->lh_first->field.le_prev = &(elm)->field.le_next;\
	(head)->lh_first = (elm);					\
	(elm)->field.le_prev = &(head)->lh_first;			\
}

#define LIST_REMOVE(elm, field) {					\
	if ((elm)->field.le_next != NULL)				\
		(elm)->field.le_next->field.le_prev = 			\
		    (elm)->field.le_prev;				\
	*(elm)->field.le_prev = (elm)->field.le_next;			\
}

/*
 * Tail queue definitions.
 */
#define TAILQ_HEAD(name, type)						\
struct name {								\
	struct type *tqh_first;	/* first element */			\
	struct type **tqh_last;	/* addr of last next element */		\
}

#define TAILQ_ENTRY(type)						\
struct {								\
	struct type *tqe_next;	/* next element */			\
	struct type **tqe_prev;	/* address of previous next element */	\
}

/*
 * Tail queue functions.
 */
#define	TAILQ_INIT(head) {						\
	(head)->tqh_first = NULL;					\
	(head)->tqh_last = &(head)->tqh_first;				\
}

#define TAILQ_INSERT_HEAD(head, elm, field) {				\
	if (((elm)->field.tqe_next = (head)->tqh_first) != NULL)	\
		(elm)->field.tqe_next->field.tqe_prev =			\
		    &(elm)->field.tqe_next;				\
	else								\
		(head)->tqh_last = &(elm)->field.tqe_next;		\
	(head)->tqh_first = (elm);					\
	(elm)->field.tqe_prev = &(head)->tqh_first;			\
}

#define TAILQ_INSERT_TAIL(head, elm, field) {				\
	(elm)->field.tqe_next = NULL;					\
	(elm)->field.tqe_prev = (head)->tqh_last;			\
	*(head)->tqh_last = (elm);					\
	(head)->tqh_last = &(elm)->field.tqe_next;			\
}

#define TAILQ_INSERT_AFTER(head, listelm, elm, field) {			\
	if (((elm)->field.tqe_next = (listelm)->field.tqe_next) != NULL)\
		(elm)->field.tqe_next->field.tqe_prev = 		\
		    &(elm)->field.tqe_next;				\
	else								\
		(head)->tqh_last = &(elm)->field.tqe_next;		\
	(listelm)->field.tqe_next = (elm);				\
	(elm)->field.tqe_prev = &(listelm)->field.tqe_next;		\
}

#define TAILQ_REMOVE(head, elm, field) {				\
	if (((elm)->field.tqe_next) != NULL)				\
		(elm)->field.tqe_next->field.tqe_prev = 		\
		    (elm)->field.tqe_prev;				\
	else								\
		(head)->tqh_last = (elm)->field.tqe_prev;		\
	*(elm)->field.tqe_prev = (elm)->field.tqe_next;			\
}

/*
 * Circular queue definitions.
 */
#define CIRCLEQ_HEAD(name, type)					\
struct name {								\
	struct type *cqh_first;		/* first element */		\
	struct type *cqh_last;		/* last element */		\
}

#define CIRCLEQ_ENTRY(type)						\
struct {								\
	struct type *cqe_next;		/* next element */		\
	struct type *cqe_prev;		/* previous element */		\
}

/*
 * Circular queue functions.
 */
#define	CIRCLEQ_INIT(head) {						\
	(head)->cqh_first = (void *)(head);				\
	(head)->cqh_last = (void *)(head);				\
}

#define CIRCLEQ_INSERT_AFTER(head, listelm, elm, field) {		\
	(elm)->field.cqe_next = (listelm)->field.cqe_next;		\
	(elm)->field.cqe_prev = (listelm);				\
	if ((listelm)->field.cqe_next == (void *)(head))		\
		(head)->cqh_last = (elm);				\
	else								\
		(listelm)->field.cqe_next->field.cqe_prev = (elm);	\
	(listelm)->field.cqe_next = (elm);				\
}

#define CIRCLEQ_INSERT_BEFORE(head, listelm, elm, field) {		\
	(elm)->field.cqe_next = (listelm);				\
	(elm)->field.cqe_prev = (listelm)->field.cqe_prev;		\
	if ((listelm)->field.cqe_prev == (void *)(head))		\
		(head)->cqh_first = (elm);				\
	else								\
		(listelm)->field.cqe_prev->field.cqe_next = (elm);	\
	(listelm)->field.cqe_prev = (elm);				\
}

#define CIRCLEQ_INSERT_HEAD(head, elm, field) {				\
	(elm)->field.cqe_next = (head)->cqh_first;			\
	(elm)->field.cqe_prev = (void *)(head);				\
	if ((head)->cqh_last == (void *)(head))				\
		(head)->cqh_last = (elm);				\
	else								\
		(head)->cqh_first->field.cqe_prev = (elm);		\
	(head)->cqh_first = (elm);					\
}

#define CIRCLEQ_INSERT_TAIL(head, elm, field) {				\
	(elm)->field.cqe_next = (void *)(head);				\
	(elm)->field.cqe_prev = (head)->cqh_last;			\
	if ((head)->cqh_first == (void *)(head))			\
		(head)->cqh_first = (elm);				\
	else								\
		(head)->cqh_last->field.cqe_next = (elm);		\
	(head)->cqh_last = (elm);					\
}

#define	CIRCLEQ_REMOVE(head, elm, field) {				\
	if ((elm)->field.cqe_next == (void *)(head))			\
		(head)->cqh_last = (elm)->field.cqe_prev;		\
	else								\
		(elm)->field.cqe_next->field.cqe_prev =			\
		    (elm)->field.cqe_prev;				\
	if ((elm)->field.cqe_prev == (void *)(head))			\
		(head)->cqh_first = (elm)->field.cqe_next;		\
	else								\
		(elm)->field.cqe_prev->field.cqe_next =			\
		    (elm)->field.cqe_next;				\
}
#define MAX_TCPOPTLEN	40

typedef unsigned char octet_t[6];

struct tcp_opt {
	char	optlist[MAX_TCPOPTLEN]; /* This list has TCPOPT_XXX options;
				 * it's terminated with a TCPOPT_EOL */
	int	len; 		/* length of tcp option field */
        char 	saw_tstamp;	/* flag for timestamp exists */
        char 	tstamp_ok;	/* flag set when timestamp is negotiated */
        char	sack_ok;	/* flag set when selective ack is negotiated */
        unsigned long rcv_tsval;
        unsigned long rcv_tsecr;
        int     num_sacks;
};

/* TCP attributes of pspec struct, each of the field is directly
 * related to fields in a TCP packet
 */
typedef struct
{
	unsigned short  sport;		/* source port */
	unsigned short  dport; 		/* dest port */
	unsigned long   seq;		/* sequence # */
	unsigned long   ack;		/* ack # */
	unsigned char   flags;		/* TCP flags */
	unsigned short  win;		/* window */
	unsigned short  opwin;		/* opportunity window */
	unsigned long   mss;		/* max segment size */
	unsigned long   wscale;		/* window scale */
	unsigned long   ts;		/* time stamp */
	unsigned long   ts_echo_reply;	/* time stamp echo reply */
	struct tcp_opt  option;		/* option values struct */
	char            opt_str[MAX_TCPOPTLEN]; /* literal string of options
					 * from the incoming packet */
	int             opt_str_len;	/* payload length */
	int             datalen;	/* payload length */
	int             pad; 		/* flag 1: pad to 32-bit word */
	int             csum_err;	/* set if tcp csum error */
} pspec_tcp_t;

/* UDP attributes of pspec struct */
typedef struct
{
	unsigned short  sport;
	unsigned short  dport;
	unsigned short  datalen;
	int             udp_pad;
	int  csum_err;              /* we will do checksums */
} pspec_udp_t;

/* ICMP attributes of the pspec struct */
typedef struct
{
	unsigned char   type;
	unsigned char   code;
	unsigned short  datalen;
	int             icmp_pad;
	union {
		unsigned long gateway; 
		struct {
			unsigned short   id;
			unsigned short   sequence;
		} echo;
		struct {
			unsigned short	unused;
			unsigned short	mtu;
		} frag;
	} un;
	int  csum_err;              /* we will do checksums */
} pspec_icmp_t;

/* ARP attributes of pspec struct */
typedef struct
{
	unsigned short prot;
	unsigned short  op;
} pspec_arp_t;

/* pspec struct is a C-formatted form of a
 * IP frame and its transport protocol.
 * A new packet is built by filling out all 
 * members of this struct, tcpgen() converts
 * the filled struct into the IP frame format
 * ready to be sent to an ethernet device.
 * Vice versa, on the receiving side, tcpsink()
 * converts the ethernet IP frame from the 
 * network into pspec form for the calling C
 * routine to parse struct members.
 */
typedef struct pspec
{
	octet_t		daddr; 		/* dest mac addr */
	octet_t		saddr; 		/* source mac addr */
	unsigned long	sip;		/* source IP addr */
	unsigned long	dip;		/* dest IP addr */
	struct vlan_en			/* optional VLAN enable fields */
	{
		unsigned short type; 	/* 801Q or ??? */
		unsigned short num;  	/* vlan number, 0 is valid */
	} vlan;
	unsigned short  ip_id;		/* 16-bit Identification in the IP header */
	unsigned short  ip_offset; 	/* IP offset field */
	unsigned char   ip_tos;		/* type of service */
	unsigned char   ip_ttl; 	/* time-to-live */
	char		ip_optlist[MAX_IPOPTLEN];/* if not NULL, this is the IP option types list */
	struct ip_opt   ip_option;		/* values used in the enabled option types */
	int		ip_pad; 	/* 1: pad to min frame size */
	int		csum_err; 	/* set if ip csum error */
	unsigned char	*data; 		/* protocol payload start */
	union
	{
		unsigned short	offset;
		pspec_tcp_t	tcp;		/* TCP attributes */
        	pspec_udp_t     udp;		/* UDP attributes */
		pspec_icmp_t    icmp;		/* ICMP attributes */
		pspec_arp_t     arp;		/* ARP attributes */
	} u; /* union pointing to either transport or upper MAC packets */
	unsigned short predict_id;	/* prediction id */
	LIST_ENTRY(pspec) predict;
} pspec_t;

/*
 * Ether frame format.
 */
typedef struct ether
{
	octet_t		daddr;
	octet_t		saddr;
	unsigned char	type[2];
	unsigned char	data[1];
} ether_t;
#define ETHER_HDR_SZ	(sizeof(ether_t) - 1)

/*
 * vlan encap frame format.
 */
typedef struct vlan_encap_struct
{
	octet_t		daddr;
	octet_t		saddr;
	unsigned char	type[2];
	unsigned char	vlan[2];
	unsigned char	data[1];
} vlan_ether_t;

#define VLAN_TYPE	0x8100
/*
 * 802.2 encapsulation -- SNAP/LLC
 */
typedef struct snap
{
#define DSAP_OR_SSAP    0xAA
#define LLC_CNTL        0x03
#define SNAP_ORG_CODE   0x00
#define SNAP_ADDL_BYTES 0x08
	octet_t		daddr;
	octet_t		saddr;
	unsigned char   length[2];
	unsigned char   dsap[1]; /* AA */
	unsigned char   ssap[1]; /* AA */
	unsigned char   cntl[1]; /* 03 */
	unsigned char   org_code[3]; /* 0 */
	unsigned char   type[2];
	unsigned char	data[1];
} snap_t;
#define SNAP_HDR_SZ   (sizeof(snap_t) - 1)

typedef struct packet
{
	ether_t		ether;
	unsigned char	data[1499];
	unsigned char	crc[4];
} packet_t;
#define MAX_ETHER_FRAME	(sizeof(packet_t) - 4)

/* Prototypes */
pspec_t *tcpsink(pspec_t *pspec, ether_t *ether, int len);
ether_t *tcpgen(void *p, pspec_t *pspec, unsigned short *len);
pspec_t *udpsink(pspec_t *pspec, ether_t *ether, int len);
ether_t *udpgen(void *p, pspec_t *pspec, unsigned short *len);
pspec_t *icmpsink(pspec_t *pspec, ether_t *ether, int len);
ether_t *icmpgen(void *p, pspec_t *pspec, unsigned short *len);
ether_t *arpgen(void *p, pspec_t *pspec, unsigned short *lenp, int pad);
pspec_t *arpsink(pspec_t *pspec, ether_t *ether, int len);
snap_t *snapgen(void *p, pspec_t *pspec, unsigned short *lenp);
int snapsink(pspec_t *pspec, snap_t *snap, int len);
extern int (*protocol_recv) (unsigned short len, unsigned short vlan, 
			     unsigned char *buf);
void pgen_display_tuple (pspec_t *pspec);
void loadshort(unsigned char *p, unsigned short s);
void loadlong(unsigned char *p, unsigned long l);
unsigned short getshort(unsigned char *p);
unsigned long getlong(unsigned char *p);


#define tcp_MAX_DATA	1460
#define MAX_DATA 1460
#define MAX_OPTION  40
#define ETHER_MAC_SZ 6

typedef unsigned char maddr_t[ETHER_MAC_SZ];
typedef unsigned long ipaddr_t;
typedef unsigned long handle_t;

typedef enum
{
  CLIENT = 1,
  SERVER = 2
} client_server_t;

typedef enum
{
  OPTCMD_STACK,
  OPTCMD_NONE,
  OPTCMD_OVERRIDE
} optcmd_t;

typedef struct
{
    optcmd_t cmd;
    unsigned char *list;
    int          len;
} ipopt_t;

#define SLB_MAC_ADDR      {0x00, 0x01, 0x02, 0x03, 0x04, 0x05}
#define CLIENT_MAC_ADDR   {0x11, 0x12, 0x13, 0x14, 0x15, 0x16}
#define SERVER_MAC_ADDR   {0xa1, 0xb2, 0xc3, 0xd4, 0xe5, 0xf6}

#define SLB_IP_ADDR       0xcdbcf742
#define CLIENT_IP_ADDR    0x01feedbf
#define SERVER_IP_ADDR    0x01feedbe

#define DEFAULT_VLAN_TAG  0x55aa
#define SLB_VLAN_TAG      DEFAULT_VLAN_TAG
/*
 * some randomly chosen number, different from
 * DEFAULT_VLAN_TAG
 */
#define CLIENT_VLAN_TAG   0x007B 
#define SERVER_VLAN_TAG   0xbeee

#define SLB_IP_ID         0x00
#define CLIENT_IP_ID      0xbead
#define SERVER_IP_ID      0xcafe

#define SLB_RECV_PORT     0x50
#define CLIENT_RECV_PORT  0x00
#define SERVER_RECV_PORT  0x80

#define GMAC_VLAN_TYPE    0x0081

#define DEFAULT_INTERFACE(INTF, PROTOCOL) \
        INTF##_MAC_ADDR, INTF##_VLAN_TAG, INTF##_IP_ADDR,  \
        INTF##_IP_ID, INTF##_RECV_PORT, 0x00, PROTOCOL

#define DEFAULT_UDP_INTERFACE(I) DEFAULT_INTERFACE(I, IPPROTO_UDP)

#define DEFAULT_ICMP_INTERFACE(INTF) \
        INTF##_MAC_ADDR, INTF##_VLAN_TAG, INTF##_IP_ADDR,  \
        INTF##_IP_ID, IPPROTO_ICMP

#define DEFAULT_ARP_INTERFACE(INTF)  \
        INTF##_MAC_ADDR, INTF##_VLAN_TAG, INTF##_IP_ADDR
#define	ENABLE_SEQ_NUM_CHECK 0	/* TURN ON TO ENABLE SEQ # CHECK */

#define SEQ_LT(a,b)  ( (int)((a)-(b)) <  0 )
#define SEQ_LEQ(a,b) ( (int)((a)-(b)) <= 0 )
#define SEQ_GT(a,b)  ( (int)((a)-(b)) >  0 )
#define SEQ_GEQ(a,b) ( (int)((a)-(b)) >= 0 )

typedef struct tcb tcb_t;

/* Definitions for all TCP states */
typedef enum
{
	tcp_NEW = 0,
	tcp_ESTABLISHED,
	tcp_SYN_SENT,
	tcp_SYN_RECV,
	tcp_FIN_WAIT1,
	tcp_FIN_WAIT2,
	tcp_CLOSE,
	tcp_CLOSE_WAIT,
	tcp_TIME_WAIT,
	tcp_LAST_ACK,
	tcp_LISTEN,
	tcp_CLOSING
} tcp_state_t;

typedef enum
{
	tcp_CLIENT = 1,
	tcp_SERVER = 2
} tcp_client_server_t;

/* Definition an interface */
typedef struct tcp_intf_t_
{
	maddr_t		macaddr;	/* mac address */
	unsigned short	vlan;		/* Vlan number */
	ipaddr_t	ipaddr;		/* IP address */
	unsigned short	ip_id;		/* IP id field */
	unsigned short  port;		/* TCP port number */
	unsigned short  app;		/* ??? */
	unsigned char   prot;		/* protocol field */
        struct tcp_intf_t_     *next; 
} tcp_intf_t;

/* Definition for TCP flag field */
typedef enum
{
	tcp_FLG_FIN = 0x01,
	tcp_FLG_SYN = 0x02,
	tcp_FLG_RST = 0x04,
	tcp_FLG_PUSH = 0x08,
	tcp_FLG_ACK = 0x10,
	tcp_FLG_URG = 0x20
} tcp_flag_t;

typedef enum
{
	tcp_STAT_ACK,
	tcp_STAT_SYN,
	tcp_STAT_FIN,
	tcp_STAT_RST,
	tcp_STAT_PKT,
	tcp_STAT_CKSUM_ERR,
	tcp_STAT_MAX /* Always at the end */
} tcp_stat_t;

typedef enum
{
	tcp_XMT,
	tcp_RCV
} tcp_dir_t;

typedef enum
{
	tcp_OPTCMD_STACK,	/* use the stack built-in option list,
				 * same as if the tcpip_t * is NULL */
	tcp_OPTCMD_NONE,	/* force to use no option */
	tcp_OPTCMD_OVERRIDE	/* override stack option with this list */
} tcp_optcmd_t;

/* Data structure for the IP options */
typedef struct
{
	tcp_optcmd_t cmd;
	unsigned char list[MAX_TCPOPTLEN];
	int          len;
	unsigned short win;
	unsigned short mss;
	unsigned char  wscale;
	unsigned long  ts;
	unsigned long  ts_echo_reply;
} tcpip_opt_t;

/* handle is the pointer to the TCB */
typedef unsigned long tcp_handle_t;

/* definition for testing of Layer */
typedef enum
{
	test_L0 = 0,
	test_L4 = 1,
	test_L5 = 2
} test_l4_or_l5_t;

/*
 * Access to every field in the TCB. Refer tcb struct in tcb.h for
 * the fields definition
 */
typedef enum
{
	tcp_TCB_STATE,
	tcp_TCB_CLSV,
	tcp_TCB_TOS,
	tcp_TCB_TTL,
	tcp_TCB_PROT,
	tcp_TCB_SUNA,
	tcp_TCB_TOPTS,
	tcp_TCB_WSCALE,
	tcp_TCB_TS,
	tcp_TCB_TS_ER,
	tcp_TCB_IOPTS,
	tcp_TCB_IOPTLEN,

	tcp_TCB_LOCAL_MAC,
	tcp_TCB_LOCAL_VLAN,
	tcp_TCB_LOCAL_IPADDR,
	tcp_TCB_LOCAL_IPID,
	tcp_TCB_LOCAL_PORT,
	tcp_TCB_LOCAL_APP,
	tcp_TCB_LOCAL_PROT,
	tcp_TCB_LOCAL_ISN,
	tcp_TCB_LOCAL_CSN,
	tcp_TCB_LOCAL_FSN,
	tcp_TCB_LOCAL_WIN,
	tcp_TCB_LOCAL_MSS,

	tcp_TCB_REMOTE_MAC,
	tcp_TCB_REMOTE_VLAN,
	tcp_TCB_REMOTE_IPADDR,
	tcp_TCB_REMOTE_IPID,
	tcp_TCB_REMOTE_PORT,
	tcp_TCB_REMOTE_APP,
	tcp_TCB_REMOTE_PROT,
	tcp_TCB_REMOTE_ISN,
	tcp_TCB_REMOTE_CSN,
	tcp_TCB_REMOTE_FSN,
	tcp_TCB_REMOTE_WIN,
	tcp_TCB_REMOTE_MSS,

	tcp_TCB_PSPEC,
	tcp_TCB_DATA,
	tcp_TCB_RETRANS,
	tcp_TCB_LEN,
	tcp_TCB_L5_TXHDL,
	tcp_TCB_L5_RXHDL,
	tcp_TCB_ERROR,
	tcp_TCB_EFLG_SEND_BAD_ACK
} tcp_parm_t;

/*---------------------------------------------------------------------------
 * Function prototypes
 *---------------------------------------------------------------------------*/
int init_tcp (tcp_client_server_t client_server, tcp_intf_t *new_intf, test_l4_or_l5_t test);
int tcp_set_parm (unsigned long handle, tcp_parm_t parm, unsigned long *value);
int tcp_get_parm (unsigned long handle, tcp_parm_t parm, unsigned long *value);
tcp_handle_t tcp_connect (tcp_client_server_t client_server, tcp_intf_t remote,
			  tcpip_opt_t *tcpopt, tcpip_opt_t *ipopt, 
			  void *l5_handler, void *r);
tcp_handle_t tcp_get_next_server (tcp_handle_t cur_server);
int tcp_get_count_server (void);
int tcp_send (tcp_handle_t handle, unsigned char *data, int data_length,
	tcpip_opt_t *tcpopt, tcpip_opt_t *ipopt);
int drop_tcp (tcp_handle_t handle);
int disconnect_tcp (tcp_handle_t handle, unsigned char *data, 
	int len, tcpip_opt_t *tcpopt, tcpip_opt_t *ipopt);
pspec_t *tcp_prep_xmt (tcb_t *tcb, unsigned char flags, unsigned char *data,
	int dlen, tcpip_opt_t *tcpopt, tcpip_opt_t *ipopt);
int tcp_bkgnd ();
int tcp_bkgnd2 (int *, int *, int);
int close_tcp (void);
int reset_tcp (tcp_handle_t);
unsigned long get_seq(void);
void tcp_load_func (void *, void *);
int tcp_recv (unsigned short len, unsigned short vlan, unsigned char *buf);
int tcp_is_connected (tcp_handle_t handle);
char *tcp_state_str (tcp_state_t s);
int tcp_get_statistics (tcp_dir_t, tcp_stat_t);
int proto_load_post_process (tcp_state_t state, tcp_flag_t packet_type,
	tcp_dir_t dir, void *func);
int tcp_proto_unload_post_process (tcp_state_t state, tcp_flag_t packet_type, 
	tcp_dir_t dir);


typedef enum
{
	TX = 1,
	RX = 2
} tx_rx_t;


typedef struct pkt
{
	pspec_t pspec;	/* storage for pspec */
	caddr_t tcb;	/* pointer to the TCB */
	unsigned short vlan;
	LIST_ENTRY (pkt) list; /* control linked list */
} pkt_t;

extern pkt_t *pkt_free (pkt_t *);
extern int pkt_init (void);
extern pkt_t *pkt_alloc(tx_rx_t);
extern pkt_t *pkt_get_list(tx_rx_t);

#define TOS_DEF		0x00
#define TTL_DEF		0x20
#define PROT_TCP	0x06
#define MAX_OPTION	40

typedef struct retrans {
	int num;		/* number of times to retransmit */
	int runsim_delay;	/* delay argument to runsim */
	unsigned char any_flags; /* any bit here matches this is not */
				 /* a good idea in general */
	unsigned char all_flags; /* all bits should match */
	struct retrans *n;
} retrans_t;

struct tcb
{
	tcp_state_t         state;	/* current state to the TCP connection */
	tcp_client_server_t cl_sv;	/* tcp_CLIENT or tcp_SERVER */
	unsigned char       tos;	/* Type-of-service field */
	unsigned char       ttl;	/* Time-to-live */ 
	unsigned char       prot;	/* protocol field, i.e, TCP = 0x06 */
	unsigned long       suna;	/* expected seq number */
	unsigned char       tcpopt[MAX_OPTION]; /* TCP option list */
	unsigned char	    tcpoptlen;	/* length of the IP option list */
        unsigned char       wscale;	/* window scale */
        unsigned long       ts;		/* time stamp */
        unsigned long       ts_echo_reply; /* time stamp echo reply */
	unsigned char	    ipopt[MAX_OPTION]; /* IP option list */
	unsigned char	    ipoptlen;	/* length of the IP option list */
	struct sd
	{
		tcp_intf_t	intf;	/* MAC, VLAN, etc of the current interface */
		unsigned long   isn;    /* initial sequence num */
		unsigned long	csn;	/* current seq num */
		unsigned long	fsn;	/* fin seq num */
		unsigned long	win;
		unsigned short  mss;
	} local, remote; /* aka source, destination */
	pkt_t		*pkt;		/* pointer to the packet space */
	unsigned char	*data;		/* pointer to the TCP payload data */
	retrans_t       *retrans;	/* retransmission control */
	unsigned short	len;		/* payload length */
	int		(*l5_rx)(void *, unsigned char *, int); /* upper layer handler */
	int		(*l5_tx)(void *, unsigned char *, int); /* upper layer handler */
	int             tcb_error;	/* error flag for this connection */
	struct ef			/* error flags for inserting errors */
	{
		int send_bad_ack_number;
	} err_flags;
	LIST_ENTRY(tcb) list;		/* pointer to the TCB control linked list */
	LIST_ENTRY(tcb) action;		/* pointer to the TCB control linked list */
};

/* Function prototype */
extern int tcb_init (void);
extern tcb_t *tcb_alloc(tcp_client_server_t client_server);
extern tcb_t *tcb_free (tcb_t *tcb);
extern tcb_t *tcb_get_list (tcp_client_server_t client_server);

typedef struct tcp_protocol tcp_protocol_t;
typedef struct tcp_action tcp_action_t;
/*
 * folowing dummys used to gen routines for testing the paste function
 * of the pre-processor
 */
#define ROUTE(funky,b,c) pspec_t * funky(tcb_t * b,pspec_t * c){;}

ROUTE(last_ack_snd_ack,b,c);
ROUTE(last_ack_snd_syn,b,c);
ROUTE(last_ack_snd_fin,b,c);
ROUTE(last_ack_snd_rst,b,c);
ROUTE(last_ack_rcv_ack,b,c);
ROUTE(last_ack_rcv_rst,b,c);
ROUTE(last_ack_rcv_syn,b,c);
ROUTE(last_ack_rcv_fin,b,c);
ROUTE(dummy_rcv_rst,b,c);
ROUTE(dummy_rcv_syn,b,c);
ROUTE(dummy_rcv_ack,b,c);
ROUTE(dummy_rcv_fin,b,c);
ROUTE(dummy_snd_rst,b,c);
ROUTE(dummy_snd_syn,b,c);
ROUTE(dummy_snd_ack,b,c);
ROUTE(dummy_snd_fin,b,c);
ROUTE(closing_rcv_rst,b,c);
ROUTE(closing_rcv_syn,b,c);;
ROUTE(closing_rcv_ack,b,c);
ROUTE(closing_rcv_fin,b,c);
ROUTE(closing_snd_rst,b,c);
ROUTE(closing_snd_syn,b,c);
ROUTE(closing_snd_ack,b,c);
ROUTE(closing_snd_fin,b,c);
ROUTE(close_wait_rcv_rst,b,c);
ROUTE(close_wait_rcv_syn,b,c);
ROUTE(close_wait_rcv_ack,b,c);
ROUTE(close_wait_rcv_fin,b,c);
ROUTE(close_wait_snd_rst,b,c);
ROUTE(close_wait_snd_syn,b,c);
ROUTE(close_wait_snd_ack,b,c);
ROUTE(close_wait_snd_fin,b,c);
ROUTE(close_rcv_rst,b,c);
ROUTE(close_rcv_syn,b,c);
ROUTE(close_rcv_ack,b,c);
ROUTE(close_rcv_fin,b,c);
ROUTE(close_snd_rst,b,c);
ROUTE(close_snd_syn,b,c);
ROUTE(close_snd_ack,b,c);
ROUTE(close_snd_fin,b,c);
ROUTE(finw2_snd_rst,b,c);
ROUTE(finw2_snd_syn,b,c);
ROUTE(finw2_snd_ack,b,c);
ROUTE(finw2_snd_fin,b,c);
ROUTE(finw2_rcv_rst,b,c);
ROUTE(finw2_rcv_syn,b,c);
ROUTE(finw2_rcv_ack,b,c);
ROUTE(finw2_rcv_fin,b,c);
ROUTE(finw1_snd_rst,b,c);
ROUTE(finw1_snd_syn,b,c);
ROUTE(finw1_snd_ack,b,c);
ROUTE(finw1_snd_fin,b,c);
ROUTE(finw1_rcv_rst,b,c);
ROUTE(finw1_rcv_syn,b,c);
ROUTE(finw1_rcv_ack,b,c);
ROUTE(finw1_rcv_fin,b,c);
ROUTE(syn_recv_snd_rst,b,c);
ROUTE(syn_recv_snd_syn,b,c);
ROUTE(syn_recv_snd_ack,b,c);
ROUTE(syn_recv_snd_fin,b,c);
ROUTE(syn_recv_rcv_rst,b,c);
ROUTE(syn_recv_rcv_syn,b,c);
ROUTE(syn_recv_rcv_ack,b,c);
ROUTE(syn_recv_rcv_fin,b,c);
ROUTE(syn_sent_snd_rst,b,c);
ROUTE(syn_sent_snd_syn,b,c);
ROUTE(syn_sent_snd_ack,b,c);
ROUTE(syn_sent_snd_fin,b,c);
ROUTE(syn_sent_rcv_rst,b,c);
ROUTE(syn_sent_rcv_syn,b,c);
ROUTE(syn_sent_rcv_ack,b,c);
ROUTE(syn_sent_rcv_fin,b,c);
ROUTE(estab_snd_rst,b,c);
ROUTE(estab_snd_syn,b,c);
ROUTE(estab_snd_ack,b,c);
ROUTE(estab_snd_fin,b,c);
ROUTE(estab_rcv_rst,b,c);
ROUTE(estab_rcv_syn,b,c);
ROUTE(estab_rcv_ack,b,c);
ROUTE(estab_rcv_fin,b,c);
ROUTE(new_snd_rst,b,c);
ROUTE(new_snd_syn,b,c);
ROUTE(new_snd_ack,b,c);
ROUTE(new_snd_fin,b,c);
ROUTE(new_rcv_rst,b,c);
ROUTE(new_rcv_syn,b,c);
ROUTE(new_rcv_ack,b,c);
ROUTE(new_rcv_fin,b,c);

/*
 * This structure describes the operations available during any particular
 * TCP state for both receiving packets and sending packets (either
 * sourcing or responding).
 */
struct tcp_action
{
	struct
	{
		pspec_t *(*rst)(tcb_t *, pspec_t *);
		pspec_t *(*syn)(tcb_t *, pspec_t *);
		pspec_t *(*ack)(tcb_t *, pspec_t *);
		pspec_t *(*fin)(tcb_t *, pspec_t *);
	} rcv, snd;
};

/*
 * Used for externally declaring each of the functions for a single TCP state.
 */
#define TCP_EXTERN(state) \
extern pspec_t * state##_rcv_rst(tcb_t *,pspec_t *), \
* state##_rcv_syn(tcb_t *,pspec_t *), \
* state##_rcv_ack(tcb_t *,pspec_t *), \
* state##_rcv_fin(tcb_t *,pspec_t *), \
* state##_snd_rst(tcb_t *,pspec_t *), \
* state##_snd_syn(tcb_t *,pspec_t *), \
* state##_snd_ack(tcb_t *,pspec_t *), \
* state##_snd_fin(tcb_t *,pspec_t *)

/*
 * Used for specifying each of the functions for a single TCP state.
 */
#define TCP_ACTION(state) \
{ \
	{ \
		state##_rcv_rst, \
		state##_rcv_syn, \
		state##_rcv_ack, \
		state##_rcv_fin, \
	}, \
	{ \
		state##_snd_rst, \
		state##_snd_syn, \
		state##_snd_ack, \
		state##_snd_fin, \
	} \
}

pspec_t *inbound(tcb_t *tcb, pspec_t *pkt);
pspec_t *outbound(tcb_t *tcb, pspec_t *pkt);

extern void any_display_data (char *str, int len);
extern pspec_t *any_rcv_ack(tcb_t *tcb, pspec_t *pspec);

TCP_EXTERN(new);
TCP_EXTERN(estab);
TCP_EXTERN(syn_sent);
TCP_EXTERN(syn_recv);
TCP_EXTERN(finw1);
TCP_EXTERN(finw2);
TCP_EXTERN(time_wait);
TCP_EXTERN(close);
TCP_EXTERN(close_wait);
TCP_EXTERN(last_ack);
#ifdef UNHANDLED
TCP_EXTERN(listen);
#endif
TCP_EXTERN(closing);
TCP_EXTERN(dummy);

static tcp_action_t proc_state[] =
{
	TCP_ACTION(new),
	TCP_ACTION(estab),
	TCP_ACTION(syn_sent),
	TCP_ACTION(syn_recv),
	TCP_ACTION(finw1),
	TCP_ACTION(finw2),
	TCP_ACTION(close),
	TCP_ACTION(close_wait),
#ifdef UNHANDLED
	TCP_ACTION(time_wait),
	TCP_ACTION(last_ack),
	TCP_ACTION(listen),
#else
	TCP_ACTION(dummy),
	TCP_ACTION(last_ack),
	TCP_ACTION(dummy),
#endif /* UNHANDLED */
	TCP_ACTION(closing)
};

#define TCB_STATE(p)		(p->state)

/* State processing routines */
#define TCB_RCV(v,b,p)		(*proc_state[TCB_STATE(b)].rcv.v)((b), (p))
#define TCB_SND(v,b,p)		(*proc_state[TCB_STATE(b)].snd.v)((b), (p))

static void *do_nothing (void *nul0, void *nul1)
{
	return (0);
}

struct post_action
{
	struct pkt_action_t
	{ 
		void *(*rst)(void *, void *); void *(*syn)(void *, void *);
		void *(*ack)(void *, void *); void *(*fin)(void *, void *); 
	} rcv, snd;
};

/* Overloadable post-processing functions, optional for external apps */
static struct post_action post_proc[] =
{
	{
		{do_nothing, do_nothing, do_nothing, do_nothing} ,
		{do_nothing, do_nothing, do_nothing, do_nothing} ,
	},
	{
		{do_nothing, do_nothing, do_nothing, do_nothing} ,
		{do_nothing, do_nothing, do_nothing, do_nothing} ,
	},
	{
		{do_nothing, do_nothing, do_nothing, do_nothing} ,
		{do_nothing, do_nothing, do_nothing, do_nothing} ,
	},
	{
		{do_nothing, do_nothing, do_nothing, do_nothing} ,
		{do_nothing, do_nothing, do_nothing, do_nothing} ,
	},
	{
		{do_nothing, do_nothing, do_nothing, do_nothing} ,
		{do_nothing, do_nothing, do_nothing, do_nothing} ,
	},
	{
		{do_nothing, do_nothing, do_nothing, do_nothing} ,
		{do_nothing, do_nothing, do_nothing, do_nothing} ,
	},
	{
		{do_nothing, do_nothing, do_nothing, do_nothing} ,
		{do_nothing, do_nothing, do_nothing, do_nothing} ,
	},
	{
		{do_nothing, do_nothing, do_nothing, do_nothing} ,
		{do_nothing, do_nothing, do_nothing, do_nothing} ,
	},
	{
		{do_nothing, do_nothing, do_nothing, do_nothing} ,
		{do_nothing, do_nothing, do_nothing, do_nothing} ,
	},
	{
		{do_nothing, do_nothing, do_nothing, do_nothing} ,
		{do_nothing, do_nothing, do_nothing, do_nothing} ,
	},
	{
		{do_nothing, do_nothing, do_nothing, do_nothing} ,
		{do_nothing, do_nothing, do_nothing, do_nothing} ,
	},
	{
		{do_nothing, do_nothing, do_nothing, do_nothing} ,
		{do_nothing, do_nothing, do_nothing, do_nothing} ,
	}
};

/* Post processing routines */
#define TCB_POST_RCV(v,b,p)	(*post_proc[TCB_STATE(b)].rcv.v)((b), (p))
#define TCB_POST_SND(v,b,p)	(*post_proc[TCB_STATE(b)].snd.v)((b), (p))

/*----------------------------------------------------------------------------
 * inbound() - when a packet arrives at the TCP state machine receiving
 *	routine, this routine parses the TCP flags field then passes the
 *	packet through the current state function. The TCP state-machine
 *	is progressed through the calls of this function;
 *----------------------------------------------------------------------------*/
pspec_t *inbound(tcb_t *tcb, pspec_t *pkt)
{
	unsigned char flags;

	flags = pkt->u.tcp.flags;

	/* A priority scheme in parsing the TCP flags
	 * is employed: reset, fin, ack, and syn.
	 * Christmas packets are also parsed in this order */
	if (flags & tcp_FLG_RST)
	{
		/* {state}_rcv_rst() function is called */
		pkt = TCB_RCV(rst, tcb, pkt);
		if (pkt)
		{
			/* optional post-processing function */
			TCB_POST_RCV (rst, tcb, pkt);
		}
	}
	else if (flags & tcp_FLG_FIN)
	{
		/* {state}_rcv_fin() function is called */
		pkt = TCB_RCV(fin, tcb, pkt);
		if (pkt)
		{
			/* optional post-processing function */
			TCB_POST_RCV (fin, tcb, pkt);
		}
	}
	else if (flags & tcp_FLG_ACK)
	{
		/* {state}_rcv_ack() function is called */
		pkt = TCB_RCV(ack, tcb, pkt);
		if (pkt)
		{
			/* optional post-processing function */
			TCB_POST_RCV (ack, tcb, pkt);
		}
	}
	else if (flags & tcp_FLG_SYN)
	{
		/* {state}_rcv_syn() function is called */
		pkt = TCB_RCV(syn, tcb, pkt);
		if (pkt)
		{
			/* optional post-processing function */
			TCB_POST_RCV (syn, tcb, pkt);
		}
	}
	else
	{
		pkt = (pspec_t *)0;
	}
	return (pkt);
}

/*---------------------------------------------------------------------
 * outbound() - this function is called for progressing the transmitting
 *	side based on the flags in the transmitting packet and the
 *	current state in the TCP state machines.
 *---------------------------------------------------------------------*/
pspec_t *outbound(tcb_t *tcb, pspec_t *pkt)
{
	unsigned char flags;

	flags = pkt->u.tcp.flags;

	/* A priority scheme in parsing the TCP flags
	 * is employed: reset, fin, ack, and syn.
	 * Christmas packets are also parsed in this order */
	
	if (flags & tcp_FLG_RST)
	{
		/* {state}_snd_rst() function is called */
		pkt = TCB_SND(rst, tcb, pkt);
		if (pkt)
		{
			/* optional post-processing function */
			TCB_POST_SND (rst, tcb, pkt);
		}
	}
	else if (flags & tcp_FLG_FIN)
	{
		/* {state}_snd_fin() function is called */
		pkt = TCB_SND(fin, tcb, pkt);
		if (pkt)
		{
			/* optional post-processing function */
			TCB_POST_SND (fin, tcb, pkt);
		}
	}
	else if (flags & tcp_FLG_ACK)
	{
		/* {state}_snd_ack() function is called */
		pkt = TCB_SND(ack, tcb, pkt);
		if (pkt)
		{
			/* optional post-processing function */
			TCB_POST_SND (ack, tcb, pkt);
		}
	}
	else if (flags & tcp_FLG_SYN)
	{
		/* {state}_snd_syn() function is called */
		pkt = TCB_SND(syn, tcb, pkt);
		if (pkt)
		{
			/* optional post-processing function */
			TCB_POST_SND (syn, tcb, pkt);
		}
	}
	else
	{
		pkt = (pspec_t *)0;
	}
	return (pkt);
}

/*--------------------------------------------------------------------------
 * tcp_proto_load_post_process () - Overload the post transmit/receive state
 *	functions which execute immediately after the normal TCP state
 *	processings.
 *--------------------------------------------------------------------------*/
int proto_load_post_process (tcp_state_t state, tcp_flag_t packet_type, tcp_dir_t dir, void *func)
{
	struct pkt_action_t *cur_action = 0;

	/* parse the state */
	if (state > tcp_CLOSING)
	{
		return (-1);
	}

	/* parse direction and get the pointer to the post_action[] */
	switch (dir)
	{
	case tcp_XMT:
		cur_action = &post_proc[state].snd;
		break;
	case tcp_RCV:
		cur_action = &post_proc[state].rcv;
		break;
	default:
		return (-1);
	}

	/* check flag to overload the packet type function */
	switch (packet_type)
	{
	case tcp_FLG_FIN:
		cur_action->fin = func;
		break;
	case tcp_FLG_SYN:
		cur_action->syn = func;
		break;
	case tcp_FLG_RST:
		cur_action->rst = func;
		break;
	case tcp_FLG_ACK:
		cur_action->ack = func;
		break;
	default:
		return (-1);
	}

	return (0);
}

/*--------------------------------------------------------------------------
 * proto_unload_post_process () - Reloads the post transmit/receive state
 *	functions with do_nothing() default function
 *--------------------------------------------------------------------------*/
int tcp_proto_unload_post_process (tcp_state_t state, tcp_flag_t packet_type, tcp_dir_t dir)
{
	struct pkt_action_t *cur_action = 0;

	/* parse the state */
	if (state > tcp_CLOSING)
	{
		return (-1);
	}

	/* parse direction and get the pointer to the post_action[] */
	switch (dir)
	{
	case tcp_XMT:
		cur_action = &post_proc[state].snd;
		break;
	case tcp_RCV:
		cur_action = &post_proc[state].rcv;
		break;
	default:
		return (-1);
	}

	/* check flag to reload the packet type function with do_nothing */
	switch (packet_type)
	{
	case tcp_FLG_FIN:
		cur_action->fin = do_nothing;
		break;
	case tcp_FLG_SYN:
		cur_action->syn = do_nothing;
		break;
	case tcp_FLG_RST:
		cur_action->rst = do_nothing;
		break;
	case tcp_FLG_ACK:
		cur_action->ack = do_nothing;
		break;
	default:
		return (-1);
	}

	return (0);
}
int main()
{
	printf("\nmain");
}

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]