xref: /netbsd-src/external/bsd/libpcap/dist/testprogs/findalldevstest.c (revision f73a5f05f638a81353839a8e4bfc90d1189181e7)
19185e895Schristos #include <config.h>
29185e895Schristos 
39185e895Schristos #include <stdlib.h>
49185e895Schristos #include <string.h>
59185e895Schristos #include <sys/types.h>
69185e895Schristos #ifdef _WIN32
79185e895Schristos   #include <winsock2.h>
89185e895Schristos   #include <ws2tcpip.h>
99185e895Schristos   #include <windows.h>
109185e895Schristos #else
119185e895Schristos   #include <sys/socket.h>
129185e895Schristos   #include <netinet/in.h>
139185e895Schristos   #include <arpa/inet.h>
149185e895Schristos   #include <netdb.h>
159185e895Schristos   #include <unistd.h>
169185e895Schristos #endif
179185e895Schristos 
189185e895Schristos #include <pcap.h>
199185e895Schristos 
20748408edSchristos #include "varattrs.h"
219185e895Schristos #include "pcap/funcattrs.h"
229185e895Schristos 
239185e895Schristos static int ifprint(pcap_if_t *d);
249185e895Schristos static char *iptos(bpf_u_int32 in);
259185e895Schristos 
269185e895Schristos #ifdef _WIN32
279185e895Schristos #include "portability.h"
289185e895Schristos 
299185e895Schristos /*
309185e895Schristos  * Generate a string for a Win32-specific error (i.e. an error generated when
319185e895Schristos  * calling a Win32 API).
329185e895Schristos  * For errors occurred during standard C calls, we still use pcap_strerror()
339185e895Schristos  */
349185e895Schristos #define ERRBUF_SIZE	1024
359185e895Schristos static const char *
369185e895Schristos win32_strerror(DWORD error)
379185e895Schristos {
389185e895Schristos   static char errbuf[ERRBUF_SIZE+1];
399185e895Schristos   size_t errlen;
409185e895Schristos 
419185e895Schristos   FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, error, 0, errbuf,
429185e895Schristos                 ERRBUF_SIZE, NULL);
439185e895Schristos 
449185e895Schristos   /*
459185e895Schristos    * "FormatMessage()" "helpfully" sticks CR/LF at the end of the
469185e895Schristos    * message.  Get rid of it.
479185e895Schristos    */
489185e895Schristos   errlen = strlen(errbuf);
499185e895Schristos   if (errlen >= 2) {
509185e895Schristos     errbuf[errlen - 1] = '\0';
519185e895Schristos     errbuf[errlen - 2] = '\0';
529185e895Schristos     errlen -= 2;
539185e895Schristos   }
549185e895Schristos   return errbuf;
559185e895Schristos }
569185e895Schristos 
579185e895Schristos static char *
589185e895Schristos getpass(const char *prompt)
599185e895Schristos {
609185e895Schristos   HANDLE console_handle = GetStdHandle(STD_INPUT_HANDLE);
619185e895Schristos   DWORD console_mode, save_console_mode;
629185e895Schristos   static char password[128+1];
639185e895Schristos   char *p;
649185e895Schristos 
659185e895Schristos   fprintf(stderr, "%s", prompt);
669185e895Schristos 
679185e895Schristos   /*
689185e895Schristos    * Turn off echoing.
699185e895Schristos    */
709185e895Schristos   if (!GetConsoleMode(console_handle, &console_mode)) {
719185e895Schristos     fprintf(stderr, "Can't get console mode: %s\n",
729185e895Schristos             win32_strerror(GetLastError()));
739185e895Schristos     exit(1);
749185e895Schristos   }
759185e895Schristos   save_console_mode = console_mode;
769185e895Schristos   console_mode &= ~ENABLE_ECHO_INPUT;
779185e895Schristos   if (!SetConsoleMode(console_handle, console_mode)) {
789185e895Schristos     fprintf(stderr, "Can't set console mode: %s\n",
799185e895Schristos             win32_strerror(GetLastError()));
809185e895Schristos     exit(1);
819185e895Schristos   }
829185e895Schristos   if (fgets(password, sizeof password, stdin) == NULL) {
839185e895Schristos     fprintf(stderr, "\n");
849185e895Schristos     SetConsoleMode(console_handle, save_console_mode);
859185e895Schristos     exit(1);
869185e895Schristos   }
879185e895Schristos   fprintf(stderr, "\n");
889185e895Schristos   SetConsoleMode(console_handle, save_console_mode);
899185e895Schristos   p = strchr(password, '\n');
909185e895Schristos   if (p != NULL)
919185e895Schristos     *p = '\0';
929185e895Schristos  return password;
939185e895Schristos }
949185e895Schristos #endif
959185e895Schristos 
96748408edSchristos #ifdef ENABLE_REMOTE
979185e895Schristos int main(int argc, char **argv)
98748408edSchristos #else
99748408edSchristos int main(int argc _U_, char **argv _U_)
100748408edSchristos #endif
1019185e895Schristos {
1029185e895Schristos   pcap_if_t *alldevs;
1039185e895Schristos   pcap_if_t *d;
1049185e895Schristos   bpf_u_int32 net, mask;
1059185e895Schristos   int exit_status = 0;
1069185e895Schristos   char errbuf[PCAP_ERRBUF_SIZE+1];
1079185e895Schristos #ifdef ENABLE_REMOTE
1089185e895Schristos   struct pcap_rmtauth auth;
1099185e895Schristos   char username[128+1];
1109185e895Schristos   char *p;
1119185e895Schristos   char *password;
1129185e895Schristos #endif
1139185e895Schristos 
1149185e895Schristos #ifdef ENABLE_REMOTE
1159185e895Schristos   if (argc >= 2)
1169185e895Schristos   {
1179185e895Schristos     if (pcap_findalldevs_ex(argv[1], NULL, &alldevs, errbuf) == -1)
1189185e895Schristos     {
1199185e895Schristos       /*
1209185e895Schristos        * OK, try it with a user name and password.
1219185e895Schristos        */
1229185e895Schristos       fprintf(stderr, "User name: ");
1239185e895Schristos       if (fgets(username, sizeof username, stdin) == NULL)
1249185e895Schristos         exit(1);
1259185e895Schristos       p = strchr(username, '\n');
1269185e895Schristos       if (p != NULL)
1279185e895Schristos         *p = '\0';
1289185e895Schristos       password = getpass("Password: ");
1299185e895Schristos       auth.type = RPCAP_RMTAUTH_PWD;
1309185e895Schristos       auth.username = username;
1319185e895Schristos       auth.password = password;
1329185e895Schristos       if (pcap_findalldevs_ex(argv[1], &auth, &alldevs, errbuf) == -1)
1339185e895Schristos       {
1349185e895Schristos         fprintf(stderr,"Error in pcap_findalldevs: %s\n",errbuf);
1359185e895Schristos         exit(1);
1369185e895Schristos       }
1379185e895Schristos     }
1389185e895Schristos   }
1399185e895Schristos   else
1409185e895Schristos #endif
1419185e895Schristos   {
1429185e895Schristos     if (pcap_findalldevs(&alldevs, errbuf) == -1)
1439185e895Schristos     {
1449185e895Schristos       fprintf(stderr,"Error in pcap_findalldevs: %s\n",errbuf);
1459185e895Schristos       exit(1);
1469185e895Schristos     }
1479185e895Schristos   }
1489185e895Schristos   for(d=alldevs;d;d=d->next)
1499185e895Schristos   {
1509185e895Schristos     if (!ifprint(d))
1519185e895Schristos       exit_status = 2;
1529185e895Schristos   }
1539185e895Schristos 
1549185e895Schristos   if (alldevs != NULL)
1559185e895Schristos   {
1569185e895Schristos     if (pcap_lookupnet(alldevs->name, &net, &mask, errbuf) < 0)
1579185e895Schristos     {
158748408edSchristos       /*
159748408edSchristos        * XXX - this doesn't distinguish between "a real error
160748408edSchristos        * occurred" and "this interface doesn't *have* an IPv4
161748408edSchristos        * address".  The latter shouldn't be treated as an error.
162748408edSchristos        *
163748408edSchristos        * We look for the interface name, followed by a colon and
164748408edSchristos        * a space, and, if we find it,w e see if what follows it
165748408edSchristos        * is "no IPv4 address assigned".
166748408edSchristos        */
167748408edSchristos       size_t devnamelen = strlen(alldevs->name);
168748408edSchristos       if (strncmp(errbuf, alldevs->name, devnamelen) == 0 &&
169748408edSchristos           strncmp(errbuf + devnamelen, ": ", 2) == 0 &&
170748408edSchristos           strcmp(errbuf + devnamelen + 2, "no IPv4 address assigned") == 0)
171748408edSchristos         printf("Preferred device is not on an IPv4 network\n");
172748408edSchristos       else {
1739185e895Schristos         fprintf(stderr,"Error in pcap_lookupnet: %s\n",errbuf);
1749185e895Schristos         exit_status = 2;
1759185e895Schristos       }
176748408edSchristos     }
1779185e895Schristos     else
1789185e895Schristos     {
1799185e895Schristos       printf("Preferred device is on network: %s/%s\n",iptos(net), iptos(mask));
1809185e895Schristos     }
1819185e895Schristos   }
1829185e895Schristos 
1839185e895Schristos   pcap_freealldevs(alldevs);
1849185e895Schristos   exit(exit_status);
1859185e895Schristos }
1869185e895Schristos 
1879185e895Schristos static int ifprint(pcap_if_t *d)
1889185e895Schristos {
1899185e895Schristos   pcap_addr_t *a;
1909185e895Schristos   char ipv4_buf[INET_ADDRSTRLEN];
191*f73a5f05Schristos #ifdef INET6
1929185e895Schristos   char ipv6_buf[INET6_ADDRSTRLEN];
193*f73a5f05Schristos #endif
1949185e895Schristos   const char *sep;
1959185e895Schristos   int status = 1; /* success */
1969185e895Schristos 
1979185e895Schristos   printf("%s\n",d->name);
1989185e895Schristos   if (d->description)
1999185e895Schristos     printf("\tDescription: %s\n",d->description);
2009185e895Schristos   printf("\tFlags: ");
2019185e895Schristos   sep = "";
2029185e895Schristos   if (d->flags & PCAP_IF_UP) {
2039185e895Schristos     printf("%sUP", sep);
2049185e895Schristos     sep = ", ";
2059185e895Schristos   }
2069185e895Schristos   if (d->flags & PCAP_IF_RUNNING) {
2079185e895Schristos     printf("%sRUNNING", sep);
2089185e895Schristos     sep = ", ";
2099185e895Schristos   }
2109185e895Schristos   if (d->flags & PCAP_IF_LOOPBACK) {
2119185e895Schristos     printf("%sLOOPBACK", sep);
2129185e895Schristos     sep = ", ";
2139185e895Schristos   }
2149185e895Schristos   if (d->flags & PCAP_IF_WIRELESS) {
2159185e895Schristos     printf("%sWIRELESS", sep);
2169185e895Schristos     switch (d->flags & PCAP_IF_CONNECTION_STATUS) {
2179185e895Schristos 
2189185e895Schristos     case PCAP_IF_CONNECTION_STATUS_UNKNOWN:
2199185e895Schristos       printf(" (association status unknown)");
2209185e895Schristos       break;
2219185e895Schristos 
2229185e895Schristos     case PCAP_IF_CONNECTION_STATUS_CONNECTED:
2239185e895Schristos       printf(" (associated)");
2249185e895Schristos       break;
2259185e895Schristos 
2269185e895Schristos     case PCAP_IF_CONNECTION_STATUS_DISCONNECTED:
2279185e895Schristos       printf(" (not associated)");
2289185e895Schristos       break;
2299185e895Schristos 
2309185e895Schristos     case PCAP_IF_CONNECTION_STATUS_NOT_APPLICABLE:
2319185e895Schristos       break;
2329185e895Schristos     }
2339185e895Schristos   } else {
2349185e895Schristos     switch (d->flags & PCAP_IF_CONNECTION_STATUS) {
2359185e895Schristos 
2369185e895Schristos     case PCAP_IF_CONNECTION_STATUS_UNKNOWN:
2379185e895Schristos       printf(" (connection status unknown)");
2389185e895Schristos       break;
2399185e895Schristos 
2409185e895Schristos     case PCAP_IF_CONNECTION_STATUS_CONNECTED:
2419185e895Schristos       printf(" (connected)");
2429185e895Schristos       break;
2439185e895Schristos 
2449185e895Schristos     case PCAP_IF_CONNECTION_STATUS_DISCONNECTED:
2459185e895Schristos       printf(" (disconnected)");
2469185e895Schristos       break;
2479185e895Schristos 
2489185e895Schristos     case PCAP_IF_CONNECTION_STATUS_NOT_APPLICABLE:
2499185e895Schristos       break;
2509185e895Schristos     }
2519185e895Schristos   }
2529185e895Schristos   sep = ", ";
2539185e895Schristos   printf("\n");
2549185e895Schristos 
2559185e895Schristos   for(a=d->addresses;a;a=a->next) {
2569185e895Schristos     if (a->addr != NULL)
2579185e895Schristos       switch(a->addr->sa_family) {
2589185e895Schristos       case AF_INET:
259*f73a5f05Schristos         printf("\tAddress Family: AF_INET (%d)\n", a->addr->sa_family);
2609185e895Schristos         if (a->addr)
2619185e895Schristos           printf("\t\tAddress: %s\n",
2629185e895Schristos             inet_ntop(AF_INET,
2639185e895Schristos                &((struct sockaddr_in *)(a->addr))->sin_addr,
2649185e895Schristos                ipv4_buf, sizeof ipv4_buf));
2659185e895Schristos         if (a->netmask)
2669185e895Schristos           printf("\t\tNetmask: %s\n",
2679185e895Schristos             inet_ntop(AF_INET,
2689185e895Schristos                &((struct sockaddr_in *)(a->netmask))->sin_addr,
2699185e895Schristos                ipv4_buf, sizeof ipv4_buf));
2709185e895Schristos         if (a->broadaddr)
2719185e895Schristos           printf("\t\tBroadcast Address: %s\n",
2729185e895Schristos             inet_ntop(AF_INET,
2739185e895Schristos                &((struct sockaddr_in *)(a->broadaddr))->sin_addr,
2749185e895Schristos                ipv4_buf, sizeof ipv4_buf));
2759185e895Schristos         if (a->dstaddr)
2769185e895Schristos           printf("\t\tDestination Address: %s\n",
2779185e895Schristos             inet_ntop(AF_INET,
2789185e895Schristos                &((struct sockaddr_in *)(a->dstaddr))->sin_addr,
2799185e895Schristos                ipv4_buf, sizeof ipv4_buf));
2809185e895Schristos         break;
2819185e895Schristos #ifdef INET6
2829185e895Schristos       case AF_INET6:
283*f73a5f05Schristos         printf("\tAddress Family: AF_INET6 (%d)\n", a->addr->sa_family);
2849185e895Schristos         if (a->addr)
2859185e895Schristos           printf("\t\tAddress: %s\n",
2869185e895Schristos             inet_ntop(AF_INET6,
2879185e895Schristos                ((struct sockaddr_in6 *)(a->addr))->sin6_addr.s6_addr,
2889185e895Schristos                ipv6_buf, sizeof ipv6_buf));
2899185e895Schristos         if (a->netmask)
2909185e895Schristos           printf("\t\tNetmask: %s\n",
2919185e895Schristos             inet_ntop(AF_INET6,
2929185e895Schristos               ((struct sockaddr_in6 *)(a->netmask))->sin6_addr.s6_addr,
2939185e895Schristos                ipv6_buf, sizeof ipv6_buf));
2949185e895Schristos         if (a->broadaddr)
2959185e895Schristos           printf("\t\tBroadcast Address: %s\n",
2969185e895Schristos             inet_ntop(AF_INET6,
2979185e895Schristos               ((struct sockaddr_in6 *)(a->broadaddr))->sin6_addr.s6_addr,
2989185e895Schristos                ipv6_buf, sizeof ipv6_buf));
2999185e895Schristos         if (a->dstaddr)
3009185e895Schristos           printf("\t\tDestination Address: %s\n",
3019185e895Schristos             inet_ntop(AF_INET6,
3029185e895Schristos               ((struct sockaddr_in6 *)(a->dstaddr))->sin6_addr.s6_addr,
3039185e895Schristos                ipv6_buf, sizeof ipv6_buf));
3049185e895Schristos         break;
3059185e895Schristos #endif
3069185e895Schristos       default:
3079185e895Schristos         printf("\tAddress Family: Unknown (%d)\n", a->addr->sa_family);
3089185e895Schristos         break;
3099185e895Schristos       }
3109185e895Schristos     else
3119185e895Schristos     {
3129185e895Schristos       fprintf(stderr, "\tWarning: a->addr is NULL, skipping this address.\n");
3139185e895Schristos       status = 0;
3149185e895Schristos     }
3159185e895Schristos   }
3169185e895Schristos   printf("\n");
3179185e895Schristos   return status;
3189185e895Schristos }
3199185e895Schristos 
3209185e895Schristos /* From tcptraceroute */
3219185e895Schristos #define IPTOSBUFFERS	12
3229185e895Schristos static char *iptos(bpf_u_int32 in)
3239185e895Schristos {
324748408edSchristos 	static char output[IPTOSBUFFERS][sizeof("255.255.255.255")];
3259185e895Schristos 	static short which;
3269185e895Schristos 	u_char *p;
3279185e895Schristos 
3289185e895Schristos 	p = (u_char *)&in;
3299185e895Schristos 	which = (which + 1 == IPTOSBUFFERS ? 0 : which + 1);
330748408edSchristos 	snprintf(output[which], sizeof(output[which]), "%d.%d.%d.%d", p[0], p[1], p[2], p[3]);
3319185e895Schristos 	return output[which];
3329185e895Schristos }
333