157e22627SCy Schubert #include <config.h>
257e22627SCy Schubert
357e22627SCy Schubert #include <stdlib.h>
457e22627SCy Schubert #include <string.h>
557e22627SCy Schubert #include <sys/types.h>
657e22627SCy Schubert #ifdef _WIN32
757e22627SCy Schubert #include <winsock2.h>
857e22627SCy Schubert #include <ws2tcpip.h>
957e22627SCy Schubert #include <windows.h>
1057e22627SCy Schubert #else
1157e22627SCy Schubert #include <sys/socket.h>
1257e22627SCy Schubert #include <netinet/in.h>
1357e22627SCy Schubert #include <arpa/inet.h>
1457e22627SCy Schubert #include <netdb.h>
1557e22627SCy Schubert #include <unistd.h>
1657e22627SCy Schubert #endif
1757e22627SCy Schubert
1857e22627SCy Schubert #include <pcap.h>
1957e22627SCy Schubert
206f9cba8fSJoseph Mingrone #include "varattrs.h"
2157e22627SCy Schubert #include "pcap/funcattrs.h"
2257e22627SCy Schubert
2357e22627SCy Schubert static int ifprint(pcap_if_t *d);
2457e22627SCy Schubert static char *iptos(bpf_u_int32 in);
2557e22627SCy Schubert
2657e22627SCy Schubert #ifdef _WIN32
2757e22627SCy Schubert #include "portability.h"
2857e22627SCy Schubert
2957e22627SCy Schubert /*
3057e22627SCy Schubert * Generate a string for a Win32-specific error (i.e. an error generated when
3157e22627SCy Schubert * calling a Win32 API).
3257e22627SCy Schubert * For errors occurred during standard C calls, we still use pcap_strerror()
3357e22627SCy Schubert */
3457e22627SCy Schubert #define ERRBUF_SIZE 1024
3557e22627SCy Schubert static const char *
win32_strerror(DWORD error)3657e22627SCy Schubert win32_strerror(DWORD error)
3757e22627SCy Schubert {
3857e22627SCy Schubert static char errbuf[ERRBUF_SIZE+1];
3957e22627SCy Schubert size_t errlen;
4057e22627SCy Schubert
4157e22627SCy Schubert FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, error, 0, errbuf,
4257e22627SCy Schubert ERRBUF_SIZE, NULL);
4357e22627SCy Schubert
4457e22627SCy Schubert /*
4557e22627SCy Schubert * "FormatMessage()" "helpfully" sticks CR/LF at the end of the
4657e22627SCy Schubert * message. Get rid of it.
4757e22627SCy Schubert */
4857e22627SCy Schubert errlen = strlen(errbuf);
4957e22627SCy Schubert if (errlen >= 2) {
5057e22627SCy Schubert errbuf[errlen - 1] = '\0';
5157e22627SCy Schubert errbuf[errlen - 2] = '\0';
5257e22627SCy Schubert errlen -= 2;
5357e22627SCy Schubert }
5457e22627SCy Schubert return errbuf;
5557e22627SCy Schubert }
5657e22627SCy Schubert
5757e22627SCy Schubert static char *
getpass(const char * prompt)5857e22627SCy Schubert getpass(const char *prompt)
5957e22627SCy Schubert {
6057e22627SCy Schubert HANDLE console_handle = GetStdHandle(STD_INPUT_HANDLE);
6157e22627SCy Schubert DWORD console_mode, save_console_mode;
6257e22627SCy Schubert static char password[128+1];
6357e22627SCy Schubert char *p;
6457e22627SCy Schubert
6557e22627SCy Schubert fprintf(stderr, "%s", prompt);
6657e22627SCy Schubert
6757e22627SCy Schubert /*
6857e22627SCy Schubert * Turn off echoing.
6957e22627SCy Schubert */
7057e22627SCy Schubert if (!GetConsoleMode(console_handle, &console_mode)) {
7157e22627SCy Schubert fprintf(stderr, "Can't get console mode: %s\n",
7257e22627SCy Schubert win32_strerror(GetLastError()));
7357e22627SCy Schubert exit(1);
7457e22627SCy Schubert }
7557e22627SCy Schubert save_console_mode = console_mode;
7657e22627SCy Schubert console_mode &= ~ENABLE_ECHO_INPUT;
7757e22627SCy Schubert if (!SetConsoleMode(console_handle, console_mode)) {
7857e22627SCy Schubert fprintf(stderr, "Can't set console mode: %s\n",
7957e22627SCy Schubert win32_strerror(GetLastError()));
8057e22627SCy Schubert exit(1);
8157e22627SCy Schubert }
8257e22627SCy Schubert if (fgets(password, sizeof password, stdin) == NULL) {
8357e22627SCy Schubert fprintf(stderr, "\n");
8457e22627SCy Schubert SetConsoleMode(console_handle, save_console_mode);
8557e22627SCy Schubert exit(1);
8657e22627SCy Schubert }
8757e22627SCy Schubert fprintf(stderr, "\n");
8857e22627SCy Schubert SetConsoleMode(console_handle, save_console_mode);
8957e22627SCy Schubert p = strchr(password, '\n');
9057e22627SCy Schubert if (p != NULL)
9157e22627SCy Schubert *p = '\0';
9257e22627SCy Schubert return password;
9357e22627SCy Schubert }
9457e22627SCy Schubert #endif
9557e22627SCy Schubert
966f9cba8fSJoseph Mingrone #ifdef ENABLE_REMOTE
main(int argc,char ** argv)9757e22627SCy Schubert int main(int argc, char **argv)
986f9cba8fSJoseph Mingrone #else
996f9cba8fSJoseph Mingrone int main(int argc _U_, char **argv _U_)
1006f9cba8fSJoseph Mingrone #endif
10157e22627SCy Schubert {
10257e22627SCy Schubert pcap_if_t *alldevs;
10357e22627SCy Schubert pcap_if_t *d;
10457e22627SCy Schubert bpf_u_int32 net, mask;
10557e22627SCy Schubert int exit_status = 0;
10657e22627SCy Schubert char errbuf[PCAP_ERRBUF_SIZE+1];
10757e22627SCy Schubert #ifdef ENABLE_REMOTE
10857e22627SCy Schubert struct pcap_rmtauth auth;
10957e22627SCy Schubert char username[128+1];
11057e22627SCy Schubert char *p;
11157e22627SCy Schubert char *password;
11257e22627SCy Schubert #endif
11357e22627SCy Schubert
11457e22627SCy Schubert #ifdef ENABLE_REMOTE
11557e22627SCy Schubert if (argc >= 2)
11657e22627SCy Schubert {
11757e22627SCy Schubert if (pcap_findalldevs_ex(argv[1], NULL, &alldevs, errbuf) == -1)
11857e22627SCy Schubert {
11957e22627SCy Schubert /*
12057e22627SCy Schubert * OK, try it with a user name and password.
12157e22627SCy Schubert */
12257e22627SCy Schubert fprintf(stderr, "User name: ");
12357e22627SCy Schubert if (fgets(username, sizeof username, stdin) == NULL)
12457e22627SCy Schubert exit(1);
12557e22627SCy Schubert p = strchr(username, '\n');
12657e22627SCy Schubert if (p != NULL)
12757e22627SCy Schubert *p = '\0';
12857e22627SCy Schubert password = getpass("Password: ");
12957e22627SCy Schubert auth.type = RPCAP_RMTAUTH_PWD;
13057e22627SCy Schubert auth.username = username;
13157e22627SCy Schubert auth.password = password;
13257e22627SCy Schubert if (pcap_findalldevs_ex(argv[1], &auth, &alldevs, errbuf) == -1)
13357e22627SCy Schubert {
13457e22627SCy Schubert fprintf(stderr,"Error in pcap_findalldevs: %s\n",errbuf);
13557e22627SCy Schubert exit(1);
13657e22627SCy Schubert }
13757e22627SCy Schubert }
13857e22627SCy Schubert }
13957e22627SCy Schubert else
14057e22627SCy Schubert #endif
14157e22627SCy Schubert {
14257e22627SCy Schubert if (pcap_findalldevs(&alldevs, errbuf) == -1)
14357e22627SCy Schubert {
14457e22627SCy Schubert fprintf(stderr,"Error in pcap_findalldevs: %s\n",errbuf);
14557e22627SCy Schubert exit(1);
14657e22627SCy Schubert }
14757e22627SCy Schubert }
14857e22627SCy Schubert for(d=alldevs;d;d=d->next)
14957e22627SCy Schubert {
15057e22627SCy Schubert if (!ifprint(d))
15157e22627SCy Schubert exit_status = 2;
15257e22627SCy Schubert }
15357e22627SCy Schubert
15457e22627SCy Schubert if (alldevs != NULL)
15557e22627SCy Schubert {
15657e22627SCy Schubert if (pcap_lookupnet(alldevs->name, &net, &mask, errbuf) < 0)
15757e22627SCy Schubert {
1586f9cba8fSJoseph Mingrone /*
1596f9cba8fSJoseph Mingrone * XXX - this doesn't distinguish between "a real error
1606f9cba8fSJoseph Mingrone * occurred" and "this interface doesn't *have* an IPv4
1616f9cba8fSJoseph Mingrone * address". The latter shouldn't be treated as an error.
1626f9cba8fSJoseph Mingrone *
1636f9cba8fSJoseph Mingrone * We look for the interface name, followed by a colon and
1646f9cba8fSJoseph Mingrone * a space, and, if we find it,w e see if what follows it
1656f9cba8fSJoseph Mingrone * is "no IPv4 address assigned".
1666f9cba8fSJoseph Mingrone */
1676f9cba8fSJoseph Mingrone size_t devnamelen = strlen(alldevs->name);
1686f9cba8fSJoseph Mingrone if (strncmp(errbuf, alldevs->name, devnamelen) == 0 &&
1696f9cba8fSJoseph Mingrone strncmp(errbuf + devnamelen, ": ", 2) == 0 &&
1706f9cba8fSJoseph Mingrone strcmp(errbuf + devnamelen + 2, "no IPv4 address assigned") == 0)
1716f9cba8fSJoseph Mingrone printf("Preferred device is not on an IPv4 network\n");
1726f9cba8fSJoseph Mingrone else {
17357e22627SCy Schubert fprintf(stderr,"Error in pcap_lookupnet: %s\n",errbuf);
17457e22627SCy Schubert exit_status = 2;
17557e22627SCy Schubert }
1766f9cba8fSJoseph Mingrone }
17757e22627SCy Schubert else
17857e22627SCy Schubert {
17957e22627SCy Schubert printf("Preferred device is on network: %s/%s\n",iptos(net), iptos(mask));
18057e22627SCy Schubert }
18157e22627SCy Schubert }
18257e22627SCy Schubert
18357e22627SCy Schubert pcap_freealldevs(alldevs);
18457e22627SCy Schubert exit(exit_status);
18557e22627SCy Schubert }
18657e22627SCy Schubert
ifprint(pcap_if_t * d)18757e22627SCy Schubert static int ifprint(pcap_if_t *d)
18857e22627SCy Schubert {
18957e22627SCy Schubert pcap_addr_t *a;
19057e22627SCy Schubert char ipv4_buf[INET_ADDRSTRLEN];
191*afdbf109SJoseph Mingrone #ifdef INET6
19257e22627SCy Schubert char ipv6_buf[INET6_ADDRSTRLEN];
193*afdbf109SJoseph Mingrone #endif
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:
259*afdbf109SJoseph Mingrone printf("\tAddress Family: AF_INET (%d)\n", a->addr->sa_family);
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:
283*afdbf109SJoseph Mingrone printf("\tAddress Family: AF_INET6 (%d)\n", a->addr->sa_family);
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
iptos(bpf_u_int32 in)32257e22627SCy Schubert static char *iptos(bpf_u_int32 in)
32357e22627SCy Schubert {
3246f9cba8fSJoseph 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);
3306f9cba8fSJoseph 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