1 /* $NetBSD: domaincmp.c,v 1.1.1.1 2015/07/08 15:37:48 christos Exp $ */
3 /*****************************************************************
5 ** @(#) domaincmp.c -- compare two domain names
7 ** Copyright (c) Aug 2005, Karle Boss, Holger Zuleger (kaho).
8 ** isparentdomain() (c) Mar 2010 by Holger Zuleger
9 ** All rights reserved.
11 ** This software is open source.
13 ** Redistribution and use in source and binary forms, with or without
14 ** modification, are permitted provided that the following conditions
17 ** Redistributions of source code must retain the above copyright notice,
18 ** this list of conditions and the following disclaimer.
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.
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.
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 *****************************************************************/
46 # include "domaincmp.h"
50 #define goto_labelstart(str, p) while ( (p) > (str) && *((p)-1) != '.' ) \
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
;
78 if ( a
== NULL
) return -1;
79 if ( b
== NULL
) return 1;
81 if ( subdomain_above
)
86 if ( *a
== '.' ) /* skip a leading dot */
88 if ( *b
== '.' ) /* same at the other string */
91 /* let pa and pb point to the last non dot char */
95 while ( pa
> a
&& *pa
== '.' );
100 while ( pb
> b
&& *pb
== '.' );
102 /* cmp both domains starting at the end */
103 while ( *pa
== *pb
&& pa
> a
&& pb
> b
)
106 if ( *pa
!= *pb
) /* both domains are different ? */
109 pa
++; /* set to beginning of next label */
111 goto_labelstart (a
, pa
); /* find begin of current label */
113 pb
++; /* set to beginning of next label */
115 goto_labelstart (b
, pb
); /* find begin of current label */
117 else /* maybe one of them has a subdomain */
123 goto_labelstart (a
, pa
);
128 goto_labelstart (b
, pb
);
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 */
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,
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
)
159 if ( !child
|| !parent
|| *child
== '\0' || *parent
== '\0' )
164 for ( p
= parent
; *p
; p
++ )
169 for ( p
= child
; *p
; p
++ )
176 if ( ccnt
== 0 ) /* child is not a fqdn or is not deep enough ? */
178 if ( pcnt
== 0 ) /* parent is not a fqdn ? */
181 if ( pcnt
>= ccnt
) /* parent has more levels than child ? */
184 /* is child a (one level) subdomain of parent ? */
185 if ( strcmp (cdot
+1, parent
) == 0 ) /* the domains are equal ? */
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,
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
)
212 if ( !child
|| !parent
|| *child
== '\0' || *parent
== '\0' )
217 for ( p
= parent
; *p
; p
++ )
226 for ( p
= child
; *p
; p
++ )
233 if ( ccnt
== 0 || ccnt
< level
) /* child is not a fqdn or is not deep enough ? */
235 if ( pcnt
== 0 ) /* parent is not a fqdn ? */
238 if ( pcnt
> ccnt
) /* parent has more levels than child ? */
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 ? */
249 if ( pcnt
> ccnt
) /* parent has more levels than child ? */
252 /* is child a (one level) subdomain of parent ? */
253 if ( strcmp (cdot
+1, parent
) == 0 ) /* the domains are equal ? */
259 #ifdef DOMAINCMP_TEST
273 { ".de.", ".de.", 0 },
274 { ".de", "zde", -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 },
302 const char *progname
;
303 main (int argc
, char *argv
[])
313 for ( i
= 0; ex
[i
].a
; i
++ )
318 else if ( expect
> 0 )
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
);
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 )