netlabel_addrlist.c revision 61e1068219950c672ce979719ad2be3aadb00d7d
161e1068219950c672ce979719ad2be3aadb00d7dPaul Moore/*
261e1068219950c672ce979719ad2be3aadb00d7dPaul Moore * NetLabel Network Address Lists
361e1068219950c672ce979719ad2be3aadb00d7dPaul Moore *
461e1068219950c672ce979719ad2be3aadb00d7dPaul Moore * This file contains network address list functions used to manage ordered
561e1068219950c672ce979719ad2be3aadb00d7dPaul Moore * lists of network addresses for use by the NetLabel subsystem.  The NetLabel
661e1068219950c672ce979719ad2be3aadb00d7dPaul Moore * system manages static and dynamic label mappings for network protocols such
761e1068219950c672ce979719ad2be3aadb00d7dPaul Moore * as CIPSO and RIPSO.
861e1068219950c672ce979719ad2be3aadb00d7dPaul Moore *
961e1068219950c672ce979719ad2be3aadb00d7dPaul Moore * Author: Paul Moore <paul.moore@hp.com>
1061e1068219950c672ce979719ad2be3aadb00d7dPaul Moore *
1161e1068219950c672ce979719ad2be3aadb00d7dPaul Moore */
1261e1068219950c672ce979719ad2be3aadb00d7dPaul Moore
1361e1068219950c672ce979719ad2be3aadb00d7dPaul Moore/*
1461e1068219950c672ce979719ad2be3aadb00d7dPaul Moore * (c) Copyright Hewlett-Packard Development Company, L.P., 2008
1561e1068219950c672ce979719ad2be3aadb00d7dPaul Moore *
1661e1068219950c672ce979719ad2be3aadb00d7dPaul Moore * This program is free software;  you can redistribute it and/or modify
1761e1068219950c672ce979719ad2be3aadb00d7dPaul Moore * it under the terms of the GNU General Public License as published by
1861e1068219950c672ce979719ad2be3aadb00d7dPaul Moore * the Free Software Foundation; either version 2 of the License, or
1961e1068219950c672ce979719ad2be3aadb00d7dPaul Moore * (at your option) any later version.
2061e1068219950c672ce979719ad2be3aadb00d7dPaul Moore *
2161e1068219950c672ce979719ad2be3aadb00d7dPaul Moore * This program is distributed in the hope that it will be useful,
2261e1068219950c672ce979719ad2be3aadb00d7dPaul Moore * but WITHOUT ANY WARRANTY;  without even the implied warranty of
2361e1068219950c672ce979719ad2be3aadb00d7dPaul Moore * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
2461e1068219950c672ce979719ad2be3aadb00d7dPaul Moore * the GNU General Public License for more details.
2561e1068219950c672ce979719ad2be3aadb00d7dPaul Moore *
2661e1068219950c672ce979719ad2be3aadb00d7dPaul Moore * You should have received a copy of the GNU General Public License
2761e1068219950c672ce979719ad2be3aadb00d7dPaul Moore * along with this program;  if not, write to the Free Software
2861e1068219950c672ce979719ad2be3aadb00d7dPaul Moore * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
2961e1068219950c672ce979719ad2be3aadb00d7dPaul Moore *
3061e1068219950c672ce979719ad2be3aadb00d7dPaul Moore */
3161e1068219950c672ce979719ad2be3aadb00d7dPaul Moore
3261e1068219950c672ce979719ad2be3aadb00d7dPaul Moore#include <linux/types.h>
3361e1068219950c672ce979719ad2be3aadb00d7dPaul Moore#include <linux/rcupdate.h>
3461e1068219950c672ce979719ad2be3aadb00d7dPaul Moore#include <linux/list.h>
3561e1068219950c672ce979719ad2be3aadb00d7dPaul Moore#include <linux/spinlock.h>
3661e1068219950c672ce979719ad2be3aadb00d7dPaul Moore#include <linux/in.h>
3761e1068219950c672ce979719ad2be3aadb00d7dPaul Moore#include <linux/in6.h>
3861e1068219950c672ce979719ad2be3aadb00d7dPaul Moore#include <linux/ip.h>
3961e1068219950c672ce979719ad2be3aadb00d7dPaul Moore#include <linux/ipv6.h>
4061e1068219950c672ce979719ad2be3aadb00d7dPaul Moore#include <net/ip.h>
4161e1068219950c672ce979719ad2be3aadb00d7dPaul Moore#include <net/ipv6.h>
4261e1068219950c672ce979719ad2be3aadb00d7dPaul Moore
4361e1068219950c672ce979719ad2be3aadb00d7dPaul Moore#include "netlabel_addrlist.h"
4461e1068219950c672ce979719ad2be3aadb00d7dPaul Moore
4561e1068219950c672ce979719ad2be3aadb00d7dPaul Moore/*
4661e1068219950c672ce979719ad2be3aadb00d7dPaul Moore * Address List Functions
4761e1068219950c672ce979719ad2be3aadb00d7dPaul Moore */
4861e1068219950c672ce979719ad2be3aadb00d7dPaul Moore
4961e1068219950c672ce979719ad2be3aadb00d7dPaul Moore/**
5061e1068219950c672ce979719ad2be3aadb00d7dPaul Moore * netlbl_af4list_search - Search for a matching IPv4 address entry
5161e1068219950c672ce979719ad2be3aadb00d7dPaul Moore * @addr: IPv4 address
5261e1068219950c672ce979719ad2be3aadb00d7dPaul Moore * @head: the list head
5361e1068219950c672ce979719ad2be3aadb00d7dPaul Moore *
5461e1068219950c672ce979719ad2be3aadb00d7dPaul Moore * Description:
5561e1068219950c672ce979719ad2be3aadb00d7dPaul Moore * Searches the IPv4 address list given by @head.  If a matching address entry
5661e1068219950c672ce979719ad2be3aadb00d7dPaul Moore * is found it is returned, otherwise NULL is returned.  The caller is
5761e1068219950c672ce979719ad2be3aadb00d7dPaul Moore * responsible for calling the rcu_read_[un]lock() functions.
5861e1068219950c672ce979719ad2be3aadb00d7dPaul Moore *
5961e1068219950c672ce979719ad2be3aadb00d7dPaul Moore */
6061e1068219950c672ce979719ad2be3aadb00d7dPaul Moorestruct netlbl_af4list *netlbl_af4list_search(__be32 addr,
6161e1068219950c672ce979719ad2be3aadb00d7dPaul Moore					     struct list_head *head)
6261e1068219950c672ce979719ad2be3aadb00d7dPaul Moore{
6361e1068219950c672ce979719ad2be3aadb00d7dPaul Moore	struct netlbl_af4list *iter;
6461e1068219950c672ce979719ad2be3aadb00d7dPaul Moore
6561e1068219950c672ce979719ad2be3aadb00d7dPaul Moore	list_for_each_entry_rcu(iter, head, list)
6661e1068219950c672ce979719ad2be3aadb00d7dPaul Moore		if (iter->valid && (addr & iter->mask) == iter->addr)
6761e1068219950c672ce979719ad2be3aadb00d7dPaul Moore			return iter;
6861e1068219950c672ce979719ad2be3aadb00d7dPaul Moore
6961e1068219950c672ce979719ad2be3aadb00d7dPaul Moore	return NULL;
7061e1068219950c672ce979719ad2be3aadb00d7dPaul Moore}
7161e1068219950c672ce979719ad2be3aadb00d7dPaul Moore
7261e1068219950c672ce979719ad2be3aadb00d7dPaul Moore#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
7361e1068219950c672ce979719ad2be3aadb00d7dPaul Moore/**
7461e1068219950c672ce979719ad2be3aadb00d7dPaul Moore * netlbl_af6list_search - Search for a matching IPv6 address entry
7561e1068219950c672ce979719ad2be3aadb00d7dPaul Moore * @addr: IPv6 address
7661e1068219950c672ce979719ad2be3aadb00d7dPaul Moore * @head: the list head
7761e1068219950c672ce979719ad2be3aadb00d7dPaul Moore *
7861e1068219950c672ce979719ad2be3aadb00d7dPaul Moore * Description:
7961e1068219950c672ce979719ad2be3aadb00d7dPaul Moore * Searches the IPv6 address list given by @head.  If a matching address entry
8061e1068219950c672ce979719ad2be3aadb00d7dPaul Moore * is found it is returned, otherwise NULL is returned.  The caller is
8161e1068219950c672ce979719ad2be3aadb00d7dPaul Moore * responsible for calling the rcu_read_[un]lock() functions.
8261e1068219950c672ce979719ad2be3aadb00d7dPaul Moore *
8361e1068219950c672ce979719ad2be3aadb00d7dPaul Moore */
8461e1068219950c672ce979719ad2be3aadb00d7dPaul Moorestruct netlbl_af6list *netlbl_af6list_search(const struct in6_addr *addr,
8561e1068219950c672ce979719ad2be3aadb00d7dPaul Moore					     struct list_head *head)
8661e1068219950c672ce979719ad2be3aadb00d7dPaul Moore{
8761e1068219950c672ce979719ad2be3aadb00d7dPaul Moore	struct netlbl_af6list *iter;
8861e1068219950c672ce979719ad2be3aadb00d7dPaul Moore
8961e1068219950c672ce979719ad2be3aadb00d7dPaul Moore	list_for_each_entry_rcu(iter, head, list)
9061e1068219950c672ce979719ad2be3aadb00d7dPaul Moore		if (iter->valid &&
9161e1068219950c672ce979719ad2be3aadb00d7dPaul Moore		    ipv6_masked_addr_cmp(&iter->addr, &iter->mask, addr) == 0)
9261e1068219950c672ce979719ad2be3aadb00d7dPaul Moore			return iter;
9361e1068219950c672ce979719ad2be3aadb00d7dPaul Moore
9461e1068219950c672ce979719ad2be3aadb00d7dPaul Moore	return NULL;
9561e1068219950c672ce979719ad2be3aadb00d7dPaul Moore}
9661e1068219950c672ce979719ad2be3aadb00d7dPaul Moore#endif /* IPv6 */
9761e1068219950c672ce979719ad2be3aadb00d7dPaul Moore
9861e1068219950c672ce979719ad2be3aadb00d7dPaul Moore/**
9961e1068219950c672ce979719ad2be3aadb00d7dPaul Moore * netlbl_af4list_add - Add a new IPv4 address entry to a list
10061e1068219950c672ce979719ad2be3aadb00d7dPaul Moore * @entry: address entry
10161e1068219950c672ce979719ad2be3aadb00d7dPaul Moore * @head: the list head
10261e1068219950c672ce979719ad2be3aadb00d7dPaul Moore *
10361e1068219950c672ce979719ad2be3aadb00d7dPaul Moore * Description:
10461e1068219950c672ce979719ad2be3aadb00d7dPaul Moore * Add a new address entry to the list pointed to by @head.  On success zero is
10561e1068219950c672ce979719ad2be3aadb00d7dPaul Moore * returned, otherwise a negative value is returned.  The caller is responsible
10661e1068219950c672ce979719ad2be3aadb00d7dPaul Moore * for calling the necessary locking functions.
10761e1068219950c672ce979719ad2be3aadb00d7dPaul Moore *
10861e1068219950c672ce979719ad2be3aadb00d7dPaul Moore */
10961e1068219950c672ce979719ad2be3aadb00d7dPaul Mooreint netlbl_af4list_add(struct netlbl_af4list *entry, struct list_head *head)
11061e1068219950c672ce979719ad2be3aadb00d7dPaul Moore{
11161e1068219950c672ce979719ad2be3aadb00d7dPaul Moore	struct netlbl_af4list *iter;
11261e1068219950c672ce979719ad2be3aadb00d7dPaul Moore
11361e1068219950c672ce979719ad2be3aadb00d7dPaul Moore	iter = netlbl_af4list_search(entry->addr, head);
11461e1068219950c672ce979719ad2be3aadb00d7dPaul Moore	if (iter != NULL &&
11561e1068219950c672ce979719ad2be3aadb00d7dPaul Moore	    iter->addr == entry->addr && iter->mask == entry->mask)
11661e1068219950c672ce979719ad2be3aadb00d7dPaul Moore		return -EEXIST;
11761e1068219950c672ce979719ad2be3aadb00d7dPaul Moore
11861e1068219950c672ce979719ad2be3aadb00d7dPaul Moore	/* in order to speed up address searches through the list (the common
11961e1068219950c672ce979719ad2be3aadb00d7dPaul Moore	 * case) we need to keep the list in order based on the size of the
12061e1068219950c672ce979719ad2be3aadb00d7dPaul Moore	 * address mask such that the entry with the widest mask (smallest
12161e1068219950c672ce979719ad2be3aadb00d7dPaul Moore	 * numerical value) appears first in the list */
12261e1068219950c672ce979719ad2be3aadb00d7dPaul Moore	list_for_each_entry_rcu(iter, head, list)
12361e1068219950c672ce979719ad2be3aadb00d7dPaul Moore		if (iter->valid &&
12461e1068219950c672ce979719ad2be3aadb00d7dPaul Moore		    ntohl(entry->mask) > ntohl(iter->mask)) {
12561e1068219950c672ce979719ad2be3aadb00d7dPaul Moore			__list_add_rcu(&entry->list,
12661e1068219950c672ce979719ad2be3aadb00d7dPaul Moore				       iter->list.prev,
12761e1068219950c672ce979719ad2be3aadb00d7dPaul Moore				       &iter->list);
12861e1068219950c672ce979719ad2be3aadb00d7dPaul Moore			return 0;
12961e1068219950c672ce979719ad2be3aadb00d7dPaul Moore		}
13061e1068219950c672ce979719ad2be3aadb00d7dPaul Moore	list_add_tail_rcu(&entry->list, head);
13161e1068219950c672ce979719ad2be3aadb00d7dPaul Moore	return 0;
13261e1068219950c672ce979719ad2be3aadb00d7dPaul Moore}
13361e1068219950c672ce979719ad2be3aadb00d7dPaul Moore
13461e1068219950c672ce979719ad2be3aadb00d7dPaul Moore#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
13561e1068219950c672ce979719ad2be3aadb00d7dPaul Moore/**
13661e1068219950c672ce979719ad2be3aadb00d7dPaul Moore * netlbl_af6list_add - Add a new IPv6 address entry to a list
13761e1068219950c672ce979719ad2be3aadb00d7dPaul Moore * @entry: address entry
13861e1068219950c672ce979719ad2be3aadb00d7dPaul Moore * @head: the list head
13961e1068219950c672ce979719ad2be3aadb00d7dPaul Moore *
14061e1068219950c672ce979719ad2be3aadb00d7dPaul Moore * Description:
14161e1068219950c672ce979719ad2be3aadb00d7dPaul Moore * Add a new address entry to the list pointed to by @head.  On success zero is
14261e1068219950c672ce979719ad2be3aadb00d7dPaul Moore * returned, otherwise a negative value is returned.  The caller is responsible
14361e1068219950c672ce979719ad2be3aadb00d7dPaul Moore * for calling the necessary locking functions.
14461e1068219950c672ce979719ad2be3aadb00d7dPaul Moore *
14561e1068219950c672ce979719ad2be3aadb00d7dPaul Moore */
14661e1068219950c672ce979719ad2be3aadb00d7dPaul Mooreint netlbl_af6list_add(struct netlbl_af6list *entry, struct list_head *head)
14761e1068219950c672ce979719ad2be3aadb00d7dPaul Moore{
14861e1068219950c672ce979719ad2be3aadb00d7dPaul Moore	struct netlbl_af6list *iter;
14961e1068219950c672ce979719ad2be3aadb00d7dPaul Moore
15061e1068219950c672ce979719ad2be3aadb00d7dPaul Moore	iter = netlbl_af6list_search(&entry->addr, head);
15161e1068219950c672ce979719ad2be3aadb00d7dPaul Moore	if (iter != NULL &&
15261e1068219950c672ce979719ad2be3aadb00d7dPaul Moore	    ipv6_addr_equal(&iter->addr, &entry->addr) &&
15361e1068219950c672ce979719ad2be3aadb00d7dPaul Moore	    ipv6_addr_equal(&iter->mask, &entry->mask))
15461e1068219950c672ce979719ad2be3aadb00d7dPaul Moore		return -EEXIST;
15561e1068219950c672ce979719ad2be3aadb00d7dPaul Moore
15661e1068219950c672ce979719ad2be3aadb00d7dPaul Moore	/* in order to speed up address searches through the list (the common
15761e1068219950c672ce979719ad2be3aadb00d7dPaul Moore	 * case) we need to keep the list in order based on the size of the
15861e1068219950c672ce979719ad2be3aadb00d7dPaul Moore	 * address mask such that the entry with the widest mask (smallest
15961e1068219950c672ce979719ad2be3aadb00d7dPaul Moore	 * numerical value) appears first in the list */
16061e1068219950c672ce979719ad2be3aadb00d7dPaul Moore	list_for_each_entry_rcu(iter, head, list)
16161e1068219950c672ce979719ad2be3aadb00d7dPaul Moore		if (iter->valid &&
16261e1068219950c672ce979719ad2be3aadb00d7dPaul Moore		    ipv6_addr_cmp(&entry->mask, &iter->mask) > 0) {
16361e1068219950c672ce979719ad2be3aadb00d7dPaul Moore			__list_add_rcu(&entry->list,
16461e1068219950c672ce979719ad2be3aadb00d7dPaul Moore				       iter->list.prev,
16561e1068219950c672ce979719ad2be3aadb00d7dPaul Moore				       &iter->list);
16661e1068219950c672ce979719ad2be3aadb00d7dPaul Moore			return 0;
16761e1068219950c672ce979719ad2be3aadb00d7dPaul Moore		}
16861e1068219950c672ce979719ad2be3aadb00d7dPaul Moore	list_add_tail_rcu(&entry->list, head);
16961e1068219950c672ce979719ad2be3aadb00d7dPaul Moore	return 0;
17061e1068219950c672ce979719ad2be3aadb00d7dPaul Moore}
17161e1068219950c672ce979719ad2be3aadb00d7dPaul Moore#endif /* IPv6 */
17261e1068219950c672ce979719ad2be3aadb00d7dPaul Moore
17361e1068219950c672ce979719ad2be3aadb00d7dPaul Moore/**
17461e1068219950c672ce979719ad2be3aadb00d7dPaul Moore * netlbl_af4list_remove_entry - Remove an IPv4 address entry
17561e1068219950c672ce979719ad2be3aadb00d7dPaul Moore * @entry: address entry
17661e1068219950c672ce979719ad2be3aadb00d7dPaul Moore *
17761e1068219950c672ce979719ad2be3aadb00d7dPaul Moore * Description:
17861e1068219950c672ce979719ad2be3aadb00d7dPaul Moore * Remove the specified IP address entry.  The caller is responsible for
17961e1068219950c672ce979719ad2be3aadb00d7dPaul Moore * calling the necessary locking functions.
18061e1068219950c672ce979719ad2be3aadb00d7dPaul Moore *
18161e1068219950c672ce979719ad2be3aadb00d7dPaul Moore */
18261e1068219950c672ce979719ad2be3aadb00d7dPaul Moorevoid netlbl_af4list_remove_entry(struct netlbl_af4list *entry)
18361e1068219950c672ce979719ad2be3aadb00d7dPaul Moore{
18461e1068219950c672ce979719ad2be3aadb00d7dPaul Moore	entry->valid = 0;
18561e1068219950c672ce979719ad2be3aadb00d7dPaul Moore	list_del_rcu(&entry->list);
18661e1068219950c672ce979719ad2be3aadb00d7dPaul Moore}
18761e1068219950c672ce979719ad2be3aadb00d7dPaul Moore
18861e1068219950c672ce979719ad2be3aadb00d7dPaul Moore/**
18961e1068219950c672ce979719ad2be3aadb00d7dPaul Moore * netlbl_af4list_remove - Remove an IPv4 address entry
19061e1068219950c672ce979719ad2be3aadb00d7dPaul Moore * @addr: IP address
19161e1068219950c672ce979719ad2be3aadb00d7dPaul Moore * @mask: IP address mask
19261e1068219950c672ce979719ad2be3aadb00d7dPaul Moore * @head: the list head
19361e1068219950c672ce979719ad2be3aadb00d7dPaul Moore *
19461e1068219950c672ce979719ad2be3aadb00d7dPaul Moore * Description:
19561e1068219950c672ce979719ad2be3aadb00d7dPaul Moore * Remove an IP address entry from the list pointed to by @head.  Returns the
19661e1068219950c672ce979719ad2be3aadb00d7dPaul Moore * entry on success, NULL on failure.  The caller is responsible for calling
19761e1068219950c672ce979719ad2be3aadb00d7dPaul Moore * the necessary locking functions.
19861e1068219950c672ce979719ad2be3aadb00d7dPaul Moore *
19961e1068219950c672ce979719ad2be3aadb00d7dPaul Moore */
20061e1068219950c672ce979719ad2be3aadb00d7dPaul Moorestruct netlbl_af4list *netlbl_af4list_remove(__be32 addr, __be32 mask,
20161e1068219950c672ce979719ad2be3aadb00d7dPaul Moore					     struct list_head *head)
20261e1068219950c672ce979719ad2be3aadb00d7dPaul Moore{
20361e1068219950c672ce979719ad2be3aadb00d7dPaul Moore	struct netlbl_af4list *entry;
20461e1068219950c672ce979719ad2be3aadb00d7dPaul Moore
20561e1068219950c672ce979719ad2be3aadb00d7dPaul Moore	entry = netlbl_af4list_search(addr, head);
20661e1068219950c672ce979719ad2be3aadb00d7dPaul Moore	if (entry != NULL && entry->addr == addr && entry->mask == mask) {
20761e1068219950c672ce979719ad2be3aadb00d7dPaul Moore		netlbl_af4list_remove_entry(entry);
20861e1068219950c672ce979719ad2be3aadb00d7dPaul Moore		return entry;
20961e1068219950c672ce979719ad2be3aadb00d7dPaul Moore	}
21061e1068219950c672ce979719ad2be3aadb00d7dPaul Moore
21161e1068219950c672ce979719ad2be3aadb00d7dPaul Moore	return NULL;
21261e1068219950c672ce979719ad2be3aadb00d7dPaul Moore}
21361e1068219950c672ce979719ad2be3aadb00d7dPaul Moore
21461e1068219950c672ce979719ad2be3aadb00d7dPaul Moore#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
21561e1068219950c672ce979719ad2be3aadb00d7dPaul Moore/**
21661e1068219950c672ce979719ad2be3aadb00d7dPaul Moore * netlbl_af6list_remove_entry - Remove an IPv6 address entry
21761e1068219950c672ce979719ad2be3aadb00d7dPaul Moore * @entry: address entry
21861e1068219950c672ce979719ad2be3aadb00d7dPaul Moore *
21961e1068219950c672ce979719ad2be3aadb00d7dPaul Moore * Description:
22061e1068219950c672ce979719ad2be3aadb00d7dPaul Moore * Remove the specified IP address entry.  The caller is responsible for
22161e1068219950c672ce979719ad2be3aadb00d7dPaul Moore * calling the necessary locking functions.
22261e1068219950c672ce979719ad2be3aadb00d7dPaul Moore *
22361e1068219950c672ce979719ad2be3aadb00d7dPaul Moore */
22461e1068219950c672ce979719ad2be3aadb00d7dPaul Moorevoid netlbl_af6list_remove_entry(struct netlbl_af6list *entry)
22561e1068219950c672ce979719ad2be3aadb00d7dPaul Moore{
22661e1068219950c672ce979719ad2be3aadb00d7dPaul Moore	entry->valid = 0;
22761e1068219950c672ce979719ad2be3aadb00d7dPaul Moore	list_del_rcu(&entry->list);
22861e1068219950c672ce979719ad2be3aadb00d7dPaul Moore}
22961e1068219950c672ce979719ad2be3aadb00d7dPaul Moore
23061e1068219950c672ce979719ad2be3aadb00d7dPaul Moore/**
23161e1068219950c672ce979719ad2be3aadb00d7dPaul Moore * netlbl_af6list_remove - Remove an IPv6 address entry
23261e1068219950c672ce979719ad2be3aadb00d7dPaul Moore * @addr: IP address
23361e1068219950c672ce979719ad2be3aadb00d7dPaul Moore * @mask: IP address mask
23461e1068219950c672ce979719ad2be3aadb00d7dPaul Moore * @head: the list head
23561e1068219950c672ce979719ad2be3aadb00d7dPaul Moore *
23661e1068219950c672ce979719ad2be3aadb00d7dPaul Moore * Description:
23761e1068219950c672ce979719ad2be3aadb00d7dPaul Moore * Remove an IP address entry from the list pointed to by @head.  Returns the
23861e1068219950c672ce979719ad2be3aadb00d7dPaul Moore * entry on success, NULL on failure.  The caller is responsible for calling
23961e1068219950c672ce979719ad2be3aadb00d7dPaul Moore * the necessary locking functions.
24061e1068219950c672ce979719ad2be3aadb00d7dPaul Moore *
24161e1068219950c672ce979719ad2be3aadb00d7dPaul Moore */
24261e1068219950c672ce979719ad2be3aadb00d7dPaul Moorestruct netlbl_af6list *netlbl_af6list_remove(const struct in6_addr *addr,
24361e1068219950c672ce979719ad2be3aadb00d7dPaul Moore					     const struct in6_addr *mask,
24461e1068219950c672ce979719ad2be3aadb00d7dPaul Moore					     struct list_head *head)
24561e1068219950c672ce979719ad2be3aadb00d7dPaul Moore{
24661e1068219950c672ce979719ad2be3aadb00d7dPaul Moore	struct netlbl_af6list *entry;
24761e1068219950c672ce979719ad2be3aadb00d7dPaul Moore
24861e1068219950c672ce979719ad2be3aadb00d7dPaul Moore	entry = netlbl_af6list_search(addr, head);
24961e1068219950c672ce979719ad2be3aadb00d7dPaul Moore	if (entry != NULL &&
25061e1068219950c672ce979719ad2be3aadb00d7dPaul Moore	    ipv6_addr_equal(&entry->addr, addr) &&
25161e1068219950c672ce979719ad2be3aadb00d7dPaul Moore	    ipv6_addr_equal(&entry->mask, mask)) {
25261e1068219950c672ce979719ad2be3aadb00d7dPaul Moore		netlbl_af6list_remove_entry(entry);
25361e1068219950c672ce979719ad2be3aadb00d7dPaul Moore		return entry;
25461e1068219950c672ce979719ad2be3aadb00d7dPaul Moore	}
25561e1068219950c672ce979719ad2be3aadb00d7dPaul Moore
25661e1068219950c672ce979719ad2be3aadb00d7dPaul Moore	return NULL;
25761e1068219950c672ce979719ad2be3aadb00d7dPaul Moore}
25861e1068219950c672ce979719ad2be3aadb00d7dPaul Moore#endif /* IPv6 */
259