1 #include <config.h> 2 3 #include <stdlib.h> 4 #include <string.h> 5 #include <sys/types.h> 6 #ifdef _WIN32 7 #include <winsock2.h> 8 #include <ws2tcpip.h> 9 #include <windows.h> 10 #else 11 #include <sys/socket.h> 12 #include <netinet/in.h> 13 #include <arpa/inet.h> 14 #include <netdb.h> 15 #include <unistd.h> 16 #endif 17 18 #include <pcap.h> 19 20 #include "varattrs.h" 21 #include "pcap/funcattrs.h" 22 23 static int ifprint(pcap_if_t *d); 24 static char *iptos(bpf_u_int32 in); 25 26 #ifdef _WIN32 27 #include "portability.h" 28 29 /* 30 * Generate a string for a Win32-specific error (i.e. an error generated when 31 * calling a Win32 API). 32 * For errors occurred during standard C calls, we still use pcap_strerror() 33 */ 34 #define ERRBUF_SIZE 1024 35 static const char * 36 win32_strerror(DWORD error) 37 { 38 static char errbuf[ERRBUF_SIZE+1]; 39 size_t errlen; 40 41 FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, error, 0, errbuf, 42 ERRBUF_SIZE, NULL); 43 44 /* 45 * "FormatMessage()" "helpfully" sticks CR/LF at the end of the 46 * message. Get rid of it. 47 */ 48 errlen = strlen(errbuf); 49 if (errlen >= 2) { 50 errbuf[errlen - 1] = '\0'; 51 errbuf[errlen - 2] = '\0'; 52 errlen -= 2; 53 } 54 return errbuf; 55 } 56 57 static char * 58 getpass(const char *prompt) 59 { 60 HANDLE console_handle = GetStdHandle(STD_INPUT_HANDLE); 61 DWORD console_mode, save_console_mode; 62 static char password[128+1]; 63 char *p; 64 65 fprintf(stderr, "%s", prompt); 66 67 /* 68 * Turn off echoing. 69 */ 70 if (!GetConsoleMode(console_handle, &console_mode)) { 71 fprintf(stderr, "Can't get console mode: %s\n", 72 win32_strerror(GetLastError())); 73 exit(1); 74 } 75 save_console_mode = console_mode; 76 console_mode &= ~ENABLE_ECHO_INPUT; 77 if (!SetConsoleMode(console_handle, console_mode)) { 78 fprintf(stderr, "Can't set console mode: %s\n", 79 win32_strerror(GetLastError())); 80 exit(1); 81 } 82 if (fgets(password, sizeof password, stdin) == NULL) { 83 fprintf(stderr, "\n"); 84 SetConsoleMode(console_handle, save_console_mode); 85 exit(1); 86 } 87 fprintf(stderr, "\n"); 88 SetConsoleMode(console_handle, save_console_mode); 89 p = strchr(password, '\n'); 90 if (p != NULL) 91 *p = '\0'; 92 return password; 93 } 94 #endif 95 96 #ifdef ENABLE_REMOTE 97 int main(int argc, char **argv) 98 #else 99 int main(int argc _U_, char **argv _U_) 100 #endif 101 { 102 pcap_if_t *alldevs; 103 pcap_if_t *d; 104 bpf_u_int32 net, mask; 105 int exit_status = 0; 106 char errbuf[PCAP_ERRBUF_SIZE+1]; 107 #ifdef ENABLE_REMOTE 108 struct pcap_rmtauth auth; 109 char username[128+1]; 110 char *p; 111 char *password; 112 #endif 113 114 #ifdef ENABLE_REMOTE 115 if (argc >= 2) 116 { 117 if (pcap_findalldevs_ex(argv[1], NULL, &alldevs, errbuf) == -1) 118 { 119 /* 120 * OK, try it with a user name and password. 121 */ 122 fprintf(stderr, "User name: "); 123 if (fgets(username, sizeof username, stdin) == NULL) 124 exit(1); 125 p = strchr(username, '\n'); 126 if (p != NULL) 127 *p = '\0'; 128 password = getpass("Password: "); 129 auth.type = RPCAP_RMTAUTH_PWD; 130 auth.username = username; 131 auth.password = password; 132 if (pcap_findalldevs_ex(argv[1], &auth, &alldevs, errbuf) == -1) 133 { 134 fprintf(stderr,"Error in pcap_findalldevs: %s\n",errbuf); 135 exit(1); 136 } 137 } 138 } 139 else 140 #endif 141 { 142 if (pcap_findalldevs(&alldevs, errbuf) == -1) 143 { 144 fprintf(stderr,"Error in pcap_findalldevs: %s\n",errbuf); 145 exit(1); 146 } 147 } 148 for(d=alldevs;d;d=d->next) 149 { 150 if (!ifprint(d)) 151 exit_status = 2; 152 } 153 154 if (alldevs != NULL) 155 { 156 if (pcap_lookupnet(alldevs->name, &net, &mask, errbuf) < 0) 157 { 158 /* 159 * XXX - this doesn't distinguish between "a real error 160 * occurred" and "this interface doesn't *have* an IPv4 161 * address". The latter shouldn't be treated as an error. 162 * 163 * We look for the interface name, followed by a colon and 164 * a space, and, if we find it,w e see if what follows it 165 * is "no IPv4 address assigned". 166 */ 167 size_t devnamelen = strlen(alldevs->name); 168 if (strncmp(errbuf, alldevs->name, devnamelen) == 0 && 169 strncmp(errbuf + devnamelen, ": ", 2) == 0 && 170 strcmp(errbuf + devnamelen + 2, "no IPv4 address assigned") == 0) 171 printf("Preferred device is not on an IPv4 network\n"); 172 else { 173 fprintf(stderr,"Error in pcap_lookupnet: %s\n",errbuf); 174 exit_status = 2; 175 } 176 } 177 else 178 { 179 printf("Preferred device is on network: %s/%s\n",iptos(net), iptos(mask)); 180 } 181 } 182 183 pcap_freealldevs(alldevs); 184 exit(exit_status); 185 } 186 187 static int ifprint(pcap_if_t *d) 188 { 189 pcap_addr_t *a; 190 char ipv4_buf[INET_ADDRSTRLEN]; 191 #ifdef INET6 192 char ipv6_buf[INET6_ADDRSTRLEN]; 193 #endif 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 (%d)\n", a->addr->sa_family); 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 (%d)\n", a->addr->sa_family); 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