]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - lib/libc/nameser/ns_samedomain.c
Optionally bind ktls threads to NUMA domains
[FreeBSD/FreeBSD.git] / lib / libc / nameser / ns_samedomain.c
1 /*-
2  * SPDX-License-Identifier: ISC
3  *
4  * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
5  * Copyright (c) 1995,1999 by Internet Software Consortium.
6  *
7  * Permission to use, copy, modify, and distribute this software for any
8  * purpose with or without fee is hereby granted, provided that the above
9  * copyright notice and this permission notice appear in all copies.
10  *
11  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
12  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13  * MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR
14  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
17  * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18  */
19
20 #ifndef lint
21 static const char rcsid[] = "$Id: ns_samedomain.c,v 1.6 2005/04/27 04:56:40 sra Exp $";
22 #endif
23 #include <sys/cdefs.h>
24 __FBSDID("$FreeBSD$");
25
26 #include "port_before.h"
27
28 #include <sys/types.h>
29 #include <arpa/nameser.h>
30 #include <errno.h>
31 #include <string.h>
32
33 #include "port_after.h"
34
35 /*%
36  *      Check whether a name belongs to a domain.
37  *
38  * Inputs:
39  *\li   a - the domain whose ancestry is being verified
40  *\li   b - the potential ancestor we're checking against
41  *
42  * Return:
43  *\li   boolean - is a at or below b?
44  *
45  * Notes:
46  *\li   Trailing dots are first removed from name and domain.
47  *      Always compare complete subdomains, not only whether the
48  *      domain name is the trailing string of the given name.
49  *
50  *\li   "host.foobar.top" lies in "foobar.top" and in "top" and in ""
51  *      but NOT in "bar.top"
52  */
53
54 int
55 ns_samedomain(const char *a, const char *b) {
56         size_t la, lb;
57         int diff, i, escaped;
58         const char *cp;
59
60         la = strlen(a);
61         lb = strlen(b);
62
63         /* Ignore a trailing label separator (i.e. an unescaped dot) in 'a'. */
64         if (la != 0U && a[la - 1] == '.') {
65                 escaped = 0;
66                 /* Note this loop doesn't get executed if la==1. */
67                 for (i = la - 2; i >= 0; i--)
68                         if (a[i] == '\\') {
69                                 if (escaped)
70                                         escaped = 0;
71                                 else
72                                         escaped = 1;
73                         } else
74                                 break;
75                 if (!escaped)
76                         la--;
77         }
78
79         /* Ignore a trailing label separator (i.e. an unescaped dot) in 'b'. */
80         if (lb != 0U && b[lb - 1] == '.') {
81                 escaped = 0;
82                 /* note this loop doesn't get executed if lb==1 */
83                 for (i = lb - 2; i >= 0; i--)
84                         if (b[i] == '\\') {
85                                 if (escaped)
86                                         escaped = 0;
87                                 else
88                                         escaped = 1;
89                         } else
90                                 break;
91                 if (!escaped)
92                         lb--;
93         }
94
95         /* lb == 0 means 'b' is the root domain, so 'a' must be in 'b'. */
96         if (lb == 0U)
97                 return (1);
98
99         /* 'b' longer than 'a' means 'a' can't be in 'b'. */
100         if (lb > la)
101                 return (0);
102
103         /* 'a' and 'b' being equal at this point indicates sameness. */
104         if (lb == la)
105                 return (strncasecmp(a, b, lb) == 0);
106
107         /* Ok, we know la > lb. */
108
109         diff = la - lb;
110
111         /*
112          * If 'a' is only 1 character longer than 'b', then it can't be
113          * a subdomain of 'b' (because of the need for the '.' label
114          * separator).
115          */
116         if (diff < 2)
117                 return (0);
118
119         /*
120          * If the character before the last 'lb' characters of 'b'
121          * isn't '.', then it can't be a match (this lets us avoid
122          * having "foobar.com" match "bar.com").
123          */
124         if (a[diff - 1] != '.')
125                 return (0);
126
127         /*
128          * We're not sure about that '.', however.  It could be escaped
129          * and thus not a really a label separator.
130          */
131         escaped = 0;
132         for (i = diff - 2; i >= 0; i--)
133                 if (a[i] == '\\') {
134                         if (escaped)
135                                 escaped = 0;
136                         else
137                                 escaped = 1;
138                 } else
139                         break;
140         if (escaped)
141                 return (0);
142           
143         /* Now compare aligned trailing substring. */
144         cp = a + diff;
145         return (strncasecmp(cp, b, lb) == 0);
146 }
147
148 #ifndef _LIBC
149 /*%
150  *      is "a" a subdomain of "b"?
151  */
152 int
153 ns_subdomain(const char *a, const char *b) {
154         return (ns_samename(a, b) != 1 && ns_samedomain(a, b));
155 }
156 #endif
157
158 /*%
159  *      make a canonical copy of domain name "src"
160  *
161  * notes:
162  * \code
163  *      foo -> foo.
164  *      foo. -> foo.
165  *      foo.. -> foo.
166  *      foo\. -> foo\..
167  *      foo\\. -> foo\\.
168  * \endcode
169  */
170
171 int
172 ns_makecanon(const char *src, char *dst, size_t dstsize) {
173         size_t n = strlen(src);
174
175         if (n + sizeof "." > dstsize) {                 /*%< Note: sizeof == 2 */
176                 errno = EMSGSIZE;
177                 return (-1);
178         }
179         strcpy(dst, src);
180         while (n >= 1U && dst[n - 1] == '.')            /*%< Ends in "." */
181                 if (n >= 2U && dst[n - 2] == '\\' &&    /*%< Ends in "\." */
182                     (n < 3U || dst[n - 3] != '\\'))     /*%< But not "\\." */
183                         break;
184                 else
185                         dst[--n] = '\0';
186         dst[n++] = '.';
187         dst[n] = '\0';
188         return (0);
189 }
190
191 /*%
192  *      determine whether domain name "a" is the same as domain name "b"
193  *
194  * return:
195  *\li   -1 on error
196  *\li   0 if names differ
197  *\li   1 if names are the same
198  */
199
200 int
201 ns_samename(const char *a, const char *b) {
202         char ta[NS_MAXDNAME], tb[NS_MAXDNAME];
203
204         if (ns_makecanon(a, ta, sizeof ta) < 0 ||
205             ns_makecanon(b, tb, sizeof tb) < 0)
206                 return (-1);
207         if (strcasecmp(ta, tb) == 0)
208                 return (1);
209         else
210                 return (0);
211 }
212
213 /*! \file */