3 * $Id: bres-adns.c,v 1.2 2003/12/14 14:46:38 mdw Exp $
5 * Background reverse name resolution (ADNS version)
7 * (c) 2003 Straylight/Edgeware
10 /*----- Licensing notice --------------------------------------------------*
12 * This file is part of the mLib utilities library.
14 * mLib is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU Library General Public License as
16 * published by the Free Software Foundation; either version 2 of the
17 * License, or (at your option) any later version.
19 * mLib is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU Library General Public License for more details.
24 * You should have received a copy of the GNU Library General Public
25 * License along with mLib; if not, write to the Free
26 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
30 * HOWEVER, since GNU adns is covered by the full GNU General Public
31 * License, this file (only) is also covered by the full GNU GPL, and
32 * you may NOT take advantage of the more liberal conditions of the
33 * LGPL when modifying or redistributing this file. This doesn't mean
34 * that a program which uses the interface provided by this file is
35 * covered by the GPL, since @bres.c@ provides the same interface and
36 * is LGPL. However, it does mean that if your program depends, for
37 * some reason (e.g., to meet particular performance criteria), on
38 * this adns-based implementation of mLib's background resolver then it
39 * must be licensed under the full GPL.
42 /*----- Revision history --------------------------------------------------*
44 * $Log: bres-adns.c,v $
45 * Revision 1.2 2003/12/14 14:46:38 mdw
46 * Qualify name given to @bres_byname@.
48 * Revision 1.1 2003/12/13 20:37:59 mdw
49 * Add adns support in background resolver.
54 # error "You need the ADNS library to compile this file."
57 /*----- Header files ------------------------------------------------------*/
66 #include <sys/types.h>
71 #include <sys/socket.h>
72 #include <netinet/in.h>
73 #include <arpa/inet.h>
84 /*----- Static variables --------------------------------------------------*/
86 static adns_state ads
;
87 static sel_state
*sel
;
88 static sel_hook selhook
;
90 /*----- Main code ---------------------------------------------------------*/
92 /* --- @bres_abort@ --- *
94 * Arguments: @bres_client *rc@ = pointer to client block
98 * Use: Removes a queued job.
101 void bres_abort(bres_client
*rc
)
103 if (rc
->q
== adns_r_addr
) xfree(rc
->u
.name
);
104 if (rc
->a
) free(rc
->a
);
108 /* --- @bres_byaddr@ --- *
110 * Arguments: @bres_client *rc@ = pointer to client block
111 * @struct in_addr addr@ = address to resolve
112 * @void (*func)(struct hostent *h, void *p)@ = handler function
113 * @void *p@ = argument for handler function
117 * Use: Adds an address lookup job to the queue. The job will be
118 * processed when there's a spare resolver process to deal with
122 void bres_byaddr(bres_client
*rc
, struct in_addr addr
,
123 void (*func
)(struct hostent */
*h*/
, void */
*p*/
),
127 struct sockaddr_in sin
;
130 sin
.sin_family
= AF_INET
;
133 if ((e
= adns_submit_reverse(ads
, (struct sockaddr
*)&sin
, adns_r_ptr
,
134 0, rc
, &rc
->aq
)) != 0)
147 /* --- @bres_byname@ --- *
149 * Arguments: @bres_client *rc@ = pointer to client block
150 * @const char *name@ = name to resolve
151 * @void (*func)(struct hostent *h, void *p)@ = handler function
152 * @void *p@ = argument for handler function
156 * Use: Adds a name lookup job to the queue. The job will be
157 * processed when there's a spare resolver process to deal with
161 void bres_byname(bres_client
*rc
, const char *name
,
162 void (*func
)(struct hostent */
*h*/
, void */
*p*/
),
168 if ((e
= adns_submit(ads
, name
, adns_r_addr
,
169 adns_qf_search
| adns_qf_owner
, rc
, &rc
->aq
)) != 0)
173 rc
->u
.name
= xstrdup(name
);
182 /* --- @bres_exec@ --- *
184 * Arguments: @const char *file@ = file containing server code or null
188 * Use: Makes `bres' use a standalone server rather than copies of
189 * the current process. This can reduce memory consumption for
190 * large processes, at the expense of startup time (which
191 * shouldn't be too bad anyway, because of the resolver design).
192 * If the filename is null, a default set up at install time is
193 * used. It's probably a good idea to leave it alone.
196 void bres_exec(const char *file
)
201 /* --- @report@ --- *
203 * Arguments: @bres_client *c@ = client descriptor block
204 * @adns_answer *a@ = A-record answer from resolver library
205 * @adns_rr_addr *av@ = vector of address records
206 * @int an@ = number of address records (must be positive)
207 * @char **nv@ = vector of name strings
208 * @int nn@ = number of name strings (must be positive)
212 * Use: Formats the given answer into a @struct hostent@ and reports
213 * it to the waiting client application.
216 static void report(bres_client
*rc
, adns_answer
*a
,
217 adns_rr_addr
*av
, int an
,
226 if (a
->cname
) n
[j
++] = a
->cname
;
227 else { n
[j
++] = *nv
; nv
++; nn
--; }
228 for (i
= 0; i
< nn
&& j
< N(n
) - 1; i
++)
229 if (strcmp(n
[0], nv
[i
]) != 0) n
[j
++] = nv
[i
];
231 for (i
= j
= 0; i
< an
&& j
< N(av
) - 1; i
++) {
232 if (av
[i
].addr
.sa
.sa_family
== AF_INET
)
233 aa
[j
++] = (char *)&av
[i
].addr
.inet
.sin_addr
;
238 h
.h_addrtype
= AF_INET
;
239 h
.h_length
= sizeof(struct in_addr
);
244 /* --- @beforehook@, @afterhook@ --- *
246 * Arguments: @sel_state *s@ = select state
247 * @sel_args *sa@ = argument block
248 * @void *p@ = uninteresting pointer
252 * Use: Processes the selector's arguments before @select@ is
253 * called, to allow ADNS to do its thing.
256 static void beforehook(sel_state
*s
, sel_args
*sa
, void *p
)
258 adns_beforeselect(ads
, &sa
->maxfd
,
259 &sa
->fd
[SEL_READ
], &sa
->fd
[SEL_WRITE
], &sa
->fd
[SEL_EXC
],
260 &sa
->tvp
, &sa
->tv
, &sa
->now
);
263 static void afterhook(sel_state
*s
, sel_args
*sa
, void *p
)
272 adns_afterselect(ads
, sa
->maxfd
,
273 &sa
->fd
[SEL_READ
], &sa
->fd
[SEL_WRITE
], &sa
->fd
[SEL_EXC
],
275 while (q
= 0, (e
= adns_check(ads
, &q
, &a
, &c
)) == 0) {
279 else switch (rc
->q
) {
281 assert(a
->type
== adns_r_addr
);
282 report(rc
, a
, a
->rrs
.addr
, a
->nrrs
, &a
->owner
, 1);
287 if (a
->type
== adns_r_ptr
) {
289 if ((e
= adns_submit(ads
, a
->rrs
.str
[0], adns_r_addr
,
294 assert(a
->type
== adns_r_addr
);
295 for (i
= 0; i
< a
->nrrs
; i
++) {
296 if (a
->rrs
.addr
[i
].addr
.sa
.sa_family
== AF_INET
&&
297 a
->rrs
.addr
[i
].addr
.inet
.sin_addr
.s_addr
==
303 report(rc
, a
, &a
->rrs
.addr
[i
], 1, rc
->a
->rrs
.str
, rc
->a
->nrrs
);
315 if (rc
->q
== adns_r_addr
) xfree(rc
->u
.name
);
316 if (rc
->a
) free(rc
->a
);
321 /* --- @bres_init@ --- *
323 * Arguments: @sel_state *s@ = pointer to select multiplexor
327 * Use: Initializes the background resolver for use.
330 void bres_init(sel_state
*s
)
334 if ((e
= adns_init(&ads
, 0, 0)) != 0) {
335 moan("adns_init failed: resolver won't work");
338 sel_addhook(s
, &selhook
, beforehook
, afterhook
, 0);
342 /*----- That's all, folks -------------------------------------------------*/