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 * 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 * 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 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 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 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