1 /*
2 * Various comparison functions
3 */
4
5 #include <errno.h>
6 #include <stdio.h> /* For NULL */
7
8 #include <libcidr.h>
9
10
11 /* Is one block entirely contained in another? */
12 int
cidr_contains(const CIDR * big,const CIDR * little)13 cidr_contains(const CIDR *big, const CIDR *little)
14 {
15 int i, oct, bit;
16 int pflen;
17
18 /* Sanity */
19 if(big==NULL || little==NULL)
20 {
21 errno = EFAULT;
22 return(-1);
23 }
24
25 /* First off, they better be the same type */
26 if(big->proto != little->proto)
27 {
28 errno = EPROTO;
29 return(-1);
30 }
31
32 /* We better understand the protocol, too */
33 if(big->proto!=CIDR_IPV4 && big->proto!=CIDR_IPV6)
34 {
35 errno = EINVAL;
36 return(-1);
37 }
38
39 /*
40 * little better be SMALL enough to fit in big. Note: The prefix
41 * lengths CAN be the same, and little could still 'fit' in big if
42 * the network bits are all the same. No need to special-case it, as
43 * the normal tests below will DTRT. Save big's pflen for the test
44 * loop.
45 */
46 if(cidr_get_pflen(little) < (pflen = cidr_get_pflen(big)))
47 {
48 errno = 0;
49 return(-1);
50 }
51
52 /*
53 * Now let's compare. Note that for IPv4 addresses, the first 12
54 * octets are irrelevant. We take care throughout to keep them
55 * zero'd out, so we don't _need_ to explicitly ignore them. But,
56 * it's wasteful; it quadrules the amount of work needed to be done
57 * to compare to v4 blocks, and this function may be useful in fairly
58 * performance-sensitive parts of the application. Sure, an extra 12
59 * uint8_t compares better not be the make-or-break perforamnce point
60 * for anything real, but why make it harder unnecessarily?
61 */
62 if(big->proto==CIDR_IPV4)
63 {
64 i = 96;
65 pflen += 96;
66 }
67 else if(big->proto==CIDR_IPV6)
68 i = 0;
69 else
70 {
71 /* Shouldn't happen */
72 errno = ENOENT; /* This is a really bad choice of errno */
73 return(-1);
74 }
75
76 /* Start comparing */
77 for( /* i */ ; i < pflen ; i++ )
78 {
79 /* For convenience, set temp. vars to the octet/bit */
80 oct = i/8;
81 bit = 7-(i%8);
82
83 if((big->addr[oct] & (1<<bit)) != (little->addr[oct] & (1<<bit)))
84 {
85 errno = 0;
86 return(-1);
87 }
88 }
89
90 /* If we get here, all their network bits are the same */
91 return(0);
92 }
93
94
95 /* Are two CIDR's the same? */
96 int
cidr_equals(const CIDR * one,const CIDR * two)97 cidr_equals(const CIDR *one, const CIDR *two)
98 {
99 int i;
100
101 /* Check protocols */
102 if(one->proto != two->proto)
103 return(-1);
104
105 /* Check addresses/masks */
106 if(one->proto==CIDR_IPV4)
107 i = 12;
108 else
109 i = 0;
110 for(/* i */ ; i<=15 ; i++)
111 {
112 if(one->addr[i] != two->addr[i])
113 return(-1);
114 if(one->mask[i] != two->mask[i])
115 return(-1);
116 }
117
118 /* If we make it here, they're the same */
119 return(0);
120 }
121