157e22627SCy Schubert #ifdef HAVE_CONFIG_H 257e22627SCy Schubert #include <config.h> 357e22627SCy Schubert #endif 457e22627SCy Schubert 557e22627SCy Schubert #include <stdlib.h> 657e22627SCy Schubert #include <string.h> 757e22627SCy Schubert #include <sys/types.h> 857e22627SCy Schubert #ifdef _WIN32 957e22627SCy Schubert #include <winsock2.h> 1057e22627SCy Schubert #include <ws2tcpip.h> 1157e22627SCy Schubert #include <windows.h> 1257e22627SCy Schubert #else 1357e22627SCy Schubert #include <sys/socket.h> 1457e22627SCy Schubert #include <netinet/in.h> 1557e22627SCy Schubert #include <arpa/inet.h> 1657e22627SCy Schubert #include <netdb.h> 1757e22627SCy Schubert #include <unistd.h> 1857e22627SCy Schubert #endif 1957e22627SCy Schubert 2057e22627SCy Schubert #include <pcap.h> 2157e22627SCy Schubert 22*6f9cba8fSJoseph Mingrone #include "varattrs.h" 2357e22627SCy Schubert #include "pcap/funcattrs.h" 2457e22627SCy Schubert 2557e22627SCy Schubert static int ifprint(pcap_if_t *d); 2657e22627SCy Schubert static char *iptos(bpf_u_int32 in); 2757e22627SCy Schubert 2857e22627SCy Schubert #ifdef _WIN32 2957e22627SCy Schubert #include "portability.h" 3057e22627SCy Schubert 3157e22627SCy Schubert /* 3257e22627SCy Schubert * Generate a string for a Win32-specific error (i.e. an error generated when 3357e22627SCy Schubert * calling a Win32 API). 3457e22627SCy Schubert * For errors occurred during standard C calls, we still use pcap_strerror() 3557e22627SCy Schubert */ 3657e22627SCy Schubert #define ERRBUF_SIZE 1024 3757e22627SCy Schubert static const char * 3857e22627SCy Schubert win32_strerror(DWORD error) 3957e22627SCy Schubert { 4057e22627SCy Schubert static char errbuf[ERRBUF_SIZE+1]; 4157e22627SCy Schubert size_t errlen; 4257e22627SCy Schubert 4357e22627SCy Schubert FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, error, 0, errbuf, 4457e22627SCy Schubert ERRBUF_SIZE, NULL); 4557e22627SCy Schubert 4657e22627SCy Schubert /* 4757e22627SCy Schubert * "FormatMessage()" "helpfully" sticks CR/LF at the end of the 4857e22627SCy Schubert * message. Get rid of it. 4957e22627SCy Schubert */ 5057e22627SCy Schubert errlen = strlen(errbuf); 5157e22627SCy Schubert if (errlen >= 2) { 5257e22627SCy Schubert errbuf[errlen - 1] = '\0'; 5357e22627SCy Schubert errbuf[errlen - 2] = '\0'; 5457e22627SCy Schubert errlen -= 2; 5557e22627SCy Schubert } 5657e22627SCy Schubert return errbuf; 5757e22627SCy Schubert } 5857e22627SCy Schubert 5957e22627SCy Schubert static char * 6057e22627SCy Schubert getpass(const char *prompt) 6157e22627SCy Schubert { 6257e22627SCy Schubert HANDLE console_handle = GetStdHandle(STD_INPUT_HANDLE); 6357e22627SCy Schubert DWORD console_mode, save_console_mode; 6457e22627SCy Schubert static char password[128+1]; 6557e22627SCy Schubert char *p; 6657e22627SCy Schubert 6757e22627SCy Schubert fprintf(stderr, "%s", prompt); 6857e22627SCy Schubert 6957e22627SCy Schubert /* 7057e22627SCy Schubert * Turn off echoing. 7157e22627SCy Schubert */ 7257e22627SCy Schubert if (!GetConsoleMode(console_handle, &console_mode)) { 7357e22627SCy Schubert fprintf(stderr, "Can't get console mode: %s\n", 7457e22627SCy Schubert win32_strerror(GetLastError())); 7557e22627SCy Schubert exit(1); 7657e22627SCy Schubert } 7757e22627SCy Schubert save_console_mode = console_mode; 7857e22627SCy Schubert console_mode &= ~ENABLE_ECHO_INPUT; 7957e22627SCy Schubert if (!SetConsoleMode(console_handle, console_mode)) { 8057e22627SCy Schubert fprintf(stderr, "Can't set console mode: %s\n", 8157e22627SCy Schubert win32_strerror(GetLastError())); 8257e22627SCy Schubert exit(1); 8357e22627SCy Schubert } 8457e22627SCy Schubert if (fgets(password, sizeof password, stdin) == NULL) { 8557e22627SCy Schubert fprintf(stderr, "\n"); 8657e22627SCy Schubert SetConsoleMode(console_handle, save_console_mode); 8757e22627SCy Schubert exit(1); 8857e22627SCy Schubert } 8957e22627SCy Schubert fprintf(stderr, "\n"); 9057e22627SCy Schubert SetConsoleMode(console_handle, save_console_mode); 9157e22627SCy Schubert p = strchr(password, '\n'); 9257e22627SCy Schubert if (p != NULL) 9357e22627SCy Schubert *p = '\0'; 9457e22627SCy Schubert return password; 9557e22627SCy Schubert } 9657e22627SCy Schubert #endif 9757e22627SCy Schubert 98*6f9cba8fSJoseph Mingrone #ifdef ENABLE_REMOTE 9957e22627SCy Schubert int main(int argc, char **argv) 100*6f9cba8fSJoseph Mingrone #else 101*6f9cba8fSJoseph Mingrone int main(int argc _U_, char **argv _U_) 102*6f9cba8fSJoseph Mingrone #endif 10357e22627SCy Schubert { 10457e22627SCy Schubert pcap_if_t *alldevs; 10557e22627SCy Schubert pcap_if_t *d; 10657e22627SCy Schubert bpf_u_int32 net, mask; 10757e22627SCy Schubert int exit_status = 0; 10857e22627SCy Schubert char errbuf[PCAP_ERRBUF_SIZE+1]; 10957e22627SCy Schubert #ifdef ENABLE_REMOTE 11057e22627SCy Schubert struct pcap_rmtauth auth; 11157e22627SCy Schubert char username[128+1]; 11257e22627SCy Schubert char *p; 11357e22627SCy Schubert char *password; 11457e22627SCy Schubert #endif 11557e22627SCy Schubert 11657e22627SCy Schubert #ifdef ENABLE_REMOTE 11757e22627SCy Schubert if (argc >= 2) 11857e22627SCy Schubert { 11957e22627SCy Schubert if (pcap_findalldevs_ex(argv[1], NULL, &alldevs, errbuf) == -1) 12057e22627SCy Schubert { 12157e22627SCy Schubert /* 12257e22627SCy Schubert * OK, try it with a user name and password. 12357e22627SCy Schubert */ 12457e22627SCy Schubert fprintf(stderr, "User name: "); 12557e22627SCy Schubert if (fgets(username, sizeof username, stdin) == NULL) 12657e22627SCy Schubert exit(1); 12757e22627SCy Schubert p = strchr(username, '\n'); 12857e22627SCy Schubert if (p != NULL) 12957e22627SCy Schubert *p = '\0'; 13057e22627SCy Schubert password = getpass("Password: "); 13157e22627SCy Schubert auth.type = RPCAP_RMTAUTH_PWD; 13257e22627SCy Schubert auth.username = username; 13357e22627SCy Schubert auth.password = password; 13457e22627SCy Schubert if (pcap_findalldevs_ex(argv[1], &auth, &alldevs, errbuf) == -1) 13557e22627SCy Schubert { 13657e22627SCy Schubert fprintf(stderr,"Error in pcap_findalldevs: %s\n",errbuf); 13757e22627SCy Schubert exit(1); 13857e22627SCy Schubert } 13957e22627SCy Schubert } 14057e22627SCy Schubert } 14157e22627SCy Schubert else 14257e22627SCy Schubert #endif 14357e22627SCy Schubert { 14457e22627SCy Schubert if (pcap_findalldevs(&alldevs, errbuf) == -1) 14557e22627SCy Schubert { 14657e22627SCy Schubert fprintf(stderr,"Error in pcap_findalldevs: %s\n",errbuf); 14757e22627SCy Schubert exit(1); 14857e22627SCy Schubert } 14957e22627SCy Schubert } 15057e22627SCy Schubert for(d=alldevs;d;d=d->next) 15157e22627SCy Schubert { 15257e22627SCy Schubert if (!ifprint(d)) 15357e22627SCy Schubert exit_status = 2; 15457e22627SCy Schubert } 15557e22627SCy Schubert 15657e22627SCy Schubert if (alldevs != NULL) 15757e22627SCy Schubert { 15857e22627SCy Schubert if (pcap_lookupnet(alldevs->name, &net, &mask, errbuf) < 0) 15957e22627SCy Schubert { 160*6f9cba8fSJoseph Mingrone /* 161*6f9cba8fSJoseph Mingrone * XXX - this doesn't distinguish between "a real error 162*6f9cba8fSJoseph Mingrone * occurred" and "this interface doesn't *have* an IPv4 163*6f9cba8fSJoseph Mingrone * address". The latter shouldn't be treated as an error. 164*6f9cba8fSJoseph Mingrone * 165*6f9cba8fSJoseph Mingrone * We look for the interface name, followed by a colon and 166*6f9cba8fSJoseph Mingrone * a space, and, if we find it,w e see if what follows it 167*6f9cba8fSJoseph Mingrone * is "no IPv4 address assigned". 168*6f9cba8fSJoseph Mingrone */ 169*6f9cba8fSJoseph Mingrone size_t devnamelen = strlen(alldevs->name); 170*6f9cba8fSJoseph Mingrone if (strncmp(errbuf, alldevs->name, devnamelen) == 0 && 171*6f9cba8fSJoseph Mingrone strncmp(errbuf + devnamelen, ": ", 2) == 0 && 172*6f9cba8fSJoseph Mingrone strcmp(errbuf + devnamelen + 2, "no IPv4 address assigned") == 0) 173*6f9cba8fSJoseph Mingrone printf("Preferred device is not on an IPv4 network\n"); 174*6f9cba8fSJoseph Mingrone else { 17557e22627SCy Schubert fprintf(stderr,"Error in pcap_lookupnet: %s\n",errbuf); 17657e22627SCy Schubert exit_status = 2; 17757e22627SCy Schubert } 178*6f9cba8fSJoseph Mingrone } 17957e22627SCy Schubert else 18057e22627SCy Schubert { 18157e22627SCy Schubert printf("Preferred device is on network: %s/%s\n",iptos(net), iptos(mask)); 18257e22627SCy Schubert } 18357e22627SCy Schubert } 18457e22627SCy Schubert 18557e22627SCy Schubert pcap_freealldevs(alldevs); 18657e22627SCy Schubert exit(exit_status); 18757e22627SCy Schubert } 18857e22627SCy Schubert 18957e22627SCy Schubert static int ifprint(pcap_if_t *d) 19057e22627SCy Schubert { 19157e22627SCy Schubert pcap_addr_t *a; 19257e22627SCy Schubert char ipv4_buf[INET_ADDRSTRLEN]; 19357e22627SCy Schubert char ipv6_buf[INET6_ADDRSTRLEN]; 19457e22627SCy Schubert const char *sep; 19557e22627SCy Schubert int status = 1; /* success */ 19657e22627SCy Schubert 19757e22627SCy Schubert printf("%s\n",d->name); 19857e22627SCy Schubert if (d->description) 19957e22627SCy Schubert printf("\tDescription: %s\n",d->description); 20057e22627SCy Schubert printf("\tFlags: "); 20157e22627SCy Schubert sep = ""; 20257e22627SCy Schubert if (d->flags & PCAP_IF_UP) { 20357e22627SCy Schubert printf("%sUP", sep); 20457e22627SCy Schubert sep = ", "; 20557e22627SCy Schubert } 20657e22627SCy Schubert if (d->flags & PCAP_IF_RUNNING) { 20757e22627SCy Schubert printf("%sRUNNING", sep); 20857e22627SCy Schubert sep = ", "; 20957e22627SCy Schubert } 21057e22627SCy Schubert if (d->flags & PCAP_IF_LOOPBACK) { 21157e22627SCy Schubert printf("%sLOOPBACK", sep); 21257e22627SCy Schubert sep = ", "; 21357e22627SCy Schubert } 21457e22627SCy Schubert if (d->flags & PCAP_IF_WIRELESS) { 21557e22627SCy Schubert printf("%sWIRELESS", sep); 21657e22627SCy Schubert switch (d->flags & PCAP_IF_CONNECTION_STATUS) { 21757e22627SCy Schubert 21857e22627SCy Schubert case PCAP_IF_CONNECTION_STATUS_UNKNOWN: 21957e22627SCy Schubert printf(" (association status unknown)"); 22057e22627SCy Schubert break; 22157e22627SCy Schubert 22257e22627SCy Schubert case PCAP_IF_CONNECTION_STATUS_CONNECTED: 22357e22627SCy Schubert printf(" (associated)"); 22457e22627SCy Schubert break; 22557e22627SCy Schubert 22657e22627SCy Schubert case PCAP_IF_CONNECTION_STATUS_DISCONNECTED: 22757e22627SCy Schubert printf(" (not associated)"); 22857e22627SCy Schubert break; 22957e22627SCy Schubert 23057e22627SCy Schubert case PCAP_IF_CONNECTION_STATUS_NOT_APPLICABLE: 23157e22627SCy Schubert break; 23257e22627SCy Schubert } 23357e22627SCy Schubert } else { 23457e22627SCy Schubert switch (d->flags & PCAP_IF_CONNECTION_STATUS) { 23557e22627SCy Schubert 23657e22627SCy Schubert case PCAP_IF_CONNECTION_STATUS_UNKNOWN: 23757e22627SCy Schubert printf(" (connection status unknown)"); 23857e22627SCy Schubert break; 23957e22627SCy Schubert 24057e22627SCy Schubert case PCAP_IF_CONNECTION_STATUS_CONNECTED: 24157e22627SCy Schubert printf(" (connected)"); 24257e22627SCy Schubert break; 24357e22627SCy Schubert 24457e22627SCy Schubert case PCAP_IF_CONNECTION_STATUS_DISCONNECTED: 24557e22627SCy Schubert printf(" (disconnected)"); 24657e22627SCy Schubert break; 24757e22627SCy Schubert 24857e22627SCy Schubert case PCAP_IF_CONNECTION_STATUS_NOT_APPLICABLE: 24957e22627SCy Schubert break; 25057e22627SCy Schubert } 25157e22627SCy Schubert } 25257e22627SCy Schubert sep = ", "; 25357e22627SCy Schubert printf("\n"); 25457e22627SCy Schubert 25557e22627SCy Schubert for(a=d->addresses;a;a=a->next) { 25657e22627SCy Schubert if (a->addr != NULL) 25757e22627SCy Schubert switch(a->addr->sa_family) { 25857e22627SCy Schubert case AF_INET: 25957e22627SCy Schubert printf("\tAddress Family: AF_INET\n"); 26057e22627SCy Schubert if (a->addr) 26157e22627SCy Schubert printf("\t\tAddress: %s\n", 26257e22627SCy Schubert inet_ntop(AF_INET, 26357e22627SCy Schubert &((struct sockaddr_in *)(a->addr))->sin_addr, 26457e22627SCy Schubert ipv4_buf, sizeof ipv4_buf)); 26557e22627SCy Schubert if (a->netmask) 26657e22627SCy Schubert printf("\t\tNetmask: %s\n", 26757e22627SCy Schubert inet_ntop(AF_INET, 26857e22627SCy Schubert &((struct sockaddr_in *)(a->netmask))->sin_addr, 26957e22627SCy Schubert ipv4_buf, sizeof ipv4_buf)); 27057e22627SCy Schubert if (a->broadaddr) 27157e22627SCy Schubert printf("\t\tBroadcast Address: %s\n", 27257e22627SCy Schubert inet_ntop(AF_INET, 27357e22627SCy Schubert &((struct sockaddr_in *)(a->broadaddr))->sin_addr, 27457e22627SCy Schubert ipv4_buf, sizeof ipv4_buf)); 27557e22627SCy Schubert if (a->dstaddr) 27657e22627SCy Schubert printf("\t\tDestination Address: %s\n", 27757e22627SCy Schubert inet_ntop(AF_INET, 27857e22627SCy Schubert &((struct sockaddr_in *)(a->dstaddr))->sin_addr, 27957e22627SCy Schubert ipv4_buf, sizeof ipv4_buf)); 28057e22627SCy Schubert break; 28157e22627SCy Schubert #ifdef INET6 28257e22627SCy Schubert case AF_INET6: 28357e22627SCy Schubert printf("\tAddress Family: AF_INET6\n"); 28457e22627SCy Schubert if (a->addr) 28557e22627SCy Schubert printf("\t\tAddress: %s\n", 28657e22627SCy Schubert inet_ntop(AF_INET6, 28757e22627SCy Schubert ((struct sockaddr_in6 *)(a->addr))->sin6_addr.s6_addr, 28857e22627SCy Schubert ipv6_buf, sizeof ipv6_buf)); 28957e22627SCy Schubert if (a->netmask) 29057e22627SCy Schubert printf("\t\tNetmask: %s\n", 29157e22627SCy Schubert inet_ntop(AF_INET6, 29257e22627SCy Schubert ((struct sockaddr_in6 *)(a->netmask))->sin6_addr.s6_addr, 29357e22627SCy Schubert ipv6_buf, sizeof ipv6_buf)); 29457e22627SCy Schubert if (a->broadaddr) 29557e22627SCy Schubert printf("\t\tBroadcast Address: %s\n", 29657e22627SCy Schubert inet_ntop(AF_INET6, 29757e22627SCy Schubert ((struct sockaddr_in6 *)(a->broadaddr))->sin6_addr.s6_addr, 29857e22627SCy Schubert ipv6_buf, sizeof ipv6_buf)); 29957e22627SCy Schubert if (a->dstaddr) 30057e22627SCy Schubert printf("\t\tDestination Address: %s\n", 30157e22627SCy Schubert inet_ntop(AF_INET6, 30257e22627SCy Schubert ((struct sockaddr_in6 *)(a->dstaddr))->sin6_addr.s6_addr, 30357e22627SCy Schubert ipv6_buf, sizeof ipv6_buf)); 30457e22627SCy Schubert break; 30557e22627SCy Schubert #endif 30657e22627SCy Schubert default: 30757e22627SCy Schubert printf("\tAddress Family: Unknown (%d)\n", a->addr->sa_family); 30857e22627SCy Schubert break; 30957e22627SCy Schubert } 31057e22627SCy Schubert else 31157e22627SCy Schubert { 31257e22627SCy Schubert fprintf(stderr, "\tWarning: a->addr is NULL, skipping this address.\n"); 31357e22627SCy Schubert status = 0; 31457e22627SCy Schubert } 31557e22627SCy Schubert } 31657e22627SCy Schubert printf("\n"); 31757e22627SCy Schubert return status; 31857e22627SCy Schubert } 31957e22627SCy Schubert 32057e22627SCy Schubert /* From tcptraceroute */ 32157e22627SCy Schubert #define IPTOSBUFFERS 12 32257e22627SCy Schubert static char *iptos(bpf_u_int32 in) 32357e22627SCy Schubert { 324*6f9cba8fSJoseph Mingrone static char output[IPTOSBUFFERS][sizeof("255.255.255.255")]; 32557e22627SCy Schubert static short which; 32657e22627SCy Schubert u_char *p; 32757e22627SCy Schubert 32857e22627SCy Schubert p = (u_char *)∈ 32957e22627SCy Schubert which = (which + 1 == IPTOSBUFFERS ? 0 : which + 1); 330*6f9cba8fSJoseph Mingrone snprintf(output[which], sizeof(output[which]), "%d.%d.%d.%d", p[0], p[1], p[2], p[3]); 33157e22627SCy Schubert return output[which]; 33257e22627SCy Schubert } 333