#include #include #include #include #include #include #include #include "codnsresolv.h" #define CODNS_PORT 4119 /* CODNS PORT */ /* query info - fixed part */ typedef struct LocalQueryInfo { int lqi_size; /* length of the name string */ int lqi_id; /* query id */ int lqi_cache; /* not being used now */ } LocalQueryInfo; /* query info + name query structure expected from a client */ #define MAX_QUERY_NAME 256 #define SIG_SPLIT_TRANSACTION 0 /* signature for split-transaction */ typedef struct LocalQuery { int lq_zero; /* always set to SIG_SPLIT_TRANSACTION(=0) */ LocalQueryInfo lq_info; /* query info */ char lq_name[MAX_QUERY_NAME]; /* name */ } LocalQuery; /* query result from CoDNS we set MAX_ANSWERS for easy implementation. if lq.address[i].s_addr == 0, that means it returned i-1 valid anwers. */ #define MAX_ANSWERS 8 typedef struct LocalQueryResult { int lq_id; /* query id */ int lq_ttl; /* TTL of the record */ struct in_addr lq_address[MAX_ANSWERS]; /* IP addresses for the query */ } LocalQueryResult; /*----------------------------------------------------------------*/ #define TO_HOST_L(x) x = ntohl(x) #define TO_NETWORK_L(x) x = htonl(x) static void HtoN_LocalQueryInfo(LocalQueryInfo *p) { TO_NETWORK_L(p->lqi_size); TO_NETWORK_L(p->lqi_id); TO_NETWORK_L(p->lqi_cache); } /*----------------------------------------------------------------*/ static void NtoH_LocalQueryResult(LocalQueryResult* p) { TO_HOST_L(p->lq_id); TO_HOST_L(p->lq_ttl); } /*-----------------------------------------------------------------*/ static int MakeLoopbackConnection(int portNum) { struct sockaddr_in saddr; int fd; if ((fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) return(-1); saddr.sin_family = AF_INET; saddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); saddr.sin_port = htons(portNum); if (connect(fd, (struct sockaddr *) &saddr, sizeof(struct sockaddr_in)) < 0) { close(fd); return(-1); } return(fd); } /*----------------------------------------------------------*/ int CoDNSGetHostByNameSync(const char *name, struct in_addr *res) { static int fd = -1; LocalQuery query; int size; LocalQueryResult result; /* create a persistent connection to CoDNS */ if (fd == -1 && (fd = MakeLoopbackConnection(CODNS_PORT)) < 0) { fprintf(stderr, "connection failed\n"); /* try to resolve names using gethostbyname() */ { struct hostent* hp; if ((hp = gethostbyname(name)) == NULL) return -1; if (res) *res = *(struct in_addr *)hp->h_addr; } return 0; } memset(&query, 0, sizeof(query)); size = strlen(name) + 1; query.lq_info.lqi_size = size; /* length of name */ query.lq_info.lqi_cache = 1; strcpy(query.lq_name, name); size += sizeof(query.lq_info) + sizeof(query.lq_zero); /* send a query */ HtoN_LocalQueryInfo(&query.lq_info); if (write(fd, &query, size) != size) { fprintf(stderr, "write failed\n"); close(fd); fd = -1; return(-1); } /* get answer */ do { size = read(fd, &result, sizeof(result)); } while (size == -1 && errno == EINTR); NtoH_LocalQueryResult(&result); if (size != sizeof(result)) { fprintf(stderr, "read failed %d, %d\n", size, sizeof(result)); return(-1); } *res = result.lq_address[0]; return 0; }