aboutsummaryrefslogtreecommitdiffstats
path: root/net/netlabel/netlabel_unlabeled.c
diff options
context:
space:
mode:
authorPaul Moore <paul.moore@hp.com>2008-10-10 10:16:32 -0400
committerPaul Moore <paul.moore@hp.com>2008-10-10 10:16:32 -0400
commit61e1068219950c672ce979719ad2be3aadb00d7d (patch)
treeda987ee4b5be90f95ca8e0b20bd872ff75d82934 /net/netlabel/netlabel_unlabeled.c
parentb1edeb102397546438ab4624489c6ccd7b410d97 (diff)
netlabel: Add a generic way to create ordered linked lists of network addrs
Create an ordered IP address linked list mechanism similar to the core kernel's linked list construct. The idea behind this list functionality is to create an extensibile linked list ordered by IP address mask to ease the matching of network addresses. The linked list is ordered with larger address masks at the front of the list and shorter address masks at the end to facilitate overriding network entries with individual host or subnet entries. Signed-off-by: Paul Moore <paul.moore@hp.com> Reviewed-by: James Morris <jmorris@namei.org>
Diffstat (limited to 'net/netlabel/netlabel_unlabeled.c')
-rw-r--r--net/netlabel/netlabel_unlabeled.c350
1 files changed, 135 insertions, 215 deletions
diff --git a/net/netlabel/netlabel_unlabeled.c b/net/netlabel/netlabel_unlabeled.c
index cc105a10e3f8..ab8131a8e489 100644
--- a/net/netlabel/netlabel_unlabeled.c
+++ b/net/netlabel/netlabel_unlabeled.c
@@ -10,7 +10,7 @@
10 */ 10 */
11 11
12/* 12/*
13 * (c) Copyright Hewlett-Packard Development Company, L.P., 2006 - 2007 13 * (c) Copyright Hewlett-Packard Development Company, L.P., 2006 - 2008
14 * 14 *
15 * This program is free software; you can redistribute it and/or modify 15 * This program is free software; you can redistribute it and/or modify
16 * it under the terms of the GNU General Public License as published by 16 * it under the terms of the GNU General Public License as published by
@@ -54,6 +54,7 @@
54#include <asm/atomic.h> 54#include <asm/atomic.h>
55 55
56#include "netlabel_user.h" 56#include "netlabel_user.h"
57#include "netlabel_addrlist.h"
57#include "netlabel_domainhash.h" 58#include "netlabel_domainhash.h"
58#include "netlabel_unlabeled.h" 59#include "netlabel_unlabeled.h"
59#include "netlabel_mgmt.h" 60#include "netlabel_mgmt.h"
@@ -76,22 +77,20 @@ struct netlbl_unlhsh_tbl {
76 struct list_head *tbl; 77 struct list_head *tbl;
77 u32 size; 78 u32 size;
78}; 79};
80#define netlbl_unlhsh_addr4_entry(iter) \
81 container_of(iter, struct netlbl_unlhsh_addr4, list)
79struct netlbl_unlhsh_addr4 { 82struct netlbl_unlhsh_addr4 {
80 __be32 addr;
81 __be32 mask;
82 u32 secid; 83 u32 secid;
83 84
84 u32 valid; 85 struct netlbl_af4list list;
85 struct list_head list;
86 struct rcu_head rcu; 86 struct rcu_head rcu;
87}; 87};
88#define netlbl_unlhsh_addr6_entry(iter) \
89 container_of(iter, struct netlbl_unlhsh_addr6, list)
88struct netlbl_unlhsh_addr6 { 90struct netlbl_unlhsh_addr6 {
89 struct in6_addr addr;
90 struct in6_addr mask;
91 u32 secid; 91 u32 secid;
92 92
93 u32 valid; 93 struct netlbl_af6list list;
94 struct list_head list;
95 struct rcu_head rcu; 94 struct rcu_head rcu;
96}; 95};
97struct netlbl_unlhsh_iface { 96struct netlbl_unlhsh_iface {
@@ -274,26 +273,28 @@ static void netlbl_unlhsh_free_addr6(struct rcu_head *entry)
274static void netlbl_unlhsh_free_iface(struct rcu_head *entry) 273static void netlbl_unlhsh_free_iface(struct rcu_head *entry)
275{ 274{
276 struct netlbl_unlhsh_iface *iface; 275 struct netlbl_unlhsh_iface *iface;
277 struct netlbl_unlhsh_addr4 *iter4; 276 struct netlbl_af4list *iter4;
278 struct netlbl_unlhsh_addr4 *tmp4; 277 struct netlbl_af4list *tmp4;
279 struct netlbl_unlhsh_addr6 *iter6; 278#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
280 struct netlbl_unlhsh_addr6 *tmp6; 279 struct netlbl_af6list *iter6;
280 struct netlbl_af6list *tmp6;
281#endif /* IPv6 */
281 282
282 iface = container_of(entry, struct netlbl_unlhsh_iface, rcu); 283 iface = container_of(entry, struct netlbl_unlhsh_iface, rcu);
283 284
284 /* no need for locks here since we are the only one with access to this 285 /* no need for locks here since we are the only one with access to this
285 * structure */ 286 * structure */
286 287
287 list_for_each_entry_safe(iter4, tmp4, &iface->addr4_list, list) 288 netlbl_af4list_foreach_safe(iter4, tmp4, &iface->addr4_list) {
288 if (iter4->valid) { 289 netlbl_af4list_remove_entry(iter4);
289 list_del_rcu(&iter4->list); 290 kfree(netlbl_unlhsh_addr4_entry(iter4));
290 kfree(iter4); 291 }
291 } 292#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
292 list_for_each_entry_safe(iter6, tmp6, &iface->addr6_list, list) 293 netlbl_af6list_foreach_safe(iter6, tmp6, &iface->addr6_list) {
293 if (iter6->valid) { 294 netlbl_af6list_remove_entry(iter6);
294 list_del_rcu(&iter6->list); 295 kfree(netlbl_unlhsh_addr6_entry(iter6));
295 kfree(iter6); 296 }
296 } 297#endif /* IPv6 */
297 kfree(iface); 298 kfree(iface);
298} 299}
299 300
@@ -316,59 +317,6 @@ static u32 netlbl_unlhsh_hash(int ifindex)
316} 317}
317 318
318/** 319/**
319 * netlbl_unlhsh_search_addr4 - Search for a matching IPv4 address entry
320 * @addr: IPv4 address
321 * @iface: the network interface entry
322 *
323 * Description:
324 * Searches the IPv4 address list of the network interface specified by @iface.
325 * If a matching address entry is found it is returned, otherwise NULL is
326 * returned. The caller is responsible for calling the rcu_read_[un]lock()
327 * functions.
328 *
329 */
330static struct netlbl_unlhsh_addr4 *netlbl_unlhsh_search_addr4(
331 __be32 addr,
332 const struct netlbl_unlhsh_iface *iface)
333{
334 struct netlbl_unlhsh_addr4 *iter;
335
336 list_for_each_entry_rcu(iter, &iface->addr4_list, list)
337 if (iter->valid && (addr & iter->mask) == iter->addr)
338 return iter;
339
340 return NULL;
341}
342
343#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
344/**
345 * netlbl_unlhsh_search_addr6 - Search for a matching IPv6 address entry
346 * @addr: IPv6 address
347 * @iface: the network interface entry
348 *
349 * Description:
350 * Searches the IPv6 address list of the network interface specified by @iface.
351 * If a matching address entry is found it is returned, otherwise NULL is
352 * returned. The caller is responsible for calling the rcu_read_[un]lock()
353 * functions.
354 *
355 */
356static struct netlbl_unlhsh_addr6 *netlbl_unlhsh_search_addr6(
357 const struct in6_addr *addr,
358 const struct netlbl_unlhsh_iface *iface)
359{
360 struct netlbl_unlhsh_addr6 *iter;
361
362 list_for_each_entry_rcu(iter, &iface->addr6_list, list)
363 if (iter->valid &&
364 ipv6_masked_addr_cmp(&iter->addr, &iter->mask, addr) == 0)
365 return iter;
366
367 return NULL;
368}
369#endif /* IPv6 */
370
371/**
372 * netlbl_unlhsh_search_iface - Search for a matching interface entry 320 * netlbl_unlhsh_search_iface - Search for a matching interface entry
373 * @ifindex: the network interface 321 * @ifindex: the network interface
374 * 322 *
@@ -439,43 +387,26 @@ static int netlbl_unlhsh_add_addr4(struct netlbl_unlhsh_iface *iface,
439 const struct in_addr *mask, 387 const struct in_addr *mask,
440 u32 secid) 388 u32 secid)
441{ 389{
390 int ret_val;
442 struct netlbl_unlhsh_addr4 *entry; 391 struct netlbl_unlhsh_addr4 *entry;
443 struct netlbl_unlhsh_addr4 *iter;
444 392
445 entry = kzalloc(sizeof(*entry), GFP_ATOMIC); 393 entry = kzalloc(sizeof(*entry), GFP_ATOMIC);
446 if (entry == NULL) 394 if (entry == NULL)
447 return -ENOMEM; 395 return -ENOMEM;
448 396
449 entry->addr = addr->s_addr & mask->s_addr; 397 entry->list.addr = addr->s_addr & mask->s_addr;
450 entry->mask = mask->s_addr; 398 entry->list.mask = mask->s_addr;
451 entry->secid = secid; 399 entry->list.valid = 1;
452 entry->valid = 1;
453 INIT_RCU_HEAD(&entry->rcu); 400 INIT_RCU_HEAD(&entry->rcu);
401 entry->secid = secid;
454 402
455 spin_lock(&netlbl_unlhsh_lock); 403 spin_lock(&netlbl_unlhsh_lock);
456 iter = netlbl_unlhsh_search_addr4(entry->addr, iface); 404 ret_val = netlbl_af4list_add(&entry->list, &iface->addr4_list);
457 if (iter != NULL &&
458 iter->addr == addr->s_addr && iter->mask == mask->s_addr) {
459 spin_unlock(&netlbl_unlhsh_lock);
460 kfree(entry);
461 return -EEXIST;
462 }
463 /* in order to speed up address searches through the list (the common
464 * case) we need to keep the list in order based on the size of the
465 * address mask such that the entry with the widest mask (smallest
466 * numerical value) appears first in the list */
467 list_for_each_entry_rcu(iter, &iface->addr4_list, list)
468 if (iter->valid &&
469 ntohl(entry->mask) > ntohl(iter->mask)) {
470 __list_add_rcu(&entry->list,
471 iter->list.prev,
472 &iter->list);
473 spin_unlock(&netlbl_unlhsh_lock);
474 return 0;
475 }
476 list_add_tail_rcu(&entry->list, &iface->addr4_list);
477 spin_unlock(&netlbl_unlhsh_lock); 405 spin_unlock(&netlbl_unlhsh_lock);
478 return 0; 406
407 if (ret_val != 0)
408 kfree(entry);
409 return ret_val;
479} 410}
480 411
481#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) 412#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
@@ -498,47 +429,29 @@ static int netlbl_unlhsh_add_addr6(struct netlbl_unlhsh_iface *iface,
498 const struct in6_addr *mask, 429 const struct in6_addr *mask,
499 u32 secid) 430 u32 secid)
500{ 431{
432 int ret_val;
501 struct netlbl_unlhsh_addr6 *entry; 433 struct netlbl_unlhsh_addr6 *entry;
502 struct netlbl_unlhsh_addr6 *iter;
503 434
504 entry = kzalloc(sizeof(*entry), GFP_ATOMIC); 435 entry = kzalloc(sizeof(*entry), GFP_ATOMIC);
505 if (entry == NULL) 436 if (entry == NULL)
506 return -ENOMEM; 437 return -ENOMEM;
507 438
508 ipv6_addr_copy(&entry->addr, addr); 439 ipv6_addr_copy(&entry->list.addr, addr);
509 entry->addr.s6_addr32[0] &= mask->s6_addr32[0]; 440 entry->list.addr.s6_addr32[0] &= mask->s6_addr32[0];
510 entry->addr.s6_addr32[1] &= mask->s6_addr32[1]; 441 entry->list.addr.s6_addr32[1] &= mask->s6_addr32[1];
511 entry->addr.s6_addr32[2] &= mask->s6_addr32[2]; 442 entry->list.addr.s6_addr32[2] &= mask->s6_addr32[2];
512 entry->addr.s6_addr32[3] &= mask->s6_addr32[3]; 443 entry->list.addr.s6_addr32[3] &= mask->s6_addr32[3];
513 ipv6_addr_copy(&entry->mask, mask); 444 ipv6_addr_copy(&entry->list.mask, mask);
514 entry->secid = secid; 445 entry->list.valid = 1;
515 entry->valid = 1;
516 INIT_RCU_HEAD(&entry->rcu); 446 INIT_RCU_HEAD(&entry->rcu);
447 entry->secid = secid;
517 448
518 spin_lock(&netlbl_unlhsh_lock); 449 spin_lock(&netlbl_unlhsh_lock);
519 iter = netlbl_unlhsh_search_addr6(&entry->addr, iface); 450 ret_val = netlbl_af6list_add(&entry->list, &iface->addr6_list);
520 if (iter != NULL &&
521 (ipv6_addr_equal(&iter->addr, addr) &&
522 ipv6_addr_equal(&iter->mask, mask))) {
523 spin_unlock(&netlbl_unlhsh_lock);
524 kfree(entry);
525 return -EEXIST;
526 }
527 /* in order to speed up address searches through the list (the common
528 * case) we need to keep the list in order based on the size of the
529 * address mask such that the entry with the widest mask (smallest
530 * numerical value) appears first in the list */
531 list_for_each_entry_rcu(iter, &iface->addr6_list, list)
532 if (iter->valid &&
533 ipv6_addr_cmp(&entry->mask, &iter->mask) > 0) {
534 __list_add_rcu(&entry->list,
535 iter->list.prev,
536 &iter->list);
537 spin_unlock(&netlbl_unlhsh_lock);
538 return 0;
539 }
540 list_add_tail_rcu(&entry->list, &iface->addr6_list);
541 spin_unlock(&netlbl_unlhsh_lock); 451 spin_unlock(&netlbl_unlhsh_lock);
452
453 if (ret_val != 0)
454 kfree(entry);
542 return 0; 455 return 0;
543} 456}
544#endif /* IPv6 */ 457#endif /* IPv6 */
@@ -719,22 +632,21 @@ static int netlbl_unlhsh_remove_addr4(struct net *net,
719 const struct in_addr *mask, 632 const struct in_addr *mask,
720 struct netlbl_audit *audit_info) 633 struct netlbl_audit *audit_info)
721{ 634{
722 int ret_val = -ENOENT; 635 int ret_val = 0;
636 struct netlbl_af4list *list_entry;
723 struct netlbl_unlhsh_addr4 *entry; 637 struct netlbl_unlhsh_addr4 *entry;
724 struct audit_buffer *audit_buf = NULL; 638 struct audit_buffer *audit_buf;
725 struct net_device *dev; 639 struct net_device *dev;
726 char *secctx = NULL; 640 char *secctx;
727 u32 secctx_len; 641 u32 secctx_len;
728 642
729 spin_lock(&netlbl_unlhsh_lock); 643 spin_lock(&netlbl_unlhsh_lock);
730 entry = netlbl_unlhsh_search_addr4(addr->s_addr, iface); 644 list_entry = netlbl_af4list_remove(addr->s_addr, mask->s_addr,
731 if (entry != NULL && 645 &iface->addr4_list);
732 entry->addr == addr->s_addr && entry->mask == mask->s_addr) {
733 entry->valid = 0;
734 list_del_rcu(&entry->list);
735 ret_val = 0;
736 }
737 spin_unlock(&netlbl_unlhsh_lock); 646 spin_unlock(&netlbl_unlhsh_lock);
647 if (list_entry == NULL)
648 ret_val = -ENOENT;
649 entry = netlbl_unlhsh_addr4_entry(list_entry);
738 650
739 audit_buf = netlbl_audit_start_common(AUDIT_MAC_UNLBL_STCDEL, 651 audit_buf = netlbl_audit_start_common(AUDIT_MAC_UNLBL_STCDEL,
740 audit_info); 652 audit_info);
@@ -742,12 +654,12 @@ static int netlbl_unlhsh_remove_addr4(struct net *net,
742 dev = dev_get_by_index(net, iface->ifindex); 654 dev = dev_get_by_index(net, iface->ifindex);
743 netlbl_unlabel_audit_addr4(audit_buf, 655 netlbl_unlabel_audit_addr4(audit_buf,
744 (dev != NULL ? dev->name : NULL), 656 (dev != NULL ? dev->name : NULL),
745 entry->addr, entry->mask); 657 addr->s_addr, mask->s_addr);
746 if (dev != NULL) 658 if (dev != NULL)
747 dev_put(dev); 659 dev_put(dev);
748 if (security_secid_to_secctx(entry->secid, 660 if (entry && security_secid_to_secctx(entry->secid,
749 &secctx, 661 &secctx,
750 &secctx_len) == 0) { 662 &secctx_len) == 0) {
751 audit_log_format(audit_buf, " sec_obj=%s", secctx); 663 audit_log_format(audit_buf, " sec_obj=%s", secctx);
752 security_release_secctx(secctx, secctx_len); 664 security_release_secctx(secctx, secctx_len);
753 } 665 }
@@ -781,23 +693,20 @@ static int netlbl_unlhsh_remove_addr6(struct net *net,
781 const struct in6_addr *mask, 693 const struct in6_addr *mask,
782 struct netlbl_audit *audit_info) 694 struct netlbl_audit *audit_info)
783{ 695{
784 int ret_val = -ENOENT; 696 int ret_val = 0;
697 struct netlbl_af6list *list_entry;
785 struct netlbl_unlhsh_addr6 *entry; 698 struct netlbl_unlhsh_addr6 *entry;
786 struct audit_buffer *audit_buf = NULL; 699 struct audit_buffer *audit_buf;
787 struct net_device *dev; 700 struct net_device *dev;
788 char *secctx = NULL; 701 char *secctx;
789 u32 secctx_len; 702 u32 secctx_len;
790 703
791 spin_lock(&netlbl_unlhsh_lock); 704 spin_lock(&netlbl_unlhsh_lock);
792 entry = netlbl_unlhsh_search_addr6(addr, iface); 705 list_entry = netlbl_af6list_remove(addr, mask, &iface->addr6_list);
793 if (entry != NULL &&
794 (ipv6_addr_equal(&entry->addr, addr) &&
795 ipv6_addr_equal(&entry->mask, mask))) {
796 entry->valid = 0;
797 list_del_rcu(&entry->list);
798 ret_val = 0;
799 }
800 spin_unlock(&netlbl_unlhsh_lock); 706 spin_unlock(&netlbl_unlhsh_lock);
707 if (list_entry == NULL)
708 ret_val = -ENOENT;
709 entry = netlbl_unlhsh_addr6_entry(list_entry);
801 710
802 audit_buf = netlbl_audit_start_common(AUDIT_MAC_UNLBL_STCDEL, 711 audit_buf = netlbl_audit_start_common(AUDIT_MAC_UNLBL_STCDEL,
803 audit_info); 712 audit_info);
@@ -808,9 +717,9 @@ static int netlbl_unlhsh_remove_addr6(struct net *net,
808 addr, mask); 717 addr, mask);
809 if (dev != NULL) 718 if (dev != NULL)
810 dev_put(dev); 719 dev_put(dev);
811 if (security_secid_to_secctx(entry->secid, 720 if (entry && security_secid_to_secctx(entry->secid,
812 &secctx, 721 &secctx,
813 &secctx_len) == 0) { 722 &secctx_len) == 0) {
814 audit_log_format(audit_buf, " sec_obj=%s", secctx); 723 audit_log_format(audit_buf, " sec_obj=%s", secctx);
815 security_release_secctx(secctx, secctx_len); 724 security_release_secctx(secctx, secctx_len);
816 } 725 }
@@ -836,16 +745,18 @@ static int netlbl_unlhsh_remove_addr6(struct net *net,
836 */ 745 */
837static void netlbl_unlhsh_condremove_iface(struct netlbl_unlhsh_iface *iface) 746static void netlbl_unlhsh_condremove_iface(struct netlbl_unlhsh_iface *iface)
838{ 747{
839 struct netlbl_unlhsh_addr4 *iter4; 748 struct netlbl_af4list *iter4;
840 struct netlbl_unlhsh_addr6 *iter6; 749#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
750 struct netlbl_af6list *iter6;
751#endif /* IPv6 */
841 752
842 spin_lock(&netlbl_unlhsh_lock); 753 spin_lock(&netlbl_unlhsh_lock);
843 list_for_each_entry_rcu(iter4, &iface->addr4_list, list) 754 netlbl_af4list_foreach_rcu(iter4, &iface->addr4_list)
844 if (iter4->valid) 755 goto unlhsh_condremove_failure;
845 goto unlhsh_condremove_failure; 756#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
846 list_for_each_entry_rcu(iter6, &iface->addr6_list, list) 757 netlbl_af6list_foreach_rcu(iter6, &iface->addr6_list)
847 if (iter6->valid) 758 goto unlhsh_condremove_failure;
848 goto unlhsh_condremove_failure; 759#endif /* IPv6 */
849 iface->valid = 0; 760 iface->valid = 0;
850 if (iface->ifindex > 0) 761 if (iface->ifindex > 0)
851 list_del_rcu(&iface->list); 762 list_del_rcu(&iface->list);
@@ -1349,7 +1260,7 @@ static int netlbl_unlabel_staticlist_gen(u32 cmd,
1349 if (addr4) { 1260 if (addr4) {
1350 struct in_addr addr_struct; 1261 struct in_addr addr_struct;
1351 1262
1352 addr_struct.s_addr = addr4->addr; 1263 addr_struct.s_addr = addr4->list.addr;
1353 ret_val = nla_put(cb_arg->skb, 1264 ret_val = nla_put(cb_arg->skb,
1354 NLBL_UNLABEL_A_IPV4ADDR, 1265 NLBL_UNLABEL_A_IPV4ADDR,
1355 sizeof(struct in_addr), 1266 sizeof(struct in_addr),
@@ -1357,7 +1268,7 @@ static int netlbl_unlabel_staticlist_gen(u32 cmd,
1357 if (ret_val != 0) 1268 if (ret_val != 0)
1358 goto list_cb_failure; 1269 goto list_cb_failure;
1359 1270
1360 addr_struct.s_addr = addr4->mask; 1271 addr_struct.s_addr = addr4->list.mask;
1361 ret_val = nla_put(cb_arg->skb, 1272 ret_val = nla_put(cb_arg->skb,
1362 NLBL_UNLABEL_A_IPV4MASK, 1273 NLBL_UNLABEL_A_IPV4MASK,
1363 sizeof(struct in_addr), 1274 sizeof(struct in_addr),
@@ -1370,14 +1281,14 @@ static int netlbl_unlabel_staticlist_gen(u32 cmd,
1370 ret_val = nla_put(cb_arg->skb, 1281 ret_val = nla_put(cb_arg->skb,
1371 NLBL_UNLABEL_A_IPV6ADDR, 1282 NLBL_UNLABEL_A_IPV6ADDR,
1372 sizeof(struct in6_addr), 1283 sizeof(struct in6_addr),
1373 &addr6->addr); 1284 &addr6->list.addr);
1374 if (ret_val != 0) 1285 if (ret_val != 0)
1375 goto list_cb_failure; 1286 goto list_cb_failure;
1376 1287
1377 ret_val = nla_put(cb_arg->skb, 1288 ret_val = nla_put(cb_arg->skb,
1378 NLBL_UNLABEL_A_IPV6MASK, 1289 NLBL_UNLABEL_A_IPV6MASK,
1379 sizeof(struct in6_addr), 1290 sizeof(struct in6_addr),
1380 &addr6->mask); 1291 &addr6->list.mask);
1381 if (ret_val != 0) 1292 if (ret_val != 0)
1382 goto list_cb_failure; 1293 goto list_cb_failure;
1383 1294
@@ -1425,9 +1336,11 @@ static int netlbl_unlabel_staticlist(struct sk_buff *skb,
1425 u32 iter_bkt; 1336 u32 iter_bkt;
1426 u32 iter_chain = 0, iter_addr4 = 0, iter_addr6 = 0; 1337 u32 iter_chain = 0, iter_addr4 = 0, iter_addr6 = 0;
1427 struct netlbl_unlhsh_iface *iface; 1338 struct netlbl_unlhsh_iface *iface;
1428 struct netlbl_unlhsh_addr4 *addr4;
1429 struct netlbl_unlhsh_addr6 *addr6;
1430 struct list_head *iter_list; 1339 struct list_head *iter_list;
1340 struct netlbl_af4list *addr4;
1341#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
1342 struct netlbl_af6list *addr6;
1343#endif
1431 1344
1432 cb_arg.nl_cb = cb; 1345 cb_arg.nl_cb = cb;
1433 cb_arg.skb = skb; 1346 cb_arg.skb = skb;
@@ -1442,38 +1355,38 @@ static int netlbl_unlabel_staticlist(struct sk_buff *skb,
1442 if (!iface->valid || 1355 if (!iface->valid ||
1443 iter_chain++ < skip_chain) 1356 iter_chain++ < skip_chain)
1444 continue; 1357 continue;
1445 list_for_each_entry_rcu(addr4, 1358 netlbl_af4list_foreach_rcu(addr4,
1446 &iface->addr4_list, 1359 &iface->addr4_list) {
1447 list) { 1360 if (iter_addr4++ < skip_addr4)
1448 if (!addr4->valid || iter_addr4++ < skip_addr4)
1449 continue; 1361 continue;
1450 if (netlbl_unlabel_staticlist_gen( 1362 if (netlbl_unlabel_staticlist_gen(
1451 NLBL_UNLABEL_C_STATICLIST, 1363 NLBL_UNLABEL_C_STATICLIST,
1452 iface, 1364 iface,
1453 addr4, 1365 netlbl_unlhsh_addr4_entry(addr4),
1454 NULL, 1366 NULL,
1455 &cb_arg) < 0) { 1367 &cb_arg) < 0) {
1456 iter_addr4--; 1368 iter_addr4--;
1457 iter_chain--; 1369 iter_chain--;
1458 goto unlabel_staticlist_return; 1370 goto unlabel_staticlist_return;
1459 } 1371 }
1460 } 1372 }
1461 list_for_each_entry_rcu(addr6, 1373#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
1462 &iface->addr6_list, 1374 netlbl_af6list_foreach_rcu(addr6,
1463 list) { 1375 &iface->addr6_list) {
1464 if (!addr6->valid || iter_addr6++ < skip_addr6) 1376 if (iter_addr6++ < skip_addr6)
1465 continue; 1377 continue;
1466 if (netlbl_unlabel_staticlist_gen( 1378 if (netlbl_unlabel_staticlist_gen(
1467 NLBL_UNLABEL_C_STATICLIST, 1379 NLBL_UNLABEL_C_STATICLIST,
1468 iface, 1380 iface,
1469 NULL, 1381 NULL,
1470 addr6, 1382 netlbl_unlhsh_addr6_entry(addr6),
1471 &cb_arg) < 0) { 1383 &cb_arg) < 0) {
1472 iter_addr6--; 1384 iter_addr6--;
1473 iter_chain--; 1385 iter_chain--;
1474 goto unlabel_staticlist_return; 1386 goto unlabel_staticlist_return;
1475 } 1387 }
1476 } 1388 }
1389#endif /* IPv6 */
1477 } 1390 }
1478 } 1391 }
1479 1392
@@ -1504,9 +1417,12 @@ static int netlbl_unlabel_staticlistdef(struct sk_buff *skb,
1504 struct netlbl_unlhsh_iface *iface; 1417 struct netlbl_unlhsh_iface *iface;
1505 u32 skip_addr4 = cb->args[0]; 1418 u32 skip_addr4 = cb->args[0];
1506 u32 skip_addr6 = cb->args[1]; 1419 u32 skip_addr6 = cb->args[1];
1507 u32 iter_addr4 = 0, iter_addr6 = 0; 1420 u32 iter_addr4 = 0;
1508 struct netlbl_unlhsh_addr4 *addr4; 1421 struct netlbl_af4list *addr4;
1509 struct netlbl_unlhsh_addr6 *addr6; 1422#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
1423 u32 iter_addr6 = 0;
1424 struct netlbl_af6list *addr6;
1425#endif
1510 1426
1511 cb_arg.nl_cb = cb; 1427 cb_arg.nl_cb = cb;
1512 cb_arg.skb = skb; 1428 cb_arg.skb = skb;
@@ -1517,30 +1433,32 @@ static int netlbl_unlabel_staticlistdef(struct sk_buff *skb,
1517 if (iface == NULL || !iface->valid) 1433 if (iface == NULL || !iface->valid)
1518 goto unlabel_staticlistdef_return; 1434 goto unlabel_staticlistdef_return;
1519 1435
1520 list_for_each_entry_rcu(addr4, &iface->addr4_list, list) { 1436 netlbl_af4list_foreach_rcu(addr4, &iface->addr4_list) {
1521 if (!addr4->valid || iter_addr4++ < skip_addr4) 1437 if (iter_addr4++ < skip_addr4)
1522 continue; 1438 continue;
1523 if (netlbl_unlabel_staticlist_gen(NLBL_UNLABEL_C_STATICLISTDEF, 1439 if (netlbl_unlabel_staticlist_gen(NLBL_UNLABEL_C_STATICLISTDEF,
1524 iface, 1440 iface,
1525 addr4, 1441 netlbl_unlhsh_addr4_entry(addr4),
1526 NULL, 1442 NULL,
1527 &cb_arg) < 0) { 1443 &cb_arg) < 0) {
1528 iter_addr4--; 1444 iter_addr4--;
1529 goto unlabel_staticlistdef_return; 1445 goto unlabel_staticlistdef_return;
1530 } 1446 }
1531 } 1447 }
1532 list_for_each_entry_rcu(addr6, &iface->addr6_list, list) { 1448#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
1533 if (!addr6->valid || iter_addr6++ < skip_addr6) 1449 netlbl_af6list_foreach_rcu(addr6, &iface->addr6_list) {
1450 if (iter_addr6++ < skip_addr6)
1534 continue; 1451 continue;
1535 if (netlbl_unlabel_staticlist_gen(NLBL_UNLABEL_C_STATICLISTDEF, 1452 if (netlbl_unlabel_staticlist_gen(NLBL_UNLABEL_C_STATICLISTDEF,
1536 iface, 1453 iface,
1537 NULL, 1454 NULL,
1538 addr6, 1455 netlbl_unlhsh_addr6_entry(addr6),
1539 &cb_arg) < 0) { 1456 &cb_arg) < 0) {
1540 iter_addr6--; 1457 iter_addr6--;
1541 goto unlabel_staticlistdef_return; 1458 goto unlabel_staticlistdef_return;
1542 } 1459 }
1543 } 1460 }
1461#endif /* IPv6 */
1544 1462
1545unlabel_staticlistdef_return: 1463unlabel_staticlistdef_return:
1546 rcu_read_unlock(); 1464 rcu_read_unlock();
@@ -1718,25 +1636,27 @@ int netlbl_unlabel_getattr(const struct sk_buff *skb,
1718 switch (family) { 1636 switch (family) {
1719 case PF_INET: { 1637 case PF_INET: {
1720 struct iphdr *hdr4; 1638 struct iphdr *hdr4;
1721 struct netlbl_unlhsh_addr4 *addr4; 1639 struct netlbl_af4list *addr4;
1722 1640
1723 hdr4 = ip_hdr(skb); 1641 hdr4 = ip_hdr(skb);
1724 addr4 = netlbl_unlhsh_search_addr4(hdr4->saddr, iface); 1642 addr4 = netlbl_af4list_search(hdr4->saddr,
1643 &iface->addr4_list);
1725 if (addr4 == NULL) 1644 if (addr4 == NULL)
1726 goto unlabel_getattr_nolabel; 1645 goto unlabel_getattr_nolabel;
1727 secattr->attr.secid = addr4->secid; 1646 secattr->attr.secid = netlbl_unlhsh_addr4_entry(addr4)->secid;
1728 break; 1647 break;
1729 } 1648 }
1730#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) 1649#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
1731 case PF_INET6: { 1650 case PF_INET6: {
1732 struct ipv6hdr *hdr6; 1651 struct ipv6hdr *hdr6;
1733 struct netlbl_unlhsh_addr6 *addr6; 1652 struct netlbl_af6list *addr6;
1734 1653
1735 hdr6 = ipv6_hdr(skb); 1654 hdr6 = ipv6_hdr(skb);
1736 addr6 = netlbl_unlhsh_search_addr6(&hdr6->saddr, iface); 1655 addr6 = netlbl_af6list_search(&hdr6->saddr,
1656 &iface->addr6_list);
1737 if (addr6 == NULL) 1657 if (addr6 == NULL)
1738 goto unlabel_getattr_nolabel; 1658 goto unlabel_getattr_nolabel;
1739 secattr->attr.secid = addr6->secid; 1659 secattr->attr.secid = netlbl_unlhsh_addr6_entry(addr6)->secid;
1740 break; 1660 break;
1741 } 1661 }
1742#endif /* IPv6 */ 1662#endif /* IPv6 */