1 /* MIT License
2 *
3 * Copyright (c) 1998, 2011 Massachusetts Institute of Technology
4 * Copyright (c) The c-ares project and its contributors
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice (including the next
14 * paragraph) shall be included in all copies or substantial portions of the
15 * Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 * SOFTWARE.
24 *
25 * SPDX-License-Identifier: MIT
26 */
27
28 #include "ares_private.h"
29
30 #ifdef HAVE_NETINET_IN_H
31 # include <netinet/in.h>
32 #endif
33
34 #include "ares_nameser.h"
35
ares_expand_name_validated(const unsigned char * encoded,const unsigned char * abuf,size_t alen,char ** s,size_t * enclen,ares_bool_t is_hostname)36 ares_status_t ares_expand_name_validated(const unsigned char *encoded,
37 const unsigned char *abuf, size_t alen,
38 char **s, size_t *enclen,
39 ares_bool_t is_hostname)
40 {
41 ares_status_t status;
42 ares_buf_t *buf = NULL;
43 size_t start_len;
44
45 if (encoded == NULL || abuf == NULL || alen == 0 || enclen == NULL) {
46 return ARES_EBADNAME; /* EFORMERR would be better */
47 }
48
49 if (encoded < abuf || encoded >= abuf + alen) {
50 return ARES_EBADNAME; /* EFORMERR would be better */
51 }
52
53 *enclen = 0;
54
55 /* NOTE: we allow 's' to be NULL to skip it */
56 if (s) {
57 *s = NULL;
58 }
59
60 buf = ares_buf_create_const(abuf, alen);
61
62 if (buf == NULL) {
63 return ARES_ENOMEM;
64 }
65
66 status = ares_buf_set_position(buf, (size_t)(encoded - abuf));
67 if (status != ARES_SUCCESS) {
68 goto done;
69 }
70
71 start_len = ares_buf_len(buf);
72 status = ares_dns_name_parse(buf, s, is_hostname);
73 if (status != ARES_SUCCESS) {
74 goto done;
75 }
76
77 *enclen = start_len - ares_buf_len(buf);
78
79 done:
80 ares_buf_destroy(buf);
81 return status;
82 }
83
ares_expand_name(const unsigned char * encoded,const unsigned char * abuf,int alen,char ** s,long * enclen)84 int ares_expand_name(const unsigned char *encoded, const unsigned char *abuf,
85 int alen, char **s, long *enclen)
86 {
87 /* Keep public API compatible */
88 size_t enclen_temp = 0;
89 ares_status_t status;
90
91 if (encoded == NULL || abuf == NULL || alen <= 0 || enclen == NULL) {
92 return ARES_EBADNAME;
93 }
94
95 status = ares_expand_name_validated(encoded, abuf, (size_t)alen, s,
96 &enclen_temp, ARES_FALSE);
97 *enclen = (long)enclen_temp;
98 return (int)status;
99 }
100