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