Home | History | Annotate | Download | only in testprogs
      1 #ifdef HAVE_CONFIG_H
      2 #include <config.h>
      3 #endif
      4 
      5 #include <stdlib.h>
      6 #include <string.h>
      7 #include <sys/types.h>
      8 #ifdef _WIN32
      9   #include <winsock2.h>
     10   #include <ws2tcpip.h>
     11   #include <windows.h>
     12 #else
     13   #include <sys/socket.h>
     14   #include <netinet/in.h>
     15   #include <arpa/inet.h>
     16   #include <netdb.h>
     17   #include <unistd.h>
     18 #endif
     19 
     20 #include <pcap.h>
     21 
     22 #include "pcap/funcattrs.h"
     23 
     24 static int ifprint(pcap_if_t *d);
     25 static char *iptos(bpf_u_int32 in);
     26 
     27 #ifdef _WIN32
     28 #include "portability.h"
     29 
     30 /*
     31  * Generate a string for a Win32-specific error (i.e. an error generated when
     32  * calling a Win32 API).
     33  * For errors occurred during standard C calls, we still use pcap_strerror()
     34  */
     35 #define ERRBUF_SIZE	1024
     36 static const char *
     37 win32_strerror(DWORD error)
     38 {
     39   static char errbuf[ERRBUF_SIZE+1];
     40   size_t errlen;
     41 
     42   FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, error, 0, errbuf,
     43                 ERRBUF_SIZE, NULL);
     44 
     45   /*
     46    * "FormatMessage()" "helpfully" sticks CR/LF at the end of the
     47    * message.  Get rid of it.
     48    */
     49   errlen = strlen(errbuf);
     50   if (errlen >= 2) {
     51     errbuf[errlen - 1] = '\0';
     52     errbuf[errlen - 2] = '\0';
     53     errlen -= 2;
     54   }
     55   return errbuf;
     56 }
     57 
     58 static char *
     59 getpass(const char *prompt)
     60 {
     61   HANDLE console_handle = GetStdHandle(STD_INPUT_HANDLE);
     62   DWORD console_mode, save_console_mode;
     63   static char password[128+1];
     64   char *p;
     65 
     66   fprintf(stderr, "%s", prompt);
     67 
     68   /*
     69    * Turn off echoing.
     70    */
     71   if (!GetConsoleMode(console_handle, &console_mode)) {
     72     fprintf(stderr, "Can't get console mode: %s\n",
     73             win32_strerror(GetLastError()));
     74     exit(1);
     75   }
     76   save_console_mode = console_mode;
     77   console_mode &= ~ENABLE_ECHO_INPUT;
     78   if (!SetConsoleMode(console_handle, console_mode)) {
     79     fprintf(stderr, "Can't set console mode: %s\n",
     80             win32_strerror(GetLastError()));
     81     exit(1);
     82   }
     83   if (fgets(password, sizeof password, stdin) == NULL) {
     84     fprintf(stderr, "\n");
     85     SetConsoleMode(console_handle, save_console_mode);
     86     exit(1);
     87   }
     88   fprintf(stderr, "\n");
     89   SetConsoleMode(console_handle, save_console_mode);
     90   p = strchr(password, '\n');
     91   if (p != NULL)
     92     *p = '\0';
     93  return password;
     94 }
     95 #endif
     96 
     97 int main(int argc, char **argv)
     98 {
     99   pcap_if_t *alldevs;
    100   pcap_if_t *d;
    101   bpf_u_int32 net, mask;
    102   int exit_status = 0;
    103   char errbuf[PCAP_ERRBUF_SIZE+1];
    104 #ifdef ENABLE_REMOTE
    105   struct pcap_rmtauth auth;
    106   char username[128+1];
    107   char *p;
    108   char *password;
    109 #endif
    110 
    111 #ifdef ENABLE_REMOTE
    112   if (argc >= 2)
    113   {
    114     if (pcap_findalldevs_ex(argv[1], NULL, &alldevs, errbuf) == -1)
    115     {
    116       /*
    117        * OK, try it with a user name and password.
    118        */
    119       fprintf(stderr, "User name: ");
    120       if (fgets(username, sizeof username, stdin) == NULL)
    121         exit(1);
    122       p = strchr(username, '\n');
    123       if (p != NULL)
    124         *p = '\0';
    125       password = getpass("Password: ");
    126       auth.type = RPCAP_RMTAUTH_PWD;
    127       auth.username = username;
    128       auth.password = password;
    129       if (pcap_findalldevs_ex(argv[1], &auth, &alldevs, errbuf) == -1)
    130       {
    131         fprintf(stderr,"Error in pcap_findalldevs: %s\n",errbuf);
    132         exit(1);
    133       }
    134     }
    135   }
    136   else
    137 #endif
    138   {
    139     if (pcap_findalldevs(&alldevs, errbuf) == -1)
    140     {
    141       fprintf(stderr,"Error in pcap_findalldevs: %s\n",errbuf);
    142       exit(1);
    143     }
    144   }
    145   for(d=alldevs;d;d=d->next)
    146   {
    147     if (!ifprint(d))
    148       exit_status = 2;
    149   }
    150 
    151   if (alldevs != NULL)
    152   {
    153     if (pcap_lookupnet(alldevs->name, &net, &mask, errbuf) < 0)
    154     {
    155       fprintf(stderr,"Error in pcap_lookupnet: %s\n",errbuf);
    156       exit_status = 2;
    157     }
    158     else
    159     {
    160       printf("Preferred device is on network: %s/%s\n",iptos(net), iptos(mask));
    161     }
    162   }
    163 
    164   pcap_freealldevs(alldevs);
    165   exit(exit_status);
    166 }
    167 
    168 static int ifprint(pcap_if_t *d)
    169 {
    170   pcap_addr_t *a;
    171   char ipv4_buf[INET_ADDRSTRLEN];
    172   char ipv6_buf[INET6_ADDRSTRLEN];
    173   const char *sep;
    174   int status = 1; /* success */
    175 
    176   printf("%s\n",d->name);
    177   if (d->description)
    178     printf("\tDescription: %s\n",d->description);
    179   printf("\tFlags: ");
    180   sep = "";
    181   if (d->flags & PCAP_IF_UP) {
    182     printf("%sUP", sep);
    183     sep = ", ";
    184   }
    185   if (d->flags & PCAP_IF_RUNNING) {
    186     printf("%sRUNNING", sep);
    187     sep = ", ";
    188   }
    189   if (d->flags & PCAP_IF_LOOPBACK) {
    190     printf("%sLOOPBACK", sep);
    191     sep = ", ";
    192   }
    193   if (d->flags & PCAP_IF_WIRELESS) {
    194     printf("%sWIRELESS", sep);
    195     switch (d->flags & PCAP_IF_CONNECTION_STATUS) {
    196 
    197     case PCAP_IF_CONNECTION_STATUS_UNKNOWN:
    198       printf(" (association status unknown)");
    199       break;
    200 
    201     case PCAP_IF_CONNECTION_STATUS_CONNECTED:
    202       printf(" (associated)");
    203       break;
    204 
    205     case PCAP_IF_CONNECTION_STATUS_DISCONNECTED:
    206       printf(" (not associated)");
    207       break;
    208 
    209     case PCAP_IF_CONNECTION_STATUS_NOT_APPLICABLE:
    210       break;
    211     }
    212   } else {
    213     switch (d->flags & PCAP_IF_CONNECTION_STATUS) {
    214 
    215     case PCAP_IF_CONNECTION_STATUS_UNKNOWN:
    216       printf(" (connection status unknown)");
    217       break;
    218 
    219     case PCAP_IF_CONNECTION_STATUS_CONNECTED:
    220       printf(" (connected)");
    221       break;
    222 
    223     case PCAP_IF_CONNECTION_STATUS_DISCONNECTED:
    224       printf(" (disconnected)");
    225       break;
    226 
    227     case PCAP_IF_CONNECTION_STATUS_NOT_APPLICABLE:
    228       break;
    229     }
    230   }
    231   sep = ", ";
    232   printf("\n");
    233 
    234   for(a=d->addresses;a;a=a->next) {
    235     if (a->addr != NULL)
    236       switch(a->addr->sa_family) {
    237       case AF_INET:
    238         printf("\tAddress Family: AF_INET\n");
    239         if (a->addr)
    240           printf("\t\tAddress: %s\n",
    241             inet_ntop(AF_INET,
    242                &((struct sockaddr_in *)(a->addr))->sin_addr,
    243                ipv4_buf, sizeof ipv4_buf));
    244         if (a->netmask)
    245           printf("\t\tNetmask: %s\n",
    246             inet_ntop(AF_INET,
    247                &((struct sockaddr_in *)(a->netmask))->sin_addr,
    248                ipv4_buf, sizeof ipv4_buf));
    249         if (a->broadaddr)
    250           printf("\t\tBroadcast Address: %s\n",
    251             inet_ntop(AF_INET,
    252                &((struct sockaddr_in *)(a->broadaddr))->sin_addr,
    253                ipv4_buf, sizeof ipv4_buf));
    254         if (a->dstaddr)
    255           printf("\t\tDestination Address: %s\n",
    256             inet_ntop(AF_INET,
    257                &((struct sockaddr_in *)(a->dstaddr))->sin_addr,
    258                ipv4_buf, sizeof ipv4_buf));
    259         break;
    260 #ifdef INET6
    261       case AF_INET6:
    262         printf("\tAddress Family: AF_INET6\n");
    263         if (a->addr)
    264           printf("\t\tAddress: %s\n",
    265             inet_ntop(AF_INET6,
    266                ((struct sockaddr_in6 *)(a->addr))->sin6_addr.s6_addr,
    267                ipv6_buf, sizeof ipv6_buf));
    268         if (a->netmask)
    269           printf("\t\tNetmask: %s\n",
    270             inet_ntop(AF_INET6,
    271               ((struct sockaddr_in6 *)(a->netmask))->sin6_addr.s6_addr,
    272                ipv6_buf, sizeof ipv6_buf));
    273         if (a->broadaddr)
    274           printf("\t\tBroadcast Address: %s\n",
    275             inet_ntop(AF_INET6,
    276               ((struct sockaddr_in6 *)(a->broadaddr))->sin6_addr.s6_addr,
    277                ipv6_buf, sizeof ipv6_buf));
    278         if (a->dstaddr)
    279           printf("\t\tDestination Address: %s\n",
    280             inet_ntop(AF_INET6,
    281               ((struct sockaddr_in6 *)(a->dstaddr))->sin6_addr.s6_addr,
    282                ipv6_buf, sizeof ipv6_buf));
    283         break;
    284 #endif
    285       default:
    286         printf("\tAddress Family: Unknown (%d)\n", a->addr->sa_family);
    287         break;
    288       }
    289     else
    290     {
    291       fprintf(stderr, "\tWarning: a->addr is NULL, skipping this address.\n");
    292       status = 0;
    293     }
    294   }
    295   printf("\n");
    296   return status;
    297 }
    298 
    299 /* From tcptraceroute */
    300 #define IPTOSBUFFERS	12
    301 static char *iptos(bpf_u_int32 in)
    302 {
    303 	static char output[IPTOSBUFFERS][3*4+3+1];
    304 	static short which;
    305 	u_char *p;
    306 
    307 	p = (u_char *)&in;
    308 	which = (which + 1 == IPTOSBUFFERS ? 0 : which + 1);
    309 	sprintf(output[which], "%d.%d.%d.%d", p[0], p[1], p[2], p[3]);
    310 	return output[which];
    311 }
    312