1 #include "ip6.h"
2 
3 #include <string.h>
4 #include "sorted_array.h"
5 
6 static int
addr_cmp(struct in6_addr const * a,struct in6_addr const * b)7 addr_cmp(struct in6_addr const *a, struct in6_addr const *b)
8 {
9 	/* The addresses are stored in big endian. */
10 	return memcmp(a, b, sizeof(uint32_t[4]));
11 }
12 
13 /* a == b? */
14 static bool
addr_equals(struct in6_addr const * a,struct in6_addr const * b)15 addr_equals(struct in6_addr const *a, struct in6_addr const *b)
16 {
17 	return addr_cmp(a, b) == 0;
18 }
19 
20 /* a <= b? */
21 static bool
addr_le(struct in6_addr const * a,struct in6_addr const * b)22 addr_le(struct in6_addr const *a, struct in6_addr const *b)
23 {
24 	return addr_cmp(a, b) <= 0;
25 }
26 
27 /* a < b? */
28 static bool
addr_lt(struct in6_addr const * a,struct in6_addr const * b)29 addr_lt(struct in6_addr const *a, struct in6_addr const *b)
30 {
31 	return addr_cmp(a, b) < 0;
32 }
33 
34 /* a + 1 == b? */
35 static bool
addr_is_successor(struct in6_addr const * a,struct in6_addr const * b)36 addr_is_successor(struct in6_addr const *a, struct in6_addr const *b)
37 {
38 	struct in6_addr a_plus_1;
39 	int i;
40 
41 	memcpy(&a_plus_1, a, sizeof(a_plus_1));
42 	for (i = 15; i >= 0; i--) {
43 		if (a_plus_1.s6_addr[i] != UINT8_MAX) {
44 			a_plus_1.s6_addr[i]++;
45 			return memcmp(&a_plus_1, b, sizeof(a_plus_1)) == 0;
46 		}
47 		a_plus_1.s6_addr[i] = 0;
48 	}
49 
50 	return false; /* b cannot be the successor of 0xFFFFF...FFF */
51 }
52 
53 static enum sarray_comparison
r6_cmp(void * arg1,void * arg2)54 r6_cmp(void *arg1, void *arg2)
55 {
56 	struct in6_addr const *a1min = &((struct ipv6_range *) arg1)->min;
57 	struct in6_addr const *a2min = &((struct ipv6_range *) arg2)->min;
58 	struct in6_addr const *a1max = &((struct ipv6_range *) arg1)->max;
59 	struct in6_addr const *a2max = &((struct ipv6_range *) arg2)->max;
60 
61 	if (addr_equals(a1min, a2min) && addr_equals(a1max, a2max))
62 		return SACMP_EQUAL;
63 	if (addr_le(a1min, a2min) && addr_le(a2max, a1max))
64 		return SACMP_CHILD;
65 	if (addr_le(a2min, a1min) && addr_le(a1max, a2max))
66 		return SACMP_PARENT;
67 	if (addr_is_successor(a1max, a2min))
68 		return SACMP_ADJACENT_RIGHT;
69 	if (addr_lt(a1max, a2min))
70 		return SACMP_RIGHT;
71 	if (addr_is_successor(a2max, a1min))
72 		return SACMP_ADJACENT_LEFT;
73 	if (addr_lt(a2max, a1min))
74 		return SACMP_LEFT;
75 
76 	return SACMP_INTERSECTION;
77 }
78 
79 static void
ptor(struct ipv6_prefix const * p,struct ipv6_range * r)80 ptor(struct ipv6_prefix const *p, struct ipv6_range *r)
81 {
82 	r->min = p->addr;
83 	r->max = p->addr;
84 	ipv6_suffix_mask(p->len, &r->max);
85 }
86 
87 struct resources_ipv6 *
res6_create(void)88 res6_create(void)
89 {
90 	return (struct resources_ipv6 *)
91 	    sarray_create(sizeof(struct ipv6_range), r6_cmp);
92 }
93 
94 void
res6_get(struct resources_ipv6 * ips)95 res6_get(struct resources_ipv6 *ips)
96 {
97 	sarray_get((struct sorted_array *) ips);
98 }
99 
100 void
res6_put(struct resources_ipv6 * ips)101 res6_put(struct resources_ipv6 *ips)
102 {
103 	sarray_put((struct sorted_array *) ips);
104 }
105 
106 int
res6_add_prefix(struct resources_ipv6 * ips,struct ipv6_prefix * prefix)107 res6_add_prefix(struct resources_ipv6 *ips, struct ipv6_prefix *prefix)
108 {
109 	struct ipv6_range r;
110 	ptor(prefix, &r);
111 	return sarray_add((struct sorted_array *) ips, &r);
112 }
113 
114 int
res6_add_range(struct resources_ipv6 * ips,struct ipv6_range * range)115 res6_add_range(struct resources_ipv6 *ips, struct ipv6_range *range)
116 {
117 	return sarray_add((struct sorted_array *) ips, range);
118 }
119 
120 bool
res6_empty(struct resources_ipv6 * ips)121 res6_empty(struct resources_ipv6 *ips)
122 {
123 	return sarray_empty((struct sorted_array *) ips);
124 }
125 
126 bool
res6_contains_prefix(struct resources_ipv6 * ips,struct ipv6_prefix * prefix)127 res6_contains_prefix(struct resources_ipv6 *ips, struct ipv6_prefix *prefix)
128 {
129 	struct ipv6_range r;
130 	ptor(prefix, &r);
131 	return sarray_contains((struct sorted_array *) ips, &r);
132 }
133 
134 bool
res6_contains_range(struct resources_ipv6 * ips,struct ipv6_range * range)135 res6_contains_range(struct resources_ipv6 *ips, struct ipv6_range *range)
136 {
137 	return sarray_contains((struct sorted_array *) ips, range);
138 }
139