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
24static int ifprint(pcap_if_t *d);
25static 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
36static const char *
37win32_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
58static char *
59getpass(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
97int 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
168static 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
301static 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