]> jfr.im git - solanum.git/blob - authd/dns.c
include: add msgbuf.h for future msgbuf api
[solanum.git] / authd / dns.c
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"
23
24 static void
25 submit_dns_answer(void *userdata, struct DNSReply *reply)
26 {
27 struct dns_request *req = userdata;
28 char response[64] = "*";
29 char status = 'E';
30
31 if (reply == NULL)
32 {
33 rb_helper_write(authd_helper, "E %s E %c *", req->reqid, req->type);
34 goto cleanup;
35 }
36
37 switch (req->type)
38 {
39 case '4':
40 if (GET_SS_FAMILY(&reply->addr) == AF_INET)
41 {
42 status = 'O';
43 rb_inet_ntop_sock((struct sockaddr *) &reply->addr, response, sizeof(response));
44 }
45 break;
46 #ifdef RB_IPV6
47 case '6':
48 if (GET_SS_FAMILY(&reply->addr) == AF_INET6)
49 {
50 char tmpres[63];
51 rb_inet_ntop_sock((struct sockaddr *) &reply->addr, tmpres, sizeof(tmpres));
52
53 if (*tmpres == ':')
54 {
55 rb_strlcpy(response, "0", sizeof(response));
56 rb_strlcat(response, tmpres, sizeof(response));
57 }
58 else
59 rb_strlcpy(response, tmpres, sizeof(response));
60
61 status = 'O';
62 }
63 break;
64 #endif
65 case 'R':
66 {
67 struct sockaddr_in *ip, *ip_fwd;
68 ip = (struct sockaddr_in *) &req->addr;
69 ip_fwd = (struct sockaddr_in *) &reply->addr;
70
71 if(ip->sin_addr.s_addr == ip_fwd->sin_addr.s_addr && strlen(reply->h_name) < 63)
72 {
73 rb_strlcpy(response, reply->h_name, sizeof(response));
74 status = 'O';
75 }
76 }
77 break;
78 #ifdef RB_IPV6
79 case 'S':
80 {
81 struct sockaddr_in6 *ip, *ip_fwd;
82 ip = (struct sockaddr_in6 *) &req->addr;
83 ip_fwd = (struct sockaddr_in6 *) &reply->addr;
84
85 if(memcmp(&ip->sin6_addr, &ip_fwd->sin6_addr, sizeof(struct in6_addr)) == 0 && strlen(reply->h_name) < 63)
86 {
87 rb_strlcpy(response, reply->h_name, sizeof(response));
88 status = 'O';
89 }
90 }
91 break;
92 #endif
93 default:
94 exit(7);
95 }
96
97 rb_helper_write(authd_helper, "E %s %c %c %s", req->reqid, status, req->type, response);
98 cleanup:
99 rb_free(req);
100 }
101
102 void
103 resolve_dns(int parc, char *parv[])
104 {
105 struct dns_request *req;
106 char *requestid = parv[1];
107 char *qtype = parv[2];
108 char *rec = parv[3];
109 int type;
110
111 req = rb_malloc(sizeof(*req));
112 rb_strlcpy(req->reqid, requestid, sizeof(req->reqid));
113 req->type = *qtype;
114
115 switch (req->type)
116 {
117 case '4':
118 type = T_A;
119 break;
120 case '6':
121 type = T_AAAA;
122 break;
123 case 'R':
124 case 'S':
125 if(!rb_inet_pton_sock(rec, (struct sockaddr *) &req->addr))
126 exit(6);
127 type = T_PTR;
128 break;
129 }
130
131 req->query.ptr = req;
132 req->query.callback = submit_dns_answer;
133
134 if (type != T_PTR)
135 gethost_byname_type(rec, &req->query, type);
136 else
137 gethost_byaddr(&req->addr, &req->query);
138 }