1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32#include <linux/types.h>
33#include <linux/rcupdate.h>
34#include <linux/list.h>
35#include <linux/spinlock.h>
36#include <linux/in.h>
37#include <linux/in6.h>
38#include <linux/ip.h>
39#include <linux/ipv6.h>
40#include <net/ip.h>
41#include <net/ipv6.h>
42#include <linux/audit.h>
43
44#include "netlabel_addrlist.h"
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61struct netlbl_af4list *netlbl_af4list_search(__be32 addr,
62 struct list_head *head)
63{
64 struct netlbl_af4list *iter;
65
66 list_for_each_entry_rcu(iter, head, list)
67 if (iter->valid && (addr & iter->mask) == iter->addr)
68 return iter;
69
70 return NULL;
71}
72
73
74
75
76
77
78
79
80
81
82
83
84
85struct netlbl_af4list *netlbl_af4list_search_exact(__be32 addr,
86 __be32 mask,
87 struct list_head *head)
88{
89 struct netlbl_af4list *iter;
90
91 list_for_each_entry_rcu(iter, head, list)
92 if (iter->valid && iter->addr == addr && iter->mask == mask)
93 return iter;
94
95 return NULL;
96}
97
98
99#if IS_ENABLED(CONFIG_IPV6)
100
101
102
103
104
105
106
107
108
109
110
111struct netlbl_af6list *netlbl_af6list_search(const struct in6_addr *addr,
112 struct list_head *head)
113{
114 struct netlbl_af6list *iter;
115
116 list_for_each_entry_rcu(iter, head, list)
117 if (iter->valid &&
118 ipv6_masked_addr_cmp(&iter->addr, &iter->mask, addr) == 0)
119 return iter;
120
121 return NULL;
122}
123
124
125
126
127
128
129
130
131
132
133
134
135
136struct netlbl_af6list *netlbl_af6list_search_exact(const struct in6_addr *addr,
137 const struct in6_addr *mask,
138 struct list_head *head)
139{
140 struct netlbl_af6list *iter;
141
142 list_for_each_entry_rcu(iter, head, list)
143 if (iter->valid &&
144 ipv6_addr_equal(&iter->addr, addr) &&
145 ipv6_addr_equal(&iter->mask, mask))
146 return iter;
147
148 return NULL;
149}
150#endif
151
152
153
154
155
156
157
158
159
160
161
162
163int netlbl_af4list_add(struct netlbl_af4list *entry, struct list_head *head)
164{
165 struct netlbl_af4list *iter;
166
167 iter = netlbl_af4list_search(entry->addr, head);
168 if (iter != NULL &&
169 iter->addr == entry->addr && iter->mask == entry->mask)
170 return -EEXIST;
171
172
173
174
175
176 list_for_each_entry_rcu(iter, head, list)
177 if (iter->valid &&
178 ntohl(entry->mask) > ntohl(iter->mask)) {
179 __list_add_rcu(&entry->list,
180 iter->list.prev,
181 &iter->list);
182 return 0;
183 }
184 list_add_tail_rcu(&entry->list, head);
185 return 0;
186}
187
188#if IS_ENABLED(CONFIG_IPV6)
189
190
191
192
193
194
195
196
197
198
199
200int netlbl_af6list_add(struct netlbl_af6list *entry, struct list_head *head)
201{
202 struct netlbl_af6list *iter;
203
204 iter = netlbl_af6list_search(&entry->addr, head);
205 if (iter != NULL &&
206 ipv6_addr_equal(&iter->addr, &entry->addr) &&
207 ipv6_addr_equal(&iter->mask, &entry->mask))
208 return -EEXIST;
209
210
211
212
213
214 list_for_each_entry_rcu(iter, head, list)
215 if (iter->valid &&
216 ipv6_addr_cmp(&entry->mask, &iter->mask) > 0) {
217 __list_add_rcu(&entry->list,
218 iter->list.prev,
219 &iter->list);
220 return 0;
221 }
222 list_add_tail_rcu(&entry->list, head);
223 return 0;
224}
225#endif
226
227
228
229
230
231
232
233
234
235
236void netlbl_af4list_remove_entry(struct netlbl_af4list *entry)
237{
238 entry->valid = 0;
239 list_del_rcu(&entry->list);
240}
241
242
243
244
245
246
247
248
249
250
251
252
253
254struct netlbl_af4list *netlbl_af4list_remove(__be32 addr, __be32 mask,
255 struct list_head *head)
256{
257 struct netlbl_af4list *entry;
258
259 entry = netlbl_af4list_search_exact(addr, mask, head);
260 if (entry == NULL)
261 return NULL;
262 netlbl_af4list_remove_entry(entry);
263 return entry;
264}
265
266#if IS_ENABLED(CONFIG_IPV6)
267
268
269
270
271
272
273
274
275
276void netlbl_af6list_remove_entry(struct netlbl_af6list *entry)
277{
278 entry->valid = 0;
279 list_del_rcu(&entry->list);
280}
281
282
283
284
285
286
287
288
289
290
291
292
293
294struct netlbl_af6list *netlbl_af6list_remove(const struct in6_addr *addr,
295 const struct in6_addr *mask,
296 struct list_head *head)
297{
298 struct netlbl_af6list *entry;
299
300 entry = netlbl_af6list_search_exact(addr, mask, head);
301 if (entry == NULL)
302 return NULL;
303 netlbl_af6list_remove_entry(entry);
304 return entry;
305}
306#endif
307
308
309
310
311
312#ifdef CONFIG_AUDIT
313
314
315
316
317
318
319
320
321
322
323
324
325void netlbl_af4list_audit_addr(struct audit_buffer *audit_buf,
326 int src, const char *dev,
327 __be32 addr, __be32 mask)
328{
329 u32 mask_val = ntohl(mask);
330 char *dir = (src ? "src" : "dst");
331
332 if (dev != NULL)
333 audit_log_format(audit_buf, " netif=%s", dev);
334 audit_log_format(audit_buf, " %s=%pI4", dir, &addr);
335 if (mask_val != 0xffffffff) {
336 u32 mask_len = 0;
337 while (mask_val > 0) {
338 mask_val <<= 1;
339 mask_len++;
340 }
341 audit_log_format(audit_buf, " %s_prefixlen=%d", dir, mask_len);
342 }
343}
344
345#if IS_ENABLED(CONFIG_IPV6)
346
347
348
349
350
351
352
353
354
355
356
357
358void netlbl_af6list_audit_addr(struct audit_buffer *audit_buf,
359 int src,
360 const char *dev,
361 const struct in6_addr *addr,
362 const struct in6_addr *mask)
363{
364 char *dir = (src ? "src" : "dst");
365
366 if (dev != NULL)
367 audit_log_format(audit_buf, " netif=%s", dev);
368 audit_log_format(audit_buf, " %s=%pI6", dir, addr);
369 if (ntohl(mask->s6_addr32[3]) != 0xffffffff) {
370 u32 mask_len = 0;
371 u32 mask_val;
372 int iter = -1;
373 while (ntohl(mask->s6_addr32[++iter]) == 0xffffffff)
374 mask_len += 32;
375 mask_val = ntohl(mask->s6_addr32[iter]);
376 while (mask_val > 0) {
377 mask_val <<= 1;
378 mask_len++;
379 }
380 audit_log_format(audit_buf, " %s_prefixlen=%d", dir, mask_len);
381 }
382}
383#endif
384#endif
385