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 *
win32_strerror(DWORD error)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 *
getpass(const char * prompt)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
main(int argc,char ** argv)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
ifprint(pcap_if_t * d)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
iptos(bpf_u_int32 in)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 *)∈
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