]> jfr.im git - solanum.git/blame - authd/dns.c
authd/provider: use rb_sockaddr_storage for IP addresses.
[solanum.git] / authd / dns.c
CommitLineData
8cf45447
AC
1/* authd/dns.h - header for authd DNS functions
2 * Copyright (c) 2016 William Pitcock <nenolod@dereferenced.org>
3 *
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.
7 *
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.
19 */
20
21#include "authd.h"
22#include "dns.h"
394b8dde 23#include "res.h"
8cf45447 24
1c99f551
EM
25void
26format_address(struct rb_sockaddr_storage *addr, char *buffer, size_t length)
27{
28 if(GET_SS_FAMILY(addr) == AF_INET)
29 {
30 rb_inet_ntop_sock((struct sockaddr *)addr, buffer, length);
31 }
b3265d7a 32#ifdef RB_IPV6
1c99f551
EM
33 else if(GET_SS_FAMILY(addr) == AF_INET6)
34 {
35 char tmpbuf[length];
36
37 rb_inet_ntop_sock((struct sockaddr *)addr, tmpbuf, length);
38
39 if(*tmpbuf == ':')
40 {
41 rb_strlcpy(buffer, "0", length);
42 rb_strlcat(buffer, tmpbuf, length);
43 }
44 else
45 rb_strlcpy(buffer, tmpbuf, length);
46 }
b3265d7a
EM
47#endif
48}
49
50bool
51sockcmp(struct rb_sockaddr_storage *addr, struct rb_sockaddr_storage *addr2, int family)
52{
53 if(family == AF_INET)
54 {
55 struct sockaddr_in *ip, *ip2;
56 ip = (struct sockaddr_in *)addr;
57 ip2 = (struct sockaddr_in *)addr2;
58
59 return ip->sin_addr.s_addr == ip2->sin_addr.s_addr;
60 }
61#ifdef RB_IPV6
62 else if(family == AF_INET6)
63 {
64 struct sockaddr_in6 *ip, *ip2;
65 ip = (struct sockaddr_in6 *) addr;
66 ip2 = (struct sockaddr_in6 *) addr2;
67
68 return(memcmp(&ip->sin6_addr, &ip2->sin6_addr, sizeof(struct in6_addr)) == 0);
69 }
70#endif
71
72 return false;
1c99f551
EM
73}
74
8cf45447
AC
75static void
76submit_dns_answer(void *userdata, struct DNSReply *reply)
77{
78 struct dns_request *req = userdata;
79 char response[64] = "*";
80 char status = 'E';
b3265d7a 81 int family = AF_INET;
8cf45447
AC
82
83 if (reply == NULL)
84 {
c7c009b5 85 rb_helper_write(authd_helper, "E %s E %c *", req->reqid, req->type);
8cf45447
AC
86 goto cleanup;
87 }
88
89 switch (req->type)
90 {
91 case '4':
8cf45447
AC
92#ifdef RB_IPV6
93 case '6':
1c99f551 94 format_address(&reply->addr, response, sizeof(response));
8cf45447
AC
95 break;
96#endif
8cf45447
AC
97#ifdef RB_IPV6
98 case 'S':
b3265d7a
EM
99 family = AF_INET6;
100#endif
101 case 'R':
102 if(sockcmp(&req->addr, &reply->addr, family) && strlen(reply->h_name) < 63)
8cf45447 103 {
b3265d7a
EM
104 rb_strlcpy(response, reply->h_name, sizeof(response));
105 status = 'O';
8cf45447
AC
106 }
107 break;
8cf45447
AC
108 default:
109 exit(7);
110 }
111
c7c009b5 112 rb_helper_write(authd_helper, "E %s %c %c %s", req->reqid, status, req->type, response);
8cf45447
AC
113cleanup:
114 rb_free(req);
115}
116
117void
118resolve_dns(int parc, char *parv[])
119{
120 struct dns_request *req;
121 char *requestid = parv[1];
122 char *qtype = parv[2];
123 char *rec = parv[3];
124 int type;
125
126 req = rb_malloc(sizeof(*req));
127 rb_strlcpy(req->reqid, requestid, sizeof(req->reqid));
128 req->type = *qtype;
129
130 switch (req->type)
131 {
132 case '4':
133 type = T_A;
8cf45447
AC
134 break;
135 case '6':
136 type = T_AAAA;
8cf45447
AC
137 break;
138 case 'R':
139 case 'S':
fa43f559
AC
140 if(!rb_inet_pton_sock(rec, (struct sockaddr *) &req->addr))
141 exit(6);
8cf45447
AC
142 type = T_PTR;
143 break;
144 }
145
146 req->query.ptr = req;
147 req->query.callback = submit_dns_answer;
148
fa43f559
AC
149 if (type != T_PTR)
150 gethost_byname_type(rec, &req->query, type);
151 else
152 gethost_byaddr(&req->addr, &req->query);
8cf45447 153}
394b8dde
EM
154
155void
156enumerate_nameservers(const char *rid, const char letter)
157{
158 char buf[40 * IRCD_MAXNS]; /* Plenty */
159 char *c = buf;
160 int i;
161
162 if (!irc_nscount)
163 {
164 /* Shouldn't happen */
165 rb_helper_write(authd_helper, "X %s %c NONAMESERVERS", rid, letter);
166 return;
167 }
168
169 for(i = 0; i < irc_nscount; i++)
170 {
171 char addr[40];
172 int ret;
173
174 rb_inet_ntop_sock((struct sockaddr *)&irc_nsaddr_list[i], addr, sizeof(addr));
175
176 if (!addr[0])
177 {
178 /* Shouldn't happen */
179 rb_helper_write(authd_helper, "X %s %c INVALIDNAMESERVER", rid, letter);
180 return;
181 }
182
183 ret = snprintf(c, 40, "%s ", addr);
184 c += (size_t)ret;
185 }
186
187 *(--c) = '\0';
188
189 rb_helper_write(authd_helper, "Y %s %c %s", rid, letter, buf);
190}
6445c1cf
EM
191
192void
193reload_nameservers(const char letter)
194{
195 /* Not a whole lot to it */
196 restart_resolver();
197}