This is the mail archive of the
gcc-bugs@gcc.gnu.org
mailing list for the GCC project.
Re: gcc error: warning: pasting "syn" and ")" does not give a valid preprocessing token
- To: Neil Booth <neil at daikokuya dot demon dot co dot uk>
- Subject: Re: gcc error: warning: pasting "syn" and ")" does not give a valid preprocessing token
- From: Kiet Tran <ktran at extremenetworks dot com>
- Date: Wed, 04 Jul 2001 16:45:20 -0700
- CC: Alexandre Oliva <aoliva at redhat dot com>, gcc-bugs at gcc dot gnu dot org
- References: <20010704233551.A32655@daikokuya.demon.co.uk>
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");
}