C - invalid application of ‘sizeof’ to incomplete type ‘struct ipheader’ and other errors
===

I am having some trouble with compiling my code due to these error messages (I suspect they are somewhat related)

    In function ‘forgepacket’:
    error: expected specifier-qualifier-list before ‘send_tcp’

    In function ‘send_tcp’:
    error: invalid application of ‘sizeof’ to incomplete type ‘struct ipheader’
    error: invalid application of ‘sizeof’ to incomplete type ‘struct tcpheader’
and

    error: dereferencing pointer to incomplete type
every time i try to access `ip->iph` or `tcp->tcph`. Now I've gathered that the problem lies with the definition of `struct ipheader` and `struct tcpheader`, but I can't really figure out what.

I've been looking at similar error message questions as the ones above but I can't really figure it out.

Here is the code:

    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <string.h>
    #include <getopt.h>
    #include <sys/socket.h>
    #include <netinet/ip.h>
    #include <netinet/tcp.h>

    #define VERSION "1.0"
    #define PCKT_LEN 8192
	
	/* Prototypes */	

    void forgepacket (unsigned int, unsigned int, unsigned short, unsigned short);
    int send_tcp();	
    void usage(); 

    /* Checksum */
    unsigned short checksum (unsigned short *pac, int len)
	{ 
		unsigned long sum;
		for (sum = 0; len > 0; len--)
				sum += *pac++;
		sum = (sum >> 16) + (sum & 0xffff);
		sum += (sum >> 16);
		return(~sum);
	}				

	in_addr_t sip;
	in_addr_t dip;
	int sport;
	int dport;					

    int main(int argc,char **argv)
    {
	int c;
	
	/* Are we in root? */	
	if(geteuid() !=0)
		{
			printf("Root access is required to run this program.\n\n");
			exit(0);		
		}	
		
	while (1)
		{
			static struct option long_options[] =
				{
					/* Options */
				{"send",       no_argument,       0, 's'}, /* args s and r have no function yet */
				{"recieve",    no_argument,       0, 'r'},
				{"file",       required_argument, 0, 'f'}, 
				{"destip",     required_argument, 0, 'i'},
				{"destport",   required_argument, 0, 'p'},
				{"sourceip",   required_argument, 0, 'o'},
				{"sourceport", required_argument, 0, 't'},
				{0, 0, 0, 0}
				};
			
			   int option_index = 0;
		     
			   c = getopt_long (argc, argv, "srf:d:i:p:o:t:",
				            long_options, &option_index);
		     
						  /* Detect the end of the options. */
			   if (c == -1)
			     break;
		     
			   switch (c)
			     {
			     case 0:
			       /* If this option set a flag, do nothing else now. */
			       if (long_options[option_index].flag != 0)
				 break;
			       printf ("option %s", long_options[option_index].name);
			       if (optarg)
				 printf (" with arg %s", optarg);
			       printf ("\n");
			       break;
		     
			     case 's':
			       puts ("option -s\n");
			       break;
		     
			     case 'r':
			       puts ("option -r\n");
			       break;
		     
			     case 'f':
			       printf ("option -f with value `%s'\n", optarg);
			       break;
		     				   
				 case 'i':
				   dip = inet_addr(optarg);
			       break;
		     
			     case 'p':
			       dport = htons(atoi(optarg)); 
				   /* Add handling of bad/non number input here */
			       break;
				   
				 case 'o': 
				   sip = inet_addr(optarg);
				   break;
				   
				 case 't': 
				   sport = htons(atoi(optarg));
				   break;
		     
			     case '?':
			       /* Error message printed */
			       break;
		     
			     default:
			       abort ();
			     }
			 }
		     
		       /* Print any remaining command line arguments (not options). */
		    if (optind < argc)
		{
			printf ("\nNon-option ARGV-elements: ");
			while (optind < argc)
			printf ("%s ", argv[optind++]);
			putchar ('\n');
		}
		 
				/* check if all mandatory options are set and for unknown arguments */
				/* This really needs changing... */
		 if (dip, sip, dport, sport == 0)
			{
				usage();
				return (-1);
			}
		 
		 
		forgepacket(dip, sip, dport, sport);
		 
		getchar ();
		exit (0);
	
    }

    void forgepacket(unsigned int sourceip, unsigned int destip, unsigned short sourceport,
					 unsigned short destport)
    {			
		/* IP header structure */
		struct ipheader {

			unsigned char      iph_ihl:5, 
							   iph_ver:4;
			unsigned char      iph_tos;
			unsigned short int iph_len;
			unsigned short int iph_id;
			unsigned char      iph_flags;
			unsigned short int iph_offset;
			unsigned char      iph_ttl;
			unsigned char      iph_protocol;
			unsigned short int iph_chksum;
			unsigned int       iph_sourceip;
			unsigned int       iph_destip;

			};
					
		/* TCP header structure */		
		struct tcpheader {

			unsigned short int tcph_sourceport;
			unsigned short int tcph_destport;
			unsigned int       tcph_seqnum;
			unsigned int       tcph_acknum;
			unsigned char      tcph_reserved:4, tcph_offset:4;
		    unsigned int

				tcp_res1:4,       
				tcph_hlen:4,      
				tcph_fin:1,       
				tcph_syn:1,       
				tcph_rst:1,       
				tcph_psh:1,       
				tcph_ack:1,       
				tcph_urg:1,       
				tcph_res2:2;

			unsigned short int tcph_win;
			unsigned short int tcph_chksum;
			unsigned short int tcph_urgptr;

			send_tcp();
			};
    }			

		int send_tcp()
			{
				int sock, one = 1;
				char buffer[PCKT_LEN];
				struct sockaddr_in sin, din;
				const int *val = &one;
						
				sock = socket(PF_INET, SOCK_RAW, IPPROTO_TCP);
				if (sock < 0)
					{
						printf("\nError: socket()\n\n");
						exit (-1);
					}
				else
						printf ("\nsocket() - Using SOCK_RAW and TCP protocol is OK.\n\n");
				
				/* Size of the headers */			
				struct ipheader *ip = (struct ipheader *) buffer;
				struct tcpheader *tcp = (struct tcpheader *) (buffer + sizeof (struct ipheader));
				memset (buffer, 0, PCKT_LEN);
				
				/* IP attributes */
				ip->iph_ihl = 5;
				ip->iph_ver = 4;
				ip->iph_tos = 16;
				ip->iph_len = sizeof(struct ipheader) + sizeof(struct tcpheader);
				ip->iph_id = htons(54321);
				ip->iph_offset = 0;
				ip->iph_ttl = 64;
				ip->iph_protocol = 6;
				ip->iph_chksum = 0; 
				
				ip->iph_sourceip = sip;
				ip->iph_destip = dip;
				
				/* TCP attributes */
				tcp->tcph_sourceport = sport;
				tcp->tcph_destport = dport;
				
				tcp->tcph_seqnum = htonl(1);
				tcp->tcph_acknum = 0;
				tcp->tcph_offset = 5;
				tcp->tcph_syn = 1;
				tcp->tcph_ack = 0;
				tcp->tcph_win = htons(32767);
				tcp->tcph_chksum = 0; 
				tcp->tcph_urgptr = 0;
				
				ip->iph_chksum = checksum ((unsigned short *) buffer, (sizeof (struct ipheader )+ sizeof (struct tcpheader)));
				
				/* Address family */ 
				sin.sin_family = AF_INET;
				din.sin_family = AF_INET;
				
				/* Source port */
				sin.sin_port = sport;
				din.sin_port = dport;
				
				/* Source IP */
				sin.sin_addr.s_addr = sip;
				din.sin_addr.s_addr = dip;		
					
				/* Tell the Kernel we're building our own packet */
				if ((setsockopt(sock, IPPROTO_IP, IP_HDRINCL, (char *)&one, sizeof (one))) < 0)
					{
						printf("\nError: Can't set socketoptions\n\n");
						return (-1);
					}
				
				/* Send */
				if (sendto(sock, buffer, ip->iph_len, 0, (struct sockaddr *)&sin, sizeof(sin)) < 0)
					{
						printf("\nError: Can't send packet\n\n");
						return (-1);
					}
					
				else
						printf("Packet sent to %d", dip); 
						
				close(sock);
		}			
		
    void usage() 

    {
	 /* This is the user manual */	

		printf("\nTCP project %s\n\n", VERSION);

     	printf("Usage:  -s -f <file> -i <destip> -p <destport> -o <sourceip> -t <sourceport>\n\n"); 
		
		printf("-s, --send,    		Puts program in send mode\n");
		printf("-r, --recieve,		Puts program in recieve mode\n"); 
		printf("-f, --file, 		Specify file containing steganographic message\n"); 		
		printf("-i, --destip,		Destination IP address\n"); 
		printf("-p, --destport,		Destination port\n"); 
		printf("-o, --sourceip			Source IP address\n"); 
		printf("-t, --sourceport		Source port\n"); 
		
    } 	
