xref: /freebsd/contrib/libpcap/testprogs/findalldevstest.c (revision afdbf109c6a661a729938f68211054a0a50d38ac)
157e22627SCy Schubert #include <config.h>
257e22627SCy Schubert 
357e22627SCy Schubert #include <stdlib.h>
457e22627SCy Schubert #include <string.h>
557e22627SCy Schubert #include <sys/types.h>
657e22627SCy Schubert #ifdef _WIN32
757e22627SCy Schubert   #include <winsock2.h>
857e22627SCy Schubert   #include <ws2tcpip.h>
957e22627SCy Schubert   #include <windows.h>
1057e22627SCy Schubert #else
1157e22627SCy Schubert   #include <sys/socket.h>
1257e22627SCy Schubert   #include <netinet/in.h>
1357e22627SCy Schubert   #include <arpa/inet.h>
1457e22627SCy Schubert   #include <netdb.h>
1557e22627SCy Schubert   #include <unistd.h>
1657e22627SCy Schubert #endif
1757e22627SCy Schubert 
1857e22627SCy Schubert #include <pcap.h>
1957e22627SCy Schubert 
206f9cba8fSJoseph Mingrone #include "varattrs.h"
2157e22627SCy Schubert #include "pcap/funcattrs.h"
2257e22627SCy Schubert 
2357e22627SCy Schubert static int ifprint(pcap_if_t *d);
2457e22627SCy Schubert static char *iptos(bpf_u_int32 in);
2557e22627SCy Schubert 
2657e22627SCy Schubert #ifdef _WIN32
2757e22627SCy Schubert #include "portability.h"
2857e22627SCy Schubert 
2957e22627SCy Schubert /*
3057e22627SCy Schubert  * Generate a string for a Win32-specific error (i.e. an error generated when
3157e22627SCy Schubert  * calling a Win32 API).
3257e22627SCy Schubert  * For errors occurred during standard C calls, we still use pcap_strerror()
3357e22627SCy Schubert  */
3457e22627SCy Schubert #define ERRBUF_SIZE	1024
3557e22627SCy Schubert static const char *
win32_strerror(DWORD error)3657e22627SCy Schubert win32_strerror(DWORD error)
3757e22627SCy Schubert {
3857e22627SCy Schubert   static char errbuf[ERRBUF_SIZE+1];
3957e22627SCy Schubert   size_t errlen;
4057e22627SCy Schubert 
4157e22627SCy Schubert   FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, error, 0, errbuf,
4257e22627SCy Schubert                 ERRBUF_SIZE, NULL);
4357e22627SCy Schubert 
4457e22627SCy Schubert   /*
4557e22627SCy Schubert    * "FormatMessage()" "helpfully" sticks CR/LF at the end of the
4657e22627SCy Schubert    * message.  Get rid of it.
4757e22627SCy Schubert    */
4857e22627SCy Schubert   errlen = strlen(errbuf);
4957e22627SCy Schubert   if (errlen >= 2) {
5057e22627SCy Schubert     errbuf[errlen - 1] = '\0';
5157e22627SCy Schubert     errbuf[errlen - 2] = '\0';
5257e22627SCy Schubert     errlen -= 2;
5357e22627SCy Schubert   }
5457e22627SCy Schubert   return errbuf;
5557e22627SCy Schubert }
5657e22627SCy Schubert 
5757e22627SCy Schubert static char *
getpass(const char * prompt)5857e22627SCy Schubert getpass(const char *prompt)
5957e22627SCy Schubert {
6057e22627SCy Schubert   HANDLE console_handle = GetStdHandle(STD_INPUT_HANDLE);
6157e22627SCy Schubert   DWORD console_mode, save_console_mode;
6257e22627SCy Schubert   static char password[128+1];
6357e22627SCy Schubert   char *p;
6457e22627SCy Schubert 
6557e22627SCy Schubert   fprintf(stderr, "%s", prompt);
6657e22627SCy Schubert 
6757e22627SCy Schubert   /*
6857e22627SCy Schubert    * Turn off echoing.
6957e22627SCy Schubert    */
7057e22627SCy Schubert   if (!GetConsoleMode(console_handle, &console_mode)) {
7157e22627SCy Schubert     fprintf(stderr, "Can't get console mode: %s\n",
7257e22627SCy Schubert             win32_strerror(GetLastError()));
7357e22627SCy Schubert     exit(1);
7457e22627SCy Schubert   }
7557e22627SCy Schubert   save_console_mode = console_mode;
7657e22627SCy Schubert   console_mode &= ~ENABLE_ECHO_INPUT;
7757e22627SCy Schubert   if (!SetConsoleMode(console_handle, console_mode)) {
7857e22627SCy Schubert     fprintf(stderr, "Can't set console mode: %s\n",
7957e22627SCy Schubert             win32_strerror(GetLastError()));
8057e22627SCy Schubert     exit(1);
8157e22627SCy Schubert   }
8257e22627SCy Schubert   if (fgets(password, sizeof password, stdin) == NULL) {
8357e22627SCy Schubert     fprintf(stderr, "\n");
8457e22627SCy Schubert     SetConsoleMode(console_handle, save_console_mode);
8557e22627SCy Schubert     exit(1);
8657e22627SCy Schubert   }
8757e22627SCy Schubert   fprintf(stderr, "\n");
8857e22627SCy Schubert   SetConsoleMode(console_handle, save_console_mode);
8957e22627SCy Schubert   p = strchr(password, '\n');
9057e22627SCy Schubert   if (p != NULL)
9157e22627SCy Schubert     *p = '\0';
9257e22627SCy Schubert  return password;
9357e22627SCy Schubert }
9457e22627SCy Schubert #endif
9557e22627SCy Schubert 
966f9cba8fSJoseph Mingrone #ifdef ENABLE_REMOTE
main(int argc,char ** argv)9757e22627SCy Schubert int main(int argc, char **argv)
986f9cba8fSJoseph Mingrone #else
996f9cba8fSJoseph Mingrone int main(int argc _U_, char **argv _U_)
1006f9cba8fSJoseph Mingrone #endif
10157e22627SCy Schubert {
10257e22627SCy Schubert   pcap_if_t *alldevs;
10357e22627SCy Schubert   pcap_if_t *d;
10457e22627SCy Schubert   bpf_u_int32 net, mask;
10557e22627SCy Schubert   int exit_status = 0;
10657e22627SCy Schubert   char errbuf[PCAP_ERRBUF_SIZE+1];
10757e22627SCy Schubert #ifdef ENABLE_REMOTE
10857e22627SCy Schubert   struct pcap_rmtauth auth;
10957e22627SCy Schubert   char username[128+1];
11057e22627SCy Schubert   char *p;
11157e22627SCy Schubert   char *password;
11257e22627SCy Schubert #endif
11357e22627SCy Schubert 
11457e22627SCy Schubert #ifdef ENABLE_REMOTE
11557e22627SCy Schubert   if (argc >= 2)
11657e22627SCy Schubert   {
11757e22627SCy Schubert     if (pcap_findalldevs_ex(argv[1], NULL, &alldevs, errbuf) == -1)
11857e22627SCy Schubert     {
11957e22627SCy Schubert       /*
12057e22627SCy Schubert        * OK, try it with a user name and password.
12157e22627SCy Schubert        */
12257e22627SCy Schubert       fprintf(stderr, "User name: ");
12357e22627SCy Schubert       if (fgets(username, sizeof username, stdin) == NULL)
12457e22627SCy Schubert         exit(1);
12557e22627SCy Schubert       p = strchr(username, '\n');
12657e22627SCy Schubert       if (p != NULL)
12757e22627SCy Schubert         *p = '\0';
12857e22627SCy Schubert       password = getpass("Password: ");
12957e22627SCy Schubert       auth.type = RPCAP_RMTAUTH_PWD;
13057e22627SCy Schubert       auth.username = username;
13157e22627SCy Schubert       auth.password = password;
13257e22627SCy Schubert       if (pcap_findalldevs_ex(argv[1], &auth, &alldevs, errbuf) == -1)
13357e22627SCy Schubert       {
13457e22627SCy Schubert         fprintf(stderr,"Error in pcap_findalldevs: %s\n",errbuf);
13557e22627SCy Schubert         exit(1);
13657e22627SCy Schubert       }
13757e22627SCy Schubert     }
13857e22627SCy Schubert   }
13957e22627SCy Schubert   else
14057e22627SCy Schubert #endif
14157e22627SCy Schubert   {
14257e22627SCy Schubert     if (pcap_findalldevs(&alldevs, errbuf) == -1)
14357e22627SCy Schubert     {
14457e22627SCy Schubert       fprintf(stderr,"Error in pcap_findalldevs: %s\n",errbuf);
14557e22627SCy Schubert       exit(1);
14657e22627SCy Schubert     }
14757e22627SCy Schubert   }
14857e22627SCy Schubert   for(d=alldevs;d;d=d->next)
14957e22627SCy Schubert   {
15057e22627SCy Schubert     if (!ifprint(d))
15157e22627SCy Schubert       exit_status = 2;
15257e22627SCy Schubert   }
15357e22627SCy Schubert 
15457e22627SCy Schubert   if (alldevs != NULL)
15557e22627SCy Schubert   {
15657e22627SCy Schubert     if (pcap_lookupnet(alldevs->name, &net, &mask, errbuf) < 0)
15757e22627SCy Schubert     {
1586f9cba8fSJoseph Mingrone       /*
1596f9cba8fSJoseph Mingrone        * XXX - this doesn't distinguish between "a real error
1606f9cba8fSJoseph Mingrone        * occurred" and "this interface doesn't *have* an IPv4
1616f9cba8fSJoseph Mingrone        * address".  The latter shouldn't be treated as an error.
1626f9cba8fSJoseph Mingrone        *
1636f9cba8fSJoseph Mingrone        * We look for the interface name, followed by a colon and
1646f9cba8fSJoseph Mingrone        * a space, and, if we find it,w e see if what follows it
1656f9cba8fSJoseph Mingrone        * is "no IPv4 address assigned".
1666f9cba8fSJoseph Mingrone        */
1676f9cba8fSJoseph Mingrone       size_t devnamelen = strlen(alldevs->name);
1686f9cba8fSJoseph Mingrone       if (strncmp(errbuf, alldevs->name, devnamelen) == 0 &&
1696f9cba8fSJoseph Mingrone           strncmp(errbuf + devnamelen, ": ", 2) == 0 &&
1706f9cba8fSJoseph Mingrone           strcmp(errbuf + devnamelen + 2, "no IPv4 address assigned") == 0)
1716f9cba8fSJoseph Mingrone         printf("Preferred device is not on an IPv4 network\n");
1726f9cba8fSJoseph Mingrone       else {
17357e22627SCy Schubert         fprintf(stderr,"Error in pcap_lookupnet: %s\n",errbuf);
17457e22627SCy Schubert         exit_status = 2;
17557e22627SCy Schubert       }
1766f9cba8fSJoseph Mingrone     }
17757e22627SCy Schubert     else
17857e22627SCy Schubert     {
17957e22627SCy Schubert       printf("Preferred device is on network: %s/%s\n",iptos(net), iptos(mask));
18057e22627SCy Schubert     }
18157e22627SCy Schubert   }
18257e22627SCy Schubert 
18357e22627SCy Schubert   pcap_freealldevs(alldevs);
18457e22627SCy Schubert   exit(exit_status);
18557e22627SCy Schubert }
18657e22627SCy Schubert 
ifprint(pcap_if_t * d)18757e22627SCy Schubert static int ifprint(pcap_if_t *d)
18857e22627SCy Schubert {
18957e22627SCy Schubert   pcap_addr_t *a;
19057e22627SCy Schubert   char ipv4_buf[INET_ADDRSTRLEN];
191*afdbf109SJoseph Mingrone #ifdef INET6
19257e22627SCy Schubert   char ipv6_buf[INET6_ADDRSTRLEN];
193*afdbf109SJoseph Mingrone #endif
19457e22627SCy Schubert   const char *sep;
19557e22627SCy Schubert   int status = 1; /* success */
19657e22627SCy Schubert 
19757e22627SCy Schubert   printf("%s\n",d->name);
19857e22627SCy Schubert   if (d->description)
19957e22627SCy Schubert     printf("\tDescription: %s\n",d->description);
20057e22627SCy Schubert   printf("\tFlags: ");
20157e22627SCy Schubert   sep = "";
20257e22627SCy Schubert   if (d->flags & PCAP_IF_UP) {
20357e22627SCy Schubert     printf("%sUP", sep);
20457e22627SCy Schubert     sep = ", ";
20557e22627SCy Schubert   }
20657e22627SCy Schubert   if (d->flags & PCAP_IF_RUNNING) {
20757e22627SCy Schubert     printf("%sRUNNING", sep);
20857e22627SCy Schubert     sep = ", ";
20957e22627SCy Schubert   }
21057e22627SCy Schubert   if (d->flags & PCAP_IF_LOOPBACK) {
21157e22627SCy Schubert     printf("%sLOOPBACK", sep);
21257e22627SCy Schubert     sep = ", ";
21357e22627SCy Schubert   }
21457e22627SCy Schubert   if (d->flags & PCAP_IF_WIRELESS) {
21557e22627SCy Schubert     printf("%sWIRELESS", sep);
21657e22627SCy Schubert     switch (d->flags & PCAP_IF_CONNECTION_STATUS) {
21757e22627SCy Schubert 
21857e22627SCy Schubert     case PCAP_IF_CONNECTION_STATUS_UNKNOWN:
21957e22627SCy Schubert       printf(" (association status unknown)");
22057e22627SCy Schubert       break;
22157e22627SCy Schubert 
22257e22627SCy Schubert     case PCAP_IF_CONNECTION_STATUS_CONNECTED:
22357e22627SCy Schubert       printf(" (associated)");
22457e22627SCy Schubert       break;
22557e22627SCy Schubert 
22657e22627SCy Schubert     case PCAP_IF_CONNECTION_STATUS_DISCONNECTED:
22757e22627SCy Schubert       printf(" (not associated)");
22857e22627SCy Schubert       break;
22957e22627SCy Schubert 
23057e22627SCy Schubert     case PCAP_IF_CONNECTION_STATUS_NOT_APPLICABLE:
23157e22627SCy Schubert       break;
23257e22627SCy Schubert     }
23357e22627SCy Schubert   } else {
23457e22627SCy Schubert     switch (d->flags & PCAP_IF_CONNECTION_STATUS) {
23557e22627SCy Schubert 
23657e22627SCy Schubert     case PCAP_IF_CONNECTION_STATUS_UNKNOWN:
23757e22627SCy Schubert       printf(" (connection status unknown)");
23857e22627SCy Schubert       break;
23957e22627SCy Schubert 
24057e22627SCy Schubert     case PCAP_IF_CONNECTION_STATUS_CONNECTED:
24157e22627SCy Schubert       printf(" (connected)");
24257e22627SCy Schubert       break;
24357e22627SCy Schubert 
24457e22627SCy Schubert     case PCAP_IF_CONNECTION_STATUS_DISCONNECTED:
24557e22627SCy Schubert       printf(" (disconnected)");
24657e22627SCy Schubert       break;
24757e22627SCy Schubert 
24857e22627SCy Schubert     case PCAP_IF_CONNECTION_STATUS_NOT_APPLICABLE:
24957e22627SCy Schubert       break;
25057e22627SCy Schubert     }
25157e22627SCy Schubert   }
25257e22627SCy Schubert   sep = ", ";
25357e22627SCy Schubert   printf("\n");
25457e22627SCy Schubert 
25557e22627SCy Schubert   for(a=d->addresses;a;a=a->next) {
25657e22627SCy Schubert     if (a->addr != NULL)
25757e22627SCy Schubert       switch(a->addr->sa_family) {
25857e22627SCy Schubert       case AF_INET:
259*afdbf109SJoseph Mingrone         printf("\tAddress Family: AF_INET (%d)\n", a->addr->sa_family);
26057e22627SCy Schubert         if (a->addr)
26157e22627SCy Schubert           printf("\t\tAddress: %s\n",
26257e22627SCy Schubert             inet_ntop(AF_INET,
26357e22627SCy Schubert                &((struct sockaddr_in *)(a->addr))->sin_addr,
26457e22627SCy Schubert                ipv4_buf, sizeof ipv4_buf));
26557e22627SCy Schubert         if (a->netmask)
26657e22627SCy Schubert           printf("\t\tNetmask: %s\n",
26757e22627SCy Schubert             inet_ntop(AF_INET,
26857e22627SCy Schubert                &((struct sockaddr_in *)(a->netmask))->sin_addr,
26957e22627SCy Schubert                ipv4_buf, sizeof ipv4_buf));
27057e22627SCy Schubert         if (a->broadaddr)
27157e22627SCy Schubert           printf("\t\tBroadcast Address: %s\n",
27257e22627SCy Schubert             inet_ntop(AF_INET,
27357e22627SCy Schubert                &((struct sockaddr_in *)(a->broadaddr))->sin_addr,
27457e22627SCy Schubert                ipv4_buf, sizeof ipv4_buf));
27557e22627SCy Schubert         if (a->dstaddr)
27657e22627SCy Schubert           printf("\t\tDestination Address: %s\n",
27757e22627SCy Schubert             inet_ntop(AF_INET,
27857e22627SCy Schubert                &((struct sockaddr_in *)(a->dstaddr))->sin_addr,
27957e22627SCy Schubert                ipv4_buf, sizeof ipv4_buf));
28057e22627SCy Schubert         break;
28157e22627SCy Schubert #ifdef INET6
28257e22627SCy Schubert       case AF_INET6:
283*afdbf109SJoseph Mingrone         printf("\tAddress Family: AF_INET6 (%d)\n", a->addr->sa_family);
28457e22627SCy Schubert         if (a->addr)
28557e22627SCy Schubert           printf("\t\tAddress: %s\n",
28657e22627SCy Schubert             inet_ntop(AF_INET6,
28757e22627SCy Schubert                ((struct sockaddr_in6 *)(a->addr))->sin6_addr.s6_addr,
28857e22627SCy Schubert                ipv6_buf, sizeof ipv6_buf));
28957e22627SCy Schubert         if (a->netmask)
29057e22627SCy Schubert           printf("\t\tNetmask: %s\n",
29157e22627SCy Schubert             inet_ntop(AF_INET6,
29257e22627SCy Schubert               ((struct sockaddr_in6 *)(a->netmask))->sin6_addr.s6_addr,
29357e22627SCy Schubert                ipv6_buf, sizeof ipv6_buf));
29457e22627SCy Schubert         if (a->broadaddr)
29557e22627SCy Schubert           printf("\t\tBroadcast Address: %s\n",
29657e22627SCy Schubert             inet_ntop(AF_INET6,
29757e22627SCy Schubert               ((struct sockaddr_in6 *)(a->broadaddr))->sin6_addr.s6_addr,
29857e22627SCy Schubert                ipv6_buf, sizeof ipv6_buf));
29957e22627SCy Schubert         if (a->dstaddr)
30057e22627SCy Schubert           printf("\t\tDestination Address: %s\n",
30157e22627SCy Schubert             inet_ntop(AF_INET6,
30257e22627SCy Schubert               ((struct sockaddr_in6 *)(a->dstaddr))->sin6_addr.s6_addr,
30357e22627SCy Schubert                ipv6_buf, sizeof ipv6_buf));
30457e22627SCy Schubert         break;
30557e22627SCy Schubert #endif
30657e22627SCy Schubert       default:
30757e22627SCy Schubert         printf("\tAddress Family: Unknown (%d)\n", a->addr->sa_family);
30857e22627SCy Schubert         break;
30957e22627SCy Schubert       }
31057e22627SCy Schubert     else
31157e22627SCy Schubert     {
31257e22627SCy Schubert       fprintf(stderr, "\tWarning: a->addr is NULL, skipping this address.\n");
31357e22627SCy Schubert       status = 0;
31457e22627SCy Schubert     }
31557e22627SCy Schubert   }
31657e22627SCy Schubert   printf("\n");
31757e22627SCy Schubert   return status;
31857e22627SCy Schubert }
31957e22627SCy Schubert 
32057e22627SCy Schubert /* From tcptraceroute */
32157e22627SCy Schubert #define IPTOSBUFFERS	12
iptos(bpf_u_int32 in)32257e22627SCy Schubert static char *iptos(bpf_u_int32 in)
32357e22627SCy Schubert {
3246f9cba8fSJoseph Mingrone 	static char output[IPTOSBUFFERS][sizeof("255.255.255.255")];
32557e22627SCy Schubert 	static short which;
32657e22627SCy Schubert 	u_char *p;
32757e22627SCy Schubert 
32857e22627SCy Schubert 	p = (u_char *)&in;
32957e22627SCy Schubert 	which = (which + 1 == IPTOSBUFFERS ? 0 : which + 1);
3306f9cba8fSJoseph Mingrone 	snprintf(output[which], sizeof(output[which]), "%d.%d.%d.%d", p[0], p[1], p[2], p[3]);
33157e22627SCy Schubert 	return output[which];
33257e22627SCy Schubert }
333