3 #include "adns-internal.h"
5 static void vdebug(adns_state ads
, const char *fmt
, va_list al
) {
6 if (!(ads
->iflags
& adns_if_debug
)) return;
7 fputs("adns debug: ",stderr
);
8 vfprintf(stderr
,fmt
,al
);
12 void adns__debug(adns_state ads
, const char *fmt
, ...) {
20 static void vdiag(adns_state ads
, const char *fmt
, va_list al
) {
21 if (ads
->iflags
& adns_if_noerrprint
) return;
22 fputs("adns: ",stderr
);
23 vfprintf(stderr
,fmt
,al
);
27 void adns__diag(adns_state ads
, const char *fmt
, ...) {
35 static void addserver(adns_state ads
, struct in_addr addr
) {
39 for (i
=0; i
<ads
->nservers
; i
++) {
40 if (ads
->servers
[i
].addr
.s_addr
== addr
.s_addr
) {
41 debug(ads
,"duplicate nameserver %s ignored",inet_ntoa(addr
));
46 if (ads
->nservers
>=MAXSERVERS
) {
47 diag(ads
,"too many nameservers, ignoring %s",inet_ntoa(addr
));
51 ss
= ads
->servers
+ads
->nservers
;
53 ss
->state
= server_disc
;
54 ss
->connw
.head
= ss
->connw
.tail
= 0;
58 static void configparseerr(adns_state ads
, const char *fn
, int lno
,
59 const char *fmt
, ...) {
62 if (ads
->iflags
& adns_if_noerrprint
) return;
63 if (lno
==-1) fprintf(stderr
,"adns: %s: ",fn
);
64 else fprintf(stderr
,"adns: %s:%d: ",fn
,lno
);
66 vfprintf(stderr
,fmt
,al
);
71 static void ccf_nameserver(adns_state ads
, const char *fn
, int lno
, const char *buf
) {
74 if (!inet_aton(buf
,&ia
)) {
75 configparseerr(ads
,fn
,lno
,"invalid nameserver address `%s'",buf
);
78 debug(ads
,"using nameserver %s",inet_ntoa(ia
));
82 static void ccf_search(adns_state ads
, const char *fn
, int lno
, const char *buf
) {
84 diag(ads
,"warning - `search' ignored FIXME");
87 static void ccf_sortlist(adns_state ads
, const char *fn
, int lno
, const char *buf
) {
88 diag(ads
,"warning - `sortlist' ignored FIXME");
91 static void ccf_options(adns_state ads
, const char *fn
, int lno
, const char *buf
) {
93 diag(ads
,"warning - `options' ignored FIXME");
96 static void ccf_clearnss(adns_state ads
, const char *fn
, int lno
, const char *buf
) {
100 static const struct configcommandinfo
{
102 void (*fn
)(adns_state ads
, const char *fn
, int lno
, const char *buf
);
103 } configcommandinfos
[]= {
104 { "nameserver", ccf_nameserver
},
105 { "domain", ccf_search
},
106 { "search", ccf_search
},
107 { "sortlist", ccf_sortlist
},
108 { "options", ccf_options
},
109 { "clearnameservers", ccf_clearnss
},
113 static int ctype_whitespace(int c
) { return c
==' ' || c
=='\n' || c
=='\t'; }
114 static int ctype_digit(int c
) { return c
>='0' && c
<='9'; }
116 static void readconfig(adns_state ads
, const char *filename
) {
117 char linebuf
[2000], *p
, *q
;
120 const struct configcommandinfo
*ccip
;
122 file
= fopen(filename
,"r");
124 if (errno
== ENOENT
) {
125 debug(ads
,"configuration file `%s' does not exist",filename
);
128 diag(ads
,"cannot open configuration file `%s': %s",filename
,strerror(errno
));
132 for (lno
=1; fgets(linebuf
,sizeof(linebuf
),file
); lno
++) {
135 if (linebuf
[l
-1] != '\n' && !feof(file
)) {
136 diag(ads
,"%s:%d: line too long",filename
,lno
);
137 while ((c
= getc(file
)) != EOF
&& c
!= '\n') { }
141 while (l
>0 && ctype_whitespace(linebuf
[l
-1])) l
--;
144 while (ctype_whitespace(*p
)) p
++;
145 if (*p
== '#' || *p
== '\n') continue;
147 while (*q
&& !ctype_whitespace(*q
)) q
++;
148 for (ccip
=configcommandinfos
;
149 ccip
->name
&& strncmp(ccip
->name
,p
,q
-p
);
152 diag(ads
,"%s:%d: unknown configuration directive `%.*s'",filename
,lno
,q
-p
,p
);
155 while (ctype_whitespace(*q
)) q
++;
156 ccip
->fn(ads
,filename
,lno
,q
);
159 diag(ads
,"%s:%d: read error: %s",filename
,lno
,strerror(errno
));
164 static const char *instrum_getenv(adns_state ads
, const char *envvar
) {
167 value
= getenv(envvar
);
168 if (!value
) debug(ads
,"environment variable %s not set",envvar
);
169 else debug(ads
,"environment variable %s set to `%s'",envvar
,value
);
173 static void readconfigenv(adns_state ads
, const char *envvar
) {
174 const char *filename
;
176 if (ads
->iflags
& adns_if_noenv
) {
177 debug(ads
,"not checking environment variable `%s'",envvar
);
180 filename
= instrum_getenv(ads
,envvar
);
181 if (filename
) readconfig(ads
,filename
);
184 int adns_init(adns_state
*ads_r
, adns_initflags flags
) {
186 const char *res_options
, *adns_res_options
;
187 struct protoent
*proto
;
190 ads
= malloc(sizeof(*ads
)); if (!ads
) return errno
;
191 ads
->tosend
.head
= ads
->tosend
.tail
= 0;
192 ads
->timew
.head
= ads
->timew
.tail
= 0;
193 ads
->childw
.head
= ads
->childw
.tail
= 0;
194 ads
->output
.head
= ads
->output
.tail
= 0;
199 ads
->tcpbufavail
= ads
->tcpbufused
= ads
->tcpbufdone
= 0;
205 res_options
= instrum_getenv(ads
,"RES_OPTIONS");
206 adns_res_options
= instrum_getenv(ads
,"ADNS_RES_OPTIONS");
207 ccf_options(ads
,"RES_OPTIONS",-1,res_options
);
208 ccf_options(ads
,"ADNS_RES_OPTIONS",-1,adns_res_options
);
210 readconfig(ads
,"/etc/resolv.conf");
211 readconfigenv(ads
,"RES_CONF");
212 readconfigenv(ads
,"ADNS_RES_CONF");
214 ccf_options(ads
,"RES_OPTIONS",-1,res_options
);
215 ccf_options(ads
,"ADNS_RES_OPTIONS",-1,adns_res_options
);
217 ccf_search(ads
,"LOCALDOMAIN",-1,instrum_getenv(ads
,"LOCALDOMAIN"));
218 ccf_search(ads
,"ADNS_LOCALDOMAIN",-1,instrum_getenv(ads
,"ADNS_LOCALDOMAIN"));
220 if (!ads
->nservers
) {
222 if (ads
->iflags
& adns_if_debug
)
223 fprintf(stderr
,"adns: no nameservers, using localhost\n");
224 ia
.s_addr
= INADDR_LOOPBACK
;
228 proto
= getprotobyname("udp"); if (!proto
) { r
= ENOPROTOOPT
; goto x_free
; }
229 ads
->udpsocket
= socket(AF_INET
,SOCK_DGRAM
,proto
->p_proto
);
230 if (!ads
->udpsocket
) { r
= errno
; goto x_closeudp
; }
236 close(ads
->udpsocket
);
242 int adns_finish(adns_state ads
) {