netlabel_addrlist.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384
  1. /*
  2. * NetLabel Network Address Lists
  3. *
  4. * This file contains network address list functions used to manage ordered
  5. * lists of network addresses for use by the NetLabel subsystem. The NetLabel
  6. * system manages static and dynamic label mappings for network protocols such
  7. * as CIPSO and RIPSO.
  8. *
  9. * Author: Paul Moore <paul@paul-moore.com>
  10. *
  11. */
  12. /*
  13. * (c) Copyright Hewlett-Packard Development Company, L.P., 2008
  14. *
  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
  17. * the Free Software Foundation; either version 2 of the License, or
  18. * (at your option) any later version.
  19. *
  20. * This program is distributed in the hope that it will be useful,
  21. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  22. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
  23. * the GNU General Public License for more details.
  24. *
  25. * You should have received a copy of the GNU General Public License
  26. * along with this program; if not, see <http://www.gnu.org/licenses/>.
  27. *
  28. */
  29. #include <linux/types.h>
  30. #include <linux/rcupdate.h>
  31. #include <linux/list.h>
  32. #include <linux/spinlock.h>
  33. #include <linux/in.h>
  34. #include <linux/in6.h>
  35. #include <linux/ip.h>
  36. #include <linux/ipv6.h>
  37. #include <net/ip.h>
  38. #include <net/ipv6.h>
  39. #include <linux/audit.h>
  40. #include "netlabel_addrlist.h"
  41. /*
  42. * Address List Functions
  43. */
  44. /**
  45. * netlbl_af4list_search - Search for a matching IPv4 address entry
  46. * @addr: IPv4 address
  47. * @head: the list head
  48. *
  49. * Description:
  50. * Searches the IPv4 address list given by @head. If a matching address entry
  51. * is found it is returned, otherwise NULL is returned. The caller is
  52. * responsible for calling the rcu_read_[un]lock() functions.
  53. *
  54. */
  55. struct netlbl_af4list *netlbl_af4list_search(__be32 addr,
  56. struct list_head *head)
  57. {
  58. struct netlbl_af4list *iter;
  59. list_for_each_entry_rcu(iter, head, list)
  60. if (iter->valid && (addr & iter->mask) == iter->addr)
  61. return iter;
  62. return NULL;
  63. }
  64. /**
  65. * netlbl_af4list_search_exact - Search for an exact IPv4 address entry
  66. * @addr: IPv4 address
  67. * @mask: IPv4 address mask
  68. * @head: the list head
  69. *
  70. * Description:
  71. * Searches the IPv4 address list given by @head. If an exact match if found
  72. * it is returned, otherwise NULL is returned. The caller is responsible for
  73. * calling the rcu_read_[un]lock() functions.
  74. *
  75. */
  76. struct netlbl_af4list *netlbl_af4list_search_exact(__be32 addr,
  77. __be32 mask,
  78. struct list_head *head)
  79. {
  80. struct netlbl_af4list *iter;
  81. list_for_each_entry_rcu(iter, head, list)
  82. if (iter->valid && iter->addr == addr && iter->mask == mask)
  83. return iter;
  84. return NULL;
  85. }
  86. #if IS_ENABLED(CONFIG_IPV6)
  87. /**
  88. * netlbl_af6list_search - Search for a matching IPv6 address entry
  89. * @addr: IPv6 address
  90. * @head: the list head
  91. *
  92. * Description:
  93. * Searches the IPv6 address list given by @head. If a matching address entry
  94. * is found it is returned, otherwise NULL is returned. The caller is
  95. * responsible for calling the rcu_read_[un]lock() functions.
  96. *
  97. */
  98. struct netlbl_af6list *netlbl_af6list_search(const struct in6_addr *addr,
  99. struct list_head *head)
  100. {
  101. struct netlbl_af6list *iter;
  102. list_for_each_entry_rcu(iter, head, list)
  103. if (iter->valid &&
  104. ipv6_masked_addr_cmp(&iter->addr, &iter->mask, addr) == 0)
  105. return iter;
  106. return NULL;
  107. }
  108. /**
  109. * netlbl_af6list_search_exact - Search for an exact IPv6 address entry
  110. * @addr: IPv6 address
  111. * @mask: IPv6 address mask
  112. * @head: the list head
  113. *
  114. * Description:
  115. * Searches the IPv6 address list given by @head. If an exact match if found
  116. * it is returned, otherwise NULL is returned. The caller is responsible for
  117. * calling the rcu_read_[un]lock() functions.
  118. *
  119. */
  120. struct netlbl_af6list *netlbl_af6list_search_exact(const struct in6_addr *addr,
  121. const struct in6_addr *mask,
  122. struct list_head *head)
  123. {
  124. struct netlbl_af6list *iter;
  125. list_for_each_entry_rcu(iter, head, list)
  126. if (iter->valid &&
  127. ipv6_addr_equal(&iter->addr, addr) &&
  128. ipv6_addr_equal(&iter->mask, mask))
  129. return iter;
  130. return NULL;
  131. }
  132. #endif /* IPv6 */
  133. /**
  134. * netlbl_af4list_add - Add a new IPv4 address entry to a list
  135. * @entry: address entry
  136. * @head: the list head
  137. *
  138. * Description:
  139. * Add a new address entry to the list pointed to by @head. On success zero is
  140. * returned, otherwise a negative value is returned. The caller is responsible
  141. * for calling the necessary locking functions.
  142. *
  143. */
  144. int netlbl_af4list_add(struct netlbl_af4list *entry, struct list_head *head)
  145. {
  146. struct netlbl_af4list *iter;
  147. iter = netlbl_af4list_search(entry->addr, head);
  148. if (iter != NULL &&
  149. iter->addr == entry->addr && iter->mask == entry->mask)
  150. return -EEXIST;
  151. /* in order to speed up address searches through the list (the common
  152. * case) we need to keep the list in order based on the size of the
  153. * address mask such that the entry with the widest mask (smallest
  154. * numerical value) appears first in the list */
  155. list_for_each_entry_rcu(iter, head, list)
  156. if (iter->valid &&
  157. ntohl(entry->mask) > ntohl(iter->mask)) {
  158. __list_add_rcu(&entry->list,
  159. iter->list.prev,
  160. &iter->list);
  161. return 0;
  162. }
  163. list_add_tail_rcu(&entry->list, head);
  164. return 0;
  165. }
  166. #if IS_ENABLED(CONFIG_IPV6)
  167. /**
  168. * netlbl_af6list_add - Add a new IPv6 address entry to a list
  169. * @entry: address entry
  170. * @head: the list head
  171. *
  172. * Description:
  173. * Add a new address entry to the list pointed to by @head. On success zero is
  174. * returned, otherwise a negative value is returned. The caller is responsible
  175. * for calling the necessary locking functions.
  176. *
  177. */
  178. int netlbl_af6list_add(struct netlbl_af6list *entry, struct list_head *head)
  179. {
  180. struct netlbl_af6list *iter;
  181. iter = netlbl_af6list_search(&entry->addr, head);
  182. if (iter != NULL &&
  183. ipv6_addr_equal(&iter->addr, &entry->addr) &&
  184. ipv6_addr_equal(&iter->mask, &entry->mask))
  185. return -EEXIST;
  186. /* in order to speed up address searches through the list (the common
  187. * case) we need to keep the list in order based on the size of the
  188. * address mask such that the entry with the widest mask (smallest
  189. * numerical value) appears first in the list */
  190. list_for_each_entry_rcu(iter, head, list)
  191. if (iter->valid &&
  192. ipv6_addr_cmp(&entry->mask, &iter->mask) > 0) {
  193. __list_add_rcu(&entry->list,
  194. iter->list.prev,
  195. &iter->list);
  196. return 0;
  197. }
  198. list_add_tail_rcu(&entry->list, head);
  199. return 0;
  200. }
  201. #endif /* IPv6 */
  202. /**
  203. * netlbl_af4list_remove_entry - Remove an IPv4 address entry
  204. * @entry: address entry
  205. *
  206. * Description:
  207. * Remove the specified IP address entry. The caller is responsible for
  208. * calling the necessary locking functions.
  209. *
  210. */
  211. void netlbl_af4list_remove_entry(struct netlbl_af4list *entry)
  212. {
  213. entry->valid = 0;
  214. list_del_rcu(&entry->list);
  215. }
  216. /**
  217. * netlbl_af4list_remove - Remove an IPv4 address entry
  218. * @addr: IP address
  219. * @mask: IP address mask
  220. * @head: the list head
  221. *
  222. * Description:
  223. * Remove an IP address entry from the list pointed to by @head. Returns the
  224. * entry on success, NULL on failure. The caller is responsible for calling
  225. * the necessary locking functions.
  226. *
  227. */
  228. struct netlbl_af4list *netlbl_af4list_remove(__be32 addr, __be32 mask,
  229. struct list_head *head)
  230. {
  231. struct netlbl_af4list *entry;
  232. entry = netlbl_af4list_search_exact(addr, mask, head);
  233. if (entry == NULL)
  234. return NULL;
  235. netlbl_af4list_remove_entry(entry);
  236. return entry;
  237. }
  238. #if IS_ENABLED(CONFIG_IPV6)
  239. /**
  240. * netlbl_af6list_remove_entry - Remove an IPv6 address entry
  241. * @entry: address entry
  242. *
  243. * Description:
  244. * Remove the specified IP address entry. The caller is responsible for
  245. * calling the necessary locking functions.
  246. *
  247. */
  248. void netlbl_af6list_remove_entry(struct netlbl_af6list *entry)
  249. {
  250. entry->valid = 0;
  251. list_del_rcu(&entry->list);
  252. }
  253. /**
  254. * netlbl_af6list_remove - Remove an IPv6 address entry
  255. * @addr: IP address
  256. * @mask: IP address mask
  257. * @head: the list head
  258. *
  259. * Description:
  260. * Remove an IP address entry from the list pointed to by @head. Returns the
  261. * entry on success, NULL on failure. The caller is responsible for calling
  262. * the necessary locking functions.
  263. *
  264. */
  265. struct netlbl_af6list *netlbl_af6list_remove(const struct in6_addr *addr,
  266. const struct in6_addr *mask,
  267. struct list_head *head)
  268. {
  269. struct netlbl_af6list *entry;
  270. entry = netlbl_af6list_search_exact(addr, mask, head);
  271. if (entry == NULL)
  272. return NULL;
  273. netlbl_af6list_remove_entry(entry);
  274. return entry;
  275. }
  276. #endif /* IPv6 */
  277. /*
  278. * Audit Helper Functions
  279. */
  280. #ifdef CONFIG_AUDIT
  281. /**
  282. * netlbl_af4list_audit_addr - Audit an IPv4 address
  283. * @audit_buf: audit buffer
  284. * @src: true if source address, false if destination
  285. * @dev: network interface
  286. * @addr: IP address
  287. * @mask: IP address mask
  288. *
  289. * Description:
  290. * Write the IPv4 address and address mask, if necessary, to @audit_buf.
  291. *
  292. */
  293. void netlbl_af4list_audit_addr(struct audit_buffer *audit_buf,
  294. int src, const char *dev,
  295. __be32 addr, __be32 mask)
  296. {
  297. u32 mask_val = ntohl(mask);
  298. char *dir = (src ? "src" : "dst");
  299. if (dev != NULL)
  300. audit_log_format(audit_buf, " netif=%s", dev);
  301. audit_log_format(audit_buf, " %s=%pI4", dir, &addr);
  302. if (mask_val != 0xffffffff) {
  303. u32 mask_len = 0;
  304. while (mask_val > 0) {
  305. mask_val <<= 1;
  306. mask_len++;
  307. }
  308. audit_log_format(audit_buf, " %s_prefixlen=%d", dir, mask_len);
  309. }
  310. }
  311. #if IS_ENABLED(CONFIG_IPV6)
  312. /**
  313. * netlbl_af6list_audit_addr - Audit an IPv6 address
  314. * @audit_buf: audit buffer
  315. * @src: true if source address, false if destination
  316. * @dev: network interface
  317. * @addr: IP address
  318. * @mask: IP address mask
  319. *
  320. * Description:
  321. * Write the IPv6 address and address mask, if necessary, to @audit_buf.
  322. *
  323. */
  324. void netlbl_af6list_audit_addr(struct audit_buffer *audit_buf,
  325. int src,
  326. const char *dev,
  327. const struct in6_addr *addr,
  328. const struct in6_addr *mask)
  329. {
  330. char *dir = (src ? "src" : "dst");
  331. if (dev != NULL)
  332. audit_log_format(audit_buf, " netif=%s", dev);
  333. audit_log_format(audit_buf, " %s=%pI6", dir, addr);
  334. if (ntohl(mask->s6_addr32[3]) != 0xffffffff) {
  335. u32 mask_len = 0;
  336. u32 mask_val;
  337. int iter = -1;
  338. while (ntohl(mask->s6_addr32[++iter]) == 0xffffffff)
  339. mask_len += 32;
  340. mask_val = ntohl(mask->s6_addr32[iter]);
  341. while (mask_val > 0) {
  342. mask_val <<= 1;
  343. mask_len++;
  344. }
  345. audit_log_format(audit_buf, " %s_prefixlen=%d", dir, mask_len);
  346. }
  347. }
  348. #endif /* IPv6 */
  349. #endif /* CONFIG_AUDIT */