2012-07-20 66 views
0

我想构建一个可以发送TCP数据包的程序,但是当我编译我的代码来测试发送函数时,它只是不会按照它应该的方式运行。当给定参数时,它跳到getchar并退出程序,就好像该函数根本不被调用一样。现在我不是特别有经验,这可能是一个愚蠢的问题,但我一直无法在其他地方找到解决方案。我的猜测是我以某种方式称它错了,也许send_tcp函数不能在forgepacket函数中。C - 功能不执行。调用错误?

以下是我的代码(完全没有完成,但应该足够进行一点测试运行),并且给我提供问题的函数是伪造的。

#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); 
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, r and f 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 ("non-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; 

     }; 

    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"); 

} 

回答

1

看来的send_tcp()函数的定义是forgepacket()函数定义中(我不知道这甚至可能吗?),但它没有呼叫。复制你有forgepacket()安排为send_tcp()

/* Prototype. */ 
int send_tcp(); /* add whatever parameters are required. */ 

和移动send_tcp()forgepacket()的定义和调用中forgepacket()添加到send_tcp()

1

默认情况下,C不允许嵌套函数。而且,即使这样做,我也没有看到在代码中调用send_tcp(它可能在那里,但快速扫描不会显示它)。

如果您将send_tcp函数从forge_packet中分离出来并确保将所需的数据作为参数传递,会发生什么情况?