etc/services - sync with NetBSD-8
[minix.git] / external / bsd / bind / dist / contrib / zkt-1.1.3 / domaincmp.c
blob09d1c58e254b53e9c2d3bc7532a2da64434820ae
1 /* $NetBSD: domaincmp.c,v 1.1.1.1 2015/07/08 15:37:48 christos Exp $ */
3 /*****************************************************************
4 **
5 ** @(#) domaincmp.c -- compare two domain names
6 **
7 ** Copyright (c) Aug 2005, Karle Boss, Holger Zuleger (kaho).
8 ** isparentdomain() (c) Mar 2010 by Holger Zuleger
9 ** All rights reserved.
10 **
11 ** This software is open source.
12 **
13 ** Redistribution and use in source and binary forms, with or without
14 ** modification, are permitted provided that the following conditions
15 ** are met:
16 **
17 ** Redistributions of source code must retain the above copyright notice,
18 ** this list of conditions and the following disclaimer.
19 **
20 ** Redistributions in binary form must reproduce the above copyright notice,
21 ** this list of conditions and the following disclaimer in the documentation
22 ** and/or other materials provided with the distribution.
23 **
24 ** Neither the name of Karle Boss or Holger Zuleger (kaho) nor the
25 ** names of its contributors may be used to endorse or promote products
26 ** derived from this software without specific prior written permission.
27 **
28 ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
29 ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
30 ** TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
31 ** PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
32 ** LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
33 ** CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
34 ** SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
35 ** INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
36 ** CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
37 ** ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
38 ** POSSIBILITY OF SUCH DAMAGE.
40 *****************************************************************/
41 # include <stdio.h>
42 # include <string.h>
43 # include <assert.h>
44 # include <ctype.h>
45 #define extern
46 # include "domaincmp.h"
47 #undef extern
50 #define goto_labelstart(str, p) while ( (p) > (str) && *((p)-1) != '.' ) \
51 (p)--
53 /*****************************************************************
54 ** int domaincmp (a, b)
55 ** compare a and b as fqdns.
56 ** return <0 | 0 | >0 as in strcmp
57 ** A subdomain is less than the corresponding parent domain,
58 ** thus domaincmp ("z.example.net", "example.net") return < 0 !!
59 *****************************************************************/
60 int domaincmp (const char *a, const char *b)
62 return domaincmp_dir (a, b, 1);
65 /*****************************************************************
66 ** int domaincmp_dir (a, b, subdomain_above)
67 ** compare a and b as fqdns.
68 ** return <0 | 0 | >0 as in strcmp
69 ** A subdomain is less than the corresponding parent domain,
70 ** thus domaincmp ("z.example.net", "example.net") return < 0 !!
71 *****************************************************************/
72 int domaincmp_dir (const char *a, const char *b, int subdomain_above)
74 register const char *pa;
75 register const char *pb;
76 int dir;
78 if ( a == NULL ) return -1;
79 if ( b == NULL ) return 1;
81 if ( subdomain_above )
82 dir = 1;
83 else
84 dir = -1;
86 if ( *a == '.' ) /* skip a leading dot */
87 a++;
88 if ( *b == '.' ) /* same at the other string */
89 b++;
91 /* let pa and pb point to the last non dot char */
92 pa = a + strlen (a);
93 do
94 pa--;
95 while ( pa > a && *pa == '.' );
97 pb = b + strlen (b);
98 do
99 pb--;
100 while ( pb > b && *pb == '.' );
102 /* cmp both domains starting at the end */
103 while ( *pa == *pb && pa > a && pb > b )
104 pa--, pb--;
106 if ( *pa != *pb ) /* both domains are different ? */
108 if ( *pa == '.' )
109 pa++; /* set to beginning of next label */
110 else
111 goto_labelstart (a, pa); /* find begin of current label */
112 if ( *pb == '.' )
113 pb++; /* set to beginning of next label */
114 else
115 goto_labelstart (b, pb); /* find begin of current label */
117 else /* maybe one of them has a subdomain */
119 if ( pa > a )
120 if ( pa[-1] == '.' )
121 return -1 * dir;
122 else
123 goto_labelstart (a, pa);
124 else if ( pb > b )
125 if ( pb[-1] == '.' )
126 return 1 * dir;
127 else
128 goto_labelstart (b, pb);
129 else
130 return 0; /* both are at the beginning, so they are equal */
133 /* both domains are definitly unequal */
134 while ( *pa == *pb ) /* so we have to look at the point where they differ */
135 pa++, pb++;
137 return *pa - *pb;
140 /*****************************************************************
142 ** int issubdomain ("child", "parent")
144 ** "child" and "parent" are standardized domain names in such
145 ** a way that even both domain names are ending with a dot,
146 ** or none of them.
148 ** returns 1 if "child" is a subdomain of "parent"
149 ** returns 0 if "child" is not a subdomain of "parent"
151 *****************************************************************/
152 int issubdomain (const char *child, const char *parent)
154 const char *p;
155 const char *cdot;
156 int ccnt;
157 int pcnt;
159 if ( !child || !parent || *child == '\0' || *parent == '\0' )
160 return 0;
162 cdot = NULL;
163 pcnt = 0;
164 for ( p = parent; *p; p++ )
165 if ( *p == '.' )
166 pcnt++;
168 ccnt = 0;
169 for ( p = child; *p; p++ )
170 if ( *p == '.' )
172 if ( ccnt == 0 )
173 cdot = p;
174 ccnt++;
176 if ( ccnt == 0 ) /* child is not a fqdn or is not deep enough ? */
177 return 0;
178 if ( pcnt == 0 ) /* parent is not a fqdn ? */
179 return 0;
181 if ( pcnt >= ccnt ) /* parent has more levels than child ? */
182 return 0;
184 /* is child a (one level) subdomain of parent ? */
185 if ( strcmp (cdot+1, parent) == 0 ) /* the domains are equal ? */
186 return 1;
188 return 0;
191 /*****************************************************************
193 ** int isparentdomain ("child", "parent", level)
195 ** "child" and "parent" are standardized domain names in such
196 ** a way that even both domain names are ending with a dot,
197 ** or none of them.
199 ** returns 1 if "child" is a subdomain of "parent"
200 ** returns 0 if "child" is not a subdomain of "parent"
201 ** returns -1 if "child" and "parent" are the same domain
203 *****************************************************************/
204 int isparentdomain (const char *child, const char *parent, int level)
206 const char *p;
207 const char *cdot;
208 const char *pdot;
209 int ccnt;
210 int pcnt;
212 if ( !child || !parent || *child == '\0' || *parent == '\0' )
213 return 0;
215 pdot = cdot = NULL;
216 pcnt = 0;
217 for ( p = parent; *p; p++ )
218 if ( *p == '.' )
220 if ( pcnt == 0 )
221 pdot = p;
222 pcnt++;
225 ccnt = 0;
226 for ( p = child; *p; p++ )
227 if ( *p == '.' )
229 if ( ccnt == 0 )
230 cdot = p;
231 ccnt++;
233 if ( ccnt == 0 || ccnt < level ) /* child is not a fqdn or is not deep enough ? */
234 return 0;
235 if ( pcnt == 0 ) /* parent is not a fqdn ? */
236 return 0;
238 if ( pcnt > ccnt ) /* parent has more levels than child ? */
239 return 0;
241 if ( pcnt == ccnt ) /* both are at the same level ? */
243 /* let's check the domain part */
244 if ( strcmp (cdot, pdot) == 0 ) /* the domains are equal ? */
245 return -1;
246 return 0;
249 if ( pcnt > ccnt ) /* parent has more levels than child ? */
250 return 0;
252 /* is child a (one level) subdomain of parent ? */
253 if ( strcmp (cdot+1, parent) == 0 ) /* the domains are equal ? */
254 return 1;
256 return 0;
259 #ifdef DOMAINCMP_TEST
260 static struct {
261 char *a;
262 char *b;
263 int res;
264 } ex[] = {
265 { ".", ".", 0 },
266 { "test", "", 1 },
267 { "", "test2", -1 },
268 { "", "", 0 },
269 { "de", "de", 0 },
270 { ".de", "de", 0 },
271 { "de.", "de.", 0 },
272 { ".de", ".de", 0 },
273 { ".de.", ".de.", 0 },
274 { ".de", "zde", -1 },
275 { ".de", "ade", 1 },
276 { "zde", ".de", 1 },
277 { "ade", ".de", -1 },
278 { "a.de", ".de", -1 },
279 { ".de", "a.de", 1 },
280 { "a.de", "b.de", -1 },
281 { "a.de.", "b.de", -1 },
282 { "a.de", "b.de.", -1 },
283 { "a.de", "a.de.", 0 },
284 { "aa.de", "b.de", -1 },
285 { "ba.de", "b.de", 1 },
286 { "a.de", "a.dk", -1 },
287 { "anna.example.de", "anna.example.de", 0 },
288 { "anna.example.de", "annamirl.example.de", -1 },
289 { "anna.example.de", "ann.example.de", 1 },
290 { "example.de.", "xy.example.de.", 1 },
291 { "example.de.", "ab.example.de.", 1 },
292 { "example.de", "ab.example.de", 1 },
293 { "xy.example.de.", "example.de.", -1 },
294 { "ab.example.de.", "example.de.", -1 },
295 { "ab.example.de", "example.de", -1 },
296 { "ab.mast.de", "axt.de", 1 },
297 { "ab.mast.de", "obt.de", -1 },
298 { "abc.example.de.", "xy.example.de.", -1 },
299 { NULL, NULL, 0 }
302 const char *progname;
303 main (int argc, char *argv[])
306 int expect;
307 int res;
308 int c;
309 int i;
311 progname = *argv;
313 for ( i = 0; ex[i].a; i++ )
315 expect = ex[i].res;
316 if ( expect < 0 )
317 c = '<';
318 else if ( expect > 0 )
319 c = '>';
320 else
321 c = '=';
322 printf ("%-20s %-20s ", ex[i].a, ex[i].b);
323 printf ("%3d ", issubdomain (ex[i].a, ex[i].b));
324 printf ("\t==> 0 %c ", c);
325 fflush (stdout);
326 res = domaincmp (ex[i].a, ex[i].b);
327 printf ("%3d ", res);
328 if ( res < 0 && expect < 0 || res > 0 && expect > 0 || res == 0 && expect == 0 )
329 puts ("ok");
330 else
331 puts ("not ok");
334 #endif