1  /* SPDX-License-Identifier: GPL-2.0-or-later */
2  /*
3   * NetLabel Network Address Lists
4   *
5   * This file contains network address list functions used to manage ordered
6   * lists of network addresses for use by the NetLabel subsystem.  The NetLabel
7   * system manages static and dynamic label mappings for network protocols such
8   * as CIPSO and RIPSO.
9   *
10   * Author: Paul Moore <paul@paul-moore.com>
11   */
12  
13  /*
14   * (c) Copyright Hewlett-Packard Development Company, L.P., 2008
15   */
16  
17  #ifndef _NETLABEL_ADDRLIST_H
18  #define _NETLABEL_ADDRLIST_H
19  
20  #include <linux/types.h>
21  #include <linux/rcupdate.h>
22  #include <linux/list.h>
23  #include <linux/in6.h>
24  #include <linux/audit.h>
25  
26  /**
27   * struct netlbl_af4list - NetLabel IPv4 address list
28   * @addr: IPv4 address
29   * @mask: IPv4 address mask
30   * @valid: valid flag
31   * @list: list structure, used internally
32   */
33  struct netlbl_af4list {
34  	__be32 addr;
35  	__be32 mask;
36  
37  	u32 valid;
38  	struct list_head list;
39  };
40  
41  /**
42   * struct netlbl_af6list - NetLabel IPv6 address list
43   * @addr: IPv6 address
44   * @mask: IPv6 address mask
45   * @valid: valid flag
46   * @list: list structure, used internally
47   */
48  struct netlbl_af6list {
49  	struct in6_addr addr;
50  	struct in6_addr mask;
51  
52  	u32 valid;
53  	struct list_head list;
54  };
55  
56  #define __af4list_entry(ptr) container_of(ptr, struct netlbl_af4list, list)
57  
__af4list_valid(struct list_head * s,struct list_head * h)58  static inline struct netlbl_af4list *__af4list_valid(struct list_head *s,
59  						     struct list_head *h)
60  {
61  	struct list_head *i = s;
62  	struct netlbl_af4list *n = __af4list_entry(s);
63  	while (i != h && !n->valid) {
64  		i = i->next;
65  		n = __af4list_entry(i);
66  	}
67  	return n;
68  }
69  
__af4list_valid_rcu(struct list_head * s,struct list_head * h)70  static inline struct netlbl_af4list *__af4list_valid_rcu(struct list_head *s,
71  							 struct list_head *h)
72  {
73  	struct list_head *i = s;
74  	struct netlbl_af4list *n = __af4list_entry(s);
75  	while (i != h && !n->valid) {
76  		i = rcu_dereference(list_next_rcu(i));
77  		n = __af4list_entry(i);
78  	}
79  	return n;
80  }
81  
82  #define netlbl_af4list_foreach(iter, head)				\
83  	for (iter = __af4list_valid((head)->next, head);		\
84  	     &iter->list != (head);					\
85  	     iter = __af4list_valid(iter->list.next, head))
86  
87  #define netlbl_af4list_foreach_rcu(iter, head)				\
88  	for (iter = __af4list_valid_rcu((head)->next, head);		\
89  	     &iter->list != (head);					\
90  	     iter = __af4list_valid_rcu(iter->list.next, head))
91  
92  #define netlbl_af4list_foreach_safe(iter, tmp, head)			\
93  	for (iter = __af4list_valid((head)->next, head),		\
94  		     tmp = __af4list_valid(iter->list.next, head);	\
95  	     &iter->list != (head);					\
96  	     iter = tmp, tmp = __af4list_valid(iter->list.next, head))
97  
98  int netlbl_af4list_add(struct netlbl_af4list *entry,
99  		       struct list_head *head);
100  struct netlbl_af4list *netlbl_af4list_remove(__be32 addr, __be32 mask,
101  					     struct list_head *head);
102  void netlbl_af4list_remove_entry(struct netlbl_af4list *entry);
103  struct netlbl_af4list *netlbl_af4list_search(__be32 addr,
104  					     struct list_head *head);
105  struct netlbl_af4list *netlbl_af4list_search_exact(__be32 addr,
106  						   __be32 mask,
107  						   struct list_head *head);
108  
109  #ifdef CONFIG_AUDIT
110  void netlbl_af4list_audit_addr(struct audit_buffer *audit_buf,
111  			       int src, const char *dev,
112  			       __be32 addr, __be32 mask);
113  #else
netlbl_af4list_audit_addr(struct audit_buffer * audit_buf,int src,const char * dev,__be32 addr,__be32 mask)114  static inline void netlbl_af4list_audit_addr(struct audit_buffer *audit_buf,
115  					     int src, const char *dev,
116  					     __be32 addr, __be32 mask)
117  {
118  }
119  #endif
120  
121  #if IS_ENABLED(CONFIG_IPV6)
122  
123  #define __af6list_entry(ptr) container_of(ptr, struct netlbl_af6list, list)
124  
__af6list_valid(struct list_head * s,struct list_head * h)125  static inline struct netlbl_af6list *__af6list_valid(struct list_head *s,
126  						     struct list_head *h)
127  {
128  	struct list_head *i = s;
129  	struct netlbl_af6list *n = __af6list_entry(s);
130  	while (i != h && !n->valid) {
131  		i = i->next;
132  		n = __af6list_entry(i);
133  	}
134  	return n;
135  }
136  
__af6list_valid_rcu(struct list_head * s,struct list_head * h)137  static inline struct netlbl_af6list *__af6list_valid_rcu(struct list_head *s,
138  							 struct list_head *h)
139  {
140  	struct list_head *i = s;
141  	struct netlbl_af6list *n = __af6list_entry(s);
142  	while (i != h && !n->valid) {
143  		i = rcu_dereference(list_next_rcu(i));
144  		n = __af6list_entry(i);
145  	}
146  	return n;
147  }
148  
149  #define netlbl_af6list_foreach(iter, head)				\
150  	for (iter = __af6list_valid((head)->next, head);		\
151  	     &iter->list != (head);					\
152  	     iter = __af6list_valid(iter->list.next, head))
153  
154  #define netlbl_af6list_foreach_rcu(iter, head)				\
155  	for (iter = __af6list_valid_rcu((head)->next, head);		\
156  	     &iter->list != (head);					\
157  	     iter = __af6list_valid_rcu(iter->list.next, head))
158  
159  #define netlbl_af6list_foreach_safe(iter, tmp, head)			\
160  	for (iter = __af6list_valid((head)->next, head),		\
161  		     tmp = __af6list_valid(iter->list.next, head);	\
162  	     &iter->list != (head);					\
163  	     iter = tmp, tmp = __af6list_valid(iter->list.next, head))
164  
165  int netlbl_af6list_add(struct netlbl_af6list *entry,
166  		       struct list_head *head);
167  struct netlbl_af6list *netlbl_af6list_remove(const struct in6_addr *addr,
168  					     const struct in6_addr *mask,
169  					     struct list_head *head);
170  void netlbl_af6list_remove_entry(struct netlbl_af6list *entry);
171  struct netlbl_af6list *netlbl_af6list_search(const struct in6_addr *addr,
172  					     struct list_head *head);
173  struct netlbl_af6list *netlbl_af6list_search_exact(const struct in6_addr *addr,
174  						   const struct in6_addr *mask,
175  						   struct list_head *head);
176  
177  #ifdef CONFIG_AUDIT
178  void netlbl_af6list_audit_addr(struct audit_buffer *audit_buf,
179  			       int src,
180  			       const char *dev,
181  			       const struct in6_addr *addr,
182  			       const struct in6_addr *mask);
183  #else
netlbl_af6list_audit_addr(struct audit_buffer * audit_buf,int src,const char * dev,const struct in6_addr * addr,const struct in6_addr * mask)184  static inline void netlbl_af6list_audit_addr(struct audit_buffer *audit_buf,
185  					     int src,
186  					     const char *dev,
187  					     const struct in6_addr *addr,
188  					     const struct in6_addr *mask)
189  {
190  }
191  #endif
192  #endif /* IPV6 */
193  
194  #endif
195