1 /* authd/providers/rdns.c - rDNS lookup provider for authd
2 * Copyright (c) 2016 Elizabeth Myers <elizabeth@interlinked.me>
4 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice is present in all copies.
8 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
9 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
10 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
11 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
12 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
13 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
14 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
15 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
16 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
17 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
18 * POSSIBILITY OF SUCH DAMAGE.
22 #include "rb_commio.h"
32 struct auth_client
*auth
; /* Our client */
33 struct DNSQuery query
; /* DNS query */
34 time_t timeout
; /* When the request times out */
37 /* Goinked from old s_auth.c --Elizabeth */
38 static const char *messages
[] =
40 "*** Looking up your hostname...",
41 "*** Found your hostname",
42 "*** Couldn't look up your hostname",
43 "*** Your hostname is too long, ignoring hostname",
54 static EVH timeout_dns_queries_event
;
55 static void client_fail(struct dns_query
*query
, dns_message message
);
56 static void client_success(struct dns_query
*query
);
57 static void get_dns_answer(void *userdata
, struct DNSReply
*reply
);
59 rb_dlink_list queries
;
60 static struct ev_entry
*timeout_ev
;
64 bool client_dns_init(void)
66 timeout_ev
= rb_event_addish("timeout_dns_queries_event", timeout_dns_queries_event
, NULL
, 1);
67 return (timeout_ev
!= NULL
);
70 void client_dns_destroy(void)
72 rb_dlink_node
*ptr
, *nptr
;
73 struct dns_query
*query
;
75 RB_DLINK_FOREACH_SAFE(ptr
, nptr
, queries
.head
)
77 client_fail(ptr
->data
, REPORT_FAIL
);
78 rb_dlinkDelete(ptr
, &queries
);
82 rb_event_delete(timeout_ev
);
85 bool client_dns_start(struct auth_client
*auth
)
87 struct dns_query
*query
= rb_malloc(sizeof(struct dns_query
));
90 query
->timeout
= rb_current_time() + timeout
;
92 query
->query
.ptr
= query
;
93 query
->query
.callback
= get_dns_answer
;
95 gethost_byaddr(&auth
->c_addr
, &query
->query
);
96 notice_client(auth
, messages
[REPORT_LOOKUP
]);
97 set_provider(auth
, PROVIDER_RDNS
);
101 void client_dns_cancel(struct auth_client
*auth
)
105 /* Bah, the stupid DNS resolver code doesn't have a cancellation
107 RB_DLINK_FOREACH(ptr
, queries
.head
)
109 struct dns_query
*query
= ptr
->data
;
111 if(query
->auth
== auth
)
113 /* This will get cleaned up later by the DNS stuff */
114 client_fail(query
, REPORT_FAIL
);
121 get_dns_answer(void *userdata
, struct DNSReply
*reply
)
123 struct dns_query
*query
= userdata
;
124 struct auth_client
*auth
= query
->auth
;
125 rb_dlink_node
*ptr
, *nptr
;
127 dns_message response
;
129 if(reply
== NULL
|| auth
== NULL
)
131 response
= REPORT_FAIL
;
136 if(!sockcmp(&auth
->c_addr
, &reply
->addr
, GET_SS_FAMILY(&auth
->c_addr
)))
138 response
= REPORT_FAIL
;
143 if(strlen(reply
->h_name
) > HOSTLEN
)
146 response
= REPORT_TOOLONG
;
151 rb_strlcpy(auth
->hostname
, reply
->h_name
, HOSTLEN
+ 1);
154 /* Clean us up off the pending queries list */
155 RB_DLINK_FOREACH_SAFE(ptr
, nptr
, queries
.head
)
157 struct dns_query
*query_l
= ptr
->data
;
163 client_fail(query
, response
);
165 client_success(query
);
167 rb_dlinkDelete(ptr
, &queries
);
174 /* Timeout outstanding queries */
175 static void timeout_dns_queries_event(void *notused
)
179 /* NOTE - we do not delete queries from the list from a timeout, when
180 * the query times out later it will be deleted.
182 RB_DLINK_FOREACH(ptr
, queries
.head
)
184 struct dns_query
*query
= ptr
->data
;
186 if(query
->auth
&& query
->timeout
< rb_current_time())
188 client_fail(query
, REPORT_FAIL
);
194 static void client_fail(struct dns_query
*query
, dns_message report
)
196 struct auth_client
*auth
= query
->auth
;
200 rb_strlcpy(auth
->hostname
, "*", sizeof(auth
->hostname
));
201 notice_client(auth
, messages
[report
]);
202 provider_done(auth
, PROVIDER_RDNS
);
207 static void client_success(struct dns_query
*query
)
209 struct auth_client
*auth
= query
->auth
;
213 notice_client(auth
, messages
[REPORT_FOUND
]);
214 provider_done(auth
, PROVIDER_RDNS
);
219 struct auth_provider rdns_provider
=
222 .init
= client_dns_init
,
223 .destroy
= client_dns_destroy
,
224 .start
= client_dns_start
,
225 .cancel
= client_dns_cancel
,