aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorJeff Garzik <jeff@garzik.org>2006-09-26 13:13:19 -0400
committerJeff Garzik <jeff@garzik.org>2006-09-26 13:13:19 -0400
commitc226951b93f7cd7c3a10b17384535b617bd43fd0 (patch)
tree07b8796a5c99fbbf587b8d0dbcbc173cfe5e381e /net
parentb0df3bd1e553e901ec7297267611a5db88240b38 (diff)
parente8216dee838c09776680a6f1a2e54d81f3cdfa14 (diff)
Merge branch 'master' into upstream
Diffstat (limited to 'net')
-rw-r--r--net/dccp/Kconfig16
-rw-r--r--net/dccp/Makefile2
-rw-r--r--net/dccp/ccids/ccid2.c2
-rw-r--r--net/dccp/ccids/ccid3.c2
-rw-r--r--net/dccp/ipv4.c3
-rw-r--r--net/dccp/probe.c198
-rw-r--r--net/dccp/proto.c11
-rw-r--r--net/ipv4/Kconfig53
-rw-r--r--net/ipv4/cipso_ipv4.c267
-rw-r--r--net/ipv4/sysctl_net_ipv4.c6
-rw-r--r--net/ipv4/tcp_cong.c2
-rw-r--r--net/netlabel/Kconfig5
-rw-r--r--net/netlabel/netlabel_cipso_v4.c628
-rw-r--r--net/netlabel/netlabel_cipso_v4.h225
-rw-r--r--net/netlabel/netlabel_domainhash.c183
-rw-r--r--net/netlabel/netlabel_domainhash.h6
-rw-r--r--net/netlabel/netlabel_kapi.c23
-rw-r--r--net/netlabel/netlabel_mgmt.c541
-rw-r--r--net/netlabel/netlabel_mgmt.h211
-rw-r--r--net/netlabel/netlabel_unlabeled.c79
-rw-r--r--net/netlabel/netlabel_unlabeled.h41
-rw-r--r--net/netlabel/netlabel_user.c82
-rw-r--r--net/netlabel/netlabel_user.h141
23 files changed, 1300 insertions, 1427 deletions
diff --git a/net/dccp/Kconfig b/net/dccp/Kconfig
index 859e3359fcda..e2a095d0fd80 100644
--- a/net/dccp/Kconfig
+++ b/net/dccp/Kconfig
@@ -40,6 +40,22 @@ config IP_DCCP_DEBUG
40 40
41 Just say N. 41 Just say N.
42 42
43config NET_DCCPPROBE
44 tristate "DCCP connection probing"
45 depends on PROC_FS && KPROBES
46 ---help---
47 This module allows for capturing the changes to DCCP connection
48 state in response to incoming packets. It is used for debugging
49 DCCP congestion avoidance modules. If you don't understand
50 what was just said, you don't need it: say N.
51
52 Documentation on how to use the packet generator can be found
53 at http://linux-net.osdl.org/index.php/DccpProbe
54
55 To compile this code as a module, choose M here: the
56 module will be called dccp_probe.
57
58
43endmenu 59endmenu
44 60
45endmenu 61endmenu
diff --git a/net/dccp/Makefile b/net/dccp/Makefile
index 7696e219b05d..17ed99c46617 100644
--- a/net/dccp/Makefile
+++ b/net/dccp/Makefile
@@ -11,9 +11,11 @@ dccp_ipv4-y := ipv4.o
11dccp-$(CONFIG_IP_DCCP_ACKVEC) += ackvec.o 11dccp-$(CONFIG_IP_DCCP_ACKVEC) += ackvec.o
12 12
13obj-$(CONFIG_INET_DCCP_DIAG) += dccp_diag.o 13obj-$(CONFIG_INET_DCCP_DIAG) += dccp_diag.o
14obj-$(CONFIG_NET_DCCPPROBE) += dccp_probe.o
14 15
15dccp-$(CONFIG_SYSCTL) += sysctl.o 16dccp-$(CONFIG_SYSCTL) += sysctl.o
16 17
17dccp_diag-y := diag.o 18dccp_diag-y := diag.o
19dccp_probe-y := probe.o
18 20
19obj-y += ccids/ 21obj-y += ccids/
diff --git a/net/dccp/ccids/ccid2.c b/net/dccp/ccids/ccid2.c
index 457dd3db7f41..2efb505aeb35 100644
--- a/net/dccp/ccids/ccid2.c
+++ b/net/dccp/ccids/ccid2.c
@@ -808,7 +808,7 @@ static void ccid2_hc_rx_packet_recv(struct sock *sk, struct sk_buff *skb)
808} 808}
809 809
810static struct ccid_operations ccid2 = { 810static struct ccid_operations ccid2 = {
811 .ccid_id = 2, 811 .ccid_id = DCCPC_CCID2,
812 .ccid_name = "ccid2", 812 .ccid_name = "ccid2",
813 .ccid_owner = THIS_MODULE, 813 .ccid_owner = THIS_MODULE,
814 .ccid_hc_tx_obj_size = sizeof(struct ccid2_hc_tx_sock), 814 .ccid_hc_tx_obj_size = sizeof(struct ccid2_hc_tx_sock),
diff --git a/net/dccp/ccids/ccid3.c b/net/dccp/ccids/ccid3.c
index 195aa9566228..67d2dc0e7c67 100644
--- a/net/dccp/ccids/ccid3.c
+++ b/net/dccp/ccids/ccid3.c
@@ -1240,7 +1240,7 @@ static int ccid3_hc_tx_getsockopt(struct sock *sk, const int optname, int len,
1240} 1240}
1241 1241
1242static struct ccid_operations ccid3 = { 1242static struct ccid_operations ccid3 = {
1243 .ccid_id = 3, 1243 .ccid_id = DCCPC_CCID3,
1244 .ccid_name = "ccid3", 1244 .ccid_name = "ccid3",
1245 .ccid_owner = THIS_MODULE, 1245 .ccid_owner = THIS_MODULE,
1246 .ccid_hc_tx_obj_size = sizeof(struct ccid3_hc_tx_sock), 1246 .ccid_hc_tx_obj_size = sizeof(struct ccid3_hc_tx_sock),
diff --git a/net/dccp/ipv4.c b/net/dccp/ipv4.c
index 9a1a76a7dc41..66be29b6f508 100644
--- a/net/dccp/ipv4.c
+++ b/net/dccp/ipv4.c
@@ -56,9 +56,6 @@ int dccp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
56 56
57 dp->dccps_role = DCCP_ROLE_CLIENT; 57 dp->dccps_role = DCCP_ROLE_CLIENT;
58 58
59 if (dccp_service_not_initialized(sk))
60 return -EPROTO;
61
62 if (addr_len < sizeof(struct sockaddr_in)) 59 if (addr_len < sizeof(struct sockaddr_in))
63 return -EINVAL; 60 return -EINVAL;
64 61
diff --git a/net/dccp/probe.c b/net/dccp/probe.c
new file mode 100644
index 000000000000..146496fce2e2
--- /dev/null
+++ b/net/dccp/probe.c
@@ -0,0 +1,198 @@
1/*
2 * dccp_probe - Observe the DCCP flow with kprobes.
3 *
4 * The idea for this came from Werner Almesberger's umlsim
5 * Copyright (C) 2004, Stephen Hemminger <shemminger@osdl.org>
6 *
7 * Modified for DCCP from Stephen Hemminger's code
8 * Copyright (C) 2006, Ian McDonald <ian.mcdonald@jandi.co.nz>
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 */
24
25#include <linux/kernel.h>
26#include <linux/kprobes.h>
27#include <linux/socket.h>
28#include <linux/dccp.h>
29#include <linux/proc_fs.h>
30#include <linux/module.h>
31#include <linux/kfifo.h>
32#include <linux/vmalloc.h>
33
34#include "dccp.h"
35#include "ccid.h"
36#include "ccids/ccid3.h"
37
38static int port;
39
40static int bufsize = 64 * 1024;
41
42static const char procname[] = "dccpprobe";
43
44struct {
45 struct kfifo *fifo;
46 spinlock_t lock;
47 wait_queue_head_t wait;
48 struct timeval tstart;
49} dccpw;
50
51static void printl(const char *fmt, ...)
52{
53 va_list args;
54 int len;
55 struct timeval now;
56 char tbuf[256];
57
58 va_start(args, fmt);
59 do_gettimeofday(&now);
60
61 now.tv_sec -= dccpw.tstart.tv_sec;
62 now.tv_usec -= dccpw.tstart.tv_usec;
63 if (now.tv_usec < 0) {
64 --now.tv_sec;
65 now.tv_usec += 1000000;
66 }
67
68 len = sprintf(tbuf, "%lu.%06lu ",
69 (unsigned long) now.tv_sec,
70 (unsigned long) now.tv_usec);
71 len += vscnprintf(tbuf+len, sizeof(tbuf)-len, fmt, args);
72 va_end(args);
73
74 kfifo_put(dccpw.fifo, tbuf, len);
75 wake_up(&dccpw.wait);
76}
77
78static int jdccp_sendmsg(struct kiocb *iocb, struct sock *sk,
79 struct msghdr *msg, size_t size)
80{
81 const struct dccp_minisock *dmsk = dccp_msk(sk);
82 const struct inet_sock *inet = inet_sk(sk);
83 const struct ccid3_hc_tx_sock *hctx;
84
85 if (dmsk->dccpms_tx_ccid == DCCPC_CCID3)
86 hctx = ccid3_hc_tx_sk(sk);
87 else
88 hctx = NULL;
89
90 if (port == 0 || ntohs(inet->dport) == port ||
91 ntohs(inet->sport) == port) {
92 if (hctx)
93 printl("%d.%d.%d.%d:%u %d.%d.%d.%d:%u %d %d %d %d %d\n",
94 NIPQUAD(inet->saddr), ntohs(inet->sport),
95 NIPQUAD(inet->daddr), ntohs(inet->dport), size,
96 hctx->ccid3hctx_s, hctx->ccid3hctx_rtt,
97 hctx->ccid3hctx_p, hctx->ccid3hctx_t_ipi);
98 else
99 printl("%d.%d.%d.%d:%u %d.%d.%d.%d:%u %d\n",
100 NIPQUAD(inet->saddr), ntohs(inet->sport),
101 NIPQUAD(inet->daddr), ntohs(inet->dport), size);
102 }
103
104 jprobe_return();
105 return 0;
106}
107
108static struct jprobe dccp_send_probe = {
109 .kp = { .addr = (kprobe_opcode_t *)&dccp_sendmsg, },
110 .entry = (kprobe_opcode_t *)&jdccp_sendmsg,
111};
112
113static int dccpprobe_open(struct inode *inode, struct file *file)
114{
115 kfifo_reset(dccpw.fifo);
116 do_gettimeofday(&dccpw.tstart);
117 return 0;
118}
119
120static ssize_t dccpprobe_read(struct file *file, char __user *buf,
121 size_t len, loff_t *ppos)
122{
123 int error = 0, cnt = 0;
124 unsigned char *tbuf;
125
126 if (!buf || len < 0)
127 return -EINVAL;
128
129 if (len == 0)
130 return 0;
131
132 tbuf = vmalloc(len);
133 if (!tbuf)
134 return -ENOMEM;
135
136 error = wait_event_interruptible(dccpw.wait,
137 __kfifo_len(dccpw.fifo) != 0);
138 if (error)
139 goto out_free;
140
141 cnt = kfifo_get(dccpw.fifo, tbuf, len);
142 error = copy_to_user(buf, tbuf, cnt);
143
144out_free:
145 vfree(tbuf);
146
147 return error ? error : cnt;
148}
149
150static struct file_operations dccpprobe_fops = {
151 .owner = THIS_MODULE,
152 .open = dccpprobe_open,
153 .read = dccpprobe_read,
154};
155
156static __init int dccpprobe_init(void)
157{
158 int ret = -ENOMEM;
159
160 init_waitqueue_head(&dccpw.wait);
161 spin_lock_init(&dccpw.lock);
162 dccpw.fifo = kfifo_alloc(bufsize, GFP_KERNEL, &dccpw.lock);
163
164 if (!proc_net_fops_create(procname, S_IRUSR, &dccpprobe_fops))
165 goto err0;
166
167 ret = register_jprobe(&dccp_send_probe);
168 if (ret)
169 goto err1;
170
171 pr_info("DCCP watch registered (port=%d)\n", port);
172 return 0;
173err1:
174 proc_net_remove(procname);
175err0:
176 kfifo_free(dccpw.fifo);
177 return ret;
178}
179module_init(dccpprobe_init);
180
181static __exit void dccpprobe_exit(void)
182{
183 kfifo_free(dccpw.fifo);
184 proc_net_remove(procname);
185 unregister_jprobe(&dccp_send_probe);
186
187}
188module_exit(dccpprobe_exit);
189
190MODULE_PARM_DESC(port, "Port to match (0=all)");
191module_param(port, int, 0);
192
193MODULE_PARM_DESC(bufsize, "Log buffer size (default 64k)");
194module_param(bufsize, int, 0);
195
196MODULE_AUTHOR("Ian McDonald <ian.mcdonald@jandi.co.nz>");
197MODULE_DESCRIPTION("DCCP snooper");
198MODULE_LICENSE("GPL");
diff --git a/net/dccp/proto.c b/net/dccp/proto.c
index 962df0ea31aa..72cbdcfc2c65 100644
--- a/net/dccp/proto.c
+++ b/net/dccp/proto.c
@@ -217,7 +217,7 @@ int dccp_init_sock(struct sock *sk, const __u8 ctl_sock_initialized)
217 icsk->icsk_sync_mss = dccp_sync_mss; 217 icsk->icsk_sync_mss = dccp_sync_mss;
218 dp->dccps_mss_cache = 536; 218 dp->dccps_mss_cache = 536;
219 dp->dccps_role = DCCP_ROLE_UNDEFINED; 219 dp->dccps_role = DCCP_ROLE_UNDEFINED;
220 dp->dccps_service = DCCP_SERVICE_INVALID_VALUE; 220 dp->dccps_service = DCCP_SERVICE_CODE_IS_ABSENT;
221 dp->dccps_l_ack_ratio = dp->dccps_r_ack_ratio = 1; 221 dp->dccps_l_ack_ratio = dp->dccps_r_ack_ratio = 1;
222 222
223 return 0; 223 return 0;
@@ -267,12 +267,6 @@ static inline int dccp_listen_start(struct sock *sk)
267 struct dccp_sock *dp = dccp_sk(sk); 267 struct dccp_sock *dp = dccp_sk(sk);
268 268
269 dp->dccps_role = DCCP_ROLE_LISTEN; 269 dp->dccps_role = DCCP_ROLE_LISTEN;
270 /*
271 * Apps need to use setsockopt(DCCP_SOCKOPT_SERVICE)
272 * before calling listen()
273 */
274 if (dccp_service_not_initialized(sk))
275 return -EPROTO;
276 return inet_csk_listen_start(sk, TCP_SYNQ_HSIZE); 270 return inet_csk_listen_start(sk, TCP_SYNQ_HSIZE);
277} 271}
278 272
@@ -540,9 +534,6 @@ static int dccp_getsockopt_service(struct sock *sk, int len,
540 int err = -ENOENT, slen = 0, total_len = sizeof(u32); 534 int err = -ENOENT, slen = 0, total_len = sizeof(u32);
541 535
542 lock_sock(sk); 536 lock_sock(sk);
543 if (dccp_service_not_initialized(sk))
544 goto out;
545
546 if ((sl = dp->dccps_service_list) != NULL) { 537 if ((sl = dp->dccps_service_list) != NULL) {
547 slen = sl->dccpsl_nr * sizeof(u32); 538 slen = sl->dccpsl_nr * sizeof(u32);
548 total_len += slen; 539 total_len += slen;
diff --git a/net/ipv4/Kconfig b/net/ipv4/Kconfig
index 1650b64415aa..30af4a4dfcc8 100644
--- a/net/ipv4/Kconfig
+++ b/net/ipv4/Kconfig
@@ -448,24 +448,22 @@ config INET_TCP_DIAG
448 depends on INET_DIAG 448 depends on INET_DIAG
449 def_tristate INET_DIAG 449 def_tristate INET_DIAG
450 450
451config TCP_CONG_ADVANCED 451menuconfig TCP_CONG_ADVANCED
452 bool "TCP: advanced congestion control" 452 bool "TCP: advanced congestion control"
453 ---help--- 453 ---help---
454 Support for selection of various TCP congestion control 454 Support for selection of various TCP congestion control
455 modules. 455 modules.
456 456
457 Nearly all users can safely say no here, and a safe default 457 Nearly all users can safely say no here, and a safe default
458 selection will be made (BIC-TCP with new Reno as a fallback). 458 selection will be made (CUBIC with new Reno as a fallback).
459 459
460 If unsure, say N. 460 If unsure, say N.
461 461
462# TCP Reno is builtin (required as fallback) 462if TCP_CONG_ADVANCED
463menu "TCP congestion control"
464 depends on TCP_CONG_ADVANCED
465 463
466config TCP_CONG_BIC 464config TCP_CONG_BIC
467 tristate "Binary Increase Congestion (BIC) control" 465 tristate "Binary Increase Congestion (BIC) control"
468 default y 466 default m
469 ---help--- 467 ---help---
470 BIC-TCP is a sender-side only change that ensures a linear RTT 468 BIC-TCP is a sender-side only change that ensures a linear RTT
471 fairness under large windows while offering both scalability and 469 fairness under large windows while offering both scalability and
@@ -479,7 +477,7 @@ config TCP_CONG_BIC
479 477
480config TCP_CONG_CUBIC 478config TCP_CONG_CUBIC
481 tristate "CUBIC TCP" 479 tristate "CUBIC TCP"
482 default m 480 default y
483 ---help--- 481 ---help---
484 This is version 2.0 of BIC-TCP which uses a cubic growth function 482 This is version 2.0 of BIC-TCP which uses a cubic growth function
485 among other techniques. 483 among other techniques.
@@ -574,12 +572,49 @@ config TCP_CONG_VENO
574 loss packets. 572 loss packets.
575 See http://www.ntu.edu.sg/home5/ZHOU0022/papers/CPFu03a.pdf 573 See http://www.ntu.edu.sg/home5/ZHOU0022/papers/CPFu03a.pdf
576 574
577endmenu 575choice
576 prompt "Default TCP congestion control"
577 default DEFAULT_CUBIC
578 help
579 Select the TCP congestion control that will be used by default
580 for all connections.
578 581
579config TCP_CONG_BIC 582 config DEFAULT_BIC
583 bool "Bic" if TCP_CONG_BIC=y
584
585 config DEFAULT_CUBIC
586 bool "Cubic" if TCP_CONG_CUBIC=y
587
588 config DEFAULT_HTCP
589 bool "Htcp" if TCP_CONG_HTCP=y
590
591 config DEFAULT_VEGAS
592 bool "Vegas" if TCP_CONG_VEGAS=y
593
594 config DEFAULT_WESTWOOD
595 bool "Westwood" if TCP_CONG_WESTWOOD=y
596
597 config DEFAULT_RENO
598 bool "Reno"
599
600endchoice
601
602endif
603
604config TCP_CONG_CUBIC
580 tristate 605 tristate
581 depends on !TCP_CONG_ADVANCED 606 depends on !TCP_CONG_ADVANCED
582 default y 607 default y
583 608
609config DEFAULT_TCP_CONG
610 string
611 default "bic" if DEFAULT_BIC
612 default "cubic" if DEFAULT_CUBIC
613 default "htcp" if DEFAULT_HTCP
614 default "vegas" if DEFAULT_VEGAS
615 default "westwood" if DEFAULT_WESTWOOD
616 default "reno" if DEFAULT_RENO
617 default "cubic"
618
584source "net/ipv4/ipvs/Kconfig" 619source "net/ipv4/ipvs/Kconfig"
585 620
diff --git a/net/ipv4/cipso_ipv4.c b/net/ipv4/cipso_ipv4.c
index 80a2a0911b49..e6ce0b3ba62a 100644
--- a/net/ipv4/cipso_ipv4.c
+++ b/net/ipv4/cipso_ipv4.c
@@ -259,7 +259,7 @@ void cipso_v4_cache_invalidate(void)
259 u32 iter; 259 u32 iter;
260 260
261 for (iter = 0; iter < CIPSO_V4_CACHE_BUCKETS; iter++) { 261 for (iter = 0; iter < CIPSO_V4_CACHE_BUCKETS; iter++) {
262 spin_lock(&cipso_v4_cache[iter].lock); 262 spin_lock_bh(&cipso_v4_cache[iter].lock);
263 list_for_each_entry_safe(entry, 263 list_for_each_entry_safe(entry,
264 tmp_entry, 264 tmp_entry,
265 &cipso_v4_cache[iter].list, list) { 265 &cipso_v4_cache[iter].list, list) {
@@ -267,7 +267,7 @@ void cipso_v4_cache_invalidate(void)
267 cipso_v4_cache_entry_free(entry); 267 cipso_v4_cache_entry_free(entry);
268 } 268 }
269 cipso_v4_cache[iter].size = 0; 269 cipso_v4_cache[iter].size = 0;
270 spin_unlock(&cipso_v4_cache[iter].lock); 270 spin_unlock_bh(&cipso_v4_cache[iter].lock);
271 } 271 }
272 272
273 return; 273 return;
@@ -309,7 +309,7 @@ static int cipso_v4_cache_check(const unsigned char *key,
309 309
310 hash = cipso_v4_map_cache_hash(key, key_len); 310 hash = cipso_v4_map_cache_hash(key, key_len);
311 bkt = hash & (CIPSO_V4_CACHE_BUCKETBITS - 1); 311 bkt = hash & (CIPSO_V4_CACHE_BUCKETBITS - 1);
312 spin_lock(&cipso_v4_cache[bkt].lock); 312 spin_lock_bh(&cipso_v4_cache[bkt].lock);
313 list_for_each_entry(entry, &cipso_v4_cache[bkt].list, list) { 313 list_for_each_entry(entry, &cipso_v4_cache[bkt].list, list) {
314 if (entry->hash == hash && 314 if (entry->hash == hash &&
315 entry->key_len == key_len && 315 entry->key_len == key_len &&
@@ -318,7 +318,7 @@ static int cipso_v4_cache_check(const unsigned char *key,
318 secattr->cache.free = entry->lsm_data.free; 318 secattr->cache.free = entry->lsm_data.free;
319 secattr->cache.data = entry->lsm_data.data; 319 secattr->cache.data = entry->lsm_data.data;
320 if (prev_entry == NULL) { 320 if (prev_entry == NULL) {
321 spin_unlock(&cipso_v4_cache[bkt].lock); 321 spin_unlock_bh(&cipso_v4_cache[bkt].lock);
322 return 0; 322 return 0;
323 } 323 }
324 324
@@ -333,12 +333,12 @@ static int cipso_v4_cache_check(const unsigned char *key,
333 &prev_entry->list); 333 &prev_entry->list);
334 } 334 }
335 335
336 spin_unlock(&cipso_v4_cache[bkt].lock); 336 spin_unlock_bh(&cipso_v4_cache[bkt].lock);
337 return 0; 337 return 0;
338 } 338 }
339 prev_entry = entry; 339 prev_entry = entry;
340 } 340 }
341 spin_unlock(&cipso_v4_cache[bkt].lock); 341 spin_unlock_bh(&cipso_v4_cache[bkt].lock);
342 342
343 return -ENOENT; 343 return -ENOENT;
344} 344}
@@ -387,7 +387,7 @@ int cipso_v4_cache_add(const struct sk_buff *skb,
387 entry->lsm_data.data = secattr->cache.data; 387 entry->lsm_data.data = secattr->cache.data;
388 388
389 bkt = entry->hash & (CIPSO_V4_CACHE_BUCKETBITS - 1); 389 bkt = entry->hash & (CIPSO_V4_CACHE_BUCKETBITS - 1);
390 spin_lock(&cipso_v4_cache[bkt].lock); 390 spin_lock_bh(&cipso_v4_cache[bkt].lock);
391 if (cipso_v4_cache[bkt].size < cipso_v4_cache_bucketsize) { 391 if (cipso_v4_cache[bkt].size < cipso_v4_cache_bucketsize) {
392 list_add(&entry->list, &cipso_v4_cache[bkt].list); 392 list_add(&entry->list, &cipso_v4_cache[bkt].list);
393 cipso_v4_cache[bkt].size += 1; 393 cipso_v4_cache[bkt].size += 1;
@@ -398,7 +398,7 @@ int cipso_v4_cache_add(const struct sk_buff *skb,
398 list_add(&entry->list, &cipso_v4_cache[bkt].list); 398 list_add(&entry->list, &cipso_v4_cache[bkt].list);
399 cipso_v4_cache_entry_free(old_entry); 399 cipso_v4_cache_entry_free(old_entry);
400 } 400 }
401 spin_unlock(&cipso_v4_cache[bkt].lock); 401 spin_unlock_bh(&cipso_v4_cache[bkt].lock);
402 402
403 return 0; 403 return 0;
404 404
@@ -530,197 +530,42 @@ struct cipso_v4_doi *cipso_v4_doi_getdef(u32 doi)
530} 530}
531 531
532/** 532/**
533 * cipso_v4_doi_dump_all - Dump all the CIPSO DOI definitions into a sk_buff 533 * cipso_v4_doi_walk - Iterate through the DOI definitions
534 * @headroom: the amount of headroom to allocate for the sk_buff 534 * @skip_cnt: skip past this number of DOI definitions, updated
535 * @callback: callback for each DOI definition
536 * @cb_arg: argument for the callback function
535 * 537 *
536 * Description: 538 * Description:
537 * Dump a list of all the configured DOI values into a sk_buff. The returned 539 * Iterate over the DOI definition list, skipping the first @skip_cnt entries.
538 * sk_buff has room at the front of the sk_buff for @headroom bytes. See 540 * For each entry call @callback, if @callback returns a negative value stop
539 * net/netlabel/netlabel_cipso_v4.h for the LISTALL message format. This 541 * 'walking' through the list and return. Updates the value in @skip_cnt upon
540 * function may fail if another process is changing the DOI list at the same 542 * return. Returns zero on success, negative values on failure.
541 * time. Returns a pointer to a sk_buff on success, NULL on error.
542 * 543 *
543 */ 544 */
544struct sk_buff *cipso_v4_doi_dump_all(size_t headroom) 545int cipso_v4_doi_walk(u32 *skip_cnt,
546 int (*callback) (struct cipso_v4_doi *doi_def, void *arg),
547 void *cb_arg)
545{ 548{
546 struct sk_buff *skb = NULL; 549 int ret_val = -ENOENT;
547 struct cipso_v4_doi *iter;
548 u32 doi_cnt = 0; 550 u32 doi_cnt = 0;
549 ssize_t buf_len; 551 struct cipso_v4_doi *iter_doi;
550 552
551 buf_len = NETLBL_LEN_U32;
552 rcu_read_lock(); 553 rcu_read_lock();
553 list_for_each_entry_rcu(iter, &cipso_v4_doi_list, list) 554 list_for_each_entry_rcu(iter_doi, &cipso_v4_doi_list, list)
554 if (iter->valid) { 555 if (iter_doi->valid) {
555 doi_cnt += 1; 556 if (doi_cnt++ < *skip_cnt)
556 buf_len += 2 * NETLBL_LEN_U32; 557 continue;
557 } 558 ret_val = callback(iter_doi, cb_arg);
558 559 if (ret_val < 0) {
559 skb = netlbl_netlink_alloc_skb(headroom, buf_len, GFP_ATOMIC); 560 doi_cnt--;
560 if (skb == NULL) 561 goto doi_walk_return;
561 goto doi_dump_all_failure;
562
563 if (nla_put_u32(skb, NLA_U32, doi_cnt) != 0)
564 goto doi_dump_all_failure;
565 buf_len -= NETLBL_LEN_U32;
566 list_for_each_entry_rcu(iter, &cipso_v4_doi_list, list)
567 if (iter->valid) {
568 if (buf_len < 2 * NETLBL_LEN_U32)
569 goto doi_dump_all_failure;
570 if (nla_put_u32(skb, NLA_U32, iter->doi) != 0)
571 goto doi_dump_all_failure;
572 if (nla_put_u32(skb, NLA_U32, iter->type) != 0)
573 goto doi_dump_all_failure;
574 buf_len -= 2 * NETLBL_LEN_U32;
575 }
576 rcu_read_unlock();
577
578 return skb;
579
580doi_dump_all_failure:
581 rcu_read_unlock();
582 kfree(skb);
583 return NULL;
584}
585
586/**
587 * cipso_v4_doi_dump - Dump a CIPSO DOI definition into a sk_buff
588 * @doi: the DOI value
589 * @headroom: the amount of headroom to allocate for the sk_buff
590 *
591 * Description:
592 * Lookup the DOI definition matching @doi and dump it's contents into a
593 * sk_buff. The returned sk_buff has room at the front of the sk_buff for
594 * @headroom bytes. See net/netlabel/netlabel_cipso_v4.h for the LIST message
595 * format. This function may fail if another process is changing the DOI list
596 * at the same time. Returns a pointer to a sk_buff on success, NULL on error.
597 *
598 */
599struct sk_buff *cipso_v4_doi_dump(u32 doi, size_t headroom)
600{
601 struct sk_buff *skb = NULL;
602 struct cipso_v4_doi *iter;
603 u32 tag_cnt = 0;
604 u32 lvl_cnt = 0;
605 u32 cat_cnt = 0;
606 ssize_t buf_len;
607 ssize_t tmp;
608
609 rcu_read_lock();
610 iter = cipso_v4_doi_getdef(doi);
611 if (iter == NULL)
612 goto doi_dump_failure;
613 buf_len = NETLBL_LEN_U32;
614 switch (iter->type) {
615 case CIPSO_V4_MAP_PASS:
616 buf_len += NETLBL_LEN_U32;
617 while(tag_cnt < CIPSO_V4_TAG_MAXCNT &&
618 iter->tags[tag_cnt] != CIPSO_V4_TAG_INVALID) {
619 tag_cnt += 1;
620 buf_len += NETLBL_LEN_U8;
621 }
622 break;
623 case CIPSO_V4_MAP_STD:
624 buf_len += 3 * NETLBL_LEN_U32;
625 while (tag_cnt < CIPSO_V4_TAG_MAXCNT &&
626 iter->tags[tag_cnt] != CIPSO_V4_TAG_INVALID) {
627 tag_cnt += 1;
628 buf_len += NETLBL_LEN_U8;
629 }
630 for (tmp = 0; tmp < iter->map.std->lvl.local_size; tmp++)
631 if (iter->map.std->lvl.local[tmp] !=
632 CIPSO_V4_INV_LVL) {
633 lvl_cnt += 1;
634 buf_len += NETLBL_LEN_U32 + NETLBL_LEN_U8;
635 }
636 for (tmp = 0; tmp < iter->map.std->cat.local_size; tmp++)
637 if (iter->map.std->cat.local[tmp] !=
638 CIPSO_V4_INV_CAT) {
639 cat_cnt += 1;
640 buf_len += NETLBL_LEN_U32 + NETLBL_LEN_U16;
641 } 562 }
642 break;
643 }
644
645 skb = netlbl_netlink_alloc_skb(headroom, buf_len, GFP_ATOMIC);
646 if (skb == NULL)
647 goto doi_dump_failure;
648
649 if (nla_put_u32(skb, NLA_U32, iter->type) != 0)
650 goto doi_dump_failure;
651 buf_len -= NETLBL_LEN_U32;
652 if (iter != cipso_v4_doi_getdef(doi))
653 goto doi_dump_failure;
654 switch (iter->type) {
655 case CIPSO_V4_MAP_PASS:
656 if (nla_put_u32(skb, NLA_U32, tag_cnt) != 0)
657 goto doi_dump_failure;
658 buf_len -= NETLBL_LEN_U32;
659 for (tmp = 0;
660 tmp < CIPSO_V4_TAG_MAXCNT &&
661 iter->tags[tmp] != CIPSO_V4_TAG_INVALID;
662 tmp++) {
663 if (buf_len < NETLBL_LEN_U8)
664 goto doi_dump_failure;
665 if (nla_put_u8(skb, NLA_U8, iter->tags[tmp]) != 0)
666 goto doi_dump_failure;
667 buf_len -= NETLBL_LEN_U8;
668 } 563 }
669 break;
670 case CIPSO_V4_MAP_STD:
671 if (nla_put_u32(skb, NLA_U32, tag_cnt) != 0)
672 goto doi_dump_failure;
673 if (nla_put_u32(skb, NLA_U32, lvl_cnt) != 0)
674 goto doi_dump_failure;
675 if (nla_put_u32(skb, NLA_U32, cat_cnt) != 0)
676 goto doi_dump_failure;
677 buf_len -= 3 * NETLBL_LEN_U32;
678 for (tmp = 0;
679 tmp < CIPSO_V4_TAG_MAXCNT &&
680 iter->tags[tmp] != CIPSO_V4_TAG_INVALID;
681 tmp++) {
682 if (buf_len < NETLBL_LEN_U8)
683 goto doi_dump_failure;
684 if (nla_put_u8(skb, NLA_U8, iter->tags[tmp]) != 0)
685 goto doi_dump_failure;
686 buf_len -= NETLBL_LEN_U8;
687 }
688 for (tmp = 0; tmp < iter->map.std->lvl.local_size; tmp++)
689 if (iter->map.std->lvl.local[tmp] !=
690 CIPSO_V4_INV_LVL) {
691 if (buf_len < NETLBL_LEN_U32 + NETLBL_LEN_U8)
692 goto doi_dump_failure;
693 if (nla_put_u32(skb, NLA_U32, tmp) != 0)
694 goto doi_dump_failure;
695 if (nla_put_u8(skb,
696 NLA_U8,
697 iter->map.std->lvl.local[tmp]) != 0)
698 goto doi_dump_failure;
699 buf_len -= NETLBL_LEN_U32 + NETLBL_LEN_U8;
700 }
701 for (tmp = 0; tmp < iter->map.std->cat.local_size; tmp++)
702 if (iter->map.std->cat.local[tmp] !=
703 CIPSO_V4_INV_CAT) {
704 if (buf_len < NETLBL_LEN_U32 + NETLBL_LEN_U16)
705 goto doi_dump_failure;
706 if (nla_put_u32(skb, NLA_U32, tmp) != 0)
707 goto doi_dump_failure;
708 if (nla_put_u16(skb,
709 NLA_U16,
710 iter->map.std->cat.local[tmp]) != 0)
711 goto doi_dump_failure;
712 buf_len -= NETLBL_LEN_U32 + NETLBL_LEN_U16;
713 }
714 break;
715 }
716 rcu_read_unlock();
717
718 return skb;
719 564
720doi_dump_failure: 565doi_walk_return:
721 rcu_read_unlock(); 566 rcu_read_unlock();
722 kfree(skb); 567 *skip_cnt = doi_cnt;
723 return NULL; 568 return ret_val;
724} 569}
725 570
726/** 571/**
@@ -1486,43 +1331,40 @@ socket_setattr_failure:
1486} 1331}
1487 1332
1488/** 1333/**
1489 * cipso_v4_socket_getattr - Get the security attributes from a socket 1334 * cipso_v4_sock_getattr - Get the security attributes from a sock
1490 * @sock: the socket 1335 * @sk: the sock
1491 * @secattr: the security attributes 1336 * @secattr: the security attributes
1492 * 1337 *
1493 * Description: 1338 * Description:
1494 * Query @sock to see if there is a CIPSO option attached to the socket and if 1339 * Query @sk to see if there is a CIPSO option attached to the sock and if
1495 * there is return the CIPSO security attributes in @secattr. Returns zero on 1340 * there is return the CIPSO security attributes in @secattr. This function
1496 * success and negative values on failure. 1341 * requires that @sk be locked, or privately held, but it does not do any
1342 * locking itself. Returns zero on success and negative values on failure.
1497 * 1343 *
1498 */ 1344 */
1499int cipso_v4_socket_getattr(const struct socket *sock, 1345int cipso_v4_sock_getattr(struct sock *sk, struct netlbl_lsm_secattr *secattr)
1500 struct netlbl_lsm_secattr *secattr)
1501{ 1346{
1502 int ret_val = -ENOMSG; 1347 int ret_val = -ENOMSG;
1503 struct sock *sk;
1504 struct inet_sock *sk_inet; 1348 struct inet_sock *sk_inet;
1505 unsigned char *cipso_ptr; 1349 unsigned char *cipso_ptr;
1506 u32 doi; 1350 u32 doi;
1507 struct cipso_v4_doi *doi_def; 1351 struct cipso_v4_doi *doi_def;
1508 1352
1509 sk = sock->sk;
1510 lock_sock(sk);
1511 sk_inet = inet_sk(sk); 1353 sk_inet = inet_sk(sk);
1512 if (sk_inet->opt == NULL || sk_inet->opt->cipso == 0) 1354 if (sk_inet->opt == NULL || sk_inet->opt->cipso == 0)
1513 goto socket_getattr_return; 1355 return -ENOMSG;
1514 cipso_ptr = sk_inet->opt->__data + sk_inet->opt->cipso - 1356 cipso_ptr = sk_inet->opt->__data + sk_inet->opt->cipso -
1515 sizeof(struct iphdr); 1357 sizeof(struct iphdr);
1516 ret_val = cipso_v4_cache_check(cipso_ptr, cipso_ptr[1], secattr); 1358 ret_val = cipso_v4_cache_check(cipso_ptr, cipso_ptr[1], secattr);
1517 if (ret_val == 0) 1359 if (ret_val == 0)
1518 goto socket_getattr_return; 1360 return ret_val;
1519 1361
1520 doi = ntohl(*(u32 *)&cipso_ptr[2]); 1362 doi = ntohl(*(u32 *)&cipso_ptr[2]);
1521 rcu_read_lock(); 1363 rcu_read_lock();
1522 doi_def = cipso_v4_doi_getdef(doi); 1364 doi_def = cipso_v4_doi_getdef(doi);
1523 if (doi_def == NULL) { 1365 if (doi_def == NULL) {
1524 rcu_read_unlock(); 1366 rcu_read_unlock();
1525 goto socket_getattr_return; 1367 return -ENOMSG;
1526 } 1368 }
1527 switch (cipso_ptr[6]) { 1369 switch (cipso_ptr[6]) {
1528 case CIPSO_V4_TAG_RBITMAP: 1370 case CIPSO_V4_TAG_RBITMAP:
@@ -1533,8 +1375,29 @@ int cipso_v4_socket_getattr(const struct socket *sock,
1533 } 1375 }
1534 rcu_read_unlock(); 1376 rcu_read_unlock();
1535 1377
1536socket_getattr_return: 1378 return ret_val;
1537 release_sock(sk); 1379}
1380
1381/**
1382 * cipso_v4_socket_getattr - Get the security attributes from a socket
1383 * @sock: the socket
1384 * @secattr: the security attributes
1385 *
1386 * Description:
1387 * Query @sock to see if there is a CIPSO option attached to the socket and if
1388 * there is return the CIPSO security attributes in @secattr. Returns zero on
1389 * success and negative values on failure.
1390 *
1391 */
1392int cipso_v4_socket_getattr(const struct socket *sock,
1393 struct netlbl_lsm_secattr *secattr)
1394{
1395 int ret_val;
1396
1397 lock_sock(sock->sk);
1398 ret_val = cipso_v4_sock_getattr(sock->sk, secattr);
1399 release_sock(sock->sk);
1400
1538 return ret_val; 1401 return ret_val;
1539} 1402}
1540 1403
diff --git a/net/ipv4/sysctl_net_ipv4.c b/net/ipv4/sysctl_net_ipv4.c
index 19b2071ff319..e82a5be894b5 100644
--- a/net/ipv4/sysctl_net_ipv4.c
+++ b/net/ipv4/sysctl_net_ipv4.c
@@ -129,6 +129,12 @@ static int sysctl_tcp_congestion_control(ctl_table *table, int __user *name,
129 return ret; 129 return ret;
130} 130}
131 131
132static int __init tcp_congestion_default(void)
133{
134 return tcp_set_default_congestion_control(CONFIG_DEFAULT_TCP_CONG);
135}
136
137late_initcall(tcp_congestion_default);
132 138
133ctl_table ipv4_table[] = { 139ctl_table ipv4_table[] = {
134 { 140 {
diff --git a/net/ipv4/tcp_cong.c b/net/ipv4/tcp_cong.c
index 7ff2e4273a7c..af0aca1e6be6 100644
--- a/net/ipv4/tcp_cong.c
+++ b/net/ipv4/tcp_cong.c
@@ -48,7 +48,7 @@ int tcp_register_congestion_control(struct tcp_congestion_ops *ca)
48 printk(KERN_NOTICE "TCP %s already registered\n", ca->name); 48 printk(KERN_NOTICE "TCP %s already registered\n", ca->name);
49 ret = -EEXIST; 49 ret = -EEXIST;
50 } else { 50 } else {
51 list_add_rcu(&ca->list, &tcp_cong_list); 51 list_add_tail_rcu(&ca->list, &tcp_cong_list);
52 printk(KERN_INFO "TCP %s registered\n", ca->name); 52 printk(KERN_INFO "TCP %s registered\n", ca->name);
53 } 53 }
54 spin_unlock(&tcp_cong_list_lock); 54 spin_unlock(&tcp_cong_list_lock);
diff --git a/net/netlabel/Kconfig b/net/netlabel/Kconfig
index fe23cb7f1e87..9f7121ae13e9 100644
--- a/net/netlabel/Kconfig
+++ b/net/netlabel/Kconfig
@@ -9,6 +9,9 @@ config NETLABEL
9 ---help--- 9 ---help---
10 NetLabel provides support for explicit network packet labeling 10 NetLabel provides support for explicit network packet labeling
11 protocols such as CIPSO and RIPSO. For more information see 11 protocols such as CIPSO and RIPSO. For more information see
12 Documentation/netlabel. 12 Documentation/netlabel as well as the NetLabel SourceForge project
13 for configuration tools and additional documentation.
14
15 * http://netlabel.sf.net
13 16
14 If you are unsure, say N. 17 If you are unsure, say N.
diff --git a/net/netlabel/netlabel_cipso_v4.c b/net/netlabel/netlabel_cipso_v4.c
index a4f40adc447b..4125a55f469f 100644
--- a/net/netlabel/netlabel_cipso_v4.c
+++ b/net/netlabel/netlabel_cipso_v4.c
@@ -41,15 +41,37 @@
41#include "netlabel_user.h" 41#include "netlabel_user.h"
42#include "netlabel_cipso_v4.h" 42#include "netlabel_cipso_v4.h"
43 43
44/* Argument struct for cipso_v4_doi_walk() */
45struct netlbl_cipsov4_doiwalk_arg {
46 struct netlink_callback *nl_cb;
47 struct sk_buff *skb;
48 u32 seq;
49};
50
44/* NetLabel Generic NETLINK CIPSOv4 family */ 51/* NetLabel Generic NETLINK CIPSOv4 family */
45static struct genl_family netlbl_cipsov4_gnl_family = { 52static struct genl_family netlbl_cipsov4_gnl_family = {
46 .id = GENL_ID_GENERATE, 53 .id = GENL_ID_GENERATE,
47 .hdrsize = 0, 54 .hdrsize = 0,
48 .name = NETLBL_NLTYPE_CIPSOV4_NAME, 55 .name = NETLBL_NLTYPE_CIPSOV4_NAME,
49 .version = NETLBL_PROTO_VERSION, 56 .version = NETLBL_PROTO_VERSION,
50 .maxattr = 0, 57 .maxattr = NLBL_CIPSOV4_A_MAX,
51}; 58};
52 59
60/* NetLabel Netlink attribute policy */
61static struct nla_policy netlbl_cipsov4_genl_policy[NLBL_CIPSOV4_A_MAX + 1] = {
62 [NLBL_CIPSOV4_A_DOI] = { .type = NLA_U32 },
63 [NLBL_CIPSOV4_A_MTYPE] = { .type = NLA_U32 },
64 [NLBL_CIPSOV4_A_TAG] = { .type = NLA_U8 },
65 [NLBL_CIPSOV4_A_TAGLST] = { .type = NLA_NESTED },
66 [NLBL_CIPSOV4_A_MLSLVLLOC] = { .type = NLA_U32 },
67 [NLBL_CIPSOV4_A_MLSLVLREM] = { .type = NLA_U32 },
68 [NLBL_CIPSOV4_A_MLSLVL] = { .type = NLA_NESTED },
69 [NLBL_CIPSOV4_A_MLSLVLLST] = { .type = NLA_NESTED },
70 [NLBL_CIPSOV4_A_MLSCATLOC] = { .type = NLA_U32 },
71 [NLBL_CIPSOV4_A_MLSCATREM] = { .type = NLA_U32 },
72 [NLBL_CIPSOV4_A_MLSCAT] = { .type = NLA_NESTED },
73 [NLBL_CIPSOV4_A_MLSCATLST] = { .type = NLA_NESTED },
74};
53 75
54/* 76/*
55 * Helper Functions 77 * Helper Functions
@@ -81,6 +103,41 @@ static void netlbl_cipsov4_doi_free(struct rcu_head *entry)
81 kfree(ptr); 103 kfree(ptr);
82} 104}
83 105
106/**
107 * netlbl_cipsov4_add_common - Parse the common sections of a ADD message
108 * @info: the Generic NETLINK info block
109 * @doi_def: the CIPSO V4 DOI definition
110 *
111 * Description:
112 * Parse the common sections of a ADD message and fill in the related values
113 * in @doi_def. Returns zero on success, negative values on failure.
114 *
115 */
116static int netlbl_cipsov4_add_common(struct genl_info *info,
117 struct cipso_v4_doi *doi_def)
118{
119 struct nlattr *nla;
120 int nla_rem;
121 u32 iter = 0;
122
123 doi_def->doi = nla_get_u32(info->attrs[NLBL_CIPSOV4_A_DOI]);
124
125 if (nla_validate_nested(info->attrs[NLBL_CIPSOV4_A_TAGLST],
126 NLBL_CIPSOV4_A_MAX,
127 netlbl_cipsov4_genl_policy) != 0)
128 return -EINVAL;
129
130 nla_for_each_nested(nla, info->attrs[NLBL_CIPSOV4_A_TAGLST], nla_rem)
131 if (nla->nla_type == NLBL_CIPSOV4_A_TAG) {
132 if (iter > CIPSO_V4_TAG_MAXCNT)
133 return -EINVAL;
134 doi_def->tags[iter++] = nla_get_u8(nla);
135 }
136 if (iter < CIPSO_V4_TAG_MAXCNT)
137 doi_def->tags[iter] = CIPSO_V4_TAG_INVALID;
138
139 return 0;
140}
84 141
85/* 142/*
86 * NetLabel Command Handlers 143 * NetLabel Command Handlers
@@ -88,9 +145,7 @@ static void netlbl_cipsov4_doi_free(struct rcu_head *entry)
88 145
89/** 146/**
90 * netlbl_cipsov4_add_std - Adds a CIPSO V4 DOI definition 147 * netlbl_cipsov4_add_std - Adds a CIPSO V4 DOI definition
91 * @doi: the DOI value 148 * @info: the Generic NETLINK info block
92 * @msg: the ADD message data
93 * @msg_size: the size of the ADD message buffer
94 * 149 *
95 * Description: 150 * Description:
96 * Create a new CIPSO_V4_MAP_STD DOI definition based on the given ADD message 151 * Create a new CIPSO_V4_MAP_STD DOI definition based on the given ADD message
@@ -98,29 +153,28 @@ static void netlbl_cipsov4_doi_free(struct rcu_head *entry)
98 * error. 153 * error.
99 * 154 *
100 */ 155 */
101static int netlbl_cipsov4_add_std(u32 doi, struct nlattr *msg, size_t msg_size) 156static int netlbl_cipsov4_add_std(struct genl_info *info)
102{ 157{
103 int ret_val = -EINVAL; 158 int ret_val = -EINVAL;
104 int msg_len = msg_size;
105 u32 num_tags;
106 u32 num_lvls;
107 u32 num_cats;
108 struct cipso_v4_doi *doi_def = NULL; 159 struct cipso_v4_doi *doi_def = NULL;
109 u32 iter; 160 struct nlattr *nla_a;
110 u32 tmp_val_a; 161 struct nlattr *nla_b;
111 u32 tmp_val_b; 162 int nla_a_rem;
163 int nla_b_rem;
112 164
113 if (msg_len < NETLBL_LEN_U32) 165 if (!info->attrs[NLBL_CIPSOV4_A_DOI] ||
114 goto add_std_failure; 166 !info->attrs[NLBL_CIPSOV4_A_TAGLST] ||
115 num_tags = netlbl_getinc_u32(&msg, &msg_len); 167 !info->attrs[NLBL_CIPSOV4_A_MLSLVLLST])
116 if (num_tags == 0 || num_tags > CIPSO_V4_TAG_MAXCNT) 168 return -EINVAL;
117 goto add_std_failure; 169
170 if (nla_validate_nested(info->attrs[NLBL_CIPSOV4_A_MLSLVLLST],
171 NLBL_CIPSOV4_A_MAX,
172 netlbl_cipsov4_genl_policy) != 0)
173 return -EINVAL;
118 174
119 doi_def = kmalloc(sizeof(*doi_def), GFP_KERNEL); 175 doi_def = kmalloc(sizeof(*doi_def), GFP_KERNEL);
120 if (doi_def == NULL) { 176 if (doi_def == NULL)
121 ret_val = -ENOMEM; 177 return -ENOMEM;
122 goto add_std_failure;
123 }
124 doi_def->map.std = kzalloc(sizeof(*doi_def->map.std), GFP_KERNEL); 178 doi_def->map.std = kzalloc(sizeof(*doi_def->map.std), GFP_KERNEL);
125 if (doi_def->map.std == NULL) { 179 if (doi_def->map.std == NULL) {
126 ret_val = -ENOMEM; 180 ret_val = -ENOMEM;
@@ -128,28 +182,32 @@ static int netlbl_cipsov4_add_std(u32 doi, struct nlattr *msg, size_t msg_size)
128 } 182 }
129 doi_def->type = CIPSO_V4_MAP_STD; 183 doi_def->type = CIPSO_V4_MAP_STD;
130 184
131 for (iter = 0; iter < num_tags; iter++) { 185 ret_val = netlbl_cipsov4_add_common(info, doi_def);
132 if (msg_len < NETLBL_LEN_U8) 186 if (ret_val != 0)
133 goto add_std_failure;
134 doi_def->tags[iter] = netlbl_getinc_u8(&msg, &msg_len);
135 switch (doi_def->tags[iter]) {
136 case CIPSO_V4_TAG_RBITMAP:
137 break;
138 default:
139 goto add_std_failure;
140 }
141 }
142 if (iter < CIPSO_V4_TAG_MAXCNT)
143 doi_def->tags[iter] = CIPSO_V4_TAG_INVALID;
144
145 if (msg_len < 6 * NETLBL_LEN_U32)
146 goto add_std_failure; 187 goto add_std_failure;
147 188
148 num_lvls = netlbl_getinc_u32(&msg, &msg_len); 189 nla_for_each_nested(nla_a,
149 if (num_lvls == 0) 190 info->attrs[NLBL_CIPSOV4_A_MLSLVLLST],
150 goto add_std_failure; 191 nla_a_rem)
151 doi_def->map.std->lvl.local_size = netlbl_getinc_u32(&msg, &msg_len); 192 if (nla_a->nla_type == NLBL_CIPSOV4_A_MLSLVL) {
152 if (doi_def->map.std->lvl.local_size > CIPSO_V4_MAX_LOC_LVLS) 193 nla_for_each_nested(nla_b, nla_a, nla_b_rem)
194 switch (nla_b->nla_type) {
195 case NLBL_CIPSOV4_A_MLSLVLLOC:
196 if (nla_get_u32(nla_b) >=
197 doi_def->map.std->lvl.local_size)
198 doi_def->map.std->lvl.local_size =
199 nla_get_u32(nla_b) + 1;
200 break;
201 case NLBL_CIPSOV4_A_MLSLVLREM:
202 if (nla_get_u32(nla_b) >=
203 doi_def->map.std->lvl.cipso_size)
204 doi_def->map.std->lvl.cipso_size =
205 nla_get_u32(nla_b) + 1;
206 break;
207 }
208 }
209 if (doi_def->map.std->lvl.local_size > CIPSO_V4_MAX_LOC_LVLS ||
210 doi_def->map.std->lvl.cipso_size > CIPSO_V4_MAX_REM_LVLS)
153 goto add_std_failure; 211 goto add_std_failure;
154 doi_def->map.std->lvl.local = kcalloc(doi_def->map.std->lvl.local_size, 212 doi_def->map.std->lvl.local = kcalloc(doi_def->map.std->lvl.local_size,
155 sizeof(u32), 213 sizeof(u32),
@@ -158,9 +216,6 @@ static int netlbl_cipsov4_add_std(u32 doi, struct nlattr *msg, size_t msg_size)
158 ret_val = -ENOMEM; 216 ret_val = -ENOMEM;
159 goto add_std_failure; 217 goto add_std_failure;
160 } 218 }
161 doi_def->map.std->lvl.cipso_size = netlbl_getinc_u8(&msg, &msg_len);
162 if (doi_def->map.std->lvl.cipso_size > CIPSO_V4_MAX_REM_LVLS)
163 goto add_std_failure;
164 doi_def->map.std->lvl.cipso = kcalloc(doi_def->map.std->lvl.cipso_size, 219 doi_def->map.std->lvl.cipso = kcalloc(doi_def->map.std->lvl.cipso_size,
165 sizeof(u32), 220 sizeof(u32),
166 GFP_KERNEL); 221 GFP_KERNEL);
@@ -168,68 +223,101 @@ static int netlbl_cipsov4_add_std(u32 doi, struct nlattr *msg, size_t msg_size)
168 ret_val = -ENOMEM; 223 ret_val = -ENOMEM;
169 goto add_std_failure; 224 goto add_std_failure;
170 } 225 }
226 nla_for_each_nested(nla_a,
227 info->attrs[NLBL_CIPSOV4_A_MLSLVLLST],
228 nla_a_rem)
229 if (nla_a->nla_type == NLBL_CIPSOV4_A_MLSLVL) {
230 struct nlattr *lvl_loc;
231 struct nlattr *lvl_rem;
232
233 if (nla_validate_nested(nla_a,
234 NLBL_CIPSOV4_A_MAX,
235 netlbl_cipsov4_genl_policy) != 0)
236 goto add_std_failure;
237
238 lvl_loc = nla_find_nested(nla_a,
239 NLBL_CIPSOV4_A_MLSLVLLOC);
240 lvl_rem = nla_find_nested(nla_a,
241 NLBL_CIPSOV4_A_MLSLVLREM);
242 if (lvl_loc == NULL || lvl_rem == NULL)
243 goto add_std_failure;
244 doi_def->map.std->lvl.local[nla_get_u32(lvl_loc)] =
245 nla_get_u32(lvl_rem);
246 doi_def->map.std->lvl.cipso[nla_get_u32(lvl_rem)] =
247 nla_get_u32(lvl_loc);
248 }
171 249
172 num_cats = netlbl_getinc_u32(&msg, &msg_len); 250 if (info->attrs[NLBL_CIPSOV4_A_MLSCATLST]) {
173 doi_def->map.std->cat.local_size = netlbl_getinc_u32(&msg, &msg_len); 251 if (nla_validate_nested(info->attrs[NLBL_CIPSOV4_A_MLSCATLST],
174 if (doi_def->map.std->cat.local_size > CIPSO_V4_MAX_LOC_CATS) 252 NLBL_CIPSOV4_A_MAX,
175 goto add_std_failure; 253 netlbl_cipsov4_genl_policy) != 0)
176 doi_def->map.std->cat.local = kcalloc(doi_def->map.std->cat.local_size, 254 goto add_std_failure;
255
256 nla_for_each_nested(nla_a,
257 info->attrs[NLBL_CIPSOV4_A_MLSCATLST],
258 nla_a_rem)
259 if (nla_a->nla_type == NLBL_CIPSOV4_A_MLSCAT) {
260 if (nla_validate_nested(nla_a,
261 NLBL_CIPSOV4_A_MAX,
262 netlbl_cipsov4_genl_policy) != 0)
263 goto add_std_failure;
264 nla_for_each_nested(nla_b, nla_a, nla_b_rem)
265 switch (nla_b->nla_type) {
266 case NLBL_CIPSOV4_A_MLSCATLOC:
267 if (nla_get_u32(nla_b) >=
268 doi_def->map.std->cat.local_size)
269 doi_def->map.std->cat.local_size =
270 nla_get_u32(nla_b) + 1;
271 break;
272 case NLBL_CIPSOV4_A_MLSCATREM:
273 if (nla_get_u32(nla_b) >=
274 doi_def->map.std->cat.cipso_size)
275 doi_def->map.std->cat.cipso_size =
276 nla_get_u32(nla_b) + 1;
277 break;
278 }
279 }
280 if (doi_def->map.std->cat.local_size > CIPSO_V4_MAX_LOC_CATS ||
281 doi_def->map.std->cat.cipso_size > CIPSO_V4_MAX_REM_CATS)
282 goto add_std_failure;
283 doi_def->map.std->cat.local = kcalloc(
284 doi_def->map.std->cat.local_size,
177 sizeof(u32), 285 sizeof(u32),
178 GFP_KERNEL); 286 GFP_KERNEL);
179 if (doi_def->map.std->cat.local == NULL) { 287 if (doi_def->map.std->cat.local == NULL) {
180 ret_val = -ENOMEM; 288 ret_val = -ENOMEM;
181 goto add_std_failure; 289 goto add_std_failure;
182 } 290 }
183 doi_def->map.std->cat.cipso_size = netlbl_getinc_u16(&msg, &msg_len); 291 doi_def->map.std->cat.cipso = kcalloc(
184 if (doi_def->map.std->cat.cipso_size > CIPSO_V4_MAX_REM_CATS) 292 doi_def->map.std->cat.cipso_size,
185 goto add_std_failure;
186 doi_def->map.std->cat.cipso = kcalloc(doi_def->map.std->cat.cipso_size,
187 sizeof(u32), 293 sizeof(u32),
188 GFP_KERNEL); 294 GFP_KERNEL);
189 if (doi_def->map.std->cat.cipso == NULL) { 295 if (doi_def->map.std->cat.cipso == NULL) {
190 ret_val = -ENOMEM; 296 ret_val = -ENOMEM;
191 goto add_std_failure;
192 }
193
194 if (msg_len <
195 num_lvls * (NETLBL_LEN_U32 + NETLBL_LEN_U8) +
196 num_cats * (NETLBL_LEN_U32 + NETLBL_LEN_U16))
197 goto add_std_failure;
198
199 for (iter = 0; iter < doi_def->map.std->lvl.cipso_size; iter++)
200 doi_def->map.std->lvl.cipso[iter] = CIPSO_V4_INV_LVL;
201 for (iter = 0; iter < doi_def->map.std->lvl.local_size; iter++)
202 doi_def->map.std->lvl.local[iter] = CIPSO_V4_INV_LVL;
203 for (iter = 0; iter < doi_def->map.std->cat.cipso_size; iter++)
204 doi_def->map.std->cat.cipso[iter] = CIPSO_V4_INV_CAT;
205 for (iter = 0; iter < doi_def->map.std->cat.local_size; iter++)
206 doi_def->map.std->cat.local[iter] = CIPSO_V4_INV_CAT;
207
208 for (iter = 0; iter < num_lvls; iter++) {
209 tmp_val_a = netlbl_getinc_u32(&msg, &msg_len);
210 tmp_val_b = netlbl_getinc_u8(&msg, &msg_len);
211
212 if (tmp_val_a >= doi_def->map.std->lvl.local_size ||
213 tmp_val_b >= doi_def->map.std->lvl.cipso_size)
214 goto add_std_failure;
215
216 doi_def->map.std->lvl.cipso[tmp_val_b] = tmp_val_a;
217 doi_def->map.std->lvl.local[tmp_val_a] = tmp_val_b;
218 }
219
220 for (iter = 0; iter < num_cats; iter++) {
221 tmp_val_a = netlbl_getinc_u32(&msg, &msg_len);
222 tmp_val_b = netlbl_getinc_u16(&msg, &msg_len);
223
224 if (tmp_val_a >= doi_def->map.std->cat.local_size ||
225 tmp_val_b >= doi_def->map.std->cat.cipso_size)
226 goto add_std_failure; 297 goto add_std_failure;
227 298 }
228 doi_def->map.std->cat.cipso[tmp_val_b] = tmp_val_a; 299 nla_for_each_nested(nla_a,
229 doi_def->map.std->cat.local[tmp_val_a] = tmp_val_b; 300 info->attrs[NLBL_CIPSOV4_A_MLSCATLST],
301 nla_a_rem)
302 if (nla_a->nla_type == NLBL_CIPSOV4_A_MLSCAT) {
303 struct nlattr *cat_loc;
304 struct nlattr *cat_rem;
305
306 cat_loc = nla_find_nested(nla_a,
307 NLBL_CIPSOV4_A_MLSCATLOC);
308 cat_rem = nla_find_nested(nla_a,
309 NLBL_CIPSOV4_A_MLSCATREM);
310 if (cat_loc == NULL || cat_rem == NULL)
311 goto add_std_failure;
312 doi_def->map.std->cat.local[
313 nla_get_u32(cat_loc)] =
314 nla_get_u32(cat_rem);
315 doi_def->map.std->cat.cipso[
316 nla_get_u32(cat_rem)] =
317 nla_get_u32(cat_loc);
318 }
230 } 319 }
231 320
232 doi_def->doi = doi;
233 ret_val = cipso_v4_doi_add(doi_def); 321 ret_val = cipso_v4_doi_add(doi_def);
234 if (ret_val != 0) 322 if (ret_val != 0)
235 goto add_std_failure; 323 goto add_std_failure;
@@ -243,9 +331,7 @@ add_std_failure:
243 331
244/** 332/**
245 * netlbl_cipsov4_add_pass - Adds a CIPSO V4 DOI definition 333 * netlbl_cipsov4_add_pass - Adds a CIPSO V4 DOI definition
246 * @doi: the DOI value 334 * @info: the Generic NETLINK info block
247 * @msg: the ADD message data
248 * @msg_size: the size of the ADD message buffer
249 * 335 *
250 * Description: 336 * Description:
251 * Create a new CIPSO_V4_MAP_PASS DOI definition based on the given ADD message 337 * Create a new CIPSO_V4_MAP_PASS DOI definition based on the given ADD message
@@ -253,52 +339,31 @@ add_std_failure:
253 * error. 339 * error.
254 * 340 *
255 */ 341 */
256static int netlbl_cipsov4_add_pass(u32 doi, 342static int netlbl_cipsov4_add_pass(struct genl_info *info)
257 struct nlattr *msg,
258 size_t msg_size)
259{ 343{
260 int ret_val = -EINVAL; 344 int ret_val;
261 int msg_len = msg_size;
262 u32 num_tags;
263 struct cipso_v4_doi *doi_def = NULL; 345 struct cipso_v4_doi *doi_def = NULL;
264 u32 iter;
265 346
266 if (msg_len < NETLBL_LEN_U32) 347 if (!info->attrs[NLBL_CIPSOV4_A_DOI] ||
267 goto add_pass_failure; 348 !info->attrs[NLBL_CIPSOV4_A_TAGLST])
268 num_tags = netlbl_getinc_u32(&msg, &msg_len); 349 return -EINVAL;
269 if (num_tags == 0 || num_tags > CIPSO_V4_TAG_MAXCNT)
270 goto add_pass_failure;
271 350
272 doi_def = kmalloc(sizeof(*doi_def), GFP_KERNEL); 351 doi_def = kmalloc(sizeof(*doi_def), GFP_KERNEL);
273 if (doi_def == NULL) { 352 if (doi_def == NULL)
274 ret_val = -ENOMEM; 353 return -ENOMEM;
275 goto add_pass_failure;
276 }
277 doi_def->type = CIPSO_V4_MAP_PASS; 354 doi_def->type = CIPSO_V4_MAP_PASS;
278 355
279 for (iter = 0; iter < num_tags; iter++) { 356 ret_val = netlbl_cipsov4_add_common(info, doi_def);
280 if (msg_len < NETLBL_LEN_U8) 357 if (ret_val != 0)
281 goto add_pass_failure; 358 goto add_pass_failure;
282 doi_def->tags[iter] = netlbl_getinc_u8(&msg, &msg_len);
283 switch (doi_def->tags[iter]) {
284 case CIPSO_V4_TAG_RBITMAP:
285 break;
286 default:
287 goto add_pass_failure;
288 }
289 }
290 if (iter < CIPSO_V4_TAG_MAXCNT)
291 doi_def->tags[iter] = CIPSO_V4_TAG_INVALID;
292 359
293 doi_def->doi = doi;
294 ret_val = cipso_v4_doi_add(doi_def); 360 ret_val = cipso_v4_doi_add(doi_def);
295 if (ret_val != 0) 361 if (ret_val != 0)
296 goto add_pass_failure; 362 goto add_pass_failure;
297 return 0; 363 return 0;
298 364
299add_pass_failure: 365add_pass_failure:
300 if (doi_def) 366 netlbl_cipsov4_doi_free(&doi_def->rcu);
301 netlbl_cipsov4_doi_free(&doi_def->rcu);
302 return ret_val; 367 return ret_val;
303} 368}
304 369
@@ -316,34 +381,21 @@ static int netlbl_cipsov4_add(struct sk_buff *skb, struct genl_info *info)
316 381
317{ 382{
318 int ret_val = -EINVAL; 383 int ret_val = -EINVAL;
319 u32 doi;
320 u32 map_type; 384 u32 map_type;
321 int msg_len = netlbl_netlink_payload_len(skb);
322 struct nlattr *msg = netlbl_netlink_payload_data(skb);
323
324 ret_val = netlbl_netlink_cap_check(skb, CAP_NET_ADMIN);
325 if (ret_val != 0)
326 goto add_return;
327 385
328 if (msg_len < 2 * NETLBL_LEN_U32) 386 if (!info->attrs[NLBL_CIPSOV4_A_MTYPE])
329 goto add_return; 387 return -EINVAL;
330 388
331 doi = netlbl_getinc_u32(&msg, &msg_len); 389 map_type = nla_get_u32(info->attrs[NLBL_CIPSOV4_A_MTYPE]);
332 map_type = netlbl_getinc_u32(&msg, &msg_len);
333 switch (map_type) { 390 switch (map_type) {
334 case CIPSO_V4_MAP_STD: 391 case CIPSO_V4_MAP_STD:
335 ret_val = netlbl_cipsov4_add_std(doi, msg, msg_len); 392 ret_val = netlbl_cipsov4_add_std(info);
336 break; 393 break;
337 case CIPSO_V4_MAP_PASS: 394 case CIPSO_V4_MAP_PASS:
338 ret_val = netlbl_cipsov4_add_pass(doi, msg, msg_len); 395 ret_val = netlbl_cipsov4_add_pass(info);
339 break; 396 break;
340 } 397 }
341 398
342add_return:
343 netlbl_netlink_send_ack(info,
344 netlbl_cipsov4_gnl_family.id,
345 NLBL_CIPSOV4_C_ACK,
346 -ret_val);
347 return ret_val; 399 return ret_val;
348} 400}
349 401
@@ -353,84 +405,239 @@ add_return:
353 * @info: the Generic NETLINK info block 405 * @info: the Generic NETLINK info block
354 * 406 *
355 * Description: 407 * Description:
356 * Process a user generated LIST message and respond accordingly. Returns 408 * Process a user generated LIST message and respond accordingly. While the
357 * zero on success and negative values on error. 409 * response message generated by the kernel is straightforward, determining
410 * before hand the size of the buffer to allocate is not (we have to generate
411 * the message to know the size). In order to keep this function sane what we
412 * do is allocate a buffer of NLMSG_GOODSIZE and try to fit the response in
413 * that size, if we fail then we restart with a larger buffer and try again.
414 * We continue in this manner until we hit a limit of failed attempts then we
415 * give up and just send an error message. Returns zero on success and
416 * negative values on error.
358 * 417 *
359 */ 418 */
360static int netlbl_cipsov4_list(struct sk_buff *skb, struct genl_info *info) 419static int netlbl_cipsov4_list(struct sk_buff *skb, struct genl_info *info)
361{ 420{
362 int ret_val = -EINVAL; 421 int ret_val;
422 struct sk_buff *ans_skb = NULL;
423 u32 nlsze_mult = 1;
424 void *data;
363 u32 doi; 425 u32 doi;
364 struct nlattr *msg = netlbl_netlink_payload_data(skb); 426 struct nlattr *nla_a;
365 struct sk_buff *ans_skb; 427 struct nlattr *nla_b;
428 struct cipso_v4_doi *doi_def;
429 u32 iter;
366 430
367 if (netlbl_netlink_payload_len(skb) != NETLBL_LEN_U32) 431 if (!info->attrs[NLBL_CIPSOV4_A_DOI]) {
432 ret_val = -EINVAL;
368 goto list_failure; 433 goto list_failure;
434 }
369 435
370 doi = nla_get_u32(msg); 436list_start:
371 ans_skb = cipso_v4_doi_dump(doi, NLMSG_SPACE(GENL_HDRLEN)); 437 ans_skb = nlmsg_new(NLMSG_GOODSIZE * nlsze_mult, GFP_KERNEL);
372 if (ans_skb == NULL) { 438 if (ans_skb == NULL) {
373 ret_val = -ENOMEM; 439 ret_val = -ENOMEM;
374 goto list_failure; 440 goto list_failure;
375 } 441 }
376 netlbl_netlink_hdr_push(ans_skb, 442 data = netlbl_netlink_hdr_put(ans_skb,
377 info->snd_pid, 443 info->snd_pid,
378 0, 444 info->snd_seq,
379 netlbl_cipsov4_gnl_family.id, 445 netlbl_cipsov4_gnl_family.id,
380 NLBL_CIPSOV4_C_LIST); 446 0,
447 NLBL_CIPSOV4_C_LIST);
448 if (data == NULL) {
449 ret_val = -ENOMEM;
450 goto list_failure;
451 }
452
453 doi = nla_get_u32(info->attrs[NLBL_CIPSOV4_A_DOI]);
454
455 rcu_read_lock();
456 doi_def = cipso_v4_doi_getdef(doi);
457 if (doi_def == NULL) {
458 ret_val = -EINVAL;
459 goto list_failure;
460 }
461
462 ret_val = nla_put_u32(ans_skb, NLBL_CIPSOV4_A_MTYPE, doi_def->type);
463 if (ret_val != 0)
464 goto list_failure_lock;
465
466 nla_a = nla_nest_start(ans_skb, NLBL_CIPSOV4_A_TAGLST);
467 if (nla_a == NULL) {
468 ret_val = -ENOMEM;
469 goto list_failure_lock;
470 }
471 for (iter = 0;
472 iter < CIPSO_V4_TAG_MAXCNT &&
473 doi_def->tags[iter] != CIPSO_V4_TAG_INVALID;
474 iter++) {
475 ret_val = nla_put_u8(ans_skb,
476 NLBL_CIPSOV4_A_TAG,
477 doi_def->tags[iter]);
478 if (ret_val != 0)
479 goto list_failure_lock;
480 }
481 nla_nest_end(ans_skb, nla_a);
482
483 switch (doi_def->type) {
484 case CIPSO_V4_MAP_STD:
485 nla_a = nla_nest_start(ans_skb, NLBL_CIPSOV4_A_MLSLVLLST);
486 if (nla_a == NULL) {
487 ret_val = -ENOMEM;
488 goto list_failure_lock;
489 }
490 for (iter = 0;
491 iter < doi_def->map.std->lvl.local_size;
492 iter++) {
493 if (doi_def->map.std->lvl.local[iter] ==
494 CIPSO_V4_INV_LVL)
495 continue;
496
497 nla_b = nla_nest_start(ans_skb, NLBL_CIPSOV4_A_MLSLVL);
498 if (nla_b == NULL) {
499 ret_val = -ENOMEM;
500 goto list_retry;
501 }
502 ret_val = nla_put_u32(ans_skb,
503 NLBL_CIPSOV4_A_MLSLVLLOC,
504 iter);
505 if (ret_val != 0)
506 goto list_retry;
507 ret_val = nla_put_u32(ans_skb,
508 NLBL_CIPSOV4_A_MLSLVLREM,
509 doi_def->map.std->lvl.local[iter]);
510 if (ret_val != 0)
511 goto list_retry;
512 nla_nest_end(ans_skb, nla_b);
513 }
514 nla_nest_end(ans_skb, nla_a);
515
516 nla_a = nla_nest_start(ans_skb, NLBL_CIPSOV4_A_MLSCATLST);
517 if (nla_a == NULL) {
518 ret_val = -ENOMEM;
519 goto list_retry;
520 }
521 for (iter = 0;
522 iter < doi_def->map.std->cat.local_size;
523 iter++) {
524 if (doi_def->map.std->cat.local[iter] ==
525 CIPSO_V4_INV_CAT)
526 continue;
527
528 nla_b = nla_nest_start(ans_skb, NLBL_CIPSOV4_A_MLSCAT);
529 if (nla_b == NULL) {
530 ret_val = -ENOMEM;
531 goto list_retry;
532 }
533 ret_val = nla_put_u32(ans_skb,
534 NLBL_CIPSOV4_A_MLSCATLOC,
535 iter);
536 if (ret_val != 0)
537 goto list_retry;
538 ret_val = nla_put_u32(ans_skb,
539 NLBL_CIPSOV4_A_MLSCATREM,
540 doi_def->map.std->cat.local[iter]);
541 if (ret_val != 0)
542 goto list_retry;
543 nla_nest_end(ans_skb, nla_b);
544 }
545 nla_nest_end(ans_skb, nla_a);
546
547 break;
548 }
549 rcu_read_unlock();
381 550
382 ret_val = netlbl_netlink_snd(ans_skb, info->snd_pid); 551 genlmsg_end(ans_skb, data);
552
553 ret_val = genlmsg_unicast(ans_skb, info->snd_pid);
383 if (ret_val != 0) 554 if (ret_val != 0)
384 goto list_failure; 555 goto list_failure;
385 556
386 return 0; 557 return 0;
387 558
559list_retry:
560 /* XXX - this limit is a guesstimate */
561 if (nlsze_mult < 4) {
562 rcu_read_unlock();
563 kfree_skb(ans_skb);
564 nlsze_mult++;
565 goto list_start;
566 }
567list_failure_lock:
568 rcu_read_unlock();
388list_failure: 569list_failure:
389 netlbl_netlink_send_ack(info, 570 kfree_skb(ans_skb);
390 netlbl_cipsov4_gnl_family.id, 571 return ret_val;
391 NLBL_CIPSOV4_C_ACK, 572}
392 -ret_val); 573
574/**
575 * netlbl_cipsov4_listall_cb - cipso_v4_doi_walk() callback for LISTALL
576 * @doi_def: the CIPSOv4 DOI definition
577 * @arg: the netlbl_cipsov4_doiwalk_arg structure
578 *
579 * Description:
580 * This function is designed to be used as a callback to the
581 * cipso_v4_doi_walk() function for use in generating a response for a LISTALL
582 * message. Returns the size of the message on success, negative values on
583 * failure.
584 *
585 */
586static int netlbl_cipsov4_listall_cb(struct cipso_v4_doi *doi_def, void *arg)
587{
588 int ret_val = -ENOMEM;
589 struct netlbl_cipsov4_doiwalk_arg *cb_arg = arg;
590 void *data;
591
592 data = netlbl_netlink_hdr_put(cb_arg->skb,
593 NETLINK_CB(cb_arg->nl_cb->skb).pid,
594 cb_arg->seq,
595 netlbl_cipsov4_gnl_family.id,
596 NLM_F_MULTI,
597 NLBL_CIPSOV4_C_LISTALL);
598 if (data == NULL)
599 goto listall_cb_failure;
600
601 ret_val = nla_put_u32(cb_arg->skb, NLBL_CIPSOV4_A_DOI, doi_def->doi);
602 if (ret_val != 0)
603 goto listall_cb_failure;
604 ret_val = nla_put_u32(cb_arg->skb,
605 NLBL_CIPSOV4_A_MTYPE,
606 doi_def->type);
607 if (ret_val != 0)
608 goto listall_cb_failure;
609
610 return genlmsg_end(cb_arg->skb, data);
611
612listall_cb_failure:
613 genlmsg_cancel(cb_arg->skb, data);
393 return ret_val; 614 return ret_val;
394} 615}
395 616
396/** 617/**
397 * netlbl_cipsov4_listall - Handle a LISTALL message 618 * netlbl_cipsov4_listall - Handle a LISTALL message
398 * @skb: the NETLINK buffer 619 * @skb: the NETLINK buffer
399 * @info: the Generic NETLINK info block 620 * @cb: the NETLINK callback
400 * 621 *
401 * Description: 622 * Description:
402 * Process a user generated LISTALL message and respond accordingly. Returns 623 * Process a user generated LISTALL message and respond accordingly. Returns
403 * zero on success and negative values on error. 624 * zero on success and negative values on error.
404 * 625 *
405 */ 626 */
406static int netlbl_cipsov4_listall(struct sk_buff *skb, struct genl_info *info) 627static int netlbl_cipsov4_listall(struct sk_buff *skb,
628 struct netlink_callback *cb)
407{ 629{
408 int ret_val = -EINVAL; 630 struct netlbl_cipsov4_doiwalk_arg cb_arg;
409 struct sk_buff *ans_skb; 631 int doi_skip = cb->args[0];
410 632
411 ans_skb = cipso_v4_doi_dump_all(NLMSG_SPACE(GENL_HDRLEN)); 633 cb_arg.nl_cb = cb;
412 if (ans_skb == NULL) { 634 cb_arg.skb = skb;
413 ret_val = -ENOMEM; 635 cb_arg.seq = cb->nlh->nlmsg_seq;
414 goto listall_failure;
415 }
416 netlbl_netlink_hdr_push(ans_skb,
417 info->snd_pid,
418 0,
419 netlbl_cipsov4_gnl_family.id,
420 NLBL_CIPSOV4_C_LISTALL);
421 636
422 ret_val = netlbl_netlink_snd(ans_skb, info->snd_pid); 637 cipso_v4_doi_walk(&doi_skip, netlbl_cipsov4_listall_cb, &cb_arg);
423 if (ret_val != 0)
424 goto listall_failure;
425
426 return 0;
427 638
428listall_failure: 639 cb->args[0] = doi_skip;
429 netlbl_netlink_send_ack(info, 640 return skb->len;
430 netlbl_cipsov4_gnl_family.id,
431 NLBL_CIPSOV4_C_ACK,
432 -ret_val);
433 return ret_val;
434} 641}
435 642
436/** 643/**
@@ -445,27 +652,14 @@ listall_failure:
445 */ 652 */
446static int netlbl_cipsov4_remove(struct sk_buff *skb, struct genl_info *info) 653static int netlbl_cipsov4_remove(struct sk_buff *skb, struct genl_info *info)
447{ 654{
448 int ret_val; 655 int ret_val = -EINVAL;
449 u32 doi; 656 u32 doi;
450 struct nlattr *msg = netlbl_netlink_payload_data(skb);
451 657
452 ret_val = netlbl_netlink_cap_check(skb, CAP_NET_ADMIN); 658 if (info->attrs[NLBL_CIPSOV4_A_DOI]) {
453 if (ret_val != 0) 659 doi = nla_get_u32(info->attrs[NLBL_CIPSOV4_A_DOI]);
454 goto remove_return; 660 ret_val = cipso_v4_doi_remove(doi, netlbl_cipsov4_doi_free);
455
456 if (netlbl_netlink_payload_len(skb) != NETLBL_LEN_U32) {
457 ret_val = -EINVAL;
458 goto remove_return;
459 } 661 }
460 662
461 doi = nla_get_u32(msg);
462 ret_val = cipso_v4_doi_remove(doi, netlbl_cipsov4_doi_free);
463
464remove_return:
465 netlbl_netlink_send_ack(info,
466 netlbl_cipsov4_gnl_family.id,
467 NLBL_CIPSOV4_C_ACK,
468 -ret_val);
469 return ret_val; 663 return ret_val;
470} 664}
471 665
@@ -475,14 +669,16 @@ remove_return:
475 669
476static struct genl_ops netlbl_cipsov4_genl_c_add = { 670static struct genl_ops netlbl_cipsov4_genl_c_add = {
477 .cmd = NLBL_CIPSOV4_C_ADD, 671 .cmd = NLBL_CIPSOV4_C_ADD,
478 .flags = 0, 672 .flags = GENL_ADMIN_PERM,
673 .policy = netlbl_cipsov4_genl_policy,
479 .doit = netlbl_cipsov4_add, 674 .doit = netlbl_cipsov4_add,
480 .dumpit = NULL, 675 .dumpit = NULL,
481}; 676};
482 677
483static struct genl_ops netlbl_cipsov4_genl_c_remove = { 678static struct genl_ops netlbl_cipsov4_genl_c_remove = {
484 .cmd = NLBL_CIPSOV4_C_REMOVE, 679 .cmd = NLBL_CIPSOV4_C_REMOVE,
485 .flags = 0, 680 .flags = GENL_ADMIN_PERM,
681 .policy = netlbl_cipsov4_genl_policy,
486 .doit = netlbl_cipsov4_remove, 682 .doit = netlbl_cipsov4_remove,
487 .dumpit = NULL, 683 .dumpit = NULL,
488}; 684};
@@ -490,6 +686,7 @@ static struct genl_ops netlbl_cipsov4_genl_c_remove = {
490static struct genl_ops netlbl_cipsov4_genl_c_list = { 686static struct genl_ops netlbl_cipsov4_genl_c_list = {
491 .cmd = NLBL_CIPSOV4_C_LIST, 687 .cmd = NLBL_CIPSOV4_C_LIST,
492 .flags = 0, 688 .flags = 0,
689 .policy = netlbl_cipsov4_genl_policy,
493 .doit = netlbl_cipsov4_list, 690 .doit = netlbl_cipsov4_list,
494 .dumpit = NULL, 691 .dumpit = NULL,
495}; 692};
@@ -497,8 +694,9 @@ static struct genl_ops netlbl_cipsov4_genl_c_list = {
497static struct genl_ops netlbl_cipsov4_genl_c_listall = { 694static struct genl_ops netlbl_cipsov4_genl_c_listall = {
498 .cmd = NLBL_CIPSOV4_C_LISTALL, 695 .cmd = NLBL_CIPSOV4_C_LISTALL,
499 .flags = 0, 696 .flags = 0,
500 .doit = netlbl_cipsov4_listall, 697 .policy = netlbl_cipsov4_genl_policy,
501 .dumpit = NULL, 698 .doit = NULL,
699 .dumpit = netlbl_cipsov4_listall,
502}; 700};
503 701
504/* 702/*
diff --git a/net/netlabel/netlabel_cipso_v4.h b/net/netlabel/netlabel_cipso_v4.h
index 4c6ff4b93004..f03cf9b78286 100644
--- a/net/netlabel/netlabel_cipso_v4.h
+++ b/net/netlabel/netlabel_cipso_v4.h
@@ -34,175 +34,71 @@
34#include <net/netlabel.h> 34#include <net/netlabel.h>
35 35
36/* 36/*
37 * The following NetLabel payloads are supported by the CIPSO subsystem, all 37 * The following NetLabel payloads are supported by the CIPSO subsystem.
38 * of which are preceeded by the nlmsghdr struct.
39 * 38 *
40 * o ACK: 39 * o ADD:
41 * Sent by the kernel in response to an applications message, applications 40 * Sent by an application to add a new DOI mapping table.
42 * should never send this message.
43 * 41 *
44 * +----------------------+-----------------------+ 42 * Required attributes:
45 * | seq number (32 bits) | return code (32 bits) |
46 * +----------------------+-----------------------+
47 * 43 *
48 * seq number: the sequence number of the original message, taken from the 44 * NLBL_CIPSOV4_A_DOI
49 * nlmsghdr structure 45 * NLBL_CIPSOV4_A_MTYPE
50 * return code: return value, based on errno values 46 * NLBL_CIPSOV4_A_TAGLST
51 * 47 *
52 * o ADD: 48 * If using CIPSO_V4_MAP_STD the following attributes are required:
53 * Sent by an application to add a new DOI mapping table, after completion 49 *
54 * of the task the kernel should ACK this message. 50 * NLBL_CIPSOV4_A_MLSLVLLST
55 * 51 * NLBL_CIPSOV4_A_MLSCATLST
56 * +---------------+--------------------+---------------------+ 52 *
57 * | DOI (32 bits) | map type (32 bits) | tag count (32 bits) | ... 53 * If using CIPSO_V4_MAP_PASS no additional attributes are required.
58 * +---------------+--------------------+---------------------+
59 *
60 * +-----------------+
61 * | tag #X (8 bits) | ... repeated
62 * +-----------------+
63 *
64 * +-------------- ---- --- -- -
65 * | mapping data
66 * +-------------- ---- --- -- -
67 *
68 * DOI: the DOI value
69 * map type: the mapping table type (defined in the cipso_ipv4.h header
70 * as CIPSO_V4_MAP_*)
71 * tag count: the number of tags, must be greater than zero
72 * tag: the CIPSO tag for the DOI, tags listed first are given
73 * higher priorirty when sending packets
74 * mapping data: specific to the map type (see below)
75 *
76 * CIPSO_V4_MAP_STD
77 *
78 * +------------------+-----------------------+----------------------+
79 * | levels (32 bits) | max l level (32 bits) | max r level (8 bits) | ...
80 * +------------------+-----------------------+----------------------+
81 *
82 * +----------------------+---------------------+---------------------+
83 * | categories (32 bits) | max l cat (32 bits) | max r cat (16 bits) | ...
84 * +----------------------+---------------------+---------------------+
85 *
86 * +--------------------------+-------------------------+
87 * | local level #X (32 bits) | CIPSO level #X (8 bits) | ... repeated
88 * +--------------------------+-------------------------+
89 *
90 * +-----------------------------+-----------------------------+
91 * | local category #X (32 bits) | CIPSO category #X (16 bits) | ... repeated
92 * +-----------------------------+-----------------------------+
93 *
94 * levels: the number of level mappings
95 * max l level: the highest local level
96 * max r level: the highest remote/CIPSO level
97 * categories: the number of category mappings
98 * max l cat: the highest local category
99 * max r cat: the highest remote/CIPSO category
100 * local level: the local part of a level mapping
101 * CIPSO level: the remote/CIPSO part of a level mapping
102 * local category: the local part of a category mapping
103 * CIPSO category: the remote/CIPSO part of a category mapping
104 *
105 * CIPSO_V4_MAP_PASS
106 *
107 * No mapping data is needed for this map type.
108 * 54 *
109 * o REMOVE: 55 * o REMOVE:
110 * Sent by an application to remove a specific DOI mapping table from the 56 * Sent by an application to remove a specific DOI mapping table from the
111 * CIPSO V4 system. The kernel should ACK this message. 57 * CIPSO V4 system.
112 * 58 *
113 * +---------------+ 59 * Required attributes:
114 * | DOI (32 bits) |
115 * +---------------+
116 * 60 *
117 * DOI: the DOI value 61 * NLBL_CIPSOV4_A_DOI
118 * 62 *
119 * o LIST: 63 * o LIST:
120 * Sent by an application to list the details of a DOI definition. The 64 * Sent by an application to list the details of a DOI definition. On
121 * kernel should send an ACK on error or a response as indicated below. The 65 * success the kernel should send a response using the following format.
122 * application generated message format is shown below.
123 * 66 *
124 * +---------------+ 67 * Required attributes:
125 * | DOI (32 bits) |
126 * +---------------+
127 * 68 *
128 * DOI: the DOI value 69 * NLBL_CIPSOV4_A_DOI
129 * 70 *
130 * The valid response message format depends on the type of the DOI mapping, 71 * The valid response message format depends on the type of the DOI mapping,
131 * the known formats are shown below. 72 * the defined formats are shown below.
132 *
133 * +--------------------+
134 * | map type (32 bits) | ...
135 * +--------------------+
136 *
137 * map type: the DOI mapping table type (defined in the cipso_ipv4.h
138 * header as CIPSO_V4_MAP_*)
139 *
140 * (map type == CIPSO_V4_MAP_STD)
141 *
142 * +----------------+------------------+----------------------+
143 * | tags (32 bits) | levels (32 bits) | categories (32 bits) | ...
144 * +----------------+------------------+----------------------+
145 * 73 *
146 * +-----------------+ 74 * Required attributes:
147 * | tag #X (8 bits) | ... repeated
148 * +-----------------+
149 * 75 *
150 * +--------------------------+-------------------------+ 76 * NLBL_CIPSOV4_A_MTYPE
151 * | local level #X (32 bits) | CIPSO level #X (8 bits) | ... repeated 77 * NLBL_CIPSOV4_A_TAGLST
152 * +--------------------------+-------------------------+
153 * 78 *
154 * +-----------------------------+-----------------------------+ 79 * If using CIPSO_V4_MAP_STD the following attributes are required:
155 * | local category #X (32 bits) | CIPSO category #X (16 bits) | ... repeated
156 * +-----------------------------+-----------------------------+
157 * 80 *
158 * tags: the number of CIPSO tag types 81 * NLBL_CIPSOV4_A_MLSLVLLST
159 * levels: the number of level mappings 82 * NLBL_CIPSOV4_A_MLSCATLST
160 * categories: the number of category mappings
161 * tag: the tag number, tags listed first are given higher
162 * priority when sending packets
163 * local level: the local part of a level mapping
164 * CIPSO level: the remote/CIPSO part of a level mapping
165 * local category: the local part of a category mapping
166 * CIPSO category: the remote/CIPSO part of a category mapping
167 * 83 *
168 * (map type == CIPSO_V4_MAP_PASS) 84 * If using CIPSO_V4_MAP_PASS no additional attributes are required.
169 *
170 * +----------------+
171 * | tags (32 bits) | ...
172 * +----------------+
173 *
174 * +-----------------+
175 * | tag #X (8 bits) | ... repeated
176 * +-----------------+
177 *
178 * tags: the number of CIPSO tag types
179 * tag: the tag number, tags listed first are given higher
180 * priority when sending packets
181 * 85 *
182 * o LISTALL: 86 * o LISTALL:
183 * This message is sent by an application to list the valid DOIs on the 87 * This message is sent by an application to list the valid DOIs on the
184 * system. There is no payload and the kernel should respond with an ACK 88 * system. When sent by an application there is no payload and the
185 * or the following message. 89 * NLM_F_DUMP flag should be set. The kernel should respond with a series of
186 * 90 * the following messages.
187 * +---------------------+------------------+-----------------------+
188 * | DOI count (32 bits) | DOI #X (32 bits) | map type #X (32 bits) |
189 * +---------------------+------------------+-----------------------+
190 * 91 *
191 * +-----------------------+ 92 * Required attributes:
192 * | map type #X (32 bits) | ...
193 * +-----------------------+
194 * 93 *
195 * DOI count: the number of DOIs 94 * NLBL_CIPSOV4_A_DOI
196 * DOI: the DOI value 95 * NLBL_CIPSOV4_A_MTYPE
197 * map type: the DOI mapping table type (defined in the cipso_ipv4.h
198 * header as CIPSO_V4_MAP_*)
199 * 96 *
200 */ 97 */
201 98
202/* NetLabel CIPSOv4 commands */ 99/* NetLabel CIPSOv4 commands */
203enum { 100enum {
204 NLBL_CIPSOV4_C_UNSPEC, 101 NLBL_CIPSOV4_C_UNSPEC,
205 NLBL_CIPSOV4_C_ACK,
206 NLBL_CIPSOV4_C_ADD, 102 NLBL_CIPSOV4_C_ADD,
207 NLBL_CIPSOV4_C_REMOVE, 103 NLBL_CIPSOV4_C_REMOVE,
208 NLBL_CIPSOV4_C_LIST, 104 NLBL_CIPSOV4_C_LIST,
@@ -211,6 +107,59 @@ enum {
211}; 107};
212#define NLBL_CIPSOV4_C_MAX (__NLBL_CIPSOV4_C_MAX - 1) 108#define NLBL_CIPSOV4_C_MAX (__NLBL_CIPSOV4_C_MAX - 1)
213 109
110/* NetLabel CIPSOv4 attributes */
111enum {
112 NLBL_CIPSOV4_A_UNSPEC,
113 NLBL_CIPSOV4_A_DOI,
114 /* (NLA_U32)
115 * the DOI value */
116 NLBL_CIPSOV4_A_MTYPE,
117 /* (NLA_U32)
118 * the mapping table type (defined in the cipso_ipv4.h header as
119 * CIPSO_V4_MAP_*) */
120 NLBL_CIPSOV4_A_TAG,
121 /* (NLA_U8)
122 * a CIPSO tag type, meant to be used within a NLBL_CIPSOV4_A_TAGLST
123 * attribute */
124 NLBL_CIPSOV4_A_TAGLST,
125 /* (NLA_NESTED)
126 * the CIPSO tag list for the DOI, there must be at least one
127 * NLBL_CIPSOV4_A_TAG attribute, tags listed first are given higher
128 * priorirty when sending packets */
129 NLBL_CIPSOV4_A_MLSLVLLOC,
130 /* (NLA_U32)
131 * the local MLS sensitivity level */
132 NLBL_CIPSOV4_A_MLSLVLREM,
133 /* (NLA_U32)
134 * the remote MLS sensitivity level */
135 NLBL_CIPSOV4_A_MLSLVL,
136 /* (NLA_NESTED)
137 * a MLS sensitivity level mapping, must contain only one attribute of
138 * each of the following types: NLBL_CIPSOV4_A_MLSLVLLOC and
139 * NLBL_CIPSOV4_A_MLSLVLREM */
140 NLBL_CIPSOV4_A_MLSLVLLST,
141 /* (NLA_NESTED)
142 * the CIPSO level mappings, there must be at least one
143 * NLBL_CIPSOV4_A_MLSLVL attribute */
144 NLBL_CIPSOV4_A_MLSCATLOC,
145 /* (NLA_U32)
146 * the local MLS category */
147 NLBL_CIPSOV4_A_MLSCATREM,
148 /* (NLA_U32)
149 * the remote MLS category */
150 NLBL_CIPSOV4_A_MLSCAT,
151 /* (NLA_NESTED)
152 * a MLS category mapping, must contain only one attribute of each of
153 * the following types: NLBL_CIPSOV4_A_MLSCATLOC and
154 * NLBL_CIPSOV4_A_MLSCATREM */
155 NLBL_CIPSOV4_A_MLSCATLST,
156 /* (NLA_NESTED)
157 * the CIPSO category mappings, there must be at least one
158 * NLBL_CIPSOV4_A_MLSCAT attribute */
159 __NLBL_CIPSOV4_A_MAX,
160};
161#define NLBL_CIPSOV4_A_MAX (__NLBL_CIPSOV4_A_MAX - 1)
162
214/* NetLabel protocol functions */ 163/* NetLabel protocol functions */
215int netlbl_cipsov4_genl_init(void); 164int netlbl_cipsov4_genl_init(void);
216 165
diff --git a/net/netlabel/netlabel_domainhash.c b/net/netlabel/netlabel_domainhash.c
index 0489a1378101..f56d7a8ac7b7 100644
--- a/net/netlabel/netlabel_domainhash.c
+++ b/net/netlabel/netlabel_domainhash.c
@@ -354,160 +354,51 @@ struct netlbl_dom_map *netlbl_domhsh_getentry(const char *domain)
354} 354}
355 355
356/** 356/**
357 * netlbl_domhsh_dump - Dump the domain hash table into a sk_buff 357 * netlbl_domhsh_walk - Iterate through the domain mapping hash table
358 * @skip_bkt: the number of buckets to skip at the start
359 * @skip_chain: the number of entries to skip in the first iterated bucket
360 * @callback: callback for each entry
361 * @cb_arg: argument for the callback function
358 * 362 *
359 * Description: 363 * Description:
360 * Dump the domain hash table into a buffer suitable for returning to an 364 * Interate over the domain mapping hash table, skipping the first @skip_bkt
361 * application in response to a NetLabel management DOMAIN message. This 365 * buckets and @skip_chain entries. For each entry in the table call
362 * function may fail if another process is growing the hash table at the same 366 * @callback, if @callback returns a negative value stop 'walking' through the
363 * time. The returned sk_buff has room at the front of the sk_buff for 367 * table and return. Updates the values in @skip_bkt and @skip_chain on
364 * @headroom bytes. See netlabel.h for the DOMAIN message format. Returns a 368 * return. Returns zero on succcess, negative values on failure.
365 * pointer to a sk_buff on success, NULL on error.
366 * 369 *
367 */ 370 */
368struct sk_buff *netlbl_domhsh_dump(size_t headroom) 371int netlbl_domhsh_walk(u32 *skip_bkt,
372 u32 *skip_chain,
373 int (*callback) (struct netlbl_dom_map *entry, void *arg),
374 void *cb_arg)
369{ 375{
370 struct sk_buff *skb = NULL; 376 int ret_val = -ENOENT;
371 ssize_t buf_len; 377 u32 iter_bkt;
372 u32 bkt_iter; 378 struct netlbl_dom_map *iter_entry;
373 u32 dom_cnt = 0; 379 u32 chain_cnt = 0;
374 struct netlbl_domhsh_tbl *hsh_tbl;
375 struct netlbl_dom_map *list_iter;
376 ssize_t tmp_len;
377 380
378 buf_len = NETLBL_LEN_U32;
379 rcu_read_lock(); 381 rcu_read_lock();
380 hsh_tbl = rcu_dereference(netlbl_domhsh); 382 for (iter_bkt = *skip_bkt;
381 for (bkt_iter = 0; bkt_iter < hsh_tbl->size; bkt_iter++) 383 iter_bkt < rcu_dereference(netlbl_domhsh)->size;
382 list_for_each_entry_rcu(list_iter, 384 iter_bkt++, chain_cnt = 0) {
383 &hsh_tbl->tbl[bkt_iter], list) { 385 list_for_each_entry_rcu(iter_entry,
384 buf_len += NETLBL_LEN_U32 + 386 &netlbl_domhsh->tbl[iter_bkt],
385 nla_total_size(strlen(list_iter->domain) + 1); 387 list)
386 switch (list_iter->type) { 388 if (iter_entry->valid) {
387 case NETLBL_NLTYPE_UNLABELED: 389 if (chain_cnt++ < *skip_chain)
388 break; 390 continue;
389 case NETLBL_NLTYPE_CIPSOV4: 391 ret_val = callback(iter_entry, cb_arg);
390 buf_len += 2 * NETLBL_LEN_U32; 392 if (ret_val < 0) {
391 break; 393 chain_cnt--;
392 } 394 goto walk_return;
393 dom_cnt++; 395 }
394 }
395
396 skb = netlbl_netlink_alloc_skb(headroom, buf_len, GFP_ATOMIC);
397 if (skb == NULL)
398 goto dump_failure;
399
400 if (nla_put_u32(skb, NLA_U32, dom_cnt) != 0)
401 goto dump_failure;
402 buf_len -= NETLBL_LEN_U32;
403 hsh_tbl = rcu_dereference(netlbl_domhsh);
404 for (bkt_iter = 0; bkt_iter < hsh_tbl->size; bkt_iter++)
405 list_for_each_entry_rcu(list_iter,
406 &hsh_tbl->tbl[bkt_iter], list) {
407 tmp_len = nla_total_size(strlen(list_iter->domain) +
408 1);
409 if (buf_len < NETLBL_LEN_U32 + tmp_len)
410 goto dump_failure;
411 if (nla_put_string(skb,
412 NLA_STRING,
413 list_iter->domain) != 0)
414 goto dump_failure;
415 if (nla_put_u32(skb, NLA_U32, list_iter->type) != 0)
416 goto dump_failure;
417 buf_len -= NETLBL_LEN_U32 + tmp_len;
418 switch (list_iter->type) {
419 case NETLBL_NLTYPE_UNLABELED:
420 break;
421 case NETLBL_NLTYPE_CIPSOV4:
422 if (buf_len < 2 * NETLBL_LEN_U32)
423 goto dump_failure;
424 if (nla_put_u32(skb,
425 NLA_U32,
426 list_iter->type_def.cipsov4->type) != 0)
427 goto dump_failure;
428 if (nla_put_u32(skb,
429 NLA_U32,
430 list_iter->type_def.cipsov4->doi) != 0)
431 goto dump_failure;
432 buf_len -= 2 * NETLBL_LEN_U32;
433 break;
434 } 396 }
435 } 397 }
436 rcu_read_unlock();
437
438 return skb;
439
440dump_failure:
441 rcu_read_unlock();
442 kfree_skb(skb);
443 return NULL;
444}
445
446/**
447 * netlbl_domhsh_dump_default - Dump the default domain mapping into a sk_buff
448 *
449 * Description:
450 * Dump the default domain mapping into a buffer suitable for returning to an
451 * application in response to a NetLabel management DEFDOMAIN message. This
452 * function may fail if another process is changing the default domain mapping
453 * at the same time. The returned sk_buff has room at the front of the
454 * skb_buff for @headroom bytes. See netlabel.h for the DEFDOMAIN message
455 * format. Returns a pointer to a sk_buff on success, NULL on error.
456 *
457 */
458struct sk_buff *netlbl_domhsh_dump_default(size_t headroom)
459{
460 struct sk_buff *skb;
461 ssize_t buf_len;
462 struct netlbl_dom_map *entry;
463
464 buf_len = NETLBL_LEN_U32;
465 rcu_read_lock();
466 entry = rcu_dereference(netlbl_domhsh_def);
467 if (entry != NULL)
468 switch (entry->type) {
469 case NETLBL_NLTYPE_UNLABELED:
470 break;
471 case NETLBL_NLTYPE_CIPSOV4:
472 buf_len += 2 * NETLBL_LEN_U32;
473 break;
474 }
475
476 skb = netlbl_netlink_alloc_skb(headroom, buf_len, GFP_ATOMIC);
477 if (skb == NULL)
478 goto dump_default_failure;
479
480 if (entry != rcu_dereference(netlbl_domhsh_def))
481 goto dump_default_failure;
482 if (entry != NULL) {
483 if (nla_put_u32(skb, NLA_U32, entry->type) != 0)
484 goto dump_default_failure;
485 buf_len -= NETLBL_LEN_U32;
486 switch (entry->type) {
487 case NETLBL_NLTYPE_UNLABELED:
488 break;
489 case NETLBL_NLTYPE_CIPSOV4:
490 if (buf_len < 2 * NETLBL_LEN_U32)
491 goto dump_default_failure;
492 if (nla_put_u32(skb,
493 NLA_U32,
494 entry->type_def.cipsov4->type) != 0)
495 goto dump_default_failure;
496 if (nla_put_u32(skb,
497 NLA_U32,
498 entry->type_def.cipsov4->doi) != 0)
499 goto dump_default_failure;
500 buf_len -= 2 * NETLBL_LEN_U32;
501 break;
502 }
503 } else
504 nla_put_u32(skb, NLA_U32, NETLBL_NLTYPE_NONE);
505 rcu_read_unlock();
506
507 return skb;
508 398
509dump_default_failure: 399walk_return:
510 rcu_read_unlock(); 400 rcu_read_unlock();
511 kfree_skb(skb); 401 *skip_bkt = iter_bkt;
512 return NULL; 402 *skip_chain = chain_cnt;
403 return ret_val;
513} 404}
diff --git a/net/netlabel/netlabel_domainhash.h b/net/netlabel/netlabel_domainhash.h
index 99a2287de246..02af72a7877c 100644
--- a/net/netlabel/netlabel_domainhash.h
+++ b/net/netlabel/netlabel_domainhash.h
@@ -61,7 +61,9 @@ int netlbl_domhsh_add(struct netlbl_dom_map *entry);
61int netlbl_domhsh_add_default(struct netlbl_dom_map *entry); 61int netlbl_domhsh_add_default(struct netlbl_dom_map *entry);
62int netlbl_domhsh_remove_default(void); 62int netlbl_domhsh_remove_default(void);
63struct netlbl_dom_map *netlbl_domhsh_getentry(const char *domain); 63struct netlbl_dom_map *netlbl_domhsh_getentry(const char *domain);
64struct sk_buff *netlbl_domhsh_dump(size_t headroom); 64int netlbl_domhsh_walk(u32 *skip_bkt,
65struct sk_buff *netlbl_domhsh_dump_default(size_t headroom); 65 u32 *skip_chain,
66 int (*callback) (struct netlbl_dom_map *entry, void *arg),
67 void *cb_arg);
66 68
67#endif 69#endif
diff --git a/net/netlabel/netlabel_kapi.c b/net/netlabel/netlabel_kapi.c
index 0fd8aaafe23f..54fb7de3c2b1 100644
--- a/net/netlabel/netlabel_kapi.c
+++ b/net/netlabel/netlabel_kapi.c
@@ -85,6 +85,29 @@ socket_setattr_return:
85} 85}
86 86
87/** 87/**
88 * netlbl_sock_getattr - Determine the security attributes of a sock
89 * @sk: the sock
90 * @secattr: the security attributes
91 *
92 * Description:
93 * Examines the given sock to see any NetLabel style labeling has been
94 * applied to the sock, if so it parses the socket label and returns the
95 * security attributes in @secattr. Returns zero on success, negative values
96 * on failure.
97 *
98 */
99int netlbl_sock_getattr(struct sock *sk, struct netlbl_lsm_secattr *secattr)
100{
101 int ret_val;
102
103 ret_val = cipso_v4_sock_getattr(sk, secattr);
104 if (ret_val == 0)
105 return 0;
106
107 return netlbl_unlabel_getattr(secattr);
108}
109
110/**
88 * netlbl_socket_getattr - Determine the security attributes of a socket 111 * netlbl_socket_getattr - Determine the security attributes of a socket
89 * @sock: the socket 112 * @sock: the socket
90 * @secattr: the security attributes 113 * @secattr: the security attributes
diff --git a/net/netlabel/netlabel_mgmt.c b/net/netlabel/netlabel_mgmt.c
index 85bc11a1fc46..8626c9f678eb 100644
--- a/net/netlabel/netlabel_mgmt.c
+++ b/net/netlabel/netlabel_mgmt.c
@@ -42,15 +42,29 @@
42#include "netlabel_user.h" 42#include "netlabel_user.h"
43#include "netlabel_mgmt.h" 43#include "netlabel_mgmt.h"
44 44
45/* Argument struct for netlbl_domhsh_walk() */
46struct netlbl_domhsh_walk_arg {
47 struct netlink_callback *nl_cb;
48 struct sk_buff *skb;
49 u32 seq;
50};
51
45/* NetLabel Generic NETLINK CIPSOv4 family */ 52/* NetLabel Generic NETLINK CIPSOv4 family */
46static struct genl_family netlbl_mgmt_gnl_family = { 53static struct genl_family netlbl_mgmt_gnl_family = {
47 .id = GENL_ID_GENERATE, 54 .id = GENL_ID_GENERATE,
48 .hdrsize = 0, 55 .hdrsize = 0,
49 .name = NETLBL_NLTYPE_MGMT_NAME, 56 .name = NETLBL_NLTYPE_MGMT_NAME,
50 .version = NETLBL_PROTO_VERSION, 57 .version = NETLBL_PROTO_VERSION,
51 .maxattr = 0, 58 .maxattr = NLBL_MGMT_A_MAX,
52}; 59};
53 60
61/* NetLabel Netlink attribute policy */
62static struct nla_policy netlbl_mgmt_genl_policy[NLBL_MGMT_A_MAX + 1] = {
63 [NLBL_MGMT_A_DOMAIN] = { .type = NLA_NUL_STRING },
64 [NLBL_MGMT_A_PROTOCOL] = { .type = NLA_U32 },
65 [NLBL_MGMT_A_VERSION] = { .type = NLA_U32 },
66 [NLBL_MGMT_A_CV4DOI] = { .type = NLA_U32 },
67};
54 68
55/* 69/*
56 * NetLabel Command Handlers 70 * NetLabel Command Handlers
@@ -70,97 +84,62 @@ static struct genl_family netlbl_mgmt_gnl_family = {
70static int netlbl_mgmt_add(struct sk_buff *skb, struct genl_info *info) 84static int netlbl_mgmt_add(struct sk_buff *skb, struct genl_info *info)
71{ 85{
72 int ret_val = -EINVAL; 86 int ret_val = -EINVAL;
73 struct nlattr *msg_ptr = netlbl_netlink_payload_data(skb);
74 int msg_len = netlbl_netlink_payload_len(skb);
75 u32 count;
76 struct netlbl_dom_map *entry = NULL; 87 struct netlbl_dom_map *entry = NULL;
77 u32 iter; 88 size_t tmp_size;
78 u32 tmp_val; 89 u32 tmp_val;
79 int tmp_size;
80 90
81 ret_val = netlbl_netlink_cap_check(skb, CAP_NET_ADMIN); 91 if (!info->attrs[NLBL_MGMT_A_DOMAIN] ||
82 if (ret_val != 0) 92 !info->attrs[NLBL_MGMT_A_PROTOCOL])
83 goto add_failure; 93 goto add_failure;
84 94
85 if (msg_len < NETLBL_LEN_U32) 95 entry = kzalloc(sizeof(*entry), GFP_KERNEL);
96 if (entry == NULL) {
97 ret_val = -ENOMEM;
98 goto add_failure;
99 }
100 tmp_size = nla_len(info->attrs[NLBL_MGMT_A_DOMAIN]);
101 entry->domain = kmalloc(tmp_size, GFP_KERNEL);
102 if (entry->domain == NULL) {
103 ret_val = -ENOMEM;
86 goto add_failure; 104 goto add_failure;
87 count = netlbl_getinc_u32(&msg_ptr, &msg_len); 105 }
106 entry->type = nla_get_u32(info->attrs[NLBL_MGMT_A_PROTOCOL]);
107 nla_strlcpy(entry->domain, info->attrs[NLBL_MGMT_A_DOMAIN], tmp_size);
88 108
89 for (iter = 0; iter < count && msg_len > 0; iter++, entry = NULL) { 109 switch (entry->type) {
90 if (msg_len <= 0) { 110 case NETLBL_NLTYPE_UNLABELED:
91 ret_val = -EINVAL; 111 ret_val = netlbl_domhsh_add(entry);
92 goto add_failure; 112 break;
93 } 113 case NETLBL_NLTYPE_CIPSOV4:
94 entry = kzalloc(sizeof(*entry), GFP_KERNEL); 114 if (!info->attrs[NLBL_MGMT_A_CV4DOI])
95 if (entry == NULL) {
96 ret_val = -ENOMEM;
97 goto add_failure;
98 }
99 tmp_size = nla_len(msg_ptr);
100 if (tmp_size <= 0 || tmp_size > msg_len) {
101 ret_val = -EINVAL;
102 goto add_failure;
103 }
104 entry->domain = kmalloc(tmp_size, GFP_KERNEL);
105 if (entry->domain == NULL) {
106 ret_val = -ENOMEM;
107 goto add_failure; 115 goto add_failure;
108 }
109 nla_strlcpy(entry->domain, msg_ptr, tmp_size);
110 entry->domain[tmp_size - 1] = '\0';
111 msg_ptr = nla_next(msg_ptr, &msg_len);
112 116
113 if (msg_len < NETLBL_LEN_U32) { 117 tmp_val = nla_get_u32(info->attrs[NLBL_MGMT_A_CV4DOI]);
114 ret_val = -EINVAL; 118 /* We should be holding a rcu_read_lock() here while we hold
115 goto add_failure; 119 * the result but since the entry will always be deleted when
116 } 120 * the CIPSO DOI is deleted we aren't going to keep the
117 tmp_val = netlbl_getinc_u32(&msg_ptr, &msg_len); 121 * lock. */
118 entry->type = tmp_val; 122 rcu_read_lock();
119 switch (tmp_val) { 123 entry->type_def.cipsov4 = cipso_v4_doi_getdef(tmp_val);
120 case NETLBL_NLTYPE_UNLABELED: 124 if (entry->type_def.cipsov4 == NULL) {
121 ret_val = netlbl_domhsh_add(entry);
122 break;
123 case NETLBL_NLTYPE_CIPSOV4:
124 if (msg_len < NETLBL_LEN_U32) {
125 ret_val = -EINVAL;
126 goto add_failure;
127 }
128 tmp_val = netlbl_getinc_u32(&msg_ptr, &msg_len);
129 /* We should be holding a rcu_read_lock() here
130 * while we hold the result but since the entry
131 * will always be deleted when the CIPSO DOI
132 * is deleted we aren't going to keep the lock. */
133 rcu_read_lock();
134 entry->type_def.cipsov4 = cipso_v4_doi_getdef(tmp_val);
135 if (entry->type_def.cipsov4 == NULL) {
136 rcu_read_unlock();
137 ret_val = -EINVAL;
138 goto add_failure;
139 }
140 ret_val = netlbl_domhsh_add(entry);
141 rcu_read_unlock(); 125 rcu_read_unlock();
142 break;
143 default:
144 ret_val = -EINVAL;
145 }
146 if (ret_val != 0)
147 goto add_failure; 126 goto add_failure;
127 }
128 ret_val = netlbl_domhsh_add(entry);
129 rcu_read_unlock();
130 break;
131 default:
132 goto add_failure;
148 } 133 }
134 if (ret_val != 0)
135 goto add_failure;
149 136
150 netlbl_netlink_send_ack(info,
151 netlbl_mgmt_gnl_family.id,
152 NLBL_MGMT_C_ACK,
153 NETLBL_E_OK);
154 return 0; 137 return 0;
155 138
156add_failure: 139add_failure:
157 if (entry) 140 if (entry)
158 kfree(entry->domain); 141 kfree(entry->domain);
159 kfree(entry); 142 kfree(entry);
160 netlbl_netlink_send_ack(info,
161 netlbl_mgmt_gnl_family.id,
162 NLBL_MGMT_C_ACK,
163 -ret_val);
164 return ret_val; 143 return ret_val;
165} 144}
166 145
@@ -176,87 +155,98 @@ add_failure:
176 */ 155 */
177static int netlbl_mgmt_remove(struct sk_buff *skb, struct genl_info *info) 156static int netlbl_mgmt_remove(struct sk_buff *skb, struct genl_info *info)
178{ 157{
179 int ret_val = -EINVAL; 158 char *domain;
180 struct nlattr *msg_ptr = netlbl_netlink_payload_data(skb);
181 int msg_len = netlbl_netlink_payload_len(skb);
182 u32 count;
183 u32 iter;
184 int tmp_size;
185 unsigned char *domain;
186
187 ret_val = netlbl_netlink_cap_check(skb, CAP_NET_ADMIN);
188 if (ret_val != 0)
189 goto remove_return;
190 159
191 if (msg_len < NETLBL_LEN_U32) 160 if (!info->attrs[NLBL_MGMT_A_DOMAIN])
192 goto remove_return; 161 return -EINVAL;
193 count = netlbl_getinc_u32(&msg_ptr, &msg_len);
194 162
195 for (iter = 0; iter < count && msg_len > 0; iter++) { 163 domain = nla_data(info->attrs[NLBL_MGMT_A_DOMAIN]);
196 if (msg_len <= 0) { 164 return netlbl_domhsh_remove(domain);
197 ret_val = -EINVAL; 165}
198 goto remove_return; 166
199 } 167/**
200 tmp_size = nla_len(msg_ptr); 168 * netlbl_mgmt_listall_cb - netlbl_domhsh_walk() callback for LISTALL
201 domain = nla_data(msg_ptr); 169 * @entry: the domain mapping hash table entry
202 if (tmp_size <= 0 || tmp_size > msg_len || 170 * @arg: the netlbl_domhsh_walk_arg structure
203 domain[tmp_size - 1] != '\0') { 171 *
204 ret_val = -EINVAL; 172 * Description:
205 goto remove_return; 173 * This function is designed to be used as a callback to the
206 } 174 * netlbl_domhsh_walk() function for use in generating a response for a LISTALL
207 ret_val = netlbl_domhsh_remove(domain); 175 * message. Returns the size of the message on success, negative values on
176 * failure.
177 *
178 */
179static int netlbl_mgmt_listall_cb(struct netlbl_dom_map *entry, void *arg)
180{
181 int ret_val = -ENOMEM;
182 struct netlbl_domhsh_walk_arg *cb_arg = arg;
183 void *data;
184
185 data = netlbl_netlink_hdr_put(cb_arg->skb,
186 NETLINK_CB(cb_arg->nl_cb->skb).pid,
187 cb_arg->seq,
188 netlbl_mgmt_gnl_family.id,
189 NLM_F_MULTI,
190 NLBL_MGMT_C_LISTALL);
191 if (data == NULL)
192 goto listall_cb_failure;
193
194 ret_val = nla_put_string(cb_arg->skb,
195 NLBL_MGMT_A_DOMAIN,
196 entry->domain);
197 if (ret_val != 0)
198 goto listall_cb_failure;
199 ret_val = nla_put_u32(cb_arg->skb, NLBL_MGMT_A_PROTOCOL, entry->type);
200 if (ret_val != 0)
201 goto listall_cb_failure;
202 switch (entry->type) {
203 case NETLBL_NLTYPE_CIPSOV4:
204 ret_val = nla_put_u32(cb_arg->skb,
205 NLBL_MGMT_A_CV4DOI,
206 entry->type_def.cipsov4->doi);
208 if (ret_val != 0) 207 if (ret_val != 0)
209 goto remove_return; 208 goto listall_cb_failure;
210 msg_ptr = nla_next(msg_ptr, &msg_len); 209 break;
211 } 210 }
212 211
213 ret_val = 0; 212 cb_arg->seq++;
213 return genlmsg_end(cb_arg->skb, data);
214 214
215remove_return: 215listall_cb_failure:
216 netlbl_netlink_send_ack(info, 216 genlmsg_cancel(cb_arg->skb, data);
217 netlbl_mgmt_gnl_family.id,
218 NLBL_MGMT_C_ACK,
219 -ret_val);
220 return ret_val; 217 return ret_val;
221} 218}
222 219
223/** 220/**
224 * netlbl_mgmt_list - Handle a LIST message 221 * netlbl_mgmt_listall - Handle a LISTALL message
225 * @skb: the NETLINK buffer 222 * @skb: the NETLINK buffer
226 * @info: the Generic NETLINK info block 223 * @cb: the NETLINK callback
227 * 224 *
228 * Description: 225 * Description:
229 * Process a user generated LIST message and dumps the domain hash table in a 226 * Process a user generated LISTALL message and dumps the domain hash table in
230 * form suitable for use in a kernel generated LIST message. Returns zero on 227 * a form suitable for use in a kernel generated LISTALL message. Returns zero
231 * success, negative values on failure. 228 * on success, negative values on failure.
232 * 229 *
233 */ 230 */
234static int netlbl_mgmt_list(struct sk_buff *skb, struct genl_info *info) 231static int netlbl_mgmt_listall(struct sk_buff *skb,
232 struct netlink_callback *cb)
235{ 233{
236 int ret_val = -ENOMEM; 234 struct netlbl_domhsh_walk_arg cb_arg;
237 struct sk_buff *ans_skb; 235 u32 skip_bkt = cb->args[0];
238 236 u32 skip_chain = cb->args[1];
239 ans_skb = netlbl_domhsh_dump(NLMSG_SPACE(GENL_HDRLEN)); 237
240 if (ans_skb == NULL) 238 cb_arg.nl_cb = cb;
241 goto list_failure; 239 cb_arg.skb = skb;
242 netlbl_netlink_hdr_push(ans_skb, 240 cb_arg.seq = cb->nlh->nlmsg_seq;
243 info->snd_pid, 241
244 0, 242 netlbl_domhsh_walk(&skip_bkt,
245 netlbl_mgmt_gnl_family.id, 243 &skip_chain,
246 NLBL_MGMT_C_LIST); 244 netlbl_mgmt_listall_cb,
247 245 &cb_arg);
248 ret_val = netlbl_netlink_snd(ans_skb, info->snd_pid); 246
249 if (ret_val != 0) 247 cb->args[0] = skip_bkt;
250 goto list_failure; 248 cb->args[1] = skip_chain;
251 249 return skb->len;
252 return 0;
253
254list_failure:
255 netlbl_netlink_send_ack(info,
256 netlbl_mgmt_gnl_family.id,
257 NLBL_MGMT_C_ACK,
258 -ret_val);
259 return ret_val;
260} 250}
261 251
262/** 252/**
@@ -272,68 +262,51 @@ list_failure:
272static int netlbl_mgmt_adddef(struct sk_buff *skb, struct genl_info *info) 262static int netlbl_mgmt_adddef(struct sk_buff *skb, struct genl_info *info)
273{ 263{
274 int ret_val = -EINVAL; 264 int ret_val = -EINVAL;
275 struct nlattr *msg_ptr = netlbl_netlink_payload_data(skb);
276 int msg_len = netlbl_netlink_payload_len(skb);
277 struct netlbl_dom_map *entry = NULL; 265 struct netlbl_dom_map *entry = NULL;
278 u32 tmp_val; 266 u32 tmp_val;
279 267
280 ret_val = netlbl_netlink_cap_check(skb, CAP_NET_ADMIN); 268 if (!info->attrs[NLBL_MGMT_A_PROTOCOL])
281 if (ret_val != 0)
282 goto adddef_failure;
283
284 if (msg_len < NETLBL_LEN_U32)
285 goto adddef_failure; 269 goto adddef_failure;
286 tmp_val = netlbl_getinc_u32(&msg_ptr, &msg_len);
287 270
288 entry = kzalloc(sizeof(*entry), GFP_KERNEL); 271 entry = kzalloc(sizeof(*entry), GFP_KERNEL);
289 if (entry == NULL) { 272 if (entry == NULL) {
290 ret_val = -ENOMEM; 273 ret_val = -ENOMEM;
291 goto adddef_failure; 274 goto adddef_failure;
292 } 275 }
276 entry->type = nla_get_u32(info->attrs[NLBL_MGMT_A_PROTOCOL]);
293 277
294 entry->type = tmp_val;
295 switch (entry->type) { 278 switch (entry->type) {
296 case NETLBL_NLTYPE_UNLABELED: 279 case NETLBL_NLTYPE_UNLABELED:
297 ret_val = netlbl_domhsh_add_default(entry); 280 ret_val = netlbl_domhsh_add_default(entry);
298 break; 281 break;
299 case NETLBL_NLTYPE_CIPSOV4: 282 case NETLBL_NLTYPE_CIPSOV4:
300 if (msg_len < NETLBL_LEN_U32) { 283 if (!info->attrs[NLBL_MGMT_A_CV4DOI])
301 ret_val = -EINVAL;
302 goto adddef_failure; 284 goto adddef_failure;
303 } 285
304 tmp_val = netlbl_getinc_u32(&msg_ptr, &msg_len); 286 tmp_val = nla_get_u32(info->attrs[NLBL_MGMT_A_CV4DOI]);
305 /* We should be holding a rcu_read_lock here while we 287 /* We should be holding a rcu_read_lock() here while we hold
306 * hold the result but since the entry will always be 288 * the result but since the entry will always be deleted when
307 * deleted when the CIPSO DOI is deleted we are going 289 * the CIPSO DOI is deleted we aren't going to keep the
308 * to skip the lock. */ 290 * lock. */
309 rcu_read_lock(); 291 rcu_read_lock();
310 entry->type_def.cipsov4 = cipso_v4_doi_getdef(tmp_val); 292 entry->type_def.cipsov4 = cipso_v4_doi_getdef(tmp_val);
311 if (entry->type_def.cipsov4 == NULL) { 293 if (entry->type_def.cipsov4 == NULL) {
312 rcu_read_unlock(); 294 rcu_read_unlock();
313 ret_val = -EINVAL;
314 goto adddef_failure; 295 goto adddef_failure;
315 } 296 }
316 ret_val = netlbl_domhsh_add_default(entry); 297 ret_val = netlbl_domhsh_add_default(entry);
317 rcu_read_unlock(); 298 rcu_read_unlock();
318 break; 299 break;
319 default: 300 default:
320 ret_val = -EINVAL; 301 goto adddef_failure;
321 } 302 }
322 if (ret_val != 0) 303 if (ret_val != 0)
323 goto adddef_failure; 304 goto adddef_failure;
324 305
325 netlbl_netlink_send_ack(info,
326 netlbl_mgmt_gnl_family.id,
327 NLBL_MGMT_C_ACK,
328 NETLBL_E_OK);
329 return 0; 306 return 0;
330 307
331adddef_failure: 308adddef_failure:
332 kfree(entry); 309 kfree(entry);
333 netlbl_netlink_send_ack(info,
334 netlbl_mgmt_gnl_family.id,
335 NLBL_MGMT_C_ACK,
336 -ret_val);
337 return ret_val; 310 return ret_val;
338} 311}
339 312
@@ -349,20 +322,7 @@ adddef_failure:
349 */ 322 */
350static int netlbl_mgmt_removedef(struct sk_buff *skb, struct genl_info *info) 323static int netlbl_mgmt_removedef(struct sk_buff *skb, struct genl_info *info)
351{ 324{
352 int ret_val; 325 return netlbl_domhsh_remove_default();
353
354 ret_val = netlbl_netlink_cap_check(skb, CAP_NET_ADMIN);
355 if (ret_val != 0)
356 goto removedef_return;
357
358 ret_val = netlbl_domhsh_remove_default();
359
360removedef_return:
361 netlbl_netlink_send_ack(info,
362 netlbl_mgmt_gnl_family.id,
363 NLBL_MGMT_C_ACK,
364 -ret_val);
365 return ret_val;
366} 326}
367 327
368/** 328/**
@@ -379,88 +339,131 @@ removedef_return:
379static int netlbl_mgmt_listdef(struct sk_buff *skb, struct genl_info *info) 339static int netlbl_mgmt_listdef(struct sk_buff *skb, struct genl_info *info)
380{ 340{
381 int ret_val = -ENOMEM; 341 int ret_val = -ENOMEM;
382 struct sk_buff *ans_skb; 342 struct sk_buff *ans_skb = NULL;
343 void *data;
344 struct netlbl_dom_map *entry;
383 345
384 ans_skb = netlbl_domhsh_dump_default(NLMSG_SPACE(GENL_HDRLEN)); 346 ans_skb = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
385 if (ans_skb == NULL) 347 if (ans_skb == NULL)
348 return -ENOMEM;
349 data = netlbl_netlink_hdr_put(ans_skb,
350 info->snd_pid,
351 info->snd_seq,
352 netlbl_mgmt_gnl_family.id,
353 0,
354 NLBL_MGMT_C_LISTDEF);
355 if (data == NULL)
386 goto listdef_failure; 356 goto listdef_failure;
387 netlbl_netlink_hdr_push(ans_skb,
388 info->snd_pid,
389 0,
390 netlbl_mgmt_gnl_family.id,
391 NLBL_MGMT_C_LISTDEF);
392 357
393 ret_val = netlbl_netlink_snd(ans_skb, info->snd_pid); 358 rcu_read_lock();
359 entry = netlbl_domhsh_getentry(NULL);
360 if (entry == NULL) {
361 ret_val = -ENOENT;
362 goto listdef_failure_lock;
363 }
364 ret_val = nla_put_u32(ans_skb, NLBL_MGMT_A_PROTOCOL, entry->type);
394 if (ret_val != 0) 365 if (ret_val != 0)
395 goto listdef_failure; 366 goto listdef_failure_lock;
367 switch (entry->type) {
368 case NETLBL_NLTYPE_CIPSOV4:
369 ret_val = nla_put_u32(ans_skb,
370 NLBL_MGMT_A_CV4DOI,
371 entry->type_def.cipsov4->doi);
372 if (ret_val != 0)
373 goto listdef_failure_lock;
374 break;
375 }
376 rcu_read_unlock();
396 377
378 genlmsg_end(ans_skb, data);
379
380 ret_val = genlmsg_unicast(ans_skb, info->snd_pid);
381 if (ret_val != 0)
382 goto listdef_failure;
397 return 0; 383 return 0;
398 384
385listdef_failure_lock:
386 rcu_read_unlock();
399listdef_failure: 387listdef_failure:
400 netlbl_netlink_send_ack(info, 388 kfree_skb(ans_skb);
401 netlbl_mgmt_gnl_family.id,
402 NLBL_MGMT_C_ACK,
403 -ret_val);
404 return ret_val; 389 return ret_val;
405} 390}
406 391
407/** 392/**
408 * netlbl_mgmt_modules - Handle a MODULES message 393 * netlbl_mgmt_protocols_cb - Write an individual PROTOCOL message response
409 * @skb: the NETLINK buffer 394 * @skb: the skb to write to
410 * @info: the Generic NETLINK info block 395 * @seq: the NETLINK sequence number
396 * @cb: the NETLINK callback
397 * @protocol: the NetLabel protocol to use in the message
411 * 398 *
412 * Description: 399 * Description:
413 * Process a user generated MODULES message and respond accordingly. 400 * This function is to be used in conjunction with netlbl_mgmt_protocols() to
401 * answer a application's PROTOCOLS message. Returns the size of the message
402 * on success, negative values on failure.
414 * 403 *
415 */ 404 */
416static int netlbl_mgmt_modules(struct sk_buff *skb, struct genl_info *info) 405static int netlbl_mgmt_protocols_cb(struct sk_buff *skb,
406 struct netlink_callback *cb,
407 u32 protocol)
417{ 408{
418 int ret_val = -ENOMEM; 409 int ret_val = -ENOMEM;
419 size_t data_size; 410 void *data;
420 u32 mod_count; 411
421 struct sk_buff *ans_skb = NULL; 412 data = netlbl_netlink_hdr_put(skb,
422 413 NETLINK_CB(cb->skb).pid,
423 /* unlabeled + cipsov4 */ 414 cb->nlh->nlmsg_seq,
424 mod_count = 2; 415 netlbl_mgmt_gnl_family.id,
425 416 NLM_F_MULTI,
426 data_size = GENL_HDRLEN + NETLBL_LEN_U32 + mod_count * NETLBL_LEN_U32; 417 NLBL_MGMT_C_PROTOCOLS);
427 ans_skb = netlbl_netlink_alloc_skb(0, data_size, GFP_KERNEL); 418 if (data == NULL)
428 if (ans_skb == NULL) 419 goto protocols_cb_failure;
429 goto modules_failure; 420
430 421 ret_val = nla_put_u32(skb, NLBL_MGMT_A_PROTOCOL, protocol);
431 if (netlbl_netlink_hdr_put(ans_skb,
432 info->snd_pid,
433 0,
434 netlbl_mgmt_gnl_family.id,
435 NLBL_MGMT_C_MODULES) == NULL)
436 goto modules_failure;
437
438 ret_val = nla_put_u32(ans_skb, NLA_U32, mod_count);
439 if (ret_val != 0)
440 goto modules_failure;
441 ret_val = nla_put_u32(ans_skb, NLA_U32, NETLBL_NLTYPE_UNLABELED);
442 if (ret_val != 0) 422 if (ret_val != 0)
443 goto modules_failure; 423 goto protocols_cb_failure;
444 ret_val = nla_put_u32(ans_skb, NLA_U32, NETLBL_NLTYPE_CIPSOV4);
445 if (ret_val != 0)
446 goto modules_failure;
447
448 ret_val = netlbl_netlink_snd(ans_skb, info->snd_pid);
449 if (ret_val != 0)
450 goto modules_failure;
451 424
452 return 0; 425 return genlmsg_end(skb, data);
453 426
454modules_failure: 427protocols_cb_failure:
455 kfree_skb(ans_skb); 428 genlmsg_cancel(skb, data);
456 netlbl_netlink_send_ack(info,
457 netlbl_mgmt_gnl_family.id,
458 NLBL_MGMT_C_ACK,
459 -ret_val);
460 return ret_val; 429 return ret_val;
461} 430}
462 431
463/** 432/**
433 * netlbl_mgmt_protocols - Handle a PROTOCOLS message
434 * @skb: the NETLINK buffer
435 * @cb: the NETLINK callback
436 *
437 * Description:
438 * Process a user generated PROTOCOLS message and respond accordingly.
439 *
440 */
441static int netlbl_mgmt_protocols(struct sk_buff *skb,
442 struct netlink_callback *cb)
443{
444 u32 protos_sent = cb->args[0];
445
446 if (protos_sent == 0) {
447 if (netlbl_mgmt_protocols_cb(skb,
448 cb,
449 NETLBL_NLTYPE_UNLABELED) < 0)
450 goto protocols_return;
451 protos_sent++;
452 }
453 if (protos_sent == 1) {
454 if (netlbl_mgmt_protocols_cb(skb,
455 cb,
456 NETLBL_NLTYPE_CIPSOV4) < 0)
457 goto protocols_return;
458 protos_sent++;
459 }
460
461protocols_return:
462 cb->args[0] = protos_sent;
463 return skb->len;
464}
465
466/**
464 * netlbl_mgmt_version - Handle a VERSION message 467 * netlbl_mgmt_version - Handle a VERSION message
465 * @skb: the NETLINK buffer 468 * @skb: the NETLINK buffer
466 * @info: the Generic NETLINK info block 469 * @info: the Generic NETLINK info block
@@ -474,35 +477,35 @@ static int netlbl_mgmt_version(struct sk_buff *skb, struct genl_info *info)
474{ 477{
475 int ret_val = -ENOMEM; 478 int ret_val = -ENOMEM;
476 struct sk_buff *ans_skb = NULL; 479 struct sk_buff *ans_skb = NULL;
480 void *data;
477 481
478 ans_skb = netlbl_netlink_alloc_skb(0, 482 ans_skb = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
479 GENL_HDRLEN + NETLBL_LEN_U32,
480 GFP_KERNEL);
481 if (ans_skb == NULL) 483 if (ans_skb == NULL)
482 goto version_failure; 484 return -ENOMEM;
483 if (netlbl_netlink_hdr_put(ans_skb, 485 data = netlbl_netlink_hdr_put(ans_skb,
484 info->snd_pid, 486 info->snd_pid,
485 0, 487 info->snd_seq,
486 netlbl_mgmt_gnl_family.id, 488 netlbl_mgmt_gnl_family.id,
487 NLBL_MGMT_C_VERSION) == NULL) 489 0,
490 NLBL_MGMT_C_VERSION);
491 if (data == NULL)
488 goto version_failure; 492 goto version_failure;
489 493
490 ret_val = nla_put_u32(ans_skb, NLA_U32, NETLBL_PROTO_VERSION); 494 ret_val = nla_put_u32(ans_skb,
495 NLBL_MGMT_A_VERSION,
496 NETLBL_PROTO_VERSION);
491 if (ret_val != 0) 497 if (ret_val != 0)
492 goto version_failure; 498 goto version_failure;
493 499
494 ret_val = netlbl_netlink_snd(ans_skb, info->snd_pid); 500 genlmsg_end(ans_skb, data);
501
502 ret_val = genlmsg_unicast(ans_skb, info->snd_pid);
495 if (ret_val != 0) 503 if (ret_val != 0)
496 goto version_failure; 504 goto version_failure;
497
498 return 0; 505 return 0;
499 506
500version_failure: 507version_failure:
501 kfree_skb(ans_skb); 508 kfree_skb(ans_skb);
502 netlbl_netlink_send_ack(info,
503 netlbl_mgmt_gnl_family.id,
504 NLBL_MGMT_C_ACK,
505 -ret_val);
506 return ret_val; 509 return ret_val;
507} 510}
508 511
@@ -513,35 +516,40 @@ version_failure:
513 516
514static struct genl_ops netlbl_mgmt_genl_c_add = { 517static struct genl_ops netlbl_mgmt_genl_c_add = {
515 .cmd = NLBL_MGMT_C_ADD, 518 .cmd = NLBL_MGMT_C_ADD,
516 .flags = 0, 519 .flags = GENL_ADMIN_PERM,
520 .policy = netlbl_mgmt_genl_policy,
517 .doit = netlbl_mgmt_add, 521 .doit = netlbl_mgmt_add,
518 .dumpit = NULL, 522 .dumpit = NULL,
519}; 523};
520 524
521static struct genl_ops netlbl_mgmt_genl_c_remove = { 525static struct genl_ops netlbl_mgmt_genl_c_remove = {
522 .cmd = NLBL_MGMT_C_REMOVE, 526 .cmd = NLBL_MGMT_C_REMOVE,
523 .flags = 0, 527 .flags = GENL_ADMIN_PERM,
528 .policy = netlbl_mgmt_genl_policy,
524 .doit = netlbl_mgmt_remove, 529 .doit = netlbl_mgmt_remove,
525 .dumpit = NULL, 530 .dumpit = NULL,
526}; 531};
527 532
528static struct genl_ops netlbl_mgmt_genl_c_list = { 533static struct genl_ops netlbl_mgmt_genl_c_listall = {
529 .cmd = NLBL_MGMT_C_LIST, 534 .cmd = NLBL_MGMT_C_LISTALL,
530 .flags = 0, 535 .flags = 0,
531 .doit = netlbl_mgmt_list, 536 .policy = netlbl_mgmt_genl_policy,
532 .dumpit = NULL, 537 .doit = NULL,
538 .dumpit = netlbl_mgmt_listall,
533}; 539};
534 540
535static struct genl_ops netlbl_mgmt_genl_c_adddef = { 541static struct genl_ops netlbl_mgmt_genl_c_adddef = {
536 .cmd = NLBL_MGMT_C_ADDDEF, 542 .cmd = NLBL_MGMT_C_ADDDEF,
537 .flags = 0, 543 .flags = GENL_ADMIN_PERM,
544 .policy = netlbl_mgmt_genl_policy,
538 .doit = netlbl_mgmt_adddef, 545 .doit = netlbl_mgmt_adddef,
539 .dumpit = NULL, 546 .dumpit = NULL,
540}; 547};
541 548
542static struct genl_ops netlbl_mgmt_genl_c_removedef = { 549static struct genl_ops netlbl_mgmt_genl_c_removedef = {
543 .cmd = NLBL_MGMT_C_REMOVEDEF, 550 .cmd = NLBL_MGMT_C_REMOVEDEF,
544 .flags = 0, 551 .flags = GENL_ADMIN_PERM,
552 .policy = netlbl_mgmt_genl_policy,
545 .doit = netlbl_mgmt_removedef, 553 .doit = netlbl_mgmt_removedef,
546 .dumpit = NULL, 554 .dumpit = NULL,
547}; 555};
@@ -549,20 +557,23 @@ static struct genl_ops netlbl_mgmt_genl_c_removedef = {
549static struct genl_ops netlbl_mgmt_genl_c_listdef = { 557static struct genl_ops netlbl_mgmt_genl_c_listdef = {
550 .cmd = NLBL_MGMT_C_LISTDEF, 558 .cmd = NLBL_MGMT_C_LISTDEF,
551 .flags = 0, 559 .flags = 0,
560 .policy = netlbl_mgmt_genl_policy,
552 .doit = netlbl_mgmt_listdef, 561 .doit = netlbl_mgmt_listdef,
553 .dumpit = NULL, 562 .dumpit = NULL,
554}; 563};
555 564
556static struct genl_ops netlbl_mgmt_genl_c_modules = { 565static struct genl_ops netlbl_mgmt_genl_c_protocols = {
557 .cmd = NLBL_MGMT_C_MODULES, 566 .cmd = NLBL_MGMT_C_PROTOCOLS,
558 .flags = 0, 567 .flags = 0,
559 .doit = netlbl_mgmt_modules, 568 .policy = netlbl_mgmt_genl_policy,
560 .dumpit = NULL, 569 .doit = NULL,
570 .dumpit = netlbl_mgmt_protocols,
561}; 571};
562 572
563static struct genl_ops netlbl_mgmt_genl_c_version = { 573static struct genl_ops netlbl_mgmt_genl_c_version = {
564 .cmd = NLBL_MGMT_C_VERSION, 574 .cmd = NLBL_MGMT_C_VERSION,
565 .flags = 0, 575 .flags = 0,
576 .policy = netlbl_mgmt_genl_policy,
566 .doit = netlbl_mgmt_version, 577 .doit = netlbl_mgmt_version,
567 .dumpit = NULL, 578 .dumpit = NULL,
568}; 579};
@@ -596,7 +607,7 @@ int netlbl_mgmt_genl_init(void)
596 if (ret_val != 0) 607 if (ret_val != 0)
597 return ret_val; 608 return ret_val;
598 ret_val = genl_register_ops(&netlbl_mgmt_gnl_family, 609 ret_val = genl_register_ops(&netlbl_mgmt_gnl_family,
599 &netlbl_mgmt_genl_c_list); 610 &netlbl_mgmt_genl_c_listall);
600 if (ret_val != 0) 611 if (ret_val != 0)
601 return ret_val; 612 return ret_val;
602 ret_val = genl_register_ops(&netlbl_mgmt_gnl_family, 613 ret_val = genl_register_ops(&netlbl_mgmt_gnl_family,
@@ -612,7 +623,7 @@ int netlbl_mgmt_genl_init(void)
612 if (ret_val != 0) 623 if (ret_val != 0)
613 return ret_val; 624 return ret_val;
614 ret_val = genl_register_ops(&netlbl_mgmt_gnl_family, 625 ret_val = genl_register_ops(&netlbl_mgmt_gnl_family,
615 &netlbl_mgmt_genl_c_modules); 626 &netlbl_mgmt_genl_c_protocols);
616 if (ret_val != 0) 627 if (ret_val != 0)
617 return ret_val; 628 return ret_val;
618 ret_val = genl_register_ops(&netlbl_mgmt_gnl_family, 629 ret_val = genl_register_ops(&netlbl_mgmt_gnl_family,
diff --git a/net/netlabel/netlabel_mgmt.h b/net/netlabel/netlabel_mgmt.h
index fd6c6acbfa08..3642d3bfc8eb 100644
--- a/net/netlabel/netlabel_mgmt.h
+++ b/net/netlabel/netlabel_mgmt.h
@@ -34,212 +34,137 @@
34#include <net/netlabel.h> 34#include <net/netlabel.h>
35 35
36/* 36/*
37 * The following NetLabel payloads are supported by the management interface, 37 * The following NetLabel payloads are supported by the management interface.
38 * all of which are preceeded by the nlmsghdr struct.
39 *
40 * o ACK:
41 * Sent by the kernel in response to an applications message, applications
42 * should never send this message.
43 *
44 * +----------------------+-----------------------+
45 * | seq number (32 bits) | return code (32 bits) |
46 * +----------------------+-----------------------+
47 *
48 * seq number: the sequence number of the original message, taken from the
49 * nlmsghdr structure
50 * return code: return value, based on errno values
51 * 38 *
52 * o ADD: 39 * o ADD:
53 * Sent by an application to add a domain mapping to the NetLabel system. 40 * Sent by an application to add a domain mapping to the NetLabel system.
54 * The kernel should respond with an ACK.
55 *
56 * +-------------------+
57 * | domains (32 bits) | ...
58 * +-------------------+
59 *
60 * domains: the number of domains in the message
61 *
62 * +--------------------------+-------------------------+
63 * | domain string (variable) | protocol type (32 bits) | ...
64 * +--------------------------+-------------------------+
65 * 41 *
66 * +-------------- ---- --- -- - 42 * Required attributes:
67 * | mapping data ... repeated
68 * +-------------- ---- --- -- -
69 * 43 *
70 * domain string: the domain string, NULL terminated 44 * NLBL_MGMT_A_DOMAIN
71 * protocol type: the protocol type (defined by NETLBL_NLTYPE_*) 45 * NLBL_MGMT_A_PROTOCOL
72 * mapping data: specific to the map type (see below)
73 * 46 *
74 * NETLBL_NLTYPE_UNLABELED 47 * If using NETLBL_NLTYPE_CIPSOV4 the following attributes are required:
75 * 48 *
76 * No mapping data for this protocol type. 49 * NLBL_MGMT_A_CV4DOI
77 * 50 *
78 * NETLBL_NLTYPE_CIPSOV4 51 * If using NETLBL_NLTYPE_UNLABELED no other attributes are required.
79 *
80 * +---------------+
81 * | doi (32 bits) |
82 * +---------------+
83 *
84 * doi: the CIPSO DOI value
85 * 52 *
86 * o REMOVE: 53 * o REMOVE:
87 * Sent by an application to remove a domain mapping from the NetLabel 54 * Sent by an application to remove a domain mapping from the NetLabel
88 * system. The kernel should ACK this message. 55 * system.
89 *
90 * +-------------------+
91 * | domains (32 bits) | ...
92 * +-------------------+
93 * 56 *
94 * domains: the number of domains in the message 57 * Required attributes:
95 * 58 *
96 * +--------------------------+ 59 * NLBL_MGMT_A_DOMAIN
97 * | domain string (variable) | ...
98 * +--------------------------+
99 * 60 *
100 * domain string: the domain string, NULL terminated 61 * o LISTALL:
101 *
102 * o LIST:
103 * This message can be sent either from an application or by the kernel in 62 * This message can be sent either from an application or by the kernel in
104 * response to an application generated LIST message. When sent by an 63 * response to an application generated LISTALL message. When sent by an
105 * application there is no payload. The kernel should respond to a LIST 64 * application there is no payload and the NLM_F_DUMP flag should be set.
106 * message either with a LIST message on success or an ACK message on 65 * The kernel should respond with a series of the following messages.
107 * failure.
108 *
109 * +-------------------+
110 * | domains (32 bits) | ...
111 * +-------------------+
112 *
113 * domains: the number of domains in the message
114 * 66 *
115 * +--------------------------+ 67 * Required attributes:
116 * | domain string (variable) | ...
117 * +--------------------------+
118 * 68 *
119 * +-------------------------+-------------- ---- --- -- - 69 * NLBL_MGMT_A_DOMAIN
120 * | protocol type (32 bits) | mapping data ... repeated 70 * NLBL_MGMT_A_PROTOCOL
121 * +-------------------------+-------------- ---- --- -- -
122 * 71 *
123 * domain string: the domain string, NULL terminated 72 * If using NETLBL_NLTYPE_CIPSOV4 the following attributes are required:
124 * protocol type: the protocol type (defined by NETLBL_NLTYPE_*)
125 * mapping data: specific to the map type (see below)
126 * 73 *
127 * NETLBL_NLTYPE_UNLABELED 74 * NLBL_MGMT_A_CV4DOI
128 * 75 *
129 * No mapping data for this protocol type. 76 * If using NETLBL_NLTYPE_UNLABELED no other attributes are required.
130 *
131 * NETLBL_NLTYPE_CIPSOV4
132 *
133 * +----------------+---------------+
134 * | type (32 bits) | doi (32 bits) |
135 * +----------------+---------------+
136 *
137 * type: the CIPSO mapping table type (defined in the cipso_ipv4.h header
138 * as CIPSO_V4_MAP_*)
139 * doi: the CIPSO DOI value
140 * 77 *
141 * o ADDDEF: 78 * o ADDDEF:
142 * Sent by an application to set the default domain mapping for the NetLabel 79 * Sent by an application to set the default domain mapping for the NetLabel
143 * system. The kernel should respond with an ACK. 80 * system.
144 * 81 *
145 * +-------------------------+-------------- ---- --- -- - 82 * Required attributes:
146 * | protocol type (32 bits) | mapping data ... repeated
147 * +-------------------------+-------------- ---- --- -- -
148 * 83 *
149 * protocol type: the protocol type (defined by NETLBL_NLTYPE_*) 84 * NLBL_MGMT_A_PROTOCOL
150 * mapping data: specific to the map type (see below)
151 * 85 *
152 * NETLBL_NLTYPE_UNLABELED 86 * If using NETLBL_NLTYPE_CIPSOV4 the following attributes are required:
153 * 87 *
154 * No mapping data for this protocol type. 88 * NLBL_MGMT_A_CV4DOI
155 * 89 *
156 * NETLBL_NLTYPE_CIPSOV4 90 * If using NETLBL_NLTYPE_UNLABELED no other attributes are required.
157 *
158 * +---------------+
159 * | doi (32 bits) |
160 * +---------------+
161 *
162 * doi: the CIPSO DOI value
163 * 91 *
164 * o REMOVEDEF: 92 * o REMOVEDEF:
165 * Sent by an application to remove the default domain mapping from the 93 * Sent by an application to remove the default domain mapping from the
166 * NetLabel system, there is no payload. The kernel should ACK this message. 94 * NetLabel system, there is no payload.
167 * 95 *
168 * o LISTDEF: 96 * o LISTDEF:
169 * This message can be sent either from an application or by the kernel in 97 * This message can be sent either from an application or by the kernel in
170 * response to an application generated LISTDEF message. When sent by an 98 * response to an application generated LISTDEF message. When sent by an
171 * application there is no payload. The kernel should respond to a 99 * application there is no payload. On success the kernel should send a
172 * LISTDEF message either with a LISTDEF message on success or an ACK message 100 * response using the following format.
173 * on failure.
174 *
175 * +-------------------------+-------------- ---- --- -- -
176 * | protocol type (32 bits) | mapping data ... repeated
177 * +-------------------------+-------------- ---- --- -- -
178 * 101 *
179 * protocol type: the protocol type (defined by NETLBL_NLTYPE_*) 102 * Required attributes:
180 * mapping data: specific to the map type (see below)
181 * 103 *
182 * NETLBL_NLTYPE_UNLABELED 104 * NLBL_MGMT_A_PROTOCOL
183 * 105 *
184 * No mapping data for this protocol type. 106 * If using NETLBL_NLTYPE_CIPSOV4 the following attributes are required:
185 * 107 *
186 * NETLBL_NLTYPE_CIPSOV4 108 * NLBL_MGMT_A_CV4DOI
187 * 109 *
188 * +----------------+---------------+ 110 * If using NETLBL_NLTYPE_UNLABELED no other attributes are required.
189 * | type (32 bits) | doi (32 bits) |
190 * +----------------+---------------+
191 * 111 *
192 * type: the CIPSO mapping table type (defined in the cipso_ipv4.h header 112 * o PROTOCOLS:
193 * as CIPSO_V4_MAP_*) 113 * Sent by an application to request a list of configured NetLabel protocols
194 * doi: the CIPSO DOI value 114 * in the kernel. When sent by an application there is no payload and the
115 * NLM_F_DUMP flag should be set. The kernel should respond with a series of
116 * the following messages.
195 * 117 *
196 * o MODULES: 118 * Required attributes:
197 * Sent by an application to request a list of configured NetLabel modules
198 * in the kernel. When sent by an application there is no payload.
199 * 119 *
200 * +-------------------+ 120 * NLBL_MGMT_A_PROTOCOL
201 * | modules (32 bits) | ...
202 * +-------------------+
203 *
204 * modules: the number of modules in the message, if this is an application
205 * generated message and the value is zero then return a list of
206 * the configured modules
207 *
208 * +------------------+
209 * | module (32 bits) | ... repeated
210 * +------------------+
211 *
212 * module: the module number as defined by NETLBL_NLTYPE_*
213 * 121 *
214 * o VERSION: 122 * o VERSION:
215 * Sent by an application to request the NetLabel version string. When sent 123 * Sent by an application to request the NetLabel version. When sent by an
216 * by an application there is no payload. This message type is also used by 124 * application there is no payload. This message type is also used by the
217 * the kernel to respond to an VERSION request. 125 * kernel to respond to an VERSION request.
218 * 126 *
219 * +-------------------+ 127 * Required attributes:
220 * | version (32 bits) |
221 * +-------------------+
222 * 128 *
223 * version: the protocol version number 129 * NLBL_MGMT_A_VERSION
224 * 130 *
225 */ 131 */
226 132
227/* NetLabel Management commands */ 133/* NetLabel Management commands */
228enum { 134enum {
229 NLBL_MGMT_C_UNSPEC, 135 NLBL_MGMT_C_UNSPEC,
230 NLBL_MGMT_C_ACK,
231 NLBL_MGMT_C_ADD, 136 NLBL_MGMT_C_ADD,
232 NLBL_MGMT_C_REMOVE, 137 NLBL_MGMT_C_REMOVE,
233 NLBL_MGMT_C_LIST, 138 NLBL_MGMT_C_LISTALL,
234 NLBL_MGMT_C_ADDDEF, 139 NLBL_MGMT_C_ADDDEF,
235 NLBL_MGMT_C_REMOVEDEF, 140 NLBL_MGMT_C_REMOVEDEF,
236 NLBL_MGMT_C_LISTDEF, 141 NLBL_MGMT_C_LISTDEF,
237 NLBL_MGMT_C_MODULES, 142 NLBL_MGMT_C_PROTOCOLS,
238 NLBL_MGMT_C_VERSION, 143 NLBL_MGMT_C_VERSION,
239 __NLBL_MGMT_C_MAX, 144 __NLBL_MGMT_C_MAX,
240}; 145};
241#define NLBL_MGMT_C_MAX (__NLBL_MGMT_C_MAX - 1) 146#define NLBL_MGMT_C_MAX (__NLBL_MGMT_C_MAX - 1)
242 147
148/* NetLabel Management attributes */
149enum {
150 NLBL_MGMT_A_UNSPEC,
151 NLBL_MGMT_A_DOMAIN,
152 /* (NLA_NUL_STRING)
153 * the NULL terminated LSM domain string */
154 NLBL_MGMT_A_PROTOCOL,
155 /* (NLA_U32)
156 * the NetLabel protocol type (defined by NETLBL_NLTYPE_*) */
157 NLBL_MGMT_A_VERSION,
158 /* (NLA_U32)
159 * the NetLabel protocol version number (defined by
160 * NETLBL_PROTO_VERSION) */
161 NLBL_MGMT_A_CV4DOI,
162 /* (NLA_U32)
163 * the CIPSOv4 DOI value */
164 __NLBL_MGMT_A_MAX,
165};
166#define NLBL_MGMT_A_MAX (__NLBL_MGMT_A_MAX - 1)
167
243/* NetLabel protocol functions */ 168/* NetLabel protocol functions */
244int netlbl_mgmt_genl_init(void); 169int netlbl_mgmt_genl_init(void);
245 170
diff --git a/net/netlabel/netlabel_unlabeled.c b/net/netlabel/netlabel_unlabeled.c
index 785f4960e0d3..440f5c4e1e2d 100644
--- a/net/netlabel/netlabel_unlabeled.c
+++ b/net/netlabel/netlabel_unlabeled.c
@@ -55,9 +55,13 @@ static struct genl_family netlbl_unlabel_gnl_family = {
55 .hdrsize = 0, 55 .hdrsize = 0,
56 .name = NETLBL_NLTYPE_UNLABELED_NAME, 56 .name = NETLBL_NLTYPE_UNLABELED_NAME,
57 .version = NETLBL_PROTO_VERSION, 57 .version = NETLBL_PROTO_VERSION,
58 .maxattr = 0, 58 .maxattr = NLBL_UNLABEL_A_MAX,
59}; 59};
60 60
61/* NetLabel Netlink attribute policy */
62static struct nla_policy netlbl_unlabel_genl_policy[NLBL_UNLABEL_A_MAX + 1] = {
63 [NLBL_UNLABEL_A_ACPTFLG] = { .type = NLA_U8 },
64};
61 65
62/* 66/*
63 * NetLabel Command Handlers 67 * NetLabel Command Handlers
@@ -75,31 +79,18 @@ static struct genl_family netlbl_unlabel_gnl_family = {
75 */ 79 */
76static int netlbl_unlabel_accept(struct sk_buff *skb, struct genl_info *info) 80static int netlbl_unlabel_accept(struct sk_buff *skb, struct genl_info *info)
77{ 81{
78 int ret_val; 82 int ret_val = -EINVAL;
79 struct nlattr *data = netlbl_netlink_payload_data(skb); 83 u8 value;
80 u32 value;
81
82 ret_val = netlbl_netlink_cap_check(skb, CAP_NET_ADMIN);
83 if (ret_val != 0)
84 return ret_val;
85 84
86 if (netlbl_netlink_payload_len(skb) == NETLBL_LEN_U32) { 85 if (info->attrs[NLBL_UNLABEL_A_ACPTFLG]) {
87 value = nla_get_u32(data); 86 value = nla_get_u8(info->attrs[NLBL_UNLABEL_A_ACPTFLG]);
88 if (value == 1 || value == 0) { 87 if (value == 1 || value == 0) {
89 atomic_set(&netlabel_unlabel_accept_flg, value); 88 atomic_set(&netlabel_unlabel_accept_flg, value);
90 netlbl_netlink_send_ack(info, 89 ret_val = 0;
91 netlbl_unlabel_gnl_family.id,
92 NLBL_UNLABEL_C_ACK,
93 NETLBL_E_OK);
94 return 0;
95 } 90 }
96 } 91 }
97 92
98 netlbl_netlink_send_ack(info, 93 return ret_val;
99 netlbl_unlabel_gnl_family.id,
100 NLBL_UNLABEL_C_ACK,
101 EINVAL);
102 return -EINVAL;
103} 94}
104 95
105/** 96/**
@@ -114,39 +105,39 @@ static int netlbl_unlabel_accept(struct sk_buff *skb, struct genl_info *info)
114 */ 105 */
115static int netlbl_unlabel_list(struct sk_buff *skb, struct genl_info *info) 106static int netlbl_unlabel_list(struct sk_buff *skb, struct genl_info *info)
116{ 107{
117 int ret_val = -ENOMEM; 108 int ret_val = -EINVAL;
118 struct sk_buff *ans_skb; 109 struct sk_buff *ans_skb;
110 void *data;
119 111
120 ans_skb = netlbl_netlink_alloc_skb(0, 112 ans_skb = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
121 GENL_HDRLEN + NETLBL_LEN_U32,
122 GFP_KERNEL);
123 if (ans_skb == NULL) 113 if (ans_skb == NULL)
124 goto list_failure; 114 goto list_failure;
125 115 data = netlbl_netlink_hdr_put(ans_skb,
126 if (netlbl_netlink_hdr_put(ans_skb, 116 info->snd_pid,
127 info->snd_pid, 117 info->snd_seq,
128 0, 118 netlbl_unlabel_gnl_family.id,
129 netlbl_unlabel_gnl_family.id, 119 0,
130 NLBL_UNLABEL_C_LIST) == NULL) 120 NLBL_UNLABEL_C_LIST);
121 if (data == NULL) {
122 ret_val = -ENOMEM;
131 goto list_failure; 123 goto list_failure;
124 }
132 125
133 ret_val = nla_put_u32(ans_skb, 126 ret_val = nla_put_u8(ans_skb,
134 NLA_U32, 127 NLBL_UNLABEL_A_ACPTFLG,
135 atomic_read(&netlabel_unlabel_accept_flg)); 128 atomic_read(&netlabel_unlabel_accept_flg));
136 if (ret_val != 0) 129 if (ret_val != 0)
137 goto list_failure; 130 goto list_failure;
138 131
139 ret_val = netlbl_netlink_snd(ans_skb, info->snd_pid); 132 genlmsg_end(ans_skb, data);
133
134 ret_val = genlmsg_unicast(ans_skb, info->snd_pid);
140 if (ret_val != 0) 135 if (ret_val != 0)
141 goto list_failure; 136 goto list_failure;
142
143 return 0; 137 return 0;
144 138
145list_failure: 139list_failure:
146 netlbl_netlink_send_ack(info, 140 kfree(ans_skb);
147 netlbl_unlabel_gnl_family.id,
148 NLBL_UNLABEL_C_ACK,
149 -ret_val);
150 return ret_val; 141 return ret_val;
151} 142}
152 143
@@ -157,7 +148,8 @@ list_failure:
157 148
158static struct genl_ops netlbl_unlabel_genl_c_accept = { 149static struct genl_ops netlbl_unlabel_genl_c_accept = {
159 .cmd = NLBL_UNLABEL_C_ACCEPT, 150 .cmd = NLBL_UNLABEL_C_ACCEPT,
160 .flags = 0, 151 .flags = GENL_ADMIN_PERM,
152 .policy = netlbl_unlabel_genl_policy,
161 .doit = netlbl_unlabel_accept, 153 .doit = netlbl_unlabel_accept,
162 .dumpit = NULL, 154 .dumpit = NULL,
163}; 155};
@@ -165,6 +157,7 @@ static struct genl_ops netlbl_unlabel_genl_c_accept = {
165static struct genl_ops netlbl_unlabel_genl_c_list = { 157static struct genl_ops netlbl_unlabel_genl_c_list = {
166 .cmd = NLBL_UNLABEL_C_LIST, 158 .cmd = NLBL_UNLABEL_C_LIST,
167 .flags = 0, 159 .flags = 0,
160 .policy = netlbl_unlabel_genl_policy,
168 .doit = netlbl_unlabel_list, 161 .doit = netlbl_unlabel_list,
169 .dumpit = NULL, 162 .dumpit = NULL,
170}; 163};
@@ -218,10 +211,8 @@ int netlbl_unlabel_genl_init(void)
218 */ 211 */
219int netlbl_unlabel_getattr(struct netlbl_lsm_secattr *secattr) 212int netlbl_unlabel_getattr(struct netlbl_lsm_secattr *secattr)
220{ 213{
221 if (atomic_read(&netlabel_unlabel_accept_flg) == 1) { 214 if (atomic_read(&netlabel_unlabel_accept_flg) == 1)
222 memset(secattr, 0, sizeof(*secattr)); 215 return netlbl_secattr_init(secattr);
223 return 0;
224 }
225 216
226 return -ENOMSG; 217 return -ENOMSG;
227} 218}
diff --git a/net/netlabel/netlabel_unlabeled.h b/net/netlabel/netlabel_unlabeled.h
index f300e54e14b6..c2917fbb42cf 100644
--- a/net/netlabel/netlabel_unlabeled.h
+++ b/net/netlabel/netlabel_unlabeled.h
@@ -36,56 +36,47 @@
36/* 36/*
37 * The following NetLabel payloads are supported by the Unlabeled subsystem. 37 * The following NetLabel payloads are supported by the Unlabeled subsystem.
38 * 38 *
39 * o ACK:
40 * Sent by the kernel in response to an applications message, applications
41 * should never send this message.
42 *
43 * +----------------------+-----------------------+
44 * | seq number (32 bits) | return code (32 bits) |
45 * +----------------------+-----------------------+
46 *
47 * seq number: the sequence number of the original message, taken from the
48 * nlmsghdr structure
49 * return code: return value, based on errno values
50 *
51 * o ACCEPT 39 * o ACCEPT
52 * This message is sent from an application to specify if the kernel should 40 * This message is sent from an application to specify if the kernel should
53 * allow unlabled packets to pass if they do not match any of the static 41 * allow unlabled packets to pass if they do not match any of the static
54 * mappings defined in the unlabeled module. 42 * mappings defined in the unlabeled module.
55 * 43 *
56 * +-----------------+ 44 * Required attributes:
57 * | allow (32 bits) |
58 * +-----------------+
59 * 45 *
60 * allow: if true (1) then allow the packets to pass, if false (0) then 46 * NLBL_UNLABEL_A_ACPTFLG
61 * reject the packets
62 * 47 *
63 * o LIST 48 * o LIST
64 * This message can be sent either from an application or by the kernel in 49 * This message can be sent either from an application or by the kernel in
65 * response to an application generated LIST message. When sent by an 50 * response to an application generated LIST message. When sent by an
66 * application there is no payload. The kernel should respond to a LIST 51 * application there is no payload. The kernel should respond to a LIST
67 * message either with a LIST message on success or an ACK message on 52 * message with a LIST message on success.
68 * failure.
69 * 53 *
70 * +-----------------------+ 54 * Required attributes:
71 * | accept flag (32 bits) |
72 * +-----------------------+
73 * 55 *
74 * accept flag: if true (1) then unlabeled packets are allowed to pass, 56 * NLBL_UNLABEL_A_ACPTFLG
75 * if false (0) then unlabeled packets are rejected
76 * 57 *
77 */ 58 */
78 59
79/* NetLabel Unlabeled commands */ 60/* NetLabel Unlabeled commands */
80enum { 61enum {
81 NLBL_UNLABEL_C_UNSPEC, 62 NLBL_UNLABEL_C_UNSPEC,
82 NLBL_UNLABEL_C_ACK,
83 NLBL_UNLABEL_C_ACCEPT, 63 NLBL_UNLABEL_C_ACCEPT,
84 NLBL_UNLABEL_C_LIST, 64 NLBL_UNLABEL_C_LIST,
85 __NLBL_UNLABEL_C_MAX, 65 __NLBL_UNLABEL_C_MAX,
86}; 66};
87#define NLBL_UNLABEL_C_MAX (__NLBL_UNLABEL_C_MAX - 1) 67#define NLBL_UNLABEL_C_MAX (__NLBL_UNLABEL_C_MAX - 1)
88 68
69/* NetLabel Unlabeled attributes */
70enum {
71 NLBL_UNLABEL_A_UNSPEC,
72 NLBL_UNLABEL_A_ACPTFLG,
73 /* (NLA_U8)
74 * if true then unlabeled packets are allowed to pass, else unlabeled
75 * packets are rejected */
76 __NLBL_UNLABEL_A_MAX,
77};
78#define NLBL_UNLABEL_A_MAX (__NLBL_UNLABEL_A_MAX - 1)
79
89/* NetLabel protocol functions */ 80/* NetLabel protocol functions */
90int netlbl_unlabel_genl_init(void); 81int netlbl_unlabel_genl_init(void);
91 82
diff --git a/net/netlabel/netlabel_user.c b/net/netlabel/netlabel_user.c
index 73cbe66e42ff..eeb7d768d2bb 100644
--- a/net/netlabel/netlabel_user.c
+++ b/net/netlabel/netlabel_user.c
@@ -74,85 +74,3 @@ int netlbl_netlink_init(void)
74 74
75 return 0; 75 return 0;
76} 76}
77
78/*
79 * NetLabel Common Protocol Functions
80 */
81
82/**
83 * netlbl_netlink_send_ack - Send an ACK message
84 * @info: the generic NETLINK information
85 * @genl_family: the generic NETLINK family ID value
86 * @ack_cmd: the generic NETLINK family ACK command value
87 * @ret_code: return code to use
88 *
89 * Description:
90 * This function sends an ACK message to the sender of the NETLINK message
91 * specified by @info.
92 *
93 */
94void netlbl_netlink_send_ack(const struct genl_info *info,
95 u32 genl_family,
96 u8 ack_cmd,
97 u32 ret_code)
98{
99 size_t data_size;
100 struct sk_buff *skb;
101
102 data_size = GENL_HDRLEN + 2 * NETLBL_LEN_U32;
103 skb = netlbl_netlink_alloc_skb(0, data_size, GFP_KERNEL);
104 if (skb == NULL)
105 return;
106
107 if (netlbl_netlink_hdr_put(skb,
108 info->snd_pid,
109 0,
110 genl_family,
111 ack_cmd) == NULL)
112 goto send_ack_failure;
113
114 if (nla_put_u32(skb, NLA_U32, info->snd_seq) != 0)
115 goto send_ack_failure;
116 if (nla_put_u32(skb, NLA_U32, ret_code) != 0)
117 goto send_ack_failure;
118
119 netlbl_netlink_snd(skb, info->snd_pid);
120 return;
121
122send_ack_failure:
123 kfree_skb(skb);
124}
125
126/*
127 * NETLINK I/O Functions
128 */
129
130/**
131 * netlbl_netlink_snd - Send a NetLabel message
132 * @skb: NetLabel message
133 * @pid: destination PID
134 *
135 * Description:
136 * Sends a unicast NetLabel message over the NETLINK socket.
137 *
138 */
139int netlbl_netlink_snd(struct sk_buff *skb, u32 pid)
140{
141 return genlmsg_unicast(skb, pid);
142}
143
144/**
145 * netlbl_netlink_snd - Send a NetLabel message
146 * @skb: NetLabel message
147 * @pid: sending PID
148 * @group: multicast group id
149 *
150 * Description:
151 * Sends a multicast NetLabel message over the NETLINK socket to all members
152 * of @group except @pid.
153 *
154 */
155int netlbl_netlink_snd_multicast(struct sk_buff *skb, u32 pid, u32 group)
156{
157 return genlmsg_multicast(skb, pid, group, GFP_KERNEL);
158}
diff --git a/net/netlabel/netlabel_user.h b/net/netlabel/netlabel_user.h
index 385a6c7488c6..3f9386b917df 100644
--- a/net/netlabel/netlabel_user.h
+++ b/net/netlabel/netlabel_user.h
@@ -41,72 +41,6 @@
41/* NetLabel NETLINK helper functions */ 41/* NetLabel NETLINK helper functions */
42 42
43/** 43/**
44 * netlbl_netlink_cap_check - Check the NETLINK msg capabilities
45 * @skb: the NETLINK buffer
46 * @req_cap: the required capability
47 *
48 * Description:
49 * Check the NETLINK buffer's capabilities against the required capabilities.
50 * Returns zero on success, negative values on failure.
51 *
52 */
53static inline int netlbl_netlink_cap_check(const struct sk_buff *skb,
54 kernel_cap_t req_cap)
55{
56 if (cap_raised(NETLINK_CB(skb).eff_cap, req_cap))
57 return 0;
58 return -EPERM;
59}
60
61/**
62 * netlbl_getinc_u8 - Read a u8 value from a nlattr stream and move on
63 * @nla: the attribute
64 * @rem_len: remaining length
65 *
66 * Description:
67 * Return a u8 value pointed to by @nla and advance it to the next attribute.
68 *
69 */
70static inline u8 netlbl_getinc_u8(struct nlattr **nla, int *rem_len)
71{
72 u8 val = nla_get_u8(*nla);
73 *nla = nla_next(*nla, rem_len);
74 return val;
75}
76
77/**
78 * netlbl_getinc_u16 - Read a u16 value from a nlattr stream and move on
79 * @nla: the attribute
80 * @rem_len: remaining length
81 *
82 * Description:
83 * Return a u16 value pointed to by @nla and advance it to the next attribute.
84 *
85 */
86static inline u16 netlbl_getinc_u16(struct nlattr **nla, int *rem_len)
87{
88 u16 val = nla_get_u16(*nla);
89 *nla = nla_next(*nla, rem_len);
90 return val;
91}
92
93/**
94 * netlbl_getinc_u32 - Read a u32 value from a nlattr stream and move on
95 * @nla: the attribute
96 * @rem_len: remaining length
97 *
98 * Description:
99 * Return a u32 value pointed to by @nla and advance it to the next attribute.
100 *
101 */
102static inline u32 netlbl_getinc_u32(struct nlattr **nla, int *rem_len)
103{
104 u32 val = nla_get_u32(*nla);
105 *nla = nla_next(*nla, rem_len);
106 return val;
107}
108
109/**
110 * netlbl_netlink_hdr_put - Write the NETLINK buffers into a sk_buff 44 * netlbl_netlink_hdr_put - Write the NETLINK buffers into a sk_buff
111 * @skb: the packet 45 * @skb: the packet
112 * @pid: the PID of the receipient 46 * @pid: the PID of the receipient
@@ -124,6 +58,7 @@ static inline void *netlbl_netlink_hdr_put(struct sk_buff *skb,
124 u32 pid, 58 u32 pid,
125 u32 seq, 59 u32 seq,
126 int type, 60 int type,
61 int flags,
127 u8 cmd) 62 u8 cmd)
128{ 63{
129 return genlmsg_put(skb, 64 return genlmsg_put(skb,
@@ -131,85 +66,13 @@ static inline void *netlbl_netlink_hdr_put(struct sk_buff *skb,
131 seq, 66 seq,
132 type, 67 type,
133 0, 68 0,
134 0, 69 flags,
135 cmd, 70 cmd,
136 NETLBL_PROTO_VERSION); 71 NETLBL_PROTO_VERSION);
137} 72}
138 73
139/**
140 * netlbl_netlink_hdr_push - Write the NETLINK buffers into a sk_buff
141 * @skb: the packet
142 * @pid: the PID of the receipient
143 * @seq: the sequence number
144 * @type: the generic NETLINK message family type
145 * @cmd: command
146 *
147 * Description:
148 * Write both a NETLINK nlmsghdr structure and a Generic NETLINK genlmsghdr
149 * struct to the packet.
150 *
151 */
152static inline void netlbl_netlink_hdr_push(struct sk_buff *skb,
153 u32 pid,
154 u32 seq,
155 int type,
156 u8 cmd)
157
158{
159 struct nlmsghdr *nlh;
160 struct genlmsghdr *hdr;
161
162 nlh = (struct nlmsghdr *)skb_push(skb, NLMSG_SPACE(GENL_HDRLEN));
163 nlh->nlmsg_type = type;
164 nlh->nlmsg_len = skb->len;
165 nlh->nlmsg_flags = 0;
166 nlh->nlmsg_pid = pid;
167 nlh->nlmsg_seq = seq;
168
169 hdr = nlmsg_data(nlh);
170 hdr->cmd = cmd;
171 hdr->version = NETLBL_PROTO_VERSION;
172 hdr->reserved = 0;
173}
174
175/**
176 * netlbl_netlink_payload_len - Return the length of the payload
177 * @skb: the NETLINK buffer
178 *
179 * Description:
180 * This function returns the length of the NetLabel payload.
181 *
182 */
183static inline u32 netlbl_netlink_payload_len(const struct sk_buff *skb)
184{
185 return nlmsg_len((struct nlmsghdr *)skb->data) - GENL_HDRLEN;
186}
187
188/**
189 * netlbl_netlink_payload_data - Returns a pointer to the start of the payload
190 * @skb: the NETLINK buffer
191 *
192 * Description:
193 * This function returns a pointer to the start of the NetLabel payload.
194 *
195 */
196static inline void *netlbl_netlink_payload_data(const struct sk_buff *skb)
197{
198 return (unsigned char *)nlmsg_data((struct nlmsghdr *)skb->data) +
199 GENL_HDRLEN;
200}
201
202/* NetLabel common protocol functions */
203
204void netlbl_netlink_send_ack(const struct genl_info *info,
205 u32 genl_family,
206 u8 ack_cmd,
207 u32 ret_code);
208
209/* NetLabel NETLINK I/O functions */ 74/* NetLabel NETLINK I/O functions */
210 75
211int netlbl_netlink_init(void); 76int netlbl_netlink_init(void);
212int netlbl_netlink_snd(struct sk_buff *skb, u32 pid);
213int netlbl_netlink_snd_multicast(struct sk_buff *skb, u32 pid, u32 group);
214 77
215#endif 78#endif