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 "varattrs.h" 23 #include "pcap/funcattrs.h" 24 25 static int ifprint(pcap_if_t *d); 26 static char *iptos(bpf_u_int32 in); 27 28 #ifdef _WIN32 29 #include "portability.h" 30 31 /* 32 * Generate a string for a Win32-specific error (i.e. an error generated when 33 * calling a Win32 API). 34 * For errors occurred during standard C calls, we still use pcap_strerror() 35 */ 36 #define ERRBUF_SIZE 1024 37 static const char * 38 win32_strerror(DWORD error) 39 { 40 static char errbuf[ERRBUF_SIZE+1]; 41 size_t errlen; 42 43 FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, error, 0, errbuf, 44 ERRBUF_SIZE, NULL); 45 46 /* 47 * "FormatMessage()" "helpfully" sticks CR/LF at the end of the 48 * message. Get rid of it. 49 */ 50 errlen = strlen(errbuf); 51 if (errlen >= 2) { 52 errbuf[errlen - 1] = '\0'; 53 errbuf[errlen - 2] = '\0'; 54 errlen -= 2; 55 } 56 return errbuf; 57 } 58 59 static char * 60 getpass(const char *prompt) 61 { 62 HANDLE console_handle = GetStdHandle(STD_INPUT_HANDLE); 63 DWORD console_mode, save_console_mode; 64 static char password[128+1]; 65 char *p; 66 67 fprintf(stderr, "%s", prompt); 68 69 /* 70 * Turn off echoing. 71 */ 72 if (!GetConsoleMode(console_handle, &console_mode)) { 73 fprintf(stderr, "Can't get console mode: %s\n", 74 win32_strerror(GetLastError())); 75 exit(1); 76 } 77 save_console_mode = console_mode; 78 console_mode &= ~ENABLE_ECHO_INPUT; 79 if (!SetConsoleMode(console_handle, console_mode)) { 80 fprintf(stderr, "Can't set console mode: %s\n", 81 win32_strerror(GetLastError())); 82 exit(1); 83 } 84 if (fgets(password, sizeof password, stdin) == NULL) { 85 fprintf(stderr, "\n"); 86 SetConsoleMode(console_handle, save_console_mode); 87 exit(1); 88 } 89 fprintf(stderr, "\n"); 90 SetConsoleMode(console_handle, save_console_mode); 91 p = strchr(password, '\n'); 92 if (p != NULL) 93 *p = '\0'; 94 return password; 95 } 96 #endif 97 98 #ifdef ENABLE_REMOTE 99 int main(int argc, char **argv) 100 #else 101 int main(int argc _U_, char **argv _U_) 102 #endif 103 { 104 pcap_if_t *alldevs; 105 pcap_if_t *d; 106 bpf_u_int32 net, mask; 107 int exit_status = 0; 108 char errbuf[PCAP_ERRBUF_SIZE+1]; 109 #ifdef ENABLE_REMOTE 110 struct pcap_rmtauth auth; 111 char username[128+1]; 112 char *p; 113 char *password; 114 #endif 115 116 #ifdef ENABLE_REMOTE 117 if (argc >= 2) 118 { 119 if (pcap_findalldevs_ex(argv[1], NULL, &alldevs, errbuf) == -1) 120 { 121 /* 122 * OK, try it with a user name and password. 123 */ 124 fprintf(stderr, "User name: "); 125 if (fgets(username, sizeof username, stdin) == NULL) 126 exit(1); 127 p = strchr(username, '\n'); 128 if (p != NULL) 129 *p = '\0'; 130 password = getpass("Password: "); 131 auth.type = RPCAP_RMTAUTH_PWD; 132 auth.username = username; 133 auth.password = password; 134 if (pcap_findalldevs_ex(argv[1], &auth, &alldevs, errbuf) == -1) 135 { 136 fprintf(stderr,"Error in pcap_findalldevs: %s\n",errbuf); 137 exit(1); 138 } 139 } 140 } 141 else 142 #endif 143 { 144 if (pcap_findalldevs(&alldevs, errbuf) == -1) 145 { 146 fprintf(stderr,"Error in pcap_findalldevs: %s\n",errbuf); 147 exit(1); 148 } 149 } 150 for(d=alldevs;d;d=d->next) 151 { 152 if (!ifprint(d)) 153 exit_status = 2; 154 } 155 156 if (alldevs != NULL) 157 { 158 if (pcap_lookupnet(alldevs->name, &net, &mask, errbuf) < 0) 159 { 160 /* 161 * XXX - this doesn't distinguish between "a real error 162 * occurred" and "this interface doesn't *have* an IPv4 163 * address". The latter shouldn't be treated as an error. 164 * 165 * We look for the interface name, followed by a colon and 166 * a space, and, if we find it,w e see if what follows it 167 * is "no IPv4 address assigned". 168 */ 169 size_t devnamelen = strlen(alldevs->name); 170 if (strncmp(errbuf, alldevs->name, devnamelen) == 0 && 171 strncmp(errbuf + devnamelen, ": ", 2) == 0 && 172 strcmp(errbuf + devnamelen + 2, "no IPv4 address assigned") == 0) 173 printf("Preferred device is not on an IPv4 network\n"); 174 else { 175 fprintf(stderr,"Error in pcap_lookupnet: %s\n",errbuf); 176 exit_status = 2; 177 } 178 } 179 else 180 { 181 printf("Preferred device is on network: %s/%s\n",iptos(net), iptos(mask)); 182 } 183 } 184 185 pcap_freealldevs(alldevs); 186 exit(exit_status); 187 } 188 189 static int ifprint(pcap_if_t *d) 190 { 191 pcap_addr_t *a; 192 char ipv4_buf[INET_ADDRSTRLEN]; 193 char ipv6_buf[INET6_ADDRSTRLEN]; 194 const char *sep; 195 int status = 1; /* success */ 196 197 printf("%s\n",d->name); 198 if (d->description) 199 printf("\tDescription: %s\n",d->description); 200 printf("\tFlags: "); 201 sep = ""; 202 if (d->flags & PCAP_IF_UP) { 203 printf("%sUP", sep); 204 sep = ", "; 205 } 206 if (d->flags & PCAP_IF_RUNNING) { 207 printf("%sRUNNING", sep); 208 sep = ", "; 209 } 210 if (d->flags & PCAP_IF_LOOPBACK) { 211 printf("%sLOOPBACK", sep); 212 sep = ", "; 213 } 214 if (d->flags & PCAP_IF_WIRELESS) { 215 printf("%sWIRELESS", sep); 216 switch (d->flags & PCAP_IF_CONNECTION_STATUS) { 217 218 case PCAP_IF_CONNECTION_STATUS_UNKNOWN: 219 printf(" (association status unknown)"); 220 break; 221 222 case PCAP_IF_CONNECTION_STATUS_CONNECTED: 223 printf(" (associated)"); 224 break; 225 226 case PCAP_IF_CONNECTION_STATUS_DISCONNECTED: 227 printf(" (not associated)"); 228 break; 229 230 case PCAP_IF_CONNECTION_STATUS_NOT_APPLICABLE: 231 break; 232 } 233 } else { 234 switch (d->flags & PCAP_IF_CONNECTION_STATUS) { 235 236 case PCAP_IF_CONNECTION_STATUS_UNKNOWN: 237 printf(" (connection status unknown)"); 238 break; 239 240 case PCAP_IF_CONNECTION_STATUS_CONNECTED: 241 printf(" (connected)"); 242 break; 243 244 case PCAP_IF_CONNECTION_STATUS_DISCONNECTED: 245 printf(" (disconnected)"); 246 break; 247 248 case PCAP_IF_CONNECTION_STATUS_NOT_APPLICABLE: 249 break; 250 } 251 } 252 sep = ", "; 253 printf("\n"); 254 255 for(a=d->addresses;a;a=a->next) { 256 if (a->addr != NULL) 257 switch(a->addr->sa_family) { 258 case AF_INET: 259 printf("\tAddress Family: AF_INET\n"); 260 if (a->addr) 261 printf("\t\tAddress: %s\n", 262 inet_ntop(AF_INET, 263 &((struct sockaddr_in *)(a->addr))->sin_addr, 264 ipv4_buf, sizeof ipv4_buf)); 265 if (a->netmask) 266 printf("\t\tNetmask: %s\n", 267 inet_ntop(AF_INET, 268 &((struct sockaddr_in *)(a->netmask))->sin_addr, 269 ipv4_buf, sizeof ipv4_buf)); 270 if (a->broadaddr) 271 printf("\t\tBroadcast Address: %s\n", 272 inet_ntop(AF_INET, 273 &((struct sockaddr_in *)(a->broadaddr))->sin_addr, 274 ipv4_buf, sizeof ipv4_buf)); 275 if (a->dstaddr) 276 printf("\t\tDestination Address: %s\n", 277 inet_ntop(AF_INET, 278 &((struct sockaddr_in *)(a->dstaddr))->sin_addr, 279 ipv4_buf, sizeof ipv4_buf)); 280 break; 281 #ifdef INET6 282 case AF_INET6: 283 printf("\tAddress Family: AF_INET6\n"); 284 if (a->addr) 285 printf("\t\tAddress: %s\n", 286 inet_ntop(AF_INET6, 287 ((struct sockaddr_in6 *)(a->addr))->sin6_addr.s6_addr, 288 ipv6_buf, sizeof ipv6_buf)); 289 if (a->netmask) 290 printf("\t\tNetmask: %s\n", 291 inet_ntop(AF_INET6, 292 ((struct sockaddr_in6 *)(a->netmask))->sin6_addr.s6_addr, 293 ipv6_buf, sizeof ipv6_buf)); 294 if (a->broadaddr) 295 printf("\t\tBroadcast Address: %s\n", 296 inet_ntop(AF_INET6, 297 ((struct sockaddr_in6 *)(a->broadaddr))->sin6_addr.s6_addr, 298 ipv6_buf, sizeof ipv6_buf)); 299 if (a->dstaddr) 300 printf("\t\tDestination Address: %s\n", 301 inet_ntop(AF_INET6, 302 ((struct sockaddr_in6 *)(a->dstaddr))->sin6_addr.s6_addr, 303 ipv6_buf, sizeof ipv6_buf)); 304 break; 305 #endif 306 default: 307 printf("\tAddress Family: Unknown (%d)\n", a->addr->sa_family); 308 break; 309 } 310 else 311 { 312 fprintf(stderr, "\tWarning: a->addr is NULL, skipping this address.\n"); 313 status = 0; 314 } 315 } 316 printf("\n"); 317 return status; 318 } 319 320 /* From tcptraceroute */ 321 #define IPTOSBUFFERS 12 322 static char *iptos(bpf_u_int32 in) 323 { 324 static char output[IPTOSBUFFERS][sizeof("255.255.255.255")]; 325 static short which; 326 u_char *p; 327 328 p = (u_char *)∈ 329 which = (which + 1 == IPTOSBUFFERS ? 0 : which + 1); 330 snprintf(output[which], sizeof(output[which]), "%d.%d.%d.%d", p[0], p[1], p[2], p[3]); 331 return output[which]; 332 } 333