source: mainline/uspace/srv/net/dnsrsrv/query.c

Last change on this file was a63966d, checked in by Jakub Jermar <jakub@…>, 7 years ago

Provide doc/doxygroups.h for most apps

  • Property mode set to 100644
File size: 5.5 KB
RevLine 
[adae30d]1/*
[dc95342]2 * Copyright (c) 2013 Jiri Svoboda
[adae30d]3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
[a63966d]29/** @addtogroup dnsrsrv
[adae30d]30 * @{
31 */
32/**
33 * @file
34 */
35
36#include <errno.h>
[48171fc4]37#include <io/log.h>
[08a6382]38#include <mem.h>
[dc95342]39#include <stdlib.h>
[7262f89]40#include <str.h>
41#include "dns_msg.h"
[adae30d]42#include "dns_std.h"
43#include "dns_type.h"
44#include "query.h"
[f85ed4b]45#include "transport.h"
[adae30d]46
47static uint16_t msg_id;
48
[b7fd2a0]49static errno_t dns_name_query(const char *name, dns_qtype_t qtype,
[0aa70f4]50 dns_host_info_t *info)
[adae30d]51{
[0aa70f4]52 /* Start with the caller-provided name */
53 char *sname = str_dup(name);
54 if (sname == NULL)
[a0d97f83]55 return ENOMEM;
[a35b458]56
[0aa70f4]57 char *qname = str_dup(name);
58 if (qname == NULL) {
59 free(sname);
60 return ENOMEM;
61 }
[a35b458]62
[0aa70f4]63 dns_question_t *question = calloc(1, sizeof(dns_question_t));
64 if (question == NULL) {
65 free(qname);
66 free(sname);
67 return ENOMEM;
68 }
[a35b458]69
[0aa70f4]70 question->qname = qname;
71 question->qtype = qtype;
[a0d97f83]72 question->qclass = DC_IN;
[a35b458]73
[0aa70f4]74 dns_message_t *msg = dns_message_new();
75 if (msg == NULL) {
76 free(question);
77 free(qname);
78 free(sname);
[48171fc4]79 return ENOMEM;
[0aa70f4]80 }
[a35b458]81
[48171fc4]82 msg->id = msg_id++;
83 msg->qr = QR_QUERY;
84 msg->opcode = OPC_QUERY;
85 msg->aa = false;
86 msg->tc = false;
87 msg->rd = true;
88 msg->ra = false;
[a35b458]89
[0aa70f4]90 list_append(&question->msg, &msg->question);
[a35b458]91
[58e8646]92 log_msg(LOG_DEFAULT, LVL_DEBUG, "dns_name_query: send DNS request");
[0aa70f4]93 dns_message_t *amsg;
[b7fd2a0]94 errno_t rc = dns_request(msg, &amsg);
[48171fc4]95 if (rc != EOK) {
[0aa70f4]96 dns_message_destroy(msg);
97 free(sname);
[f85ed4b]98 return rc;
[48171fc4]99 }
[a35b458]100
[feeac0d]101 list_foreach(amsg->answer, msg, dns_rr_t, rr) {
[716357f]102 log_msg(LOG_DEFAULT, LVL_DEBUG, " - '%s' %u/%u, dsize %zu",
[0aa70f4]103 rr->name, rr->rtype, rr->rclass, rr->rdata_size);
[a35b458]104
[0aa70f4]105 if ((rr->rtype == DTYPE_CNAME) && (rr->rclass == DC_IN) &&
106 (str_cmp(rr->name, sname) == 0)) {
[a35b458]107
[d531bd6]108 log_msg(LOG_DEFAULT, LVL_DEBUG, "decode cname (%p, %zu, %zu)",
[9f029aa]109 amsg->pdu.data, amsg->pdu.size, rr->roff);
[a35b458]110
[0aa70f4]111 char *cname;
112 size_t eoff;
[9f029aa]113 rc = dns_name_decode(&amsg->pdu, rr->roff, &cname, &eoff);
[d531bd6]114 if (rc != EOK) {
[0aa70f4]115 assert((rc == EINVAL) || (rc == ENOMEM));
[a35b458]116
[0aa70f4]117 log_msg(LOG_DEFAULT, LVL_DEBUG, "error decoding cname");
[a35b458]118
[d531bd6]119 dns_message_destroy(msg);
120 dns_message_destroy(amsg);
[0aa70f4]121 free(sname);
[a35b458]122
[d531bd6]123 return rc;
124 }
[a35b458]125
[d531bd6]126 log_msg(LOG_DEFAULT, LVL_DEBUG, "name = '%s' "
127 "cname = '%s'", sname, cname);
[a35b458]128
[d531bd6]129 /* Continue looking for the more canonical name */
[0aa70f4]130 free(sname);
[d531bd6]131 sname = cname;
132 }
[a35b458]133
[0aa70f4]134 if ((qtype == DTYPE_A) && (rr->rtype == DTYPE_A) &&
135 (rr->rclass == DC_IN) && (rr->rdata_size == sizeof(addr32_t)) &&
136 (str_cmp(rr->name, sname) == 0)) {
[a35b458]137
[0aa70f4]138 info->cname = str_dup(rr->name);
139 if (info->cname == NULL) {
[d531bd6]140 dns_message_destroy(msg);
[dc95342]141 dns_message_destroy(amsg);
[0aa70f4]142 free(sname);
[a35b458]143
[dc95342]144 return ENOMEM;
[7262f89]145 }
[a35b458]146
[02a09ed]147 inet_addr_set(dns_uint32_t_decode(rr->rdata, rr->rdata_size),
[3e66428]148 &info->addr);
[a35b458]149
[a0d97f83]150 dns_message_destroy(msg);
[dc95342]151 dns_message_destroy(amsg);
[0aa70f4]152 free(sname);
[a35b458]153
[0aa70f4]154 return EOK;
155 }
[a35b458]156
[0aa70f4]157 if ((qtype == DTYPE_AAAA) && (rr->rtype == DTYPE_AAAA) &&
158 (rr->rclass == DC_IN) && (rr->rdata_size == sizeof(addr128_t)) &&
159 (str_cmp(rr->name, sname) == 0)) {
[a35b458]160
[0aa70f4]161 info->cname = str_dup(rr->name);
162 if (info->cname == NULL) {
163 dns_message_destroy(msg);
164 dns_message_destroy(amsg);
165 free(sname);
[a35b458]166
[0aa70f4]167 return ENOMEM;
168 }
[a35b458]169
[0aa70f4]170 addr128_t addr;
171 dns_addr128_t_decode(rr->rdata, rr->rdata_size, addr);
[a35b458]172
[0aa70f4]173 inet_addr_set6(addr, &info->addr);
[a35b458]174
[0aa70f4]175 dns_message_destroy(msg);
176 dns_message_destroy(amsg);
177 free(sname);
[a35b458]178
[7262f89]179 return EOK;
180 }
181 }
[a35b458]182
[0aa70f4]183 log_msg(LOG_DEFAULT, LVL_DEBUG, "'%s' not resolved, fail", sname);
[a35b458]184
[48171fc4]185 dns_message_destroy(msg);
[dc95342]186 dns_message_destroy(amsg);
[0aa70f4]187 free(sname);
[a35b458]188
[7262f89]189 return EIO;
[adae30d]190}
191
[b7fd2a0]192errno_t dns_name2host(const char *name, dns_host_info_t **rinfo, ip_ver_t ver)
[0aa70f4]193{
194 dns_host_info_t *info = calloc(1, sizeof(dns_host_info_t));
195 if (info == NULL)
196 return ENOMEM;
[a35b458]197
[b7fd2a0]198 errno_t rc;
[a35b458]199
[e948fde]200 switch (ver) {
201 case ip_any:
[0aa70f4]202 rc = dns_name_query(name, DTYPE_AAAA, info);
[a35b458]203
[0aa70f4]204 if (rc != EOK)
205 rc = dns_name_query(name, DTYPE_A, info);
[a35b458]206
[0aa70f4]207 break;
[e948fde]208 case ip_v4:
[0aa70f4]209 rc = dns_name_query(name, DTYPE_A, info);
210 break;
[e948fde]211 case ip_v6:
[0aa70f4]212 rc = dns_name_query(name, DTYPE_AAAA, info);
213 break;
214 default:
215 rc = EINVAL;
216 }
[a35b458]217
[0aa70f4]218 if (rc == EOK)
219 *rinfo = info;
220 else
221 free(info);
[a35b458]222
[0aa70f4]223 return rc;
224}
225
[dc95342]226void dns_hostinfo_destroy(dns_host_info_t *info)
227{
[959d2ec]228 free(info->cname);
[dc95342]229 free(info);
230}
231
[adae30d]232/** @}
233 */
Note: See TracBrowser for help on using the repository browser.