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