discover |
Subversion Repositories: |
Compare with Previous - Blame - Download
#include <arpa/inet.h>
#include <netinet/in.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <netdb.h>
#include <sys/select.h>
#include <sys/time.h>
#include <ifaddrs.h>
#include <net/if.h>
#define BUFLEN 1024
#define UBNT_PORT 10001
#define SNDLEN 4
struct udisc_msg_hdr {
uint8_t vh;
uint8_t vl;
uint16_t length;
} __attribute__((packed));
struct udisc_rec_hdr {
uint8_t type;
uint16_t length;
} __attribute__((packed));
int main(int argc, char *argv[])
{
struct sockaddr_in si_srv;
struct sockaddr_in si_clnt;
int sock;
socklen_t soutlen = sizeof(si_srv);
socklen_t sinlen = sizeof(si_srv);
char rcvbuf[BUFLEN];
char sendbuf[BUFLEN];
ssize_t rlen;
struct udisc_msg_hdr *umh;
struct udisc_rec_hdr *urh;
char *p;
char *dest;
struct addrinfo hints;
struct addrinfo *ai_res;
int result;
int i, t;
fd_set socks;
struct timeval tv;
int multicast;
int responses = 0;
struct ifaddrs *ifa;
memset(&hints, 0, sizeof(hints));
hints.ai_protocol = IPPROTO_UDP;
hints.ai_socktype = SOCK_DGRAM;
hints.ai_flags = AI_CANONNAME;
hints.ai_family = PF_UNSPEC;
if (argc < 2) {
dest = "233.89.188.1";
multicast = 1;
} else {
dest = argv[1];
multicast = 0;
}
if ((result = getaddrinfo(dest, NULL, &hints, &ai_res))) {
printf("getaddrinfo-failed: %s\n", gai_strerror(result));
exit(1);
}
if ((sock=socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1) {
perror("socket");
exit(1);
}
memset((char *) &si_clnt, 0, sizeof(si_clnt));
si_clnt.sin_family = AF_INET;
si_clnt.sin_port = htons(UBNT_PORT);
si_clnt.sin_addr = ((struct sockaddr_in *)ai_res->ai_addr)->sin_addr;
sendbuf[0] = 1;
sendbuf[1] = 0;
sendbuf[2] = 0;
sendbuf[3] = 0;
if (multicast) {
char loop = 0;
setsockopt(sock, IPPROTO_IP, IP_MULTICAST_LOOP, &loop, sizeof(char));
if (getifaddrs(&ifa)) {
perror("getifaddrs");
exit(1);
}
for (; ifa; ifa = ifa->ifa_next) {
if (!(ifa->ifa_flags & IFF_UP))
continue;
if (!ifa->ifa_addr)
continue;
if (ifa->ifa_addr->sa_family != AF_INET)
continue;
if (!strcmp(ifa->ifa_name, "lo"))
continue;
if (!strncmp(ifa->ifa_name, "dummy", 5))
continue;
printf("Probing %s:%d", inet_ntoa(si_clnt.sin_addr), UBNT_PORT);
printf(" via %s (%s).\n", ifa->ifa_name, inet_ntoa(((struct sockaddr_in *)ifa->ifa_addr)->sin_addr));
if (setsockopt(sock, IPPROTO_IP, IP_MULTICAST_IF, &(((struct sockaddr_in *)ifa->ifa_addr)->sin_addr), sizeof(struct in_addr))) {
perror("setsockopt");
exit(1);
}
if (sendto(sock, sendbuf, SNDLEN, 0, (struct sockaddr *)&si_clnt, soutlen) == -1) {
perror("socket");
exit(1);
}
}
} else {
printf("Probing %s:%d.\n", inet_ntoa(si_clnt.sin_addr), UBNT_PORT);
if (sendto(sock, sendbuf, SNDLEN, 0, (struct sockaddr *)&si_clnt, soutlen) == -1) {
perror("socket");
exit(1);
}
}
FD_ZERO(&socks);
FD_SET(sock, &socks);
tv.tv_sec = 0;
tv.tv_usec = 200000;
while (select(sock + 1, &socks, NULL, NULL, &tv)) {
if ((rlen = recvfrom(sock, rcvbuf, BUFLEN, 0, (struct sockaddr *)&si_srv, &sinlen)) == -1) {
perror("recvfrom");
exit(1);
}
if (ntohs(si_srv.sin_port) != UBNT_PORT)
continue;
responses++;
printf("\n");
printf("Response : %s:%d\n", inet_ntoa(si_srv.sin_addr), ntohs(si_srv.sin_port));
p = rcvbuf;
umh = (void*)p;
p += sizeof(struct udisc_msg_hdr);
rlen -= sizeof(struct udisc_msg_hdr);
printf("Discovery: v%d.%02d\n", umh->vh, umh->vl);
if (umh->vh != 1 && umh->vl != 0 && ntohs(umh->length) != rlen) {
fprintf(stderr, "protocol invalid\n");
exit(1);
}
while (rlen > 0) {
urh = (void*)p;
p += sizeof(struct udisc_rec_hdr);
rlen -= sizeof(struct udisc_rec_hdr);
switch (urh->type) {
case 2:
printf("IP Address: ");
for (i = 0; i < 4; i++) {
printf("%d", (unsigned char) p[i + 6]);
if (i < 3)
printf(".");
}
printf(" (");
for (i = 0; i < 6; i++) {
printf("%02x", (unsigned char) p[i]);
if (i < 5)
printf(":");
}
printf(")\n");
break;
case 1:
printf("MAC Address: ");
for (i = 0; i < 6; i++) {
printf("%02x", (unsigned char) p[i]);
if (i < 5)
printf(":");
}
printf("\n");
break;
case 3:
case 11:
case 12:
case 13:
switch(urh->type) {
case 3:
printf("FW Version: ");
break;
case 11:
printf("Hostname: ");
break;
case 12:
printf("Model: ");
break;
case 13:
printf("ESSID: ");
break;
}
for (i = 0; i < ntohs(urh->length); i++)
printf("%c", isprint(p[i]) ? p[i] : '.');
printf("\n");
break;
case 14:
printf("Mode: %s (%d)\n", *p == 2 ? "Station" : (*p == 3 ? "AP" : "?"), *p);
break;
case 10:
t = ntohl(*(uint32_t *)p);
printf("Uptime: %dd, %d:%02d:%02d\n", t / 60 / 60 / 24, t / 60 / 60 % 24, t / 60 % 60, t % 60);
break;
default:
printf("Entry %3d: ", urh->type);
for (i = 0; i < ntohs(urh->length); i++)
printf("%02x ", (unsigned char) p[i]);
printf(" >");
for (i = 0; i < ntohs(urh->length); i++)
printf("%c", isprint(p[i]) ? p[i] : '.');
printf("<\n");
}
p += ntohs(urh->length);
rlen -= ntohs(urh->length);
}
}
close(sock);
if (!responses) {
printf("No UBNT routers found.\n");
return 1;
}
printf("\n");
return 0;
}