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
]);
100 void client_dns_cancel(struct auth_client
*auth
)
104 /* Bah, the stupid DNS resolver code doesn't have a cancellation
106 RB_DLINK_FOREACH(ptr
, queries
.head
)
108 struct dns_query
*query
= ptr
->data
;
110 if(query
->auth
== auth
)
112 /* This will get cleaned up later by the DNS stuff */
113 client_fail(query
, REPORT_FAIL
);
120 get_dns_answer(void *userdata
, struct DNSReply
*reply
)
122 struct dns_query
*query
= userdata
;
123 struct auth_client
*auth
= query
->auth
;
124 rb_dlink_node
*ptr
, *nptr
;
126 dns_message response
;
128 if(reply
== NULL
|| auth
== NULL
)
130 response
= REPORT_FAIL
;
135 if(!sockcmp(&auth
->c_addr
, &reply
->addr
, GET_SS_FAMILY(&auth
->c_addr
)))
137 response
= REPORT_FAIL
;
142 if(strlen(reply
->h_name
) > HOSTLEN
)
145 response
= REPORT_TOOLONG
;
150 rb_strlcpy(auth
->hostname
, reply
->h_name
, HOSTLEN
+ 1);
153 /* Clean us up off the pending queries list */
154 RB_DLINK_FOREACH_SAFE(ptr
, nptr
, queries
.head
)
156 struct dns_query
*query_l
= ptr
->data
;
162 client_fail(query
, response
);
164 client_success(query
);
166 rb_dlinkDelete(ptr
, &queries
);
173 /* Timeout outstanding queries */
174 static void timeout_dns_queries_event(void *notused
)
178 /* NOTE - we do not delete queries from the list from a timeout, when
179 * the query times out later it will be deleted.
181 RB_DLINK_FOREACH(ptr
, queries
.head
)
183 struct dns_query
*query
= ptr
->data
;
185 if(query
->auth
&& query
->timeout
< rb_current_time())
187 client_fail(query
, REPORT_FAIL
);
193 static void client_fail(struct dns_query
*query
, dns_message report
)
195 struct auth_client
*auth
= query
->auth
;
199 rb_strlcpy(auth
->hostname
, "*", sizeof(auth
->hostname
));
200 notice_client(auth
, messages
[report
]);
201 provider_done(auth
, PROVIDER_RDNS
);
206 static void client_success(struct dns_query
*query
)
208 struct auth_client
*auth
= query
->auth
;
212 notice_client(auth
, messages
[REPORT_FOUND
]);
213 provider_done(auth
, PROVIDER_RDNS
);
218 struct auth_provider rdns_provider
=
221 .init
= client_dns_init
,
222 .destroy
= client_dns_destroy
,
223 .start
= client_dns_start
,
224 .cancel
= client_dns_cancel
,