/* resolv.c: DNS Resolver
*
* Copyright (C) 1998 Kenneth Albanowski <kjahds@kjahds.com>,
* The Silver Hammer Group, Ltd.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* 5-Oct-2000 W. Greathouse wgreathouse@smva.com
* Fix memory leak and memory corruption.
* -- Every name resolution resulted in
* a new parse of resolv.conf and new
* copy of nameservers allocated by
* strdup.
* -- Every name resolution resulted in
* a new read of resolv.conf without
* resetting index from prior read...
* resulting in exceeding array bounds.
*
* Limit nameservers read from resolv.conf
*
* Add "search" domains from resolv.conf
*
* Some systems will return a security
* signature along with query answer for
* dynamic DNS entries.
* -- skip/ignore this answer
*
* Include arpa/nameser.h for defines.
*
* General cleanup
*
* 20-Jun-2001 Michal Moskal <malekith@pld.org.pl>
* partial IPv6 support (i.e. gethostbyname2() and resolve_address2()
* functions added), IPv6 nameservers are also supported.
*
* 6-Oct-2001 Jari Korva <jari.korva@iki.fi>
* more IPv6 support (IPv6 support for gethostbyaddr();
* address family parameter and improved IPv6 support for get_hosts_byname
* and read_etc_hosts; getnameinfo() port from glibc; defined
* defined ip6addr_any and in6addr_loopback)
*/
#define __FORCE_GLIBC
#include <features.h>
#include <string.h>
#include <stdio.h>
#include <signal.h>
#include <errno.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <unistd.h>
#include <resolv.h>
#include <netdb.h>
#include <ctype.h>
#include <arpa/nameser.h>
#include <sys/utsname.h>
#include <sys/un.h>
#define MAX_RECURSE 5
#define REPLY_TIMEOUT 10
#define MAX_RETRIES 15
#define MAX_SERVERS 3
#define MAX_SEARCH 4
#undef DEBUG
/*#define DEBUG*/
#ifdef DEBUG
#define DPRINTF(X,args...) fprintf(stderr, X, ##args)
#else
#define DPRINTF(X,args...)
#endif /* DEBUG */
struct resolv_header {
int id;
int qr,opcode,aa,tc,rd,ra,rcode;
int qdcount;
int ancount;
int nscount;
int arcount;
};
struct resolv_question {
char * dotted;
int qtype;
int qclass;
};
struct resolv_answer {
char * dotted;
int atype;
int aclass;
int ttl;
int rdlength;
unsigned char * rdata;
int rdoffset;
};
extern int nameservers;
extern char * nameserver[MAX_SERVERS];
extern int searchdomains;
extern char * searchdomain[MAX_SEARCH];
extern struct hostent * get_hosts_byname(const char * name, int type);
extern struct hostent * get_hosts_byaddr(const char * addr, int len, int type);
extern struct hostent * read_etc_hosts(const char * name, int type, int ip);
extern int resolve_address(const char * address, int nscount,
char ** nsip, struct in_addr * in);
extern int resolve_mailbox(const char * address, int nscount,
char ** nsip, struct in_addr * in);
extern int dns_lookup(const char * name, int type, int nscount,
char ** nsip, unsigned char ** outpacket, struct resolv_answer * a);
int encode_dotted(const char * dotted, unsigned char * dest, int maxlen);
int decode_dotted(const unsigned char * message, int offset,
char * dest, int maxlen);
int length_dotted(const unsigned char * message, int offset);
int encode_header(struct resolv_header * h, unsigned char * dest, int maxlen);
int decode_header(unsigned char * data, struct resolv_header * h);
int encode_question(struct resolv_question * q,
unsigned char * dest, int maxlen);
int decode_question(unsigned char * message, int offset,
struct resolv_question * q);
int encode_answer(struct resolv_answer * a,
unsigned char * dest, int maxlen);
int decode_answer(unsigned char * message, int offset,
struct resolv_answer * a);
int length_question(unsigned char * message, int offset);
extern int open_nameservers(void);
#ifdef L_encodeh
int encode_header(struct resolv_header *h, unsigned char *dest, int maxlen)
{
if (maxlen < HFIXEDSZ)
return -1;
dest[0] = (h->id & 0xff00) >> 8;
dest[1] = (h->id & 0x00ff) >> 0;
dest[2] = (h->qr ? 0x80 : 0) |
((h->opcode & 0x0f) << 3) |
(h->aa ? 0x04 : 0) |
(h->tc ? 0x02 : 0) |
(h->rd ? 0x01 : 0);
dest[3] = (h->ra ? 0x80 : 0) | (h->rcode & 0x0f);
dest[4] =
|