Возможно, проблема с указателем.Программа для Linux + libpcap + getopt_long () + язык C - PullRequest
0 голосов
/ 25 октября 2010

Я делаю сетевой анализатор для своего проекта в колледже, используя библиотеку libpcap.Большая часть кода работает без проблем, однако я застрял в следующей проблеме.Я добавил пять опций командной строки, используя функцию getopt_long(), но одна опция не работает должным образом.

Опция -d (--device_info) и используется для печати связанных I.P address и netmaskс интерфейсом.Он принимает один аргумент - имя interface, для которого должна быть напечатана информация.

Необходимая часть кода из программы прилагается ниже.Моя проблема в том, что, хотя я явно назначаю имя interface для char *device (строка 35), а затем передаю его в качестве аргумента print_device_info() (строка 36), когда print_device_info() выполняется, оно всегдавыполняет блок if (строка 4), т.е. char *device всегда равен NULL в print_device_info(), даже если я передаю его в качестве аргумента.

Я начинающий программист, и этоПервый «настоящий» проект я разрабатываю.Я предполагаю, что это проблема с указателем, но я не уверен.

Пожалуйста, также предложите какой-нибудь метод для ее решения.

1)   //Prints information associated with an interface.
 2)   void print_device_info(char *device)
 3)   { 
      ...
      ...
      ...

 4)     if(device == NULL);
 5)      {
 6)       fprintf(stdout, "No interface specified \n");
 7)       exit(1);
 8)      }
      ...
      ...
      ...
 9)    }

 10)   int main(int argc, char *argv[])
 11)   { 
 12)     int next_option; // Options

 13)     char *device=NULL; // NIC to sniff packet from. 

 14)     // A string listing valid short options letters.
 15)     const char* const short_options = "ho:i:d:p";

 16)     /* An array describing valid long options. */
 17)     const struct option long_options[] = 
 18)      {
 19)       { "help",        0, NULL, 'h' },
 20)       { "output",      1, NULL, 'o' },
 21)       { "interface",   1, NULL, 'i' },
 22)       { "device_info", 1, NULL, 'd' },
 23)       { "promisc_off", 0, NULL, 'p' },
 24)       { NULL,          0, NULL,  0  } /* Required at end of array. */
 25)      };

 26)     //Check the arguments and perform their respective functions
 27)   do {
 28)     next_option = getopt_long (argc, argv, short_options,
 29)                                 long_options, NULL);
 30)     switch (next_option)
 31)     {
 32)       case 'd':    /* -d or --device_info */
 33)        /* User has requested information associated an interface. Print it to standard
 34)           output, and exit with exit code zero (normal termination). */
 35)        device = optarg;
 36)        print_device_info (device);
 37)     }
 38)     }while (next_option != -1);
       }

Редактировать: Здесь я публикую отредактированную версиюоригинальная программа.Эта отредактированная версия сама по себе является законченной программой, поэтому ее должно быть достаточно для любых будущих запросов.

#include <pcap.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <getopt.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

//Prints information associated with an interface.
void print_device_info(char *device)
 { 

  struct in_addr addr_struct; //Stores I.P address.

  char *ipaddr=NULL; //Points to I.P address in dotted-decimal form.

  char *netmask=NULL; //Points to  Netmask in dotted-decimal form.

  int ret; //Return code (Useful for error detection).

  bpf_u_int32 tmpip; // Stores I.P address temporarily in host-byte (little-endian) order.

  bpf_u_int32 tmpmask;// Stores Netmask temporarily in host-byte (little-endian) order.

  char errbuf[PCAP_ERRBUF_SIZE]; // Stores error messages.

   printf("%s\n",device);

  if(device==NULL);
   {
    fprintf(stdout, "No interface specified \n");
    exit(1);
   }

/*Lookup device info and store the return value in ret */
  ret = pcap_lookupnet(device, &tmpip, &tmpmask, errbuf);

//error checking
 if(ret==-1)
  {
   fprintf(stderr, "Couldn't find IP address and subnet mask: %s\n", errbuf);
   exit(1);
  }

//Calculate IP address
  addr_struct.s_addr=tmpip;
  ipaddr=inet_ntoa(addr_struct);

//error checking.
  if(ipaddr==NULL)
   {
    perror("Error in locating the I.P address");
    exit(1);
   }

//Print the IP address
  printf("IP address: %s\n",ipaddr);

//Calculate subnet mask
  addr_struct.s_addr=tmpmask;
  netmask=inet_ntoa(addr_struct);

//error checking.
  if(netmask==NULL)
   {
    perror("Error in locating the subnet mask");
    exit(1);
   }

//Print the subnet mask 
  printf("Subnet mask: %s\n",netmask);

  exit(0);
}

int main(int argc, char *argv[])
{ 

//A) Declarations -----------------------------------------------------------------------------------------------------
  int next_option; // Options

  char *device=NULL; // NIC to sniff packet from. 

  char errbuf[PCAP_ERRBUF_SIZE]; // Stores error messages.

// A string listing valid short options letters.
  const char* const short_options = "i:d:";

/* An array describing valid long options. */
  const struct option long_options[] = 
   {
    { "interface",   1, NULL, 'i' },
    { "device_info", 1, NULL, 'd' },
    { NULL,          0, NULL,  0  } /* Required at end of array. */
   };

//Check the arguments and perform their respective functions
do {
  next_option = getopt_long (argc, argv, short_options,
                              long_options, NULL);
  switch (next_option)
  {

  case 'i':    /* -i or  --interface */
     /* User has specified the NIC device to sniff from */
     device = optarg;
     break;

  case 'd':    /* -d or --device_info */
     /* User has requested information associated an interface. Print it to standard
        output, and exit with exit code zero (normal termination). */
     device = optarg;
     printf("%s\n",device);
     print_device_info (device);

  case -1:     /* Done with options.  */
     break;

  default:     /* Something else: unexpected.  */
     abort ();
  }
}
while (next_option != -1);

//B)Lookup device
  if (device == NULL)
  {
    device=pcap_lookupdev(errbuf);  

     //Check for error  
     if(device==NULL)
      {
        fprintf(stderr, "Couldn't find device %s\n",errbuf);
        return(2);
      }
  }

//Print Device
  printf("Device: %s\n", device);

}

Ответы [ 2 ]

3 голосов
/ 25 октября 2010

У вас есть случайная точка с запятой (;) в конце теста.

Это означает, что единственное, что контролируется тестом, это пустое выражение, а блок, следующий за оператором if, является просто вложенным блоком (всегда будет выполняться).

2 голосов
/ 25 октября 2010

Я изменил ваш код, чтобы выйти из цикла чтения аргументов, и он работает точно так, как я ожидал:

$ ./longopt
(Нуль)
$ ./longopt -d eth0
eth0

Вот код:

#include <stdio.h>
#include <stdlib.h>
#include <getopt.h>


int main(int argc, char *argv[])
{ 
    int next_option; // Options
    char *device=NULL; // NIC to sniff packet from.

    // A string listing valid short options letters.
    const char* const short_options = "ho:i:d:p";

    /* An array describing valid long options. */
    const struct option long_options[] = 
        {
            { "help",        0, NULL, 'h' },
            { "output",      1, NULL, 'o' },
            { "interface",   1, NULL, 'i' },
            { "device_info", 1, NULL, 'd' },
            { "promisc_off", 0, NULL, 'p' },
            { NULL,          0, NULL,  0  } /* Required at end of array. */
        };

    //Check the arguments and perform their respective functions
    while(1) {
        next_option = getopt_long (argc, argv, short_options,
                                   long_options, NULL);
        if (next_option == -1)
            break;


        switch (next_option)
        {
            case 'd':    /* -d or --device_info */
                /* User has requested information associated an interface. Print it to standard
                   output, and exit with exit code zero (normal termination). */
                device = optarg;


        }
    } 

    printf("%s\n", device);

    return(0);

}
...