2012-07-20 65 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中分離出來並確保將所需的數據作爲參數傳遞,會發生什麼情況?