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