/* * Copyright (c) 2006 Bjorn Andersson , Erik Ekman * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include "dns.h" static int host2dns(const char *, char *, int); struct sockaddr_in peer; int open_dns() { int fd; int flag; struct sockaddr_in addr; bzero(&addr, sizeof(addr)); addr.sin_family = AF_INET; addr.sin_port = htons(0); addr.sin_addr.s_addr = htonl(INADDR_ANY); fd = socket(AF_INET, SOCK_DGRAM, 0); if(fd < 0) { warn("Could not get UDP socket"); return 0; } flag = 1; #ifdef SO_REUSEPORT setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &flag, sizeof(flag)); #endif setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &flag, sizeof(flag)); if(bind(fd, (struct sockaddr*)&addr, sizeof(addr)) < 0) { warn("Could not bind UDP socket locally"); return 0; } printf("Opened UDP socket\n"); return fd; } void close_dns(int fd) { close(fd); } void dns_set_peer(const char *host) { struct hostent *h; h = gethostbyname(host); bzero(&peer, sizeof(peer)); peer.sin_family = AF_INET; peer.sin_port = htons(53); peer.sin_addr = *((struct in_addr *) h->h_addr); } void dns_ping() { } void dns_query(int fd, char *host, int type) { char *p; int len; int peerlen; char buf[1024]; HEADER *header; len = 0; memset(buf, 0, sizeof(buf)); header = (HEADER*)buf; header->id = 0; header->qr = 0; header->opcode = 0; header->aa = 0; header->tc = 0; header->rd = 1; header->ra = 0; header->qdcount = htons(1); p = buf + sizeof(HEADER); p += host2dns(host, p, strlen(host)); PUTSHORT(type, p); PUTSHORT(C_IN, p); peerlen = sizeof(peer); len = p - buf; sendto(fd, buf, len+1, 0, (struct sockaddr*)&peer, peerlen); } static int host2dns(const char *host, char *buffer, int size) { char *h; char *p; char *word; h = strdup(host); memset(buffer, 0, size); p = buffer; word = strtok(h, "."); while(word) { *p++ = (char)strlen(word); memcpy(p, word, strlen(word)); p += strlen(word); word = strtok(NULL, "."); } *p++ = 0; free(h); return p - buffer; }