jablonka.czprosek.czf

discover

Subversion Repositories:
[/] [trunk/] [discover.c] - Rev 5

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));

struct cache_entry {
        unsigned long s_addr;
        unsigned short s_port;
};

#define MAXENTRIES 1024
struct cache_entry cache[MAXENTRIES];
size_t cachep;

int add_cache(unsigned long s_addr, unsigned short s_port)
{
        if (cachep == 1024)
                return 0;

        cache[cachep].s_addr = s_addr;
        cache[cachep].s_port = s_port;
        cachep++;

        return 1;
}

int lookup_cache(unsigned long s_addr, unsigned short s_port)
{
        int i;

        for (i = 0; i <= cachep; i++)
                if (cache[i].s_addr == s_addr && cache[i].s_port == s_port)
                        return 1;
        return 0;
}

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++;

                if (!lookup_cache(si_srv.sin_addr.s_addr, si_srv.sin_port)) {
                        if (!add_cache(si_srv.sin_addr.s_addr, si_srv.sin_port)) {
                                fprintf(stderr, "too many unique responses\n");
                                exit(1);
                        }
                } else {
                        continue;
                }

                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;

                                case 16:
                                        printf("System ID:     0x%02hhX%02hhX\n", p[0], p[1]);
                                        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;

}


Powered by WebSVN 2.2.1