diff options
Diffstat (limited to 'net')
272 files changed, 8765 insertions, 4569 deletions
diff --git a/net/9p/Kconfig b/net/9p/Kconfig index 66821cd64a76..71bc110aebf8 100644 --- a/net/9p/Kconfig +++ b/net/9p/Kconfig | |||
@@ -13,9 +13,19 @@ menuconfig NET_9P | |||
13 | 13 | ||
14 | If unsure, say N. | 14 | If unsure, say N. |
15 | 15 | ||
16 | config NET_9P_FD | ||
17 | depends on NET_9P | ||
18 | default y if NET_9P | ||
19 | tristate "9P File Descriptor Transports (Experimental)" | ||
20 | help | ||
21 | This builds support for file descriptor transports for 9p | ||
22 | which includes support for TCP/IP, named pipes, or passed | ||
23 | file descriptors. TCP/IP is the default transport for 9p, | ||
24 | so if you are going to use 9p, you'll likely want this. | ||
25 | |||
16 | config NET_9P_DEBUG | 26 | config NET_9P_DEBUG |
17 | bool "Debug information" | 27 | bool "Debug information" |
18 | depends on NET_9P | 28 | depends on NET_9P |
19 | help | 29 | help |
20 | Say Y if you want the 9P subsistem to log debug information. | 30 | Say Y if you want the 9P subsystem to log debug information. |
21 | 31 | ||
diff --git a/net/9p/Makefile b/net/9p/Makefile index 85b3a7838acf..5059bc06f8f3 100644 --- a/net/9p/Makefile +++ b/net/9p/Makefile | |||
@@ -1,8 +1,8 @@ | |||
1 | obj-$(CONFIG_NET_9P) := 9pnet.o | 1 | obj-$(CONFIG_NET_9P) := 9pnet.o |
2 | obj-$(CONFIG_NET_9P_FD) += 9pnet_fd.o | ||
2 | 3 | ||
3 | 9pnet-objs := \ | 4 | 9pnet-objs := \ |
4 | mod.o \ | 5 | mod.o \ |
5 | trans_fd.o \ | ||
6 | mux.o \ | 6 | mux.o \ |
7 | client.o \ | 7 | client.o \ |
8 | conv.o \ | 8 | conv.o \ |
@@ -10,4 +10,5 @@ obj-$(CONFIG_NET_9P) := 9pnet.o | |||
10 | fcprint.o \ | 10 | fcprint.o \ |
11 | util.o \ | 11 | util.o \ |
12 | 12 | ||
13 | 9pnet-$(CONFIG_SYSCTL) += sysctl.o | 13 | 9pnet_fd-objs := \ |
14 | trans_fd.o \ | ||
diff --git a/net/9p/client.c b/net/9p/client.c index cb170750337c..af9199364049 100644 --- a/net/9p/client.c +++ b/net/9p/client.c | |||
@@ -30,6 +30,7 @@ | |||
30 | #include <linux/sched.h> | 30 | #include <linux/sched.h> |
31 | #include <linux/uaccess.h> | 31 | #include <linux/uaccess.h> |
32 | #include <net/9p/9p.h> | 32 | #include <net/9p/9p.h> |
33 | #include <linux/parser.h> | ||
33 | #include <net/9p/transport.h> | 34 | #include <net/9p/transport.h> |
34 | #include <net/9p/conn.h> | 35 | #include <net/9p/conn.h> |
35 | #include <net/9p/client.h> | 36 | #include <net/9p/client.h> |
@@ -38,7 +39,7 @@ static struct p9_fid *p9_fid_create(struct p9_client *clnt); | |||
38 | static void p9_fid_destroy(struct p9_fid *fid); | 39 | static void p9_fid_destroy(struct p9_fid *fid); |
39 | static struct p9_stat *p9_clone_stat(struct p9_stat *st, int dotu); | 40 | static struct p9_stat *p9_clone_stat(struct p9_stat *st, int dotu); |
40 | 41 | ||
41 | struct p9_client *p9_client_create(struct p9_transport *trans, int msize, | 42 | struct p9_client *p9_client_create(struct p9_trans *trans, int msize, |
42 | int dotu) | 43 | int dotu) |
43 | { | 44 | { |
44 | int err, n; | 45 | int err, n; |
@@ -146,7 +147,7 @@ void p9_client_disconnect(struct p9_client *clnt) | |||
146 | EXPORT_SYMBOL(p9_client_disconnect); | 147 | EXPORT_SYMBOL(p9_client_disconnect); |
147 | 148 | ||
148 | struct p9_fid *p9_client_attach(struct p9_client *clnt, struct p9_fid *afid, | 149 | struct p9_fid *p9_client_attach(struct p9_client *clnt, struct p9_fid *afid, |
149 | char *uname, char *aname) | 150 | char *uname, u32 n_uname, char *aname) |
150 | { | 151 | { |
151 | int err; | 152 | int err; |
152 | struct p9_fcall *tc, *rc; | 153 | struct p9_fcall *tc, *rc; |
@@ -165,7 +166,8 @@ struct p9_fid *p9_client_attach(struct p9_client *clnt, struct p9_fid *afid, | |||
165 | goto error; | 166 | goto error; |
166 | } | 167 | } |
167 | 168 | ||
168 | tc = p9_create_tattach(fid->fid, afid?afid->fid:P9_NOFID, uname, aname); | 169 | tc = p9_create_tattach(fid->fid, afid?afid->fid:P9_NOFID, uname, aname, |
170 | n_uname, clnt->dotu); | ||
169 | if (IS_ERR(tc)) { | 171 | if (IS_ERR(tc)) { |
170 | err = PTR_ERR(tc); | 172 | err = PTR_ERR(tc); |
171 | tc = NULL; | 173 | tc = NULL; |
@@ -190,7 +192,8 @@ error: | |||
190 | } | 192 | } |
191 | EXPORT_SYMBOL(p9_client_attach); | 193 | EXPORT_SYMBOL(p9_client_attach); |
192 | 194 | ||
193 | struct p9_fid *p9_client_auth(struct p9_client *clnt, char *uname, char *aname) | 195 | struct p9_fid *p9_client_auth(struct p9_client *clnt, char *uname, |
196 | u32 n_uname, char *aname) | ||
194 | { | 197 | { |
195 | int err; | 198 | int err; |
196 | struct p9_fcall *tc, *rc; | 199 | struct p9_fcall *tc, *rc; |
@@ -209,7 +212,7 @@ struct p9_fid *p9_client_auth(struct p9_client *clnt, char *uname, char *aname) | |||
209 | goto error; | 212 | goto error; |
210 | } | 213 | } |
211 | 214 | ||
212 | tc = p9_create_tauth(fid->fid, uname, aname); | 215 | tc = p9_create_tauth(fid->fid, uname, aname, n_uname, clnt->dotu); |
213 | if (IS_ERR(tc)) { | 216 | if (IS_ERR(tc)) { |
214 | err = PTR_ERR(tc); | 217 | err = PTR_ERR(tc); |
215 | tc = NULL; | 218 | tc = NULL; |
diff --git a/net/9p/conv.c b/net/9p/conv.c index d979d958ea19..aa2aa9884f95 100644 --- a/net/9p/conv.c +++ b/net/9p/conv.c | |||
@@ -547,7 +547,8 @@ error: | |||
547 | } | 547 | } |
548 | EXPORT_SYMBOL(p9_create_tversion); | 548 | EXPORT_SYMBOL(p9_create_tversion); |
549 | 549 | ||
550 | struct p9_fcall *p9_create_tauth(u32 afid, char *uname, char *aname) | 550 | struct p9_fcall *p9_create_tauth(u32 afid, char *uname, char *aname, |
551 | u32 n_uname, int dotu) | ||
551 | { | 552 | { |
552 | int size; | 553 | int size; |
553 | struct p9_fcall *fc; | 554 | struct p9_fcall *fc; |
@@ -555,7 +556,16 @@ struct p9_fcall *p9_create_tauth(u32 afid, char *uname, char *aname) | |||
555 | struct cbuf *bufp = &buffer; | 556 | struct cbuf *bufp = &buffer; |
556 | 557 | ||
557 | /* afid[4] uname[s] aname[s] */ | 558 | /* afid[4] uname[s] aname[s] */ |
558 | size = 4 + 2 + strlen(uname) + 2 + strlen(aname); | 559 | size = 4 + 2 + 2; |
560 | if (uname) | ||
561 | size += strlen(uname); | ||
562 | |||
563 | if (aname) | ||
564 | size += strlen(aname); | ||
565 | |||
566 | if (dotu) | ||
567 | size += 4; /* n_uname */ | ||
568 | |||
559 | fc = p9_create_common(bufp, size, P9_TAUTH); | 569 | fc = p9_create_common(bufp, size, P9_TAUTH); |
560 | if (IS_ERR(fc)) | 570 | if (IS_ERR(fc)) |
561 | goto error; | 571 | goto error; |
@@ -563,6 +573,8 @@ struct p9_fcall *p9_create_tauth(u32 afid, char *uname, char *aname) | |||
563 | p9_put_int32(bufp, afid, &fc->params.tauth.afid); | 573 | p9_put_int32(bufp, afid, &fc->params.tauth.afid); |
564 | p9_put_str(bufp, uname, &fc->params.tauth.uname); | 574 | p9_put_str(bufp, uname, &fc->params.tauth.uname); |
565 | p9_put_str(bufp, aname, &fc->params.tauth.aname); | 575 | p9_put_str(bufp, aname, &fc->params.tauth.aname); |
576 | if (dotu) | ||
577 | p9_put_int32(bufp, n_uname, &fc->params.tauth.n_uname); | ||
566 | 578 | ||
567 | if (buf_check_overflow(bufp)) { | 579 | if (buf_check_overflow(bufp)) { |
568 | kfree(fc); | 580 | kfree(fc); |
@@ -574,7 +586,8 @@ error: | |||
574 | EXPORT_SYMBOL(p9_create_tauth); | 586 | EXPORT_SYMBOL(p9_create_tauth); |
575 | 587 | ||
576 | struct p9_fcall * | 588 | struct p9_fcall * |
577 | p9_create_tattach(u32 fid, u32 afid, char *uname, char *aname) | 589 | p9_create_tattach(u32 fid, u32 afid, char *uname, char *aname, |
590 | u32 n_uname, int dotu) | ||
578 | { | 591 | { |
579 | int size; | 592 | int size; |
580 | struct p9_fcall *fc; | 593 | struct p9_fcall *fc; |
@@ -582,7 +595,16 @@ p9_create_tattach(u32 fid, u32 afid, char *uname, char *aname) | |||
582 | struct cbuf *bufp = &buffer; | 595 | struct cbuf *bufp = &buffer; |
583 | 596 | ||
584 | /* fid[4] afid[4] uname[s] aname[s] */ | 597 | /* fid[4] afid[4] uname[s] aname[s] */ |
585 | size = 4 + 4 + 2 + strlen(uname) + 2 + strlen(aname); | 598 | size = 4 + 4 + 2 + 2; |
599 | if (uname) | ||
600 | size += strlen(uname); | ||
601 | |||
602 | if (aname) | ||
603 | size += strlen(aname); | ||
604 | |||
605 | if (dotu) | ||
606 | size += 4; /* n_uname */ | ||
607 | |||
586 | fc = p9_create_common(bufp, size, P9_TATTACH); | 608 | fc = p9_create_common(bufp, size, P9_TATTACH); |
587 | if (IS_ERR(fc)) | 609 | if (IS_ERR(fc)) |
588 | goto error; | 610 | goto error; |
@@ -591,6 +613,8 @@ p9_create_tattach(u32 fid, u32 afid, char *uname, char *aname) | |||
591 | p9_put_int32(bufp, afid, &fc->params.tattach.afid); | 613 | p9_put_int32(bufp, afid, &fc->params.tattach.afid); |
592 | p9_put_str(bufp, uname, &fc->params.tattach.uname); | 614 | p9_put_str(bufp, uname, &fc->params.tattach.uname); |
593 | p9_put_str(bufp, aname, &fc->params.tattach.aname); | 615 | p9_put_str(bufp, aname, &fc->params.tattach.aname); |
616 | if (dotu) | ||
617 | p9_put_int32(bufp, n_uname, &fc->params.tattach.n_uname); | ||
594 | 618 | ||
595 | error: | 619 | error: |
596 | return fc; | 620 | return fc; |
diff --git a/net/9p/mod.c b/net/9p/mod.c index 4f9e1d2ac257..41d70f47375d 100644 --- a/net/9p/mod.c +++ b/net/9p/mod.c | |||
@@ -27,6 +27,10 @@ | |||
27 | #include <linux/module.h> | 27 | #include <linux/module.h> |
28 | #include <linux/moduleparam.h> | 28 | #include <linux/moduleparam.h> |
29 | #include <net/9p/9p.h> | 29 | #include <net/9p/9p.h> |
30 | #include <linux/fs.h> | ||
31 | #include <linux/parser.h> | ||
32 | #include <net/9p/transport.h> | ||
33 | #include <linux/list.h> | ||
30 | 34 | ||
31 | #ifdef CONFIG_NET_9P_DEBUG | 35 | #ifdef CONFIG_NET_9P_DEBUG |
32 | unsigned int p9_debug_level = 0; /* feature-rific global debug level */ | 36 | unsigned int p9_debug_level = 0; /* feature-rific global debug level */ |
@@ -37,8 +41,64 @@ MODULE_PARM_DESC(debug, "9P debugging level"); | |||
37 | 41 | ||
38 | extern int p9_mux_global_init(void); | 42 | extern int p9_mux_global_init(void); |
39 | extern void p9_mux_global_exit(void); | 43 | extern void p9_mux_global_exit(void); |
40 | extern int p9_sysctl_register(void); | 44 | |
41 | extern void p9_sysctl_unregister(void); | 45 | /* |
46 | * Dynamic Transport Registration Routines | ||
47 | * | ||
48 | */ | ||
49 | |||
50 | static LIST_HEAD(v9fs_trans_list); | ||
51 | static struct p9_trans_module *v9fs_default_transport; | ||
52 | |||
53 | /** | ||
54 | * v9fs_register_trans - register a new transport with 9p | ||
55 | * @m - structure describing the transport module and entry points | ||
56 | * | ||
57 | */ | ||
58 | void v9fs_register_trans(struct p9_trans_module *m) | ||
59 | { | ||
60 | list_add_tail(&m->list, &v9fs_trans_list); | ||
61 | if (m->def) | ||
62 | v9fs_default_transport = m; | ||
63 | } | ||
64 | EXPORT_SYMBOL(v9fs_register_trans); | ||
65 | |||
66 | /** | ||
67 | * v9fs_match_trans - match transport versus registered transports | ||
68 | * @arg: string identifying transport | ||
69 | * | ||
70 | */ | ||
71 | struct p9_trans_module *v9fs_match_trans(const substring_t *name) | ||
72 | { | ||
73 | struct list_head *p; | ||
74 | struct p9_trans_module *t = NULL; | ||
75 | |||
76 | list_for_each(p, &v9fs_trans_list) { | ||
77 | t = list_entry(p, struct p9_trans_module, list); | ||
78 | if (strncmp(t->name, name->from, name->to-name->from) == 0) | ||
79 | break; | ||
80 | } | ||
81 | return t; | ||
82 | } | ||
83 | EXPORT_SYMBOL(v9fs_match_trans); | ||
84 | |||
85 | /** | ||
86 | * v9fs_default_trans - returns pointer to default transport | ||
87 | * | ||
88 | */ | ||
89 | |||
90 | struct p9_trans_module *v9fs_default_trans(void) | ||
91 | { | ||
92 | if (v9fs_default_transport) | ||
93 | return v9fs_default_transport; | ||
94 | else if (!list_empty(&v9fs_trans_list)) | ||
95 | return list_first_entry(&v9fs_trans_list, | ||
96 | struct p9_trans_module, list); | ||
97 | else | ||
98 | return NULL; | ||
99 | } | ||
100 | EXPORT_SYMBOL(v9fs_default_trans); | ||
101 | |||
42 | 102 | ||
43 | /** | 103 | /** |
44 | * v9fs_init - Initialize module | 104 | * v9fs_init - Initialize module |
@@ -56,12 +116,6 @@ static int __init init_p9(void) | |||
56 | return ret; | 116 | return ret; |
57 | } | 117 | } |
58 | 118 | ||
59 | ret = p9_sysctl_register(); | ||
60 | if (ret) { | ||
61 | printk(KERN_WARNING "9p: registering sysctl failed\n"); | ||
62 | return ret; | ||
63 | } | ||
64 | |||
65 | return ret; | 119 | return ret; |
66 | } | 120 | } |
67 | 121 | ||
@@ -72,7 +126,6 @@ static int __init init_p9(void) | |||
72 | 126 | ||
73 | static void __exit exit_p9(void) | 127 | static void __exit exit_p9(void) |
74 | { | 128 | { |
75 | p9_sysctl_unregister(); | ||
76 | p9_mux_global_exit(); | 129 | p9_mux_global_exit(); |
77 | } | 130 | } |
78 | 131 | ||
diff --git a/net/9p/mux.c b/net/9p/mux.c index 5d70558c4c61..f14014793bed 100644 --- a/net/9p/mux.c +++ b/net/9p/mux.c | |||
@@ -31,6 +31,7 @@ | |||
31 | #include <linux/idr.h> | 31 | #include <linux/idr.h> |
32 | #include <linux/mutex.h> | 32 | #include <linux/mutex.h> |
33 | #include <net/9p/9p.h> | 33 | #include <net/9p/9p.h> |
34 | #include <linux/parser.h> | ||
34 | #include <net/9p/transport.h> | 35 | #include <net/9p/transport.h> |
35 | #include <net/9p/conn.h> | 36 | #include <net/9p/conn.h> |
36 | 37 | ||
@@ -71,7 +72,7 @@ struct p9_conn { | |||
71 | struct p9_mux_poll_task *poll_task; | 72 | struct p9_mux_poll_task *poll_task; |
72 | int msize; | 73 | int msize; |
73 | unsigned char *extended; | 74 | unsigned char *extended; |
74 | struct p9_transport *trans; | 75 | struct p9_trans *trans; |
75 | struct p9_idpool *tagpool; | 76 | struct p9_idpool *tagpool; |
76 | int err; | 77 | int err; |
77 | wait_queue_head_t equeue; | 78 | wait_queue_head_t equeue; |
@@ -271,7 +272,7 @@ static void p9_mux_poll_stop(struct p9_conn *m) | |||
271 | * @msize - maximum message size | 272 | * @msize - maximum message size |
272 | * @extended - pointer to the extended flag | 273 | * @extended - pointer to the extended flag |
273 | */ | 274 | */ |
274 | struct p9_conn *p9_conn_create(struct p9_transport *trans, int msize, | 275 | struct p9_conn *p9_conn_create(struct p9_trans *trans, int msize, |
275 | unsigned char *extended) | 276 | unsigned char *extended) |
276 | { | 277 | { |
277 | int i, n; | 278 | int i, n; |
diff --git a/net/9p/sysctl.c b/net/9p/sysctl.c deleted file mode 100644 index 8b61027a24ea..000000000000 --- a/net/9p/sysctl.c +++ /dev/null | |||
@@ -1,81 +0,0 @@ | |||
1 | /* | ||
2 | * net/9p/sysctl.c | ||
3 | * | ||
4 | * 9P sysctl interface | ||
5 | * | ||
6 | * Copyright (C) 2007 by Latchesar Ionkov <lucho@ionkov.net> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 | ||
10 | * as published by the Free Software Foundation. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to: | ||
19 | * Free Software Foundation | ||
20 | * 51 Franklin Street, Fifth Floor | ||
21 | * Boston, MA 02111-1301 USA | ||
22 | * | ||
23 | */ | ||
24 | |||
25 | #include <linux/kernel.h> | ||
26 | #include <linux/mm.h> | ||
27 | #include <linux/sysctl.h> | ||
28 | #include <linux/init.h> | ||
29 | #include <net/9p/9p.h> | ||
30 | |||
31 | static struct ctl_table p9_table[] = { | ||
32 | #ifdef CONFIG_NET_9P_DEBUG | ||
33 | { | ||
34 | .ctl_name = CTL_UNNUMBERED, | ||
35 | .procname = "debug", | ||
36 | .data = &p9_debug_level, | ||
37 | .maxlen = sizeof(int), | ||
38 | .mode = 0644, | ||
39 | .proc_handler = &proc_dointvec | ||
40 | }, | ||
41 | #endif | ||
42 | {}, | ||
43 | }; | ||
44 | |||
45 | static struct ctl_table p9_net_table[] = { | ||
46 | { | ||
47 | .ctl_name = CTL_UNNUMBERED, | ||
48 | .procname = "9p", | ||
49 | .maxlen = 0, | ||
50 | .mode = 0555, | ||
51 | .child = p9_table, | ||
52 | }, | ||
53 | {}, | ||
54 | }; | ||
55 | |||
56 | static struct ctl_table p9_ctl_table[] = { | ||
57 | { | ||
58 | .ctl_name = CTL_NET, | ||
59 | .procname = "net", | ||
60 | .maxlen = 0, | ||
61 | .mode = 0555, | ||
62 | .child = p9_net_table, | ||
63 | }, | ||
64 | {}, | ||
65 | }; | ||
66 | |||
67 | static struct ctl_table_header *p9_table_header; | ||
68 | |||
69 | int __init p9_sysctl_register(void) | ||
70 | { | ||
71 | p9_table_header = register_sysctl_table(p9_ctl_table); | ||
72 | if (!p9_table_header) | ||
73 | return -ENOMEM; | ||
74 | |||
75 | return 0; | ||
76 | } | ||
77 | |||
78 | void __exit p9_sysctl_unregister(void) | ||
79 | { | ||
80 | unregister_sysctl_table(p9_table_header); | ||
81 | } | ||
diff --git a/net/9p/trans_fd.c b/net/9p/trans_fd.c index fd636e94358f..30269a4ff22a 100644 --- a/net/9p/trans_fd.c +++ b/net/9p/trans_fd.c | |||
@@ -5,7 +5,7 @@ | |||
5 | * | 5 | * |
6 | * Copyright (C) 2006 by Russ Cox <rsc@swtch.com> | 6 | * Copyright (C) 2006 by Russ Cox <rsc@swtch.com> |
7 | * Copyright (C) 2004-2005 by Latchesar Ionkov <lucho@ionkov.net> | 7 | * Copyright (C) 2004-2005 by Latchesar Ionkov <lucho@ionkov.net> |
8 | * Copyright (C) 2004-2005 by Eric Van Hensbergen <ericvh@gmail.com> | 8 | * Copyright (C) 2004-2007 by Eric Van Hensbergen <ericvh@gmail.com> |
9 | * Copyright (C) 1997-2002 by Ron Minnich <rminnich@sarnoff.com> | 9 | * Copyright (C) 1997-2002 by Ron Minnich <rminnich@sarnoff.com> |
10 | * | 10 | * |
11 | * This program is free software; you can redistribute it and/or modify | 11 | * This program is free software; you can redistribute it and/or modify |
@@ -36,160 +36,114 @@ | |||
36 | #include <linux/inet.h> | 36 | #include <linux/inet.h> |
37 | #include <linux/idr.h> | 37 | #include <linux/idr.h> |
38 | #include <linux/file.h> | 38 | #include <linux/file.h> |
39 | #include <linux/parser.h> | ||
39 | #include <net/9p/9p.h> | 40 | #include <net/9p/9p.h> |
40 | #include <net/9p/transport.h> | 41 | #include <net/9p/transport.h> |
41 | 42 | ||
42 | #define P9_PORT 564 | 43 | #define P9_PORT 564 |
44 | #define MAX_SOCK_BUF (64*1024) | ||
45 | |||
46 | |||
47 | struct p9_fd_opts { | ||
48 | int rfd; | ||
49 | int wfd; | ||
50 | u16 port; | ||
51 | }; | ||
43 | 52 | ||
44 | struct p9_trans_fd { | 53 | struct p9_trans_fd { |
45 | struct file *rd; | 54 | struct file *rd; |
46 | struct file *wr; | 55 | struct file *wr; |
47 | }; | 56 | }; |
48 | 57 | ||
49 | static int p9_socket_open(struct p9_transport *trans, struct socket *csocket); | 58 | /* |
50 | static int p9_fd_open(struct p9_transport *trans, int rfd, int wfd); | 59 | * Option Parsing (code inspired by NFS code) |
51 | static int p9_fd_read(struct p9_transport *trans, void *v, int len); | 60 | * - a little lazy - parse all fd-transport options |
52 | static int p9_fd_write(struct p9_transport *trans, void *v, int len); | 61 | */ |
53 | static unsigned int p9_fd_poll(struct p9_transport *trans, | ||
54 | struct poll_table_struct *pt); | ||
55 | static void p9_fd_close(struct p9_transport *trans); | ||
56 | |||
57 | struct p9_transport *p9_trans_create_tcp(const char *addr, int port) | ||
58 | { | ||
59 | int err; | ||
60 | struct p9_transport *trans; | ||
61 | struct socket *csocket; | ||
62 | struct sockaddr_in sin_server; | ||
63 | |||
64 | csocket = NULL; | ||
65 | trans = kmalloc(sizeof(struct p9_transport), GFP_KERNEL); | ||
66 | if (!trans) | ||
67 | return ERR_PTR(-ENOMEM); | ||
68 | |||
69 | trans->write = p9_fd_write; | ||
70 | trans->read = p9_fd_read; | ||
71 | trans->close = p9_fd_close; | ||
72 | trans->poll = p9_fd_poll; | ||
73 | |||
74 | sin_server.sin_family = AF_INET; | ||
75 | sin_server.sin_addr.s_addr = in_aton(addr); | ||
76 | sin_server.sin_port = htons(port); | ||
77 | sock_create_kern(PF_INET, SOCK_STREAM, IPPROTO_TCP, &csocket); | ||
78 | |||
79 | if (!csocket) { | ||
80 | P9_EPRINTK(KERN_ERR, "p9_trans_tcp: problem creating socket\n"); | ||
81 | err = -EIO; | ||
82 | goto error; | ||
83 | } | ||
84 | |||
85 | err = csocket->ops->connect(csocket, | ||
86 | (struct sockaddr *)&sin_server, | ||
87 | sizeof(struct sockaddr_in), 0); | ||
88 | if (err < 0) { | ||
89 | P9_EPRINTK(KERN_ERR, | ||
90 | "p9_trans_tcp: problem connecting socket to %s\n", | ||
91 | addr); | ||
92 | goto error; | ||
93 | } | ||
94 | |||
95 | err = p9_socket_open(trans, csocket); | ||
96 | if (err < 0) | ||
97 | goto error; | ||
98 | 62 | ||
99 | return trans; | 63 | enum { |
64 | /* Options that take integer arguments */ | ||
65 | Opt_port, Opt_rfdno, Opt_wfdno, | ||
66 | }; | ||
100 | 67 | ||
101 | error: | 68 | static match_table_t tokens = { |
102 | if (csocket) | 69 | {Opt_port, "port=%u"}, |
103 | sock_release(csocket); | 70 | {Opt_rfdno, "rfdno=%u"}, |
71 | {Opt_wfdno, "wfdno=%u"}, | ||
72 | }; | ||
104 | 73 | ||
105 | kfree(trans); | 74 | /** |
106 | return ERR_PTR(err); | 75 | * v9fs_parse_options - parse mount options into session structure |
107 | } | 76 | * @options: options string passed from mount |
108 | EXPORT_SYMBOL(p9_trans_create_tcp); | 77 | * @v9ses: existing v9fs session information |
78 | * | ||
79 | */ | ||
109 | 80 | ||
110 | struct p9_transport *p9_trans_create_unix(const char *addr) | 81 | static void parse_opts(char *options, struct p9_fd_opts *opts) |
111 | { | 82 | { |
112 | int err; | 83 | char *p; |
113 | struct socket *csocket; | 84 | substring_t args[MAX_OPT_ARGS]; |
114 | struct sockaddr_un sun_server; | 85 | int option; |
115 | struct p9_transport *trans; | 86 | int ret; |
116 | |||
117 | csocket = NULL; | ||
118 | trans = kmalloc(sizeof(struct p9_transport), GFP_KERNEL); | ||
119 | if (!trans) | ||
120 | return ERR_PTR(-ENOMEM); | ||
121 | 87 | ||
122 | trans->write = p9_fd_write; | 88 | opts->port = P9_PORT; |
123 | trans->read = p9_fd_read; | 89 | opts->rfd = ~0; |
124 | trans->close = p9_fd_close; | 90 | opts->wfd = ~0; |
125 | trans->poll = p9_fd_poll; | ||
126 | 91 | ||
127 | if (strlen(addr) > UNIX_PATH_MAX) { | 92 | if (!options) |
128 | P9_EPRINTK(KERN_ERR, "p9_trans_unix: address too long: %s\n", | 93 | return; |
129 | addr); | ||
130 | err = -ENAMETOOLONG; | ||
131 | goto error; | ||
132 | } | ||
133 | 94 | ||
134 | sun_server.sun_family = PF_UNIX; | 95 | while ((p = strsep(&options, ",")) != NULL) { |
135 | strcpy(sun_server.sun_path, addr); | 96 | int token; |
136 | sock_create_kern(PF_UNIX, SOCK_STREAM, 0, &csocket); | 97 | if (!*p) |
137 | err = csocket->ops->connect(csocket, (struct sockaddr *)&sun_server, | 98 | continue; |
138 | sizeof(struct sockaddr_un) - 1, 0); | 99 | token = match_token(p, tokens, args); |
139 | if (err < 0) { | 100 | ret = match_int(&args[0], &option); |
140 | P9_EPRINTK(KERN_ERR, | 101 | if (ret < 0) { |
141 | "p9_trans_unix: problem connecting socket: %s: %d\n", | 102 | P9_DPRINTK(P9_DEBUG_ERROR, |
142 | addr, err); | 103 | "integer field, but no integer?\n"); |
143 | goto error; | 104 | continue; |
105 | } | ||
106 | switch (token) { | ||
107 | case Opt_port: | ||
108 | opts->port = option; | ||
109 | break; | ||
110 | case Opt_rfdno: | ||
111 | opts->rfd = option; | ||
112 | break; | ||
113 | case Opt_wfdno: | ||
114 | opts->wfd = option; | ||
115 | break; | ||
116 | default: | ||
117 | continue; | ||
118 | } | ||
144 | } | 119 | } |
145 | |||
146 | err = p9_socket_open(trans, csocket); | ||
147 | if (err < 0) | ||
148 | goto error; | ||
149 | |||
150 | return trans; | ||
151 | |||
152 | error: | ||
153 | if (csocket) | ||
154 | sock_release(csocket); | ||
155 | |||
156 | kfree(trans); | ||
157 | return ERR_PTR(err); | ||
158 | } | 120 | } |
159 | EXPORT_SYMBOL(p9_trans_create_unix); | ||
160 | 121 | ||
161 | struct p9_transport *p9_trans_create_fd(int rfd, int wfd) | 122 | static int p9_fd_open(struct p9_trans *trans, int rfd, int wfd) |
162 | { | 123 | { |
163 | int err; | 124 | struct p9_trans_fd *ts = kmalloc(sizeof(struct p9_trans_fd), |
164 | struct p9_transport *trans; | 125 | GFP_KERNEL); |
126 | if (!ts) | ||
127 | return -ENOMEM; | ||
165 | 128 | ||
166 | if (rfd == ~0 || wfd == ~0) { | 129 | ts->rd = fget(rfd); |
167 | printk(KERN_ERR "v9fs: Insufficient options for proto=fd\n"); | 130 | ts->wr = fget(wfd); |
168 | return ERR_PTR(-ENOPROTOOPT); | 131 | if (!ts->rd || !ts->wr) { |
132 | if (ts->rd) | ||
133 | fput(ts->rd); | ||
134 | if (ts->wr) | ||
135 | fput(ts->wr); | ||
136 | kfree(ts); | ||
137 | return -EIO; | ||
169 | } | 138 | } |
170 | 139 | ||
171 | trans = kmalloc(sizeof(struct p9_transport), GFP_KERNEL); | 140 | trans->priv = ts; |
172 | if (!trans) | 141 | trans->status = Connected; |
173 | return ERR_PTR(-ENOMEM); | ||
174 | |||
175 | trans->write = p9_fd_write; | ||
176 | trans->read = p9_fd_read; | ||
177 | trans->close = p9_fd_close; | ||
178 | trans->poll = p9_fd_poll; | ||
179 | |||
180 | err = p9_fd_open(trans, rfd, wfd); | ||
181 | if (err < 0) | ||
182 | goto error; | ||
183 | |||
184 | return trans; | ||
185 | 142 | ||
186 | error: | 143 | return 0; |
187 | kfree(trans); | ||
188 | return ERR_PTR(err); | ||
189 | } | 144 | } |
190 | EXPORT_SYMBOL(p9_trans_create_fd); | ||
191 | 145 | ||
192 | static int p9_socket_open(struct p9_transport *trans, struct socket *csocket) | 146 | static int p9_socket_open(struct p9_trans *trans, struct socket *csocket) |
193 | { | 147 | { |
194 | int fd, ret; | 148 | int fd, ret; |
195 | 149 | ||
@@ -212,30 +166,6 @@ static int p9_socket_open(struct p9_transport *trans, struct socket *csocket) | |||
212 | return 0; | 166 | return 0; |
213 | } | 167 | } |
214 | 168 | ||
215 | static int p9_fd_open(struct p9_transport *trans, int rfd, int wfd) | ||
216 | { | ||
217 | struct p9_trans_fd *ts = kmalloc(sizeof(struct p9_trans_fd), | ||
218 | GFP_KERNEL); | ||
219 | if (!ts) | ||
220 | return -ENOMEM; | ||
221 | |||
222 | ts->rd = fget(rfd); | ||
223 | ts->wr = fget(wfd); | ||
224 | if (!ts->rd || !ts->wr) { | ||
225 | if (ts->rd) | ||
226 | fput(ts->rd); | ||
227 | if (ts->wr) | ||
228 | fput(ts->wr); | ||
229 | kfree(ts); | ||
230 | return -EIO; | ||
231 | } | ||
232 | |||
233 | trans->priv = ts; | ||
234 | trans->status = Connected; | ||
235 | |||
236 | return 0; | ||
237 | } | ||
238 | |||
239 | /** | 169 | /** |
240 | * p9_fd_read- read from a fd | 170 | * p9_fd_read- read from a fd |
241 | * @v9ses: session information | 171 | * @v9ses: session information |
@@ -243,7 +173,7 @@ static int p9_fd_open(struct p9_transport *trans, int rfd, int wfd) | |||
243 | * @len: size of receive buffer | 173 | * @len: size of receive buffer |
244 | * | 174 | * |
245 | */ | 175 | */ |
246 | static int p9_fd_read(struct p9_transport *trans, void *v, int len) | 176 | static int p9_fd_read(struct p9_trans *trans, void *v, int len) |
247 | { | 177 | { |
248 | int ret; | 178 | int ret; |
249 | struct p9_trans_fd *ts = NULL; | 179 | struct p9_trans_fd *ts = NULL; |
@@ -270,7 +200,7 @@ static int p9_fd_read(struct p9_transport *trans, void *v, int len) | |||
270 | * @len: size of send buffer | 200 | * @len: size of send buffer |
271 | * | 201 | * |
272 | */ | 202 | */ |
273 | static int p9_fd_write(struct p9_transport *trans, void *v, int len) | 203 | static int p9_fd_write(struct p9_trans *trans, void *v, int len) |
274 | { | 204 | { |
275 | int ret; | 205 | int ret; |
276 | mm_segment_t oldfs; | 206 | mm_segment_t oldfs; |
@@ -297,7 +227,7 @@ static int p9_fd_write(struct p9_transport *trans, void *v, int len) | |||
297 | } | 227 | } |
298 | 228 | ||
299 | static unsigned int | 229 | static unsigned int |
300 | p9_fd_poll(struct p9_transport *trans, struct poll_table_struct *pt) | 230 | p9_fd_poll(struct p9_trans *trans, struct poll_table_struct *pt) |
301 | { | 231 | { |
302 | int ret, n; | 232 | int ret, n; |
303 | struct p9_trans_fd *ts = NULL; | 233 | struct p9_trans_fd *ts = NULL; |
@@ -341,7 +271,7 @@ end: | |||
341 | * @trans: private socket structure | 271 | * @trans: private socket structure |
342 | * | 272 | * |
343 | */ | 273 | */ |
344 | static void p9_fd_close(struct p9_transport *trans) | 274 | static void p9_fd_close(struct p9_trans *trans) |
345 | { | 275 | { |
346 | struct p9_trans_fd *ts; | 276 | struct p9_trans_fd *ts; |
347 | 277 | ||
@@ -361,3 +291,182 @@ static void p9_fd_close(struct p9_transport *trans) | |||
361 | kfree(ts); | 291 | kfree(ts); |
362 | } | 292 | } |
363 | 293 | ||
294 | static struct p9_trans *p9_trans_create_tcp(const char *addr, char *args) | ||
295 | { | ||
296 | int err; | ||
297 | struct p9_trans *trans; | ||
298 | struct socket *csocket; | ||
299 | struct sockaddr_in sin_server; | ||
300 | struct p9_fd_opts opts; | ||
301 | |||
302 | parse_opts(args, &opts); | ||
303 | |||
304 | csocket = NULL; | ||
305 | trans = kmalloc(sizeof(struct p9_trans), GFP_KERNEL); | ||
306 | if (!trans) | ||
307 | return ERR_PTR(-ENOMEM); | ||
308 | |||
309 | trans->write = p9_fd_write; | ||
310 | trans->read = p9_fd_read; | ||
311 | trans->close = p9_fd_close; | ||
312 | trans->poll = p9_fd_poll; | ||
313 | |||
314 | sin_server.sin_family = AF_INET; | ||
315 | sin_server.sin_addr.s_addr = in_aton(addr); | ||
316 | sin_server.sin_port = htons(opts.port); | ||
317 | sock_create_kern(PF_INET, SOCK_STREAM, IPPROTO_TCP, &csocket); | ||
318 | |||
319 | if (!csocket) { | ||
320 | P9_EPRINTK(KERN_ERR, "p9_trans_tcp: problem creating socket\n"); | ||
321 | err = -EIO; | ||
322 | goto error; | ||
323 | } | ||
324 | |||
325 | err = csocket->ops->connect(csocket, | ||
326 | (struct sockaddr *)&sin_server, | ||
327 | sizeof(struct sockaddr_in), 0); | ||
328 | if (err < 0) { | ||
329 | P9_EPRINTK(KERN_ERR, | ||
330 | "p9_trans_tcp: problem connecting socket to %s\n", | ||
331 | addr); | ||
332 | goto error; | ||
333 | } | ||
334 | |||
335 | err = p9_socket_open(trans, csocket); | ||
336 | if (err < 0) | ||
337 | goto error; | ||
338 | |||
339 | return trans; | ||
340 | |||
341 | error: | ||
342 | if (csocket) | ||
343 | sock_release(csocket); | ||
344 | |||
345 | kfree(trans); | ||
346 | return ERR_PTR(err); | ||
347 | } | ||
348 | |||
349 | static struct p9_trans *p9_trans_create_unix(const char *addr, char *args) | ||
350 | { | ||
351 | int err; | ||
352 | struct socket *csocket; | ||
353 | struct sockaddr_un sun_server; | ||
354 | struct p9_trans *trans; | ||
355 | |||
356 | csocket = NULL; | ||
357 | trans = kmalloc(sizeof(struct p9_trans), GFP_KERNEL); | ||
358 | if (!trans) | ||
359 | return ERR_PTR(-ENOMEM); | ||
360 | |||
361 | trans->write = p9_fd_write; | ||
362 | trans->read = p9_fd_read; | ||
363 | trans->close = p9_fd_close; | ||
364 | trans->poll = p9_fd_poll; | ||
365 | |||
366 | if (strlen(addr) > UNIX_PATH_MAX) { | ||
367 | P9_EPRINTK(KERN_ERR, "p9_trans_unix: address too long: %s\n", | ||
368 | addr); | ||
369 | err = -ENAMETOOLONG; | ||
370 | goto error; | ||
371 | } | ||
372 | |||
373 | sun_server.sun_family = PF_UNIX; | ||
374 | strcpy(sun_server.sun_path, addr); | ||
375 | sock_create_kern(PF_UNIX, SOCK_STREAM, 0, &csocket); | ||
376 | err = csocket->ops->connect(csocket, (struct sockaddr *)&sun_server, | ||
377 | sizeof(struct sockaddr_un) - 1, 0); | ||
378 | if (err < 0) { | ||
379 | P9_EPRINTK(KERN_ERR, | ||
380 | "p9_trans_unix: problem connecting socket: %s: %d\n", | ||
381 | addr, err); | ||
382 | goto error; | ||
383 | } | ||
384 | |||
385 | err = p9_socket_open(trans, csocket); | ||
386 | if (err < 0) | ||
387 | goto error; | ||
388 | |||
389 | return trans; | ||
390 | |||
391 | error: | ||
392 | if (csocket) | ||
393 | sock_release(csocket); | ||
394 | |||
395 | kfree(trans); | ||
396 | return ERR_PTR(err); | ||
397 | } | ||
398 | |||
399 | static struct p9_trans *p9_trans_create_fd(const char *name, char *args) | ||
400 | { | ||
401 | int err; | ||
402 | struct p9_trans *trans; | ||
403 | struct p9_fd_opts opts; | ||
404 | |||
405 | parse_opts(args, &opts); | ||
406 | |||
407 | if (opts.rfd == ~0 || opts.wfd == ~0) { | ||
408 | printk(KERN_ERR "v9fs: Insufficient options for proto=fd\n"); | ||
409 | return ERR_PTR(-ENOPROTOOPT); | ||
410 | } | ||
411 | |||
412 | trans = kmalloc(sizeof(struct p9_trans), GFP_KERNEL); | ||
413 | if (!trans) | ||
414 | return ERR_PTR(-ENOMEM); | ||
415 | |||
416 | trans->write = p9_fd_write; | ||
417 | trans->read = p9_fd_read; | ||
418 | trans->close = p9_fd_close; | ||
419 | trans->poll = p9_fd_poll; | ||
420 | |||
421 | err = p9_fd_open(trans, opts.rfd, opts.wfd); | ||
422 | if (err < 0) | ||
423 | goto error; | ||
424 | |||
425 | return trans; | ||
426 | |||
427 | error: | ||
428 | kfree(trans); | ||
429 | return ERR_PTR(err); | ||
430 | } | ||
431 | |||
432 | static struct p9_trans_module p9_tcp_trans = { | ||
433 | .name = "tcp", | ||
434 | .maxsize = MAX_SOCK_BUF, | ||
435 | .def = 1, | ||
436 | .create = p9_trans_create_tcp, | ||
437 | }; | ||
438 | |||
439 | static struct p9_trans_module p9_unix_trans = { | ||
440 | .name = "unix", | ||
441 | .maxsize = MAX_SOCK_BUF, | ||
442 | .def = 0, | ||
443 | .create = p9_trans_create_unix, | ||
444 | }; | ||
445 | |||
446 | static struct p9_trans_module p9_fd_trans = { | ||
447 | .name = "fd", | ||
448 | .maxsize = MAX_SOCK_BUF, | ||
449 | .def = 0, | ||
450 | .create = p9_trans_create_fd, | ||
451 | }; | ||
452 | |||
453 | static int __init p9_trans_fd_init(void) | ||
454 | { | ||
455 | v9fs_register_trans(&p9_tcp_trans); | ||
456 | v9fs_register_trans(&p9_unix_trans); | ||
457 | v9fs_register_trans(&p9_fd_trans); | ||
458 | |||
459 | return 1; | ||
460 | } | ||
461 | |||
462 | static void __exit p9_trans_fd_exit(void) { | ||
463 | printk(KERN_ERR "Removal of 9p transports not implemented\n"); | ||
464 | BUG(); | ||
465 | } | ||
466 | |||
467 | module_init(p9_trans_fd_init); | ||
468 | module_exit(p9_trans_fd_exit); | ||
469 | |||
470 | MODULE_AUTHOR("Latchesar Ionkov <lucho@ionkov.net>"); | ||
471 | MODULE_AUTHOR("Eric Van Hensbergen <ericvh@gmail.com>"); | ||
472 | MODULE_LICENSE("GPL"); | ||
diff --git a/net/atm/br2684.c b/net/atm/br2684.c index c742d37bfb97..ba6428f204f9 100644 --- a/net/atm/br2684.c +++ b/net/atm/br2684.c | |||
@@ -24,16 +24,6 @@ Author: Marcell GAL, 2000, XDSL Ltd, Hungary | |||
24 | 24 | ||
25 | #include "common.h" | 25 | #include "common.h" |
26 | 26 | ||
27 | /* | ||
28 | * Define this to use a version of the code which interacts with the higher | ||
29 | * layers in a more intellegent way, by always reserving enough space for | ||
30 | * our header at the begining of the packet. However, there may still be | ||
31 | * some problems with programs like tcpdump. In 2.5 we'll sort out what | ||
32 | * we need to do to get this perfect. For now we just will copy the packet | ||
33 | * if we need space for the header | ||
34 | */ | ||
35 | /* #define FASTER_VERSION */ | ||
36 | |||
37 | #ifdef SKB_DEBUG | 27 | #ifdef SKB_DEBUG |
38 | static void skb_debug(const struct sk_buff *skb) | 28 | static void skb_debug(const struct sk_buff *skb) |
39 | { | 29 | { |
@@ -69,9 +59,7 @@ struct br2684_vcc { | |||
69 | #ifdef CONFIG_ATM_BR2684_IPFILTER | 59 | #ifdef CONFIG_ATM_BR2684_IPFILTER |
70 | struct br2684_filter filter; | 60 | struct br2684_filter filter; |
71 | #endif /* CONFIG_ATM_BR2684_IPFILTER */ | 61 | #endif /* CONFIG_ATM_BR2684_IPFILTER */ |
72 | #ifndef FASTER_VERSION | ||
73 | unsigned copies_needed, copies_failed; | 62 | unsigned copies_needed, copies_failed; |
74 | #endif /* FASTER_VERSION */ | ||
75 | }; | 63 | }; |
76 | 64 | ||
77 | struct br2684_dev { | 65 | struct br2684_dev { |
@@ -147,13 +135,6 @@ static int br2684_xmit_vcc(struct sk_buff *skb, struct br2684_dev *brdev, | |||
147 | struct br2684_vcc *brvcc) | 135 | struct br2684_vcc *brvcc) |
148 | { | 136 | { |
149 | struct atm_vcc *atmvcc; | 137 | struct atm_vcc *atmvcc; |
150 | #ifdef FASTER_VERSION | ||
151 | if (brvcc->encaps == e_llc) | ||
152 | memcpy(skb_push(skb, 8), llc_oui_pid_pad, 8); | ||
153 | /* last 2 bytes of llc_oui_pid_pad are managed by header routines; | ||
154 | yes, you got it: 8 + 2 = sizeof(llc_oui_pid_pad) | ||
155 | */ | ||
156 | #else | ||
157 | int minheadroom = (brvcc->encaps == e_llc) ? 10 : 2; | 138 | int minheadroom = (brvcc->encaps == e_llc) ? 10 : 2; |
158 | if (skb_headroom(skb) < minheadroom) { | 139 | if (skb_headroom(skb) < minheadroom) { |
159 | struct sk_buff *skb2 = skb_realloc_headroom(skb, minheadroom); | 140 | struct sk_buff *skb2 = skb_realloc_headroom(skb, minheadroom); |
@@ -170,7 +151,6 @@ static int br2684_xmit_vcc(struct sk_buff *skb, struct br2684_dev *brdev, | |||
170 | skb_copy_to_linear_data(skb, llc_oui_pid_pad, 10); | 151 | skb_copy_to_linear_data(skb, llc_oui_pid_pad, 10); |
171 | else | 152 | else |
172 | memset(skb->data, 0, 2); | 153 | memset(skb->data, 0, 2); |
173 | #endif /* FASTER_VERSION */ | ||
174 | skb_debug(skb); | 154 | skb_debug(skb); |
175 | 155 | ||
176 | ATM_SKB(skb)->vcc = atmvcc = brvcc->atmvcc; | 156 | ATM_SKB(skb)->vcc = atmvcc = brvcc->atmvcc; |
@@ -237,87 +217,6 @@ static struct net_device_stats *br2684_get_stats(struct net_device *dev) | |||
237 | return &BRPRIV(dev)->stats; | 217 | return &BRPRIV(dev)->stats; |
238 | } | 218 | } |
239 | 219 | ||
240 | #ifdef FASTER_VERSION | ||
241 | /* | ||
242 | * These mirror eth_header and eth_header_cache. They are not usually | ||
243 | * exported for use in modules, so we grab them from net_device | ||
244 | * after ether_setup() is done with it. Bit of a hack. | ||
245 | */ | ||
246 | static int (*my_eth_header)(struct sk_buff *, struct net_device *, | ||
247 | unsigned short, void *, void *, unsigned); | ||
248 | static int (*my_eth_header_cache)(struct neighbour *, struct hh_cache *); | ||
249 | |||
250 | static int | ||
251 | br2684_header(struct sk_buff *skb, struct net_device *dev, | ||
252 | unsigned short type, void *daddr, void *saddr, unsigned len) | ||
253 | { | ||
254 | u16 *pad_before_eth; | ||
255 | int t = my_eth_header(skb, dev, type, daddr, saddr, len); | ||
256 | if (t > 0) { | ||
257 | pad_before_eth = (u16 *) skb_push(skb, 2); | ||
258 | *pad_before_eth = 0; | ||
259 | return dev->hard_header_len; /* or return 16; ? */ | ||
260 | } else | ||
261 | return t; | ||
262 | } | ||
263 | |||
264 | static int | ||
265 | br2684_header_cache(struct neighbour *neigh, struct hh_cache *hh) | ||
266 | { | ||
267 | /* hh_data is 16 bytes long. if encaps is ether-llc we need 24, so | ||
268 | xmit will add the additional header part in that case */ | ||
269 | u16 *pad_before_eth = (u16 *)(hh->hh_data); | ||
270 | int t = my_eth_header_cache(neigh, hh); | ||
271 | DPRINTK("br2684_header_cache, neigh=%p, hh_cache=%p\n", neigh, hh); | ||
272 | if (t < 0) | ||
273 | return t; | ||
274 | else { | ||
275 | *pad_before_eth = 0; | ||
276 | hh->hh_len = PADLEN + ETH_HLEN; | ||
277 | } | ||
278 | return 0; | ||
279 | } | ||
280 | |||
281 | /* | ||
282 | * This is similar to eth_type_trans, which cannot be used because of | ||
283 | * our dev->hard_header_len | ||
284 | */ | ||
285 | static inline __be16 br_type_trans(struct sk_buff *skb, struct net_device *dev) | ||
286 | { | ||
287 | struct ethhdr *eth; | ||
288 | unsigned char *rawp; | ||
289 | eth = eth_hdr(skb); | ||
290 | |||
291 | if (is_multicast_ether_addr(eth->h_dest)) { | ||
292 | if (!compare_ether_addr(eth->h_dest, dev->broadcast)) | ||
293 | skb->pkt_type = PACKET_BROADCAST; | ||
294 | else | ||
295 | skb->pkt_type = PACKET_MULTICAST; | ||
296 | } | ||
297 | |||
298 | else if (compare_ether_addr(eth->h_dest, dev->dev_addr)) | ||
299 | skb->pkt_type = PACKET_OTHERHOST; | ||
300 | |||
301 | if (ntohs(eth->h_proto) >= 1536) | ||
302 | return eth->h_proto; | ||
303 | |||
304 | rawp = skb->data; | ||
305 | |||
306 | /* | ||
307 | * This is a magic hack to spot IPX packets. Older Novell breaks | ||
308 | * the protocol design and runs IPX over 802.3 without an 802.2 LLC | ||
309 | * layer. We look for FFFF which isn't a used 802.2 SSAP/DSAP. This | ||
310 | * won't work for fault tolerant netware but does for the rest. | ||
311 | */ | ||
312 | if (*(unsigned short *) rawp == 0xFFFF) | ||
313 | return htons(ETH_P_802_3); | ||
314 | |||
315 | /* | ||
316 | * Real 802.2 LLC | ||
317 | */ | ||
318 | return htons(ETH_P_802_2); | ||
319 | } | ||
320 | #endif /* FASTER_VERSION */ | ||
321 | 220 | ||
322 | /* | 221 | /* |
323 | * We remember when the MAC gets set, so we don't override it later with | 222 | * We remember when the MAC gets set, so we don't override it later with |
@@ -448,17 +347,8 @@ static void br2684_push(struct atm_vcc *atmvcc, struct sk_buff *skb) | |||
448 | return; | 347 | return; |
449 | } | 348 | } |
450 | 349 | ||
451 | #ifdef FASTER_VERSION | ||
452 | /* FIXME: tcpdump shows that pointer to mac header is 2 bytes earlier, | ||
453 | than should be. What else should I set? */ | ||
454 | skb_pull(skb, plen); | ||
455 | skb_set_mac_header(skb, -ETH_HLEN); | ||
456 | skb->pkt_type = PACKET_HOST; | ||
457 | skb->protocol = br_type_trans(skb, net_dev); | ||
458 | #else | ||
459 | skb_pull(skb, plen - ETH_HLEN); | 350 | skb_pull(skb, plen - ETH_HLEN); |
460 | skb->protocol = eth_type_trans(skb, net_dev); | 351 | skb->protocol = eth_type_trans(skb, net_dev); |
461 | #endif /* FASTER_VERSION */ | ||
462 | #ifdef CONFIG_ATM_BR2684_IPFILTER | 352 | #ifdef CONFIG_ATM_BR2684_IPFILTER |
463 | if (unlikely(packet_fails_filter(skb->protocol, brvcc, skb))) { | 353 | if (unlikely(packet_fails_filter(skb->protocol, brvcc, skb))) { |
464 | brdev->stats.rx_dropped++; | 354 | brdev->stats.rx_dropped++; |
@@ -584,13 +474,6 @@ static void br2684_setup(struct net_device *netdev) | |||
584 | ether_setup(netdev); | 474 | ether_setup(netdev); |
585 | brdev->net_dev = netdev; | 475 | brdev->net_dev = netdev; |
586 | 476 | ||
587 | #ifdef FASTER_VERSION | ||
588 | my_eth_header = netdev->hard_header; | ||
589 | netdev->hard_header = br2684_header; | ||
590 | my_eth_header_cache = netdev->hard_header_cache; | ||
591 | netdev->hard_header_cache = br2684_header_cache; | ||
592 | netdev->hard_header_len = sizeof(llc_oui_pid_pad) + ETH_HLEN; /* 10 + 14 */ | ||
593 | #endif | ||
594 | my_eth_mac_addr = netdev->set_mac_address; | 477 | my_eth_mac_addr = netdev->set_mac_address; |
595 | netdev->set_mac_address = br2684_mac_addr; | 478 | netdev->set_mac_address = br2684_mac_addr; |
596 | netdev->hard_start_xmit = br2684_start_xmit; | 479 | netdev->hard_start_xmit = br2684_start_xmit; |
@@ -719,16 +602,12 @@ static int br2684_seq_show(struct seq_file *seq, void *v) | |||
719 | 602 | ||
720 | list_for_each_entry(brvcc, &brdev->brvccs, brvccs) { | 603 | list_for_each_entry(brvcc, &brdev->brvccs, brvccs) { |
721 | seq_printf(seq, " vcc %d.%d.%d: encaps=%s" | 604 | seq_printf(seq, " vcc %d.%d.%d: encaps=%s" |
722 | #ifndef FASTER_VERSION | ||
723 | ", failed copies %u/%u" | 605 | ", failed copies %u/%u" |
724 | #endif /* FASTER_VERSION */ | ||
725 | "\n", brvcc->atmvcc->dev->number, | 606 | "\n", brvcc->atmvcc->dev->number, |
726 | brvcc->atmvcc->vpi, brvcc->atmvcc->vci, | 607 | brvcc->atmvcc->vpi, brvcc->atmvcc->vci, |
727 | (brvcc->encaps == e_llc) ? "LLC" : "VC" | 608 | (brvcc->encaps == e_llc) ? "LLC" : "VC" |
728 | #ifndef FASTER_VERSION | ||
729 | , brvcc->copies_failed | 609 | , brvcc->copies_failed |
730 | , brvcc->copies_needed | 610 | , brvcc->copies_needed |
731 | #endif /* FASTER_VERSION */ | ||
732 | ); | 611 | ); |
733 | #ifdef CONFIG_ATM_BR2684_IPFILTER | 612 | #ifdef CONFIG_ATM_BR2684_IPFILTER |
734 | #define b1(var, byte) ((u8 *) &brvcc->filter.var)[byte] | 613 | #define b1(var, byte) ((u8 *) &brvcc->filter.var)[byte] |
diff --git a/net/ax25/ax25_ds_in.c b/net/ax25/ax25_ds_in.c index e37d217a986a..8273b1200eee 100644 --- a/net/ax25/ax25_ds_in.c +++ b/net/ax25/ax25_ds_in.c | |||
@@ -75,7 +75,7 @@ static int ax25_ds_state1_machine(ax25_cb *ax25, struct sk_buff *skb, int framet | |||
75 | } | 75 | } |
76 | ax25_dama_on(ax25); | 76 | ax25_dama_on(ax25); |
77 | 77 | ||
78 | /* according to DK4EG´s spec we are required to | 78 | /* according to DK4EG's spec we are required to |
79 | * send a RR RESPONSE FINAL NR=0. | 79 | * send a RR RESPONSE FINAL NR=0. |
80 | */ | 80 | */ |
81 | 81 | ||
diff --git a/net/ax25/ax25_ds_subr.c b/net/ax25/ax25_ds_subr.c index a49773ff2b92..b5e59787be2f 100644 --- a/net/ax25/ax25_ds_subr.c +++ b/net/ax25/ax25_ds_subr.c | |||
@@ -41,7 +41,7 @@ void ax25_ds_enquiry_response(ax25_cb *ax25) | |||
41 | ax25_cb *ax25o; | 41 | ax25_cb *ax25o; |
42 | struct hlist_node *node; | 42 | struct hlist_node *node; |
43 | 43 | ||
44 | /* Please note that neither DK4EG´s nor DG2FEF´s | 44 | /* Please note that neither DK4EG's nor DG2FEF's |
45 | * DAMA spec mention the following behaviour as seen | 45 | * DAMA spec mention the following behaviour as seen |
46 | * with TheFirmware: | 46 | * with TheFirmware: |
47 | * | 47 | * |
diff --git a/net/bluetooth/bnep/core.c b/net/bluetooth/bnep/core.c index 1f78c3e336d8..347e935faaf0 100644 --- a/net/bluetooth/bnep/core.c +++ b/net/bluetooth/bnep/core.c | |||
@@ -2,7 +2,7 @@ | |||
2 | BNEP implementation for Linux Bluetooth stack (BlueZ). | 2 | BNEP implementation for Linux Bluetooth stack (BlueZ). |
3 | Copyright (C) 2001-2002 Inventel Systemes | 3 | Copyright (C) 2001-2002 Inventel Systemes |
4 | Written 2001-2002 by | 4 | Written 2001-2002 by |
5 | Clément Moreau <clement.moreau@inventel.fr> | 5 | Clément Moreau <clement.moreau@inventel.fr> |
6 | David Libault <david.libault@inventel.fr> | 6 | David Libault <david.libault@inventel.fr> |
7 | 7 | ||
8 | Copyright (C) 2002 Maxim Krasnyansky <maxk@qualcomm.com> | 8 | Copyright (C) 2002 Maxim Krasnyansky <maxk@qualcomm.com> |
diff --git a/net/bluetooth/bnep/netdev.c b/net/bluetooth/bnep/netdev.c index 9092816f58de..95e3837e4312 100644 --- a/net/bluetooth/bnep/netdev.c +++ b/net/bluetooth/bnep/netdev.c | |||
@@ -2,7 +2,7 @@ | |||
2 | BNEP implementation for Linux Bluetooth stack (BlueZ). | 2 | BNEP implementation for Linux Bluetooth stack (BlueZ). |
3 | Copyright (C) 2001-2002 Inventel Systemes | 3 | Copyright (C) 2001-2002 Inventel Systemes |
4 | Written 2001-2002 by | 4 | Written 2001-2002 by |
5 | Clément Moreau <clement.moreau@inventel.fr> | 5 | Clément Moreau <clement.moreau@inventel.fr> |
6 | David Libault <david.libault@inventel.fr> | 6 | David Libault <david.libault@inventel.fr> |
7 | 7 | ||
8 | Copyright (C) 2002 Maxim Krasnyansky <maxk@qualcomm.com> | 8 | Copyright (C) 2002 Maxim Krasnyansky <maxk@qualcomm.com> |
diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c index 5fdfc9a67d39..9483320f6dad 100644 --- a/net/bluetooth/hci_conn.c +++ b/net/bluetooth/hci_conn.c | |||
@@ -78,11 +78,11 @@ void hci_acl_connect(struct hci_conn *conn) | |||
78 | 78 | ||
79 | cp.pkt_type = cpu_to_le16(hdev->pkt_type & ACL_PTYPE_MASK); | 79 | cp.pkt_type = cpu_to_le16(hdev->pkt_type & ACL_PTYPE_MASK); |
80 | if (lmp_rswitch_capable(hdev) && !(hdev->link_mode & HCI_LM_MASTER)) | 80 | if (lmp_rswitch_capable(hdev) && !(hdev->link_mode & HCI_LM_MASTER)) |
81 | cp.role_switch = 0x01; | 81 | cp.role_switch = 0x01; |
82 | else | 82 | else |
83 | cp.role_switch = 0x00; | 83 | cp.role_switch = 0x00; |
84 | 84 | ||
85 | hci_send_cmd(hdev, OGF_LINK_CTL, OCF_CREATE_CONN, sizeof(cp), &cp); | 85 | hci_send_cmd(hdev, HCI_OP_CREATE_CONN, sizeof(cp), &cp); |
86 | } | 86 | } |
87 | 87 | ||
88 | static void hci_acl_connect_cancel(struct hci_conn *conn) | 88 | static void hci_acl_connect_cancel(struct hci_conn *conn) |
@@ -95,8 +95,7 @@ static void hci_acl_connect_cancel(struct hci_conn *conn) | |||
95 | return; | 95 | return; |
96 | 96 | ||
97 | bacpy(&cp.bdaddr, &conn->dst); | 97 | bacpy(&cp.bdaddr, &conn->dst); |
98 | hci_send_cmd(conn->hdev, OGF_LINK_CTL, | 98 | hci_send_cmd(conn->hdev, HCI_OP_CREATE_CONN_CANCEL, sizeof(cp), &cp); |
99 | OCF_CREATE_CONN_CANCEL, sizeof(cp), &cp); | ||
100 | } | 99 | } |
101 | 100 | ||
102 | void hci_acl_disconn(struct hci_conn *conn, __u8 reason) | 101 | void hci_acl_disconn(struct hci_conn *conn, __u8 reason) |
@@ -109,8 +108,7 @@ void hci_acl_disconn(struct hci_conn *conn, __u8 reason) | |||
109 | 108 | ||
110 | cp.handle = cpu_to_le16(conn->handle); | 109 | cp.handle = cpu_to_le16(conn->handle); |
111 | cp.reason = reason; | 110 | cp.reason = reason; |
112 | hci_send_cmd(conn->hdev, OGF_LINK_CTL, | 111 | hci_send_cmd(conn->hdev, HCI_OP_DISCONNECT, sizeof(cp), &cp); |
113 | OCF_DISCONNECT, sizeof(cp), &cp); | ||
114 | } | 112 | } |
115 | 113 | ||
116 | void hci_add_sco(struct hci_conn *conn, __u16 handle) | 114 | void hci_add_sco(struct hci_conn *conn, __u16 handle) |
@@ -126,7 +124,29 @@ void hci_add_sco(struct hci_conn *conn, __u16 handle) | |||
126 | cp.handle = cpu_to_le16(handle); | 124 | cp.handle = cpu_to_le16(handle); |
127 | cp.pkt_type = cpu_to_le16(hdev->pkt_type & SCO_PTYPE_MASK); | 125 | cp.pkt_type = cpu_to_le16(hdev->pkt_type & SCO_PTYPE_MASK); |
128 | 126 | ||
129 | hci_send_cmd(hdev, OGF_LINK_CTL, OCF_ADD_SCO, sizeof(cp), &cp); | 127 | hci_send_cmd(hdev, HCI_OP_ADD_SCO, sizeof(cp), &cp); |
128 | } | ||
129 | |||
130 | void hci_setup_sync(struct hci_conn *conn, __u16 handle) | ||
131 | { | ||
132 | struct hci_dev *hdev = conn->hdev; | ||
133 | struct hci_cp_setup_sync_conn cp; | ||
134 | |||
135 | BT_DBG("%p", conn); | ||
136 | |||
137 | conn->state = BT_CONNECT; | ||
138 | conn->out = 1; | ||
139 | |||
140 | cp.handle = cpu_to_le16(handle); | ||
141 | cp.pkt_type = cpu_to_le16(hdev->esco_type); | ||
142 | |||
143 | cp.tx_bandwidth = cpu_to_le32(0x00001f40); | ||
144 | cp.rx_bandwidth = cpu_to_le32(0x00001f40); | ||
145 | cp.max_latency = cpu_to_le16(0xffff); | ||
146 | cp.voice_setting = cpu_to_le16(hdev->voice_setting); | ||
147 | cp.retrans_effort = 0xff; | ||
148 | |||
149 | hci_send_cmd(hdev, HCI_OP_SETUP_SYNC_CONN, sizeof(cp), &cp); | ||
130 | } | 150 | } |
131 | 151 | ||
132 | static void hci_conn_timeout(unsigned long arg) | 152 | static void hci_conn_timeout(unsigned long arg) |
@@ -143,7 +163,10 @@ static void hci_conn_timeout(unsigned long arg) | |||
143 | 163 | ||
144 | switch (conn->state) { | 164 | switch (conn->state) { |
145 | case BT_CONNECT: | 165 | case BT_CONNECT: |
146 | hci_acl_connect_cancel(conn); | 166 | if (conn->type == ACL_LINK) |
167 | hci_acl_connect_cancel(conn); | ||
168 | else | ||
169 | hci_acl_disconn(conn, 0x13); | ||
147 | break; | 170 | break; |
148 | case BT_CONNECTED: | 171 | case BT_CONNECTED: |
149 | hci_acl_disconn(conn, 0x13); | 172 | hci_acl_disconn(conn, 0x13); |
@@ -330,8 +353,12 @@ struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst) | |||
330 | hci_conn_hold(sco); | 353 | hci_conn_hold(sco); |
331 | 354 | ||
332 | if (acl->state == BT_CONNECTED && | 355 | if (acl->state == BT_CONNECTED && |
333 | (sco->state == BT_OPEN || sco->state == BT_CLOSED)) | 356 | (sco->state == BT_OPEN || sco->state == BT_CLOSED)) { |
334 | hci_add_sco(sco, acl->handle); | 357 | if (lmp_esco_capable(hdev)) |
358 | hci_setup_sync(sco, acl->handle); | ||
359 | else | ||
360 | hci_add_sco(sco, acl->handle); | ||
361 | } | ||
335 | 362 | ||
336 | return sco; | 363 | return sco; |
337 | } | 364 | } |
@@ -348,7 +375,7 @@ int hci_conn_auth(struct hci_conn *conn) | |||
348 | if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->pend)) { | 375 | if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->pend)) { |
349 | struct hci_cp_auth_requested cp; | 376 | struct hci_cp_auth_requested cp; |
350 | cp.handle = cpu_to_le16(conn->handle); | 377 | cp.handle = cpu_to_le16(conn->handle); |
351 | hci_send_cmd(conn->hdev, OGF_LINK_CTL, OCF_AUTH_REQUESTED, sizeof(cp), &cp); | 378 | hci_send_cmd(conn->hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp); |
352 | } | 379 | } |
353 | return 0; | 380 | return 0; |
354 | } | 381 | } |
@@ -369,7 +396,7 @@ int hci_conn_encrypt(struct hci_conn *conn) | |||
369 | struct hci_cp_set_conn_encrypt cp; | 396 | struct hci_cp_set_conn_encrypt cp; |
370 | cp.handle = cpu_to_le16(conn->handle); | 397 | cp.handle = cpu_to_le16(conn->handle); |
371 | cp.encrypt = 1; | 398 | cp.encrypt = 1; |
372 | hci_send_cmd(conn->hdev, OGF_LINK_CTL, OCF_SET_CONN_ENCRYPT, sizeof(cp), &cp); | 399 | hci_send_cmd(conn->hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp), &cp); |
373 | } | 400 | } |
374 | return 0; | 401 | return 0; |
375 | } | 402 | } |
@@ -383,7 +410,7 @@ int hci_conn_change_link_key(struct hci_conn *conn) | |||
383 | if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->pend)) { | 410 | if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->pend)) { |
384 | struct hci_cp_change_conn_link_key cp; | 411 | struct hci_cp_change_conn_link_key cp; |
385 | cp.handle = cpu_to_le16(conn->handle); | 412 | cp.handle = cpu_to_le16(conn->handle); |
386 | hci_send_cmd(conn->hdev, OGF_LINK_CTL, OCF_CHANGE_CONN_LINK_KEY, sizeof(cp), &cp); | 413 | hci_send_cmd(conn->hdev, HCI_OP_CHANGE_CONN_LINK_KEY, sizeof(cp), &cp); |
387 | } | 414 | } |
388 | return 0; | 415 | return 0; |
389 | } | 416 | } |
@@ -401,7 +428,7 @@ int hci_conn_switch_role(struct hci_conn *conn, uint8_t role) | |||
401 | struct hci_cp_switch_role cp; | 428 | struct hci_cp_switch_role cp; |
402 | bacpy(&cp.bdaddr, &conn->dst); | 429 | bacpy(&cp.bdaddr, &conn->dst); |
403 | cp.role = role; | 430 | cp.role = role; |
404 | hci_send_cmd(conn->hdev, OGF_LINK_POLICY, OCF_SWITCH_ROLE, sizeof(cp), &cp); | 431 | hci_send_cmd(conn->hdev, HCI_OP_SWITCH_ROLE, sizeof(cp), &cp); |
405 | } | 432 | } |
406 | return 0; | 433 | return 0; |
407 | } | 434 | } |
@@ -423,8 +450,7 @@ void hci_conn_enter_active_mode(struct hci_conn *conn) | |||
423 | if (!test_and_set_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->pend)) { | 450 | if (!test_and_set_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->pend)) { |
424 | struct hci_cp_exit_sniff_mode cp; | 451 | struct hci_cp_exit_sniff_mode cp; |
425 | cp.handle = cpu_to_le16(conn->handle); | 452 | cp.handle = cpu_to_le16(conn->handle); |
426 | hci_send_cmd(hdev, OGF_LINK_POLICY, | 453 | hci_send_cmd(hdev, HCI_OP_EXIT_SNIFF_MODE, sizeof(cp), &cp); |
427 | OCF_EXIT_SNIFF_MODE, sizeof(cp), &cp); | ||
428 | } | 454 | } |
429 | 455 | ||
430 | timer: | 456 | timer: |
@@ -455,8 +481,7 @@ void hci_conn_enter_sniff_mode(struct hci_conn *conn) | |||
455 | cp.max_latency = cpu_to_le16(0); | 481 | cp.max_latency = cpu_to_le16(0); |
456 | cp.min_remote_timeout = cpu_to_le16(0); | 482 | cp.min_remote_timeout = cpu_to_le16(0); |
457 | cp.min_local_timeout = cpu_to_le16(0); | 483 | cp.min_local_timeout = cpu_to_le16(0); |
458 | hci_send_cmd(hdev, OGF_LINK_POLICY, | 484 | hci_send_cmd(hdev, HCI_OP_SNIFF_SUBRATE, sizeof(cp), &cp); |
459 | OCF_SNIFF_SUBRATE, sizeof(cp), &cp); | ||
460 | } | 485 | } |
461 | 486 | ||
462 | if (!test_and_set_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->pend)) { | 487 | if (!test_and_set_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->pend)) { |
@@ -466,8 +491,7 @@ void hci_conn_enter_sniff_mode(struct hci_conn *conn) | |||
466 | cp.min_interval = cpu_to_le16(hdev->sniff_min_interval); | 491 | cp.min_interval = cpu_to_le16(hdev->sniff_min_interval); |
467 | cp.attempt = cpu_to_le16(4); | 492 | cp.attempt = cpu_to_le16(4); |
468 | cp.timeout = cpu_to_le16(1); | 493 | cp.timeout = cpu_to_le16(1); |
469 | hci_send_cmd(hdev, OGF_LINK_POLICY, | 494 | hci_send_cmd(hdev, HCI_OP_SNIFF_MODE, sizeof(cp), &cp); |
470 | OCF_SNIFF_MODE, sizeof(cp), &cp); | ||
471 | } | 495 | } |
472 | } | 496 | } |
473 | 497 | ||
@@ -493,6 +517,22 @@ void hci_conn_hash_flush(struct hci_dev *hdev) | |||
493 | } | 517 | } |
494 | } | 518 | } |
495 | 519 | ||
520 | /* Check pending connect attempts */ | ||
521 | void hci_conn_check_pending(struct hci_dev *hdev) | ||
522 | { | ||
523 | struct hci_conn *conn; | ||
524 | |||
525 | BT_DBG("hdev %s", hdev->name); | ||
526 | |||
527 | hci_dev_lock(hdev); | ||
528 | |||
529 | conn = hci_conn_hash_lookup_state(hdev, ACL_LINK, BT_CONNECT2); | ||
530 | if (conn) | ||
531 | hci_acl_connect(conn); | ||
532 | |||
533 | hci_dev_unlock(hdev); | ||
534 | } | ||
535 | |||
496 | int hci_get_conn_list(void __user *arg) | 536 | int hci_get_conn_list(void __user *arg) |
497 | { | 537 | { |
498 | struct hci_conn_list_req req, *cl; | 538 | struct hci_conn_list_req req, *cl; |
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index 18e3afc964df..372b0d3b75a8 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c | |||
@@ -176,7 +176,7 @@ static void hci_reset_req(struct hci_dev *hdev, unsigned long opt) | |||
176 | BT_DBG("%s %ld", hdev->name, opt); | 176 | BT_DBG("%s %ld", hdev->name, opt); |
177 | 177 | ||
178 | /* Reset device */ | 178 | /* Reset device */ |
179 | hci_send_cmd(hdev, OGF_HOST_CTL, OCF_RESET, 0, NULL); | 179 | hci_send_cmd(hdev, HCI_OP_RESET, 0, NULL); |
180 | } | 180 | } |
181 | 181 | ||
182 | static void hci_init_req(struct hci_dev *hdev, unsigned long opt) | 182 | static void hci_init_req(struct hci_dev *hdev, unsigned long opt) |
@@ -202,16 +202,16 @@ static void hci_init_req(struct hci_dev *hdev, unsigned long opt) | |||
202 | 202 | ||
203 | /* Reset */ | 203 | /* Reset */ |
204 | if (test_bit(HCI_QUIRK_RESET_ON_INIT, &hdev->quirks)) | 204 | if (test_bit(HCI_QUIRK_RESET_ON_INIT, &hdev->quirks)) |
205 | hci_send_cmd(hdev, OGF_HOST_CTL, OCF_RESET, 0, NULL); | 205 | hci_send_cmd(hdev, HCI_OP_RESET, 0, NULL); |
206 | 206 | ||
207 | /* Read Local Supported Features */ | 207 | /* Read Local Supported Features */ |
208 | hci_send_cmd(hdev, OGF_INFO_PARAM, OCF_READ_LOCAL_FEATURES, 0, NULL); | 208 | hci_send_cmd(hdev, HCI_OP_READ_LOCAL_FEATURES, 0, NULL); |
209 | 209 | ||
210 | /* Read Local Version */ | 210 | /* Read Local Version */ |
211 | hci_send_cmd(hdev, OGF_INFO_PARAM, OCF_READ_LOCAL_VERSION, 0, NULL); | 211 | hci_send_cmd(hdev, HCI_OP_READ_LOCAL_VERSION, 0, NULL); |
212 | 212 | ||
213 | /* Read Buffer Size (ACL mtu, max pkt, etc.) */ | 213 | /* Read Buffer Size (ACL mtu, max pkt, etc.) */ |
214 | hci_send_cmd(hdev, OGF_INFO_PARAM, OCF_READ_BUFFER_SIZE, 0, NULL); | 214 | hci_send_cmd(hdev, HCI_OP_READ_BUFFER_SIZE, 0, NULL); |
215 | 215 | ||
216 | #if 0 | 216 | #if 0 |
217 | /* Host buffer size */ | 217 | /* Host buffer size */ |
@@ -221,29 +221,35 @@ static void hci_init_req(struct hci_dev *hdev, unsigned long opt) | |||
221 | cp.sco_mtu = HCI_MAX_SCO_SIZE; | 221 | cp.sco_mtu = HCI_MAX_SCO_SIZE; |
222 | cp.acl_max_pkt = cpu_to_le16(0xffff); | 222 | cp.acl_max_pkt = cpu_to_le16(0xffff); |
223 | cp.sco_max_pkt = cpu_to_le16(0xffff); | 223 | cp.sco_max_pkt = cpu_to_le16(0xffff); |
224 | hci_send_cmd(hdev, OGF_HOST_CTL, OCF_HOST_BUFFER_SIZE, sizeof(cp), &cp); | 224 | hci_send_cmd(hdev, HCI_OP_HOST_BUFFER_SIZE, sizeof(cp), &cp); |
225 | } | 225 | } |
226 | #endif | 226 | #endif |
227 | 227 | ||
228 | /* Read BD Address */ | 228 | /* Read BD Address */ |
229 | hci_send_cmd(hdev, OGF_INFO_PARAM, OCF_READ_BD_ADDR, 0, NULL); | 229 | hci_send_cmd(hdev, HCI_OP_READ_BD_ADDR, 0, NULL); |
230 | |||
231 | /* Read Class of Device */ | ||
232 | hci_send_cmd(hdev, HCI_OP_READ_CLASS_OF_DEV, 0, NULL); | ||
233 | |||
234 | /* Read Local Name */ | ||
235 | hci_send_cmd(hdev, HCI_OP_READ_LOCAL_NAME, 0, NULL); | ||
230 | 236 | ||
231 | /* Read Voice Setting */ | 237 | /* Read Voice Setting */ |
232 | hci_send_cmd(hdev, OGF_HOST_CTL, OCF_READ_VOICE_SETTING, 0, NULL); | 238 | hci_send_cmd(hdev, HCI_OP_READ_VOICE_SETTING, 0, NULL); |
233 | 239 | ||
234 | /* Optional initialization */ | 240 | /* Optional initialization */ |
235 | 241 | ||
236 | /* Clear Event Filters */ | 242 | /* Clear Event Filters */ |
237 | flt_type = HCI_FLT_CLEAR_ALL; | 243 | flt_type = HCI_FLT_CLEAR_ALL; |
238 | hci_send_cmd(hdev, OGF_HOST_CTL, OCF_SET_EVENT_FLT, 1, &flt_type); | 244 | hci_send_cmd(hdev, HCI_OP_SET_EVENT_FLT, 1, &flt_type); |
239 | 245 | ||
240 | /* Page timeout ~20 secs */ | 246 | /* Page timeout ~20 secs */ |
241 | param = cpu_to_le16(0x8000); | 247 | param = cpu_to_le16(0x8000); |
242 | hci_send_cmd(hdev, OGF_HOST_CTL, OCF_WRITE_PG_TIMEOUT, 2, ¶m); | 248 | hci_send_cmd(hdev, HCI_OP_WRITE_PG_TIMEOUT, 2, ¶m); |
243 | 249 | ||
244 | /* Connection accept timeout ~20 secs */ | 250 | /* Connection accept timeout ~20 secs */ |
245 | param = cpu_to_le16(0x7d00); | 251 | param = cpu_to_le16(0x7d00); |
246 | hci_send_cmd(hdev, OGF_HOST_CTL, OCF_WRITE_CA_TIMEOUT, 2, ¶m); | 252 | hci_send_cmd(hdev, HCI_OP_WRITE_CA_TIMEOUT, 2, ¶m); |
247 | } | 253 | } |
248 | 254 | ||
249 | static void hci_scan_req(struct hci_dev *hdev, unsigned long opt) | 255 | static void hci_scan_req(struct hci_dev *hdev, unsigned long opt) |
@@ -253,7 +259,7 @@ static void hci_scan_req(struct hci_dev *hdev, unsigned long opt) | |||
253 | BT_DBG("%s %x", hdev->name, scan); | 259 | BT_DBG("%s %x", hdev->name, scan); |
254 | 260 | ||
255 | /* Inquiry and Page scans */ | 261 | /* Inquiry and Page scans */ |
256 | hci_send_cmd(hdev, OGF_HOST_CTL, OCF_WRITE_SCAN_ENABLE, 1, &scan); | 262 | hci_send_cmd(hdev, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan); |
257 | } | 263 | } |
258 | 264 | ||
259 | static void hci_auth_req(struct hci_dev *hdev, unsigned long opt) | 265 | static void hci_auth_req(struct hci_dev *hdev, unsigned long opt) |
@@ -263,7 +269,7 @@ static void hci_auth_req(struct hci_dev *hdev, unsigned long opt) | |||
263 | BT_DBG("%s %x", hdev->name, auth); | 269 | BT_DBG("%s %x", hdev->name, auth); |
264 | 270 | ||
265 | /* Authentication */ | 271 | /* Authentication */ |
266 | hci_send_cmd(hdev, OGF_HOST_CTL, OCF_WRITE_AUTH_ENABLE, 1, &auth); | 272 | hci_send_cmd(hdev, HCI_OP_WRITE_AUTH_ENABLE, 1, &auth); |
267 | } | 273 | } |
268 | 274 | ||
269 | static void hci_encrypt_req(struct hci_dev *hdev, unsigned long opt) | 275 | static void hci_encrypt_req(struct hci_dev *hdev, unsigned long opt) |
@@ -273,7 +279,7 @@ static void hci_encrypt_req(struct hci_dev *hdev, unsigned long opt) | |||
273 | BT_DBG("%s %x", hdev->name, encrypt); | 279 | BT_DBG("%s %x", hdev->name, encrypt); |
274 | 280 | ||
275 | /* Authentication */ | 281 | /* Authentication */ |
276 | hci_send_cmd(hdev, OGF_HOST_CTL, OCF_WRITE_ENCRYPT_MODE, 1, &encrypt); | 282 | hci_send_cmd(hdev, HCI_OP_WRITE_ENCRYPT_MODE, 1, &encrypt); |
277 | } | 283 | } |
278 | 284 | ||
279 | /* Get HCI device by index. | 285 | /* Get HCI device by index. |
@@ -384,7 +390,7 @@ static void hci_inq_req(struct hci_dev *hdev, unsigned long opt) | |||
384 | memcpy(&cp.lap, &ir->lap, 3); | 390 | memcpy(&cp.lap, &ir->lap, 3); |
385 | cp.length = ir->length; | 391 | cp.length = ir->length; |
386 | cp.num_rsp = ir->num_rsp; | 392 | cp.num_rsp = ir->num_rsp; |
387 | hci_send_cmd(hdev, OGF_LINK_CTL, OCF_INQUIRY, sizeof(cp), &cp); | 393 | hci_send_cmd(hdev, HCI_OP_INQUIRY, sizeof(cp), &cp); |
388 | } | 394 | } |
389 | 395 | ||
390 | int hci_inquiry(void __user *arg) | 396 | int hci_inquiry(void __user *arg) |
@@ -1111,13 +1117,13 @@ static int hci_send_frame(struct sk_buff *skb) | |||
1111 | } | 1117 | } |
1112 | 1118 | ||
1113 | /* Send HCI command */ | 1119 | /* Send HCI command */ |
1114 | int hci_send_cmd(struct hci_dev *hdev, __u16 ogf, __u16 ocf, __u32 plen, void *param) | 1120 | int hci_send_cmd(struct hci_dev *hdev, __u16 opcode, __u32 plen, void *param) |
1115 | { | 1121 | { |
1116 | int len = HCI_COMMAND_HDR_SIZE + plen; | 1122 | int len = HCI_COMMAND_HDR_SIZE + plen; |
1117 | struct hci_command_hdr *hdr; | 1123 | struct hci_command_hdr *hdr; |
1118 | struct sk_buff *skb; | 1124 | struct sk_buff *skb; |
1119 | 1125 | ||
1120 | BT_DBG("%s ogf 0x%x ocf 0x%x plen %d", hdev->name, ogf, ocf, plen); | 1126 | BT_DBG("%s opcode 0x%x plen %d", hdev->name, opcode, plen); |
1121 | 1127 | ||
1122 | skb = bt_skb_alloc(len, GFP_ATOMIC); | 1128 | skb = bt_skb_alloc(len, GFP_ATOMIC); |
1123 | if (!skb) { | 1129 | if (!skb) { |
@@ -1126,7 +1132,7 @@ int hci_send_cmd(struct hci_dev *hdev, __u16 ogf, __u16 ocf, __u32 plen, void *p | |||
1126 | } | 1132 | } |
1127 | 1133 | ||
1128 | hdr = (struct hci_command_hdr *) skb_put(skb, HCI_COMMAND_HDR_SIZE); | 1134 | hdr = (struct hci_command_hdr *) skb_put(skb, HCI_COMMAND_HDR_SIZE); |
1129 | hdr->opcode = cpu_to_le16(hci_opcode_pack(ogf, ocf)); | 1135 | hdr->opcode = cpu_to_le16(opcode); |
1130 | hdr->plen = plen; | 1136 | hdr->plen = plen; |
1131 | 1137 | ||
1132 | if (plen) | 1138 | if (plen) |
@@ -1143,7 +1149,7 @@ int hci_send_cmd(struct hci_dev *hdev, __u16 ogf, __u16 ocf, __u32 plen, void *p | |||
1143 | } | 1149 | } |
1144 | 1150 | ||
1145 | /* Get data from the previously sent command */ | 1151 | /* Get data from the previously sent command */ |
1146 | void *hci_sent_cmd_data(struct hci_dev *hdev, __u16 ogf, __u16 ocf) | 1152 | void *hci_sent_cmd_data(struct hci_dev *hdev, __u16 opcode) |
1147 | { | 1153 | { |
1148 | struct hci_command_hdr *hdr; | 1154 | struct hci_command_hdr *hdr; |
1149 | 1155 | ||
@@ -1152,10 +1158,10 @@ void *hci_sent_cmd_data(struct hci_dev *hdev, __u16 ogf, __u16 ocf) | |||
1152 | 1158 | ||
1153 | hdr = (void *) hdev->sent_cmd->data; | 1159 | hdr = (void *) hdev->sent_cmd->data; |
1154 | 1160 | ||
1155 | if (hdr->opcode != cpu_to_le16(hci_opcode_pack(ogf, ocf))) | 1161 | if (hdr->opcode != cpu_to_le16(opcode)) |
1156 | return NULL; | 1162 | return NULL; |
1157 | 1163 | ||
1158 | BT_DBG("%s ogf 0x%x ocf 0x%x", hdev->name, ogf, ocf); | 1164 | BT_DBG("%s opcode 0x%x", hdev->name, opcode); |
1159 | 1165 | ||
1160 | return hdev->sent_cmd->data + HCI_COMMAND_HDR_SIZE; | 1166 | return hdev->sent_cmd->data + HCI_COMMAND_HDR_SIZE; |
1161 | } | 1167 | } |
@@ -1355,6 +1361,26 @@ static inline void hci_sched_sco(struct hci_dev *hdev) | |||
1355 | } | 1361 | } |
1356 | } | 1362 | } |
1357 | 1363 | ||
1364 | static inline void hci_sched_esco(struct hci_dev *hdev) | ||
1365 | { | ||
1366 | struct hci_conn *conn; | ||
1367 | struct sk_buff *skb; | ||
1368 | int quote; | ||
1369 | |||
1370 | BT_DBG("%s", hdev->name); | ||
1371 | |||
1372 | while (hdev->sco_cnt && (conn = hci_low_sent(hdev, ESCO_LINK, "e))) { | ||
1373 | while (quote-- && (skb = skb_dequeue(&conn->data_q))) { | ||
1374 | BT_DBG("skb %p len %d", skb, skb->len); | ||
1375 | hci_send_frame(skb); | ||
1376 | |||
1377 | conn->sent++; | ||
1378 | if (conn->sent == ~0) | ||
1379 | conn->sent = 0; | ||
1380 | } | ||
1381 | } | ||
1382 | } | ||
1383 | |||
1358 | static void hci_tx_task(unsigned long arg) | 1384 | static void hci_tx_task(unsigned long arg) |
1359 | { | 1385 | { |
1360 | struct hci_dev *hdev = (struct hci_dev *) arg; | 1386 | struct hci_dev *hdev = (struct hci_dev *) arg; |
@@ -1370,6 +1396,8 @@ static void hci_tx_task(unsigned long arg) | |||
1370 | 1396 | ||
1371 | hci_sched_sco(hdev); | 1397 | hci_sched_sco(hdev); |
1372 | 1398 | ||
1399 | hci_sched_esco(hdev); | ||
1400 | |||
1373 | /* Send next queued raw (unknown type) packet */ | 1401 | /* Send next queued raw (unknown type) packet */ |
1374 | while ((skb = skb_dequeue(&hdev->raw_q))) | 1402 | while ((skb = skb_dequeue(&hdev->raw_q))) |
1375 | hci_send_frame(skb); | 1403 | hci_send_frame(skb); |
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 4baea1e38652..46df2e403df8 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c | |||
@@ -52,234 +52,273 @@ | |||
52 | 52 | ||
53 | /* Handle HCI Event packets */ | 53 | /* Handle HCI Event packets */ |
54 | 54 | ||
55 | /* Command Complete OGF LINK_CTL */ | 55 | static void hci_cc_inquiry_cancel(struct hci_dev *hdev, struct sk_buff *skb) |
56 | static void hci_cc_link_ctl(struct hci_dev *hdev, __u16 ocf, struct sk_buff *skb) | ||
57 | { | 56 | { |
58 | __u8 status; | 57 | __u8 status = *((__u8 *) skb->data); |
59 | struct hci_conn *pend; | ||
60 | 58 | ||
61 | BT_DBG("%s ocf 0x%x", hdev->name, ocf); | 59 | BT_DBG("%s status 0x%x", hdev->name, status); |
62 | 60 | ||
63 | switch (ocf) { | 61 | if (status) |
64 | case OCF_INQUIRY_CANCEL: | 62 | return; |
65 | case OCF_EXIT_PERIODIC_INQ: | ||
66 | status = *((__u8 *) skb->data); | ||
67 | 63 | ||
68 | if (status) { | 64 | clear_bit(HCI_INQUIRY, &hdev->flags); |
69 | BT_DBG("%s Inquiry cancel error: status 0x%x", hdev->name, status); | ||
70 | } else { | ||
71 | clear_bit(HCI_INQUIRY, &hdev->flags); | ||
72 | hci_req_complete(hdev, status); | ||
73 | } | ||
74 | 65 | ||
75 | hci_dev_lock(hdev); | 66 | hci_req_complete(hdev, status); |
76 | 67 | ||
77 | pend = hci_conn_hash_lookup_state(hdev, ACL_LINK, BT_CONNECT2); | 68 | hci_conn_check_pending(hdev); |
78 | if (pend) | 69 | } |
79 | hci_acl_connect(pend); | ||
80 | 70 | ||
81 | hci_dev_unlock(hdev); | 71 | static void hci_cc_exit_periodic_inq(struct hci_dev *hdev, struct sk_buff *skb) |
72 | { | ||
73 | __u8 status = *((__u8 *) skb->data); | ||
82 | 74 | ||
83 | break; | 75 | BT_DBG("%s status 0x%x", hdev->name, status); |
84 | 76 | ||
85 | default: | 77 | if (status) |
86 | BT_DBG("%s Command complete: ogf LINK_CTL ocf %x", hdev->name, ocf); | 78 | return; |
87 | break; | 79 | |
80 | clear_bit(HCI_INQUIRY, &hdev->flags); | ||
81 | |||
82 | hci_conn_check_pending(hdev); | ||
83 | } | ||
84 | |||
85 | static void hci_cc_remote_name_req_cancel(struct hci_dev *hdev, struct sk_buff *skb) | ||
86 | { | ||
87 | BT_DBG("%s", hdev->name); | ||
88 | } | ||
89 | |||
90 | static void hci_cc_role_discovery(struct hci_dev *hdev, struct sk_buff *skb) | ||
91 | { | ||
92 | struct hci_rp_role_discovery *rp = (void *) skb->data; | ||
93 | struct hci_conn *conn; | ||
94 | |||
95 | BT_DBG("%s status 0x%x", hdev->name, rp->status); | ||
96 | |||
97 | if (rp->status) | ||
98 | return; | ||
99 | |||
100 | hci_dev_lock(hdev); | ||
101 | |||
102 | conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle)); | ||
103 | if (conn) { | ||
104 | if (rp->role) | ||
105 | conn->link_mode &= ~HCI_LM_MASTER; | ||
106 | else | ||
107 | conn->link_mode |= HCI_LM_MASTER; | ||
88 | } | 108 | } |
109 | |||
110 | hci_dev_unlock(hdev); | ||
89 | } | 111 | } |
90 | 112 | ||
91 | /* Command Complete OGF LINK_POLICY */ | 113 | static void hci_cc_write_link_policy(struct hci_dev *hdev, struct sk_buff *skb) |
92 | static void hci_cc_link_policy(struct hci_dev *hdev, __u16 ocf, struct sk_buff *skb) | ||
93 | { | 114 | { |
115 | struct hci_rp_write_link_policy *rp = (void *) skb->data; | ||
94 | struct hci_conn *conn; | 116 | struct hci_conn *conn; |
95 | struct hci_rp_role_discovery *rd; | ||
96 | struct hci_rp_write_link_policy *lp; | ||
97 | void *sent; | 117 | void *sent; |
98 | 118 | ||
99 | BT_DBG("%s ocf 0x%x", hdev->name, ocf); | 119 | BT_DBG("%s status 0x%x", hdev->name, rp->status); |
100 | 120 | ||
101 | switch (ocf) { | 121 | if (rp->status) |
102 | case OCF_ROLE_DISCOVERY: | 122 | return; |
103 | rd = (void *) skb->data; | ||
104 | 123 | ||
105 | if (rd->status) | 124 | sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LINK_POLICY); |
106 | break; | 125 | if (!sent) |
126 | return; | ||
107 | 127 | ||
108 | hci_dev_lock(hdev); | 128 | hci_dev_lock(hdev); |
109 | 129 | ||
110 | conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rd->handle)); | 130 | conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle)); |
111 | if (conn) { | 131 | if (conn) { |
112 | if (rd->role) | 132 | __le16 policy = get_unaligned((__le16 *) (sent + 2)); |
113 | conn->link_mode &= ~HCI_LM_MASTER; | 133 | conn->link_policy = __le16_to_cpu(policy); |
114 | else | 134 | } |
115 | conn->link_mode |= HCI_LM_MASTER; | ||
116 | } | ||
117 | 135 | ||
118 | hci_dev_unlock(hdev); | 136 | hci_dev_unlock(hdev); |
119 | break; | 137 | } |
120 | 138 | ||
121 | case OCF_WRITE_LINK_POLICY: | 139 | static void hci_cc_reset(struct hci_dev *hdev, struct sk_buff *skb) |
122 | sent = hci_sent_cmd_data(hdev, OGF_LINK_POLICY, OCF_WRITE_LINK_POLICY); | 140 | { |
123 | if (!sent) | 141 | __u8 status = *((__u8 *) skb->data); |
124 | break; | ||
125 | 142 | ||
126 | lp = (struct hci_rp_write_link_policy *) skb->data; | 143 | BT_DBG("%s status 0x%x", hdev->name, status); |
127 | 144 | ||
128 | if (lp->status) | 145 | hci_req_complete(hdev, status); |
129 | break; | 146 | } |
130 | 147 | ||
131 | hci_dev_lock(hdev); | 148 | static void hci_cc_write_local_name(struct hci_dev *hdev, struct sk_buff *skb) |
149 | { | ||
150 | __u8 status = *((__u8 *) skb->data); | ||
151 | void *sent; | ||
132 | 152 | ||
133 | conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(lp->handle)); | 153 | BT_DBG("%s status 0x%x", hdev->name, status); |
134 | if (conn) { | ||
135 | __le16 policy = get_unaligned((__le16 *) (sent + 2)); | ||
136 | conn->link_policy = __le16_to_cpu(policy); | ||
137 | } | ||
138 | 154 | ||
139 | hci_dev_unlock(hdev); | 155 | sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LOCAL_NAME); |
140 | break; | 156 | if (!sent) |
157 | return; | ||
141 | 158 | ||
142 | default: | 159 | if (!status) |
143 | BT_DBG("%s: Command complete: ogf LINK_POLICY ocf %x", | 160 | memcpy(hdev->dev_name, sent, 248); |
144 | hdev->name, ocf); | 161 | } |
145 | break; | 162 | |
163 | static void hci_cc_read_local_name(struct hci_dev *hdev, struct sk_buff *skb) | ||
164 | { | ||
165 | struct hci_rp_read_local_name *rp = (void *) skb->data; | ||
166 | |||
167 | BT_DBG("%s status 0x%x", hdev->name, rp->status); | ||
168 | |||
169 | if (rp->status) | ||
170 | return; | ||
171 | |||
172 | memcpy(hdev->dev_name, rp->name, 248); | ||
173 | } | ||
174 | |||
175 | static void hci_cc_write_auth_enable(struct hci_dev *hdev, struct sk_buff *skb) | ||
176 | { | ||
177 | __u8 status = *((__u8 *) skb->data); | ||
178 | void *sent; | ||
179 | |||
180 | BT_DBG("%s status 0x%x", hdev->name, status); | ||
181 | |||
182 | sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_AUTH_ENABLE); | ||
183 | if (!sent) | ||
184 | return; | ||
185 | |||
186 | if (!status) { | ||
187 | __u8 param = *((__u8 *) sent); | ||
188 | |||
189 | if (param == AUTH_ENABLED) | ||
190 | set_bit(HCI_AUTH, &hdev->flags); | ||
191 | else | ||
192 | clear_bit(HCI_AUTH, &hdev->flags); | ||
146 | } | 193 | } |
194 | |||
195 | hci_req_complete(hdev, status); | ||
147 | } | 196 | } |
148 | 197 | ||
149 | /* Command Complete OGF HOST_CTL */ | 198 | static void hci_cc_write_encrypt_mode(struct hci_dev *hdev, struct sk_buff *skb) |
150 | static void hci_cc_host_ctl(struct hci_dev *hdev, __u16 ocf, struct sk_buff *skb) | ||
151 | { | 199 | { |
152 | __u8 status, param; | 200 | __u8 status = *((__u8 *) skb->data); |
153 | __u16 setting; | ||
154 | struct hci_rp_read_voice_setting *vs; | ||
155 | void *sent; | 201 | void *sent; |
156 | 202 | ||
157 | BT_DBG("%s ocf 0x%x", hdev->name, ocf); | 203 | BT_DBG("%s status 0x%x", hdev->name, status); |
158 | 204 | ||
159 | switch (ocf) { | 205 | sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_ENCRYPT_MODE); |
160 | case OCF_RESET: | 206 | if (!sent) |
161 | status = *((__u8 *) skb->data); | 207 | return; |
162 | hci_req_complete(hdev, status); | ||
163 | break; | ||
164 | 208 | ||
165 | case OCF_SET_EVENT_FLT: | 209 | if (!status) { |
166 | status = *((__u8 *) skb->data); | 210 | __u8 param = *((__u8 *) sent); |
167 | if (status) { | ||
168 | BT_DBG("%s SET_EVENT_FLT failed %d", hdev->name, status); | ||
169 | } else { | ||
170 | BT_DBG("%s SET_EVENT_FLT succeseful", hdev->name); | ||
171 | } | ||
172 | break; | ||
173 | 211 | ||
174 | case OCF_WRITE_AUTH_ENABLE: | 212 | if (param) |
175 | sent = hci_sent_cmd_data(hdev, OGF_HOST_CTL, OCF_WRITE_AUTH_ENABLE); | 213 | set_bit(HCI_ENCRYPT, &hdev->flags); |
176 | if (!sent) | 214 | else |
177 | break; | 215 | clear_bit(HCI_ENCRYPT, &hdev->flags); |
216 | } | ||
178 | 217 | ||
179 | status = *((__u8 *) skb->data); | 218 | hci_req_complete(hdev, status); |
180 | param = *((__u8 *) sent); | 219 | } |
181 | 220 | ||
182 | if (!status) { | 221 | static void hci_cc_write_scan_enable(struct hci_dev *hdev, struct sk_buff *skb) |
183 | if (param == AUTH_ENABLED) | 222 | { |
184 | set_bit(HCI_AUTH, &hdev->flags); | 223 | __u8 status = *((__u8 *) skb->data); |
185 | else | 224 | void *sent; |
186 | clear_bit(HCI_AUTH, &hdev->flags); | ||
187 | } | ||
188 | hci_req_complete(hdev, status); | ||
189 | break; | ||
190 | 225 | ||
191 | case OCF_WRITE_ENCRYPT_MODE: | 226 | BT_DBG("%s status 0x%x", hdev->name, status); |
192 | sent = hci_sent_cmd_data(hdev, OGF_HOST_CTL, OCF_WRITE_ENCRYPT_MODE); | ||
193 | if (!sent) | ||
194 | break; | ||
195 | 227 | ||
196 | status = *((__u8 *) skb->data); | 228 | sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SCAN_ENABLE); |
197 | param = *((__u8 *) sent); | 229 | if (!sent) |
230 | return; | ||
198 | 231 | ||
199 | if (!status) { | 232 | if (!status) { |
200 | if (param) | 233 | __u8 param = *((__u8 *) sent); |
201 | set_bit(HCI_ENCRYPT, &hdev->flags); | ||
202 | else | ||
203 | clear_bit(HCI_ENCRYPT, &hdev->flags); | ||
204 | } | ||
205 | hci_req_complete(hdev, status); | ||
206 | break; | ||
207 | 234 | ||
208 | case OCF_WRITE_CA_TIMEOUT: | 235 | clear_bit(HCI_PSCAN, &hdev->flags); |
209 | status = *((__u8 *) skb->data); | 236 | clear_bit(HCI_ISCAN, &hdev->flags); |
210 | if (status) { | ||
211 | BT_DBG("%s OCF_WRITE_CA_TIMEOUT failed %d", hdev->name, status); | ||
212 | } else { | ||
213 | BT_DBG("%s OCF_WRITE_CA_TIMEOUT succeseful", hdev->name); | ||
214 | } | ||
215 | break; | ||
216 | 237 | ||
217 | case OCF_WRITE_PG_TIMEOUT: | 238 | if (param & SCAN_INQUIRY) |
218 | status = *((__u8 *) skb->data); | 239 | set_bit(HCI_ISCAN, &hdev->flags); |
219 | if (status) { | ||
220 | BT_DBG("%s OCF_WRITE_PG_TIMEOUT failed %d", hdev->name, status); | ||
221 | } else { | ||
222 | BT_DBG("%s: OCF_WRITE_PG_TIMEOUT succeseful", hdev->name); | ||
223 | } | ||
224 | break; | ||
225 | 240 | ||
226 | case OCF_WRITE_SCAN_ENABLE: | 241 | if (param & SCAN_PAGE) |
227 | sent = hci_sent_cmd_data(hdev, OGF_HOST_CTL, OCF_WRITE_SCAN_ENABLE); | 242 | set_bit(HCI_PSCAN, &hdev->flags); |
228 | if (!sent) | 243 | } |
229 | break; | ||
230 | 244 | ||
231 | status = *((__u8 *) skb->data); | 245 | hci_req_complete(hdev, status); |
232 | param = *((__u8 *) sent); | 246 | } |
233 | 247 | ||
234 | BT_DBG("param 0x%x", param); | 248 | static void hci_cc_read_class_of_dev(struct hci_dev *hdev, struct sk_buff *skb) |
249 | { | ||
250 | struct hci_rp_read_class_of_dev *rp = (void *) skb->data; | ||
235 | 251 | ||
236 | if (!status) { | 252 | BT_DBG("%s status 0x%x", hdev->name, rp->status); |
237 | clear_bit(HCI_PSCAN, &hdev->flags); | ||
238 | clear_bit(HCI_ISCAN, &hdev->flags); | ||
239 | if (param & SCAN_INQUIRY) | ||
240 | set_bit(HCI_ISCAN, &hdev->flags); | ||
241 | 253 | ||
242 | if (param & SCAN_PAGE) | 254 | if (rp->status) |
243 | set_bit(HCI_PSCAN, &hdev->flags); | 255 | return; |
244 | } | ||
245 | hci_req_complete(hdev, status); | ||
246 | break; | ||
247 | 256 | ||
248 | case OCF_READ_VOICE_SETTING: | 257 | memcpy(hdev->dev_class, rp->dev_class, 3); |
249 | vs = (struct hci_rp_read_voice_setting *) skb->data; | ||
250 | 258 | ||
251 | if (vs->status) { | 259 | BT_DBG("%s class 0x%.2x%.2x%.2x", hdev->name, |
252 | BT_DBG("%s READ_VOICE_SETTING failed %d", hdev->name, vs->status); | 260 | hdev->dev_class[2], hdev->dev_class[1], hdev->dev_class[0]); |
253 | break; | 261 | } |
254 | } | ||
255 | 262 | ||
256 | setting = __le16_to_cpu(vs->voice_setting); | 263 | static void hci_cc_write_class_of_dev(struct hci_dev *hdev, struct sk_buff *skb) |
264 | { | ||
265 | __u8 status = *((__u8 *) skb->data); | ||
266 | void *sent; | ||
257 | 267 | ||
258 | if (hdev->voice_setting != setting ) { | 268 | BT_DBG("%s status 0x%x", hdev->name, status); |
259 | hdev->voice_setting = setting; | ||
260 | 269 | ||
261 | BT_DBG("%s: voice setting 0x%04x", hdev->name, setting); | 270 | sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_CLASS_OF_DEV); |
271 | if (!sent) | ||
272 | return; | ||
262 | 273 | ||
263 | if (hdev->notify) { | 274 | if (!status) |
264 | tasklet_disable(&hdev->tx_task); | 275 | memcpy(hdev->dev_class, sent, 3); |
265 | hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING); | 276 | } |
266 | tasklet_enable(&hdev->tx_task); | ||
267 | } | ||
268 | } | ||
269 | break; | ||
270 | 277 | ||
271 | case OCF_WRITE_VOICE_SETTING: | 278 | static void hci_cc_read_voice_setting(struct hci_dev *hdev, struct sk_buff *skb) |
272 | sent = hci_sent_cmd_data(hdev, OGF_HOST_CTL, OCF_WRITE_VOICE_SETTING); | 279 | { |
273 | if (!sent) | 280 | struct hci_rp_read_voice_setting *rp = (void *) skb->data; |
274 | break; | 281 | __u16 setting; |
282 | |||
283 | BT_DBG("%s status 0x%x", hdev->name, rp->status); | ||
284 | |||
285 | if (rp->status) | ||
286 | return; | ||
287 | |||
288 | setting = __le16_to_cpu(rp->voice_setting); | ||
289 | |||
290 | if (hdev->voice_setting == setting ) | ||
291 | return; | ||
292 | |||
293 | hdev->voice_setting = setting; | ||
275 | 294 | ||
276 | status = *((__u8 *) skb->data); | 295 | BT_DBG("%s voice setting 0x%04x", hdev->name, setting); |
277 | setting = __le16_to_cpu(get_unaligned((__le16 *) sent)); | ||
278 | 296 | ||
279 | if (!status && hdev->voice_setting != setting) { | 297 | if (hdev->notify) { |
298 | tasklet_disable(&hdev->tx_task); | ||
299 | hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING); | ||
300 | tasklet_enable(&hdev->tx_task); | ||
301 | } | ||
302 | } | ||
303 | |||
304 | static void hci_cc_write_voice_setting(struct hci_dev *hdev, struct sk_buff *skb) | ||
305 | { | ||
306 | __u8 status = *((__u8 *) skb->data); | ||
307 | void *sent; | ||
308 | |||
309 | BT_DBG("%s status 0x%x", hdev->name, status); | ||
310 | |||
311 | sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_VOICE_SETTING); | ||
312 | if (!sent) | ||
313 | return; | ||
314 | |||
315 | if (!status) { | ||
316 | __u16 setting = __le16_to_cpu(get_unaligned((__le16 *) sent)); | ||
317 | |||
318 | if (hdev->voice_setting != setting) { | ||
280 | hdev->voice_setting = setting; | 319 | hdev->voice_setting = setting; |
281 | 320 | ||
282 | BT_DBG("%s: voice setting 0x%04x", hdev->name, setting); | 321 | BT_DBG("%s voice setting 0x%04x", hdev->name, setting); |
283 | 322 | ||
284 | if (hdev->notify) { | 323 | if (hdev->notify) { |
285 | tasklet_disable(&hdev->tx_task); | 324 | tasklet_disable(&hdev->tx_task); |
@@ -287,143 +326,153 @@ static void hci_cc_host_ctl(struct hci_dev *hdev, __u16 ocf, struct sk_buff *skb | |||
287 | tasklet_enable(&hdev->tx_task); | 326 | tasklet_enable(&hdev->tx_task); |
288 | } | 327 | } |
289 | } | 328 | } |
290 | hci_req_complete(hdev, status); | ||
291 | break; | ||
292 | |||
293 | case OCF_HOST_BUFFER_SIZE: | ||
294 | status = *((__u8 *) skb->data); | ||
295 | if (status) { | ||
296 | BT_DBG("%s OCF_BUFFER_SIZE failed %d", hdev->name, status); | ||
297 | hci_req_complete(hdev, status); | ||
298 | } | ||
299 | break; | ||
300 | |||
301 | default: | ||
302 | BT_DBG("%s Command complete: ogf HOST_CTL ocf %x", hdev->name, ocf); | ||
303 | break; | ||
304 | } | 329 | } |
305 | } | 330 | } |
306 | 331 | ||
307 | /* Command Complete OGF INFO_PARAM */ | 332 | static void hci_cc_host_buffer_size(struct hci_dev *hdev, struct sk_buff *skb) |
308 | static void hci_cc_info_param(struct hci_dev *hdev, __u16 ocf, struct sk_buff *skb) | ||
309 | { | 333 | { |
310 | struct hci_rp_read_loc_version *lv; | 334 | __u8 status = *((__u8 *) skb->data); |
311 | struct hci_rp_read_local_features *lf; | ||
312 | struct hci_rp_read_buffer_size *bs; | ||
313 | struct hci_rp_read_bd_addr *ba; | ||
314 | 335 | ||
315 | BT_DBG("%s ocf 0x%x", hdev->name, ocf); | 336 | BT_DBG("%s status 0x%x", hdev->name, status); |
316 | 337 | ||
317 | switch (ocf) { | 338 | hci_req_complete(hdev, status); |
318 | case OCF_READ_LOCAL_VERSION: | 339 | } |
319 | lv = (struct hci_rp_read_loc_version *) skb->data; | ||
320 | 340 | ||
321 | if (lv->status) { | 341 | static void hci_cc_read_local_version(struct hci_dev *hdev, struct sk_buff *skb) |
322 | BT_DBG("%s READ_LOCAL_VERSION failed %d", hdev->name, lf->status); | 342 | { |
323 | break; | 343 | struct hci_rp_read_local_version *rp = (void *) skb->data; |
324 | } | ||
325 | 344 | ||
326 | hdev->hci_ver = lv->hci_ver; | 345 | BT_DBG("%s status 0x%x", hdev->name, rp->status); |
327 | hdev->hci_rev = btohs(lv->hci_rev); | ||
328 | hdev->manufacturer = btohs(lv->manufacturer); | ||
329 | 346 | ||
330 | BT_DBG("%s: manufacturer %d hci_ver %d hci_rev %d", hdev->name, | 347 | if (rp->status) |
331 | hdev->manufacturer, hdev->hci_ver, hdev->hci_rev); | 348 | return; |
332 | 349 | ||
333 | break; | 350 | hdev->hci_ver = rp->hci_ver; |
351 | hdev->hci_rev = btohs(rp->hci_rev); | ||
352 | hdev->manufacturer = btohs(rp->manufacturer); | ||
334 | 353 | ||
335 | case OCF_READ_LOCAL_FEATURES: | 354 | BT_DBG("%s manufacturer %d hci ver %d:%d", hdev->name, |
336 | lf = (struct hci_rp_read_local_features *) skb->data; | 355 | hdev->manufacturer, |
356 | hdev->hci_ver, hdev->hci_rev); | ||
357 | } | ||
337 | 358 | ||
338 | if (lf->status) { | 359 | static void hci_cc_read_local_commands(struct hci_dev *hdev, struct sk_buff *skb) |
339 | BT_DBG("%s READ_LOCAL_FEATURES failed %d", hdev->name, lf->status); | 360 | { |
340 | break; | 361 | struct hci_rp_read_local_commands *rp = (void *) skb->data; |
341 | } | ||
342 | 362 | ||
343 | memcpy(hdev->features, lf->features, sizeof(hdev->features)); | 363 | BT_DBG("%s status 0x%x", hdev->name, rp->status); |
344 | 364 | ||
345 | /* Adjust default settings according to features | 365 | if (rp->status) |
346 | * supported by device. */ | 366 | return; |
347 | if (hdev->features[0] & LMP_3SLOT) | ||
348 | hdev->pkt_type |= (HCI_DM3 | HCI_DH3); | ||
349 | 367 | ||
350 | if (hdev->features[0] & LMP_5SLOT) | 368 | memcpy(hdev->commands, rp->commands, sizeof(hdev->commands)); |
351 | hdev->pkt_type |= (HCI_DM5 | HCI_DH5); | 369 | } |
352 | 370 | ||
353 | if (hdev->features[1] & LMP_HV2) { | 371 | static void hci_cc_read_local_features(struct hci_dev *hdev, struct sk_buff *skb) |
354 | hdev->pkt_type |= (HCI_HV2); | 372 | { |
355 | hdev->esco_type |= (ESCO_HV2); | 373 | struct hci_rp_read_local_features *rp = (void *) skb->data; |
356 | } | ||
357 | 374 | ||
358 | if (hdev->features[1] & LMP_HV3) { | 375 | BT_DBG("%s status 0x%x", hdev->name, rp->status); |
359 | hdev->pkt_type |= (HCI_HV3); | ||
360 | hdev->esco_type |= (ESCO_HV3); | ||
361 | } | ||
362 | 376 | ||
363 | if (hdev->features[3] & LMP_ESCO) | 377 | if (rp->status) |
364 | hdev->esco_type |= (ESCO_EV3); | 378 | return; |
365 | 379 | ||
366 | if (hdev->features[4] & LMP_EV4) | 380 | memcpy(hdev->features, rp->features, 8); |
367 | hdev->esco_type |= (ESCO_EV4); | ||
368 | 381 | ||
369 | if (hdev->features[4] & LMP_EV5) | 382 | /* Adjust default settings according to features |
370 | hdev->esco_type |= (ESCO_EV5); | 383 | * supported by device. */ |
371 | 384 | ||
372 | BT_DBG("%s: features 0x%x 0x%x 0x%x", hdev->name, | 385 | if (hdev->features[0] & LMP_3SLOT) |
373 | lf->features[0], lf->features[1], lf->features[2]); | 386 | hdev->pkt_type |= (HCI_DM3 | HCI_DH3); |
374 | 387 | ||
375 | break; | 388 | if (hdev->features[0] & LMP_5SLOT) |
389 | hdev->pkt_type |= (HCI_DM5 | HCI_DH5); | ||
376 | 390 | ||
377 | case OCF_READ_BUFFER_SIZE: | 391 | if (hdev->features[1] & LMP_HV2) { |
378 | bs = (struct hci_rp_read_buffer_size *) skb->data; | 392 | hdev->pkt_type |= (HCI_HV2); |
393 | hdev->esco_type |= (ESCO_HV2); | ||
394 | } | ||
379 | 395 | ||
380 | if (bs->status) { | 396 | if (hdev->features[1] & LMP_HV3) { |
381 | BT_DBG("%s READ_BUFFER_SIZE failed %d", hdev->name, bs->status); | 397 | hdev->pkt_type |= (HCI_HV3); |
382 | hci_req_complete(hdev, bs->status); | 398 | hdev->esco_type |= (ESCO_HV3); |
383 | break; | 399 | } |
384 | } | ||
385 | 400 | ||
386 | hdev->acl_mtu = __le16_to_cpu(bs->acl_mtu); | 401 | if (hdev->features[3] & LMP_ESCO) |
387 | hdev->sco_mtu = bs->sco_mtu; | 402 | hdev->esco_type |= (ESCO_EV3); |
388 | hdev->acl_pkts = __le16_to_cpu(bs->acl_max_pkt); | ||
389 | hdev->sco_pkts = __le16_to_cpu(bs->sco_max_pkt); | ||
390 | 403 | ||
391 | if (test_bit(HCI_QUIRK_FIXUP_BUFFER_SIZE, &hdev->quirks)) { | 404 | if (hdev->features[4] & LMP_EV4) |
392 | hdev->sco_mtu = 64; | 405 | hdev->esco_type |= (ESCO_EV4); |
393 | hdev->sco_pkts = 8; | ||
394 | } | ||
395 | 406 | ||
396 | hdev->acl_cnt = hdev->acl_pkts; | 407 | if (hdev->features[4] & LMP_EV5) |
397 | hdev->sco_cnt = hdev->sco_pkts; | 408 | hdev->esco_type |= (ESCO_EV5); |
398 | 409 | ||
399 | BT_DBG("%s mtu: acl %d, sco %d max_pkt: acl %d, sco %d", hdev->name, | 410 | BT_DBG("%s features 0x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x", hdev->name, |
400 | hdev->acl_mtu, hdev->sco_mtu, hdev->acl_pkts, hdev->sco_pkts); | 411 | hdev->features[0], hdev->features[1], |
401 | break; | 412 | hdev->features[2], hdev->features[3], |
413 | hdev->features[4], hdev->features[5], | ||
414 | hdev->features[6], hdev->features[7]); | ||
415 | } | ||
402 | 416 | ||
403 | case OCF_READ_BD_ADDR: | 417 | static void hci_cc_read_buffer_size(struct hci_dev *hdev, struct sk_buff *skb) |
404 | ba = (struct hci_rp_read_bd_addr *) skb->data; | 418 | { |
419 | struct hci_rp_read_buffer_size *rp = (void *) skb->data; | ||
405 | 420 | ||
406 | if (!ba->status) { | 421 | BT_DBG("%s status 0x%x", hdev->name, rp->status); |
407 | bacpy(&hdev->bdaddr, &ba->bdaddr); | ||
408 | } else { | ||
409 | BT_DBG("%s: READ_BD_ADDR failed %d", hdev->name, ba->status); | ||
410 | } | ||
411 | 422 | ||
412 | hci_req_complete(hdev, ba->status); | 423 | if (rp->status) |
413 | break; | 424 | return; |
414 | 425 | ||
415 | default: | 426 | hdev->acl_mtu = __le16_to_cpu(rp->acl_mtu); |
416 | BT_DBG("%s Command complete: ogf INFO_PARAM ocf %x", hdev->name, ocf); | 427 | hdev->sco_mtu = rp->sco_mtu; |
417 | break; | 428 | hdev->acl_pkts = __le16_to_cpu(rp->acl_max_pkt); |
429 | hdev->sco_pkts = __le16_to_cpu(rp->sco_max_pkt); | ||
430 | |||
431 | if (test_bit(HCI_QUIRK_FIXUP_BUFFER_SIZE, &hdev->quirks)) { | ||
432 | hdev->sco_mtu = 64; | ||
433 | hdev->sco_pkts = 8; | ||
418 | } | 434 | } |
435 | |||
436 | hdev->acl_cnt = hdev->acl_pkts; | ||
437 | hdev->sco_cnt = hdev->sco_pkts; | ||
438 | |||
439 | BT_DBG("%s acl mtu %d:%d sco mtu %d:%d", hdev->name, | ||
440 | hdev->acl_mtu, hdev->acl_pkts, | ||
441 | hdev->sco_mtu, hdev->sco_pkts); | ||
442 | } | ||
443 | |||
444 | static void hci_cc_read_bd_addr(struct hci_dev *hdev, struct sk_buff *skb) | ||
445 | { | ||
446 | struct hci_rp_read_bd_addr *rp = (void *) skb->data; | ||
447 | |||
448 | BT_DBG("%s status 0x%x", hdev->name, rp->status); | ||
449 | |||
450 | if (!rp->status) | ||
451 | bacpy(&hdev->bdaddr, &rp->bdaddr); | ||
452 | |||
453 | hci_req_complete(hdev, rp->status); | ||
454 | } | ||
455 | |||
456 | static inline void hci_cs_inquiry(struct hci_dev *hdev, __u8 status) | ||
457 | { | ||
458 | BT_DBG("%s status 0x%x", hdev->name, status); | ||
459 | |||
460 | if (status) { | ||
461 | hci_req_complete(hdev, status); | ||
462 | |||
463 | hci_conn_check_pending(hdev); | ||
464 | } else | ||
465 | set_bit(HCI_INQUIRY, &hdev->flags); | ||
419 | } | 466 | } |
420 | 467 | ||
421 | /* Command Status OGF LINK_CTL */ | ||
422 | static inline void hci_cs_create_conn(struct hci_dev *hdev, __u8 status) | 468 | static inline void hci_cs_create_conn(struct hci_dev *hdev, __u8 status) |
423 | { | 469 | { |
470 | struct hci_cp_create_conn *cp; | ||
424 | struct hci_conn *conn; | 471 | struct hci_conn *conn; |
425 | struct hci_cp_create_conn *cp = hci_sent_cmd_data(hdev, OGF_LINK_CTL, OCF_CREATE_CONN); | ||
426 | 472 | ||
473 | BT_DBG("%s status 0x%x", hdev->name, status); | ||
474 | |||
475 | cp = hci_sent_cmd_data(hdev, HCI_OP_CREATE_CONN); | ||
427 | if (!cp) | 476 | if (!cp) |
428 | return; | 477 | return; |
429 | 478 | ||
@@ -431,8 +480,7 @@ static inline void hci_cs_create_conn(struct hci_dev *hdev, __u8 status) | |||
431 | 480 | ||
432 | conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr); | 481 | conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr); |
433 | 482 | ||
434 | BT_DBG("%s status 0x%x bdaddr %s conn %p", hdev->name, | 483 | BT_DBG("%s bdaddr %s conn %p", hdev->name, batostr(&cp->bdaddr), conn); |
435 | status, batostr(&cp->bdaddr), conn); | ||
436 | 484 | ||
437 | if (status) { | 485 | if (status) { |
438 | if (conn && conn->state == BT_CONNECT) { | 486 | if (conn && conn->state == BT_CONNECT) { |
@@ -457,234 +505,138 @@ static inline void hci_cs_create_conn(struct hci_dev *hdev, __u8 status) | |||
457 | hci_dev_unlock(hdev); | 505 | hci_dev_unlock(hdev); |
458 | } | 506 | } |
459 | 507 | ||
460 | static void hci_cs_link_ctl(struct hci_dev *hdev, __u16 ocf, __u8 status) | 508 | static void hci_cs_add_sco(struct hci_dev *hdev, __u8 status) |
461 | { | 509 | { |
462 | BT_DBG("%s ocf 0x%x", hdev->name, ocf); | 510 | struct hci_cp_add_sco *cp; |
511 | struct hci_conn *acl, *sco; | ||
512 | __u16 handle; | ||
463 | 513 | ||
464 | switch (ocf) { | 514 | BT_DBG("%s status 0x%x", hdev->name, status); |
465 | case OCF_CREATE_CONN: | ||
466 | hci_cs_create_conn(hdev, status); | ||
467 | break; | ||
468 | |||
469 | case OCF_ADD_SCO: | ||
470 | if (status) { | ||
471 | struct hci_conn *acl, *sco; | ||
472 | struct hci_cp_add_sco *cp = hci_sent_cmd_data(hdev, OGF_LINK_CTL, OCF_ADD_SCO); | ||
473 | __u16 handle; | ||
474 | |||
475 | if (!cp) | ||
476 | break; | ||
477 | 515 | ||
478 | handle = __le16_to_cpu(cp->handle); | 516 | if (!status) |
479 | 517 | return; | |
480 | BT_DBG("%s Add SCO error: handle %d status 0x%x", hdev->name, handle, status); | ||
481 | 518 | ||
482 | hci_dev_lock(hdev); | 519 | cp = hci_sent_cmd_data(hdev, HCI_OP_ADD_SCO); |
520 | if (!cp) | ||
521 | return; | ||
483 | 522 | ||
484 | acl = hci_conn_hash_lookup_handle(hdev, handle); | 523 | handle = __le16_to_cpu(cp->handle); |
485 | if (acl && (sco = acl->link)) { | ||
486 | sco->state = BT_CLOSED; | ||
487 | 524 | ||
488 | hci_proto_connect_cfm(sco, status); | 525 | BT_DBG("%s handle %d", hdev->name, handle); |
489 | hci_conn_del(sco); | ||
490 | } | ||
491 | 526 | ||
492 | hci_dev_unlock(hdev); | 527 | hci_dev_lock(hdev); |
493 | } | ||
494 | break; | ||
495 | 528 | ||
496 | case OCF_INQUIRY: | 529 | acl = hci_conn_hash_lookup_handle(hdev, handle); |
497 | if (status) { | 530 | if (acl && (sco = acl->link)) { |
498 | BT_DBG("%s Inquiry error: status 0x%x", hdev->name, status); | 531 | sco->state = BT_CLOSED; |
499 | hci_req_complete(hdev, status); | ||
500 | } else { | ||
501 | set_bit(HCI_INQUIRY, &hdev->flags); | ||
502 | } | ||
503 | break; | ||
504 | 532 | ||
505 | default: | 533 | hci_proto_connect_cfm(sco, status); |
506 | BT_DBG("%s Command status: ogf LINK_CTL ocf %x status %d", | 534 | hci_conn_del(sco); |
507 | hdev->name, ocf, status); | ||
508 | break; | ||
509 | } | 535 | } |
536 | |||
537 | hci_dev_unlock(hdev); | ||
510 | } | 538 | } |
511 | 539 | ||
512 | /* Command Status OGF LINK_POLICY */ | 540 | static void hci_cs_remote_name_req(struct hci_dev *hdev, __u8 status) |
513 | static void hci_cs_link_policy(struct hci_dev *hdev, __u16 ocf, __u8 status) | ||
514 | { | 541 | { |
515 | BT_DBG("%s ocf 0x%x", hdev->name, ocf); | 542 | BT_DBG("%s status 0x%x", hdev->name, status); |
516 | 543 | } | |
517 | switch (ocf) { | ||
518 | case OCF_SNIFF_MODE: | ||
519 | if (status) { | ||
520 | struct hci_conn *conn; | ||
521 | struct hci_cp_sniff_mode *cp = hci_sent_cmd_data(hdev, OGF_LINK_POLICY, OCF_SNIFF_MODE); | ||
522 | 544 | ||
523 | if (!cp) | 545 | static void hci_cs_setup_sync_conn(struct hci_dev *hdev, __u8 status) |
524 | break; | 546 | { |
547 | struct hci_cp_setup_sync_conn *cp; | ||
548 | struct hci_conn *acl, *sco; | ||
549 | __u16 handle; | ||
525 | 550 | ||
526 | hci_dev_lock(hdev); | 551 | BT_DBG("%s status 0x%x", hdev->name, status); |
527 | 552 | ||
528 | conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); | 553 | if (!status) |
529 | if (conn) { | 554 | return; |
530 | clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->pend); | ||
531 | } | ||
532 | |||
533 | hci_dev_unlock(hdev); | ||
534 | } | ||
535 | break; | ||
536 | 555 | ||
537 | case OCF_EXIT_SNIFF_MODE: | 556 | cp = hci_sent_cmd_data(hdev, HCI_OP_SETUP_SYNC_CONN); |
538 | if (status) { | 557 | if (!cp) |
539 | struct hci_conn *conn; | 558 | return; |
540 | struct hci_cp_exit_sniff_mode *cp = hci_sent_cmd_data(hdev, OGF_LINK_POLICY, OCF_EXIT_SNIFF_MODE); | ||
541 | 559 | ||
542 | if (!cp) | 560 | handle = __le16_to_cpu(cp->handle); |
543 | break; | ||
544 | 561 | ||
545 | hci_dev_lock(hdev); | 562 | BT_DBG("%s handle %d", hdev->name, handle); |
546 | 563 | ||
547 | conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); | 564 | hci_dev_lock(hdev); |
548 | if (conn) { | ||
549 | clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->pend); | ||
550 | } | ||
551 | 565 | ||
552 | hci_dev_unlock(hdev); | 566 | acl = hci_conn_hash_lookup_handle(hdev, handle); |
553 | } | 567 | if (acl && (sco = acl->link)) { |
554 | break; | 568 | sco->state = BT_CLOSED; |
555 | 569 | ||
556 | default: | 570 | hci_proto_connect_cfm(sco, status); |
557 | BT_DBG("%s Command status: ogf LINK_POLICY ocf %x", hdev->name, ocf); | 571 | hci_conn_del(sco); |
558 | break; | ||
559 | } | 572 | } |
560 | } | ||
561 | 573 | ||
562 | /* Command Status OGF HOST_CTL */ | 574 | hci_dev_unlock(hdev); |
563 | static void hci_cs_host_ctl(struct hci_dev *hdev, __u16 ocf, __u8 status) | ||
564 | { | ||
565 | BT_DBG("%s ocf 0x%x", hdev->name, ocf); | ||
566 | |||
567 | switch (ocf) { | ||
568 | default: | ||
569 | BT_DBG("%s Command status: ogf HOST_CTL ocf %x", hdev->name, ocf); | ||
570 | break; | ||
571 | } | ||
572 | } | 575 | } |
573 | 576 | ||
574 | /* Command Status OGF INFO_PARAM */ | 577 | static void hci_cs_sniff_mode(struct hci_dev *hdev, __u8 status) |
575 | static void hci_cs_info_param(struct hci_dev *hdev, __u16 ocf, __u8 status) | ||
576 | { | 578 | { |
577 | BT_DBG("%s: hci_cs_info_param: ocf 0x%x", hdev->name, ocf); | 579 | struct hci_cp_sniff_mode *cp; |
578 | 580 | struct hci_conn *conn; | |
579 | switch (ocf) { | ||
580 | default: | ||
581 | BT_DBG("%s Command status: ogf INFO_PARAM ocf %x", hdev->name, ocf); | ||
582 | break; | ||
583 | } | ||
584 | } | ||
585 | 581 | ||
586 | /* Inquiry Complete */ | 582 | BT_DBG("%s status 0x%x", hdev->name, status); |
587 | static inline void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) | ||
588 | { | ||
589 | __u8 status = *((__u8 *) skb->data); | ||
590 | struct hci_conn *pend; | ||
591 | 583 | ||
592 | BT_DBG("%s status %d", hdev->name, status); | 584 | if (!status) |
585 | return; | ||
593 | 586 | ||
594 | clear_bit(HCI_INQUIRY, &hdev->flags); | 587 | cp = hci_sent_cmd_data(hdev, HCI_OP_SNIFF_MODE); |
595 | hci_req_complete(hdev, status); | 588 | if (!cp) |
589 | return; | ||
596 | 590 | ||
597 | hci_dev_lock(hdev); | 591 | hci_dev_lock(hdev); |
598 | 592 | ||
599 | pend = hci_conn_hash_lookup_state(hdev, ACL_LINK, BT_CONNECT2); | 593 | conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); |
600 | if (pend) | 594 | if (conn) |
601 | hci_acl_connect(pend); | 595 | clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->pend); |
602 | 596 | ||
603 | hci_dev_unlock(hdev); | 597 | hci_dev_unlock(hdev); |
604 | } | 598 | } |
605 | 599 | ||
606 | /* Inquiry Result */ | 600 | static void hci_cs_exit_sniff_mode(struct hci_dev *hdev, __u8 status) |
607 | static inline void hci_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb) | ||
608 | { | 601 | { |
609 | struct inquiry_data data; | 602 | struct hci_cp_exit_sniff_mode *cp; |
610 | struct inquiry_info *info = (struct inquiry_info *) (skb->data + 1); | 603 | struct hci_conn *conn; |
611 | int num_rsp = *((__u8 *) skb->data); | ||
612 | 604 | ||
613 | BT_DBG("%s num_rsp %d", hdev->name, num_rsp); | 605 | BT_DBG("%s status 0x%x", hdev->name, status); |
614 | 606 | ||
615 | if (!num_rsp) | 607 | if (!status) |
608 | return; | ||
609 | |||
610 | cp = hci_sent_cmd_data(hdev, HCI_OP_EXIT_SNIFF_MODE); | ||
611 | if (!cp) | ||
616 | return; | 612 | return; |
617 | 613 | ||
618 | hci_dev_lock(hdev); | 614 | hci_dev_lock(hdev); |
619 | 615 | ||
620 | for (; num_rsp; num_rsp--) { | 616 | conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); |
621 | bacpy(&data.bdaddr, &info->bdaddr); | 617 | if (conn) |
622 | data.pscan_rep_mode = info->pscan_rep_mode; | 618 | clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->pend); |
623 | data.pscan_period_mode = info->pscan_period_mode; | ||
624 | data.pscan_mode = info->pscan_mode; | ||
625 | memcpy(data.dev_class, info->dev_class, 3); | ||
626 | data.clock_offset = info->clock_offset; | ||
627 | data.rssi = 0x00; | ||
628 | info++; | ||
629 | hci_inquiry_cache_update(hdev, &data); | ||
630 | } | ||
631 | 619 | ||
632 | hci_dev_unlock(hdev); | 620 | hci_dev_unlock(hdev); |
633 | } | 621 | } |
634 | 622 | ||
635 | /* Inquiry Result With RSSI */ | 623 | static inline void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) |
636 | static inline void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev, struct sk_buff *skb) | ||
637 | { | 624 | { |
638 | struct inquiry_data data; | 625 | __u8 status = *((__u8 *) skb->data); |
639 | int num_rsp = *((__u8 *) skb->data); | ||
640 | |||
641 | BT_DBG("%s num_rsp %d", hdev->name, num_rsp); | ||
642 | |||
643 | if (!num_rsp) | ||
644 | return; | ||
645 | |||
646 | hci_dev_lock(hdev); | ||
647 | 626 | ||
648 | if ((skb->len - 1) / num_rsp != sizeof(struct inquiry_info_with_rssi)) { | 627 | BT_DBG("%s status %d", hdev->name, status); |
649 | struct inquiry_info_with_rssi_and_pscan_mode *info = | ||
650 | (struct inquiry_info_with_rssi_and_pscan_mode *) (skb->data + 1); | ||
651 | 628 | ||
652 | for (; num_rsp; num_rsp--) { | 629 | clear_bit(HCI_INQUIRY, &hdev->flags); |
653 | bacpy(&data.bdaddr, &info->bdaddr); | ||
654 | data.pscan_rep_mode = info->pscan_rep_mode; | ||
655 | data.pscan_period_mode = info->pscan_period_mode; | ||
656 | data.pscan_mode = info->pscan_mode; | ||
657 | memcpy(data.dev_class, info->dev_class, 3); | ||
658 | data.clock_offset = info->clock_offset; | ||
659 | data.rssi = info->rssi; | ||
660 | info++; | ||
661 | hci_inquiry_cache_update(hdev, &data); | ||
662 | } | ||
663 | } else { | ||
664 | struct inquiry_info_with_rssi *info = | ||
665 | (struct inquiry_info_with_rssi *) (skb->data + 1); | ||
666 | 630 | ||
667 | for (; num_rsp; num_rsp--) { | 631 | hci_req_complete(hdev, status); |
668 | bacpy(&data.bdaddr, &info->bdaddr); | ||
669 | data.pscan_rep_mode = info->pscan_rep_mode; | ||
670 | data.pscan_period_mode = info->pscan_period_mode; | ||
671 | data.pscan_mode = 0x00; | ||
672 | memcpy(data.dev_class, info->dev_class, 3); | ||
673 | data.clock_offset = info->clock_offset; | ||
674 | data.rssi = info->rssi; | ||
675 | info++; | ||
676 | hci_inquiry_cache_update(hdev, &data); | ||
677 | } | ||
678 | } | ||
679 | 632 | ||
680 | hci_dev_unlock(hdev); | 633 | hci_conn_check_pending(hdev); |
681 | } | 634 | } |
682 | 635 | ||
683 | /* Extended Inquiry Result */ | 636 | static inline void hci_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb) |
684 | static inline void hci_extended_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb) | ||
685 | { | 637 | { |
686 | struct inquiry_data data; | 638 | struct inquiry_data data; |
687 | struct extended_inquiry_info *info = (struct extended_inquiry_info *) (skb->data + 1); | 639 | struct inquiry_info *info = (void *) (skb->data + 1); |
688 | int num_rsp = *((__u8 *) skb->data); | 640 | int num_rsp = *((__u8 *) skb->data); |
689 | 641 | ||
690 | BT_DBG("%s num_rsp %d", hdev->name, num_rsp); | 642 | BT_DBG("%s num_rsp %d", hdev->name, num_rsp); |
@@ -696,12 +648,12 @@ static inline void hci_extended_inquiry_result_evt(struct hci_dev *hdev, struct | |||
696 | 648 | ||
697 | for (; num_rsp; num_rsp--) { | 649 | for (; num_rsp; num_rsp--) { |
698 | bacpy(&data.bdaddr, &info->bdaddr); | 650 | bacpy(&data.bdaddr, &info->bdaddr); |
699 | data.pscan_rep_mode = info->pscan_rep_mode; | 651 | data.pscan_rep_mode = info->pscan_rep_mode; |
700 | data.pscan_period_mode = info->pscan_period_mode; | 652 | data.pscan_period_mode = info->pscan_period_mode; |
701 | data.pscan_mode = 0x00; | 653 | data.pscan_mode = info->pscan_mode; |
702 | memcpy(data.dev_class, info->dev_class, 3); | 654 | memcpy(data.dev_class, info->dev_class, 3); |
703 | data.clock_offset = info->clock_offset; | 655 | data.clock_offset = info->clock_offset; |
704 | data.rssi = info->rssi; | 656 | data.rssi = 0x00; |
705 | info++; | 657 | info++; |
706 | hci_inquiry_cache_update(hdev, &data); | 658 | hci_inquiry_cache_update(hdev, &data); |
707 | } | 659 | } |
@@ -709,70 +661,18 @@ static inline void hci_extended_inquiry_result_evt(struct hci_dev *hdev, struct | |||
709 | hci_dev_unlock(hdev); | 661 | hci_dev_unlock(hdev); |
710 | } | 662 | } |
711 | 663 | ||
712 | /* Connect Request */ | ||
713 | static inline void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *skb) | ||
714 | { | ||
715 | struct hci_ev_conn_request *ev = (struct hci_ev_conn_request *) skb->data; | ||
716 | int mask = hdev->link_mode; | ||
717 | |||
718 | BT_DBG("%s Connection request: %s type 0x%x", hdev->name, | ||
719 | batostr(&ev->bdaddr), ev->link_type); | ||
720 | |||
721 | mask |= hci_proto_connect_ind(hdev, &ev->bdaddr, ev->link_type); | ||
722 | |||
723 | if (mask & HCI_LM_ACCEPT) { | ||
724 | /* Connection accepted */ | ||
725 | struct hci_conn *conn; | ||
726 | struct hci_cp_accept_conn_req cp; | ||
727 | |||
728 | hci_dev_lock(hdev); | ||
729 | conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr); | ||
730 | if (!conn) { | ||
731 | if (!(conn = hci_conn_add(hdev, ev->link_type, &ev->bdaddr))) { | ||
732 | BT_ERR("No memmory for new connection"); | ||
733 | hci_dev_unlock(hdev); | ||
734 | return; | ||
735 | } | ||
736 | } | ||
737 | memcpy(conn->dev_class, ev->dev_class, 3); | ||
738 | conn->state = BT_CONNECT; | ||
739 | hci_dev_unlock(hdev); | ||
740 | |||
741 | bacpy(&cp.bdaddr, &ev->bdaddr); | ||
742 | |||
743 | if (lmp_rswitch_capable(hdev) && (mask & HCI_LM_MASTER)) | ||
744 | cp.role = 0x00; /* Become master */ | ||
745 | else | ||
746 | cp.role = 0x01; /* Remain slave */ | ||
747 | |||
748 | hci_send_cmd(hdev, OGF_LINK_CTL, | ||
749 | OCF_ACCEPT_CONN_REQ, sizeof(cp), &cp); | ||
750 | } else { | ||
751 | /* Connection rejected */ | ||
752 | struct hci_cp_reject_conn_req cp; | ||
753 | |||
754 | bacpy(&cp.bdaddr, &ev->bdaddr); | ||
755 | cp.reason = 0x0f; | ||
756 | hci_send_cmd(hdev, OGF_LINK_CTL, | ||
757 | OCF_REJECT_CONN_REQ, sizeof(cp), &cp); | ||
758 | } | ||
759 | } | ||
760 | |||
761 | /* Connect Complete */ | ||
762 | static inline void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) | 664 | static inline void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) |
763 | { | 665 | { |
764 | struct hci_ev_conn_complete *ev = (struct hci_ev_conn_complete *) skb->data; | 666 | struct hci_ev_conn_complete *ev = (void *) skb->data; |
765 | struct hci_conn *conn, *pend; | 667 | struct hci_conn *conn; |
766 | 668 | ||
767 | BT_DBG("%s", hdev->name); | 669 | BT_DBG("%s", hdev->name); |
768 | 670 | ||
769 | hci_dev_lock(hdev); | 671 | hci_dev_lock(hdev); |
770 | 672 | ||
771 | conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr); | 673 | conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr); |
772 | if (!conn) { | 674 | if (!conn) |
773 | hci_dev_unlock(hdev); | 675 | goto unlock; |
774 | return; | ||
775 | } | ||
776 | 676 | ||
777 | if (!ev->status) { | 677 | if (!ev->status) { |
778 | conn->handle = __le16_to_cpu(ev->handle); | 678 | conn->handle = __le16_to_cpu(ev->handle); |
@@ -788,8 +688,7 @@ static inline void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *s | |||
788 | if (conn->type == ACL_LINK) { | 688 | if (conn->type == ACL_LINK) { |
789 | struct hci_cp_read_remote_features cp; | 689 | struct hci_cp_read_remote_features cp; |
790 | cp.handle = ev->handle; | 690 | cp.handle = ev->handle; |
791 | hci_send_cmd(hdev, OGF_LINK_CTL, | 691 | hci_send_cmd(hdev, HCI_OP_READ_REMOTE_FEATURES, sizeof(cp), &cp); |
792 | OCF_READ_REMOTE_FEATURES, sizeof(cp), &cp); | ||
793 | } | 692 | } |
794 | 693 | ||
795 | /* Set link policy */ | 694 | /* Set link policy */ |
@@ -797,8 +696,7 @@ static inline void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *s | |||
797 | struct hci_cp_write_link_policy cp; | 696 | struct hci_cp_write_link_policy cp; |
798 | cp.handle = ev->handle; | 697 | cp.handle = ev->handle; |
799 | cp.policy = cpu_to_le16(hdev->link_policy); | 698 | cp.policy = cpu_to_le16(hdev->link_policy); |
800 | hci_send_cmd(hdev, OGF_LINK_POLICY, | 699 | hci_send_cmd(hdev, HCI_OP_WRITE_LINK_POLICY, sizeof(cp), &cp); |
801 | OCF_WRITE_LINK_POLICY, sizeof(cp), &cp); | ||
802 | } | 700 | } |
803 | 701 | ||
804 | /* Set packet type for incoming connection */ | 702 | /* Set packet type for incoming connection */ |
@@ -809,8 +707,7 @@ static inline void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *s | |||
809 | cpu_to_le16(hdev->pkt_type & ACL_PTYPE_MASK): | 707 | cpu_to_le16(hdev->pkt_type & ACL_PTYPE_MASK): |
810 | cpu_to_le16(hdev->pkt_type & SCO_PTYPE_MASK); | 708 | cpu_to_le16(hdev->pkt_type & SCO_PTYPE_MASK); |
811 | 709 | ||
812 | hci_send_cmd(hdev, OGF_LINK_CTL, | 710 | hci_send_cmd(hdev, HCI_OP_CHANGE_CONN_PTYPE, sizeof(cp), &cp); |
813 | OCF_CHANGE_CONN_PTYPE, sizeof(cp), &cp); | ||
814 | } else { | 711 | } else { |
815 | /* Update disconnect timer */ | 712 | /* Update disconnect timer */ |
816 | hci_conn_hold(conn); | 713 | hci_conn_hold(conn); |
@@ -822,9 +719,12 @@ static inline void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *s | |||
822 | if (conn->type == ACL_LINK) { | 719 | if (conn->type == ACL_LINK) { |
823 | struct hci_conn *sco = conn->link; | 720 | struct hci_conn *sco = conn->link; |
824 | if (sco) { | 721 | if (sco) { |
825 | if (!ev->status) | 722 | if (!ev->status) { |
826 | hci_add_sco(sco, conn->handle); | 723 | if (lmp_esco_capable(hdev)) |
827 | else { | 724 | hci_setup_sync(sco, conn->handle); |
725 | else | ||
726 | hci_add_sco(sco, conn->handle); | ||
727 | } else { | ||
828 | hci_proto_connect_cfm(sco, ev->status); | 728 | hci_proto_connect_cfm(sco, ev->status); |
829 | hci_conn_del(sco); | 729 | hci_conn_del(sco); |
830 | } | 730 | } |
@@ -835,136 +735,104 @@ static inline void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *s | |||
835 | if (ev->status) | 735 | if (ev->status) |
836 | hci_conn_del(conn); | 736 | hci_conn_del(conn); |
837 | 737 | ||
838 | pend = hci_conn_hash_lookup_state(hdev, ACL_LINK, BT_CONNECT2); | 738 | unlock: |
839 | if (pend) | ||
840 | hci_acl_connect(pend); | ||
841 | |||
842 | hci_dev_unlock(hdev); | 739 | hci_dev_unlock(hdev); |
843 | } | ||
844 | |||
845 | /* Disconnect Complete */ | ||
846 | static inline void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) | ||
847 | { | ||
848 | struct hci_ev_disconn_complete *ev = (struct hci_ev_disconn_complete *) skb->data; | ||
849 | struct hci_conn *conn; | ||
850 | |||
851 | BT_DBG("%s status %d", hdev->name, ev->status); | ||
852 | |||
853 | if (ev->status) | ||
854 | return; | ||
855 | 740 | ||
856 | hci_dev_lock(hdev); | 741 | hci_conn_check_pending(hdev); |
857 | |||
858 | conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); | ||
859 | if (conn) { | ||
860 | conn->state = BT_CLOSED; | ||
861 | hci_proto_disconn_ind(conn, ev->reason); | ||
862 | hci_conn_del(conn); | ||
863 | } | ||
864 | |||
865 | hci_dev_unlock(hdev); | ||
866 | } | 742 | } |
867 | 743 | ||
868 | /* Number of completed packets */ | 744 | static inline void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *skb) |
869 | static inline void hci_num_comp_pkts_evt(struct hci_dev *hdev, struct sk_buff *skb) | ||
870 | { | 745 | { |
871 | struct hci_ev_num_comp_pkts *ev = (struct hci_ev_num_comp_pkts *) skb->data; | 746 | struct hci_ev_conn_request *ev = (void *) skb->data; |
872 | __le16 *ptr; | 747 | int mask = hdev->link_mode; |
873 | int i; | ||
874 | |||
875 | skb_pull(skb, sizeof(*ev)); | ||
876 | |||
877 | BT_DBG("%s num_hndl %d", hdev->name, ev->num_hndl); | ||
878 | 748 | ||
879 | if (skb->len < ev->num_hndl * 4) { | 749 | BT_DBG("%s bdaddr %s type 0x%x", hdev->name, |
880 | BT_DBG("%s bad parameters", hdev->name); | 750 | batostr(&ev->bdaddr), ev->link_type); |
881 | return; | ||
882 | } | ||
883 | 751 | ||
884 | tasklet_disable(&hdev->tx_task); | 752 | mask |= hci_proto_connect_ind(hdev, &ev->bdaddr, ev->link_type); |
885 | 753 | ||
886 | for (i = 0, ptr = (__le16 *) skb->data; i < ev->num_hndl; i++) { | 754 | if (mask & HCI_LM_ACCEPT) { |
755 | /* Connection accepted */ | ||
887 | struct hci_conn *conn; | 756 | struct hci_conn *conn; |
888 | __u16 handle, count; | ||
889 | |||
890 | handle = __le16_to_cpu(get_unaligned(ptr++)); | ||
891 | count = __le16_to_cpu(get_unaligned(ptr++)); | ||
892 | 757 | ||
893 | conn = hci_conn_hash_lookup_handle(hdev, handle); | 758 | hci_dev_lock(hdev); |
894 | if (conn) { | ||
895 | conn->sent -= count; | ||
896 | 759 | ||
897 | if (conn->type == ACL_LINK) { | 760 | conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr); |
898 | if ((hdev->acl_cnt += count) > hdev->acl_pkts) | 761 | if (!conn) { |
899 | hdev->acl_cnt = hdev->acl_pkts; | 762 | if (!(conn = hci_conn_add(hdev, ev->link_type, &ev->bdaddr))) { |
900 | } else { | 763 | BT_ERR("No memmory for new connection"); |
901 | if ((hdev->sco_cnt += count) > hdev->sco_pkts) | 764 | hci_dev_unlock(hdev); |
902 | hdev->sco_cnt = hdev->sco_pkts; | 765 | return; |
903 | } | 766 | } |
904 | } | 767 | } |
905 | } | ||
906 | hci_sched_tx(hdev); | ||
907 | 768 | ||
908 | tasklet_enable(&hdev->tx_task); | 769 | memcpy(conn->dev_class, ev->dev_class, 3); |
909 | } | 770 | conn->state = BT_CONNECT; |
910 | 771 | ||
911 | /* Role Change */ | 772 | hci_dev_unlock(hdev); |
912 | static inline void hci_role_change_evt(struct hci_dev *hdev, struct sk_buff *skb) | ||
913 | { | ||
914 | struct hci_ev_role_change *ev = (struct hci_ev_role_change *) skb->data; | ||
915 | struct hci_conn *conn; | ||
916 | 773 | ||
917 | BT_DBG("%s status %d", hdev->name, ev->status); | 774 | if (ev->link_type == ACL_LINK || !lmp_esco_capable(hdev)) { |
775 | struct hci_cp_accept_conn_req cp; | ||
918 | 776 | ||
919 | hci_dev_lock(hdev); | 777 | bacpy(&cp.bdaddr, &ev->bdaddr); |
920 | 778 | ||
921 | conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); | 779 | if (lmp_rswitch_capable(hdev) && (mask & HCI_LM_MASTER)) |
922 | if (conn) { | 780 | cp.role = 0x00; /* Become master */ |
923 | if (!ev->status) { | ||
924 | if (ev->role) | ||
925 | conn->link_mode &= ~HCI_LM_MASTER; | ||
926 | else | 781 | else |
927 | conn->link_mode |= HCI_LM_MASTER; | 782 | cp.role = 0x01; /* Remain slave */ |
928 | } | ||
929 | 783 | ||
930 | clear_bit(HCI_CONN_RSWITCH_PEND, &conn->pend); | 784 | hci_send_cmd(hdev, HCI_OP_ACCEPT_CONN_REQ, |
785 | sizeof(cp), &cp); | ||
786 | } else { | ||
787 | struct hci_cp_accept_sync_conn_req cp; | ||
931 | 788 | ||
932 | hci_role_switch_cfm(conn, ev->status, ev->role); | 789 | bacpy(&cp.bdaddr, &ev->bdaddr); |
933 | } | 790 | cp.pkt_type = cpu_to_le16(hdev->esco_type); |
934 | 791 | ||
935 | hci_dev_unlock(hdev); | 792 | cp.tx_bandwidth = cpu_to_le32(0x00001f40); |
793 | cp.rx_bandwidth = cpu_to_le32(0x00001f40); | ||
794 | cp.max_latency = cpu_to_le16(0xffff); | ||
795 | cp.content_format = cpu_to_le16(hdev->voice_setting); | ||
796 | cp.retrans_effort = 0xff; | ||
797 | |||
798 | hci_send_cmd(hdev, HCI_OP_ACCEPT_SYNC_CONN_REQ, | ||
799 | sizeof(cp), &cp); | ||
800 | } | ||
801 | } else { | ||
802 | /* Connection rejected */ | ||
803 | struct hci_cp_reject_conn_req cp; | ||
804 | |||
805 | bacpy(&cp.bdaddr, &ev->bdaddr); | ||
806 | cp.reason = 0x0f; | ||
807 | hci_send_cmd(hdev, HCI_OP_REJECT_CONN_REQ, sizeof(cp), &cp); | ||
808 | } | ||
936 | } | 809 | } |
937 | 810 | ||
938 | /* Mode Change */ | 811 | static inline void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) |
939 | static inline void hci_mode_change_evt(struct hci_dev *hdev, struct sk_buff *skb) | ||
940 | { | 812 | { |
941 | struct hci_ev_mode_change *ev = (struct hci_ev_mode_change *) skb->data; | 813 | struct hci_ev_disconn_complete *ev = (void *) skb->data; |
942 | struct hci_conn *conn; | 814 | struct hci_conn *conn; |
943 | 815 | ||
944 | BT_DBG("%s status %d", hdev->name, ev->status); | 816 | BT_DBG("%s status %d", hdev->name, ev->status); |
945 | 817 | ||
818 | if (ev->status) | ||
819 | return; | ||
820 | |||
946 | hci_dev_lock(hdev); | 821 | hci_dev_lock(hdev); |
947 | 822 | ||
948 | conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); | 823 | conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); |
949 | if (conn) { | 824 | if (conn) { |
950 | conn->mode = ev->mode; | 825 | conn->state = BT_CLOSED; |
951 | conn->interval = __le16_to_cpu(ev->interval); | 826 | hci_proto_disconn_ind(conn, ev->reason); |
952 | 827 | hci_conn_del(conn); | |
953 | if (!test_and_clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->pend)) { | ||
954 | if (conn->mode == HCI_CM_ACTIVE) | ||
955 | conn->power_save = 1; | ||
956 | else | ||
957 | conn->power_save = 0; | ||
958 | } | ||
959 | } | 828 | } |
960 | 829 | ||
961 | hci_dev_unlock(hdev); | 830 | hci_dev_unlock(hdev); |
962 | } | 831 | } |
963 | 832 | ||
964 | /* Authentication Complete */ | ||
965 | static inline void hci_auth_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) | 833 | static inline void hci_auth_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) |
966 | { | 834 | { |
967 | struct hci_ev_auth_complete *ev = (struct hci_ev_auth_complete *) skb->data; | 835 | struct hci_ev_auth_complete *ev = (void *) skb->data; |
968 | struct hci_conn *conn; | 836 | struct hci_conn *conn; |
969 | 837 | ||
970 | BT_DBG("%s status %d", hdev->name, ev->status); | 838 | BT_DBG("%s status %d", hdev->name, ev->status); |
@@ -985,8 +853,8 @@ static inline void hci_auth_complete_evt(struct hci_dev *hdev, struct sk_buff *s | |||
985 | struct hci_cp_set_conn_encrypt cp; | 853 | struct hci_cp_set_conn_encrypt cp; |
986 | cp.handle = cpu_to_le16(conn->handle); | 854 | cp.handle = cpu_to_le16(conn->handle); |
987 | cp.encrypt = 1; | 855 | cp.encrypt = 1; |
988 | hci_send_cmd(conn->hdev, OGF_LINK_CTL, | 856 | hci_send_cmd(conn->hdev, |
989 | OCF_SET_CONN_ENCRYPT, sizeof(cp), &cp); | 857 | HCI_OP_SET_CONN_ENCRYPT, sizeof(cp), &cp); |
990 | } else { | 858 | } else { |
991 | clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend); | 859 | clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend); |
992 | hci_encrypt_cfm(conn, ev->status, 0x00); | 860 | hci_encrypt_cfm(conn, ev->status, 0x00); |
@@ -997,10 +865,16 @@ static inline void hci_auth_complete_evt(struct hci_dev *hdev, struct sk_buff *s | |||
997 | hci_dev_unlock(hdev); | 865 | hci_dev_unlock(hdev); |
998 | } | 866 | } |
999 | 867 | ||
1000 | /* Encryption Change */ | 868 | static inline void hci_remote_name_evt(struct hci_dev *hdev, struct sk_buff *skb) |
869 | { | ||
870 | BT_DBG("%s", hdev->name); | ||
871 | |||
872 | hci_conn_check_pending(hdev); | ||
873 | } | ||
874 | |||
1001 | static inline void hci_encrypt_change_evt(struct hci_dev *hdev, struct sk_buff *skb) | 875 | static inline void hci_encrypt_change_evt(struct hci_dev *hdev, struct sk_buff *skb) |
1002 | { | 876 | { |
1003 | struct hci_ev_encrypt_change *ev = (struct hci_ev_encrypt_change *) skb->data; | 877 | struct hci_ev_encrypt_change *ev = (void *) skb->data; |
1004 | struct hci_conn *conn; | 878 | struct hci_conn *conn; |
1005 | 879 | ||
1006 | BT_DBG("%s status %d", hdev->name, ev->status); | 880 | BT_DBG("%s status %d", hdev->name, ev->status); |
@@ -1024,10 +898,9 @@ static inline void hci_encrypt_change_evt(struct hci_dev *hdev, struct sk_buff * | |||
1024 | hci_dev_unlock(hdev); | 898 | hci_dev_unlock(hdev); |
1025 | } | 899 | } |
1026 | 900 | ||
1027 | /* Change Connection Link Key Complete */ | 901 | static inline void hci_change_link_key_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) |
1028 | static inline void hci_change_conn_link_key_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) | ||
1029 | { | 902 | { |
1030 | struct hci_ev_change_conn_link_key_complete *ev = (struct hci_ev_change_conn_link_key_complete *) skb->data; | 903 | struct hci_ev_change_link_key_complete *ev = (void *) skb->data; |
1031 | struct hci_conn *conn; | 904 | struct hci_conn *conn; |
1032 | 905 | ||
1033 | BT_DBG("%s status %d", hdev->name, ev->status); | 906 | BT_DBG("%s status %d", hdev->name, ev->status); |
@@ -1047,25 +920,263 @@ static inline void hci_change_conn_link_key_complete_evt(struct hci_dev *hdev, s | |||
1047 | hci_dev_unlock(hdev); | 920 | hci_dev_unlock(hdev); |
1048 | } | 921 | } |
1049 | 922 | ||
1050 | /* Pin Code Request*/ | 923 | static inline void hci_remote_features_evt(struct hci_dev *hdev, struct sk_buff *skb) |
1051 | static inline void hci_pin_code_request_evt(struct hci_dev *hdev, struct sk_buff *skb) | ||
1052 | { | 924 | { |
925 | struct hci_ev_remote_features *ev = (void *) skb->data; | ||
926 | struct hci_conn *conn; | ||
927 | |||
928 | BT_DBG("%s status %d", hdev->name, ev->status); | ||
929 | |||
930 | if (ev->status) | ||
931 | return; | ||
932 | |||
933 | hci_dev_lock(hdev); | ||
934 | |||
935 | conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); | ||
936 | if (conn) | ||
937 | memcpy(conn->features, ev->features, 8); | ||
938 | |||
939 | hci_dev_unlock(hdev); | ||
1053 | } | 940 | } |
1054 | 941 | ||
1055 | /* Link Key Request */ | 942 | static inline void hci_remote_version_evt(struct hci_dev *hdev, struct sk_buff *skb) |
1056 | static inline void hci_link_key_request_evt(struct hci_dev *hdev, struct sk_buff *skb) | ||
1057 | { | 943 | { |
944 | BT_DBG("%s", hdev->name); | ||
1058 | } | 945 | } |
1059 | 946 | ||
1060 | /* Link Key Notification */ | 947 | static inline void hci_qos_setup_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) |
1061 | static inline void hci_link_key_notify_evt(struct hci_dev *hdev, struct sk_buff *skb) | ||
1062 | { | 948 | { |
949 | BT_DBG("%s", hdev->name); | ||
1063 | } | 950 | } |
1064 | 951 | ||
1065 | /* Remote Features */ | 952 | static inline void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) |
1066 | static inline void hci_remote_features_evt(struct hci_dev *hdev, struct sk_buff *skb) | ||
1067 | { | 953 | { |
1068 | struct hci_ev_remote_features *ev = (struct hci_ev_remote_features *) skb->data; | 954 | struct hci_ev_cmd_complete *ev = (void *) skb->data; |
955 | __u16 opcode; | ||
956 | |||
957 | skb_pull(skb, sizeof(*ev)); | ||
958 | |||
959 | opcode = __le16_to_cpu(ev->opcode); | ||
960 | |||
961 | switch (opcode) { | ||
962 | case HCI_OP_INQUIRY_CANCEL: | ||
963 | hci_cc_inquiry_cancel(hdev, skb); | ||
964 | break; | ||
965 | |||
966 | case HCI_OP_EXIT_PERIODIC_INQ: | ||
967 | hci_cc_exit_periodic_inq(hdev, skb); | ||
968 | break; | ||
969 | |||
970 | case HCI_OP_REMOTE_NAME_REQ_CANCEL: | ||
971 | hci_cc_remote_name_req_cancel(hdev, skb); | ||
972 | break; | ||
973 | |||
974 | case HCI_OP_ROLE_DISCOVERY: | ||
975 | hci_cc_role_discovery(hdev, skb); | ||
976 | break; | ||
977 | |||
978 | case HCI_OP_WRITE_LINK_POLICY: | ||
979 | hci_cc_write_link_policy(hdev, skb); | ||
980 | break; | ||
981 | |||
982 | case HCI_OP_RESET: | ||
983 | hci_cc_reset(hdev, skb); | ||
984 | break; | ||
985 | |||
986 | case HCI_OP_WRITE_LOCAL_NAME: | ||
987 | hci_cc_write_local_name(hdev, skb); | ||
988 | break; | ||
989 | |||
990 | case HCI_OP_READ_LOCAL_NAME: | ||
991 | hci_cc_read_local_name(hdev, skb); | ||
992 | break; | ||
993 | |||
994 | case HCI_OP_WRITE_AUTH_ENABLE: | ||
995 | hci_cc_write_auth_enable(hdev, skb); | ||
996 | break; | ||
997 | |||
998 | case HCI_OP_WRITE_ENCRYPT_MODE: | ||
999 | hci_cc_write_encrypt_mode(hdev, skb); | ||
1000 | break; | ||
1001 | |||
1002 | case HCI_OP_WRITE_SCAN_ENABLE: | ||
1003 | hci_cc_write_scan_enable(hdev, skb); | ||
1004 | break; | ||
1005 | |||
1006 | case HCI_OP_READ_CLASS_OF_DEV: | ||
1007 | hci_cc_read_class_of_dev(hdev, skb); | ||
1008 | break; | ||
1009 | |||
1010 | case HCI_OP_WRITE_CLASS_OF_DEV: | ||
1011 | hci_cc_write_class_of_dev(hdev, skb); | ||
1012 | break; | ||
1013 | |||
1014 | case HCI_OP_READ_VOICE_SETTING: | ||
1015 | hci_cc_read_voice_setting(hdev, skb); | ||
1016 | break; | ||
1017 | |||
1018 | case HCI_OP_WRITE_VOICE_SETTING: | ||
1019 | hci_cc_write_voice_setting(hdev, skb); | ||
1020 | break; | ||
1021 | |||
1022 | case HCI_OP_HOST_BUFFER_SIZE: | ||
1023 | hci_cc_host_buffer_size(hdev, skb); | ||
1024 | break; | ||
1025 | |||
1026 | case HCI_OP_READ_LOCAL_VERSION: | ||
1027 | hci_cc_read_local_version(hdev, skb); | ||
1028 | break; | ||
1029 | |||
1030 | case HCI_OP_READ_LOCAL_COMMANDS: | ||
1031 | hci_cc_read_local_commands(hdev, skb); | ||
1032 | break; | ||
1033 | |||
1034 | case HCI_OP_READ_LOCAL_FEATURES: | ||
1035 | hci_cc_read_local_features(hdev, skb); | ||
1036 | break; | ||
1037 | |||
1038 | case HCI_OP_READ_BUFFER_SIZE: | ||
1039 | hci_cc_read_buffer_size(hdev, skb); | ||
1040 | break; | ||
1041 | |||
1042 | case HCI_OP_READ_BD_ADDR: | ||
1043 | hci_cc_read_bd_addr(hdev, skb); | ||
1044 | break; | ||
1045 | |||
1046 | default: | ||
1047 | BT_DBG("%s opcode 0x%x", hdev->name, opcode); | ||
1048 | break; | ||
1049 | } | ||
1050 | |||
1051 | if (ev->ncmd) { | ||
1052 | atomic_set(&hdev->cmd_cnt, 1); | ||
1053 | if (!skb_queue_empty(&hdev->cmd_q)) | ||
1054 | hci_sched_cmd(hdev); | ||
1055 | } | ||
1056 | } | ||
1057 | |||
1058 | static inline void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb) | ||
1059 | { | ||
1060 | struct hci_ev_cmd_status *ev = (void *) skb->data; | ||
1061 | __u16 opcode; | ||
1062 | |||
1063 | skb_pull(skb, sizeof(*ev)); | ||
1064 | |||
1065 | opcode = __le16_to_cpu(ev->opcode); | ||
1066 | |||
1067 | switch (opcode) { | ||
1068 | case HCI_OP_INQUIRY: | ||
1069 | hci_cs_inquiry(hdev, ev->status); | ||
1070 | break; | ||
1071 | |||
1072 | case HCI_OP_CREATE_CONN: | ||
1073 | hci_cs_create_conn(hdev, ev->status); | ||
1074 | break; | ||
1075 | |||
1076 | case HCI_OP_ADD_SCO: | ||
1077 | hci_cs_add_sco(hdev, ev->status); | ||
1078 | break; | ||
1079 | |||
1080 | case HCI_OP_REMOTE_NAME_REQ: | ||
1081 | hci_cs_remote_name_req(hdev, ev->status); | ||
1082 | break; | ||
1083 | |||
1084 | case HCI_OP_SETUP_SYNC_CONN: | ||
1085 | hci_cs_setup_sync_conn(hdev, ev->status); | ||
1086 | break; | ||
1087 | |||
1088 | case HCI_OP_SNIFF_MODE: | ||
1089 | hci_cs_sniff_mode(hdev, ev->status); | ||
1090 | break; | ||
1091 | |||
1092 | case HCI_OP_EXIT_SNIFF_MODE: | ||
1093 | hci_cs_exit_sniff_mode(hdev, ev->status); | ||
1094 | break; | ||
1095 | |||
1096 | default: | ||
1097 | BT_DBG("%s opcode 0x%x", hdev->name, opcode); | ||
1098 | break; | ||
1099 | } | ||
1100 | |||
1101 | if (ev->ncmd) { | ||
1102 | atomic_set(&hdev->cmd_cnt, 1); | ||
1103 | if (!skb_queue_empty(&hdev->cmd_q)) | ||
1104 | hci_sched_cmd(hdev); | ||
1105 | } | ||
1106 | } | ||
1107 | |||
1108 | static inline void hci_role_change_evt(struct hci_dev *hdev, struct sk_buff *skb) | ||
1109 | { | ||
1110 | struct hci_ev_role_change *ev = (void *) skb->data; | ||
1111 | struct hci_conn *conn; | ||
1112 | |||
1113 | BT_DBG("%s status %d", hdev->name, ev->status); | ||
1114 | |||
1115 | hci_dev_lock(hdev); | ||
1116 | |||
1117 | conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); | ||
1118 | if (conn) { | ||
1119 | if (!ev->status) { | ||
1120 | if (ev->role) | ||
1121 | conn->link_mode &= ~HCI_LM_MASTER; | ||
1122 | else | ||
1123 | conn->link_mode |= HCI_LM_MASTER; | ||
1124 | } | ||
1125 | |||
1126 | clear_bit(HCI_CONN_RSWITCH_PEND, &conn->pend); | ||
1127 | |||
1128 | hci_role_switch_cfm(conn, ev->status, ev->role); | ||
1129 | } | ||
1130 | |||
1131 | hci_dev_unlock(hdev); | ||
1132 | } | ||
1133 | |||
1134 | static inline void hci_num_comp_pkts_evt(struct hci_dev *hdev, struct sk_buff *skb) | ||
1135 | { | ||
1136 | struct hci_ev_num_comp_pkts *ev = (void *) skb->data; | ||
1137 | __le16 *ptr; | ||
1138 | int i; | ||
1139 | |||
1140 | skb_pull(skb, sizeof(*ev)); | ||
1141 | |||
1142 | BT_DBG("%s num_hndl %d", hdev->name, ev->num_hndl); | ||
1143 | |||
1144 | if (skb->len < ev->num_hndl * 4) { | ||
1145 | BT_DBG("%s bad parameters", hdev->name); | ||
1146 | return; | ||
1147 | } | ||
1148 | |||
1149 | tasklet_disable(&hdev->tx_task); | ||
1150 | |||
1151 | for (i = 0, ptr = (__le16 *) skb->data; i < ev->num_hndl; i++) { | ||
1152 | struct hci_conn *conn; | ||
1153 | __u16 handle, count; | ||
1154 | |||
1155 | handle = __le16_to_cpu(get_unaligned(ptr++)); | ||
1156 | count = __le16_to_cpu(get_unaligned(ptr++)); | ||
1157 | |||
1158 | conn = hci_conn_hash_lookup_handle(hdev, handle); | ||
1159 | if (conn) { | ||
1160 | conn->sent -= count; | ||
1161 | |||
1162 | if (conn->type == ACL_LINK) { | ||
1163 | if ((hdev->acl_cnt += count) > hdev->acl_pkts) | ||
1164 | hdev->acl_cnt = hdev->acl_pkts; | ||
1165 | } else { | ||
1166 | if ((hdev->sco_cnt += count) > hdev->sco_pkts) | ||
1167 | hdev->sco_cnt = hdev->sco_pkts; | ||
1168 | } | ||
1169 | } | ||
1170 | } | ||
1171 | |||
1172 | hci_sched_tx(hdev); | ||
1173 | |||
1174 | tasklet_enable(&hdev->tx_task); | ||
1175 | } | ||
1176 | |||
1177 | static inline void hci_mode_change_evt(struct hci_dev *hdev, struct sk_buff *skb) | ||
1178 | { | ||
1179 | struct hci_ev_mode_change *ev = (void *) skb->data; | ||
1069 | struct hci_conn *conn; | 1180 | struct hci_conn *conn; |
1070 | 1181 | ||
1071 | BT_DBG("%s status %d", hdev->name, ev->status); | 1182 | BT_DBG("%s status %d", hdev->name, ev->status); |
@@ -1073,17 +1184,39 @@ static inline void hci_remote_features_evt(struct hci_dev *hdev, struct sk_buff | |||
1073 | hci_dev_lock(hdev); | 1184 | hci_dev_lock(hdev); |
1074 | 1185 | ||
1075 | conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); | 1186 | conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); |
1076 | if (conn && !ev->status) { | 1187 | if (conn) { |
1077 | memcpy(conn->features, ev->features, sizeof(conn->features)); | 1188 | conn->mode = ev->mode; |
1189 | conn->interval = __le16_to_cpu(ev->interval); | ||
1190 | |||
1191 | if (!test_and_clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->pend)) { | ||
1192 | if (conn->mode == HCI_CM_ACTIVE) | ||
1193 | conn->power_save = 1; | ||
1194 | else | ||
1195 | conn->power_save = 0; | ||
1196 | } | ||
1078 | } | 1197 | } |
1079 | 1198 | ||
1080 | hci_dev_unlock(hdev); | 1199 | hci_dev_unlock(hdev); |
1081 | } | 1200 | } |
1082 | 1201 | ||
1083 | /* Clock Offset */ | 1202 | static inline void hci_pin_code_request_evt(struct hci_dev *hdev, struct sk_buff *skb) |
1203 | { | ||
1204 | BT_DBG("%s", hdev->name); | ||
1205 | } | ||
1206 | |||
1207 | static inline void hci_link_key_request_evt(struct hci_dev *hdev, struct sk_buff *skb) | ||
1208 | { | ||
1209 | BT_DBG("%s", hdev->name); | ||
1210 | } | ||
1211 | |||
1212 | static inline void hci_link_key_notify_evt(struct hci_dev *hdev, struct sk_buff *skb) | ||
1213 | { | ||
1214 | BT_DBG("%s", hdev->name); | ||
1215 | } | ||
1216 | |||
1084 | static inline void hci_clock_offset_evt(struct hci_dev *hdev, struct sk_buff *skb) | 1217 | static inline void hci_clock_offset_evt(struct hci_dev *hdev, struct sk_buff *skb) |
1085 | { | 1218 | { |
1086 | struct hci_ev_clock_offset *ev = (struct hci_ev_clock_offset *) skb->data; | 1219 | struct hci_ev_clock_offset *ev = (void *) skb->data; |
1087 | struct hci_conn *conn; | 1220 | struct hci_conn *conn; |
1088 | 1221 | ||
1089 | BT_DBG("%s status %d", hdev->name, ev->status); | 1222 | BT_DBG("%s status %d", hdev->name, ev->status); |
@@ -1103,10 +1236,9 @@ static inline void hci_clock_offset_evt(struct hci_dev *hdev, struct sk_buff *sk | |||
1103 | hci_dev_unlock(hdev); | 1236 | hci_dev_unlock(hdev); |
1104 | } | 1237 | } |
1105 | 1238 | ||
1106 | /* Page Scan Repetition Mode */ | ||
1107 | static inline void hci_pscan_rep_mode_evt(struct hci_dev *hdev, struct sk_buff *skb) | 1239 | static inline void hci_pscan_rep_mode_evt(struct hci_dev *hdev, struct sk_buff *skb) |
1108 | { | 1240 | { |
1109 | struct hci_ev_pscan_rep_mode *ev = (struct hci_ev_pscan_rep_mode *) skb->data; | 1241 | struct hci_ev_pscan_rep_mode *ev = (void *) skb->data; |
1110 | struct inquiry_entry *ie; | 1242 | struct inquiry_entry *ie; |
1111 | 1243 | ||
1112 | BT_DBG("%s", hdev->name); | 1244 | BT_DBG("%s", hdev->name); |
@@ -1121,10 +1253,91 @@ static inline void hci_pscan_rep_mode_evt(struct hci_dev *hdev, struct sk_buff * | |||
1121 | hci_dev_unlock(hdev); | 1253 | hci_dev_unlock(hdev); |
1122 | } | 1254 | } |
1123 | 1255 | ||
1124 | /* Sniff Subrate */ | 1256 | static inline void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev, struct sk_buff *skb) |
1257 | { | ||
1258 | struct inquiry_data data; | ||
1259 | int num_rsp = *((__u8 *) skb->data); | ||
1260 | |||
1261 | BT_DBG("%s num_rsp %d", hdev->name, num_rsp); | ||
1262 | |||
1263 | if (!num_rsp) | ||
1264 | return; | ||
1265 | |||
1266 | hci_dev_lock(hdev); | ||
1267 | |||
1268 | if ((skb->len - 1) / num_rsp != sizeof(struct inquiry_info_with_rssi)) { | ||
1269 | struct inquiry_info_with_rssi_and_pscan_mode *info = (void *) (skb->data + 1); | ||
1270 | |||
1271 | for (; num_rsp; num_rsp--) { | ||
1272 | bacpy(&data.bdaddr, &info->bdaddr); | ||
1273 | data.pscan_rep_mode = info->pscan_rep_mode; | ||
1274 | data.pscan_period_mode = info->pscan_period_mode; | ||
1275 | data.pscan_mode = info->pscan_mode; | ||
1276 | memcpy(data.dev_class, info->dev_class, 3); | ||
1277 | data.clock_offset = info->clock_offset; | ||
1278 | data.rssi = info->rssi; | ||
1279 | info++; | ||
1280 | hci_inquiry_cache_update(hdev, &data); | ||
1281 | } | ||
1282 | } else { | ||
1283 | struct inquiry_info_with_rssi *info = (void *) (skb->data + 1); | ||
1284 | |||
1285 | for (; num_rsp; num_rsp--) { | ||
1286 | bacpy(&data.bdaddr, &info->bdaddr); | ||
1287 | data.pscan_rep_mode = info->pscan_rep_mode; | ||
1288 | data.pscan_period_mode = info->pscan_period_mode; | ||
1289 | data.pscan_mode = 0x00; | ||
1290 | memcpy(data.dev_class, info->dev_class, 3); | ||
1291 | data.clock_offset = info->clock_offset; | ||
1292 | data.rssi = info->rssi; | ||
1293 | info++; | ||
1294 | hci_inquiry_cache_update(hdev, &data); | ||
1295 | } | ||
1296 | } | ||
1297 | |||
1298 | hci_dev_unlock(hdev); | ||
1299 | } | ||
1300 | |||
1301 | static inline void hci_remote_ext_features_evt(struct hci_dev *hdev, struct sk_buff *skb) | ||
1302 | { | ||
1303 | BT_DBG("%s", hdev->name); | ||
1304 | } | ||
1305 | |||
1306 | static inline void hci_sync_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) | ||
1307 | { | ||
1308 | struct hci_ev_sync_conn_complete *ev = (void *) skb->data; | ||
1309 | struct hci_conn *conn; | ||
1310 | |||
1311 | BT_DBG("%s status %d", hdev->name, ev->status); | ||
1312 | |||
1313 | hci_dev_lock(hdev); | ||
1314 | |||
1315 | conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr); | ||
1316 | if (!conn) | ||
1317 | goto unlock; | ||
1318 | |||
1319 | if (!ev->status) { | ||
1320 | conn->handle = __le16_to_cpu(ev->handle); | ||
1321 | conn->state = BT_CONNECTED; | ||
1322 | } else | ||
1323 | conn->state = BT_CLOSED; | ||
1324 | |||
1325 | hci_proto_connect_cfm(conn, ev->status); | ||
1326 | if (ev->status) | ||
1327 | hci_conn_del(conn); | ||
1328 | |||
1329 | unlock: | ||
1330 | hci_dev_unlock(hdev); | ||
1331 | } | ||
1332 | |||
1333 | static inline void hci_sync_conn_changed_evt(struct hci_dev *hdev, struct sk_buff *skb) | ||
1334 | { | ||
1335 | BT_DBG("%s", hdev->name); | ||
1336 | } | ||
1337 | |||
1125 | static inline void hci_sniff_subrate_evt(struct hci_dev *hdev, struct sk_buff *skb) | 1338 | static inline void hci_sniff_subrate_evt(struct hci_dev *hdev, struct sk_buff *skb) |
1126 | { | 1339 | { |
1127 | struct hci_ev_sniff_subrate *ev = (struct hci_ev_sniff_subrate *) skb->data; | 1340 | struct hci_ev_sniff_subrate *ev = (void *) skb->data; |
1128 | struct hci_conn *conn; | 1341 | struct hci_conn *conn; |
1129 | 1342 | ||
1130 | BT_DBG("%s status %d", hdev->name, ev->status); | 1343 | BT_DBG("%s status %d", hdev->name, ev->status); |
@@ -1138,22 +1351,42 @@ static inline void hci_sniff_subrate_evt(struct hci_dev *hdev, struct sk_buff *s | |||
1138 | hci_dev_unlock(hdev); | 1351 | hci_dev_unlock(hdev); |
1139 | } | 1352 | } |
1140 | 1353 | ||
1141 | void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb) | 1354 | static inline void hci_extended_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb) |
1142 | { | 1355 | { |
1143 | struct hci_event_hdr *hdr = (struct hci_event_hdr *) skb->data; | 1356 | struct inquiry_data data; |
1144 | struct hci_ev_cmd_complete *ec; | 1357 | struct extended_inquiry_info *info = (void *) (skb->data + 1); |
1145 | struct hci_ev_cmd_status *cs; | 1358 | int num_rsp = *((__u8 *) skb->data); |
1146 | u16 opcode, ocf, ogf; | ||
1147 | 1359 | ||
1148 | skb_pull(skb, HCI_EVENT_HDR_SIZE); | 1360 | BT_DBG("%s num_rsp %d", hdev->name, num_rsp); |
1149 | 1361 | ||
1150 | BT_DBG("%s evt 0x%x", hdev->name, hdr->evt); | 1362 | if (!num_rsp) |
1363 | return; | ||
1151 | 1364 | ||
1152 | switch (hdr->evt) { | 1365 | hci_dev_lock(hdev); |
1153 | case HCI_EV_NUM_COMP_PKTS: | 1366 | |
1154 | hci_num_comp_pkts_evt(hdev, skb); | 1367 | for (; num_rsp; num_rsp--) { |
1155 | break; | 1368 | bacpy(&data.bdaddr, &info->bdaddr); |
1369 | data.pscan_rep_mode = info->pscan_rep_mode; | ||
1370 | data.pscan_period_mode = info->pscan_period_mode; | ||
1371 | data.pscan_mode = 0x00; | ||
1372 | memcpy(data.dev_class, info->dev_class, 3); | ||
1373 | data.clock_offset = info->clock_offset; | ||
1374 | data.rssi = info->rssi; | ||
1375 | info++; | ||
1376 | hci_inquiry_cache_update(hdev, &data); | ||
1377 | } | ||
1156 | 1378 | ||
1379 | hci_dev_unlock(hdev); | ||
1380 | } | ||
1381 | |||
1382 | void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb) | ||
1383 | { | ||
1384 | struct hci_event_hdr *hdr = (void *) skb->data; | ||
1385 | __u8 event = hdr->evt; | ||
1386 | |||
1387 | skb_pull(skb, HCI_EVENT_HDR_SIZE); | ||
1388 | |||
1389 | switch (event) { | ||
1157 | case HCI_EV_INQUIRY_COMPLETE: | 1390 | case HCI_EV_INQUIRY_COMPLETE: |
1158 | hci_inquiry_complete_evt(hdev, skb); | 1391 | hci_inquiry_complete_evt(hdev, skb); |
1159 | break; | 1392 | break; |
@@ -1162,44 +1395,64 @@ void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb) | |||
1162 | hci_inquiry_result_evt(hdev, skb); | 1395 | hci_inquiry_result_evt(hdev, skb); |
1163 | break; | 1396 | break; |
1164 | 1397 | ||
1165 | case HCI_EV_INQUIRY_RESULT_WITH_RSSI: | 1398 | case HCI_EV_CONN_COMPLETE: |
1166 | hci_inquiry_result_with_rssi_evt(hdev, skb); | 1399 | hci_conn_complete_evt(hdev, skb); |
1167 | break; | ||
1168 | |||
1169 | case HCI_EV_EXTENDED_INQUIRY_RESULT: | ||
1170 | hci_extended_inquiry_result_evt(hdev, skb); | ||
1171 | break; | 1400 | break; |
1172 | 1401 | ||
1173 | case HCI_EV_CONN_REQUEST: | 1402 | case HCI_EV_CONN_REQUEST: |
1174 | hci_conn_request_evt(hdev, skb); | 1403 | hci_conn_request_evt(hdev, skb); |
1175 | break; | 1404 | break; |
1176 | 1405 | ||
1177 | case HCI_EV_CONN_COMPLETE: | ||
1178 | hci_conn_complete_evt(hdev, skb); | ||
1179 | break; | ||
1180 | |||
1181 | case HCI_EV_DISCONN_COMPLETE: | 1406 | case HCI_EV_DISCONN_COMPLETE: |
1182 | hci_disconn_complete_evt(hdev, skb); | 1407 | hci_disconn_complete_evt(hdev, skb); |
1183 | break; | 1408 | break; |
1184 | 1409 | ||
1185 | case HCI_EV_ROLE_CHANGE: | ||
1186 | hci_role_change_evt(hdev, skb); | ||
1187 | break; | ||
1188 | |||
1189 | case HCI_EV_MODE_CHANGE: | ||
1190 | hci_mode_change_evt(hdev, skb); | ||
1191 | break; | ||
1192 | |||
1193 | case HCI_EV_AUTH_COMPLETE: | 1410 | case HCI_EV_AUTH_COMPLETE: |
1194 | hci_auth_complete_evt(hdev, skb); | 1411 | hci_auth_complete_evt(hdev, skb); |
1195 | break; | 1412 | break; |
1196 | 1413 | ||
1414 | case HCI_EV_REMOTE_NAME: | ||
1415 | hci_remote_name_evt(hdev, skb); | ||
1416 | break; | ||
1417 | |||
1197 | case HCI_EV_ENCRYPT_CHANGE: | 1418 | case HCI_EV_ENCRYPT_CHANGE: |
1198 | hci_encrypt_change_evt(hdev, skb); | 1419 | hci_encrypt_change_evt(hdev, skb); |
1199 | break; | 1420 | break; |
1200 | 1421 | ||
1201 | case HCI_EV_CHANGE_CONN_LINK_KEY_COMPLETE: | 1422 | case HCI_EV_CHANGE_LINK_KEY_COMPLETE: |
1202 | hci_change_conn_link_key_complete_evt(hdev, skb); | 1423 | hci_change_link_key_complete_evt(hdev, skb); |
1424 | break; | ||
1425 | |||
1426 | case HCI_EV_REMOTE_FEATURES: | ||
1427 | hci_remote_features_evt(hdev, skb); | ||
1428 | break; | ||
1429 | |||
1430 | case HCI_EV_REMOTE_VERSION: | ||
1431 | hci_remote_version_evt(hdev, skb); | ||
1432 | break; | ||
1433 | |||
1434 | case HCI_EV_QOS_SETUP_COMPLETE: | ||
1435 | hci_qos_setup_complete_evt(hdev, skb); | ||
1436 | break; | ||
1437 | |||
1438 | case HCI_EV_CMD_COMPLETE: | ||
1439 | hci_cmd_complete_evt(hdev, skb); | ||
1440 | break; | ||
1441 | |||
1442 | case HCI_EV_CMD_STATUS: | ||
1443 | hci_cmd_status_evt(hdev, skb); | ||
1444 | break; | ||
1445 | |||
1446 | case HCI_EV_ROLE_CHANGE: | ||
1447 | hci_role_change_evt(hdev, skb); | ||
1448 | break; | ||
1449 | |||
1450 | case HCI_EV_NUM_COMP_PKTS: | ||
1451 | hci_num_comp_pkts_evt(hdev, skb); | ||
1452 | break; | ||
1453 | |||
1454 | case HCI_EV_MODE_CHANGE: | ||
1455 | hci_mode_change_evt(hdev, skb); | ||
1203 | break; | 1456 | break; |
1204 | 1457 | ||
1205 | case HCI_EV_PIN_CODE_REQ: | 1458 | case HCI_EV_PIN_CODE_REQ: |
@@ -1214,10 +1467,6 @@ void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb) | |||
1214 | hci_link_key_notify_evt(hdev, skb); | 1467 | hci_link_key_notify_evt(hdev, skb); |
1215 | break; | 1468 | break; |
1216 | 1469 | ||
1217 | case HCI_EV_REMOTE_FEATURES: | ||
1218 | hci_remote_features_evt(hdev, skb); | ||
1219 | break; | ||
1220 | |||
1221 | case HCI_EV_CLOCK_OFFSET: | 1470 | case HCI_EV_CLOCK_OFFSET: |
1222 | hci_clock_offset_evt(hdev, skb); | 1471 | hci_clock_offset_evt(hdev, skb); |
1223 | break; | 1472 | break; |
@@ -1226,82 +1475,32 @@ void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb) | |||
1226 | hci_pscan_rep_mode_evt(hdev, skb); | 1475 | hci_pscan_rep_mode_evt(hdev, skb); |
1227 | break; | 1476 | break; |
1228 | 1477 | ||
1229 | case HCI_EV_SNIFF_SUBRATE: | 1478 | case HCI_EV_INQUIRY_RESULT_WITH_RSSI: |
1230 | hci_sniff_subrate_evt(hdev, skb); | 1479 | hci_inquiry_result_with_rssi_evt(hdev, skb); |
1231 | break; | 1480 | break; |
1232 | 1481 | ||
1233 | case HCI_EV_CMD_STATUS: | 1482 | case HCI_EV_REMOTE_EXT_FEATURES: |
1234 | cs = (struct hci_ev_cmd_status *) skb->data; | 1483 | hci_remote_ext_features_evt(hdev, skb); |
1235 | skb_pull(skb, sizeof(cs)); | ||
1236 | |||
1237 | opcode = __le16_to_cpu(cs->opcode); | ||
1238 | ogf = hci_opcode_ogf(opcode); | ||
1239 | ocf = hci_opcode_ocf(opcode); | ||
1240 | |||
1241 | switch (ogf) { | ||
1242 | case OGF_INFO_PARAM: | ||
1243 | hci_cs_info_param(hdev, ocf, cs->status); | ||
1244 | break; | ||
1245 | |||
1246 | case OGF_HOST_CTL: | ||
1247 | hci_cs_host_ctl(hdev, ocf, cs->status); | ||
1248 | break; | ||
1249 | |||
1250 | case OGF_LINK_CTL: | ||
1251 | hci_cs_link_ctl(hdev, ocf, cs->status); | ||
1252 | break; | ||
1253 | |||
1254 | case OGF_LINK_POLICY: | ||
1255 | hci_cs_link_policy(hdev, ocf, cs->status); | ||
1256 | break; | ||
1257 | |||
1258 | default: | ||
1259 | BT_DBG("%s Command Status OGF %x", hdev->name, ogf); | ||
1260 | break; | ||
1261 | } | ||
1262 | |||
1263 | if (cs->ncmd) { | ||
1264 | atomic_set(&hdev->cmd_cnt, 1); | ||
1265 | if (!skb_queue_empty(&hdev->cmd_q)) | ||
1266 | hci_sched_cmd(hdev); | ||
1267 | } | ||
1268 | break; | 1484 | break; |
1269 | 1485 | ||
1270 | case HCI_EV_CMD_COMPLETE: | 1486 | case HCI_EV_SYNC_CONN_COMPLETE: |
1271 | ec = (struct hci_ev_cmd_complete *) skb->data; | 1487 | hci_sync_conn_complete_evt(hdev, skb); |
1272 | skb_pull(skb, sizeof(*ec)); | 1488 | break; |
1273 | |||
1274 | opcode = __le16_to_cpu(ec->opcode); | ||
1275 | ogf = hci_opcode_ogf(opcode); | ||
1276 | ocf = hci_opcode_ocf(opcode); | ||
1277 | |||
1278 | switch (ogf) { | ||
1279 | case OGF_INFO_PARAM: | ||
1280 | hci_cc_info_param(hdev, ocf, skb); | ||
1281 | break; | ||
1282 | |||
1283 | case OGF_HOST_CTL: | ||
1284 | hci_cc_host_ctl(hdev, ocf, skb); | ||
1285 | break; | ||
1286 | 1489 | ||
1287 | case OGF_LINK_CTL: | 1490 | case HCI_EV_SYNC_CONN_CHANGED: |
1288 | hci_cc_link_ctl(hdev, ocf, skb); | 1491 | hci_sync_conn_changed_evt(hdev, skb); |
1289 | break; | 1492 | break; |
1290 | 1493 | ||
1291 | case OGF_LINK_POLICY: | 1494 | case HCI_EV_SNIFF_SUBRATE: |
1292 | hci_cc_link_policy(hdev, ocf, skb); | 1495 | hci_sniff_subrate_evt(hdev, skb); |
1293 | break; | 1496 | break; |
1294 | 1497 | ||
1295 | default: | 1498 | case HCI_EV_EXTENDED_INQUIRY_RESULT: |
1296 | BT_DBG("%s Command Completed OGF %x", hdev->name, ogf); | 1499 | hci_extended_inquiry_result_evt(hdev, skb); |
1297 | break; | 1500 | break; |
1298 | } | ||
1299 | 1501 | ||
1300 | if (ec->ncmd) { | 1502 | default: |
1301 | atomic_set(&hdev->cmd_cnt, 1); | 1503 | BT_DBG("%s event 0x%x", hdev->name, event); |
1302 | if (!skb_queue_empty(&hdev->cmd_q)) | ||
1303 | hci_sched_cmd(hdev); | ||
1304 | } | ||
1305 | break; | 1504 | break; |
1306 | } | 1505 | } |
1307 | 1506 | ||
diff --git a/net/bluetooth/hci_sock.c b/net/bluetooth/hci_sock.c index 43dd6373bff9..8825102c517c 100644 --- a/net/bluetooth/hci_sock.c +++ b/net/bluetooth/hci_sock.c | |||
@@ -451,7 +451,7 @@ static int hci_sock_sendmsg(struct kiocb *iocb, struct socket *sock, | |||
451 | goto drop; | 451 | goto drop; |
452 | } | 452 | } |
453 | 453 | ||
454 | if (test_bit(HCI_RAW, &hdev->flags) || (ogf == OGF_VENDOR_CMD)) { | 454 | if (test_bit(HCI_RAW, &hdev->flags) || (ogf == 0x3f)) { |
455 | skb_queue_tail(&hdev->raw_q, skb); | 455 | skb_queue_tail(&hdev->raw_q, skb); |
456 | hci_sched_tx(hdev); | 456 | hci_sched_tx(hdev); |
457 | } else { | 457 | } else { |
diff --git a/net/bluetooth/hci_sysfs.c b/net/bluetooth/hci_sysfs.c index 25835403d659..cef1e3e1881c 100644 --- a/net/bluetooth/hci_sysfs.c +++ b/net/bluetooth/hci_sysfs.c | |||
@@ -41,6 +41,26 @@ static ssize_t show_type(struct device *dev, struct device_attribute *attr, char | |||
41 | return sprintf(buf, "%s\n", typetostr(hdev->type)); | 41 | return sprintf(buf, "%s\n", typetostr(hdev->type)); |
42 | } | 42 | } |
43 | 43 | ||
44 | static ssize_t show_name(struct device *dev, struct device_attribute *attr, char *buf) | ||
45 | { | ||
46 | struct hci_dev *hdev = dev_get_drvdata(dev); | ||
47 | char name[249]; | ||
48 | int i; | ||
49 | |||
50 | for (i = 0; i < 248; i++) | ||
51 | name[i] = hdev->dev_name[i]; | ||
52 | |||
53 | name[248] = '\0'; | ||
54 | return sprintf(buf, "%s\n", name); | ||
55 | } | ||
56 | |||
57 | static ssize_t show_class(struct device *dev, struct device_attribute *attr, char *buf) | ||
58 | { | ||
59 | struct hci_dev *hdev = dev_get_drvdata(dev); | ||
60 | return sprintf(buf, "0x%.2x%.2x%.2x\n", | ||
61 | hdev->dev_class[2], hdev->dev_class[1], hdev->dev_class[0]); | ||
62 | } | ||
63 | |||
44 | static ssize_t show_address(struct device *dev, struct device_attribute *attr, char *buf) | 64 | static ssize_t show_address(struct device *dev, struct device_attribute *attr, char *buf) |
45 | { | 65 | { |
46 | struct hci_dev *hdev = dev_get_drvdata(dev); | 66 | struct hci_dev *hdev = dev_get_drvdata(dev); |
@@ -49,6 +69,17 @@ static ssize_t show_address(struct device *dev, struct device_attribute *attr, c | |||
49 | return sprintf(buf, "%s\n", batostr(&bdaddr)); | 69 | return sprintf(buf, "%s\n", batostr(&bdaddr)); |
50 | } | 70 | } |
51 | 71 | ||
72 | static ssize_t show_features(struct device *dev, struct device_attribute *attr, char *buf) | ||
73 | { | ||
74 | struct hci_dev *hdev = dev_get_drvdata(dev); | ||
75 | |||
76 | return sprintf(buf, "0x%02x%02x%02x%02x%02x%02x%02x%02x\n", | ||
77 | hdev->features[0], hdev->features[1], | ||
78 | hdev->features[2], hdev->features[3], | ||
79 | hdev->features[4], hdev->features[5], | ||
80 | hdev->features[6], hdev->features[7]); | ||
81 | } | ||
82 | |||
52 | static ssize_t show_manufacturer(struct device *dev, struct device_attribute *attr, char *buf) | 83 | static ssize_t show_manufacturer(struct device *dev, struct device_attribute *attr, char *buf) |
53 | { | 84 | { |
54 | struct hci_dev *hdev = dev_get_drvdata(dev); | 85 | struct hci_dev *hdev = dev_get_drvdata(dev); |
@@ -170,7 +201,10 @@ static ssize_t store_sniff_min_interval(struct device *dev, struct device_attrib | |||
170 | } | 201 | } |
171 | 202 | ||
172 | static DEVICE_ATTR(type, S_IRUGO, show_type, NULL); | 203 | static DEVICE_ATTR(type, S_IRUGO, show_type, NULL); |
204 | static DEVICE_ATTR(name, S_IRUGO, show_name, NULL); | ||
205 | static DEVICE_ATTR(class, S_IRUGO, show_class, NULL); | ||
173 | static DEVICE_ATTR(address, S_IRUGO, show_address, NULL); | 206 | static DEVICE_ATTR(address, S_IRUGO, show_address, NULL); |
207 | static DEVICE_ATTR(features, S_IRUGO, show_features, NULL); | ||
174 | static DEVICE_ATTR(manufacturer, S_IRUGO, show_manufacturer, NULL); | 208 | static DEVICE_ATTR(manufacturer, S_IRUGO, show_manufacturer, NULL); |
175 | static DEVICE_ATTR(hci_version, S_IRUGO, show_hci_version, NULL); | 209 | static DEVICE_ATTR(hci_version, S_IRUGO, show_hci_version, NULL); |
176 | static DEVICE_ATTR(hci_revision, S_IRUGO, show_hci_revision, NULL); | 210 | static DEVICE_ATTR(hci_revision, S_IRUGO, show_hci_revision, NULL); |
@@ -185,7 +219,10 @@ static DEVICE_ATTR(sniff_min_interval, S_IRUGO | S_IWUSR, | |||
185 | 219 | ||
186 | static struct device_attribute *bt_attrs[] = { | 220 | static struct device_attribute *bt_attrs[] = { |
187 | &dev_attr_type, | 221 | &dev_attr_type, |
222 | &dev_attr_name, | ||
223 | &dev_attr_class, | ||
188 | &dev_attr_address, | 224 | &dev_attr_address, |
225 | &dev_attr_features, | ||
189 | &dev_attr_manufacturer, | 226 | &dev_attr_manufacturer, |
190 | &dev_attr_hci_version, | 227 | &dev_attr_hci_version, |
191 | &dev_attr_hci_revision, | 228 | &dev_attr_hci_revision, |
diff --git a/net/bluetooth/hidp/core.c b/net/bluetooth/hidp/core.c index ff5784b440d7..4bbacddeb49d 100644 --- a/net/bluetooth/hidp/core.c +++ b/net/bluetooth/hidp/core.c | |||
@@ -247,7 +247,7 @@ static inline int hidp_queue_report(struct hidp_session *session, unsigned char | |||
247 | { | 247 | { |
248 | struct sk_buff *skb; | 248 | struct sk_buff *skb; |
249 | 249 | ||
250 | BT_DBG("session %p hid %p data %p size %d", session, device, data, size); | 250 | BT_DBG("session %p hid %p data %p size %d", session, session->hid, data, size); |
251 | 251 | ||
252 | if (!(skb = alloc_skb(size + 1, GFP_ATOMIC))) { | 252 | if (!(skb = alloc_skb(size + 1, GFP_ATOMIC))) { |
253 | BT_ERR("Can't allocate memory for new frame"); | 253 | BT_ERR("Can't allocate memory for new frame"); |
@@ -656,11 +656,13 @@ static inline int hidp_setup_input(struct hidp_session *session, struct hidp_con | |||
656 | } | 656 | } |
657 | 657 | ||
658 | if (req->subclass & 0x80) { | 658 | if (req->subclass & 0x80) { |
659 | input->evbit[0] = BIT(EV_KEY) | BIT(EV_REL); | 659 | input->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REL); |
660 | input->keybit[LONG(BTN_MOUSE)] = BIT(BTN_LEFT) | BIT(BTN_RIGHT) | BIT(BTN_MIDDLE); | 660 | input->keybit[BIT_WORD(BTN_MOUSE)] = BIT_MASK(BTN_LEFT) | |
661 | input->relbit[0] = BIT(REL_X) | BIT(REL_Y); | 661 | BIT_MASK(BTN_RIGHT) | BIT_MASK(BTN_MIDDLE); |
662 | input->keybit[LONG(BTN_MOUSE)] |= BIT(BTN_SIDE) | BIT(BTN_EXTRA); | 662 | input->relbit[0] = BIT_MASK(REL_X) | BIT_MASK(REL_Y); |
663 | input->relbit[0] |= BIT(REL_WHEEL); | 663 | input->keybit[BIT_WORD(BTN_MOUSE)] |= BIT_MASK(BTN_SIDE) | |
664 | BIT_MASK(BTN_EXTRA); | ||
665 | input->relbit[0] |= BIT_MASK(REL_WHEEL); | ||
664 | } | 666 | } |
665 | 667 | ||
666 | input->dev.parent = hidp_get_device(session); | 668 | input->dev.parent = hidp_get_device(session); |
diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c index 36ef27b625db..6fbbae78b304 100644 --- a/net/bluetooth/l2cap.c +++ b/net/bluetooth/l2cap.c | |||
@@ -55,7 +55,9 @@ | |||
55 | #define BT_DBG(D...) | 55 | #define BT_DBG(D...) |
56 | #endif | 56 | #endif |
57 | 57 | ||
58 | #define VERSION "2.8" | 58 | #define VERSION "2.9" |
59 | |||
60 | static u32 l2cap_feat_mask = 0x0000; | ||
59 | 61 | ||
60 | static const struct proto_ops l2cap_sock_ops; | 62 | static const struct proto_ops l2cap_sock_ops; |
61 | 63 | ||
@@ -258,7 +260,119 @@ static void l2cap_chan_del(struct sock *sk, int err) | |||
258 | sk->sk_state_change(sk); | 260 | sk->sk_state_change(sk); |
259 | } | 261 | } |
260 | 262 | ||
263 | static inline u8 l2cap_get_ident(struct l2cap_conn *conn) | ||
264 | { | ||
265 | u8 id; | ||
266 | |||
267 | /* Get next available identificator. | ||
268 | * 1 - 128 are used by kernel. | ||
269 | * 129 - 199 are reserved. | ||
270 | * 200 - 254 are used by utilities like l2ping, etc. | ||
271 | */ | ||
272 | |||
273 | spin_lock_bh(&conn->lock); | ||
274 | |||
275 | if (++conn->tx_ident > 128) | ||
276 | conn->tx_ident = 1; | ||
277 | |||
278 | id = conn->tx_ident; | ||
279 | |||
280 | spin_unlock_bh(&conn->lock); | ||
281 | |||
282 | return id; | ||
283 | } | ||
284 | |||
285 | static inline int l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len, void *data) | ||
286 | { | ||
287 | struct sk_buff *skb = l2cap_build_cmd(conn, code, ident, len, data); | ||
288 | |||
289 | BT_DBG("code 0x%2.2x", code); | ||
290 | |||
291 | if (!skb) | ||
292 | return -ENOMEM; | ||
293 | |||
294 | return hci_send_acl(conn->hcon, skb, 0); | ||
295 | } | ||
296 | |||
261 | /* ---- L2CAP connections ---- */ | 297 | /* ---- L2CAP connections ---- */ |
298 | static void l2cap_conn_start(struct l2cap_conn *conn) | ||
299 | { | ||
300 | struct l2cap_chan_list *l = &conn->chan_list; | ||
301 | struct sock *sk; | ||
302 | |||
303 | BT_DBG("conn %p", conn); | ||
304 | |||
305 | read_lock(&l->lock); | ||
306 | |||
307 | for (sk = l->head; sk; sk = l2cap_pi(sk)->next_c) { | ||
308 | bh_lock_sock(sk); | ||
309 | |||
310 | if (sk->sk_type != SOCK_SEQPACKET) { | ||
311 | l2cap_sock_clear_timer(sk); | ||
312 | sk->sk_state = BT_CONNECTED; | ||
313 | sk->sk_state_change(sk); | ||
314 | } else if (sk->sk_state == BT_CONNECT) { | ||
315 | struct l2cap_conn_req req; | ||
316 | l2cap_pi(sk)->ident = l2cap_get_ident(conn); | ||
317 | req.scid = cpu_to_le16(l2cap_pi(sk)->scid); | ||
318 | req.psm = l2cap_pi(sk)->psm; | ||
319 | l2cap_send_cmd(conn, l2cap_pi(sk)->ident, | ||
320 | L2CAP_CONN_REQ, sizeof(req), &req); | ||
321 | } | ||
322 | |||
323 | bh_unlock_sock(sk); | ||
324 | } | ||
325 | |||
326 | read_unlock(&l->lock); | ||
327 | } | ||
328 | |||
329 | static void l2cap_conn_ready(struct l2cap_conn *conn) | ||
330 | { | ||
331 | BT_DBG("conn %p", conn); | ||
332 | |||
333 | if (conn->chan_list.head || !hlist_empty(&l2cap_sk_list.head)) { | ||
334 | struct l2cap_info_req req; | ||
335 | |||
336 | req.type = cpu_to_le16(L2CAP_IT_FEAT_MASK); | ||
337 | |||
338 | conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT; | ||
339 | conn->info_ident = l2cap_get_ident(conn); | ||
340 | |||
341 | mod_timer(&conn->info_timer, | ||
342 | jiffies + msecs_to_jiffies(L2CAP_INFO_TIMEOUT)); | ||
343 | |||
344 | l2cap_send_cmd(conn, conn->info_ident, | ||
345 | L2CAP_INFO_REQ, sizeof(req), &req); | ||
346 | } | ||
347 | } | ||
348 | |||
349 | /* Notify sockets that we cannot guaranty reliability anymore */ | ||
350 | static void l2cap_conn_unreliable(struct l2cap_conn *conn, int err) | ||
351 | { | ||
352 | struct l2cap_chan_list *l = &conn->chan_list; | ||
353 | struct sock *sk; | ||
354 | |||
355 | BT_DBG("conn %p", conn); | ||
356 | |||
357 | read_lock(&l->lock); | ||
358 | |||
359 | for (sk = l->head; sk; sk = l2cap_pi(sk)->next_c) { | ||
360 | if (l2cap_pi(sk)->link_mode & L2CAP_LM_RELIABLE) | ||
361 | sk->sk_err = err; | ||
362 | } | ||
363 | |||
364 | read_unlock(&l->lock); | ||
365 | } | ||
366 | |||
367 | static void l2cap_info_timeout(unsigned long arg) | ||
368 | { | ||
369 | struct l2cap_conn *conn = (void *) arg; | ||
370 | |||
371 | conn->info_ident = 0; | ||
372 | |||
373 | l2cap_conn_start(conn); | ||
374 | } | ||
375 | |||
262 | static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon, u8 status) | 376 | static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon, u8 status) |
263 | { | 377 | { |
264 | struct l2cap_conn *conn = hcon->l2cap_data; | 378 | struct l2cap_conn *conn = hcon->l2cap_data; |
@@ -279,6 +393,12 @@ static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon, u8 status) | |||
279 | conn->src = &hcon->hdev->bdaddr; | 393 | conn->src = &hcon->hdev->bdaddr; |
280 | conn->dst = &hcon->dst; | 394 | conn->dst = &hcon->dst; |
281 | 395 | ||
396 | conn->feat_mask = 0; | ||
397 | |||
398 | init_timer(&conn->info_timer); | ||
399 | conn->info_timer.function = l2cap_info_timeout; | ||
400 | conn->info_timer.data = (unsigned long) conn; | ||
401 | |||
282 | spin_lock_init(&conn->lock); | 402 | spin_lock_init(&conn->lock); |
283 | rwlock_init(&conn->chan_list.lock); | 403 | rwlock_init(&conn->chan_list.lock); |
284 | 404 | ||
@@ -318,40 +438,6 @@ static inline void l2cap_chan_add(struct l2cap_conn *conn, struct sock *sk, stru | |||
318 | write_unlock_bh(&l->lock); | 438 | write_unlock_bh(&l->lock); |
319 | } | 439 | } |
320 | 440 | ||
321 | static inline u8 l2cap_get_ident(struct l2cap_conn *conn) | ||
322 | { | ||
323 | u8 id; | ||
324 | |||
325 | /* Get next available identificator. | ||
326 | * 1 - 128 are used by kernel. | ||
327 | * 129 - 199 are reserved. | ||
328 | * 200 - 254 are used by utilities like l2ping, etc. | ||
329 | */ | ||
330 | |||
331 | spin_lock_bh(&conn->lock); | ||
332 | |||
333 | if (++conn->tx_ident > 128) | ||
334 | conn->tx_ident = 1; | ||
335 | |||
336 | id = conn->tx_ident; | ||
337 | |||
338 | spin_unlock_bh(&conn->lock); | ||
339 | |||
340 | return id; | ||
341 | } | ||
342 | |||
343 | static inline int l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len, void *data) | ||
344 | { | ||
345 | struct sk_buff *skb = l2cap_build_cmd(conn, code, ident, len, data); | ||
346 | |||
347 | BT_DBG("code 0x%2.2x", code); | ||
348 | |||
349 | if (!skb) | ||
350 | return -ENOMEM; | ||
351 | |||
352 | return hci_send_acl(conn->hcon, skb, 0); | ||
353 | } | ||
354 | |||
355 | /* ---- Socket interface ---- */ | 441 | /* ---- Socket interface ---- */ |
356 | static struct sock *__l2cap_get_sock_by_addr(__le16 psm, bdaddr_t *src) | 442 | static struct sock *__l2cap_get_sock_by_addr(__le16 psm, bdaddr_t *src) |
357 | { | 443 | { |
@@ -508,7 +594,6 @@ static void l2cap_sock_init(struct sock *sk, struct sock *parent) | |||
508 | 594 | ||
509 | /* Default config options */ | 595 | /* Default config options */ |
510 | pi->conf_len = 0; | 596 | pi->conf_len = 0; |
511 | pi->conf_mtu = L2CAP_DEFAULT_MTU; | ||
512 | pi->flush_to = L2CAP_DEFAULT_FLUSH_TO; | 597 | pi->flush_to = L2CAP_DEFAULT_FLUSH_TO; |
513 | } | 598 | } |
514 | 599 | ||
@@ -530,7 +615,7 @@ static struct sock *l2cap_sock_alloc(struct net *net, struct socket *sock, int p | |||
530 | INIT_LIST_HEAD(&bt_sk(sk)->accept_q); | 615 | INIT_LIST_HEAD(&bt_sk(sk)->accept_q); |
531 | 616 | ||
532 | sk->sk_destruct = l2cap_sock_destruct; | 617 | sk->sk_destruct = l2cap_sock_destruct; |
533 | sk->sk_sndtimeo = L2CAP_CONN_TIMEOUT; | 618 | sk->sk_sndtimeo = msecs_to_jiffies(L2CAP_CONN_TIMEOUT); |
534 | 619 | ||
535 | sock_reset_flag(sk, SOCK_ZAPPED); | 620 | sock_reset_flag(sk, SOCK_ZAPPED); |
536 | 621 | ||
@@ -650,6 +735,11 @@ static int l2cap_do_connect(struct sock *sk) | |||
650 | l2cap_sock_set_timer(sk, sk->sk_sndtimeo); | 735 | l2cap_sock_set_timer(sk, sk->sk_sndtimeo); |
651 | 736 | ||
652 | if (hcon->state == BT_CONNECTED) { | 737 | if (hcon->state == BT_CONNECTED) { |
738 | if (!(conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT)) { | ||
739 | l2cap_conn_ready(conn); | ||
740 | goto done; | ||
741 | } | ||
742 | |||
653 | if (sk->sk_type == SOCK_SEQPACKET) { | 743 | if (sk->sk_type == SOCK_SEQPACKET) { |
654 | struct l2cap_conn_req req; | 744 | struct l2cap_conn_req req; |
655 | l2cap_pi(sk)->ident = l2cap_get_ident(conn); | 745 | l2cap_pi(sk)->ident = l2cap_get_ident(conn); |
@@ -958,7 +1048,7 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, ch | |||
958 | opts.imtu = l2cap_pi(sk)->imtu; | 1048 | opts.imtu = l2cap_pi(sk)->imtu; |
959 | opts.omtu = l2cap_pi(sk)->omtu; | 1049 | opts.omtu = l2cap_pi(sk)->omtu; |
960 | opts.flush_to = l2cap_pi(sk)->flush_to; | 1050 | opts.flush_to = l2cap_pi(sk)->flush_to; |
961 | opts.mode = 0x00; | 1051 | opts.mode = L2CAP_MODE_BASIC; |
962 | 1052 | ||
963 | len = min_t(unsigned int, sizeof(opts), optlen); | 1053 | len = min_t(unsigned int, sizeof(opts), optlen); |
964 | if (copy_from_user((char *) &opts, optval, len)) { | 1054 | if (copy_from_user((char *) &opts, optval, len)) { |
@@ -1007,7 +1097,7 @@ static int l2cap_sock_getsockopt(struct socket *sock, int level, int optname, ch | |||
1007 | opts.imtu = l2cap_pi(sk)->imtu; | 1097 | opts.imtu = l2cap_pi(sk)->imtu; |
1008 | opts.omtu = l2cap_pi(sk)->omtu; | 1098 | opts.omtu = l2cap_pi(sk)->omtu; |
1009 | opts.flush_to = l2cap_pi(sk)->flush_to; | 1099 | opts.flush_to = l2cap_pi(sk)->flush_to; |
1010 | opts.mode = 0x00; | 1100 | opts.mode = L2CAP_MODE_BASIC; |
1011 | 1101 | ||
1012 | len = min_t(unsigned int, len, sizeof(opts)); | 1102 | len = min_t(unsigned int, len, sizeof(opts)); |
1013 | if (copy_to_user(optval, (char *) &opts, len)) | 1103 | if (copy_to_user(optval, (char *) &opts, len)) |
@@ -1084,52 +1174,6 @@ static int l2cap_sock_release(struct socket *sock) | |||
1084 | return err; | 1174 | return err; |
1085 | } | 1175 | } |
1086 | 1176 | ||
1087 | static void l2cap_conn_ready(struct l2cap_conn *conn) | ||
1088 | { | ||
1089 | struct l2cap_chan_list *l = &conn->chan_list; | ||
1090 | struct sock *sk; | ||
1091 | |||
1092 | BT_DBG("conn %p", conn); | ||
1093 | |||
1094 | read_lock(&l->lock); | ||
1095 | |||
1096 | for (sk = l->head; sk; sk = l2cap_pi(sk)->next_c) { | ||
1097 | bh_lock_sock(sk); | ||
1098 | |||
1099 | if (sk->sk_type != SOCK_SEQPACKET) { | ||
1100 | l2cap_sock_clear_timer(sk); | ||
1101 | sk->sk_state = BT_CONNECTED; | ||
1102 | sk->sk_state_change(sk); | ||
1103 | } else if (sk->sk_state == BT_CONNECT) { | ||
1104 | struct l2cap_conn_req req; | ||
1105 | l2cap_pi(sk)->ident = l2cap_get_ident(conn); | ||
1106 | req.scid = cpu_to_le16(l2cap_pi(sk)->scid); | ||
1107 | req.psm = l2cap_pi(sk)->psm; | ||
1108 | l2cap_send_cmd(conn, l2cap_pi(sk)->ident, L2CAP_CONN_REQ, sizeof(req), &req); | ||
1109 | } | ||
1110 | |||
1111 | bh_unlock_sock(sk); | ||
1112 | } | ||
1113 | |||
1114 | read_unlock(&l->lock); | ||
1115 | } | ||
1116 | |||
1117 | /* Notify sockets that we cannot guaranty reliability anymore */ | ||
1118 | static void l2cap_conn_unreliable(struct l2cap_conn *conn, int err) | ||
1119 | { | ||
1120 | struct l2cap_chan_list *l = &conn->chan_list; | ||
1121 | struct sock *sk; | ||
1122 | |||
1123 | BT_DBG("conn %p", conn); | ||
1124 | |||
1125 | read_lock(&l->lock); | ||
1126 | for (sk = l->head; sk; sk = l2cap_pi(sk)->next_c) { | ||
1127 | if (l2cap_pi(sk)->link_mode & L2CAP_LM_RELIABLE) | ||
1128 | sk->sk_err = err; | ||
1129 | } | ||
1130 | read_unlock(&l->lock); | ||
1131 | } | ||
1132 | |||
1133 | static void l2cap_chan_ready(struct sock *sk) | 1177 | static void l2cap_chan_ready(struct sock *sk) |
1134 | { | 1178 | { |
1135 | struct sock *parent = bt_sk(sk)->parent; | 1179 | struct sock *parent = bt_sk(sk)->parent; |
@@ -1256,11 +1300,11 @@ static inline int l2cap_get_conf_opt(void **ptr, int *type, int *olen, unsigned | |||
1256 | break; | 1300 | break; |
1257 | 1301 | ||
1258 | case 2: | 1302 | case 2: |
1259 | *val = __le16_to_cpu(*((__le16 *)opt->val)); | 1303 | *val = __le16_to_cpu(*((__le16 *) opt->val)); |
1260 | break; | 1304 | break; |
1261 | 1305 | ||
1262 | case 4: | 1306 | case 4: |
1263 | *val = __le32_to_cpu(*((__le32 *)opt->val)); | 1307 | *val = __le32_to_cpu(*((__le32 *) opt->val)); |
1264 | break; | 1308 | break; |
1265 | 1309 | ||
1266 | default: | 1310 | default: |
@@ -1332,6 +1376,8 @@ static int l2cap_parse_conf_req(struct sock *sk, void *data) | |||
1332 | int len = pi->conf_len; | 1376 | int len = pi->conf_len; |
1333 | int type, hint, olen; | 1377 | int type, hint, olen; |
1334 | unsigned long val; | 1378 | unsigned long val; |
1379 | struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC }; | ||
1380 | u16 mtu = L2CAP_DEFAULT_MTU; | ||
1335 | u16 result = L2CAP_CONF_SUCCESS; | 1381 | u16 result = L2CAP_CONF_SUCCESS; |
1336 | 1382 | ||
1337 | BT_DBG("sk %p", sk); | 1383 | BT_DBG("sk %p", sk); |
@@ -1344,7 +1390,7 @@ static int l2cap_parse_conf_req(struct sock *sk, void *data) | |||
1344 | 1390 | ||
1345 | switch (type) { | 1391 | switch (type) { |
1346 | case L2CAP_CONF_MTU: | 1392 | case L2CAP_CONF_MTU: |
1347 | pi->conf_mtu = val; | 1393 | mtu = val; |
1348 | break; | 1394 | break; |
1349 | 1395 | ||
1350 | case L2CAP_CONF_FLUSH_TO: | 1396 | case L2CAP_CONF_FLUSH_TO: |
@@ -1354,6 +1400,11 @@ static int l2cap_parse_conf_req(struct sock *sk, void *data) | |||
1354 | case L2CAP_CONF_QOS: | 1400 | case L2CAP_CONF_QOS: |
1355 | break; | 1401 | break; |
1356 | 1402 | ||
1403 | case L2CAP_CONF_RFC: | ||
1404 | if (olen == sizeof(rfc)) | ||
1405 | memcpy(&rfc, (void *) val, olen); | ||
1406 | break; | ||
1407 | |||
1357 | default: | 1408 | default: |
1358 | if (hint) | 1409 | if (hint) |
1359 | break; | 1410 | break; |
@@ -1368,12 +1419,24 @@ static int l2cap_parse_conf_req(struct sock *sk, void *data) | |||
1368 | /* Configure output options and let the other side know | 1419 | /* Configure output options and let the other side know |
1369 | * which ones we don't like. */ | 1420 | * which ones we don't like. */ |
1370 | 1421 | ||
1371 | if (pi->conf_mtu < pi->omtu) | 1422 | if (rfc.mode == L2CAP_MODE_BASIC) { |
1423 | if (mtu < pi->omtu) | ||
1424 | result = L2CAP_CONF_UNACCEPT; | ||
1425 | else { | ||
1426 | pi->omtu = mtu; | ||
1427 | pi->conf_state |= L2CAP_CONF_OUTPUT_DONE; | ||
1428 | } | ||
1429 | |||
1430 | l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, pi->omtu); | ||
1431 | } else { | ||
1372 | result = L2CAP_CONF_UNACCEPT; | 1432 | result = L2CAP_CONF_UNACCEPT; |
1373 | else | ||
1374 | pi->omtu = pi->conf_mtu; | ||
1375 | 1433 | ||
1376 | l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, pi->omtu); | 1434 | memset(&rfc, 0, sizeof(rfc)); |
1435 | rfc.mode = L2CAP_MODE_BASIC; | ||
1436 | |||
1437 | l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, | ||
1438 | sizeof(rfc), (unsigned long) &rfc); | ||
1439 | } | ||
1377 | } | 1440 | } |
1378 | 1441 | ||
1379 | rsp->scid = cpu_to_le16(pi->dcid); | 1442 | rsp->scid = cpu_to_le16(pi->dcid); |
@@ -1397,6 +1460,23 @@ static int l2cap_build_conf_rsp(struct sock *sk, void *data, u16 result, u16 fla | |||
1397 | return ptr - data; | 1460 | return ptr - data; |
1398 | } | 1461 | } |
1399 | 1462 | ||
1463 | static inline int l2cap_command_rej(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data) | ||
1464 | { | ||
1465 | struct l2cap_cmd_rej *rej = (struct l2cap_cmd_rej *) data; | ||
1466 | |||
1467 | if (rej->reason != 0x0000) | ||
1468 | return 0; | ||
1469 | |||
1470 | if ((conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) && | ||
1471 | cmd->ident == conn->info_ident) { | ||
1472 | conn->info_ident = 0; | ||
1473 | del_timer(&conn->info_timer); | ||
1474 | l2cap_conn_start(conn); | ||
1475 | } | ||
1476 | |||
1477 | return 0; | ||
1478 | } | ||
1479 | |||
1400 | static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data) | 1480 | static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data) |
1401 | { | 1481 | { |
1402 | struct l2cap_chan_list *list = &conn->chan_list; | 1482 | struct l2cap_chan_list *list = &conn->chan_list; |
@@ -1577,16 +1657,19 @@ static inline int l2cap_config_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr | |||
1577 | 1657 | ||
1578 | l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, len, rsp); | 1658 | l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, len, rsp); |
1579 | 1659 | ||
1580 | /* Output config done. */ | ||
1581 | l2cap_pi(sk)->conf_state |= L2CAP_CONF_OUTPUT_DONE; | ||
1582 | |||
1583 | /* Reset config buffer. */ | 1660 | /* Reset config buffer. */ |
1584 | l2cap_pi(sk)->conf_len = 0; | 1661 | l2cap_pi(sk)->conf_len = 0; |
1585 | 1662 | ||
1663 | if (!(l2cap_pi(sk)->conf_state & L2CAP_CONF_OUTPUT_DONE)) | ||
1664 | goto unlock; | ||
1665 | |||
1586 | if (l2cap_pi(sk)->conf_state & L2CAP_CONF_INPUT_DONE) { | 1666 | if (l2cap_pi(sk)->conf_state & L2CAP_CONF_INPUT_DONE) { |
1587 | sk->sk_state = BT_CONNECTED; | 1667 | sk->sk_state = BT_CONNECTED; |
1588 | l2cap_chan_ready(sk); | 1668 | l2cap_chan_ready(sk); |
1589 | } else if (!(l2cap_pi(sk)->conf_state & L2CAP_CONF_REQ_SENT)) { | 1669 | goto unlock; |
1670 | } | ||
1671 | |||
1672 | if (!(l2cap_pi(sk)->conf_state & L2CAP_CONF_REQ_SENT)) { | ||
1590 | u8 req[64]; | 1673 | u8 req[64]; |
1591 | l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ, | 1674 | l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ, |
1592 | l2cap_build_conf_req(sk, req), req); | 1675 | l2cap_build_conf_req(sk, req), req); |
@@ -1646,7 +1729,6 @@ static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr | |||
1646 | if (flags & 0x01) | 1729 | if (flags & 0x01) |
1647 | goto done; | 1730 | goto done; |
1648 | 1731 | ||
1649 | /* Input config done */ | ||
1650 | l2cap_pi(sk)->conf_state |= L2CAP_CONF_INPUT_DONE; | 1732 | l2cap_pi(sk)->conf_state |= L2CAP_CONF_INPUT_DONE; |
1651 | 1733 | ||
1652 | if (l2cap_pi(sk)->conf_state & L2CAP_CONF_OUTPUT_DONE) { | 1734 | if (l2cap_pi(sk)->conf_state & L2CAP_CONF_OUTPUT_DONE) { |
@@ -1711,16 +1793,27 @@ static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, struct l2cap_cmd | |||
1711 | static inline int l2cap_information_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data) | 1793 | static inline int l2cap_information_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data) |
1712 | { | 1794 | { |
1713 | struct l2cap_info_req *req = (struct l2cap_info_req *) data; | 1795 | struct l2cap_info_req *req = (struct l2cap_info_req *) data; |
1714 | struct l2cap_info_rsp rsp; | ||
1715 | u16 type; | 1796 | u16 type; |
1716 | 1797 | ||
1717 | type = __le16_to_cpu(req->type); | 1798 | type = __le16_to_cpu(req->type); |
1718 | 1799 | ||
1719 | BT_DBG("type 0x%4.4x", type); | 1800 | BT_DBG("type 0x%4.4x", type); |
1720 | 1801 | ||
1721 | rsp.type = cpu_to_le16(type); | 1802 | if (type == L2CAP_IT_FEAT_MASK) { |
1722 | rsp.result = cpu_to_le16(L2CAP_IR_NOTSUPP); | 1803 | u8 buf[8]; |
1723 | l2cap_send_cmd(conn, cmd->ident, L2CAP_INFO_RSP, sizeof(rsp), &rsp); | 1804 | struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf; |
1805 | rsp->type = cpu_to_le16(L2CAP_IT_FEAT_MASK); | ||
1806 | rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS); | ||
1807 | put_unaligned(cpu_to_le32(l2cap_feat_mask), (__le32 *) rsp->data); | ||
1808 | l2cap_send_cmd(conn, cmd->ident, | ||
1809 | L2CAP_INFO_RSP, sizeof(buf), buf); | ||
1810 | } else { | ||
1811 | struct l2cap_info_rsp rsp; | ||
1812 | rsp.type = cpu_to_le16(type); | ||
1813 | rsp.result = cpu_to_le16(L2CAP_IR_NOTSUPP); | ||
1814 | l2cap_send_cmd(conn, cmd->ident, | ||
1815 | L2CAP_INFO_RSP, sizeof(rsp), &rsp); | ||
1816 | } | ||
1724 | 1817 | ||
1725 | return 0; | 1818 | return 0; |
1726 | } | 1819 | } |
@@ -1735,6 +1828,15 @@ static inline int l2cap_information_rsp(struct l2cap_conn *conn, struct l2cap_cm | |||
1735 | 1828 | ||
1736 | BT_DBG("type 0x%4.4x result 0x%2.2x", type, result); | 1829 | BT_DBG("type 0x%4.4x result 0x%2.2x", type, result); |
1737 | 1830 | ||
1831 | conn->info_ident = 0; | ||
1832 | |||
1833 | del_timer(&conn->info_timer); | ||
1834 | |||
1835 | if (type == L2CAP_IT_FEAT_MASK) | ||
1836 | conn->feat_mask = __le32_to_cpu(get_unaligned((__le32 *) rsp->data)); | ||
1837 | |||
1838 | l2cap_conn_start(conn); | ||
1839 | |||
1738 | return 0; | 1840 | return 0; |
1739 | } | 1841 | } |
1740 | 1842 | ||
@@ -1764,7 +1866,7 @@ static inline void l2cap_sig_channel(struct l2cap_conn *conn, struct sk_buff *sk | |||
1764 | 1866 | ||
1765 | switch (cmd.code) { | 1867 | switch (cmd.code) { |
1766 | case L2CAP_COMMAND_REJ: | 1868 | case L2CAP_COMMAND_REJ: |
1767 | /* FIXME: We should process this */ | 1869 | l2cap_command_rej(conn, &cmd, data); |
1768 | break; | 1870 | break; |
1769 | 1871 | ||
1770 | case L2CAP_CONN_REQ: | 1872 | case L2CAP_CONN_REQ: |
diff --git a/net/bluetooth/rfcomm/core.c b/net/bluetooth/rfcomm/core.c index bb7220770f2c..e7ac6ba7ecab 100644 --- a/net/bluetooth/rfcomm/core.c +++ b/net/bluetooth/rfcomm/core.c | |||
@@ -33,11 +33,11 @@ | |||
33 | #include <linux/sched.h> | 33 | #include <linux/sched.h> |
34 | #include <linux/signal.h> | 34 | #include <linux/signal.h> |
35 | #include <linux/init.h> | 35 | #include <linux/init.h> |
36 | #include <linux/freezer.h> | ||
37 | #include <linux/wait.h> | 36 | #include <linux/wait.h> |
38 | #include <linux/device.h> | 37 | #include <linux/device.h> |
39 | #include <linux/net.h> | 38 | #include <linux/net.h> |
40 | #include <linux/mutex.h> | 39 | #include <linux/mutex.h> |
40 | #include <linux/kthread.h> | ||
41 | 41 | ||
42 | #include <net/sock.h> | 42 | #include <net/sock.h> |
43 | #include <asm/uaccess.h> | 43 | #include <asm/uaccess.h> |
@@ -68,7 +68,6 @@ static DEFINE_MUTEX(rfcomm_mutex); | |||
68 | static unsigned long rfcomm_event; | 68 | static unsigned long rfcomm_event; |
69 | 69 | ||
70 | static LIST_HEAD(session_list); | 70 | static LIST_HEAD(session_list); |
71 | static atomic_t terminate, running; | ||
72 | 71 | ||
73 | static int rfcomm_send_frame(struct rfcomm_session *s, u8 *data, int len); | 72 | static int rfcomm_send_frame(struct rfcomm_session *s, u8 *data, int len); |
74 | static int rfcomm_send_sabm(struct rfcomm_session *s, u8 dlci); | 73 | static int rfcomm_send_sabm(struct rfcomm_session *s, u8 dlci); |
@@ -1850,26 +1849,6 @@ static inline void rfcomm_process_sessions(void) | |||
1850 | rfcomm_unlock(); | 1849 | rfcomm_unlock(); |
1851 | } | 1850 | } |
1852 | 1851 | ||
1853 | static void rfcomm_worker(void) | ||
1854 | { | ||
1855 | BT_DBG(""); | ||
1856 | |||
1857 | while (!atomic_read(&terminate)) { | ||
1858 | set_current_state(TASK_INTERRUPTIBLE); | ||
1859 | if (!test_bit(RFCOMM_SCHED_WAKEUP, &rfcomm_event)) { | ||
1860 | /* No pending events. Let's sleep. | ||
1861 | * Incoming connections and data will wake us up. */ | ||
1862 | schedule(); | ||
1863 | } | ||
1864 | set_current_state(TASK_RUNNING); | ||
1865 | |||
1866 | /* Process stuff */ | ||
1867 | clear_bit(RFCOMM_SCHED_WAKEUP, &rfcomm_event); | ||
1868 | rfcomm_process_sessions(); | ||
1869 | } | ||
1870 | return; | ||
1871 | } | ||
1872 | |||
1873 | static int rfcomm_add_listener(bdaddr_t *ba) | 1852 | static int rfcomm_add_listener(bdaddr_t *ba) |
1874 | { | 1853 | { |
1875 | struct sockaddr_l2 addr; | 1854 | struct sockaddr_l2 addr; |
@@ -1935,22 +1914,28 @@ static void rfcomm_kill_listener(void) | |||
1935 | 1914 | ||
1936 | static int rfcomm_run(void *unused) | 1915 | static int rfcomm_run(void *unused) |
1937 | { | 1916 | { |
1938 | rfcomm_thread = current; | 1917 | BT_DBG(""); |
1939 | |||
1940 | atomic_inc(&running); | ||
1941 | 1918 | ||
1942 | daemonize("krfcommd"); | ||
1943 | set_user_nice(current, -10); | 1919 | set_user_nice(current, -10); |
1944 | 1920 | ||
1945 | BT_DBG(""); | ||
1946 | |||
1947 | rfcomm_add_listener(BDADDR_ANY); | 1921 | rfcomm_add_listener(BDADDR_ANY); |
1948 | 1922 | ||
1949 | rfcomm_worker(); | 1923 | while (!kthread_should_stop()) { |
1924 | set_current_state(TASK_INTERRUPTIBLE); | ||
1925 | if (!test_bit(RFCOMM_SCHED_WAKEUP, &rfcomm_event)) { | ||
1926 | /* No pending events. Let's sleep. | ||
1927 | * Incoming connections and data will wake us up. */ | ||
1928 | schedule(); | ||
1929 | } | ||
1930 | set_current_state(TASK_RUNNING); | ||
1931 | |||
1932 | /* Process stuff */ | ||
1933 | clear_bit(RFCOMM_SCHED_WAKEUP, &rfcomm_event); | ||
1934 | rfcomm_process_sessions(); | ||
1935 | } | ||
1950 | 1936 | ||
1951 | rfcomm_kill_listener(); | 1937 | rfcomm_kill_listener(); |
1952 | 1938 | ||
1953 | atomic_dec(&running); | ||
1954 | return 0; | 1939 | return 0; |
1955 | } | 1940 | } |
1956 | 1941 | ||
@@ -2059,7 +2044,11 @@ static int __init rfcomm_init(void) | |||
2059 | 2044 | ||
2060 | hci_register_cb(&rfcomm_cb); | 2045 | hci_register_cb(&rfcomm_cb); |
2061 | 2046 | ||
2062 | kernel_thread(rfcomm_run, NULL, CLONE_KERNEL); | 2047 | rfcomm_thread = kthread_run(rfcomm_run, NULL, "krfcommd"); |
2048 | if (IS_ERR(rfcomm_thread)) { | ||
2049 | hci_unregister_cb(&rfcomm_cb); | ||
2050 | return PTR_ERR(rfcomm_thread); | ||
2051 | } | ||
2063 | 2052 | ||
2064 | if (class_create_file(bt_class, &class_attr_rfcomm_dlc) < 0) | 2053 | if (class_create_file(bt_class, &class_attr_rfcomm_dlc) < 0) |
2065 | BT_ERR("Failed to create RFCOMM info file"); | 2054 | BT_ERR("Failed to create RFCOMM info file"); |
@@ -2081,14 +2070,7 @@ static void __exit rfcomm_exit(void) | |||
2081 | 2070 | ||
2082 | hci_unregister_cb(&rfcomm_cb); | 2071 | hci_unregister_cb(&rfcomm_cb); |
2083 | 2072 | ||
2084 | /* Terminate working thread. | 2073 | kthread_stop(rfcomm_thread); |
2085 | * ie. Set terminate flag and wake it up */ | ||
2086 | atomic_inc(&terminate); | ||
2087 | rfcomm_schedule(RFCOMM_SCHED_STATE); | ||
2088 | |||
2089 | /* Wait until thread is running */ | ||
2090 | while (atomic_read(&running)) | ||
2091 | schedule(); | ||
2092 | 2074 | ||
2093 | #ifdef CONFIG_BT_RFCOMM_TTY | 2075 | #ifdef CONFIG_BT_RFCOMM_TTY |
2094 | rfcomm_cleanup_ttys(); | 2076 | rfcomm_cleanup_ttys(); |
diff --git a/net/bluetooth/rfcomm/tty.c b/net/bluetooth/rfcomm/tty.c index 22a832098d44..e447651a2dbe 100644 --- a/net/bluetooth/rfcomm/tty.c +++ b/net/bluetooth/rfcomm/tty.c | |||
@@ -189,6 +189,23 @@ static struct device *rfcomm_get_device(struct rfcomm_dev *dev) | |||
189 | return conn ? &conn->dev : NULL; | 189 | return conn ? &conn->dev : NULL; |
190 | } | 190 | } |
191 | 191 | ||
192 | static ssize_t show_address(struct device *tty_dev, struct device_attribute *attr, char *buf) | ||
193 | { | ||
194 | struct rfcomm_dev *dev = dev_get_drvdata(tty_dev); | ||
195 | bdaddr_t bdaddr; | ||
196 | baswap(&bdaddr, &dev->dst); | ||
197 | return sprintf(buf, "%s\n", batostr(&bdaddr)); | ||
198 | } | ||
199 | |||
200 | static ssize_t show_channel(struct device *tty_dev, struct device_attribute *attr, char *buf) | ||
201 | { | ||
202 | struct rfcomm_dev *dev = dev_get_drvdata(tty_dev); | ||
203 | return sprintf(buf, "%d\n", dev->channel); | ||
204 | } | ||
205 | |||
206 | static DEVICE_ATTR(address, S_IRUGO, show_address, NULL); | ||
207 | static DEVICE_ATTR(channel, S_IRUGO, show_channel, NULL); | ||
208 | |||
192 | static int rfcomm_dev_add(struct rfcomm_dev_req *req, struct rfcomm_dlc *dlc) | 209 | static int rfcomm_dev_add(struct rfcomm_dev_req *req, struct rfcomm_dlc *dlc) |
193 | { | 210 | { |
194 | struct rfcomm_dev *dev; | 211 | struct rfcomm_dev *dev; |
@@ -281,6 +298,14 @@ out: | |||
281 | return err; | 298 | return err; |
282 | } | 299 | } |
283 | 300 | ||
301 | dev_set_drvdata(dev->tty_dev, dev); | ||
302 | |||
303 | if (device_create_file(dev->tty_dev, &dev_attr_address) < 0) | ||
304 | BT_ERR("Failed to create address attribute"); | ||
305 | |||
306 | if (device_create_file(dev->tty_dev, &dev_attr_channel) < 0) | ||
307 | BT_ERR("Failed to create channel attribute"); | ||
308 | |||
284 | return dev->id; | 309 | return dev->id; |
285 | } | 310 | } |
286 | 311 | ||
diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c index 65b6fb1c4154..82d0dfdfa7e2 100644 --- a/net/bluetooth/sco.c +++ b/net/bluetooth/sco.c | |||
@@ -189,7 +189,7 @@ static int sco_connect(struct sock *sk) | |||
189 | struct sco_conn *conn; | 189 | struct sco_conn *conn; |
190 | struct hci_conn *hcon; | 190 | struct hci_conn *hcon; |
191 | struct hci_dev *hdev; | 191 | struct hci_dev *hdev; |
192 | int err = 0; | 192 | int err, type; |
193 | 193 | ||
194 | BT_DBG("%s -> %s", batostr(src), batostr(dst)); | 194 | BT_DBG("%s -> %s", batostr(src), batostr(dst)); |
195 | 195 | ||
@@ -200,7 +200,9 @@ static int sco_connect(struct sock *sk) | |||
200 | 200 | ||
201 | err = -ENOMEM; | 201 | err = -ENOMEM; |
202 | 202 | ||
203 | hcon = hci_connect(hdev, SCO_LINK, dst); | 203 | type = lmp_esco_capable(hdev) ? ESCO_LINK : SCO_LINK; |
204 | |||
205 | hcon = hci_connect(hdev, type, dst); | ||
204 | if (!hcon) | 206 | if (!hcon) |
205 | goto done; | 207 | goto done; |
206 | 208 | ||
@@ -224,6 +226,7 @@ static int sco_connect(struct sock *sk) | |||
224 | sk->sk_state = BT_CONNECT; | 226 | sk->sk_state = BT_CONNECT; |
225 | sco_sock_set_timer(sk, sk->sk_sndtimeo); | 227 | sco_sock_set_timer(sk, sk->sk_sndtimeo); |
226 | } | 228 | } |
229 | |||
227 | done: | 230 | done: |
228 | hci_dev_unlock_bh(hdev); | 231 | hci_dev_unlock_bh(hdev); |
229 | hci_dev_put(hdev); | 232 | hci_dev_put(hdev); |
@@ -846,7 +849,7 @@ static int sco_connect_cfm(struct hci_conn *hcon, __u8 status) | |||
846 | { | 849 | { |
847 | BT_DBG("hcon %p bdaddr %s status %d", hcon, batostr(&hcon->dst), status); | 850 | BT_DBG("hcon %p bdaddr %s status %d", hcon, batostr(&hcon->dst), status); |
848 | 851 | ||
849 | if (hcon->type != SCO_LINK) | 852 | if (hcon->type != SCO_LINK && hcon->type != ESCO_LINK) |
850 | return 0; | 853 | return 0; |
851 | 854 | ||
852 | if (!status) { | 855 | if (!status) { |
@@ -865,10 +868,11 @@ static int sco_disconn_ind(struct hci_conn *hcon, __u8 reason) | |||
865 | { | 868 | { |
866 | BT_DBG("hcon %p reason %d", hcon, reason); | 869 | BT_DBG("hcon %p reason %d", hcon, reason); |
867 | 870 | ||
868 | if (hcon->type != SCO_LINK) | 871 | if (hcon->type != SCO_LINK && hcon->type != ESCO_LINK) |
869 | return 0; | 872 | return 0; |
870 | 873 | ||
871 | sco_conn_del(hcon, bt_err(reason)); | 874 | sco_conn_del(hcon, bt_err(reason)); |
875 | |||
872 | return 0; | 876 | return 0; |
873 | } | 877 | } |
874 | 878 | ||
diff --git a/net/bridge/br.c b/net/bridge/br.c index 848b8fa8bedd..93867bb6cc97 100644 --- a/net/bridge/br.c +++ b/net/bridge/br.c | |||
@@ -23,7 +23,7 @@ | |||
23 | 23 | ||
24 | #include "br_private.h" | 24 | #include "br_private.h" |
25 | 25 | ||
26 | int (*br_should_route_hook) (struct sk_buff **pskb) = NULL; | 26 | int (*br_should_route_hook)(struct sk_buff *skb); |
27 | 27 | ||
28 | static struct llc_sap *br_stp_sap; | 28 | static struct llc_sap *br_stp_sap; |
29 | 29 | ||
diff --git a/net/bridge/br_input.c b/net/bridge/br_input.c index 3a8a015c92e0..3cedd4eeeed6 100644 --- a/net/bridge/br_input.c +++ b/net/bridge/br_input.c | |||
@@ -126,6 +126,10 @@ struct sk_buff *br_handle_frame(struct net_bridge_port *p, struct sk_buff *skb) | |||
126 | if (!is_valid_ether_addr(eth_hdr(skb)->h_source)) | 126 | if (!is_valid_ether_addr(eth_hdr(skb)->h_source)) |
127 | goto drop; | 127 | goto drop; |
128 | 128 | ||
129 | skb = skb_share_check(skb, GFP_ATOMIC); | ||
130 | if (!skb) | ||
131 | return NULL; | ||
132 | |||
129 | if (unlikely(is_link_local(dest))) { | 133 | if (unlikely(is_link_local(dest))) { |
130 | /* Pause frames shouldn't be passed up by driver anyway */ | 134 | /* Pause frames shouldn't be passed up by driver anyway */ |
131 | if (skb->protocol == htons(ETH_P_PAUSE)) | 135 | if (skb->protocol == htons(ETH_P_PAUSE)) |
@@ -145,7 +149,7 @@ struct sk_buff *br_handle_frame(struct net_bridge_port *p, struct sk_buff *skb) | |||
145 | case BR_STATE_FORWARDING: | 149 | case BR_STATE_FORWARDING: |
146 | 150 | ||
147 | if (br_should_route_hook) { | 151 | if (br_should_route_hook) { |
148 | if (br_should_route_hook(&skb)) | 152 | if (br_should_route_hook(skb)) |
149 | return skb; | 153 | return skb; |
150 | dest = eth_hdr(skb)->h_dest; | 154 | dest = eth_hdr(skb)->h_dest; |
151 | } | 155 | } |
diff --git a/net/bridge/br_netfilter.c b/net/bridge/br_netfilter.c index 8245f051ccbb..da22f900e89d 100644 --- a/net/bridge/br_netfilter.c +++ b/net/bridge/br_netfilter.c | |||
@@ -503,18 +503,14 @@ inhdr_error: | |||
503 | * receiving device) to make netfilter happy, the REDIRECT | 503 | * receiving device) to make netfilter happy, the REDIRECT |
504 | * target in particular. Save the original destination IP | 504 | * target in particular. Save the original destination IP |
505 | * address to be able to detect DNAT afterwards. */ | 505 | * address to be able to detect DNAT afterwards. */ |
506 | static unsigned int br_nf_pre_routing(unsigned int hook, struct sk_buff **pskb, | 506 | static unsigned int br_nf_pre_routing(unsigned int hook, struct sk_buff *skb, |
507 | const struct net_device *in, | 507 | const struct net_device *in, |
508 | const struct net_device *out, | 508 | const struct net_device *out, |
509 | int (*okfn)(struct sk_buff *)) | 509 | int (*okfn)(struct sk_buff *)) |
510 | { | 510 | { |
511 | struct iphdr *iph; | 511 | struct iphdr *iph; |
512 | struct sk_buff *skb = *pskb; | ||
513 | __u32 len = nf_bridge_encap_header_len(skb); | 512 | __u32 len = nf_bridge_encap_header_len(skb); |
514 | 513 | ||
515 | if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL) | ||
516 | return NF_STOLEN; | ||
517 | |||
518 | if (unlikely(!pskb_may_pull(skb, len))) | 514 | if (unlikely(!pskb_may_pull(skb, len))) |
519 | goto out; | 515 | goto out; |
520 | 516 | ||
@@ -584,13 +580,11 @@ out: | |||
584 | * took place when the packet entered the bridge), but we | 580 | * took place when the packet entered the bridge), but we |
585 | * register an IPv4 PRE_ROUTING 'sabotage' hook that will | 581 | * register an IPv4 PRE_ROUTING 'sabotage' hook that will |
586 | * prevent this from happening. */ | 582 | * prevent this from happening. */ |
587 | static unsigned int br_nf_local_in(unsigned int hook, struct sk_buff **pskb, | 583 | static unsigned int br_nf_local_in(unsigned int hook, struct sk_buff *skb, |
588 | const struct net_device *in, | 584 | const struct net_device *in, |
589 | const struct net_device *out, | 585 | const struct net_device *out, |
590 | int (*okfn)(struct sk_buff *)) | 586 | int (*okfn)(struct sk_buff *)) |
591 | { | 587 | { |
592 | struct sk_buff *skb = *pskb; | ||
593 | |||
594 | if (skb->dst == (struct dst_entry *)&__fake_rtable) { | 588 | if (skb->dst == (struct dst_entry *)&__fake_rtable) { |
595 | dst_release(skb->dst); | 589 | dst_release(skb->dst); |
596 | skb->dst = NULL; | 590 | skb->dst = NULL; |
@@ -625,12 +619,11 @@ static int br_nf_forward_finish(struct sk_buff *skb) | |||
625 | * but we are still able to filter on the 'real' indev/outdev | 619 | * but we are still able to filter on the 'real' indev/outdev |
626 | * because of the physdev module. For ARP, indev and outdev are the | 620 | * because of the physdev module. For ARP, indev and outdev are the |
627 | * bridge ports. */ | 621 | * bridge ports. */ |
628 | static unsigned int br_nf_forward_ip(unsigned int hook, struct sk_buff **pskb, | 622 | static unsigned int br_nf_forward_ip(unsigned int hook, struct sk_buff *skb, |
629 | const struct net_device *in, | 623 | const struct net_device *in, |
630 | const struct net_device *out, | 624 | const struct net_device *out, |
631 | int (*okfn)(struct sk_buff *)) | 625 | int (*okfn)(struct sk_buff *)) |
632 | { | 626 | { |
633 | struct sk_buff *skb = *pskb; | ||
634 | struct nf_bridge_info *nf_bridge; | 627 | struct nf_bridge_info *nf_bridge; |
635 | struct net_device *parent; | 628 | struct net_device *parent; |
636 | int pf; | 629 | int pf; |
@@ -648,7 +641,7 @@ static unsigned int br_nf_forward_ip(unsigned int hook, struct sk_buff **pskb, | |||
648 | else | 641 | else |
649 | pf = PF_INET6; | 642 | pf = PF_INET6; |
650 | 643 | ||
651 | nf_bridge_pull_encap_header(*pskb); | 644 | nf_bridge_pull_encap_header(skb); |
652 | 645 | ||
653 | nf_bridge = skb->nf_bridge; | 646 | nf_bridge = skb->nf_bridge; |
654 | if (skb->pkt_type == PACKET_OTHERHOST) { | 647 | if (skb->pkt_type == PACKET_OTHERHOST) { |
@@ -666,12 +659,11 @@ static unsigned int br_nf_forward_ip(unsigned int hook, struct sk_buff **pskb, | |||
666 | return NF_STOLEN; | 659 | return NF_STOLEN; |
667 | } | 660 | } |
668 | 661 | ||
669 | static unsigned int br_nf_forward_arp(unsigned int hook, struct sk_buff **pskb, | 662 | static unsigned int br_nf_forward_arp(unsigned int hook, struct sk_buff *skb, |
670 | const struct net_device *in, | 663 | const struct net_device *in, |
671 | const struct net_device *out, | 664 | const struct net_device *out, |
672 | int (*okfn)(struct sk_buff *)) | 665 | int (*okfn)(struct sk_buff *)) |
673 | { | 666 | { |
674 | struct sk_buff *skb = *pskb; | ||
675 | struct net_device **d = (struct net_device **)(skb->cb); | 667 | struct net_device **d = (struct net_device **)(skb->cb); |
676 | 668 | ||
677 | #ifdef CONFIG_SYSCTL | 669 | #ifdef CONFIG_SYSCTL |
@@ -682,12 +674,12 @@ static unsigned int br_nf_forward_arp(unsigned int hook, struct sk_buff **pskb, | |||
682 | if (skb->protocol != htons(ETH_P_ARP)) { | 674 | if (skb->protocol != htons(ETH_P_ARP)) { |
683 | if (!IS_VLAN_ARP(skb)) | 675 | if (!IS_VLAN_ARP(skb)) |
684 | return NF_ACCEPT; | 676 | return NF_ACCEPT; |
685 | nf_bridge_pull_encap_header(*pskb); | 677 | nf_bridge_pull_encap_header(skb); |
686 | } | 678 | } |
687 | 679 | ||
688 | if (arp_hdr(skb)->ar_pln != 4) { | 680 | if (arp_hdr(skb)->ar_pln != 4) { |
689 | if (IS_VLAN_ARP(skb)) | 681 | if (IS_VLAN_ARP(skb)) |
690 | nf_bridge_push_encap_header(*pskb); | 682 | nf_bridge_push_encap_header(skb); |
691 | return NF_ACCEPT; | 683 | return NF_ACCEPT; |
692 | } | 684 | } |
693 | *d = (struct net_device *)in; | 685 | *d = (struct net_device *)in; |
@@ -709,13 +701,12 @@ static unsigned int br_nf_forward_arp(unsigned int hook, struct sk_buff **pskb, | |||
709 | * NF_BR_PRI_FIRST, so no relevant PF_BRIDGE/INPUT functions have been nor | 701 | * NF_BR_PRI_FIRST, so no relevant PF_BRIDGE/INPUT functions have been nor |
710 | * will be executed. | 702 | * will be executed. |
711 | */ | 703 | */ |
712 | static unsigned int br_nf_local_out(unsigned int hook, struct sk_buff **pskb, | 704 | static unsigned int br_nf_local_out(unsigned int hook, struct sk_buff *skb, |
713 | const struct net_device *in, | 705 | const struct net_device *in, |
714 | const struct net_device *out, | 706 | const struct net_device *out, |
715 | int (*okfn)(struct sk_buff *)) | 707 | int (*okfn)(struct sk_buff *)) |
716 | { | 708 | { |
717 | struct net_device *realindev; | 709 | struct net_device *realindev; |
718 | struct sk_buff *skb = *pskb; | ||
719 | struct nf_bridge_info *nf_bridge; | 710 | struct nf_bridge_info *nf_bridge; |
720 | 711 | ||
721 | if (!skb->nf_bridge) | 712 | if (!skb->nf_bridge) |
@@ -752,13 +743,12 @@ static int br_nf_dev_queue_xmit(struct sk_buff *skb) | |||
752 | } | 743 | } |
753 | 744 | ||
754 | /* PF_BRIDGE/POST_ROUTING ********************************************/ | 745 | /* PF_BRIDGE/POST_ROUTING ********************************************/ |
755 | static unsigned int br_nf_post_routing(unsigned int hook, struct sk_buff **pskb, | 746 | static unsigned int br_nf_post_routing(unsigned int hook, struct sk_buff *skb, |
756 | const struct net_device *in, | 747 | const struct net_device *in, |
757 | const struct net_device *out, | 748 | const struct net_device *out, |
758 | int (*okfn)(struct sk_buff *)) | 749 | int (*okfn)(struct sk_buff *)) |
759 | { | 750 | { |
760 | struct sk_buff *skb = *pskb; | 751 | struct nf_bridge_info *nf_bridge = skb->nf_bridge; |
761 | struct nf_bridge_info *nf_bridge = (*pskb)->nf_bridge; | ||
762 | struct net_device *realoutdev = bridge_parent(skb->dev); | 752 | struct net_device *realoutdev = bridge_parent(skb->dev); |
763 | int pf; | 753 | int pf; |
764 | 754 | ||
@@ -828,13 +818,13 @@ print_error: | |||
828 | /* IP/SABOTAGE *****************************************************/ | 818 | /* IP/SABOTAGE *****************************************************/ |
829 | /* Don't hand locally destined packets to PF_INET(6)/PRE_ROUTING | 819 | /* Don't hand locally destined packets to PF_INET(6)/PRE_ROUTING |
830 | * for the second time. */ | 820 | * for the second time. */ |
831 | static unsigned int ip_sabotage_in(unsigned int hook, struct sk_buff **pskb, | 821 | static unsigned int ip_sabotage_in(unsigned int hook, struct sk_buff *skb, |
832 | const struct net_device *in, | 822 | const struct net_device *in, |
833 | const struct net_device *out, | 823 | const struct net_device *out, |
834 | int (*okfn)(struct sk_buff *)) | 824 | int (*okfn)(struct sk_buff *)) |
835 | { | 825 | { |
836 | if ((*pskb)->nf_bridge && | 826 | if (skb->nf_bridge && |
837 | !((*pskb)->nf_bridge->mask & BRNF_NF_BRIDGE_PREROUTING)) { | 827 | !(skb->nf_bridge->mask & BRNF_NF_BRIDGE_PREROUTING)) { |
838 | return NF_STOP; | 828 | return NF_STOP; |
839 | } | 829 | } |
840 | 830 | ||
diff --git a/net/bridge/netfilter/ebt_arpreply.c b/net/bridge/netfilter/ebt_arpreply.c index ffe468a632e7..48a80e423287 100644 --- a/net/bridge/netfilter/ebt_arpreply.c +++ b/net/bridge/netfilter/ebt_arpreply.c | |||
@@ -15,7 +15,7 @@ | |||
15 | #include <net/arp.h> | 15 | #include <net/arp.h> |
16 | #include <linux/module.h> | 16 | #include <linux/module.h> |
17 | 17 | ||
18 | static int ebt_target_reply(struct sk_buff **pskb, unsigned int hooknr, | 18 | static int ebt_target_reply(struct sk_buff *skb, unsigned int hooknr, |
19 | const struct net_device *in, const struct net_device *out, | 19 | const struct net_device *in, const struct net_device *out, |
20 | const void *data, unsigned int datalen) | 20 | const void *data, unsigned int datalen) |
21 | { | 21 | { |
@@ -23,7 +23,6 @@ static int ebt_target_reply(struct sk_buff **pskb, unsigned int hooknr, | |||
23 | __be32 _sip, *siptr, _dip, *diptr; | 23 | __be32 _sip, *siptr, _dip, *diptr; |
24 | struct arphdr _ah, *ap; | 24 | struct arphdr _ah, *ap; |
25 | unsigned char _sha[ETH_ALEN], *shp; | 25 | unsigned char _sha[ETH_ALEN], *shp; |
26 | struct sk_buff *skb = *pskb; | ||
27 | 26 | ||
28 | ap = skb_header_pointer(skb, 0, sizeof(_ah), &_ah); | 27 | ap = skb_header_pointer(skb, 0, sizeof(_ah), &_ah); |
29 | if (ap == NULL) | 28 | if (ap == NULL) |
diff --git a/net/bridge/netfilter/ebt_dnat.c b/net/bridge/netfilter/ebt_dnat.c index 4582659dff0e..74262e9a566a 100644 --- a/net/bridge/netfilter/ebt_dnat.c +++ b/net/bridge/netfilter/ebt_dnat.c | |||
@@ -8,29 +8,22 @@ | |||
8 | * | 8 | * |
9 | */ | 9 | */ |
10 | 10 | ||
11 | #include <linux/netfilter.h> | ||
11 | #include <linux/netfilter_bridge/ebtables.h> | 12 | #include <linux/netfilter_bridge/ebtables.h> |
12 | #include <linux/netfilter_bridge/ebt_nat.h> | 13 | #include <linux/netfilter_bridge/ebt_nat.h> |
13 | #include <linux/module.h> | 14 | #include <linux/module.h> |
14 | #include <net/sock.h> | 15 | #include <net/sock.h> |
15 | 16 | ||
16 | static int ebt_target_dnat(struct sk_buff **pskb, unsigned int hooknr, | 17 | static int ebt_target_dnat(struct sk_buff *skb, unsigned int hooknr, |
17 | const struct net_device *in, const struct net_device *out, | 18 | const struct net_device *in, const struct net_device *out, |
18 | const void *data, unsigned int datalen) | 19 | const void *data, unsigned int datalen) |
19 | { | 20 | { |
20 | struct ebt_nat_info *info = (struct ebt_nat_info *)data; | 21 | struct ebt_nat_info *info = (struct ebt_nat_info *)data; |
21 | 22 | ||
22 | if (skb_shared(*pskb) || skb_cloned(*pskb)) { | 23 | if (skb_make_writable(skb, 0)) |
23 | struct sk_buff *nskb; | 24 | return NF_DROP; |
24 | 25 | ||
25 | nskb = skb_copy(*pskb, GFP_ATOMIC); | 26 | memcpy(eth_hdr(skb)->h_dest, info->mac, ETH_ALEN); |
26 | if (!nskb) | ||
27 | return NF_DROP; | ||
28 | if ((*pskb)->sk) | ||
29 | skb_set_owner_w(nskb, (*pskb)->sk); | ||
30 | kfree_skb(*pskb); | ||
31 | *pskb = nskb; | ||
32 | } | ||
33 | memcpy(eth_hdr(*pskb)->h_dest, info->mac, ETH_ALEN); | ||
34 | return info->target; | 27 | return info->target; |
35 | } | 28 | } |
36 | 29 | ||
diff --git a/net/bridge/netfilter/ebt_mark.c b/net/bridge/netfilter/ebt_mark.c index 62d23c7b25e6..6cba54309c09 100644 --- a/net/bridge/netfilter/ebt_mark.c +++ b/net/bridge/netfilter/ebt_mark.c | |||
@@ -17,7 +17,7 @@ | |||
17 | #include <linux/netfilter_bridge/ebt_mark_t.h> | 17 | #include <linux/netfilter_bridge/ebt_mark_t.h> |
18 | #include <linux/module.h> | 18 | #include <linux/module.h> |
19 | 19 | ||
20 | static int ebt_target_mark(struct sk_buff **pskb, unsigned int hooknr, | 20 | static int ebt_target_mark(struct sk_buff *skb, unsigned int hooknr, |
21 | const struct net_device *in, const struct net_device *out, | 21 | const struct net_device *in, const struct net_device *out, |
22 | const void *data, unsigned int datalen) | 22 | const void *data, unsigned int datalen) |
23 | { | 23 | { |
@@ -25,13 +25,13 @@ static int ebt_target_mark(struct sk_buff **pskb, unsigned int hooknr, | |||
25 | int action = info->target & -16; | 25 | int action = info->target & -16; |
26 | 26 | ||
27 | if (action == MARK_SET_VALUE) | 27 | if (action == MARK_SET_VALUE) |
28 | (*pskb)->mark = info->mark; | 28 | skb->mark = info->mark; |
29 | else if (action == MARK_OR_VALUE) | 29 | else if (action == MARK_OR_VALUE) |
30 | (*pskb)->mark |= info->mark; | 30 | skb->mark |= info->mark; |
31 | else if (action == MARK_AND_VALUE) | 31 | else if (action == MARK_AND_VALUE) |
32 | (*pskb)->mark &= info->mark; | 32 | skb->mark &= info->mark; |
33 | else | 33 | else |
34 | (*pskb)->mark ^= info->mark; | 34 | skb->mark ^= info->mark; |
35 | 35 | ||
36 | return info->target | ~EBT_VERDICT_BITS; | 36 | return info->target | ~EBT_VERDICT_BITS; |
37 | } | 37 | } |
diff --git a/net/bridge/netfilter/ebt_redirect.c b/net/bridge/netfilter/ebt_redirect.c index 9f378eab72d0..422cb834cff9 100644 --- a/net/bridge/netfilter/ebt_redirect.c +++ b/net/bridge/netfilter/ebt_redirect.c | |||
@@ -8,35 +8,28 @@ | |||
8 | * | 8 | * |
9 | */ | 9 | */ |
10 | 10 | ||
11 | #include <linux/netfilter.h> | ||
11 | #include <linux/netfilter_bridge/ebtables.h> | 12 | #include <linux/netfilter_bridge/ebtables.h> |
12 | #include <linux/netfilter_bridge/ebt_redirect.h> | 13 | #include <linux/netfilter_bridge/ebt_redirect.h> |
13 | #include <linux/module.h> | 14 | #include <linux/module.h> |
14 | #include <net/sock.h> | 15 | #include <net/sock.h> |
15 | #include "../br_private.h" | 16 | #include "../br_private.h" |
16 | 17 | ||
17 | static int ebt_target_redirect(struct sk_buff **pskb, unsigned int hooknr, | 18 | static int ebt_target_redirect(struct sk_buff *skb, unsigned int hooknr, |
18 | const struct net_device *in, const struct net_device *out, | 19 | const struct net_device *in, const struct net_device *out, |
19 | const void *data, unsigned int datalen) | 20 | const void *data, unsigned int datalen) |
20 | { | 21 | { |
21 | struct ebt_redirect_info *info = (struct ebt_redirect_info *)data; | 22 | struct ebt_redirect_info *info = (struct ebt_redirect_info *)data; |
22 | 23 | ||
23 | if (skb_shared(*pskb) || skb_cloned(*pskb)) { | 24 | if (skb_make_writable(skb, 0)) |
24 | struct sk_buff *nskb; | 25 | return NF_DROP; |
25 | 26 | ||
26 | nskb = skb_copy(*pskb, GFP_ATOMIC); | ||
27 | if (!nskb) | ||
28 | return NF_DROP; | ||
29 | if ((*pskb)->sk) | ||
30 | skb_set_owner_w(nskb, (*pskb)->sk); | ||
31 | kfree_skb(*pskb); | ||
32 | *pskb = nskb; | ||
33 | } | ||
34 | if (hooknr != NF_BR_BROUTING) | 27 | if (hooknr != NF_BR_BROUTING) |
35 | memcpy(eth_hdr(*pskb)->h_dest, | 28 | memcpy(eth_hdr(skb)->h_dest, |
36 | in->br_port->br->dev->dev_addr, ETH_ALEN); | 29 | in->br_port->br->dev->dev_addr, ETH_ALEN); |
37 | else | 30 | else |
38 | memcpy(eth_hdr(*pskb)->h_dest, in->dev_addr, ETH_ALEN); | 31 | memcpy(eth_hdr(skb)->h_dest, in->dev_addr, ETH_ALEN); |
39 | (*pskb)->pkt_type = PACKET_HOST; | 32 | skb->pkt_type = PACKET_HOST; |
40 | return info->target; | 33 | return info->target; |
41 | } | 34 | } |
42 | 35 | ||
diff --git a/net/bridge/netfilter/ebt_snat.c b/net/bridge/netfilter/ebt_snat.c index a50722182bfe..425ac920904d 100644 --- a/net/bridge/netfilter/ebt_snat.c +++ b/net/bridge/netfilter/ebt_snat.c | |||
@@ -8,6 +8,7 @@ | |||
8 | * | 8 | * |
9 | */ | 9 | */ |
10 | 10 | ||
11 | #include <linux/netfilter.h> | ||
11 | #include <linux/netfilter_bridge/ebtables.h> | 12 | #include <linux/netfilter_bridge/ebtables.h> |
12 | #include <linux/netfilter_bridge/ebt_nat.h> | 13 | #include <linux/netfilter_bridge/ebt_nat.h> |
13 | #include <linux/module.h> | 14 | #include <linux/module.h> |
@@ -15,34 +16,26 @@ | |||
15 | #include <linux/if_arp.h> | 16 | #include <linux/if_arp.h> |
16 | #include <net/arp.h> | 17 | #include <net/arp.h> |
17 | 18 | ||
18 | static int ebt_target_snat(struct sk_buff **pskb, unsigned int hooknr, | 19 | static int ebt_target_snat(struct sk_buff *skb, unsigned int hooknr, |
19 | const struct net_device *in, const struct net_device *out, | 20 | const struct net_device *in, const struct net_device *out, |
20 | const void *data, unsigned int datalen) | 21 | const void *data, unsigned int datalen) |
21 | { | 22 | { |
22 | struct ebt_nat_info *info = (struct ebt_nat_info *) data; | 23 | struct ebt_nat_info *info = (struct ebt_nat_info *) data; |
23 | 24 | ||
24 | if (skb_shared(*pskb) || skb_cloned(*pskb)) { | 25 | if (skb_make_writable(skb, 0)) |
25 | struct sk_buff *nskb; | 26 | return NF_DROP; |
26 | 27 | ||
27 | nskb = skb_copy(*pskb, GFP_ATOMIC); | 28 | memcpy(eth_hdr(skb)->h_source, info->mac, ETH_ALEN); |
28 | if (!nskb) | ||
29 | return NF_DROP; | ||
30 | if ((*pskb)->sk) | ||
31 | skb_set_owner_w(nskb, (*pskb)->sk); | ||
32 | kfree_skb(*pskb); | ||
33 | *pskb = nskb; | ||
34 | } | ||
35 | memcpy(eth_hdr(*pskb)->h_source, info->mac, ETH_ALEN); | ||
36 | if (!(info->target & NAT_ARP_BIT) && | 29 | if (!(info->target & NAT_ARP_BIT) && |
37 | eth_hdr(*pskb)->h_proto == htons(ETH_P_ARP)) { | 30 | eth_hdr(skb)->h_proto == htons(ETH_P_ARP)) { |
38 | struct arphdr _ah, *ap; | 31 | struct arphdr _ah, *ap; |
39 | 32 | ||
40 | ap = skb_header_pointer(*pskb, 0, sizeof(_ah), &_ah); | 33 | ap = skb_header_pointer(skb, 0, sizeof(_ah), &_ah); |
41 | if (ap == NULL) | 34 | if (ap == NULL) |
42 | return EBT_DROP; | 35 | return EBT_DROP; |
43 | if (ap->ar_hln != ETH_ALEN) | 36 | if (ap->ar_hln != ETH_ALEN) |
44 | goto out; | 37 | goto out; |
45 | if (skb_store_bits(*pskb, sizeof(_ah), info->mac,ETH_ALEN)) | 38 | if (skb_store_bits(skb, sizeof(_ah), info->mac,ETH_ALEN)) |
46 | return EBT_DROP; | 39 | return EBT_DROP; |
47 | } | 40 | } |
48 | out: | 41 | out: |
diff --git a/net/bridge/netfilter/ebtable_broute.c b/net/bridge/netfilter/ebtable_broute.c index d37ce0478938..e44519ebf1d2 100644 --- a/net/bridge/netfilter/ebtable_broute.c +++ b/net/bridge/netfilter/ebtable_broute.c | |||
@@ -51,11 +51,11 @@ static struct ebt_table broute_table = | |||
51 | .me = THIS_MODULE, | 51 | .me = THIS_MODULE, |
52 | }; | 52 | }; |
53 | 53 | ||
54 | static int ebt_broute(struct sk_buff **pskb) | 54 | static int ebt_broute(struct sk_buff *skb) |
55 | { | 55 | { |
56 | int ret; | 56 | int ret; |
57 | 57 | ||
58 | ret = ebt_do_table(NF_BR_BROUTING, pskb, (*pskb)->dev, NULL, | 58 | ret = ebt_do_table(NF_BR_BROUTING, skb, skb->dev, NULL, |
59 | &broute_table); | 59 | &broute_table); |
60 | if (ret == NF_DROP) | 60 | if (ret == NF_DROP) |
61 | return 1; /* route it */ | 61 | return 1; /* route it */ |
diff --git a/net/bridge/netfilter/ebtable_filter.c b/net/bridge/netfilter/ebtable_filter.c index 81d84145c417..210493f99bc4 100644 --- a/net/bridge/netfilter/ebtable_filter.c +++ b/net/bridge/netfilter/ebtable_filter.c | |||
@@ -61,10 +61,10 @@ static struct ebt_table frame_filter = | |||
61 | }; | 61 | }; |
62 | 62 | ||
63 | static unsigned int | 63 | static unsigned int |
64 | ebt_hook (unsigned int hook, struct sk_buff **pskb, const struct net_device *in, | 64 | ebt_hook(unsigned int hook, struct sk_buff *skb, const struct net_device *in, |
65 | const struct net_device *out, int (*okfn)(struct sk_buff *)) | 65 | const struct net_device *out, int (*okfn)(struct sk_buff *)) |
66 | { | 66 | { |
67 | return ebt_do_table(hook, pskb, in, out, &frame_filter); | 67 | return ebt_do_table(hook, skb, in, out, &frame_filter); |
68 | } | 68 | } |
69 | 69 | ||
70 | static struct nf_hook_ops ebt_ops_filter[] = { | 70 | static struct nf_hook_ops ebt_ops_filter[] = { |
diff --git a/net/bridge/netfilter/ebtable_nat.c b/net/bridge/netfilter/ebtable_nat.c index 9c50488b62eb..3e58c2e5ee21 100644 --- a/net/bridge/netfilter/ebtable_nat.c +++ b/net/bridge/netfilter/ebtable_nat.c | |||
@@ -61,17 +61,17 @@ static struct ebt_table frame_nat = | |||
61 | }; | 61 | }; |
62 | 62 | ||
63 | static unsigned int | 63 | static unsigned int |
64 | ebt_nat_dst(unsigned int hook, struct sk_buff **pskb, const struct net_device *in | 64 | ebt_nat_dst(unsigned int hook, struct sk_buff *skb, const struct net_device *in |
65 | , const struct net_device *out, int (*okfn)(struct sk_buff *)) | 65 | , const struct net_device *out, int (*okfn)(struct sk_buff *)) |
66 | { | 66 | { |
67 | return ebt_do_table(hook, pskb, in, out, &frame_nat); | 67 | return ebt_do_table(hook, skb, in, out, &frame_nat); |
68 | } | 68 | } |
69 | 69 | ||
70 | static unsigned int | 70 | static unsigned int |
71 | ebt_nat_src(unsigned int hook, struct sk_buff **pskb, const struct net_device *in | 71 | ebt_nat_src(unsigned int hook, struct sk_buff *skb, const struct net_device *in |
72 | , const struct net_device *out, int (*okfn)(struct sk_buff *)) | 72 | , const struct net_device *out, int (*okfn)(struct sk_buff *)) |
73 | { | 73 | { |
74 | return ebt_do_table(hook, pskb, in, out, &frame_nat); | 74 | return ebt_do_table(hook, skb, in, out, &frame_nat); |
75 | } | 75 | } |
76 | 76 | ||
77 | static struct nf_hook_ops ebt_ops_nat[] = { | 77 | static struct nf_hook_ops ebt_ops_nat[] = { |
diff --git a/net/bridge/netfilter/ebtables.c b/net/bridge/netfilter/ebtables.c index 6018d0e51938..817169e718c1 100644 --- a/net/bridge/netfilter/ebtables.c +++ b/net/bridge/netfilter/ebtables.c | |||
@@ -142,7 +142,7 @@ static inline int ebt_basic_match(struct ebt_entry *e, struct ethhdr *h, | |||
142 | } | 142 | } |
143 | 143 | ||
144 | /* Do some firewalling */ | 144 | /* Do some firewalling */ |
145 | unsigned int ebt_do_table (unsigned int hook, struct sk_buff **pskb, | 145 | unsigned int ebt_do_table (unsigned int hook, struct sk_buff *skb, |
146 | const struct net_device *in, const struct net_device *out, | 146 | const struct net_device *in, const struct net_device *out, |
147 | struct ebt_table *table) | 147 | struct ebt_table *table) |
148 | { | 148 | { |
@@ -172,19 +172,19 @@ unsigned int ebt_do_table (unsigned int hook, struct sk_buff **pskb, | |||
172 | base = private->entries; | 172 | base = private->entries; |
173 | i = 0; | 173 | i = 0; |
174 | while (i < nentries) { | 174 | while (i < nentries) { |
175 | if (ebt_basic_match(point, eth_hdr(*pskb), in, out)) | 175 | if (ebt_basic_match(point, eth_hdr(skb), in, out)) |
176 | goto letscontinue; | 176 | goto letscontinue; |
177 | 177 | ||
178 | if (EBT_MATCH_ITERATE(point, ebt_do_match, *pskb, in, out) != 0) | 178 | if (EBT_MATCH_ITERATE(point, ebt_do_match, skb, in, out) != 0) |
179 | goto letscontinue; | 179 | goto letscontinue; |
180 | 180 | ||
181 | /* increase counter */ | 181 | /* increase counter */ |
182 | (*(counter_base + i)).pcnt++; | 182 | (*(counter_base + i)).pcnt++; |
183 | (*(counter_base + i)).bcnt+=(**pskb).len; | 183 | (*(counter_base + i)).bcnt += skb->len; |
184 | 184 | ||
185 | /* these should only watch: not modify, nor tell us | 185 | /* these should only watch: not modify, nor tell us |
186 | what to do with the packet */ | 186 | what to do with the packet */ |
187 | EBT_WATCHER_ITERATE(point, ebt_do_watcher, *pskb, hook, in, | 187 | EBT_WATCHER_ITERATE(point, ebt_do_watcher, skb, hook, in, |
188 | out); | 188 | out); |
189 | 189 | ||
190 | t = (struct ebt_entry_target *) | 190 | t = (struct ebt_entry_target *) |
@@ -193,7 +193,7 @@ unsigned int ebt_do_table (unsigned int hook, struct sk_buff **pskb, | |||
193 | if (!t->u.target->target) | 193 | if (!t->u.target->target) |
194 | verdict = ((struct ebt_standard_target *)t)->verdict; | 194 | verdict = ((struct ebt_standard_target *)t)->verdict; |
195 | else | 195 | else |
196 | verdict = t->u.target->target(pskb, hook, | 196 | verdict = t->u.target->target(skb, hook, |
197 | in, out, t->data, t->target_size); | 197 | in, out, t->data, t->target_size); |
198 | if (verdict == EBT_ACCEPT) { | 198 | if (verdict == EBT_ACCEPT) { |
199 | read_unlock_bh(&table->lock); | 199 | read_unlock_bh(&table->lock); |
@@ -871,7 +871,7 @@ static int translate_table(char *name, struct ebt_table_info *newinfo) | |||
871 | return -EINVAL; | 871 | return -EINVAL; |
872 | } | 872 | } |
873 | 873 | ||
874 | /* we now know the following (along with E=mc²): | 874 | /* we now know the following (along with E=mc²): |
875 | - the nr of entries in each chain is right | 875 | - the nr of entries in each chain is right |
876 | - the size of the allocated space is right | 876 | - the size of the allocated space is right |
877 | - all valid hooks have a corresponding chain | 877 | - all valid hooks have a corresponding chain |
diff --git a/net/core/dev.c b/net/core/dev.c index 99b7bda37d10..872658927e47 100644 --- a/net/core/dev.c +++ b/net/core/dev.c | |||
@@ -1362,22 +1362,21 @@ int skb_checksum_help(struct sk_buff *skb) | |||
1362 | goto out_set_summed; | 1362 | goto out_set_summed; |
1363 | } | 1363 | } |
1364 | 1364 | ||
1365 | if (skb_cloned(skb)) { | 1365 | offset = skb->csum_start - skb_headroom(skb); |
1366 | BUG_ON(offset >= skb_headlen(skb)); | ||
1367 | csum = skb_checksum(skb, offset, skb->len - offset, 0); | ||
1368 | |||
1369 | offset += skb->csum_offset; | ||
1370 | BUG_ON(offset + sizeof(__sum16) > skb_headlen(skb)); | ||
1371 | |||
1372 | if (skb_cloned(skb) && | ||
1373 | !skb_clone_writable(skb, offset + sizeof(__sum16))) { | ||
1366 | ret = pskb_expand_head(skb, 0, 0, GFP_ATOMIC); | 1374 | ret = pskb_expand_head(skb, 0, 0, GFP_ATOMIC); |
1367 | if (ret) | 1375 | if (ret) |
1368 | goto out; | 1376 | goto out; |
1369 | } | 1377 | } |
1370 | 1378 | ||
1371 | offset = skb->csum_start - skb_headroom(skb); | 1379 | *(__sum16 *)(skb->data + offset) = csum_fold(csum); |
1372 | BUG_ON(offset > (int)skb->len); | ||
1373 | csum = skb_checksum(skb, offset, skb->len-offset, 0); | ||
1374 | |||
1375 | offset = skb_headlen(skb) - offset; | ||
1376 | BUG_ON(offset <= 0); | ||
1377 | BUG_ON(skb->csum_offset + 2 > offset); | ||
1378 | |||
1379 | *(__sum16 *)(skb->head + skb->csum_start + skb->csum_offset) = | ||
1380 | csum_fold(csum); | ||
1381 | out_set_summed: | 1380 | out_set_summed: |
1382 | skb->ip_summed = CHECKSUM_NONE; | 1381 | skb->ip_summed = CHECKSUM_NONE; |
1383 | out: | 1382 | out: |
@@ -1554,7 +1553,7 @@ gso: | |||
1554 | return rc; | 1553 | return rc; |
1555 | } | 1554 | } |
1556 | if (unlikely((netif_queue_stopped(dev) || | 1555 | if (unlikely((netif_queue_stopped(dev) || |
1557 | netif_subqueue_stopped(dev, skb->queue_mapping)) && | 1556 | netif_subqueue_stopped(dev, skb)) && |
1558 | skb->next)) | 1557 | skb->next)) |
1559 | return NETDEV_TX_BUSY; | 1558 | return NETDEV_TX_BUSY; |
1560 | } while (skb->next); | 1559 | } while (skb->next); |
@@ -1662,7 +1661,7 @@ gso: | |||
1662 | q = dev->qdisc; | 1661 | q = dev->qdisc; |
1663 | if (q->enqueue) { | 1662 | if (q->enqueue) { |
1664 | /* reset queue_mapping to zero */ | 1663 | /* reset queue_mapping to zero */ |
1665 | skb->queue_mapping = 0; | 1664 | skb_set_queue_mapping(skb, 0); |
1666 | rc = q->enqueue(skb, q); | 1665 | rc = q->enqueue(skb, q); |
1667 | qdisc_run(dev); | 1666 | qdisc_run(dev); |
1668 | spin_unlock(&dev->queue_lock); | 1667 | spin_unlock(&dev->queue_lock); |
@@ -1693,7 +1692,7 @@ gso: | |||
1693 | HARD_TX_LOCK(dev, cpu); | 1692 | HARD_TX_LOCK(dev, cpu); |
1694 | 1693 | ||
1695 | if (!netif_queue_stopped(dev) && | 1694 | if (!netif_queue_stopped(dev) && |
1696 | !netif_subqueue_stopped(dev, skb->queue_mapping)) { | 1695 | !netif_subqueue_stopped(dev, skb)) { |
1697 | rc = 0; | 1696 | rc = 0; |
1698 | if (!dev_hard_start_xmit(skb, dev)) { | 1697 | if (!dev_hard_start_xmit(skb, dev)) { |
1699 | HARD_TX_UNLOCK(dev); | 1698 | HARD_TX_UNLOCK(dev); |
@@ -1949,27 +1948,51 @@ static int ing_filter(struct sk_buff *skb) | |||
1949 | struct Qdisc *q; | 1948 | struct Qdisc *q; |
1950 | struct net_device *dev = skb->dev; | 1949 | struct net_device *dev = skb->dev; |
1951 | int result = TC_ACT_OK; | 1950 | int result = TC_ACT_OK; |
1951 | u32 ttl = G_TC_RTTL(skb->tc_verd); | ||
1952 | 1952 | ||
1953 | if (dev->qdisc_ingress) { | 1953 | if (MAX_RED_LOOP < ttl++) { |
1954 | __u32 ttl = (__u32) G_TC_RTTL(skb->tc_verd); | 1954 | printk(KERN_WARNING |
1955 | if (MAX_RED_LOOP < ttl++) { | 1955 | "Redir loop detected Dropping packet (%d->%d)\n", |
1956 | printk(KERN_WARNING "Redir loop detected Dropping packet (%d->%d)\n", | 1956 | skb->iif, dev->ifindex); |
1957 | skb->iif, skb->dev->ifindex); | 1957 | return TC_ACT_SHOT; |
1958 | return TC_ACT_SHOT; | 1958 | } |
1959 | } | 1959 | |
1960 | skb->tc_verd = SET_TC_RTTL(skb->tc_verd, ttl); | ||
1961 | skb->tc_verd = SET_TC_AT(skb->tc_verd, AT_INGRESS); | ||
1960 | 1962 | ||
1961 | skb->tc_verd = SET_TC_RTTL(skb->tc_verd,ttl); | 1963 | spin_lock(&dev->ingress_lock); |
1964 | if ((q = dev->qdisc_ingress) != NULL) | ||
1965 | result = q->enqueue(skb, q); | ||
1966 | spin_unlock(&dev->ingress_lock); | ||
1962 | 1967 | ||
1963 | skb->tc_verd = SET_TC_AT(skb->tc_verd,AT_INGRESS); | 1968 | return result; |
1969 | } | ||
1970 | |||
1971 | static inline struct sk_buff *handle_ing(struct sk_buff *skb, | ||
1972 | struct packet_type **pt_prev, | ||
1973 | int *ret, struct net_device *orig_dev) | ||
1974 | { | ||
1975 | if (!skb->dev->qdisc_ingress) | ||
1976 | goto out; | ||
1964 | 1977 | ||
1965 | spin_lock(&dev->ingress_lock); | 1978 | if (*pt_prev) { |
1966 | if ((q = dev->qdisc_ingress) != NULL) | 1979 | *ret = deliver_skb(skb, *pt_prev, orig_dev); |
1967 | result = q->enqueue(skb, q); | 1980 | *pt_prev = NULL; |
1968 | spin_unlock(&dev->ingress_lock); | 1981 | } else { |
1982 | /* Huh? Why does turning on AF_PACKET affect this? */ | ||
1983 | skb->tc_verd = SET_TC_OK2MUNGE(skb->tc_verd); | ||
1984 | } | ||
1969 | 1985 | ||
1986 | switch (ing_filter(skb)) { | ||
1987 | case TC_ACT_SHOT: | ||
1988 | case TC_ACT_STOLEN: | ||
1989 | kfree_skb(skb); | ||
1990 | return NULL; | ||
1970 | } | 1991 | } |
1971 | 1992 | ||
1972 | return result; | 1993 | out: |
1994 | skb->tc_verd = 0; | ||
1995 | return skb; | ||
1973 | } | 1996 | } |
1974 | #endif | 1997 | #endif |
1975 | 1998 | ||
@@ -2021,21 +2044,9 @@ int netif_receive_skb(struct sk_buff *skb) | |||
2021 | } | 2044 | } |
2022 | 2045 | ||
2023 | #ifdef CONFIG_NET_CLS_ACT | 2046 | #ifdef CONFIG_NET_CLS_ACT |
2024 | if (pt_prev) { | 2047 | skb = handle_ing(skb, &pt_prev, &ret, orig_dev); |
2025 | ret = deliver_skb(skb, pt_prev, orig_dev); | 2048 | if (!skb) |
2026 | pt_prev = NULL; /* noone else should process this after*/ | ||
2027 | } else { | ||
2028 | skb->tc_verd = SET_TC_OK2MUNGE(skb->tc_verd); | ||
2029 | } | ||
2030 | |||
2031 | ret = ing_filter(skb); | ||
2032 | |||
2033 | if (ret == TC_ACT_SHOT || (ret == TC_ACT_STOLEN)) { | ||
2034 | kfree_skb(skb); | ||
2035 | goto out; | 2049 | goto out; |
2036 | } | ||
2037 | |||
2038 | skb->tc_verd = 0; | ||
2039 | ncls: | 2050 | ncls: |
2040 | #endif | 2051 | #endif |
2041 | 2052 | ||
diff --git a/net/core/filter.c b/net/core/filter.c index bd903aaf7aa7..e0a06942c025 100644 --- a/net/core/filter.c +++ b/net/core/filter.c | |||
@@ -387,6 +387,25 @@ int sk_chk_filter(struct sock_filter *filter, int flen) | |||
387 | } | 387 | } |
388 | 388 | ||
389 | /** | 389 | /** |
390 | * sk_filter_rcu_release: Release a socket filter by rcu_head | ||
391 | * @rcu: rcu_head that contains the sk_filter to free | ||
392 | */ | ||
393 | static void sk_filter_rcu_release(struct rcu_head *rcu) | ||
394 | { | ||
395 | struct sk_filter *fp = container_of(rcu, struct sk_filter, rcu); | ||
396 | |||
397 | sk_filter_release(fp); | ||
398 | } | ||
399 | |||
400 | static void sk_filter_delayed_uncharge(struct sock *sk, struct sk_filter *fp) | ||
401 | { | ||
402 | unsigned int size = sk_filter_len(fp); | ||
403 | |||
404 | atomic_sub(size, &sk->sk_omem_alloc); | ||
405 | call_rcu_bh(&fp->rcu, sk_filter_rcu_release); | ||
406 | } | ||
407 | |||
408 | /** | ||
390 | * sk_attach_filter - attach a socket filter | 409 | * sk_attach_filter - attach a socket filter |
391 | * @fprog: the filter program | 410 | * @fprog: the filter program |
392 | * @sk: the socket to use | 411 | * @sk: the socket to use |
@@ -398,7 +417,7 @@ int sk_chk_filter(struct sock_filter *filter, int flen) | |||
398 | */ | 417 | */ |
399 | int sk_attach_filter(struct sock_fprog *fprog, struct sock *sk) | 418 | int sk_attach_filter(struct sock_fprog *fprog, struct sock *sk) |
400 | { | 419 | { |
401 | struct sk_filter *fp; | 420 | struct sk_filter *fp, *old_fp; |
402 | unsigned int fsize = sizeof(struct sock_filter) * fprog->len; | 421 | unsigned int fsize = sizeof(struct sock_filter) * fprog->len; |
403 | int err; | 422 | int err; |
404 | 423 | ||
@@ -418,19 +437,35 @@ int sk_attach_filter(struct sock_fprog *fprog, struct sock *sk) | |||
418 | fp->len = fprog->len; | 437 | fp->len = fprog->len; |
419 | 438 | ||
420 | err = sk_chk_filter(fp->insns, fp->len); | 439 | err = sk_chk_filter(fp->insns, fp->len); |
421 | if (!err) { | 440 | if (err) { |
422 | struct sk_filter *old_fp; | 441 | sk_filter_uncharge(sk, fp); |
423 | 442 | return err; | |
424 | rcu_read_lock_bh(); | ||
425 | old_fp = rcu_dereference(sk->sk_filter); | ||
426 | rcu_assign_pointer(sk->sk_filter, fp); | ||
427 | rcu_read_unlock_bh(); | ||
428 | fp = old_fp; | ||
429 | } | 443 | } |
430 | 444 | ||
431 | if (fp) | 445 | rcu_read_lock_bh(); |
432 | sk_filter_release(sk, fp); | 446 | old_fp = rcu_dereference(sk->sk_filter); |
433 | return err; | 447 | rcu_assign_pointer(sk->sk_filter, fp); |
448 | rcu_read_unlock_bh(); | ||
449 | |||
450 | if (old_fp) | ||
451 | sk_filter_delayed_uncharge(sk, old_fp); | ||
452 | return 0; | ||
453 | } | ||
454 | |||
455 | int sk_detach_filter(struct sock *sk) | ||
456 | { | ||
457 | int ret = -ENOENT; | ||
458 | struct sk_filter *filter; | ||
459 | |||
460 | rcu_read_lock_bh(); | ||
461 | filter = rcu_dereference(sk->sk_filter); | ||
462 | if (filter) { | ||
463 | rcu_assign_pointer(sk->sk_filter, NULL); | ||
464 | sk_filter_delayed_uncharge(sk, filter); | ||
465 | ret = 0; | ||
466 | } | ||
467 | rcu_read_unlock_bh(); | ||
468 | return ret; | ||
434 | } | 469 | } |
435 | 470 | ||
436 | EXPORT_SYMBOL(sk_chk_filter); | 471 | EXPORT_SYMBOL(sk_chk_filter); |
diff --git a/net/core/gen_estimator.c b/net/core/gen_estimator.c index 590a767b029c..daadbcc4e8dd 100644 --- a/net/core/gen_estimator.c +++ b/net/core/gen_estimator.c | |||
@@ -15,7 +15,7 @@ | |||
15 | 15 | ||
16 | #include <asm/uaccess.h> | 16 | #include <asm/uaccess.h> |
17 | #include <asm/system.h> | 17 | #include <asm/system.h> |
18 | #include <asm/bitops.h> | 18 | #include <linux/bitops.h> |
19 | #include <linux/module.h> | 19 | #include <linux/module.h> |
20 | #include <linux/types.h> | 20 | #include <linux/types.h> |
21 | #include <linux/kernel.h> | 21 | #include <linux/kernel.h> |
diff --git a/net/core/neighbour.c b/net/core/neighbour.c index c52df858d0be..05979e356963 100644 --- a/net/core/neighbour.c +++ b/net/core/neighbour.c | |||
@@ -481,6 +481,8 @@ struct pneigh_entry * pneigh_lookup(struct neigh_table *tbl, const void *pkey, | |||
481 | if (!creat) | 481 | if (!creat) |
482 | goto out; | 482 | goto out; |
483 | 483 | ||
484 | ASSERT_RTNL(); | ||
485 | |||
484 | n = kmalloc(sizeof(*n) + key_len, GFP_KERNEL); | 486 | n = kmalloc(sizeof(*n) + key_len, GFP_KERNEL); |
485 | if (!n) | 487 | if (!n) |
486 | goto out; | 488 | goto out; |
@@ -1436,6 +1438,9 @@ int neigh_table_clear(struct neigh_table *tbl) | |||
1436 | free_percpu(tbl->stats); | 1438 | free_percpu(tbl->stats); |
1437 | tbl->stats = NULL; | 1439 | tbl->stats = NULL; |
1438 | 1440 | ||
1441 | kmem_cache_destroy(tbl->kmem_cachep); | ||
1442 | tbl->kmem_cachep = NULL; | ||
1443 | |||
1439 | return 0; | 1444 | return 0; |
1440 | } | 1445 | } |
1441 | 1446 | ||
@@ -2494,7 +2499,6 @@ static struct neigh_sysctl_table { | |||
2494 | .proc_handler = &proc_dointvec, | 2499 | .proc_handler = &proc_dointvec, |
2495 | }, | 2500 | }, |
2496 | { | 2501 | { |
2497 | .ctl_name = NET_NEIGH_RETRANS_TIME, | ||
2498 | .procname = "retrans_time", | 2502 | .procname = "retrans_time", |
2499 | .maxlen = sizeof(int), | 2503 | .maxlen = sizeof(int), |
2500 | .mode = 0644, | 2504 | .mode = 0644, |
@@ -2539,27 +2543,40 @@ static struct neigh_sysctl_table { | |||
2539 | .proc_handler = &proc_dointvec, | 2543 | .proc_handler = &proc_dointvec, |
2540 | }, | 2544 | }, |
2541 | { | 2545 | { |
2542 | .ctl_name = NET_NEIGH_ANYCAST_DELAY, | ||
2543 | .procname = "anycast_delay", | 2546 | .procname = "anycast_delay", |
2544 | .maxlen = sizeof(int), | 2547 | .maxlen = sizeof(int), |
2545 | .mode = 0644, | 2548 | .mode = 0644, |
2546 | .proc_handler = &proc_dointvec_userhz_jiffies, | 2549 | .proc_handler = &proc_dointvec_userhz_jiffies, |
2547 | }, | 2550 | }, |
2548 | { | 2551 | { |
2549 | .ctl_name = NET_NEIGH_PROXY_DELAY, | ||
2550 | .procname = "proxy_delay", | 2552 | .procname = "proxy_delay", |
2551 | .maxlen = sizeof(int), | 2553 | .maxlen = sizeof(int), |
2552 | .mode = 0644, | 2554 | .mode = 0644, |
2553 | .proc_handler = &proc_dointvec_userhz_jiffies, | 2555 | .proc_handler = &proc_dointvec_userhz_jiffies, |
2554 | }, | 2556 | }, |
2555 | { | 2557 | { |
2556 | .ctl_name = NET_NEIGH_LOCKTIME, | ||
2557 | .procname = "locktime", | 2558 | .procname = "locktime", |
2558 | .maxlen = sizeof(int), | 2559 | .maxlen = sizeof(int), |
2559 | .mode = 0644, | 2560 | .mode = 0644, |
2560 | .proc_handler = &proc_dointvec_userhz_jiffies, | 2561 | .proc_handler = &proc_dointvec_userhz_jiffies, |
2561 | }, | 2562 | }, |
2562 | { | 2563 | { |
2564 | .ctl_name = NET_NEIGH_RETRANS_TIME_MS, | ||
2565 | .procname = "retrans_time_ms", | ||
2566 | .maxlen = sizeof(int), | ||
2567 | .mode = 0644, | ||
2568 | .proc_handler = &proc_dointvec_ms_jiffies, | ||
2569 | .strategy = &sysctl_ms_jiffies, | ||
2570 | }, | ||
2571 | { | ||
2572 | .ctl_name = NET_NEIGH_REACHABLE_TIME_MS, | ||
2573 | .procname = "base_reachable_time_ms", | ||
2574 | .maxlen = sizeof(int), | ||
2575 | .mode = 0644, | ||
2576 | .proc_handler = &proc_dointvec_ms_jiffies, | ||
2577 | .strategy = &sysctl_ms_jiffies, | ||
2578 | }, | ||
2579 | { | ||
2563 | .ctl_name = NET_NEIGH_GC_INTERVAL, | 2580 | .ctl_name = NET_NEIGH_GC_INTERVAL, |
2564 | .procname = "gc_interval", | 2581 | .procname = "gc_interval", |
2565 | .maxlen = sizeof(int), | 2582 | .maxlen = sizeof(int), |
@@ -2588,22 +2605,7 @@ static struct neigh_sysctl_table { | |||
2588 | .mode = 0644, | 2605 | .mode = 0644, |
2589 | .proc_handler = &proc_dointvec, | 2606 | .proc_handler = &proc_dointvec, |
2590 | }, | 2607 | }, |
2591 | { | 2608 | {} |
2592 | .ctl_name = NET_NEIGH_RETRANS_TIME_MS, | ||
2593 | .procname = "retrans_time_ms", | ||
2594 | .maxlen = sizeof(int), | ||
2595 | .mode = 0644, | ||
2596 | .proc_handler = &proc_dointvec_ms_jiffies, | ||
2597 | .strategy = &sysctl_ms_jiffies, | ||
2598 | }, | ||
2599 | { | ||
2600 | .ctl_name = NET_NEIGH_REACHABLE_TIME_MS, | ||
2601 | .procname = "base_reachable_time_ms", | ||
2602 | .maxlen = sizeof(int), | ||
2603 | .mode = 0644, | ||
2604 | .proc_handler = &proc_dointvec_ms_jiffies, | ||
2605 | .strategy = &sysctl_ms_jiffies, | ||
2606 | }, | ||
2607 | }, | 2609 | }, |
2608 | .neigh_dev = { | 2610 | .neigh_dev = { |
2609 | { | 2611 | { |
@@ -2656,42 +2658,48 @@ int neigh_sysctl_register(struct net_device *dev, struct neigh_parms *p, | |||
2656 | t->neigh_vars[9].data = &p->anycast_delay; | 2658 | t->neigh_vars[9].data = &p->anycast_delay; |
2657 | t->neigh_vars[10].data = &p->proxy_delay; | 2659 | t->neigh_vars[10].data = &p->proxy_delay; |
2658 | t->neigh_vars[11].data = &p->locktime; | 2660 | t->neigh_vars[11].data = &p->locktime; |
2661 | t->neigh_vars[12].data = &p->retrans_time; | ||
2662 | t->neigh_vars[13].data = &p->base_reachable_time; | ||
2659 | 2663 | ||
2660 | if (dev) { | 2664 | if (dev) { |
2661 | dev_name_source = dev->name; | 2665 | dev_name_source = dev->name; |
2662 | t->neigh_dev[0].ctl_name = dev->ifindex; | 2666 | t->neigh_dev[0].ctl_name = dev->ifindex; |
2663 | t->neigh_vars[12].procname = NULL; | 2667 | /* Terminate the table early */ |
2664 | t->neigh_vars[13].procname = NULL; | 2668 | memset(&t->neigh_vars[14], 0, sizeof(t->neigh_vars[14])); |
2665 | t->neigh_vars[14].procname = NULL; | ||
2666 | t->neigh_vars[15].procname = NULL; | ||
2667 | } else { | 2669 | } else { |
2668 | dev_name_source = t->neigh_dev[0].procname; | 2670 | dev_name_source = t->neigh_dev[0].procname; |
2669 | t->neigh_vars[12].data = (int *)(p + 1); | 2671 | t->neigh_vars[14].data = (int *)(p + 1); |
2670 | t->neigh_vars[13].data = (int *)(p + 1) + 1; | 2672 | t->neigh_vars[15].data = (int *)(p + 1) + 1; |
2671 | t->neigh_vars[14].data = (int *)(p + 1) + 2; | 2673 | t->neigh_vars[16].data = (int *)(p + 1) + 2; |
2672 | t->neigh_vars[15].data = (int *)(p + 1) + 3; | 2674 | t->neigh_vars[17].data = (int *)(p + 1) + 3; |
2673 | } | 2675 | } |
2674 | 2676 | ||
2675 | t->neigh_vars[16].data = &p->retrans_time; | ||
2676 | t->neigh_vars[17].data = &p->base_reachable_time; | ||
2677 | 2677 | ||
2678 | if (handler || strategy) { | 2678 | if (handler || strategy) { |
2679 | /* RetransTime */ | 2679 | /* RetransTime */ |
2680 | t->neigh_vars[3].proc_handler = handler; | 2680 | t->neigh_vars[3].proc_handler = handler; |
2681 | t->neigh_vars[3].strategy = strategy; | 2681 | t->neigh_vars[3].strategy = strategy; |
2682 | t->neigh_vars[3].extra1 = dev; | 2682 | t->neigh_vars[3].extra1 = dev; |
2683 | if (!strategy) | ||
2684 | t->neigh_vars[3].ctl_name = CTL_UNNUMBERED; | ||
2683 | /* ReachableTime */ | 2685 | /* ReachableTime */ |
2684 | t->neigh_vars[4].proc_handler = handler; | 2686 | t->neigh_vars[4].proc_handler = handler; |
2685 | t->neigh_vars[4].strategy = strategy; | 2687 | t->neigh_vars[4].strategy = strategy; |
2686 | t->neigh_vars[4].extra1 = dev; | 2688 | t->neigh_vars[4].extra1 = dev; |
2689 | if (!strategy) | ||
2690 | t->neigh_vars[4].ctl_name = CTL_UNNUMBERED; | ||
2687 | /* RetransTime (in milliseconds)*/ | 2691 | /* RetransTime (in milliseconds)*/ |
2688 | t->neigh_vars[16].proc_handler = handler; | 2692 | t->neigh_vars[12].proc_handler = handler; |
2689 | t->neigh_vars[16].strategy = strategy; | 2693 | t->neigh_vars[12].strategy = strategy; |
2690 | t->neigh_vars[16].extra1 = dev; | 2694 | t->neigh_vars[12].extra1 = dev; |
2695 | if (!strategy) | ||
2696 | t->neigh_vars[12].ctl_name = CTL_UNNUMBERED; | ||
2691 | /* ReachableTime (in milliseconds) */ | 2697 | /* ReachableTime (in milliseconds) */ |
2692 | t->neigh_vars[17].proc_handler = handler; | 2698 | t->neigh_vars[13].proc_handler = handler; |
2693 | t->neigh_vars[17].strategy = strategy; | 2699 | t->neigh_vars[13].strategy = strategy; |
2694 | t->neigh_vars[17].extra1 = dev; | 2700 | t->neigh_vars[13].extra1 = dev; |
2701 | if (!strategy) | ||
2702 | t->neigh_vars[13].ctl_name = CTL_UNNUMBERED; | ||
2695 | } | 2703 | } |
2696 | 2704 | ||
2697 | dev_name = kstrdup(dev_name_source, GFP_KERNEL); | 2705 | dev_name = kstrdup(dev_name_source, GFP_KERNEL); |
diff --git a/net/core/netpoll.c b/net/core/netpoll.c index 95daba624967..bf8d18f1b013 100644 --- a/net/core/netpoll.c +++ b/net/core/netpoll.c | |||
@@ -67,7 +67,7 @@ static void queue_process(struct work_struct *work) | |||
67 | local_irq_save(flags); | 67 | local_irq_save(flags); |
68 | netif_tx_lock(dev); | 68 | netif_tx_lock(dev); |
69 | if ((netif_queue_stopped(dev) || | 69 | if ((netif_queue_stopped(dev) || |
70 | netif_subqueue_stopped(dev, skb->queue_mapping)) || | 70 | netif_subqueue_stopped(dev, skb)) || |
71 | dev->hard_start_xmit(skb, dev) != NETDEV_TX_OK) { | 71 | dev->hard_start_xmit(skb, dev) != NETDEV_TX_OK) { |
72 | skb_queue_head(&npinfo->txq, skb); | 72 | skb_queue_head(&npinfo->txq, skb); |
73 | netif_tx_unlock(dev); | 73 | netif_tx_unlock(dev); |
@@ -269,7 +269,7 @@ static void netpoll_send_skb(struct netpoll *np, struct sk_buff *skb) | |||
269 | tries > 0; --tries) { | 269 | tries > 0; --tries) { |
270 | if (netif_tx_trylock(dev)) { | 270 | if (netif_tx_trylock(dev)) { |
271 | if (!netif_queue_stopped(dev) && | 271 | if (!netif_queue_stopped(dev) && |
272 | !netif_subqueue_stopped(dev, skb->queue_mapping)) | 272 | !netif_subqueue_stopped(dev, skb)) |
273 | status = dev->hard_start_xmit(skb, dev); | 273 | status = dev->hard_start_xmit(skb, dev); |
274 | netif_tx_unlock(dev); | 274 | netif_tx_unlock(dev); |
275 | 275 | ||
diff --git a/net/core/pktgen.c b/net/core/pktgen.c index 2100c734b102..de33f36947e9 100644 --- a/net/core/pktgen.c +++ b/net/core/pktgen.c | |||
@@ -6,7 +6,7 @@ | |||
6 | * | 6 | * |
7 | * Alexey Kuznetsov <kuznet@ms2.inr.ac.ru> | 7 | * Alexey Kuznetsov <kuznet@ms2.inr.ac.ru> |
8 | * Ben Greear <greearb@candelatech.com> | 8 | * Ben Greear <greearb@candelatech.com> |
9 | * Jens Låås <jens.laas@data.slu.se> | 9 | * Jens Låås <jens.laas@data.slu.se> |
10 | * | 10 | * |
11 | * This program is free software; you can redistribute it and/or | 11 | * This program is free software; you can redistribute it and/or |
12 | * modify it under the terms of the GNU General Public License | 12 | * modify it under the terms of the GNU General Public License |
@@ -161,7 +161,7 @@ | |||
161 | #endif | 161 | #endif |
162 | #include <asm/byteorder.h> | 162 | #include <asm/byteorder.h> |
163 | #include <linux/rcupdate.h> | 163 | #include <linux/rcupdate.h> |
164 | #include <asm/bitops.h> | 164 | #include <linux/bitops.h> |
165 | #include <asm/io.h> | 165 | #include <asm/io.h> |
166 | #include <asm/dma.h> | 166 | #include <asm/dma.h> |
167 | #include <asm/uaccess.h> | 167 | #include <asm/uaccess.h> |
@@ -2454,7 +2454,7 @@ static int pktgen_output_ipsec(struct sk_buff *skb, struct pktgen_dev *pkt_dev) | |||
2454 | spin_lock(&x->lock); | 2454 | spin_lock(&x->lock); |
2455 | iph = ip_hdr(skb); | 2455 | iph = ip_hdr(skb); |
2456 | 2456 | ||
2457 | err = x->mode->output(x, skb); | 2457 | err = x->outer_mode->output(x, skb); |
2458 | if (err) | 2458 | if (err) |
2459 | goto error; | 2459 | goto error; |
2460 | err = x->type->output(x, skb); | 2460 | err = x->type->output(x, skb); |
@@ -2603,8 +2603,7 @@ static struct sk_buff *fill_packet_ipv4(struct net_device *odev, | |||
2603 | skb->network_header = skb->tail; | 2603 | skb->network_header = skb->tail; |
2604 | skb->transport_header = skb->network_header + sizeof(struct iphdr); | 2604 | skb->transport_header = skb->network_header + sizeof(struct iphdr); |
2605 | skb_put(skb, sizeof(struct iphdr) + sizeof(struct udphdr)); | 2605 | skb_put(skb, sizeof(struct iphdr) + sizeof(struct udphdr)); |
2606 | skb->queue_mapping = pkt_dev->cur_queue_map; | 2606 | skb_set_queue_mapping(skb, pkt_dev->cur_queue_map); |
2607 | |||
2608 | iph = ip_hdr(skb); | 2607 | iph = ip_hdr(skb); |
2609 | udph = udp_hdr(skb); | 2608 | udph = udp_hdr(skb); |
2610 | 2609 | ||
@@ -2941,8 +2940,7 @@ static struct sk_buff *fill_packet_ipv6(struct net_device *odev, | |||
2941 | skb->network_header = skb->tail; | 2940 | skb->network_header = skb->tail; |
2942 | skb->transport_header = skb->network_header + sizeof(struct ipv6hdr); | 2941 | skb->transport_header = skb->network_header + sizeof(struct ipv6hdr); |
2943 | skb_put(skb, sizeof(struct ipv6hdr) + sizeof(struct udphdr)); | 2942 | skb_put(skb, sizeof(struct ipv6hdr) + sizeof(struct udphdr)); |
2944 | skb->queue_mapping = pkt_dev->cur_queue_map; | 2943 | skb_set_queue_mapping(skb, pkt_dev->cur_queue_map); |
2945 | |||
2946 | iph = ipv6_hdr(skb); | 2944 | iph = ipv6_hdr(skb); |
2947 | udph = udp_hdr(skb); | 2945 | udph = udp_hdr(skb); |
2948 | 2946 | ||
@@ -3385,7 +3383,7 @@ static __inline__ void pktgen_xmit(struct pktgen_dev *pkt_dev) | |||
3385 | 3383 | ||
3386 | if ((netif_queue_stopped(odev) || | 3384 | if ((netif_queue_stopped(odev) || |
3387 | (pkt_dev->skb && | 3385 | (pkt_dev->skb && |
3388 | netif_subqueue_stopped(odev, pkt_dev->skb->queue_mapping))) || | 3386 | netif_subqueue_stopped(odev, pkt_dev->skb))) || |
3389 | need_resched()) { | 3387 | need_resched()) { |
3390 | idle_start = getCurUs(); | 3388 | idle_start = getCurUs(); |
3391 | 3389 | ||
@@ -3402,7 +3400,7 @@ static __inline__ void pktgen_xmit(struct pktgen_dev *pkt_dev) | |||
3402 | pkt_dev->idle_acc += getCurUs() - idle_start; | 3400 | pkt_dev->idle_acc += getCurUs() - idle_start; |
3403 | 3401 | ||
3404 | if (netif_queue_stopped(odev) || | 3402 | if (netif_queue_stopped(odev) || |
3405 | netif_subqueue_stopped(odev, pkt_dev->skb->queue_mapping)) { | 3403 | netif_subqueue_stopped(odev, pkt_dev->skb)) { |
3406 | pkt_dev->next_tx_us = getCurUs(); /* TODO */ | 3404 | pkt_dev->next_tx_us = getCurUs(); /* TODO */ |
3407 | pkt_dev->next_tx_ns = 0; | 3405 | pkt_dev->next_tx_ns = 0; |
3408 | goto out; /* Try the next interface */ | 3406 | goto out; /* Try the next interface */ |
@@ -3431,7 +3429,7 @@ static __inline__ void pktgen_xmit(struct pktgen_dev *pkt_dev) | |||
3431 | 3429 | ||
3432 | netif_tx_lock_bh(odev); | 3430 | netif_tx_lock_bh(odev); |
3433 | if (!netif_queue_stopped(odev) && | 3431 | if (!netif_queue_stopped(odev) && |
3434 | !netif_subqueue_stopped(odev, pkt_dev->skb->queue_mapping)) { | 3432 | !netif_subqueue_stopped(odev, pkt_dev->skb)) { |
3435 | 3433 | ||
3436 | atomic_inc(&(pkt_dev->skb->users)); | 3434 | atomic_inc(&(pkt_dev->skb->users)); |
3437 | retry_now: | 3435 | retry_now: |
@@ -3514,7 +3512,7 @@ static int pktgen_thread_worker(void *arg) | |||
3514 | 3512 | ||
3515 | init_waitqueue_head(&t->queue); | 3513 | init_waitqueue_head(&t->queue); |
3516 | 3514 | ||
3517 | pr_debug("pktgen: starting pktgen/%d: pid=%d\n", cpu, current->pid); | 3515 | pr_debug("pktgen: starting pktgen/%d: pid=%d\n", cpu, task_pid_nr(current)); |
3518 | 3516 | ||
3519 | set_current_state(TASK_INTERRUPTIBLE); | 3517 | set_current_state(TASK_INTERRUPTIBLE); |
3520 | 3518 | ||
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index 1072d16696c3..4a2640d38261 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c | |||
@@ -744,10 +744,10 @@ static struct net *get_net_ns_by_pid(pid_t pid) | |||
744 | rcu_read_lock(); | 744 | rcu_read_lock(); |
745 | tsk = find_task_by_pid(pid); | 745 | tsk = find_task_by_pid(pid); |
746 | if (tsk) { | 746 | if (tsk) { |
747 | task_lock(tsk); | 747 | struct nsproxy *nsproxy; |
748 | if (tsk->nsproxy) | 748 | nsproxy = task_nsproxy(tsk); |
749 | net = get_net(tsk->nsproxy->net_ns); | 749 | if (nsproxy) |
750 | task_unlock(tsk); | 750 | net = get_net(nsproxy->net_ns); |
751 | } | 751 | } |
752 | rcu_read_unlock(); | 752 | rcu_read_unlock(); |
753 | return net; | 753 | return net; |
diff --git a/net/core/scm.c b/net/core/scm.c index 530bee8d9ed9..100ba6d9d478 100644 --- a/net/core/scm.c +++ b/net/core/scm.c | |||
@@ -24,6 +24,8 @@ | |||
24 | #include <linux/interrupt.h> | 24 | #include <linux/interrupt.h> |
25 | #include <linux/netdevice.h> | 25 | #include <linux/netdevice.h> |
26 | #include <linux/security.h> | 26 | #include <linux/security.h> |
27 | #include <linux/pid.h> | ||
28 | #include <linux/nsproxy.h> | ||
27 | 29 | ||
28 | #include <asm/system.h> | 30 | #include <asm/system.h> |
29 | #include <asm/uaccess.h> | 31 | #include <asm/uaccess.h> |
@@ -42,7 +44,7 @@ | |||
42 | 44 | ||
43 | static __inline__ int scm_check_creds(struct ucred *creds) | 45 | static __inline__ int scm_check_creds(struct ucred *creds) |
44 | { | 46 | { |
45 | if ((creds->pid == current->tgid || capable(CAP_SYS_ADMIN)) && | 47 | if ((creds->pid == task_tgid_vnr(current) || capable(CAP_SYS_ADMIN)) && |
46 | ((creds->uid == current->uid || creds->uid == current->euid || | 48 | ((creds->uid == current->uid || creds->uid == current->euid || |
47 | creds->uid == current->suid) || capable(CAP_SETUID)) && | 49 | creds->uid == current->suid) || capable(CAP_SETUID)) && |
48 | ((creds->gid == current->gid || creds->gid == current->egid || | 50 | ((creds->gid == current->gid || creds->gid == current->egid || |
diff --git a/net/core/skbuff.c b/net/core/skbuff.c index 944189d96323..4e2c84fcf276 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c | |||
@@ -362,6 +362,97 @@ void kfree_skb(struct sk_buff *skb) | |||
362 | __kfree_skb(skb); | 362 | __kfree_skb(skb); |
363 | } | 363 | } |
364 | 364 | ||
365 | static void __copy_skb_header(struct sk_buff *new, const struct sk_buff *old) | ||
366 | { | ||
367 | new->tstamp = old->tstamp; | ||
368 | new->dev = old->dev; | ||
369 | new->transport_header = old->transport_header; | ||
370 | new->network_header = old->network_header; | ||
371 | new->mac_header = old->mac_header; | ||
372 | new->dst = dst_clone(old->dst); | ||
373 | #ifdef CONFIG_INET | ||
374 | new->sp = secpath_get(old->sp); | ||
375 | #endif | ||
376 | memcpy(new->cb, old->cb, sizeof(old->cb)); | ||
377 | new->csum_start = old->csum_start; | ||
378 | new->csum_offset = old->csum_offset; | ||
379 | new->local_df = old->local_df; | ||
380 | new->pkt_type = old->pkt_type; | ||
381 | new->ip_summed = old->ip_summed; | ||
382 | skb_copy_queue_mapping(new, old); | ||
383 | new->priority = old->priority; | ||
384 | #if defined(CONFIG_IP_VS) || defined(CONFIG_IP_VS_MODULE) | ||
385 | new->ipvs_property = old->ipvs_property; | ||
386 | #endif | ||
387 | new->protocol = old->protocol; | ||
388 | new->mark = old->mark; | ||
389 | __nf_copy(new, old); | ||
390 | #if defined(CONFIG_NETFILTER_XT_TARGET_TRACE) || \ | ||
391 | defined(CONFIG_NETFILTER_XT_TARGET_TRACE_MODULE) | ||
392 | new->nf_trace = old->nf_trace; | ||
393 | #endif | ||
394 | #ifdef CONFIG_NET_SCHED | ||
395 | new->tc_index = old->tc_index; | ||
396 | #ifdef CONFIG_NET_CLS_ACT | ||
397 | new->tc_verd = old->tc_verd; | ||
398 | #endif | ||
399 | #endif | ||
400 | skb_copy_secmark(new, old); | ||
401 | } | ||
402 | |||
403 | static struct sk_buff *__skb_clone(struct sk_buff *n, struct sk_buff *skb) | ||
404 | { | ||
405 | #define C(x) n->x = skb->x | ||
406 | |||
407 | n->next = n->prev = NULL; | ||
408 | n->sk = NULL; | ||
409 | __copy_skb_header(n, skb); | ||
410 | |||
411 | C(len); | ||
412 | C(data_len); | ||
413 | C(mac_len); | ||
414 | n->cloned = 1; | ||
415 | n->hdr_len = skb->nohdr ? skb_headroom(skb) : skb->hdr_len; | ||
416 | n->nohdr = 0; | ||
417 | n->destructor = NULL; | ||
418 | #ifdef CONFIG_NET_CLS_ACT | ||
419 | /* FIXME What is this and why don't we do it in copy_skb_header? */ | ||
420 | n->tc_verd = SET_TC_VERD(n->tc_verd,0); | ||
421 | n->tc_verd = CLR_TC_OK2MUNGE(n->tc_verd); | ||
422 | n->tc_verd = CLR_TC_MUNGED(n->tc_verd); | ||
423 | C(iif); | ||
424 | #endif | ||
425 | C(truesize); | ||
426 | atomic_set(&n->users, 1); | ||
427 | C(head); | ||
428 | C(data); | ||
429 | C(tail); | ||
430 | C(end); | ||
431 | |||
432 | atomic_inc(&(skb_shinfo(skb)->dataref)); | ||
433 | skb->cloned = 1; | ||
434 | |||
435 | return n; | ||
436 | #undef C | ||
437 | } | ||
438 | |||
439 | /** | ||
440 | * skb_morph - morph one skb into another | ||
441 | * @dst: the skb to receive the contents | ||
442 | * @src: the skb to supply the contents | ||
443 | * | ||
444 | * This is identical to skb_clone except that the target skb is | ||
445 | * supplied by the user. | ||
446 | * | ||
447 | * The target skb is returned upon exit. | ||
448 | */ | ||
449 | struct sk_buff *skb_morph(struct sk_buff *dst, struct sk_buff *src) | ||
450 | { | ||
451 | skb_release_data(dst); | ||
452 | return __skb_clone(dst, src); | ||
453 | } | ||
454 | EXPORT_SYMBOL_GPL(skb_morph); | ||
455 | |||
365 | /** | 456 | /** |
366 | * skb_clone - duplicate an sk_buff | 457 | * skb_clone - duplicate an sk_buff |
367 | * @skb: buffer to clone | 458 | * @skb: buffer to clone |
@@ -393,66 +484,7 @@ struct sk_buff *skb_clone(struct sk_buff *skb, gfp_t gfp_mask) | |||
393 | n->fclone = SKB_FCLONE_UNAVAILABLE; | 484 | n->fclone = SKB_FCLONE_UNAVAILABLE; |
394 | } | 485 | } |
395 | 486 | ||
396 | #define C(x) n->x = skb->x | 487 | return __skb_clone(n, skb); |
397 | |||
398 | n->next = n->prev = NULL; | ||
399 | n->sk = NULL; | ||
400 | C(tstamp); | ||
401 | C(dev); | ||
402 | C(transport_header); | ||
403 | C(network_header); | ||
404 | C(mac_header); | ||
405 | C(dst); | ||
406 | dst_clone(skb->dst); | ||
407 | C(sp); | ||
408 | #ifdef CONFIG_INET | ||
409 | secpath_get(skb->sp); | ||
410 | #endif | ||
411 | memcpy(n->cb, skb->cb, sizeof(skb->cb)); | ||
412 | C(len); | ||
413 | C(data_len); | ||
414 | C(mac_len); | ||
415 | C(csum); | ||
416 | C(local_df); | ||
417 | n->cloned = 1; | ||
418 | n->hdr_len = skb->nohdr ? skb_headroom(skb) : skb->hdr_len; | ||
419 | n->nohdr = 0; | ||
420 | C(pkt_type); | ||
421 | C(ip_summed); | ||
422 | skb_copy_queue_mapping(n, skb); | ||
423 | C(priority); | ||
424 | #if defined(CONFIG_IP_VS) || defined(CONFIG_IP_VS_MODULE) | ||
425 | C(ipvs_property); | ||
426 | #endif | ||
427 | C(protocol); | ||
428 | n->destructor = NULL; | ||
429 | C(mark); | ||
430 | __nf_copy(n, skb); | ||
431 | #if defined(CONFIG_NETFILTER_XT_TARGET_TRACE) || \ | ||
432 | defined(CONFIG_NETFILTER_XT_TARGET_TRACE_MODULE) | ||
433 | C(nf_trace); | ||
434 | #endif | ||
435 | #ifdef CONFIG_NET_SCHED | ||
436 | C(tc_index); | ||
437 | #ifdef CONFIG_NET_CLS_ACT | ||
438 | n->tc_verd = SET_TC_VERD(skb->tc_verd,0); | ||
439 | n->tc_verd = CLR_TC_OK2MUNGE(n->tc_verd); | ||
440 | n->tc_verd = CLR_TC_MUNGED(n->tc_verd); | ||
441 | C(iif); | ||
442 | #endif | ||
443 | #endif | ||
444 | skb_copy_secmark(n, skb); | ||
445 | C(truesize); | ||
446 | atomic_set(&n->users, 1); | ||
447 | C(head); | ||
448 | C(data); | ||
449 | C(tail); | ||
450 | C(end); | ||
451 | |||
452 | atomic_inc(&(skb_shinfo(skb)->dataref)); | ||
453 | skb->cloned = 1; | ||
454 | |||
455 | return n; | ||
456 | } | 488 | } |
457 | 489 | ||
458 | static void copy_skb_header(struct sk_buff *new, const struct sk_buff *old) | 490 | static void copy_skb_header(struct sk_buff *new, const struct sk_buff *old) |
@@ -463,50 +495,15 @@ static void copy_skb_header(struct sk_buff *new, const struct sk_buff *old) | |||
463 | */ | 495 | */ |
464 | unsigned long offset = new->data - old->data; | 496 | unsigned long offset = new->data - old->data; |
465 | #endif | 497 | #endif |
466 | new->sk = NULL; | 498 | |
467 | new->dev = old->dev; | 499 | __copy_skb_header(new, old); |
468 | skb_copy_queue_mapping(new, old); | 500 | |
469 | new->priority = old->priority; | ||
470 | new->protocol = old->protocol; | ||
471 | new->dst = dst_clone(old->dst); | ||
472 | #ifdef CONFIG_INET | ||
473 | new->sp = secpath_get(old->sp); | ||
474 | #endif | ||
475 | new->csum_start = old->csum_start; | ||
476 | new->csum_offset = old->csum_offset; | ||
477 | new->ip_summed = old->ip_summed; | ||
478 | new->transport_header = old->transport_header; | ||
479 | new->network_header = old->network_header; | ||
480 | new->mac_header = old->mac_header; | ||
481 | #ifndef NET_SKBUFF_DATA_USES_OFFSET | 501 | #ifndef NET_SKBUFF_DATA_USES_OFFSET |
482 | /* {transport,network,mac}_header are relative to skb->head */ | 502 | /* {transport,network,mac}_header are relative to skb->head */ |
483 | new->transport_header += offset; | 503 | new->transport_header += offset; |
484 | new->network_header += offset; | 504 | new->network_header += offset; |
485 | new->mac_header += offset; | 505 | new->mac_header += offset; |
486 | #endif | 506 | #endif |
487 | memcpy(new->cb, old->cb, sizeof(old->cb)); | ||
488 | new->local_df = old->local_df; | ||
489 | new->fclone = SKB_FCLONE_UNAVAILABLE; | ||
490 | new->pkt_type = old->pkt_type; | ||
491 | new->tstamp = old->tstamp; | ||
492 | new->destructor = NULL; | ||
493 | new->mark = old->mark; | ||
494 | __nf_copy(new, old); | ||
495 | #if defined(CONFIG_NETFILTER_XT_TARGET_TRACE) || \ | ||
496 | defined(CONFIG_NETFILTER_XT_TARGET_TRACE_MODULE) | ||
497 | new->nf_trace = old->nf_trace; | ||
498 | #endif | ||
499 | #if defined(CONFIG_IP_VS) || defined(CONFIG_IP_VS_MODULE) | ||
500 | new->ipvs_property = old->ipvs_property; | ||
501 | #endif | ||
502 | #ifdef CONFIG_NET_SCHED | ||
503 | #ifdef CONFIG_NET_CLS_ACT | ||
504 | new->tc_verd = old->tc_verd; | ||
505 | #endif | ||
506 | new->tc_index = old->tc_index; | ||
507 | #endif | ||
508 | skb_copy_secmark(new, old); | ||
509 | atomic_set(&new->users, 1); | ||
510 | skb_shinfo(new)->gso_size = skb_shinfo(old)->gso_size; | 507 | skb_shinfo(new)->gso_size = skb_shinfo(old)->gso_size; |
511 | skb_shinfo(new)->gso_segs = skb_shinfo(old)->gso_segs; | 508 | skb_shinfo(new)->gso_segs = skb_shinfo(old)->gso_segs; |
512 | skb_shinfo(new)->gso_type = skb_shinfo(old)->gso_type; | 509 | skb_shinfo(new)->gso_type = skb_shinfo(old)->gso_type; |
@@ -685,7 +682,7 @@ int pskb_expand_head(struct sk_buff *skb, int nhead, int ntail, | |||
685 | skb->transport_header += off; | 682 | skb->transport_header += off; |
686 | skb->network_header += off; | 683 | skb->network_header += off; |
687 | skb->mac_header += off; | 684 | skb->mac_header += off; |
688 | skb->csum_start += off; | 685 | skb->csum_start += nhead; |
689 | skb->cloned = 0; | 686 | skb->cloned = 0; |
690 | skb->hdr_len = 0; | 687 | skb->hdr_len = 0; |
691 | skb->nohdr = 0; | 688 | skb->nohdr = 0; |
@@ -2048,7 +2045,7 @@ skb_to_sgvec(struct sk_buff *skb, struct scatterlist *sg, int offset, int len) | |||
2048 | if (copy > 0) { | 2045 | if (copy > 0) { |
2049 | if (copy > len) | 2046 | if (copy > len) |
2050 | copy = len; | 2047 | copy = len; |
2051 | sg[elt].page = virt_to_page(skb->data + offset); | 2048 | sg_set_page(&sg[elt], virt_to_page(skb->data + offset)); |
2052 | sg[elt].offset = (unsigned long)(skb->data + offset) % PAGE_SIZE; | 2049 | sg[elt].offset = (unsigned long)(skb->data + offset) % PAGE_SIZE; |
2053 | sg[elt].length = copy; | 2050 | sg[elt].length = copy; |
2054 | elt++; | 2051 | elt++; |
@@ -2068,7 +2065,7 @@ skb_to_sgvec(struct sk_buff *skb, struct scatterlist *sg, int offset, int len) | |||
2068 | 2065 | ||
2069 | if (copy > len) | 2066 | if (copy > len) |
2070 | copy = len; | 2067 | copy = len; |
2071 | sg[elt].page = frag->page; | 2068 | sg_set_page(&sg[elt], frag->page); |
2072 | sg[elt].offset = frag->page_offset+offset-start; | 2069 | sg[elt].offset = frag->page_offset+offset-start; |
2073 | sg[elt].length = copy; | 2070 | sg[elt].length = copy; |
2074 | elt++; | 2071 | elt++; |
diff --git a/net/core/sock.c b/net/core/sock.c index d45ecdccc6a1..febbcbcf8022 100644 --- a/net/core/sock.c +++ b/net/core/sock.c | |||
@@ -232,7 +232,7 @@ static int sock_set_timeout(long *timeo_p, char __user *optval, int optlen) | |||
232 | warned++; | 232 | warned++; |
233 | printk(KERN_INFO "sock_set_timeout: `%s' (pid %d) " | 233 | printk(KERN_INFO "sock_set_timeout: `%s' (pid %d) " |
234 | "tries to set negative timeout\n", | 234 | "tries to set negative timeout\n", |
235 | current->comm, current->pid); | 235 | current->comm, task_pid_nr(current)); |
236 | return 0; | 236 | return 0; |
237 | } | 237 | } |
238 | *timeo_p = MAX_SCHEDULE_TIMEOUT; | 238 | *timeo_p = MAX_SCHEDULE_TIMEOUT; |
@@ -428,7 +428,6 @@ int sock_setsockopt(struct socket *sock, int level, int optname, | |||
428 | char __user *optval, int optlen) | 428 | char __user *optval, int optlen) |
429 | { | 429 | { |
430 | struct sock *sk=sock->sk; | 430 | struct sock *sk=sock->sk; |
431 | struct sk_filter *filter; | ||
432 | int val; | 431 | int val; |
433 | int valbool; | 432 | int valbool; |
434 | struct linger ling; | 433 | struct linger ling; |
@@ -652,16 +651,7 @@ set_rcvbuf: | |||
652 | break; | 651 | break; |
653 | 652 | ||
654 | case SO_DETACH_FILTER: | 653 | case SO_DETACH_FILTER: |
655 | rcu_read_lock_bh(); | 654 | ret = sk_detach_filter(sk); |
656 | filter = rcu_dereference(sk->sk_filter); | ||
657 | if (filter) { | ||
658 | rcu_assign_pointer(sk->sk_filter, NULL); | ||
659 | sk_filter_release(sk, filter); | ||
660 | rcu_read_unlock_bh(); | ||
661 | break; | ||
662 | } | ||
663 | rcu_read_unlock_bh(); | ||
664 | ret = -ENONET; | ||
665 | break; | 655 | break; |
666 | 656 | ||
667 | case SO_PASSSEC: | 657 | case SO_PASSSEC: |
@@ -925,7 +915,7 @@ void sk_free(struct sock *sk) | |||
925 | 915 | ||
926 | filter = rcu_dereference(sk->sk_filter); | 916 | filter = rcu_dereference(sk->sk_filter); |
927 | if (filter) { | 917 | if (filter) { |
928 | sk_filter_release(sk, filter); | 918 | sk_filter_uncharge(sk, filter); |
929 | rcu_assign_pointer(sk->sk_filter, NULL); | 919 | rcu_assign_pointer(sk->sk_filter, NULL); |
930 | } | 920 | } |
931 | 921 | ||
diff --git a/net/dccp/diag.c b/net/dccp/diag.c index 0f3745585a94..d8a3509b26f6 100644 --- a/net/dccp/diag.c +++ b/net/dccp/diag.c | |||
@@ -68,3 +68,4 @@ module_exit(dccp_diag_fini); | |||
68 | MODULE_LICENSE("GPL"); | 68 | MODULE_LICENSE("GPL"); |
69 | MODULE_AUTHOR("Arnaldo Carvalho de Melo <acme@mandriva.com>"); | 69 | MODULE_AUTHOR("Arnaldo Carvalho de Melo <acme@mandriva.com>"); |
70 | MODULE_DESCRIPTION("DCCP inet_diag handler"); | 70 | MODULE_DESCRIPTION("DCCP inet_diag handler"); |
71 | MODULE_ALIAS_NET_PF_PROTO_TYPE(PF_NETLINK, NETLINK_INET_DIAG, DCCPDIAG_GETSOCK); | ||
diff --git a/net/dccp/input.c b/net/dccp/input.c index 19d7e1dbd87e..3560a2a875a0 100644 --- a/net/dccp/input.c +++ b/net/dccp/input.c | |||
@@ -19,6 +19,9 @@ | |||
19 | #include "ccid.h" | 19 | #include "ccid.h" |
20 | #include "dccp.h" | 20 | #include "dccp.h" |
21 | 21 | ||
22 | /* rate-limit for syncs in reply to sequence-invalid packets; RFC 4340, 7.5.4 */ | ||
23 | int sysctl_dccp_sync_ratelimit __read_mostly = HZ / 8; | ||
24 | |||
22 | static void dccp_fin(struct sock *sk, struct sk_buff *skb) | 25 | static void dccp_fin(struct sock *sk, struct sk_buff *skb) |
23 | { | 26 | { |
24 | sk->sk_shutdown |= RCV_SHUTDOWN; | 27 | sk->sk_shutdown |= RCV_SHUTDOWN; |
diff --git a/net/dccp/ipv4.c b/net/dccp/ipv4.c index 44f6e17e105f..222549ab274a 100644 --- a/net/dccp/ipv4.c +++ b/net/dccp/ipv4.c | |||
@@ -1037,8 +1037,8 @@ module_exit(dccp_v4_exit); | |||
1037 | * values directly, Also cover the case where the protocol is not specified, | 1037 | * values directly, Also cover the case where the protocol is not specified, |
1038 | * i.e. net-pf-PF_INET-proto-0-type-SOCK_DCCP | 1038 | * i.e. net-pf-PF_INET-proto-0-type-SOCK_DCCP |
1039 | */ | 1039 | */ |
1040 | MODULE_ALIAS("net-pf-" __stringify(PF_INET) "-proto-33-type-6"); | 1040 | MODULE_ALIAS_NET_PF_PROTO_TYPE(PF_INET, 33, 6); |
1041 | MODULE_ALIAS("net-pf-" __stringify(PF_INET) "-proto-0-type-6"); | 1041 | MODULE_ALIAS_NET_PF_PROTO_TYPE(PF_INET, 0, 6); |
1042 | MODULE_LICENSE("GPL"); | 1042 | MODULE_LICENSE("GPL"); |
1043 | MODULE_AUTHOR("Arnaldo Carvalho de Melo <acme@mandriva.com>"); | 1043 | MODULE_AUTHOR("Arnaldo Carvalho de Melo <acme@mandriva.com>"); |
1044 | MODULE_DESCRIPTION("DCCP - Datagram Congestion Controlled Protocol"); | 1044 | MODULE_DESCRIPTION("DCCP - Datagram Congestion Controlled Protocol"); |
diff --git a/net/dccp/ipv6.c b/net/dccp/ipv6.c index 006a3834fbcd..bbadd6681b83 100644 --- a/net/dccp/ipv6.c +++ b/net/dccp/ipv6.c | |||
@@ -767,10 +767,9 @@ discard: | |||
767 | return 0; | 767 | return 0; |
768 | } | 768 | } |
769 | 769 | ||
770 | static int dccp_v6_rcv(struct sk_buff **pskb) | 770 | static int dccp_v6_rcv(struct sk_buff *skb) |
771 | { | 771 | { |
772 | const struct dccp_hdr *dh; | 772 | const struct dccp_hdr *dh; |
773 | struct sk_buff *skb = *pskb; | ||
774 | struct sock *sk; | 773 | struct sock *sk; |
775 | int min_cov; | 774 | int min_cov; |
776 | 775 | ||
@@ -1220,8 +1219,8 @@ module_exit(dccp_v6_exit); | |||
1220 | * values directly, Also cover the case where the protocol is not specified, | 1219 | * values directly, Also cover the case where the protocol is not specified, |
1221 | * i.e. net-pf-PF_INET6-proto-0-type-SOCK_DCCP | 1220 | * i.e. net-pf-PF_INET6-proto-0-type-SOCK_DCCP |
1222 | */ | 1221 | */ |
1223 | MODULE_ALIAS("net-pf-" __stringify(PF_INET6) "-proto-33-type-6"); | 1222 | MODULE_ALIAS_NET_PF_PROTO_TYPE(PF_INET6, 33, 6); |
1224 | MODULE_ALIAS("net-pf-" __stringify(PF_INET6) "-proto-0-type-6"); | 1223 | MODULE_ALIAS_NET_PF_PROTO_TYPE(PF_INET6, 0, 6); |
1225 | MODULE_LICENSE("GPL"); | 1224 | MODULE_LICENSE("GPL"); |
1226 | MODULE_AUTHOR("Arnaldo Carvalho de Melo <acme@mandriva.com>"); | 1225 | MODULE_AUTHOR("Arnaldo Carvalho de Melo <acme@mandriva.com>"); |
1227 | MODULE_DESCRIPTION("DCCPv6 - Datagram Congestion Controlled Protocol"); | 1226 | MODULE_DESCRIPTION("DCCPv6 - Datagram Congestion Controlled Protocol"); |
diff --git a/net/dccp/sysctl.c b/net/dccp/sysctl.c index 9364b2fb4dbd..c62c05039f69 100644 --- a/net/dccp/sysctl.c +++ b/net/dccp/sysctl.c | |||
@@ -18,9 +18,6 @@ | |||
18 | #error This file should not be compiled without CONFIG_SYSCTL defined | 18 | #error This file should not be compiled without CONFIG_SYSCTL defined |
19 | #endif | 19 | #endif |
20 | 20 | ||
21 | /* rate-limit for syncs in reply to sequence-invalid packets; RFC 4340, 7.5.4 */ | ||
22 | int sysctl_dccp_sync_ratelimit __read_mostly = HZ / 8; | ||
23 | |||
24 | static struct ctl_table dccp_default_table[] = { | 21 | static struct ctl_table dccp_default_table[] = { |
25 | { | 22 | { |
26 | .procname = "seq_window", | 23 | .procname = "seq_window", |
diff --git a/net/decnet/netfilter/dn_rtmsg.c b/net/decnet/netfilter/dn_rtmsg.c index f7fba7721e63..43fcd29046d1 100644 --- a/net/decnet/netfilter/dn_rtmsg.c +++ b/net/decnet/netfilter/dn_rtmsg.c | |||
@@ -88,12 +88,12 @@ static void dnrmg_send_peer(struct sk_buff *skb) | |||
88 | 88 | ||
89 | 89 | ||
90 | static unsigned int dnrmg_hook(unsigned int hook, | 90 | static unsigned int dnrmg_hook(unsigned int hook, |
91 | struct sk_buff **pskb, | 91 | struct sk_buff *skb, |
92 | const struct net_device *in, | 92 | const struct net_device *in, |
93 | const struct net_device *out, | 93 | const struct net_device *out, |
94 | int (*okfn)(struct sk_buff *)) | 94 | int (*okfn)(struct sk_buff *)) |
95 | { | 95 | { |
96 | dnrmg_send_peer(*pskb); | 96 | dnrmg_send_peer(skb); |
97 | return NF_ACCEPT; | 97 | return NF_ACCEPT; |
98 | } | 98 | } |
99 | 99 | ||
diff --git a/net/ieee80211/ieee80211_crypt_tkip.c b/net/ieee80211/ieee80211_crypt_tkip.c index 6cc54eeca3ed..c796661a021b 100644 --- a/net/ieee80211/ieee80211_crypt_tkip.c +++ b/net/ieee80211/ieee80211_crypt_tkip.c | |||
@@ -390,9 +390,7 @@ static int ieee80211_tkip_encrypt(struct sk_buff *skb, int hdr_len, void *priv) | |||
390 | icv[3] = crc >> 24; | 390 | icv[3] = crc >> 24; |
391 | 391 | ||
392 | crypto_blkcipher_setkey(tkey->tx_tfm_arc4, rc4key, 16); | 392 | crypto_blkcipher_setkey(tkey->tx_tfm_arc4, rc4key, 16); |
393 | sg.page = virt_to_page(pos); | 393 | sg_init_one(&sg, pos, len + 4); |
394 | sg.offset = offset_in_page(pos); | ||
395 | sg.length = len + 4; | ||
396 | return crypto_blkcipher_encrypt(&desc, &sg, &sg, len + 4); | 394 | return crypto_blkcipher_encrypt(&desc, &sg, &sg, len + 4); |
397 | } | 395 | } |
398 | 396 | ||
@@ -485,9 +483,7 @@ static int ieee80211_tkip_decrypt(struct sk_buff *skb, int hdr_len, void *priv) | |||
485 | plen = skb->len - hdr_len - 12; | 483 | plen = skb->len - hdr_len - 12; |
486 | 484 | ||
487 | crypto_blkcipher_setkey(tkey->rx_tfm_arc4, rc4key, 16); | 485 | crypto_blkcipher_setkey(tkey->rx_tfm_arc4, rc4key, 16); |
488 | sg.page = virt_to_page(pos); | 486 | sg_init_one(&sg, pos, plen + 4); |
489 | sg.offset = offset_in_page(pos); | ||
490 | sg.length = plen + 4; | ||
491 | if (crypto_blkcipher_decrypt(&desc, &sg, &sg, plen + 4)) { | 487 | if (crypto_blkcipher_decrypt(&desc, &sg, &sg, plen + 4)) { |
492 | if (net_ratelimit()) { | 488 | if (net_ratelimit()) { |
493 | printk(KERN_DEBUG ": TKIP: failed to decrypt " | 489 | printk(KERN_DEBUG ": TKIP: failed to decrypt " |
@@ -539,11 +535,12 @@ static int michael_mic(struct crypto_hash *tfm_michael, u8 * key, u8 * hdr, | |||
539 | printk(KERN_WARNING "michael_mic: tfm_michael == NULL\n"); | 535 | printk(KERN_WARNING "michael_mic: tfm_michael == NULL\n"); |
540 | return -1; | 536 | return -1; |
541 | } | 537 | } |
542 | sg[0].page = virt_to_page(hdr); | 538 | sg_init_table(sg, 2); |
539 | sg_set_page(&sg[0], virt_to_page(hdr)); | ||
543 | sg[0].offset = offset_in_page(hdr); | 540 | sg[0].offset = offset_in_page(hdr); |
544 | sg[0].length = 16; | 541 | sg[0].length = 16; |
545 | 542 | ||
546 | sg[1].page = virt_to_page(data); | 543 | sg_set_page(&sg[1], virt_to_page(data)); |
547 | sg[1].offset = offset_in_page(data); | 544 | sg[1].offset = offset_in_page(data); |
548 | sg[1].length = data_len; | 545 | sg[1].length = data_len; |
549 | 546 | ||
@@ -586,7 +583,7 @@ static void michael_mic_hdr(struct sk_buff *skb, u8 * hdr) | |||
586 | if (stype & IEEE80211_STYPE_QOS_DATA) { | 583 | if (stype & IEEE80211_STYPE_QOS_DATA) { |
587 | const struct ieee80211_hdr_3addrqos *qoshdr = | 584 | const struct ieee80211_hdr_3addrqos *qoshdr = |
588 | (struct ieee80211_hdr_3addrqos *)skb->data; | 585 | (struct ieee80211_hdr_3addrqos *)skb->data; |
589 | hdr[12] = qoshdr->qos_ctl & cpu_to_le16(IEEE80211_QCTL_TID); | 586 | hdr[12] = le16_to_cpu(qoshdr->qos_ctl) & IEEE80211_QCTL_TID; |
590 | } else | 587 | } else |
591 | hdr[12] = 0; /* priority */ | 588 | hdr[12] = 0; /* priority */ |
592 | 589 | ||
diff --git a/net/ieee80211/ieee80211_crypt_wep.c b/net/ieee80211/ieee80211_crypt_wep.c index 8d182459344e..0af6103d715c 100644 --- a/net/ieee80211/ieee80211_crypt_wep.c +++ b/net/ieee80211/ieee80211_crypt_wep.c | |||
@@ -170,9 +170,7 @@ static int prism2_wep_encrypt(struct sk_buff *skb, int hdr_len, void *priv) | |||
170 | icv[3] = crc >> 24; | 170 | icv[3] = crc >> 24; |
171 | 171 | ||
172 | crypto_blkcipher_setkey(wep->tx_tfm, key, klen); | 172 | crypto_blkcipher_setkey(wep->tx_tfm, key, klen); |
173 | sg.page = virt_to_page(pos); | 173 | sg_init_one(&sg, pos, len + 4); |
174 | sg.offset = offset_in_page(pos); | ||
175 | sg.length = len + 4; | ||
176 | return crypto_blkcipher_encrypt(&desc, &sg, &sg, len + 4); | 174 | return crypto_blkcipher_encrypt(&desc, &sg, &sg, len + 4); |
177 | } | 175 | } |
178 | 176 | ||
@@ -212,9 +210,7 @@ static int prism2_wep_decrypt(struct sk_buff *skb, int hdr_len, void *priv) | |||
212 | plen = skb->len - hdr_len - 8; | 210 | plen = skb->len - hdr_len - 8; |
213 | 211 | ||
214 | crypto_blkcipher_setkey(wep->rx_tfm, key, klen); | 212 | crypto_blkcipher_setkey(wep->rx_tfm, key, klen); |
215 | sg.page = virt_to_page(pos); | 213 | sg_init_one(&sg, pos, plen + 4); |
216 | sg.offset = offset_in_page(pos); | ||
217 | sg.length = plen + 4; | ||
218 | if (crypto_blkcipher_decrypt(&desc, &sg, &sg, plen + 4)) | 214 | if (crypto_blkcipher_decrypt(&desc, &sg, &sg, plen + 4)) |
219 | return -7; | 215 | return -7; |
220 | 216 | ||
diff --git a/net/ieee80211/ieee80211_wx.c b/net/ieee80211/ieee80211_wx.c index 9b58dd67acb6..d309e8f19992 100644 --- a/net/ieee80211/ieee80211_wx.c +++ b/net/ieee80211/ieee80211_wx.c | |||
@@ -409,7 +409,7 @@ int ieee80211_wx_set_encode(struct ieee80211_device *ieee, | |||
409 | (*crypt)->priv); | 409 | (*crypt)->priv); |
410 | sec.flags |= (1 << key); | 410 | sec.flags |= (1 << key); |
411 | /* This ensures a key will be activated if no key is | 411 | /* This ensures a key will be activated if no key is |
412 | * explicitely set */ | 412 | * explicitly set */ |
413 | if (key == sec.active_key) | 413 | if (key == sec.active_key) |
414 | sec.flags |= SEC_ACTIVE_KEY; | 414 | sec.flags |= SEC_ACTIVE_KEY; |
415 | 415 | ||
diff --git a/net/ipv4/Kconfig b/net/ipv4/Kconfig index d894f616c3d6..9f9fd2c6f6e2 100644 --- a/net/ipv4/Kconfig +++ b/net/ipv4/Kconfig | |||
@@ -560,7 +560,7 @@ config TCP_CONG_ILLINOIS | |||
560 | depends on EXPERIMENTAL | 560 | depends on EXPERIMENTAL |
561 | default n | 561 | default n |
562 | ---help--- | 562 | ---help--- |
563 | TCP-Illinois is a sender-side modificatio of TCP Reno for | 563 | TCP-Illinois is a sender-side modification of TCP Reno for |
564 | high speed long delay links. It uses round-trip-time to | 564 | high speed long delay links. It uses round-trip-time to |
565 | adjust the alpha and beta parameters to achieve a higher average | 565 | adjust the alpha and beta parameters to achieve a higher average |
566 | throughput and maintain fairness. | 566 | throughput and maintain fairness. |
diff --git a/net/ipv4/Makefile b/net/ipv4/Makefile index a02c36d0a13e..93fe3966805d 100644 --- a/net/ipv4/Makefile +++ b/net/ipv4/Makefile | |||
@@ -10,7 +10,8 @@ obj-y := route.o inetpeer.o protocol.o \ | |||
10 | tcp_minisocks.o tcp_cong.o \ | 10 | tcp_minisocks.o tcp_cong.o \ |
11 | datagram.o raw.o udp.o udplite.o \ | 11 | datagram.o raw.o udp.o udplite.o \ |
12 | arp.o icmp.o devinet.o af_inet.o igmp.o \ | 12 | arp.o icmp.o devinet.o af_inet.o igmp.o \ |
13 | sysctl_net_ipv4.o fib_frontend.o fib_semantics.o | 13 | sysctl_net_ipv4.o fib_frontend.o fib_semantics.o \ |
14 | inet_fragment.o | ||
14 | 15 | ||
15 | obj-$(CONFIG_IP_FIB_HASH) += fib_hash.o | 16 | obj-$(CONFIG_IP_FIB_HASH) += fib_hash.o |
16 | obj-$(CONFIG_IP_FIB_TRIE) += fib_trie.o | 17 | obj-$(CONFIG_IP_FIB_TRIE) += fib_trie.o |
diff --git a/net/ipv4/fib_trie.c b/net/ipv4/fib_trie.c index 81a8285d6d6a..8d8c2915e064 100644 --- a/net/ipv4/fib_trie.c +++ b/net/ipv4/fib_trie.c | |||
@@ -54,7 +54,7 @@ | |||
54 | 54 | ||
55 | #include <asm/uaccess.h> | 55 | #include <asm/uaccess.h> |
56 | #include <asm/system.h> | 56 | #include <asm/system.h> |
57 | #include <asm/bitops.h> | 57 | #include <linux/bitops.h> |
58 | #include <linux/types.h> | 58 | #include <linux/types.h> |
59 | #include <linux/kernel.h> | 59 | #include <linux/kernel.h> |
60 | #include <linux/mm.h> | 60 | #include <linux/mm.h> |
diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c index 3cef12835c4b..8fb6ca23700a 100644 --- a/net/ipv4/inet_connection_sock.c +++ b/net/ipv4/inet_connection_sock.c | |||
@@ -93,7 +93,7 @@ int inet_csk_get_port(struct inet_hashinfo *hashinfo, | |||
93 | int remaining, rover, low, high; | 93 | int remaining, rover, low, high; |
94 | 94 | ||
95 | inet_get_local_port_range(&low, &high); | 95 | inet_get_local_port_range(&low, &high); |
96 | remaining = high - low; | 96 | remaining = (high - low) + 1; |
97 | rover = net_random() % remaining + low; | 97 | rover = net_random() % remaining + low; |
98 | 98 | ||
99 | do { | 99 | do { |
diff --git a/net/ipv4/inet_diag.c b/net/ipv4/inet_diag.c index 7eb83ebed2ec..dc429b6b0ba6 100644 --- a/net/ipv4/inet_diag.c +++ b/net/ipv4/inet_diag.c | |||
@@ -815,6 +815,12 @@ static int inet_diag_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh) | |||
815 | nlmsg_len(nlh) < hdrlen) | 815 | nlmsg_len(nlh) < hdrlen) |
816 | return -EINVAL; | 816 | return -EINVAL; |
817 | 817 | ||
818 | #ifdef CONFIG_KMOD | ||
819 | if (inet_diag_table[nlh->nlmsg_type] == NULL) | ||
820 | request_module("net-pf-%d-proto-%d-type-%d", PF_NETLINK, | ||
821 | NETLINK_INET_DIAG, nlh->nlmsg_type); | ||
822 | #endif | ||
823 | |||
818 | if (inet_diag_table[nlh->nlmsg_type] == NULL) | 824 | if (inet_diag_table[nlh->nlmsg_type] == NULL) |
819 | return -ENOENT; | 825 | return -ENOENT; |
820 | 826 | ||
@@ -914,3 +920,4 @@ static void __exit inet_diag_exit(void) | |||
914 | module_init(inet_diag_init); | 920 | module_init(inet_diag_init); |
915 | module_exit(inet_diag_exit); | 921 | module_exit(inet_diag_exit); |
916 | MODULE_LICENSE("GPL"); | 922 | MODULE_LICENSE("GPL"); |
923 | MODULE_ALIAS_NET_PF_PROTO(PF_NETLINK, NETLINK_INET_DIAG); | ||
diff --git a/net/ipv4/inet_fragment.c b/net/ipv4/inet_fragment.c new file mode 100644 index 000000000000..e15e04fc6661 --- /dev/null +++ b/net/ipv4/inet_fragment.c | |||
@@ -0,0 +1,261 @@ | |||
1 | /* | ||
2 | * inet fragments management | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or | ||
5 | * modify it under the terms of the GNU General Public License | ||
6 | * as published by the Free Software Foundation; either version | ||
7 | * 2 of the License, or (at your option) any later version. | ||
8 | * | ||
9 | * Authors: Pavel Emelyanov <xemul@openvz.org> | ||
10 | * Started as consolidation of ipv4/ip_fragment.c, | ||
11 | * ipv6/reassembly. and ipv6 nf conntrack reassembly | ||
12 | */ | ||
13 | |||
14 | #include <linux/list.h> | ||
15 | #include <linux/spinlock.h> | ||
16 | #include <linux/module.h> | ||
17 | #include <linux/timer.h> | ||
18 | #include <linux/mm.h> | ||
19 | #include <linux/random.h> | ||
20 | #include <linux/skbuff.h> | ||
21 | #include <linux/rtnetlink.h> | ||
22 | |||
23 | #include <net/inet_frag.h> | ||
24 | |||
25 | static void inet_frag_secret_rebuild(unsigned long dummy) | ||
26 | { | ||
27 | struct inet_frags *f = (struct inet_frags *)dummy; | ||
28 | unsigned long now = jiffies; | ||
29 | int i; | ||
30 | |||
31 | write_lock(&f->lock); | ||
32 | get_random_bytes(&f->rnd, sizeof(u32)); | ||
33 | for (i = 0; i < INETFRAGS_HASHSZ; i++) { | ||
34 | struct inet_frag_queue *q; | ||
35 | struct hlist_node *p, *n; | ||
36 | |||
37 | hlist_for_each_entry_safe(q, p, n, &f->hash[i], list) { | ||
38 | unsigned int hval = f->hashfn(q); | ||
39 | |||
40 | if (hval != i) { | ||
41 | hlist_del(&q->list); | ||
42 | |||
43 | /* Relink to new hash chain. */ | ||
44 | hlist_add_head(&q->list, &f->hash[hval]); | ||
45 | } | ||
46 | } | ||
47 | } | ||
48 | write_unlock(&f->lock); | ||
49 | |||
50 | mod_timer(&f->secret_timer, now + f->ctl->secret_interval); | ||
51 | } | ||
52 | |||
53 | void inet_frags_init(struct inet_frags *f) | ||
54 | { | ||
55 | int i; | ||
56 | |||
57 | for (i = 0; i < INETFRAGS_HASHSZ; i++) | ||
58 | INIT_HLIST_HEAD(&f->hash[i]); | ||
59 | |||
60 | INIT_LIST_HEAD(&f->lru_list); | ||
61 | rwlock_init(&f->lock); | ||
62 | |||
63 | f->rnd = (u32) ((num_physpages ^ (num_physpages>>7)) ^ | ||
64 | (jiffies ^ (jiffies >> 6))); | ||
65 | |||
66 | f->nqueues = 0; | ||
67 | atomic_set(&f->mem, 0); | ||
68 | |||
69 | init_timer(&f->secret_timer); | ||
70 | f->secret_timer.function = inet_frag_secret_rebuild; | ||
71 | f->secret_timer.data = (unsigned long)f; | ||
72 | f->secret_timer.expires = jiffies + f->ctl->secret_interval; | ||
73 | add_timer(&f->secret_timer); | ||
74 | } | ||
75 | EXPORT_SYMBOL(inet_frags_init); | ||
76 | |||
77 | void inet_frags_fini(struct inet_frags *f) | ||
78 | { | ||
79 | del_timer(&f->secret_timer); | ||
80 | } | ||
81 | EXPORT_SYMBOL(inet_frags_fini); | ||
82 | |||
83 | static inline void fq_unlink(struct inet_frag_queue *fq, struct inet_frags *f) | ||
84 | { | ||
85 | write_lock(&f->lock); | ||
86 | hlist_del(&fq->list); | ||
87 | list_del(&fq->lru_list); | ||
88 | f->nqueues--; | ||
89 | write_unlock(&f->lock); | ||
90 | } | ||
91 | |||
92 | void inet_frag_kill(struct inet_frag_queue *fq, struct inet_frags *f) | ||
93 | { | ||
94 | if (del_timer(&fq->timer)) | ||
95 | atomic_dec(&fq->refcnt); | ||
96 | |||
97 | if (!(fq->last_in & COMPLETE)) { | ||
98 | fq_unlink(fq, f); | ||
99 | atomic_dec(&fq->refcnt); | ||
100 | fq->last_in |= COMPLETE; | ||
101 | } | ||
102 | } | ||
103 | |||
104 | EXPORT_SYMBOL(inet_frag_kill); | ||
105 | |||
106 | static inline void frag_kfree_skb(struct inet_frags *f, struct sk_buff *skb, | ||
107 | int *work) | ||
108 | { | ||
109 | if (work) | ||
110 | *work -= skb->truesize; | ||
111 | |||
112 | atomic_sub(skb->truesize, &f->mem); | ||
113 | if (f->skb_free) | ||
114 | f->skb_free(skb); | ||
115 | kfree_skb(skb); | ||
116 | } | ||
117 | |||
118 | void inet_frag_destroy(struct inet_frag_queue *q, struct inet_frags *f, | ||
119 | int *work) | ||
120 | { | ||
121 | struct sk_buff *fp; | ||
122 | |||
123 | BUG_TRAP(q->last_in & COMPLETE); | ||
124 | BUG_TRAP(del_timer(&q->timer) == 0); | ||
125 | |||
126 | /* Release all fragment data. */ | ||
127 | fp = q->fragments; | ||
128 | while (fp) { | ||
129 | struct sk_buff *xp = fp->next; | ||
130 | |||
131 | frag_kfree_skb(f, fp, work); | ||
132 | fp = xp; | ||
133 | } | ||
134 | |||
135 | if (work) | ||
136 | *work -= f->qsize; | ||
137 | atomic_sub(f->qsize, &f->mem); | ||
138 | |||
139 | if (f->destructor) | ||
140 | f->destructor(q); | ||
141 | kfree(q); | ||
142 | |||
143 | } | ||
144 | EXPORT_SYMBOL(inet_frag_destroy); | ||
145 | |||
146 | int inet_frag_evictor(struct inet_frags *f) | ||
147 | { | ||
148 | struct inet_frag_queue *q; | ||
149 | int work, evicted = 0; | ||
150 | |||
151 | work = atomic_read(&f->mem) - f->ctl->low_thresh; | ||
152 | while (work > 0) { | ||
153 | read_lock(&f->lock); | ||
154 | if (list_empty(&f->lru_list)) { | ||
155 | read_unlock(&f->lock); | ||
156 | break; | ||
157 | } | ||
158 | |||
159 | q = list_first_entry(&f->lru_list, | ||
160 | struct inet_frag_queue, lru_list); | ||
161 | atomic_inc(&q->refcnt); | ||
162 | read_unlock(&f->lock); | ||
163 | |||
164 | spin_lock(&q->lock); | ||
165 | if (!(q->last_in & COMPLETE)) | ||
166 | inet_frag_kill(q, f); | ||
167 | spin_unlock(&q->lock); | ||
168 | |||
169 | if (atomic_dec_and_test(&q->refcnt)) | ||
170 | inet_frag_destroy(q, f, &work); | ||
171 | evicted++; | ||
172 | } | ||
173 | |||
174 | return evicted; | ||
175 | } | ||
176 | EXPORT_SYMBOL(inet_frag_evictor); | ||
177 | |||
178 | static struct inet_frag_queue *inet_frag_intern(struct inet_frag_queue *qp_in, | ||
179 | struct inet_frags *f, unsigned int hash, void *arg) | ||
180 | { | ||
181 | struct inet_frag_queue *qp; | ||
182 | #ifdef CONFIG_SMP | ||
183 | struct hlist_node *n; | ||
184 | #endif | ||
185 | |||
186 | write_lock(&f->lock); | ||
187 | #ifdef CONFIG_SMP | ||
188 | /* With SMP race we have to recheck hash table, because | ||
189 | * such entry could be created on other cpu, while we | ||
190 | * promoted read lock to write lock. | ||
191 | */ | ||
192 | hlist_for_each_entry(qp, n, &f->hash[hash], list) { | ||
193 | if (f->match(qp, arg)) { | ||
194 | atomic_inc(&qp->refcnt); | ||
195 | write_unlock(&f->lock); | ||
196 | qp_in->last_in |= COMPLETE; | ||
197 | inet_frag_put(qp_in, f); | ||
198 | return qp; | ||
199 | } | ||
200 | } | ||
201 | #endif | ||
202 | qp = qp_in; | ||
203 | if (!mod_timer(&qp->timer, jiffies + f->ctl->timeout)) | ||
204 | atomic_inc(&qp->refcnt); | ||
205 | |||
206 | atomic_inc(&qp->refcnt); | ||
207 | hlist_add_head(&qp->list, &f->hash[hash]); | ||
208 | list_add_tail(&qp->lru_list, &f->lru_list); | ||
209 | f->nqueues++; | ||
210 | write_unlock(&f->lock); | ||
211 | return qp; | ||
212 | } | ||
213 | |||
214 | static struct inet_frag_queue *inet_frag_alloc(struct inet_frags *f, void *arg) | ||
215 | { | ||
216 | struct inet_frag_queue *q; | ||
217 | |||
218 | q = kzalloc(f->qsize, GFP_ATOMIC); | ||
219 | if (q == NULL) | ||
220 | return NULL; | ||
221 | |||
222 | f->constructor(q, arg); | ||
223 | atomic_add(f->qsize, &f->mem); | ||
224 | setup_timer(&q->timer, f->frag_expire, (unsigned long)q); | ||
225 | spin_lock_init(&q->lock); | ||
226 | atomic_set(&q->refcnt, 1); | ||
227 | |||
228 | return q; | ||
229 | } | ||
230 | |||
231 | static struct inet_frag_queue *inet_frag_create(struct inet_frags *f, | ||
232 | void *arg, unsigned int hash) | ||
233 | { | ||
234 | struct inet_frag_queue *q; | ||
235 | |||
236 | q = inet_frag_alloc(f, arg); | ||
237 | if (q == NULL) | ||
238 | return NULL; | ||
239 | |||
240 | return inet_frag_intern(q, f, hash, arg); | ||
241 | } | ||
242 | |||
243 | struct inet_frag_queue *inet_frag_find(struct inet_frags *f, void *key, | ||
244 | unsigned int hash) | ||
245 | { | ||
246 | struct inet_frag_queue *q; | ||
247 | struct hlist_node *n; | ||
248 | |||
249 | read_lock(&f->lock); | ||
250 | hlist_for_each_entry(q, n, &f->hash[hash], list) { | ||
251 | if (f->match(q, key)) { | ||
252 | atomic_inc(&q->refcnt); | ||
253 | read_unlock(&f->lock); | ||
254 | return q; | ||
255 | } | ||
256 | } | ||
257 | read_unlock(&f->lock); | ||
258 | |||
259 | return inet_frag_create(f, key, hash); | ||
260 | } | ||
261 | EXPORT_SYMBOL(inet_frag_find); | ||
diff --git a/net/ipv4/inet_hashtables.c b/net/ipv4/inet_hashtables.c index fac6398e4367..16eecc7046a3 100644 --- a/net/ipv4/inet_hashtables.c +++ b/net/ipv4/inet_hashtables.c | |||
@@ -286,7 +286,7 @@ int inet_hash_connect(struct inet_timewait_death_row *death_row, | |||
286 | struct inet_timewait_sock *tw = NULL; | 286 | struct inet_timewait_sock *tw = NULL; |
287 | 287 | ||
288 | inet_get_local_port_range(&low, &high); | 288 | inet_get_local_port_range(&low, &high); |
289 | remaining = high - low; | 289 | remaining = (high - low) + 1; |
290 | 290 | ||
291 | local_bh_disable(); | 291 | local_bh_disable(); |
292 | for (i = 1; i <= remaining; i++) { | 292 | for (i = 1; i <= remaining; i++) { |
diff --git a/net/ipv4/ip_forward.c b/net/ipv4/ip_forward.c index afbf938836f5..877da3ed52e2 100644 --- a/net/ipv4/ip_forward.c +++ b/net/ipv4/ip_forward.c | |||
@@ -40,7 +40,7 @@ | |||
40 | #include <net/route.h> | 40 | #include <net/route.h> |
41 | #include <net/xfrm.h> | 41 | #include <net/xfrm.h> |
42 | 42 | ||
43 | static inline int ip_forward_finish(struct sk_buff *skb) | 43 | static int ip_forward_finish(struct sk_buff *skb) |
44 | { | 44 | { |
45 | struct ip_options * opt = &(IPCB(skb)->opt); | 45 | struct ip_options * opt = &(IPCB(skb)->opt); |
46 | 46 | ||
diff --git a/net/ipv4/ip_fragment.c b/net/ipv4/ip_fragment.c index fabb86db763b..2143bf30597a 100644 --- a/net/ipv4/ip_fragment.c +++ b/net/ipv4/ip_fragment.c | |||
@@ -39,6 +39,7 @@ | |||
39 | #include <net/icmp.h> | 39 | #include <net/icmp.h> |
40 | #include <net/checksum.h> | 40 | #include <net/checksum.h> |
41 | #include <net/inetpeer.h> | 41 | #include <net/inetpeer.h> |
42 | #include <net/inet_frag.h> | ||
42 | #include <linux/tcp.h> | 43 | #include <linux/tcp.h> |
43 | #include <linux/udp.h> | 44 | #include <linux/udp.h> |
44 | #include <linux/inet.h> | 45 | #include <linux/inet.h> |
@@ -49,21 +50,8 @@ | |||
49 | * as well. Or notify me, at least. --ANK | 50 | * as well. Or notify me, at least. --ANK |
50 | */ | 51 | */ |
51 | 52 | ||
52 | /* Fragment cache limits. We will commit 256K at one time. Should we | ||
53 | * cross that limit we will prune down to 192K. This should cope with | ||
54 | * even the most extreme cases without allowing an attacker to measurably | ||
55 | * harm machine performance. | ||
56 | */ | ||
57 | int sysctl_ipfrag_high_thresh __read_mostly = 256*1024; | ||
58 | int sysctl_ipfrag_low_thresh __read_mostly = 192*1024; | ||
59 | |||
60 | int sysctl_ipfrag_max_dist __read_mostly = 64; | 53 | int sysctl_ipfrag_max_dist __read_mostly = 64; |
61 | 54 | ||
62 | /* Important NOTE! Fragment queue must be destroyed before MSL expires. | ||
63 | * RFC791 is wrong proposing to prolongate timer each fragment arrival by TTL. | ||
64 | */ | ||
65 | int sysctl_ipfrag_time __read_mostly = IP_FRAG_TIME; | ||
66 | |||
67 | struct ipfrag_skb_cb | 55 | struct ipfrag_skb_cb |
68 | { | 56 | { |
69 | struct inet_skb_parm h; | 57 | struct inet_skb_parm h; |
@@ -74,153 +62,123 @@ struct ipfrag_skb_cb | |||
74 | 62 | ||
75 | /* Describe an entry in the "incomplete datagrams" queue. */ | 63 | /* Describe an entry in the "incomplete datagrams" queue. */ |
76 | struct ipq { | 64 | struct ipq { |
77 | struct hlist_node list; | 65 | struct inet_frag_queue q; |
78 | struct list_head lru_list; /* lru list member */ | 66 | |
79 | u32 user; | 67 | u32 user; |
80 | __be32 saddr; | 68 | __be32 saddr; |
81 | __be32 daddr; | 69 | __be32 daddr; |
82 | __be16 id; | 70 | __be16 id; |
83 | u8 protocol; | 71 | u8 protocol; |
84 | u8 last_in; | ||
85 | #define COMPLETE 4 | ||
86 | #define FIRST_IN 2 | ||
87 | #define LAST_IN 1 | ||
88 | |||
89 | struct sk_buff *fragments; /* linked list of received fragments */ | ||
90 | int len; /* total length of original datagram */ | ||
91 | int meat; | ||
92 | spinlock_t lock; | ||
93 | atomic_t refcnt; | ||
94 | struct timer_list timer; /* when will this queue expire? */ | ||
95 | ktime_t stamp; | ||
96 | int iif; | 72 | int iif; |
97 | unsigned int rid; | 73 | unsigned int rid; |
98 | struct inet_peer *peer; | 74 | struct inet_peer *peer; |
99 | }; | 75 | }; |
100 | 76 | ||
101 | /* Hash table. */ | 77 | struct inet_frags_ctl ip4_frags_ctl __read_mostly = { |
78 | /* | ||
79 | * Fragment cache limits. We will commit 256K at one time. Should we | ||
80 | * cross that limit we will prune down to 192K. This should cope with | ||
81 | * even the most extreme cases without allowing an attacker to | ||
82 | * measurably harm machine performance. | ||
83 | */ | ||
84 | .high_thresh = 256 * 1024, | ||
85 | .low_thresh = 192 * 1024, | ||
102 | 86 | ||
103 | #define IPQ_HASHSZ 64 | 87 | /* |
88 | * Important NOTE! Fragment queue must be destroyed before MSL expires. | ||
89 | * RFC791 is wrong proposing to prolongate timer each fragment arrival | ||
90 | * by TTL. | ||
91 | */ | ||
92 | .timeout = IP_FRAG_TIME, | ||
93 | .secret_interval = 10 * 60 * HZ, | ||
94 | }; | ||
104 | 95 | ||
105 | /* Per-bucket lock is easy to add now. */ | 96 | static struct inet_frags ip4_frags; |
106 | static struct hlist_head ipq_hash[IPQ_HASHSZ]; | ||
107 | static DEFINE_RWLOCK(ipfrag_lock); | ||
108 | static u32 ipfrag_hash_rnd; | ||
109 | static LIST_HEAD(ipq_lru_list); | ||
110 | int ip_frag_nqueues = 0; | ||
111 | 97 | ||
112 | static __inline__ void __ipq_unlink(struct ipq *qp) | 98 | int ip_frag_nqueues(void) |
113 | { | 99 | { |
114 | hlist_del(&qp->list); | 100 | return ip4_frags.nqueues; |
115 | list_del(&qp->lru_list); | ||
116 | ip_frag_nqueues--; | ||
117 | } | 101 | } |
118 | 102 | ||
119 | static __inline__ void ipq_unlink(struct ipq *ipq) | 103 | int ip_frag_mem(void) |
120 | { | 104 | { |
121 | write_lock(&ipfrag_lock); | 105 | return atomic_read(&ip4_frags.mem); |
122 | __ipq_unlink(ipq); | ||
123 | write_unlock(&ipfrag_lock); | ||
124 | } | 106 | } |
125 | 107 | ||
108 | static int ip_frag_reasm(struct ipq *qp, struct sk_buff *prev, | ||
109 | struct net_device *dev); | ||
110 | |||
111 | struct ip4_create_arg { | ||
112 | struct iphdr *iph; | ||
113 | u32 user; | ||
114 | }; | ||
115 | |||
126 | static unsigned int ipqhashfn(__be16 id, __be32 saddr, __be32 daddr, u8 prot) | 116 | static unsigned int ipqhashfn(__be16 id, __be32 saddr, __be32 daddr, u8 prot) |
127 | { | 117 | { |
128 | return jhash_3words((__force u32)id << 16 | prot, | 118 | return jhash_3words((__force u32)id << 16 | prot, |
129 | (__force u32)saddr, (__force u32)daddr, | 119 | (__force u32)saddr, (__force u32)daddr, |
130 | ipfrag_hash_rnd) & (IPQ_HASHSZ - 1); | 120 | ip4_frags.rnd) & (INETFRAGS_HASHSZ - 1); |
131 | } | 121 | } |
132 | 122 | ||
133 | static struct timer_list ipfrag_secret_timer; | 123 | static unsigned int ip4_hashfn(struct inet_frag_queue *q) |
134 | int sysctl_ipfrag_secret_interval __read_mostly = 10 * 60 * HZ; | ||
135 | |||
136 | static void ipfrag_secret_rebuild(unsigned long dummy) | ||
137 | { | 124 | { |
138 | unsigned long now = jiffies; | 125 | struct ipq *ipq; |
139 | int i; | ||
140 | 126 | ||
141 | write_lock(&ipfrag_lock); | 127 | ipq = container_of(q, struct ipq, q); |
142 | get_random_bytes(&ipfrag_hash_rnd, sizeof(u32)); | 128 | return ipqhashfn(ipq->id, ipq->saddr, ipq->daddr, ipq->protocol); |
143 | for (i = 0; i < IPQ_HASHSZ; i++) { | ||
144 | struct ipq *q; | ||
145 | struct hlist_node *p, *n; | ||
146 | |||
147 | hlist_for_each_entry_safe(q, p, n, &ipq_hash[i], list) { | ||
148 | unsigned int hval = ipqhashfn(q->id, q->saddr, | ||
149 | q->daddr, q->protocol); | ||
150 | |||
151 | if (hval != i) { | ||
152 | hlist_del(&q->list); | ||
153 | |||
154 | /* Relink to new hash chain. */ | ||
155 | hlist_add_head(&q->list, &ipq_hash[hval]); | ||
156 | } | ||
157 | } | ||
158 | } | ||
159 | write_unlock(&ipfrag_lock); | ||
160 | |||
161 | mod_timer(&ipfrag_secret_timer, now + sysctl_ipfrag_secret_interval); | ||
162 | } | 129 | } |
163 | 130 | ||
164 | atomic_t ip_frag_mem = ATOMIC_INIT(0); /* Memory used for fragments */ | 131 | static int ip4_frag_match(struct inet_frag_queue *q, void *a) |
132 | { | ||
133 | struct ipq *qp; | ||
134 | struct ip4_create_arg *arg = a; | ||
135 | |||
136 | qp = container_of(q, struct ipq, q); | ||
137 | return (qp->id == arg->iph->id && | ||
138 | qp->saddr == arg->iph->saddr && | ||
139 | qp->daddr == arg->iph->daddr && | ||
140 | qp->protocol == arg->iph->protocol && | ||
141 | qp->user == arg->user); | ||
142 | } | ||
165 | 143 | ||
166 | /* Memory Tracking Functions. */ | 144 | /* Memory Tracking Functions. */ |
167 | static __inline__ void frag_kfree_skb(struct sk_buff *skb, int *work) | 145 | static __inline__ void frag_kfree_skb(struct sk_buff *skb, int *work) |
168 | { | 146 | { |
169 | if (work) | 147 | if (work) |
170 | *work -= skb->truesize; | 148 | *work -= skb->truesize; |
171 | atomic_sub(skb->truesize, &ip_frag_mem); | 149 | atomic_sub(skb->truesize, &ip4_frags.mem); |
172 | kfree_skb(skb); | 150 | kfree_skb(skb); |
173 | } | 151 | } |
174 | 152 | ||
175 | static __inline__ void frag_free_queue(struct ipq *qp, int *work) | 153 | static void ip4_frag_init(struct inet_frag_queue *q, void *a) |
176 | { | 154 | { |
177 | if (work) | 155 | struct ipq *qp = container_of(q, struct ipq, q); |
178 | *work -= sizeof(struct ipq); | 156 | struct ip4_create_arg *arg = a; |
179 | atomic_sub(sizeof(struct ipq), &ip_frag_mem); | 157 | |
180 | kfree(qp); | 158 | qp->protocol = arg->iph->protocol; |
159 | qp->id = arg->iph->id; | ||
160 | qp->saddr = arg->iph->saddr; | ||
161 | qp->daddr = arg->iph->daddr; | ||
162 | qp->user = arg->user; | ||
163 | qp->peer = sysctl_ipfrag_max_dist ? | ||
164 | inet_getpeer(arg->iph->saddr, 1) : NULL; | ||
181 | } | 165 | } |
182 | 166 | ||
183 | static __inline__ struct ipq *frag_alloc_queue(void) | 167 | static __inline__ void ip4_frag_free(struct inet_frag_queue *q) |
184 | { | 168 | { |
185 | struct ipq *qp = kmalloc(sizeof(struct ipq), GFP_ATOMIC); | 169 | struct ipq *qp; |
186 | |||
187 | if (!qp) | ||
188 | return NULL; | ||
189 | atomic_add(sizeof(struct ipq), &ip_frag_mem); | ||
190 | return qp; | ||
191 | } | ||
192 | |||
193 | |||
194 | /* Destruction primitives. */ | ||
195 | |||
196 | /* Complete destruction of ipq. */ | ||
197 | static void ip_frag_destroy(struct ipq *qp, int *work) | ||
198 | { | ||
199 | struct sk_buff *fp; | ||
200 | |||
201 | BUG_TRAP(qp->last_in&COMPLETE); | ||
202 | BUG_TRAP(del_timer(&qp->timer) == 0); | ||
203 | 170 | ||
171 | qp = container_of(q, struct ipq, q); | ||
204 | if (qp->peer) | 172 | if (qp->peer) |
205 | inet_putpeer(qp->peer); | 173 | inet_putpeer(qp->peer); |
174 | } | ||
206 | 175 | ||
207 | /* Release all fragment data. */ | ||
208 | fp = qp->fragments; | ||
209 | while (fp) { | ||
210 | struct sk_buff *xp = fp->next; | ||
211 | |||
212 | frag_kfree_skb(fp, work); | ||
213 | fp = xp; | ||
214 | } | ||
215 | 176 | ||
216 | /* Finally, release the queue descriptor itself. */ | 177 | /* Destruction primitives. */ |
217 | frag_free_queue(qp, work); | ||
218 | } | ||
219 | 178 | ||
220 | static __inline__ void ipq_put(struct ipq *ipq, int *work) | 179 | static __inline__ void ipq_put(struct ipq *ipq) |
221 | { | 180 | { |
222 | if (atomic_dec_and_test(&ipq->refcnt)) | 181 | inet_frag_put(&ipq->q, &ip4_frags); |
223 | ip_frag_destroy(ipq, work); | ||
224 | } | 182 | } |
225 | 183 | ||
226 | /* Kill ipq entry. It is not destroyed immediately, | 184 | /* Kill ipq entry. It is not destroyed immediately, |
@@ -228,14 +186,7 @@ static __inline__ void ipq_put(struct ipq *ipq, int *work) | |||
228 | */ | 186 | */ |
229 | static void ipq_kill(struct ipq *ipq) | 187 | static void ipq_kill(struct ipq *ipq) |
230 | { | 188 | { |
231 | if (del_timer(&ipq->timer)) | 189 | inet_frag_kill(&ipq->q, &ip4_frags); |
232 | atomic_dec(&ipq->refcnt); | ||
233 | |||
234 | if (!(ipq->last_in & COMPLETE)) { | ||
235 | ipq_unlink(ipq); | ||
236 | atomic_dec(&ipq->refcnt); | ||
237 | ipq->last_in |= COMPLETE; | ||
238 | } | ||
239 | } | 190 | } |
240 | 191 | ||
241 | /* Memory limiting on fragments. Evictor trashes the oldest | 192 | /* Memory limiting on fragments. Evictor trashes the oldest |
@@ -243,33 +194,11 @@ static void ipq_kill(struct ipq *ipq) | |||
243 | */ | 194 | */ |
244 | static void ip_evictor(void) | 195 | static void ip_evictor(void) |
245 | { | 196 | { |
246 | struct ipq *qp; | 197 | int evicted; |
247 | struct list_head *tmp; | ||
248 | int work; | ||
249 | |||
250 | work = atomic_read(&ip_frag_mem) - sysctl_ipfrag_low_thresh; | ||
251 | if (work <= 0) | ||
252 | return; | ||
253 | |||
254 | while (work > 0) { | ||
255 | read_lock(&ipfrag_lock); | ||
256 | if (list_empty(&ipq_lru_list)) { | ||
257 | read_unlock(&ipfrag_lock); | ||
258 | return; | ||
259 | } | ||
260 | tmp = ipq_lru_list.next; | ||
261 | qp = list_entry(tmp, struct ipq, lru_list); | ||
262 | atomic_inc(&qp->refcnt); | ||
263 | read_unlock(&ipfrag_lock); | ||
264 | |||
265 | spin_lock(&qp->lock); | ||
266 | if (!(qp->last_in&COMPLETE)) | ||
267 | ipq_kill(qp); | ||
268 | spin_unlock(&qp->lock); | ||
269 | 198 | ||
270 | ipq_put(qp, &work); | 199 | evicted = inet_frag_evictor(&ip4_frags); |
271 | IP_INC_STATS_BH(IPSTATS_MIB_REASMFAILS); | 200 | if (evicted) |
272 | } | 201 | IP_ADD_STATS_BH(IPSTATS_MIB_REASMFAILS, evicted); |
273 | } | 202 | } |
274 | 203 | ||
275 | /* | 204 | /* |
@@ -277,11 +206,13 @@ static void ip_evictor(void) | |||
277 | */ | 206 | */ |
278 | static void ip_expire(unsigned long arg) | 207 | static void ip_expire(unsigned long arg) |
279 | { | 208 | { |
280 | struct ipq *qp = (struct ipq *) arg; | 209 | struct ipq *qp; |
210 | |||
211 | qp = container_of((struct inet_frag_queue *) arg, struct ipq, q); | ||
281 | 212 | ||
282 | spin_lock(&qp->lock); | 213 | spin_lock(&qp->q.lock); |
283 | 214 | ||
284 | if (qp->last_in & COMPLETE) | 215 | if (qp->q.last_in & COMPLETE) |
285 | goto out; | 216 | goto out; |
286 | 217 | ||
287 | ipq_kill(qp); | 218 | ipq_kill(qp); |
@@ -289,8 +220,8 @@ static void ip_expire(unsigned long arg) | |||
289 | IP_INC_STATS_BH(IPSTATS_MIB_REASMTIMEOUT); | 220 | IP_INC_STATS_BH(IPSTATS_MIB_REASMTIMEOUT); |
290 | IP_INC_STATS_BH(IPSTATS_MIB_REASMFAILS); | 221 | IP_INC_STATS_BH(IPSTATS_MIB_REASMFAILS); |
291 | 222 | ||
292 | if ((qp->last_in&FIRST_IN) && qp->fragments != NULL) { | 223 | if ((qp->q.last_in&FIRST_IN) && qp->q.fragments != NULL) { |
293 | struct sk_buff *head = qp->fragments; | 224 | struct sk_buff *head = qp->q.fragments; |
294 | /* Send an ICMP "Fragment Reassembly Timeout" message. */ | 225 | /* Send an ICMP "Fragment Reassembly Timeout" message. */ |
295 | if ((head->dev = dev_get_by_index(&init_net, qp->iif)) != NULL) { | 226 | if ((head->dev = dev_get_by_index(&init_net, qp->iif)) != NULL) { |
296 | icmp_send(head, ICMP_TIME_EXCEEDED, ICMP_EXC_FRAGTIME, 0); | 227 | icmp_send(head, ICMP_TIME_EXCEEDED, ICMP_EXC_FRAGTIME, 0); |
@@ -298,121 +229,34 @@ static void ip_expire(unsigned long arg) | |||
298 | } | 229 | } |
299 | } | 230 | } |
300 | out: | 231 | out: |
301 | spin_unlock(&qp->lock); | 232 | spin_unlock(&qp->q.lock); |
302 | ipq_put(qp, NULL); | 233 | ipq_put(qp); |
303 | } | 234 | } |
304 | 235 | ||
305 | /* Creation primitives. */ | 236 | /* Find the correct entry in the "incomplete datagrams" queue for |
306 | 237 | * this IP datagram, and create new one, if nothing is found. | |
307 | static struct ipq *ip_frag_intern(struct ipq *qp_in) | 238 | */ |
239 | static inline struct ipq *ip_find(struct iphdr *iph, u32 user) | ||
308 | { | 240 | { |
309 | struct ipq *qp; | 241 | struct inet_frag_queue *q; |
310 | #ifdef CONFIG_SMP | 242 | struct ip4_create_arg arg; |
311 | struct hlist_node *n; | ||
312 | #endif | ||
313 | unsigned int hash; | 243 | unsigned int hash; |
314 | 244 | ||
315 | write_lock(&ipfrag_lock); | 245 | arg.iph = iph; |
316 | hash = ipqhashfn(qp_in->id, qp_in->saddr, qp_in->daddr, | 246 | arg.user = user; |
317 | qp_in->protocol); | 247 | hash = ipqhashfn(iph->id, iph->saddr, iph->daddr, iph->protocol); |
318 | #ifdef CONFIG_SMP | ||
319 | /* With SMP race we have to recheck hash table, because | ||
320 | * such entry could be created on other cpu, while we | ||
321 | * promoted read lock to write lock. | ||
322 | */ | ||
323 | hlist_for_each_entry(qp, n, &ipq_hash[hash], list) { | ||
324 | if (qp->id == qp_in->id && | ||
325 | qp->saddr == qp_in->saddr && | ||
326 | qp->daddr == qp_in->daddr && | ||
327 | qp->protocol == qp_in->protocol && | ||
328 | qp->user == qp_in->user) { | ||
329 | atomic_inc(&qp->refcnt); | ||
330 | write_unlock(&ipfrag_lock); | ||
331 | qp_in->last_in |= COMPLETE; | ||
332 | ipq_put(qp_in, NULL); | ||
333 | return qp; | ||
334 | } | ||
335 | } | ||
336 | #endif | ||
337 | qp = qp_in; | ||
338 | |||
339 | if (!mod_timer(&qp->timer, jiffies + sysctl_ipfrag_time)) | ||
340 | atomic_inc(&qp->refcnt); | ||
341 | |||
342 | atomic_inc(&qp->refcnt); | ||
343 | hlist_add_head(&qp->list, &ipq_hash[hash]); | ||
344 | INIT_LIST_HEAD(&qp->lru_list); | ||
345 | list_add_tail(&qp->lru_list, &ipq_lru_list); | ||
346 | ip_frag_nqueues++; | ||
347 | write_unlock(&ipfrag_lock); | ||
348 | return qp; | ||
349 | } | ||
350 | |||
351 | /* Add an entry to the 'ipq' queue for a newly received IP datagram. */ | ||
352 | static struct ipq *ip_frag_create(struct iphdr *iph, u32 user) | ||
353 | { | ||
354 | struct ipq *qp; | ||
355 | 248 | ||
356 | if ((qp = frag_alloc_queue()) == NULL) | 249 | q = inet_frag_find(&ip4_frags, &arg, hash); |
250 | if (q == NULL) | ||
357 | goto out_nomem; | 251 | goto out_nomem; |
358 | 252 | ||
359 | qp->protocol = iph->protocol; | 253 | return container_of(q, struct ipq, q); |
360 | qp->last_in = 0; | ||
361 | qp->id = iph->id; | ||
362 | qp->saddr = iph->saddr; | ||
363 | qp->daddr = iph->daddr; | ||
364 | qp->user = user; | ||
365 | qp->len = 0; | ||
366 | qp->meat = 0; | ||
367 | qp->fragments = NULL; | ||
368 | qp->iif = 0; | ||
369 | qp->peer = sysctl_ipfrag_max_dist ? inet_getpeer(iph->saddr, 1) : NULL; | ||
370 | |||
371 | /* Initialize a timer for this entry. */ | ||
372 | init_timer(&qp->timer); | ||
373 | qp->timer.data = (unsigned long) qp; /* pointer to queue */ | ||
374 | qp->timer.function = ip_expire; /* expire function */ | ||
375 | spin_lock_init(&qp->lock); | ||
376 | atomic_set(&qp->refcnt, 1); | ||
377 | |||
378 | return ip_frag_intern(qp); | ||
379 | 254 | ||
380 | out_nomem: | 255 | out_nomem: |
381 | LIMIT_NETDEBUG(KERN_ERR "ip_frag_create: no memory left !\n"); | 256 | LIMIT_NETDEBUG(KERN_ERR "ip_frag_create: no memory left !\n"); |
382 | return NULL; | 257 | return NULL; |
383 | } | 258 | } |
384 | 259 | ||
385 | /* Find the correct entry in the "incomplete datagrams" queue for | ||
386 | * this IP datagram, and create new one, if nothing is found. | ||
387 | */ | ||
388 | static inline struct ipq *ip_find(struct iphdr *iph, u32 user) | ||
389 | { | ||
390 | __be16 id = iph->id; | ||
391 | __be32 saddr = iph->saddr; | ||
392 | __be32 daddr = iph->daddr; | ||
393 | __u8 protocol = iph->protocol; | ||
394 | unsigned int hash; | ||
395 | struct ipq *qp; | ||
396 | struct hlist_node *n; | ||
397 | |||
398 | read_lock(&ipfrag_lock); | ||
399 | hash = ipqhashfn(id, saddr, daddr, protocol); | ||
400 | hlist_for_each_entry(qp, n, &ipq_hash[hash], list) { | ||
401 | if (qp->id == id && | ||
402 | qp->saddr == saddr && | ||
403 | qp->daddr == daddr && | ||
404 | qp->protocol == protocol && | ||
405 | qp->user == user) { | ||
406 | atomic_inc(&qp->refcnt); | ||
407 | read_unlock(&ipfrag_lock); | ||
408 | return qp; | ||
409 | } | ||
410 | } | ||
411 | read_unlock(&ipfrag_lock); | ||
412 | |||
413 | return ip_frag_create(iph, user); | ||
414 | } | ||
415 | |||
416 | /* Is the fragment too far ahead to be part of ipq? */ | 260 | /* Is the fragment too far ahead to be part of ipq? */ |
417 | static inline int ip_frag_too_far(struct ipq *qp) | 261 | static inline int ip_frag_too_far(struct ipq *qp) |
418 | { | 262 | { |
@@ -429,7 +273,7 @@ static inline int ip_frag_too_far(struct ipq *qp) | |||
429 | end = atomic_inc_return(&peer->rid); | 273 | end = atomic_inc_return(&peer->rid); |
430 | qp->rid = end; | 274 | qp->rid = end; |
431 | 275 | ||
432 | rc = qp->fragments && (end - start) > max; | 276 | rc = qp->q.fragments && (end - start) > max; |
433 | 277 | ||
434 | if (rc) { | 278 | if (rc) { |
435 | IP_INC_STATS_BH(IPSTATS_MIB_REASMFAILS); | 279 | IP_INC_STATS_BH(IPSTATS_MIB_REASMFAILS); |
@@ -442,39 +286,42 @@ static int ip_frag_reinit(struct ipq *qp) | |||
442 | { | 286 | { |
443 | struct sk_buff *fp; | 287 | struct sk_buff *fp; |
444 | 288 | ||
445 | if (!mod_timer(&qp->timer, jiffies + sysctl_ipfrag_time)) { | 289 | if (!mod_timer(&qp->q.timer, jiffies + ip4_frags_ctl.timeout)) { |
446 | atomic_inc(&qp->refcnt); | 290 | atomic_inc(&qp->q.refcnt); |
447 | return -ETIMEDOUT; | 291 | return -ETIMEDOUT; |
448 | } | 292 | } |
449 | 293 | ||
450 | fp = qp->fragments; | 294 | fp = qp->q.fragments; |
451 | do { | 295 | do { |
452 | struct sk_buff *xp = fp->next; | 296 | struct sk_buff *xp = fp->next; |
453 | frag_kfree_skb(fp, NULL); | 297 | frag_kfree_skb(fp, NULL); |
454 | fp = xp; | 298 | fp = xp; |
455 | } while (fp); | 299 | } while (fp); |
456 | 300 | ||
457 | qp->last_in = 0; | 301 | qp->q.last_in = 0; |
458 | qp->len = 0; | 302 | qp->q.len = 0; |
459 | qp->meat = 0; | 303 | qp->q.meat = 0; |
460 | qp->fragments = NULL; | 304 | qp->q.fragments = NULL; |
461 | qp->iif = 0; | 305 | qp->iif = 0; |
462 | 306 | ||
463 | return 0; | 307 | return 0; |
464 | } | 308 | } |
465 | 309 | ||
466 | /* Add new segment to existing queue. */ | 310 | /* Add new segment to existing queue. */ |
467 | static void ip_frag_queue(struct ipq *qp, struct sk_buff *skb) | 311 | static int ip_frag_queue(struct ipq *qp, struct sk_buff *skb) |
468 | { | 312 | { |
469 | struct sk_buff *prev, *next; | 313 | struct sk_buff *prev, *next; |
314 | struct net_device *dev; | ||
470 | int flags, offset; | 315 | int flags, offset; |
471 | int ihl, end; | 316 | int ihl, end; |
317 | int err = -ENOENT; | ||
472 | 318 | ||
473 | if (qp->last_in & COMPLETE) | 319 | if (qp->q.last_in & COMPLETE) |
474 | goto err; | 320 | goto err; |
475 | 321 | ||
476 | if (!(IPCB(skb)->flags & IPSKB_FRAG_COMPLETE) && | 322 | if (!(IPCB(skb)->flags & IPSKB_FRAG_COMPLETE) && |
477 | unlikely(ip_frag_too_far(qp)) && unlikely(ip_frag_reinit(qp))) { | 323 | unlikely(ip_frag_too_far(qp)) && |
324 | unlikely(err = ip_frag_reinit(qp))) { | ||
478 | ipq_kill(qp); | 325 | ipq_kill(qp); |
479 | goto err; | 326 | goto err; |
480 | } | 327 | } |
@@ -487,36 +334,40 @@ static void ip_frag_queue(struct ipq *qp, struct sk_buff *skb) | |||
487 | 334 | ||
488 | /* Determine the position of this fragment. */ | 335 | /* Determine the position of this fragment. */ |
489 | end = offset + skb->len - ihl; | 336 | end = offset + skb->len - ihl; |
337 | err = -EINVAL; | ||
490 | 338 | ||
491 | /* Is this the final fragment? */ | 339 | /* Is this the final fragment? */ |
492 | if ((flags & IP_MF) == 0) { | 340 | if ((flags & IP_MF) == 0) { |
493 | /* If we already have some bits beyond end | 341 | /* If we already have some bits beyond end |
494 | * or have different end, the segment is corrrupted. | 342 | * or have different end, the segment is corrrupted. |
495 | */ | 343 | */ |
496 | if (end < qp->len || | 344 | if (end < qp->q.len || |
497 | ((qp->last_in & LAST_IN) && end != qp->len)) | 345 | ((qp->q.last_in & LAST_IN) && end != qp->q.len)) |
498 | goto err; | 346 | goto err; |
499 | qp->last_in |= LAST_IN; | 347 | qp->q.last_in |= LAST_IN; |
500 | qp->len = end; | 348 | qp->q.len = end; |
501 | } else { | 349 | } else { |
502 | if (end&7) { | 350 | if (end&7) { |
503 | end &= ~7; | 351 | end &= ~7; |
504 | if (skb->ip_summed != CHECKSUM_UNNECESSARY) | 352 | if (skb->ip_summed != CHECKSUM_UNNECESSARY) |
505 | skb->ip_summed = CHECKSUM_NONE; | 353 | skb->ip_summed = CHECKSUM_NONE; |
506 | } | 354 | } |
507 | if (end > qp->len) { | 355 | if (end > qp->q.len) { |
508 | /* Some bits beyond end -> corruption. */ | 356 | /* Some bits beyond end -> corruption. */ |
509 | if (qp->last_in & LAST_IN) | 357 | if (qp->q.last_in & LAST_IN) |
510 | goto err; | 358 | goto err; |
511 | qp->len = end; | 359 | qp->q.len = end; |
512 | } | 360 | } |
513 | } | 361 | } |
514 | if (end == offset) | 362 | if (end == offset) |
515 | goto err; | 363 | goto err; |
516 | 364 | ||
365 | err = -ENOMEM; | ||
517 | if (pskb_pull(skb, ihl) == NULL) | 366 | if (pskb_pull(skb, ihl) == NULL) |
518 | goto err; | 367 | goto err; |
519 | if (pskb_trim_rcsum(skb, end-offset)) | 368 | |
369 | err = pskb_trim_rcsum(skb, end - offset); | ||
370 | if (err) | ||
520 | goto err; | 371 | goto err; |
521 | 372 | ||
522 | /* Find out which fragments are in front and at the back of us | 373 | /* Find out which fragments are in front and at the back of us |
@@ -524,7 +375,7 @@ static void ip_frag_queue(struct ipq *qp, struct sk_buff *skb) | |||
524 | * this fragment, right? | 375 | * this fragment, right? |
525 | */ | 376 | */ |
526 | prev = NULL; | 377 | prev = NULL; |
527 | for (next = qp->fragments; next != NULL; next = next->next) { | 378 | for (next = qp->q.fragments; next != NULL; next = next->next) { |
528 | if (FRAG_CB(next)->offset >= offset) | 379 | if (FRAG_CB(next)->offset >= offset) |
529 | break; /* bingo! */ | 380 | break; /* bingo! */ |
530 | prev = next; | 381 | prev = next; |
@@ -539,8 +390,10 @@ static void ip_frag_queue(struct ipq *qp, struct sk_buff *skb) | |||
539 | 390 | ||
540 | if (i > 0) { | 391 | if (i > 0) { |
541 | offset += i; | 392 | offset += i; |
393 | err = -EINVAL; | ||
542 | if (end <= offset) | 394 | if (end <= offset) |
543 | goto err; | 395 | goto err; |
396 | err = -ENOMEM; | ||
544 | if (!pskb_pull(skb, i)) | 397 | if (!pskb_pull(skb, i)) |
545 | goto err; | 398 | goto err; |
546 | if (skb->ip_summed != CHECKSUM_UNNECESSARY) | 399 | if (skb->ip_summed != CHECKSUM_UNNECESSARY) |
@@ -548,6 +401,8 @@ static void ip_frag_queue(struct ipq *qp, struct sk_buff *skb) | |||
548 | } | 401 | } |
549 | } | 402 | } |
550 | 403 | ||
404 | err = -ENOMEM; | ||
405 | |||
551 | while (next && FRAG_CB(next)->offset < end) { | 406 | while (next && FRAG_CB(next)->offset < end) { |
552 | int i = end - FRAG_CB(next)->offset; /* overlap is 'i' bytes */ | 407 | int i = end - FRAG_CB(next)->offset; /* overlap is 'i' bytes */ |
553 | 408 | ||
@@ -558,7 +413,7 @@ static void ip_frag_queue(struct ipq *qp, struct sk_buff *skb) | |||
558 | if (!pskb_pull(next, i)) | 413 | if (!pskb_pull(next, i)) |
559 | goto err; | 414 | goto err; |
560 | FRAG_CB(next)->offset += i; | 415 | FRAG_CB(next)->offset += i; |
561 | qp->meat -= i; | 416 | qp->q.meat -= i; |
562 | if (next->ip_summed != CHECKSUM_UNNECESSARY) | 417 | if (next->ip_summed != CHECKSUM_UNNECESSARY) |
563 | next->ip_summed = CHECKSUM_NONE; | 418 | next->ip_summed = CHECKSUM_NONE; |
564 | break; | 419 | break; |
@@ -573,9 +428,9 @@ static void ip_frag_queue(struct ipq *qp, struct sk_buff *skb) | |||
573 | if (prev) | 428 | if (prev) |
574 | prev->next = next; | 429 | prev->next = next; |
575 | else | 430 | else |
576 | qp->fragments = next; | 431 | qp->q.fragments = next; |
577 | 432 | ||
578 | qp->meat -= free_it->len; | 433 | qp->q.meat -= free_it->len; |
579 | frag_kfree_skb(free_it, NULL); | 434 | frag_kfree_skb(free_it, NULL); |
580 | } | 435 | } |
581 | } | 436 | } |
@@ -587,46 +442,71 @@ static void ip_frag_queue(struct ipq *qp, struct sk_buff *skb) | |||
587 | if (prev) | 442 | if (prev) |
588 | prev->next = skb; | 443 | prev->next = skb; |
589 | else | 444 | else |
590 | qp->fragments = skb; | 445 | qp->q.fragments = skb; |
591 | 446 | ||
592 | if (skb->dev) | 447 | dev = skb->dev; |
593 | qp->iif = skb->dev->ifindex; | 448 | if (dev) { |
594 | skb->dev = NULL; | 449 | qp->iif = dev->ifindex; |
595 | qp->stamp = skb->tstamp; | 450 | skb->dev = NULL; |
596 | qp->meat += skb->len; | 451 | } |
597 | atomic_add(skb->truesize, &ip_frag_mem); | 452 | qp->q.stamp = skb->tstamp; |
453 | qp->q.meat += skb->len; | ||
454 | atomic_add(skb->truesize, &ip4_frags.mem); | ||
598 | if (offset == 0) | 455 | if (offset == 0) |
599 | qp->last_in |= FIRST_IN; | 456 | qp->q.last_in |= FIRST_IN; |
600 | 457 | ||
601 | write_lock(&ipfrag_lock); | 458 | if (qp->q.last_in == (FIRST_IN | LAST_IN) && qp->q.meat == qp->q.len) |
602 | list_move_tail(&qp->lru_list, &ipq_lru_list); | 459 | return ip_frag_reasm(qp, prev, dev); |
603 | write_unlock(&ipfrag_lock); | ||
604 | 460 | ||
605 | return; | 461 | write_lock(&ip4_frags.lock); |
462 | list_move_tail(&qp->q.lru_list, &ip4_frags.lru_list); | ||
463 | write_unlock(&ip4_frags.lock); | ||
464 | return -EINPROGRESS; | ||
606 | 465 | ||
607 | err: | 466 | err: |
608 | kfree_skb(skb); | 467 | kfree_skb(skb); |
468 | return err; | ||
609 | } | 469 | } |
610 | 470 | ||
611 | 471 | ||
612 | /* Build a new IP datagram from all its fragments. */ | 472 | /* Build a new IP datagram from all its fragments. */ |
613 | 473 | ||
614 | static struct sk_buff *ip_frag_reasm(struct ipq *qp, struct net_device *dev) | 474 | static int ip_frag_reasm(struct ipq *qp, struct sk_buff *prev, |
475 | struct net_device *dev) | ||
615 | { | 476 | { |
616 | struct iphdr *iph; | 477 | struct iphdr *iph; |
617 | struct sk_buff *fp, *head = qp->fragments; | 478 | struct sk_buff *fp, *head = qp->q.fragments; |
618 | int len; | 479 | int len; |
619 | int ihlen; | 480 | int ihlen; |
481 | int err; | ||
620 | 482 | ||
621 | ipq_kill(qp); | 483 | ipq_kill(qp); |
622 | 484 | ||
485 | /* Make the one we just received the head. */ | ||
486 | if (prev) { | ||
487 | head = prev->next; | ||
488 | fp = skb_clone(head, GFP_ATOMIC); | ||
489 | if (!fp) | ||
490 | goto out_nomem; | ||
491 | |||
492 | fp->next = head->next; | ||
493 | prev->next = fp; | ||
494 | |||
495 | skb_morph(head, qp->q.fragments); | ||
496 | head->next = qp->q.fragments->next; | ||
497 | |||
498 | kfree_skb(qp->q.fragments); | ||
499 | qp->q.fragments = head; | ||
500 | } | ||
501 | |||
623 | BUG_TRAP(head != NULL); | 502 | BUG_TRAP(head != NULL); |
624 | BUG_TRAP(FRAG_CB(head)->offset == 0); | 503 | BUG_TRAP(FRAG_CB(head)->offset == 0); |
625 | 504 | ||
626 | /* Allocate a new buffer for the datagram. */ | 505 | /* Allocate a new buffer for the datagram. */ |
627 | ihlen = ip_hdrlen(head); | 506 | ihlen = ip_hdrlen(head); |
628 | len = ihlen + qp->len; | 507 | len = ihlen + qp->q.len; |
629 | 508 | ||
509 | err = -E2BIG; | ||
630 | if (len > 65535) | 510 | if (len > 65535) |
631 | goto out_oversize; | 511 | goto out_oversize; |
632 | 512 | ||
@@ -654,12 +534,12 @@ static struct sk_buff *ip_frag_reasm(struct ipq *qp, struct net_device *dev) | |||
654 | head->len -= clone->len; | 534 | head->len -= clone->len; |
655 | clone->csum = 0; | 535 | clone->csum = 0; |
656 | clone->ip_summed = head->ip_summed; | 536 | clone->ip_summed = head->ip_summed; |
657 | atomic_add(clone->truesize, &ip_frag_mem); | 537 | atomic_add(clone->truesize, &ip4_frags.mem); |
658 | } | 538 | } |
659 | 539 | ||
660 | skb_shinfo(head)->frag_list = head->next; | 540 | skb_shinfo(head)->frag_list = head->next; |
661 | skb_push(head, head->data - skb_network_header(head)); | 541 | skb_push(head, head->data - skb_network_header(head)); |
662 | atomic_sub(head->truesize, &ip_frag_mem); | 542 | atomic_sub(head->truesize, &ip4_frags.mem); |
663 | 543 | ||
664 | for (fp=head->next; fp; fp = fp->next) { | 544 | for (fp=head->next; fp; fp = fp->next) { |
665 | head->data_len += fp->len; | 545 | head->data_len += fp->len; |
@@ -669,23 +549,24 @@ static struct sk_buff *ip_frag_reasm(struct ipq *qp, struct net_device *dev) | |||
669 | else if (head->ip_summed == CHECKSUM_COMPLETE) | 549 | else if (head->ip_summed == CHECKSUM_COMPLETE) |
670 | head->csum = csum_add(head->csum, fp->csum); | 550 | head->csum = csum_add(head->csum, fp->csum); |
671 | head->truesize += fp->truesize; | 551 | head->truesize += fp->truesize; |
672 | atomic_sub(fp->truesize, &ip_frag_mem); | 552 | atomic_sub(fp->truesize, &ip4_frags.mem); |
673 | } | 553 | } |
674 | 554 | ||
675 | head->next = NULL; | 555 | head->next = NULL; |
676 | head->dev = dev; | 556 | head->dev = dev; |
677 | head->tstamp = qp->stamp; | 557 | head->tstamp = qp->q.stamp; |
678 | 558 | ||
679 | iph = ip_hdr(head); | 559 | iph = ip_hdr(head); |
680 | iph->frag_off = 0; | 560 | iph->frag_off = 0; |
681 | iph->tot_len = htons(len); | 561 | iph->tot_len = htons(len); |
682 | IP_INC_STATS_BH(IPSTATS_MIB_REASMOKS); | 562 | IP_INC_STATS_BH(IPSTATS_MIB_REASMOKS); |
683 | qp->fragments = NULL; | 563 | qp->q.fragments = NULL; |
684 | return head; | 564 | return 0; |
685 | 565 | ||
686 | out_nomem: | 566 | out_nomem: |
687 | LIMIT_NETDEBUG(KERN_ERR "IP: queue_glue: no memory for gluing " | 567 | LIMIT_NETDEBUG(KERN_ERR "IP: queue_glue: no memory for gluing " |
688 | "queue %p\n", qp); | 568 | "queue %p\n", qp); |
569 | err = -ENOMEM; | ||
689 | goto out_fail; | 570 | goto out_fail; |
690 | out_oversize: | 571 | out_oversize: |
691 | if (net_ratelimit()) | 572 | if (net_ratelimit()) |
@@ -694,54 +575,49 @@ out_oversize: | |||
694 | NIPQUAD(qp->saddr)); | 575 | NIPQUAD(qp->saddr)); |
695 | out_fail: | 576 | out_fail: |
696 | IP_INC_STATS_BH(IPSTATS_MIB_REASMFAILS); | 577 | IP_INC_STATS_BH(IPSTATS_MIB_REASMFAILS); |
697 | return NULL; | 578 | return err; |
698 | } | 579 | } |
699 | 580 | ||
700 | /* Process an incoming IP datagram fragment. */ | 581 | /* Process an incoming IP datagram fragment. */ |
701 | struct sk_buff *ip_defrag(struct sk_buff *skb, u32 user) | 582 | int ip_defrag(struct sk_buff *skb, u32 user) |
702 | { | 583 | { |
703 | struct ipq *qp; | 584 | struct ipq *qp; |
704 | struct net_device *dev; | ||
705 | 585 | ||
706 | IP_INC_STATS_BH(IPSTATS_MIB_REASMREQDS); | 586 | IP_INC_STATS_BH(IPSTATS_MIB_REASMREQDS); |
707 | 587 | ||
708 | /* Start by cleaning up the memory. */ | 588 | /* Start by cleaning up the memory. */ |
709 | if (atomic_read(&ip_frag_mem) > sysctl_ipfrag_high_thresh) | 589 | if (atomic_read(&ip4_frags.mem) > ip4_frags_ctl.high_thresh) |
710 | ip_evictor(); | 590 | ip_evictor(); |
711 | 591 | ||
712 | dev = skb->dev; | ||
713 | |||
714 | /* Lookup (or create) queue header */ | 592 | /* Lookup (or create) queue header */ |
715 | if ((qp = ip_find(ip_hdr(skb), user)) != NULL) { | 593 | if ((qp = ip_find(ip_hdr(skb), user)) != NULL) { |
716 | struct sk_buff *ret = NULL; | 594 | int ret; |
717 | 595 | ||
718 | spin_lock(&qp->lock); | 596 | spin_lock(&qp->q.lock); |
719 | 597 | ||
720 | ip_frag_queue(qp, skb); | 598 | ret = ip_frag_queue(qp, skb); |
721 | 599 | ||
722 | if (qp->last_in == (FIRST_IN|LAST_IN) && | 600 | spin_unlock(&qp->q.lock); |
723 | qp->meat == qp->len) | 601 | ipq_put(qp); |
724 | ret = ip_frag_reasm(qp, dev); | ||
725 | |||
726 | spin_unlock(&qp->lock); | ||
727 | ipq_put(qp, NULL); | ||
728 | return ret; | 602 | return ret; |
729 | } | 603 | } |
730 | 604 | ||
731 | IP_INC_STATS_BH(IPSTATS_MIB_REASMFAILS); | 605 | IP_INC_STATS_BH(IPSTATS_MIB_REASMFAILS); |
732 | kfree_skb(skb); | 606 | kfree_skb(skb); |
733 | return NULL; | 607 | return -ENOMEM; |
734 | } | 608 | } |
735 | 609 | ||
736 | void __init ipfrag_init(void) | 610 | void __init ipfrag_init(void) |
737 | { | 611 | { |
738 | ipfrag_hash_rnd = (u32) ((num_physpages ^ (num_physpages>>7)) ^ | 612 | ip4_frags.ctl = &ip4_frags_ctl; |
739 | (jiffies ^ (jiffies >> 6))); | 613 | ip4_frags.hashfn = ip4_hashfn; |
740 | 614 | ip4_frags.constructor = ip4_frag_init; | |
741 | init_timer(&ipfrag_secret_timer); | 615 | ip4_frags.destructor = ip4_frag_free; |
742 | ipfrag_secret_timer.function = ipfrag_secret_rebuild; | 616 | ip4_frags.skb_free = NULL; |
743 | ipfrag_secret_timer.expires = jiffies + sysctl_ipfrag_secret_interval; | 617 | ip4_frags.qsize = sizeof(struct ipq); |
744 | add_timer(&ipfrag_secret_timer); | 618 | ip4_frags.match = ip4_frag_match; |
619 | ip4_frags.frag_expire = ip_expire; | ||
620 | inet_frags_init(&ip4_frags); | ||
745 | } | 621 | } |
746 | 622 | ||
747 | EXPORT_SYMBOL(ip_defrag); | 623 | EXPORT_SYMBOL(ip_defrag); |
diff --git a/net/ipv4/ip_input.c b/net/ipv4/ip_input.c index 41d8964591e7..168c871fcd79 100644 --- a/net/ipv4/ip_input.c +++ b/net/ipv4/ip_input.c | |||
@@ -172,8 +172,7 @@ int ip_call_ra_chain(struct sk_buff *skb) | |||
172 | (!sk->sk_bound_dev_if || | 172 | (!sk->sk_bound_dev_if || |
173 | sk->sk_bound_dev_if == skb->dev->ifindex)) { | 173 | sk->sk_bound_dev_if == skb->dev->ifindex)) { |
174 | if (ip_hdr(skb)->frag_off & htons(IP_MF | IP_OFFSET)) { | 174 | if (ip_hdr(skb)->frag_off & htons(IP_MF | IP_OFFSET)) { |
175 | skb = ip_defrag(skb, IP_DEFRAG_CALL_RA_CHAIN); | 175 | if (ip_defrag(skb, IP_DEFRAG_CALL_RA_CHAIN)) { |
176 | if (skb == NULL) { | ||
177 | read_unlock(&ip_ra_lock); | 176 | read_unlock(&ip_ra_lock); |
178 | return 1; | 177 | return 1; |
179 | } | 178 | } |
@@ -196,7 +195,7 @@ int ip_call_ra_chain(struct sk_buff *skb) | |||
196 | return 0; | 195 | return 0; |
197 | } | 196 | } |
198 | 197 | ||
199 | static inline int ip_local_deliver_finish(struct sk_buff *skb) | 198 | static int ip_local_deliver_finish(struct sk_buff *skb) |
200 | { | 199 | { |
201 | __skb_pull(skb, ip_hdrlen(skb)); | 200 | __skb_pull(skb, ip_hdrlen(skb)); |
202 | 201 | ||
@@ -265,8 +264,7 @@ int ip_local_deliver(struct sk_buff *skb) | |||
265 | */ | 264 | */ |
266 | 265 | ||
267 | if (ip_hdr(skb)->frag_off & htons(IP_MF | IP_OFFSET)) { | 266 | if (ip_hdr(skb)->frag_off & htons(IP_MF | IP_OFFSET)) { |
268 | skb = ip_defrag(skb, IP_DEFRAG_LOCAL_DELIVER); | 267 | if (ip_defrag(skb, IP_DEFRAG_LOCAL_DELIVER)) |
269 | if (!skb) | ||
270 | return 0; | 268 | return 0; |
271 | } | 269 | } |
272 | 270 | ||
@@ -326,7 +324,7 @@ drop: | |||
326 | return -1; | 324 | return -1; |
327 | } | 325 | } |
328 | 326 | ||
329 | static inline int ip_rcv_finish(struct sk_buff *skb) | 327 | static int ip_rcv_finish(struct sk_buff *skb) |
330 | { | 328 | { |
331 | const struct iphdr *iph = ip_hdr(skb); | 329 | const struct iphdr *iph = ip_hdr(skb); |
332 | struct rtable *rt; | 330 | struct rtable *rt; |
diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c index 699f06781fd8..f508835ba713 100644 --- a/net/ipv4/ip_output.c +++ b/net/ipv4/ip_output.c | |||
@@ -202,7 +202,7 @@ static inline int ip_skb_dst_mtu(struct sk_buff *skb) | |||
202 | skb->dst->dev->mtu : dst_mtu(skb->dst); | 202 | skb->dst->dev->mtu : dst_mtu(skb->dst); |
203 | } | 203 | } |
204 | 204 | ||
205 | static inline int ip_finish_output(struct sk_buff *skb) | 205 | static int ip_finish_output(struct sk_buff *skb) |
206 | { | 206 | { |
207 | #if defined(CONFIG_NETFILTER) && defined(CONFIG_XFRM) | 207 | #if defined(CONFIG_NETFILTER) && defined(CONFIG_XFRM) |
208 | /* Policy lookup after SNAT yielded a new policy */ | 208 | /* Policy lookup after SNAT yielded a new policy */ |
diff --git a/net/ipv4/ipvs/ip_vs_app.c b/net/ipv4/ipvs/ip_vs_app.c index 341474eefa55..664cb8e97c1c 100644 --- a/net/ipv4/ipvs/ip_vs_app.c +++ b/net/ipv4/ipvs/ip_vs_app.c | |||
@@ -25,6 +25,7 @@ | |||
25 | #include <linux/skbuff.h> | 25 | #include <linux/skbuff.h> |
26 | #include <linux/in.h> | 26 | #include <linux/in.h> |
27 | #include <linux/ip.h> | 27 | #include <linux/ip.h> |
28 | #include <linux/netfilter.h> | ||
28 | #include <net/net_namespace.h> | 29 | #include <net/net_namespace.h> |
29 | #include <net/protocol.h> | 30 | #include <net/protocol.h> |
30 | #include <net/tcp.h> | 31 | #include <net/tcp.h> |
@@ -328,18 +329,18 @@ static inline void vs_seq_update(struct ip_vs_conn *cp, struct ip_vs_seq *vseq, | |||
328 | spin_unlock(&cp->lock); | 329 | spin_unlock(&cp->lock); |
329 | } | 330 | } |
330 | 331 | ||
331 | static inline int app_tcp_pkt_out(struct ip_vs_conn *cp, struct sk_buff **pskb, | 332 | static inline int app_tcp_pkt_out(struct ip_vs_conn *cp, struct sk_buff *skb, |
332 | struct ip_vs_app *app) | 333 | struct ip_vs_app *app) |
333 | { | 334 | { |
334 | int diff; | 335 | int diff; |
335 | const unsigned int tcp_offset = ip_hdrlen(*pskb); | 336 | const unsigned int tcp_offset = ip_hdrlen(skb); |
336 | struct tcphdr *th; | 337 | struct tcphdr *th; |
337 | __u32 seq; | 338 | __u32 seq; |
338 | 339 | ||
339 | if (!ip_vs_make_skb_writable(pskb, tcp_offset + sizeof(*th))) | 340 | if (!skb_make_writable(skb, tcp_offset + sizeof(*th))) |
340 | return 0; | 341 | return 0; |
341 | 342 | ||
342 | th = (struct tcphdr *)(skb_network_header(*pskb) + tcp_offset); | 343 | th = (struct tcphdr *)(skb_network_header(skb) + tcp_offset); |
343 | 344 | ||
344 | /* | 345 | /* |
345 | * Remember seq number in case this pkt gets resized | 346 | * Remember seq number in case this pkt gets resized |
@@ -360,7 +361,7 @@ static inline int app_tcp_pkt_out(struct ip_vs_conn *cp, struct sk_buff **pskb, | |||
360 | if (app->pkt_out == NULL) | 361 | if (app->pkt_out == NULL) |
361 | return 1; | 362 | return 1; |
362 | 363 | ||
363 | if (!app->pkt_out(app, cp, pskb, &diff)) | 364 | if (!app->pkt_out(app, cp, skb, &diff)) |
364 | return 0; | 365 | return 0; |
365 | 366 | ||
366 | /* | 367 | /* |
@@ -378,7 +379,7 @@ static inline int app_tcp_pkt_out(struct ip_vs_conn *cp, struct sk_buff **pskb, | |||
378 | * called by ipvs packet handler, assumes previously checked cp!=NULL | 379 | * called by ipvs packet handler, assumes previously checked cp!=NULL |
379 | * returns false if it can't handle packet (oom) | 380 | * returns false if it can't handle packet (oom) |
380 | */ | 381 | */ |
381 | int ip_vs_app_pkt_out(struct ip_vs_conn *cp, struct sk_buff **pskb) | 382 | int ip_vs_app_pkt_out(struct ip_vs_conn *cp, struct sk_buff *skb) |
382 | { | 383 | { |
383 | struct ip_vs_app *app; | 384 | struct ip_vs_app *app; |
384 | 385 | ||
@@ -391,7 +392,7 @@ int ip_vs_app_pkt_out(struct ip_vs_conn *cp, struct sk_buff **pskb) | |||
391 | 392 | ||
392 | /* TCP is complicated */ | 393 | /* TCP is complicated */ |
393 | if (cp->protocol == IPPROTO_TCP) | 394 | if (cp->protocol == IPPROTO_TCP) |
394 | return app_tcp_pkt_out(cp, pskb, app); | 395 | return app_tcp_pkt_out(cp, skb, app); |
395 | 396 | ||
396 | /* | 397 | /* |
397 | * Call private output hook function | 398 | * Call private output hook function |
@@ -399,22 +400,22 @@ int ip_vs_app_pkt_out(struct ip_vs_conn *cp, struct sk_buff **pskb) | |||
399 | if (app->pkt_out == NULL) | 400 | if (app->pkt_out == NULL) |
400 | return 1; | 401 | return 1; |
401 | 402 | ||
402 | return app->pkt_out(app, cp, pskb, NULL); | 403 | return app->pkt_out(app, cp, skb, NULL); |
403 | } | 404 | } |
404 | 405 | ||
405 | 406 | ||
406 | static inline int app_tcp_pkt_in(struct ip_vs_conn *cp, struct sk_buff **pskb, | 407 | static inline int app_tcp_pkt_in(struct ip_vs_conn *cp, struct sk_buff *skb, |
407 | struct ip_vs_app *app) | 408 | struct ip_vs_app *app) |
408 | { | 409 | { |
409 | int diff; | 410 | int diff; |
410 | const unsigned int tcp_offset = ip_hdrlen(*pskb); | 411 | const unsigned int tcp_offset = ip_hdrlen(skb); |
411 | struct tcphdr *th; | 412 | struct tcphdr *th; |
412 | __u32 seq; | 413 | __u32 seq; |
413 | 414 | ||
414 | if (!ip_vs_make_skb_writable(pskb, tcp_offset + sizeof(*th))) | 415 | if (!skb_make_writable(skb, tcp_offset + sizeof(*th))) |
415 | return 0; | 416 | return 0; |
416 | 417 | ||
417 | th = (struct tcphdr *)(skb_network_header(*pskb) + tcp_offset); | 418 | th = (struct tcphdr *)(skb_network_header(skb) + tcp_offset); |
418 | 419 | ||
419 | /* | 420 | /* |
420 | * Remember seq number in case this pkt gets resized | 421 | * Remember seq number in case this pkt gets resized |
@@ -435,7 +436,7 @@ static inline int app_tcp_pkt_in(struct ip_vs_conn *cp, struct sk_buff **pskb, | |||
435 | if (app->pkt_in == NULL) | 436 | if (app->pkt_in == NULL) |
436 | return 1; | 437 | return 1; |
437 | 438 | ||
438 | if (!app->pkt_in(app, cp, pskb, &diff)) | 439 | if (!app->pkt_in(app, cp, skb, &diff)) |
439 | return 0; | 440 | return 0; |
440 | 441 | ||
441 | /* | 442 | /* |
@@ -453,7 +454,7 @@ static inline int app_tcp_pkt_in(struct ip_vs_conn *cp, struct sk_buff **pskb, | |||
453 | * called by ipvs packet handler, assumes previously checked cp!=NULL. | 454 | * called by ipvs packet handler, assumes previously checked cp!=NULL. |
454 | * returns false if can't handle packet (oom). | 455 | * returns false if can't handle packet (oom). |
455 | */ | 456 | */ |
456 | int ip_vs_app_pkt_in(struct ip_vs_conn *cp, struct sk_buff **pskb) | 457 | int ip_vs_app_pkt_in(struct ip_vs_conn *cp, struct sk_buff *skb) |
457 | { | 458 | { |
458 | struct ip_vs_app *app; | 459 | struct ip_vs_app *app; |
459 | 460 | ||
@@ -466,7 +467,7 @@ int ip_vs_app_pkt_in(struct ip_vs_conn *cp, struct sk_buff **pskb) | |||
466 | 467 | ||
467 | /* TCP is complicated */ | 468 | /* TCP is complicated */ |
468 | if (cp->protocol == IPPROTO_TCP) | 469 | if (cp->protocol == IPPROTO_TCP) |
469 | return app_tcp_pkt_in(cp, pskb, app); | 470 | return app_tcp_pkt_in(cp, skb, app); |
470 | 471 | ||
471 | /* | 472 | /* |
472 | * Call private input hook function | 473 | * Call private input hook function |
@@ -474,7 +475,7 @@ int ip_vs_app_pkt_in(struct ip_vs_conn *cp, struct sk_buff **pskb) | |||
474 | if (app->pkt_in == NULL) | 475 | if (app->pkt_in == NULL) |
475 | return 1; | 476 | return 1; |
476 | 477 | ||
477 | return app->pkt_in(app, cp, pskb, NULL); | 478 | return app->pkt_in(app, cp, skb, NULL); |
478 | } | 479 | } |
479 | 480 | ||
480 | 481 | ||
diff --git a/net/ipv4/ipvs/ip_vs_core.c b/net/ipv4/ipvs/ip_vs_core.c index fbca2a2ff29f..c6ed7654e839 100644 --- a/net/ipv4/ipvs/ip_vs_core.c +++ b/net/ipv4/ipvs/ip_vs_core.c | |||
@@ -58,7 +58,6 @@ EXPORT_SYMBOL(ip_vs_conn_put); | |||
58 | #ifdef CONFIG_IP_VS_DEBUG | 58 | #ifdef CONFIG_IP_VS_DEBUG |
59 | EXPORT_SYMBOL(ip_vs_get_debug_level); | 59 | EXPORT_SYMBOL(ip_vs_get_debug_level); |
60 | #endif | 60 | #endif |
61 | EXPORT_SYMBOL(ip_vs_make_skb_writable); | ||
62 | 61 | ||
63 | 62 | ||
64 | /* ID used in ICMP lookups */ | 63 | /* ID used in ICMP lookups */ |
@@ -163,42 +162,6 @@ ip_vs_set_state(struct ip_vs_conn *cp, int direction, | |||
163 | } | 162 | } |
164 | 163 | ||
165 | 164 | ||
166 | int ip_vs_make_skb_writable(struct sk_buff **pskb, int writable_len) | ||
167 | { | ||
168 | struct sk_buff *skb = *pskb; | ||
169 | |||
170 | /* skb is already used, better copy skb and its payload */ | ||
171 | if (unlikely(skb_shared(skb) || skb->sk)) | ||
172 | goto copy_skb; | ||
173 | |||
174 | /* skb data is already used, copy it */ | ||
175 | if (unlikely(skb_cloned(skb))) | ||
176 | goto copy_data; | ||
177 | |||
178 | return pskb_may_pull(skb, writable_len); | ||
179 | |||
180 | copy_data: | ||
181 | if (unlikely(writable_len > skb->len)) | ||
182 | return 0; | ||
183 | return !pskb_expand_head(skb, 0, 0, GFP_ATOMIC); | ||
184 | |||
185 | copy_skb: | ||
186 | if (unlikely(writable_len > skb->len)) | ||
187 | return 0; | ||
188 | skb = skb_copy(skb, GFP_ATOMIC); | ||
189 | if (!skb) | ||
190 | return 0; | ||
191 | BUG_ON(skb_is_nonlinear(skb)); | ||
192 | |||
193 | /* Rest of kernel will get very unhappy if we pass it a | ||
194 | suddenly-orphaned skbuff */ | ||
195 | if ((*pskb)->sk) | ||
196 | skb_set_owner_w(skb, (*pskb)->sk); | ||
197 | kfree_skb(*pskb); | ||
198 | *pskb = skb; | ||
199 | return 1; | ||
200 | } | ||
201 | |||
202 | /* | 165 | /* |
203 | * IPVS persistent scheduling function | 166 | * IPVS persistent scheduling function |
204 | * It creates a connection entry according to its template if exists, | 167 | * It creates a connection entry according to its template if exists, |
@@ -525,12 +488,12 @@ int ip_vs_leave(struct ip_vs_service *svc, struct sk_buff *skb, | |||
525 | * for VS/NAT. | 488 | * for VS/NAT. |
526 | */ | 489 | */ |
527 | static unsigned int ip_vs_post_routing(unsigned int hooknum, | 490 | static unsigned int ip_vs_post_routing(unsigned int hooknum, |
528 | struct sk_buff **pskb, | 491 | struct sk_buff *skb, |
529 | const struct net_device *in, | 492 | const struct net_device *in, |
530 | const struct net_device *out, | 493 | const struct net_device *out, |
531 | int (*okfn)(struct sk_buff *)) | 494 | int (*okfn)(struct sk_buff *)) |
532 | { | 495 | { |
533 | if (!((*pskb)->ipvs_property)) | 496 | if (!skb->ipvs_property) |
534 | return NF_ACCEPT; | 497 | return NF_ACCEPT; |
535 | /* The packet was sent from IPVS, exit this chain */ | 498 | /* The packet was sent from IPVS, exit this chain */ |
536 | return NF_STOP; | 499 | return NF_STOP; |
@@ -541,13 +504,14 @@ __sum16 ip_vs_checksum_complete(struct sk_buff *skb, int offset) | |||
541 | return csum_fold(skb_checksum(skb, offset, skb->len - offset, 0)); | 504 | return csum_fold(skb_checksum(skb, offset, skb->len - offset, 0)); |
542 | } | 505 | } |
543 | 506 | ||
544 | static inline struct sk_buff * | 507 | static inline int ip_vs_gather_frags(struct sk_buff *skb, u_int32_t user) |
545 | ip_vs_gather_frags(struct sk_buff *skb, u_int32_t user) | ||
546 | { | 508 | { |
547 | skb = ip_defrag(skb, user); | 509 | int err = ip_defrag(skb, user); |
548 | if (skb) | 510 | |
511 | if (!err) | ||
549 | ip_send_check(ip_hdr(skb)); | 512 | ip_send_check(ip_hdr(skb)); |
550 | return skb; | 513 | |
514 | return err; | ||
551 | } | 515 | } |
552 | 516 | ||
553 | /* | 517 | /* |
@@ -605,9 +569,8 @@ void ip_vs_nat_icmp(struct sk_buff *skb, struct ip_vs_protocol *pp, | |||
605 | * Currently handles error types - unreachable, quench, ttl exceeded. | 569 | * Currently handles error types - unreachable, quench, ttl exceeded. |
606 | * (Only used in VS/NAT) | 570 | * (Only used in VS/NAT) |
607 | */ | 571 | */ |
608 | static int ip_vs_out_icmp(struct sk_buff **pskb, int *related) | 572 | static int ip_vs_out_icmp(struct sk_buff *skb, int *related) |
609 | { | 573 | { |
610 | struct sk_buff *skb = *pskb; | ||
611 | struct iphdr *iph; | 574 | struct iphdr *iph; |
612 | struct icmphdr _icmph, *ic; | 575 | struct icmphdr _icmph, *ic; |
613 | struct iphdr _ciph, *cih; /* The ip header contained within the ICMP */ | 576 | struct iphdr _ciph, *cih; /* The ip header contained within the ICMP */ |
@@ -619,10 +582,8 @@ static int ip_vs_out_icmp(struct sk_buff **pskb, int *related) | |||
619 | 582 | ||
620 | /* reassemble IP fragments */ | 583 | /* reassemble IP fragments */ |
621 | if (ip_hdr(skb)->frag_off & htons(IP_MF | IP_OFFSET)) { | 584 | if (ip_hdr(skb)->frag_off & htons(IP_MF | IP_OFFSET)) { |
622 | skb = ip_vs_gather_frags(skb, IP_DEFRAG_VS_OUT); | 585 | if (ip_vs_gather_frags(skb, IP_DEFRAG_VS_OUT)) |
623 | if (!skb) | ||
624 | return NF_STOLEN; | 586 | return NF_STOLEN; |
625 | *pskb = skb; | ||
626 | } | 587 | } |
627 | 588 | ||
628 | iph = ip_hdr(skb); | 589 | iph = ip_hdr(skb); |
@@ -690,9 +651,8 @@ static int ip_vs_out_icmp(struct sk_buff **pskb, int *related) | |||
690 | 651 | ||
691 | if (IPPROTO_TCP == cih->protocol || IPPROTO_UDP == cih->protocol) | 652 | if (IPPROTO_TCP == cih->protocol || IPPROTO_UDP == cih->protocol) |
692 | offset += 2 * sizeof(__u16); | 653 | offset += 2 * sizeof(__u16); |
693 | if (!ip_vs_make_skb_writable(pskb, offset)) | 654 | if (!skb_make_writable(skb, offset)) |
694 | goto out; | 655 | goto out; |
695 | skb = *pskb; | ||
696 | 656 | ||
697 | ip_vs_nat_icmp(skb, pp, cp, 1); | 657 | ip_vs_nat_icmp(skb, pp, cp, 1); |
698 | 658 | ||
@@ -724,11 +684,10 @@ static inline int is_tcp_reset(const struct sk_buff *skb) | |||
724 | * rewrite addresses of the packet and send it on its way... | 684 | * rewrite addresses of the packet and send it on its way... |
725 | */ | 685 | */ |
726 | static unsigned int | 686 | static unsigned int |
727 | ip_vs_out(unsigned int hooknum, struct sk_buff **pskb, | 687 | ip_vs_out(unsigned int hooknum, struct sk_buff *skb, |
728 | const struct net_device *in, const struct net_device *out, | 688 | const struct net_device *in, const struct net_device *out, |
729 | int (*okfn)(struct sk_buff *)) | 689 | int (*okfn)(struct sk_buff *)) |
730 | { | 690 | { |
731 | struct sk_buff *skb = *pskb; | ||
732 | struct iphdr *iph; | 691 | struct iphdr *iph; |
733 | struct ip_vs_protocol *pp; | 692 | struct ip_vs_protocol *pp; |
734 | struct ip_vs_conn *cp; | 693 | struct ip_vs_conn *cp; |
@@ -741,11 +700,10 @@ ip_vs_out(unsigned int hooknum, struct sk_buff **pskb, | |||
741 | 700 | ||
742 | iph = ip_hdr(skb); | 701 | iph = ip_hdr(skb); |
743 | if (unlikely(iph->protocol == IPPROTO_ICMP)) { | 702 | if (unlikely(iph->protocol == IPPROTO_ICMP)) { |
744 | int related, verdict = ip_vs_out_icmp(pskb, &related); | 703 | int related, verdict = ip_vs_out_icmp(skb, &related); |
745 | 704 | ||
746 | if (related) | 705 | if (related) |
747 | return verdict; | 706 | return verdict; |
748 | skb = *pskb; | ||
749 | iph = ip_hdr(skb); | 707 | iph = ip_hdr(skb); |
750 | } | 708 | } |
751 | 709 | ||
@@ -756,11 +714,9 @@ ip_vs_out(unsigned int hooknum, struct sk_buff **pskb, | |||
756 | /* reassemble IP fragments */ | 714 | /* reassemble IP fragments */ |
757 | if (unlikely(iph->frag_off & htons(IP_MF|IP_OFFSET) && | 715 | if (unlikely(iph->frag_off & htons(IP_MF|IP_OFFSET) && |
758 | !pp->dont_defrag)) { | 716 | !pp->dont_defrag)) { |
759 | skb = ip_vs_gather_frags(skb, IP_DEFRAG_VS_OUT); | 717 | if (ip_vs_gather_frags(skb, IP_DEFRAG_VS_OUT)) |
760 | if (!skb) | ||
761 | return NF_STOLEN; | 718 | return NF_STOLEN; |
762 | iph = ip_hdr(skb); | 719 | iph = ip_hdr(skb); |
763 | *pskb = skb; | ||
764 | } | 720 | } |
765 | 721 | ||
766 | ihl = iph->ihl << 2; | 722 | ihl = iph->ihl << 2; |
@@ -802,13 +758,12 @@ ip_vs_out(unsigned int hooknum, struct sk_buff **pskb, | |||
802 | 758 | ||
803 | IP_VS_DBG_PKT(11, pp, skb, 0, "Outgoing packet"); | 759 | IP_VS_DBG_PKT(11, pp, skb, 0, "Outgoing packet"); |
804 | 760 | ||
805 | if (!ip_vs_make_skb_writable(pskb, ihl)) | 761 | if (!skb_make_writable(skb, ihl)) |
806 | goto drop; | 762 | goto drop; |
807 | 763 | ||
808 | /* mangle the packet */ | 764 | /* mangle the packet */ |
809 | if (pp->snat_handler && !pp->snat_handler(pskb, pp, cp)) | 765 | if (pp->snat_handler && !pp->snat_handler(skb, pp, cp)) |
810 | goto drop; | 766 | goto drop; |
811 | skb = *pskb; | ||
812 | ip_hdr(skb)->saddr = cp->vaddr; | 767 | ip_hdr(skb)->saddr = cp->vaddr; |
813 | ip_send_check(ip_hdr(skb)); | 768 | ip_send_check(ip_hdr(skb)); |
814 | 769 | ||
@@ -818,9 +773,8 @@ ip_vs_out(unsigned int hooknum, struct sk_buff **pskb, | |||
818 | * if it came from this machine itself. So re-compute | 773 | * if it came from this machine itself. So re-compute |
819 | * the routing information. | 774 | * the routing information. |
820 | */ | 775 | */ |
821 | if (ip_route_me_harder(pskb, RTN_LOCAL) != 0) | 776 | if (ip_route_me_harder(skb, RTN_LOCAL) != 0) |
822 | goto drop; | 777 | goto drop; |
823 | skb = *pskb; | ||
824 | 778 | ||
825 | IP_VS_DBG_PKT(10, pp, skb, 0, "After SNAT"); | 779 | IP_VS_DBG_PKT(10, pp, skb, 0, "After SNAT"); |
826 | 780 | ||
@@ -835,7 +789,7 @@ ip_vs_out(unsigned int hooknum, struct sk_buff **pskb, | |||
835 | 789 | ||
836 | drop: | 790 | drop: |
837 | ip_vs_conn_put(cp); | 791 | ip_vs_conn_put(cp); |
838 | kfree_skb(*pskb); | 792 | kfree_skb(skb); |
839 | return NF_STOLEN; | 793 | return NF_STOLEN; |
840 | } | 794 | } |
841 | 795 | ||
@@ -847,9 +801,8 @@ ip_vs_out(unsigned int hooknum, struct sk_buff **pskb, | |||
847 | * Currently handles error types - unreachable, quench, ttl exceeded. | 801 | * Currently handles error types - unreachable, quench, ttl exceeded. |
848 | */ | 802 | */ |
849 | static int | 803 | static int |
850 | ip_vs_in_icmp(struct sk_buff **pskb, int *related, unsigned int hooknum) | 804 | ip_vs_in_icmp(struct sk_buff *skb, int *related, unsigned int hooknum) |
851 | { | 805 | { |
852 | struct sk_buff *skb = *pskb; | ||
853 | struct iphdr *iph; | 806 | struct iphdr *iph; |
854 | struct icmphdr _icmph, *ic; | 807 | struct icmphdr _icmph, *ic; |
855 | struct iphdr _ciph, *cih; /* The ip header contained within the ICMP */ | 808 | struct iphdr _ciph, *cih; /* The ip header contained within the ICMP */ |
@@ -861,12 +814,9 @@ ip_vs_in_icmp(struct sk_buff **pskb, int *related, unsigned int hooknum) | |||
861 | 814 | ||
862 | /* reassemble IP fragments */ | 815 | /* reassemble IP fragments */ |
863 | if (ip_hdr(skb)->frag_off & htons(IP_MF | IP_OFFSET)) { | 816 | if (ip_hdr(skb)->frag_off & htons(IP_MF | IP_OFFSET)) { |
864 | skb = ip_vs_gather_frags(skb, | 817 | if (ip_vs_gather_frags(skb, hooknum == NF_IP_LOCAL_IN ? |
865 | hooknum == NF_IP_LOCAL_IN ? | 818 | IP_DEFRAG_VS_IN : IP_DEFRAG_VS_FWD)) |
866 | IP_DEFRAG_VS_IN : IP_DEFRAG_VS_FWD); | ||
867 | if (!skb) | ||
868 | return NF_STOLEN; | 819 | return NF_STOLEN; |
869 | *pskb = skb; | ||
870 | } | 820 | } |
871 | 821 | ||
872 | iph = ip_hdr(skb); | 822 | iph = ip_hdr(skb); |
@@ -945,11 +895,10 @@ ip_vs_in_icmp(struct sk_buff **pskb, int *related, unsigned int hooknum) | |||
945 | * and send it on its way... | 895 | * and send it on its way... |
946 | */ | 896 | */ |
947 | static unsigned int | 897 | static unsigned int |
948 | ip_vs_in(unsigned int hooknum, struct sk_buff **pskb, | 898 | ip_vs_in(unsigned int hooknum, struct sk_buff *skb, |
949 | const struct net_device *in, const struct net_device *out, | 899 | const struct net_device *in, const struct net_device *out, |
950 | int (*okfn)(struct sk_buff *)) | 900 | int (*okfn)(struct sk_buff *)) |
951 | { | 901 | { |
952 | struct sk_buff *skb = *pskb; | ||
953 | struct iphdr *iph; | 902 | struct iphdr *iph; |
954 | struct ip_vs_protocol *pp; | 903 | struct ip_vs_protocol *pp; |
955 | struct ip_vs_conn *cp; | 904 | struct ip_vs_conn *cp; |
@@ -971,11 +920,10 @@ ip_vs_in(unsigned int hooknum, struct sk_buff **pskb, | |||
971 | 920 | ||
972 | iph = ip_hdr(skb); | 921 | iph = ip_hdr(skb); |
973 | if (unlikely(iph->protocol == IPPROTO_ICMP)) { | 922 | if (unlikely(iph->protocol == IPPROTO_ICMP)) { |
974 | int related, verdict = ip_vs_in_icmp(pskb, &related, hooknum); | 923 | int related, verdict = ip_vs_in_icmp(skb, &related, hooknum); |
975 | 924 | ||
976 | if (related) | 925 | if (related) |
977 | return verdict; | 926 | return verdict; |
978 | skb = *pskb; | ||
979 | iph = ip_hdr(skb); | 927 | iph = ip_hdr(skb); |
980 | } | 928 | } |
981 | 929 | ||
@@ -1056,16 +1004,16 @@ ip_vs_in(unsigned int hooknum, struct sk_buff **pskb, | |||
1056 | * and send them to ip_vs_in_icmp. | 1004 | * and send them to ip_vs_in_icmp. |
1057 | */ | 1005 | */ |
1058 | static unsigned int | 1006 | static unsigned int |
1059 | ip_vs_forward_icmp(unsigned int hooknum, struct sk_buff **pskb, | 1007 | ip_vs_forward_icmp(unsigned int hooknum, struct sk_buff *skb, |
1060 | const struct net_device *in, const struct net_device *out, | 1008 | const struct net_device *in, const struct net_device *out, |
1061 | int (*okfn)(struct sk_buff *)) | 1009 | int (*okfn)(struct sk_buff *)) |
1062 | { | 1010 | { |
1063 | int r; | 1011 | int r; |
1064 | 1012 | ||
1065 | if (ip_hdr(*pskb)->protocol != IPPROTO_ICMP) | 1013 | if (ip_hdr(skb)->protocol != IPPROTO_ICMP) |
1066 | return NF_ACCEPT; | 1014 | return NF_ACCEPT; |
1067 | 1015 | ||
1068 | return ip_vs_in_icmp(pskb, &r, hooknum); | 1016 | return ip_vs_in_icmp(skb, &r, hooknum); |
1069 | } | 1017 | } |
1070 | 1018 | ||
1071 | 1019 | ||
diff --git a/net/ipv4/ipvs/ip_vs_ftp.c b/net/ipv4/ipvs/ip_vs_ftp.c index 344ddbbdc756..59aa166b7678 100644 --- a/net/ipv4/ipvs/ip_vs_ftp.c +++ b/net/ipv4/ipvs/ip_vs_ftp.c | |||
@@ -30,6 +30,7 @@ | |||
30 | #include <linux/skbuff.h> | 30 | #include <linux/skbuff.h> |
31 | #include <linux/in.h> | 31 | #include <linux/in.h> |
32 | #include <linux/ip.h> | 32 | #include <linux/ip.h> |
33 | #include <linux/netfilter.h> | ||
33 | #include <net/protocol.h> | 34 | #include <net/protocol.h> |
34 | #include <net/tcp.h> | 35 | #include <net/tcp.h> |
35 | #include <asm/unaligned.h> | 36 | #include <asm/unaligned.h> |
@@ -135,7 +136,7 @@ static int ip_vs_ftp_get_addrport(char *data, char *data_limit, | |||
135 | * xxx,xxx,xxx,xxx is the server address, ppp,ppp is the server port number. | 136 | * xxx,xxx,xxx,xxx is the server address, ppp,ppp is the server port number. |
136 | */ | 137 | */ |
137 | static int ip_vs_ftp_out(struct ip_vs_app *app, struct ip_vs_conn *cp, | 138 | static int ip_vs_ftp_out(struct ip_vs_app *app, struct ip_vs_conn *cp, |
138 | struct sk_buff **pskb, int *diff) | 139 | struct sk_buff *skb, int *diff) |
139 | { | 140 | { |
140 | struct iphdr *iph; | 141 | struct iphdr *iph; |
141 | struct tcphdr *th; | 142 | struct tcphdr *th; |
@@ -155,14 +156,14 @@ static int ip_vs_ftp_out(struct ip_vs_app *app, struct ip_vs_conn *cp, | |||
155 | return 1; | 156 | return 1; |
156 | 157 | ||
157 | /* Linear packets are much easier to deal with. */ | 158 | /* Linear packets are much easier to deal with. */ |
158 | if (!ip_vs_make_skb_writable(pskb, (*pskb)->len)) | 159 | if (!skb_make_writable(skb, skb->len)) |
159 | return 0; | 160 | return 0; |
160 | 161 | ||
161 | if (cp->app_data == &ip_vs_ftp_pasv) { | 162 | if (cp->app_data == &ip_vs_ftp_pasv) { |
162 | iph = ip_hdr(*pskb); | 163 | iph = ip_hdr(skb); |
163 | th = (struct tcphdr *)&(((char *)iph)[iph->ihl*4]); | 164 | th = (struct tcphdr *)&(((char *)iph)[iph->ihl*4]); |
164 | data = (char *)th + (th->doff << 2); | 165 | data = (char *)th + (th->doff << 2); |
165 | data_limit = skb_tail_pointer(*pskb); | 166 | data_limit = skb_tail_pointer(skb); |
166 | 167 | ||
167 | if (ip_vs_ftp_get_addrport(data, data_limit, | 168 | if (ip_vs_ftp_get_addrport(data, data_limit, |
168 | SERVER_STRING, | 169 | SERVER_STRING, |
@@ -213,7 +214,7 @@ static int ip_vs_ftp_out(struct ip_vs_app *app, struct ip_vs_conn *cp, | |||
213 | memcpy(start, buf, buf_len); | 214 | memcpy(start, buf, buf_len); |
214 | ret = 1; | 215 | ret = 1; |
215 | } else { | 216 | } else { |
216 | ret = !ip_vs_skb_replace(*pskb, GFP_ATOMIC, start, | 217 | ret = !ip_vs_skb_replace(skb, GFP_ATOMIC, start, |
217 | end-start, buf, buf_len); | 218 | end-start, buf, buf_len); |
218 | } | 219 | } |
219 | 220 | ||
@@ -238,7 +239,7 @@ static int ip_vs_ftp_out(struct ip_vs_app *app, struct ip_vs_conn *cp, | |||
238 | * the client. | 239 | * the client. |
239 | */ | 240 | */ |
240 | static int ip_vs_ftp_in(struct ip_vs_app *app, struct ip_vs_conn *cp, | 241 | static int ip_vs_ftp_in(struct ip_vs_app *app, struct ip_vs_conn *cp, |
241 | struct sk_buff **pskb, int *diff) | 242 | struct sk_buff *skb, int *diff) |
242 | { | 243 | { |
243 | struct iphdr *iph; | 244 | struct iphdr *iph; |
244 | struct tcphdr *th; | 245 | struct tcphdr *th; |
@@ -256,20 +257,20 @@ static int ip_vs_ftp_in(struct ip_vs_app *app, struct ip_vs_conn *cp, | |||
256 | return 1; | 257 | return 1; |
257 | 258 | ||
258 | /* Linear packets are much easier to deal with. */ | 259 | /* Linear packets are much easier to deal with. */ |
259 | if (!ip_vs_make_skb_writable(pskb, (*pskb)->len)) | 260 | if (!skb_make_writable(skb, skb->len)) |
260 | return 0; | 261 | return 0; |
261 | 262 | ||
262 | /* | 263 | /* |
263 | * Detecting whether it is passive | 264 | * Detecting whether it is passive |
264 | */ | 265 | */ |
265 | iph = ip_hdr(*pskb); | 266 | iph = ip_hdr(skb); |
266 | th = (struct tcphdr *)&(((char *)iph)[iph->ihl*4]); | 267 | th = (struct tcphdr *)&(((char *)iph)[iph->ihl*4]); |
267 | 268 | ||
268 | /* Since there may be OPTIONS in the TCP packet and the HLEN is | 269 | /* Since there may be OPTIONS in the TCP packet and the HLEN is |
269 | the length of the header in 32-bit multiples, it is accurate | 270 | the length of the header in 32-bit multiples, it is accurate |
270 | to calculate data address by th+HLEN*4 */ | 271 | to calculate data address by th+HLEN*4 */ |
271 | data = data_start = (char *)th + (th->doff << 2); | 272 | data = data_start = (char *)th + (th->doff << 2); |
272 | data_limit = skb_tail_pointer(*pskb); | 273 | data_limit = skb_tail_pointer(skb); |
273 | 274 | ||
274 | while (data <= data_limit - 6) { | 275 | while (data <= data_limit - 6) { |
275 | if (strnicmp(data, "PASV\r\n", 6) == 0) { | 276 | if (strnicmp(data, "PASV\r\n", 6) == 0) { |
diff --git a/net/ipv4/ipvs/ip_vs_proto_tcp.c b/net/ipv4/ipvs/ip_vs_proto_tcp.c index e65577a77006..12dc0d640b6d 100644 --- a/net/ipv4/ipvs/ip_vs_proto_tcp.c +++ b/net/ipv4/ipvs/ip_vs_proto_tcp.c | |||
@@ -20,6 +20,7 @@ | |||
20 | #include <linux/tcp.h> /* for tcphdr */ | 20 | #include <linux/tcp.h> /* for tcphdr */ |
21 | #include <net/ip.h> | 21 | #include <net/ip.h> |
22 | #include <net/tcp.h> /* for csum_tcpudp_magic */ | 22 | #include <net/tcp.h> /* for csum_tcpudp_magic */ |
23 | #include <linux/netfilter.h> | ||
23 | #include <linux/netfilter_ipv4.h> | 24 | #include <linux/netfilter_ipv4.h> |
24 | 25 | ||
25 | #include <net/ip_vs.h> | 26 | #include <net/ip_vs.h> |
@@ -122,27 +123,27 @@ tcp_fast_csum_update(struct tcphdr *tcph, __be32 oldip, __be32 newip, | |||
122 | 123 | ||
123 | 124 | ||
124 | static int | 125 | static int |
125 | tcp_snat_handler(struct sk_buff **pskb, | 126 | tcp_snat_handler(struct sk_buff *skb, |
126 | struct ip_vs_protocol *pp, struct ip_vs_conn *cp) | 127 | struct ip_vs_protocol *pp, struct ip_vs_conn *cp) |
127 | { | 128 | { |
128 | struct tcphdr *tcph; | 129 | struct tcphdr *tcph; |
129 | const unsigned int tcphoff = ip_hdrlen(*pskb); | 130 | const unsigned int tcphoff = ip_hdrlen(skb); |
130 | 131 | ||
131 | /* csum_check requires unshared skb */ | 132 | /* csum_check requires unshared skb */ |
132 | if (!ip_vs_make_skb_writable(pskb, tcphoff+sizeof(*tcph))) | 133 | if (!skb_make_writable(skb, tcphoff+sizeof(*tcph))) |
133 | return 0; | 134 | return 0; |
134 | 135 | ||
135 | if (unlikely(cp->app != NULL)) { | 136 | if (unlikely(cp->app != NULL)) { |
136 | /* Some checks before mangling */ | 137 | /* Some checks before mangling */ |
137 | if (pp->csum_check && !pp->csum_check(*pskb, pp)) | 138 | if (pp->csum_check && !pp->csum_check(skb, pp)) |
138 | return 0; | 139 | return 0; |
139 | 140 | ||
140 | /* Call application helper if needed */ | 141 | /* Call application helper if needed */ |
141 | if (!ip_vs_app_pkt_out(cp, pskb)) | 142 | if (!ip_vs_app_pkt_out(cp, skb)) |
142 | return 0; | 143 | return 0; |
143 | } | 144 | } |
144 | 145 | ||
145 | tcph = (void *)ip_hdr(*pskb) + tcphoff; | 146 | tcph = (void *)ip_hdr(skb) + tcphoff; |
146 | tcph->source = cp->vport; | 147 | tcph->source = cp->vport; |
147 | 148 | ||
148 | /* Adjust TCP checksums */ | 149 | /* Adjust TCP checksums */ |
@@ -150,17 +151,15 @@ tcp_snat_handler(struct sk_buff **pskb, | |||
150 | /* Only port and addr are changed, do fast csum update */ | 151 | /* Only port and addr are changed, do fast csum update */ |
151 | tcp_fast_csum_update(tcph, cp->daddr, cp->vaddr, | 152 | tcp_fast_csum_update(tcph, cp->daddr, cp->vaddr, |
152 | cp->dport, cp->vport); | 153 | cp->dport, cp->vport); |
153 | if ((*pskb)->ip_summed == CHECKSUM_COMPLETE) | 154 | if (skb->ip_summed == CHECKSUM_COMPLETE) |
154 | (*pskb)->ip_summed = CHECKSUM_NONE; | 155 | skb->ip_summed = CHECKSUM_NONE; |
155 | } else { | 156 | } else { |
156 | /* full checksum calculation */ | 157 | /* full checksum calculation */ |
157 | tcph->check = 0; | 158 | tcph->check = 0; |
158 | (*pskb)->csum = skb_checksum(*pskb, tcphoff, | 159 | skb->csum = skb_checksum(skb, tcphoff, skb->len - tcphoff, 0); |
159 | (*pskb)->len - tcphoff, 0); | ||
160 | tcph->check = csum_tcpudp_magic(cp->vaddr, cp->caddr, | 160 | tcph->check = csum_tcpudp_magic(cp->vaddr, cp->caddr, |
161 | (*pskb)->len - tcphoff, | 161 | skb->len - tcphoff, |
162 | cp->protocol, | 162 | cp->protocol, skb->csum); |
163 | (*pskb)->csum); | ||
164 | IP_VS_DBG(11, "O-pkt: %s O-csum=%d (+%zd)\n", | 163 | IP_VS_DBG(11, "O-pkt: %s O-csum=%d (+%zd)\n", |
165 | pp->name, tcph->check, | 164 | pp->name, tcph->check, |
166 | (char*)&(tcph->check) - (char*)tcph); | 165 | (char*)&(tcph->check) - (char*)tcph); |
@@ -170,30 +169,30 @@ tcp_snat_handler(struct sk_buff **pskb, | |||
170 | 169 | ||
171 | 170 | ||
172 | static int | 171 | static int |
173 | tcp_dnat_handler(struct sk_buff **pskb, | 172 | tcp_dnat_handler(struct sk_buff *skb, |
174 | struct ip_vs_protocol *pp, struct ip_vs_conn *cp) | 173 | struct ip_vs_protocol *pp, struct ip_vs_conn *cp) |
175 | { | 174 | { |
176 | struct tcphdr *tcph; | 175 | struct tcphdr *tcph; |
177 | const unsigned int tcphoff = ip_hdrlen(*pskb); | 176 | const unsigned int tcphoff = ip_hdrlen(skb); |
178 | 177 | ||
179 | /* csum_check requires unshared skb */ | 178 | /* csum_check requires unshared skb */ |
180 | if (!ip_vs_make_skb_writable(pskb, tcphoff+sizeof(*tcph))) | 179 | if (!skb_make_writable(skb, tcphoff+sizeof(*tcph))) |
181 | return 0; | 180 | return 0; |
182 | 181 | ||
183 | if (unlikely(cp->app != NULL)) { | 182 | if (unlikely(cp->app != NULL)) { |
184 | /* Some checks before mangling */ | 183 | /* Some checks before mangling */ |
185 | if (pp->csum_check && !pp->csum_check(*pskb, pp)) | 184 | if (pp->csum_check && !pp->csum_check(skb, pp)) |
186 | return 0; | 185 | return 0; |
187 | 186 | ||
188 | /* | 187 | /* |
189 | * Attempt ip_vs_app call. | 188 | * Attempt ip_vs_app call. |
190 | * It will fix ip_vs_conn and iph ack_seq stuff | 189 | * It will fix ip_vs_conn and iph ack_seq stuff |
191 | */ | 190 | */ |
192 | if (!ip_vs_app_pkt_in(cp, pskb)) | 191 | if (!ip_vs_app_pkt_in(cp, skb)) |
193 | return 0; | 192 | return 0; |
194 | } | 193 | } |
195 | 194 | ||
196 | tcph = (void *)ip_hdr(*pskb) + tcphoff; | 195 | tcph = (void *)ip_hdr(skb) + tcphoff; |
197 | tcph->dest = cp->dport; | 196 | tcph->dest = cp->dport; |
198 | 197 | ||
199 | /* | 198 | /* |
@@ -203,18 +202,16 @@ tcp_dnat_handler(struct sk_buff **pskb, | |||
203 | /* Only port and addr are changed, do fast csum update */ | 202 | /* Only port and addr are changed, do fast csum update */ |
204 | tcp_fast_csum_update(tcph, cp->vaddr, cp->daddr, | 203 | tcp_fast_csum_update(tcph, cp->vaddr, cp->daddr, |
205 | cp->vport, cp->dport); | 204 | cp->vport, cp->dport); |
206 | if ((*pskb)->ip_summed == CHECKSUM_COMPLETE) | 205 | if (skb->ip_summed == CHECKSUM_COMPLETE) |
207 | (*pskb)->ip_summed = CHECKSUM_NONE; | 206 | skb->ip_summed = CHECKSUM_NONE; |
208 | } else { | 207 | } else { |
209 | /* full checksum calculation */ | 208 | /* full checksum calculation */ |
210 | tcph->check = 0; | 209 | tcph->check = 0; |
211 | (*pskb)->csum = skb_checksum(*pskb, tcphoff, | 210 | skb->csum = skb_checksum(skb, tcphoff, skb->len - tcphoff, 0); |
212 | (*pskb)->len - tcphoff, 0); | ||
213 | tcph->check = csum_tcpudp_magic(cp->caddr, cp->daddr, | 211 | tcph->check = csum_tcpudp_magic(cp->caddr, cp->daddr, |
214 | (*pskb)->len - tcphoff, | 212 | skb->len - tcphoff, |
215 | cp->protocol, | 213 | cp->protocol, skb->csum); |
216 | (*pskb)->csum); | 214 | skb->ip_summed = CHECKSUM_UNNECESSARY; |
217 | (*pskb)->ip_summed = CHECKSUM_UNNECESSARY; | ||
218 | } | 215 | } |
219 | return 1; | 216 | return 1; |
220 | } | 217 | } |
diff --git a/net/ipv4/ipvs/ip_vs_proto_udp.c b/net/ipv4/ipvs/ip_vs_proto_udp.c index 8ee5fe6a101d..1fa7b330b9ac 100644 --- a/net/ipv4/ipvs/ip_vs_proto_udp.c +++ b/net/ipv4/ipvs/ip_vs_proto_udp.c | |||
@@ -18,6 +18,7 @@ | |||
18 | #include <linux/in.h> | 18 | #include <linux/in.h> |
19 | #include <linux/ip.h> | 19 | #include <linux/ip.h> |
20 | #include <linux/kernel.h> | 20 | #include <linux/kernel.h> |
21 | #include <linux/netfilter.h> | ||
21 | #include <linux/netfilter_ipv4.h> | 22 | #include <linux/netfilter_ipv4.h> |
22 | #include <linux/udp.h> | 23 | #include <linux/udp.h> |
23 | 24 | ||
@@ -129,29 +130,29 @@ udp_fast_csum_update(struct udphdr *uhdr, __be32 oldip, __be32 newip, | |||
129 | } | 130 | } |
130 | 131 | ||
131 | static int | 132 | static int |
132 | udp_snat_handler(struct sk_buff **pskb, | 133 | udp_snat_handler(struct sk_buff *skb, |
133 | struct ip_vs_protocol *pp, struct ip_vs_conn *cp) | 134 | struct ip_vs_protocol *pp, struct ip_vs_conn *cp) |
134 | { | 135 | { |
135 | struct udphdr *udph; | 136 | struct udphdr *udph; |
136 | const unsigned int udphoff = ip_hdrlen(*pskb); | 137 | const unsigned int udphoff = ip_hdrlen(skb); |
137 | 138 | ||
138 | /* csum_check requires unshared skb */ | 139 | /* csum_check requires unshared skb */ |
139 | if (!ip_vs_make_skb_writable(pskb, udphoff+sizeof(*udph))) | 140 | if (!skb_make_writable(skb, udphoff+sizeof(*udph))) |
140 | return 0; | 141 | return 0; |
141 | 142 | ||
142 | if (unlikely(cp->app != NULL)) { | 143 | if (unlikely(cp->app != NULL)) { |
143 | /* Some checks before mangling */ | 144 | /* Some checks before mangling */ |
144 | if (pp->csum_check && !pp->csum_check(*pskb, pp)) | 145 | if (pp->csum_check && !pp->csum_check(skb, pp)) |
145 | return 0; | 146 | return 0; |
146 | 147 | ||
147 | /* | 148 | /* |
148 | * Call application helper if needed | 149 | * Call application helper if needed |
149 | */ | 150 | */ |
150 | if (!ip_vs_app_pkt_out(cp, pskb)) | 151 | if (!ip_vs_app_pkt_out(cp, skb)) |
151 | return 0; | 152 | return 0; |
152 | } | 153 | } |
153 | 154 | ||
154 | udph = (void *)ip_hdr(*pskb) + udphoff; | 155 | udph = (void *)ip_hdr(skb) + udphoff; |
155 | udph->source = cp->vport; | 156 | udph->source = cp->vport; |
156 | 157 | ||
157 | /* | 158 | /* |
@@ -161,17 +162,15 @@ udp_snat_handler(struct sk_buff **pskb, | |||
161 | /* Only port and addr are changed, do fast csum update */ | 162 | /* Only port and addr are changed, do fast csum update */ |
162 | udp_fast_csum_update(udph, cp->daddr, cp->vaddr, | 163 | udp_fast_csum_update(udph, cp->daddr, cp->vaddr, |
163 | cp->dport, cp->vport); | 164 | cp->dport, cp->vport); |
164 | if ((*pskb)->ip_summed == CHECKSUM_COMPLETE) | 165 | if (skb->ip_summed == CHECKSUM_COMPLETE) |
165 | (*pskb)->ip_summed = CHECKSUM_NONE; | 166 | skb->ip_summed = CHECKSUM_NONE; |
166 | } else { | 167 | } else { |
167 | /* full checksum calculation */ | 168 | /* full checksum calculation */ |
168 | udph->check = 0; | 169 | udph->check = 0; |
169 | (*pskb)->csum = skb_checksum(*pskb, udphoff, | 170 | skb->csum = skb_checksum(skb, udphoff, skb->len - udphoff, 0); |
170 | (*pskb)->len - udphoff, 0); | ||
171 | udph->check = csum_tcpudp_magic(cp->vaddr, cp->caddr, | 171 | udph->check = csum_tcpudp_magic(cp->vaddr, cp->caddr, |
172 | (*pskb)->len - udphoff, | 172 | skb->len - udphoff, |
173 | cp->protocol, | 173 | cp->protocol, skb->csum); |
174 | (*pskb)->csum); | ||
175 | if (udph->check == 0) | 174 | if (udph->check == 0) |
176 | udph->check = CSUM_MANGLED_0; | 175 | udph->check = CSUM_MANGLED_0; |
177 | IP_VS_DBG(11, "O-pkt: %s O-csum=%d (+%zd)\n", | 176 | IP_VS_DBG(11, "O-pkt: %s O-csum=%d (+%zd)\n", |
@@ -183,30 +182,30 @@ udp_snat_handler(struct sk_buff **pskb, | |||
183 | 182 | ||
184 | 183 | ||
185 | static int | 184 | static int |
186 | udp_dnat_handler(struct sk_buff **pskb, | 185 | udp_dnat_handler(struct sk_buff *skb, |
187 | struct ip_vs_protocol *pp, struct ip_vs_conn *cp) | 186 | struct ip_vs_protocol *pp, struct ip_vs_conn *cp) |
188 | { | 187 | { |
189 | struct udphdr *udph; | 188 | struct udphdr *udph; |
190 | unsigned int udphoff = ip_hdrlen(*pskb); | 189 | unsigned int udphoff = ip_hdrlen(skb); |
191 | 190 | ||
192 | /* csum_check requires unshared skb */ | 191 | /* csum_check requires unshared skb */ |
193 | if (!ip_vs_make_skb_writable(pskb, udphoff+sizeof(*udph))) | 192 | if (!skb_make_writable(skb, udphoff+sizeof(*udph))) |
194 | return 0; | 193 | return 0; |
195 | 194 | ||
196 | if (unlikely(cp->app != NULL)) { | 195 | if (unlikely(cp->app != NULL)) { |
197 | /* Some checks before mangling */ | 196 | /* Some checks before mangling */ |
198 | if (pp->csum_check && !pp->csum_check(*pskb, pp)) | 197 | if (pp->csum_check && !pp->csum_check(skb, pp)) |
199 | return 0; | 198 | return 0; |
200 | 199 | ||
201 | /* | 200 | /* |
202 | * Attempt ip_vs_app call. | 201 | * Attempt ip_vs_app call. |
203 | * It will fix ip_vs_conn | 202 | * It will fix ip_vs_conn |
204 | */ | 203 | */ |
205 | if (!ip_vs_app_pkt_in(cp, pskb)) | 204 | if (!ip_vs_app_pkt_in(cp, skb)) |
206 | return 0; | 205 | return 0; |
207 | } | 206 | } |
208 | 207 | ||
209 | udph = (void *)ip_hdr(*pskb) + udphoff; | 208 | udph = (void *)ip_hdr(skb) + udphoff; |
210 | udph->dest = cp->dport; | 209 | udph->dest = cp->dport; |
211 | 210 | ||
212 | /* | 211 | /* |
@@ -216,20 +215,18 @@ udp_dnat_handler(struct sk_buff **pskb, | |||
216 | /* Only port and addr are changed, do fast csum update */ | 215 | /* Only port and addr are changed, do fast csum update */ |
217 | udp_fast_csum_update(udph, cp->vaddr, cp->daddr, | 216 | udp_fast_csum_update(udph, cp->vaddr, cp->daddr, |
218 | cp->vport, cp->dport); | 217 | cp->vport, cp->dport); |
219 | if ((*pskb)->ip_summed == CHECKSUM_COMPLETE) | 218 | if (skb->ip_summed == CHECKSUM_COMPLETE) |
220 | (*pskb)->ip_summed = CHECKSUM_NONE; | 219 | skb->ip_summed = CHECKSUM_NONE; |
221 | } else { | 220 | } else { |
222 | /* full checksum calculation */ | 221 | /* full checksum calculation */ |
223 | udph->check = 0; | 222 | udph->check = 0; |
224 | (*pskb)->csum = skb_checksum(*pskb, udphoff, | 223 | skb->csum = skb_checksum(skb, udphoff, skb->len - udphoff, 0); |
225 | (*pskb)->len - udphoff, 0); | ||
226 | udph->check = csum_tcpudp_magic(cp->caddr, cp->daddr, | 224 | udph->check = csum_tcpudp_magic(cp->caddr, cp->daddr, |
227 | (*pskb)->len - udphoff, | 225 | skb->len - udphoff, |
228 | cp->protocol, | 226 | cp->protocol, skb->csum); |
229 | (*pskb)->csum); | ||
230 | if (udph->check == 0) | 227 | if (udph->check == 0) |
231 | udph->check = CSUM_MANGLED_0; | 228 | udph->check = CSUM_MANGLED_0; |
232 | (*pskb)->ip_summed = CHECKSUM_UNNECESSARY; | 229 | skb->ip_summed = CHECKSUM_UNNECESSARY; |
233 | } | 230 | } |
234 | return 1; | 231 | return 1; |
235 | } | 232 | } |
diff --git a/net/ipv4/ipvs/ip_vs_sync.c b/net/ipv4/ipvs/ip_vs_sync.c index 1960747f354c..c99f2a33fb9e 100644 --- a/net/ipv4/ipvs/ip_vs_sync.c +++ b/net/ipv4/ipvs/ip_vs_sync.c | |||
@@ -794,7 +794,7 @@ static int sync_thread(void *startup) | |||
794 | 794 | ||
795 | add_wait_queue(&sync_wait, &wait); | 795 | add_wait_queue(&sync_wait, &wait); |
796 | 796 | ||
797 | set_sync_pid(state, current->pid); | 797 | set_sync_pid(state, task_pid_nr(current)); |
798 | complete(tinfo->startup); | 798 | complete(tinfo->startup); |
799 | 799 | ||
800 | /* | 800 | /* |
@@ -877,7 +877,7 @@ int start_sync_thread(int state, char *mcast_ifn, __u8 syncid) | |||
877 | if (!tinfo) | 877 | if (!tinfo) |
878 | return -ENOMEM; | 878 | return -ENOMEM; |
879 | 879 | ||
880 | IP_VS_DBG(7, "%s: pid %d\n", __FUNCTION__, current->pid); | 880 | IP_VS_DBG(7, "%s: pid %d\n", __FUNCTION__, task_pid_nr(current)); |
881 | IP_VS_DBG(7, "Each ip_vs_sync_conn entry need %Zd bytes\n", | 881 | IP_VS_DBG(7, "Each ip_vs_sync_conn entry need %Zd bytes\n", |
882 | sizeof(struct ip_vs_sync_conn)); | 882 | sizeof(struct ip_vs_sync_conn)); |
883 | 883 | ||
@@ -917,7 +917,7 @@ int stop_sync_thread(int state) | |||
917 | (state == IP_VS_STATE_BACKUP && !sync_backup_pid)) | 917 | (state == IP_VS_STATE_BACKUP && !sync_backup_pid)) |
918 | return -ESRCH; | 918 | return -ESRCH; |
919 | 919 | ||
920 | IP_VS_DBG(7, "%s: pid %d\n", __FUNCTION__, current->pid); | 920 | IP_VS_DBG(7, "%s: pid %d\n", __FUNCTION__, task_pid_nr(current)); |
921 | IP_VS_INFO("stopping sync thread %d ...\n", | 921 | IP_VS_INFO("stopping sync thread %d ...\n", |
922 | (state == IP_VS_STATE_MASTER) ? | 922 | (state == IP_VS_STATE_MASTER) ? |
923 | sync_master_pid : sync_backup_pid); | 923 | sync_master_pid : sync_backup_pid); |
diff --git a/net/ipv4/ipvs/ip_vs_xmit.c b/net/ipv4/ipvs/ip_vs_xmit.c index 666e080a74a3..d0a92dec1050 100644 --- a/net/ipv4/ipvs/ip_vs_xmit.c +++ b/net/ipv4/ipvs/ip_vs_xmit.c | |||
@@ -253,7 +253,7 @@ ip_vs_nat_xmit(struct sk_buff *skb, struct ip_vs_conn *cp, | |||
253 | } | 253 | } |
254 | 254 | ||
255 | /* copy-on-write the packet before mangling it */ | 255 | /* copy-on-write the packet before mangling it */ |
256 | if (!ip_vs_make_skb_writable(&skb, sizeof(struct iphdr))) | 256 | if (!skb_make_writable(skb, sizeof(struct iphdr))) |
257 | goto tx_error_put; | 257 | goto tx_error_put; |
258 | 258 | ||
259 | if (skb_cow(skb, rt->u.dst.dev->hard_header_len)) | 259 | if (skb_cow(skb, rt->u.dst.dev->hard_header_len)) |
@@ -264,7 +264,7 @@ ip_vs_nat_xmit(struct sk_buff *skb, struct ip_vs_conn *cp, | |||
264 | skb->dst = &rt->u.dst; | 264 | skb->dst = &rt->u.dst; |
265 | 265 | ||
266 | /* mangle the packet */ | 266 | /* mangle the packet */ |
267 | if (pp->dnat_handler && !pp->dnat_handler(&skb, pp, cp)) | 267 | if (pp->dnat_handler && !pp->dnat_handler(skb, pp, cp)) |
268 | goto tx_error; | 268 | goto tx_error; |
269 | ip_hdr(skb)->daddr = cp->daddr; | 269 | ip_hdr(skb)->daddr = cp->daddr; |
270 | ip_send_check(ip_hdr(skb)); | 270 | ip_send_check(ip_hdr(skb)); |
@@ -529,7 +529,7 @@ ip_vs_icmp_xmit(struct sk_buff *skb, struct ip_vs_conn *cp, | |||
529 | } | 529 | } |
530 | 530 | ||
531 | /* copy-on-write the packet before mangling it */ | 531 | /* copy-on-write the packet before mangling it */ |
532 | if (!ip_vs_make_skb_writable(&skb, offset)) | 532 | if (!skb_make_writable(skb, offset)) |
533 | goto tx_error_put; | 533 | goto tx_error_put; |
534 | 534 | ||
535 | if (skb_cow(skb, rt->u.dst.dev->hard_header_len)) | 535 | if (skb_cow(skb, rt->u.dst.dev->hard_header_len)) |
diff --git a/net/ipv4/netfilter.c b/net/ipv4/netfilter.c index b44192924f95..5539debf4973 100644 --- a/net/ipv4/netfilter.c +++ b/net/ipv4/netfilter.c | |||
@@ -3,14 +3,15 @@ | |||
3 | #include <linux/netfilter.h> | 3 | #include <linux/netfilter.h> |
4 | #include <linux/netfilter_ipv4.h> | 4 | #include <linux/netfilter_ipv4.h> |
5 | #include <linux/ip.h> | 5 | #include <linux/ip.h> |
6 | #include <linux/skbuff.h> | ||
6 | #include <net/route.h> | 7 | #include <net/route.h> |
7 | #include <net/xfrm.h> | 8 | #include <net/xfrm.h> |
8 | #include <net/ip.h> | 9 | #include <net/ip.h> |
9 | 10 | ||
10 | /* route_me_harder function, used by iptable_nat, iptable_mangle + ip_queue */ | 11 | /* route_me_harder function, used by iptable_nat, iptable_mangle + ip_queue */ |
11 | int ip_route_me_harder(struct sk_buff **pskb, unsigned addr_type) | 12 | int ip_route_me_harder(struct sk_buff *skb, unsigned addr_type) |
12 | { | 13 | { |
13 | const struct iphdr *iph = ip_hdr(*pskb); | 14 | const struct iphdr *iph = ip_hdr(skb); |
14 | struct rtable *rt; | 15 | struct rtable *rt; |
15 | struct flowi fl = {}; | 16 | struct flowi fl = {}; |
16 | struct dst_entry *odst; | 17 | struct dst_entry *odst; |
@@ -29,14 +30,14 @@ int ip_route_me_harder(struct sk_buff **pskb, unsigned addr_type) | |||
29 | if (type == RTN_LOCAL) | 30 | if (type == RTN_LOCAL) |
30 | fl.nl_u.ip4_u.saddr = iph->saddr; | 31 | fl.nl_u.ip4_u.saddr = iph->saddr; |
31 | fl.nl_u.ip4_u.tos = RT_TOS(iph->tos); | 32 | fl.nl_u.ip4_u.tos = RT_TOS(iph->tos); |
32 | fl.oif = (*pskb)->sk ? (*pskb)->sk->sk_bound_dev_if : 0; | 33 | fl.oif = skb->sk ? skb->sk->sk_bound_dev_if : 0; |
33 | fl.mark = (*pskb)->mark; | 34 | fl.mark = skb->mark; |
34 | if (ip_route_output_key(&rt, &fl) != 0) | 35 | if (ip_route_output_key(&rt, &fl) != 0) |
35 | return -1; | 36 | return -1; |
36 | 37 | ||
37 | /* Drop old route. */ | 38 | /* Drop old route. */ |
38 | dst_release((*pskb)->dst); | 39 | dst_release(skb->dst); |
39 | (*pskb)->dst = &rt->u.dst; | 40 | skb->dst = &rt->u.dst; |
40 | } else { | 41 | } else { |
41 | /* non-local src, find valid iif to satisfy | 42 | /* non-local src, find valid iif to satisfy |
42 | * rp-filter when calling ip_route_input. */ | 43 | * rp-filter when calling ip_route_input. */ |
@@ -44,8 +45,8 @@ int ip_route_me_harder(struct sk_buff **pskb, unsigned addr_type) | |||
44 | if (ip_route_output_key(&rt, &fl) != 0) | 45 | if (ip_route_output_key(&rt, &fl) != 0) |
45 | return -1; | 46 | return -1; |
46 | 47 | ||
47 | odst = (*pskb)->dst; | 48 | odst = skb->dst; |
48 | if (ip_route_input(*pskb, iph->daddr, iph->saddr, | 49 | if (ip_route_input(skb, iph->daddr, iph->saddr, |
49 | RT_TOS(iph->tos), rt->u.dst.dev) != 0) { | 50 | RT_TOS(iph->tos), rt->u.dst.dev) != 0) { |
50 | dst_release(&rt->u.dst); | 51 | dst_release(&rt->u.dst); |
51 | return -1; | 52 | return -1; |
@@ -54,70 +55,54 @@ int ip_route_me_harder(struct sk_buff **pskb, unsigned addr_type) | |||
54 | dst_release(odst); | 55 | dst_release(odst); |
55 | } | 56 | } |
56 | 57 | ||
57 | if ((*pskb)->dst->error) | 58 | if (skb->dst->error) |
58 | return -1; | 59 | return -1; |
59 | 60 | ||
60 | #ifdef CONFIG_XFRM | 61 | #ifdef CONFIG_XFRM |
61 | if (!(IPCB(*pskb)->flags & IPSKB_XFRM_TRANSFORMED) && | 62 | if (!(IPCB(skb)->flags & IPSKB_XFRM_TRANSFORMED) && |
62 | xfrm_decode_session(*pskb, &fl, AF_INET) == 0) | 63 | xfrm_decode_session(skb, &fl, AF_INET) == 0) |
63 | if (xfrm_lookup(&(*pskb)->dst, &fl, (*pskb)->sk, 0)) | 64 | if (xfrm_lookup(&skb->dst, &fl, skb->sk, 0)) |
64 | return -1; | 65 | return -1; |
65 | #endif | 66 | #endif |
66 | 67 | ||
67 | /* Change in oif may mean change in hh_len. */ | 68 | /* Change in oif may mean change in hh_len. */ |
68 | hh_len = (*pskb)->dst->dev->hard_header_len; | 69 | hh_len = skb->dst->dev->hard_header_len; |
69 | if (skb_headroom(*pskb) < hh_len) { | 70 | if (skb_headroom(skb) < hh_len && |
70 | struct sk_buff *nskb; | 71 | pskb_expand_head(skb, hh_len - skb_headroom(skb), 0, GFP_ATOMIC)) |
71 | 72 | return -1; | |
72 | nskb = skb_realloc_headroom(*pskb, hh_len); | ||
73 | if (!nskb) | ||
74 | return -1; | ||
75 | if ((*pskb)->sk) | ||
76 | skb_set_owner_w(nskb, (*pskb)->sk); | ||
77 | kfree_skb(*pskb); | ||
78 | *pskb = nskb; | ||
79 | } | ||
80 | 73 | ||
81 | return 0; | 74 | return 0; |
82 | } | 75 | } |
83 | EXPORT_SYMBOL(ip_route_me_harder); | 76 | EXPORT_SYMBOL(ip_route_me_harder); |
84 | 77 | ||
85 | #ifdef CONFIG_XFRM | 78 | #ifdef CONFIG_XFRM |
86 | int ip_xfrm_me_harder(struct sk_buff **pskb) | 79 | int ip_xfrm_me_harder(struct sk_buff *skb) |
87 | { | 80 | { |
88 | struct flowi fl; | 81 | struct flowi fl; |
89 | unsigned int hh_len; | 82 | unsigned int hh_len; |
90 | struct dst_entry *dst; | 83 | struct dst_entry *dst; |
91 | 84 | ||
92 | if (IPCB(*pskb)->flags & IPSKB_XFRM_TRANSFORMED) | 85 | if (IPCB(skb)->flags & IPSKB_XFRM_TRANSFORMED) |
93 | return 0; | 86 | return 0; |
94 | if (xfrm_decode_session(*pskb, &fl, AF_INET) < 0) | 87 | if (xfrm_decode_session(skb, &fl, AF_INET) < 0) |
95 | return -1; | 88 | return -1; |
96 | 89 | ||
97 | dst = (*pskb)->dst; | 90 | dst = skb->dst; |
98 | if (dst->xfrm) | 91 | if (dst->xfrm) |
99 | dst = ((struct xfrm_dst *)dst)->route; | 92 | dst = ((struct xfrm_dst *)dst)->route; |
100 | dst_hold(dst); | 93 | dst_hold(dst); |
101 | 94 | ||
102 | if (xfrm_lookup(&dst, &fl, (*pskb)->sk, 0) < 0) | 95 | if (xfrm_lookup(&dst, &fl, skb->sk, 0) < 0) |
103 | return -1; | 96 | return -1; |
104 | 97 | ||
105 | dst_release((*pskb)->dst); | 98 | dst_release(skb->dst); |
106 | (*pskb)->dst = dst; | 99 | skb->dst = dst; |
107 | 100 | ||
108 | /* Change in oif may mean change in hh_len. */ | 101 | /* Change in oif may mean change in hh_len. */ |
109 | hh_len = (*pskb)->dst->dev->hard_header_len; | 102 | hh_len = skb->dst->dev->hard_header_len; |
110 | if (skb_headroom(*pskb) < hh_len) { | 103 | if (skb_headroom(skb) < hh_len && |
111 | struct sk_buff *nskb; | 104 | pskb_expand_head(skb, hh_len - skb_headroom(skb), 0, GFP_ATOMIC)) |
112 | 105 | return -1; | |
113 | nskb = skb_realloc_headroom(*pskb, hh_len); | ||
114 | if (!nskb) | ||
115 | return -1; | ||
116 | if ((*pskb)->sk) | ||
117 | skb_set_owner_w(nskb, (*pskb)->sk); | ||
118 | kfree_skb(*pskb); | ||
119 | *pskb = nskb; | ||
120 | } | ||
121 | return 0; | 106 | return 0; |
122 | } | 107 | } |
123 | EXPORT_SYMBOL(ip_xfrm_me_harder); | 108 | EXPORT_SYMBOL(ip_xfrm_me_harder); |
@@ -150,17 +135,17 @@ static void nf_ip_saveroute(const struct sk_buff *skb, struct nf_info *info) | |||
150 | } | 135 | } |
151 | } | 136 | } |
152 | 137 | ||
153 | static int nf_ip_reroute(struct sk_buff **pskb, const struct nf_info *info) | 138 | static int nf_ip_reroute(struct sk_buff *skb, const struct nf_info *info) |
154 | { | 139 | { |
155 | const struct ip_rt_info *rt_info = nf_info_reroute(info); | 140 | const struct ip_rt_info *rt_info = nf_info_reroute(info); |
156 | 141 | ||
157 | if (info->hook == NF_IP_LOCAL_OUT) { | 142 | if (info->hook == NF_IP_LOCAL_OUT) { |
158 | const struct iphdr *iph = ip_hdr(*pskb); | 143 | const struct iphdr *iph = ip_hdr(skb); |
159 | 144 | ||
160 | if (!(iph->tos == rt_info->tos | 145 | if (!(iph->tos == rt_info->tos |
161 | && iph->daddr == rt_info->daddr | 146 | && iph->daddr == rt_info->daddr |
162 | && iph->saddr == rt_info->saddr)) | 147 | && iph->saddr == rt_info->saddr)) |
163 | return ip_route_me_harder(pskb, RTN_UNSPEC); | 148 | return ip_route_me_harder(skb, RTN_UNSPEC); |
164 | } | 149 | } |
165 | return 0; | 150 | return 0; |
166 | } | 151 | } |
diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c index 29114a9ccd1d..2909c92ecd99 100644 --- a/net/ipv4/netfilter/arp_tables.c +++ b/net/ipv4/netfilter/arp_tables.c | |||
@@ -197,7 +197,7 @@ static inline int arp_checkentry(const struct arpt_arp *arp) | |||
197 | return 1; | 197 | return 1; |
198 | } | 198 | } |
199 | 199 | ||
200 | static unsigned int arpt_error(struct sk_buff **pskb, | 200 | static unsigned int arpt_error(struct sk_buff *skb, |
201 | const struct net_device *in, | 201 | const struct net_device *in, |
202 | const struct net_device *out, | 202 | const struct net_device *out, |
203 | unsigned int hooknum, | 203 | unsigned int hooknum, |
@@ -215,7 +215,7 @@ static inline struct arpt_entry *get_entry(void *base, unsigned int offset) | |||
215 | return (struct arpt_entry *)(base + offset); | 215 | return (struct arpt_entry *)(base + offset); |
216 | } | 216 | } |
217 | 217 | ||
218 | unsigned int arpt_do_table(struct sk_buff **pskb, | 218 | unsigned int arpt_do_table(struct sk_buff *skb, |
219 | unsigned int hook, | 219 | unsigned int hook, |
220 | const struct net_device *in, | 220 | const struct net_device *in, |
221 | const struct net_device *out, | 221 | const struct net_device *out, |
@@ -231,9 +231,9 @@ unsigned int arpt_do_table(struct sk_buff **pskb, | |||
231 | struct xt_table_info *private; | 231 | struct xt_table_info *private; |
232 | 232 | ||
233 | /* ARP header, plus 2 device addresses, plus 2 IP addresses. */ | 233 | /* ARP header, plus 2 device addresses, plus 2 IP addresses. */ |
234 | if (!pskb_may_pull((*pskb), (sizeof(struct arphdr) + | 234 | if (!pskb_may_pull(skb, (sizeof(struct arphdr) + |
235 | (2 * (*pskb)->dev->addr_len) + | 235 | (2 * skb->dev->addr_len) + |
236 | (2 * sizeof(u32))))) | 236 | (2 * sizeof(u32))))) |
237 | return NF_DROP; | 237 | return NF_DROP; |
238 | 238 | ||
239 | indev = in ? in->name : nulldevname; | 239 | indev = in ? in->name : nulldevname; |
@@ -245,14 +245,14 @@ unsigned int arpt_do_table(struct sk_buff **pskb, | |||
245 | e = get_entry(table_base, private->hook_entry[hook]); | 245 | e = get_entry(table_base, private->hook_entry[hook]); |
246 | back = get_entry(table_base, private->underflow[hook]); | 246 | back = get_entry(table_base, private->underflow[hook]); |
247 | 247 | ||
248 | arp = arp_hdr(*pskb); | 248 | arp = arp_hdr(skb); |
249 | do { | 249 | do { |
250 | if (arp_packet_match(arp, (*pskb)->dev, indev, outdev, &e->arp)) { | 250 | if (arp_packet_match(arp, skb->dev, indev, outdev, &e->arp)) { |
251 | struct arpt_entry_target *t; | 251 | struct arpt_entry_target *t; |
252 | int hdr_len; | 252 | int hdr_len; |
253 | 253 | ||
254 | hdr_len = sizeof(*arp) + (2 * sizeof(struct in_addr)) + | 254 | hdr_len = sizeof(*arp) + (2 * sizeof(struct in_addr)) + |
255 | (2 * (*pskb)->dev->addr_len); | 255 | (2 * skb->dev->addr_len); |
256 | ADD_COUNTER(e->counters, hdr_len, 1); | 256 | ADD_COUNTER(e->counters, hdr_len, 1); |
257 | 257 | ||
258 | t = arpt_get_target(e); | 258 | t = arpt_get_target(e); |
@@ -290,14 +290,14 @@ unsigned int arpt_do_table(struct sk_buff **pskb, | |||
290 | /* Targets which reenter must return | 290 | /* Targets which reenter must return |
291 | * abs. verdicts | 291 | * abs. verdicts |
292 | */ | 292 | */ |
293 | verdict = t->u.kernel.target->target(pskb, | 293 | verdict = t->u.kernel.target->target(skb, |
294 | in, out, | 294 | in, out, |
295 | hook, | 295 | hook, |
296 | t->u.kernel.target, | 296 | t->u.kernel.target, |
297 | t->data); | 297 | t->data); |
298 | 298 | ||
299 | /* Target might have changed stuff. */ | 299 | /* Target might have changed stuff. */ |
300 | arp = arp_hdr(*pskb); | 300 | arp = arp_hdr(skb); |
301 | 301 | ||
302 | if (verdict == ARPT_CONTINUE) | 302 | if (verdict == ARPT_CONTINUE) |
303 | e = (void *)e + e->next_offset; | 303 | e = (void *)e + e->next_offset; |
diff --git a/net/ipv4/netfilter/arpt_mangle.c b/net/ipv4/netfilter/arpt_mangle.c index c4bdab47597f..45fa4e20094a 100644 --- a/net/ipv4/netfilter/arpt_mangle.c +++ b/net/ipv4/netfilter/arpt_mangle.c | |||
@@ -1,5 +1,6 @@ | |||
1 | /* module that allows mangling of the arp payload */ | 1 | /* module that allows mangling of the arp payload */ |
2 | #include <linux/module.h> | 2 | #include <linux/module.h> |
3 | #include <linux/netfilter.h> | ||
3 | #include <linux/netfilter_arp/arpt_mangle.h> | 4 | #include <linux/netfilter_arp/arpt_mangle.h> |
4 | #include <net/sock.h> | 5 | #include <net/sock.h> |
5 | 6 | ||
@@ -8,7 +9,7 @@ MODULE_AUTHOR("Bart De Schuymer <bdschuym@pandora.be>"); | |||
8 | MODULE_DESCRIPTION("arptables arp payload mangle target"); | 9 | MODULE_DESCRIPTION("arptables arp payload mangle target"); |
9 | 10 | ||
10 | static unsigned int | 11 | static unsigned int |
11 | target(struct sk_buff **pskb, | 12 | target(struct sk_buff *skb, |
12 | const struct net_device *in, const struct net_device *out, | 13 | const struct net_device *in, const struct net_device *out, |
13 | unsigned int hooknum, const struct xt_target *target, | 14 | unsigned int hooknum, const struct xt_target *target, |
14 | const void *targinfo) | 15 | const void *targinfo) |
@@ -18,47 +19,38 @@ target(struct sk_buff **pskb, | |||
18 | unsigned char *arpptr; | 19 | unsigned char *arpptr; |
19 | int pln, hln; | 20 | int pln, hln; |
20 | 21 | ||
21 | if (skb_shared(*pskb) || skb_cloned(*pskb)) { | 22 | if (skb_make_writable(skb, skb->len)) |
22 | struct sk_buff *nskb; | 23 | return NF_DROP; |
23 | 24 | ||
24 | nskb = skb_copy(*pskb, GFP_ATOMIC); | 25 | arp = arp_hdr(skb); |
25 | if (!nskb) | 26 | arpptr = skb_network_header(skb) + sizeof(*arp); |
26 | return NF_DROP; | ||
27 | if ((*pskb)->sk) | ||
28 | skb_set_owner_w(nskb, (*pskb)->sk); | ||
29 | kfree_skb(*pskb); | ||
30 | *pskb = nskb; | ||
31 | } | ||
32 | |||
33 | arp = arp_hdr(*pskb); | ||
34 | arpptr = skb_network_header(*pskb) + sizeof(*arp); | ||
35 | pln = arp->ar_pln; | 27 | pln = arp->ar_pln; |
36 | hln = arp->ar_hln; | 28 | hln = arp->ar_hln; |
37 | /* We assume that pln and hln were checked in the match */ | 29 | /* We assume that pln and hln were checked in the match */ |
38 | if (mangle->flags & ARPT_MANGLE_SDEV) { | 30 | if (mangle->flags & ARPT_MANGLE_SDEV) { |
39 | if (ARPT_DEV_ADDR_LEN_MAX < hln || | 31 | if (ARPT_DEV_ADDR_LEN_MAX < hln || |
40 | (arpptr + hln > skb_tail_pointer(*pskb))) | 32 | (arpptr + hln > skb_tail_pointer(skb))) |
41 | return NF_DROP; | 33 | return NF_DROP; |
42 | memcpy(arpptr, mangle->src_devaddr, hln); | 34 | memcpy(arpptr, mangle->src_devaddr, hln); |
43 | } | 35 | } |
44 | arpptr += hln; | 36 | arpptr += hln; |
45 | if (mangle->flags & ARPT_MANGLE_SIP) { | 37 | if (mangle->flags & ARPT_MANGLE_SIP) { |
46 | if (ARPT_MANGLE_ADDR_LEN_MAX < pln || | 38 | if (ARPT_MANGLE_ADDR_LEN_MAX < pln || |
47 | (arpptr + pln > skb_tail_pointer(*pskb))) | 39 | (arpptr + pln > skb_tail_pointer(skb))) |
48 | return NF_DROP; | 40 | return NF_DROP; |
49 | memcpy(arpptr, &mangle->u_s.src_ip, pln); | 41 | memcpy(arpptr, &mangle->u_s.src_ip, pln); |
50 | } | 42 | } |
51 | arpptr += pln; | 43 | arpptr += pln; |
52 | if (mangle->flags & ARPT_MANGLE_TDEV) { | 44 | if (mangle->flags & ARPT_MANGLE_TDEV) { |
53 | if (ARPT_DEV_ADDR_LEN_MAX < hln || | 45 | if (ARPT_DEV_ADDR_LEN_MAX < hln || |
54 | (arpptr + hln > skb_tail_pointer(*pskb))) | 46 | (arpptr + hln > skb_tail_pointer(skb))) |
55 | return NF_DROP; | 47 | return NF_DROP; |
56 | memcpy(arpptr, mangle->tgt_devaddr, hln); | 48 | memcpy(arpptr, mangle->tgt_devaddr, hln); |
57 | } | 49 | } |
58 | arpptr += hln; | 50 | arpptr += hln; |
59 | if (mangle->flags & ARPT_MANGLE_TIP) { | 51 | if (mangle->flags & ARPT_MANGLE_TIP) { |
60 | if (ARPT_MANGLE_ADDR_LEN_MAX < pln || | 52 | if (ARPT_MANGLE_ADDR_LEN_MAX < pln || |
61 | (arpptr + pln > skb_tail_pointer(*pskb))) | 53 | (arpptr + pln > skb_tail_pointer(skb))) |
62 | return NF_DROP; | 54 | return NF_DROP; |
63 | memcpy(arpptr, &mangle->u_t.tgt_ip, pln); | 55 | memcpy(arpptr, &mangle->u_t.tgt_ip, pln); |
64 | } | 56 | } |
diff --git a/net/ipv4/netfilter/arptable_filter.c b/net/ipv4/netfilter/arptable_filter.c index 75c023062533..302d3da5f696 100644 --- a/net/ipv4/netfilter/arptable_filter.c +++ b/net/ipv4/netfilter/arptable_filter.c | |||
@@ -56,12 +56,12 @@ static struct arpt_table packet_filter = { | |||
56 | 56 | ||
57 | /* The work comes in here from netfilter.c */ | 57 | /* The work comes in here from netfilter.c */ |
58 | static unsigned int arpt_hook(unsigned int hook, | 58 | static unsigned int arpt_hook(unsigned int hook, |
59 | struct sk_buff **pskb, | 59 | struct sk_buff *skb, |
60 | const struct net_device *in, | 60 | const struct net_device *in, |
61 | const struct net_device *out, | 61 | const struct net_device *out, |
62 | int (*okfn)(struct sk_buff *)) | 62 | int (*okfn)(struct sk_buff *)) |
63 | { | 63 | { |
64 | return arpt_do_table(pskb, hook, in, out, &packet_filter); | 64 | return arpt_do_table(skb, hook, in, out, &packet_filter); |
65 | } | 65 | } |
66 | 66 | ||
67 | static struct nf_hook_ops arpt_ops[] = { | 67 | static struct nf_hook_ops arpt_ops[] = { |
diff --git a/net/ipv4/netfilter/ip_queue.c b/net/ipv4/netfilter/ip_queue.c index 23cbfc7c80fd..10a2ce09fd8e 100644 --- a/net/ipv4/netfilter/ip_queue.c +++ b/net/ipv4/netfilter/ip_queue.c | |||
@@ -335,6 +335,7 @@ static int | |||
335 | ipq_mangle_ipv4(ipq_verdict_msg_t *v, struct ipq_queue_entry *e) | 335 | ipq_mangle_ipv4(ipq_verdict_msg_t *v, struct ipq_queue_entry *e) |
336 | { | 336 | { |
337 | int diff; | 337 | int diff; |
338 | int err; | ||
338 | struct iphdr *user_iph = (struct iphdr *)v->payload; | 339 | struct iphdr *user_iph = (struct iphdr *)v->payload; |
339 | 340 | ||
340 | if (v->data_len < sizeof(*user_iph)) | 341 | if (v->data_len < sizeof(*user_iph)) |
@@ -347,25 +348,18 @@ ipq_mangle_ipv4(ipq_verdict_msg_t *v, struct ipq_queue_entry *e) | |||
347 | if (v->data_len > 0xFFFF) | 348 | if (v->data_len > 0xFFFF) |
348 | return -EINVAL; | 349 | return -EINVAL; |
349 | if (diff > skb_tailroom(e->skb)) { | 350 | if (diff > skb_tailroom(e->skb)) { |
350 | struct sk_buff *newskb; | 351 | err = pskb_expand_head(e->skb, 0, |
351 | 352 | diff - skb_tailroom(e->skb), | |
352 | newskb = skb_copy_expand(e->skb, | 353 | GFP_ATOMIC); |
353 | skb_headroom(e->skb), | 354 | if (err) { |
354 | diff, | 355 | printk(KERN_WARNING "ip_queue: error " |
355 | GFP_ATOMIC); | 356 | "in mangle, dropping packet: %d\n", -err); |
356 | if (newskb == NULL) { | 357 | return err; |
357 | printk(KERN_WARNING "ip_queue: OOM " | ||
358 | "in mangle, dropping packet\n"); | ||
359 | return -ENOMEM; | ||
360 | } | 358 | } |
361 | if (e->skb->sk) | ||
362 | skb_set_owner_w(newskb, e->skb->sk); | ||
363 | kfree_skb(e->skb); | ||
364 | e->skb = newskb; | ||
365 | } | 359 | } |
366 | skb_put(e->skb, diff); | 360 | skb_put(e->skb, diff); |
367 | } | 361 | } |
368 | if (!skb_make_writable(&e->skb, v->data_len)) | 362 | if (!skb_make_writable(e->skb, v->data_len)) |
369 | return -ENOMEM; | 363 | return -ENOMEM; |
370 | skb_copy_to_linear_data(e->skb, v->payload, v->data_len); | 364 | skb_copy_to_linear_data(e->skb, v->payload, v->data_len); |
371 | e->skb->ip_summed = CHECKSUM_NONE; | 365 | e->skb->ip_summed = CHECKSUM_NONE; |
diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c index 6486894f450c..4b10b98640ac 100644 --- a/net/ipv4/netfilter/ip_tables.c +++ b/net/ipv4/netfilter/ip_tables.c | |||
@@ -169,7 +169,7 @@ ip_checkentry(const struct ipt_ip *ip) | |||
169 | } | 169 | } |
170 | 170 | ||
171 | static unsigned int | 171 | static unsigned int |
172 | ipt_error(struct sk_buff **pskb, | 172 | ipt_error(struct sk_buff *skb, |
173 | const struct net_device *in, | 173 | const struct net_device *in, |
174 | const struct net_device *out, | 174 | const struct net_device *out, |
175 | unsigned int hooknum, | 175 | unsigned int hooknum, |
@@ -312,7 +312,7 @@ static void trace_packet(struct sk_buff *skb, | |||
312 | 312 | ||
313 | /* Returns one of the generic firewall policies, like NF_ACCEPT. */ | 313 | /* Returns one of the generic firewall policies, like NF_ACCEPT. */ |
314 | unsigned int | 314 | unsigned int |
315 | ipt_do_table(struct sk_buff **pskb, | 315 | ipt_do_table(struct sk_buff *skb, |
316 | unsigned int hook, | 316 | unsigned int hook, |
317 | const struct net_device *in, | 317 | const struct net_device *in, |
318 | const struct net_device *out, | 318 | const struct net_device *out, |
@@ -331,8 +331,8 @@ ipt_do_table(struct sk_buff **pskb, | |||
331 | struct xt_table_info *private; | 331 | struct xt_table_info *private; |
332 | 332 | ||
333 | /* Initialization */ | 333 | /* Initialization */ |
334 | ip = ip_hdr(*pskb); | 334 | ip = ip_hdr(skb); |
335 | datalen = (*pskb)->len - ip->ihl * 4; | 335 | datalen = skb->len - ip->ihl * 4; |
336 | indev = in ? in->name : nulldevname; | 336 | indev = in ? in->name : nulldevname; |
337 | outdev = out ? out->name : nulldevname; | 337 | outdev = out ? out->name : nulldevname; |
338 | /* We handle fragments by dealing with the first fragment as | 338 | /* We handle fragments by dealing with the first fragment as |
@@ -359,7 +359,7 @@ ipt_do_table(struct sk_buff **pskb, | |||
359 | struct ipt_entry_target *t; | 359 | struct ipt_entry_target *t; |
360 | 360 | ||
361 | if (IPT_MATCH_ITERATE(e, do_match, | 361 | if (IPT_MATCH_ITERATE(e, do_match, |
362 | *pskb, in, out, | 362 | skb, in, out, |
363 | offset, &hotdrop) != 0) | 363 | offset, &hotdrop) != 0) |
364 | goto no_match; | 364 | goto no_match; |
365 | 365 | ||
@@ -371,8 +371,8 @@ ipt_do_table(struct sk_buff **pskb, | |||
371 | #if defined(CONFIG_NETFILTER_XT_TARGET_TRACE) || \ | 371 | #if defined(CONFIG_NETFILTER_XT_TARGET_TRACE) || \ |
372 | defined(CONFIG_NETFILTER_XT_TARGET_TRACE_MODULE) | 372 | defined(CONFIG_NETFILTER_XT_TARGET_TRACE_MODULE) |
373 | /* The packet is traced: log it */ | 373 | /* The packet is traced: log it */ |
374 | if (unlikely((*pskb)->nf_trace)) | 374 | if (unlikely(skb->nf_trace)) |
375 | trace_packet(*pskb, hook, in, out, | 375 | trace_packet(skb, hook, in, out, |
376 | table->name, private, e); | 376 | table->name, private, e); |
377 | #endif | 377 | #endif |
378 | /* Standard target? */ | 378 | /* Standard target? */ |
@@ -410,7 +410,7 @@ ipt_do_table(struct sk_buff **pskb, | |||
410 | ((struct ipt_entry *)table_base)->comefrom | 410 | ((struct ipt_entry *)table_base)->comefrom |
411 | = 0xeeeeeeec; | 411 | = 0xeeeeeeec; |
412 | #endif | 412 | #endif |
413 | verdict = t->u.kernel.target->target(pskb, | 413 | verdict = t->u.kernel.target->target(skb, |
414 | in, out, | 414 | in, out, |
415 | hook, | 415 | hook, |
416 | t->u.kernel.target, | 416 | t->u.kernel.target, |
@@ -428,8 +428,8 @@ ipt_do_table(struct sk_buff **pskb, | |||
428 | = 0x57acc001; | 428 | = 0x57acc001; |
429 | #endif | 429 | #endif |
430 | /* Target might have changed stuff. */ | 430 | /* Target might have changed stuff. */ |
431 | ip = ip_hdr(*pskb); | 431 | ip = ip_hdr(skb); |
432 | datalen = (*pskb)->len - ip->ihl * 4; | 432 | datalen = skb->len - ip->ihl * 4; |
433 | 433 | ||
434 | if (verdict == IPT_CONTINUE) | 434 | if (verdict == IPT_CONTINUE) |
435 | e = (void *)e + e->next_offset; | 435 | e = (void *)e + e->next_offset; |
diff --git a/net/ipv4/netfilter/ipt_CLUSTERIP.c b/net/ipv4/netfilter/ipt_CLUSTERIP.c index 27f14e1ebd8b..2f544dac72df 100644 --- a/net/ipv4/netfilter/ipt_CLUSTERIP.c +++ b/net/ipv4/netfilter/ipt_CLUSTERIP.c | |||
@@ -289,7 +289,7 @@ clusterip_responsible(const struct clusterip_config *config, u_int32_t hash) | |||
289 | ***********************************************************************/ | 289 | ***********************************************************************/ |
290 | 290 | ||
291 | static unsigned int | 291 | static unsigned int |
292 | target(struct sk_buff **pskb, | 292 | target(struct sk_buff *skb, |
293 | const struct net_device *in, | 293 | const struct net_device *in, |
294 | const struct net_device *out, | 294 | const struct net_device *out, |
295 | unsigned int hooknum, | 295 | unsigned int hooknum, |
@@ -305,7 +305,7 @@ target(struct sk_buff **pskb, | |||
305 | * is only decremented by destroy() - and ip_tables guarantees | 305 | * is only decremented by destroy() - and ip_tables guarantees |
306 | * that the ->target() function isn't called after ->destroy() */ | 306 | * that the ->target() function isn't called after ->destroy() */ |
307 | 307 | ||
308 | ct = nf_ct_get(*pskb, &ctinfo); | 308 | ct = nf_ct_get(skb, &ctinfo); |
309 | if (ct == NULL) { | 309 | if (ct == NULL) { |
310 | printk(KERN_ERR "CLUSTERIP: no conntrack!\n"); | 310 | printk(KERN_ERR "CLUSTERIP: no conntrack!\n"); |
311 | /* FIXME: need to drop invalid ones, since replies | 311 | /* FIXME: need to drop invalid ones, since replies |
@@ -316,7 +316,7 @@ target(struct sk_buff **pskb, | |||
316 | 316 | ||
317 | /* special case: ICMP error handling. conntrack distinguishes between | 317 | /* special case: ICMP error handling. conntrack distinguishes between |
318 | * error messages (RELATED) and information requests (see below) */ | 318 | * error messages (RELATED) and information requests (see below) */ |
319 | if (ip_hdr(*pskb)->protocol == IPPROTO_ICMP | 319 | if (ip_hdr(skb)->protocol == IPPROTO_ICMP |
320 | && (ctinfo == IP_CT_RELATED | 320 | && (ctinfo == IP_CT_RELATED |
321 | || ctinfo == IP_CT_RELATED+IP_CT_IS_REPLY)) | 321 | || ctinfo == IP_CT_RELATED+IP_CT_IS_REPLY)) |
322 | return XT_CONTINUE; | 322 | return XT_CONTINUE; |
@@ -325,7 +325,7 @@ target(struct sk_buff **pskb, | |||
325 | * TIMESTAMP, INFO_REQUEST or ADDRESS type icmp packets from here | 325 | * TIMESTAMP, INFO_REQUEST or ADDRESS type icmp packets from here |
326 | * on, which all have an ID field [relevant for hashing]. */ | 326 | * on, which all have an ID field [relevant for hashing]. */ |
327 | 327 | ||
328 | hash = clusterip_hashfn(*pskb, cipinfo->config); | 328 | hash = clusterip_hashfn(skb, cipinfo->config); |
329 | 329 | ||
330 | switch (ctinfo) { | 330 | switch (ctinfo) { |
331 | case IP_CT_NEW: | 331 | case IP_CT_NEW: |
@@ -355,7 +355,7 @@ target(struct sk_buff **pskb, | |||
355 | 355 | ||
356 | /* despite being received via linklayer multicast, this is | 356 | /* despite being received via linklayer multicast, this is |
357 | * actually a unicast IP packet. TCP doesn't like PACKET_MULTICAST */ | 357 | * actually a unicast IP packet. TCP doesn't like PACKET_MULTICAST */ |
358 | (*pskb)->pkt_type = PACKET_HOST; | 358 | skb->pkt_type = PACKET_HOST; |
359 | 359 | ||
360 | return XT_CONTINUE; | 360 | return XT_CONTINUE; |
361 | } | 361 | } |
@@ -505,12 +505,12 @@ static void arp_print(struct arp_payload *payload) | |||
505 | 505 | ||
506 | static unsigned int | 506 | static unsigned int |
507 | arp_mangle(unsigned int hook, | 507 | arp_mangle(unsigned int hook, |
508 | struct sk_buff **pskb, | 508 | struct sk_buff *skb, |
509 | const struct net_device *in, | 509 | const struct net_device *in, |
510 | const struct net_device *out, | 510 | const struct net_device *out, |
511 | int (*okfn)(struct sk_buff *)) | 511 | int (*okfn)(struct sk_buff *)) |
512 | { | 512 | { |
513 | struct arphdr *arp = arp_hdr(*pskb); | 513 | struct arphdr *arp = arp_hdr(skb); |
514 | struct arp_payload *payload; | 514 | struct arp_payload *payload; |
515 | struct clusterip_config *c; | 515 | struct clusterip_config *c; |
516 | 516 | ||
diff --git a/net/ipv4/netfilter/ipt_ECN.c b/net/ipv4/netfilter/ipt_ECN.c index f1253bd3837f..add110060a22 100644 --- a/net/ipv4/netfilter/ipt_ECN.c +++ b/net/ipv4/netfilter/ipt_ECN.c | |||
@@ -26,15 +26,15 @@ MODULE_DESCRIPTION("iptables ECN modification module"); | |||
26 | /* set ECT codepoint from IP header. | 26 | /* set ECT codepoint from IP header. |
27 | * return false if there was an error. */ | 27 | * return false if there was an error. */ |
28 | static inline bool | 28 | static inline bool |
29 | set_ect_ip(struct sk_buff **pskb, const struct ipt_ECN_info *einfo) | 29 | set_ect_ip(struct sk_buff *skb, const struct ipt_ECN_info *einfo) |
30 | { | 30 | { |
31 | struct iphdr *iph = ip_hdr(*pskb); | 31 | struct iphdr *iph = ip_hdr(skb); |
32 | 32 | ||
33 | if ((iph->tos & IPT_ECN_IP_MASK) != (einfo->ip_ect & IPT_ECN_IP_MASK)) { | 33 | if ((iph->tos & IPT_ECN_IP_MASK) != (einfo->ip_ect & IPT_ECN_IP_MASK)) { |
34 | __u8 oldtos; | 34 | __u8 oldtos; |
35 | if (!skb_make_writable(pskb, sizeof(struct iphdr))) | 35 | if (!skb_make_writable(skb, sizeof(struct iphdr))) |
36 | return false; | 36 | return false; |
37 | iph = ip_hdr(*pskb); | 37 | iph = ip_hdr(skb); |
38 | oldtos = iph->tos; | 38 | oldtos = iph->tos; |
39 | iph->tos &= ~IPT_ECN_IP_MASK; | 39 | iph->tos &= ~IPT_ECN_IP_MASK; |
40 | iph->tos |= (einfo->ip_ect & IPT_ECN_IP_MASK); | 40 | iph->tos |= (einfo->ip_ect & IPT_ECN_IP_MASK); |
@@ -45,14 +45,13 @@ set_ect_ip(struct sk_buff **pskb, const struct ipt_ECN_info *einfo) | |||
45 | 45 | ||
46 | /* Return false if there was an error. */ | 46 | /* Return false if there was an error. */ |
47 | static inline bool | 47 | static inline bool |
48 | set_ect_tcp(struct sk_buff **pskb, const struct ipt_ECN_info *einfo) | 48 | set_ect_tcp(struct sk_buff *skb, const struct ipt_ECN_info *einfo) |
49 | { | 49 | { |
50 | struct tcphdr _tcph, *tcph; | 50 | struct tcphdr _tcph, *tcph; |
51 | __be16 oldval; | 51 | __be16 oldval; |
52 | 52 | ||
53 | /* Not enought header? */ | 53 | /* Not enought header? */ |
54 | tcph = skb_header_pointer(*pskb, ip_hdrlen(*pskb), | 54 | tcph = skb_header_pointer(skb, ip_hdrlen(skb), sizeof(_tcph), &_tcph); |
55 | sizeof(_tcph), &_tcph); | ||
56 | if (!tcph) | 55 | if (!tcph) |
57 | return false; | 56 | return false; |
58 | 57 | ||
@@ -62,9 +61,9 @@ set_ect_tcp(struct sk_buff **pskb, const struct ipt_ECN_info *einfo) | |||
62 | tcph->cwr == einfo->proto.tcp.cwr)) | 61 | tcph->cwr == einfo->proto.tcp.cwr)) |
63 | return true; | 62 | return true; |
64 | 63 | ||
65 | if (!skb_make_writable(pskb, ip_hdrlen(*pskb) + sizeof(*tcph))) | 64 | if (!skb_make_writable(skb, ip_hdrlen(skb) + sizeof(*tcph))) |
66 | return false; | 65 | return false; |
67 | tcph = (void *)ip_hdr(*pskb) + ip_hdrlen(*pskb); | 66 | tcph = (void *)ip_hdr(skb) + ip_hdrlen(skb); |
68 | 67 | ||
69 | oldval = ((__be16 *)tcph)[6]; | 68 | oldval = ((__be16 *)tcph)[6]; |
70 | if (einfo->operation & IPT_ECN_OP_SET_ECE) | 69 | if (einfo->operation & IPT_ECN_OP_SET_ECE) |
@@ -72,13 +71,13 @@ set_ect_tcp(struct sk_buff **pskb, const struct ipt_ECN_info *einfo) | |||
72 | if (einfo->operation & IPT_ECN_OP_SET_CWR) | 71 | if (einfo->operation & IPT_ECN_OP_SET_CWR) |
73 | tcph->cwr = einfo->proto.tcp.cwr; | 72 | tcph->cwr = einfo->proto.tcp.cwr; |
74 | 73 | ||
75 | nf_proto_csum_replace2(&tcph->check, *pskb, | 74 | nf_proto_csum_replace2(&tcph->check, skb, |
76 | oldval, ((__be16 *)tcph)[6], 0); | 75 | oldval, ((__be16 *)tcph)[6], 0); |
77 | return true; | 76 | return true; |
78 | } | 77 | } |
79 | 78 | ||
80 | static unsigned int | 79 | static unsigned int |
81 | target(struct sk_buff **pskb, | 80 | target(struct sk_buff *skb, |
82 | const struct net_device *in, | 81 | const struct net_device *in, |
83 | const struct net_device *out, | 82 | const struct net_device *out, |
84 | unsigned int hooknum, | 83 | unsigned int hooknum, |
@@ -88,12 +87,12 @@ target(struct sk_buff **pskb, | |||
88 | const struct ipt_ECN_info *einfo = targinfo; | 87 | const struct ipt_ECN_info *einfo = targinfo; |
89 | 88 | ||
90 | if (einfo->operation & IPT_ECN_OP_SET_IP) | 89 | if (einfo->operation & IPT_ECN_OP_SET_IP) |
91 | if (!set_ect_ip(pskb, einfo)) | 90 | if (!set_ect_ip(skb, einfo)) |
92 | return NF_DROP; | 91 | return NF_DROP; |
93 | 92 | ||
94 | if (einfo->operation & (IPT_ECN_OP_SET_ECE | IPT_ECN_OP_SET_CWR) | 93 | if (einfo->operation & (IPT_ECN_OP_SET_ECE | IPT_ECN_OP_SET_CWR) |
95 | && ip_hdr(*pskb)->protocol == IPPROTO_TCP) | 94 | && ip_hdr(skb)->protocol == IPPROTO_TCP) |
96 | if (!set_ect_tcp(pskb, einfo)) | 95 | if (!set_ect_tcp(skb, einfo)) |
97 | return NF_DROP; | 96 | return NF_DROP; |
98 | 97 | ||
99 | return XT_CONTINUE; | 98 | return XT_CONTINUE; |
diff --git a/net/ipv4/netfilter/ipt_LOG.c b/net/ipv4/netfilter/ipt_LOG.c index 127a5e89bf14..4b5e8216a4e7 100644 --- a/net/ipv4/netfilter/ipt_LOG.c +++ b/net/ipv4/netfilter/ipt_LOG.c | |||
@@ -418,7 +418,7 @@ ipt_log_packet(unsigned int pf, | |||
418 | } | 418 | } |
419 | 419 | ||
420 | static unsigned int | 420 | static unsigned int |
421 | ipt_log_target(struct sk_buff **pskb, | 421 | ipt_log_target(struct sk_buff *skb, |
422 | const struct net_device *in, | 422 | const struct net_device *in, |
423 | const struct net_device *out, | 423 | const struct net_device *out, |
424 | unsigned int hooknum, | 424 | unsigned int hooknum, |
@@ -432,7 +432,7 @@ ipt_log_target(struct sk_buff **pskb, | |||
432 | li.u.log.level = loginfo->level; | 432 | li.u.log.level = loginfo->level; |
433 | li.u.log.logflags = loginfo->logflags; | 433 | li.u.log.logflags = loginfo->logflags; |
434 | 434 | ||
435 | ipt_log_packet(PF_INET, hooknum, *pskb, in, out, &li, | 435 | ipt_log_packet(PF_INET, hooknum, skb, in, out, &li, |
436 | loginfo->prefix); | 436 | loginfo->prefix); |
437 | return XT_CONTINUE; | 437 | return XT_CONTINUE; |
438 | } | 438 | } |
diff --git a/net/ipv4/netfilter/ipt_MASQUERADE.c b/net/ipv4/netfilter/ipt_MASQUERADE.c index 3e0b562b2db7..44b516e7cb79 100644 --- a/net/ipv4/netfilter/ipt_MASQUERADE.c +++ b/net/ipv4/netfilter/ipt_MASQUERADE.c | |||
@@ -52,7 +52,7 @@ masquerade_check(const char *tablename, | |||
52 | } | 52 | } |
53 | 53 | ||
54 | static unsigned int | 54 | static unsigned int |
55 | masquerade_target(struct sk_buff **pskb, | 55 | masquerade_target(struct sk_buff *skb, |
56 | const struct net_device *in, | 56 | const struct net_device *in, |
57 | const struct net_device *out, | 57 | const struct net_device *out, |
58 | unsigned int hooknum, | 58 | unsigned int hooknum, |
@@ -69,7 +69,7 @@ masquerade_target(struct sk_buff **pskb, | |||
69 | 69 | ||
70 | NF_CT_ASSERT(hooknum == NF_IP_POST_ROUTING); | 70 | NF_CT_ASSERT(hooknum == NF_IP_POST_ROUTING); |
71 | 71 | ||
72 | ct = nf_ct_get(*pskb, &ctinfo); | 72 | ct = nf_ct_get(skb, &ctinfo); |
73 | nat = nfct_nat(ct); | 73 | nat = nfct_nat(ct); |
74 | 74 | ||
75 | NF_CT_ASSERT(ct && (ctinfo == IP_CT_NEW || ctinfo == IP_CT_RELATED | 75 | NF_CT_ASSERT(ct && (ctinfo == IP_CT_NEW || ctinfo == IP_CT_RELATED |
@@ -82,7 +82,7 @@ masquerade_target(struct sk_buff **pskb, | |||
82 | return NF_ACCEPT; | 82 | return NF_ACCEPT; |
83 | 83 | ||
84 | mr = targinfo; | 84 | mr = targinfo; |
85 | rt = (struct rtable *)(*pskb)->dst; | 85 | rt = (struct rtable *)skb->dst; |
86 | newsrc = inet_select_addr(out, rt->rt_gateway, RT_SCOPE_UNIVERSE); | 86 | newsrc = inet_select_addr(out, rt->rt_gateway, RT_SCOPE_UNIVERSE); |
87 | if (!newsrc) { | 87 | if (!newsrc) { |
88 | printk("MASQUERADE: %s ate my IP address\n", out->name); | 88 | printk("MASQUERADE: %s ate my IP address\n", out->name); |
diff --git a/net/ipv4/netfilter/ipt_NETMAP.c b/net/ipv4/netfilter/ipt_NETMAP.c index 41a011d5a065..f8699291e33d 100644 --- a/net/ipv4/netfilter/ipt_NETMAP.c +++ b/net/ipv4/netfilter/ipt_NETMAP.c | |||
@@ -43,7 +43,7 @@ check(const char *tablename, | |||
43 | } | 43 | } |
44 | 44 | ||
45 | static unsigned int | 45 | static unsigned int |
46 | target(struct sk_buff **pskb, | 46 | target(struct sk_buff *skb, |
47 | const struct net_device *in, | 47 | const struct net_device *in, |
48 | const struct net_device *out, | 48 | const struct net_device *out, |
49 | unsigned int hooknum, | 49 | unsigned int hooknum, |
@@ -59,14 +59,14 @@ target(struct sk_buff **pskb, | |||
59 | NF_CT_ASSERT(hooknum == NF_IP_PRE_ROUTING | 59 | NF_CT_ASSERT(hooknum == NF_IP_PRE_ROUTING |
60 | || hooknum == NF_IP_POST_ROUTING | 60 | || hooknum == NF_IP_POST_ROUTING |
61 | || hooknum == NF_IP_LOCAL_OUT); | 61 | || hooknum == NF_IP_LOCAL_OUT); |
62 | ct = nf_ct_get(*pskb, &ctinfo); | 62 | ct = nf_ct_get(skb, &ctinfo); |
63 | 63 | ||
64 | netmask = ~(mr->range[0].min_ip ^ mr->range[0].max_ip); | 64 | netmask = ~(mr->range[0].min_ip ^ mr->range[0].max_ip); |
65 | 65 | ||
66 | if (hooknum == NF_IP_PRE_ROUTING || hooknum == NF_IP_LOCAL_OUT) | 66 | if (hooknum == NF_IP_PRE_ROUTING || hooknum == NF_IP_LOCAL_OUT) |
67 | new_ip = ip_hdr(*pskb)->daddr & ~netmask; | 67 | new_ip = ip_hdr(skb)->daddr & ~netmask; |
68 | else | 68 | else |
69 | new_ip = ip_hdr(*pskb)->saddr & ~netmask; | 69 | new_ip = ip_hdr(skb)->saddr & ~netmask; |
70 | new_ip |= mr->range[0].min_ip & netmask; | 70 | new_ip |= mr->range[0].min_ip & netmask; |
71 | 71 | ||
72 | newrange = ((struct nf_nat_range) | 72 | newrange = ((struct nf_nat_range) |
diff --git a/net/ipv4/netfilter/ipt_REDIRECT.c b/net/ipv4/netfilter/ipt_REDIRECT.c index 6ac7a2373316..f7cf7d61a2d4 100644 --- a/net/ipv4/netfilter/ipt_REDIRECT.c +++ b/net/ipv4/netfilter/ipt_REDIRECT.c | |||
@@ -47,7 +47,7 @@ redirect_check(const char *tablename, | |||
47 | } | 47 | } |
48 | 48 | ||
49 | static unsigned int | 49 | static unsigned int |
50 | redirect_target(struct sk_buff **pskb, | 50 | redirect_target(struct sk_buff *skb, |
51 | const struct net_device *in, | 51 | const struct net_device *in, |
52 | const struct net_device *out, | 52 | const struct net_device *out, |
53 | unsigned int hooknum, | 53 | unsigned int hooknum, |
@@ -63,7 +63,7 @@ redirect_target(struct sk_buff **pskb, | |||
63 | NF_CT_ASSERT(hooknum == NF_IP_PRE_ROUTING | 63 | NF_CT_ASSERT(hooknum == NF_IP_PRE_ROUTING |
64 | || hooknum == NF_IP_LOCAL_OUT); | 64 | || hooknum == NF_IP_LOCAL_OUT); |
65 | 65 | ||
66 | ct = nf_ct_get(*pskb, &ctinfo); | 66 | ct = nf_ct_get(skb, &ctinfo); |
67 | NF_CT_ASSERT(ct && (ctinfo == IP_CT_NEW || ctinfo == IP_CT_RELATED)); | 67 | NF_CT_ASSERT(ct && (ctinfo == IP_CT_NEW || ctinfo == IP_CT_RELATED)); |
68 | 68 | ||
69 | /* Local packets: make them go to loopback */ | 69 | /* Local packets: make them go to loopback */ |
@@ -76,7 +76,7 @@ redirect_target(struct sk_buff **pskb, | |||
76 | newdst = 0; | 76 | newdst = 0; |
77 | 77 | ||
78 | rcu_read_lock(); | 78 | rcu_read_lock(); |
79 | indev = __in_dev_get_rcu((*pskb)->dev); | 79 | indev = __in_dev_get_rcu(skb->dev); |
80 | if (indev && (ifa = indev->ifa_list)) | 80 | if (indev && (ifa = indev->ifa_list)) |
81 | newdst = ifa->ifa_local; | 81 | newdst = ifa->ifa_local; |
82 | rcu_read_unlock(); | 82 | rcu_read_unlock(); |
diff --git a/net/ipv4/netfilter/ipt_REJECT.c b/net/ipv4/netfilter/ipt_REJECT.c index cb038c8fbc9d..dcf4d21d5116 100644 --- a/net/ipv4/netfilter/ipt_REJECT.c +++ b/net/ipv4/netfilter/ipt_REJECT.c | |||
@@ -131,7 +131,7 @@ static void send_reset(struct sk_buff *oldskb, int hook) | |||
131 | ) | 131 | ) |
132 | addr_type = RTN_LOCAL; | 132 | addr_type = RTN_LOCAL; |
133 | 133 | ||
134 | if (ip_route_me_harder(&nskb, addr_type)) | 134 | if (ip_route_me_harder(nskb, addr_type)) |
135 | goto free_nskb; | 135 | goto free_nskb; |
136 | 136 | ||
137 | nskb->ip_summed = CHECKSUM_NONE; | 137 | nskb->ip_summed = CHECKSUM_NONE; |
@@ -162,7 +162,7 @@ static inline void send_unreach(struct sk_buff *skb_in, int code) | |||
162 | icmp_send(skb_in, ICMP_DEST_UNREACH, code, 0); | 162 | icmp_send(skb_in, ICMP_DEST_UNREACH, code, 0); |
163 | } | 163 | } |
164 | 164 | ||
165 | static unsigned int reject(struct sk_buff **pskb, | 165 | static unsigned int reject(struct sk_buff *skb, |
166 | const struct net_device *in, | 166 | const struct net_device *in, |
167 | const struct net_device *out, | 167 | const struct net_device *out, |
168 | unsigned int hooknum, | 168 | unsigned int hooknum, |
@@ -173,7 +173,7 @@ static unsigned int reject(struct sk_buff **pskb, | |||
173 | 173 | ||
174 | /* Our naive response construction doesn't deal with IP | 174 | /* Our naive response construction doesn't deal with IP |
175 | options, and probably shouldn't try. */ | 175 | options, and probably shouldn't try. */ |
176 | if (ip_hdrlen(*pskb) != sizeof(struct iphdr)) | 176 | if (ip_hdrlen(skb) != sizeof(struct iphdr)) |
177 | return NF_DROP; | 177 | return NF_DROP; |
178 | 178 | ||
179 | /* WARNING: This code causes reentry within iptables. | 179 | /* WARNING: This code causes reentry within iptables. |
@@ -181,28 +181,28 @@ static unsigned int reject(struct sk_buff **pskb, | |||
181 | must return an absolute verdict. --RR */ | 181 | must return an absolute verdict. --RR */ |
182 | switch (reject->with) { | 182 | switch (reject->with) { |
183 | case IPT_ICMP_NET_UNREACHABLE: | 183 | case IPT_ICMP_NET_UNREACHABLE: |
184 | send_unreach(*pskb, ICMP_NET_UNREACH); | 184 | send_unreach(skb, ICMP_NET_UNREACH); |
185 | break; | 185 | break; |
186 | case IPT_ICMP_HOST_UNREACHABLE: | 186 | case IPT_ICMP_HOST_UNREACHABLE: |
187 | send_unreach(*pskb, ICMP_HOST_UNREACH); | 187 | send_unreach(skb, ICMP_HOST_UNREACH); |
188 | break; | 188 | break; |
189 | case IPT_ICMP_PROT_UNREACHABLE: | 189 | case IPT_ICMP_PROT_UNREACHABLE: |
190 | send_unreach(*pskb, ICMP_PROT_UNREACH); | 190 | send_unreach(skb, ICMP_PROT_UNREACH); |
191 | break; | 191 | break; |
192 | case IPT_ICMP_PORT_UNREACHABLE: | 192 | case IPT_ICMP_PORT_UNREACHABLE: |
193 | send_unreach(*pskb, ICMP_PORT_UNREACH); | 193 | send_unreach(skb, ICMP_PORT_UNREACH); |
194 | break; | 194 | break; |
195 | case IPT_ICMP_NET_PROHIBITED: | 195 | case IPT_ICMP_NET_PROHIBITED: |
196 | send_unreach(*pskb, ICMP_NET_ANO); | 196 | send_unreach(skb, ICMP_NET_ANO); |
197 | break; | 197 | break; |
198 | case IPT_ICMP_HOST_PROHIBITED: | 198 | case IPT_ICMP_HOST_PROHIBITED: |
199 | send_unreach(*pskb, ICMP_HOST_ANO); | 199 | send_unreach(skb, ICMP_HOST_ANO); |
200 | break; | 200 | break; |
201 | case IPT_ICMP_ADMIN_PROHIBITED: | 201 | case IPT_ICMP_ADMIN_PROHIBITED: |
202 | send_unreach(*pskb, ICMP_PKT_FILTERED); | 202 | send_unreach(skb, ICMP_PKT_FILTERED); |
203 | break; | 203 | break; |
204 | case IPT_TCP_RESET: | 204 | case IPT_TCP_RESET: |
205 | send_reset(*pskb, hooknum); | 205 | send_reset(skb, hooknum); |
206 | case IPT_ICMP_ECHOREPLY: | 206 | case IPT_ICMP_ECHOREPLY: |
207 | /* Doesn't happen. */ | 207 | /* Doesn't happen. */ |
208 | break; | 208 | break; |
diff --git a/net/ipv4/netfilter/ipt_SAME.c b/net/ipv4/netfilter/ipt_SAME.c index 97641f1a97f6..8988571436b8 100644 --- a/net/ipv4/netfilter/ipt_SAME.c +++ b/net/ipv4/netfilter/ipt_SAME.c | |||
@@ -104,7 +104,7 @@ same_destroy(const struct xt_target *target, void *targinfo) | |||
104 | } | 104 | } |
105 | 105 | ||
106 | static unsigned int | 106 | static unsigned int |
107 | same_target(struct sk_buff **pskb, | 107 | same_target(struct sk_buff *skb, |
108 | const struct net_device *in, | 108 | const struct net_device *in, |
109 | const struct net_device *out, | 109 | const struct net_device *out, |
110 | unsigned int hooknum, | 110 | unsigned int hooknum, |
@@ -121,7 +121,7 @@ same_target(struct sk_buff **pskb, | |||
121 | 121 | ||
122 | NF_CT_ASSERT(hooknum == NF_IP_PRE_ROUTING || | 122 | NF_CT_ASSERT(hooknum == NF_IP_PRE_ROUTING || |
123 | hooknum == NF_IP_POST_ROUTING); | 123 | hooknum == NF_IP_POST_ROUTING); |
124 | ct = nf_ct_get(*pskb, &ctinfo); | 124 | ct = nf_ct_get(skb, &ctinfo); |
125 | 125 | ||
126 | t = &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple; | 126 | t = &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple; |
127 | 127 | ||
diff --git a/net/ipv4/netfilter/ipt_TOS.c b/net/ipv4/netfilter/ipt_TOS.c index 25f5d0b39065..d4573baa7f27 100644 --- a/net/ipv4/netfilter/ipt_TOS.c +++ b/net/ipv4/netfilter/ipt_TOS.c | |||
@@ -21,7 +21,7 @@ MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>"); | |||
21 | MODULE_DESCRIPTION("iptables TOS mangling module"); | 21 | MODULE_DESCRIPTION("iptables TOS mangling module"); |
22 | 22 | ||
23 | static unsigned int | 23 | static unsigned int |
24 | target(struct sk_buff **pskb, | 24 | target(struct sk_buff *skb, |
25 | const struct net_device *in, | 25 | const struct net_device *in, |
26 | const struct net_device *out, | 26 | const struct net_device *out, |
27 | unsigned int hooknum, | 27 | unsigned int hooknum, |
@@ -29,13 +29,13 @@ target(struct sk_buff **pskb, | |||
29 | const void *targinfo) | 29 | const void *targinfo) |
30 | { | 30 | { |
31 | const struct ipt_tos_target_info *tosinfo = targinfo; | 31 | const struct ipt_tos_target_info *tosinfo = targinfo; |
32 | struct iphdr *iph = ip_hdr(*pskb); | 32 | struct iphdr *iph = ip_hdr(skb); |
33 | 33 | ||
34 | if ((iph->tos & IPTOS_TOS_MASK) != tosinfo->tos) { | 34 | if ((iph->tos & IPTOS_TOS_MASK) != tosinfo->tos) { |
35 | __u8 oldtos; | 35 | __u8 oldtos; |
36 | if (!skb_make_writable(pskb, sizeof(struct iphdr))) | 36 | if (!skb_make_writable(skb, sizeof(struct iphdr))) |
37 | return NF_DROP; | 37 | return NF_DROP; |
38 | iph = ip_hdr(*pskb); | 38 | iph = ip_hdr(skb); |
39 | oldtos = iph->tos; | 39 | oldtos = iph->tos; |
40 | iph->tos = (iph->tos & IPTOS_PREC_MASK) | tosinfo->tos; | 40 | iph->tos = (iph->tos & IPTOS_PREC_MASK) | tosinfo->tos; |
41 | nf_csum_replace2(&iph->check, htons(oldtos), htons(iph->tos)); | 41 | nf_csum_replace2(&iph->check, htons(oldtos), htons(iph->tos)); |
diff --git a/net/ipv4/netfilter/ipt_TTL.c b/net/ipv4/netfilter/ipt_TTL.c index 2b54e7b0cfe8..c620a0527666 100644 --- a/net/ipv4/netfilter/ipt_TTL.c +++ b/net/ipv4/netfilter/ipt_TTL.c | |||
@@ -20,7 +20,7 @@ MODULE_DESCRIPTION("IP tables TTL modification module"); | |||
20 | MODULE_LICENSE("GPL"); | 20 | MODULE_LICENSE("GPL"); |
21 | 21 | ||
22 | static unsigned int | 22 | static unsigned int |
23 | ipt_ttl_target(struct sk_buff **pskb, | 23 | ipt_ttl_target(struct sk_buff *skb, |
24 | const struct net_device *in, const struct net_device *out, | 24 | const struct net_device *in, const struct net_device *out, |
25 | unsigned int hooknum, const struct xt_target *target, | 25 | unsigned int hooknum, const struct xt_target *target, |
26 | const void *targinfo) | 26 | const void *targinfo) |
@@ -29,10 +29,10 @@ ipt_ttl_target(struct sk_buff **pskb, | |||
29 | const struct ipt_TTL_info *info = targinfo; | 29 | const struct ipt_TTL_info *info = targinfo; |
30 | int new_ttl; | 30 | int new_ttl; |
31 | 31 | ||
32 | if (!skb_make_writable(pskb, (*pskb)->len)) | 32 | if (!skb_make_writable(skb, skb->len)) |
33 | return NF_DROP; | 33 | return NF_DROP; |
34 | 34 | ||
35 | iph = ip_hdr(*pskb); | 35 | iph = ip_hdr(skb); |
36 | 36 | ||
37 | switch (info->mode) { | 37 | switch (info->mode) { |
38 | case IPT_TTL_SET: | 38 | case IPT_TTL_SET: |
diff --git a/net/ipv4/netfilter/ipt_ULOG.c b/net/ipv4/netfilter/ipt_ULOG.c index c636d6d63574..212b830765a4 100644 --- a/net/ipv4/netfilter/ipt_ULOG.c +++ b/net/ipv4/netfilter/ipt_ULOG.c | |||
@@ -279,7 +279,7 @@ alloc_failure: | |||
279 | spin_unlock_bh(&ulog_lock); | 279 | spin_unlock_bh(&ulog_lock); |
280 | } | 280 | } |
281 | 281 | ||
282 | static unsigned int ipt_ulog_target(struct sk_buff **pskb, | 282 | static unsigned int ipt_ulog_target(struct sk_buff *skb, |
283 | const struct net_device *in, | 283 | const struct net_device *in, |
284 | const struct net_device *out, | 284 | const struct net_device *out, |
285 | unsigned int hooknum, | 285 | unsigned int hooknum, |
@@ -288,7 +288,7 @@ static unsigned int ipt_ulog_target(struct sk_buff **pskb, | |||
288 | { | 288 | { |
289 | struct ipt_ulog_info *loginfo = (struct ipt_ulog_info *) targinfo; | 289 | struct ipt_ulog_info *loginfo = (struct ipt_ulog_info *) targinfo; |
290 | 290 | ||
291 | ipt_ulog_packet(hooknum, *pskb, in, out, loginfo, NULL); | 291 | ipt_ulog_packet(hooknum, skb, in, out, loginfo, NULL); |
292 | 292 | ||
293 | return XT_CONTINUE; | 293 | return XT_CONTINUE; |
294 | } | 294 | } |
diff --git a/net/ipv4/netfilter/iptable_filter.c b/net/ipv4/netfilter/iptable_filter.c index 4f51c1d7d2d6..ba3262c60437 100644 --- a/net/ipv4/netfilter/iptable_filter.c +++ b/net/ipv4/netfilter/iptable_filter.c | |||
@@ -62,31 +62,31 @@ static struct xt_table packet_filter = { | |||
62 | /* The work comes in here from netfilter.c. */ | 62 | /* The work comes in here from netfilter.c. */ |
63 | static unsigned int | 63 | static unsigned int |
64 | ipt_hook(unsigned int hook, | 64 | ipt_hook(unsigned int hook, |
65 | struct sk_buff **pskb, | 65 | struct sk_buff *skb, |
66 | const struct net_device *in, | 66 | const struct net_device *in, |
67 | const struct net_device *out, | 67 | const struct net_device *out, |
68 | int (*okfn)(struct sk_buff *)) | 68 | int (*okfn)(struct sk_buff *)) |
69 | { | 69 | { |
70 | return ipt_do_table(pskb, hook, in, out, &packet_filter); | 70 | return ipt_do_table(skb, hook, in, out, &packet_filter); |
71 | } | 71 | } |
72 | 72 | ||
73 | static unsigned int | 73 | static unsigned int |
74 | ipt_local_out_hook(unsigned int hook, | 74 | ipt_local_out_hook(unsigned int hook, |
75 | struct sk_buff **pskb, | 75 | struct sk_buff *skb, |
76 | const struct net_device *in, | 76 | const struct net_device *in, |
77 | const struct net_device *out, | 77 | const struct net_device *out, |
78 | int (*okfn)(struct sk_buff *)) | 78 | int (*okfn)(struct sk_buff *)) |
79 | { | 79 | { |
80 | /* root is playing with raw sockets. */ | 80 | /* root is playing with raw sockets. */ |
81 | if ((*pskb)->len < sizeof(struct iphdr) | 81 | if (skb->len < sizeof(struct iphdr) || |
82 | || ip_hdrlen(*pskb) < sizeof(struct iphdr)) { | 82 | ip_hdrlen(skb) < sizeof(struct iphdr)) { |
83 | if (net_ratelimit()) | 83 | if (net_ratelimit()) |
84 | printk("iptable_filter: ignoring short SOCK_RAW " | 84 | printk("iptable_filter: ignoring short SOCK_RAW " |
85 | "packet.\n"); | 85 | "packet.\n"); |
86 | return NF_ACCEPT; | 86 | return NF_ACCEPT; |
87 | } | 87 | } |
88 | 88 | ||
89 | return ipt_do_table(pskb, hook, in, out, &packet_filter); | 89 | return ipt_do_table(skb, hook, in, out, &packet_filter); |
90 | } | 90 | } |
91 | 91 | ||
92 | static struct nf_hook_ops ipt_ops[] = { | 92 | static struct nf_hook_ops ipt_ops[] = { |
diff --git a/net/ipv4/netfilter/iptable_mangle.c b/net/ipv4/netfilter/iptable_mangle.c index 902446f7cbca..b4360a69d5ca 100644 --- a/net/ipv4/netfilter/iptable_mangle.c +++ b/net/ipv4/netfilter/iptable_mangle.c | |||
@@ -75,17 +75,17 @@ static struct xt_table packet_mangler = { | |||
75 | /* The work comes in here from netfilter.c. */ | 75 | /* The work comes in here from netfilter.c. */ |
76 | static unsigned int | 76 | static unsigned int |
77 | ipt_route_hook(unsigned int hook, | 77 | ipt_route_hook(unsigned int hook, |
78 | struct sk_buff **pskb, | 78 | struct sk_buff *skb, |
79 | const struct net_device *in, | 79 | const struct net_device *in, |
80 | const struct net_device *out, | 80 | const struct net_device *out, |
81 | int (*okfn)(struct sk_buff *)) | 81 | int (*okfn)(struct sk_buff *)) |
82 | { | 82 | { |
83 | return ipt_do_table(pskb, hook, in, out, &packet_mangler); | 83 | return ipt_do_table(skb, hook, in, out, &packet_mangler); |
84 | } | 84 | } |
85 | 85 | ||
86 | static unsigned int | 86 | static unsigned int |
87 | ipt_local_hook(unsigned int hook, | 87 | ipt_local_hook(unsigned int hook, |
88 | struct sk_buff **pskb, | 88 | struct sk_buff *skb, |
89 | const struct net_device *in, | 89 | const struct net_device *in, |
90 | const struct net_device *out, | 90 | const struct net_device *out, |
91 | int (*okfn)(struct sk_buff *)) | 91 | int (*okfn)(struct sk_buff *)) |
@@ -97,8 +97,8 @@ ipt_local_hook(unsigned int hook, | |||
97 | u_int32_t mark; | 97 | u_int32_t mark; |
98 | 98 | ||
99 | /* root is playing with raw sockets. */ | 99 | /* root is playing with raw sockets. */ |
100 | if ((*pskb)->len < sizeof(struct iphdr) | 100 | if (skb->len < sizeof(struct iphdr) |
101 | || ip_hdrlen(*pskb) < sizeof(struct iphdr)) { | 101 | || ip_hdrlen(skb) < sizeof(struct iphdr)) { |
102 | if (net_ratelimit()) | 102 | if (net_ratelimit()) |
103 | printk("iptable_mangle: ignoring short SOCK_RAW " | 103 | printk("iptable_mangle: ignoring short SOCK_RAW " |
104 | "packet.\n"); | 104 | "packet.\n"); |
@@ -106,22 +106,22 @@ ipt_local_hook(unsigned int hook, | |||
106 | } | 106 | } |
107 | 107 | ||
108 | /* Save things which could affect route */ | 108 | /* Save things which could affect route */ |
109 | mark = (*pskb)->mark; | 109 | mark = skb->mark; |
110 | iph = ip_hdr(*pskb); | 110 | iph = ip_hdr(skb); |
111 | saddr = iph->saddr; | 111 | saddr = iph->saddr; |
112 | daddr = iph->daddr; | 112 | daddr = iph->daddr; |
113 | tos = iph->tos; | 113 | tos = iph->tos; |
114 | 114 | ||
115 | ret = ipt_do_table(pskb, hook, in, out, &packet_mangler); | 115 | ret = ipt_do_table(skb, hook, in, out, &packet_mangler); |
116 | /* Reroute for ANY change. */ | 116 | /* Reroute for ANY change. */ |
117 | if (ret != NF_DROP && ret != NF_STOLEN && ret != NF_QUEUE) { | 117 | if (ret != NF_DROP && ret != NF_STOLEN && ret != NF_QUEUE) { |
118 | iph = ip_hdr(*pskb); | 118 | iph = ip_hdr(skb); |
119 | 119 | ||
120 | if (iph->saddr != saddr || | 120 | if (iph->saddr != saddr || |
121 | iph->daddr != daddr || | 121 | iph->daddr != daddr || |
122 | (*pskb)->mark != mark || | 122 | skb->mark != mark || |
123 | iph->tos != tos) | 123 | iph->tos != tos) |
124 | if (ip_route_me_harder(pskb, RTN_UNSPEC)) | 124 | if (ip_route_me_harder(skb, RTN_UNSPEC)) |
125 | ret = NF_DROP; | 125 | ret = NF_DROP; |
126 | } | 126 | } |
127 | 127 | ||
diff --git a/net/ipv4/netfilter/iptable_raw.c b/net/ipv4/netfilter/iptable_raw.c index d6e503395684..5de6e57ac55c 100644 --- a/net/ipv4/netfilter/iptable_raw.c +++ b/net/ipv4/netfilter/iptable_raw.c | |||
@@ -47,30 +47,30 @@ static struct xt_table packet_raw = { | |||
47 | /* The work comes in here from netfilter.c. */ | 47 | /* The work comes in here from netfilter.c. */ |
48 | static unsigned int | 48 | static unsigned int |
49 | ipt_hook(unsigned int hook, | 49 | ipt_hook(unsigned int hook, |
50 | struct sk_buff **pskb, | 50 | struct sk_buff *skb, |
51 | const struct net_device *in, | 51 | const struct net_device *in, |
52 | const struct net_device *out, | 52 | const struct net_device *out, |
53 | int (*okfn)(struct sk_buff *)) | 53 | int (*okfn)(struct sk_buff *)) |
54 | { | 54 | { |
55 | return ipt_do_table(pskb, hook, in, out, &packet_raw); | 55 | return ipt_do_table(skb, hook, in, out, &packet_raw); |
56 | } | 56 | } |
57 | 57 | ||
58 | static unsigned int | 58 | static unsigned int |
59 | ipt_local_hook(unsigned int hook, | 59 | ipt_local_hook(unsigned int hook, |
60 | struct sk_buff **pskb, | 60 | struct sk_buff *skb, |
61 | const struct net_device *in, | 61 | const struct net_device *in, |
62 | const struct net_device *out, | 62 | const struct net_device *out, |
63 | int (*okfn)(struct sk_buff *)) | 63 | int (*okfn)(struct sk_buff *)) |
64 | { | 64 | { |
65 | /* root is playing with raw sockets. */ | 65 | /* root is playing with raw sockets. */ |
66 | if ((*pskb)->len < sizeof(struct iphdr) || | 66 | if (skb->len < sizeof(struct iphdr) || |
67 | ip_hdrlen(*pskb) < sizeof(struct iphdr)) { | 67 | ip_hdrlen(skb) < sizeof(struct iphdr)) { |
68 | if (net_ratelimit()) | 68 | if (net_ratelimit()) |
69 | printk("iptable_raw: ignoring short SOCK_RAW" | 69 | printk("iptable_raw: ignoring short SOCK_RAW" |
70 | "packet.\n"); | 70 | "packet.\n"); |
71 | return NF_ACCEPT; | 71 | return NF_ACCEPT; |
72 | } | 72 | } |
73 | return ipt_do_table(pskb, hook, in, out, &packet_raw); | 73 | return ipt_do_table(skb, hook, in, out, &packet_raw); |
74 | } | 74 | } |
75 | 75 | ||
76 | /* 'raw' is the very first table. */ | 76 | /* 'raw' is the very first table. */ |
diff --git a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c index 2fcb9249a8da..831e9b29806d 100644 --- a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c +++ b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c | |||
@@ -63,19 +63,20 @@ static int ipv4_print_conntrack(struct seq_file *s, | |||
63 | } | 63 | } |
64 | 64 | ||
65 | /* Returns new sk_buff, or NULL */ | 65 | /* Returns new sk_buff, or NULL */ |
66 | static struct sk_buff * | 66 | static int nf_ct_ipv4_gather_frags(struct sk_buff *skb, u_int32_t user) |
67 | nf_ct_ipv4_gather_frags(struct sk_buff *skb, u_int32_t user) | ||
68 | { | 67 | { |
68 | int err; | ||
69 | |||
69 | skb_orphan(skb); | 70 | skb_orphan(skb); |
70 | 71 | ||
71 | local_bh_disable(); | 72 | local_bh_disable(); |
72 | skb = ip_defrag(skb, user); | 73 | err = ip_defrag(skb, user); |
73 | local_bh_enable(); | 74 | local_bh_enable(); |
74 | 75 | ||
75 | if (skb) | 76 | if (!err) |
76 | ip_send_check(ip_hdr(skb)); | 77 | ip_send_check(ip_hdr(skb)); |
77 | 78 | ||
78 | return skb; | 79 | return err; |
79 | } | 80 | } |
80 | 81 | ||
81 | static int ipv4_get_l4proto(const struct sk_buff *skb, unsigned int nhoff, | 82 | static int ipv4_get_l4proto(const struct sk_buff *skb, unsigned int nhoff, |
@@ -99,17 +100,17 @@ static int ipv4_get_l4proto(const struct sk_buff *skb, unsigned int nhoff, | |||
99 | } | 100 | } |
100 | 101 | ||
101 | static unsigned int ipv4_confirm(unsigned int hooknum, | 102 | static unsigned int ipv4_confirm(unsigned int hooknum, |
102 | struct sk_buff **pskb, | 103 | struct sk_buff *skb, |
103 | const struct net_device *in, | 104 | const struct net_device *in, |
104 | const struct net_device *out, | 105 | const struct net_device *out, |
105 | int (*okfn)(struct sk_buff *)) | 106 | int (*okfn)(struct sk_buff *)) |
106 | { | 107 | { |
107 | /* We've seen it coming out the other side: confirm it */ | 108 | /* We've seen it coming out the other side: confirm it */ |
108 | return nf_conntrack_confirm(pskb); | 109 | return nf_conntrack_confirm(skb); |
109 | } | 110 | } |
110 | 111 | ||
111 | static unsigned int ipv4_conntrack_help(unsigned int hooknum, | 112 | static unsigned int ipv4_conntrack_help(unsigned int hooknum, |
112 | struct sk_buff **pskb, | 113 | struct sk_buff *skb, |
113 | const struct net_device *in, | 114 | const struct net_device *in, |
114 | const struct net_device *out, | 115 | const struct net_device *out, |
115 | int (*okfn)(struct sk_buff *)) | 116 | int (*okfn)(struct sk_buff *)) |
@@ -120,7 +121,7 @@ static unsigned int ipv4_conntrack_help(unsigned int hooknum, | |||
120 | struct nf_conntrack_helper *helper; | 121 | struct nf_conntrack_helper *helper; |
121 | 122 | ||
122 | /* This is where we call the helper: as the packet goes out. */ | 123 | /* This is where we call the helper: as the packet goes out. */ |
123 | ct = nf_ct_get(*pskb, &ctinfo); | 124 | ct = nf_ct_get(skb, &ctinfo); |
124 | if (!ct || ctinfo == IP_CT_RELATED + IP_CT_IS_REPLY) | 125 | if (!ct || ctinfo == IP_CT_RELATED + IP_CT_IS_REPLY) |
125 | return NF_ACCEPT; | 126 | return NF_ACCEPT; |
126 | 127 | ||
@@ -131,56 +132,55 @@ static unsigned int ipv4_conntrack_help(unsigned int hooknum, | |||
131 | helper = rcu_dereference(help->helper); | 132 | helper = rcu_dereference(help->helper); |
132 | if (!helper) | 133 | if (!helper) |
133 | return NF_ACCEPT; | 134 | return NF_ACCEPT; |
134 | return helper->help(pskb, skb_network_offset(*pskb) + ip_hdrlen(*pskb), | 135 | return helper->help(skb, skb_network_offset(skb) + ip_hdrlen(skb), |
135 | ct, ctinfo); | 136 | ct, ctinfo); |
136 | } | 137 | } |
137 | 138 | ||
138 | static unsigned int ipv4_conntrack_defrag(unsigned int hooknum, | 139 | static unsigned int ipv4_conntrack_defrag(unsigned int hooknum, |
139 | struct sk_buff **pskb, | 140 | struct sk_buff *skb, |
140 | const struct net_device *in, | 141 | const struct net_device *in, |
141 | const struct net_device *out, | 142 | const struct net_device *out, |
142 | int (*okfn)(struct sk_buff *)) | 143 | int (*okfn)(struct sk_buff *)) |
143 | { | 144 | { |
144 | /* Previously seen (loopback)? Ignore. Do this before | 145 | /* Previously seen (loopback)? Ignore. Do this before |
145 | fragment check. */ | 146 | fragment check. */ |
146 | if ((*pskb)->nfct) | 147 | if (skb->nfct) |
147 | return NF_ACCEPT; | 148 | return NF_ACCEPT; |
148 | 149 | ||
149 | /* Gather fragments. */ | 150 | /* Gather fragments. */ |
150 | if (ip_hdr(*pskb)->frag_off & htons(IP_MF | IP_OFFSET)) { | 151 | if (ip_hdr(skb)->frag_off & htons(IP_MF | IP_OFFSET)) { |
151 | *pskb = nf_ct_ipv4_gather_frags(*pskb, | 152 | if (nf_ct_ipv4_gather_frags(skb, |
152 | hooknum == NF_IP_PRE_ROUTING ? | 153 | hooknum == NF_IP_PRE_ROUTING ? |
153 | IP_DEFRAG_CONNTRACK_IN : | 154 | IP_DEFRAG_CONNTRACK_IN : |
154 | IP_DEFRAG_CONNTRACK_OUT); | 155 | IP_DEFRAG_CONNTRACK_OUT)) |
155 | if (!*pskb) | ||
156 | return NF_STOLEN; | 156 | return NF_STOLEN; |
157 | } | 157 | } |
158 | return NF_ACCEPT; | 158 | return NF_ACCEPT; |
159 | } | 159 | } |
160 | 160 | ||
161 | static unsigned int ipv4_conntrack_in(unsigned int hooknum, | 161 | static unsigned int ipv4_conntrack_in(unsigned int hooknum, |
162 | struct sk_buff **pskb, | 162 | struct sk_buff *skb, |
163 | const struct net_device *in, | 163 | const struct net_device *in, |
164 | const struct net_device *out, | 164 | const struct net_device *out, |
165 | int (*okfn)(struct sk_buff *)) | 165 | int (*okfn)(struct sk_buff *)) |
166 | { | 166 | { |
167 | return nf_conntrack_in(PF_INET, hooknum, pskb); | 167 | return nf_conntrack_in(PF_INET, hooknum, skb); |
168 | } | 168 | } |
169 | 169 | ||
170 | static unsigned int ipv4_conntrack_local(unsigned int hooknum, | 170 | static unsigned int ipv4_conntrack_local(unsigned int hooknum, |
171 | struct sk_buff **pskb, | 171 | struct sk_buff *skb, |
172 | const struct net_device *in, | 172 | const struct net_device *in, |
173 | const struct net_device *out, | 173 | const struct net_device *out, |
174 | int (*okfn)(struct sk_buff *)) | 174 | int (*okfn)(struct sk_buff *)) |
175 | { | 175 | { |
176 | /* root is playing with raw sockets. */ | 176 | /* root is playing with raw sockets. */ |
177 | if ((*pskb)->len < sizeof(struct iphdr) | 177 | if (skb->len < sizeof(struct iphdr) || |
178 | || ip_hdrlen(*pskb) < sizeof(struct iphdr)) { | 178 | ip_hdrlen(skb) < sizeof(struct iphdr)) { |
179 | if (net_ratelimit()) | 179 | if (net_ratelimit()) |
180 | printk("ipt_hook: happy cracking.\n"); | 180 | printk("ipt_hook: happy cracking.\n"); |
181 | return NF_ACCEPT; | 181 | return NF_ACCEPT; |
182 | } | 182 | } |
183 | return nf_conntrack_in(PF_INET, hooknum, pskb); | 183 | return nf_conntrack_in(PF_INET, hooknum, skb); |
184 | } | 184 | } |
185 | 185 | ||
186 | /* Connection tracking may drop packets, but never alters them, so | 186 | /* Connection tracking may drop packets, but never alters them, so |
diff --git a/net/ipv4/netfilter/nf_conntrack_proto_icmp.c b/net/ipv4/netfilter/nf_conntrack_proto_icmp.c index 11fedc73049c..adcbaf6d4299 100644 --- a/net/ipv4/netfilter/nf_conntrack_proto_icmp.c +++ b/net/ipv4/netfilter/nf_conntrack_proto_icmp.c | |||
@@ -281,7 +281,6 @@ static int icmp_nlattr_to_tuple(struct nlattr *tb[], | |||
281 | static struct ctl_table_header *icmp_sysctl_header; | 281 | static struct ctl_table_header *icmp_sysctl_header; |
282 | static struct ctl_table icmp_sysctl_table[] = { | 282 | static struct ctl_table icmp_sysctl_table[] = { |
283 | { | 283 | { |
284 | .ctl_name = NET_NF_CONNTRACK_ICMP_TIMEOUT, | ||
285 | .procname = "nf_conntrack_icmp_timeout", | 284 | .procname = "nf_conntrack_icmp_timeout", |
286 | .data = &nf_ct_icmp_timeout, | 285 | .data = &nf_ct_icmp_timeout, |
287 | .maxlen = sizeof(unsigned int), | 286 | .maxlen = sizeof(unsigned int), |
@@ -295,7 +294,6 @@ static struct ctl_table icmp_sysctl_table[] = { | |||
295 | #ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT | 294 | #ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT |
296 | static struct ctl_table icmp_compat_sysctl_table[] = { | 295 | static struct ctl_table icmp_compat_sysctl_table[] = { |
297 | { | 296 | { |
298 | .ctl_name = NET_IPV4_NF_CONNTRACK_ICMP_TIMEOUT, | ||
299 | .procname = "ip_conntrack_icmp_timeout", | 297 | .procname = "ip_conntrack_icmp_timeout", |
300 | .data = &nf_ct_icmp_timeout, | 298 | .data = &nf_ct_icmp_timeout, |
301 | .maxlen = sizeof(unsigned int), | 299 | .maxlen = sizeof(unsigned int), |
diff --git a/net/ipv4/netfilter/nf_nat_amanda.c b/net/ipv4/netfilter/nf_nat_amanda.c index bd93a1d71052..35a5aa69cd92 100644 --- a/net/ipv4/netfilter/nf_nat_amanda.c +++ b/net/ipv4/netfilter/nf_nat_amanda.c | |||
@@ -24,7 +24,7 @@ MODULE_DESCRIPTION("Amanda NAT helper"); | |||
24 | MODULE_LICENSE("GPL"); | 24 | MODULE_LICENSE("GPL"); |
25 | MODULE_ALIAS("ip_nat_amanda"); | 25 | MODULE_ALIAS("ip_nat_amanda"); |
26 | 26 | ||
27 | static unsigned int help(struct sk_buff **pskb, | 27 | static unsigned int help(struct sk_buff *skb, |
28 | enum ip_conntrack_info ctinfo, | 28 | enum ip_conntrack_info ctinfo, |
29 | unsigned int matchoff, | 29 | unsigned int matchoff, |
30 | unsigned int matchlen, | 30 | unsigned int matchlen, |
@@ -53,7 +53,7 @@ static unsigned int help(struct sk_buff **pskb, | |||
53 | return NF_DROP; | 53 | return NF_DROP; |
54 | 54 | ||
55 | sprintf(buffer, "%u", port); | 55 | sprintf(buffer, "%u", port); |
56 | ret = nf_nat_mangle_udp_packet(pskb, exp->master, ctinfo, | 56 | ret = nf_nat_mangle_udp_packet(skb, exp->master, ctinfo, |
57 | matchoff, matchlen, | 57 | matchoff, matchlen, |
58 | buffer, strlen(buffer)); | 58 | buffer, strlen(buffer)); |
59 | if (ret != NF_ACCEPT) | 59 | if (ret != NF_ACCEPT) |
diff --git a/net/ipv4/netfilter/nf_nat_core.c b/net/ipv4/netfilter/nf_nat_core.c index 7221aa20e6ff..56e93f692e82 100644 --- a/net/ipv4/netfilter/nf_nat_core.c +++ b/net/ipv4/netfilter/nf_nat_core.c | |||
@@ -349,7 +349,7 @@ EXPORT_SYMBOL(nf_nat_setup_info); | |||
349 | /* Returns true if succeeded. */ | 349 | /* Returns true if succeeded. */ |
350 | static int | 350 | static int |
351 | manip_pkt(u_int16_t proto, | 351 | manip_pkt(u_int16_t proto, |
352 | struct sk_buff **pskb, | 352 | struct sk_buff *skb, |
353 | unsigned int iphdroff, | 353 | unsigned int iphdroff, |
354 | const struct nf_conntrack_tuple *target, | 354 | const struct nf_conntrack_tuple *target, |
355 | enum nf_nat_manip_type maniptype) | 355 | enum nf_nat_manip_type maniptype) |
@@ -357,19 +357,19 @@ manip_pkt(u_int16_t proto, | |||
357 | struct iphdr *iph; | 357 | struct iphdr *iph; |
358 | struct nf_nat_protocol *p; | 358 | struct nf_nat_protocol *p; |
359 | 359 | ||
360 | if (!skb_make_writable(pskb, iphdroff + sizeof(*iph))) | 360 | if (!skb_make_writable(skb, iphdroff + sizeof(*iph))) |
361 | return 0; | 361 | return 0; |
362 | 362 | ||
363 | iph = (void *)(*pskb)->data + iphdroff; | 363 | iph = (void *)skb->data + iphdroff; |
364 | 364 | ||
365 | /* Manipulate protcol part. */ | 365 | /* Manipulate protcol part. */ |
366 | 366 | ||
367 | /* rcu_read_lock()ed by nf_hook_slow */ | 367 | /* rcu_read_lock()ed by nf_hook_slow */ |
368 | p = __nf_nat_proto_find(proto); | 368 | p = __nf_nat_proto_find(proto); |
369 | if (!p->manip_pkt(pskb, iphdroff, target, maniptype)) | 369 | if (!p->manip_pkt(skb, iphdroff, target, maniptype)) |
370 | return 0; | 370 | return 0; |
371 | 371 | ||
372 | iph = (void *)(*pskb)->data + iphdroff; | 372 | iph = (void *)skb->data + iphdroff; |
373 | 373 | ||
374 | if (maniptype == IP_NAT_MANIP_SRC) { | 374 | if (maniptype == IP_NAT_MANIP_SRC) { |
375 | nf_csum_replace4(&iph->check, iph->saddr, target->src.u3.ip); | 375 | nf_csum_replace4(&iph->check, iph->saddr, target->src.u3.ip); |
@@ -385,7 +385,7 @@ manip_pkt(u_int16_t proto, | |||
385 | unsigned int nf_nat_packet(struct nf_conn *ct, | 385 | unsigned int nf_nat_packet(struct nf_conn *ct, |
386 | enum ip_conntrack_info ctinfo, | 386 | enum ip_conntrack_info ctinfo, |
387 | unsigned int hooknum, | 387 | unsigned int hooknum, |
388 | struct sk_buff **pskb) | 388 | struct sk_buff *skb) |
389 | { | 389 | { |
390 | enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo); | 390 | enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo); |
391 | unsigned long statusbit; | 391 | unsigned long statusbit; |
@@ -407,7 +407,7 @@ unsigned int nf_nat_packet(struct nf_conn *ct, | |||
407 | /* We are aiming to look like inverse of other direction. */ | 407 | /* We are aiming to look like inverse of other direction. */ |
408 | nf_ct_invert_tuplepr(&target, &ct->tuplehash[!dir].tuple); | 408 | nf_ct_invert_tuplepr(&target, &ct->tuplehash[!dir].tuple); |
409 | 409 | ||
410 | if (!manip_pkt(target.dst.protonum, pskb, 0, &target, mtype)) | 410 | if (!manip_pkt(target.dst.protonum, skb, 0, &target, mtype)) |
411 | return NF_DROP; | 411 | return NF_DROP; |
412 | } | 412 | } |
413 | return NF_ACCEPT; | 413 | return NF_ACCEPT; |
@@ -418,7 +418,7 @@ EXPORT_SYMBOL_GPL(nf_nat_packet); | |||
418 | int nf_nat_icmp_reply_translation(struct nf_conn *ct, | 418 | int nf_nat_icmp_reply_translation(struct nf_conn *ct, |
419 | enum ip_conntrack_info ctinfo, | 419 | enum ip_conntrack_info ctinfo, |
420 | unsigned int hooknum, | 420 | unsigned int hooknum, |
421 | struct sk_buff **pskb) | 421 | struct sk_buff *skb) |
422 | { | 422 | { |
423 | struct { | 423 | struct { |
424 | struct icmphdr icmp; | 424 | struct icmphdr icmp; |
@@ -426,24 +426,24 @@ int nf_nat_icmp_reply_translation(struct nf_conn *ct, | |||
426 | } *inside; | 426 | } *inside; |
427 | struct nf_conntrack_l4proto *l4proto; | 427 | struct nf_conntrack_l4proto *l4proto; |
428 | struct nf_conntrack_tuple inner, target; | 428 | struct nf_conntrack_tuple inner, target; |
429 | int hdrlen = ip_hdrlen(*pskb); | 429 | int hdrlen = ip_hdrlen(skb); |
430 | enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo); | 430 | enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo); |
431 | unsigned long statusbit; | 431 | unsigned long statusbit; |
432 | enum nf_nat_manip_type manip = HOOK2MANIP(hooknum); | 432 | enum nf_nat_manip_type manip = HOOK2MANIP(hooknum); |
433 | 433 | ||
434 | if (!skb_make_writable(pskb, hdrlen + sizeof(*inside))) | 434 | if (!skb_make_writable(skb, hdrlen + sizeof(*inside))) |
435 | return 0; | 435 | return 0; |
436 | 436 | ||
437 | inside = (void *)(*pskb)->data + ip_hdrlen(*pskb); | 437 | inside = (void *)skb->data + ip_hdrlen(skb); |
438 | 438 | ||
439 | /* We're actually going to mangle it beyond trivial checksum | 439 | /* We're actually going to mangle it beyond trivial checksum |
440 | adjustment, so make sure the current checksum is correct. */ | 440 | adjustment, so make sure the current checksum is correct. */ |
441 | if (nf_ip_checksum(*pskb, hooknum, hdrlen, 0)) | 441 | if (nf_ip_checksum(skb, hooknum, hdrlen, 0)) |
442 | return 0; | 442 | return 0; |
443 | 443 | ||
444 | /* Must be RELATED */ | 444 | /* Must be RELATED */ |
445 | NF_CT_ASSERT((*pskb)->nfctinfo == IP_CT_RELATED || | 445 | NF_CT_ASSERT(skb->nfctinfo == IP_CT_RELATED || |
446 | (*pskb)->nfctinfo == IP_CT_RELATED+IP_CT_IS_REPLY); | 446 | skb->nfctinfo == IP_CT_RELATED+IP_CT_IS_REPLY); |
447 | 447 | ||
448 | /* Redirects on non-null nats must be dropped, else they'll | 448 | /* Redirects on non-null nats must be dropped, else they'll |
449 | start talking to each other without our translation, and be | 449 | start talking to each other without our translation, and be |
@@ -458,15 +458,15 @@ int nf_nat_icmp_reply_translation(struct nf_conn *ct, | |||
458 | } | 458 | } |
459 | 459 | ||
460 | pr_debug("icmp_reply_translation: translating error %p manip %u " | 460 | pr_debug("icmp_reply_translation: translating error %p manip %u " |
461 | "dir %s\n", *pskb, manip, | 461 | "dir %s\n", skb, manip, |
462 | dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY"); | 462 | dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY"); |
463 | 463 | ||
464 | /* rcu_read_lock()ed by nf_hook_slow */ | 464 | /* rcu_read_lock()ed by nf_hook_slow */ |
465 | l4proto = __nf_ct_l4proto_find(PF_INET, inside->ip.protocol); | 465 | l4proto = __nf_ct_l4proto_find(PF_INET, inside->ip.protocol); |
466 | 466 | ||
467 | if (!nf_ct_get_tuple(*pskb, | 467 | if (!nf_ct_get_tuple(skb, |
468 | ip_hdrlen(*pskb) + sizeof(struct icmphdr), | 468 | ip_hdrlen(skb) + sizeof(struct icmphdr), |
469 | (ip_hdrlen(*pskb) + | 469 | (ip_hdrlen(skb) + |
470 | sizeof(struct icmphdr) + inside->ip.ihl * 4), | 470 | sizeof(struct icmphdr) + inside->ip.ihl * 4), |
471 | (u_int16_t)AF_INET, | 471 | (u_int16_t)AF_INET, |
472 | inside->ip.protocol, | 472 | inside->ip.protocol, |
@@ -478,19 +478,19 @@ int nf_nat_icmp_reply_translation(struct nf_conn *ct, | |||
478 | pass all hooks (locally-generated ICMP). Consider incoming | 478 | pass all hooks (locally-generated ICMP). Consider incoming |
479 | packet: PREROUTING (DST manip), routing produces ICMP, goes | 479 | packet: PREROUTING (DST manip), routing produces ICMP, goes |
480 | through POSTROUTING (which must correct the DST manip). */ | 480 | through POSTROUTING (which must correct the DST manip). */ |
481 | if (!manip_pkt(inside->ip.protocol, pskb, | 481 | if (!manip_pkt(inside->ip.protocol, skb, |
482 | ip_hdrlen(*pskb) + sizeof(inside->icmp), | 482 | ip_hdrlen(skb) + sizeof(inside->icmp), |
483 | &ct->tuplehash[!dir].tuple, | 483 | &ct->tuplehash[!dir].tuple, |
484 | !manip)) | 484 | !manip)) |
485 | return 0; | 485 | return 0; |
486 | 486 | ||
487 | if ((*pskb)->ip_summed != CHECKSUM_PARTIAL) { | 487 | if (skb->ip_summed != CHECKSUM_PARTIAL) { |
488 | /* Reloading "inside" here since manip_pkt inner. */ | 488 | /* Reloading "inside" here since manip_pkt inner. */ |
489 | inside = (void *)(*pskb)->data + ip_hdrlen(*pskb); | 489 | inside = (void *)skb->data + ip_hdrlen(skb); |
490 | inside->icmp.checksum = 0; | 490 | inside->icmp.checksum = 0; |
491 | inside->icmp.checksum = | 491 | inside->icmp.checksum = |
492 | csum_fold(skb_checksum(*pskb, hdrlen, | 492 | csum_fold(skb_checksum(skb, hdrlen, |
493 | (*pskb)->len - hdrlen, 0)); | 493 | skb->len - hdrlen, 0)); |
494 | } | 494 | } |
495 | 495 | ||
496 | /* Change outer to look the reply to an incoming packet | 496 | /* Change outer to look the reply to an incoming packet |
@@ -506,7 +506,7 @@ int nf_nat_icmp_reply_translation(struct nf_conn *ct, | |||
506 | 506 | ||
507 | if (ct->status & statusbit) { | 507 | if (ct->status & statusbit) { |
508 | nf_ct_invert_tuplepr(&target, &ct->tuplehash[!dir].tuple); | 508 | nf_ct_invert_tuplepr(&target, &ct->tuplehash[!dir].tuple); |
509 | if (!manip_pkt(0, pskb, 0, &target, manip)) | 509 | if (!manip_pkt(0, skb, 0, &target, manip)) |
510 | return 0; | 510 | return 0; |
511 | } | 511 | } |
512 | 512 | ||
diff --git a/net/ipv4/netfilter/nf_nat_ftp.c b/net/ipv4/netfilter/nf_nat_ftp.c index 3663bd879c39..e1a16d3ea4cb 100644 --- a/net/ipv4/netfilter/nf_nat_ftp.c +++ b/net/ipv4/netfilter/nf_nat_ftp.c | |||
@@ -28,7 +28,7 @@ MODULE_ALIAS("ip_nat_ftp"); | |||
28 | /* FIXME: Time out? --RR */ | 28 | /* FIXME: Time out? --RR */ |
29 | 29 | ||
30 | static int | 30 | static int |
31 | mangle_rfc959_packet(struct sk_buff **pskb, | 31 | mangle_rfc959_packet(struct sk_buff *skb, |
32 | __be32 newip, | 32 | __be32 newip, |
33 | u_int16_t port, | 33 | u_int16_t port, |
34 | unsigned int matchoff, | 34 | unsigned int matchoff, |
@@ -43,13 +43,13 @@ mangle_rfc959_packet(struct sk_buff **pskb, | |||
43 | 43 | ||
44 | pr_debug("calling nf_nat_mangle_tcp_packet\n"); | 44 | pr_debug("calling nf_nat_mangle_tcp_packet\n"); |
45 | 45 | ||
46 | return nf_nat_mangle_tcp_packet(pskb, ct, ctinfo, matchoff, | 46 | return nf_nat_mangle_tcp_packet(skb, ct, ctinfo, matchoff, |
47 | matchlen, buffer, strlen(buffer)); | 47 | matchlen, buffer, strlen(buffer)); |
48 | } | 48 | } |
49 | 49 | ||
50 | /* |1|132.235.1.2|6275| */ | 50 | /* |1|132.235.1.2|6275| */ |
51 | static int | 51 | static int |
52 | mangle_eprt_packet(struct sk_buff **pskb, | 52 | mangle_eprt_packet(struct sk_buff *skb, |
53 | __be32 newip, | 53 | __be32 newip, |
54 | u_int16_t port, | 54 | u_int16_t port, |
55 | unsigned int matchoff, | 55 | unsigned int matchoff, |
@@ -63,13 +63,13 @@ mangle_eprt_packet(struct sk_buff **pskb, | |||
63 | 63 | ||
64 | pr_debug("calling nf_nat_mangle_tcp_packet\n"); | 64 | pr_debug("calling nf_nat_mangle_tcp_packet\n"); |
65 | 65 | ||
66 | return nf_nat_mangle_tcp_packet(pskb, ct, ctinfo, matchoff, | 66 | return nf_nat_mangle_tcp_packet(skb, ct, ctinfo, matchoff, |
67 | matchlen, buffer, strlen(buffer)); | 67 | matchlen, buffer, strlen(buffer)); |
68 | } | 68 | } |
69 | 69 | ||
70 | /* |1|132.235.1.2|6275| */ | 70 | /* |1|132.235.1.2|6275| */ |
71 | static int | 71 | static int |
72 | mangle_epsv_packet(struct sk_buff **pskb, | 72 | mangle_epsv_packet(struct sk_buff *skb, |
73 | __be32 newip, | 73 | __be32 newip, |
74 | u_int16_t port, | 74 | u_int16_t port, |
75 | unsigned int matchoff, | 75 | unsigned int matchoff, |
@@ -83,11 +83,11 @@ mangle_epsv_packet(struct sk_buff **pskb, | |||
83 | 83 | ||
84 | pr_debug("calling nf_nat_mangle_tcp_packet\n"); | 84 | pr_debug("calling nf_nat_mangle_tcp_packet\n"); |
85 | 85 | ||
86 | return nf_nat_mangle_tcp_packet(pskb, ct, ctinfo, matchoff, | 86 | return nf_nat_mangle_tcp_packet(skb, ct, ctinfo, matchoff, |
87 | matchlen, buffer, strlen(buffer)); | 87 | matchlen, buffer, strlen(buffer)); |
88 | } | 88 | } |
89 | 89 | ||
90 | static int (*mangle[])(struct sk_buff **, __be32, u_int16_t, | 90 | static int (*mangle[])(struct sk_buff *, __be32, u_int16_t, |
91 | unsigned int, unsigned int, struct nf_conn *, | 91 | unsigned int, unsigned int, struct nf_conn *, |
92 | enum ip_conntrack_info) | 92 | enum ip_conntrack_info) |
93 | = { | 93 | = { |
@@ -99,7 +99,7 @@ static int (*mangle[])(struct sk_buff **, __be32, u_int16_t, | |||
99 | 99 | ||
100 | /* So, this packet has hit the connection tracking matching code. | 100 | /* So, this packet has hit the connection tracking matching code. |
101 | Mangle it, and change the expectation to match the new version. */ | 101 | Mangle it, and change the expectation to match the new version. */ |
102 | static unsigned int nf_nat_ftp(struct sk_buff **pskb, | 102 | static unsigned int nf_nat_ftp(struct sk_buff *skb, |
103 | enum ip_conntrack_info ctinfo, | 103 | enum ip_conntrack_info ctinfo, |
104 | enum nf_ct_ftp_type type, | 104 | enum nf_ct_ftp_type type, |
105 | unsigned int matchoff, | 105 | unsigned int matchoff, |
@@ -132,7 +132,7 @@ static unsigned int nf_nat_ftp(struct sk_buff **pskb, | |||
132 | if (port == 0) | 132 | if (port == 0) |
133 | return NF_DROP; | 133 | return NF_DROP; |
134 | 134 | ||
135 | if (!mangle[type](pskb, newip, port, matchoff, matchlen, ct, ctinfo)) { | 135 | if (!mangle[type](skb, newip, port, matchoff, matchlen, ct, ctinfo)) { |
136 | nf_ct_unexpect_related(exp); | 136 | nf_ct_unexpect_related(exp); |
137 | return NF_DROP; | 137 | return NF_DROP; |
138 | } | 138 | } |
diff --git a/net/ipv4/netfilter/nf_nat_h323.c b/net/ipv4/netfilter/nf_nat_h323.c index c1b059a73708..a868c8c41328 100644 --- a/net/ipv4/netfilter/nf_nat_h323.c +++ b/net/ipv4/netfilter/nf_nat_h323.c | |||
@@ -22,12 +22,12 @@ | |||
22 | #include <linux/netfilter/nf_conntrack_h323.h> | 22 | #include <linux/netfilter/nf_conntrack_h323.h> |
23 | 23 | ||
24 | /****************************************************************************/ | 24 | /****************************************************************************/ |
25 | static int set_addr(struct sk_buff **pskb, | 25 | static int set_addr(struct sk_buff *skb, |
26 | unsigned char **data, int dataoff, | 26 | unsigned char **data, int dataoff, |
27 | unsigned int addroff, __be32 ip, __be16 port) | 27 | unsigned int addroff, __be32 ip, __be16 port) |
28 | { | 28 | { |
29 | enum ip_conntrack_info ctinfo; | 29 | enum ip_conntrack_info ctinfo; |
30 | struct nf_conn *ct = nf_ct_get(*pskb, &ctinfo); | 30 | struct nf_conn *ct = nf_ct_get(skb, &ctinfo); |
31 | struct { | 31 | struct { |
32 | __be32 ip; | 32 | __be32 ip; |
33 | __be16 port; | 33 | __be16 port; |
@@ -38,8 +38,8 @@ static int set_addr(struct sk_buff **pskb, | |||
38 | buf.port = port; | 38 | buf.port = port; |
39 | addroff += dataoff; | 39 | addroff += dataoff; |
40 | 40 | ||
41 | if (ip_hdr(*pskb)->protocol == IPPROTO_TCP) { | 41 | if (ip_hdr(skb)->protocol == IPPROTO_TCP) { |
42 | if (!nf_nat_mangle_tcp_packet(pskb, ct, ctinfo, | 42 | if (!nf_nat_mangle_tcp_packet(skb, ct, ctinfo, |
43 | addroff, sizeof(buf), | 43 | addroff, sizeof(buf), |
44 | (char *) &buf, sizeof(buf))) { | 44 | (char *) &buf, sizeof(buf))) { |
45 | if (net_ratelimit()) | 45 | if (net_ratelimit()) |
@@ -49,14 +49,13 @@ static int set_addr(struct sk_buff **pskb, | |||
49 | } | 49 | } |
50 | 50 | ||
51 | /* Relocate data pointer */ | 51 | /* Relocate data pointer */ |
52 | th = skb_header_pointer(*pskb, ip_hdrlen(*pskb), | 52 | th = skb_header_pointer(skb, ip_hdrlen(skb), |
53 | sizeof(_tcph), &_tcph); | 53 | sizeof(_tcph), &_tcph); |
54 | if (th == NULL) | 54 | if (th == NULL) |
55 | return -1; | 55 | return -1; |
56 | *data = (*pskb)->data + ip_hdrlen(*pskb) + | 56 | *data = skb->data + ip_hdrlen(skb) + th->doff * 4 + dataoff; |
57 | th->doff * 4 + dataoff; | ||
58 | } else { | 57 | } else { |
59 | if (!nf_nat_mangle_udp_packet(pskb, ct, ctinfo, | 58 | if (!nf_nat_mangle_udp_packet(skb, ct, ctinfo, |
60 | addroff, sizeof(buf), | 59 | addroff, sizeof(buf), |
61 | (char *) &buf, sizeof(buf))) { | 60 | (char *) &buf, sizeof(buf))) { |
62 | if (net_ratelimit()) | 61 | if (net_ratelimit()) |
@@ -67,36 +66,35 @@ static int set_addr(struct sk_buff **pskb, | |||
67 | /* nf_nat_mangle_udp_packet uses skb_make_writable() to copy | 66 | /* nf_nat_mangle_udp_packet uses skb_make_writable() to copy |
68 | * or pull everything in a linear buffer, so we can safely | 67 | * or pull everything in a linear buffer, so we can safely |
69 | * use the skb pointers now */ | 68 | * use the skb pointers now */ |
70 | *data = ((*pskb)->data + ip_hdrlen(*pskb) + | 69 | *data = skb->data + ip_hdrlen(skb) + sizeof(struct udphdr); |
71 | sizeof(struct udphdr)); | ||
72 | } | 70 | } |
73 | 71 | ||
74 | return 0; | 72 | return 0; |
75 | } | 73 | } |
76 | 74 | ||
77 | /****************************************************************************/ | 75 | /****************************************************************************/ |
78 | static int set_h225_addr(struct sk_buff **pskb, | 76 | static int set_h225_addr(struct sk_buff *skb, |
79 | unsigned char **data, int dataoff, | 77 | unsigned char **data, int dataoff, |
80 | TransportAddress *taddr, | 78 | TransportAddress *taddr, |
81 | union nf_conntrack_address *addr, __be16 port) | 79 | union nf_conntrack_address *addr, __be16 port) |
82 | { | 80 | { |
83 | return set_addr(pskb, data, dataoff, taddr->ipAddress.ip, | 81 | return set_addr(skb, data, dataoff, taddr->ipAddress.ip, |
84 | addr->ip, port); | 82 | addr->ip, port); |
85 | } | 83 | } |
86 | 84 | ||
87 | /****************************************************************************/ | 85 | /****************************************************************************/ |
88 | static int set_h245_addr(struct sk_buff **pskb, | 86 | static int set_h245_addr(struct sk_buff *skb, |
89 | unsigned char **data, int dataoff, | 87 | unsigned char **data, int dataoff, |
90 | H245_TransportAddress *taddr, | 88 | H245_TransportAddress *taddr, |
91 | union nf_conntrack_address *addr, __be16 port) | 89 | union nf_conntrack_address *addr, __be16 port) |
92 | { | 90 | { |
93 | return set_addr(pskb, data, dataoff, | 91 | return set_addr(skb, data, dataoff, |
94 | taddr->unicastAddress.iPAddress.network, | 92 | taddr->unicastAddress.iPAddress.network, |
95 | addr->ip, port); | 93 | addr->ip, port); |
96 | } | 94 | } |
97 | 95 | ||
98 | /****************************************************************************/ | 96 | /****************************************************************************/ |
99 | static int set_sig_addr(struct sk_buff **pskb, struct nf_conn *ct, | 97 | static int set_sig_addr(struct sk_buff *skb, struct nf_conn *ct, |
100 | enum ip_conntrack_info ctinfo, | 98 | enum ip_conntrack_info ctinfo, |
101 | unsigned char **data, | 99 | unsigned char **data, |
102 | TransportAddress *taddr, int count) | 100 | TransportAddress *taddr, int count) |
@@ -125,7 +123,7 @@ static int set_sig_addr(struct sk_buff **pskb, struct nf_conn *ct, | |||
125 | NIPQUAD(addr.ip), port, | 123 | NIPQUAD(addr.ip), port, |
126 | NIPQUAD(ct->tuplehash[!dir].tuple.dst.u3.ip), | 124 | NIPQUAD(ct->tuplehash[!dir].tuple.dst.u3.ip), |
127 | info->sig_port[!dir]); | 125 | info->sig_port[!dir]); |
128 | return set_h225_addr(pskb, data, 0, &taddr[i], | 126 | return set_h225_addr(skb, data, 0, &taddr[i], |
129 | &ct->tuplehash[!dir]. | 127 | &ct->tuplehash[!dir]. |
130 | tuple.dst.u3, | 128 | tuple.dst.u3, |
131 | info->sig_port[!dir]); | 129 | info->sig_port[!dir]); |
@@ -137,7 +135,7 @@ static int set_sig_addr(struct sk_buff **pskb, struct nf_conn *ct, | |||
137 | NIPQUAD(addr.ip), port, | 135 | NIPQUAD(addr.ip), port, |
138 | NIPQUAD(ct->tuplehash[!dir].tuple.src.u3.ip), | 136 | NIPQUAD(ct->tuplehash[!dir].tuple.src.u3.ip), |
139 | info->sig_port[!dir]); | 137 | info->sig_port[!dir]); |
140 | return set_h225_addr(pskb, data, 0, &taddr[i], | 138 | return set_h225_addr(skb, data, 0, &taddr[i], |
141 | &ct->tuplehash[!dir]. | 139 | &ct->tuplehash[!dir]. |
142 | tuple.src.u3, | 140 | tuple.src.u3, |
143 | info->sig_port[!dir]); | 141 | info->sig_port[!dir]); |
@@ -149,7 +147,7 @@ static int set_sig_addr(struct sk_buff **pskb, struct nf_conn *ct, | |||
149 | } | 147 | } |
150 | 148 | ||
151 | /****************************************************************************/ | 149 | /****************************************************************************/ |
152 | static int set_ras_addr(struct sk_buff **pskb, struct nf_conn *ct, | 150 | static int set_ras_addr(struct sk_buff *skb, struct nf_conn *ct, |
153 | enum ip_conntrack_info ctinfo, | 151 | enum ip_conntrack_info ctinfo, |
154 | unsigned char **data, | 152 | unsigned char **data, |
155 | TransportAddress *taddr, int count) | 153 | TransportAddress *taddr, int count) |
@@ -168,7 +166,7 @@ static int set_ras_addr(struct sk_buff **pskb, struct nf_conn *ct, | |||
168 | NIPQUAD(addr.ip), ntohs(port), | 166 | NIPQUAD(addr.ip), ntohs(port), |
169 | NIPQUAD(ct->tuplehash[!dir].tuple.dst.u3.ip), | 167 | NIPQUAD(ct->tuplehash[!dir].tuple.dst.u3.ip), |
170 | ntohs(ct->tuplehash[!dir].tuple.dst.u.udp.port)); | 168 | ntohs(ct->tuplehash[!dir].tuple.dst.u.udp.port)); |
171 | return set_h225_addr(pskb, data, 0, &taddr[i], | 169 | return set_h225_addr(skb, data, 0, &taddr[i], |
172 | &ct->tuplehash[!dir].tuple.dst.u3, | 170 | &ct->tuplehash[!dir].tuple.dst.u3, |
173 | ct->tuplehash[!dir].tuple. | 171 | ct->tuplehash[!dir].tuple. |
174 | dst.u.udp.port); | 172 | dst.u.udp.port); |
@@ -179,7 +177,7 @@ static int set_ras_addr(struct sk_buff **pskb, struct nf_conn *ct, | |||
179 | } | 177 | } |
180 | 178 | ||
181 | /****************************************************************************/ | 179 | /****************************************************************************/ |
182 | static int nat_rtp_rtcp(struct sk_buff **pskb, struct nf_conn *ct, | 180 | static int nat_rtp_rtcp(struct sk_buff *skb, struct nf_conn *ct, |
183 | enum ip_conntrack_info ctinfo, | 181 | enum ip_conntrack_info ctinfo, |
184 | unsigned char **data, int dataoff, | 182 | unsigned char **data, int dataoff, |
185 | H245_TransportAddress *taddr, | 183 | H245_TransportAddress *taddr, |
@@ -244,7 +242,7 @@ static int nat_rtp_rtcp(struct sk_buff **pskb, struct nf_conn *ct, | |||
244 | } | 242 | } |
245 | 243 | ||
246 | /* Modify signal */ | 244 | /* Modify signal */ |
247 | if (set_h245_addr(pskb, data, dataoff, taddr, | 245 | if (set_h245_addr(skb, data, dataoff, taddr, |
248 | &ct->tuplehash[!dir].tuple.dst.u3, | 246 | &ct->tuplehash[!dir].tuple.dst.u3, |
249 | htons((port & htons(1)) ? nated_port + 1 : | 247 | htons((port & htons(1)) ? nated_port + 1 : |
250 | nated_port)) == 0) { | 248 | nated_port)) == 0) { |
@@ -273,7 +271,7 @@ static int nat_rtp_rtcp(struct sk_buff **pskb, struct nf_conn *ct, | |||
273 | } | 271 | } |
274 | 272 | ||
275 | /****************************************************************************/ | 273 | /****************************************************************************/ |
276 | static int nat_t120(struct sk_buff **pskb, struct nf_conn *ct, | 274 | static int nat_t120(struct sk_buff *skb, struct nf_conn *ct, |
277 | enum ip_conntrack_info ctinfo, | 275 | enum ip_conntrack_info ctinfo, |
278 | unsigned char **data, int dataoff, | 276 | unsigned char **data, int dataoff, |
279 | H245_TransportAddress *taddr, __be16 port, | 277 | H245_TransportAddress *taddr, __be16 port, |
@@ -301,7 +299,7 @@ static int nat_t120(struct sk_buff **pskb, struct nf_conn *ct, | |||
301 | } | 299 | } |
302 | 300 | ||
303 | /* Modify signal */ | 301 | /* Modify signal */ |
304 | if (set_h245_addr(pskb, data, dataoff, taddr, | 302 | if (set_h245_addr(skb, data, dataoff, taddr, |
305 | &ct->tuplehash[!dir].tuple.dst.u3, | 303 | &ct->tuplehash[!dir].tuple.dst.u3, |
306 | htons(nated_port)) < 0) { | 304 | htons(nated_port)) < 0) { |
307 | nf_ct_unexpect_related(exp); | 305 | nf_ct_unexpect_related(exp); |
@@ -318,7 +316,7 @@ static int nat_t120(struct sk_buff **pskb, struct nf_conn *ct, | |||
318 | } | 316 | } |
319 | 317 | ||
320 | /****************************************************************************/ | 318 | /****************************************************************************/ |
321 | static int nat_h245(struct sk_buff **pskb, struct nf_conn *ct, | 319 | static int nat_h245(struct sk_buff *skb, struct nf_conn *ct, |
322 | enum ip_conntrack_info ctinfo, | 320 | enum ip_conntrack_info ctinfo, |
323 | unsigned char **data, int dataoff, | 321 | unsigned char **data, int dataoff, |
324 | TransportAddress *taddr, __be16 port, | 322 | TransportAddress *taddr, __be16 port, |
@@ -351,7 +349,7 @@ static int nat_h245(struct sk_buff **pskb, struct nf_conn *ct, | |||
351 | } | 349 | } |
352 | 350 | ||
353 | /* Modify signal */ | 351 | /* Modify signal */ |
354 | if (set_h225_addr(pskb, data, dataoff, taddr, | 352 | if (set_h225_addr(skb, data, dataoff, taddr, |
355 | &ct->tuplehash[!dir].tuple.dst.u3, | 353 | &ct->tuplehash[!dir].tuple.dst.u3, |
356 | htons(nated_port)) == 0) { | 354 | htons(nated_port)) == 0) { |
357 | /* Save ports */ | 355 | /* Save ports */ |
@@ -406,7 +404,7 @@ static void ip_nat_q931_expect(struct nf_conn *new, | |||
406 | } | 404 | } |
407 | 405 | ||
408 | /****************************************************************************/ | 406 | /****************************************************************************/ |
409 | static int nat_q931(struct sk_buff **pskb, struct nf_conn *ct, | 407 | static int nat_q931(struct sk_buff *skb, struct nf_conn *ct, |
410 | enum ip_conntrack_info ctinfo, | 408 | enum ip_conntrack_info ctinfo, |
411 | unsigned char **data, TransportAddress *taddr, int idx, | 409 | unsigned char **data, TransportAddress *taddr, int idx, |
412 | __be16 port, struct nf_conntrack_expect *exp) | 410 | __be16 port, struct nf_conntrack_expect *exp) |
@@ -439,7 +437,7 @@ static int nat_q931(struct sk_buff **pskb, struct nf_conn *ct, | |||
439 | } | 437 | } |
440 | 438 | ||
441 | /* Modify signal */ | 439 | /* Modify signal */ |
442 | if (set_h225_addr(pskb, data, 0, &taddr[idx], | 440 | if (set_h225_addr(skb, data, 0, &taddr[idx], |
443 | &ct->tuplehash[!dir].tuple.dst.u3, | 441 | &ct->tuplehash[!dir].tuple.dst.u3, |
444 | htons(nated_port)) == 0) { | 442 | htons(nated_port)) == 0) { |
445 | /* Save ports */ | 443 | /* Save ports */ |
@@ -450,7 +448,7 @@ static int nat_q931(struct sk_buff **pskb, struct nf_conn *ct, | |||
450 | if (idx > 0 && | 448 | if (idx > 0 && |
451 | get_h225_addr(ct, *data, &taddr[0], &addr, &port) && | 449 | get_h225_addr(ct, *data, &taddr[0], &addr, &port) && |
452 | (ntohl(addr.ip) & 0xff000000) == 0x7f000000) { | 450 | (ntohl(addr.ip) & 0xff000000) == 0x7f000000) { |
453 | set_h225_addr(pskb, data, 0, &taddr[0], | 451 | set_h225_addr(skb, data, 0, &taddr[0], |
454 | &ct->tuplehash[!dir].tuple.dst.u3, | 452 | &ct->tuplehash[!dir].tuple.dst.u3, |
455 | info->sig_port[!dir]); | 453 | info->sig_port[!dir]); |
456 | } | 454 | } |
@@ -495,7 +493,7 @@ static void ip_nat_callforwarding_expect(struct nf_conn *new, | |||
495 | } | 493 | } |
496 | 494 | ||
497 | /****************************************************************************/ | 495 | /****************************************************************************/ |
498 | static int nat_callforwarding(struct sk_buff **pskb, struct nf_conn *ct, | 496 | static int nat_callforwarding(struct sk_buff *skb, struct nf_conn *ct, |
499 | enum ip_conntrack_info ctinfo, | 497 | enum ip_conntrack_info ctinfo, |
500 | unsigned char **data, int dataoff, | 498 | unsigned char **data, int dataoff, |
501 | TransportAddress *taddr, __be16 port, | 499 | TransportAddress *taddr, __be16 port, |
@@ -525,7 +523,7 @@ static int nat_callforwarding(struct sk_buff **pskb, struct nf_conn *ct, | |||
525 | } | 523 | } |
526 | 524 | ||
527 | /* Modify signal */ | 525 | /* Modify signal */ |
528 | if (!set_h225_addr(pskb, data, dataoff, taddr, | 526 | if (!set_h225_addr(skb, data, dataoff, taddr, |
529 | &ct->tuplehash[!dir].tuple.dst.u3, | 527 | &ct->tuplehash[!dir].tuple.dst.u3, |
530 | htons(nated_port)) == 0) { | 528 | htons(nated_port)) == 0) { |
531 | nf_ct_unexpect_related(exp); | 529 | nf_ct_unexpect_related(exp); |
diff --git a/net/ipv4/netfilter/nf_nat_helper.c b/net/ipv4/netfilter/nf_nat_helper.c index 93d8a0a8f035..8718da00ef2a 100644 --- a/net/ipv4/netfilter/nf_nat_helper.c +++ b/net/ipv4/netfilter/nf_nat_helper.c | |||
@@ -111,22 +111,14 @@ static void mangle_contents(struct sk_buff *skb, | |||
111 | } | 111 | } |
112 | 112 | ||
113 | /* Unusual, but possible case. */ | 113 | /* Unusual, but possible case. */ |
114 | static int enlarge_skb(struct sk_buff **pskb, unsigned int extra) | 114 | static int enlarge_skb(struct sk_buff *skb, unsigned int extra) |
115 | { | 115 | { |
116 | struct sk_buff *nskb; | 116 | if (skb->len + extra > 65535) |
117 | |||
118 | if ((*pskb)->len + extra > 65535) | ||
119 | return 0; | 117 | return 0; |
120 | 118 | ||
121 | nskb = skb_copy_expand(*pskb, skb_headroom(*pskb), extra, GFP_ATOMIC); | 119 | if (pskb_expand_head(skb, 0, extra - skb_tailroom(skb), GFP_ATOMIC)) |
122 | if (!nskb) | ||
123 | return 0; | 120 | return 0; |
124 | 121 | ||
125 | /* Transfer socket to new skb. */ | ||
126 | if ((*pskb)->sk) | ||
127 | skb_set_owner_w(nskb, (*pskb)->sk); | ||
128 | kfree_skb(*pskb); | ||
129 | *pskb = nskb; | ||
130 | return 1; | 122 | return 1; |
131 | } | 123 | } |
132 | 124 | ||
@@ -139,7 +131,7 @@ static int enlarge_skb(struct sk_buff **pskb, unsigned int extra) | |||
139 | * | 131 | * |
140 | * */ | 132 | * */ |
141 | int | 133 | int |
142 | nf_nat_mangle_tcp_packet(struct sk_buff **pskb, | 134 | nf_nat_mangle_tcp_packet(struct sk_buff *skb, |
143 | struct nf_conn *ct, | 135 | struct nf_conn *ct, |
144 | enum ip_conntrack_info ctinfo, | 136 | enum ip_conntrack_info ctinfo, |
145 | unsigned int match_offset, | 137 | unsigned int match_offset, |
@@ -147,37 +139,37 @@ nf_nat_mangle_tcp_packet(struct sk_buff **pskb, | |||
147 | const char *rep_buffer, | 139 | const char *rep_buffer, |
148 | unsigned int rep_len) | 140 | unsigned int rep_len) |
149 | { | 141 | { |
150 | struct rtable *rt = (struct rtable *)(*pskb)->dst; | 142 | struct rtable *rt = (struct rtable *)skb->dst; |
151 | struct iphdr *iph; | 143 | struct iphdr *iph; |
152 | struct tcphdr *tcph; | 144 | struct tcphdr *tcph; |
153 | int oldlen, datalen; | 145 | int oldlen, datalen; |
154 | 146 | ||
155 | if (!skb_make_writable(pskb, (*pskb)->len)) | 147 | if (!skb_make_writable(skb, skb->len)) |
156 | return 0; | 148 | return 0; |
157 | 149 | ||
158 | if (rep_len > match_len && | 150 | if (rep_len > match_len && |
159 | rep_len - match_len > skb_tailroom(*pskb) && | 151 | rep_len - match_len > skb_tailroom(skb) && |
160 | !enlarge_skb(pskb, rep_len - match_len)) | 152 | !enlarge_skb(skb, rep_len - match_len)) |
161 | return 0; | 153 | return 0; |
162 | 154 | ||
163 | SKB_LINEAR_ASSERT(*pskb); | 155 | SKB_LINEAR_ASSERT(skb); |
164 | 156 | ||
165 | iph = ip_hdr(*pskb); | 157 | iph = ip_hdr(skb); |
166 | tcph = (void *)iph + iph->ihl*4; | 158 | tcph = (void *)iph + iph->ihl*4; |
167 | 159 | ||
168 | oldlen = (*pskb)->len - iph->ihl*4; | 160 | oldlen = skb->len - iph->ihl*4; |
169 | mangle_contents(*pskb, iph->ihl*4 + tcph->doff*4, | 161 | mangle_contents(skb, iph->ihl*4 + tcph->doff*4, |
170 | match_offset, match_len, rep_buffer, rep_len); | 162 | match_offset, match_len, rep_buffer, rep_len); |
171 | 163 | ||
172 | datalen = (*pskb)->len - iph->ihl*4; | 164 | datalen = skb->len - iph->ihl*4; |
173 | if ((*pskb)->ip_summed != CHECKSUM_PARTIAL) { | 165 | if (skb->ip_summed != CHECKSUM_PARTIAL) { |
174 | if (!(rt->rt_flags & RTCF_LOCAL) && | 166 | if (!(rt->rt_flags & RTCF_LOCAL) && |
175 | (*pskb)->dev->features & NETIF_F_V4_CSUM) { | 167 | skb->dev->features & NETIF_F_V4_CSUM) { |
176 | (*pskb)->ip_summed = CHECKSUM_PARTIAL; | 168 | skb->ip_summed = CHECKSUM_PARTIAL; |
177 | (*pskb)->csum_start = skb_headroom(*pskb) + | 169 | skb->csum_start = skb_headroom(skb) + |
178 | skb_network_offset(*pskb) + | 170 | skb_network_offset(skb) + |
179 | iph->ihl * 4; | 171 | iph->ihl * 4; |
180 | (*pskb)->csum_offset = offsetof(struct tcphdr, check); | 172 | skb->csum_offset = offsetof(struct tcphdr, check); |
181 | tcph->check = ~tcp_v4_check(datalen, | 173 | tcph->check = ~tcp_v4_check(datalen, |
182 | iph->saddr, iph->daddr, 0); | 174 | iph->saddr, iph->daddr, 0); |
183 | } else { | 175 | } else { |
@@ -188,7 +180,7 @@ nf_nat_mangle_tcp_packet(struct sk_buff **pskb, | |||
188 | datalen, 0)); | 180 | datalen, 0)); |
189 | } | 181 | } |
190 | } else | 182 | } else |
191 | nf_proto_csum_replace2(&tcph->check, *pskb, | 183 | nf_proto_csum_replace2(&tcph->check, skb, |
192 | htons(oldlen), htons(datalen), 1); | 184 | htons(oldlen), htons(datalen), 1); |
193 | 185 | ||
194 | if (rep_len != match_len) { | 186 | if (rep_len != match_len) { |
@@ -197,7 +189,7 @@ nf_nat_mangle_tcp_packet(struct sk_buff **pskb, | |||
197 | (int)rep_len - (int)match_len, | 189 | (int)rep_len - (int)match_len, |
198 | ct, ctinfo); | 190 | ct, ctinfo); |
199 | /* Tell TCP window tracking about seq change */ | 191 | /* Tell TCP window tracking about seq change */ |
200 | nf_conntrack_tcp_update(*pskb, ip_hdrlen(*pskb), | 192 | nf_conntrack_tcp_update(skb, ip_hdrlen(skb), |
201 | ct, CTINFO2DIR(ctinfo)); | 193 | ct, CTINFO2DIR(ctinfo)); |
202 | } | 194 | } |
203 | return 1; | 195 | return 1; |
@@ -215,7 +207,7 @@ EXPORT_SYMBOL(nf_nat_mangle_tcp_packet); | |||
215 | * should be fairly easy to do. | 207 | * should be fairly easy to do. |
216 | */ | 208 | */ |
217 | int | 209 | int |
218 | nf_nat_mangle_udp_packet(struct sk_buff **pskb, | 210 | nf_nat_mangle_udp_packet(struct sk_buff *skb, |
219 | struct nf_conn *ct, | 211 | struct nf_conn *ct, |
220 | enum ip_conntrack_info ctinfo, | 212 | enum ip_conntrack_info ctinfo, |
221 | unsigned int match_offset, | 213 | unsigned int match_offset, |
@@ -223,48 +215,48 @@ nf_nat_mangle_udp_packet(struct sk_buff **pskb, | |||
223 | const char *rep_buffer, | 215 | const char *rep_buffer, |
224 | unsigned int rep_len) | 216 | unsigned int rep_len) |
225 | { | 217 | { |
226 | struct rtable *rt = (struct rtable *)(*pskb)->dst; | 218 | struct rtable *rt = (struct rtable *)skb->dst; |
227 | struct iphdr *iph; | 219 | struct iphdr *iph; |
228 | struct udphdr *udph; | 220 | struct udphdr *udph; |
229 | int datalen, oldlen; | 221 | int datalen, oldlen; |
230 | 222 | ||
231 | /* UDP helpers might accidentally mangle the wrong packet */ | 223 | /* UDP helpers might accidentally mangle the wrong packet */ |
232 | iph = ip_hdr(*pskb); | 224 | iph = ip_hdr(skb); |
233 | if ((*pskb)->len < iph->ihl*4 + sizeof(*udph) + | 225 | if (skb->len < iph->ihl*4 + sizeof(*udph) + |
234 | match_offset + match_len) | 226 | match_offset + match_len) |
235 | return 0; | 227 | return 0; |
236 | 228 | ||
237 | if (!skb_make_writable(pskb, (*pskb)->len)) | 229 | if (!skb_make_writable(skb, skb->len)) |
238 | return 0; | 230 | return 0; |
239 | 231 | ||
240 | if (rep_len > match_len && | 232 | if (rep_len > match_len && |
241 | rep_len - match_len > skb_tailroom(*pskb) && | 233 | rep_len - match_len > skb_tailroom(skb) && |
242 | !enlarge_skb(pskb, rep_len - match_len)) | 234 | !enlarge_skb(skb, rep_len - match_len)) |
243 | return 0; | 235 | return 0; |
244 | 236 | ||
245 | iph = ip_hdr(*pskb); | 237 | iph = ip_hdr(skb); |
246 | udph = (void *)iph + iph->ihl*4; | 238 | udph = (void *)iph + iph->ihl*4; |
247 | 239 | ||
248 | oldlen = (*pskb)->len - iph->ihl*4; | 240 | oldlen = skb->len - iph->ihl*4; |
249 | mangle_contents(*pskb, iph->ihl*4 + sizeof(*udph), | 241 | mangle_contents(skb, iph->ihl*4 + sizeof(*udph), |
250 | match_offset, match_len, rep_buffer, rep_len); | 242 | match_offset, match_len, rep_buffer, rep_len); |
251 | 243 | ||
252 | /* update the length of the UDP packet */ | 244 | /* update the length of the UDP packet */ |
253 | datalen = (*pskb)->len - iph->ihl*4; | 245 | datalen = skb->len - iph->ihl*4; |
254 | udph->len = htons(datalen); | 246 | udph->len = htons(datalen); |
255 | 247 | ||
256 | /* fix udp checksum if udp checksum was previously calculated */ | 248 | /* fix udp checksum if udp checksum was previously calculated */ |
257 | if (!udph->check && (*pskb)->ip_summed != CHECKSUM_PARTIAL) | 249 | if (!udph->check && skb->ip_summed != CHECKSUM_PARTIAL) |
258 | return 1; | 250 | return 1; |
259 | 251 | ||
260 | if ((*pskb)->ip_summed != CHECKSUM_PARTIAL) { | 252 | if (skb->ip_summed != CHECKSUM_PARTIAL) { |
261 | if (!(rt->rt_flags & RTCF_LOCAL) && | 253 | if (!(rt->rt_flags & RTCF_LOCAL) && |
262 | (*pskb)->dev->features & NETIF_F_V4_CSUM) { | 254 | skb->dev->features & NETIF_F_V4_CSUM) { |
263 | (*pskb)->ip_summed = CHECKSUM_PARTIAL; | 255 | skb->ip_summed = CHECKSUM_PARTIAL; |
264 | (*pskb)->csum_start = skb_headroom(*pskb) + | 256 | skb->csum_start = skb_headroom(skb) + |
265 | skb_network_offset(*pskb) + | 257 | skb_network_offset(skb) + |
266 | iph->ihl * 4; | 258 | iph->ihl * 4; |
267 | (*pskb)->csum_offset = offsetof(struct udphdr, check); | 259 | skb->csum_offset = offsetof(struct udphdr, check); |
268 | udph->check = ~csum_tcpudp_magic(iph->saddr, iph->daddr, | 260 | udph->check = ~csum_tcpudp_magic(iph->saddr, iph->daddr, |
269 | datalen, IPPROTO_UDP, | 261 | datalen, IPPROTO_UDP, |
270 | 0); | 262 | 0); |
@@ -278,7 +270,7 @@ nf_nat_mangle_udp_packet(struct sk_buff **pskb, | |||
278 | udph->check = CSUM_MANGLED_0; | 270 | udph->check = CSUM_MANGLED_0; |
279 | } | 271 | } |
280 | } else | 272 | } else |
281 | nf_proto_csum_replace2(&udph->check, *pskb, | 273 | nf_proto_csum_replace2(&udph->check, skb, |
282 | htons(oldlen), htons(datalen), 1); | 274 | htons(oldlen), htons(datalen), 1); |
283 | 275 | ||
284 | return 1; | 276 | return 1; |
@@ -330,7 +322,7 @@ sack_adjust(struct sk_buff *skb, | |||
330 | 322 | ||
331 | /* TCP SACK sequence number adjustment */ | 323 | /* TCP SACK sequence number adjustment */ |
332 | static inline unsigned int | 324 | static inline unsigned int |
333 | nf_nat_sack_adjust(struct sk_buff **pskb, | 325 | nf_nat_sack_adjust(struct sk_buff *skb, |
334 | struct tcphdr *tcph, | 326 | struct tcphdr *tcph, |
335 | struct nf_conn *ct, | 327 | struct nf_conn *ct, |
336 | enum ip_conntrack_info ctinfo) | 328 | enum ip_conntrack_info ctinfo) |
@@ -338,17 +330,17 @@ nf_nat_sack_adjust(struct sk_buff **pskb, | |||
338 | unsigned int dir, optoff, optend; | 330 | unsigned int dir, optoff, optend; |
339 | struct nf_conn_nat *nat = nfct_nat(ct); | 331 | struct nf_conn_nat *nat = nfct_nat(ct); |
340 | 332 | ||
341 | optoff = ip_hdrlen(*pskb) + sizeof(struct tcphdr); | 333 | optoff = ip_hdrlen(skb) + sizeof(struct tcphdr); |
342 | optend = ip_hdrlen(*pskb) + tcph->doff * 4; | 334 | optend = ip_hdrlen(skb) + tcph->doff * 4; |
343 | 335 | ||
344 | if (!skb_make_writable(pskb, optend)) | 336 | if (!skb_make_writable(skb, optend)) |
345 | return 0; | 337 | return 0; |
346 | 338 | ||
347 | dir = CTINFO2DIR(ctinfo); | 339 | dir = CTINFO2DIR(ctinfo); |
348 | 340 | ||
349 | while (optoff < optend) { | 341 | while (optoff < optend) { |
350 | /* Usually: option, length. */ | 342 | /* Usually: option, length. */ |
351 | unsigned char *op = (*pskb)->data + optoff; | 343 | unsigned char *op = skb->data + optoff; |
352 | 344 | ||
353 | switch (op[0]) { | 345 | switch (op[0]) { |
354 | case TCPOPT_EOL: | 346 | case TCPOPT_EOL: |
@@ -365,7 +357,7 @@ nf_nat_sack_adjust(struct sk_buff **pskb, | |||
365 | if (op[0] == TCPOPT_SACK && | 357 | if (op[0] == TCPOPT_SACK && |
366 | op[1] >= 2+TCPOLEN_SACK_PERBLOCK && | 358 | op[1] >= 2+TCPOLEN_SACK_PERBLOCK && |
367 | ((op[1] - 2) % TCPOLEN_SACK_PERBLOCK) == 0) | 359 | ((op[1] - 2) % TCPOLEN_SACK_PERBLOCK) == 0) |
368 | sack_adjust(*pskb, tcph, optoff+2, | 360 | sack_adjust(skb, tcph, optoff+2, |
369 | optoff+op[1], &nat->seq[!dir]); | 361 | optoff+op[1], &nat->seq[!dir]); |
370 | optoff += op[1]; | 362 | optoff += op[1]; |
371 | } | 363 | } |
@@ -375,7 +367,7 @@ nf_nat_sack_adjust(struct sk_buff **pskb, | |||
375 | 367 | ||
376 | /* TCP sequence number adjustment. Returns 1 on success, 0 on failure */ | 368 | /* TCP sequence number adjustment. Returns 1 on success, 0 on failure */ |
377 | int | 369 | int |
378 | nf_nat_seq_adjust(struct sk_buff **pskb, | 370 | nf_nat_seq_adjust(struct sk_buff *skb, |
379 | struct nf_conn *ct, | 371 | struct nf_conn *ct, |
380 | enum ip_conntrack_info ctinfo) | 372 | enum ip_conntrack_info ctinfo) |
381 | { | 373 | { |
@@ -390,10 +382,10 @@ nf_nat_seq_adjust(struct sk_buff **pskb, | |||
390 | this_way = &nat->seq[dir]; | 382 | this_way = &nat->seq[dir]; |
391 | other_way = &nat->seq[!dir]; | 383 | other_way = &nat->seq[!dir]; |
392 | 384 | ||
393 | if (!skb_make_writable(pskb, ip_hdrlen(*pskb) + sizeof(*tcph))) | 385 | if (!skb_make_writable(skb, ip_hdrlen(skb) + sizeof(*tcph))) |
394 | return 0; | 386 | return 0; |
395 | 387 | ||
396 | tcph = (void *)(*pskb)->data + ip_hdrlen(*pskb); | 388 | tcph = (void *)skb->data + ip_hdrlen(skb); |
397 | if (after(ntohl(tcph->seq), this_way->correction_pos)) | 389 | if (after(ntohl(tcph->seq), this_way->correction_pos)) |
398 | newseq = htonl(ntohl(tcph->seq) + this_way->offset_after); | 390 | newseq = htonl(ntohl(tcph->seq) + this_way->offset_after); |
399 | else | 391 | else |
@@ -405,8 +397,8 @@ nf_nat_seq_adjust(struct sk_buff **pskb, | |||
405 | else | 397 | else |
406 | newack = htonl(ntohl(tcph->ack_seq) - other_way->offset_before); | 398 | newack = htonl(ntohl(tcph->ack_seq) - other_way->offset_before); |
407 | 399 | ||
408 | nf_proto_csum_replace4(&tcph->check, *pskb, tcph->seq, newseq, 0); | 400 | nf_proto_csum_replace4(&tcph->check, skb, tcph->seq, newseq, 0); |
409 | nf_proto_csum_replace4(&tcph->check, *pskb, tcph->ack_seq, newack, 0); | 401 | nf_proto_csum_replace4(&tcph->check, skb, tcph->ack_seq, newack, 0); |
410 | 402 | ||
411 | pr_debug("Adjusting sequence number from %u->%u, ack from %u->%u\n", | 403 | pr_debug("Adjusting sequence number from %u->%u, ack from %u->%u\n", |
412 | ntohl(tcph->seq), ntohl(newseq), ntohl(tcph->ack_seq), | 404 | ntohl(tcph->seq), ntohl(newseq), ntohl(tcph->ack_seq), |
@@ -415,10 +407,10 @@ nf_nat_seq_adjust(struct sk_buff **pskb, | |||
415 | tcph->seq = newseq; | 407 | tcph->seq = newseq; |
416 | tcph->ack_seq = newack; | 408 | tcph->ack_seq = newack; |
417 | 409 | ||
418 | if (!nf_nat_sack_adjust(pskb, tcph, ct, ctinfo)) | 410 | if (!nf_nat_sack_adjust(skb, tcph, ct, ctinfo)) |
419 | return 0; | 411 | return 0; |
420 | 412 | ||
421 | nf_conntrack_tcp_update(*pskb, ip_hdrlen(*pskb), ct, dir); | 413 | nf_conntrack_tcp_update(skb, ip_hdrlen(skb), ct, dir); |
422 | 414 | ||
423 | return 1; | 415 | return 1; |
424 | } | 416 | } |
diff --git a/net/ipv4/netfilter/nf_nat_irc.c b/net/ipv4/netfilter/nf_nat_irc.c index bcf274bba602..766e2c16c6b9 100644 --- a/net/ipv4/netfilter/nf_nat_irc.c +++ b/net/ipv4/netfilter/nf_nat_irc.c | |||
@@ -27,7 +27,7 @@ MODULE_DESCRIPTION("IRC (DCC) NAT helper"); | |||
27 | MODULE_LICENSE("GPL"); | 27 | MODULE_LICENSE("GPL"); |
28 | MODULE_ALIAS("ip_nat_irc"); | 28 | MODULE_ALIAS("ip_nat_irc"); |
29 | 29 | ||
30 | static unsigned int help(struct sk_buff **pskb, | 30 | static unsigned int help(struct sk_buff *skb, |
31 | enum ip_conntrack_info ctinfo, | 31 | enum ip_conntrack_info ctinfo, |
32 | unsigned int matchoff, | 32 | unsigned int matchoff, |
33 | unsigned int matchlen, | 33 | unsigned int matchlen, |
@@ -58,7 +58,7 @@ static unsigned int help(struct sk_buff **pskb, | |||
58 | pr_debug("nf_nat_irc: inserting '%s' == %u.%u.%u.%u, port %u\n", | 58 | pr_debug("nf_nat_irc: inserting '%s' == %u.%u.%u.%u, port %u\n", |
59 | buffer, NIPQUAD(ip), port); | 59 | buffer, NIPQUAD(ip), port); |
60 | 60 | ||
61 | ret = nf_nat_mangle_tcp_packet(pskb, exp->master, ctinfo, | 61 | ret = nf_nat_mangle_tcp_packet(skb, exp->master, ctinfo, |
62 | matchoff, matchlen, buffer, | 62 | matchoff, matchlen, buffer, |
63 | strlen(buffer)); | 63 | strlen(buffer)); |
64 | if (ret != NF_ACCEPT) | 64 | if (ret != NF_ACCEPT) |
diff --git a/net/ipv4/netfilter/nf_nat_pptp.c b/net/ipv4/netfilter/nf_nat_pptp.c index 984ec8308b2e..e1385a099079 100644 --- a/net/ipv4/netfilter/nf_nat_pptp.c +++ b/net/ipv4/netfilter/nf_nat_pptp.c | |||
@@ -110,7 +110,7 @@ static void pptp_nat_expected(struct nf_conn *ct, | |||
110 | 110 | ||
111 | /* outbound packets == from PNS to PAC */ | 111 | /* outbound packets == from PNS to PAC */ |
112 | static int | 112 | static int |
113 | pptp_outbound_pkt(struct sk_buff **pskb, | 113 | pptp_outbound_pkt(struct sk_buff *skb, |
114 | struct nf_conn *ct, | 114 | struct nf_conn *ct, |
115 | enum ip_conntrack_info ctinfo, | 115 | enum ip_conntrack_info ctinfo, |
116 | struct PptpControlHeader *ctlh, | 116 | struct PptpControlHeader *ctlh, |
@@ -175,7 +175,7 @@ pptp_outbound_pkt(struct sk_buff **pskb, | |||
175 | ntohs(REQ_CID(pptpReq, cid_off)), ntohs(new_callid)); | 175 | ntohs(REQ_CID(pptpReq, cid_off)), ntohs(new_callid)); |
176 | 176 | ||
177 | /* mangle packet */ | 177 | /* mangle packet */ |
178 | if (nf_nat_mangle_tcp_packet(pskb, ct, ctinfo, | 178 | if (nf_nat_mangle_tcp_packet(skb, ct, ctinfo, |
179 | cid_off + sizeof(struct pptp_pkt_hdr) + | 179 | cid_off + sizeof(struct pptp_pkt_hdr) + |
180 | sizeof(struct PptpControlHeader), | 180 | sizeof(struct PptpControlHeader), |
181 | sizeof(new_callid), (char *)&new_callid, | 181 | sizeof(new_callid), (char *)&new_callid, |
@@ -213,7 +213,7 @@ pptp_exp_gre(struct nf_conntrack_expect *expect_orig, | |||
213 | 213 | ||
214 | /* inbound packets == from PAC to PNS */ | 214 | /* inbound packets == from PAC to PNS */ |
215 | static int | 215 | static int |
216 | pptp_inbound_pkt(struct sk_buff **pskb, | 216 | pptp_inbound_pkt(struct sk_buff *skb, |
217 | struct nf_conn *ct, | 217 | struct nf_conn *ct, |
218 | enum ip_conntrack_info ctinfo, | 218 | enum ip_conntrack_info ctinfo, |
219 | struct PptpControlHeader *ctlh, | 219 | struct PptpControlHeader *ctlh, |
@@ -268,7 +268,7 @@ pptp_inbound_pkt(struct sk_buff **pskb, | |||
268 | pr_debug("altering peer call id from 0x%04x to 0x%04x\n", | 268 | pr_debug("altering peer call id from 0x%04x to 0x%04x\n", |
269 | ntohs(REQ_CID(pptpReq, pcid_off)), ntohs(new_pcid)); | 269 | ntohs(REQ_CID(pptpReq, pcid_off)), ntohs(new_pcid)); |
270 | 270 | ||
271 | if (nf_nat_mangle_tcp_packet(pskb, ct, ctinfo, | 271 | if (nf_nat_mangle_tcp_packet(skb, ct, ctinfo, |
272 | pcid_off + sizeof(struct pptp_pkt_hdr) + | 272 | pcid_off + sizeof(struct pptp_pkt_hdr) + |
273 | sizeof(struct PptpControlHeader), | 273 | sizeof(struct PptpControlHeader), |
274 | sizeof(new_pcid), (char *)&new_pcid, | 274 | sizeof(new_pcid), (char *)&new_pcid, |
diff --git a/net/ipv4/netfilter/nf_nat_proto_gre.c b/net/ipv4/netfilter/nf_nat_proto_gre.c index d562290b1820..b820f9960356 100644 --- a/net/ipv4/netfilter/nf_nat_proto_gre.c +++ b/net/ipv4/netfilter/nf_nat_proto_gre.c | |||
@@ -98,21 +98,21 @@ gre_unique_tuple(struct nf_conntrack_tuple *tuple, | |||
98 | 98 | ||
99 | /* manipulate a GRE packet according to maniptype */ | 99 | /* manipulate a GRE packet according to maniptype */ |
100 | static int | 100 | static int |
101 | gre_manip_pkt(struct sk_buff **pskb, unsigned int iphdroff, | 101 | gre_manip_pkt(struct sk_buff *skb, unsigned int iphdroff, |
102 | const struct nf_conntrack_tuple *tuple, | 102 | const struct nf_conntrack_tuple *tuple, |
103 | enum nf_nat_manip_type maniptype) | 103 | enum nf_nat_manip_type maniptype) |
104 | { | 104 | { |
105 | struct gre_hdr *greh; | 105 | struct gre_hdr *greh; |
106 | struct gre_hdr_pptp *pgreh; | 106 | struct gre_hdr_pptp *pgreh; |
107 | struct iphdr *iph = (struct iphdr *)((*pskb)->data + iphdroff); | 107 | struct iphdr *iph = (struct iphdr *)(skb->data + iphdroff); |
108 | unsigned int hdroff = iphdroff + iph->ihl * 4; | 108 | unsigned int hdroff = iphdroff + iph->ihl * 4; |
109 | 109 | ||
110 | /* pgreh includes two optional 32bit fields which are not required | 110 | /* pgreh includes two optional 32bit fields which are not required |
111 | * to be there. That's where the magic '8' comes from */ | 111 | * to be there. That's where the magic '8' comes from */ |
112 | if (!skb_make_writable(pskb, hdroff + sizeof(*pgreh) - 8)) | 112 | if (!skb_make_writable(skb, hdroff + sizeof(*pgreh) - 8)) |
113 | return 0; | 113 | return 0; |
114 | 114 | ||
115 | greh = (void *)(*pskb)->data + hdroff; | 115 | greh = (void *)skb->data + hdroff; |
116 | pgreh = (struct gre_hdr_pptp *)greh; | 116 | pgreh = (struct gre_hdr_pptp *)greh; |
117 | 117 | ||
118 | /* we only have destination manip of a packet, since 'source key' | 118 | /* we only have destination manip of a packet, since 'source key' |
diff --git a/net/ipv4/netfilter/nf_nat_proto_icmp.c b/net/ipv4/netfilter/nf_nat_proto_icmp.c index 898d73771155..b9fc724388fc 100644 --- a/net/ipv4/netfilter/nf_nat_proto_icmp.c +++ b/net/ipv4/netfilter/nf_nat_proto_icmp.c | |||
@@ -52,20 +52,20 @@ icmp_unique_tuple(struct nf_conntrack_tuple *tuple, | |||
52 | } | 52 | } |
53 | 53 | ||
54 | static int | 54 | static int |
55 | icmp_manip_pkt(struct sk_buff **pskb, | 55 | icmp_manip_pkt(struct sk_buff *skb, |
56 | unsigned int iphdroff, | 56 | unsigned int iphdroff, |
57 | const struct nf_conntrack_tuple *tuple, | 57 | const struct nf_conntrack_tuple *tuple, |
58 | enum nf_nat_manip_type maniptype) | 58 | enum nf_nat_manip_type maniptype) |
59 | { | 59 | { |
60 | struct iphdr *iph = (struct iphdr *)((*pskb)->data + iphdroff); | 60 | struct iphdr *iph = (struct iphdr *)(skb->data + iphdroff); |
61 | struct icmphdr *hdr; | 61 | struct icmphdr *hdr; |
62 | unsigned int hdroff = iphdroff + iph->ihl*4; | 62 | unsigned int hdroff = iphdroff + iph->ihl*4; |
63 | 63 | ||
64 | if (!skb_make_writable(pskb, hdroff + sizeof(*hdr))) | 64 | if (!skb_make_writable(skb, hdroff + sizeof(*hdr))) |
65 | return 0; | 65 | return 0; |
66 | 66 | ||
67 | hdr = (struct icmphdr *)((*pskb)->data + hdroff); | 67 | hdr = (struct icmphdr *)(skb->data + hdroff); |
68 | nf_proto_csum_replace2(&hdr->checksum, *pskb, | 68 | nf_proto_csum_replace2(&hdr->checksum, skb, |
69 | hdr->un.echo.id, tuple->src.u.icmp.id, 0); | 69 | hdr->un.echo.id, tuple->src.u.icmp.id, 0); |
70 | hdr->un.echo.id = tuple->src.u.icmp.id; | 70 | hdr->un.echo.id = tuple->src.u.icmp.id; |
71 | return 1; | 71 | return 1; |
diff --git a/net/ipv4/netfilter/nf_nat_proto_tcp.c b/net/ipv4/netfilter/nf_nat_proto_tcp.c index 5bbbb2acdc70..6bab2e184455 100644 --- a/net/ipv4/netfilter/nf_nat_proto_tcp.c +++ b/net/ipv4/netfilter/nf_nat_proto_tcp.c | |||
@@ -88,12 +88,12 @@ tcp_unique_tuple(struct nf_conntrack_tuple *tuple, | |||
88 | } | 88 | } |
89 | 89 | ||
90 | static int | 90 | static int |
91 | tcp_manip_pkt(struct sk_buff **pskb, | 91 | tcp_manip_pkt(struct sk_buff *skb, |
92 | unsigned int iphdroff, | 92 | unsigned int iphdroff, |
93 | const struct nf_conntrack_tuple *tuple, | 93 | const struct nf_conntrack_tuple *tuple, |
94 | enum nf_nat_manip_type maniptype) | 94 | enum nf_nat_manip_type maniptype) |
95 | { | 95 | { |
96 | struct iphdr *iph = (struct iphdr *)((*pskb)->data + iphdroff); | 96 | struct iphdr *iph = (struct iphdr *)(skb->data + iphdroff); |
97 | struct tcphdr *hdr; | 97 | struct tcphdr *hdr; |
98 | unsigned int hdroff = iphdroff + iph->ihl*4; | 98 | unsigned int hdroff = iphdroff + iph->ihl*4; |
99 | __be32 oldip, newip; | 99 | __be32 oldip, newip; |
@@ -103,14 +103,14 @@ tcp_manip_pkt(struct sk_buff **pskb, | |||
103 | /* this could be a inner header returned in icmp packet; in such | 103 | /* this could be a inner header returned in icmp packet; in such |
104 | cases we cannot update the checksum field since it is outside of | 104 | cases we cannot update the checksum field since it is outside of |
105 | the 8 bytes of transport layer headers we are guaranteed */ | 105 | the 8 bytes of transport layer headers we are guaranteed */ |
106 | if ((*pskb)->len >= hdroff + sizeof(struct tcphdr)) | 106 | if (skb->len >= hdroff + sizeof(struct tcphdr)) |
107 | hdrsize = sizeof(struct tcphdr); | 107 | hdrsize = sizeof(struct tcphdr); |
108 | 108 | ||
109 | if (!skb_make_writable(pskb, hdroff + hdrsize)) | 109 | if (!skb_make_writable(skb, hdroff + hdrsize)) |
110 | return 0; | 110 | return 0; |
111 | 111 | ||
112 | iph = (struct iphdr *)((*pskb)->data + iphdroff); | 112 | iph = (struct iphdr *)(skb->data + iphdroff); |
113 | hdr = (struct tcphdr *)((*pskb)->data + hdroff); | 113 | hdr = (struct tcphdr *)(skb->data + hdroff); |
114 | 114 | ||
115 | if (maniptype == IP_NAT_MANIP_SRC) { | 115 | if (maniptype == IP_NAT_MANIP_SRC) { |
116 | /* Get rid of src ip and src pt */ | 116 | /* Get rid of src ip and src pt */ |
@@ -132,8 +132,8 @@ tcp_manip_pkt(struct sk_buff **pskb, | |||
132 | if (hdrsize < sizeof(*hdr)) | 132 | if (hdrsize < sizeof(*hdr)) |
133 | return 1; | 133 | return 1; |
134 | 134 | ||
135 | nf_proto_csum_replace4(&hdr->check, *pskb, oldip, newip, 1); | 135 | nf_proto_csum_replace4(&hdr->check, skb, oldip, newip, 1); |
136 | nf_proto_csum_replace2(&hdr->check, *pskb, oldport, newport, 0); | 136 | nf_proto_csum_replace2(&hdr->check, skb, oldport, newport, 0); |
137 | return 1; | 137 | return 1; |
138 | } | 138 | } |
139 | 139 | ||
diff --git a/net/ipv4/netfilter/nf_nat_proto_udp.c b/net/ipv4/netfilter/nf_nat_proto_udp.c index a0af4fd95584..cbf1a61e2908 100644 --- a/net/ipv4/netfilter/nf_nat_proto_udp.c +++ b/net/ipv4/netfilter/nf_nat_proto_udp.c | |||
@@ -86,22 +86,22 @@ udp_unique_tuple(struct nf_conntrack_tuple *tuple, | |||
86 | } | 86 | } |
87 | 87 | ||
88 | static int | 88 | static int |
89 | udp_manip_pkt(struct sk_buff **pskb, | 89 | udp_manip_pkt(struct sk_buff *skb, |
90 | unsigned int iphdroff, | 90 | unsigned int iphdroff, |
91 | const struct nf_conntrack_tuple *tuple, | 91 | const struct nf_conntrack_tuple *tuple, |
92 | enum nf_nat_manip_type maniptype) | 92 | enum nf_nat_manip_type maniptype) |
93 | { | 93 | { |
94 | struct iphdr *iph = (struct iphdr *)((*pskb)->data + iphdroff); | 94 | struct iphdr *iph = (struct iphdr *)(skb->data + iphdroff); |
95 | struct udphdr *hdr; | 95 | struct udphdr *hdr; |
96 | unsigned int hdroff = iphdroff + iph->ihl*4; | 96 | unsigned int hdroff = iphdroff + iph->ihl*4; |
97 | __be32 oldip, newip; | 97 | __be32 oldip, newip; |
98 | __be16 *portptr, newport; | 98 | __be16 *portptr, newport; |
99 | 99 | ||
100 | if (!skb_make_writable(pskb, hdroff + sizeof(*hdr))) | 100 | if (!skb_make_writable(skb, hdroff + sizeof(*hdr))) |
101 | return 0; | 101 | return 0; |
102 | 102 | ||
103 | iph = (struct iphdr *)((*pskb)->data + iphdroff); | 103 | iph = (struct iphdr *)(skb->data + iphdroff); |
104 | hdr = (struct udphdr *)((*pskb)->data + hdroff); | 104 | hdr = (struct udphdr *)(skb->data + hdroff); |
105 | 105 | ||
106 | if (maniptype == IP_NAT_MANIP_SRC) { | 106 | if (maniptype == IP_NAT_MANIP_SRC) { |
107 | /* Get rid of src ip and src pt */ | 107 | /* Get rid of src ip and src pt */ |
@@ -116,9 +116,9 @@ udp_manip_pkt(struct sk_buff **pskb, | |||
116 | newport = tuple->dst.u.udp.port; | 116 | newport = tuple->dst.u.udp.port; |
117 | portptr = &hdr->dest; | 117 | portptr = &hdr->dest; |
118 | } | 118 | } |
119 | if (hdr->check || (*pskb)->ip_summed == CHECKSUM_PARTIAL) { | 119 | if (hdr->check || skb->ip_summed == CHECKSUM_PARTIAL) { |
120 | nf_proto_csum_replace4(&hdr->check, *pskb, oldip, newip, 1); | 120 | nf_proto_csum_replace4(&hdr->check, skb, oldip, newip, 1); |
121 | nf_proto_csum_replace2(&hdr->check, *pskb, *portptr, newport, | 121 | nf_proto_csum_replace2(&hdr->check, skb, *portptr, newport, |
122 | 0); | 122 | 0); |
123 | if (!hdr->check) | 123 | if (!hdr->check) |
124 | hdr->check = CSUM_MANGLED_0; | 124 | hdr->check = CSUM_MANGLED_0; |
diff --git a/net/ipv4/netfilter/nf_nat_proto_unknown.c b/net/ipv4/netfilter/nf_nat_proto_unknown.c index f50d0203f9c0..cfd2742e9706 100644 --- a/net/ipv4/netfilter/nf_nat_proto_unknown.c +++ b/net/ipv4/netfilter/nf_nat_proto_unknown.c | |||
@@ -37,7 +37,7 @@ static int unknown_unique_tuple(struct nf_conntrack_tuple *tuple, | |||
37 | } | 37 | } |
38 | 38 | ||
39 | static int | 39 | static int |
40 | unknown_manip_pkt(struct sk_buff **pskb, | 40 | unknown_manip_pkt(struct sk_buff *skb, |
41 | unsigned int iphdroff, | 41 | unsigned int iphdroff, |
42 | const struct nf_conntrack_tuple *tuple, | 42 | const struct nf_conntrack_tuple *tuple, |
43 | enum nf_nat_manip_type maniptype) | 43 | enum nf_nat_manip_type maniptype) |
diff --git a/net/ipv4/netfilter/nf_nat_rule.c b/net/ipv4/netfilter/nf_nat_rule.c index 76ec59ae524d..46b25ab5f78b 100644 --- a/net/ipv4/netfilter/nf_nat_rule.c +++ b/net/ipv4/netfilter/nf_nat_rule.c | |||
@@ -65,7 +65,7 @@ static struct xt_table nat_table = { | |||
65 | }; | 65 | }; |
66 | 66 | ||
67 | /* Source NAT */ | 67 | /* Source NAT */ |
68 | static unsigned int ipt_snat_target(struct sk_buff **pskb, | 68 | static unsigned int ipt_snat_target(struct sk_buff *skb, |
69 | const struct net_device *in, | 69 | const struct net_device *in, |
70 | const struct net_device *out, | 70 | const struct net_device *out, |
71 | unsigned int hooknum, | 71 | unsigned int hooknum, |
@@ -78,7 +78,7 @@ static unsigned int ipt_snat_target(struct sk_buff **pskb, | |||
78 | 78 | ||
79 | NF_CT_ASSERT(hooknum == NF_IP_POST_ROUTING); | 79 | NF_CT_ASSERT(hooknum == NF_IP_POST_ROUTING); |
80 | 80 | ||
81 | ct = nf_ct_get(*pskb, &ctinfo); | 81 | ct = nf_ct_get(skb, &ctinfo); |
82 | 82 | ||
83 | /* Connection must be valid and new. */ | 83 | /* Connection must be valid and new. */ |
84 | NF_CT_ASSERT(ct && (ctinfo == IP_CT_NEW || ctinfo == IP_CT_RELATED || | 84 | NF_CT_ASSERT(ct && (ctinfo == IP_CT_NEW || ctinfo == IP_CT_RELATED || |
@@ -107,7 +107,7 @@ static void warn_if_extra_mangle(__be32 dstip, __be32 srcip) | |||
107 | ip_rt_put(rt); | 107 | ip_rt_put(rt); |
108 | } | 108 | } |
109 | 109 | ||
110 | static unsigned int ipt_dnat_target(struct sk_buff **pskb, | 110 | static unsigned int ipt_dnat_target(struct sk_buff *skb, |
111 | const struct net_device *in, | 111 | const struct net_device *in, |
112 | const struct net_device *out, | 112 | const struct net_device *out, |
113 | unsigned int hooknum, | 113 | unsigned int hooknum, |
@@ -121,14 +121,14 @@ static unsigned int ipt_dnat_target(struct sk_buff **pskb, | |||
121 | NF_CT_ASSERT(hooknum == NF_IP_PRE_ROUTING || | 121 | NF_CT_ASSERT(hooknum == NF_IP_PRE_ROUTING || |
122 | hooknum == NF_IP_LOCAL_OUT); | 122 | hooknum == NF_IP_LOCAL_OUT); |
123 | 123 | ||
124 | ct = nf_ct_get(*pskb, &ctinfo); | 124 | ct = nf_ct_get(skb, &ctinfo); |
125 | 125 | ||
126 | /* Connection must be valid and new. */ | 126 | /* Connection must be valid and new. */ |
127 | NF_CT_ASSERT(ct && (ctinfo == IP_CT_NEW || ctinfo == IP_CT_RELATED)); | 127 | NF_CT_ASSERT(ct && (ctinfo == IP_CT_NEW || ctinfo == IP_CT_RELATED)); |
128 | 128 | ||
129 | if (hooknum == NF_IP_LOCAL_OUT && | 129 | if (hooknum == NF_IP_LOCAL_OUT && |
130 | mr->range[0].flags & IP_NAT_RANGE_MAP_IPS) | 130 | mr->range[0].flags & IP_NAT_RANGE_MAP_IPS) |
131 | warn_if_extra_mangle(ip_hdr(*pskb)->daddr, | 131 | warn_if_extra_mangle(ip_hdr(skb)->daddr, |
132 | mr->range[0].min_ip); | 132 | mr->range[0].min_ip); |
133 | 133 | ||
134 | return nf_nat_setup_info(ct, &mr->range[0], hooknum); | 134 | return nf_nat_setup_info(ct, &mr->range[0], hooknum); |
@@ -204,7 +204,7 @@ alloc_null_binding_confirmed(struct nf_conn *ct, unsigned int hooknum) | |||
204 | return nf_nat_setup_info(ct, &range, hooknum); | 204 | return nf_nat_setup_info(ct, &range, hooknum); |
205 | } | 205 | } |
206 | 206 | ||
207 | int nf_nat_rule_find(struct sk_buff **pskb, | 207 | int nf_nat_rule_find(struct sk_buff *skb, |
208 | unsigned int hooknum, | 208 | unsigned int hooknum, |
209 | const struct net_device *in, | 209 | const struct net_device *in, |
210 | const struct net_device *out, | 210 | const struct net_device *out, |
@@ -212,7 +212,7 @@ int nf_nat_rule_find(struct sk_buff **pskb, | |||
212 | { | 212 | { |
213 | int ret; | 213 | int ret; |
214 | 214 | ||
215 | ret = ipt_do_table(pskb, hooknum, in, out, &nat_table); | 215 | ret = ipt_do_table(skb, hooknum, in, out, &nat_table); |
216 | 216 | ||
217 | if (ret == NF_ACCEPT) { | 217 | if (ret == NF_ACCEPT) { |
218 | if (!nf_nat_initialized(ct, HOOK2MANIP(hooknum))) | 218 | if (!nf_nat_initialized(ct, HOOK2MANIP(hooknum))) |
diff --git a/net/ipv4/netfilter/nf_nat_sip.c b/net/ipv4/netfilter/nf_nat_sip.c index e14d41976c27..ce9edbcc01e3 100644 --- a/net/ipv4/netfilter/nf_nat_sip.c +++ b/net/ipv4/netfilter/nf_nat_sip.c | |||
@@ -60,7 +60,7 @@ static void addr_map_init(struct nf_conn *ct, struct addr_map *map) | |||
60 | } | 60 | } |
61 | } | 61 | } |
62 | 62 | ||
63 | static int map_sip_addr(struct sk_buff **pskb, enum ip_conntrack_info ctinfo, | 63 | static int map_sip_addr(struct sk_buff *skb, enum ip_conntrack_info ctinfo, |
64 | struct nf_conn *ct, const char **dptr, size_t dlen, | 64 | struct nf_conn *ct, const char **dptr, size_t dlen, |
65 | enum sip_header_pos pos, struct addr_map *map) | 65 | enum sip_header_pos pos, struct addr_map *map) |
66 | { | 66 | { |
@@ -84,15 +84,15 @@ static int map_sip_addr(struct sk_buff **pskb, enum ip_conntrack_info ctinfo, | |||
84 | } else | 84 | } else |
85 | return 1; | 85 | return 1; |
86 | 86 | ||
87 | if (!nf_nat_mangle_udp_packet(pskb, ct, ctinfo, | 87 | if (!nf_nat_mangle_udp_packet(skb, ct, ctinfo, |
88 | matchoff, matchlen, addr, addrlen)) | 88 | matchoff, matchlen, addr, addrlen)) |
89 | return 0; | 89 | return 0; |
90 | *dptr = (*pskb)->data + ip_hdrlen(*pskb) + sizeof(struct udphdr); | 90 | *dptr = skb->data + ip_hdrlen(skb) + sizeof(struct udphdr); |
91 | return 1; | 91 | return 1; |
92 | 92 | ||
93 | } | 93 | } |
94 | 94 | ||
95 | static unsigned int ip_nat_sip(struct sk_buff **pskb, | 95 | static unsigned int ip_nat_sip(struct sk_buff *skb, |
96 | enum ip_conntrack_info ctinfo, | 96 | enum ip_conntrack_info ctinfo, |
97 | struct nf_conn *ct, | 97 | struct nf_conn *ct, |
98 | const char **dptr) | 98 | const char **dptr) |
@@ -101,8 +101,8 @@ static unsigned int ip_nat_sip(struct sk_buff **pskb, | |||
101 | struct addr_map map; | 101 | struct addr_map map; |
102 | int dataoff, datalen; | 102 | int dataoff, datalen; |
103 | 103 | ||
104 | dataoff = ip_hdrlen(*pskb) + sizeof(struct udphdr); | 104 | dataoff = ip_hdrlen(skb) + sizeof(struct udphdr); |
105 | datalen = (*pskb)->len - dataoff; | 105 | datalen = skb->len - dataoff; |
106 | if (datalen < sizeof("SIP/2.0") - 1) | 106 | if (datalen < sizeof("SIP/2.0") - 1) |
107 | return NF_ACCEPT; | 107 | return NF_ACCEPT; |
108 | 108 | ||
@@ -121,19 +121,19 @@ static unsigned int ip_nat_sip(struct sk_buff **pskb, | |||
121 | else | 121 | else |
122 | pos = POS_REQ_URI; | 122 | pos = POS_REQ_URI; |
123 | 123 | ||
124 | if (!map_sip_addr(pskb, ctinfo, ct, dptr, datalen, pos, &map)) | 124 | if (!map_sip_addr(skb, ctinfo, ct, dptr, datalen, pos, &map)) |
125 | return NF_DROP; | 125 | return NF_DROP; |
126 | } | 126 | } |
127 | 127 | ||
128 | if (!map_sip_addr(pskb, ctinfo, ct, dptr, datalen, POS_FROM, &map) || | 128 | if (!map_sip_addr(skb, ctinfo, ct, dptr, datalen, POS_FROM, &map) || |
129 | !map_sip_addr(pskb, ctinfo, ct, dptr, datalen, POS_TO, &map) || | 129 | !map_sip_addr(skb, ctinfo, ct, dptr, datalen, POS_TO, &map) || |
130 | !map_sip_addr(pskb, ctinfo, ct, dptr, datalen, POS_VIA, &map) || | 130 | !map_sip_addr(skb, ctinfo, ct, dptr, datalen, POS_VIA, &map) || |
131 | !map_sip_addr(pskb, ctinfo, ct, dptr, datalen, POS_CONTACT, &map)) | 131 | !map_sip_addr(skb, ctinfo, ct, dptr, datalen, POS_CONTACT, &map)) |
132 | return NF_DROP; | 132 | return NF_DROP; |
133 | return NF_ACCEPT; | 133 | return NF_ACCEPT; |
134 | } | 134 | } |
135 | 135 | ||
136 | static unsigned int mangle_sip_packet(struct sk_buff **pskb, | 136 | static unsigned int mangle_sip_packet(struct sk_buff *skb, |
137 | enum ip_conntrack_info ctinfo, | 137 | enum ip_conntrack_info ctinfo, |
138 | struct nf_conn *ct, | 138 | struct nf_conn *ct, |
139 | const char **dptr, size_t dlen, | 139 | const char **dptr, size_t dlen, |
@@ -145,16 +145,16 @@ static unsigned int mangle_sip_packet(struct sk_buff **pskb, | |||
145 | if (ct_sip_get_info(ct, *dptr, dlen, &matchoff, &matchlen, pos) <= 0) | 145 | if (ct_sip_get_info(ct, *dptr, dlen, &matchoff, &matchlen, pos) <= 0) |
146 | return 0; | 146 | return 0; |
147 | 147 | ||
148 | if (!nf_nat_mangle_udp_packet(pskb, ct, ctinfo, | 148 | if (!nf_nat_mangle_udp_packet(skb, ct, ctinfo, |
149 | matchoff, matchlen, buffer, bufflen)) | 149 | matchoff, matchlen, buffer, bufflen)) |
150 | return 0; | 150 | return 0; |
151 | 151 | ||
152 | /* We need to reload this. Thanks Patrick. */ | 152 | /* We need to reload this. Thanks Patrick. */ |
153 | *dptr = (*pskb)->data + ip_hdrlen(*pskb) + sizeof(struct udphdr); | 153 | *dptr = skb->data + ip_hdrlen(skb) + sizeof(struct udphdr); |
154 | return 1; | 154 | return 1; |
155 | } | 155 | } |
156 | 156 | ||
157 | static int mangle_content_len(struct sk_buff **pskb, | 157 | static int mangle_content_len(struct sk_buff *skb, |
158 | enum ip_conntrack_info ctinfo, | 158 | enum ip_conntrack_info ctinfo, |
159 | struct nf_conn *ct, | 159 | struct nf_conn *ct, |
160 | const char *dptr) | 160 | const char *dptr) |
@@ -163,22 +163,22 @@ static int mangle_content_len(struct sk_buff **pskb, | |||
163 | char buffer[sizeof("65536")]; | 163 | char buffer[sizeof("65536")]; |
164 | int bufflen; | 164 | int bufflen; |
165 | 165 | ||
166 | dataoff = ip_hdrlen(*pskb) + sizeof(struct udphdr); | 166 | dataoff = ip_hdrlen(skb) + sizeof(struct udphdr); |
167 | 167 | ||
168 | /* Get actual SDP lenght */ | 168 | /* Get actual SDP lenght */ |
169 | if (ct_sip_get_info(ct, dptr, (*pskb)->len - dataoff, &matchoff, | 169 | if (ct_sip_get_info(ct, dptr, skb->len - dataoff, &matchoff, |
170 | &matchlen, POS_SDP_HEADER) > 0) { | 170 | &matchlen, POS_SDP_HEADER) > 0) { |
171 | 171 | ||
172 | /* since ct_sip_get_info() give us a pointer passing 'v=' | 172 | /* since ct_sip_get_info() give us a pointer passing 'v=' |
173 | we need to add 2 bytes in this count. */ | 173 | we need to add 2 bytes in this count. */ |
174 | int c_len = (*pskb)->len - dataoff - matchoff + 2; | 174 | int c_len = skb->len - dataoff - matchoff + 2; |
175 | 175 | ||
176 | /* Now, update SDP length */ | 176 | /* Now, update SDP length */ |
177 | if (ct_sip_get_info(ct, dptr, (*pskb)->len - dataoff, &matchoff, | 177 | if (ct_sip_get_info(ct, dptr, skb->len - dataoff, &matchoff, |
178 | &matchlen, POS_CONTENT) > 0) { | 178 | &matchlen, POS_CONTENT) > 0) { |
179 | 179 | ||
180 | bufflen = sprintf(buffer, "%u", c_len); | 180 | bufflen = sprintf(buffer, "%u", c_len); |
181 | return nf_nat_mangle_udp_packet(pskb, ct, ctinfo, | 181 | return nf_nat_mangle_udp_packet(skb, ct, ctinfo, |
182 | matchoff, matchlen, | 182 | matchoff, matchlen, |
183 | buffer, bufflen); | 183 | buffer, bufflen); |
184 | } | 184 | } |
@@ -186,7 +186,7 @@ static int mangle_content_len(struct sk_buff **pskb, | |||
186 | return 0; | 186 | return 0; |
187 | } | 187 | } |
188 | 188 | ||
189 | static unsigned int mangle_sdp(struct sk_buff **pskb, | 189 | static unsigned int mangle_sdp(struct sk_buff *skb, |
190 | enum ip_conntrack_info ctinfo, | 190 | enum ip_conntrack_info ctinfo, |
191 | struct nf_conn *ct, | 191 | struct nf_conn *ct, |
192 | __be32 newip, u_int16_t port, | 192 | __be32 newip, u_int16_t port, |
@@ -195,25 +195,25 @@ static unsigned int mangle_sdp(struct sk_buff **pskb, | |||
195 | char buffer[sizeof("nnn.nnn.nnn.nnn")]; | 195 | char buffer[sizeof("nnn.nnn.nnn.nnn")]; |
196 | unsigned int dataoff, bufflen; | 196 | unsigned int dataoff, bufflen; |
197 | 197 | ||
198 | dataoff = ip_hdrlen(*pskb) + sizeof(struct udphdr); | 198 | dataoff = ip_hdrlen(skb) + sizeof(struct udphdr); |
199 | 199 | ||
200 | /* Mangle owner and contact info. */ | 200 | /* Mangle owner and contact info. */ |
201 | bufflen = sprintf(buffer, "%u.%u.%u.%u", NIPQUAD(newip)); | 201 | bufflen = sprintf(buffer, "%u.%u.%u.%u", NIPQUAD(newip)); |
202 | if (!mangle_sip_packet(pskb, ctinfo, ct, &dptr, (*pskb)->len - dataoff, | 202 | if (!mangle_sip_packet(skb, ctinfo, ct, &dptr, skb->len - dataoff, |
203 | buffer, bufflen, POS_OWNER_IP4)) | 203 | buffer, bufflen, POS_OWNER_IP4)) |
204 | return 0; | 204 | return 0; |
205 | 205 | ||
206 | if (!mangle_sip_packet(pskb, ctinfo, ct, &dptr, (*pskb)->len - dataoff, | 206 | if (!mangle_sip_packet(skb, ctinfo, ct, &dptr, skb->len - dataoff, |
207 | buffer, bufflen, POS_CONNECTION_IP4)) | 207 | buffer, bufflen, POS_CONNECTION_IP4)) |
208 | return 0; | 208 | return 0; |
209 | 209 | ||
210 | /* Mangle media port. */ | 210 | /* Mangle media port. */ |
211 | bufflen = sprintf(buffer, "%u", port); | 211 | bufflen = sprintf(buffer, "%u", port); |
212 | if (!mangle_sip_packet(pskb, ctinfo, ct, &dptr, (*pskb)->len - dataoff, | 212 | if (!mangle_sip_packet(skb, ctinfo, ct, &dptr, skb->len - dataoff, |
213 | buffer, bufflen, POS_MEDIA)) | 213 | buffer, bufflen, POS_MEDIA)) |
214 | return 0; | 214 | return 0; |
215 | 215 | ||
216 | return mangle_content_len(pskb, ctinfo, ct, dptr); | 216 | return mangle_content_len(skb, ctinfo, ct, dptr); |
217 | } | 217 | } |
218 | 218 | ||
219 | static void ip_nat_sdp_expect(struct nf_conn *ct, | 219 | static void ip_nat_sdp_expect(struct nf_conn *ct, |
@@ -241,7 +241,7 @@ static void ip_nat_sdp_expect(struct nf_conn *ct, | |||
241 | 241 | ||
242 | /* So, this packet has hit the connection tracking matching code. | 242 | /* So, this packet has hit the connection tracking matching code. |
243 | Mangle it, and change the expectation to match the new version. */ | 243 | Mangle it, and change the expectation to match the new version. */ |
244 | static unsigned int ip_nat_sdp(struct sk_buff **pskb, | 244 | static unsigned int ip_nat_sdp(struct sk_buff *skb, |
245 | enum ip_conntrack_info ctinfo, | 245 | enum ip_conntrack_info ctinfo, |
246 | struct nf_conntrack_expect *exp, | 246 | struct nf_conntrack_expect *exp, |
247 | const char *dptr) | 247 | const char *dptr) |
@@ -277,7 +277,7 @@ static unsigned int ip_nat_sdp(struct sk_buff **pskb, | |||
277 | if (port == 0) | 277 | if (port == 0) |
278 | return NF_DROP; | 278 | return NF_DROP; |
279 | 279 | ||
280 | if (!mangle_sdp(pskb, ctinfo, ct, newip, port, dptr)) { | 280 | if (!mangle_sdp(skb, ctinfo, ct, newip, port, dptr)) { |
281 | nf_ct_unexpect_related(exp); | 281 | nf_ct_unexpect_related(exp); |
282 | return NF_DROP; | 282 | return NF_DROP; |
283 | } | 283 | } |
diff --git a/net/ipv4/netfilter/nf_nat_snmp_basic.c b/net/ipv4/netfilter/nf_nat_snmp_basic.c index 6bfcd3a90f08..03709d6b4b06 100644 --- a/net/ipv4/netfilter/nf_nat_snmp_basic.c +++ b/net/ipv4/netfilter/nf_nat_snmp_basic.c | |||
@@ -1188,9 +1188,9 @@ static int snmp_parse_mangle(unsigned char *msg, | |||
1188 | */ | 1188 | */ |
1189 | static int snmp_translate(struct nf_conn *ct, | 1189 | static int snmp_translate(struct nf_conn *ct, |
1190 | enum ip_conntrack_info ctinfo, | 1190 | enum ip_conntrack_info ctinfo, |
1191 | struct sk_buff **pskb) | 1191 | struct sk_buff *skb) |
1192 | { | 1192 | { |
1193 | struct iphdr *iph = ip_hdr(*pskb); | 1193 | struct iphdr *iph = ip_hdr(skb); |
1194 | struct udphdr *udph = (struct udphdr *)((__be32 *)iph + iph->ihl); | 1194 | struct udphdr *udph = (struct udphdr *)((__be32 *)iph + iph->ihl); |
1195 | u_int16_t udplen = ntohs(udph->len); | 1195 | u_int16_t udplen = ntohs(udph->len); |
1196 | u_int16_t paylen = udplen - sizeof(struct udphdr); | 1196 | u_int16_t paylen = udplen - sizeof(struct udphdr); |
@@ -1225,13 +1225,13 @@ static int snmp_translate(struct nf_conn *ct, | |||
1225 | 1225 | ||
1226 | /* We don't actually set up expectations, just adjust internal IP | 1226 | /* We don't actually set up expectations, just adjust internal IP |
1227 | * addresses if this is being NATted */ | 1227 | * addresses if this is being NATted */ |
1228 | static int help(struct sk_buff **pskb, unsigned int protoff, | 1228 | static int help(struct sk_buff *skb, unsigned int protoff, |
1229 | struct nf_conn *ct, | 1229 | struct nf_conn *ct, |
1230 | enum ip_conntrack_info ctinfo) | 1230 | enum ip_conntrack_info ctinfo) |
1231 | { | 1231 | { |
1232 | int dir = CTINFO2DIR(ctinfo); | 1232 | int dir = CTINFO2DIR(ctinfo); |
1233 | unsigned int ret; | 1233 | unsigned int ret; |
1234 | struct iphdr *iph = ip_hdr(*pskb); | 1234 | struct iphdr *iph = ip_hdr(skb); |
1235 | struct udphdr *udph = (struct udphdr *)((u_int32_t *)iph + iph->ihl); | 1235 | struct udphdr *udph = (struct udphdr *)((u_int32_t *)iph + iph->ihl); |
1236 | 1236 | ||
1237 | /* SNMP replies and originating SNMP traps get mangled */ | 1237 | /* SNMP replies and originating SNMP traps get mangled */ |
@@ -1250,7 +1250,7 @@ static int help(struct sk_buff **pskb, unsigned int protoff, | |||
1250 | * enough room for a UDP header. Just verify the UDP length field so we | 1250 | * enough room for a UDP header. Just verify the UDP length field so we |
1251 | * can mess around with the payload. | 1251 | * can mess around with the payload. |
1252 | */ | 1252 | */ |
1253 | if (ntohs(udph->len) != (*pskb)->len - (iph->ihl << 2)) { | 1253 | if (ntohs(udph->len) != skb->len - (iph->ihl << 2)) { |
1254 | if (net_ratelimit()) | 1254 | if (net_ratelimit()) |
1255 | printk(KERN_WARNING "SNMP: dropping malformed packet " | 1255 | printk(KERN_WARNING "SNMP: dropping malformed packet " |
1256 | "src=%u.%u.%u.%u dst=%u.%u.%u.%u\n", | 1256 | "src=%u.%u.%u.%u dst=%u.%u.%u.%u\n", |
@@ -1258,11 +1258,11 @@ static int help(struct sk_buff **pskb, unsigned int protoff, | |||
1258 | return NF_DROP; | 1258 | return NF_DROP; |
1259 | } | 1259 | } |
1260 | 1260 | ||
1261 | if (!skb_make_writable(pskb, (*pskb)->len)) | 1261 | if (!skb_make_writable(skb, skb->len)) |
1262 | return NF_DROP; | 1262 | return NF_DROP; |
1263 | 1263 | ||
1264 | spin_lock_bh(&snmp_lock); | 1264 | spin_lock_bh(&snmp_lock); |
1265 | ret = snmp_translate(ct, ctinfo, pskb); | 1265 | ret = snmp_translate(ct, ctinfo, skb); |
1266 | spin_unlock_bh(&snmp_lock); | 1266 | spin_unlock_bh(&snmp_lock); |
1267 | return ret; | 1267 | return ret; |
1268 | } | 1268 | } |
diff --git a/net/ipv4/netfilter/nf_nat_standalone.c b/net/ipv4/netfilter/nf_nat_standalone.c index 46cc99def165..7db76ea9af91 100644 --- a/net/ipv4/netfilter/nf_nat_standalone.c +++ b/net/ipv4/netfilter/nf_nat_standalone.c | |||
@@ -67,7 +67,7 @@ static void nat_decode_session(struct sk_buff *skb, struct flowi *fl) | |||
67 | 67 | ||
68 | static unsigned int | 68 | static unsigned int |
69 | nf_nat_fn(unsigned int hooknum, | 69 | nf_nat_fn(unsigned int hooknum, |
70 | struct sk_buff **pskb, | 70 | struct sk_buff *skb, |
71 | const struct net_device *in, | 71 | const struct net_device *in, |
72 | const struct net_device *out, | 72 | const struct net_device *out, |
73 | int (*okfn)(struct sk_buff *)) | 73 | int (*okfn)(struct sk_buff *)) |
@@ -80,9 +80,9 @@ nf_nat_fn(unsigned int hooknum, | |||
80 | 80 | ||
81 | /* We never see fragments: conntrack defrags on pre-routing | 81 | /* We never see fragments: conntrack defrags on pre-routing |
82 | and local-out, and nf_nat_out protects post-routing. */ | 82 | and local-out, and nf_nat_out protects post-routing. */ |
83 | NF_CT_ASSERT(!(ip_hdr(*pskb)->frag_off & htons(IP_MF | IP_OFFSET))); | 83 | NF_CT_ASSERT(!(ip_hdr(skb)->frag_off & htons(IP_MF | IP_OFFSET))); |
84 | 84 | ||
85 | ct = nf_ct_get(*pskb, &ctinfo); | 85 | ct = nf_ct_get(skb, &ctinfo); |
86 | /* Can't track? It's not due to stress, or conntrack would | 86 | /* Can't track? It's not due to stress, or conntrack would |
87 | have dropped it. Hence it's the user's responsibilty to | 87 | have dropped it. Hence it's the user's responsibilty to |
88 | packet filter it out, or implement conntrack/NAT for that | 88 | packet filter it out, or implement conntrack/NAT for that |
@@ -91,10 +91,10 @@ nf_nat_fn(unsigned int hooknum, | |||
91 | /* Exception: ICMP redirect to new connection (not in | 91 | /* Exception: ICMP redirect to new connection (not in |
92 | hash table yet). We must not let this through, in | 92 | hash table yet). We must not let this through, in |
93 | case we're doing NAT to the same network. */ | 93 | case we're doing NAT to the same network. */ |
94 | if (ip_hdr(*pskb)->protocol == IPPROTO_ICMP) { | 94 | if (ip_hdr(skb)->protocol == IPPROTO_ICMP) { |
95 | struct icmphdr _hdr, *hp; | 95 | struct icmphdr _hdr, *hp; |
96 | 96 | ||
97 | hp = skb_header_pointer(*pskb, ip_hdrlen(*pskb), | 97 | hp = skb_header_pointer(skb, ip_hdrlen(skb), |
98 | sizeof(_hdr), &_hdr); | 98 | sizeof(_hdr), &_hdr); |
99 | if (hp != NULL && | 99 | if (hp != NULL && |
100 | hp->type == ICMP_REDIRECT) | 100 | hp->type == ICMP_REDIRECT) |
@@ -119,9 +119,9 @@ nf_nat_fn(unsigned int hooknum, | |||
119 | switch (ctinfo) { | 119 | switch (ctinfo) { |
120 | case IP_CT_RELATED: | 120 | case IP_CT_RELATED: |
121 | case IP_CT_RELATED+IP_CT_IS_REPLY: | 121 | case IP_CT_RELATED+IP_CT_IS_REPLY: |
122 | if (ip_hdr(*pskb)->protocol == IPPROTO_ICMP) { | 122 | if (ip_hdr(skb)->protocol == IPPROTO_ICMP) { |
123 | if (!nf_nat_icmp_reply_translation(ct, ctinfo, | 123 | if (!nf_nat_icmp_reply_translation(ct, ctinfo, |
124 | hooknum, pskb)) | 124 | hooknum, skb)) |
125 | return NF_DROP; | 125 | return NF_DROP; |
126 | else | 126 | else |
127 | return NF_ACCEPT; | 127 | return NF_ACCEPT; |
@@ -141,7 +141,7 @@ nf_nat_fn(unsigned int hooknum, | |||
141 | /* LOCAL_IN hook doesn't have a chain! */ | 141 | /* LOCAL_IN hook doesn't have a chain! */ |
142 | ret = alloc_null_binding(ct, hooknum); | 142 | ret = alloc_null_binding(ct, hooknum); |
143 | else | 143 | else |
144 | ret = nf_nat_rule_find(pskb, hooknum, in, out, | 144 | ret = nf_nat_rule_find(skb, hooknum, in, out, |
145 | ct); | 145 | ct); |
146 | 146 | ||
147 | if (ret != NF_ACCEPT) { | 147 | if (ret != NF_ACCEPT) { |
@@ -159,31 +159,31 @@ nf_nat_fn(unsigned int hooknum, | |||
159 | ctinfo == (IP_CT_ESTABLISHED+IP_CT_IS_REPLY)); | 159 | ctinfo == (IP_CT_ESTABLISHED+IP_CT_IS_REPLY)); |
160 | } | 160 | } |
161 | 161 | ||
162 | return nf_nat_packet(ct, ctinfo, hooknum, pskb); | 162 | return nf_nat_packet(ct, ctinfo, hooknum, skb); |
163 | } | 163 | } |
164 | 164 | ||
165 | static unsigned int | 165 | static unsigned int |
166 | nf_nat_in(unsigned int hooknum, | 166 | nf_nat_in(unsigned int hooknum, |
167 | struct sk_buff **pskb, | 167 | struct sk_buff *skb, |
168 | const struct net_device *in, | 168 | const struct net_device *in, |
169 | const struct net_device *out, | 169 | const struct net_device *out, |
170 | int (*okfn)(struct sk_buff *)) | 170 | int (*okfn)(struct sk_buff *)) |
171 | { | 171 | { |
172 | unsigned int ret; | 172 | unsigned int ret; |
173 | __be32 daddr = ip_hdr(*pskb)->daddr; | 173 | __be32 daddr = ip_hdr(skb)->daddr; |
174 | 174 | ||
175 | ret = nf_nat_fn(hooknum, pskb, in, out, okfn); | 175 | ret = nf_nat_fn(hooknum, skb, in, out, okfn); |
176 | if (ret != NF_DROP && ret != NF_STOLEN && | 176 | if (ret != NF_DROP && ret != NF_STOLEN && |
177 | daddr != ip_hdr(*pskb)->daddr) { | 177 | daddr != ip_hdr(skb)->daddr) { |
178 | dst_release((*pskb)->dst); | 178 | dst_release(skb->dst); |
179 | (*pskb)->dst = NULL; | 179 | skb->dst = NULL; |
180 | } | 180 | } |
181 | return ret; | 181 | return ret; |
182 | } | 182 | } |
183 | 183 | ||
184 | static unsigned int | 184 | static unsigned int |
185 | nf_nat_out(unsigned int hooknum, | 185 | nf_nat_out(unsigned int hooknum, |
186 | struct sk_buff **pskb, | 186 | struct sk_buff *skb, |
187 | const struct net_device *in, | 187 | const struct net_device *in, |
188 | const struct net_device *out, | 188 | const struct net_device *out, |
189 | int (*okfn)(struct sk_buff *)) | 189 | int (*okfn)(struct sk_buff *)) |
@@ -195,14 +195,14 @@ nf_nat_out(unsigned int hooknum, | |||
195 | unsigned int ret; | 195 | unsigned int ret; |
196 | 196 | ||
197 | /* root is playing with raw sockets. */ | 197 | /* root is playing with raw sockets. */ |
198 | if ((*pskb)->len < sizeof(struct iphdr) || | 198 | if (skb->len < sizeof(struct iphdr) || |
199 | ip_hdrlen(*pskb) < sizeof(struct iphdr)) | 199 | ip_hdrlen(skb) < sizeof(struct iphdr)) |
200 | return NF_ACCEPT; | 200 | return NF_ACCEPT; |
201 | 201 | ||
202 | ret = nf_nat_fn(hooknum, pskb, in, out, okfn); | 202 | ret = nf_nat_fn(hooknum, skb, in, out, okfn); |
203 | #ifdef CONFIG_XFRM | 203 | #ifdef CONFIG_XFRM |
204 | if (ret != NF_DROP && ret != NF_STOLEN && | 204 | if (ret != NF_DROP && ret != NF_STOLEN && |
205 | (ct = nf_ct_get(*pskb, &ctinfo)) != NULL) { | 205 | (ct = nf_ct_get(skb, &ctinfo)) != NULL) { |
206 | enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo); | 206 | enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo); |
207 | 207 | ||
208 | if (ct->tuplehash[dir].tuple.src.u3.ip != | 208 | if (ct->tuplehash[dir].tuple.src.u3.ip != |
@@ -210,7 +210,7 @@ nf_nat_out(unsigned int hooknum, | |||
210 | || ct->tuplehash[dir].tuple.src.u.all != | 210 | || ct->tuplehash[dir].tuple.src.u.all != |
211 | ct->tuplehash[!dir].tuple.dst.u.all | 211 | ct->tuplehash[!dir].tuple.dst.u.all |
212 | ) | 212 | ) |
213 | return ip_xfrm_me_harder(pskb) == 0 ? ret : NF_DROP; | 213 | return ip_xfrm_me_harder(skb) == 0 ? ret : NF_DROP; |
214 | } | 214 | } |
215 | #endif | 215 | #endif |
216 | return ret; | 216 | return ret; |
@@ -218,7 +218,7 @@ nf_nat_out(unsigned int hooknum, | |||
218 | 218 | ||
219 | static unsigned int | 219 | static unsigned int |
220 | nf_nat_local_fn(unsigned int hooknum, | 220 | nf_nat_local_fn(unsigned int hooknum, |
221 | struct sk_buff **pskb, | 221 | struct sk_buff *skb, |
222 | const struct net_device *in, | 222 | const struct net_device *in, |
223 | const struct net_device *out, | 223 | const struct net_device *out, |
224 | int (*okfn)(struct sk_buff *)) | 224 | int (*okfn)(struct sk_buff *)) |
@@ -228,24 +228,24 @@ nf_nat_local_fn(unsigned int hooknum, | |||
228 | unsigned int ret; | 228 | unsigned int ret; |
229 | 229 | ||
230 | /* root is playing with raw sockets. */ | 230 | /* root is playing with raw sockets. */ |
231 | if ((*pskb)->len < sizeof(struct iphdr) || | 231 | if (skb->len < sizeof(struct iphdr) || |
232 | ip_hdrlen(*pskb) < sizeof(struct iphdr)) | 232 | ip_hdrlen(skb) < sizeof(struct iphdr)) |
233 | return NF_ACCEPT; | 233 | return NF_ACCEPT; |
234 | 234 | ||
235 | ret = nf_nat_fn(hooknum, pskb, in, out, okfn); | 235 | ret = nf_nat_fn(hooknum, skb, in, out, okfn); |
236 | if (ret != NF_DROP && ret != NF_STOLEN && | 236 | if (ret != NF_DROP && ret != NF_STOLEN && |
237 | (ct = nf_ct_get(*pskb, &ctinfo)) != NULL) { | 237 | (ct = nf_ct_get(skb, &ctinfo)) != NULL) { |
238 | enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo); | 238 | enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo); |
239 | 239 | ||
240 | if (ct->tuplehash[dir].tuple.dst.u3.ip != | 240 | if (ct->tuplehash[dir].tuple.dst.u3.ip != |
241 | ct->tuplehash[!dir].tuple.src.u3.ip) { | 241 | ct->tuplehash[!dir].tuple.src.u3.ip) { |
242 | if (ip_route_me_harder(pskb, RTN_UNSPEC)) | 242 | if (ip_route_me_harder(skb, RTN_UNSPEC)) |
243 | ret = NF_DROP; | 243 | ret = NF_DROP; |
244 | } | 244 | } |
245 | #ifdef CONFIG_XFRM | 245 | #ifdef CONFIG_XFRM |
246 | else if (ct->tuplehash[dir].tuple.dst.u.all != | 246 | else if (ct->tuplehash[dir].tuple.dst.u.all != |
247 | ct->tuplehash[!dir].tuple.src.u.all) | 247 | ct->tuplehash[!dir].tuple.src.u.all) |
248 | if (ip_xfrm_me_harder(pskb)) | 248 | if (ip_xfrm_me_harder(skb)) |
249 | ret = NF_DROP; | 249 | ret = NF_DROP; |
250 | #endif | 250 | #endif |
251 | } | 251 | } |
@@ -254,7 +254,7 @@ nf_nat_local_fn(unsigned int hooknum, | |||
254 | 254 | ||
255 | static unsigned int | 255 | static unsigned int |
256 | nf_nat_adjust(unsigned int hooknum, | 256 | nf_nat_adjust(unsigned int hooknum, |
257 | struct sk_buff **pskb, | 257 | struct sk_buff *skb, |
258 | const struct net_device *in, | 258 | const struct net_device *in, |
259 | const struct net_device *out, | 259 | const struct net_device *out, |
260 | int (*okfn)(struct sk_buff *)) | 260 | int (*okfn)(struct sk_buff *)) |
@@ -262,10 +262,10 @@ nf_nat_adjust(unsigned int hooknum, | |||
262 | struct nf_conn *ct; | 262 | struct nf_conn *ct; |
263 | enum ip_conntrack_info ctinfo; | 263 | enum ip_conntrack_info ctinfo; |
264 | 264 | ||
265 | ct = nf_ct_get(*pskb, &ctinfo); | 265 | ct = nf_ct_get(skb, &ctinfo); |
266 | if (ct && test_bit(IPS_SEQ_ADJUST_BIT, &ct->status)) { | 266 | if (ct && test_bit(IPS_SEQ_ADJUST_BIT, &ct->status)) { |
267 | pr_debug("nf_nat_standalone: adjusting sequence number\n"); | 267 | pr_debug("nf_nat_standalone: adjusting sequence number\n"); |
268 | if (!nf_nat_seq_adjust(pskb, ct, ctinfo)) | 268 | if (!nf_nat_seq_adjust(skb, ct, ctinfo)) |
269 | return NF_DROP; | 269 | return NF_DROP; |
270 | } | 270 | } |
271 | return NF_ACCEPT; | 271 | return NF_ACCEPT; |
diff --git a/net/ipv4/netfilter/nf_nat_tftp.c b/net/ipv4/netfilter/nf_nat_tftp.c index 04dfeaefec02..0ecec701cb44 100644 --- a/net/ipv4/netfilter/nf_nat_tftp.c +++ b/net/ipv4/netfilter/nf_nat_tftp.c | |||
@@ -20,7 +20,7 @@ MODULE_DESCRIPTION("TFTP NAT helper"); | |||
20 | MODULE_LICENSE("GPL"); | 20 | MODULE_LICENSE("GPL"); |
21 | MODULE_ALIAS("ip_nat_tftp"); | 21 | MODULE_ALIAS("ip_nat_tftp"); |
22 | 22 | ||
23 | static unsigned int help(struct sk_buff **pskb, | 23 | static unsigned int help(struct sk_buff *skb, |
24 | enum ip_conntrack_info ctinfo, | 24 | enum ip_conntrack_info ctinfo, |
25 | struct nf_conntrack_expect *exp) | 25 | struct nf_conntrack_expect *exp) |
26 | { | 26 | { |
diff --git a/net/ipv4/proc.c b/net/ipv4/proc.c index e5b05b039101..fd16cb8f8abe 100644 --- a/net/ipv4/proc.c +++ b/net/ipv4/proc.c | |||
@@ -70,8 +70,8 @@ static int sockstat_seq_show(struct seq_file *seq, void *v) | |||
70 | seq_printf(seq, "UDP: inuse %d\n", fold_prot_inuse(&udp_prot)); | 70 | seq_printf(seq, "UDP: inuse %d\n", fold_prot_inuse(&udp_prot)); |
71 | seq_printf(seq, "UDPLITE: inuse %d\n", fold_prot_inuse(&udplite_prot)); | 71 | seq_printf(seq, "UDPLITE: inuse %d\n", fold_prot_inuse(&udplite_prot)); |
72 | seq_printf(seq, "RAW: inuse %d\n", fold_prot_inuse(&raw_prot)); | 72 | seq_printf(seq, "RAW: inuse %d\n", fold_prot_inuse(&raw_prot)); |
73 | seq_printf(seq, "FRAG: inuse %d memory %d\n", ip_frag_nqueues, | 73 | seq_printf(seq, "FRAG: inuse %d memory %d\n", |
74 | atomic_read(&ip_frag_mem)); | 74 | ip_frag_nqueues(), ip_frag_mem()); |
75 | return 0; | 75 | return 0; |
76 | } | 76 | } |
77 | 77 | ||
diff --git a/net/ipv4/sysctl_net_ipv4.c b/net/ipv4/sysctl_net_ipv4.c index eb286abcf5dc..ffddd2b45352 100644 --- a/net/ipv4/sysctl_net_ipv4.c +++ b/net/ipv4/sysctl_net_ipv4.c | |||
@@ -19,6 +19,7 @@ | |||
19 | #include <net/route.h> | 19 | #include <net/route.h> |
20 | #include <net/tcp.h> | 20 | #include <net/tcp.h> |
21 | #include <net/cipso_ipv4.h> | 21 | #include <net/cipso_ipv4.h> |
22 | #include <net/inet_frag.h> | ||
22 | 23 | ||
23 | /* From af_inet.c */ | 24 | /* From af_inet.c */ |
24 | extern int sysctl_ip_nonlocal_bind; | 25 | extern int sysctl_ip_nonlocal_bind; |
@@ -121,7 +122,7 @@ static int ipv4_local_port_range(ctl_table *table, int write, struct file *filp, | |||
121 | ret = proc_dointvec_minmax(&tmp, write, filp, buffer, lenp, ppos); | 122 | ret = proc_dointvec_minmax(&tmp, write, filp, buffer, lenp, ppos); |
122 | 123 | ||
123 | if (write && ret == 0) { | 124 | if (write && ret == 0) { |
124 | if (range[1] <= range[0]) | 125 | if (range[1] < range[0]) |
125 | ret = -EINVAL; | 126 | ret = -EINVAL; |
126 | else | 127 | else |
127 | set_local_port_range(range); | 128 | set_local_port_range(range); |
@@ -149,7 +150,7 @@ static int ipv4_sysctl_local_port_range(ctl_table *table, int __user *name, | |||
149 | 150 | ||
150 | ret = sysctl_intvec(&tmp, name, nlen, oldval, oldlenp, newval, newlen); | 151 | ret = sysctl_intvec(&tmp, name, nlen, oldval, oldlenp, newval, newlen); |
151 | if (ret == 0 && newval && newlen) { | 152 | if (ret == 0 && newval && newlen) { |
152 | if (range[1] <= range[0]) | 153 | if (range[1] < range[0]) |
153 | ret = -EINVAL; | 154 | ret = -EINVAL; |
154 | else | 155 | else |
155 | set_local_port_range(range); | 156 | set_local_port_range(range); |
@@ -357,7 +358,7 @@ ctl_table ipv4_table[] = { | |||
357 | { | 358 | { |
358 | .ctl_name = NET_IPV4_IPFRAG_HIGH_THRESH, | 359 | .ctl_name = NET_IPV4_IPFRAG_HIGH_THRESH, |
359 | .procname = "ipfrag_high_thresh", | 360 | .procname = "ipfrag_high_thresh", |
360 | .data = &sysctl_ipfrag_high_thresh, | 361 | .data = &ip4_frags_ctl.high_thresh, |
361 | .maxlen = sizeof(int), | 362 | .maxlen = sizeof(int), |
362 | .mode = 0644, | 363 | .mode = 0644, |
363 | .proc_handler = &proc_dointvec | 364 | .proc_handler = &proc_dointvec |
@@ -365,7 +366,7 @@ ctl_table ipv4_table[] = { | |||
365 | { | 366 | { |
366 | .ctl_name = NET_IPV4_IPFRAG_LOW_THRESH, | 367 | .ctl_name = NET_IPV4_IPFRAG_LOW_THRESH, |
367 | .procname = "ipfrag_low_thresh", | 368 | .procname = "ipfrag_low_thresh", |
368 | .data = &sysctl_ipfrag_low_thresh, | 369 | .data = &ip4_frags_ctl.low_thresh, |
369 | .maxlen = sizeof(int), | 370 | .maxlen = sizeof(int), |
370 | .mode = 0644, | 371 | .mode = 0644, |
371 | .proc_handler = &proc_dointvec | 372 | .proc_handler = &proc_dointvec |
@@ -381,7 +382,7 @@ ctl_table ipv4_table[] = { | |||
381 | { | 382 | { |
382 | .ctl_name = NET_IPV4_IPFRAG_TIME, | 383 | .ctl_name = NET_IPV4_IPFRAG_TIME, |
383 | .procname = "ipfrag_time", | 384 | .procname = "ipfrag_time", |
384 | .data = &sysctl_ipfrag_time, | 385 | .data = &ip4_frags_ctl.timeout, |
385 | .maxlen = sizeof(int), | 386 | .maxlen = sizeof(int), |
386 | .mode = 0644, | 387 | .mode = 0644, |
387 | .proc_handler = &proc_dointvec_jiffies, | 388 | .proc_handler = &proc_dointvec_jiffies, |
@@ -732,14 +733,13 @@ ctl_table ipv4_table[] = { | |||
732 | { | 733 | { |
733 | .ctl_name = NET_IPV4_IPFRAG_SECRET_INTERVAL, | 734 | .ctl_name = NET_IPV4_IPFRAG_SECRET_INTERVAL, |
734 | .procname = "ipfrag_secret_interval", | 735 | .procname = "ipfrag_secret_interval", |
735 | .data = &sysctl_ipfrag_secret_interval, | 736 | .data = &ip4_frags_ctl.secret_interval, |
736 | .maxlen = sizeof(int), | 737 | .maxlen = sizeof(int), |
737 | .mode = 0644, | 738 | .mode = 0644, |
738 | .proc_handler = &proc_dointvec_jiffies, | 739 | .proc_handler = &proc_dointvec_jiffies, |
739 | .strategy = &sysctl_jiffies | 740 | .strategy = &sysctl_jiffies |
740 | }, | 741 | }, |
741 | { | 742 | { |
742 | .ctl_name = NET_IPV4_IPFRAG_MAX_DIST, | ||
743 | .procname = "ipfrag_max_dist", | 743 | .procname = "ipfrag_max_dist", |
744 | .data = &sysctl_ipfrag_max_dist, | 744 | .data = &sysctl_ipfrag_max_dist, |
745 | .maxlen = sizeof(int), | 745 | .maxlen = sizeof(int), |
@@ -864,7 +864,6 @@ ctl_table ipv4_table[] = { | |||
864 | }, | 864 | }, |
865 | #endif /* CONFIG_NETLABEL */ | 865 | #endif /* CONFIG_NETLABEL */ |
866 | { | 866 | { |
867 | .ctl_name = NET_TCP_AVAIL_CONG_CONTROL, | ||
868 | .procname = "tcp_available_congestion_control", | 867 | .procname = "tcp_available_congestion_control", |
869 | .maxlen = TCP_CA_BUF_MAX, | 868 | .maxlen = TCP_CA_BUF_MAX, |
870 | .mode = 0444, | 869 | .mode = 0444, |
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index 4f322003835d..2e6ad6dbba6c 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c | |||
@@ -1334,7 +1334,7 @@ do_prequeue: | |||
1334 | if ((flags & MSG_PEEK) && peek_seq != tp->copied_seq) { | 1334 | if ((flags & MSG_PEEK) && peek_seq != tp->copied_seq) { |
1335 | if (net_ratelimit()) | 1335 | if (net_ratelimit()) |
1336 | printk(KERN_DEBUG "TCP(%s:%d): Application bug, race in MSG_PEEK.\n", | 1336 | printk(KERN_DEBUG "TCP(%s:%d): Application bug, race in MSG_PEEK.\n", |
1337 | current->comm, current->pid); | 1337 | current->comm, task_pid_nr(current)); |
1338 | peek_seq = tp->copied_seq; | 1338 | peek_seq = tp->copied_seq; |
1339 | } | 1339 | } |
1340 | continue; | 1340 | continue; |
diff --git a/net/ipv4/tcp_diag.c b/net/ipv4/tcp_diag.c index 3904d2158a92..2fbcc7d1b1a0 100644 --- a/net/ipv4/tcp_diag.c +++ b/net/ipv4/tcp_diag.c | |||
@@ -56,3 +56,4 @@ static void __exit tcp_diag_exit(void) | |||
56 | module_init(tcp_diag_init); | 56 | module_init(tcp_diag_init); |
57 | module_exit(tcp_diag_exit); | 57 | module_exit(tcp_diag_exit); |
58 | MODULE_LICENSE("GPL"); | 58 | MODULE_LICENSE("GPL"); |
59 | MODULE_ALIAS_NET_PF_PROTO_TYPE(PF_NETLINK, NETLINK_INET_DIAG, TCPDIAG_GETSOCK); | ||
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index 0a42e9340346..9288220b73a8 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c | |||
@@ -1121,7 +1121,7 @@ static int tcp_mark_lost_retrans(struct sock *sk, u32 received_upto) | |||
1121 | struct sk_buff *skb; | 1121 | struct sk_buff *skb; |
1122 | int flag = 0; | 1122 | int flag = 0; |
1123 | int cnt = 0; | 1123 | int cnt = 0; |
1124 | u32 new_low_seq = 0; | 1124 | u32 new_low_seq = tp->snd_nxt; |
1125 | 1125 | ||
1126 | tcp_for_write_queue(skb, sk) { | 1126 | tcp_for_write_queue(skb, sk) { |
1127 | u32 ack_seq = TCP_SKB_CB(skb)->ack_seq; | 1127 | u32 ack_seq = TCP_SKB_CB(skb)->ack_seq; |
@@ -1153,7 +1153,7 @@ static int tcp_mark_lost_retrans(struct sock *sk, u32 received_upto) | |||
1153 | NET_INC_STATS_BH(LINUX_MIB_TCPLOSTRETRANSMIT); | 1153 | NET_INC_STATS_BH(LINUX_MIB_TCPLOSTRETRANSMIT); |
1154 | } | 1154 | } |
1155 | } else { | 1155 | } else { |
1156 | if (!new_low_seq || before(ack_seq, new_low_seq)) | 1156 | if (before(ack_seq, new_low_seq)) |
1157 | new_low_seq = ack_seq; | 1157 | new_low_seq = ack_seq; |
1158 | cnt += tcp_skb_pcount(skb); | 1158 | cnt += tcp_skb_pcount(skb); |
1159 | } | 1159 | } |
@@ -1242,7 +1242,7 @@ tcp_sacktag_write_queue(struct sock *sk, struct sk_buff *ack_skb, u32 prior_snd_ | |||
1242 | int num_sacks = (ptr[1] - TCPOLEN_SACK_BASE)>>3; | 1242 | int num_sacks = (ptr[1] - TCPOLEN_SACK_BASE)>>3; |
1243 | int reord = tp->packets_out; | 1243 | int reord = tp->packets_out; |
1244 | int prior_fackets; | 1244 | int prior_fackets; |
1245 | u32 highest_sack_end_seq = 0; | 1245 | u32 highest_sack_end_seq = tp->lost_retrans_low; |
1246 | int flag = 0; | 1246 | int flag = 0; |
1247 | int found_dup_sack = 0; | 1247 | int found_dup_sack = 0; |
1248 | int cached_fack_count; | 1248 | int cached_fack_count; |
@@ -1995,8 +1995,7 @@ static void tcp_verify_retransmit_hint(struct tcp_sock *tp, | |||
1995 | } | 1995 | } |
1996 | 1996 | ||
1997 | /* Mark head of queue up as lost. */ | 1997 | /* Mark head of queue up as lost. */ |
1998 | static void tcp_mark_head_lost(struct sock *sk, | 1998 | static void tcp_mark_head_lost(struct sock *sk, int packets) |
1999 | int packets, u32 high_seq) | ||
2000 | { | 1999 | { |
2001 | struct tcp_sock *tp = tcp_sk(sk); | 2000 | struct tcp_sock *tp = tcp_sk(sk); |
2002 | struct sk_buff *skb; | 2001 | struct sk_buff *skb; |
@@ -2019,7 +2018,7 @@ static void tcp_mark_head_lost(struct sock *sk, | |||
2019 | tp->lost_skb_hint = skb; | 2018 | tp->lost_skb_hint = skb; |
2020 | tp->lost_cnt_hint = cnt; | 2019 | tp->lost_cnt_hint = cnt; |
2021 | cnt += tcp_skb_pcount(skb); | 2020 | cnt += tcp_skb_pcount(skb); |
2022 | if (cnt > packets || after(TCP_SKB_CB(skb)->end_seq, high_seq)) | 2021 | if (cnt > packets || after(TCP_SKB_CB(skb)->end_seq, tp->high_seq)) |
2023 | break; | 2022 | break; |
2024 | if (!(TCP_SKB_CB(skb)->sacked & (TCPCB_SACKED_ACKED|TCPCB_LOST))) { | 2023 | if (!(TCP_SKB_CB(skb)->sacked & (TCPCB_SACKED_ACKED|TCPCB_LOST))) { |
2025 | TCP_SKB_CB(skb)->sacked |= TCPCB_LOST; | 2024 | TCP_SKB_CB(skb)->sacked |= TCPCB_LOST; |
@@ -2040,9 +2039,9 @@ static void tcp_update_scoreboard(struct sock *sk) | |||
2040 | int lost = tp->fackets_out - tp->reordering; | 2039 | int lost = tp->fackets_out - tp->reordering; |
2041 | if (lost <= 0) | 2040 | if (lost <= 0) |
2042 | lost = 1; | 2041 | lost = 1; |
2043 | tcp_mark_head_lost(sk, lost, tp->high_seq); | 2042 | tcp_mark_head_lost(sk, lost); |
2044 | } else { | 2043 | } else { |
2045 | tcp_mark_head_lost(sk, 1, tp->high_seq); | 2044 | tcp_mark_head_lost(sk, 1); |
2046 | } | 2045 | } |
2047 | 2046 | ||
2048 | /* New heuristics: it is possible only after we switched | 2047 | /* New heuristics: it is possible only after we switched |
@@ -2381,7 +2380,7 @@ tcp_fastretrans_alert(struct sock *sk, int pkts_acked, int flag) | |||
2381 | before(tp->snd_una, tp->high_seq) && | 2380 | before(tp->snd_una, tp->high_seq) && |
2382 | icsk->icsk_ca_state != TCP_CA_Open && | 2381 | icsk->icsk_ca_state != TCP_CA_Open && |
2383 | tp->fackets_out > tp->reordering) { | 2382 | tp->fackets_out > tp->reordering) { |
2384 | tcp_mark_head_lost(sk, tp->fackets_out-tp->reordering, tp->high_seq); | 2383 | tcp_mark_head_lost(sk, tp->fackets_out - tp->reordering); |
2385 | NET_INC_STATS_BH(LINUX_MIB_TCPLOSS); | 2384 | NET_INC_STATS_BH(LINUX_MIB_TCPLOSS); |
2386 | } | 2385 | } |
2387 | 2386 | ||
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index cb9fc58efb2f..35d2b0e9e10b 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c | |||
@@ -147,13 +147,14 @@ int __udp_lib_get_port(struct sock *sk, unsigned short snum, | |||
147 | write_lock_bh(&udp_hash_lock); | 147 | write_lock_bh(&udp_hash_lock); |
148 | 148 | ||
149 | if (!snum) { | 149 | if (!snum) { |
150 | int i, low, high; | 150 | int i, low, high, remaining; |
151 | unsigned rover, best, best_size_so_far; | 151 | unsigned rover, best, best_size_so_far; |
152 | 152 | ||
153 | inet_get_local_port_range(&low, &high); | 153 | inet_get_local_port_range(&low, &high); |
154 | remaining = (high - low) + 1; | ||
154 | 155 | ||
155 | best_size_so_far = UINT_MAX; | 156 | best_size_so_far = UINT_MAX; |
156 | best = rover = net_random() % (high - low) + low; | 157 | best = rover = net_random() % remaining + low; |
157 | 158 | ||
158 | /* 1st pass: look for empty (or shortest) hash chain */ | 159 | /* 1st pass: look for empty (or shortest) hash chain */ |
159 | for (i = 0; i < UDP_HTABLE_SIZE; i++) { | 160 | for (i = 0; i < UDP_HTABLE_SIZE; i++) { |
diff --git a/net/ipv4/xfrm4_input.c b/net/ipv4/xfrm4_input.c index e9bbfde19ac3..5e95c8a07efb 100644 --- a/net/ipv4/xfrm4_input.c +++ b/net/ipv4/xfrm4_input.c | |||
@@ -16,19 +16,6 @@ | |||
16 | #include <net/ip.h> | 16 | #include <net/ip.h> |
17 | #include <net/xfrm.h> | 17 | #include <net/xfrm.h> |
18 | 18 | ||
19 | static int xfrm4_parse_spi(struct sk_buff *skb, u8 nexthdr, __be32 *spi, __be32 *seq) | ||
20 | { | ||
21 | switch (nexthdr) { | ||
22 | case IPPROTO_IPIP: | ||
23 | case IPPROTO_IPV6: | ||
24 | *spi = ip_hdr(skb)->saddr; | ||
25 | *seq = 0; | ||
26 | return 0; | ||
27 | } | ||
28 | |||
29 | return xfrm_parse_spi(skb, nexthdr, spi, seq); | ||
30 | } | ||
31 | |||
32 | #ifdef CONFIG_NETFILTER | 19 | #ifdef CONFIG_NETFILTER |
33 | static inline int xfrm4_rcv_encap_finish(struct sk_buff *skb) | 20 | static inline int xfrm4_rcv_encap_finish(struct sk_buff *skb) |
34 | { | 21 | { |
@@ -46,28 +33,29 @@ drop: | |||
46 | } | 33 | } |
47 | #endif | 34 | #endif |
48 | 35 | ||
49 | static int xfrm4_rcv_encap(struct sk_buff *skb, __u16 encap_type) | 36 | int xfrm4_rcv_encap(struct sk_buff *skb, int nexthdr, __be32 spi, |
37 | int encap_type) | ||
50 | { | 38 | { |
51 | __be32 spi, seq; | 39 | int err; |
40 | __be32 seq; | ||
52 | struct xfrm_state *xfrm_vec[XFRM_MAX_DEPTH]; | 41 | struct xfrm_state *xfrm_vec[XFRM_MAX_DEPTH]; |
53 | struct xfrm_state *x; | 42 | struct xfrm_state *x; |
54 | int xfrm_nr = 0; | 43 | int xfrm_nr = 0; |
55 | int decaps = 0; | 44 | int decaps = 0; |
56 | int err = xfrm4_parse_spi(skb, ip_hdr(skb)->protocol, &spi, &seq); | ||
57 | unsigned int nhoff = offsetof(struct iphdr, protocol); | 45 | unsigned int nhoff = offsetof(struct iphdr, protocol); |
58 | 46 | ||
59 | if (err != 0) | 47 | seq = 0; |
48 | if (!spi && (err = xfrm_parse_spi(skb, nexthdr, &spi, &seq)) != 0) | ||
60 | goto drop; | 49 | goto drop; |
61 | 50 | ||
62 | do { | 51 | do { |
63 | const struct iphdr *iph = ip_hdr(skb); | 52 | const struct iphdr *iph = ip_hdr(skb); |
64 | int nexthdr; | ||
65 | 53 | ||
66 | if (xfrm_nr == XFRM_MAX_DEPTH) | 54 | if (xfrm_nr == XFRM_MAX_DEPTH) |
67 | goto drop; | 55 | goto drop; |
68 | 56 | ||
69 | x = xfrm_state_lookup((xfrm_address_t *)&iph->daddr, spi, | 57 | x = xfrm_state_lookup((xfrm_address_t *)&iph->daddr, spi, |
70 | iph->protocol != IPPROTO_IPV6 ? iph->protocol : IPPROTO_IPIP, AF_INET); | 58 | nexthdr, AF_INET); |
71 | if (x == NULL) | 59 | if (x == NULL) |
72 | goto drop; | 60 | goto drop; |
73 | 61 | ||
@@ -103,15 +91,15 @@ static int xfrm4_rcv_encap(struct sk_buff *skb, __u16 encap_type) | |||
103 | 91 | ||
104 | xfrm_vec[xfrm_nr++] = x; | 92 | xfrm_vec[xfrm_nr++] = x; |
105 | 93 | ||
106 | if (x->mode->input(x, skb)) | 94 | if (x->outer_mode->input(x, skb)) |
107 | goto drop; | 95 | goto drop; |
108 | 96 | ||
109 | if (x->props.mode == XFRM_MODE_TUNNEL) { | 97 | if (x->outer_mode->flags & XFRM_MODE_FLAG_TUNNEL) { |
110 | decaps = 1; | 98 | decaps = 1; |
111 | break; | 99 | break; |
112 | } | 100 | } |
113 | 101 | ||
114 | err = xfrm_parse_spi(skb, ip_hdr(skb)->protocol, &spi, &seq); | 102 | err = xfrm_parse_spi(skb, nexthdr, &spi, &seq); |
115 | if (err < 0) | 103 | if (err < 0) |
116 | goto drop; | 104 | goto drop; |
117 | } while (!err); | 105 | } while (!err); |
@@ -165,6 +153,7 @@ drop: | |||
165 | kfree_skb(skb); | 153 | kfree_skb(skb); |
166 | return 0; | 154 | return 0; |
167 | } | 155 | } |
156 | EXPORT_SYMBOL(xfrm4_rcv_encap); | ||
168 | 157 | ||
169 | /* If it's a keepalive packet, then just eat it. | 158 | /* If it's a keepalive packet, then just eat it. |
170 | * If it's an encapsulated packet, then pass it to the | 159 | * If it's an encapsulated packet, then pass it to the |
@@ -252,11 +241,8 @@ int xfrm4_udp_encap_rcv(struct sock *sk, struct sk_buff *skb) | |||
252 | __skb_pull(skb, len); | 241 | __skb_pull(skb, len); |
253 | skb_reset_transport_header(skb); | 242 | skb_reset_transport_header(skb); |
254 | 243 | ||
255 | /* modify the protocol (it's ESP!) */ | ||
256 | iph->protocol = IPPROTO_ESP; | ||
257 | |||
258 | /* process ESP */ | 244 | /* process ESP */ |
259 | ret = xfrm4_rcv_encap(skb, encap_type); | 245 | ret = xfrm4_rcv_encap(skb, IPPROTO_ESP, 0, encap_type); |
260 | return ret; | 246 | return ret; |
261 | 247 | ||
262 | drop: | 248 | drop: |
@@ -266,7 +252,7 @@ drop: | |||
266 | 252 | ||
267 | int xfrm4_rcv(struct sk_buff *skb) | 253 | int xfrm4_rcv(struct sk_buff *skb) |
268 | { | 254 | { |
269 | return xfrm4_rcv_encap(skb, 0); | 255 | return xfrm4_rcv_spi(skb, ip_hdr(skb)->protocol, 0); |
270 | } | 256 | } |
271 | 257 | ||
272 | EXPORT_SYMBOL(xfrm4_rcv); | 258 | EXPORT_SYMBOL(xfrm4_rcv); |
diff --git a/net/ipv4/xfrm4_mode_beet.c b/net/ipv4/xfrm4_mode_beet.c index 73d2338bec55..e42e122414be 100644 --- a/net/ipv4/xfrm4_mode_beet.c +++ b/net/ipv4/xfrm4_mode_beet.c | |||
@@ -114,6 +114,7 @@ static struct xfrm_mode xfrm4_beet_mode = { | |||
114 | .output = xfrm4_beet_output, | 114 | .output = xfrm4_beet_output, |
115 | .owner = THIS_MODULE, | 115 | .owner = THIS_MODULE, |
116 | .encap = XFRM_MODE_BEET, | 116 | .encap = XFRM_MODE_BEET, |
117 | .flags = XFRM_MODE_FLAG_TUNNEL, | ||
117 | }; | 118 | }; |
118 | 119 | ||
119 | static int __init xfrm4_beet_init(void) | 120 | static int __init xfrm4_beet_init(void) |
diff --git a/net/ipv4/xfrm4_mode_tunnel.c b/net/ipv4/xfrm4_mode_tunnel.c index 1ae9d32276f0..e4deecba6dd2 100644 --- a/net/ipv4/xfrm4_mode_tunnel.c +++ b/net/ipv4/xfrm4_mode_tunnel.c | |||
@@ -139,6 +139,7 @@ static struct xfrm_mode xfrm4_tunnel_mode = { | |||
139 | .output = xfrm4_tunnel_output, | 139 | .output = xfrm4_tunnel_output, |
140 | .owner = THIS_MODULE, | 140 | .owner = THIS_MODULE, |
141 | .encap = XFRM_MODE_TUNNEL, | 141 | .encap = XFRM_MODE_TUNNEL, |
142 | .flags = XFRM_MODE_FLAG_TUNNEL, | ||
142 | }; | 143 | }; |
143 | 144 | ||
144 | static int __init xfrm4_tunnel_init(void) | 145 | static int __init xfrm4_tunnel_init(void) |
diff --git a/net/ipv4/xfrm4_output.c b/net/ipv4/xfrm4_output.c index 434ef302ba83..c4a7156962bd 100644 --- a/net/ipv4/xfrm4_output.c +++ b/net/ipv4/xfrm4_output.c | |||
@@ -47,7 +47,7 @@ static inline int xfrm4_output_one(struct sk_buff *skb) | |||
47 | struct iphdr *iph; | 47 | struct iphdr *iph; |
48 | int err; | 48 | int err; |
49 | 49 | ||
50 | if (x->props.mode == XFRM_MODE_TUNNEL) { | 50 | if (x->outer_mode->flags & XFRM_MODE_FLAG_TUNNEL) { |
51 | err = xfrm4_tunnel_check_size(skb); | 51 | err = xfrm4_tunnel_check_size(skb); |
52 | if (err) | 52 | if (err) |
53 | goto error_nolock; | 53 | goto error_nolock; |
@@ -78,7 +78,7 @@ static int xfrm4_output_finish2(struct sk_buff *skb) | |||
78 | while (likely((err = xfrm4_output_one(skb)) == 0)) { | 78 | while (likely((err = xfrm4_output_one(skb)) == 0)) { |
79 | nf_reset(skb); | 79 | nf_reset(skb); |
80 | 80 | ||
81 | err = nf_hook(PF_INET, NF_IP_LOCAL_OUT, &skb, NULL, | 81 | err = nf_hook(PF_INET, NF_IP_LOCAL_OUT, skb, NULL, |
82 | skb->dst->dev, dst_output); | 82 | skb->dst->dev, dst_output); |
83 | if (unlikely(err != 1)) | 83 | if (unlikely(err != 1)) |
84 | break; | 84 | break; |
@@ -86,7 +86,7 @@ static int xfrm4_output_finish2(struct sk_buff *skb) | |||
86 | if (!skb->dst->xfrm) | 86 | if (!skb->dst->xfrm) |
87 | return dst_output(skb); | 87 | return dst_output(skb); |
88 | 88 | ||
89 | err = nf_hook(PF_INET, NF_IP_POST_ROUTING, &skb, NULL, | 89 | err = nf_hook(PF_INET, NF_IP_POST_ROUTING, skb, NULL, |
90 | skb->dst->dev, xfrm4_output_finish2); | 90 | skb->dst->dev, xfrm4_output_finish2); |
91 | if (unlikely(err != 1)) | 91 | if (unlikely(err != 1)) |
92 | break; | 92 | break; |
diff --git a/net/ipv4/xfrm4_policy.c b/net/ipv4/xfrm4_policy.c index 329825ca68fe..cc86fb110dd8 100644 --- a/net/ipv4/xfrm4_policy.c +++ b/net/ipv4/xfrm4_policy.c | |||
@@ -117,7 +117,7 @@ __xfrm4_bundle_create(struct xfrm_policy *policy, struct xfrm_state **xfrm, int | |||
117 | header_len += xfrm[i]->props.header_len; | 117 | header_len += xfrm[i]->props.header_len; |
118 | trailer_len += xfrm[i]->props.trailer_len; | 118 | trailer_len += xfrm[i]->props.trailer_len; |
119 | 119 | ||
120 | if (xfrm[i]->props.mode == XFRM_MODE_TUNNEL) { | 120 | if (xfrm[i]->props.mode != XFRM_MODE_TRANSPORT) { |
121 | unsigned short encap_family = xfrm[i]->props.family; | 121 | unsigned short encap_family = xfrm[i]->props.family; |
122 | switch (encap_family) { | 122 | switch (encap_family) { |
123 | case AF_INET: | 123 | case AF_INET: |
@@ -151,7 +151,6 @@ __xfrm4_bundle_create(struct xfrm_policy *policy, struct xfrm_state **xfrm, int | |||
151 | i = 0; | 151 | i = 0; |
152 | for (; dst_prev != &rt->u.dst; dst_prev = dst_prev->child) { | 152 | for (; dst_prev != &rt->u.dst; dst_prev = dst_prev->child) { |
153 | struct xfrm_dst *x = (struct xfrm_dst*)dst_prev; | 153 | struct xfrm_dst *x = (struct xfrm_dst*)dst_prev; |
154 | struct xfrm_state_afinfo *afinfo; | ||
155 | x->u.rt.fl = *fl; | 154 | x->u.rt.fl = *fl; |
156 | 155 | ||
157 | dst_prev->xfrm = xfrm[i++]; | 156 | dst_prev->xfrm = xfrm[i++]; |
@@ -169,27 +168,17 @@ __xfrm4_bundle_create(struct xfrm_policy *policy, struct xfrm_state **xfrm, int | |||
169 | /* Copy neighbout for reachability confirmation */ | 168 | /* Copy neighbout for reachability confirmation */ |
170 | dst_prev->neighbour = neigh_clone(rt->u.dst.neighbour); | 169 | dst_prev->neighbour = neigh_clone(rt->u.dst.neighbour); |
171 | dst_prev->input = rt->u.dst.input; | 170 | dst_prev->input = rt->u.dst.input; |
172 | /* XXX: When IPv6 module can be unloaded, we should manage reference | 171 | dst_prev->output = dst_prev->xfrm->outer_mode->afinfo->output; |
173 | * to xfrm6_output in afinfo->output. Miyazawa | 172 | if (rt0->peer) |
174 | * */ | 173 | atomic_inc(&rt0->peer->refcnt); |
175 | afinfo = xfrm_state_get_afinfo(dst_prev->xfrm->props.family); | 174 | x->u.rt.peer = rt0->peer; |
176 | if (!afinfo) { | ||
177 | dst = *dst_p; | ||
178 | err = -EAFNOSUPPORT; | ||
179 | goto error; | ||
180 | } | ||
181 | dst_prev->output = afinfo->output; | ||
182 | xfrm_state_put_afinfo(afinfo); | ||
183 | if (dst_prev->xfrm->props.family == AF_INET && rt->peer) | ||
184 | atomic_inc(&rt->peer->refcnt); | ||
185 | x->u.rt.peer = rt->peer; | ||
186 | /* Sheit... I remember I did this right. Apparently, | 175 | /* Sheit... I remember I did this right. Apparently, |
187 | * it was magically lost, so this code needs audit */ | 176 | * it was magically lost, so this code needs audit */ |
188 | x->u.rt.rt_flags = rt0->rt_flags&(RTCF_BROADCAST|RTCF_MULTICAST|RTCF_LOCAL); | 177 | x->u.rt.rt_flags = rt0->rt_flags&(RTCF_BROADCAST|RTCF_MULTICAST|RTCF_LOCAL); |
189 | x->u.rt.rt_type = rt->rt_type; | 178 | x->u.rt.rt_type = rt0->rt_type; |
190 | x->u.rt.rt_src = rt0->rt_src; | 179 | x->u.rt.rt_src = rt0->rt_src; |
191 | x->u.rt.rt_dst = rt0->rt_dst; | 180 | x->u.rt.rt_dst = rt0->rt_dst; |
192 | x->u.rt.rt_gateway = rt->rt_gateway; | 181 | x->u.rt.rt_gateway = rt0->rt_gateway; |
193 | x->u.rt.rt_spec_dst = rt0->rt_spec_dst; | 182 | x->u.rt.rt_spec_dst = rt0->rt_spec_dst; |
194 | x->u.rt.idev = rt0->idev; | 183 | x->u.rt.idev = rt0->idev; |
195 | in_dev_hold(rt0->idev); | 184 | in_dev_hold(rt0->idev); |
@@ -291,7 +280,7 @@ static void xfrm4_dst_destroy(struct dst_entry *dst) | |||
291 | 280 | ||
292 | if (likely(xdst->u.rt.idev)) | 281 | if (likely(xdst->u.rt.idev)) |
293 | in_dev_put(xdst->u.rt.idev); | 282 | in_dev_put(xdst->u.rt.idev); |
294 | if (dst->xfrm && dst->xfrm->props.family == AF_INET && likely(xdst->u.rt.peer)) | 283 | if (likely(xdst->u.rt.peer)) |
295 | inet_putpeer(xdst->u.rt.peer); | 284 | inet_putpeer(xdst->u.rt.peer); |
296 | xfrm_dst_destroy(xdst); | 285 | xfrm_dst_destroy(xdst); |
297 | } | 286 | } |
diff --git a/net/ipv4/xfrm4_state.c b/net/ipv4/xfrm4_state.c index 93e2c061cdda..13d54a1c3337 100644 --- a/net/ipv4/xfrm4_state.c +++ b/net/ipv4/xfrm4_state.c | |||
@@ -49,6 +49,7 @@ __xfrm4_init_tempsel(struct xfrm_state *x, struct flowi *fl, | |||
49 | 49 | ||
50 | static struct xfrm_state_afinfo xfrm4_state_afinfo = { | 50 | static struct xfrm_state_afinfo xfrm4_state_afinfo = { |
51 | .family = AF_INET, | 51 | .family = AF_INET, |
52 | .owner = THIS_MODULE, | ||
52 | .init_flags = xfrm4_init_flags, | 53 | .init_flags = xfrm4_init_flags, |
53 | .init_tempsel = __xfrm4_init_tempsel, | 54 | .init_tempsel = __xfrm4_init_tempsel, |
54 | .output = xfrm4_output, | 55 | .output = xfrm4_output, |
diff --git a/net/ipv4/xfrm4_tunnel.c b/net/ipv4/xfrm4_tunnel.c index 1312417608e2..326845195620 100644 --- a/net/ipv4/xfrm4_tunnel.c +++ b/net/ipv4/xfrm4_tunnel.c | |||
@@ -18,7 +18,7 @@ static int ipip_output(struct xfrm_state *x, struct sk_buff *skb) | |||
18 | 18 | ||
19 | static int ipip_xfrm_rcv(struct xfrm_state *x, struct sk_buff *skb) | 19 | static int ipip_xfrm_rcv(struct xfrm_state *x, struct sk_buff *skb) |
20 | { | 20 | { |
21 | return IPPROTO_IP; | 21 | return ip_hdr(skb)->protocol; |
22 | } | 22 | } |
23 | 23 | ||
24 | static int ipip_init_state(struct xfrm_state *x) | 24 | static int ipip_init_state(struct xfrm_state *x) |
@@ -48,20 +48,25 @@ static struct xfrm_type ipip_type = { | |||
48 | .output = ipip_output | 48 | .output = ipip_output |
49 | }; | 49 | }; |
50 | 50 | ||
51 | static int xfrm_tunnel_rcv(struct sk_buff *skb) | ||
52 | { | ||
53 | return xfrm4_rcv_spi(skb, IPPROTO_IP, ip_hdr(skb)->saddr); | ||
54 | } | ||
55 | |||
51 | static int xfrm_tunnel_err(struct sk_buff *skb, u32 info) | 56 | static int xfrm_tunnel_err(struct sk_buff *skb, u32 info) |
52 | { | 57 | { |
53 | return -ENOENT; | 58 | return -ENOENT; |
54 | } | 59 | } |
55 | 60 | ||
56 | static struct xfrm_tunnel xfrm_tunnel_handler = { | 61 | static struct xfrm_tunnel xfrm_tunnel_handler = { |
57 | .handler = xfrm4_rcv, | 62 | .handler = xfrm_tunnel_rcv, |
58 | .err_handler = xfrm_tunnel_err, | 63 | .err_handler = xfrm_tunnel_err, |
59 | .priority = 2, | 64 | .priority = 2, |
60 | }; | 65 | }; |
61 | 66 | ||
62 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) | 67 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) |
63 | static struct xfrm_tunnel xfrm64_tunnel_handler = { | 68 | static struct xfrm_tunnel xfrm64_tunnel_handler = { |
64 | .handler = xfrm4_rcv, | 69 | .handler = xfrm_tunnel_rcv, |
65 | .err_handler = xfrm_tunnel_err, | 70 | .err_handler = xfrm_tunnel_err, |
66 | .priority = 2, | 71 | .priority = 2, |
67 | }; | 72 | }; |
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index 52d10d213217..348bd8d06112 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c | |||
@@ -255,11 +255,6 @@ static void addrconf_mod_timer(struct inet6_ifaddr *ifp, | |||
255 | 255 | ||
256 | static int snmp6_alloc_dev(struct inet6_dev *idev) | 256 | static int snmp6_alloc_dev(struct inet6_dev *idev) |
257 | { | 257 | { |
258 | int err = -ENOMEM; | ||
259 | |||
260 | if (!idev || !idev->dev) | ||
261 | return -EINVAL; | ||
262 | |||
263 | if (snmp_mib_init((void **)idev->stats.ipv6, | 258 | if (snmp_mib_init((void **)idev->stats.ipv6, |
264 | sizeof(struct ipstats_mib), | 259 | sizeof(struct ipstats_mib), |
265 | __alignof__(struct ipstats_mib)) < 0) | 260 | __alignof__(struct ipstats_mib)) < 0) |
@@ -280,15 +275,14 @@ err_icmpmsg: | |||
280 | err_icmp: | 275 | err_icmp: |
281 | snmp_mib_free((void **)idev->stats.ipv6); | 276 | snmp_mib_free((void **)idev->stats.ipv6); |
282 | err_ip: | 277 | err_ip: |
283 | return err; | 278 | return -ENOMEM; |
284 | } | 279 | } |
285 | 280 | ||
286 | static int snmp6_free_dev(struct inet6_dev *idev) | 281 | static void snmp6_free_dev(struct inet6_dev *idev) |
287 | { | 282 | { |
288 | snmp_mib_free((void **)idev->stats.icmpv6msg); | 283 | snmp_mib_free((void **)idev->stats.icmpv6msg); |
289 | snmp_mib_free((void **)idev->stats.icmpv6); | 284 | snmp_mib_free((void **)idev->stats.icmpv6); |
290 | snmp_mib_free((void **)idev->stats.ipv6); | 285 | snmp_mib_free((void **)idev->stats.ipv6); |
291 | return 0; | ||
292 | } | 286 | } |
293 | 287 | ||
294 | /* Nobody refers to this device, we may destroy it. */ | 288 | /* Nobody refers to this device, we may destroy it. */ |
diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c index bc929381fa46..1b1caf3aa1c1 100644 --- a/net/ipv6/af_inet6.c +++ b/net/ipv6/af_inet6.c | |||
@@ -747,6 +747,7 @@ static void cleanup_ipv6_mibs(void) | |||
747 | { | 747 | { |
748 | snmp_mib_free((void **)ipv6_statistics); | 748 | snmp_mib_free((void **)ipv6_statistics); |
749 | snmp_mib_free((void **)icmpv6_statistics); | 749 | snmp_mib_free((void **)icmpv6_statistics); |
750 | snmp_mib_free((void **)icmpv6msg_statistics); | ||
750 | snmp_mib_free((void **)udp_stats_in6); | 751 | snmp_mib_free((void **)udp_stats_in6); |
751 | snmp_mib_free((void **)udplite_stats_in6); | 752 | snmp_mib_free((void **)udplite_stats_in6); |
752 | } | 753 | } |
diff --git a/net/ipv6/ah6.c b/net/ipv6/ah6.c index f9f689162692..66a9139d46e9 100644 --- a/net/ipv6/ah6.c +++ b/net/ipv6/ah6.c | |||
@@ -344,6 +344,8 @@ static int ah6_input(struct xfrm_state *x, struct sk_buff *skb) | |||
344 | pskb_expand_head(skb, 0, 0, GFP_ATOMIC)) | 344 | pskb_expand_head(skb, 0, 0, GFP_ATOMIC)) |
345 | goto out; | 345 | goto out; |
346 | 346 | ||
347 | skb->ip_summed = CHECKSUM_NONE; | ||
348 | |||
347 | hdr_len = skb->data - skb_network_header(skb); | 349 | hdr_len = skb->data - skb_network_header(skb); |
348 | ah = (struct ip_auth_hdr *)skb->data; | 350 | ah = (struct ip_auth_hdr *)skb->data; |
349 | ahp = x->data; | 351 | ahp = x->data; |
@@ -475,8 +477,16 @@ static int ah6_init_state(struct xfrm_state *x) | |||
475 | 477 | ||
476 | x->props.header_len = XFRM_ALIGN8(sizeof(struct ip_auth_hdr) + | 478 | x->props.header_len = XFRM_ALIGN8(sizeof(struct ip_auth_hdr) + |
477 | ahp->icv_trunc_len); | 479 | ahp->icv_trunc_len); |
478 | if (x->props.mode == XFRM_MODE_TUNNEL) | 480 | switch (x->props.mode) { |
481 | case XFRM_MODE_BEET: | ||
482 | case XFRM_MODE_TRANSPORT: | ||
483 | break; | ||
484 | case XFRM_MODE_TUNNEL: | ||
479 | x->props.header_len += sizeof(struct ipv6hdr); | 485 | x->props.header_len += sizeof(struct ipv6hdr); |
486 | break; | ||
487 | default: | ||
488 | goto error; | ||
489 | } | ||
480 | x->data = ahp; | 490 | x->data = ahp; |
481 | 491 | ||
482 | return 0; | 492 | return 0; |
diff --git a/net/ipv6/esp6.c b/net/ipv6/esp6.c index 9eb928598351..72a659806cad 100644 --- a/net/ipv6/esp6.c +++ b/net/ipv6/esp6.c | |||
@@ -354,8 +354,16 @@ static int esp6_init_state(struct xfrm_state *x) | |||
354 | (x->ealg->alg_key_len + 7) / 8)) | 354 | (x->ealg->alg_key_len + 7) / 8)) |
355 | goto error; | 355 | goto error; |
356 | x->props.header_len = sizeof(struct ip_esp_hdr) + esp->conf.ivlen; | 356 | x->props.header_len = sizeof(struct ip_esp_hdr) + esp->conf.ivlen; |
357 | if (x->props.mode == XFRM_MODE_TUNNEL) | 357 | switch (x->props.mode) { |
358 | case XFRM_MODE_BEET: | ||
359 | case XFRM_MODE_TRANSPORT: | ||
360 | break; | ||
361 | case XFRM_MODE_TUNNEL: | ||
358 | x->props.header_len += sizeof(struct ipv6hdr); | 362 | x->props.header_len += sizeof(struct ipv6hdr); |
363 | break; | ||
364 | default: | ||
365 | goto error; | ||
366 | } | ||
359 | x->data = esp; | 367 | x->data = esp; |
360 | return 0; | 368 | return 0; |
361 | 369 | ||
diff --git a/net/ipv6/exthdrs.c b/net/ipv6/exthdrs.c index c82d4d49f71f..1e89efd38a0c 100644 --- a/net/ipv6/exthdrs.c +++ b/net/ipv6/exthdrs.c | |||
@@ -102,7 +102,7 @@ EXPORT_SYMBOL_GPL(ipv6_find_tlv); | |||
102 | 102 | ||
103 | struct tlvtype_proc { | 103 | struct tlvtype_proc { |
104 | int type; | 104 | int type; |
105 | int (*func)(struct sk_buff **skbp, int offset); | 105 | int (*func)(struct sk_buff *skb, int offset); |
106 | }; | 106 | }; |
107 | 107 | ||
108 | /********************* | 108 | /********************* |
@@ -111,10 +111,8 @@ struct tlvtype_proc { | |||
111 | 111 | ||
112 | /* An unknown option is detected, decide what to do */ | 112 | /* An unknown option is detected, decide what to do */ |
113 | 113 | ||
114 | static int ip6_tlvopt_unknown(struct sk_buff **skbp, int optoff) | 114 | static int ip6_tlvopt_unknown(struct sk_buff *skb, int optoff) |
115 | { | 115 | { |
116 | struct sk_buff *skb = *skbp; | ||
117 | |||
118 | switch ((skb_network_header(skb)[optoff] & 0xC0) >> 6) { | 116 | switch ((skb_network_header(skb)[optoff] & 0xC0) >> 6) { |
119 | case 0: /* ignore */ | 117 | case 0: /* ignore */ |
120 | return 1; | 118 | return 1; |
@@ -139,9 +137,8 @@ static int ip6_tlvopt_unknown(struct sk_buff **skbp, int optoff) | |||
139 | 137 | ||
140 | /* Parse tlv encoded option header (hop-by-hop or destination) */ | 138 | /* Parse tlv encoded option header (hop-by-hop or destination) */ |
141 | 139 | ||
142 | static int ip6_parse_tlv(struct tlvtype_proc *procs, struct sk_buff **skbp) | 140 | static int ip6_parse_tlv(struct tlvtype_proc *procs, struct sk_buff *skb) |
143 | { | 141 | { |
144 | struct sk_buff *skb = *skbp; | ||
145 | struct tlvtype_proc *curr; | 142 | struct tlvtype_proc *curr; |
146 | const unsigned char *nh = skb_network_header(skb); | 143 | const unsigned char *nh = skb_network_header(skb); |
147 | int off = skb_network_header_len(skb); | 144 | int off = skb_network_header_len(skb); |
@@ -172,13 +169,13 @@ static int ip6_parse_tlv(struct tlvtype_proc *procs, struct sk_buff **skbp) | |||
172 | /* type specific length/alignment | 169 | /* type specific length/alignment |
173 | checks will be performed in the | 170 | checks will be performed in the |
174 | func(). */ | 171 | func(). */ |
175 | if (curr->func(skbp, off) == 0) | 172 | if (curr->func(skb, off) == 0) |
176 | return 0; | 173 | return 0; |
177 | break; | 174 | break; |
178 | } | 175 | } |
179 | } | 176 | } |
180 | if (curr->type < 0) { | 177 | if (curr->type < 0) { |
181 | if (ip6_tlvopt_unknown(skbp, off) == 0) | 178 | if (ip6_tlvopt_unknown(skb, off) == 0) |
182 | return 0; | 179 | return 0; |
183 | } | 180 | } |
184 | break; | 181 | break; |
@@ -198,9 +195,8 @@ bad: | |||
198 | *****************************/ | 195 | *****************************/ |
199 | 196 | ||
200 | #if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE) | 197 | #if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE) |
201 | static int ipv6_dest_hao(struct sk_buff **skbp, int optoff) | 198 | static int ipv6_dest_hao(struct sk_buff *skb, int optoff) |
202 | { | 199 | { |
203 | struct sk_buff *skb = *skbp; | ||
204 | struct ipv6_destopt_hao *hao; | 200 | struct ipv6_destopt_hao *hao; |
205 | struct inet6_skb_parm *opt = IP6CB(skb); | 201 | struct inet6_skb_parm *opt = IP6CB(skb); |
206 | struct ipv6hdr *ipv6h = ipv6_hdr(skb); | 202 | struct ipv6hdr *ipv6h = ipv6_hdr(skb); |
@@ -234,22 +230,13 @@ static int ipv6_dest_hao(struct sk_buff **skbp, int optoff) | |||
234 | goto discard; | 230 | goto discard; |
235 | 231 | ||
236 | if (skb_cloned(skb)) { | 232 | if (skb_cloned(skb)) { |
237 | struct sk_buff *skb2 = skb_copy(skb, GFP_ATOMIC); | 233 | if (pskb_expand_head(skb, 0, 0, GFP_ATOMIC)) |
238 | struct inet6_skb_parm *opt2; | ||
239 | |||
240 | if (skb2 == NULL) | ||
241 | goto discard; | 234 | goto discard; |
242 | 235 | ||
243 | opt2 = IP6CB(skb2); | ||
244 | memcpy(opt2, opt, sizeof(*opt2)); | ||
245 | |||
246 | kfree_skb(skb); | ||
247 | |||
248 | /* update all variable using below by copied skbuff */ | 236 | /* update all variable using below by copied skbuff */ |
249 | *skbp = skb = skb2; | 237 | hao = (struct ipv6_destopt_hao *)(skb_network_header(skb) + |
250 | hao = (struct ipv6_destopt_hao *)(skb_network_header(skb2) + | ||
251 | optoff); | 238 | optoff); |
252 | ipv6h = ipv6_hdr(skb2); | 239 | ipv6h = ipv6_hdr(skb); |
253 | } | 240 | } |
254 | 241 | ||
255 | if (skb->ip_summed == CHECKSUM_COMPLETE) | 242 | if (skb->ip_summed == CHECKSUM_COMPLETE) |
@@ -280,9 +267,8 @@ static struct tlvtype_proc tlvprocdestopt_lst[] = { | |||
280 | {-1, NULL} | 267 | {-1, NULL} |
281 | }; | 268 | }; |
282 | 269 | ||
283 | static int ipv6_destopt_rcv(struct sk_buff **skbp) | 270 | static int ipv6_destopt_rcv(struct sk_buff *skb) |
284 | { | 271 | { |
285 | struct sk_buff *skb = *skbp; | ||
286 | struct inet6_skb_parm *opt = IP6CB(skb); | 272 | struct inet6_skb_parm *opt = IP6CB(skb); |
287 | #if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE) | 273 | #if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE) |
288 | __u16 dstbuf; | 274 | __u16 dstbuf; |
@@ -304,9 +290,8 @@ static int ipv6_destopt_rcv(struct sk_buff **skbp) | |||
304 | #endif | 290 | #endif |
305 | 291 | ||
306 | dst = dst_clone(skb->dst); | 292 | dst = dst_clone(skb->dst); |
307 | if (ip6_parse_tlv(tlvprocdestopt_lst, skbp)) { | 293 | if (ip6_parse_tlv(tlvprocdestopt_lst, skb)) { |
308 | dst_release(dst); | 294 | dst_release(dst); |
309 | skb = *skbp; | ||
310 | skb->transport_header += (skb_transport_header(skb)[1] + 1) << 3; | 295 | skb->transport_header += (skb_transport_header(skb)[1] + 1) << 3; |
311 | opt = IP6CB(skb); | 296 | opt = IP6CB(skb); |
312 | #if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE) | 297 | #if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE) |
@@ -337,10 +322,8 @@ void __init ipv6_destopt_init(void) | |||
337 | NONE header. No data in packet. | 322 | NONE header. No data in packet. |
338 | ********************************/ | 323 | ********************************/ |
339 | 324 | ||
340 | static int ipv6_nodata_rcv(struct sk_buff **skbp) | 325 | static int ipv6_nodata_rcv(struct sk_buff *skb) |
341 | { | 326 | { |
342 | struct sk_buff *skb = *skbp; | ||
343 | |||
344 | kfree_skb(skb); | 327 | kfree_skb(skb); |
345 | return 0; | 328 | return 0; |
346 | } | 329 | } |
@@ -360,9 +343,8 @@ void __init ipv6_nodata_init(void) | |||
360 | Routing header. | 343 | Routing header. |
361 | ********************************/ | 344 | ********************************/ |
362 | 345 | ||
363 | static int ipv6_rthdr_rcv(struct sk_buff **skbp) | 346 | static int ipv6_rthdr_rcv(struct sk_buff *skb) |
364 | { | 347 | { |
365 | struct sk_buff *skb = *skbp; | ||
366 | struct inet6_skb_parm *opt = IP6CB(skb); | 348 | struct inet6_skb_parm *opt = IP6CB(skb); |
367 | struct in6_addr *addr = NULL; | 349 | struct in6_addr *addr = NULL; |
368 | struct in6_addr daddr; | 350 | struct in6_addr daddr; |
@@ -464,18 +446,14 @@ looped_back: | |||
464 | Do not damage packets queued somewhere. | 446 | Do not damage packets queued somewhere. |
465 | */ | 447 | */ |
466 | if (skb_cloned(skb)) { | 448 | if (skb_cloned(skb)) { |
467 | struct sk_buff *skb2 = skb_copy(skb, GFP_ATOMIC); | ||
468 | /* the copy is a forwarded packet */ | 449 | /* the copy is a forwarded packet */ |
469 | if (skb2 == NULL) { | 450 | if (pskb_expand_head(skb, 0, 0, GFP_ATOMIC)) { |
470 | IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), | 451 | IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), |
471 | IPSTATS_MIB_OUTDISCARDS); | 452 | IPSTATS_MIB_OUTDISCARDS); |
472 | kfree_skb(skb); | 453 | kfree_skb(skb); |
473 | return -1; | 454 | return -1; |
474 | } | 455 | } |
475 | kfree_skb(skb); | 456 | hdr = (struct ipv6_rt_hdr *)skb_transport_header(skb); |
476 | *skbp = skb = skb2; | ||
477 | opt = IP6CB(skb2); | ||
478 | hdr = (struct ipv6_rt_hdr *)skb_transport_header(skb2); | ||
479 | } | 457 | } |
480 | 458 | ||
481 | if (skb->ip_summed == CHECKSUM_COMPLETE) | 459 | if (skb->ip_summed == CHECKSUM_COMPLETE) |
@@ -578,9 +556,8 @@ static inline struct inet6_dev *ipv6_skb_idev(struct sk_buff *skb) | |||
578 | 556 | ||
579 | /* Router Alert as of RFC 2711 */ | 557 | /* Router Alert as of RFC 2711 */ |
580 | 558 | ||
581 | static int ipv6_hop_ra(struct sk_buff **skbp, int optoff) | 559 | static int ipv6_hop_ra(struct sk_buff *skb, int optoff) |
582 | { | 560 | { |
583 | struct sk_buff *skb = *skbp; | ||
584 | const unsigned char *nh = skb_network_header(skb); | 561 | const unsigned char *nh = skb_network_header(skb); |
585 | 562 | ||
586 | if (nh[optoff + 1] == 2) { | 563 | if (nh[optoff + 1] == 2) { |
@@ -595,9 +572,8 @@ static int ipv6_hop_ra(struct sk_buff **skbp, int optoff) | |||
595 | 572 | ||
596 | /* Jumbo payload */ | 573 | /* Jumbo payload */ |
597 | 574 | ||
598 | static int ipv6_hop_jumbo(struct sk_buff **skbp, int optoff) | 575 | static int ipv6_hop_jumbo(struct sk_buff *skb, int optoff) |
599 | { | 576 | { |
600 | struct sk_buff *skb = *skbp; | ||
601 | const unsigned char *nh = skb_network_header(skb); | 577 | const unsigned char *nh = skb_network_header(skb); |
602 | u32 pkt_len; | 578 | u32 pkt_len; |
603 | 579 | ||
@@ -648,9 +624,8 @@ static struct tlvtype_proc tlvprochopopt_lst[] = { | |||
648 | { -1, } | 624 | { -1, } |
649 | }; | 625 | }; |
650 | 626 | ||
651 | int ipv6_parse_hopopts(struct sk_buff **skbp) | 627 | int ipv6_parse_hopopts(struct sk_buff *skb) |
652 | { | 628 | { |
653 | struct sk_buff *skb = *skbp; | ||
654 | struct inet6_skb_parm *opt = IP6CB(skb); | 629 | struct inet6_skb_parm *opt = IP6CB(skb); |
655 | 630 | ||
656 | /* | 631 | /* |
@@ -667,8 +642,7 @@ int ipv6_parse_hopopts(struct sk_buff **skbp) | |||
667 | } | 642 | } |
668 | 643 | ||
669 | opt->hop = sizeof(struct ipv6hdr); | 644 | opt->hop = sizeof(struct ipv6hdr); |
670 | if (ip6_parse_tlv(tlvprochopopt_lst, skbp)) { | 645 | if (ip6_parse_tlv(tlvprochopopt_lst, skb)) { |
671 | skb = *skbp; | ||
672 | skb->transport_header += (skb_transport_header(skb)[1] + 1) << 3; | 646 | skb->transport_header += (skb_transport_header(skb)[1] + 1) << 3; |
673 | opt = IP6CB(skb); | 647 | opt = IP6CB(skb); |
674 | opt->nhoff = sizeof(struct ipv6hdr); | 648 | opt->nhoff = sizeof(struct ipv6hdr); |
diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c index 47b8ce232e84..9bb031fa1c2f 100644 --- a/net/ipv6/icmp.c +++ b/net/ipv6/icmp.c | |||
@@ -82,7 +82,7 @@ EXPORT_SYMBOL(icmpv6msg_statistics); | |||
82 | static DEFINE_PER_CPU(struct socket *, __icmpv6_socket) = NULL; | 82 | static DEFINE_PER_CPU(struct socket *, __icmpv6_socket) = NULL; |
83 | #define icmpv6_socket __get_cpu_var(__icmpv6_socket) | 83 | #define icmpv6_socket __get_cpu_var(__icmpv6_socket) |
84 | 84 | ||
85 | static int icmpv6_rcv(struct sk_buff **pskb); | 85 | static int icmpv6_rcv(struct sk_buff *skb); |
86 | 86 | ||
87 | static struct inet6_protocol icmpv6_protocol = { | 87 | static struct inet6_protocol icmpv6_protocol = { |
88 | .handler = icmpv6_rcv, | 88 | .handler = icmpv6_rcv, |
@@ -614,9 +614,8 @@ static void icmpv6_notify(struct sk_buff *skb, int type, int code, __be32 info) | |||
614 | * Handle icmp messages | 614 | * Handle icmp messages |
615 | */ | 615 | */ |
616 | 616 | ||
617 | static int icmpv6_rcv(struct sk_buff **pskb) | 617 | static int icmpv6_rcv(struct sk_buff *skb) |
618 | { | 618 | { |
619 | struct sk_buff *skb = *pskb; | ||
620 | struct net_device *dev = skb->dev; | 619 | struct net_device *dev = skb->dev; |
621 | struct inet6_dev *idev = __in6_dev_get(dev); | 620 | struct inet6_dev *idev = __in6_dev_get(dev); |
622 | struct in6_addr *saddr, *daddr; | 621 | struct in6_addr *saddr, *daddr; |
diff --git a/net/ipv6/inet6_connection_sock.c b/net/ipv6/inet6_connection_sock.c index 25b931709749..78de42ada844 100644 --- a/net/ipv6/inet6_connection_sock.c +++ b/net/ipv6/inet6_connection_sock.c | |||
@@ -146,7 +146,7 @@ void __inet6_csk_dst_store(struct sock *sk, struct dst_entry *dst, | |||
146 | __ip6_dst_store(sk, dst, daddr, saddr); | 146 | __ip6_dst_store(sk, dst, daddr, saddr); |
147 | 147 | ||
148 | #ifdef CONFIG_XFRM | 148 | #ifdef CONFIG_XFRM |
149 | if (dst) { | 149 | { |
150 | struct rt6_info *rt = (struct rt6_info *)dst; | 150 | struct rt6_info *rt = (struct rt6_info *)dst; |
151 | rt->rt6i_flow_cache_genid = atomic_read(&flow_cache_genid); | 151 | rt->rt6i_flow_cache_genid = atomic_read(&flow_cache_genid); |
152 | } | 152 | } |
diff --git a/net/ipv6/inet6_hashtables.c b/net/ipv6/inet6_hashtables.c index 1c2c27655435..d6f1026f1943 100644 --- a/net/ipv6/inet6_hashtables.c +++ b/net/ipv6/inet6_hashtables.c | |||
@@ -261,7 +261,7 @@ int inet6_hash_connect(struct inet_timewait_death_row *death_row, | |||
261 | struct inet_timewait_sock *tw = NULL; | 261 | struct inet_timewait_sock *tw = NULL; |
262 | 262 | ||
263 | inet_get_local_port_range(&low, &high); | 263 | inet_get_local_port_range(&low, &high); |
264 | remaining = high - low; | 264 | remaining = (high - low) + 1; |
265 | 265 | ||
266 | local_bh_disable(); | 266 | local_bh_disable(); |
267 | for (i = 1; i <= remaining; i++) { | 267 | for (i = 1; i <= remaining; i++) { |
diff --git a/net/ipv6/ip6_flowlabel.c b/net/ipv6/ip6_flowlabel.c index 217d60f9fc80..b12cc22e7745 100644 --- a/net/ipv6/ip6_flowlabel.c +++ b/net/ipv6/ip6_flowlabel.c | |||
@@ -154,8 +154,10 @@ static void ip6_fl_gc(unsigned long dummy) | |||
154 | write_unlock(&ip6_fl_lock); | 154 | write_unlock(&ip6_fl_lock); |
155 | } | 155 | } |
156 | 156 | ||
157 | static int fl_intern(struct ip6_flowlabel *fl, __be32 label) | 157 | static struct ip6_flowlabel *fl_intern(struct ip6_flowlabel *fl, __be32 label) |
158 | { | 158 | { |
159 | struct ip6_flowlabel *lfl; | ||
160 | |||
159 | fl->label = label & IPV6_FLOWLABEL_MASK; | 161 | fl->label = label & IPV6_FLOWLABEL_MASK; |
160 | 162 | ||
161 | write_lock_bh(&ip6_fl_lock); | 163 | write_lock_bh(&ip6_fl_lock); |
@@ -163,12 +165,26 @@ static int fl_intern(struct ip6_flowlabel *fl, __be32 label) | |||
163 | for (;;) { | 165 | for (;;) { |
164 | fl->label = htonl(net_random())&IPV6_FLOWLABEL_MASK; | 166 | fl->label = htonl(net_random())&IPV6_FLOWLABEL_MASK; |
165 | if (fl->label) { | 167 | if (fl->label) { |
166 | struct ip6_flowlabel *lfl; | ||
167 | lfl = __fl_lookup(fl->label); | 168 | lfl = __fl_lookup(fl->label); |
168 | if (lfl == NULL) | 169 | if (lfl == NULL) |
169 | break; | 170 | break; |
170 | } | 171 | } |
171 | } | 172 | } |
173 | } else { | ||
174 | /* | ||
175 | * we dropper the ip6_fl_lock, so this entry could reappear | ||
176 | * and we need to recheck with it. | ||
177 | * | ||
178 | * OTOH no need to search the active socket first, like it is | ||
179 | * done in ipv6_flowlabel_opt - sock is locked, so new entry | ||
180 | * with the same label can only appear on another sock | ||
181 | */ | ||
182 | lfl = __fl_lookup(fl->label); | ||
183 | if (lfl != NULL) { | ||
184 | atomic_inc(&lfl->users); | ||
185 | write_unlock_bh(&ip6_fl_lock); | ||
186 | return lfl; | ||
187 | } | ||
172 | } | 188 | } |
173 | 189 | ||
174 | fl->lastuse = jiffies; | 190 | fl->lastuse = jiffies; |
@@ -176,7 +192,7 @@ static int fl_intern(struct ip6_flowlabel *fl, __be32 label) | |||
176 | fl_ht[FL_HASH(fl->label)] = fl; | 192 | fl_ht[FL_HASH(fl->label)] = fl; |
177 | atomic_inc(&fl_size); | 193 | atomic_inc(&fl_size); |
178 | write_unlock_bh(&ip6_fl_lock); | 194 | write_unlock_bh(&ip6_fl_lock); |
179 | return 0; | 195 | return NULL; |
180 | } | 196 | } |
181 | 197 | ||
182 | 198 | ||
@@ -190,14 +206,17 @@ struct ip6_flowlabel * fl6_sock_lookup(struct sock *sk, __be32 label) | |||
190 | 206 | ||
191 | label &= IPV6_FLOWLABEL_MASK; | 207 | label &= IPV6_FLOWLABEL_MASK; |
192 | 208 | ||
209 | read_lock_bh(&ip6_sk_fl_lock); | ||
193 | for (sfl=np->ipv6_fl_list; sfl; sfl = sfl->next) { | 210 | for (sfl=np->ipv6_fl_list; sfl; sfl = sfl->next) { |
194 | struct ip6_flowlabel *fl = sfl->fl; | 211 | struct ip6_flowlabel *fl = sfl->fl; |
195 | if (fl->label == label) { | 212 | if (fl->label == label) { |
196 | fl->lastuse = jiffies; | 213 | fl->lastuse = jiffies; |
197 | atomic_inc(&fl->users); | 214 | atomic_inc(&fl->users); |
215 | read_unlock_bh(&ip6_sk_fl_lock); | ||
198 | return fl; | 216 | return fl; |
199 | } | 217 | } |
200 | } | 218 | } |
219 | read_unlock_bh(&ip6_sk_fl_lock); | ||
201 | return NULL; | 220 | return NULL; |
202 | } | 221 | } |
203 | 222 | ||
@@ -409,6 +428,16 @@ static int ipv6_opt_cmp(struct ipv6_txoptions *o1, struct ipv6_txoptions *o2) | |||
409 | return 0; | 428 | return 0; |
410 | } | 429 | } |
411 | 430 | ||
431 | static inline void fl_link(struct ipv6_pinfo *np, struct ipv6_fl_socklist *sfl, | ||
432 | struct ip6_flowlabel *fl) | ||
433 | { | ||
434 | write_lock_bh(&ip6_sk_fl_lock); | ||
435 | sfl->fl = fl; | ||
436 | sfl->next = np->ipv6_fl_list; | ||
437 | np->ipv6_fl_list = sfl; | ||
438 | write_unlock_bh(&ip6_sk_fl_lock); | ||
439 | } | ||
440 | |||
412 | int ipv6_flowlabel_opt(struct sock *sk, char __user *optval, int optlen) | 441 | int ipv6_flowlabel_opt(struct sock *sk, char __user *optval, int optlen) |
413 | { | 442 | { |
414 | int err; | 443 | int err; |
@@ -416,7 +445,8 @@ int ipv6_flowlabel_opt(struct sock *sk, char __user *optval, int optlen) | |||
416 | struct in6_flowlabel_req freq; | 445 | struct in6_flowlabel_req freq; |
417 | struct ipv6_fl_socklist *sfl1=NULL; | 446 | struct ipv6_fl_socklist *sfl1=NULL; |
418 | struct ipv6_fl_socklist *sfl, **sflp; | 447 | struct ipv6_fl_socklist *sfl, **sflp; |
419 | struct ip6_flowlabel *fl; | 448 | struct ip6_flowlabel *fl, *fl1 = NULL; |
449 | |||
420 | 450 | ||
421 | if (optlen < sizeof(freq)) | 451 | if (optlen < sizeof(freq)) |
422 | return -EINVAL; | 452 | return -EINVAL; |
@@ -472,8 +502,6 @@ int ipv6_flowlabel_opt(struct sock *sk, char __user *optval, int optlen) | |||
472 | sfl1 = kmalloc(sizeof(*sfl1), GFP_KERNEL); | 502 | sfl1 = kmalloc(sizeof(*sfl1), GFP_KERNEL); |
473 | 503 | ||
474 | if (freq.flr_label) { | 504 | if (freq.flr_label) { |
475 | struct ip6_flowlabel *fl1 = NULL; | ||
476 | |||
477 | err = -EEXIST; | 505 | err = -EEXIST; |
478 | read_lock_bh(&ip6_sk_fl_lock); | 506 | read_lock_bh(&ip6_sk_fl_lock); |
479 | for (sfl = np->ipv6_fl_list; sfl; sfl = sfl->next) { | 507 | for (sfl = np->ipv6_fl_list; sfl; sfl = sfl->next) { |
@@ -492,6 +520,7 @@ int ipv6_flowlabel_opt(struct sock *sk, char __user *optval, int optlen) | |||
492 | if (fl1 == NULL) | 520 | if (fl1 == NULL) |
493 | fl1 = fl_lookup(freq.flr_label); | 521 | fl1 = fl_lookup(freq.flr_label); |
494 | if (fl1) { | 522 | if (fl1) { |
523 | recheck: | ||
495 | err = -EEXIST; | 524 | err = -EEXIST; |
496 | if (freq.flr_flags&IPV6_FL_F_EXCL) | 525 | if (freq.flr_flags&IPV6_FL_F_EXCL) |
497 | goto release; | 526 | goto release; |
@@ -513,11 +542,7 @@ int ipv6_flowlabel_opt(struct sock *sk, char __user *optval, int optlen) | |||
513 | fl1->linger = fl->linger; | 542 | fl1->linger = fl->linger; |
514 | if ((long)(fl->expires - fl1->expires) > 0) | 543 | if ((long)(fl->expires - fl1->expires) > 0) |
515 | fl1->expires = fl->expires; | 544 | fl1->expires = fl->expires; |
516 | write_lock_bh(&ip6_sk_fl_lock); | 545 | fl_link(np, sfl1, fl1); |
517 | sfl1->fl = fl1; | ||
518 | sfl1->next = np->ipv6_fl_list; | ||
519 | np->ipv6_fl_list = sfl1; | ||
520 | write_unlock_bh(&ip6_sk_fl_lock); | ||
521 | fl_free(fl); | 546 | fl_free(fl); |
522 | return 0; | 547 | return 0; |
523 | 548 | ||
@@ -534,9 +559,9 @@ release: | |||
534 | if (sfl1 == NULL || (err = mem_check(sk)) != 0) | 559 | if (sfl1 == NULL || (err = mem_check(sk)) != 0) |
535 | goto done; | 560 | goto done; |
536 | 561 | ||
537 | err = fl_intern(fl, freq.flr_label); | 562 | fl1 = fl_intern(fl, freq.flr_label); |
538 | if (err) | 563 | if (fl1 != NULL) |
539 | goto done; | 564 | goto recheck; |
540 | 565 | ||
541 | if (!freq.flr_label) { | 566 | if (!freq.flr_label) { |
542 | if (copy_to_user(&((struct in6_flowlabel_req __user *) optval)->flr_label, | 567 | if (copy_to_user(&((struct in6_flowlabel_req __user *) optval)->flr_label, |
@@ -545,9 +570,7 @@ release: | |||
545 | } | 570 | } |
546 | } | 571 | } |
547 | 572 | ||
548 | sfl1->fl = fl; | 573 | fl_link(np, sfl1, fl); |
549 | sfl1->next = np->ipv6_fl_list; | ||
550 | np->ipv6_fl_list = sfl1; | ||
551 | return 0; | 574 | return 0; |
552 | 575 | ||
553 | default: | 576 | default: |
diff --git a/net/ipv6/ip6_input.c b/net/ipv6/ip6_input.c index 9149fc239759..fac6f7f9dd73 100644 --- a/net/ipv6/ip6_input.c +++ b/net/ipv6/ip6_input.c | |||
@@ -125,7 +125,7 @@ int ipv6_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt | |||
125 | } | 125 | } |
126 | 126 | ||
127 | if (hdr->nexthdr == NEXTHDR_HOP) { | 127 | if (hdr->nexthdr == NEXTHDR_HOP) { |
128 | if (ipv6_parse_hopopts(&skb) < 0) { | 128 | if (ipv6_parse_hopopts(skb) < 0) { |
129 | IP6_INC_STATS_BH(idev, IPSTATS_MIB_INHDRERRORS); | 129 | IP6_INC_STATS_BH(idev, IPSTATS_MIB_INHDRERRORS); |
130 | rcu_read_unlock(); | 130 | rcu_read_unlock(); |
131 | return 0; | 131 | return 0; |
@@ -149,7 +149,7 @@ out: | |||
149 | */ | 149 | */ |
150 | 150 | ||
151 | 151 | ||
152 | static inline int ip6_input_finish(struct sk_buff *skb) | 152 | static int ip6_input_finish(struct sk_buff *skb) |
153 | { | 153 | { |
154 | struct inet6_protocol *ipprot; | 154 | struct inet6_protocol *ipprot; |
155 | struct sock *raw_sk; | 155 | struct sock *raw_sk; |
@@ -199,7 +199,7 @@ resubmit: | |||
199 | !xfrm6_policy_check(NULL, XFRM_POLICY_IN, skb)) | 199 | !xfrm6_policy_check(NULL, XFRM_POLICY_IN, skb)) |
200 | goto discard; | 200 | goto discard; |
201 | 201 | ||
202 | ret = ipprot->handler(&skb); | 202 | ret = ipprot->handler(skb); |
203 | if (ret > 0) | 203 | if (ret > 0) |
204 | goto resubmit; | 204 | goto resubmit; |
205 | else if (ret == 0) | 205 | else if (ret == 0) |
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index 011082ed921a..13565dfb1b45 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c | |||
@@ -70,7 +70,7 @@ static __inline__ void ipv6_select_ident(struct sk_buff *skb, struct frag_hdr *f | |||
70 | spin_unlock_bh(&ip6_id_lock); | 70 | spin_unlock_bh(&ip6_id_lock); |
71 | } | 71 | } |
72 | 72 | ||
73 | static inline int ip6_output_finish(struct sk_buff *skb) | 73 | static int ip6_output_finish(struct sk_buff *skb) |
74 | { | 74 | { |
75 | struct dst_entry *dst = skb->dst; | 75 | struct dst_entry *dst = skb->dst; |
76 | 76 | ||
diff --git a/net/ipv6/ipcomp6.c b/net/ipv6/ipcomp6.c index 28fc8edfdc3a..80ef2a1d39fd 100644 --- a/net/ipv6/ipcomp6.c +++ b/net/ipv6/ipcomp6.c | |||
@@ -411,8 +411,15 @@ static int ipcomp6_init_state(struct xfrm_state *x) | |||
411 | goto out; | 411 | goto out; |
412 | 412 | ||
413 | x->props.header_len = 0; | 413 | x->props.header_len = 0; |
414 | if (x->props.mode == XFRM_MODE_TUNNEL) | 414 | switch (x->props.mode) { |
415 | case XFRM_MODE_BEET: | ||
416 | case XFRM_MODE_TRANSPORT: | ||
417 | break; | ||
418 | case XFRM_MODE_TUNNEL: | ||
415 | x->props.header_len += sizeof(struct ipv6hdr); | 419 | x->props.header_len += sizeof(struct ipv6hdr); |
420 | default: | ||
421 | goto error; | ||
422 | } | ||
416 | 423 | ||
417 | mutex_lock(&ipcomp6_resource_mutex); | 424 | mutex_lock(&ipcomp6_resource_mutex); |
418 | if (!ipcomp6_alloc_scratches()) | 425 | if (!ipcomp6_alloc_scratches()) |
diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c index 6cc33dc83d1c..20cfc90d5597 100644 --- a/net/ipv6/ndisc.c +++ b/net/ipv6/ndisc.c | |||
@@ -1658,30 +1658,26 @@ int ndisc_ifinfo_sysctl_change(struct ctl_table *ctl, int write, struct file * f | |||
1658 | struct inet6_dev *idev; | 1658 | struct inet6_dev *idev; |
1659 | int ret; | 1659 | int ret; |
1660 | 1660 | ||
1661 | if (ctl->ctl_name == NET_NEIGH_RETRANS_TIME || | 1661 | if ((strcmp(ctl->procname, "retrans_time") == 0) || |
1662 | ctl->ctl_name == NET_NEIGH_REACHABLE_TIME) | 1662 | (strcmp(ctl->procname, "base_reachable_time") == 0)) |
1663 | ndisc_warn_deprecated_sysctl(ctl, "syscall", dev ? dev->name : "default"); | 1663 | ndisc_warn_deprecated_sysctl(ctl, "syscall", dev ? dev->name : "default"); |
1664 | 1664 | ||
1665 | switch (ctl->ctl_name) { | 1665 | if (strcmp(ctl->procname, "retrans_time") == 0) |
1666 | case NET_NEIGH_RETRANS_TIME: | ||
1667 | ret = proc_dointvec(ctl, write, filp, buffer, lenp, ppos); | 1666 | ret = proc_dointvec(ctl, write, filp, buffer, lenp, ppos); |
1668 | break; | 1667 | |
1669 | case NET_NEIGH_REACHABLE_TIME: | 1668 | else if (strcmp(ctl->procname, "base_reachable_time") == 0) |
1670 | ret = proc_dointvec_jiffies(ctl, write, | 1669 | ret = proc_dointvec_jiffies(ctl, write, |
1671 | filp, buffer, lenp, ppos); | 1670 | filp, buffer, lenp, ppos); |
1672 | break; | 1671 | |
1673 | case NET_NEIGH_RETRANS_TIME_MS: | 1672 | else if ((strcmp(ctl->procname, "retrans_time_ms") == 0) || |
1674 | case NET_NEIGH_REACHABLE_TIME_MS: | 1673 | (strcmp(ctl->procname, "base_reacable_time_ms") == 0)) |
1675 | ret = proc_dointvec_ms_jiffies(ctl, write, | 1674 | ret = proc_dointvec_ms_jiffies(ctl, write, |
1676 | filp, buffer, lenp, ppos); | 1675 | filp, buffer, lenp, ppos); |
1677 | break; | 1676 | else |
1678 | default: | ||
1679 | ret = -1; | 1677 | ret = -1; |
1680 | } | ||
1681 | 1678 | ||
1682 | if (write && ret == 0 && dev && (idev = in6_dev_get(dev)) != NULL) { | 1679 | if (write && ret == 0 && dev && (idev = in6_dev_get(dev)) != NULL) { |
1683 | if (ctl->ctl_name == NET_NEIGH_REACHABLE_TIME || | 1680 | if (ctl->data == &idev->nd_parms->base_reachable_time) |
1684 | ctl->ctl_name == NET_NEIGH_REACHABLE_TIME_MS) | ||
1685 | idev->nd_parms->reachable_time = neigh_rand_reach_time(idev->nd_parms->base_reachable_time); | 1681 | idev->nd_parms->reachable_time = neigh_rand_reach_time(idev->nd_parms->base_reachable_time); |
1686 | idev->tstamp = jiffies; | 1682 | idev->tstamp = jiffies; |
1687 | inet6_ifinfo_notify(RTM_NEWLINK, idev); | 1683 | inet6_ifinfo_notify(RTM_NEWLINK, idev); |
diff --git a/net/ipv6/netfilter.c b/net/ipv6/netfilter.c index 38b149613915..b1326c2bf8aa 100644 --- a/net/ipv6/netfilter.c +++ b/net/ipv6/netfilter.c | |||
@@ -68,15 +68,15 @@ static void nf_ip6_saveroute(const struct sk_buff *skb, struct nf_info *info) | |||
68 | } | 68 | } |
69 | } | 69 | } |
70 | 70 | ||
71 | static int nf_ip6_reroute(struct sk_buff **pskb, const struct nf_info *info) | 71 | static int nf_ip6_reroute(struct sk_buff *skb, const struct nf_info *info) |
72 | { | 72 | { |
73 | struct ip6_rt_info *rt_info = nf_info_reroute(info); | 73 | struct ip6_rt_info *rt_info = nf_info_reroute(info); |
74 | 74 | ||
75 | if (info->hook == NF_IP6_LOCAL_OUT) { | 75 | if (info->hook == NF_IP6_LOCAL_OUT) { |
76 | struct ipv6hdr *iph = ipv6_hdr(*pskb); | 76 | struct ipv6hdr *iph = ipv6_hdr(skb); |
77 | if (!ipv6_addr_equal(&iph->daddr, &rt_info->daddr) || | 77 | if (!ipv6_addr_equal(&iph->daddr, &rt_info->daddr) || |
78 | !ipv6_addr_equal(&iph->saddr, &rt_info->saddr)) | 78 | !ipv6_addr_equal(&iph->saddr, &rt_info->saddr)) |
79 | return ip6_route_me_harder(*pskb); | 79 | return ip6_route_me_harder(skb); |
80 | } | 80 | } |
81 | return 0; | 81 | return 0; |
82 | } | 82 | } |
diff --git a/net/ipv6/netfilter/ip6_queue.c b/net/ipv6/netfilter/ip6_queue.c index 0473145ac534..6413a30d9f68 100644 --- a/net/ipv6/netfilter/ip6_queue.c +++ b/net/ipv6/netfilter/ip6_queue.c | |||
@@ -332,6 +332,7 @@ static int | |||
332 | ipq_mangle_ipv6(ipq_verdict_msg_t *v, struct ipq_queue_entry *e) | 332 | ipq_mangle_ipv6(ipq_verdict_msg_t *v, struct ipq_queue_entry *e) |
333 | { | 333 | { |
334 | int diff; | 334 | int diff; |
335 | int err; | ||
335 | struct ipv6hdr *user_iph = (struct ipv6hdr *)v->payload; | 336 | struct ipv6hdr *user_iph = (struct ipv6hdr *)v->payload; |
336 | 337 | ||
337 | if (v->data_len < sizeof(*user_iph)) | 338 | if (v->data_len < sizeof(*user_iph)) |
@@ -344,25 +345,18 @@ ipq_mangle_ipv6(ipq_verdict_msg_t *v, struct ipq_queue_entry *e) | |||
344 | if (v->data_len > 0xFFFF) | 345 | if (v->data_len > 0xFFFF) |
345 | return -EINVAL; | 346 | return -EINVAL; |
346 | if (diff > skb_tailroom(e->skb)) { | 347 | if (diff > skb_tailroom(e->skb)) { |
347 | struct sk_buff *newskb; | 348 | err = pskb_expand_head(e->skb, 0, |
348 | 349 | diff - skb_tailroom(e->skb), | |
349 | newskb = skb_copy_expand(e->skb, | 350 | GFP_ATOMIC); |
350 | skb_headroom(e->skb), | 351 | if (err) { |
351 | diff, | ||
352 | GFP_ATOMIC); | ||
353 | if (newskb == NULL) { | ||
354 | printk(KERN_WARNING "ip6_queue: OOM " | 352 | printk(KERN_WARNING "ip6_queue: OOM " |
355 | "in mangle, dropping packet\n"); | 353 | "in mangle, dropping packet\n"); |
356 | return -ENOMEM; | 354 | return err; |
357 | } | 355 | } |
358 | if (e->skb->sk) | ||
359 | skb_set_owner_w(newskb, e->skb->sk); | ||
360 | kfree_skb(e->skb); | ||
361 | e->skb = newskb; | ||
362 | } | 356 | } |
363 | skb_put(e->skb, diff); | 357 | skb_put(e->skb, diff); |
364 | } | 358 | } |
365 | if (!skb_make_writable(&e->skb, v->data_len)) | 359 | if (!skb_make_writable(e->skb, v->data_len)) |
366 | return -ENOMEM; | 360 | return -ENOMEM; |
367 | skb_copy_to_linear_data(e->skb, v->payload, v->data_len); | 361 | skb_copy_to_linear_data(e->skb, v->payload, v->data_len); |
368 | e->skb->ip_summed = CHECKSUM_NONE; | 362 | e->skb->ip_summed = CHECKSUM_NONE; |
diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c index cd9df02bb85c..acaba1537931 100644 --- a/net/ipv6/netfilter/ip6_tables.c +++ b/net/ipv6/netfilter/ip6_tables.c | |||
@@ -205,7 +205,7 @@ ip6_checkentry(const struct ip6t_ip6 *ipv6) | |||
205 | } | 205 | } |
206 | 206 | ||
207 | static unsigned int | 207 | static unsigned int |
208 | ip6t_error(struct sk_buff **pskb, | 208 | ip6t_error(struct sk_buff *skb, |
209 | const struct net_device *in, | 209 | const struct net_device *in, |
210 | const struct net_device *out, | 210 | const struct net_device *out, |
211 | unsigned int hooknum, | 211 | unsigned int hooknum, |
@@ -350,7 +350,7 @@ static void trace_packet(struct sk_buff *skb, | |||
350 | 350 | ||
351 | /* Returns one of the generic firewall policies, like NF_ACCEPT. */ | 351 | /* Returns one of the generic firewall policies, like NF_ACCEPT. */ |
352 | unsigned int | 352 | unsigned int |
353 | ip6t_do_table(struct sk_buff **pskb, | 353 | ip6t_do_table(struct sk_buff *skb, |
354 | unsigned int hook, | 354 | unsigned int hook, |
355 | const struct net_device *in, | 355 | const struct net_device *in, |
356 | const struct net_device *out, | 356 | const struct net_device *out, |
@@ -389,17 +389,17 @@ ip6t_do_table(struct sk_buff **pskb, | |||
389 | do { | 389 | do { |
390 | IP_NF_ASSERT(e); | 390 | IP_NF_ASSERT(e); |
391 | IP_NF_ASSERT(back); | 391 | IP_NF_ASSERT(back); |
392 | if (ip6_packet_match(*pskb, indev, outdev, &e->ipv6, | 392 | if (ip6_packet_match(skb, indev, outdev, &e->ipv6, |
393 | &protoff, &offset, &hotdrop)) { | 393 | &protoff, &offset, &hotdrop)) { |
394 | struct ip6t_entry_target *t; | 394 | struct ip6t_entry_target *t; |
395 | 395 | ||
396 | if (IP6T_MATCH_ITERATE(e, do_match, | 396 | if (IP6T_MATCH_ITERATE(e, do_match, |
397 | *pskb, in, out, | 397 | skb, in, out, |
398 | offset, protoff, &hotdrop) != 0) | 398 | offset, protoff, &hotdrop) != 0) |
399 | goto no_match; | 399 | goto no_match; |
400 | 400 | ||
401 | ADD_COUNTER(e->counters, | 401 | ADD_COUNTER(e->counters, |
402 | ntohs(ipv6_hdr(*pskb)->payload_len) | 402 | ntohs(ipv6_hdr(skb)->payload_len) |
403 | + IPV6_HDR_LEN, | 403 | + IPV6_HDR_LEN, |
404 | 1); | 404 | 1); |
405 | 405 | ||
@@ -409,8 +409,8 @@ ip6t_do_table(struct sk_buff **pskb, | |||
409 | #if defined(CONFIG_NETFILTER_XT_TARGET_TRACE) || \ | 409 | #if defined(CONFIG_NETFILTER_XT_TARGET_TRACE) || \ |
410 | defined(CONFIG_NETFILTER_XT_TARGET_TRACE_MODULE) | 410 | defined(CONFIG_NETFILTER_XT_TARGET_TRACE_MODULE) |
411 | /* The packet is traced: log it */ | 411 | /* The packet is traced: log it */ |
412 | if (unlikely((*pskb)->nf_trace)) | 412 | if (unlikely(skb->nf_trace)) |
413 | trace_packet(*pskb, hook, in, out, | 413 | trace_packet(skb, hook, in, out, |
414 | table->name, private, e); | 414 | table->name, private, e); |
415 | #endif | 415 | #endif |
416 | /* Standard target? */ | 416 | /* Standard target? */ |
@@ -448,7 +448,7 @@ ip6t_do_table(struct sk_buff **pskb, | |||
448 | ((struct ip6t_entry *)table_base)->comefrom | 448 | ((struct ip6t_entry *)table_base)->comefrom |
449 | = 0xeeeeeeec; | 449 | = 0xeeeeeeec; |
450 | #endif | 450 | #endif |
451 | verdict = t->u.kernel.target->target(pskb, | 451 | verdict = t->u.kernel.target->target(skb, |
452 | in, out, | 452 | in, out, |
453 | hook, | 453 | hook, |
454 | t->u.kernel.target, | 454 | t->u.kernel.target, |
diff --git a/net/ipv6/netfilter/ip6t_HL.c b/net/ipv6/netfilter/ip6t_HL.c index ad4d94310b87..9afc836fd454 100644 --- a/net/ipv6/netfilter/ip6t_HL.c +++ b/net/ipv6/netfilter/ip6t_HL.c | |||
@@ -18,7 +18,7 @@ MODULE_AUTHOR("Maciej Soltysiak <solt@dns.toxicfilms.tv>"); | |||
18 | MODULE_DESCRIPTION("IP6 tables Hop Limit modification module"); | 18 | MODULE_DESCRIPTION("IP6 tables Hop Limit modification module"); |
19 | MODULE_LICENSE("GPL"); | 19 | MODULE_LICENSE("GPL"); |
20 | 20 | ||
21 | static unsigned int ip6t_hl_target(struct sk_buff **pskb, | 21 | static unsigned int ip6t_hl_target(struct sk_buff *skb, |
22 | const struct net_device *in, | 22 | const struct net_device *in, |
23 | const struct net_device *out, | 23 | const struct net_device *out, |
24 | unsigned int hooknum, | 24 | unsigned int hooknum, |
@@ -29,10 +29,10 @@ static unsigned int ip6t_hl_target(struct sk_buff **pskb, | |||
29 | const struct ip6t_HL_info *info = targinfo; | 29 | const struct ip6t_HL_info *info = targinfo; |
30 | int new_hl; | 30 | int new_hl; |
31 | 31 | ||
32 | if (!skb_make_writable(pskb, (*pskb)->len)) | 32 | if (!skb_make_writable(skb, skb->len)) |
33 | return NF_DROP; | 33 | return NF_DROP; |
34 | 34 | ||
35 | ip6h = ipv6_hdr(*pskb); | 35 | ip6h = ipv6_hdr(skb); |
36 | 36 | ||
37 | switch (info->mode) { | 37 | switch (info->mode) { |
38 | case IP6T_HL_SET: | 38 | case IP6T_HL_SET: |
diff --git a/net/ipv6/netfilter/ip6t_LOG.c b/net/ipv6/netfilter/ip6t_LOG.c index 6ab99001dccc..7a48c342df46 100644 --- a/net/ipv6/netfilter/ip6t_LOG.c +++ b/net/ipv6/netfilter/ip6t_LOG.c | |||
@@ -431,7 +431,7 @@ ip6t_log_packet(unsigned int pf, | |||
431 | } | 431 | } |
432 | 432 | ||
433 | static unsigned int | 433 | static unsigned int |
434 | ip6t_log_target(struct sk_buff **pskb, | 434 | ip6t_log_target(struct sk_buff *skb, |
435 | const struct net_device *in, | 435 | const struct net_device *in, |
436 | const struct net_device *out, | 436 | const struct net_device *out, |
437 | unsigned int hooknum, | 437 | unsigned int hooknum, |
@@ -445,8 +445,7 @@ ip6t_log_target(struct sk_buff **pskb, | |||
445 | li.u.log.level = loginfo->level; | 445 | li.u.log.level = loginfo->level; |
446 | li.u.log.logflags = loginfo->logflags; | 446 | li.u.log.logflags = loginfo->logflags; |
447 | 447 | ||
448 | ip6t_log_packet(PF_INET6, hooknum, *pskb, in, out, &li, | 448 | ip6t_log_packet(PF_INET6, hooknum, skb, in, out, &li, loginfo->prefix); |
449 | loginfo->prefix); | ||
450 | return XT_CONTINUE; | 449 | return XT_CONTINUE; |
451 | } | 450 | } |
452 | 451 | ||
diff --git a/net/ipv6/netfilter/ip6t_REJECT.c b/net/ipv6/netfilter/ip6t_REJECT.c index 3fd08d5567a6..1a7d2917545d 100644 --- a/net/ipv6/netfilter/ip6t_REJECT.c +++ b/net/ipv6/netfilter/ip6t_REJECT.c | |||
@@ -172,7 +172,7 @@ send_unreach(struct sk_buff *skb_in, unsigned char code, unsigned int hooknum) | |||
172 | icmpv6_send(skb_in, ICMPV6_DEST_UNREACH, code, 0, NULL); | 172 | icmpv6_send(skb_in, ICMPV6_DEST_UNREACH, code, 0, NULL); |
173 | } | 173 | } |
174 | 174 | ||
175 | static unsigned int reject6_target(struct sk_buff **pskb, | 175 | static unsigned int reject6_target(struct sk_buff *skb, |
176 | const struct net_device *in, | 176 | const struct net_device *in, |
177 | const struct net_device *out, | 177 | const struct net_device *out, |
178 | unsigned int hooknum, | 178 | unsigned int hooknum, |
@@ -187,25 +187,25 @@ static unsigned int reject6_target(struct sk_buff **pskb, | |||
187 | must return an absolute verdict. --RR */ | 187 | must return an absolute verdict. --RR */ |
188 | switch (reject->with) { | 188 | switch (reject->with) { |
189 | case IP6T_ICMP6_NO_ROUTE: | 189 | case IP6T_ICMP6_NO_ROUTE: |
190 | send_unreach(*pskb, ICMPV6_NOROUTE, hooknum); | 190 | send_unreach(skb, ICMPV6_NOROUTE, hooknum); |
191 | break; | 191 | break; |
192 | case IP6T_ICMP6_ADM_PROHIBITED: | 192 | case IP6T_ICMP6_ADM_PROHIBITED: |
193 | send_unreach(*pskb, ICMPV6_ADM_PROHIBITED, hooknum); | 193 | send_unreach(skb, ICMPV6_ADM_PROHIBITED, hooknum); |
194 | break; | 194 | break; |
195 | case IP6T_ICMP6_NOT_NEIGHBOUR: | 195 | case IP6T_ICMP6_NOT_NEIGHBOUR: |
196 | send_unreach(*pskb, ICMPV6_NOT_NEIGHBOUR, hooknum); | 196 | send_unreach(skb, ICMPV6_NOT_NEIGHBOUR, hooknum); |
197 | break; | 197 | break; |
198 | case IP6T_ICMP6_ADDR_UNREACH: | 198 | case IP6T_ICMP6_ADDR_UNREACH: |
199 | send_unreach(*pskb, ICMPV6_ADDR_UNREACH, hooknum); | 199 | send_unreach(skb, ICMPV6_ADDR_UNREACH, hooknum); |
200 | break; | 200 | break; |
201 | case IP6T_ICMP6_PORT_UNREACH: | 201 | case IP6T_ICMP6_PORT_UNREACH: |
202 | send_unreach(*pskb, ICMPV6_PORT_UNREACH, hooknum); | 202 | send_unreach(skb, ICMPV6_PORT_UNREACH, hooknum); |
203 | break; | 203 | break; |
204 | case IP6T_ICMP6_ECHOREPLY: | 204 | case IP6T_ICMP6_ECHOREPLY: |
205 | /* Do nothing */ | 205 | /* Do nothing */ |
206 | break; | 206 | break; |
207 | case IP6T_TCP_RESET: | 207 | case IP6T_TCP_RESET: |
208 | send_reset(*pskb); | 208 | send_reset(skb); |
209 | break; | 209 | break; |
210 | default: | 210 | default: |
211 | if (net_ratelimit()) | 211 | if (net_ratelimit()) |
diff --git a/net/ipv6/netfilter/ip6table_filter.c b/net/ipv6/netfilter/ip6table_filter.c index 7e32e2aaf7f7..1d26b202bf30 100644 --- a/net/ipv6/netfilter/ip6table_filter.c +++ b/net/ipv6/netfilter/ip6table_filter.c | |||
@@ -60,32 +60,32 @@ static struct xt_table packet_filter = { | |||
60 | /* The work comes in here from netfilter.c. */ | 60 | /* The work comes in here from netfilter.c. */ |
61 | static unsigned int | 61 | static unsigned int |
62 | ip6t_hook(unsigned int hook, | 62 | ip6t_hook(unsigned int hook, |
63 | struct sk_buff **pskb, | 63 | struct sk_buff *skb, |
64 | const struct net_device *in, | 64 | const struct net_device *in, |
65 | const struct net_device *out, | 65 | const struct net_device *out, |
66 | int (*okfn)(struct sk_buff *)) | 66 | int (*okfn)(struct sk_buff *)) |
67 | { | 67 | { |
68 | return ip6t_do_table(pskb, hook, in, out, &packet_filter); | 68 | return ip6t_do_table(skb, hook, in, out, &packet_filter); |
69 | } | 69 | } |
70 | 70 | ||
71 | static unsigned int | 71 | static unsigned int |
72 | ip6t_local_out_hook(unsigned int hook, | 72 | ip6t_local_out_hook(unsigned int hook, |
73 | struct sk_buff **pskb, | 73 | struct sk_buff *skb, |
74 | const struct net_device *in, | 74 | const struct net_device *in, |
75 | const struct net_device *out, | 75 | const struct net_device *out, |
76 | int (*okfn)(struct sk_buff *)) | 76 | int (*okfn)(struct sk_buff *)) |
77 | { | 77 | { |
78 | #if 0 | 78 | #if 0 |
79 | /* root is playing with raw sockets. */ | 79 | /* root is playing with raw sockets. */ |
80 | if ((*pskb)->len < sizeof(struct iphdr) | 80 | if (skb->len < sizeof(struct iphdr) |
81 | || ip_hdrlen(*pskb) < sizeof(struct iphdr)) { | 81 | || ip_hdrlen(skb) < sizeof(struct iphdr)) { |
82 | if (net_ratelimit()) | 82 | if (net_ratelimit()) |
83 | printk("ip6t_hook: happy cracking.\n"); | 83 | printk("ip6t_hook: happy cracking.\n"); |
84 | return NF_ACCEPT; | 84 | return NF_ACCEPT; |
85 | } | 85 | } |
86 | #endif | 86 | #endif |
87 | 87 | ||
88 | return ip6t_do_table(pskb, hook, in, out, &packet_filter); | 88 | return ip6t_do_table(skb, hook, in, out, &packet_filter); |
89 | } | 89 | } |
90 | 90 | ||
91 | static struct nf_hook_ops ip6t_ops[] = { | 91 | static struct nf_hook_ops ip6t_ops[] = { |
diff --git a/net/ipv6/netfilter/ip6table_mangle.c b/net/ipv6/netfilter/ip6table_mangle.c index f0a9efa67fb5..a0b6381f1e8c 100644 --- a/net/ipv6/netfilter/ip6table_mangle.c +++ b/net/ipv6/netfilter/ip6table_mangle.c | |||
@@ -68,17 +68,17 @@ static struct xt_table packet_mangler = { | |||
68 | /* The work comes in here from netfilter.c. */ | 68 | /* The work comes in here from netfilter.c. */ |
69 | static unsigned int | 69 | static unsigned int |
70 | ip6t_route_hook(unsigned int hook, | 70 | ip6t_route_hook(unsigned int hook, |
71 | struct sk_buff **pskb, | 71 | struct sk_buff *skb, |
72 | const struct net_device *in, | 72 | const struct net_device *in, |
73 | const struct net_device *out, | 73 | const struct net_device *out, |
74 | int (*okfn)(struct sk_buff *)) | 74 | int (*okfn)(struct sk_buff *)) |
75 | { | 75 | { |
76 | return ip6t_do_table(pskb, hook, in, out, &packet_mangler); | 76 | return ip6t_do_table(skb, hook, in, out, &packet_mangler); |
77 | } | 77 | } |
78 | 78 | ||
79 | static unsigned int | 79 | static unsigned int |
80 | ip6t_local_hook(unsigned int hook, | 80 | ip6t_local_hook(unsigned int hook, |
81 | struct sk_buff **pskb, | 81 | struct sk_buff *skb, |
82 | const struct net_device *in, | 82 | const struct net_device *in, |
83 | const struct net_device *out, | 83 | const struct net_device *out, |
84 | int (*okfn)(struct sk_buff *)) | 84 | int (*okfn)(struct sk_buff *)) |
@@ -91,8 +91,8 @@ ip6t_local_hook(unsigned int hook, | |||
91 | 91 | ||
92 | #if 0 | 92 | #if 0 |
93 | /* root is playing with raw sockets. */ | 93 | /* root is playing with raw sockets. */ |
94 | if ((*pskb)->len < sizeof(struct iphdr) | 94 | if (skb->len < sizeof(struct iphdr) |
95 | || ip_hdrlen(*pskb) < sizeof(struct iphdr)) { | 95 | || ip_hdrlen(skb) < sizeof(struct iphdr)) { |
96 | if (net_ratelimit()) | 96 | if (net_ratelimit()) |
97 | printk("ip6t_hook: happy cracking.\n"); | 97 | printk("ip6t_hook: happy cracking.\n"); |
98 | return NF_ACCEPT; | 98 | return NF_ACCEPT; |
@@ -100,22 +100,22 @@ ip6t_local_hook(unsigned int hook, | |||
100 | #endif | 100 | #endif |
101 | 101 | ||
102 | /* save source/dest address, mark, hoplimit, flowlabel, priority, */ | 102 | /* save source/dest address, mark, hoplimit, flowlabel, priority, */ |
103 | memcpy(&saddr, &ipv6_hdr(*pskb)->saddr, sizeof(saddr)); | 103 | memcpy(&saddr, &ipv6_hdr(skb)->saddr, sizeof(saddr)); |
104 | memcpy(&daddr, &ipv6_hdr(*pskb)->daddr, sizeof(daddr)); | 104 | memcpy(&daddr, &ipv6_hdr(skb)->daddr, sizeof(daddr)); |
105 | mark = (*pskb)->mark; | 105 | mark = skb->mark; |
106 | hop_limit = ipv6_hdr(*pskb)->hop_limit; | 106 | hop_limit = ipv6_hdr(skb)->hop_limit; |
107 | 107 | ||
108 | /* flowlabel and prio (includes version, which shouldn't change either */ | 108 | /* flowlabel and prio (includes version, which shouldn't change either */ |
109 | flowlabel = *((u_int32_t *)ipv6_hdr(*pskb)); | 109 | flowlabel = *((u_int32_t *)ipv6_hdr(skb)); |
110 | 110 | ||
111 | ret = ip6t_do_table(pskb, hook, in, out, &packet_mangler); | 111 | ret = ip6t_do_table(skb, hook, in, out, &packet_mangler); |
112 | 112 | ||
113 | if (ret != NF_DROP && ret != NF_STOLEN | 113 | if (ret != NF_DROP && ret != NF_STOLEN |
114 | && (memcmp(&ipv6_hdr(*pskb)->saddr, &saddr, sizeof(saddr)) | 114 | && (memcmp(&ipv6_hdr(skb)->saddr, &saddr, sizeof(saddr)) |
115 | || memcmp(&ipv6_hdr(*pskb)->daddr, &daddr, sizeof(daddr)) | 115 | || memcmp(&ipv6_hdr(skb)->daddr, &daddr, sizeof(daddr)) |
116 | || (*pskb)->mark != mark | 116 | || skb->mark != mark |
117 | || ipv6_hdr(*pskb)->hop_limit != hop_limit)) | 117 | || ipv6_hdr(skb)->hop_limit != hop_limit)) |
118 | return ip6_route_me_harder(*pskb) == 0 ? ret : NF_DROP; | 118 | return ip6_route_me_harder(skb) == 0 ? ret : NF_DROP; |
119 | 119 | ||
120 | return ret; | 120 | return ret; |
121 | } | 121 | } |
diff --git a/net/ipv6/netfilter/ip6table_raw.c b/net/ipv6/netfilter/ip6table_raw.c index ec290e4ebdd8..8f7109f991e6 100644 --- a/net/ipv6/netfilter/ip6table_raw.c +++ b/net/ipv6/netfilter/ip6table_raw.c | |||
@@ -46,12 +46,12 @@ static struct xt_table packet_raw = { | |||
46 | /* The work comes in here from netfilter.c. */ | 46 | /* The work comes in here from netfilter.c. */ |
47 | static unsigned int | 47 | static unsigned int |
48 | ip6t_hook(unsigned int hook, | 48 | ip6t_hook(unsigned int hook, |
49 | struct sk_buff **pskb, | 49 | struct sk_buff *skb, |
50 | const struct net_device *in, | 50 | const struct net_device *in, |
51 | const struct net_device *out, | 51 | const struct net_device *out, |
52 | int (*okfn)(struct sk_buff *)) | 52 | int (*okfn)(struct sk_buff *)) |
53 | { | 53 | { |
54 | return ip6t_do_table(pskb, hook, in, out, &packet_raw); | 54 | return ip6t_do_table(skb, hook, in, out, &packet_raw); |
55 | } | 55 | } |
56 | 56 | ||
57 | static struct nf_hook_ops ip6t_ops[] = { | 57 | static struct nf_hook_ops ip6t_ops[] = { |
diff --git a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c index 37a3db926953..ad74bab05047 100644 --- a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c +++ b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c | |||
@@ -18,6 +18,7 @@ | |||
18 | #include <linux/icmp.h> | 18 | #include <linux/icmp.h> |
19 | #include <linux/sysctl.h> | 19 | #include <linux/sysctl.h> |
20 | #include <net/ipv6.h> | 20 | #include <net/ipv6.h> |
21 | #include <net/inet_frag.h> | ||
21 | 22 | ||
22 | #include <linux/netfilter_ipv6.h> | 23 | #include <linux/netfilter_ipv6.h> |
23 | #include <net/netfilter/nf_conntrack.h> | 24 | #include <net/netfilter/nf_conntrack.h> |
@@ -145,7 +146,7 @@ static int ipv6_get_l4proto(const struct sk_buff *skb, unsigned int nhoff, | |||
145 | } | 146 | } |
146 | 147 | ||
147 | static unsigned int ipv6_confirm(unsigned int hooknum, | 148 | static unsigned int ipv6_confirm(unsigned int hooknum, |
148 | struct sk_buff **pskb, | 149 | struct sk_buff *skb, |
149 | const struct net_device *in, | 150 | const struct net_device *in, |
150 | const struct net_device *out, | 151 | const struct net_device *out, |
151 | int (*okfn)(struct sk_buff *)) | 152 | int (*okfn)(struct sk_buff *)) |
@@ -155,12 +156,12 @@ static unsigned int ipv6_confirm(unsigned int hooknum, | |||
155 | struct nf_conntrack_helper *helper; | 156 | struct nf_conntrack_helper *helper; |
156 | enum ip_conntrack_info ctinfo; | 157 | enum ip_conntrack_info ctinfo; |
157 | unsigned int ret, protoff; | 158 | unsigned int ret, protoff; |
158 | unsigned int extoff = (u8 *)(ipv6_hdr(*pskb) + 1) - (*pskb)->data; | 159 | unsigned int extoff = (u8 *)(ipv6_hdr(skb) + 1) - skb->data; |
159 | unsigned char pnum = ipv6_hdr(*pskb)->nexthdr; | 160 | unsigned char pnum = ipv6_hdr(skb)->nexthdr; |
160 | 161 | ||
161 | 162 | ||
162 | /* This is where we call the helper: as the packet goes out. */ | 163 | /* This is where we call the helper: as the packet goes out. */ |
163 | ct = nf_ct_get(*pskb, &ctinfo); | 164 | ct = nf_ct_get(skb, &ctinfo); |
164 | if (!ct || ctinfo == IP_CT_RELATED + IP_CT_IS_REPLY) | 165 | if (!ct || ctinfo == IP_CT_RELATED + IP_CT_IS_REPLY) |
165 | goto out; | 166 | goto out; |
166 | 167 | ||
@@ -172,23 +173,23 @@ static unsigned int ipv6_confirm(unsigned int hooknum, | |||
172 | if (!helper) | 173 | if (!helper) |
173 | goto out; | 174 | goto out; |
174 | 175 | ||
175 | protoff = nf_ct_ipv6_skip_exthdr(*pskb, extoff, &pnum, | 176 | protoff = nf_ct_ipv6_skip_exthdr(skb, extoff, &pnum, |
176 | (*pskb)->len - extoff); | 177 | skb->len - extoff); |
177 | if (protoff > (*pskb)->len || pnum == NEXTHDR_FRAGMENT) { | 178 | if (protoff > skb->len || pnum == NEXTHDR_FRAGMENT) { |
178 | pr_debug("proto header not found\n"); | 179 | pr_debug("proto header not found\n"); |
179 | return NF_ACCEPT; | 180 | return NF_ACCEPT; |
180 | } | 181 | } |
181 | 182 | ||
182 | ret = helper->help(pskb, protoff, ct, ctinfo); | 183 | ret = helper->help(skb, protoff, ct, ctinfo); |
183 | if (ret != NF_ACCEPT) | 184 | if (ret != NF_ACCEPT) |
184 | return ret; | 185 | return ret; |
185 | out: | 186 | out: |
186 | /* We've seen it coming out the other side: confirm it */ | 187 | /* We've seen it coming out the other side: confirm it */ |
187 | return nf_conntrack_confirm(pskb); | 188 | return nf_conntrack_confirm(skb); |
188 | } | 189 | } |
189 | 190 | ||
190 | static unsigned int ipv6_defrag(unsigned int hooknum, | 191 | static unsigned int ipv6_defrag(unsigned int hooknum, |
191 | struct sk_buff **pskb, | 192 | struct sk_buff *skb, |
192 | const struct net_device *in, | 193 | const struct net_device *in, |
193 | const struct net_device *out, | 194 | const struct net_device *out, |
194 | int (*okfn)(struct sk_buff *)) | 195 | int (*okfn)(struct sk_buff *)) |
@@ -196,17 +197,17 @@ static unsigned int ipv6_defrag(unsigned int hooknum, | |||
196 | struct sk_buff *reasm; | 197 | struct sk_buff *reasm; |
197 | 198 | ||
198 | /* Previously seen (loopback)? */ | 199 | /* Previously seen (loopback)? */ |
199 | if ((*pskb)->nfct) | 200 | if (skb->nfct) |
200 | return NF_ACCEPT; | 201 | return NF_ACCEPT; |
201 | 202 | ||
202 | reasm = nf_ct_frag6_gather(*pskb); | 203 | reasm = nf_ct_frag6_gather(skb); |
203 | 204 | ||
204 | /* queued */ | 205 | /* queued */ |
205 | if (reasm == NULL) | 206 | if (reasm == NULL) |
206 | return NF_STOLEN; | 207 | return NF_STOLEN; |
207 | 208 | ||
208 | /* error occured or not fragmented */ | 209 | /* error occured or not fragmented */ |
209 | if (reasm == *pskb) | 210 | if (reasm == skb) |
210 | return NF_ACCEPT; | 211 | return NF_ACCEPT; |
211 | 212 | ||
212 | nf_ct_frag6_output(hooknum, reasm, (struct net_device *)in, | 213 | nf_ct_frag6_output(hooknum, reasm, (struct net_device *)in, |
@@ -216,12 +217,12 @@ static unsigned int ipv6_defrag(unsigned int hooknum, | |||
216 | } | 217 | } |
217 | 218 | ||
218 | static unsigned int ipv6_conntrack_in(unsigned int hooknum, | 219 | static unsigned int ipv6_conntrack_in(unsigned int hooknum, |
219 | struct sk_buff **pskb, | 220 | struct sk_buff *skb, |
220 | const struct net_device *in, | 221 | const struct net_device *in, |
221 | const struct net_device *out, | 222 | const struct net_device *out, |
222 | int (*okfn)(struct sk_buff *)) | 223 | int (*okfn)(struct sk_buff *)) |
223 | { | 224 | { |
224 | struct sk_buff *reasm = (*pskb)->nfct_reasm; | 225 | struct sk_buff *reasm = skb->nfct_reasm; |
225 | 226 | ||
226 | /* This packet is fragmented and has reassembled packet. */ | 227 | /* This packet is fragmented and has reassembled packet. */ |
227 | if (reasm) { | 228 | if (reasm) { |
@@ -229,32 +230,32 @@ static unsigned int ipv6_conntrack_in(unsigned int hooknum, | |||
229 | if (!reasm->nfct) { | 230 | if (!reasm->nfct) { |
230 | unsigned int ret; | 231 | unsigned int ret; |
231 | 232 | ||
232 | ret = nf_conntrack_in(PF_INET6, hooknum, &reasm); | 233 | ret = nf_conntrack_in(PF_INET6, hooknum, reasm); |
233 | if (ret != NF_ACCEPT) | 234 | if (ret != NF_ACCEPT) |
234 | return ret; | 235 | return ret; |
235 | } | 236 | } |
236 | nf_conntrack_get(reasm->nfct); | 237 | nf_conntrack_get(reasm->nfct); |
237 | (*pskb)->nfct = reasm->nfct; | 238 | skb->nfct = reasm->nfct; |
238 | (*pskb)->nfctinfo = reasm->nfctinfo; | 239 | skb->nfctinfo = reasm->nfctinfo; |
239 | return NF_ACCEPT; | 240 | return NF_ACCEPT; |
240 | } | 241 | } |
241 | 242 | ||
242 | return nf_conntrack_in(PF_INET6, hooknum, pskb); | 243 | return nf_conntrack_in(PF_INET6, hooknum, skb); |
243 | } | 244 | } |
244 | 245 | ||
245 | static unsigned int ipv6_conntrack_local(unsigned int hooknum, | 246 | static unsigned int ipv6_conntrack_local(unsigned int hooknum, |
246 | struct sk_buff **pskb, | 247 | struct sk_buff *skb, |
247 | const struct net_device *in, | 248 | const struct net_device *in, |
248 | const struct net_device *out, | 249 | const struct net_device *out, |
249 | int (*okfn)(struct sk_buff *)) | 250 | int (*okfn)(struct sk_buff *)) |
250 | { | 251 | { |
251 | /* root is playing with raw sockets. */ | 252 | /* root is playing with raw sockets. */ |
252 | if ((*pskb)->len < sizeof(struct ipv6hdr)) { | 253 | if (skb->len < sizeof(struct ipv6hdr)) { |
253 | if (net_ratelimit()) | 254 | if (net_ratelimit()) |
254 | printk("ipv6_conntrack_local: packet too short\n"); | 255 | printk("ipv6_conntrack_local: packet too short\n"); |
255 | return NF_ACCEPT; | 256 | return NF_ACCEPT; |
256 | } | 257 | } |
257 | return ipv6_conntrack_in(hooknum, pskb, in, out, okfn); | 258 | return ipv6_conntrack_in(hooknum, skb, in, out, okfn); |
258 | } | 259 | } |
259 | 260 | ||
260 | static struct nf_hook_ops ipv6_conntrack_ops[] = { | 261 | static struct nf_hook_ops ipv6_conntrack_ops[] = { |
@@ -305,9 +306,8 @@ static struct nf_hook_ops ipv6_conntrack_ops[] = { | |||
305 | #ifdef CONFIG_SYSCTL | 306 | #ifdef CONFIG_SYSCTL |
306 | static ctl_table nf_ct_ipv6_sysctl_table[] = { | 307 | static ctl_table nf_ct_ipv6_sysctl_table[] = { |
307 | { | 308 | { |
308 | .ctl_name = NET_NF_CONNTRACK_FRAG6_TIMEOUT, | ||
309 | .procname = "nf_conntrack_frag6_timeout", | 309 | .procname = "nf_conntrack_frag6_timeout", |
310 | .data = &nf_ct_frag6_timeout, | 310 | .data = &nf_frags_ctl.timeout, |
311 | .maxlen = sizeof(unsigned int), | 311 | .maxlen = sizeof(unsigned int), |
312 | .mode = 0644, | 312 | .mode = 0644, |
313 | .proc_handler = &proc_dointvec_jiffies, | 313 | .proc_handler = &proc_dointvec_jiffies, |
@@ -315,7 +315,7 @@ static ctl_table nf_ct_ipv6_sysctl_table[] = { | |||
315 | { | 315 | { |
316 | .ctl_name = NET_NF_CONNTRACK_FRAG6_LOW_THRESH, | 316 | .ctl_name = NET_NF_CONNTRACK_FRAG6_LOW_THRESH, |
317 | .procname = "nf_conntrack_frag6_low_thresh", | 317 | .procname = "nf_conntrack_frag6_low_thresh", |
318 | .data = &nf_ct_frag6_low_thresh, | 318 | .data = &nf_frags_ctl.low_thresh, |
319 | .maxlen = sizeof(unsigned int), | 319 | .maxlen = sizeof(unsigned int), |
320 | .mode = 0644, | 320 | .mode = 0644, |
321 | .proc_handler = &proc_dointvec, | 321 | .proc_handler = &proc_dointvec, |
@@ -323,7 +323,7 @@ static ctl_table nf_ct_ipv6_sysctl_table[] = { | |||
323 | { | 323 | { |
324 | .ctl_name = NET_NF_CONNTRACK_FRAG6_HIGH_THRESH, | 324 | .ctl_name = NET_NF_CONNTRACK_FRAG6_HIGH_THRESH, |
325 | .procname = "nf_conntrack_frag6_high_thresh", | 325 | .procname = "nf_conntrack_frag6_high_thresh", |
326 | .data = &nf_ct_frag6_high_thresh, | 326 | .data = &nf_frags_ctl.high_thresh, |
327 | .maxlen = sizeof(unsigned int), | 327 | .maxlen = sizeof(unsigned int), |
328 | .mode = 0644, | 328 | .mode = 0644, |
329 | .proc_handler = &proc_dointvec, | 329 | .proc_handler = &proc_dointvec, |
diff --git a/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c b/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c index fbdc66920de4..fd9123f3dc04 100644 --- a/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c +++ b/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c | |||
@@ -260,7 +260,6 @@ static int icmpv6_nlattr_to_tuple(struct nlattr *tb[], | |||
260 | static struct ctl_table_header *icmpv6_sysctl_header; | 260 | static struct ctl_table_header *icmpv6_sysctl_header; |
261 | static struct ctl_table icmpv6_sysctl_table[] = { | 261 | static struct ctl_table icmpv6_sysctl_table[] = { |
262 | { | 262 | { |
263 | .ctl_name = NET_NF_CONNTRACK_ICMPV6_TIMEOUT, | ||
264 | .procname = "nf_conntrack_icmpv6_timeout", | 263 | .procname = "nf_conntrack_icmpv6_timeout", |
265 | .data = &nf_ct_icmpv6_timeout, | 264 | .data = &nf_ct_icmpv6_timeout, |
266 | .maxlen = sizeof(unsigned int), | 265 | .maxlen = sizeof(unsigned int), |
diff --git a/net/ipv6/netfilter/nf_conntrack_reasm.c b/net/ipv6/netfilter/nf_conntrack_reasm.c index 25442a8c1ba8..e170c67c47a5 100644 --- a/net/ipv6/netfilter/nf_conntrack_reasm.c +++ b/net/ipv6/netfilter/nf_conntrack_reasm.c | |||
@@ -31,6 +31,7 @@ | |||
31 | 31 | ||
32 | #include <net/sock.h> | 32 | #include <net/sock.h> |
33 | #include <net/snmp.h> | 33 | #include <net/snmp.h> |
34 | #include <net/inet_frag.h> | ||
34 | 35 | ||
35 | #include <net/ipv6.h> | 36 | #include <net/ipv6.h> |
36 | #include <net/protocol.h> | 37 | #include <net/protocol.h> |
@@ -48,10 +49,6 @@ | |||
48 | #define NF_CT_FRAG6_LOW_THRESH 196608 /* == 192*1024 */ | 49 | #define NF_CT_FRAG6_LOW_THRESH 196608 /* == 192*1024 */ |
49 | #define NF_CT_FRAG6_TIMEOUT IPV6_FRAG_TIMEOUT | 50 | #define NF_CT_FRAG6_TIMEOUT IPV6_FRAG_TIMEOUT |
50 | 51 | ||
51 | unsigned int nf_ct_frag6_high_thresh __read_mostly = 256*1024; | ||
52 | unsigned int nf_ct_frag6_low_thresh __read_mostly = 192*1024; | ||
53 | unsigned long nf_ct_frag6_timeout __read_mostly = IPV6_FRAG_TIMEOUT; | ||
54 | |||
55 | struct nf_ct_frag6_skb_cb | 52 | struct nf_ct_frag6_skb_cb |
56 | { | 53 | { |
57 | struct inet6_skb_parm h; | 54 | struct inet6_skb_parm h; |
@@ -63,51 +60,24 @@ struct nf_ct_frag6_skb_cb | |||
63 | 60 | ||
64 | struct nf_ct_frag6_queue | 61 | struct nf_ct_frag6_queue |
65 | { | 62 | { |
66 | struct hlist_node list; | 63 | struct inet_frag_queue q; |
67 | struct list_head lru_list; /* lru list member */ | ||
68 | 64 | ||
69 | __be32 id; /* fragment id */ | 65 | __be32 id; /* fragment id */ |
70 | struct in6_addr saddr; | 66 | struct in6_addr saddr; |
71 | struct in6_addr daddr; | 67 | struct in6_addr daddr; |
72 | 68 | ||
73 | spinlock_t lock; | ||
74 | atomic_t refcnt; | ||
75 | struct timer_list timer; /* expire timer */ | ||
76 | struct sk_buff *fragments; | ||
77 | int len; | ||
78 | int meat; | ||
79 | ktime_t stamp; | ||
80 | unsigned int csum; | 69 | unsigned int csum; |
81 | __u8 last_in; /* has first/last segment arrived? */ | ||
82 | #define COMPLETE 4 | ||
83 | #define FIRST_IN 2 | ||
84 | #define LAST_IN 1 | ||
85 | __u16 nhoffset; | 70 | __u16 nhoffset; |
86 | }; | 71 | }; |
87 | 72 | ||
88 | /* Hash table. */ | 73 | struct inet_frags_ctl nf_frags_ctl __read_mostly = { |
89 | 74 | .high_thresh = 256 * 1024, | |
90 | #define FRAG6Q_HASHSZ 64 | 75 | .low_thresh = 192 * 1024, |
91 | 76 | .timeout = IPV6_FRAG_TIMEOUT, | |
92 | static struct hlist_head nf_ct_frag6_hash[FRAG6Q_HASHSZ]; | 77 | .secret_interval = 10 * 60 * HZ, |
93 | static DEFINE_RWLOCK(nf_ct_frag6_lock); | 78 | }; |
94 | static u32 nf_ct_frag6_hash_rnd; | ||
95 | static LIST_HEAD(nf_ct_frag6_lru_list); | ||
96 | int nf_ct_frag6_nqueues = 0; | ||
97 | |||
98 | static __inline__ void __fq_unlink(struct nf_ct_frag6_queue *fq) | ||
99 | { | ||
100 | hlist_del(&fq->list); | ||
101 | list_del(&fq->lru_list); | ||
102 | nf_ct_frag6_nqueues--; | ||
103 | } | ||
104 | 79 | ||
105 | static __inline__ void fq_unlink(struct nf_ct_frag6_queue *fq) | 80 | static struct inet_frags nf_frags; |
106 | { | ||
107 | write_lock(&nf_ct_frag6_lock); | ||
108 | __fq_unlink(fq); | ||
109 | write_unlock(&nf_ct_frag6_lock); | ||
110 | } | ||
111 | 81 | ||
112 | static unsigned int ip6qhashfn(__be32 id, struct in6_addr *saddr, | 82 | static unsigned int ip6qhashfn(__be32 id, struct in6_addr *saddr, |
113 | struct in6_addr *daddr) | 83 | struct in6_addr *daddr) |
@@ -120,7 +90,7 @@ static unsigned int ip6qhashfn(__be32 id, struct in6_addr *saddr, | |||
120 | 90 | ||
121 | a += JHASH_GOLDEN_RATIO; | 91 | a += JHASH_GOLDEN_RATIO; |
122 | b += JHASH_GOLDEN_RATIO; | 92 | b += JHASH_GOLDEN_RATIO; |
123 | c += nf_ct_frag6_hash_rnd; | 93 | c += nf_frags.rnd; |
124 | __jhash_mix(a, b, c); | 94 | __jhash_mix(a, b, c); |
125 | 95 | ||
126 | a += (__force u32)saddr->s6_addr32[3]; | 96 | a += (__force u32)saddr->s6_addr32[3]; |
@@ -133,100 +103,38 @@ static unsigned int ip6qhashfn(__be32 id, struct in6_addr *saddr, | |||
133 | c += (__force u32)id; | 103 | c += (__force u32)id; |
134 | __jhash_mix(a, b, c); | 104 | __jhash_mix(a, b, c); |
135 | 105 | ||
136 | return c & (FRAG6Q_HASHSZ - 1); | 106 | return c & (INETFRAGS_HASHSZ - 1); |
137 | } | 107 | } |
138 | 108 | ||
139 | static struct timer_list nf_ct_frag6_secret_timer; | 109 | static unsigned int nf_hashfn(struct inet_frag_queue *q) |
140 | int nf_ct_frag6_secret_interval = 10 * 60 * HZ; | ||
141 | |||
142 | static void nf_ct_frag6_secret_rebuild(unsigned long dummy) | ||
143 | { | 110 | { |
144 | unsigned long now = jiffies; | 111 | struct nf_ct_frag6_queue *nq; |
145 | int i; | ||
146 | |||
147 | write_lock(&nf_ct_frag6_lock); | ||
148 | get_random_bytes(&nf_ct_frag6_hash_rnd, sizeof(u32)); | ||
149 | for (i = 0; i < FRAG6Q_HASHSZ; i++) { | ||
150 | struct nf_ct_frag6_queue *q; | ||
151 | struct hlist_node *p, *n; | ||
152 | |||
153 | hlist_for_each_entry_safe(q, p, n, &nf_ct_frag6_hash[i], list) { | ||
154 | unsigned int hval = ip6qhashfn(q->id, | ||
155 | &q->saddr, | ||
156 | &q->daddr); | ||
157 | if (hval != i) { | ||
158 | hlist_del(&q->list); | ||
159 | /* Relink to new hash chain. */ | ||
160 | hlist_add_head(&q->list, | ||
161 | &nf_ct_frag6_hash[hval]); | ||
162 | } | ||
163 | } | ||
164 | } | ||
165 | write_unlock(&nf_ct_frag6_lock); | ||
166 | 112 | ||
167 | mod_timer(&nf_ct_frag6_secret_timer, now + nf_ct_frag6_secret_interval); | 113 | nq = container_of(q, struct nf_ct_frag6_queue, q); |
114 | return ip6qhashfn(nq->id, &nq->saddr, &nq->daddr); | ||
168 | } | 115 | } |
169 | 116 | ||
170 | atomic_t nf_ct_frag6_mem = ATOMIC_INIT(0); | 117 | static void nf_skb_free(struct sk_buff *skb) |
171 | |||
172 | /* Memory Tracking Functions. */ | ||
173 | static inline void frag_kfree_skb(struct sk_buff *skb, unsigned int *work) | ||
174 | { | 118 | { |
175 | if (work) | ||
176 | *work -= skb->truesize; | ||
177 | atomic_sub(skb->truesize, &nf_ct_frag6_mem); | ||
178 | if (NFCT_FRAG6_CB(skb)->orig) | 119 | if (NFCT_FRAG6_CB(skb)->orig) |
179 | kfree_skb(NFCT_FRAG6_CB(skb)->orig); | 120 | kfree_skb(NFCT_FRAG6_CB(skb)->orig); |
180 | |||
181 | kfree_skb(skb); | ||
182 | } | 121 | } |
183 | 122 | ||
184 | static inline void frag_free_queue(struct nf_ct_frag6_queue *fq, | 123 | /* Memory Tracking Functions. */ |
185 | unsigned int *work) | 124 | static inline void frag_kfree_skb(struct sk_buff *skb, unsigned int *work) |
186 | { | 125 | { |
187 | if (work) | 126 | if (work) |
188 | *work -= sizeof(struct nf_ct_frag6_queue); | 127 | *work -= skb->truesize; |
189 | atomic_sub(sizeof(struct nf_ct_frag6_queue), &nf_ct_frag6_mem); | 128 | atomic_sub(skb->truesize, &nf_frags.mem); |
190 | kfree(fq); | 129 | nf_skb_free(skb); |
191 | } | 130 | kfree_skb(skb); |
192 | |||
193 | static inline struct nf_ct_frag6_queue *frag_alloc_queue(void) | ||
194 | { | ||
195 | struct nf_ct_frag6_queue *fq = kmalloc(sizeof(struct nf_ct_frag6_queue), GFP_ATOMIC); | ||
196 | |||
197 | if (!fq) | ||
198 | return NULL; | ||
199 | atomic_add(sizeof(struct nf_ct_frag6_queue), &nf_ct_frag6_mem); | ||
200 | return fq; | ||
201 | } | 131 | } |
202 | 132 | ||
203 | /* Destruction primitives. */ | 133 | /* Destruction primitives. */ |
204 | 134 | ||
205 | /* Complete destruction of fq. */ | 135 | static __inline__ void fq_put(struct nf_ct_frag6_queue *fq) |
206 | static void nf_ct_frag6_destroy(struct nf_ct_frag6_queue *fq, | ||
207 | unsigned int *work) | ||
208 | { | 136 | { |
209 | struct sk_buff *fp; | 137 | inet_frag_put(&fq->q, &nf_frags); |
210 | |||
211 | BUG_TRAP(fq->last_in&COMPLETE); | ||
212 | BUG_TRAP(del_timer(&fq->timer) == 0); | ||
213 | |||
214 | /* Release all fragment data. */ | ||
215 | fp = fq->fragments; | ||
216 | while (fp) { | ||
217 | struct sk_buff *xp = fp->next; | ||
218 | |||
219 | frag_kfree_skb(fp, work); | ||
220 | fp = xp; | ||
221 | } | ||
222 | |||
223 | frag_free_queue(fq, work); | ||
224 | } | ||
225 | |||
226 | static __inline__ void fq_put(struct nf_ct_frag6_queue *fq, unsigned int *work) | ||
227 | { | ||
228 | if (atomic_dec_and_test(&fq->refcnt)) | ||
229 | nf_ct_frag6_destroy(fq, work); | ||
230 | } | 138 | } |
231 | 139 | ||
232 | /* Kill fq entry. It is not destroyed immediately, | 140 | /* Kill fq entry. It is not destroyed immediately, |
@@ -234,151 +142,58 @@ static __inline__ void fq_put(struct nf_ct_frag6_queue *fq, unsigned int *work) | |||
234 | */ | 142 | */ |
235 | static __inline__ void fq_kill(struct nf_ct_frag6_queue *fq) | 143 | static __inline__ void fq_kill(struct nf_ct_frag6_queue *fq) |
236 | { | 144 | { |
237 | if (del_timer(&fq->timer)) | 145 | inet_frag_kill(&fq->q, &nf_frags); |
238 | atomic_dec(&fq->refcnt); | ||
239 | |||
240 | if (!(fq->last_in & COMPLETE)) { | ||
241 | fq_unlink(fq); | ||
242 | atomic_dec(&fq->refcnt); | ||
243 | fq->last_in |= COMPLETE; | ||
244 | } | ||
245 | } | 146 | } |
246 | 147 | ||
247 | static void nf_ct_frag6_evictor(void) | 148 | static void nf_ct_frag6_evictor(void) |
248 | { | 149 | { |
249 | struct nf_ct_frag6_queue *fq; | 150 | inet_frag_evictor(&nf_frags); |
250 | struct list_head *tmp; | ||
251 | unsigned int work; | ||
252 | |||
253 | work = atomic_read(&nf_ct_frag6_mem); | ||
254 | if (work <= nf_ct_frag6_low_thresh) | ||
255 | return; | ||
256 | |||
257 | work -= nf_ct_frag6_low_thresh; | ||
258 | while (work > 0) { | ||
259 | read_lock(&nf_ct_frag6_lock); | ||
260 | if (list_empty(&nf_ct_frag6_lru_list)) { | ||
261 | read_unlock(&nf_ct_frag6_lock); | ||
262 | return; | ||
263 | } | ||
264 | tmp = nf_ct_frag6_lru_list.next; | ||
265 | BUG_ON(tmp == NULL); | ||
266 | fq = list_entry(tmp, struct nf_ct_frag6_queue, lru_list); | ||
267 | atomic_inc(&fq->refcnt); | ||
268 | read_unlock(&nf_ct_frag6_lock); | ||
269 | |||
270 | spin_lock(&fq->lock); | ||
271 | if (!(fq->last_in&COMPLETE)) | ||
272 | fq_kill(fq); | ||
273 | spin_unlock(&fq->lock); | ||
274 | |||
275 | fq_put(fq, &work); | ||
276 | } | ||
277 | } | 151 | } |
278 | 152 | ||
279 | static void nf_ct_frag6_expire(unsigned long data) | 153 | static void nf_ct_frag6_expire(unsigned long data) |
280 | { | 154 | { |
281 | struct nf_ct_frag6_queue *fq = (struct nf_ct_frag6_queue *) data; | 155 | struct nf_ct_frag6_queue *fq; |
156 | |||
157 | fq = container_of((struct inet_frag_queue *)data, | ||
158 | struct nf_ct_frag6_queue, q); | ||
282 | 159 | ||
283 | spin_lock(&fq->lock); | 160 | spin_lock(&fq->q.lock); |
284 | 161 | ||
285 | if (fq->last_in & COMPLETE) | 162 | if (fq->q.last_in & COMPLETE) |
286 | goto out; | 163 | goto out; |
287 | 164 | ||
288 | fq_kill(fq); | 165 | fq_kill(fq); |
289 | 166 | ||
290 | out: | 167 | out: |
291 | spin_unlock(&fq->lock); | 168 | spin_unlock(&fq->q.lock); |
292 | fq_put(fq, NULL); | 169 | fq_put(fq); |
293 | } | 170 | } |
294 | 171 | ||
295 | /* Creation primitives. */ | 172 | /* Creation primitives. */ |
296 | 173 | ||
297 | static struct nf_ct_frag6_queue *nf_ct_frag6_intern(unsigned int hash, | 174 | static __inline__ struct nf_ct_frag6_queue * |
298 | struct nf_ct_frag6_queue *fq_in) | 175 | fq_find(__be32 id, struct in6_addr *src, struct in6_addr *dst) |
299 | { | 176 | { |
300 | struct nf_ct_frag6_queue *fq; | 177 | struct inet_frag_queue *q; |
301 | #ifdef CONFIG_SMP | 178 | struct ip6_create_arg arg; |
302 | struct hlist_node *n; | 179 | unsigned int hash; |
303 | #endif | ||
304 | |||
305 | write_lock(&nf_ct_frag6_lock); | ||
306 | #ifdef CONFIG_SMP | ||
307 | hlist_for_each_entry(fq, n, &nf_ct_frag6_hash[hash], list) { | ||
308 | if (fq->id == fq_in->id && | ||
309 | ipv6_addr_equal(&fq_in->saddr, &fq->saddr) && | ||
310 | ipv6_addr_equal(&fq_in->daddr, &fq->daddr)) { | ||
311 | atomic_inc(&fq->refcnt); | ||
312 | write_unlock(&nf_ct_frag6_lock); | ||
313 | fq_in->last_in |= COMPLETE; | ||
314 | fq_put(fq_in, NULL); | ||
315 | return fq; | ||
316 | } | ||
317 | } | ||
318 | #endif | ||
319 | fq = fq_in; | ||
320 | |||
321 | if (!mod_timer(&fq->timer, jiffies + nf_ct_frag6_timeout)) | ||
322 | atomic_inc(&fq->refcnt); | ||
323 | |||
324 | atomic_inc(&fq->refcnt); | ||
325 | hlist_add_head(&fq->list, &nf_ct_frag6_hash[hash]); | ||
326 | INIT_LIST_HEAD(&fq->lru_list); | ||
327 | list_add_tail(&fq->lru_list, &nf_ct_frag6_lru_list); | ||
328 | nf_ct_frag6_nqueues++; | ||
329 | write_unlock(&nf_ct_frag6_lock); | ||
330 | return fq; | ||
331 | } | ||
332 | 180 | ||
181 | arg.id = id; | ||
182 | arg.src = src; | ||
183 | arg.dst = dst; | ||
184 | hash = ip6qhashfn(id, src, dst); | ||
333 | 185 | ||
334 | static struct nf_ct_frag6_queue * | 186 | q = inet_frag_find(&nf_frags, &arg, hash); |
335 | nf_ct_frag6_create(unsigned int hash, __be32 id, struct in6_addr *src, struct in6_addr *dst) | 187 | if (q == NULL) |
336 | { | ||
337 | struct nf_ct_frag6_queue *fq; | ||
338 | |||
339 | if ((fq = frag_alloc_queue()) == NULL) { | ||
340 | pr_debug("Can't alloc new queue\n"); | ||
341 | goto oom; | 188 | goto oom; |
342 | } | ||
343 | |||
344 | memset(fq, 0, sizeof(struct nf_ct_frag6_queue)); | ||
345 | |||
346 | fq->id = id; | ||
347 | ipv6_addr_copy(&fq->saddr, src); | ||
348 | ipv6_addr_copy(&fq->daddr, dst); | ||
349 | 189 | ||
350 | setup_timer(&fq->timer, nf_ct_frag6_expire, (unsigned long)fq); | 190 | return container_of(q, struct nf_ct_frag6_queue, q); |
351 | spin_lock_init(&fq->lock); | ||
352 | atomic_set(&fq->refcnt, 1); | ||
353 | |||
354 | return nf_ct_frag6_intern(hash, fq); | ||
355 | 191 | ||
356 | oom: | 192 | oom: |
193 | pr_debug("Can't alloc new queue\n"); | ||
357 | return NULL; | 194 | return NULL; |
358 | } | 195 | } |
359 | 196 | ||
360 | static __inline__ struct nf_ct_frag6_queue * | ||
361 | fq_find(__be32 id, struct in6_addr *src, struct in6_addr *dst) | ||
362 | { | ||
363 | struct nf_ct_frag6_queue *fq; | ||
364 | struct hlist_node *n; | ||
365 | unsigned int hash = ip6qhashfn(id, src, dst); | ||
366 | |||
367 | read_lock(&nf_ct_frag6_lock); | ||
368 | hlist_for_each_entry(fq, n, &nf_ct_frag6_hash[hash], list) { | ||
369 | if (fq->id == id && | ||
370 | ipv6_addr_equal(src, &fq->saddr) && | ||
371 | ipv6_addr_equal(dst, &fq->daddr)) { | ||
372 | atomic_inc(&fq->refcnt); | ||
373 | read_unlock(&nf_ct_frag6_lock); | ||
374 | return fq; | ||
375 | } | ||
376 | } | ||
377 | read_unlock(&nf_ct_frag6_lock); | ||
378 | |||
379 | return nf_ct_frag6_create(hash, id, src, dst); | ||
380 | } | ||
381 | |||
382 | 197 | ||
383 | static int nf_ct_frag6_queue(struct nf_ct_frag6_queue *fq, struct sk_buff *skb, | 198 | static int nf_ct_frag6_queue(struct nf_ct_frag6_queue *fq, struct sk_buff *skb, |
384 | struct frag_hdr *fhdr, int nhoff) | 199 | struct frag_hdr *fhdr, int nhoff) |
@@ -386,7 +201,7 @@ static int nf_ct_frag6_queue(struct nf_ct_frag6_queue *fq, struct sk_buff *skb, | |||
386 | struct sk_buff *prev, *next; | 201 | struct sk_buff *prev, *next; |
387 | int offset, end; | 202 | int offset, end; |
388 | 203 | ||
389 | if (fq->last_in & COMPLETE) { | 204 | if (fq->q.last_in & COMPLETE) { |
390 | pr_debug("Allready completed\n"); | 205 | pr_debug("Allready completed\n"); |
391 | goto err; | 206 | goto err; |
392 | } | 207 | } |
@@ -412,13 +227,13 @@ static int nf_ct_frag6_queue(struct nf_ct_frag6_queue *fq, struct sk_buff *skb, | |||
412 | /* If we already have some bits beyond end | 227 | /* If we already have some bits beyond end |
413 | * or have different end, the segment is corrupted. | 228 | * or have different end, the segment is corrupted. |
414 | */ | 229 | */ |
415 | if (end < fq->len || | 230 | if (end < fq->q.len || |
416 | ((fq->last_in & LAST_IN) && end != fq->len)) { | 231 | ((fq->q.last_in & LAST_IN) && end != fq->q.len)) { |
417 | pr_debug("already received last fragment\n"); | 232 | pr_debug("already received last fragment\n"); |
418 | goto err; | 233 | goto err; |
419 | } | 234 | } |
420 | fq->last_in |= LAST_IN; | 235 | fq->q.last_in |= LAST_IN; |
421 | fq->len = end; | 236 | fq->q.len = end; |
422 | } else { | 237 | } else { |
423 | /* Check if the fragment is rounded to 8 bytes. | 238 | /* Check if the fragment is rounded to 8 bytes. |
424 | * Required by the RFC. | 239 | * Required by the RFC. |
@@ -430,13 +245,13 @@ static int nf_ct_frag6_queue(struct nf_ct_frag6_queue *fq, struct sk_buff *skb, | |||
430 | pr_debug("end of fragment not rounded to 8 bytes.\n"); | 245 | pr_debug("end of fragment not rounded to 8 bytes.\n"); |
431 | return -1; | 246 | return -1; |
432 | } | 247 | } |
433 | if (end > fq->len) { | 248 | if (end > fq->q.len) { |
434 | /* Some bits beyond end -> corruption. */ | 249 | /* Some bits beyond end -> corruption. */ |
435 | if (fq->last_in & LAST_IN) { | 250 | if (fq->q.last_in & LAST_IN) { |
436 | pr_debug("last packet already reached.\n"); | 251 | pr_debug("last packet already reached.\n"); |
437 | goto err; | 252 | goto err; |
438 | } | 253 | } |
439 | fq->len = end; | 254 | fq->q.len = end; |
440 | } | 255 | } |
441 | } | 256 | } |
442 | 257 | ||
@@ -458,7 +273,7 @@ static int nf_ct_frag6_queue(struct nf_ct_frag6_queue *fq, struct sk_buff *skb, | |||
458 | * this fragment, right? | 273 | * this fragment, right? |
459 | */ | 274 | */ |
460 | prev = NULL; | 275 | prev = NULL; |
461 | for (next = fq->fragments; next != NULL; next = next->next) { | 276 | for (next = fq->q.fragments; next != NULL; next = next->next) { |
462 | if (NFCT_FRAG6_CB(next)->offset >= offset) | 277 | if (NFCT_FRAG6_CB(next)->offset >= offset) |
463 | break; /* bingo! */ | 278 | break; /* bingo! */ |
464 | prev = next; | 279 | prev = next; |
@@ -503,7 +318,7 @@ static int nf_ct_frag6_queue(struct nf_ct_frag6_queue *fq, struct sk_buff *skb, | |||
503 | 318 | ||
504 | /* next fragment */ | 319 | /* next fragment */ |
505 | NFCT_FRAG6_CB(next)->offset += i; | 320 | NFCT_FRAG6_CB(next)->offset += i; |
506 | fq->meat -= i; | 321 | fq->q.meat -= i; |
507 | if (next->ip_summed != CHECKSUM_UNNECESSARY) | 322 | if (next->ip_summed != CHECKSUM_UNNECESSARY) |
508 | next->ip_summed = CHECKSUM_NONE; | 323 | next->ip_summed = CHECKSUM_NONE; |
509 | break; | 324 | break; |
@@ -518,9 +333,9 @@ static int nf_ct_frag6_queue(struct nf_ct_frag6_queue *fq, struct sk_buff *skb, | |||
518 | if (prev) | 333 | if (prev) |
519 | prev->next = next; | 334 | prev->next = next; |
520 | else | 335 | else |
521 | fq->fragments = next; | 336 | fq->q.fragments = next; |
522 | 337 | ||
523 | fq->meat -= free_it->len; | 338 | fq->q.meat -= free_it->len; |
524 | frag_kfree_skb(free_it, NULL); | 339 | frag_kfree_skb(free_it, NULL); |
525 | } | 340 | } |
526 | } | 341 | } |
@@ -532,23 +347,23 @@ static int nf_ct_frag6_queue(struct nf_ct_frag6_queue *fq, struct sk_buff *skb, | |||
532 | if (prev) | 347 | if (prev) |
533 | prev->next = skb; | 348 | prev->next = skb; |
534 | else | 349 | else |
535 | fq->fragments = skb; | 350 | fq->q.fragments = skb; |
536 | 351 | ||
537 | skb->dev = NULL; | 352 | skb->dev = NULL; |
538 | fq->stamp = skb->tstamp; | 353 | fq->q.stamp = skb->tstamp; |
539 | fq->meat += skb->len; | 354 | fq->q.meat += skb->len; |
540 | atomic_add(skb->truesize, &nf_ct_frag6_mem); | 355 | atomic_add(skb->truesize, &nf_frags.mem); |
541 | 356 | ||
542 | /* The first fragment. | 357 | /* The first fragment. |
543 | * nhoffset is obtained from the first fragment, of course. | 358 | * nhoffset is obtained from the first fragment, of course. |
544 | */ | 359 | */ |
545 | if (offset == 0) { | 360 | if (offset == 0) { |
546 | fq->nhoffset = nhoff; | 361 | fq->nhoffset = nhoff; |
547 | fq->last_in |= FIRST_IN; | 362 | fq->q.last_in |= FIRST_IN; |
548 | } | 363 | } |
549 | write_lock(&nf_ct_frag6_lock); | 364 | write_lock(&nf_frags.lock); |
550 | list_move_tail(&fq->lru_list, &nf_ct_frag6_lru_list); | 365 | list_move_tail(&fq->q.lru_list, &nf_frags.lru_list); |
551 | write_unlock(&nf_ct_frag6_lock); | 366 | write_unlock(&nf_frags.lock); |
552 | return 0; | 367 | return 0; |
553 | 368 | ||
554 | err: | 369 | err: |
@@ -567,7 +382,7 @@ err: | |||
567 | static struct sk_buff * | 382 | static struct sk_buff * |
568 | nf_ct_frag6_reasm(struct nf_ct_frag6_queue *fq, struct net_device *dev) | 383 | nf_ct_frag6_reasm(struct nf_ct_frag6_queue *fq, struct net_device *dev) |
569 | { | 384 | { |
570 | struct sk_buff *fp, *op, *head = fq->fragments; | 385 | struct sk_buff *fp, *op, *head = fq->q.fragments; |
571 | int payload_len; | 386 | int payload_len; |
572 | 387 | ||
573 | fq_kill(fq); | 388 | fq_kill(fq); |
@@ -577,7 +392,7 @@ nf_ct_frag6_reasm(struct nf_ct_frag6_queue *fq, struct net_device *dev) | |||
577 | 392 | ||
578 | /* Unfragmented part is taken from the first segment. */ | 393 | /* Unfragmented part is taken from the first segment. */ |
579 | payload_len = ((head->data - skb_network_header(head)) - | 394 | payload_len = ((head->data - skb_network_header(head)) - |
580 | sizeof(struct ipv6hdr) + fq->len - | 395 | sizeof(struct ipv6hdr) + fq->q.len - |
581 | sizeof(struct frag_hdr)); | 396 | sizeof(struct frag_hdr)); |
582 | if (payload_len > IPV6_MAXPLEN) { | 397 | if (payload_len > IPV6_MAXPLEN) { |
583 | pr_debug("payload len is too large.\n"); | 398 | pr_debug("payload len is too large.\n"); |
@@ -614,7 +429,7 @@ nf_ct_frag6_reasm(struct nf_ct_frag6_queue *fq, struct net_device *dev) | |||
614 | clone->ip_summed = head->ip_summed; | 429 | clone->ip_summed = head->ip_summed; |
615 | 430 | ||
616 | NFCT_FRAG6_CB(clone)->orig = NULL; | 431 | NFCT_FRAG6_CB(clone)->orig = NULL; |
617 | atomic_add(clone->truesize, &nf_ct_frag6_mem); | 432 | atomic_add(clone->truesize, &nf_frags.mem); |
618 | } | 433 | } |
619 | 434 | ||
620 | /* We have to remove fragment header from datagram and to relocate | 435 | /* We have to remove fragment header from datagram and to relocate |
@@ -628,7 +443,7 @@ nf_ct_frag6_reasm(struct nf_ct_frag6_queue *fq, struct net_device *dev) | |||
628 | skb_shinfo(head)->frag_list = head->next; | 443 | skb_shinfo(head)->frag_list = head->next; |
629 | skb_reset_transport_header(head); | 444 | skb_reset_transport_header(head); |
630 | skb_push(head, head->data - skb_network_header(head)); | 445 | skb_push(head, head->data - skb_network_header(head)); |
631 | atomic_sub(head->truesize, &nf_ct_frag6_mem); | 446 | atomic_sub(head->truesize, &nf_frags.mem); |
632 | 447 | ||
633 | for (fp=head->next; fp; fp = fp->next) { | 448 | for (fp=head->next; fp; fp = fp->next) { |
634 | head->data_len += fp->len; | 449 | head->data_len += fp->len; |
@@ -638,12 +453,12 @@ nf_ct_frag6_reasm(struct nf_ct_frag6_queue *fq, struct net_device *dev) | |||
638 | else if (head->ip_summed == CHECKSUM_COMPLETE) | 453 | else if (head->ip_summed == CHECKSUM_COMPLETE) |
639 | head->csum = csum_add(head->csum, fp->csum); | 454 | head->csum = csum_add(head->csum, fp->csum); |
640 | head->truesize += fp->truesize; | 455 | head->truesize += fp->truesize; |
641 | atomic_sub(fp->truesize, &nf_ct_frag6_mem); | 456 | atomic_sub(fp->truesize, &nf_frags.mem); |
642 | } | 457 | } |
643 | 458 | ||
644 | head->next = NULL; | 459 | head->next = NULL; |
645 | head->dev = dev; | 460 | head->dev = dev; |
646 | head->tstamp = fq->stamp; | 461 | head->tstamp = fq->q.stamp; |
647 | ipv6_hdr(head)->payload_len = htons(payload_len); | 462 | ipv6_hdr(head)->payload_len = htons(payload_len); |
648 | 463 | ||
649 | /* Yes, and fold redundant checksum back. 8) */ | 464 | /* Yes, and fold redundant checksum back. 8) */ |
@@ -652,7 +467,7 @@ nf_ct_frag6_reasm(struct nf_ct_frag6_queue *fq, struct net_device *dev) | |||
652 | skb_network_header_len(head), | 467 | skb_network_header_len(head), |
653 | head->csum); | 468 | head->csum); |
654 | 469 | ||
655 | fq->fragments = NULL; | 470 | fq->q.fragments = NULL; |
656 | 471 | ||
657 | /* all original skbs are linked into the NFCT_FRAG6_CB(head).orig */ | 472 | /* all original skbs are linked into the NFCT_FRAG6_CB(head).orig */ |
658 | fp = skb_shinfo(head)->frag_list; | 473 | fp = skb_shinfo(head)->frag_list; |
@@ -788,7 +603,7 @@ struct sk_buff *nf_ct_frag6_gather(struct sk_buff *skb) | |||
788 | goto ret_orig; | 603 | goto ret_orig; |
789 | } | 604 | } |
790 | 605 | ||
791 | if (atomic_read(&nf_ct_frag6_mem) > nf_ct_frag6_high_thresh) | 606 | if (atomic_read(&nf_frags.mem) > nf_frags_ctl.high_thresh) |
792 | nf_ct_frag6_evictor(); | 607 | nf_ct_frag6_evictor(); |
793 | 608 | ||
794 | fq = fq_find(fhdr->identification, &hdr->saddr, &hdr->daddr); | 609 | fq = fq_find(fhdr->identification, &hdr->saddr, &hdr->daddr); |
@@ -797,23 +612,23 @@ struct sk_buff *nf_ct_frag6_gather(struct sk_buff *skb) | |||
797 | goto ret_orig; | 612 | goto ret_orig; |
798 | } | 613 | } |
799 | 614 | ||
800 | spin_lock(&fq->lock); | 615 | spin_lock(&fq->q.lock); |
801 | 616 | ||
802 | if (nf_ct_frag6_queue(fq, clone, fhdr, nhoff) < 0) { | 617 | if (nf_ct_frag6_queue(fq, clone, fhdr, nhoff) < 0) { |
803 | spin_unlock(&fq->lock); | 618 | spin_unlock(&fq->q.lock); |
804 | pr_debug("Can't insert skb to queue\n"); | 619 | pr_debug("Can't insert skb to queue\n"); |
805 | fq_put(fq, NULL); | 620 | fq_put(fq); |
806 | goto ret_orig; | 621 | goto ret_orig; |
807 | } | 622 | } |
808 | 623 | ||
809 | if (fq->last_in == (FIRST_IN|LAST_IN) && fq->meat == fq->len) { | 624 | if (fq->q.last_in == (FIRST_IN|LAST_IN) && fq->q.meat == fq->q.len) { |
810 | ret_skb = nf_ct_frag6_reasm(fq, dev); | 625 | ret_skb = nf_ct_frag6_reasm(fq, dev); |
811 | if (ret_skb == NULL) | 626 | if (ret_skb == NULL) |
812 | pr_debug("Can't reassemble fragmented packets\n"); | 627 | pr_debug("Can't reassemble fragmented packets\n"); |
813 | } | 628 | } |
814 | spin_unlock(&fq->lock); | 629 | spin_unlock(&fq->q.lock); |
815 | 630 | ||
816 | fq_put(fq, NULL); | 631 | fq_put(fq); |
817 | return ret_skb; | 632 | return ret_skb; |
818 | 633 | ||
819 | ret_orig: | 634 | ret_orig: |
@@ -859,20 +674,23 @@ int nf_ct_frag6_kfree_frags(struct sk_buff *skb) | |||
859 | 674 | ||
860 | int nf_ct_frag6_init(void) | 675 | int nf_ct_frag6_init(void) |
861 | { | 676 | { |
862 | nf_ct_frag6_hash_rnd = (u32) ((num_physpages ^ (num_physpages>>7)) ^ | 677 | nf_frags.ctl = &nf_frags_ctl; |
863 | (jiffies ^ (jiffies >> 6))); | 678 | nf_frags.hashfn = nf_hashfn; |
864 | 679 | nf_frags.constructor = ip6_frag_init; | |
865 | setup_timer(&nf_ct_frag6_secret_timer, nf_ct_frag6_secret_rebuild, 0); | 680 | nf_frags.destructor = NULL; |
866 | nf_ct_frag6_secret_timer.expires = jiffies | 681 | nf_frags.skb_free = nf_skb_free; |
867 | + nf_ct_frag6_secret_interval; | 682 | nf_frags.qsize = sizeof(struct nf_ct_frag6_queue); |
868 | add_timer(&nf_ct_frag6_secret_timer); | 683 | nf_frags.match = ip6_frag_match; |
684 | nf_frags.frag_expire = nf_ct_frag6_expire; | ||
685 | inet_frags_init(&nf_frags); | ||
869 | 686 | ||
870 | return 0; | 687 | return 0; |
871 | } | 688 | } |
872 | 689 | ||
873 | void nf_ct_frag6_cleanup(void) | 690 | void nf_ct_frag6_cleanup(void) |
874 | { | 691 | { |
875 | del_timer(&nf_ct_frag6_secret_timer); | 692 | inet_frags_fini(&nf_frags); |
876 | nf_ct_frag6_low_thresh = 0; | 693 | |
694 | nf_frags_ctl.low_thresh = 0; | ||
877 | nf_ct_frag6_evictor(); | 695 | nf_ct_frag6_evictor(); |
878 | } | 696 | } |
diff --git a/net/ipv6/proc.c b/net/ipv6/proc.c index db945018579e..be526ad92543 100644 --- a/net/ipv6/proc.c +++ b/net/ipv6/proc.c | |||
@@ -54,7 +54,7 @@ static int sockstat6_seq_show(struct seq_file *seq, void *v) | |||
54 | seq_printf(seq, "RAW6: inuse %d\n", | 54 | seq_printf(seq, "RAW6: inuse %d\n", |
55 | fold_prot_inuse(&rawv6_prot)); | 55 | fold_prot_inuse(&rawv6_prot)); |
56 | seq_printf(seq, "FRAG6: inuse %d memory %d\n", | 56 | seq_printf(seq, "FRAG6: inuse %d memory %d\n", |
57 | ip6_frag_nqueues, atomic_read(&ip6_frag_mem)); | 57 | ip6_frag_nqueues(), ip6_frag_mem()); |
58 | return 0; | 58 | return 0; |
59 | } | 59 | } |
60 | 60 | ||
diff --git a/net/ipv6/reassembly.c b/net/ipv6/reassembly.c index 31601c993541..76c88a93b9b5 100644 --- a/net/ipv6/reassembly.c +++ b/net/ipv6/reassembly.c | |||
@@ -42,6 +42,7 @@ | |||
42 | #include <linux/icmpv6.h> | 42 | #include <linux/icmpv6.h> |
43 | #include <linux/random.h> | 43 | #include <linux/random.h> |
44 | #include <linux/jhash.h> | 44 | #include <linux/jhash.h> |
45 | #include <linux/skbuff.h> | ||
45 | 46 | ||
46 | #include <net/sock.h> | 47 | #include <net/sock.h> |
47 | #include <net/snmp.h> | 48 | #include <net/snmp.h> |
@@ -53,11 +54,7 @@ | |||
53 | #include <net/rawv6.h> | 54 | #include <net/rawv6.h> |
54 | #include <net/ndisc.h> | 55 | #include <net/ndisc.h> |
55 | #include <net/addrconf.h> | 56 | #include <net/addrconf.h> |
56 | 57 | #include <net/inet_frag.h> | |
57 | int sysctl_ip6frag_high_thresh __read_mostly = 256*1024; | ||
58 | int sysctl_ip6frag_low_thresh __read_mostly = 192*1024; | ||
59 | |||
60 | int sysctl_ip6frag_time __read_mostly = IPV6_FRAG_TIMEOUT; | ||
61 | 58 | ||
62 | struct ip6frag_skb_cb | 59 | struct ip6frag_skb_cb |
63 | { | 60 | { |
@@ -74,53 +71,39 @@ struct ip6frag_skb_cb | |||
74 | 71 | ||
75 | struct frag_queue | 72 | struct frag_queue |
76 | { | 73 | { |
77 | struct hlist_node list; | 74 | struct inet_frag_queue q; |
78 | struct list_head lru_list; /* lru list member */ | ||
79 | 75 | ||
80 | __be32 id; /* fragment id */ | 76 | __be32 id; /* fragment id */ |
81 | struct in6_addr saddr; | 77 | struct in6_addr saddr; |
82 | struct in6_addr daddr; | 78 | struct in6_addr daddr; |
83 | 79 | ||
84 | spinlock_t lock; | ||
85 | atomic_t refcnt; | ||
86 | struct timer_list timer; /* expire timer */ | ||
87 | struct sk_buff *fragments; | ||
88 | int len; | ||
89 | int meat; | ||
90 | int iif; | 80 | int iif; |
91 | ktime_t stamp; | ||
92 | unsigned int csum; | 81 | unsigned int csum; |
93 | __u8 last_in; /* has first/last segment arrived? */ | ||
94 | #define COMPLETE 4 | ||
95 | #define FIRST_IN 2 | ||
96 | #define LAST_IN 1 | ||
97 | __u16 nhoffset; | 82 | __u16 nhoffset; |
98 | }; | 83 | }; |
99 | 84 | ||
100 | /* Hash table. */ | 85 | struct inet_frags_ctl ip6_frags_ctl __read_mostly = { |
101 | 86 | .high_thresh = 256 * 1024, | |
102 | #define IP6Q_HASHSZ 64 | 87 | .low_thresh = 192 * 1024, |
88 | .timeout = IPV6_FRAG_TIMEOUT, | ||
89 | .secret_interval = 10 * 60 * HZ, | ||
90 | }; | ||
103 | 91 | ||
104 | static struct hlist_head ip6_frag_hash[IP6Q_HASHSZ]; | 92 | static struct inet_frags ip6_frags; |
105 | static DEFINE_RWLOCK(ip6_frag_lock); | ||
106 | static u32 ip6_frag_hash_rnd; | ||
107 | static LIST_HEAD(ip6_frag_lru_list); | ||
108 | int ip6_frag_nqueues = 0; | ||
109 | 93 | ||
110 | static __inline__ void __fq_unlink(struct frag_queue *fq) | 94 | int ip6_frag_nqueues(void) |
111 | { | 95 | { |
112 | hlist_del(&fq->list); | 96 | return ip6_frags.nqueues; |
113 | list_del(&fq->lru_list); | ||
114 | ip6_frag_nqueues--; | ||
115 | } | 97 | } |
116 | 98 | ||
117 | static __inline__ void fq_unlink(struct frag_queue *fq) | 99 | int ip6_frag_mem(void) |
118 | { | 100 | { |
119 | write_lock(&ip6_frag_lock); | 101 | return atomic_read(&ip6_frags.mem); |
120 | __fq_unlink(fq); | ||
121 | write_unlock(&ip6_frag_lock); | ||
122 | } | 102 | } |
123 | 103 | ||
104 | static int ip6_frag_reasm(struct frag_queue *fq, struct sk_buff *prev, | ||
105 | struct net_device *dev); | ||
106 | |||
124 | /* | 107 | /* |
125 | * callers should be careful not to use the hash value outside the ipfrag_lock | 108 | * callers should be careful not to use the hash value outside the ipfrag_lock |
126 | * as doing so could race with ipfrag_hash_rnd being recalculated. | 109 | * as doing so could race with ipfrag_hash_rnd being recalculated. |
@@ -136,7 +119,7 @@ static unsigned int ip6qhashfn(__be32 id, struct in6_addr *saddr, | |||
136 | 119 | ||
137 | a += JHASH_GOLDEN_RATIO; | 120 | a += JHASH_GOLDEN_RATIO; |
138 | b += JHASH_GOLDEN_RATIO; | 121 | b += JHASH_GOLDEN_RATIO; |
139 | c += ip6_frag_hash_rnd; | 122 | c += ip6_frags.rnd; |
140 | __jhash_mix(a, b, c); | 123 | __jhash_mix(a, b, c); |
141 | 124 | ||
142 | a += (__force u32)saddr->s6_addr32[3]; | 125 | a += (__force u32)saddr->s6_addr32[3]; |
@@ -149,98 +132,54 @@ static unsigned int ip6qhashfn(__be32 id, struct in6_addr *saddr, | |||
149 | c += (__force u32)id; | 132 | c += (__force u32)id; |
150 | __jhash_mix(a, b, c); | 133 | __jhash_mix(a, b, c); |
151 | 134 | ||
152 | return c & (IP6Q_HASHSZ - 1); | 135 | return c & (INETFRAGS_HASHSZ - 1); |
153 | } | 136 | } |
154 | 137 | ||
155 | static struct timer_list ip6_frag_secret_timer; | 138 | static unsigned int ip6_hashfn(struct inet_frag_queue *q) |
156 | int sysctl_ip6frag_secret_interval __read_mostly = 10 * 60 * HZ; | ||
157 | |||
158 | static void ip6_frag_secret_rebuild(unsigned long dummy) | ||
159 | { | 139 | { |
160 | unsigned long now = jiffies; | 140 | struct frag_queue *fq; |
161 | int i; | ||
162 | |||
163 | write_lock(&ip6_frag_lock); | ||
164 | get_random_bytes(&ip6_frag_hash_rnd, sizeof(u32)); | ||
165 | for (i = 0; i < IP6Q_HASHSZ; i++) { | ||
166 | struct frag_queue *q; | ||
167 | struct hlist_node *p, *n; | ||
168 | |||
169 | hlist_for_each_entry_safe(q, p, n, &ip6_frag_hash[i], list) { | ||
170 | unsigned int hval = ip6qhashfn(q->id, | ||
171 | &q->saddr, | ||
172 | &q->daddr); | ||
173 | |||
174 | if (hval != i) { | ||
175 | hlist_del(&q->list); | ||
176 | 141 | ||
177 | /* Relink to new hash chain. */ | 142 | fq = container_of(q, struct frag_queue, q); |
178 | hlist_add_head(&q->list, | 143 | return ip6qhashfn(fq->id, &fq->saddr, &fq->daddr); |
179 | &ip6_frag_hash[hval]); | 144 | } |
180 | 145 | ||
181 | } | 146 | int ip6_frag_match(struct inet_frag_queue *q, void *a) |
182 | } | 147 | { |
183 | } | 148 | struct frag_queue *fq; |
184 | write_unlock(&ip6_frag_lock); | 149 | struct ip6_create_arg *arg = a; |
185 | 150 | ||
186 | mod_timer(&ip6_frag_secret_timer, now + sysctl_ip6frag_secret_interval); | 151 | fq = container_of(q, struct frag_queue, q); |
152 | return (fq->id == arg->id && | ||
153 | ipv6_addr_equal(&fq->saddr, arg->src) && | ||
154 | ipv6_addr_equal(&fq->daddr, arg->dst)); | ||
187 | } | 155 | } |
188 | 156 | EXPORT_SYMBOL(ip6_frag_match); | |
189 | atomic_t ip6_frag_mem = ATOMIC_INIT(0); | ||
190 | 157 | ||
191 | /* Memory Tracking Functions. */ | 158 | /* Memory Tracking Functions. */ |
192 | static inline void frag_kfree_skb(struct sk_buff *skb, int *work) | 159 | static inline void frag_kfree_skb(struct sk_buff *skb, int *work) |
193 | { | 160 | { |
194 | if (work) | 161 | if (work) |
195 | *work -= skb->truesize; | 162 | *work -= skb->truesize; |
196 | atomic_sub(skb->truesize, &ip6_frag_mem); | 163 | atomic_sub(skb->truesize, &ip6_frags.mem); |
197 | kfree_skb(skb); | 164 | kfree_skb(skb); |
198 | } | 165 | } |
199 | 166 | ||
200 | static inline void frag_free_queue(struct frag_queue *fq, int *work) | 167 | void ip6_frag_init(struct inet_frag_queue *q, void *a) |
201 | { | 168 | { |
202 | if (work) | 169 | struct frag_queue *fq = container_of(q, struct frag_queue, q); |
203 | *work -= sizeof(struct frag_queue); | 170 | struct ip6_create_arg *arg = a; |
204 | atomic_sub(sizeof(struct frag_queue), &ip6_frag_mem); | ||
205 | kfree(fq); | ||
206 | } | ||
207 | 171 | ||
208 | static inline struct frag_queue *frag_alloc_queue(void) | 172 | fq->id = arg->id; |
209 | { | 173 | ipv6_addr_copy(&fq->saddr, arg->src); |
210 | struct frag_queue *fq = kzalloc(sizeof(struct frag_queue), GFP_ATOMIC); | 174 | ipv6_addr_copy(&fq->daddr, arg->dst); |
211 | |||
212 | if(!fq) | ||
213 | return NULL; | ||
214 | atomic_add(sizeof(struct frag_queue), &ip6_frag_mem); | ||
215 | return fq; | ||
216 | } | 175 | } |
176 | EXPORT_SYMBOL(ip6_frag_init); | ||
217 | 177 | ||
218 | /* Destruction primitives. */ | 178 | /* Destruction primitives. */ |
219 | 179 | ||
220 | /* Complete destruction of fq. */ | 180 | static __inline__ void fq_put(struct frag_queue *fq) |
221 | static void ip6_frag_destroy(struct frag_queue *fq, int *work) | ||
222 | { | 181 | { |
223 | struct sk_buff *fp; | 182 | inet_frag_put(&fq->q, &ip6_frags); |
224 | |||
225 | BUG_TRAP(fq->last_in&COMPLETE); | ||
226 | BUG_TRAP(del_timer(&fq->timer) == 0); | ||
227 | |||
228 | /* Release all fragment data. */ | ||
229 | fp = fq->fragments; | ||
230 | while (fp) { | ||
231 | struct sk_buff *xp = fp->next; | ||
232 | |||
233 | frag_kfree_skb(fp, work); | ||
234 | fp = xp; | ||
235 | } | ||
236 | |||
237 | frag_free_queue(fq, work); | ||
238 | } | ||
239 | |||
240 | static __inline__ void fq_put(struct frag_queue *fq, int *work) | ||
241 | { | ||
242 | if (atomic_dec_and_test(&fq->refcnt)) | ||
243 | ip6_frag_destroy(fq, work); | ||
244 | } | 183 | } |
245 | 184 | ||
246 | /* Kill fq entry. It is not destroyed immediately, | 185 | /* Kill fq entry. It is not destroyed immediately, |
@@ -248,55 +187,28 @@ static __inline__ void fq_put(struct frag_queue *fq, int *work) | |||
248 | */ | 187 | */ |
249 | static __inline__ void fq_kill(struct frag_queue *fq) | 188 | static __inline__ void fq_kill(struct frag_queue *fq) |
250 | { | 189 | { |
251 | if (del_timer(&fq->timer)) | 190 | inet_frag_kill(&fq->q, &ip6_frags); |
252 | atomic_dec(&fq->refcnt); | ||
253 | |||
254 | if (!(fq->last_in & COMPLETE)) { | ||
255 | fq_unlink(fq); | ||
256 | atomic_dec(&fq->refcnt); | ||
257 | fq->last_in |= COMPLETE; | ||
258 | } | ||
259 | } | 191 | } |
260 | 192 | ||
261 | static void ip6_evictor(struct inet6_dev *idev) | 193 | static void ip6_evictor(struct inet6_dev *idev) |
262 | { | 194 | { |
263 | struct frag_queue *fq; | 195 | int evicted; |
264 | struct list_head *tmp; | 196 | |
265 | int work; | 197 | evicted = inet_frag_evictor(&ip6_frags); |
266 | 198 | if (evicted) | |
267 | work = atomic_read(&ip6_frag_mem) - sysctl_ip6frag_low_thresh; | 199 | IP6_ADD_STATS_BH(idev, IPSTATS_MIB_REASMFAILS, evicted); |
268 | if (work <= 0) | ||
269 | return; | ||
270 | |||
271 | while(work > 0) { | ||
272 | read_lock(&ip6_frag_lock); | ||
273 | if (list_empty(&ip6_frag_lru_list)) { | ||
274 | read_unlock(&ip6_frag_lock); | ||
275 | return; | ||
276 | } | ||
277 | tmp = ip6_frag_lru_list.next; | ||
278 | fq = list_entry(tmp, struct frag_queue, lru_list); | ||
279 | atomic_inc(&fq->refcnt); | ||
280 | read_unlock(&ip6_frag_lock); | ||
281 | |||
282 | spin_lock(&fq->lock); | ||
283 | if (!(fq->last_in&COMPLETE)) | ||
284 | fq_kill(fq); | ||
285 | spin_unlock(&fq->lock); | ||
286 | |||
287 | fq_put(fq, &work); | ||
288 | IP6_INC_STATS_BH(idev, IPSTATS_MIB_REASMFAILS); | ||
289 | } | ||
290 | } | 200 | } |
291 | 201 | ||
292 | static void ip6_frag_expire(unsigned long data) | 202 | static void ip6_frag_expire(unsigned long data) |
293 | { | 203 | { |
294 | struct frag_queue *fq = (struct frag_queue *) data; | 204 | struct frag_queue *fq; |
295 | struct net_device *dev = NULL; | 205 | struct net_device *dev = NULL; |
296 | 206 | ||
297 | spin_lock(&fq->lock); | 207 | fq = container_of((struct inet_frag_queue *)data, struct frag_queue, q); |
208 | |||
209 | spin_lock(&fq->q.lock); | ||
298 | 210 | ||
299 | if (fq->last_in & COMPLETE) | 211 | if (fq->q.last_in & COMPLETE) |
300 | goto out; | 212 | goto out; |
301 | 213 | ||
302 | fq_kill(fq); | 214 | fq_kill(fq); |
@@ -311,7 +223,7 @@ static void ip6_frag_expire(unsigned long data) | |||
311 | rcu_read_unlock(); | 223 | rcu_read_unlock(); |
312 | 224 | ||
313 | /* Don't send error if the first segment did not arrive. */ | 225 | /* Don't send error if the first segment did not arrive. */ |
314 | if (!(fq->last_in&FIRST_IN) || !fq->fragments) | 226 | if (!(fq->q.last_in&FIRST_IN) || !fq->q.fragments) |
315 | goto out; | 227 | goto out; |
316 | 228 | ||
317 | /* | 229 | /* |
@@ -319,114 +231,47 @@ static void ip6_frag_expire(unsigned long data) | |||
319 | segment was received. And do not use fq->dev | 231 | segment was received. And do not use fq->dev |
320 | pointer directly, device might already disappeared. | 232 | pointer directly, device might already disappeared. |
321 | */ | 233 | */ |
322 | fq->fragments->dev = dev; | 234 | fq->q.fragments->dev = dev; |
323 | icmpv6_send(fq->fragments, ICMPV6_TIME_EXCEED, ICMPV6_EXC_FRAGTIME, 0, dev); | 235 | icmpv6_send(fq->q.fragments, ICMPV6_TIME_EXCEED, ICMPV6_EXC_FRAGTIME, 0, dev); |
324 | out: | 236 | out: |
325 | if (dev) | 237 | if (dev) |
326 | dev_put(dev); | 238 | dev_put(dev); |
327 | spin_unlock(&fq->lock); | 239 | spin_unlock(&fq->q.lock); |
328 | fq_put(fq, NULL); | 240 | fq_put(fq); |
329 | } | 241 | } |
330 | 242 | ||
331 | /* Creation primitives. */ | 243 | static __inline__ struct frag_queue * |
332 | 244 | fq_find(__be32 id, struct in6_addr *src, struct in6_addr *dst, | |
333 | 245 | struct inet6_dev *idev) | |
334 | static struct frag_queue *ip6_frag_intern(struct frag_queue *fq_in) | ||
335 | { | 246 | { |
336 | struct frag_queue *fq; | 247 | struct inet_frag_queue *q; |
248 | struct ip6_create_arg arg; | ||
337 | unsigned int hash; | 249 | unsigned int hash; |
338 | #ifdef CONFIG_SMP | ||
339 | struct hlist_node *n; | ||
340 | #endif | ||
341 | |||
342 | write_lock(&ip6_frag_lock); | ||
343 | hash = ip6qhashfn(fq_in->id, &fq_in->saddr, &fq_in->daddr); | ||
344 | #ifdef CONFIG_SMP | ||
345 | hlist_for_each_entry(fq, n, &ip6_frag_hash[hash], list) { | ||
346 | if (fq->id == fq_in->id && | ||
347 | ipv6_addr_equal(&fq_in->saddr, &fq->saddr) && | ||
348 | ipv6_addr_equal(&fq_in->daddr, &fq->daddr)) { | ||
349 | atomic_inc(&fq->refcnt); | ||
350 | write_unlock(&ip6_frag_lock); | ||
351 | fq_in->last_in |= COMPLETE; | ||
352 | fq_put(fq_in, NULL); | ||
353 | return fq; | ||
354 | } | ||
355 | } | ||
356 | #endif | ||
357 | fq = fq_in; | ||
358 | |||
359 | if (!mod_timer(&fq->timer, jiffies + sysctl_ip6frag_time)) | ||
360 | atomic_inc(&fq->refcnt); | ||
361 | |||
362 | atomic_inc(&fq->refcnt); | ||
363 | hlist_add_head(&fq->list, &ip6_frag_hash[hash]); | ||
364 | INIT_LIST_HEAD(&fq->lru_list); | ||
365 | list_add_tail(&fq->lru_list, &ip6_frag_lru_list); | ||
366 | ip6_frag_nqueues++; | ||
367 | write_unlock(&ip6_frag_lock); | ||
368 | return fq; | ||
369 | } | ||
370 | |||
371 | 250 | ||
372 | static struct frag_queue * | 251 | arg.id = id; |
373 | ip6_frag_create(__be32 id, struct in6_addr *src, struct in6_addr *dst, | 252 | arg.src = src; |
374 | struct inet6_dev *idev) | 253 | arg.dst = dst; |
375 | { | 254 | hash = ip6qhashfn(id, src, dst); |
376 | struct frag_queue *fq; | ||
377 | 255 | ||
378 | if ((fq = frag_alloc_queue()) == NULL) | 256 | q = inet_frag_find(&ip6_frags, &arg, hash); |
257 | if (q == NULL) | ||
379 | goto oom; | 258 | goto oom; |
380 | 259 | ||
381 | fq->id = id; | 260 | return container_of(q, struct frag_queue, q); |
382 | ipv6_addr_copy(&fq->saddr, src); | ||
383 | ipv6_addr_copy(&fq->daddr, dst); | ||
384 | |||
385 | init_timer(&fq->timer); | ||
386 | fq->timer.function = ip6_frag_expire; | ||
387 | fq->timer.data = (long) fq; | ||
388 | spin_lock_init(&fq->lock); | ||
389 | atomic_set(&fq->refcnt, 1); | ||
390 | |||
391 | return ip6_frag_intern(fq); | ||
392 | 261 | ||
393 | oom: | 262 | oom: |
394 | IP6_INC_STATS_BH(idev, IPSTATS_MIB_REASMFAILS); | 263 | IP6_INC_STATS_BH(idev, IPSTATS_MIB_REASMFAILS); |
395 | return NULL; | 264 | return NULL; |
396 | } | 265 | } |
397 | 266 | ||
398 | static __inline__ struct frag_queue * | 267 | static int ip6_frag_queue(struct frag_queue *fq, struct sk_buff *skb, |
399 | fq_find(__be32 id, struct in6_addr *src, struct in6_addr *dst, | ||
400 | struct inet6_dev *idev) | ||
401 | { | ||
402 | struct frag_queue *fq; | ||
403 | struct hlist_node *n; | ||
404 | unsigned int hash; | ||
405 | |||
406 | read_lock(&ip6_frag_lock); | ||
407 | hash = ip6qhashfn(id, src, dst); | ||
408 | hlist_for_each_entry(fq, n, &ip6_frag_hash[hash], list) { | ||
409 | if (fq->id == id && | ||
410 | ipv6_addr_equal(src, &fq->saddr) && | ||
411 | ipv6_addr_equal(dst, &fq->daddr)) { | ||
412 | atomic_inc(&fq->refcnt); | ||
413 | read_unlock(&ip6_frag_lock); | ||
414 | return fq; | ||
415 | } | ||
416 | } | ||
417 | read_unlock(&ip6_frag_lock); | ||
418 | |||
419 | return ip6_frag_create(id, src, dst, idev); | ||
420 | } | ||
421 | |||
422 | |||
423 | static void ip6_frag_queue(struct frag_queue *fq, struct sk_buff *skb, | ||
424 | struct frag_hdr *fhdr, int nhoff) | 268 | struct frag_hdr *fhdr, int nhoff) |
425 | { | 269 | { |
426 | struct sk_buff *prev, *next; | 270 | struct sk_buff *prev, *next; |
271 | struct net_device *dev; | ||
427 | int offset, end; | 272 | int offset, end; |
428 | 273 | ||
429 | if (fq->last_in & COMPLETE) | 274 | if (fq->q.last_in & COMPLETE) |
430 | goto err; | 275 | goto err; |
431 | 276 | ||
432 | offset = ntohs(fhdr->frag_off) & ~0x7; | 277 | offset = ntohs(fhdr->frag_off) & ~0x7; |
@@ -439,7 +284,7 @@ static void ip6_frag_queue(struct frag_queue *fq, struct sk_buff *skb, | |||
439 | icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, | 284 | icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, |
440 | ((u8 *)&fhdr->frag_off - | 285 | ((u8 *)&fhdr->frag_off - |
441 | skb_network_header(skb))); | 286 | skb_network_header(skb))); |
442 | return; | 287 | return -1; |
443 | } | 288 | } |
444 | 289 | ||
445 | if (skb->ip_summed == CHECKSUM_COMPLETE) { | 290 | if (skb->ip_summed == CHECKSUM_COMPLETE) { |
@@ -454,11 +299,11 @@ static void ip6_frag_queue(struct frag_queue *fq, struct sk_buff *skb, | |||
454 | /* If we already have some bits beyond end | 299 | /* If we already have some bits beyond end |
455 | * or have different end, the segment is corrupted. | 300 | * or have different end, the segment is corrupted. |
456 | */ | 301 | */ |
457 | if (end < fq->len || | 302 | if (end < fq->q.len || |
458 | ((fq->last_in & LAST_IN) && end != fq->len)) | 303 | ((fq->q.last_in & LAST_IN) && end != fq->q.len)) |
459 | goto err; | 304 | goto err; |
460 | fq->last_in |= LAST_IN; | 305 | fq->q.last_in |= LAST_IN; |
461 | fq->len = end; | 306 | fq->q.len = end; |
462 | } else { | 307 | } else { |
463 | /* Check if the fragment is rounded to 8 bytes. | 308 | /* Check if the fragment is rounded to 8 bytes. |
464 | * Required by the RFC. | 309 | * Required by the RFC. |
@@ -471,13 +316,13 @@ static void ip6_frag_queue(struct frag_queue *fq, struct sk_buff *skb, | |||
471 | IPSTATS_MIB_INHDRERRORS); | 316 | IPSTATS_MIB_INHDRERRORS); |
472 | icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, | 317 | icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, |
473 | offsetof(struct ipv6hdr, payload_len)); | 318 | offsetof(struct ipv6hdr, payload_len)); |
474 | return; | 319 | return -1; |
475 | } | 320 | } |
476 | if (end > fq->len) { | 321 | if (end > fq->q.len) { |
477 | /* Some bits beyond end -> corruption. */ | 322 | /* Some bits beyond end -> corruption. */ |
478 | if (fq->last_in & LAST_IN) | 323 | if (fq->q.last_in & LAST_IN) |
479 | goto err; | 324 | goto err; |
480 | fq->len = end; | 325 | fq->q.len = end; |
481 | } | 326 | } |
482 | } | 327 | } |
483 | 328 | ||
@@ -496,7 +341,7 @@ static void ip6_frag_queue(struct frag_queue *fq, struct sk_buff *skb, | |||
496 | * this fragment, right? | 341 | * this fragment, right? |
497 | */ | 342 | */ |
498 | prev = NULL; | 343 | prev = NULL; |
499 | for(next = fq->fragments; next != NULL; next = next->next) { | 344 | for(next = fq->q.fragments; next != NULL; next = next->next) { |
500 | if (FRAG6_CB(next)->offset >= offset) | 345 | if (FRAG6_CB(next)->offset >= offset) |
501 | break; /* bingo! */ | 346 | break; /* bingo! */ |
502 | prev = next; | 347 | prev = next; |
@@ -533,7 +378,7 @@ static void ip6_frag_queue(struct frag_queue *fq, struct sk_buff *skb, | |||
533 | if (!pskb_pull(next, i)) | 378 | if (!pskb_pull(next, i)) |
534 | goto err; | 379 | goto err; |
535 | FRAG6_CB(next)->offset += i; /* next fragment */ | 380 | FRAG6_CB(next)->offset += i; /* next fragment */ |
536 | fq->meat -= i; | 381 | fq->q.meat -= i; |
537 | if (next->ip_summed != CHECKSUM_UNNECESSARY) | 382 | if (next->ip_summed != CHECKSUM_UNNECESSARY) |
538 | next->ip_summed = CHECKSUM_NONE; | 383 | next->ip_summed = CHECKSUM_NONE; |
539 | break; | 384 | break; |
@@ -548,9 +393,9 @@ static void ip6_frag_queue(struct frag_queue *fq, struct sk_buff *skb, | |||
548 | if (prev) | 393 | if (prev) |
549 | prev->next = next; | 394 | prev->next = next; |
550 | else | 395 | else |
551 | fq->fragments = next; | 396 | fq->q.fragments = next; |
552 | 397 | ||
553 | fq->meat -= free_it->len; | 398 | fq->q.meat -= free_it->len; |
554 | frag_kfree_skb(free_it, NULL); | 399 | frag_kfree_skb(free_it, NULL); |
555 | } | 400 | } |
556 | } | 401 | } |
@@ -562,30 +407,37 @@ static void ip6_frag_queue(struct frag_queue *fq, struct sk_buff *skb, | |||
562 | if (prev) | 407 | if (prev) |
563 | prev->next = skb; | 408 | prev->next = skb; |
564 | else | 409 | else |
565 | fq->fragments = skb; | 410 | fq->q.fragments = skb; |
566 | 411 | ||
567 | if (skb->dev) | 412 | dev = skb->dev; |
568 | fq->iif = skb->dev->ifindex; | 413 | if (dev) { |
569 | skb->dev = NULL; | 414 | fq->iif = dev->ifindex; |
570 | fq->stamp = skb->tstamp; | 415 | skb->dev = NULL; |
571 | fq->meat += skb->len; | 416 | } |
572 | atomic_add(skb->truesize, &ip6_frag_mem); | 417 | fq->q.stamp = skb->tstamp; |
418 | fq->q.meat += skb->len; | ||
419 | atomic_add(skb->truesize, &ip6_frags.mem); | ||
573 | 420 | ||
574 | /* The first fragment. | 421 | /* The first fragment. |
575 | * nhoffset is obtained from the first fragment, of course. | 422 | * nhoffset is obtained from the first fragment, of course. |
576 | */ | 423 | */ |
577 | if (offset == 0) { | 424 | if (offset == 0) { |
578 | fq->nhoffset = nhoff; | 425 | fq->nhoffset = nhoff; |
579 | fq->last_in |= FIRST_IN; | 426 | fq->q.last_in |= FIRST_IN; |
580 | } | 427 | } |
581 | write_lock(&ip6_frag_lock); | 428 | |
582 | list_move_tail(&fq->lru_list, &ip6_frag_lru_list); | 429 | if (fq->q.last_in == (FIRST_IN | LAST_IN) && fq->q.meat == fq->q.len) |
583 | write_unlock(&ip6_frag_lock); | 430 | return ip6_frag_reasm(fq, prev, dev); |
584 | return; | 431 | |
432 | write_lock(&ip6_frags.lock); | ||
433 | list_move_tail(&fq->q.lru_list, &ip6_frags.lru_list); | ||
434 | write_unlock(&ip6_frags.lock); | ||
435 | return -1; | ||
585 | 436 | ||
586 | err: | 437 | err: |
587 | IP6_INC_STATS(ip6_dst_idev(skb->dst), IPSTATS_MIB_REASMFAILS); | 438 | IP6_INC_STATS(ip6_dst_idev(skb->dst), IPSTATS_MIB_REASMFAILS); |
588 | kfree_skb(skb); | 439 | kfree_skb(skb); |
440 | return -1; | ||
589 | } | 441 | } |
590 | 442 | ||
591 | /* | 443 | /* |
@@ -597,21 +449,39 @@ err: | |||
597 | * queue is eligible for reassembly i.e. it is not COMPLETE, | 449 | * queue is eligible for reassembly i.e. it is not COMPLETE, |
598 | * the last and the first frames arrived and all the bits are here. | 450 | * the last and the first frames arrived and all the bits are here. |
599 | */ | 451 | */ |
600 | static int ip6_frag_reasm(struct frag_queue *fq, struct sk_buff **skb_in, | 452 | static int ip6_frag_reasm(struct frag_queue *fq, struct sk_buff *prev, |
601 | struct net_device *dev) | 453 | struct net_device *dev) |
602 | { | 454 | { |
603 | struct sk_buff *fp, *head = fq->fragments; | 455 | struct sk_buff *fp, *head = fq->q.fragments; |
604 | int payload_len; | 456 | int payload_len; |
605 | unsigned int nhoff; | 457 | unsigned int nhoff; |
606 | 458 | ||
607 | fq_kill(fq); | 459 | fq_kill(fq); |
608 | 460 | ||
461 | /* Make the one we just received the head. */ | ||
462 | if (prev) { | ||
463 | head = prev->next; | ||
464 | fp = skb_clone(head, GFP_ATOMIC); | ||
465 | |||
466 | if (!fp) | ||
467 | goto out_oom; | ||
468 | |||
469 | fp->next = head->next; | ||
470 | prev->next = fp; | ||
471 | |||
472 | skb_morph(head, fq->q.fragments); | ||
473 | head->next = fq->q.fragments->next; | ||
474 | |||
475 | kfree_skb(fq->q.fragments); | ||
476 | fq->q.fragments = head; | ||
477 | } | ||
478 | |||
609 | BUG_TRAP(head != NULL); | 479 | BUG_TRAP(head != NULL); |
610 | BUG_TRAP(FRAG6_CB(head)->offset == 0); | 480 | BUG_TRAP(FRAG6_CB(head)->offset == 0); |
611 | 481 | ||
612 | /* Unfragmented part is taken from the first segment. */ | 482 | /* Unfragmented part is taken from the first segment. */ |
613 | payload_len = ((head->data - skb_network_header(head)) - | 483 | payload_len = ((head->data - skb_network_header(head)) - |
614 | sizeof(struct ipv6hdr) + fq->len - | 484 | sizeof(struct ipv6hdr) + fq->q.len - |
615 | sizeof(struct frag_hdr)); | 485 | sizeof(struct frag_hdr)); |
616 | if (payload_len > IPV6_MAXPLEN) | 486 | if (payload_len > IPV6_MAXPLEN) |
617 | goto out_oversize; | 487 | goto out_oversize; |
@@ -640,7 +510,7 @@ static int ip6_frag_reasm(struct frag_queue *fq, struct sk_buff **skb_in, | |||
640 | head->len -= clone->len; | 510 | head->len -= clone->len; |
641 | clone->csum = 0; | 511 | clone->csum = 0; |
642 | clone->ip_summed = head->ip_summed; | 512 | clone->ip_summed = head->ip_summed; |
643 | atomic_add(clone->truesize, &ip6_frag_mem); | 513 | atomic_add(clone->truesize, &ip6_frags.mem); |
644 | } | 514 | } |
645 | 515 | ||
646 | /* We have to remove fragment header from datagram and to relocate | 516 | /* We have to remove fragment header from datagram and to relocate |
@@ -655,7 +525,7 @@ static int ip6_frag_reasm(struct frag_queue *fq, struct sk_buff **skb_in, | |||
655 | skb_shinfo(head)->frag_list = head->next; | 525 | skb_shinfo(head)->frag_list = head->next; |
656 | skb_reset_transport_header(head); | 526 | skb_reset_transport_header(head); |
657 | skb_push(head, head->data - skb_network_header(head)); | 527 | skb_push(head, head->data - skb_network_header(head)); |
658 | atomic_sub(head->truesize, &ip6_frag_mem); | 528 | atomic_sub(head->truesize, &ip6_frags.mem); |
659 | 529 | ||
660 | for (fp=head->next; fp; fp = fp->next) { | 530 | for (fp=head->next; fp; fp = fp->next) { |
661 | head->data_len += fp->len; | 531 | head->data_len += fp->len; |
@@ -665,17 +535,15 @@ static int ip6_frag_reasm(struct frag_queue *fq, struct sk_buff **skb_in, | |||
665 | else if (head->ip_summed == CHECKSUM_COMPLETE) | 535 | else if (head->ip_summed == CHECKSUM_COMPLETE) |
666 | head->csum = csum_add(head->csum, fp->csum); | 536 | head->csum = csum_add(head->csum, fp->csum); |
667 | head->truesize += fp->truesize; | 537 | head->truesize += fp->truesize; |
668 | atomic_sub(fp->truesize, &ip6_frag_mem); | 538 | atomic_sub(fp->truesize, &ip6_frags.mem); |
669 | } | 539 | } |
670 | 540 | ||
671 | head->next = NULL; | 541 | head->next = NULL; |
672 | head->dev = dev; | 542 | head->dev = dev; |
673 | head->tstamp = fq->stamp; | 543 | head->tstamp = fq->q.stamp; |
674 | ipv6_hdr(head)->payload_len = htons(payload_len); | 544 | ipv6_hdr(head)->payload_len = htons(payload_len); |
675 | IP6CB(head)->nhoff = nhoff; | 545 | IP6CB(head)->nhoff = nhoff; |
676 | 546 | ||
677 | *skb_in = head; | ||
678 | |||
679 | /* Yes, and fold redundant checksum back. 8) */ | 547 | /* Yes, and fold redundant checksum back. 8) */ |
680 | if (head->ip_summed == CHECKSUM_COMPLETE) | 548 | if (head->ip_summed == CHECKSUM_COMPLETE) |
681 | head->csum = csum_partial(skb_network_header(head), | 549 | head->csum = csum_partial(skb_network_header(head), |
@@ -685,7 +553,7 @@ static int ip6_frag_reasm(struct frag_queue *fq, struct sk_buff **skb_in, | |||
685 | rcu_read_lock(); | 553 | rcu_read_lock(); |
686 | IP6_INC_STATS_BH(__in6_dev_get(dev), IPSTATS_MIB_REASMOKS); | 554 | IP6_INC_STATS_BH(__in6_dev_get(dev), IPSTATS_MIB_REASMOKS); |
687 | rcu_read_unlock(); | 555 | rcu_read_unlock(); |
688 | fq->fragments = NULL; | 556 | fq->q.fragments = NULL; |
689 | return 1; | 557 | return 1; |
690 | 558 | ||
691 | out_oversize: | 559 | out_oversize: |
@@ -702,10 +570,8 @@ out_fail: | |||
702 | return -1; | 570 | return -1; |
703 | } | 571 | } |
704 | 572 | ||
705 | static int ipv6_frag_rcv(struct sk_buff **skbp) | 573 | static int ipv6_frag_rcv(struct sk_buff *skb) |
706 | { | 574 | { |
707 | struct sk_buff *skb = *skbp; | ||
708 | struct net_device *dev = skb->dev; | ||
709 | struct frag_hdr *fhdr; | 575 | struct frag_hdr *fhdr; |
710 | struct frag_queue *fq; | 576 | struct frag_queue *fq; |
711 | struct ipv6hdr *hdr = ipv6_hdr(skb); | 577 | struct ipv6hdr *hdr = ipv6_hdr(skb); |
@@ -739,23 +605,19 @@ static int ipv6_frag_rcv(struct sk_buff **skbp) | |||
739 | return 1; | 605 | return 1; |
740 | } | 606 | } |
741 | 607 | ||
742 | if (atomic_read(&ip6_frag_mem) > sysctl_ip6frag_high_thresh) | 608 | if (atomic_read(&ip6_frags.mem) > ip6_frags_ctl.high_thresh) |
743 | ip6_evictor(ip6_dst_idev(skb->dst)); | 609 | ip6_evictor(ip6_dst_idev(skb->dst)); |
744 | 610 | ||
745 | if ((fq = fq_find(fhdr->identification, &hdr->saddr, &hdr->daddr, | 611 | if ((fq = fq_find(fhdr->identification, &hdr->saddr, &hdr->daddr, |
746 | ip6_dst_idev(skb->dst))) != NULL) { | 612 | ip6_dst_idev(skb->dst))) != NULL) { |
747 | int ret = -1; | 613 | int ret; |
748 | 614 | ||
749 | spin_lock(&fq->lock); | 615 | spin_lock(&fq->q.lock); |
750 | 616 | ||
751 | ip6_frag_queue(fq, skb, fhdr, IP6CB(skb)->nhoff); | 617 | ret = ip6_frag_queue(fq, skb, fhdr, IP6CB(skb)->nhoff); |
752 | 618 | ||
753 | if (fq->last_in == (FIRST_IN|LAST_IN) && | 619 | spin_unlock(&fq->q.lock); |
754 | fq->meat == fq->len) | 620 | fq_put(fq); |
755 | ret = ip6_frag_reasm(fq, skbp, dev); | ||
756 | |||
757 | spin_unlock(&fq->lock); | ||
758 | fq_put(fq, NULL); | ||
759 | return ret; | 621 | return ret; |
760 | } | 622 | } |
761 | 623 | ||
@@ -775,11 +637,13 @@ void __init ipv6_frag_init(void) | |||
775 | if (inet6_add_protocol(&frag_protocol, IPPROTO_FRAGMENT) < 0) | 637 | if (inet6_add_protocol(&frag_protocol, IPPROTO_FRAGMENT) < 0) |
776 | printk(KERN_ERR "ipv6_frag_init: Could not register protocol\n"); | 638 | printk(KERN_ERR "ipv6_frag_init: Could not register protocol\n"); |
777 | 639 | ||
778 | ip6_frag_hash_rnd = (u32) ((num_physpages ^ (num_physpages>>7)) ^ | 640 | ip6_frags.ctl = &ip6_frags_ctl; |
779 | (jiffies ^ (jiffies >> 6))); | 641 | ip6_frags.hashfn = ip6_hashfn; |
780 | 642 | ip6_frags.constructor = ip6_frag_init; | |
781 | init_timer(&ip6_frag_secret_timer); | 643 | ip6_frags.destructor = NULL; |
782 | ip6_frag_secret_timer.function = ip6_frag_secret_rebuild; | 644 | ip6_frags.skb_free = NULL; |
783 | ip6_frag_secret_timer.expires = jiffies + sysctl_ip6frag_secret_interval; | 645 | ip6_frags.qsize = sizeof(struct frag_queue); |
784 | add_timer(&ip6_frag_secret_timer); | 646 | ip6_frags.match = ip6_frag_match; |
647 | ip6_frags.frag_expire = ip6_frag_expire; | ||
648 | inet_frags_init(&ip6_frags); | ||
785 | } | 649 | } |
diff --git a/net/ipv6/route.c b/net/ipv6/route.c index 6ff19f9eb9ee..95f8e4a62f68 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c | |||
@@ -663,7 +663,7 @@ static struct rt6_info *rt6_alloc_clone(struct rt6_info *ort, struct in6_addr *d | |||
663 | return rt; | 663 | return rt; |
664 | } | 664 | } |
665 | 665 | ||
666 | static struct rt6_info *ip6_pol_route_input(struct fib6_table *table, | 666 | static struct rt6_info *ip6_pol_route(struct fib6_table *table, int oif, |
667 | struct flowi *fl, int flags) | 667 | struct flowi *fl, int flags) |
668 | { | 668 | { |
669 | struct fib6_node *fn; | 669 | struct fib6_node *fn; |
@@ -682,7 +682,7 @@ restart_2: | |||
682 | fn = fib6_lookup(&table->tb6_root, &fl->fl6_dst, &fl->fl6_src); | 682 | fn = fib6_lookup(&table->tb6_root, &fl->fl6_dst, &fl->fl6_src); |
683 | 683 | ||
684 | restart: | 684 | restart: |
685 | rt = rt6_select(fn, fl->iif, strict | reachable); | 685 | rt = rt6_select(fn, oif, strict | reachable); |
686 | BACKTRACK(&fl->fl6_src); | 686 | BACKTRACK(&fl->fl6_src); |
687 | if (rt == &ip6_null_entry || | 687 | if (rt == &ip6_null_entry || |
688 | rt->rt6i_flags & RTF_CACHE) | 688 | rt->rt6i_flags & RTF_CACHE) |
@@ -735,6 +735,12 @@ out2: | |||
735 | return rt; | 735 | return rt; |
736 | } | 736 | } |
737 | 737 | ||
738 | static struct rt6_info *ip6_pol_route_input(struct fib6_table *table, | ||
739 | struct flowi *fl, int flags) | ||
740 | { | ||
741 | return ip6_pol_route(table, fl->iif, fl, flags); | ||
742 | } | ||
743 | |||
738 | void ip6_route_input(struct sk_buff *skb) | 744 | void ip6_route_input(struct sk_buff *skb) |
739 | { | 745 | { |
740 | struct ipv6hdr *iph = ipv6_hdr(skb); | 746 | struct ipv6hdr *iph = ipv6_hdr(skb); |
@@ -761,72 +767,7 @@ void ip6_route_input(struct sk_buff *skb) | |||
761 | static struct rt6_info *ip6_pol_route_output(struct fib6_table *table, | 767 | static struct rt6_info *ip6_pol_route_output(struct fib6_table *table, |
762 | struct flowi *fl, int flags) | 768 | struct flowi *fl, int flags) |
763 | { | 769 | { |
764 | struct fib6_node *fn; | 770 | return ip6_pol_route(table, fl->oif, fl, flags); |
765 | struct rt6_info *rt, *nrt; | ||
766 | int strict = 0; | ||
767 | int attempts = 3; | ||
768 | int err; | ||
769 | int reachable = ipv6_devconf.forwarding ? 0 : RT6_LOOKUP_F_REACHABLE; | ||
770 | |||
771 | strict |= flags & RT6_LOOKUP_F_IFACE; | ||
772 | |||
773 | relookup: | ||
774 | read_lock_bh(&table->tb6_lock); | ||
775 | |||
776 | restart_2: | ||
777 | fn = fib6_lookup(&table->tb6_root, &fl->fl6_dst, &fl->fl6_src); | ||
778 | |||
779 | restart: | ||
780 | rt = rt6_select(fn, fl->oif, strict | reachable); | ||
781 | BACKTRACK(&fl->fl6_src); | ||
782 | if (rt == &ip6_null_entry || | ||
783 | rt->rt6i_flags & RTF_CACHE) | ||
784 | goto out; | ||
785 | |||
786 | dst_hold(&rt->u.dst); | ||
787 | read_unlock_bh(&table->tb6_lock); | ||
788 | |||
789 | if (!rt->rt6i_nexthop && !(rt->rt6i_flags & RTF_NONEXTHOP)) | ||
790 | nrt = rt6_alloc_cow(rt, &fl->fl6_dst, &fl->fl6_src); | ||
791 | else { | ||
792 | #if CLONE_OFFLINK_ROUTE | ||
793 | nrt = rt6_alloc_clone(rt, &fl->fl6_dst); | ||
794 | #else | ||
795 | goto out2; | ||
796 | #endif | ||
797 | } | ||
798 | |||
799 | dst_release(&rt->u.dst); | ||
800 | rt = nrt ? : &ip6_null_entry; | ||
801 | |||
802 | dst_hold(&rt->u.dst); | ||
803 | if (nrt) { | ||
804 | err = ip6_ins_rt(nrt); | ||
805 | if (!err) | ||
806 | goto out2; | ||
807 | } | ||
808 | |||
809 | if (--attempts <= 0) | ||
810 | goto out2; | ||
811 | |||
812 | /* | ||
813 | * Race condition! In the gap, when table->tb6_lock was | ||
814 | * released someone could insert this route. Relookup. | ||
815 | */ | ||
816 | dst_release(&rt->u.dst); | ||
817 | goto relookup; | ||
818 | |||
819 | out: | ||
820 | if (reachable) { | ||
821 | reachable = 0; | ||
822 | goto restart_2; | ||
823 | } | ||
824 | dst_hold(&rt->u.dst); | ||
825 | read_unlock_bh(&table->tb6_lock); | ||
826 | out2: | ||
827 | rt->u.dst.lastuse = jiffies; | ||
828 | rt->u.dst.__use++; | ||
829 | return rt; | ||
830 | } | 771 | } |
831 | 772 | ||
832 | struct dst_entry * ip6_route_output(struct sock *sk, struct flowi *fl) | 773 | struct dst_entry * ip6_route_output(struct sock *sk, struct flowi *fl) |
@@ -2456,7 +2397,6 @@ int ipv6_sysctl_rtcache_flush(ctl_table *ctl, int write, struct file * filp, | |||
2456 | 2397 | ||
2457 | ctl_table ipv6_route_table[] = { | 2398 | ctl_table ipv6_route_table[] = { |
2458 | { | 2399 | { |
2459 | .ctl_name = NET_IPV6_ROUTE_FLUSH, | ||
2460 | .procname = "flush", | 2400 | .procname = "flush", |
2461 | .data = &flush_delay, | 2401 | .data = &flush_delay, |
2462 | .maxlen = sizeof(int), | 2402 | .maxlen = sizeof(int), |
diff --git a/net/ipv6/sysctl_net_ipv6.c b/net/ipv6/sysctl_net_ipv6.c index 3fb44277207b..68bb2548e469 100644 --- a/net/ipv6/sysctl_net_ipv6.c +++ b/net/ipv6/sysctl_net_ipv6.c | |||
@@ -12,6 +12,7 @@ | |||
12 | #include <net/ndisc.h> | 12 | #include <net/ndisc.h> |
13 | #include <net/ipv6.h> | 13 | #include <net/ipv6.h> |
14 | #include <net/addrconf.h> | 14 | #include <net/addrconf.h> |
15 | #include <net/inet_frag.h> | ||
15 | 16 | ||
16 | #ifdef CONFIG_SYSCTL | 17 | #ifdef CONFIG_SYSCTL |
17 | 18 | ||
@@ -41,7 +42,7 @@ static ctl_table ipv6_table[] = { | |||
41 | { | 42 | { |
42 | .ctl_name = NET_IPV6_IP6FRAG_HIGH_THRESH, | 43 | .ctl_name = NET_IPV6_IP6FRAG_HIGH_THRESH, |
43 | .procname = "ip6frag_high_thresh", | 44 | .procname = "ip6frag_high_thresh", |
44 | .data = &sysctl_ip6frag_high_thresh, | 45 | .data = &ip6_frags_ctl.high_thresh, |
45 | .maxlen = sizeof(int), | 46 | .maxlen = sizeof(int), |
46 | .mode = 0644, | 47 | .mode = 0644, |
47 | .proc_handler = &proc_dointvec | 48 | .proc_handler = &proc_dointvec |
@@ -49,7 +50,7 @@ static ctl_table ipv6_table[] = { | |||
49 | { | 50 | { |
50 | .ctl_name = NET_IPV6_IP6FRAG_LOW_THRESH, | 51 | .ctl_name = NET_IPV6_IP6FRAG_LOW_THRESH, |
51 | .procname = "ip6frag_low_thresh", | 52 | .procname = "ip6frag_low_thresh", |
52 | .data = &sysctl_ip6frag_low_thresh, | 53 | .data = &ip6_frags_ctl.low_thresh, |
53 | .maxlen = sizeof(int), | 54 | .maxlen = sizeof(int), |
54 | .mode = 0644, | 55 | .mode = 0644, |
55 | .proc_handler = &proc_dointvec | 56 | .proc_handler = &proc_dointvec |
@@ -57,7 +58,7 @@ static ctl_table ipv6_table[] = { | |||
57 | { | 58 | { |
58 | .ctl_name = NET_IPV6_IP6FRAG_TIME, | 59 | .ctl_name = NET_IPV6_IP6FRAG_TIME, |
59 | .procname = "ip6frag_time", | 60 | .procname = "ip6frag_time", |
60 | .data = &sysctl_ip6frag_time, | 61 | .data = &ip6_frags_ctl.timeout, |
61 | .maxlen = sizeof(int), | 62 | .maxlen = sizeof(int), |
62 | .mode = 0644, | 63 | .mode = 0644, |
63 | .proc_handler = &proc_dointvec_jiffies, | 64 | .proc_handler = &proc_dointvec_jiffies, |
@@ -66,7 +67,7 @@ static ctl_table ipv6_table[] = { | |||
66 | { | 67 | { |
67 | .ctl_name = NET_IPV6_IP6FRAG_SECRET_INTERVAL, | 68 | .ctl_name = NET_IPV6_IP6FRAG_SECRET_INTERVAL, |
68 | .procname = "ip6frag_secret_interval", | 69 | .procname = "ip6frag_secret_interval", |
69 | .data = &sysctl_ip6frag_secret_interval, | 70 | .data = &ip6_frags_ctl.secret_interval, |
70 | .maxlen = sizeof(int), | 71 | .maxlen = sizeof(int), |
71 | .mode = 0644, | 72 | .mode = 0644, |
72 | .proc_handler = &proc_dointvec_jiffies, | 73 | .proc_handler = &proc_dointvec_jiffies, |
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index a07b59c528f3..737b755342bd 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c | |||
@@ -1668,9 +1668,8 @@ ipv6_pktoptions: | |||
1668 | return 0; | 1668 | return 0; |
1669 | } | 1669 | } |
1670 | 1670 | ||
1671 | static int tcp_v6_rcv(struct sk_buff **pskb) | 1671 | static int tcp_v6_rcv(struct sk_buff *skb) |
1672 | { | 1672 | { |
1673 | struct sk_buff *skb = *pskb; | ||
1674 | struct tcphdr *th; | 1673 | struct tcphdr *th; |
1675 | struct sock *sk; | 1674 | struct sock *sk; |
1676 | int ret; | 1675 | int ret; |
diff --git a/net/ipv6/tunnel6.c b/net/ipv6/tunnel6.c index 23e2809878ae..6323921b40be 100644 --- a/net/ipv6/tunnel6.c +++ b/net/ipv6/tunnel6.c | |||
@@ -87,9 +87,8 @@ int xfrm6_tunnel_deregister(struct xfrm6_tunnel *handler, unsigned short family) | |||
87 | 87 | ||
88 | EXPORT_SYMBOL(xfrm6_tunnel_deregister); | 88 | EXPORT_SYMBOL(xfrm6_tunnel_deregister); |
89 | 89 | ||
90 | static int tunnel6_rcv(struct sk_buff **pskb) | 90 | static int tunnel6_rcv(struct sk_buff *skb) |
91 | { | 91 | { |
92 | struct sk_buff *skb = *pskb; | ||
93 | struct xfrm6_tunnel *handler; | 92 | struct xfrm6_tunnel *handler; |
94 | 93 | ||
95 | if (!pskb_may_pull(skb, sizeof(struct ipv6hdr))) | 94 | if (!pskb_may_pull(skb, sizeof(struct ipv6hdr))) |
@@ -106,9 +105,8 @@ drop: | |||
106 | return 0; | 105 | return 0; |
107 | } | 106 | } |
108 | 107 | ||
109 | static int tunnel46_rcv(struct sk_buff **pskb) | 108 | static int tunnel46_rcv(struct sk_buff *skb) |
110 | { | 109 | { |
111 | struct sk_buff *skb = *pskb; | ||
112 | struct xfrm6_tunnel *handler; | 110 | struct xfrm6_tunnel *handler; |
113 | 111 | ||
114 | if (!pskb_may_pull(skb, sizeof(struct ipv6hdr))) | 112 | if (!pskb_may_pull(skb, sizeof(struct ipv6hdr))) |
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c index 82ff26dd4470..caebad6ee510 100644 --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c | |||
@@ -405,10 +405,9 @@ static inline int udp6_csum_init(struct sk_buff *skb, struct udphdr *uh, | |||
405 | return 0; | 405 | return 0; |
406 | } | 406 | } |
407 | 407 | ||
408 | int __udp6_lib_rcv(struct sk_buff **pskb, struct hlist_head udptable[], | 408 | int __udp6_lib_rcv(struct sk_buff *skb, struct hlist_head udptable[], |
409 | int proto) | 409 | int proto) |
410 | { | 410 | { |
411 | struct sk_buff *skb = *pskb; | ||
412 | struct sock *sk; | 411 | struct sock *sk; |
413 | struct udphdr *uh; | 412 | struct udphdr *uh; |
414 | struct net_device *dev = skb->dev; | 413 | struct net_device *dev = skb->dev; |
@@ -494,9 +493,9 @@ discard: | |||
494 | return 0; | 493 | return 0; |
495 | } | 494 | } |
496 | 495 | ||
497 | static __inline__ int udpv6_rcv(struct sk_buff **pskb) | 496 | static __inline__ int udpv6_rcv(struct sk_buff *skb) |
498 | { | 497 | { |
499 | return __udp6_lib_rcv(pskb, udp_hash, IPPROTO_UDP); | 498 | return __udp6_lib_rcv(skb, udp_hash, IPPROTO_UDP); |
500 | } | 499 | } |
501 | 500 | ||
502 | /* | 501 | /* |
diff --git a/net/ipv6/udp_impl.h b/net/ipv6/udp_impl.h index 6e252f318f7c..2d3fda601232 100644 --- a/net/ipv6/udp_impl.h +++ b/net/ipv6/udp_impl.h | |||
@@ -6,7 +6,7 @@ | |||
6 | #include <net/addrconf.h> | 6 | #include <net/addrconf.h> |
7 | #include <net/inet_common.h> | 7 | #include <net/inet_common.h> |
8 | 8 | ||
9 | extern int __udp6_lib_rcv(struct sk_buff **, struct hlist_head [], int ); | 9 | extern int __udp6_lib_rcv(struct sk_buff *, struct hlist_head [], int ); |
10 | extern void __udp6_lib_err(struct sk_buff *, struct inet6_skb_parm *, | 10 | extern void __udp6_lib_err(struct sk_buff *, struct inet6_skb_parm *, |
11 | int , int , int , __be32 , struct hlist_head []); | 11 | int , int , int , __be32 , struct hlist_head []); |
12 | 12 | ||
diff --git a/net/ipv6/udplite.c b/net/ipv6/udplite.c index f54016a55004..766566f7de47 100644 --- a/net/ipv6/udplite.c +++ b/net/ipv6/udplite.c | |||
@@ -17,9 +17,9 @@ | |||
17 | 17 | ||
18 | DEFINE_SNMP_STAT(struct udp_mib, udplite_stats_in6) __read_mostly; | 18 | DEFINE_SNMP_STAT(struct udp_mib, udplite_stats_in6) __read_mostly; |
19 | 19 | ||
20 | static int udplitev6_rcv(struct sk_buff **pskb) | 20 | static int udplitev6_rcv(struct sk_buff *skb) |
21 | { | 21 | { |
22 | return __udp6_lib_rcv(pskb, udplite_hash, IPPROTO_UDPLITE); | 22 | return __udp6_lib_rcv(skb, udplite_hash, IPPROTO_UDPLITE); |
23 | } | 23 | } |
24 | 24 | ||
25 | static void udplitev6_err(struct sk_buff *skb, | 25 | static void udplitev6_err(struct sk_buff *skb, |
diff --git a/net/ipv6/xfrm6_input.c b/net/ipv6/xfrm6_input.c index c858537cec4b..515783707e86 100644 --- a/net/ipv6/xfrm6_input.c +++ b/net/ipv6/xfrm6_input.c | |||
@@ -16,7 +16,7 @@ | |||
16 | #include <net/ipv6.h> | 16 | #include <net/ipv6.h> |
17 | #include <net/xfrm.h> | 17 | #include <net/xfrm.h> |
18 | 18 | ||
19 | int xfrm6_rcv_spi(struct sk_buff *skb, __be32 spi) | 19 | int xfrm6_rcv_spi(struct sk_buff *skb, int nexthdr, __be32 spi) |
20 | { | 20 | { |
21 | int err; | 21 | int err; |
22 | __be32 seq; | 22 | __be32 seq; |
@@ -24,11 +24,9 @@ int xfrm6_rcv_spi(struct sk_buff *skb, __be32 spi) | |||
24 | struct xfrm_state *x; | 24 | struct xfrm_state *x; |
25 | int xfrm_nr = 0; | 25 | int xfrm_nr = 0; |
26 | int decaps = 0; | 26 | int decaps = 0; |
27 | int nexthdr; | ||
28 | unsigned int nhoff; | 27 | unsigned int nhoff; |
29 | 28 | ||
30 | nhoff = IP6CB(skb)->nhoff; | 29 | nhoff = IP6CB(skb)->nhoff; |
31 | nexthdr = skb_network_header(skb)[nhoff]; | ||
32 | 30 | ||
33 | seq = 0; | 31 | seq = 0; |
34 | if (!spi && (err = xfrm_parse_spi(skb, nexthdr, &spi, &seq)) != 0) | 32 | if (!spi && (err = xfrm_parse_spi(skb, nexthdr, &spi, &seq)) != 0) |
@@ -41,7 +39,7 @@ int xfrm6_rcv_spi(struct sk_buff *skb, __be32 spi) | |||
41 | goto drop; | 39 | goto drop; |
42 | 40 | ||
43 | x = xfrm_state_lookup((xfrm_address_t *)&iph->daddr, spi, | 41 | x = xfrm_state_lookup((xfrm_address_t *)&iph->daddr, spi, |
44 | nexthdr != IPPROTO_IPIP ? nexthdr : IPPROTO_IPV6, AF_INET6); | 42 | nexthdr, AF_INET6); |
45 | if (x == NULL) | 43 | if (x == NULL) |
46 | goto drop; | 44 | goto drop; |
47 | spin_lock(&x->lock); | 45 | spin_lock(&x->lock); |
@@ -70,10 +68,10 @@ int xfrm6_rcv_spi(struct sk_buff *skb, __be32 spi) | |||
70 | 68 | ||
71 | xfrm_vec[xfrm_nr++] = x; | 69 | xfrm_vec[xfrm_nr++] = x; |
72 | 70 | ||
73 | if (x->mode->input(x, skb)) | 71 | if (x->outer_mode->input(x, skb)) |
74 | goto drop; | 72 | goto drop; |
75 | 73 | ||
76 | if (x->props.mode == XFRM_MODE_TUNNEL) { /* XXX */ | 74 | if (x->outer_mode->flags & XFRM_MODE_FLAG_TUNNEL) { |
77 | decaps = 1; | 75 | decaps = 1; |
78 | break; | 76 | break; |
79 | } | 77 | } |
@@ -99,7 +97,6 @@ int xfrm6_rcv_spi(struct sk_buff *skb, __be32 spi) | |||
99 | memcpy(skb->sp->xvec + skb->sp->len, xfrm_vec, | 97 | memcpy(skb->sp->xvec + skb->sp->len, xfrm_vec, |
100 | xfrm_nr * sizeof(xfrm_vec[0])); | 98 | xfrm_nr * sizeof(xfrm_vec[0])); |
101 | skb->sp->len += xfrm_nr; | 99 | skb->sp->len += xfrm_nr; |
102 | skb->ip_summed = CHECKSUM_NONE; | ||
103 | 100 | ||
104 | nf_reset(skb); | 101 | nf_reset(skb); |
105 | 102 | ||
@@ -133,9 +130,10 @@ drop: | |||
133 | 130 | ||
134 | EXPORT_SYMBOL(xfrm6_rcv_spi); | 131 | EXPORT_SYMBOL(xfrm6_rcv_spi); |
135 | 132 | ||
136 | int xfrm6_rcv(struct sk_buff **pskb) | 133 | int xfrm6_rcv(struct sk_buff *skb) |
137 | { | 134 | { |
138 | return xfrm6_rcv_spi(*pskb, 0); | 135 | return xfrm6_rcv_spi(skb, skb_network_header(skb)[IP6CB(skb)->nhoff], |
136 | 0); | ||
139 | } | 137 | } |
140 | 138 | ||
141 | EXPORT_SYMBOL(xfrm6_rcv); | 139 | EXPORT_SYMBOL(xfrm6_rcv); |
diff --git a/net/ipv6/xfrm6_mode_beet.c b/net/ipv6/xfrm6_mode_beet.c index 13bb1e856764..2bfb4f05c14c 100644 --- a/net/ipv6/xfrm6_mode_beet.c +++ b/net/ipv6/xfrm6_mode_beet.c | |||
@@ -79,6 +79,7 @@ static struct xfrm_mode xfrm6_beet_mode = { | |||
79 | .output = xfrm6_beet_output, | 79 | .output = xfrm6_beet_output, |
80 | .owner = THIS_MODULE, | 80 | .owner = THIS_MODULE, |
81 | .encap = XFRM_MODE_BEET, | 81 | .encap = XFRM_MODE_BEET, |
82 | .flags = XFRM_MODE_FLAG_TUNNEL, | ||
82 | }; | 83 | }; |
83 | 84 | ||
84 | static int __init xfrm6_beet_init(void) | 85 | static int __init xfrm6_beet_init(void) |
diff --git a/net/ipv6/xfrm6_mode_ro.c b/net/ipv6/xfrm6_mode_ro.c index 957ae36b6695..a7bc8c62317a 100644 --- a/net/ipv6/xfrm6_mode_ro.c +++ b/net/ipv6/xfrm6_mode_ro.c | |||
@@ -58,16 +58,7 @@ static int xfrm6_ro_output(struct xfrm_state *x, struct sk_buff *skb) | |||
58 | return 0; | 58 | return 0; |
59 | } | 59 | } |
60 | 60 | ||
61 | /* | ||
62 | * Do nothing about routing optimization header unlike IPsec. | ||
63 | */ | ||
64 | static int xfrm6_ro_input(struct xfrm_state *x, struct sk_buff *skb) | ||
65 | { | ||
66 | return 0; | ||
67 | } | ||
68 | |||
69 | static struct xfrm_mode xfrm6_ro_mode = { | 61 | static struct xfrm_mode xfrm6_ro_mode = { |
70 | .input = xfrm6_ro_input, | ||
71 | .output = xfrm6_ro_output, | 62 | .output = xfrm6_ro_output, |
72 | .owner = THIS_MODULE, | 63 | .owner = THIS_MODULE, |
73 | .encap = XFRM_MODE_ROUTEOPTIMIZATION, | 64 | .encap = XFRM_MODE_ROUTEOPTIMIZATION, |
diff --git a/net/ipv6/xfrm6_mode_tunnel.c b/net/ipv6/xfrm6_mode_tunnel.c index ea2283879112..fd84e2217274 100644 --- a/net/ipv6/xfrm6_mode_tunnel.c +++ b/net/ipv6/xfrm6_mode_tunnel.c | |||
@@ -118,6 +118,7 @@ static struct xfrm_mode xfrm6_tunnel_mode = { | |||
118 | .output = xfrm6_tunnel_output, | 118 | .output = xfrm6_tunnel_output, |
119 | .owner = THIS_MODULE, | 119 | .owner = THIS_MODULE, |
120 | .encap = XFRM_MODE_TUNNEL, | 120 | .encap = XFRM_MODE_TUNNEL, |
121 | .flags = XFRM_MODE_FLAG_TUNNEL, | ||
121 | }; | 122 | }; |
122 | 123 | ||
123 | static int __init xfrm6_tunnel_init(void) | 124 | static int __init xfrm6_tunnel_init(void) |
diff --git a/net/ipv6/xfrm6_output.c b/net/ipv6/xfrm6_output.c index 4618c18e611d..656976760ad4 100644 --- a/net/ipv6/xfrm6_output.c +++ b/net/ipv6/xfrm6_output.c | |||
@@ -50,7 +50,7 @@ static inline int xfrm6_output_one(struct sk_buff *skb) | |||
50 | struct ipv6hdr *iph; | 50 | struct ipv6hdr *iph; |
51 | int err; | 51 | int err; |
52 | 52 | ||
53 | if (x->props.mode == XFRM_MODE_TUNNEL) { | 53 | if (x->outer_mode->flags & XFRM_MODE_FLAG_TUNNEL) { |
54 | err = xfrm6_tunnel_check_size(skb); | 54 | err = xfrm6_tunnel_check_size(skb); |
55 | if (err) | 55 | if (err) |
56 | goto error_nolock; | 56 | goto error_nolock; |
@@ -80,7 +80,7 @@ static int xfrm6_output_finish2(struct sk_buff *skb) | |||
80 | while (likely((err = xfrm6_output_one(skb)) == 0)) { | 80 | while (likely((err = xfrm6_output_one(skb)) == 0)) { |
81 | nf_reset(skb); | 81 | nf_reset(skb); |
82 | 82 | ||
83 | err = nf_hook(PF_INET6, NF_IP6_LOCAL_OUT, &skb, NULL, | 83 | err = nf_hook(PF_INET6, NF_IP6_LOCAL_OUT, skb, NULL, |
84 | skb->dst->dev, dst_output); | 84 | skb->dst->dev, dst_output); |
85 | if (unlikely(err != 1)) | 85 | if (unlikely(err != 1)) |
86 | break; | 86 | break; |
@@ -88,7 +88,7 @@ static int xfrm6_output_finish2(struct sk_buff *skb) | |||
88 | if (!skb->dst->xfrm) | 88 | if (!skb->dst->xfrm) |
89 | return dst_output(skb); | 89 | return dst_output(skb); |
90 | 90 | ||
91 | err = nf_hook(PF_INET6, NF_IP6_POST_ROUTING, &skb, NULL, | 91 | err = nf_hook(PF_INET6, NF_IP6_POST_ROUTING, skb, NULL, |
92 | skb->dst->dev, xfrm6_output_finish2); | 92 | skb->dst->dev, xfrm6_output_finish2); |
93 | if (unlikely(err != 1)) | 93 | if (unlikely(err != 1)) |
94 | break; | 94 | break; |
diff --git a/net/ipv6/xfrm6_policy.c b/net/ipv6/xfrm6_policy.c index 15aa4c58c315..82e27b80d07d 100644 --- a/net/ipv6/xfrm6_policy.c +++ b/net/ipv6/xfrm6_policy.c | |||
@@ -178,8 +178,7 @@ __xfrm6_bundle_create(struct xfrm_policy *policy, struct xfrm_state **xfrm, int | |||
178 | __xfrm6_bundle_len_inc(&header_len, &nfheader_len, xfrm[i]); | 178 | __xfrm6_bundle_len_inc(&header_len, &nfheader_len, xfrm[i]); |
179 | trailer_len += xfrm[i]->props.trailer_len; | 179 | trailer_len += xfrm[i]->props.trailer_len; |
180 | 180 | ||
181 | if (xfrm[i]->props.mode == XFRM_MODE_TUNNEL || | 181 | if (xfrm[i]->props.mode != XFRM_MODE_TRANSPORT) { |
182 | xfrm[i]->props.mode == XFRM_MODE_ROUTEOPTIMIZATION) { | ||
183 | unsigned short encap_family = xfrm[i]->props.family; | 182 | unsigned short encap_family = xfrm[i]->props.family; |
184 | switch(encap_family) { | 183 | switch(encap_family) { |
185 | case AF_INET: | 184 | case AF_INET: |
@@ -215,7 +214,6 @@ __xfrm6_bundle_create(struct xfrm_policy *policy, struct xfrm_state **xfrm, int | |||
215 | i = 0; | 214 | i = 0; |
216 | for (; dst_prev != &rt->u.dst; dst_prev = dst_prev->child) { | 215 | for (; dst_prev != &rt->u.dst; dst_prev = dst_prev->child) { |
217 | struct xfrm_dst *x = (struct xfrm_dst*)dst_prev; | 216 | struct xfrm_dst *x = (struct xfrm_dst*)dst_prev; |
218 | struct xfrm_state_afinfo *afinfo; | ||
219 | 217 | ||
220 | dst_prev->xfrm = xfrm[i++]; | 218 | dst_prev->xfrm = xfrm[i++]; |
221 | dst_prev->dev = rt->u.dst.dev; | 219 | dst_prev->dev = rt->u.dst.dev; |
@@ -232,18 +230,7 @@ __xfrm6_bundle_create(struct xfrm_policy *policy, struct xfrm_state **xfrm, int | |||
232 | /* Copy neighbour for reachability confirmation */ | 230 | /* Copy neighbour for reachability confirmation */ |
233 | dst_prev->neighbour = neigh_clone(rt->u.dst.neighbour); | 231 | dst_prev->neighbour = neigh_clone(rt->u.dst.neighbour); |
234 | dst_prev->input = rt->u.dst.input; | 232 | dst_prev->input = rt->u.dst.input; |
235 | /* XXX: When IPv4 is implemented as module and can be unloaded, | 233 | dst_prev->output = dst_prev->xfrm->outer_mode->afinfo->output; |
236 | * we should manage reference to xfrm4_output in afinfo->output. | ||
237 | * Miyazawa | ||
238 | */ | ||
239 | afinfo = xfrm_state_get_afinfo(dst_prev->xfrm->props.family); | ||
240 | if (!afinfo) { | ||
241 | dst = *dst_p; | ||
242 | goto error; | ||
243 | } | ||
244 | |||
245 | dst_prev->output = afinfo->output; | ||
246 | xfrm_state_put_afinfo(afinfo); | ||
247 | /* Sheit... I remember I did this right. Apparently, | 234 | /* Sheit... I remember I did this right. Apparently, |
248 | * it was magically lost, so this code needs audit */ | 235 | * it was magically lost, so this code needs audit */ |
249 | x->u.rt6.rt6i_flags = rt0->rt6i_flags&(RTCF_BROADCAST|RTCF_MULTICAST|RTCF_LOCAL); | 236 | x->u.rt6.rt6i_flags = rt0->rt6i_flags&(RTCF_BROADCAST|RTCF_MULTICAST|RTCF_LOCAL); |
diff --git a/net/ipv6/xfrm6_state.c b/net/ipv6/xfrm6_state.c index cdadb4847469..b392bee396f1 100644 --- a/net/ipv6/xfrm6_state.c +++ b/net/ipv6/xfrm6_state.c | |||
@@ -93,7 +93,8 @@ __xfrm6_state_sort(struct xfrm_state **dst, struct xfrm_state **src, int n) | |||
93 | /* Rule 4: select IPsec tunnel */ | 93 | /* Rule 4: select IPsec tunnel */ |
94 | for (i = 0; i < n; i++) { | 94 | for (i = 0; i < n; i++) { |
95 | if (src[i] && | 95 | if (src[i] && |
96 | src[i]->props.mode == XFRM_MODE_TUNNEL) { | 96 | (src[i]->props.mode == XFRM_MODE_TUNNEL || |
97 | src[i]->props.mode == XFRM_MODE_BEET)) { | ||
97 | dst[j++] = src[i]; | 98 | dst[j++] = src[i]; |
98 | src[i] = NULL; | 99 | src[i] = NULL; |
99 | } | 100 | } |
@@ -146,7 +147,8 @@ __xfrm6_tmpl_sort(struct xfrm_tmpl **dst, struct xfrm_tmpl **src, int n) | |||
146 | /* Rule 3: select IPsec tunnel */ | 147 | /* Rule 3: select IPsec tunnel */ |
147 | for (i = 0; i < n; i++) { | 148 | for (i = 0; i < n; i++) { |
148 | if (src[i] && | 149 | if (src[i] && |
149 | src[i]->mode == XFRM_MODE_TUNNEL) { | 150 | (src[i]->mode == XFRM_MODE_TUNNEL || |
151 | src[i]->mode == XFRM_MODE_BEET)) { | ||
150 | dst[j++] = src[i]; | 152 | dst[j++] = src[i]; |
151 | src[i] = NULL; | 153 | src[i] = NULL; |
152 | } | 154 | } |
@@ -168,6 +170,7 @@ __xfrm6_tmpl_sort(struct xfrm_tmpl **dst, struct xfrm_tmpl **src, int n) | |||
168 | 170 | ||
169 | static struct xfrm_state_afinfo xfrm6_state_afinfo = { | 171 | static struct xfrm_state_afinfo xfrm6_state_afinfo = { |
170 | .family = AF_INET6, | 172 | .family = AF_INET6, |
173 | .owner = THIS_MODULE, | ||
171 | .init_tempsel = __xfrm6_init_tempsel, | 174 | .init_tempsel = __xfrm6_init_tempsel, |
172 | .tmpl_sort = __xfrm6_tmpl_sort, | 175 | .tmpl_sort = __xfrm6_tmpl_sort, |
173 | .state_sort = __xfrm6_state_sort, | 176 | .state_sort = __xfrm6_state_sort, |
diff --git a/net/ipv6/xfrm6_tunnel.c b/net/ipv6/xfrm6_tunnel.c index 3f8a3abde67e..fae90ff31087 100644 --- a/net/ipv6/xfrm6_tunnel.c +++ b/net/ipv6/xfrm6_tunnel.c | |||
@@ -248,7 +248,7 @@ static int xfrm6_tunnel_output(struct xfrm_state *x, struct sk_buff *skb) | |||
248 | 248 | ||
249 | static int xfrm6_tunnel_input(struct xfrm_state *x, struct sk_buff *skb) | 249 | static int xfrm6_tunnel_input(struct xfrm_state *x, struct sk_buff *skb) |
250 | { | 250 | { |
251 | return 0; | 251 | return skb_network_header(skb)[IP6CB(skb)->nhoff]; |
252 | } | 252 | } |
253 | 253 | ||
254 | static int xfrm6_tunnel_rcv(struct sk_buff *skb) | 254 | static int xfrm6_tunnel_rcv(struct sk_buff *skb) |
@@ -257,7 +257,7 @@ static int xfrm6_tunnel_rcv(struct sk_buff *skb) | |||
257 | __be32 spi; | 257 | __be32 spi; |
258 | 258 | ||
259 | spi = xfrm6_tunnel_spi_lookup((xfrm_address_t *)&iph->saddr); | 259 | spi = xfrm6_tunnel_spi_lookup((xfrm_address_t *)&iph->saddr); |
260 | return xfrm6_rcv_spi(skb, spi) > 0 ? : 0; | 260 | return xfrm6_rcv_spi(skb, IPPROTO_IPV6, spi) > 0 ? : 0; |
261 | } | 261 | } |
262 | 262 | ||
263 | static int xfrm6_tunnel_err(struct sk_buff *skb, struct inet6_skb_parm *opt, | 263 | static int xfrm6_tunnel_err(struct sk_buff *skb, struct inet6_skb_parm *opt, |
diff --git a/net/irda/discovery.c b/net/irda/discovery.c index af0cea721d2a..80c33f408e3f 100644 --- a/net/irda/discovery.c +++ b/net/irda/discovery.c | |||
@@ -202,7 +202,7 @@ void irlmp_expire_discoveries(hashbin_t *log, __u32 saddr, int force) | |||
202 | /* Drop the spinlock before calling the higher layers, as | 202 | /* Drop the spinlock before calling the higher layers, as |
203 | * we can't guarantee they won't call us back and create a | 203 | * we can't guarantee they won't call us back and create a |
204 | * deadlock. We will work on our own private data, so we | 204 | * deadlock. We will work on our own private data, so we |
205 | * don't care to be interupted. - Jean II */ | 205 | * don't care to be interrupted. - Jean II */ |
206 | spin_unlock_irqrestore(&log->hb_spinlock, flags); | 206 | spin_unlock_irqrestore(&log->hb_spinlock, flags); |
207 | 207 | ||
208 | if(buffer == NULL) | 208 | if(buffer == NULL) |
diff --git a/net/irda/ircomm/ircomm_tty_attach.c b/net/irda/ircomm/ircomm_tty_attach.c index 824309dabfe9..b5a13882c927 100644 --- a/net/irda/ircomm/ircomm_tty_attach.c +++ b/net/irda/ircomm/ircomm_tty_attach.c | |||
@@ -381,18 +381,9 @@ static void ircomm_tty_discovery_indication(discinfo_t *discovery, | |||
381 | info.daddr = discovery->daddr; | 381 | info.daddr = discovery->daddr; |
382 | info.saddr = discovery->saddr; | 382 | info.saddr = discovery->saddr; |
383 | 383 | ||
384 | /* FIXME. We have a locking problem on the hashbin here. | 384 | self = (struct ircomm_tty_cb *) priv; |
385 | * We probably need to use hashbin_find_next(), but we first | 385 | ircomm_tty_do_event(self, IRCOMM_TTY_DISCOVERY_INDICATION, |
386 | * need to ensure that "line" is unique. - Jean II */ | 386 | NULL, &info); |
387 | self = (struct ircomm_tty_cb *) hashbin_get_first(ircomm_tty); | ||
388 | while (self != NULL) { | ||
389 | IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;); | ||
390 | |||
391 | ircomm_tty_do_event(self, IRCOMM_TTY_DISCOVERY_INDICATION, | ||
392 | NULL, &info); | ||
393 | |||
394 | self = (struct ircomm_tty_cb *) hashbin_get_next(ircomm_tty); | ||
395 | } | ||
396 | } | 387 | } |
397 | 388 | ||
398 | /* | 389 | /* |
diff --git a/net/irda/iriap.c b/net/irda/iriap.c index ee3889fa49ab..dc5e34a01620 100644 --- a/net/irda/iriap.c +++ b/net/irda/iriap.c | |||
@@ -18,7 +18,7 @@ | |||
18 | * published by the Free Software Foundation; either version 2 of | 18 | * published by the Free Software Foundation; either version 2 of |
19 | * the License, or (at your option) any later version. | 19 | * the License, or (at your option) any later version. |
20 | * | 20 | * |
21 | * Neither Dag Brattli nor University of Tromsø admit liability nor | 21 | * Neither Dag Brattli nor University of Tromsø admit liability nor |
22 | * provide warranty for any of this software. This material is | 22 | * provide warranty for any of this software. This material is |
23 | * provided "AS-IS" and at no charge. | 23 | * provided "AS-IS" and at no charge. |
24 | * | 24 | * |
diff --git a/net/irda/iriap_event.c b/net/irda/iriap_event.c index 99b18dc7a0b7..8fb9d7277ca8 100644 --- a/net/irda/iriap_event.c +++ b/net/irda/iriap_event.c | |||
@@ -18,7 +18,7 @@ | |||
18 | * published by the Free Software Foundation; either version 2 of | 18 | * published by the Free Software Foundation; either version 2 of |
19 | * the License, or (at your option) any later version. | 19 | * the License, or (at your option) any later version. |
20 | * | 20 | * |
21 | * Neither Dag Brattli nor University of Tromsø admit liability nor | 21 | * Neither Dag Brattli nor University of Tromsø admit liability nor |
22 | * provide warranty for any of this software. This material is | 22 | * provide warranty for any of this software. This material is |
23 | * provided "AS-IS" and at no charge. | 23 | * provided "AS-IS" and at no charge. |
24 | * | 24 | * |
diff --git a/net/irda/irias_object.c b/net/irda/irias_object.c index cf302457097b..cbcf04380f3a 100644 --- a/net/irda/irias_object.c +++ b/net/irda/irias_object.c | |||
@@ -16,7 +16,7 @@ | |||
16 | * published by the Free Software Foundation; either version 2 of | 16 | * published by the Free Software Foundation; either version 2 of |
17 | * the License, or (at your option) any later version. | 17 | * the License, or (at your option) any later version. |
18 | * | 18 | * |
19 | * Neither Dag Brattli nor University of Tromsø admit liability nor | 19 | * Neither Dag Brattli nor University of Tromsø admit liability nor |
20 | * provide warranty for any of this software. This material is | 20 | * provide warranty for any of this software. This material is |
21 | * provided "AS-IS" and at no charge. | 21 | * provided "AS-IS" and at no charge. |
22 | * | 22 | * |
diff --git a/net/irda/irlan/irlan_client.c b/net/irda/irlan/irlan_client.c index 87039c2fb6a2..fff52d57a200 100644 --- a/net/irda/irlan/irlan_client.c +++ b/net/irda/irlan/irlan_client.c | |||
@@ -20,7 +20,7 @@ | |||
20 | * published by the Free Software Foundation; either version 2 of | 20 | * published by the Free Software Foundation; either version 2 of |
21 | * the License, or (at your option) any later version. | 21 | * the License, or (at your option) any later version. |
22 | * | 22 | * |
23 | * Neither Dag Brattli nor University of Tromsø admit liability nor | 23 | * Neither Dag Brattli nor University of Tromsø admit liability nor |
24 | * provide warranty for any of this software. This material is | 24 | * provide warranty for any of this software. This material is |
25 | * provided "AS-IS" and at no charge. | 25 | * provided "AS-IS" and at no charge. |
26 | * | 26 | * |
diff --git a/net/irda/irlan/irlan_client_event.c b/net/irda/irlan/irlan_client_event.c index 843ab6fbb394..6afcee59e906 100644 --- a/net/irda/irlan/irlan_client_event.c +++ b/net/irda/irlan/irlan_client_event.c | |||
@@ -17,7 +17,7 @@ | |||
17 | * published by the Free Software Foundation; either version 2 of | 17 | * published by the Free Software Foundation; either version 2 of |
18 | * the License, or (at your option) any later version. | 18 | * the License, or (at your option) any later version. |
19 | * | 19 | * |
20 | * Neither Dag Brattli nor University of Tromsø admit liability nor | 20 | * Neither Dag Brattli nor University of Tromsø admit liability nor |
21 | * provide warranty for any of this software. This material is | 21 | * provide warranty for any of this software. This material is |
22 | * provided "AS-IS" and at no charge. | 22 | * provided "AS-IS" and at no charge. |
23 | * | 23 | * |
diff --git a/net/irda/irlan/irlan_common.c b/net/irda/irlan/irlan_common.c index f5778ef3ccc7..a4b56e25a917 100644 --- a/net/irda/irlan/irlan_common.c +++ b/net/irda/irlan/irlan_common.c | |||
@@ -17,7 +17,7 @@ | |||
17 | * published by the Free Software Foundation; either version 2 of | 17 | * published by the Free Software Foundation; either version 2 of |
18 | * the License, or (at your option) any later version. | 18 | * the License, or (at your option) any later version. |
19 | * | 19 | * |
20 | * Neither Dag Brattli nor University of Tromsø admit liability nor | 20 | * Neither Dag Brattli nor University of Tromsø admit liability nor |
21 | * provide warranty for any of this software. This material is | 21 | * provide warranty for any of this software. This material is |
22 | * provided "AS-IS" and at no charge. | 22 | * provided "AS-IS" and at no charge. |
23 | * | 23 | * |
diff --git a/net/irda/irlan/irlan_eth.c b/net/irda/irlan/irlan_eth.c index 340f04a36b02..7f9c8542e5fc 100644 --- a/net/irda/irlan/irlan_eth.c +++ b/net/irda/irlan/irlan_eth.c | |||
@@ -19,7 +19,7 @@ | |||
19 | * published by the Free Software Foundation; either version 2 of | 19 | * published by the Free Software Foundation; either version 2 of |
20 | * the License, or (at your option) any later version. | 20 | * the License, or (at your option) any later version. |
21 | * | 21 | * |
22 | * Neither Dag Brattli nor University of Tromsø admit liability nor | 22 | * Neither Dag Brattli nor University of Tromsø admit liability nor |
23 | * provide warranty for any of this software. This material is | 23 | * provide warranty for any of this software. This material is |
24 | * provided "AS-IS" and at no charge. | 24 | * provided "AS-IS" and at no charge. |
25 | * | 25 | * |
diff --git a/net/irda/irlan/irlan_event.c b/net/irda/irlan/irlan_event.c index 623e0fd16c19..a9750a801388 100644 --- a/net/irda/irlan/irlan_event.c +++ b/net/irda/irlan/irlan_event.c | |||
@@ -16,7 +16,7 @@ | |||
16 | * published by the Free Software Foundation; either version 2 of | 16 | * published by the Free Software Foundation; either version 2 of |
17 | * the License, or (at your option) any later version. | 17 | * the License, or (at your option) any later version. |
18 | * | 18 | * |
19 | * Neither Dag Brattli nor University of Tromsø admit liability nor | 19 | * Neither Dag Brattli nor University of Tromsø admit liability nor |
20 | * provide warranty for any of this software. This material is | 20 | * provide warranty for any of this software. This material is |
21 | * provided "AS-IS" and at no charge. | 21 | * provided "AS-IS" and at no charge. |
22 | * | 22 | * |
diff --git a/net/irda/irlan/irlan_filter.c b/net/irda/irlan/irlan_filter.c index e6346b88f934..4384be9a6888 100644 --- a/net/irda/irlan/irlan_filter.c +++ b/net/irda/irlan/irlan_filter.c | |||
@@ -16,7 +16,7 @@ | |||
16 | * published by the Free Software Foundation; either version 2 of | 16 | * published by the Free Software Foundation; either version 2 of |
17 | * the License, or (at your option) any later version. | 17 | * the License, or (at your option) any later version. |
18 | * | 18 | * |
19 | * Neither Dag Brattli nor University of Tromsø admit liability nor | 19 | * Neither Dag Brattli nor University of Tromsø admit liability nor |
20 | * provide warranty for any of this software. This material is | 20 | * provide warranty for any of this software. This material is |
21 | * provided "AS-IS" and at no charge. | 21 | * provided "AS-IS" and at no charge. |
22 | * | 22 | * |
diff --git a/net/irda/irlan/irlan_provider.c b/net/irda/irlan/irlan_provider.c index aac66434e473..13db942812e4 100644 --- a/net/irda/irlan/irlan_provider.c +++ b/net/irda/irlan/irlan_provider.c | |||
@@ -20,7 +20,7 @@ | |||
20 | * published by the Free Software Foundation; either version 2 of | 20 | * published by the Free Software Foundation; either version 2 of |
21 | * the License, or (at your option) any later version. | 21 | * the License, or (at your option) any later version. |
22 | * | 22 | * |
23 | * Neither Dag Brattli nor University of Tromsø admit liability nor | 23 | * Neither Dag Brattli nor University of Tromsø admit liability nor |
24 | * provide warranty for any of this software. This material is | 24 | * provide warranty for any of this software. This material is |
25 | * provided "AS-IS" and at no charge. | 25 | * provided "AS-IS" and at no charge. |
26 | * | 26 | * |
diff --git a/net/irda/irlan/irlan_provider_event.c b/net/irda/irlan/irlan_provider_event.c index ef401bd6ea00..10ece5a47522 100644 --- a/net/irda/irlan/irlan_provider_event.c +++ b/net/irda/irlan/irlan_provider_event.c | |||
@@ -16,7 +16,7 @@ | |||
16 | * published by the Free Software Foundation; either version 2 of | 16 | * published by the Free Software Foundation; either version 2 of |
17 | * the License, or (at your option) any later version. | 17 | * the License, or (at your option) any later version. |
18 | * | 18 | * |
19 | * Neither Dag Brattli nor University of Tromsø admit liability nor | 19 | * Neither Dag Brattli nor University of Tromsø admit liability nor |
20 | * provide warranty for any of this software. This material is | 20 | * provide warranty for any of this software. This material is |
21 | * provided "AS-IS" and at no charge. | 21 | * provided "AS-IS" and at no charge. |
22 | * | 22 | * |
diff --git a/net/irda/irlap_event.c b/net/irda/irlap_event.c index a8b8873aa263..4c33bf5c8354 100644 --- a/net/irda/irlap_event.c +++ b/net/irda/irlap_event.c | |||
@@ -19,7 +19,7 @@ | |||
19 | * published by the Free Software Foundation; either version 2 of | 19 | * published by the Free Software Foundation; either version 2 of |
20 | * the License, or (at your option) any later version. | 20 | * the License, or (at your option) any later version. |
21 | * | 21 | * |
22 | * Neither Dag Brattli nor University of Tromsø admit liability nor | 22 | * Neither Dag Brattli nor University of Tromsø admit liability nor |
23 | * provide warranty for any of this software. This material is | 23 | * provide warranty for any of this software. This material is |
24 | * provided "AS-IS" and at no charge. | 24 | * provided "AS-IS" and at no charge. |
25 | * | 25 | * |
diff --git a/net/irda/irlap_frame.c b/net/irda/irlap_frame.c index 77ac27e81161..4f3764546b2f 100644 --- a/net/irda/irlap_frame.c +++ b/net/irda/irlap_frame.c | |||
@@ -18,7 +18,7 @@ | |||
18 | * published by the Free Software Foundation; either version 2 of | 18 | * published by the Free Software Foundation; either version 2 of |
19 | * the License, or (at your option) any later version. | 19 | * the License, or (at your option) any later version. |
20 | * | 20 | * |
21 | * Neither Dag Brattli nor University of Tromsø admit liability nor | 21 | * Neither Dag Brattli nor University of Tromsø admit liability nor |
22 | * provide warranty for any of this software. This material is | 22 | * provide warranty for any of this software. This material is |
23 | * provided "AS-IS" and at no charge. | 23 | * provided "AS-IS" and at no charge. |
24 | * | 24 | * |
diff --git a/net/irda/irlmp.c b/net/irda/irlmp.c index 7db92ced2c02..cedff8068fbc 100644 --- a/net/irda/irlmp.c +++ b/net/irda/irlmp.c | |||
@@ -18,7 +18,7 @@ | |||
18 | * published by the Free Software Foundation; either version 2 of | 18 | * published by the Free Software Foundation; either version 2 of |
19 | * the License, or (at your option) any later version. | 19 | * the License, or (at your option) any later version. |
20 | * | 20 | * |
21 | * Neither Dag Brattli nor University of Tromsø admit liability nor | 21 | * Neither Dag Brattli nor University of Tromsø admit liability nor |
22 | * provide warranty for any of this software. This material is | 22 | * provide warranty for any of this software. This material is |
23 | * provided "AS-IS" and at no charge. | 23 | * provided "AS-IS" and at no charge. |
24 | * | 24 | * |
diff --git a/net/irda/irlmp_event.c b/net/irda/irlmp_event.c index 65ffa981510a..1bba87e78609 100644 --- a/net/irda/irlmp_event.c +++ b/net/irda/irlmp_event.c | |||
@@ -18,7 +18,7 @@ | |||
18 | * published by the Free Software Foundation; either version 2 of | 18 | * published by the Free Software Foundation; either version 2 of |
19 | * the License, or (at your option) any later version. | 19 | * the License, or (at your option) any later version. |
20 | * | 20 | * |
21 | * Neither Dag Brattli nor University of Tromsø admit liability nor | 21 | * Neither Dag Brattli nor University of Tromsø admit liability nor |
22 | * provide warranty for any of this software. This material is | 22 | * provide warranty for any of this software. This material is |
23 | * provided "AS-IS" and at no charge. | 23 | * provided "AS-IS" and at no charge. |
24 | * | 24 | * |
diff --git a/net/irda/irlmp_frame.c b/net/irda/irlmp_frame.c index 559302d3fe66..0a79d9aeb08c 100644 --- a/net/irda/irlmp_frame.c +++ b/net/irda/irlmp_frame.c | |||
@@ -18,7 +18,7 @@ | |||
18 | * published by the Free Software Foundation; either version 2 of | 18 | * published by the Free Software Foundation; either version 2 of |
19 | * the License, or (at your option) any later version. | 19 | * the License, or (at your option) any later version. |
20 | * | 20 | * |
21 | * Neither Dag Brattli nor University of Tromsø admit liability nor | 21 | * Neither Dag Brattli nor University of Tromsø admit liability nor |
22 | * provide warranty for any of this software. This material is | 22 | * provide warranty for any of this software. This material is |
23 | * provided "AS-IS" and at no charge. | 23 | * provided "AS-IS" and at no charge. |
24 | * | 24 | * |
diff --git a/net/irda/irmod.c b/net/irda/irmod.c index 8ba703da2797..01554b996b9b 100644 --- a/net/irda/irmod.c +++ b/net/irda/irmod.c | |||
@@ -17,7 +17,7 @@ | |||
17 | * published by the Free Software Foundation; either version 2 of | 17 | * published by the Free Software Foundation; either version 2 of |
18 | * the License, or (at your option) any later version. | 18 | * the License, or (at your option) any later version. |
19 | * | 19 | * |
20 | * Neither Dag Brattli nor University of Tromsø admit liability nor | 20 | * Neither Dag Brattli nor University of Tromsø admit liability nor |
21 | * provide warranty for any of this software. This material is | 21 | * provide warranty for any of this software. This material is |
22 | * provided "AS-IS" and at no charge. | 22 | * provided "AS-IS" and at no charge. |
23 | * | 23 | * |
diff --git a/net/irda/irqueue.c b/net/irda/irqueue.c index d058b467f9e4..40c28efaed95 100644 --- a/net/irda/irqueue.c +++ b/net/irda/irqueue.c | |||
@@ -28,7 +28,7 @@ | |||
28 | * published by the Free Software Foundation; either version 2 of | 28 | * published by the Free Software Foundation; either version 2 of |
29 | * the License, or (at your option) any later version. | 29 | * the License, or (at your option) any later version. |
30 | * | 30 | * |
31 | * Neither Dag Brattli nor University of Tromsø admit liability nor | 31 | * Neither Dag Brattli nor University of Tromsø admit liability nor |
32 | * provide warranty for any of this software. This material is | 32 | * provide warranty for any of this software. This material is |
33 | * provided "AS-IS" and at no charge. | 33 | * provided "AS-IS" and at no charge. |
34 | * | 34 | * |
diff --git a/net/irda/irsysctl.c b/net/irda/irsysctl.c index 957e04feb0f7..565cbf0421cd 100644 --- a/net/irda/irsysctl.c +++ b/net/irda/irsysctl.c | |||
@@ -17,7 +17,7 @@ | |||
17 | * published by the Free Software Foundation; either version 2 of | 17 | * published by the Free Software Foundation; either version 2 of |
18 | * the License, or (at your option) any later version. | 18 | * the License, or (at your option) any later version. |
19 | * | 19 | * |
20 | * Neither Dag Brattli nor University of Tromsø admit liability nor | 20 | * Neither Dag Brattli nor University of Tromsø admit liability nor |
21 | * provide warranty for any of this software. This material is | 21 | * provide warranty for any of this software. This material is |
22 | * provided "AS-IS" and at no charge. | 22 | * provided "AS-IS" and at no charge. |
23 | * | 23 | * |
@@ -31,12 +31,6 @@ | |||
31 | #include <net/irda/irda.h> /* irda_debug */ | 31 | #include <net/irda/irda.h> /* irda_debug */ |
32 | #include <net/irda/irias_object.h> | 32 | #include <net/irda/irias_object.h> |
33 | 33 | ||
34 | #define NET_IRDA 412 /* Random number */ | ||
35 | enum { DISCOVERY=1, DEVNAME, DEBUG, FAST_POLL, DISCOVERY_SLOTS, | ||
36 | DISCOVERY_TIMEOUT, SLOT_TIMEOUT, MAX_BAUD_RATE, MIN_TX_TURN_TIME, | ||
37 | MAX_TX_DATA_SIZE, MAX_TX_WINDOW, MAX_NOREPLY_TIME, WARN_NOREPLY_TIME, | ||
38 | LAP_KEEPALIVE_TIME }; | ||
39 | |||
40 | extern int sysctl_discovery; | 34 | extern int sysctl_discovery; |
41 | extern int sysctl_discovery_slots; | 35 | extern int sysctl_discovery_slots; |
42 | extern int sysctl_discovery_timeout; | 36 | extern int sysctl_discovery_timeout; |
@@ -94,7 +88,7 @@ static int do_devname(ctl_table *table, int write, struct file *filp, | |||
94 | /* One file */ | 88 | /* One file */ |
95 | static ctl_table irda_table[] = { | 89 | static ctl_table irda_table[] = { |
96 | { | 90 | { |
97 | .ctl_name = DISCOVERY, | 91 | .ctl_name = NET_IRDA_DISCOVERY, |
98 | .procname = "discovery", | 92 | .procname = "discovery", |
99 | .data = &sysctl_discovery, | 93 | .data = &sysctl_discovery, |
100 | .maxlen = sizeof(int), | 94 | .maxlen = sizeof(int), |
@@ -102,7 +96,7 @@ static ctl_table irda_table[] = { | |||
102 | .proc_handler = &proc_dointvec | 96 | .proc_handler = &proc_dointvec |
103 | }, | 97 | }, |
104 | { | 98 | { |
105 | .ctl_name = DEVNAME, | 99 | .ctl_name = NET_IRDA_DEVNAME, |
106 | .procname = "devname", | 100 | .procname = "devname", |
107 | .data = sysctl_devname, | 101 | .data = sysctl_devname, |
108 | .maxlen = 65, | 102 | .maxlen = 65, |
@@ -112,7 +106,7 @@ static ctl_table irda_table[] = { | |||
112 | }, | 106 | }, |
113 | #ifdef CONFIG_IRDA_DEBUG | 107 | #ifdef CONFIG_IRDA_DEBUG |
114 | { | 108 | { |
115 | .ctl_name = DEBUG, | 109 | .ctl_name = NET_IRDA_DEBUG, |
116 | .procname = "debug", | 110 | .procname = "debug", |
117 | .data = &irda_debug, | 111 | .data = &irda_debug, |
118 | .maxlen = sizeof(int), | 112 | .maxlen = sizeof(int), |
@@ -122,7 +116,7 @@ static ctl_table irda_table[] = { | |||
122 | #endif | 116 | #endif |
123 | #ifdef CONFIG_IRDA_FAST_RR | 117 | #ifdef CONFIG_IRDA_FAST_RR |
124 | { | 118 | { |
125 | .ctl_name = FAST_POLL, | 119 | .ctl_name = NET_IRDA_FAST_POLL, |
126 | .procname = "fast_poll_increase", | 120 | .procname = "fast_poll_increase", |
127 | .data = &sysctl_fast_poll_increase, | 121 | .data = &sysctl_fast_poll_increase, |
128 | .maxlen = sizeof(int), | 122 | .maxlen = sizeof(int), |
@@ -131,7 +125,7 @@ static ctl_table irda_table[] = { | |||
131 | }, | 125 | }, |
132 | #endif | 126 | #endif |
133 | { | 127 | { |
134 | .ctl_name = DISCOVERY_SLOTS, | 128 | .ctl_name = NET_IRDA_DISCOVERY_SLOTS, |
135 | .procname = "discovery_slots", | 129 | .procname = "discovery_slots", |
136 | .data = &sysctl_discovery_slots, | 130 | .data = &sysctl_discovery_slots, |
137 | .maxlen = sizeof(int), | 131 | .maxlen = sizeof(int), |
@@ -142,7 +136,7 @@ static ctl_table irda_table[] = { | |||
142 | .extra2 = &max_discovery_slots | 136 | .extra2 = &max_discovery_slots |
143 | }, | 137 | }, |
144 | { | 138 | { |
145 | .ctl_name = DISCOVERY_TIMEOUT, | 139 | .ctl_name = NET_IRDA_DISCOVERY_TIMEOUT, |
146 | .procname = "discovery_timeout", | 140 | .procname = "discovery_timeout", |
147 | .data = &sysctl_discovery_timeout, | 141 | .data = &sysctl_discovery_timeout, |
148 | .maxlen = sizeof(int), | 142 | .maxlen = sizeof(int), |
@@ -150,7 +144,7 @@ static ctl_table irda_table[] = { | |||
150 | .proc_handler = &proc_dointvec | 144 | .proc_handler = &proc_dointvec |
151 | }, | 145 | }, |
152 | { | 146 | { |
153 | .ctl_name = SLOT_TIMEOUT, | 147 | .ctl_name = NET_IRDA_SLOT_TIMEOUT, |
154 | .procname = "slot_timeout", | 148 | .procname = "slot_timeout", |
155 | .data = &sysctl_slot_timeout, | 149 | .data = &sysctl_slot_timeout, |
156 | .maxlen = sizeof(int), | 150 | .maxlen = sizeof(int), |
@@ -161,7 +155,7 @@ static ctl_table irda_table[] = { | |||
161 | .extra2 = &max_slot_timeout | 155 | .extra2 = &max_slot_timeout |
162 | }, | 156 | }, |
163 | { | 157 | { |
164 | .ctl_name = MAX_BAUD_RATE, | 158 | .ctl_name = NET_IRDA_MAX_BAUD_RATE, |
165 | .procname = "max_baud_rate", | 159 | .procname = "max_baud_rate", |
166 | .data = &sysctl_max_baud_rate, | 160 | .data = &sysctl_max_baud_rate, |
167 | .maxlen = sizeof(int), | 161 | .maxlen = sizeof(int), |
@@ -172,7 +166,7 @@ static ctl_table irda_table[] = { | |||
172 | .extra2 = &max_max_baud_rate | 166 | .extra2 = &max_max_baud_rate |
173 | }, | 167 | }, |
174 | { | 168 | { |
175 | .ctl_name = MIN_TX_TURN_TIME, | 169 | .ctl_name = NET_IRDA_MIN_TX_TURN_TIME, |
176 | .procname = "min_tx_turn_time", | 170 | .procname = "min_tx_turn_time", |
177 | .data = &sysctl_min_tx_turn_time, | 171 | .data = &sysctl_min_tx_turn_time, |
178 | .maxlen = sizeof(int), | 172 | .maxlen = sizeof(int), |
@@ -183,7 +177,7 @@ static ctl_table irda_table[] = { | |||
183 | .extra2 = &max_min_tx_turn_time | 177 | .extra2 = &max_min_tx_turn_time |
184 | }, | 178 | }, |
185 | { | 179 | { |
186 | .ctl_name = MAX_TX_DATA_SIZE, | 180 | .ctl_name = NET_IRDA_MAX_TX_DATA_SIZE, |
187 | .procname = "max_tx_data_size", | 181 | .procname = "max_tx_data_size", |
188 | .data = &sysctl_max_tx_data_size, | 182 | .data = &sysctl_max_tx_data_size, |
189 | .maxlen = sizeof(int), | 183 | .maxlen = sizeof(int), |
@@ -194,7 +188,7 @@ static ctl_table irda_table[] = { | |||
194 | .extra2 = &max_max_tx_data_size | 188 | .extra2 = &max_max_tx_data_size |
195 | }, | 189 | }, |
196 | { | 190 | { |
197 | .ctl_name = MAX_TX_WINDOW, | 191 | .ctl_name = NET_IRDA_MAX_TX_WINDOW, |
198 | .procname = "max_tx_window", | 192 | .procname = "max_tx_window", |
199 | .data = &sysctl_max_tx_window, | 193 | .data = &sysctl_max_tx_window, |
200 | .maxlen = sizeof(int), | 194 | .maxlen = sizeof(int), |
@@ -205,7 +199,7 @@ static ctl_table irda_table[] = { | |||
205 | .extra2 = &max_max_tx_window | 199 | .extra2 = &max_max_tx_window |
206 | }, | 200 | }, |
207 | { | 201 | { |
208 | .ctl_name = MAX_NOREPLY_TIME, | 202 | .ctl_name = NET_IRDA_MAX_NOREPLY_TIME, |
209 | .procname = "max_noreply_time", | 203 | .procname = "max_noreply_time", |
210 | .data = &sysctl_max_noreply_time, | 204 | .data = &sysctl_max_noreply_time, |
211 | .maxlen = sizeof(int), | 205 | .maxlen = sizeof(int), |
@@ -216,7 +210,7 @@ static ctl_table irda_table[] = { | |||
216 | .extra2 = &max_max_noreply_time | 210 | .extra2 = &max_max_noreply_time |
217 | }, | 211 | }, |
218 | { | 212 | { |
219 | .ctl_name = WARN_NOREPLY_TIME, | 213 | .ctl_name = NET_IRDA_WARN_NOREPLY_TIME, |
220 | .procname = "warn_noreply_time", | 214 | .procname = "warn_noreply_time", |
221 | .data = &sysctl_warn_noreply_time, | 215 | .data = &sysctl_warn_noreply_time, |
222 | .maxlen = sizeof(int), | 216 | .maxlen = sizeof(int), |
@@ -227,7 +221,7 @@ static ctl_table irda_table[] = { | |||
227 | .extra2 = &max_warn_noreply_time | 221 | .extra2 = &max_warn_noreply_time |
228 | }, | 222 | }, |
229 | { | 223 | { |
230 | .ctl_name = LAP_KEEPALIVE_TIME, | 224 | .ctl_name = NET_IRDA_LAP_KEEPALIVE_TIME, |
231 | .procname = "lap_keepalive_time", | 225 | .procname = "lap_keepalive_time", |
232 | .data = &sysctl_lap_keepalive_time, | 226 | .data = &sysctl_lap_keepalive_time, |
233 | .maxlen = sizeof(int), | 227 | .maxlen = sizeof(int), |
diff --git a/net/irda/irttp.c b/net/irda/irttp.c index 1311976c9dfe..97db158c9274 100644 --- a/net/irda/irttp.c +++ b/net/irda/irttp.c | |||
@@ -18,7 +18,7 @@ | |||
18 | * published by the Free Software Foundation; either version 2 of | 18 | * published by the Free Software Foundation; either version 2 of |
19 | * the License, or (at your option) any later version. | 19 | * the License, or (at your option) any later version. |
20 | * | 20 | * |
21 | * Neither Dag Brattli nor University of Tromsø admit liability nor | 21 | * Neither Dag Brattli nor University of Tromsø admit liability nor |
22 | * provide warranty for any of this software. This material is | 22 | * provide warranty for any of this software. This material is |
23 | * provided "AS-IS" and at no charge. | 23 | * provided "AS-IS" and at no charge. |
24 | * | 24 | * |
diff --git a/net/irda/timer.c b/net/irda/timer.c index d3a6ee8cc4a2..d730099080a2 100644 --- a/net/irda/timer.c +++ b/net/irda/timer.c | |||
@@ -18,7 +18,7 @@ | |||
18 | * published by the Free Software Foundation; either version 2 of | 18 | * published by the Free Software Foundation; either version 2 of |
19 | * the License, or (at your option) any later version. | 19 | * the License, or (at your option) any later version. |
20 | * | 20 | * |
21 | * Neither Dag Brattli nor University of Tromsø admit liability nor | 21 | * Neither Dag Brattli nor University of Tromsø admit liability nor |
22 | * provide warranty for any of this software. This material is | 22 | * provide warranty for any of this software. This material is |
23 | * provided "AS-IS" and at no charge. | 23 | * provided "AS-IS" and at no charge. |
24 | * | 24 | * |
diff --git a/net/irda/wrapper.c b/net/irda/wrapper.c index a7a7f191f1a8..e71286768a48 100644 --- a/net/irda/wrapper.c +++ b/net/irda/wrapper.c | |||
@@ -20,7 +20,7 @@ | |||
20 | * published by the Free Software Foundation; either version 2 of | 20 | * published by the Free Software Foundation; either version 2 of |
21 | * the License, or (at your option) any later version. | 21 | * the License, or (at your option) any later version. |
22 | * | 22 | * |
23 | * Neither Dag Brattli nor University of Tromsø admit liability nor | 23 | * Neither Dag Brattli nor University of Tromsø admit liability nor |
24 | * provide warranty for any of this software. This material is | 24 | * provide warranty for any of this software. This material is |
25 | * provided "AS-IS" and at no charge. | 25 | * provided "AS-IS" and at no charge. |
26 | * | 26 | * |
diff --git a/net/iucv/iucv.c b/net/iucv/iucv.c index 983058d432dc..a2f5a6ea3895 100644 --- a/net/iucv/iucv.c +++ b/net/iucv/iucv.c | |||
@@ -389,7 +389,7 @@ static void iucv_block_cpu(void *data) | |||
389 | * iucv_declare_cpu | 389 | * iucv_declare_cpu |
390 | * @data: unused | 390 | * @data: unused |
391 | * | 391 | * |
392 | * Declare a interupt buffer on this cpu. | 392 | * Declare a interrupt buffer on this cpu. |
393 | */ | 393 | */ |
394 | static void iucv_declare_cpu(void *data) | 394 | static void iucv_declare_cpu(void *data) |
395 | { | 395 | { |
diff --git a/net/llc/af_llc.c b/net/llc/af_llc.c index 49eacba824df..46cf962f7f88 100644 --- a/net/llc/af_llc.c +++ b/net/llc/af_llc.c | |||
@@ -762,7 +762,7 @@ static int llc_ui_recvmsg(struct kiocb *iocb, struct socket *sock, | |||
762 | if (net_ratelimit()) | 762 | if (net_ratelimit()) |
763 | printk(KERN_DEBUG "LLC(%s:%d): Application " | 763 | printk(KERN_DEBUG "LLC(%s:%d): Application " |
764 | "bug, race in MSG_PEEK.\n", | 764 | "bug, race in MSG_PEEK.\n", |
765 | current->comm, current->pid); | 765 | current->comm, task_pid_nr(current)); |
766 | peek_seq = llc->copied_seq; | 766 | peek_seq = llc->copied_seq; |
767 | } | 767 | } |
768 | continue; | 768 | continue; |
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index d34a9deca67a..4b4ed2a5803c 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h | |||
@@ -37,8 +37,6 @@ | |||
37 | 37 | ||
38 | struct ieee80211_local; | 38 | struct ieee80211_local; |
39 | 39 | ||
40 | #define BIT(x) (1 << (x)) | ||
41 | |||
42 | #define IEEE80211_ALIGN32_PAD(a) ((4 - ((a) & 3)) & 3) | 40 | #define IEEE80211_ALIGN32_PAD(a) ((4 - ((a) & 3)) & 3) |
43 | 41 | ||
44 | /* Maximum number of broadcast/multicast frames to buffer when some of the | 42 | /* Maximum number of broadcast/multicast frames to buffer when some of the |
diff --git a/net/mac80211/ieee80211_ioctl.c b/net/mac80211/ieee80211_ioctl.c index f0224c2311d2..6caa3ec2cff7 100644 --- a/net/mac80211/ieee80211_ioctl.c +++ b/net/mac80211/ieee80211_ioctl.c | |||
@@ -306,9 +306,12 @@ int ieee80211_set_channel(struct ieee80211_local *local, int channel, int freq) | |||
306 | ((chan->chan == channel) || (chan->freq == freq))) { | 306 | ((chan->chan == channel) || (chan->freq == freq))) { |
307 | local->oper_channel = chan; | 307 | local->oper_channel = chan; |
308 | local->oper_hw_mode = mode; | 308 | local->oper_hw_mode = mode; |
309 | set++; | 309 | set = 1; |
310 | break; | ||
310 | } | 311 | } |
311 | } | 312 | } |
313 | if (set) | ||
314 | break; | ||
312 | } | 315 | } |
313 | 316 | ||
314 | if (set) { | 317 | if (set) { |
@@ -508,10 +511,11 @@ static int ieee80211_ioctl_giwap(struct net_device *dev, | |||
508 | 511 | ||
509 | static int ieee80211_ioctl_siwscan(struct net_device *dev, | 512 | static int ieee80211_ioctl_siwscan(struct net_device *dev, |
510 | struct iw_request_info *info, | 513 | struct iw_request_info *info, |
511 | struct iw_point *data, char *extra) | 514 | union iwreq_data *wrqu, char *extra) |
512 | { | 515 | { |
513 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | 516 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); |
514 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 517 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
518 | struct iw_scan_req *req = NULL; | ||
515 | u8 *ssid = NULL; | 519 | u8 *ssid = NULL; |
516 | size_t ssid_len = 0; | 520 | size_t ssid_len = 0; |
517 | 521 | ||
@@ -536,6 +540,14 @@ static int ieee80211_ioctl_siwscan(struct net_device *dev, | |||
536 | return -EOPNOTSUPP; | 540 | return -EOPNOTSUPP; |
537 | } | 541 | } |
538 | 542 | ||
543 | /* if SSID was specified explicitly then use that */ | ||
544 | if (wrqu->data.length == sizeof(struct iw_scan_req) && | ||
545 | wrqu->data.flags & IW_SCAN_THIS_ESSID) { | ||
546 | req = (struct iw_scan_req *)extra; | ||
547 | ssid = req->essid; | ||
548 | ssid_len = req->essid_len; | ||
549 | } | ||
550 | |||
539 | return ieee80211_sta_req_scan(dev, ssid, ssid_len); | 551 | return ieee80211_sta_req_scan(dev, ssid, ssid_len); |
540 | } | 552 | } |
541 | 553 | ||
diff --git a/net/mac80211/ieee80211_sta.c b/net/mac80211/ieee80211_sta.c index 1641e8fe44b7..f7ffeec3913f 100644 --- a/net/mac80211/ieee80211_sta.c +++ b/net/mac80211/ieee80211_sta.c | |||
@@ -12,7 +12,6 @@ | |||
12 | */ | 12 | */ |
13 | 13 | ||
14 | /* TODO: | 14 | /* TODO: |
15 | * BSS table: use <BSSID,SSID> as the key to support multi-SSID APs | ||
16 | * order BSS list by RSSI(?) ("quality of AP") | 15 | * order BSS list by RSSI(?) ("quality of AP") |
17 | * scan result table filtering (by capability (privacy, IBSS/BSS, WPA/RSN IE, | 16 | * scan result table filtering (by capability (privacy, IBSS/BSS, WPA/RSN IE, |
18 | * SSID) | 17 | * SSID) |
@@ -61,7 +60,8 @@ | |||
61 | static void ieee80211_send_probe_req(struct net_device *dev, u8 *dst, | 60 | static void ieee80211_send_probe_req(struct net_device *dev, u8 *dst, |
62 | u8 *ssid, size_t ssid_len); | 61 | u8 *ssid, size_t ssid_len); |
63 | static struct ieee80211_sta_bss * | 62 | static struct ieee80211_sta_bss * |
64 | ieee80211_rx_bss_get(struct net_device *dev, u8 *bssid); | 63 | ieee80211_rx_bss_get(struct net_device *dev, u8 *bssid, int channel, |
64 | u8 *ssid, u8 ssid_len); | ||
65 | static void ieee80211_rx_bss_put(struct net_device *dev, | 65 | static void ieee80211_rx_bss_put(struct net_device *dev, |
66 | struct ieee80211_sta_bss *bss); | 66 | struct ieee80211_sta_bss *bss); |
67 | static int ieee80211_sta_find_ibss(struct net_device *dev, | 67 | static int ieee80211_sta_find_ibss(struct net_device *dev, |
@@ -108,14 +108,11 @@ struct ieee802_11_elems { | |||
108 | u8 wmm_param_len; | 108 | u8 wmm_param_len; |
109 | }; | 109 | }; |
110 | 110 | ||
111 | enum ParseRes { ParseOK = 0, ParseUnknown = 1, ParseFailed = -1 }; | 111 | static void ieee802_11_parse_elems(u8 *start, size_t len, |
112 | 112 | struct ieee802_11_elems *elems) | |
113 | static enum ParseRes ieee802_11_parse_elems(u8 *start, size_t len, | ||
114 | struct ieee802_11_elems *elems) | ||
115 | { | 113 | { |
116 | size_t left = len; | 114 | size_t left = len; |
117 | u8 *pos = start; | 115 | u8 *pos = start; |
118 | int unknown = 0; | ||
119 | 116 | ||
120 | memset(elems, 0, sizeof(*elems)); | 117 | memset(elems, 0, sizeof(*elems)); |
121 | 118 | ||
@@ -126,15 +123,8 @@ static enum ParseRes ieee802_11_parse_elems(u8 *start, size_t len, | |||
126 | elen = *pos++; | 123 | elen = *pos++; |
127 | left -= 2; | 124 | left -= 2; |
128 | 125 | ||
129 | if (elen > left) { | 126 | if (elen > left) |
130 | #if 0 | 127 | return; |
131 | if (net_ratelimit()) | ||
132 | printk(KERN_DEBUG "IEEE 802.11 element parse " | ||
133 | "failed (id=%d elen=%d left=%d)\n", | ||
134 | id, elen, left); | ||
135 | #endif | ||
136 | return ParseFailed; | ||
137 | } | ||
138 | 128 | ||
139 | switch (id) { | 129 | switch (id) { |
140 | case WLAN_EID_SSID: | 130 | case WLAN_EID_SSID: |
@@ -201,28 +191,15 @@ static enum ParseRes ieee802_11_parse_elems(u8 *start, size_t len, | |||
201 | elems->ext_supp_rates_len = elen; | 191 | elems->ext_supp_rates_len = elen; |
202 | break; | 192 | break; |
203 | default: | 193 | default: |
204 | #if 0 | ||
205 | printk(KERN_DEBUG "IEEE 802.11 element parse ignored " | ||
206 | "unknown element (id=%d elen=%d)\n", | ||
207 | id, elen); | ||
208 | #endif | ||
209 | unknown++; | ||
210 | break; | 194 | break; |
211 | } | 195 | } |
212 | 196 | ||
213 | left -= elen; | 197 | left -= elen; |
214 | pos += elen; | 198 | pos += elen; |
215 | } | 199 | } |
216 | |||
217 | /* Do not trigger error if left == 1 as Apple Airport base stations | ||
218 | * send AssocResps that are one spurious byte too long. */ | ||
219 | |||
220 | return unknown ? ParseUnknown : ParseOK; | ||
221 | } | 200 | } |
222 | 201 | ||
223 | 202 | ||
224 | |||
225 | |||
226 | static int ecw2cw(int ecw) | 203 | static int ecw2cw(int ecw) |
227 | { | 204 | { |
228 | int cw = 1; | 205 | int cw = 1; |
@@ -427,7 +404,9 @@ static void ieee80211_set_associated(struct net_device *dev, | |||
427 | if (sdata->type != IEEE80211_IF_TYPE_STA) | 404 | if (sdata->type != IEEE80211_IF_TYPE_STA) |
428 | return; | 405 | return; |
429 | 406 | ||
430 | bss = ieee80211_rx_bss_get(dev, ifsta->bssid); | 407 | bss = ieee80211_rx_bss_get(dev, ifsta->bssid, |
408 | local->hw.conf.channel, | ||
409 | ifsta->ssid, ifsta->ssid_len); | ||
431 | if (bss) { | 410 | if (bss) { |
432 | if (bss->has_erp_value) | 411 | if (bss->has_erp_value) |
433 | ieee80211_handle_erp_ie(dev, bss->erp_value); | 412 | ieee80211_handle_erp_ie(dev, bss->erp_value); |
@@ -574,7 +553,8 @@ static void ieee80211_send_assoc(struct net_device *dev, | |||
574 | capab |= WLAN_CAPABILITY_SHORT_SLOT_TIME | | 553 | capab |= WLAN_CAPABILITY_SHORT_SLOT_TIME | |
575 | WLAN_CAPABILITY_SHORT_PREAMBLE; | 554 | WLAN_CAPABILITY_SHORT_PREAMBLE; |
576 | } | 555 | } |
577 | bss = ieee80211_rx_bss_get(dev, ifsta->bssid); | 556 | bss = ieee80211_rx_bss_get(dev, ifsta->bssid, local->hw.conf.channel, |
557 | ifsta->ssid, ifsta->ssid_len); | ||
578 | if (bss) { | 558 | if (bss) { |
579 | if (bss->capability & WLAN_CAPABILITY_PRIVACY) | 559 | if (bss->capability & WLAN_CAPABILITY_PRIVACY) |
580 | capab |= WLAN_CAPABILITY_PRIVACY; | 560 | capab |= WLAN_CAPABILITY_PRIVACY; |
@@ -722,6 +702,7 @@ static void ieee80211_send_disassoc(struct net_device *dev, | |||
722 | static int ieee80211_privacy_mismatch(struct net_device *dev, | 702 | static int ieee80211_privacy_mismatch(struct net_device *dev, |
723 | struct ieee80211_if_sta *ifsta) | 703 | struct ieee80211_if_sta *ifsta) |
724 | { | 704 | { |
705 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | ||
725 | struct ieee80211_sta_bss *bss; | 706 | struct ieee80211_sta_bss *bss; |
726 | int res = 0; | 707 | int res = 0; |
727 | 708 | ||
@@ -729,7 +710,8 @@ static int ieee80211_privacy_mismatch(struct net_device *dev, | |||
729 | ifsta->key_management_enabled) | 710 | ifsta->key_management_enabled) |
730 | return 0; | 711 | return 0; |
731 | 712 | ||
732 | bss = ieee80211_rx_bss_get(dev, ifsta->bssid); | 713 | bss = ieee80211_rx_bss_get(dev, ifsta->bssid, local->hw.conf.channel, |
714 | ifsta->ssid, ifsta->ssid_len); | ||
733 | if (!bss) | 715 | if (!bss) |
734 | return 0; | 716 | return 0; |
735 | 717 | ||
@@ -926,12 +908,7 @@ static void ieee80211_auth_challenge(struct net_device *dev, | |||
926 | 908 | ||
927 | printk(KERN_DEBUG "%s: replying to auth challenge\n", dev->name); | 909 | printk(KERN_DEBUG "%s: replying to auth challenge\n", dev->name); |
928 | pos = mgmt->u.auth.variable; | 910 | pos = mgmt->u.auth.variable; |
929 | if (ieee802_11_parse_elems(pos, len - (pos - (u8 *) mgmt), &elems) | 911 | ieee802_11_parse_elems(pos, len - (pos - (u8 *) mgmt), &elems); |
930 | == ParseFailed) { | ||
931 | printk(KERN_DEBUG "%s: failed to parse Auth(challenge)\n", | ||
932 | dev->name); | ||
933 | return; | ||
934 | } | ||
935 | if (!elems.challenge) { | 912 | if (!elems.challenge) { |
936 | printk(KERN_DEBUG "%s: no challenge IE in shared key auth " | 913 | printk(KERN_DEBUG "%s: no challenge IE in shared key auth " |
937 | "frame\n", dev->name); | 914 | "frame\n", dev->name); |
@@ -1203,15 +1180,11 @@ static void ieee80211_rx_mgmt_assoc_resp(struct net_device *dev, | |||
1203 | capab_info = le16_to_cpu(mgmt->u.assoc_resp.capab_info); | 1180 | capab_info = le16_to_cpu(mgmt->u.assoc_resp.capab_info); |
1204 | status_code = le16_to_cpu(mgmt->u.assoc_resp.status_code); | 1181 | status_code = le16_to_cpu(mgmt->u.assoc_resp.status_code); |
1205 | aid = le16_to_cpu(mgmt->u.assoc_resp.aid); | 1182 | aid = le16_to_cpu(mgmt->u.assoc_resp.aid); |
1206 | if ((aid & (BIT(15) | BIT(14))) != (BIT(15) | BIT(14))) | ||
1207 | printk(KERN_DEBUG "%s: invalid aid value %d; bits 15:14 not " | ||
1208 | "set\n", dev->name, aid); | ||
1209 | aid &= ~(BIT(15) | BIT(14)); | ||
1210 | 1183 | ||
1211 | printk(KERN_DEBUG "%s: RX %sssocResp from %s (capab=0x%x " | 1184 | printk(KERN_DEBUG "%s: RX %sssocResp from %s (capab=0x%x " |
1212 | "status=%d aid=%d)\n", | 1185 | "status=%d aid=%d)\n", |
1213 | dev->name, reassoc ? "Rea" : "A", print_mac(mac, mgmt->sa), | 1186 | dev->name, reassoc ? "Rea" : "A", print_mac(mac, mgmt->sa), |
1214 | capab_info, status_code, aid); | 1187 | capab_info, status_code, aid & ~(BIT(15) | BIT(14))); |
1215 | 1188 | ||
1216 | if (status_code != WLAN_STATUS_SUCCESS) { | 1189 | if (status_code != WLAN_STATUS_SUCCESS) { |
1217 | printk(KERN_DEBUG "%s: AP denied association (code=%d)\n", | 1190 | printk(KERN_DEBUG "%s: AP denied association (code=%d)\n", |
@@ -1223,13 +1196,13 @@ static void ieee80211_rx_mgmt_assoc_resp(struct net_device *dev, | |||
1223 | return; | 1196 | return; |
1224 | } | 1197 | } |
1225 | 1198 | ||
1199 | if ((aid & (BIT(15) | BIT(14))) != (BIT(15) | BIT(14))) | ||
1200 | printk(KERN_DEBUG "%s: invalid aid value %d; bits 15:14 not " | ||
1201 | "set\n", dev->name, aid); | ||
1202 | aid &= ~(BIT(15) | BIT(14)); | ||
1203 | |||
1226 | pos = mgmt->u.assoc_resp.variable; | 1204 | pos = mgmt->u.assoc_resp.variable; |
1227 | if (ieee802_11_parse_elems(pos, len - (pos - (u8 *) mgmt), &elems) | 1205 | ieee802_11_parse_elems(pos, len - (pos - (u8 *) mgmt), &elems); |
1228 | == ParseFailed) { | ||
1229 | printk(KERN_DEBUG "%s: failed to parse AssocResp\n", | ||
1230 | dev->name); | ||
1231 | return; | ||
1232 | } | ||
1233 | 1206 | ||
1234 | if (!elems.supp_rates) { | 1207 | if (!elems.supp_rates) { |
1235 | printk(KERN_DEBUG "%s: no SuppRates element in AssocResp\n", | 1208 | printk(KERN_DEBUG "%s: no SuppRates element in AssocResp\n", |
@@ -1241,7 +1214,9 @@ static void ieee80211_rx_mgmt_assoc_resp(struct net_device *dev, | |||
1241 | * update our stored copy */ | 1214 | * update our stored copy */ |
1242 | if (elems.erp_info && elems.erp_info_len >= 1) { | 1215 | if (elems.erp_info && elems.erp_info_len >= 1) { |
1243 | struct ieee80211_sta_bss *bss | 1216 | struct ieee80211_sta_bss *bss |
1244 | = ieee80211_rx_bss_get(dev, ifsta->bssid); | 1217 | = ieee80211_rx_bss_get(dev, ifsta->bssid, |
1218 | local->hw.conf.channel, | ||
1219 | ifsta->ssid, ifsta->ssid_len); | ||
1245 | if (bss) { | 1220 | if (bss) { |
1246 | bss->erp_value = elems.erp_info[0]; | 1221 | bss->erp_value = elems.erp_info[0]; |
1247 | bss->has_erp_value = 1; | 1222 | bss->has_erp_value = 1; |
@@ -1271,7 +1246,9 @@ static void ieee80211_rx_mgmt_assoc_resp(struct net_device *dev, | |||
1271 | " AP\n", dev->name); | 1246 | " AP\n", dev->name); |
1272 | return; | 1247 | return; |
1273 | } | 1248 | } |
1274 | bss = ieee80211_rx_bss_get(dev, ifsta->bssid); | 1249 | bss = ieee80211_rx_bss_get(dev, ifsta->bssid, |
1250 | local->hw.conf.channel, | ||
1251 | ifsta->ssid, ifsta->ssid_len); | ||
1275 | if (bss) { | 1252 | if (bss) { |
1276 | sta->last_rssi = bss->rssi; | 1253 | sta->last_rssi = bss->rssi; |
1277 | sta->last_signal = bss->signal; | 1254 | sta->last_signal = bss->signal; |
@@ -1347,7 +1324,8 @@ static void __ieee80211_rx_bss_hash_del(struct net_device *dev, | |||
1347 | 1324 | ||
1348 | 1325 | ||
1349 | static struct ieee80211_sta_bss * | 1326 | static struct ieee80211_sta_bss * |
1350 | ieee80211_rx_bss_add(struct net_device *dev, u8 *bssid) | 1327 | ieee80211_rx_bss_add(struct net_device *dev, u8 *bssid, int channel, |
1328 | u8 *ssid, u8 ssid_len) | ||
1351 | { | 1329 | { |
1352 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | 1330 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); |
1353 | struct ieee80211_sta_bss *bss; | 1331 | struct ieee80211_sta_bss *bss; |
@@ -1358,6 +1336,11 @@ ieee80211_rx_bss_add(struct net_device *dev, u8 *bssid) | |||
1358 | atomic_inc(&bss->users); | 1336 | atomic_inc(&bss->users); |
1359 | atomic_inc(&bss->users); | 1337 | atomic_inc(&bss->users); |
1360 | memcpy(bss->bssid, bssid, ETH_ALEN); | 1338 | memcpy(bss->bssid, bssid, ETH_ALEN); |
1339 | bss->channel = channel; | ||
1340 | if (ssid && ssid_len <= IEEE80211_MAX_SSID_LEN) { | ||
1341 | memcpy(bss->ssid, ssid, ssid_len); | ||
1342 | bss->ssid_len = ssid_len; | ||
1343 | } | ||
1361 | 1344 | ||
1362 | spin_lock_bh(&local->sta_bss_lock); | 1345 | spin_lock_bh(&local->sta_bss_lock); |
1363 | /* TODO: order by RSSI? */ | 1346 | /* TODO: order by RSSI? */ |
@@ -1369,7 +1352,8 @@ ieee80211_rx_bss_add(struct net_device *dev, u8 *bssid) | |||
1369 | 1352 | ||
1370 | 1353 | ||
1371 | static struct ieee80211_sta_bss * | 1354 | static struct ieee80211_sta_bss * |
1372 | ieee80211_rx_bss_get(struct net_device *dev, u8 *bssid) | 1355 | ieee80211_rx_bss_get(struct net_device *dev, u8 *bssid, int channel, |
1356 | u8 *ssid, u8 ssid_len) | ||
1373 | { | 1357 | { |
1374 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | 1358 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); |
1375 | struct ieee80211_sta_bss *bss; | 1359 | struct ieee80211_sta_bss *bss; |
@@ -1377,7 +1361,10 @@ ieee80211_rx_bss_get(struct net_device *dev, u8 *bssid) | |||
1377 | spin_lock_bh(&local->sta_bss_lock); | 1361 | spin_lock_bh(&local->sta_bss_lock); |
1378 | bss = local->sta_bss_hash[STA_HASH(bssid)]; | 1362 | bss = local->sta_bss_hash[STA_HASH(bssid)]; |
1379 | while (bss) { | 1363 | while (bss) { |
1380 | if (memcmp(bss->bssid, bssid, ETH_ALEN) == 0) { | 1364 | if (!memcmp(bss->bssid, bssid, ETH_ALEN) && |
1365 | bss->channel == channel && | ||
1366 | bss->ssid_len == ssid_len && | ||
1367 | (ssid_len == 0 || !memcmp(bss->ssid, ssid, ssid_len))) { | ||
1381 | atomic_inc(&bss->users); | 1368 | atomic_inc(&bss->users); |
1382 | break; | 1369 | break; |
1383 | } | 1370 | } |
@@ -1439,7 +1426,7 @@ static void ieee80211_rx_bss_info(struct net_device *dev, | |||
1439 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | 1426 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); |
1440 | struct ieee802_11_elems elems; | 1427 | struct ieee802_11_elems elems; |
1441 | size_t baselen; | 1428 | size_t baselen; |
1442 | int channel, invalid = 0, clen; | 1429 | int channel, clen; |
1443 | struct ieee80211_sta_bss *bss; | 1430 | struct ieee80211_sta_bss *bss; |
1444 | struct sta_info *sta; | 1431 | struct sta_info *sta; |
1445 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 1432 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
@@ -1485,9 +1472,7 @@ static void ieee80211_rx_bss_info(struct net_device *dev, | |||
1485 | #endif /* CONFIG_MAC80211_IBSS_DEBUG */ | 1472 | #endif /* CONFIG_MAC80211_IBSS_DEBUG */ |
1486 | } | 1473 | } |
1487 | 1474 | ||
1488 | if (ieee802_11_parse_elems(mgmt->u.beacon.variable, len - baselen, | 1475 | ieee802_11_parse_elems(mgmt->u.beacon.variable, len - baselen, &elems); |
1489 | &elems) == ParseFailed) | ||
1490 | invalid = 1; | ||
1491 | 1476 | ||
1492 | if (sdata->type == IEEE80211_IF_TYPE_IBSS && elems.supp_rates && | 1477 | if (sdata->type == IEEE80211_IF_TYPE_IBSS && elems.supp_rates && |
1493 | memcmp(mgmt->bssid, sdata->u.sta.bssid, ETH_ALEN) == 0 && | 1478 | memcmp(mgmt->bssid, sdata->u.sta.bssid, ETH_ALEN) == 0 && |
@@ -1545,9 +1530,11 @@ static void ieee80211_rx_bss_info(struct net_device *dev, | |||
1545 | else | 1530 | else |
1546 | channel = rx_status->channel; | 1531 | channel = rx_status->channel; |
1547 | 1532 | ||
1548 | bss = ieee80211_rx_bss_get(dev, mgmt->bssid); | 1533 | bss = ieee80211_rx_bss_get(dev, mgmt->bssid, channel, |
1534 | elems.ssid, elems.ssid_len); | ||
1549 | if (!bss) { | 1535 | if (!bss) { |
1550 | bss = ieee80211_rx_bss_add(dev, mgmt->bssid); | 1536 | bss = ieee80211_rx_bss_add(dev, mgmt->bssid, channel, |
1537 | elems.ssid, elems.ssid_len); | ||
1551 | if (!bss) | 1538 | if (!bss) |
1552 | return; | 1539 | return; |
1553 | } else { | 1540 | } else { |
@@ -1573,10 +1560,6 @@ static void ieee80211_rx_bss_info(struct net_device *dev, | |||
1573 | 1560 | ||
1574 | bss->beacon_int = le16_to_cpu(mgmt->u.beacon.beacon_int); | 1561 | bss->beacon_int = le16_to_cpu(mgmt->u.beacon.beacon_int); |
1575 | bss->capability = le16_to_cpu(mgmt->u.beacon.capab_info); | 1562 | bss->capability = le16_to_cpu(mgmt->u.beacon.capab_info); |
1576 | if (elems.ssid && elems.ssid_len <= IEEE80211_MAX_SSID_LEN) { | ||
1577 | memcpy(bss->ssid, elems.ssid, elems.ssid_len); | ||
1578 | bss->ssid_len = elems.ssid_len; | ||
1579 | } | ||
1580 | 1563 | ||
1581 | bss->supp_rates_len = 0; | 1564 | bss->supp_rates_len = 0; |
1582 | if (elems.supp_rates) { | 1565 | if (elems.supp_rates) { |
@@ -1647,7 +1630,6 @@ static void ieee80211_rx_bss_info(struct net_device *dev, | |||
1647 | 1630 | ||
1648 | 1631 | ||
1649 | bss->hw_mode = rx_status->phymode; | 1632 | bss->hw_mode = rx_status->phymode; |
1650 | bss->channel = channel; | ||
1651 | bss->freq = rx_status->freq; | 1633 | bss->freq = rx_status->freq; |
1652 | if (channel != rx_status->channel && | 1634 | if (channel != rx_status->channel && |
1653 | (bss->hw_mode == MODE_IEEE80211G || | 1635 | (bss->hw_mode == MODE_IEEE80211G || |
@@ -1707,9 +1689,7 @@ static void ieee80211_rx_mgmt_beacon(struct net_device *dev, | |||
1707 | if (baselen > len) | 1689 | if (baselen > len) |
1708 | return; | 1690 | return; |
1709 | 1691 | ||
1710 | if (ieee802_11_parse_elems(mgmt->u.beacon.variable, len - baselen, | 1692 | ieee802_11_parse_elems(mgmt->u.beacon.variable, len - baselen, &elems); |
1711 | &elems) == ParseFailed) | ||
1712 | return; | ||
1713 | 1693 | ||
1714 | if (elems.erp_info && elems.erp_info_len >= 1) | 1694 | if (elems.erp_info && elems.erp_info_len >= 1) |
1715 | ieee80211_handle_erp_ie(dev, elems.erp_info[0]); | 1695 | ieee80211_handle_erp_ie(dev, elems.erp_info[0]); |
@@ -2375,7 +2355,7 @@ static int ieee80211_sta_create_ibss(struct net_device *dev, | |||
2375 | { | 2355 | { |
2376 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | 2356 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); |
2377 | struct ieee80211_sta_bss *bss; | 2357 | struct ieee80211_sta_bss *bss; |
2378 | struct ieee80211_sub_if_data *sdata; | 2358 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
2379 | struct ieee80211_hw_mode *mode; | 2359 | struct ieee80211_hw_mode *mode; |
2380 | u8 bssid[ETH_ALEN], *pos; | 2360 | u8 bssid[ETH_ALEN], *pos; |
2381 | int i; | 2361 | int i; |
@@ -2398,18 +2378,17 @@ static int ieee80211_sta_create_ibss(struct net_device *dev, | |||
2398 | printk(KERN_DEBUG "%s: Creating new IBSS network, BSSID %s\n", | 2378 | printk(KERN_DEBUG "%s: Creating new IBSS network, BSSID %s\n", |
2399 | dev->name, print_mac(mac, bssid)); | 2379 | dev->name, print_mac(mac, bssid)); |
2400 | 2380 | ||
2401 | bss = ieee80211_rx_bss_add(dev, bssid); | 2381 | bss = ieee80211_rx_bss_add(dev, bssid, local->hw.conf.channel, |
2382 | sdata->u.sta.ssid, sdata->u.sta.ssid_len); | ||
2402 | if (!bss) | 2383 | if (!bss) |
2403 | return -ENOMEM; | 2384 | return -ENOMEM; |
2404 | 2385 | ||
2405 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
2406 | mode = local->oper_hw_mode; | 2386 | mode = local->oper_hw_mode; |
2407 | 2387 | ||
2408 | if (local->hw.conf.beacon_int == 0) | 2388 | if (local->hw.conf.beacon_int == 0) |
2409 | local->hw.conf.beacon_int = 100; | 2389 | local->hw.conf.beacon_int = 100; |
2410 | bss->beacon_int = local->hw.conf.beacon_int; | 2390 | bss->beacon_int = local->hw.conf.beacon_int; |
2411 | bss->hw_mode = local->hw.conf.phymode; | 2391 | bss->hw_mode = local->hw.conf.phymode; |
2412 | bss->channel = local->hw.conf.channel; | ||
2413 | bss->freq = local->hw.conf.freq; | 2392 | bss->freq = local->hw.conf.freq; |
2414 | bss->last_update = jiffies; | 2393 | bss->last_update = jiffies; |
2415 | bss->capability = WLAN_CAPABILITY_IBSS; | 2394 | bss->capability = WLAN_CAPABILITY_IBSS; |
@@ -2469,7 +2448,8 @@ static int ieee80211_sta_find_ibss(struct net_device *dev, | |||
2469 | "%s\n", print_mac(mac, bssid), print_mac(mac2, ifsta->bssid)); | 2448 | "%s\n", print_mac(mac, bssid), print_mac(mac2, ifsta->bssid)); |
2470 | #endif /* CONFIG_MAC80211_IBSS_DEBUG */ | 2449 | #endif /* CONFIG_MAC80211_IBSS_DEBUG */ |
2471 | if (found && memcmp(ifsta->bssid, bssid, ETH_ALEN) != 0 && | 2450 | if (found && memcmp(ifsta->bssid, bssid, ETH_ALEN) != 0 && |
2472 | (bss = ieee80211_rx_bss_get(dev, bssid))) { | 2451 | (bss = ieee80211_rx_bss_get(dev, bssid, local->hw.conf.channel, |
2452 | ifsta->ssid, ifsta->ssid_len))) { | ||
2473 | printk(KERN_DEBUG "%s: Selected IBSS BSSID %s" | 2453 | printk(KERN_DEBUG "%s: Selected IBSS BSSID %s" |
2474 | " based on configured SSID\n", | 2454 | " based on configured SSID\n", |
2475 | dev->name, print_mac(mac, bssid)); | 2455 | dev->name, print_mac(mac, bssid)); |
diff --git a/net/mac80211/wep.c b/net/mac80211/wep.c index 6675261e958f..cc806d640f7a 100644 --- a/net/mac80211/wep.c +++ b/net/mac80211/wep.c | |||
@@ -138,9 +138,7 @@ void ieee80211_wep_encrypt_data(struct crypto_blkcipher *tfm, u8 *rc4key, | |||
138 | *icv = cpu_to_le32(~crc32_le(~0, data, data_len)); | 138 | *icv = cpu_to_le32(~crc32_le(~0, data, data_len)); |
139 | 139 | ||
140 | crypto_blkcipher_setkey(tfm, rc4key, klen); | 140 | crypto_blkcipher_setkey(tfm, rc4key, klen); |
141 | sg.page = virt_to_page(data); | 141 | sg_init_one(&sg, data, data_len + WEP_ICV_LEN); |
142 | sg.offset = offset_in_page(data); | ||
143 | sg.length = data_len + WEP_ICV_LEN; | ||
144 | crypto_blkcipher_encrypt(&desc, &sg, &sg, sg.length); | 142 | crypto_blkcipher_encrypt(&desc, &sg, &sg, sg.length); |
145 | } | 143 | } |
146 | 144 | ||
@@ -204,9 +202,7 @@ int ieee80211_wep_decrypt_data(struct crypto_blkcipher *tfm, u8 *rc4key, | |||
204 | __le32 crc; | 202 | __le32 crc; |
205 | 203 | ||
206 | crypto_blkcipher_setkey(tfm, rc4key, klen); | 204 | crypto_blkcipher_setkey(tfm, rc4key, klen); |
207 | sg.page = virt_to_page(data); | 205 | sg_init_one(&sg, data, data_len + WEP_ICV_LEN); |
208 | sg.offset = offset_in_page(data); | ||
209 | sg.length = data_len + WEP_ICV_LEN; | ||
210 | crypto_blkcipher_decrypt(&desc, &sg, &sg, sg.length); | 206 | crypto_blkcipher_decrypt(&desc, &sg, &sg, sg.length); |
211 | 207 | ||
212 | crc = cpu_to_le32(~crc32_le(~0, data, data_len)); | 208 | crc = cpu_to_le32(~crc32_le(~0, data, data_len)); |
diff --git a/net/netfilter/core.c b/net/netfilter/core.c index a523fa4136ed..bed9ba01e8ec 100644 --- a/net/netfilter/core.c +++ b/net/netfilter/core.c | |||
@@ -117,7 +117,7 @@ void nf_unregister_hooks(struct nf_hook_ops *reg, unsigned int n) | |||
117 | EXPORT_SYMBOL(nf_unregister_hooks); | 117 | EXPORT_SYMBOL(nf_unregister_hooks); |
118 | 118 | ||
119 | unsigned int nf_iterate(struct list_head *head, | 119 | unsigned int nf_iterate(struct list_head *head, |
120 | struct sk_buff **skb, | 120 | struct sk_buff *skb, |
121 | int hook, | 121 | int hook, |
122 | const struct net_device *indev, | 122 | const struct net_device *indev, |
123 | const struct net_device *outdev, | 123 | const struct net_device *outdev, |
@@ -160,7 +160,7 @@ unsigned int nf_iterate(struct list_head *head, | |||
160 | 160 | ||
161 | /* Returns 1 if okfn() needs to be executed by the caller, | 161 | /* Returns 1 if okfn() needs to be executed by the caller, |
162 | * -EPERM for NF_DROP, 0 otherwise. */ | 162 | * -EPERM for NF_DROP, 0 otherwise. */ |
163 | int nf_hook_slow(int pf, unsigned int hook, struct sk_buff **pskb, | 163 | int nf_hook_slow(int pf, unsigned int hook, struct sk_buff *skb, |
164 | struct net_device *indev, | 164 | struct net_device *indev, |
165 | struct net_device *outdev, | 165 | struct net_device *outdev, |
166 | int (*okfn)(struct sk_buff *), | 166 | int (*okfn)(struct sk_buff *), |
@@ -175,17 +175,17 @@ int nf_hook_slow(int pf, unsigned int hook, struct sk_buff **pskb, | |||
175 | 175 | ||
176 | elem = &nf_hooks[pf][hook]; | 176 | elem = &nf_hooks[pf][hook]; |
177 | next_hook: | 177 | next_hook: |
178 | verdict = nf_iterate(&nf_hooks[pf][hook], pskb, hook, indev, | 178 | verdict = nf_iterate(&nf_hooks[pf][hook], skb, hook, indev, |
179 | outdev, &elem, okfn, hook_thresh); | 179 | outdev, &elem, okfn, hook_thresh); |
180 | if (verdict == NF_ACCEPT || verdict == NF_STOP) { | 180 | if (verdict == NF_ACCEPT || verdict == NF_STOP) { |
181 | ret = 1; | 181 | ret = 1; |
182 | goto unlock; | 182 | goto unlock; |
183 | } else if (verdict == NF_DROP) { | 183 | } else if (verdict == NF_DROP) { |
184 | kfree_skb(*pskb); | 184 | kfree_skb(skb); |
185 | ret = -EPERM; | 185 | ret = -EPERM; |
186 | } else if ((verdict & NF_VERDICT_MASK) == NF_QUEUE) { | 186 | } else if ((verdict & NF_VERDICT_MASK) == NF_QUEUE) { |
187 | NFDEBUG("nf_hook: Verdict = QUEUE.\n"); | 187 | NFDEBUG("nf_hook: Verdict = QUEUE.\n"); |
188 | if (!nf_queue(*pskb, elem, pf, hook, indev, outdev, okfn, | 188 | if (!nf_queue(skb, elem, pf, hook, indev, outdev, okfn, |
189 | verdict >> NF_VERDICT_BITS)) | 189 | verdict >> NF_VERDICT_BITS)) |
190 | goto next_hook; | 190 | goto next_hook; |
191 | } | 191 | } |
@@ -196,34 +196,24 @@ unlock: | |||
196 | EXPORT_SYMBOL(nf_hook_slow); | 196 | EXPORT_SYMBOL(nf_hook_slow); |
197 | 197 | ||
198 | 198 | ||
199 | int skb_make_writable(struct sk_buff **pskb, unsigned int writable_len) | 199 | int skb_make_writable(struct sk_buff *skb, unsigned int writable_len) |
200 | { | 200 | { |
201 | struct sk_buff *nskb; | 201 | if (writable_len > skb->len) |
202 | |||
203 | if (writable_len > (*pskb)->len) | ||
204 | return 0; | 202 | return 0; |
205 | 203 | ||
206 | /* Not exclusive use of packet? Must copy. */ | 204 | /* Not exclusive use of packet? Must copy. */ |
207 | if (skb_cloned(*pskb) && !skb_clone_writable(*pskb, writable_len)) | 205 | if (!skb_cloned(skb)) { |
208 | goto copy_skb; | 206 | if (writable_len <= skb_headlen(skb)) |
209 | if (skb_shared(*pskb)) | 207 | return 1; |
210 | goto copy_skb; | 208 | } else if (skb_clone_writable(skb, writable_len)) |
211 | 209 | return 1; | |
212 | return pskb_may_pull(*pskb, writable_len); | 210 | |
213 | 211 | if (writable_len <= skb_headlen(skb)) | |
214 | copy_skb: | 212 | writable_len = 0; |
215 | nskb = skb_copy(*pskb, GFP_ATOMIC); | 213 | else |
216 | if (!nskb) | 214 | writable_len -= skb_headlen(skb); |
217 | return 0; | 215 | |
218 | BUG_ON(skb_is_nonlinear(nskb)); | 216 | return !!__pskb_pull_tail(skb, writable_len); |
219 | |||
220 | /* Rest of kernel will get very unhappy if we pass it a | ||
221 | suddenly-orphaned skbuff */ | ||
222 | if ((*pskb)->sk) | ||
223 | skb_set_owner_w(nskb, (*pskb)->sk); | ||
224 | kfree_skb(*pskb); | ||
225 | *pskb = nskb; | ||
226 | return 1; | ||
227 | } | 217 | } |
228 | EXPORT_SYMBOL(skb_make_writable); | 218 | EXPORT_SYMBOL(skb_make_writable); |
229 | 219 | ||
diff --git a/net/netfilter/nf_conntrack_amanda.c b/net/netfilter/nf_conntrack_amanda.c index e42ab230ad88..7b8239c0cd5e 100644 --- a/net/netfilter/nf_conntrack_amanda.c +++ b/net/netfilter/nf_conntrack_amanda.c | |||
@@ -36,7 +36,7 @@ MODULE_PARM_DESC(master_timeout, "timeout for the master connection"); | |||
36 | module_param(ts_algo, charp, 0400); | 36 | module_param(ts_algo, charp, 0400); |
37 | MODULE_PARM_DESC(ts_algo, "textsearch algorithm to use (default kmp)"); | 37 | MODULE_PARM_DESC(ts_algo, "textsearch algorithm to use (default kmp)"); |
38 | 38 | ||
39 | unsigned int (*nf_nat_amanda_hook)(struct sk_buff **pskb, | 39 | unsigned int (*nf_nat_amanda_hook)(struct sk_buff *skb, |
40 | enum ip_conntrack_info ctinfo, | 40 | enum ip_conntrack_info ctinfo, |
41 | unsigned int matchoff, | 41 | unsigned int matchoff, |
42 | unsigned int matchlen, | 42 | unsigned int matchlen, |
@@ -79,7 +79,7 @@ static struct { | |||
79 | }, | 79 | }, |
80 | }; | 80 | }; |
81 | 81 | ||
82 | static int amanda_help(struct sk_buff **pskb, | 82 | static int amanda_help(struct sk_buff *skb, |
83 | unsigned int protoff, | 83 | unsigned int protoff, |
84 | struct nf_conn *ct, | 84 | struct nf_conn *ct, |
85 | enum ip_conntrack_info ctinfo) | 85 | enum ip_conntrack_info ctinfo) |
@@ -101,25 +101,25 @@ static int amanda_help(struct sk_buff **pskb, | |||
101 | 101 | ||
102 | /* increase the UDP timeout of the master connection as replies from | 102 | /* increase the UDP timeout of the master connection as replies from |
103 | * Amanda clients to the server can be quite delayed */ | 103 | * Amanda clients to the server can be quite delayed */ |
104 | nf_ct_refresh(ct, *pskb, master_timeout * HZ); | 104 | nf_ct_refresh(ct, skb, master_timeout * HZ); |
105 | 105 | ||
106 | /* No data? */ | 106 | /* No data? */ |
107 | dataoff = protoff + sizeof(struct udphdr); | 107 | dataoff = protoff + sizeof(struct udphdr); |
108 | if (dataoff >= (*pskb)->len) { | 108 | if (dataoff >= skb->len) { |
109 | if (net_ratelimit()) | 109 | if (net_ratelimit()) |
110 | printk("amanda_help: skblen = %u\n", (*pskb)->len); | 110 | printk("amanda_help: skblen = %u\n", skb->len); |
111 | return NF_ACCEPT; | 111 | return NF_ACCEPT; |
112 | } | 112 | } |
113 | 113 | ||
114 | memset(&ts, 0, sizeof(ts)); | 114 | memset(&ts, 0, sizeof(ts)); |
115 | start = skb_find_text(*pskb, dataoff, (*pskb)->len, | 115 | start = skb_find_text(skb, dataoff, skb->len, |
116 | search[SEARCH_CONNECT].ts, &ts); | 116 | search[SEARCH_CONNECT].ts, &ts); |
117 | if (start == UINT_MAX) | 117 | if (start == UINT_MAX) |
118 | goto out; | 118 | goto out; |
119 | start += dataoff + search[SEARCH_CONNECT].len; | 119 | start += dataoff + search[SEARCH_CONNECT].len; |
120 | 120 | ||
121 | memset(&ts, 0, sizeof(ts)); | 121 | memset(&ts, 0, sizeof(ts)); |
122 | stop = skb_find_text(*pskb, start, (*pskb)->len, | 122 | stop = skb_find_text(skb, start, skb->len, |
123 | search[SEARCH_NEWLINE].ts, &ts); | 123 | search[SEARCH_NEWLINE].ts, &ts); |
124 | if (stop == UINT_MAX) | 124 | if (stop == UINT_MAX) |
125 | goto out; | 125 | goto out; |
@@ -127,13 +127,13 @@ static int amanda_help(struct sk_buff **pskb, | |||
127 | 127 | ||
128 | for (i = SEARCH_DATA; i <= SEARCH_INDEX; i++) { | 128 | for (i = SEARCH_DATA; i <= SEARCH_INDEX; i++) { |
129 | memset(&ts, 0, sizeof(ts)); | 129 | memset(&ts, 0, sizeof(ts)); |
130 | off = skb_find_text(*pskb, start, stop, search[i].ts, &ts); | 130 | off = skb_find_text(skb, start, stop, search[i].ts, &ts); |
131 | if (off == UINT_MAX) | 131 | if (off == UINT_MAX) |
132 | continue; | 132 | continue; |
133 | off += start + search[i].len; | 133 | off += start + search[i].len; |
134 | 134 | ||
135 | len = min_t(unsigned int, sizeof(pbuf) - 1, stop - off); | 135 | len = min_t(unsigned int, sizeof(pbuf) - 1, stop - off); |
136 | if (skb_copy_bits(*pskb, off, pbuf, len)) | 136 | if (skb_copy_bits(skb, off, pbuf, len)) |
137 | break; | 137 | break; |
138 | pbuf[len] = '\0'; | 138 | pbuf[len] = '\0'; |
139 | 139 | ||
@@ -153,7 +153,7 @@ static int amanda_help(struct sk_buff **pskb, | |||
153 | 153 | ||
154 | nf_nat_amanda = rcu_dereference(nf_nat_amanda_hook); | 154 | nf_nat_amanda = rcu_dereference(nf_nat_amanda_hook); |
155 | if (nf_nat_amanda && ct->status & IPS_NAT_MASK) | 155 | if (nf_nat_amanda && ct->status & IPS_NAT_MASK) |
156 | ret = nf_nat_amanda(pskb, ctinfo, off - dataoff, | 156 | ret = nf_nat_amanda(skb, ctinfo, off - dataoff, |
157 | len, exp); | 157 | len, exp); |
158 | else if (nf_ct_expect_related(exp) != 0) | 158 | else if (nf_ct_expect_related(exp) != 0) |
159 | ret = NF_DROP; | 159 | ret = NF_DROP; |
diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c index 83c30b45d170..4d6171bc0829 100644 --- a/net/netfilter/nf_conntrack_core.c +++ b/net/netfilter/nf_conntrack_core.c | |||
@@ -307,7 +307,7 @@ EXPORT_SYMBOL_GPL(nf_conntrack_hash_insert); | |||
307 | 307 | ||
308 | /* Confirm a connection given skb; places it in hash table */ | 308 | /* Confirm a connection given skb; places it in hash table */ |
309 | int | 309 | int |
310 | __nf_conntrack_confirm(struct sk_buff **pskb) | 310 | __nf_conntrack_confirm(struct sk_buff *skb) |
311 | { | 311 | { |
312 | unsigned int hash, repl_hash; | 312 | unsigned int hash, repl_hash; |
313 | struct nf_conntrack_tuple_hash *h; | 313 | struct nf_conntrack_tuple_hash *h; |
@@ -316,7 +316,7 @@ __nf_conntrack_confirm(struct sk_buff **pskb) | |||
316 | struct hlist_node *n; | 316 | struct hlist_node *n; |
317 | enum ip_conntrack_info ctinfo; | 317 | enum ip_conntrack_info ctinfo; |
318 | 318 | ||
319 | ct = nf_ct_get(*pskb, &ctinfo); | 319 | ct = nf_ct_get(skb, &ctinfo); |
320 | 320 | ||
321 | /* ipt_REJECT uses nf_conntrack_attach to attach related | 321 | /* ipt_REJECT uses nf_conntrack_attach to attach related |
322 | ICMP/TCP RST packets in other direction. Actual packet | 322 | ICMP/TCP RST packets in other direction. Actual packet |
@@ -367,14 +367,14 @@ __nf_conntrack_confirm(struct sk_buff **pskb) | |||
367 | write_unlock_bh(&nf_conntrack_lock); | 367 | write_unlock_bh(&nf_conntrack_lock); |
368 | help = nfct_help(ct); | 368 | help = nfct_help(ct); |
369 | if (help && help->helper) | 369 | if (help && help->helper) |
370 | nf_conntrack_event_cache(IPCT_HELPER, *pskb); | 370 | nf_conntrack_event_cache(IPCT_HELPER, skb); |
371 | #ifdef CONFIG_NF_NAT_NEEDED | 371 | #ifdef CONFIG_NF_NAT_NEEDED |
372 | if (test_bit(IPS_SRC_NAT_DONE_BIT, &ct->status) || | 372 | if (test_bit(IPS_SRC_NAT_DONE_BIT, &ct->status) || |
373 | test_bit(IPS_DST_NAT_DONE_BIT, &ct->status)) | 373 | test_bit(IPS_DST_NAT_DONE_BIT, &ct->status)) |
374 | nf_conntrack_event_cache(IPCT_NATINFO, *pskb); | 374 | nf_conntrack_event_cache(IPCT_NATINFO, skb); |
375 | #endif | 375 | #endif |
376 | nf_conntrack_event_cache(master_ct(ct) ? | 376 | nf_conntrack_event_cache(master_ct(ct) ? |
377 | IPCT_RELATED : IPCT_NEW, *pskb); | 377 | IPCT_RELATED : IPCT_NEW, skb); |
378 | return NF_ACCEPT; | 378 | return NF_ACCEPT; |
379 | 379 | ||
380 | out: | 380 | out: |
@@ -632,7 +632,7 @@ resolve_normal_ct(struct sk_buff *skb, | |||
632 | } | 632 | } |
633 | 633 | ||
634 | unsigned int | 634 | unsigned int |
635 | nf_conntrack_in(int pf, unsigned int hooknum, struct sk_buff **pskb) | 635 | nf_conntrack_in(int pf, unsigned int hooknum, struct sk_buff *skb) |
636 | { | 636 | { |
637 | struct nf_conn *ct; | 637 | struct nf_conn *ct; |
638 | enum ip_conntrack_info ctinfo; | 638 | enum ip_conntrack_info ctinfo; |
@@ -644,14 +644,14 @@ nf_conntrack_in(int pf, unsigned int hooknum, struct sk_buff **pskb) | |||
644 | int ret; | 644 | int ret; |
645 | 645 | ||
646 | /* Previously seen (loopback or untracked)? Ignore. */ | 646 | /* Previously seen (loopback or untracked)? Ignore. */ |
647 | if ((*pskb)->nfct) { | 647 | if (skb->nfct) { |
648 | NF_CT_STAT_INC_ATOMIC(ignore); | 648 | NF_CT_STAT_INC_ATOMIC(ignore); |
649 | return NF_ACCEPT; | 649 | return NF_ACCEPT; |
650 | } | 650 | } |
651 | 651 | ||
652 | /* rcu_read_lock()ed by nf_hook_slow */ | 652 | /* rcu_read_lock()ed by nf_hook_slow */ |
653 | l3proto = __nf_ct_l3proto_find((u_int16_t)pf); | 653 | l3proto = __nf_ct_l3proto_find((u_int16_t)pf); |
654 | ret = l3proto->get_l4proto(*pskb, skb_network_offset(*pskb), | 654 | ret = l3proto->get_l4proto(skb, skb_network_offset(skb), |
655 | &dataoff, &protonum); | 655 | &dataoff, &protonum); |
656 | if (ret <= 0) { | 656 | if (ret <= 0) { |
657 | pr_debug("not prepared to track yet or error occured\n"); | 657 | pr_debug("not prepared to track yet or error occured\n"); |
@@ -666,13 +666,13 @@ nf_conntrack_in(int pf, unsigned int hooknum, struct sk_buff **pskb) | |||
666 | * inverse of the return code tells to the netfilter | 666 | * inverse of the return code tells to the netfilter |
667 | * core what to do with the packet. */ | 667 | * core what to do with the packet. */ |
668 | if (l4proto->error != NULL && | 668 | if (l4proto->error != NULL && |
669 | (ret = l4proto->error(*pskb, dataoff, &ctinfo, pf, hooknum)) <= 0) { | 669 | (ret = l4proto->error(skb, dataoff, &ctinfo, pf, hooknum)) <= 0) { |
670 | NF_CT_STAT_INC_ATOMIC(error); | 670 | NF_CT_STAT_INC_ATOMIC(error); |
671 | NF_CT_STAT_INC_ATOMIC(invalid); | 671 | NF_CT_STAT_INC_ATOMIC(invalid); |
672 | return -ret; | 672 | return -ret; |
673 | } | 673 | } |
674 | 674 | ||
675 | ct = resolve_normal_ct(*pskb, dataoff, pf, protonum, l3proto, l4proto, | 675 | ct = resolve_normal_ct(skb, dataoff, pf, protonum, l3proto, l4proto, |
676 | &set_reply, &ctinfo); | 676 | &set_reply, &ctinfo); |
677 | if (!ct) { | 677 | if (!ct) { |
678 | /* Not valid part of a connection */ | 678 | /* Not valid part of a connection */ |
@@ -686,21 +686,21 @@ nf_conntrack_in(int pf, unsigned int hooknum, struct sk_buff **pskb) | |||
686 | return NF_DROP; | 686 | return NF_DROP; |
687 | } | 687 | } |
688 | 688 | ||
689 | NF_CT_ASSERT((*pskb)->nfct); | 689 | NF_CT_ASSERT(skb->nfct); |
690 | 690 | ||
691 | ret = l4proto->packet(ct, *pskb, dataoff, ctinfo, pf, hooknum); | 691 | ret = l4proto->packet(ct, skb, dataoff, ctinfo, pf, hooknum); |
692 | if (ret < 0) { | 692 | if (ret < 0) { |
693 | /* Invalid: inverse of the return code tells | 693 | /* Invalid: inverse of the return code tells |
694 | * the netfilter core what to do */ | 694 | * the netfilter core what to do */ |
695 | pr_debug("nf_conntrack_in: Can't track with proto module\n"); | 695 | pr_debug("nf_conntrack_in: Can't track with proto module\n"); |
696 | nf_conntrack_put((*pskb)->nfct); | 696 | nf_conntrack_put(skb->nfct); |
697 | (*pskb)->nfct = NULL; | 697 | skb->nfct = NULL; |
698 | NF_CT_STAT_INC_ATOMIC(invalid); | 698 | NF_CT_STAT_INC_ATOMIC(invalid); |
699 | return -ret; | 699 | return -ret; |
700 | } | 700 | } |
701 | 701 | ||
702 | if (set_reply && !test_and_set_bit(IPS_SEEN_REPLY_BIT, &ct->status)) | 702 | if (set_reply && !test_and_set_bit(IPS_SEEN_REPLY_BIT, &ct->status)) |
703 | nf_conntrack_event_cache(IPCT_STATUS, *pskb); | 703 | nf_conntrack_event_cache(IPCT_STATUS, skb); |
704 | 704 | ||
705 | return ret; | 705 | return ret; |
706 | } | 706 | } |
diff --git a/net/netfilter/nf_conntrack_ftp.c b/net/netfilter/nf_conntrack_ftp.c index c763ee74ea02..6df259067f7e 100644 --- a/net/netfilter/nf_conntrack_ftp.c +++ b/net/netfilter/nf_conntrack_ftp.c | |||
@@ -43,7 +43,7 @@ module_param_array(ports, ushort, &ports_c, 0400); | |||
43 | static int loose; | 43 | static int loose; |
44 | module_param(loose, bool, 0600); | 44 | module_param(loose, bool, 0600); |
45 | 45 | ||
46 | unsigned int (*nf_nat_ftp_hook)(struct sk_buff **pskb, | 46 | unsigned int (*nf_nat_ftp_hook)(struct sk_buff *skb, |
47 | enum ip_conntrack_info ctinfo, | 47 | enum ip_conntrack_info ctinfo, |
48 | enum nf_ct_ftp_type type, | 48 | enum nf_ct_ftp_type type, |
49 | unsigned int matchoff, | 49 | unsigned int matchoff, |
@@ -344,7 +344,7 @@ static void update_nl_seq(u32 nl_seq, struct nf_ct_ftp_master *info, int dir, | |||
344 | } | 344 | } |
345 | } | 345 | } |
346 | 346 | ||
347 | static int help(struct sk_buff **pskb, | 347 | static int help(struct sk_buff *skb, |
348 | unsigned int protoff, | 348 | unsigned int protoff, |
349 | struct nf_conn *ct, | 349 | struct nf_conn *ct, |
350 | enum ip_conntrack_info ctinfo) | 350 | enum ip_conntrack_info ctinfo) |
@@ -371,21 +371,21 @@ static int help(struct sk_buff **pskb, | |||
371 | return NF_ACCEPT; | 371 | return NF_ACCEPT; |
372 | } | 372 | } |
373 | 373 | ||
374 | th = skb_header_pointer(*pskb, protoff, sizeof(_tcph), &_tcph); | 374 | th = skb_header_pointer(skb, protoff, sizeof(_tcph), &_tcph); |
375 | if (th == NULL) | 375 | if (th == NULL) |
376 | return NF_ACCEPT; | 376 | return NF_ACCEPT; |
377 | 377 | ||
378 | dataoff = protoff + th->doff * 4; | 378 | dataoff = protoff + th->doff * 4; |
379 | /* No data? */ | 379 | /* No data? */ |
380 | if (dataoff >= (*pskb)->len) { | 380 | if (dataoff >= skb->len) { |
381 | pr_debug("ftp: dataoff(%u) >= skblen(%u)\n", dataoff, | 381 | pr_debug("ftp: dataoff(%u) >= skblen(%u)\n", dataoff, |
382 | (*pskb)->len); | 382 | skb->len); |
383 | return NF_ACCEPT; | 383 | return NF_ACCEPT; |
384 | } | 384 | } |
385 | datalen = (*pskb)->len - dataoff; | 385 | datalen = skb->len - dataoff; |
386 | 386 | ||
387 | spin_lock_bh(&nf_ftp_lock); | 387 | spin_lock_bh(&nf_ftp_lock); |
388 | fb_ptr = skb_header_pointer(*pskb, dataoff, datalen, ftp_buffer); | 388 | fb_ptr = skb_header_pointer(skb, dataoff, datalen, ftp_buffer); |
389 | BUG_ON(fb_ptr == NULL); | 389 | BUG_ON(fb_ptr == NULL); |
390 | 390 | ||
391 | ends_in_nl = (fb_ptr[datalen - 1] == '\n'); | 391 | ends_in_nl = (fb_ptr[datalen - 1] == '\n'); |
@@ -491,7 +491,7 @@ static int help(struct sk_buff **pskb, | |||
491 | * (possibly changed) expectation itself. */ | 491 | * (possibly changed) expectation itself. */ |
492 | nf_nat_ftp = rcu_dereference(nf_nat_ftp_hook); | 492 | nf_nat_ftp = rcu_dereference(nf_nat_ftp_hook); |
493 | if (nf_nat_ftp && ct->status & IPS_NAT_MASK) | 493 | if (nf_nat_ftp && ct->status & IPS_NAT_MASK) |
494 | ret = nf_nat_ftp(pskb, ctinfo, search[dir][i].ftptype, | 494 | ret = nf_nat_ftp(skb, ctinfo, search[dir][i].ftptype, |
495 | matchoff, matchlen, exp); | 495 | matchoff, matchlen, exp); |
496 | else { | 496 | else { |
497 | /* Can't expect this? Best to drop packet now. */ | 497 | /* Can't expect this? Best to drop packet now. */ |
@@ -508,7 +508,7 @@ out_update_nl: | |||
508 | /* Now if this ends in \n, update ftp info. Seq may have been | 508 | /* Now if this ends in \n, update ftp info. Seq may have been |
509 | * adjusted by NAT code. */ | 509 | * adjusted by NAT code. */ |
510 | if (ends_in_nl) | 510 | if (ends_in_nl) |
511 | update_nl_seq(seq, ct_ftp_info, dir, *pskb); | 511 | update_nl_seq(seq, ct_ftp_info, dir, skb); |
512 | out: | 512 | out: |
513 | spin_unlock_bh(&nf_ftp_lock); | 513 | spin_unlock_bh(&nf_ftp_lock); |
514 | return ret; | 514 | return ret; |
diff --git a/net/netfilter/nf_conntrack_h323_main.c b/net/netfilter/nf_conntrack_h323_main.c index a8a9dfbe7a67..f23fd9598e19 100644 --- a/net/netfilter/nf_conntrack_h323_main.c +++ b/net/netfilter/nf_conntrack_h323_main.c | |||
@@ -47,27 +47,27 @@ MODULE_PARM_DESC(callforward_filter, "only create call forwarding expectations " | |||
47 | "(determined by routing information)"); | 47 | "(determined by routing information)"); |
48 | 48 | ||
49 | /* Hooks for NAT */ | 49 | /* Hooks for NAT */ |
50 | int (*set_h245_addr_hook) (struct sk_buff **pskb, | 50 | int (*set_h245_addr_hook) (struct sk_buff *skb, |
51 | unsigned char **data, int dataoff, | 51 | unsigned char **data, int dataoff, |
52 | H245_TransportAddress *taddr, | 52 | H245_TransportAddress *taddr, |
53 | union nf_conntrack_address *addr, __be16 port) | 53 | union nf_conntrack_address *addr, __be16 port) |
54 | __read_mostly; | 54 | __read_mostly; |
55 | int (*set_h225_addr_hook) (struct sk_buff **pskb, | 55 | int (*set_h225_addr_hook) (struct sk_buff *skb, |
56 | unsigned char **data, int dataoff, | 56 | unsigned char **data, int dataoff, |
57 | TransportAddress *taddr, | 57 | TransportAddress *taddr, |
58 | union nf_conntrack_address *addr, __be16 port) | 58 | union nf_conntrack_address *addr, __be16 port) |
59 | __read_mostly; | 59 | __read_mostly; |
60 | int (*set_sig_addr_hook) (struct sk_buff **pskb, | 60 | int (*set_sig_addr_hook) (struct sk_buff *skb, |
61 | struct nf_conn *ct, | 61 | struct nf_conn *ct, |
62 | enum ip_conntrack_info ctinfo, | 62 | enum ip_conntrack_info ctinfo, |
63 | unsigned char **data, | 63 | unsigned char **data, |
64 | TransportAddress *taddr, int count) __read_mostly; | 64 | TransportAddress *taddr, int count) __read_mostly; |
65 | int (*set_ras_addr_hook) (struct sk_buff **pskb, | 65 | int (*set_ras_addr_hook) (struct sk_buff *skb, |
66 | struct nf_conn *ct, | 66 | struct nf_conn *ct, |
67 | enum ip_conntrack_info ctinfo, | 67 | enum ip_conntrack_info ctinfo, |
68 | unsigned char **data, | 68 | unsigned char **data, |
69 | TransportAddress *taddr, int count) __read_mostly; | 69 | TransportAddress *taddr, int count) __read_mostly; |
70 | int (*nat_rtp_rtcp_hook) (struct sk_buff **pskb, | 70 | int (*nat_rtp_rtcp_hook) (struct sk_buff *skb, |
71 | struct nf_conn *ct, | 71 | struct nf_conn *ct, |
72 | enum ip_conntrack_info ctinfo, | 72 | enum ip_conntrack_info ctinfo, |
73 | unsigned char **data, int dataoff, | 73 | unsigned char **data, int dataoff, |
@@ -75,25 +75,25 @@ int (*nat_rtp_rtcp_hook) (struct sk_buff **pskb, | |||
75 | __be16 port, __be16 rtp_port, | 75 | __be16 port, __be16 rtp_port, |
76 | struct nf_conntrack_expect *rtp_exp, | 76 | struct nf_conntrack_expect *rtp_exp, |
77 | struct nf_conntrack_expect *rtcp_exp) __read_mostly; | 77 | struct nf_conntrack_expect *rtcp_exp) __read_mostly; |
78 | int (*nat_t120_hook) (struct sk_buff **pskb, | 78 | int (*nat_t120_hook) (struct sk_buff *skb, |
79 | struct nf_conn *ct, | 79 | struct nf_conn *ct, |
80 | enum ip_conntrack_info ctinfo, | 80 | enum ip_conntrack_info ctinfo, |
81 | unsigned char **data, int dataoff, | 81 | unsigned char **data, int dataoff, |
82 | H245_TransportAddress *taddr, __be16 port, | 82 | H245_TransportAddress *taddr, __be16 port, |
83 | struct nf_conntrack_expect *exp) __read_mostly; | 83 | struct nf_conntrack_expect *exp) __read_mostly; |
84 | int (*nat_h245_hook) (struct sk_buff **pskb, | 84 | int (*nat_h245_hook) (struct sk_buff *skb, |
85 | struct nf_conn *ct, | 85 | struct nf_conn *ct, |
86 | enum ip_conntrack_info ctinfo, | 86 | enum ip_conntrack_info ctinfo, |
87 | unsigned char **data, int dataoff, | 87 | unsigned char **data, int dataoff, |
88 | TransportAddress *taddr, __be16 port, | 88 | TransportAddress *taddr, __be16 port, |
89 | struct nf_conntrack_expect *exp) __read_mostly; | 89 | struct nf_conntrack_expect *exp) __read_mostly; |
90 | int (*nat_callforwarding_hook) (struct sk_buff **pskb, | 90 | int (*nat_callforwarding_hook) (struct sk_buff *skb, |
91 | struct nf_conn *ct, | 91 | struct nf_conn *ct, |
92 | enum ip_conntrack_info ctinfo, | 92 | enum ip_conntrack_info ctinfo, |
93 | unsigned char **data, int dataoff, | 93 | unsigned char **data, int dataoff, |
94 | TransportAddress *taddr, __be16 port, | 94 | TransportAddress *taddr, __be16 port, |
95 | struct nf_conntrack_expect *exp) __read_mostly; | 95 | struct nf_conntrack_expect *exp) __read_mostly; |
96 | int (*nat_q931_hook) (struct sk_buff **pskb, | 96 | int (*nat_q931_hook) (struct sk_buff *skb, |
97 | struct nf_conn *ct, | 97 | struct nf_conn *ct, |
98 | enum ip_conntrack_info ctinfo, | 98 | enum ip_conntrack_info ctinfo, |
99 | unsigned char **data, TransportAddress *taddr, int idx, | 99 | unsigned char **data, TransportAddress *taddr, int idx, |
@@ -108,7 +108,7 @@ static struct nf_conntrack_helper nf_conntrack_helper_q931[]; | |||
108 | static struct nf_conntrack_helper nf_conntrack_helper_ras[]; | 108 | static struct nf_conntrack_helper nf_conntrack_helper_ras[]; |
109 | 109 | ||
110 | /****************************************************************************/ | 110 | /****************************************************************************/ |
111 | static int get_tpkt_data(struct sk_buff **pskb, unsigned int protoff, | 111 | static int get_tpkt_data(struct sk_buff *skb, unsigned int protoff, |
112 | struct nf_conn *ct, enum ip_conntrack_info ctinfo, | 112 | struct nf_conn *ct, enum ip_conntrack_info ctinfo, |
113 | unsigned char **data, int *datalen, int *dataoff) | 113 | unsigned char **data, int *datalen, int *dataoff) |
114 | { | 114 | { |
@@ -122,7 +122,7 @@ static int get_tpkt_data(struct sk_buff **pskb, unsigned int protoff, | |||
122 | int tpktoff; | 122 | int tpktoff; |
123 | 123 | ||
124 | /* Get TCP header */ | 124 | /* Get TCP header */ |
125 | th = skb_header_pointer(*pskb, protoff, sizeof(_tcph), &_tcph); | 125 | th = skb_header_pointer(skb, protoff, sizeof(_tcph), &_tcph); |
126 | if (th == NULL) | 126 | if (th == NULL) |
127 | return 0; | 127 | return 0; |
128 | 128 | ||
@@ -130,13 +130,13 @@ static int get_tpkt_data(struct sk_buff **pskb, unsigned int protoff, | |||
130 | tcpdataoff = protoff + th->doff * 4; | 130 | tcpdataoff = protoff + th->doff * 4; |
131 | 131 | ||
132 | /* Get TCP data length */ | 132 | /* Get TCP data length */ |
133 | tcpdatalen = (*pskb)->len - tcpdataoff; | 133 | tcpdatalen = skb->len - tcpdataoff; |
134 | if (tcpdatalen <= 0) /* No TCP data */ | 134 | if (tcpdatalen <= 0) /* No TCP data */ |
135 | goto clear_out; | 135 | goto clear_out; |
136 | 136 | ||
137 | if (*data == NULL) { /* first TPKT */ | 137 | if (*data == NULL) { /* first TPKT */ |
138 | /* Get first TPKT pointer */ | 138 | /* Get first TPKT pointer */ |
139 | tpkt = skb_header_pointer(*pskb, tcpdataoff, tcpdatalen, | 139 | tpkt = skb_header_pointer(skb, tcpdataoff, tcpdatalen, |
140 | h323_buffer); | 140 | h323_buffer); |
141 | BUG_ON(tpkt == NULL); | 141 | BUG_ON(tpkt == NULL); |
142 | 142 | ||
@@ -248,7 +248,7 @@ static int get_h245_addr(struct nf_conn *ct, unsigned char *data, | |||
248 | } | 248 | } |
249 | 249 | ||
250 | /****************************************************************************/ | 250 | /****************************************************************************/ |
251 | static int expect_rtp_rtcp(struct sk_buff **pskb, struct nf_conn *ct, | 251 | static int expect_rtp_rtcp(struct sk_buff *skb, struct nf_conn *ct, |
252 | enum ip_conntrack_info ctinfo, | 252 | enum ip_conntrack_info ctinfo, |
253 | unsigned char **data, int dataoff, | 253 | unsigned char **data, int dataoff, |
254 | H245_TransportAddress *taddr) | 254 | H245_TransportAddress *taddr) |
@@ -297,7 +297,7 @@ static int expect_rtp_rtcp(struct sk_buff **pskb, struct nf_conn *ct, | |||
297 | (nat_rtp_rtcp = rcu_dereference(nat_rtp_rtcp_hook)) && | 297 | (nat_rtp_rtcp = rcu_dereference(nat_rtp_rtcp_hook)) && |
298 | ct->status & IPS_NAT_MASK) { | 298 | ct->status & IPS_NAT_MASK) { |
299 | /* NAT needed */ | 299 | /* NAT needed */ |
300 | ret = nat_rtp_rtcp(pskb, ct, ctinfo, data, dataoff, | 300 | ret = nat_rtp_rtcp(skb, ct, ctinfo, data, dataoff, |
301 | taddr, port, rtp_port, rtp_exp, rtcp_exp); | 301 | taddr, port, rtp_port, rtp_exp, rtcp_exp); |
302 | } else { /* Conntrack only */ | 302 | } else { /* Conntrack only */ |
303 | if (nf_ct_expect_related(rtp_exp) == 0) { | 303 | if (nf_ct_expect_related(rtp_exp) == 0) { |
@@ -321,7 +321,7 @@ static int expect_rtp_rtcp(struct sk_buff **pskb, struct nf_conn *ct, | |||
321 | } | 321 | } |
322 | 322 | ||
323 | /****************************************************************************/ | 323 | /****************************************************************************/ |
324 | static int expect_t120(struct sk_buff **pskb, | 324 | static int expect_t120(struct sk_buff *skb, |
325 | struct nf_conn *ct, | 325 | struct nf_conn *ct, |
326 | enum ip_conntrack_info ctinfo, | 326 | enum ip_conntrack_info ctinfo, |
327 | unsigned char **data, int dataoff, | 327 | unsigned char **data, int dataoff, |
@@ -355,7 +355,7 @@ static int expect_t120(struct sk_buff **pskb, | |||
355 | (nat_t120 = rcu_dereference(nat_t120_hook)) && | 355 | (nat_t120 = rcu_dereference(nat_t120_hook)) && |
356 | ct->status & IPS_NAT_MASK) { | 356 | ct->status & IPS_NAT_MASK) { |
357 | /* NAT needed */ | 357 | /* NAT needed */ |
358 | ret = nat_t120(pskb, ct, ctinfo, data, dataoff, taddr, | 358 | ret = nat_t120(skb, ct, ctinfo, data, dataoff, taddr, |
359 | port, exp); | 359 | port, exp); |
360 | } else { /* Conntrack only */ | 360 | } else { /* Conntrack only */ |
361 | if (nf_ct_expect_related(exp) == 0) { | 361 | if (nf_ct_expect_related(exp) == 0) { |
@@ -371,7 +371,7 @@ static int expect_t120(struct sk_buff **pskb, | |||
371 | } | 371 | } |
372 | 372 | ||
373 | /****************************************************************************/ | 373 | /****************************************************************************/ |
374 | static int process_h245_channel(struct sk_buff **pskb, | 374 | static int process_h245_channel(struct sk_buff *skb, |
375 | struct nf_conn *ct, | 375 | struct nf_conn *ct, |
376 | enum ip_conntrack_info ctinfo, | 376 | enum ip_conntrack_info ctinfo, |
377 | unsigned char **data, int dataoff, | 377 | unsigned char **data, int dataoff, |
@@ -381,7 +381,7 @@ static int process_h245_channel(struct sk_buff **pskb, | |||
381 | 381 | ||
382 | if (channel->options & eH2250LogicalChannelParameters_mediaChannel) { | 382 | if (channel->options & eH2250LogicalChannelParameters_mediaChannel) { |
383 | /* RTP */ | 383 | /* RTP */ |
384 | ret = expect_rtp_rtcp(pskb, ct, ctinfo, data, dataoff, | 384 | ret = expect_rtp_rtcp(skb, ct, ctinfo, data, dataoff, |
385 | &channel->mediaChannel); | 385 | &channel->mediaChannel); |
386 | if (ret < 0) | 386 | if (ret < 0) |
387 | return -1; | 387 | return -1; |
@@ -390,7 +390,7 @@ static int process_h245_channel(struct sk_buff **pskb, | |||
390 | if (channel-> | 390 | if (channel-> |
391 | options & eH2250LogicalChannelParameters_mediaControlChannel) { | 391 | options & eH2250LogicalChannelParameters_mediaControlChannel) { |
392 | /* RTCP */ | 392 | /* RTCP */ |
393 | ret = expect_rtp_rtcp(pskb, ct, ctinfo, data, dataoff, | 393 | ret = expect_rtp_rtcp(skb, ct, ctinfo, data, dataoff, |
394 | &channel->mediaControlChannel); | 394 | &channel->mediaControlChannel); |
395 | if (ret < 0) | 395 | if (ret < 0) |
396 | return -1; | 396 | return -1; |
@@ -400,7 +400,7 @@ static int process_h245_channel(struct sk_buff **pskb, | |||
400 | } | 400 | } |
401 | 401 | ||
402 | /****************************************************************************/ | 402 | /****************************************************************************/ |
403 | static int process_olc(struct sk_buff **pskb, struct nf_conn *ct, | 403 | static int process_olc(struct sk_buff *skb, struct nf_conn *ct, |
404 | enum ip_conntrack_info ctinfo, | 404 | enum ip_conntrack_info ctinfo, |
405 | unsigned char **data, int dataoff, | 405 | unsigned char **data, int dataoff, |
406 | OpenLogicalChannel *olc) | 406 | OpenLogicalChannel *olc) |
@@ -412,7 +412,7 @@ static int process_olc(struct sk_buff **pskb, struct nf_conn *ct, | |||
412 | if (olc->forwardLogicalChannelParameters.multiplexParameters.choice == | 412 | if (olc->forwardLogicalChannelParameters.multiplexParameters.choice == |
413 | eOpenLogicalChannel_forwardLogicalChannelParameters_multiplexParameters_h2250LogicalChannelParameters) | 413 | eOpenLogicalChannel_forwardLogicalChannelParameters_multiplexParameters_h2250LogicalChannelParameters) |
414 | { | 414 | { |
415 | ret = process_h245_channel(pskb, ct, ctinfo, data, dataoff, | 415 | ret = process_h245_channel(skb, ct, ctinfo, data, dataoff, |
416 | &olc-> | 416 | &olc-> |
417 | forwardLogicalChannelParameters. | 417 | forwardLogicalChannelParameters. |
418 | multiplexParameters. | 418 | multiplexParameters. |
@@ -430,7 +430,7 @@ static int process_olc(struct sk_buff **pskb, struct nf_conn *ct, | |||
430 | eOpenLogicalChannel_reverseLogicalChannelParameters_multiplexParameters_h2250LogicalChannelParameters)) | 430 | eOpenLogicalChannel_reverseLogicalChannelParameters_multiplexParameters_h2250LogicalChannelParameters)) |
431 | { | 431 | { |
432 | ret = | 432 | ret = |
433 | process_h245_channel(pskb, ct, ctinfo, data, dataoff, | 433 | process_h245_channel(skb, ct, ctinfo, data, dataoff, |
434 | &olc-> | 434 | &olc-> |
435 | reverseLogicalChannelParameters. | 435 | reverseLogicalChannelParameters. |
436 | multiplexParameters. | 436 | multiplexParameters. |
@@ -448,7 +448,7 @@ static int process_olc(struct sk_buff **pskb, struct nf_conn *ct, | |||
448 | t120.choice == eDataProtocolCapability_separateLANStack && | 448 | t120.choice == eDataProtocolCapability_separateLANStack && |
449 | olc->separateStack.networkAddress.choice == | 449 | olc->separateStack.networkAddress.choice == |
450 | eNetworkAccessParameters_networkAddress_localAreaAddress) { | 450 | eNetworkAccessParameters_networkAddress_localAreaAddress) { |
451 | ret = expect_t120(pskb, ct, ctinfo, data, dataoff, | 451 | ret = expect_t120(skb, ct, ctinfo, data, dataoff, |
452 | &olc->separateStack.networkAddress. | 452 | &olc->separateStack.networkAddress. |
453 | localAreaAddress); | 453 | localAreaAddress); |
454 | if (ret < 0) | 454 | if (ret < 0) |
@@ -459,7 +459,7 @@ static int process_olc(struct sk_buff **pskb, struct nf_conn *ct, | |||
459 | } | 459 | } |
460 | 460 | ||
461 | /****************************************************************************/ | 461 | /****************************************************************************/ |
462 | static int process_olca(struct sk_buff **pskb, struct nf_conn *ct, | 462 | static int process_olca(struct sk_buff *skb, struct nf_conn *ct, |
463 | enum ip_conntrack_info ctinfo, | 463 | enum ip_conntrack_info ctinfo, |
464 | unsigned char **data, int dataoff, | 464 | unsigned char **data, int dataoff, |
465 | OpenLogicalChannelAck *olca) | 465 | OpenLogicalChannelAck *olca) |
@@ -477,7 +477,7 @@ static int process_olca(struct sk_buff **pskb, struct nf_conn *ct, | |||
477 | choice == | 477 | choice == |
478 | eOpenLogicalChannelAck_reverseLogicalChannelParameters_multiplexParameters_h2250LogicalChannelParameters)) | 478 | eOpenLogicalChannelAck_reverseLogicalChannelParameters_multiplexParameters_h2250LogicalChannelParameters)) |
479 | { | 479 | { |
480 | ret = process_h245_channel(pskb, ct, ctinfo, data, dataoff, | 480 | ret = process_h245_channel(skb, ct, ctinfo, data, dataoff, |
481 | &olca-> | 481 | &olca-> |
482 | reverseLogicalChannelParameters. | 482 | reverseLogicalChannelParameters. |
483 | multiplexParameters. | 483 | multiplexParameters. |
@@ -496,7 +496,7 @@ static int process_olca(struct sk_buff **pskb, struct nf_conn *ct, | |||
496 | if (ack->options & | 496 | if (ack->options & |
497 | eH2250LogicalChannelAckParameters_mediaChannel) { | 497 | eH2250LogicalChannelAckParameters_mediaChannel) { |
498 | /* RTP */ | 498 | /* RTP */ |
499 | ret = expect_rtp_rtcp(pskb, ct, ctinfo, data, dataoff, | 499 | ret = expect_rtp_rtcp(skb, ct, ctinfo, data, dataoff, |
500 | &ack->mediaChannel); | 500 | &ack->mediaChannel); |
501 | if (ret < 0) | 501 | if (ret < 0) |
502 | return -1; | 502 | return -1; |
@@ -505,7 +505,7 @@ static int process_olca(struct sk_buff **pskb, struct nf_conn *ct, | |||
505 | if (ack->options & | 505 | if (ack->options & |
506 | eH2250LogicalChannelAckParameters_mediaControlChannel) { | 506 | eH2250LogicalChannelAckParameters_mediaControlChannel) { |
507 | /* RTCP */ | 507 | /* RTCP */ |
508 | ret = expect_rtp_rtcp(pskb, ct, ctinfo, data, dataoff, | 508 | ret = expect_rtp_rtcp(skb, ct, ctinfo, data, dataoff, |
509 | &ack->mediaControlChannel); | 509 | &ack->mediaControlChannel); |
510 | if (ret < 0) | 510 | if (ret < 0) |
511 | return -1; | 511 | return -1; |
@@ -515,7 +515,7 @@ static int process_olca(struct sk_buff **pskb, struct nf_conn *ct, | |||
515 | if ((olca->options & eOpenLogicalChannelAck_separateStack) && | 515 | if ((olca->options & eOpenLogicalChannelAck_separateStack) && |
516 | olca->separateStack.networkAddress.choice == | 516 | olca->separateStack.networkAddress.choice == |
517 | eNetworkAccessParameters_networkAddress_localAreaAddress) { | 517 | eNetworkAccessParameters_networkAddress_localAreaAddress) { |
518 | ret = expect_t120(pskb, ct, ctinfo, data, dataoff, | 518 | ret = expect_t120(skb, ct, ctinfo, data, dataoff, |
519 | &olca->separateStack.networkAddress. | 519 | &olca->separateStack.networkAddress. |
520 | localAreaAddress); | 520 | localAreaAddress); |
521 | if (ret < 0) | 521 | if (ret < 0) |
@@ -526,7 +526,7 @@ static int process_olca(struct sk_buff **pskb, struct nf_conn *ct, | |||
526 | } | 526 | } |
527 | 527 | ||
528 | /****************************************************************************/ | 528 | /****************************************************************************/ |
529 | static int process_h245(struct sk_buff **pskb, struct nf_conn *ct, | 529 | static int process_h245(struct sk_buff *skb, struct nf_conn *ct, |
530 | enum ip_conntrack_info ctinfo, | 530 | enum ip_conntrack_info ctinfo, |
531 | unsigned char **data, int dataoff, | 531 | unsigned char **data, int dataoff, |
532 | MultimediaSystemControlMessage *mscm) | 532 | MultimediaSystemControlMessage *mscm) |
@@ -535,7 +535,7 @@ static int process_h245(struct sk_buff **pskb, struct nf_conn *ct, | |||
535 | case eMultimediaSystemControlMessage_request: | 535 | case eMultimediaSystemControlMessage_request: |
536 | if (mscm->request.choice == | 536 | if (mscm->request.choice == |
537 | eRequestMessage_openLogicalChannel) { | 537 | eRequestMessage_openLogicalChannel) { |
538 | return process_olc(pskb, ct, ctinfo, data, dataoff, | 538 | return process_olc(skb, ct, ctinfo, data, dataoff, |
539 | &mscm->request.openLogicalChannel); | 539 | &mscm->request.openLogicalChannel); |
540 | } | 540 | } |
541 | pr_debug("nf_ct_h323: H.245 Request %d\n", | 541 | pr_debug("nf_ct_h323: H.245 Request %d\n", |
@@ -544,7 +544,7 @@ static int process_h245(struct sk_buff **pskb, struct nf_conn *ct, | |||
544 | case eMultimediaSystemControlMessage_response: | 544 | case eMultimediaSystemControlMessage_response: |
545 | if (mscm->response.choice == | 545 | if (mscm->response.choice == |
546 | eResponseMessage_openLogicalChannelAck) { | 546 | eResponseMessage_openLogicalChannelAck) { |
547 | return process_olca(pskb, ct, ctinfo, data, dataoff, | 547 | return process_olca(skb, ct, ctinfo, data, dataoff, |
548 | &mscm->response. | 548 | &mscm->response. |
549 | openLogicalChannelAck); | 549 | openLogicalChannelAck); |
550 | } | 550 | } |
@@ -560,7 +560,7 @@ static int process_h245(struct sk_buff **pskb, struct nf_conn *ct, | |||
560 | } | 560 | } |
561 | 561 | ||
562 | /****************************************************************************/ | 562 | /****************************************************************************/ |
563 | static int h245_help(struct sk_buff **pskb, unsigned int protoff, | 563 | static int h245_help(struct sk_buff *skb, unsigned int protoff, |
564 | struct nf_conn *ct, enum ip_conntrack_info ctinfo) | 564 | struct nf_conn *ct, enum ip_conntrack_info ctinfo) |
565 | { | 565 | { |
566 | static MultimediaSystemControlMessage mscm; | 566 | static MultimediaSystemControlMessage mscm; |
@@ -574,12 +574,12 @@ static int h245_help(struct sk_buff **pskb, unsigned int protoff, | |||
574 | ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) { | 574 | ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) { |
575 | return NF_ACCEPT; | 575 | return NF_ACCEPT; |
576 | } | 576 | } |
577 | pr_debug("nf_ct_h245: skblen = %u\n", (*pskb)->len); | 577 | pr_debug("nf_ct_h245: skblen = %u\n", skb->len); |
578 | 578 | ||
579 | spin_lock_bh(&nf_h323_lock); | 579 | spin_lock_bh(&nf_h323_lock); |
580 | 580 | ||
581 | /* Process each TPKT */ | 581 | /* Process each TPKT */ |
582 | while (get_tpkt_data(pskb, protoff, ct, ctinfo, | 582 | while (get_tpkt_data(skb, protoff, ct, ctinfo, |
583 | &data, &datalen, &dataoff)) { | 583 | &data, &datalen, &dataoff)) { |
584 | pr_debug("nf_ct_h245: TPKT len=%d ", datalen); | 584 | pr_debug("nf_ct_h245: TPKT len=%d ", datalen); |
585 | NF_CT_DUMP_TUPLE(&ct->tuplehash[CTINFO2DIR(ctinfo)].tuple); | 585 | NF_CT_DUMP_TUPLE(&ct->tuplehash[CTINFO2DIR(ctinfo)].tuple); |
@@ -596,7 +596,7 @@ static int h245_help(struct sk_buff **pskb, unsigned int protoff, | |||
596 | } | 596 | } |
597 | 597 | ||
598 | /* Process H.245 signal */ | 598 | /* Process H.245 signal */ |
599 | if (process_h245(pskb, ct, ctinfo, &data, dataoff, &mscm) < 0) | 599 | if (process_h245(skb, ct, ctinfo, &data, dataoff, &mscm) < 0) |
600 | goto drop; | 600 | goto drop; |
601 | } | 601 | } |
602 | 602 | ||
@@ -654,7 +654,7 @@ int get_h225_addr(struct nf_conn *ct, unsigned char *data, | |||
654 | } | 654 | } |
655 | 655 | ||
656 | /****************************************************************************/ | 656 | /****************************************************************************/ |
657 | static int expect_h245(struct sk_buff **pskb, struct nf_conn *ct, | 657 | static int expect_h245(struct sk_buff *skb, struct nf_conn *ct, |
658 | enum ip_conntrack_info ctinfo, | 658 | enum ip_conntrack_info ctinfo, |
659 | unsigned char **data, int dataoff, | 659 | unsigned char **data, int dataoff, |
660 | TransportAddress *taddr) | 660 | TransportAddress *taddr) |
@@ -687,7 +687,7 @@ static int expect_h245(struct sk_buff **pskb, struct nf_conn *ct, | |||
687 | (nat_h245 = rcu_dereference(nat_h245_hook)) && | 687 | (nat_h245 = rcu_dereference(nat_h245_hook)) && |
688 | ct->status & IPS_NAT_MASK) { | 688 | ct->status & IPS_NAT_MASK) { |
689 | /* NAT needed */ | 689 | /* NAT needed */ |
690 | ret = nat_h245(pskb, ct, ctinfo, data, dataoff, taddr, | 690 | ret = nat_h245(skb, ct, ctinfo, data, dataoff, taddr, |
691 | port, exp); | 691 | port, exp); |
692 | } else { /* Conntrack only */ | 692 | } else { /* Conntrack only */ |
693 | if (nf_ct_expect_related(exp) == 0) { | 693 | if (nf_ct_expect_related(exp) == 0) { |
@@ -758,7 +758,7 @@ static int callforward_do_filter(union nf_conntrack_address *src, | |||
758 | } | 758 | } |
759 | 759 | ||
760 | /****************************************************************************/ | 760 | /****************************************************************************/ |
761 | static int expect_callforwarding(struct sk_buff **pskb, | 761 | static int expect_callforwarding(struct sk_buff *skb, |
762 | struct nf_conn *ct, | 762 | struct nf_conn *ct, |
763 | enum ip_conntrack_info ctinfo, | 763 | enum ip_conntrack_info ctinfo, |
764 | unsigned char **data, int dataoff, | 764 | unsigned char **data, int dataoff, |
@@ -798,7 +798,7 @@ static int expect_callforwarding(struct sk_buff **pskb, | |||
798 | (nat_callforwarding = rcu_dereference(nat_callforwarding_hook)) && | 798 | (nat_callforwarding = rcu_dereference(nat_callforwarding_hook)) && |
799 | ct->status & IPS_NAT_MASK) { | 799 | ct->status & IPS_NAT_MASK) { |
800 | /* Need NAT */ | 800 | /* Need NAT */ |
801 | ret = nat_callforwarding(pskb, ct, ctinfo, data, dataoff, | 801 | ret = nat_callforwarding(skb, ct, ctinfo, data, dataoff, |
802 | taddr, port, exp); | 802 | taddr, port, exp); |
803 | } else { /* Conntrack only */ | 803 | } else { /* Conntrack only */ |
804 | if (nf_ct_expect_related(exp) == 0) { | 804 | if (nf_ct_expect_related(exp) == 0) { |
@@ -814,7 +814,7 @@ static int expect_callforwarding(struct sk_buff **pskb, | |||
814 | } | 814 | } |
815 | 815 | ||
816 | /****************************************************************************/ | 816 | /****************************************************************************/ |
817 | static int process_setup(struct sk_buff **pskb, struct nf_conn *ct, | 817 | static int process_setup(struct sk_buff *skb, struct nf_conn *ct, |
818 | enum ip_conntrack_info ctinfo, | 818 | enum ip_conntrack_info ctinfo, |
819 | unsigned char **data, int dataoff, | 819 | unsigned char **data, int dataoff, |
820 | Setup_UUIE *setup) | 820 | Setup_UUIE *setup) |
@@ -829,7 +829,7 @@ static int process_setup(struct sk_buff **pskb, struct nf_conn *ct, | |||
829 | pr_debug("nf_ct_q931: Setup\n"); | 829 | pr_debug("nf_ct_q931: Setup\n"); |
830 | 830 | ||
831 | if (setup->options & eSetup_UUIE_h245Address) { | 831 | if (setup->options & eSetup_UUIE_h245Address) { |
832 | ret = expect_h245(pskb, ct, ctinfo, data, dataoff, | 832 | ret = expect_h245(skb, ct, ctinfo, data, dataoff, |
833 | &setup->h245Address); | 833 | &setup->h245Address); |
834 | if (ret < 0) | 834 | if (ret < 0) |
835 | return -1; | 835 | return -1; |
@@ -846,7 +846,7 @@ static int process_setup(struct sk_buff **pskb, struct nf_conn *ct, | |||
846 | NIP6(*(struct in6_addr *)&addr), ntohs(port), | 846 | NIP6(*(struct in6_addr *)&addr), ntohs(port), |
847 | NIP6(*(struct in6_addr *)&ct->tuplehash[!dir].tuple.src.u3), | 847 | NIP6(*(struct in6_addr *)&ct->tuplehash[!dir].tuple.src.u3), |
848 | ntohs(ct->tuplehash[!dir].tuple.src.u.tcp.port)); | 848 | ntohs(ct->tuplehash[!dir].tuple.src.u.tcp.port)); |
849 | ret = set_h225_addr(pskb, data, dataoff, | 849 | ret = set_h225_addr(skb, data, dataoff, |
850 | &setup->destCallSignalAddress, | 850 | &setup->destCallSignalAddress, |
851 | &ct->tuplehash[!dir].tuple.src.u3, | 851 | &ct->tuplehash[!dir].tuple.src.u3, |
852 | ct->tuplehash[!dir].tuple.src.u.tcp.port); | 852 | ct->tuplehash[!dir].tuple.src.u.tcp.port); |
@@ -864,7 +864,7 @@ static int process_setup(struct sk_buff **pskb, struct nf_conn *ct, | |||
864 | NIP6(*(struct in6_addr *)&addr), ntohs(port), | 864 | NIP6(*(struct in6_addr *)&addr), ntohs(port), |
865 | NIP6(*(struct in6_addr *)&ct->tuplehash[!dir].tuple.dst.u3), | 865 | NIP6(*(struct in6_addr *)&ct->tuplehash[!dir].tuple.dst.u3), |
866 | ntohs(ct->tuplehash[!dir].tuple.dst.u.tcp.port)); | 866 | ntohs(ct->tuplehash[!dir].tuple.dst.u.tcp.port)); |
867 | ret = set_h225_addr(pskb, data, dataoff, | 867 | ret = set_h225_addr(skb, data, dataoff, |
868 | &setup->sourceCallSignalAddress, | 868 | &setup->sourceCallSignalAddress, |
869 | &ct->tuplehash[!dir].tuple.dst.u3, | 869 | &ct->tuplehash[!dir].tuple.dst.u3, |
870 | ct->tuplehash[!dir].tuple.dst.u.tcp.port); | 870 | ct->tuplehash[!dir].tuple.dst.u.tcp.port); |
@@ -874,7 +874,7 @@ static int process_setup(struct sk_buff **pskb, struct nf_conn *ct, | |||
874 | 874 | ||
875 | if (setup->options & eSetup_UUIE_fastStart) { | 875 | if (setup->options & eSetup_UUIE_fastStart) { |
876 | for (i = 0; i < setup->fastStart.count; i++) { | 876 | for (i = 0; i < setup->fastStart.count; i++) { |
877 | ret = process_olc(pskb, ct, ctinfo, data, dataoff, | 877 | ret = process_olc(skb, ct, ctinfo, data, dataoff, |
878 | &setup->fastStart.item[i]); | 878 | &setup->fastStart.item[i]); |
879 | if (ret < 0) | 879 | if (ret < 0) |
880 | return -1; | 880 | return -1; |
@@ -885,7 +885,7 @@ static int process_setup(struct sk_buff **pskb, struct nf_conn *ct, | |||
885 | } | 885 | } |
886 | 886 | ||
887 | /****************************************************************************/ | 887 | /****************************************************************************/ |
888 | static int process_callproceeding(struct sk_buff **pskb, | 888 | static int process_callproceeding(struct sk_buff *skb, |
889 | struct nf_conn *ct, | 889 | struct nf_conn *ct, |
890 | enum ip_conntrack_info ctinfo, | 890 | enum ip_conntrack_info ctinfo, |
891 | unsigned char **data, int dataoff, | 891 | unsigned char **data, int dataoff, |
@@ -897,7 +897,7 @@ static int process_callproceeding(struct sk_buff **pskb, | |||
897 | pr_debug("nf_ct_q931: CallProceeding\n"); | 897 | pr_debug("nf_ct_q931: CallProceeding\n"); |
898 | 898 | ||
899 | if (callproc->options & eCallProceeding_UUIE_h245Address) { | 899 | if (callproc->options & eCallProceeding_UUIE_h245Address) { |
900 | ret = expect_h245(pskb, ct, ctinfo, data, dataoff, | 900 | ret = expect_h245(skb, ct, ctinfo, data, dataoff, |
901 | &callproc->h245Address); | 901 | &callproc->h245Address); |
902 | if (ret < 0) | 902 | if (ret < 0) |
903 | return -1; | 903 | return -1; |
@@ -905,7 +905,7 @@ static int process_callproceeding(struct sk_buff **pskb, | |||
905 | 905 | ||
906 | if (callproc->options & eCallProceeding_UUIE_fastStart) { | 906 | if (callproc->options & eCallProceeding_UUIE_fastStart) { |
907 | for (i = 0; i < callproc->fastStart.count; i++) { | 907 | for (i = 0; i < callproc->fastStart.count; i++) { |
908 | ret = process_olc(pskb, ct, ctinfo, data, dataoff, | 908 | ret = process_olc(skb, ct, ctinfo, data, dataoff, |
909 | &callproc->fastStart.item[i]); | 909 | &callproc->fastStart.item[i]); |
910 | if (ret < 0) | 910 | if (ret < 0) |
911 | return -1; | 911 | return -1; |
@@ -916,7 +916,7 @@ static int process_callproceeding(struct sk_buff **pskb, | |||
916 | } | 916 | } |
917 | 917 | ||
918 | /****************************************************************************/ | 918 | /****************************************************************************/ |
919 | static int process_connect(struct sk_buff **pskb, struct nf_conn *ct, | 919 | static int process_connect(struct sk_buff *skb, struct nf_conn *ct, |
920 | enum ip_conntrack_info ctinfo, | 920 | enum ip_conntrack_info ctinfo, |
921 | unsigned char **data, int dataoff, | 921 | unsigned char **data, int dataoff, |
922 | Connect_UUIE *connect) | 922 | Connect_UUIE *connect) |
@@ -927,7 +927,7 @@ static int process_connect(struct sk_buff **pskb, struct nf_conn *ct, | |||
927 | pr_debug("nf_ct_q931: Connect\n"); | 927 | pr_debug("nf_ct_q931: Connect\n"); |
928 | 928 | ||
929 | if (connect->options & eConnect_UUIE_h245Address) { | 929 | if (connect->options & eConnect_UUIE_h245Address) { |
930 | ret = expect_h245(pskb, ct, ctinfo, data, dataoff, | 930 | ret = expect_h245(skb, ct, ctinfo, data, dataoff, |
931 | &connect->h245Address); | 931 | &connect->h245Address); |
932 | if (ret < 0) | 932 | if (ret < 0) |
933 | return -1; | 933 | return -1; |
@@ -935,7 +935,7 @@ static int process_connect(struct sk_buff **pskb, struct nf_conn *ct, | |||
935 | 935 | ||
936 | if (connect->options & eConnect_UUIE_fastStart) { | 936 | if (connect->options & eConnect_UUIE_fastStart) { |
937 | for (i = 0; i < connect->fastStart.count; i++) { | 937 | for (i = 0; i < connect->fastStart.count; i++) { |
938 | ret = process_olc(pskb, ct, ctinfo, data, dataoff, | 938 | ret = process_olc(skb, ct, ctinfo, data, dataoff, |
939 | &connect->fastStart.item[i]); | 939 | &connect->fastStart.item[i]); |
940 | if (ret < 0) | 940 | if (ret < 0) |
941 | return -1; | 941 | return -1; |
@@ -946,7 +946,7 @@ static int process_connect(struct sk_buff **pskb, struct nf_conn *ct, | |||
946 | } | 946 | } |
947 | 947 | ||
948 | /****************************************************************************/ | 948 | /****************************************************************************/ |
949 | static int process_alerting(struct sk_buff **pskb, struct nf_conn *ct, | 949 | static int process_alerting(struct sk_buff *skb, struct nf_conn *ct, |
950 | enum ip_conntrack_info ctinfo, | 950 | enum ip_conntrack_info ctinfo, |
951 | unsigned char **data, int dataoff, | 951 | unsigned char **data, int dataoff, |
952 | Alerting_UUIE *alert) | 952 | Alerting_UUIE *alert) |
@@ -957,7 +957,7 @@ static int process_alerting(struct sk_buff **pskb, struct nf_conn *ct, | |||
957 | pr_debug("nf_ct_q931: Alerting\n"); | 957 | pr_debug("nf_ct_q931: Alerting\n"); |
958 | 958 | ||
959 | if (alert->options & eAlerting_UUIE_h245Address) { | 959 | if (alert->options & eAlerting_UUIE_h245Address) { |
960 | ret = expect_h245(pskb, ct, ctinfo, data, dataoff, | 960 | ret = expect_h245(skb, ct, ctinfo, data, dataoff, |
961 | &alert->h245Address); | 961 | &alert->h245Address); |
962 | if (ret < 0) | 962 | if (ret < 0) |
963 | return -1; | 963 | return -1; |
@@ -965,7 +965,7 @@ static int process_alerting(struct sk_buff **pskb, struct nf_conn *ct, | |||
965 | 965 | ||
966 | if (alert->options & eAlerting_UUIE_fastStart) { | 966 | if (alert->options & eAlerting_UUIE_fastStart) { |
967 | for (i = 0; i < alert->fastStart.count; i++) { | 967 | for (i = 0; i < alert->fastStart.count; i++) { |
968 | ret = process_olc(pskb, ct, ctinfo, data, dataoff, | 968 | ret = process_olc(skb, ct, ctinfo, data, dataoff, |
969 | &alert->fastStart.item[i]); | 969 | &alert->fastStart.item[i]); |
970 | if (ret < 0) | 970 | if (ret < 0) |
971 | return -1; | 971 | return -1; |
@@ -976,7 +976,7 @@ static int process_alerting(struct sk_buff **pskb, struct nf_conn *ct, | |||
976 | } | 976 | } |
977 | 977 | ||
978 | /****************************************************************************/ | 978 | /****************************************************************************/ |
979 | static int process_facility(struct sk_buff **pskb, struct nf_conn *ct, | 979 | static int process_facility(struct sk_buff *skb, struct nf_conn *ct, |
980 | enum ip_conntrack_info ctinfo, | 980 | enum ip_conntrack_info ctinfo, |
981 | unsigned char **data, int dataoff, | 981 | unsigned char **data, int dataoff, |
982 | Facility_UUIE *facility) | 982 | Facility_UUIE *facility) |
@@ -988,7 +988,7 @@ static int process_facility(struct sk_buff **pskb, struct nf_conn *ct, | |||
988 | 988 | ||
989 | if (facility->reason.choice == eFacilityReason_callForwarded) { | 989 | if (facility->reason.choice == eFacilityReason_callForwarded) { |
990 | if (facility->options & eFacility_UUIE_alternativeAddress) | 990 | if (facility->options & eFacility_UUIE_alternativeAddress) |
991 | return expect_callforwarding(pskb, ct, ctinfo, data, | 991 | return expect_callforwarding(skb, ct, ctinfo, data, |
992 | dataoff, | 992 | dataoff, |
993 | &facility-> | 993 | &facility-> |
994 | alternativeAddress); | 994 | alternativeAddress); |
@@ -996,7 +996,7 @@ static int process_facility(struct sk_buff **pskb, struct nf_conn *ct, | |||
996 | } | 996 | } |
997 | 997 | ||
998 | if (facility->options & eFacility_UUIE_h245Address) { | 998 | if (facility->options & eFacility_UUIE_h245Address) { |
999 | ret = expect_h245(pskb, ct, ctinfo, data, dataoff, | 999 | ret = expect_h245(skb, ct, ctinfo, data, dataoff, |
1000 | &facility->h245Address); | 1000 | &facility->h245Address); |
1001 | if (ret < 0) | 1001 | if (ret < 0) |
1002 | return -1; | 1002 | return -1; |
@@ -1004,7 +1004,7 @@ static int process_facility(struct sk_buff **pskb, struct nf_conn *ct, | |||
1004 | 1004 | ||
1005 | if (facility->options & eFacility_UUIE_fastStart) { | 1005 | if (facility->options & eFacility_UUIE_fastStart) { |
1006 | for (i = 0; i < facility->fastStart.count; i++) { | 1006 | for (i = 0; i < facility->fastStart.count; i++) { |
1007 | ret = process_olc(pskb, ct, ctinfo, data, dataoff, | 1007 | ret = process_olc(skb, ct, ctinfo, data, dataoff, |
1008 | &facility->fastStart.item[i]); | 1008 | &facility->fastStart.item[i]); |
1009 | if (ret < 0) | 1009 | if (ret < 0) |
1010 | return -1; | 1010 | return -1; |
@@ -1015,7 +1015,7 @@ static int process_facility(struct sk_buff **pskb, struct nf_conn *ct, | |||
1015 | } | 1015 | } |
1016 | 1016 | ||
1017 | /****************************************************************************/ | 1017 | /****************************************************************************/ |
1018 | static int process_progress(struct sk_buff **pskb, struct nf_conn *ct, | 1018 | static int process_progress(struct sk_buff *skb, struct nf_conn *ct, |
1019 | enum ip_conntrack_info ctinfo, | 1019 | enum ip_conntrack_info ctinfo, |
1020 | unsigned char **data, int dataoff, | 1020 | unsigned char **data, int dataoff, |
1021 | Progress_UUIE *progress) | 1021 | Progress_UUIE *progress) |
@@ -1026,7 +1026,7 @@ static int process_progress(struct sk_buff **pskb, struct nf_conn *ct, | |||
1026 | pr_debug("nf_ct_q931: Progress\n"); | 1026 | pr_debug("nf_ct_q931: Progress\n"); |
1027 | 1027 | ||
1028 | if (progress->options & eProgress_UUIE_h245Address) { | 1028 | if (progress->options & eProgress_UUIE_h245Address) { |
1029 | ret = expect_h245(pskb, ct, ctinfo, data, dataoff, | 1029 | ret = expect_h245(skb, ct, ctinfo, data, dataoff, |
1030 | &progress->h245Address); | 1030 | &progress->h245Address); |
1031 | if (ret < 0) | 1031 | if (ret < 0) |
1032 | return -1; | 1032 | return -1; |
@@ -1034,7 +1034,7 @@ static int process_progress(struct sk_buff **pskb, struct nf_conn *ct, | |||
1034 | 1034 | ||
1035 | if (progress->options & eProgress_UUIE_fastStart) { | 1035 | if (progress->options & eProgress_UUIE_fastStart) { |
1036 | for (i = 0; i < progress->fastStart.count; i++) { | 1036 | for (i = 0; i < progress->fastStart.count; i++) { |
1037 | ret = process_olc(pskb, ct, ctinfo, data, dataoff, | 1037 | ret = process_olc(skb, ct, ctinfo, data, dataoff, |
1038 | &progress->fastStart.item[i]); | 1038 | &progress->fastStart.item[i]); |
1039 | if (ret < 0) | 1039 | if (ret < 0) |
1040 | return -1; | 1040 | return -1; |
@@ -1045,7 +1045,7 @@ static int process_progress(struct sk_buff **pskb, struct nf_conn *ct, | |||
1045 | } | 1045 | } |
1046 | 1046 | ||
1047 | /****************************************************************************/ | 1047 | /****************************************************************************/ |
1048 | static int process_q931(struct sk_buff **pskb, struct nf_conn *ct, | 1048 | static int process_q931(struct sk_buff *skb, struct nf_conn *ct, |
1049 | enum ip_conntrack_info ctinfo, | 1049 | enum ip_conntrack_info ctinfo, |
1050 | unsigned char **data, int dataoff, Q931 *q931) | 1050 | unsigned char **data, int dataoff, Q931 *q931) |
1051 | { | 1051 | { |
@@ -1055,28 +1055,28 @@ static int process_q931(struct sk_buff **pskb, struct nf_conn *ct, | |||
1055 | 1055 | ||
1056 | switch (pdu->h323_message_body.choice) { | 1056 | switch (pdu->h323_message_body.choice) { |
1057 | case eH323_UU_PDU_h323_message_body_setup: | 1057 | case eH323_UU_PDU_h323_message_body_setup: |
1058 | ret = process_setup(pskb, ct, ctinfo, data, dataoff, | 1058 | ret = process_setup(skb, ct, ctinfo, data, dataoff, |
1059 | &pdu->h323_message_body.setup); | 1059 | &pdu->h323_message_body.setup); |
1060 | break; | 1060 | break; |
1061 | case eH323_UU_PDU_h323_message_body_callProceeding: | 1061 | case eH323_UU_PDU_h323_message_body_callProceeding: |
1062 | ret = process_callproceeding(pskb, ct, ctinfo, data, dataoff, | 1062 | ret = process_callproceeding(skb, ct, ctinfo, data, dataoff, |
1063 | &pdu->h323_message_body. | 1063 | &pdu->h323_message_body. |
1064 | callProceeding); | 1064 | callProceeding); |
1065 | break; | 1065 | break; |
1066 | case eH323_UU_PDU_h323_message_body_connect: | 1066 | case eH323_UU_PDU_h323_message_body_connect: |
1067 | ret = process_connect(pskb, ct, ctinfo, data, dataoff, | 1067 | ret = process_connect(skb, ct, ctinfo, data, dataoff, |
1068 | &pdu->h323_message_body.connect); | 1068 | &pdu->h323_message_body.connect); |
1069 | break; | 1069 | break; |
1070 | case eH323_UU_PDU_h323_message_body_alerting: | 1070 | case eH323_UU_PDU_h323_message_body_alerting: |
1071 | ret = process_alerting(pskb, ct, ctinfo, data, dataoff, | 1071 | ret = process_alerting(skb, ct, ctinfo, data, dataoff, |
1072 | &pdu->h323_message_body.alerting); | 1072 | &pdu->h323_message_body.alerting); |
1073 | break; | 1073 | break; |
1074 | case eH323_UU_PDU_h323_message_body_facility: | 1074 | case eH323_UU_PDU_h323_message_body_facility: |
1075 | ret = process_facility(pskb, ct, ctinfo, data, dataoff, | 1075 | ret = process_facility(skb, ct, ctinfo, data, dataoff, |
1076 | &pdu->h323_message_body.facility); | 1076 | &pdu->h323_message_body.facility); |
1077 | break; | 1077 | break; |
1078 | case eH323_UU_PDU_h323_message_body_progress: | 1078 | case eH323_UU_PDU_h323_message_body_progress: |
1079 | ret = process_progress(pskb, ct, ctinfo, data, dataoff, | 1079 | ret = process_progress(skb, ct, ctinfo, data, dataoff, |
1080 | &pdu->h323_message_body.progress); | 1080 | &pdu->h323_message_body.progress); |
1081 | break; | 1081 | break; |
1082 | default: | 1082 | default: |
@@ -1090,7 +1090,7 @@ static int process_q931(struct sk_buff **pskb, struct nf_conn *ct, | |||
1090 | 1090 | ||
1091 | if (pdu->options & eH323_UU_PDU_h245Control) { | 1091 | if (pdu->options & eH323_UU_PDU_h245Control) { |
1092 | for (i = 0; i < pdu->h245Control.count; i++) { | 1092 | for (i = 0; i < pdu->h245Control.count; i++) { |
1093 | ret = process_h245(pskb, ct, ctinfo, data, dataoff, | 1093 | ret = process_h245(skb, ct, ctinfo, data, dataoff, |
1094 | &pdu->h245Control.item[i]); | 1094 | &pdu->h245Control.item[i]); |
1095 | if (ret < 0) | 1095 | if (ret < 0) |
1096 | return -1; | 1096 | return -1; |
@@ -1101,7 +1101,7 @@ static int process_q931(struct sk_buff **pskb, struct nf_conn *ct, | |||
1101 | } | 1101 | } |
1102 | 1102 | ||
1103 | /****************************************************************************/ | 1103 | /****************************************************************************/ |
1104 | static int q931_help(struct sk_buff **pskb, unsigned int protoff, | 1104 | static int q931_help(struct sk_buff *skb, unsigned int protoff, |
1105 | struct nf_conn *ct, enum ip_conntrack_info ctinfo) | 1105 | struct nf_conn *ct, enum ip_conntrack_info ctinfo) |
1106 | { | 1106 | { |
1107 | static Q931 q931; | 1107 | static Q931 q931; |
@@ -1115,12 +1115,12 @@ static int q931_help(struct sk_buff **pskb, unsigned int protoff, | |||
1115 | ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) { | 1115 | ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) { |
1116 | return NF_ACCEPT; | 1116 | return NF_ACCEPT; |
1117 | } | 1117 | } |
1118 | pr_debug("nf_ct_q931: skblen = %u\n", (*pskb)->len); | 1118 | pr_debug("nf_ct_q931: skblen = %u\n", skb->len); |
1119 | 1119 | ||
1120 | spin_lock_bh(&nf_h323_lock); | 1120 | spin_lock_bh(&nf_h323_lock); |
1121 | 1121 | ||
1122 | /* Process each TPKT */ | 1122 | /* Process each TPKT */ |
1123 | while (get_tpkt_data(pskb, protoff, ct, ctinfo, | 1123 | while (get_tpkt_data(skb, protoff, ct, ctinfo, |
1124 | &data, &datalen, &dataoff)) { | 1124 | &data, &datalen, &dataoff)) { |
1125 | pr_debug("nf_ct_q931: TPKT len=%d ", datalen); | 1125 | pr_debug("nf_ct_q931: TPKT len=%d ", datalen); |
1126 | NF_CT_DUMP_TUPLE(&ct->tuplehash[CTINFO2DIR(ctinfo)].tuple); | 1126 | NF_CT_DUMP_TUPLE(&ct->tuplehash[CTINFO2DIR(ctinfo)].tuple); |
@@ -1136,7 +1136,7 @@ static int q931_help(struct sk_buff **pskb, unsigned int protoff, | |||
1136 | } | 1136 | } |
1137 | 1137 | ||
1138 | /* Process Q.931 signal */ | 1138 | /* Process Q.931 signal */ |
1139 | if (process_q931(pskb, ct, ctinfo, &data, dataoff, &q931) < 0) | 1139 | if (process_q931(skb, ct, ctinfo, &data, dataoff, &q931) < 0) |
1140 | goto drop; | 1140 | goto drop; |
1141 | } | 1141 | } |
1142 | 1142 | ||
@@ -1177,20 +1177,20 @@ static struct nf_conntrack_helper nf_conntrack_helper_q931[] __read_mostly = { | |||
1177 | }; | 1177 | }; |
1178 | 1178 | ||
1179 | /****************************************************************************/ | 1179 | /****************************************************************************/ |
1180 | static unsigned char *get_udp_data(struct sk_buff **pskb, unsigned int protoff, | 1180 | static unsigned char *get_udp_data(struct sk_buff *skb, unsigned int protoff, |
1181 | int *datalen) | 1181 | int *datalen) |
1182 | { | 1182 | { |
1183 | struct udphdr _uh, *uh; | 1183 | struct udphdr _uh, *uh; |
1184 | int dataoff; | 1184 | int dataoff; |
1185 | 1185 | ||
1186 | uh = skb_header_pointer(*pskb, protoff, sizeof(_uh), &_uh); | 1186 | uh = skb_header_pointer(skb, protoff, sizeof(_uh), &_uh); |
1187 | if (uh == NULL) | 1187 | if (uh == NULL) |
1188 | return NULL; | 1188 | return NULL; |
1189 | dataoff = protoff + sizeof(_uh); | 1189 | dataoff = protoff + sizeof(_uh); |
1190 | if (dataoff >= (*pskb)->len) | 1190 | if (dataoff >= skb->len) |
1191 | return NULL; | 1191 | return NULL; |
1192 | *datalen = (*pskb)->len - dataoff; | 1192 | *datalen = skb->len - dataoff; |
1193 | return skb_header_pointer(*pskb, dataoff, *datalen, h323_buffer); | 1193 | return skb_header_pointer(skb, dataoff, *datalen, h323_buffer); |
1194 | } | 1194 | } |
1195 | 1195 | ||
1196 | /****************************************************************************/ | 1196 | /****************************************************************************/ |
@@ -1227,7 +1227,7 @@ static int set_expect_timeout(struct nf_conntrack_expect *exp, | |||
1227 | } | 1227 | } |
1228 | 1228 | ||
1229 | /****************************************************************************/ | 1229 | /****************************************************************************/ |
1230 | static int expect_q931(struct sk_buff **pskb, struct nf_conn *ct, | 1230 | static int expect_q931(struct sk_buff *skb, struct nf_conn *ct, |
1231 | enum ip_conntrack_info ctinfo, | 1231 | enum ip_conntrack_info ctinfo, |
1232 | unsigned char **data, | 1232 | unsigned char **data, |
1233 | TransportAddress *taddr, int count) | 1233 | TransportAddress *taddr, int count) |
@@ -1265,7 +1265,7 @@ static int expect_q931(struct sk_buff **pskb, struct nf_conn *ct, | |||
1265 | 1265 | ||
1266 | nat_q931 = rcu_dereference(nat_q931_hook); | 1266 | nat_q931 = rcu_dereference(nat_q931_hook); |
1267 | if (nat_q931 && ct->status & IPS_NAT_MASK) { /* Need NAT */ | 1267 | if (nat_q931 && ct->status & IPS_NAT_MASK) { /* Need NAT */ |
1268 | ret = nat_q931(pskb, ct, ctinfo, data, taddr, i, port, exp); | 1268 | ret = nat_q931(skb, ct, ctinfo, data, taddr, i, port, exp); |
1269 | } else { /* Conntrack only */ | 1269 | } else { /* Conntrack only */ |
1270 | if (nf_ct_expect_related(exp) == 0) { | 1270 | if (nf_ct_expect_related(exp) == 0) { |
1271 | pr_debug("nf_ct_ras: expect Q.931 "); | 1271 | pr_debug("nf_ct_ras: expect Q.931 "); |
@@ -1283,7 +1283,7 @@ static int expect_q931(struct sk_buff **pskb, struct nf_conn *ct, | |||
1283 | } | 1283 | } |
1284 | 1284 | ||
1285 | /****************************************************************************/ | 1285 | /****************************************************************************/ |
1286 | static int process_grq(struct sk_buff **pskb, struct nf_conn *ct, | 1286 | static int process_grq(struct sk_buff *skb, struct nf_conn *ct, |
1287 | enum ip_conntrack_info ctinfo, | 1287 | enum ip_conntrack_info ctinfo, |
1288 | unsigned char **data, GatekeeperRequest *grq) | 1288 | unsigned char **data, GatekeeperRequest *grq) |
1289 | { | 1289 | { |
@@ -1293,13 +1293,13 @@ static int process_grq(struct sk_buff **pskb, struct nf_conn *ct, | |||
1293 | 1293 | ||
1294 | set_ras_addr = rcu_dereference(set_ras_addr_hook); | 1294 | set_ras_addr = rcu_dereference(set_ras_addr_hook); |
1295 | if (set_ras_addr && ct->status & IPS_NAT_MASK) /* NATed */ | 1295 | if (set_ras_addr && ct->status & IPS_NAT_MASK) /* NATed */ |
1296 | return set_ras_addr(pskb, ct, ctinfo, data, | 1296 | return set_ras_addr(skb, ct, ctinfo, data, |
1297 | &grq->rasAddress, 1); | 1297 | &grq->rasAddress, 1); |
1298 | return 0; | 1298 | return 0; |
1299 | } | 1299 | } |
1300 | 1300 | ||
1301 | /****************************************************************************/ | 1301 | /****************************************************************************/ |
1302 | static int process_gcf(struct sk_buff **pskb, struct nf_conn *ct, | 1302 | static int process_gcf(struct sk_buff *skb, struct nf_conn *ct, |
1303 | enum ip_conntrack_info ctinfo, | 1303 | enum ip_conntrack_info ctinfo, |
1304 | unsigned char **data, GatekeeperConfirm *gcf) | 1304 | unsigned char **data, GatekeeperConfirm *gcf) |
1305 | { | 1305 | { |
@@ -1343,7 +1343,7 @@ static int process_gcf(struct sk_buff **pskb, struct nf_conn *ct, | |||
1343 | } | 1343 | } |
1344 | 1344 | ||
1345 | /****************************************************************************/ | 1345 | /****************************************************************************/ |
1346 | static int process_rrq(struct sk_buff **pskb, struct nf_conn *ct, | 1346 | static int process_rrq(struct sk_buff *skb, struct nf_conn *ct, |
1347 | enum ip_conntrack_info ctinfo, | 1347 | enum ip_conntrack_info ctinfo, |
1348 | unsigned char **data, RegistrationRequest *rrq) | 1348 | unsigned char **data, RegistrationRequest *rrq) |
1349 | { | 1349 | { |
@@ -1353,7 +1353,7 @@ static int process_rrq(struct sk_buff **pskb, struct nf_conn *ct, | |||
1353 | 1353 | ||
1354 | pr_debug("nf_ct_ras: RRQ\n"); | 1354 | pr_debug("nf_ct_ras: RRQ\n"); |
1355 | 1355 | ||
1356 | ret = expect_q931(pskb, ct, ctinfo, data, | 1356 | ret = expect_q931(skb, ct, ctinfo, data, |
1357 | rrq->callSignalAddress.item, | 1357 | rrq->callSignalAddress.item, |
1358 | rrq->callSignalAddress.count); | 1358 | rrq->callSignalAddress.count); |
1359 | if (ret < 0) | 1359 | if (ret < 0) |
@@ -1361,7 +1361,7 @@ static int process_rrq(struct sk_buff **pskb, struct nf_conn *ct, | |||
1361 | 1361 | ||
1362 | set_ras_addr = rcu_dereference(set_ras_addr_hook); | 1362 | set_ras_addr = rcu_dereference(set_ras_addr_hook); |
1363 | if (set_ras_addr && ct->status & IPS_NAT_MASK) { | 1363 | if (set_ras_addr && ct->status & IPS_NAT_MASK) { |
1364 | ret = set_ras_addr(pskb, ct, ctinfo, data, | 1364 | ret = set_ras_addr(skb, ct, ctinfo, data, |
1365 | rrq->rasAddress.item, | 1365 | rrq->rasAddress.item, |
1366 | rrq->rasAddress.count); | 1366 | rrq->rasAddress.count); |
1367 | if (ret < 0) | 1367 | if (ret < 0) |
@@ -1378,7 +1378,7 @@ static int process_rrq(struct sk_buff **pskb, struct nf_conn *ct, | |||
1378 | } | 1378 | } |
1379 | 1379 | ||
1380 | /****************************************************************************/ | 1380 | /****************************************************************************/ |
1381 | static int process_rcf(struct sk_buff **pskb, struct nf_conn *ct, | 1381 | static int process_rcf(struct sk_buff *skb, struct nf_conn *ct, |
1382 | enum ip_conntrack_info ctinfo, | 1382 | enum ip_conntrack_info ctinfo, |
1383 | unsigned char **data, RegistrationConfirm *rcf) | 1383 | unsigned char **data, RegistrationConfirm *rcf) |
1384 | { | 1384 | { |
@@ -1392,7 +1392,7 @@ static int process_rcf(struct sk_buff **pskb, struct nf_conn *ct, | |||
1392 | 1392 | ||
1393 | set_sig_addr = rcu_dereference(set_sig_addr_hook); | 1393 | set_sig_addr = rcu_dereference(set_sig_addr_hook); |
1394 | if (set_sig_addr && ct->status & IPS_NAT_MASK) { | 1394 | if (set_sig_addr && ct->status & IPS_NAT_MASK) { |
1395 | ret = set_sig_addr(pskb, ct, ctinfo, data, | 1395 | ret = set_sig_addr(skb, ct, ctinfo, data, |
1396 | rcf->callSignalAddress.item, | 1396 | rcf->callSignalAddress.item, |
1397 | rcf->callSignalAddress.count); | 1397 | rcf->callSignalAddress.count); |
1398 | if (ret < 0) | 1398 | if (ret < 0) |
@@ -1407,7 +1407,7 @@ static int process_rcf(struct sk_buff **pskb, struct nf_conn *ct, | |||
1407 | if (info->timeout > 0) { | 1407 | if (info->timeout > 0) { |
1408 | pr_debug("nf_ct_ras: set RAS connection timeout to " | 1408 | pr_debug("nf_ct_ras: set RAS connection timeout to " |
1409 | "%u seconds\n", info->timeout); | 1409 | "%u seconds\n", info->timeout); |
1410 | nf_ct_refresh(ct, *pskb, info->timeout * HZ); | 1410 | nf_ct_refresh(ct, skb, info->timeout * HZ); |
1411 | 1411 | ||
1412 | /* Set expect timeout */ | 1412 | /* Set expect timeout */ |
1413 | read_lock_bh(&nf_conntrack_lock); | 1413 | read_lock_bh(&nf_conntrack_lock); |
@@ -1427,7 +1427,7 @@ static int process_rcf(struct sk_buff **pskb, struct nf_conn *ct, | |||
1427 | } | 1427 | } |
1428 | 1428 | ||
1429 | /****************************************************************************/ | 1429 | /****************************************************************************/ |
1430 | static int process_urq(struct sk_buff **pskb, struct nf_conn *ct, | 1430 | static int process_urq(struct sk_buff *skb, struct nf_conn *ct, |
1431 | enum ip_conntrack_info ctinfo, | 1431 | enum ip_conntrack_info ctinfo, |
1432 | unsigned char **data, UnregistrationRequest *urq) | 1432 | unsigned char **data, UnregistrationRequest *urq) |
1433 | { | 1433 | { |
@@ -1440,7 +1440,7 @@ static int process_urq(struct sk_buff **pskb, struct nf_conn *ct, | |||
1440 | 1440 | ||
1441 | set_sig_addr = rcu_dereference(set_sig_addr_hook); | 1441 | set_sig_addr = rcu_dereference(set_sig_addr_hook); |
1442 | if (set_sig_addr && ct->status & IPS_NAT_MASK) { | 1442 | if (set_sig_addr && ct->status & IPS_NAT_MASK) { |
1443 | ret = set_sig_addr(pskb, ct, ctinfo, data, | 1443 | ret = set_sig_addr(skb, ct, ctinfo, data, |
1444 | urq->callSignalAddress.item, | 1444 | urq->callSignalAddress.item, |
1445 | urq->callSignalAddress.count); | 1445 | urq->callSignalAddress.count); |
1446 | if (ret < 0) | 1446 | if (ret < 0) |
@@ -1453,13 +1453,13 @@ static int process_urq(struct sk_buff **pskb, struct nf_conn *ct, | |||
1453 | info->sig_port[!dir] = 0; | 1453 | info->sig_port[!dir] = 0; |
1454 | 1454 | ||
1455 | /* Give it 30 seconds for UCF or URJ */ | 1455 | /* Give it 30 seconds for UCF or URJ */ |
1456 | nf_ct_refresh(ct, *pskb, 30 * HZ); | 1456 | nf_ct_refresh(ct, skb, 30 * HZ); |
1457 | 1457 | ||
1458 | return 0; | 1458 | return 0; |
1459 | } | 1459 | } |
1460 | 1460 | ||
1461 | /****************************************************************************/ | 1461 | /****************************************************************************/ |
1462 | static int process_arq(struct sk_buff **pskb, struct nf_conn *ct, | 1462 | static int process_arq(struct sk_buff *skb, struct nf_conn *ct, |
1463 | enum ip_conntrack_info ctinfo, | 1463 | enum ip_conntrack_info ctinfo, |
1464 | unsigned char **data, AdmissionRequest *arq) | 1464 | unsigned char **data, AdmissionRequest *arq) |
1465 | { | 1465 | { |
@@ -1479,7 +1479,7 @@ static int process_arq(struct sk_buff **pskb, struct nf_conn *ct, | |||
1479 | port == info->sig_port[dir] && | 1479 | port == info->sig_port[dir] && |
1480 | set_h225_addr && ct->status & IPS_NAT_MASK) { | 1480 | set_h225_addr && ct->status & IPS_NAT_MASK) { |
1481 | /* Answering ARQ */ | 1481 | /* Answering ARQ */ |
1482 | return set_h225_addr(pskb, data, 0, | 1482 | return set_h225_addr(skb, data, 0, |
1483 | &arq->destCallSignalAddress, | 1483 | &arq->destCallSignalAddress, |
1484 | &ct->tuplehash[!dir].tuple.dst.u3, | 1484 | &ct->tuplehash[!dir].tuple.dst.u3, |
1485 | info->sig_port[!dir]); | 1485 | info->sig_port[!dir]); |
@@ -1491,7 +1491,7 @@ static int process_arq(struct sk_buff **pskb, struct nf_conn *ct, | |||
1491 | !memcmp(&addr, &ct->tuplehash[dir].tuple.src.u3, sizeof(addr)) && | 1491 | !memcmp(&addr, &ct->tuplehash[dir].tuple.src.u3, sizeof(addr)) && |
1492 | set_h225_addr && ct->status & IPS_NAT_MASK) { | 1492 | set_h225_addr && ct->status & IPS_NAT_MASK) { |
1493 | /* Calling ARQ */ | 1493 | /* Calling ARQ */ |
1494 | return set_h225_addr(pskb, data, 0, | 1494 | return set_h225_addr(skb, data, 0, |
1495 | &arq->srcCallSignalAddress, | 1495 | &arq->srcCallSignalAddress, |
1496 | &ct->tuplehash[!dir].tuple.dst.u3, | 1496 | &ct->tuplehash[!dir].tuple.dst.u3, |
1497 | port); | 1497 | port); |
@@ -1501,7 +1501,7 @@ static int process_arq(struct sk_buff **pskb, struct nf_conn *ct, | |||
1501 | } | 1501 | } |
1502 | 1502 | ||
1503 | /****************************************************************************/ | 1503 | /****************************************************************************/ |
1504 | static int process_acf(struct sk_buff **pskb, struct nf_conn *ct, | 1504 | static int process_acf(struct sk_buff *skb, struct nf_conn *ct, |
1505 | enum ip_conntrack_info ctinfo, | 1505 | enum ip_conntrack_info ctinfo, |
1506 | unsigned char **data, AdmissionConfirm *acf) | 1506 | unsigned char **data, AdmissionConfirm *acf) |
1507 | { | 1507 | { |
@@ -1522,7 +1522,7 @@ static int process_acf(struct sk_buff **pskb, struct nf_conn *ct, | |||
1522 | /* Answering ACF */ | 1522 | /* Answering ACF */ |
1523 | set_sig_addr = rcu_dereference(set_sig_addr_hook); | 1523 | set_sig_addr = rcu_dereference(set_sig_addr_hook); |
1524 | if (set_sig_addr && ct->status & IPS_NAT_MASK) | 1524 | if (set_sig_addr && ct->status & IPS_NAT_MASK) |
1525 | return set_sig_addr(pskb, ct, ctinfo, data, | 1525 | return set_sig_addr(skb, ct, ctinfo, data, |
1526 | &acf->destCallSignalAddress, 1); | 1526 | &acf->destCallSignalAddress, 1); |
1527 | return 0; | 1527 | return 0; |
1528 | } | 1528 | } |
@@ -1548,7 +1548,7 @@ static int process_acf(struct sk_buff **pskb, struct nf_conn *ct, | |||
1548 | } | 1548 | } |
1549 | 1549 | ||
1550 | /****************************************************************************/ | 1550 | /****************************************************************************/ |
1551 | static int process_lrq(struct sk_buff **pskb, struct nf_conn *ct, | 1551 | static int process_lrq(struct sk_buff *skb, struct nf_conn *ct, |
1552 | enum ip_conntrack_info ctinfo, | 1552 | enum ip_conntrack_info ctinfo, |
1553 | unsigned char **data, LocationRequest *lrq) | 1553 | unsigned char **data, LocationRequest *lrq) |
1554 | { | 1554 | { |
@@ -1558,13 +1558,13 @@ static int process_lrq(struct sk_buff **pskb, struct nf_conn *ct, | |||
1558 | 1558 | ||
1559 | set_ras_addr = rcu_dereference(set_ras_addr_hook); | 1559 | set_ras_addr = rcu_dereference(set_ras_addr_hook); |
1560 | if (set_ras_addr && ct->status & IPS_NAT_MASK) | 1560 | if (set_ras_addr && ct->status & IPS_NAT_MASK) |
1561 | return set_ras_addr(pskb, ct, ctinfo, data, | 1561 | return set_ras_addr(skb, ct, ctinfo, data, |
1562 | &lrq->replyAddress, 1); | 1562 | &lrq->replyAddress, 1); |
1563 | return 0; | 1563 | return 0; |
1564 | } | 1564 | } |
1565 | 1565 | ||
1566 | /****************************************************************************/ | 1566 | /****************************************************************************/ |
1567 | static int process_lcf(struct sk_buff **pskb, struct nf_conn *ct, | 1567 | static int process_lcf(struct sk_buff *skb, struct nf_conn *ct, |
1568 | enum ip_conntrack_info ctinfo, | 1568 | enum ip_conntrack_info ctinfo, |
1569 | unsigned char **data, LocationConfirm *lcf) | 1569 | unsigned char **data, LocationConfirm *lcf) |
1570 | { | 1570 | { |
@@ -1603,7 +1603,7 @@ static int process_lcf(struct sk_buff **pskb, struct nf_conn *ct, | |||
1603 | } | 1603 | } |
1604 | 1604 | ||
1605 | /****************************************************************************/ | 1605 | /****************************************************************************/ |
1606 | static int process_irr(struct sk_buff **pskb, struct nf_conn *ct, | 1606 | static int process_irr(struct sk_buff *skb, struct nf_conn *ct, |
1607 | enum ip_conntrack_info ctinfo, | 1607 | enum ip_conntrack_info ctinfo, |
1608 | unsigned char **data, InfoRequestResponse *irr) | 1608 | unsigned char **data, InfoRequestResponse *irr) |
1609 | { | 1609 | { |
@@ -1615,7 +1615,7 @@ static int process_irr(struct sk_buff **pskb, struct nf_conn *ct, | |||
1615 | 1615 | ||
1616 | set_ras_addr = rcu_dereference(set_ras_addr_hook); | 1616 | set_ras_addr = rcu_dereference(set_ras_addr_hook); |
1617 | if (set_ras_addr && ct->status & IPS_NAT_MASK) { | 1617 | if (set_ras_addr && ct->status & IPS_NAT_MASK) { |
1618 | ret = set_ras_addr(pskb, ct, ctinfo, data, | 1618 | ret = set_ras_addr(skb, ct, ctinfo, data, |
1619 | &irr->rasAddress, 1); | 1619 | &irr->rasAddress, 1); |
1620 | if (ret < 0) | 1620 | if (ret < 0) |
1621 | return -1; | 1621 | return -1; |
@@ -1623,7 +1623,7 @@ static int process_irr(struct sk_buff **pskb, struct nf_conn *ct, | |||
1623 | 1623 | ||
1624 | set_sig_addr = rcu_dereference(set_sig_addr_hook); | 1624 | set_sig_addr = rcu_dereference(set_sig_addr_hook); |
1625 | if (set_sig_addr && ct->status & IPS_NAT_MASK) { | 1625 | if (set_sig_addr && ct->status & IPS_NAT_MASK) { |
1626 | ret = set_sig_addr(pskb, ct, ctinfo, data, | 1626 | ret = set_sig_addr(skb, ct, ctinfo, data, |
1627 | irr->callSignalAddress.item, | 1627 | irr->callSignalAddress.item, |
1628 | irr->callSignalAddress.count); | 1628 | irr->callSignalAddress.count); |
1629 | if (ret < 0) | 1629 | if (ret < 0) |
@@ -1634,40 +1634,40 @@ static int process_irr(struct sk_buff **pskb, struct nf_conn *ct, | |||
1634 | } | 1634 | } |
1635 | 1635 | ||
1636 | /****************************************************************************/ | 1636 | /****************************************************************************/ |
1637 | static int process_ras(struct sk_buff **pskb, struct nf_conn *ct, | 1637 | static int process_ras(struct sk_buff *skb, struct nf_conn *ct, |
1638 | enum ip_conntrack_info ctinfo, | 1638 | enum ip_conntrack_info ctinfo, |
1639 | unsigned char **data, RasMessage *ras) | 1639 | unsigned char **data, RasMessage *ras) |
1640 | { | 1640 | { |
1641 | switch (ras->choice) { | 1641 | switch (ras->choice) { |
1642 | case eRasMessage_gatekeeperRequest: | 1642 | case eRasMessage_gatekeeperRequest: |
1643 | return process_grq(pskb, ct, ctinfo, data, | 1643 | return process_grq(skb, ct, ctinfo, data, |
1644 | &ras->gatekeeperRequest); | 1644 | &ras->gatekeeperRequest); |
1645 | case eRasMessage_gatekeeperConfirm: | 1645 | case eRasMessage_gatekeeperConfirm: |
1646 | return process_gcf(pskb, ct, ctinfo, data, | 1646 | return process_gcf(skb, ct, ctinfo, data, |
1647 | &ras->gatekeeperConfirm); | 1647 | &ras->gatekeeperConfirm); |
1648 | case eRasMessage_registrationRequest: | 1648 | case eRasMessage_registrationRequest: |
1649 | return process_rrq(pskb, ct, ctinfo, data, | 1649 | return process_rrq(skb, ct, ctinfo, data, |
1650 | &ras->registrationRequest); | 1650 | &ras->registrationRequest); |
1651 | case eRasMessage_registrationConfirm: | 1651 | case eRasMessage_registrationConfirm: |
1652 | return process_rcf(pskb, ct, ctinfo, data, | 1652 | return process_rcf(skb, ct, ctinfo, data, |
1653 | &ras->registrationConfirm); | 1653 | &ras->registrationConfirm); |
1654 | case eRasMessage_unregistrationRequest: | 1654 | case eRasMessage_unregistrationRequest: |
1655 | return process_urq(pskb, ct, ctinfo, data, | 1655 | return process_urq(skb, ct, ctinfo, data, |
1656 | &ras->unregistrationRequest); | 1656 | &ras->unregistrationRequest); |
1657 | case eRasMessage_admissionRequest: | 1657 | case eRasMessage_admissionRequest: |
1658 | return process_arq(pskb, ct, ctinfo, data, | 1658 | return process_arq(skb, ct, ctinfo, data, |
1659 | &ras->admissionRequest); | 1659 | &ras->admissionRequest); |
1660 | case eRasMessage_admissionConfirm: | 1660 | case eRasMessage_admissionConfirm: |
1661 | return process_acf(pskb, ct, ctinfo, data, | 1661 | return process_acf(skb, ct, ctinfo, data, |
1662 | &ras->admissionConfirm); | 1662 | &ras->admissionConfirm); |
1663 | case eRasMessage_locationRequest: | 1663 | case eRasMessage_locationRequest: |
1664 | return process_lrq(pskb, ct, ctinfo, data, | 1664 | return process_lrq(skb, ct, ctinfo, data, |
1665 | &ras->locationRequest); | 1665 | &ras->locationRequest); |
1666 | case eRasMessage_locationConfirm: | 1666 | case eRasMessage_locationConfirm: |
1667 | return process_lcf(pskb, ct, ctinfo, data, | 1667 | return process_lcf(skb, ct, ctinfo, data, |
1668 | &ras->locationConfirm); | 1668 | &ras->locationConfirm); |
1669 | case eRasMessage_infoRequestResponse: | 1669 | case eRasMessage_infoRequestResponse: |
1670 | return process_irr(pskb, ct, ctinfo, data, | 1670 | return process_irr(skb, ct, ctinfo, data, |
1671 | &ras->infoRequestResponse); | 1671 | &ras->infoRequestResponse); |
1672 | default: | 1672 | default: |
1673 | pr_debug("nf_ct_ras: RAS message %d\n", ras->choice); | 1673 | pr_debug("nf_ct_ras: RAS message %d\n", ras->choice); |
@@ -1678,7 +1678,7 @@ static int process_ras(struct sk_buff **pskb, struct nf_conn *ct, | |||
1678 | } | 1678 | } |
1679 | 1679 | ||
1680 | /****************************************************************************/ | 1680 | /****************************************************************************/ |
1681 | static int ras_help(struct sk_buff **pskb, unsigned int protoff, | 1681 | static int ras_help(struct sk_buff *skb, unsigned int protoff, |
1682 | struct nf_conn *ct, enum ip_conntrack_info ctinfo) | 1682 | struct nf_conn *ct, enum ip_conntrack_info ctinfo) |
1683 | { | 1683 | { |
1684 | static RasMessage ras; | 1684 | static RasMessage ras; |
@@ -1686,12 +1686,12 @@ static int ras_help(struct sk_buff **pskb, unsigned int protoff, | |||
1686 | int datalen = 0; | 1686 | int datalen = 0; |
1687 | int ret; | 1687 | int ret; |
1688 | 1688 | ||
1689 | pr_debug("nf_ct_ras: skblen = %u\n", (*pskb)->len); | 1689 | pr_debug("nf_ct_ras: skblen = %u\n", skb->len); |
1690 | 1690 | ||
1691 | spin_lock_bh(&nf_h323_lock); | 1691 | spin_lock_bh(&nf_h323_lock); |
1692 | 1692 | ||
1693 | /* Get UDP data */ | 1693 | /* Get UDP data */ |
1694 | data = get_udp_data(pskb, protoff, &datalen); | 1694 | data = get_udp_data(skb, protoff, &datalen); |
1695 | if (data == NULL) | 1695 | if (data == NULL) |
1696 | goto accept; | 1696 | goto accept; |
1697 | pr_debug("nf_ct_ras: RAS message len=%d ", datalen); | 1697 | pr_debug("nf_ct_ras: RAS message len=%d ", datalen); |
@@ -1707,7 +1707,7 @@ static int ras_help(struct sk_buff **pskb, unsigned int protoff, | |||
1707 | } | 1707 | } |
1708 | 1708 | ||
1709 | /* Process RAS message */ | 1709 | /* Process RAS message */ |
1710 | if (process_ras(pskb, ct, ctinfo, &data, &ras) < 0) | 1710 | if (process_ras(skb, ct, ctinfo, &data, &ras) < 0) |
1711 | goto drop; | 1711 | goto drop; |
1712 | 1712 | ||
1713 | accept: | 1713 | accept: |
diff --git a/net/netfilter/nf_conntrack_irc.c b/net/netfilter/nf_conntrack_irc.c index 1562ca97a349..dfaed4ba83cd 100644 --- a/net/netfilter/nf_conntrack_irc.c +++ b/net/netfilter/nf_conntrack_irc.c | |||
@@ -30,7 +30,7 @@ static unsigned int dcc_timeout __read_mostly = 300; | |||
30 | static char *irc_buffer; | 30 | static char *irc_buffer; |
31 | static DEFINE_SPINLOCK(irc_buffer_lock); | 31 | static DEFINE_SPINLOCK(irc_buffer_lock); |
32 | 32 | ||
33 | unsigned int (*nf_nat_irc_hook)(struct sk_buff **pskb, | 33 | unsigned int (*nf_nat_irc_hook)(struct sk_buff *skb, |
34 | enum ip_conntrack_info ctinfo, | 34 | enum ip_conntrack_info ctinfo, |
35 | unsigned int matchoff, | 35 | unsigned int matchoff, |
36 | unsigned int matchlen, | 36 | unsigned int matchlen, |
@@ -89,7 +89,7 @@ static int parse_dcc(char *data, char *data_end, u_int32_t *ip, | |||
89 | return 0; | 89 | return 0; |
90 | } | 90 | } |
91 | 91 | ||
92 | static int help(struct sk_buff **pskb, unsigned int protoff, | 92 | static int help(struct sk_buff *skb, unsigned int protoff, |
93 | struct nf_conn *ct, enum ip_conntrack_info ctinfo) | 93 | struct nf_conn *ct, enum ip_conntrack_info ctinfo) |
94 | { | 94 | { |
95 | unsigned int dataoff; | 95 | unsigned int dataoff; |
@@ -116,22 +116,22 @@ static int help(struct sk_buff **pskb, unsigned int protoff, | |||
116 | return NF_ACCEPT; | 116 | return NF_ACCEPT; |
117 | 117 | ||
118 | /* Not a full tcp header? */ | 118 | /* Not a full tcp header? */ |
119 | th = skb_header_pointer(*pskb, protoff, sizeof(_tcph), &_tcph); | 119 | th = skb_header_pointer(skb, protoff, sizeof(_tcph), &_tcph); |
120 | if (th == NULL) | 120 | if (th == NULL) |
121 | return NF_ACCEPT; | 121 | return NF_ACCEPT; |
122 | 122 | ||
123 | /* No data? */ | 123 | /* No data? */ |
124 | dataoff = protoff + th->doff*4; | 124 | dataoff = protoff + th->doff*4; |
125 | if (dataoff >= (*pskb)->len) | 125 | if (dataoff >= skb->len) |
126 | return NF_ACCEPT; | 126 | return NF_ACCEPT; |
127 | 127 | ||
128 | spin_lock_bh(&irc_buffer_lock); | 128 | spin_lock_bh(&irc_buffer_lock); |
129 | ib_ptr = skb_header_pointer(*pskb, dataoff, (*pskb)->len - dataoff, | 129 | ib_ptr = skb_header_pointer(skb, dataoff, skb->len - dataoff, |
130 | irc_buffer); | 130 | irc_buffer); |
131 | BUG_ON(ib_ptr == NULL); | 131 | BUG_ON(ib_ptr == NULL); |
132 | 132 | ||
133 | data = ib_ptr; | 133 | data = ib_ptr; |
134 | data_limit = ib_ptr + (*pskb)->len - dataoff; | 134 | data_limit = ib_ptr + skb->len - dataoff; |
135 | 135 | ||
136 | /* strlen("\1DCC SENT t AAAAAAAA P\1\n")=24 | 136 | /* strlen("\1DCC SENT t AAAAAAAA P\1\n")=24 |
137 | * 5+MINMATCHLEN+strlen("t AAAAAAAA P\1\n")=14 */ | 137 | * 5+MINMATCHLEN+strlen("t AAAAAAAA P\1\n")=14 */ |
@@ -143,7 +143,7 @@ static int help(struct sk_buff **pskb, unsigned int protoff, | |||
143 | data += 5; | 143 | data += 5; |
144 | /* we have at least (19+MINMATCHLEN)-5 bytes valid data left */ | 144 | /* we have at least (19+MINMATCHLEN)-5 bytes valid data left */ |
145 | 145 | ||
146 | iph = ip_hdr(*pskb); | 146 | iph = ip_hdr(skb); |
147 | pr_debug("DCC found in master %u.%u.%u.%u:%u %u.%u.%u.%u:%u\n", | 147 | pr_debug("DCC found in master %u.%u.%u.%u:%u %u.%u.%u.%u:%u\n", |
148 | NIPQUAD(iph->saddr), ntohs(th->source), | 148 | NIPQUAD(iph->saddr), ntohs(th->source), |
149 | NIPQUAD(iph->daddr), ntohs(th->dest)); | 149 | NIPQUAD(iph->daddr), ntohs(th->dest)); |
@@ -193,7 +193,7 @@ static int help(struct sk_buff **pskb, unsigned int protoff, | |||
193 | 193 | ||
194 | nf_nat_irc = rcu_dereference(nf_nat_irc_hook); | 194 | nf_nat_irc = rcu_dereference(nf_nat_irc_hook); |
195 | if (nf_nat_irc && ct->status & IPS_NAT_MASK) | 195 | if (nf_nat_irc && ct->status & IPS_NAT_MASK) |
196 | ret = nf_nat_irc(pskb, ctinfo, | 196 | ret = nf_nat_irc(skb, ctinfo, |
197 | addr_beg_p - ib_ptr, | 197 | addr_beg_p - ib_ptr, |
198 | addr_end_p - addr_beg_p, | 198 | addr_end_p - addr_beg_p, |
199 | exp); | 199 | exp); |
diff --git a/net/netfilter/nf_conntrack_netbios_ns.c b/net/netfilter/nf_conntrack_netbios_ns.c index 1d59fabeb5f7..9810d81e2a06 100644 --- a/net/netfilter/nf_conntrack_netbios_ns.c +++ b/net/netfilter/nf_conntrack_netbios_ns.c | |||
@@ -42,17 +42,17 @@ static unsigned int timeout __read_mostly = 3; | |||
42 | module_param(timeout, uint, 0400); | 42 | module_param(timeout, uint, 0400); |
43 | MODULE_PARM_DESC(timeout, "timeout for master connection/replies in seconds"); | 43 | MODULE_PARM_DESC(timeout, "timeout for master connection/replies in seconds"); |
44 | 44 | ||
45 | static int help(struct sk_buff **pskb, unsigned int protoff, | 45 | static int help(struct sk_buff *skb, unsigned int protoff, |
46 | struct nf_conn *ct, enum ip_conntrack_info ctinfo) | 46 | struct nf_conn *ct, enum ip_conntrack_info ctinfo) |
47 | { | 47 | { |
48 | struct nf_conntrack_expect *exp; | 48 | struct nf_conntrack_expect *exp; |
49 | struct iphdr *iph = ip_hdr(*pskb); | 49 | struct iphdr *iph = ip_hdr(skb); |
50 | struct rtable *rt = (struct rtable *)(*pskb)->dst; | 50 | struct rtable *rt = (struct rtable *)skb->dst; |
51 | struct in_device *in_dev; | 51 | struct in_device *in_dev; |
52 | __be32 mask = 0; | 52 | __be32 mask = 0; |
53 | 53 | ||
54 | /* we're only interested in locally generated packets */ | 54 | /* we're only interested in locally generated packets */ |
55 | if ((*pskb)->sk == NULL) | 55 | if (skb->sk == NULL) |
56 | goto out; | 56 | goto out; |
57 | if (rt == NULL || !(rt->rt_flags & RTCF_BROADCAST)) | 57 | if (rt == NULL || !(rt->rt_flags & RTCF_BROADCAST)) |
58 | goto out; | 58 | goto out; |
@@ -91,7 +91,7 @@ static int help(struct sk_buff **pskb, unsigned int protoff, | |||
91 | nf_ct_expect_related(exp); | 91 | nf_ct_expect_related(exp); |
92 | nf_ct_expect_put(exp); | 92 | nf_ct_expect_put(exp); |
93 | 93 | ||
94 | nf_ct_refresh(ct, *pskb, timeout * HZ); | 94 | nf_ct_refresh(ct, skb, timeout * HZ); |
95 | out: | 95 | out: |
96 | return NF_ACCEPT; | 96 | return NF_ACCEPT; |
97 | } | 97 | } |
diff --git a/net/netfilter/nf_conntrack_pptp.c b/net/netfilter/nf_conntrack_pptp.c index b0804199ab59..099b6df3e2b5 100644 --- a/net/netfilter/nf_conntrack_pptp.c +++ b/net/netfilter/nf_conntrack_pptp.c | |||
@@ -41,14 +41,14 @@ MODULE_ALIAS("ip_conntrack_pptp"); | |||
41 | static DEFINE_SPINLOCK(nf_pptp_lock); | 41 | static DEFINE_SPINLOCK(nf_pptp_lock); |
42 | 42 | ||
43 | int | 43 | int |
44 | (*nf_nat_pptp_hook_outbound)(struct sk_buff **pskb, | 44 | (*nf_nat_pptp_hook_outbound)(struct sk_buff *skb, |
45 | struct nf_conn *ct, enum ip_conntrack_info ctinfo, | 45 | struct nf_conn *ct, enum ip_conntrack_info ctinfo, |
46 | struct PptpControlHeader *ctlh, | 46 | struct PptpControlHeader *ctlh, |
47 | union pptp_ctrl_union *pptpReq) __read_mostly; | 47 | union pptp_ctrl_union *pptpReq) __read_mostly; |
48 | EXPORT_SYMBOL_GPL(nf_nat_pptp_hook_outbound); | 48 | EXPORT_SYMBOL_GPL(nf_nat_pptp_hook_outbound); |
49 | 49 | ||
50 | int | 50 | int |
51 | (*nf_nat_pptp_hook_inbound)(struct sk_buff **pskb, | 51 | (*nf_nat_pptp_hook_inbound)(struct sk_buff *skb, |
52 | struct nf_conn *ct, enum ip_conntrack_info ctinfo, | 52 | struct nf_conn *ct, enum ip_conntrack_info ctinfo, |
53 | struct PptpControlHeader *ctlh, | 53 | struct PptpControlHeader *ctlh, |
54 | union pptp_ctrl_union *pptpReq) __read_mostly; | 54 | union pptp_ctrl_union *pptpReq) __read_mostly; |
@@ -254,7 +254,7 @@ out_unexpect_orig: | |||
254 | } | 254 | } |
255 | 255 | ||
256 | static inline int | 256 | static inline int |
257 | pptp_inbound_pkt(struct sk_buff **pskb, | 257 | pptp_inbound_pkt(struct sk_buff *skb, |
258 | struct PptpControlHeader *ctlh, | 258 | struct PptpControlHeader *ctlh, |
259 | union pptp_ctrl_union *pptpReq, | 259 | union pptp_ctrl_union *pptpReq, |
260 | unsigned int reqlen, | 260 | unsigned int reqlen, |
@@ -367,7 +367,7 @@ pptp_inbound_pkt(struct sk_buff **pskb, | |||
367 | 367 | ||
368 | nf_nat_pptp_inbound = rcu_dereference(nf_nat_pptp_hook_inbound); | 368 | nf_nat_pptp_inbound = rcu_dereference(nf_nat_pptp_hook_inbound); |
369 | if (nf_nat_pptp_inbound && ct->status & IPS_NAT_MASK) | 369 | if (nf_nat_pptp_inbound && ct->status & IPS_NAT_MASK) |
370 | return nf_nat_pptp_inbound(pskb, ct, ctinfo, ctlh, pptpReq); | 370 | return nf_nat_pptp_inbound(skb, ct, ctinfo, ctlh, pptpReq); |
371 | return NF_ACCEPT; | 371 | return NF_ACCEPT; |
372 | 372 | ||
373 | invalid: | 373 | invalid: |
@@ -380,7 +380,7 @@ invalid: | |||
380 | } | 380 | } |
381 | 381 | ||
382 | static inline int | 382 | static inline int |
383 | pptp_outbound_pkt(struct sk_buff **pskb, | 383 | pptp_outbound_pkt(struct sk_buff *skb, |
384 | struct PptpControlHeader *ctlh, | 384 | struct PptpControlHeader *ctlh, |
385 | union pptp_ctrl_union *pptpReq, | 385 | union pptp_ctrl_union *pptpReq, |
386 | unsigned int reqlen, | 386 | unsigned int reqlen, |
@@ -462,7 +462,7 @@ pptp_outbound_pkt(struct sk_buff **pskb, | |||
462 | 462 | ||
463 | nf_nat_pptp_outbound = rcu_dereference(nf_nat_pptp_hook_outbound); | 463 | nf_nat_pptp_outbound = rcu_dereference(nf_nat_pptp_hook_outbound); |
464 | if (nf_nat_pptp_outbound && ct->status & IPS_NAT_MASK) | 464 | if (nf_nat_pptp_outbound && ct->status & IPS_NAT_MASK) |
465 | return nf_nat_pptp_outbound(pskb, ct, ctinfo, ctlh, pptpReq); | 465 | return nf_nat_pptp_outbound(skb, ct, ctinfo, ctlh, pptpReq); |
466 | return NF_ACCEPT; | 466 | return NF_ACCEPT; |
467 | 467 | ||
468 | invalid: | 468 | invalid: |
@@ -492,7 +492,7 @@ static const unsigned int pptp_msg_size[] = { | |||
492 | 492 | ||
493 | /* track caller id inside control connection, call expect_related */ | 493 | /* track caller id inside control connection, call expect_related */ |
494 | static int | 494 | static int |
495 | conntrack_pptp_help(struct sk_buff **pskb, unsigned int protoff, | 495 | conntrack_pptp_help(struct sk_buff *skb, unsigned int protoff, |
496 | struct nf_conn *ct, enum ip_conntrack_info ctinfo) | 496 | struct nf_conn *ct, enum ip_conntrack_info ctinfo) |
497 | 497 | ||
498 | { | 498 | { |
@@ -502,7 +502,7 @@ conntrack_pptp_help(struct sk_buff **pskb, unsigned int protoff, | |||
502 | struct pptp_pkt_hdr _pptph, *pptph; | 502 | struct pptp_pkt_hdr _pptph, *pptph; |
503 | struct PptpControlHeader _ctlh, *ctlh; | 503 | struct PptpControlHeader _ctlh, *ctlh; |
504 | union pptp_ctrl_union _pptpReq, *pptpReq; | 504 | union pptp_ctrl_union _pptpReq, *pptpReq; |
505 | unsigned int tcplen = (*pskb)->len - protoff; | 505 | unsigned int tcplen = skb->len - protoff; |
506 | unsigned int datalen, reqlen, nexthdr_off; | 506 | unsigned int datalen, reqlen, nexthdr_off; |
507 | int oldsstate, oldcstate; | 507 | int oldsstate, oldcstate; |
508 | int ret; | 508 | int ret; |
@@ -514,12 +514,12 @@ conntrack_pptp_help(struct sk_buff **pskb, unsigned int protoff, | |||
514 | return NF_ACCEPT; | 514 | return NF_ACCEPT; |
515 | 515 | ||
516 | nexthdr_off = protoff; | 516 | nexthdr_off = protoff; |
517 | tcph = skb_header_pointer(*pskb, nexthdr_off, sizeof(_tcph), &_tcph); | 517 | tcph = skb_header_pointer(skb, nexthdr_off, sizeof(_tcph), &_tcph); |
518 | BUG_ON(!tcph); | 518 | BUG_ON(!tcph); |
519 | nexthdr_off += tcph->doff * 4; | 519 | nexthdr_off += tcph->doff * 4; |
520 | datalen = tcplen - tcph->doff * 4; | 520 | datalen = tcplen - tcph->doff * 4; |
521 | 521 | ||
522 | pptph = skb_header_pointer(*pskb, nexthdr_off, sizeof(_pptph), &_pptph); | 522 | pptph = skb_header_pointer(skb, nexthdr_off, sizeof(_pptph), &_pptph); |
523 | if (!pptph) { | 523 | if (!pptph) { |
524 | pr_debug("no full PPTP header, can't track\n"); | 524 | pr_debug("no full PPTP header, can't track\n"); |
525 | return NF_ACCEPT; | 525 | return NF_ACCEPT; |
@@ -534,7 +534,7 @@ conntrack_pptp_help(struct sk_buff **pskb, unsigned int protoff, | |||
534 | return NF_ACCEPT; | 534 | return NF_ACCEPT; |
535 | } | 535 | } |
536 | 536 | ||
537 | ctlh = skb_header_pointer(*pskb, nexthdr_off, sizeof(_ctlh), &_ctlh); | 537 | ctlh = skb_header_pointer(skb, nexthdr_off, sizeof(_ctlh), &_ctlh); |
538 | if (!ctlh) | 538 | if (!ctlh) |
539 | return NF_ACCEPT; | 539 | return NF_ACCEPT; |
540 | nexthdr_off += sizeof(_ctlh); | 540 | nexthdr_off += sizeof(_ctlh); |
@@ -547,7 +547,7 @@ conntrack_pptp_help(struct sk_buff **pskb, unsigned int protoff, | |||
547 | if (reqlen > sizeof(*pptpReq)) | 547 | if (reqlen > sizeof(*pptpReq)) |
548 | reqlen = sizeof(*pptpReq); | 548 | reqlen = sizeof(*pptpReq); |
549 | 549 | ||
550 | pptpReq = skb_header_pointer(*pskb, nexthdr_off, reqlen, &_pptpReq); | 550 | pptpReq = skb_header_pointer(skb, nexthdr_off, reqlen, &_pptpReq); |
551 | if (!pptpReq) | 551 | if (!pptpReq) |
552 | return NF_ACCEPT; | 552 | return NF_ACCEPT; |
553 | 553 | ||
@@ -560,11 +560,11 @@ conntrack_pptp_help(struct sk_buff **pskb, unsigned int protoff, | |||
560 | * established from PNS->PAC. However, RFC makes no guarantee */ | 560 | * established from PNS->PAC. However, RFC makes no guarantee */ |
561 | if (dir == IP_CT_DIR_ORIGINAL) | 561 | if (dir == IP_CT_DIR_ORIGINAL) |
562 | /* client -> server (PNS -> PAC) */ | 562 | /* client -> server (PNS -> PAC) */ |
563 | ret = pptp_outbound_pkt(pskb, ctlh, pptpReq, reqlen, ct, | 563 | ret = pptp_outbound_pkt(skb, ctlh, pptpReq, reqlen, ct, |
564 | ctinfo); | 564 | ctinfo); |
565 | else | 565 | else |
566 | /* server -> client (PAC -> PNS) */ | 566 | /* server -> client (PAC -> PNS) */ |
567 | ret = pptp_inbound_pkt(pskb, ctlh, pptpReq, reqlen, ct, | 567 | ret = pptp_inbound_pkt(skb, ctlh, pptpReq, reqlen, ct, |
568 | ctinfo); | 568 | ctinfo); |
569 | pr_debug("sstate: %d->%d, cstate: %d->%d\n", | 569 | pr_debug("sstate: %d->%d, cstate: %d->%d\n", |
570 | oldsstate, info->sstate, oldcstate, info->cstate); | 570 | oldsstate, info->sstate, oldcstate, info->cstate); |
diff --git a/net/netfilter/nf_conntrack_proto_generic.c b/net/netfilter/nf_conntrack_proto_generic.c index d8b501878d9f..13f819179642 100644 --- a/net/netfilter/nf_conntrack_proto_generic.c +++ b/net/netfilter/nf_conntrack_proto_generic.c | |||
@@ -70,7 +70,6 @@ static int new(struct nf_conn *conntrack, const struct sk_buff *skb, | |||
70 | static struct ctl_table_header *generic_sysctl_header; | 70 | static struct ctl_table_header *generic_sysctl_header; |
71 | static struct ctl_table generic_sysctl_table[] = { | 71 | static struct ctl_table generic_sysctl_table[] = { |
72 | { | 72 | { |
73 | .ctl_name = NET_NF_CONNTRACK_GENERIC_TIMEOUT, | ||
74 | .procname = "nf_conntrack_generic_timeout", | 73 | .procname = "nf_conntrack_generic_timeout", |
75 | .data = &nf_ct_generic_timeout, | 74 | .data = &nf_ct_generic_timeout, |
76 | .maxlen = sizeof(unsigned int), | 75 | .maxlen = sizeof(unsigned int), |
@@ -84,7 +83,6 @@ static struct ctl_table generic_sysctl_table[] = { | |||
84 | #ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT | 83 | #ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT |
85 | static struct ctl_table generic_compat_sysctl_table[] = { | 84 | static struct ctl_table generic_compat_sysctl_table[] = { |
86 | { | 85 | { |
87 | .ctl_name = NET_IPV4_NF_CONNTRACK_GENERIC_TIMEOUT, | ||
88 | .procname = "ip_conntrack_generic_timeout", | 86 | .procname = "ip_conntrack_generic_timeout", |
89 | .data = &nf_ct_generic_timeout, | 87 | .data = &nf_ct_generic_timeout, |
90 | .maxlen = sizeof(unsigned int), | 88 | .maxlen = sizeof(unsigned int), |
diff --git a/net/netfilter/nf_conntrack_proto_sctp.c b/net/netfilter/nf_conntrack_proto_sctp.c index 04192acc7c40..cb0467510592 100644 --- a/net/netfilter/nf_conntrack_proto_sctp.c +++ b/net/netfilter/nf_conntrack_proto_sctp.c | |||
@@ -476,7 +476,6 @@ static unsigned int sctp_sysctl_table_users; | |||
476 | static struct ctl_table_header *sctp_sysctl_header; | 476 | static struct ctl_table_header *sctp_sysctl_header; |
477 | static struct ctl_table sctp_sysctl_table[] = { | 477 | static struct ctl_table sctp_sysctl_table[] = { |
478 | { | 478 | { |
479 | .ctl_name = NET_NF_CONNTRACK_SCTP_TIMEOUT_CLOSED, | ||
480 | .procname = "nf_conntrack_sctp_timeout_closed", | 479 | .procname = "nf_conntrack_sctp_timeout_closed", |
481 | .data = &nf_ct_sctp_timeout_closed, | 480 | .data = &nf_ct_sctp_timeout_closed, |
482 | .maxlen = sizeof(unsigned int), | 481 | .maxlen = sizeof(unsigned int), |
@@ -484,7 +483,6 @@ static struct ctl_table sctp_sysctl_table[] = { | |||
484 | .proc_handler = &proc_dointvec_jiffies, | 483 | .proc_handler = &proc_dointvec_jiffies, |
485 | }, | 484 | }, |
486 | { | 485 | { |
487 | .ctl_name = NET_NF_CONNTRACK_SCTP_TIMEOUT_COOKIE_WAIT, | ||
488 | .procname = "nf_conntrack_sctp_timeout_cookie_wait", | 486 | .procname = "nf_conntrack_sctp_timeout_cookie_wait", |
489 | .data = &nf_ct_sctp_timeout_cookie_wait, | 487 | .data = &nf_ct_sctp_timeout_cookie_wait, |
490 | .maxlen = sizeof(unsigned int), | 488 | .maxlen = sizeof(unsigned int), |
@@ -492,7 +490,6 @@ static struct ctl_table sctp_sysctl_table[] = { | |||
492 | .proc_handler = &proc_dointvec_jiffies, | 490 | .proc_handler = &proc_dointvec_jiffies, |
493 | }, | 491 | }, |
494 | { | 492 | { |
495 | .ctl_name = NET_NF_CONNTRACK_SCTP_TIMEOUT_COOKIE_ECHOED, | ||
496 | .procname = "nf_conntrack_sctp_timeout_cookie_echoed", | 493 | .procname = "nf_conntrack_sctp_timeout_cookie_echoed", |
497 | .data = &nf_ct_sctp_timeout_cookie_echoed, | 494 | .data = &nf_ct_sctp_timeout_cookie_echoed, |
498 | .maxlen = sizeof(unsigned int), | 495 | .maxlen = sizeof(unsigned int), |
@@ -500,7 +497,6 @@ static struct ctl_table sctp_sysctl_table[] = { | |||
500 | .proc_handler = &proc_dointvec_jiffies, | 497 | .proc_handler = &proc_dointvec_jiffies, |
501 | }, | 498 | }, |
502 | { | 499 | { |
503 | .ctl_name = NET_NF_CONNTRACK_SCTP_TIMEOUT_ESTABLISHED, | ||
504 | .procname = "nf_conntrack_sctp_timeout_established", | 500 | .procname = "nf_conntrack_sctp_timeout_established", |
505 | .data = &nf_ct_sctp_timeout_established, | 501 | .data = &nf_ct_sctp_timeout_established, |
506 | .maxlen = sizeof(unsigned int), | 502 | .maxlen = sizeof(unsigned int), |
@@ -508,7 +504,6 @@ static struct ctl_table sctp_sysctl_table[] = { | |||
508 | .proc_handler = &proc_dointvec_jiffies, | 504 | .proc_handler = &proc_dointvec_jiffies, |
509 | }, | 505 | }, |
510 | { | 506 | { |
511 | .ctl_name = NET_NF_CONNTRACK_SCTP_TIMEOUT_SHUTDOWN_SENT, | ||
512 | .procname = "nf_conntrack_sctp_timeout_shutdown_sent", | 507 | .procname = "nf_conntrack_sctp_timeout_shutdown_sent", |
513 | .data = &nf_ct_sctp_timeout_shutdown_sent, | 508 | .data = &nf_ct_sctp_timeout_shutdown_sent, |
514 | .maxlen = sizeof(unsigned int), | 509 | .maxlen = sizeof(unsigned int), |
@@ -516,7 +511,6 @@ static struct ctl_table sctp_sysctl_table[] = { | |||
516 | .proc_handler = &proc_dointvec_jiffies, | 511 | .proc_handler = &proc_dointvec_jiffies, |
517 | }, | 512 | }, |
518 | { | 513 | { |
519 | .ctl_name = NET_NF_CONNTRACK_SCTP_TIMEOUT_SHUTDOWN_RECD, | ||
520 | .procname = "nf_conntrack_sctp_timeout_shutdown_recd", | 514 | .procname = "nf_conntrack_sctp_timeout_shutdown_recd", |
521 | .data = &nf_ct_sctp_timeout_shutdown_recd, | 515 | .data = &nf_ct_sctp_timeout_shutdown_recd, |
522 | .maxlen = sizeof(unsigned int), | 516 | .maxlen = sizeof(unsigned int), |
@@ -524,7 +518,6 @@ static struct ctl_table sctp_sysctl_table[] = { | |||
524 | .proc_handler = &proc_dointvec_jiffies, | 518 | .proc_handler = &proc_dointvec_jiffies, |
525 | }, | 519 | }, |
526 | { | 520 | { |
527 | .ctl_name = NET_NF_CONNTRACK_SCTP_TIMEOUT_SHUTDOWN_ACK_SENT, | ||
528 | .procname = "nf_conntrack_sctp_timeout_shutdown_ack_sent", | 521 | .procname = "nf_conntrack_sctp_timeout_shutdown_ack_sent", |
529 | .data = &nf_ct_sctp_timeout_shutdown_ack_sent, | 522 | .data = &nf_ct_sctp_timeout_shutdown_ack_sent, |
530 | .maxlen = sizeof(unsigned int), | 523 | .maxlen = sizeof(unsigned int), |
@@ -539,7 +532,6 @@ static struct ctl_table sctp_sysctl_table[] = { | |||
539 | #ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT | 532 | #ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT |
540 | static struct ctl_table sctp_compat_sysctl_table[] = { | 533 | static struct ctl_table sctp_compat_sysctl_table[] = { |
541 | { | 534 | { |
542 | .ctl_name = NET_IPV4_NF_CONNTRACK_SCTP_TIMEOUT_CLOSED, | ||
543 | .procname = "ip_conntrack_sctp_timeout_closed", | 535 | .procname = "ip_conntrack_sctp_timeout_closed", |
544 | .data = &nf_ct_sctp_timeout_closed, | 536 | .data = &nf_ct_sctp_timeout_closed, |
545 | .maxlen = sizeof(unsigned int), | 537 | .maxlen = sizeof(unsigned int), |
@@ -547,7 +539,6 @@ static struct ctl_table sctp_compat_sysctl_table[] = { | |||
547 | .proc_handler = &proc_dointvec_jiffies, | 539 | .proc_handler = &proc_dointvec_jiffies, |
548 | }, | 540 | }, |
549 | { | 541 | { |
550 | .ctl_name = NET_IPV4_NF_CONNTRACK_SCTP_TIMEOUT_COOKIE_WAIT, | ||
551 | .procname = "ip_conntrack_sctp_timeout_cookie_wait", | 542 | .procname = "ip_conntrack_sctp_timeout_cookie_wait", |
552 | .data = &nf_ct_sctp_timeout_cookie_wait, | 543 | .data = &nf_ct_sctp_timeout_cookie_wait, |
553 | .maxlen = sizeof(unsigned int), | 544 | .maxlen = sizeof(unsigned int), |
@@ -555,7 +546,6 @@ static struct ctl_table sctp_compat_sysctl_table[] = { | |||
555 | .proc_handler = &proc_dointvec_jiffies, | 546 | .proc_handler = &proc_dointvec_jiffies, |
556 | }, | 547 | }, |
557 | { | 548 | { |
558 | .ctl_name = NET_IPV4_NF_CONNTRACK_SCTP_TIMEOUT_COOKIE_ECHOED, | ||
559 | .procname = "ip_conntrack_sctp_timeout_cookie_echoed", | 549 | .procname = "ip_conntrack_sctp_timeout_cookie_echoed", |
560 | .data = &nf_ct_sctp_timeout_cookie_echoed, | 550 | .data = &nf_ct_sctp_timeout_cookie_echoed, |
561 | .maxlen = sizeof(unsigned int), | 551 | .maxlen = sizeof(unsigned int), |
@@ -563,7 +553,6 @@ static struct ctl_table sctp_compat_sysctl_table[] = { | |||
563 | .proc_handler = &proc_dointvec_jiffies, | 553 | .proc_handler = &proc_dointvec_jiffies, |
564 | }, | 554 | }, |
565 | { | 555 | { |
566 | .ctl_name = NET_IPV4_NF_CONNTRACK_SCTP_TIMEOUT_ESTABLISHED, | ||
567 | .procname = "ip_conntrack_sctp_timeout_established", | 556 | .procname = "ip_conntrack_sctp_timeout_established", |
568 | .data = &nf_ct_sctp_timeout_established, | 557 | .data = &nf_ct_sctp_timeout_established, |
569 | .maxlen = sizeof(unsigned int), | 558 | .maxlen = sizeof(unsigned int), |
@@ -571,7 +560,6 @@ static struct ctl_table sctp_compat_sysctl_table[] = { | |||
571 | .proc_handler = &proc_dointvec_jiffies, | 560 | .proc_handler = &proc_dointvec_jiffies, |
572 | }, | 561 | }, |
573 | { | 562 | { |
574 | .ctl_name = NET_IPV4_NF_CONNTRACK_SCTP_TIMEOUT_SHUTDOWN_SENT, | ||
575 | .procname = "ip_conntrack_sctp_timeout_shutdown_sent", | 563 | .procname = "ip_conntrack_sctp_timeout_shutdown_sent", |
576 | .data = &nf_ct_sctp_timeout_shutdown_sent, | 564 | .data = &nf_ct_sctp_timeout_shutdown_sent, |
577 | .maxlen = sizeof(unsigned int), | 565 | .maxlen = sizeof(unsigned int), |
@@ -579,7 +567,6 @@ static struct ctl_table sctp_compat_sysctl_table[] = { | |||
579 | .proc_handler = &proc_dointvec_jiffies, | 567 | .proc_handler = &proc_dointvec_jiffies, |
580 | }, | 568 | }, |
581 | { | 569 | { |
582 | .ctl_name = NET_IPV4_NF_CONNTRACK_SCTP_TIMEOUT_SHUTDOWN_RECD, | ||
583 | .procname = "ip_conntrack_sctp_timeout_shutdown_recd", | 570 | .procname = "ip_conntrack_sctp_timeout_shutdown_recd", |
584 | .data = &nf_ct_sctp_timeout_shutdown_recd, | 571 | .data = &nf_ct_sctp_timeout_shutdown_recd, |
585 | .maxlen = sizeof(unsigned int), | 572 | .maxlen = sizeof(unsigned int), |
@@ -587,7 +574,6 @@ static struct ctl_table sctp_compat_sysctl_table[] = { | |||
587 | .proc_handler = &proc_dointvec_jiffies, | 574 | .proc_handler = &proc_dointvec_jiffies, |
588 | }, | 575 | }, |
589 | { | 576 | { |
590 | .ctl_name = NET_IPV4_NF_CONNTRACK_SCTP_TIMEOUT_SHUTDOWN_ACK_SENT, | ||
591 | .procname = "ip_conntrack_sctp_timeout_shutdown_ack_sent", | 577 | .procname = "ip_conntrack_sctp_timeout_shutdown_ack_sent", |
592 | .data = &nf_ct_sctp_timeout_shutdown_ack_sent, | 578 | .data = &nf_ct_sctp_timeout_shutdown_ack_sent, |
593 | .maxlen = sizeof(unsigned int), | 579 | .maxlen = sizeof(unsigned int), |
diff --git a/net/netfilter/nf_conntrack_proto_tcp.c b/net/netfilter/nf_conntrack_proto_tcp.c index c7075345971b..7a3f64c1aca6 100644 --- a/net/netfilter/nf_conntrack_proto_tcp.c +++ b/net/netfilter/nf_conntrack_proto_tcp.c | |||
@@ -834,10 +834,12 @@ static int tcp_packet(struct nf_conn *conntrack, | |||
834 | case TCP_CONNTRACK_SYN_SENT: | 834 | case TCP_CONNTRACK_SYN_SENT: |
835 | if (old_state < TCP_CONNTRACK_TIME_WAIT) | 835 | if (old_state < TCP_CONNTRACK_TIME_WAIT) |
836 | break; | 836 | break; |
837 | if (conntrack->proto.tcp.seen[!dir].flags & | 837 | if ((conntrack->proto.tcp.seen[!dir].flags & |
838 | IP_CT_TCP_FLAG_CLOSE_INIT) { | 838 | IP_CT_TCP_FLAG_CLOSE_INIT) |
839 | /* Attempt to reopen a closed connection. | 839 | || (conntrack->proto.tcp.last_dir == dir |
840 | * Delete this connection and look up again. */ | 840 | && conntrack->proto.tcp.last_index == TCP_RST_SET)) { |
841 | /* Attempt to reopen a closed/aborted connection. | ||
842 | * Delete this connection and look up again. */ | ||
841 | write_unlock_bh(&tcp_lock); | 843 | write_unlock_bh(&tcp_lock); |
842 | if (del_timer(&conntrack->timeout)) | 844 | if (del_timer(&conntrack->timeout)) |
843 | conntrack->timeout.function((unsigned long) | 845 | conntrack->timeout.function((unsigned long) |
@@ -925,6 +927,7 @@ static int tcp_packet(struct nf_conn *conntrack, | |||
925 | in_window: | 927 | in_window: |
926 | /* From now on we have got in-window packets */ | 928 | /* From now on we have got in-window packets */ |
927 | conntrack->proto.tcp.last_index = index; | 929 | conntrack->proto.tcp.last_index = index; |
930 | conntrack->proto.tcp.last_dir = dir; | ||
928 | 931 | ||
929 | pr_debug("tcp_conntracks: "); | 932 | pr_debug("tcp_conntracks: "); |
930 | NF_CT_DUMP_TUPLE(tuple); | 933 | NF_CT_DUMP_TUPLE(tuple); |
@@ -1162,7 +1165,6 @@ static unsigned int tcp_sysctl_table_users; | |||
1162 | static struct ctl_table_header *tcp_sysctl_header; | 1165 | static struct ctl_table_header *tcp_sysctl_header; |
1163 | static struct ctl_table tcp_sysctl_table[] = { | 1166 | static struct ctl_table tcp_sysctl_table[] = { |
1164 | { | 1167 | { |
1165 | .ctl_name = NET_NF_CONNTRACK_TCP_TIMEOUT_SYN_SENT, | ||
1166 | .procname = "nf_conntrack_tcp_timeout_syn_sent", | 1168 | .procname = "nf_conntrack_tcp_timeout_syn_sent", |
1167 | .data = &nf_ct_tcp_timeout_syn_sent, | 1169 | .data = &nf_ct_tcp_timeout_syn_sent, |
1168 | .maxlen = sizeof(unsigned int), | 1170 | .maxlen = sizeof(unsigned int), |
@@ -1170,7 +1172,6 @@ static struct ctl_table tcp_sysctl_table[] = { | |||
1170 | .proc_handler = &proc_dointvec_jiffies, | 1172 | .proc_handler = &proc_dointvec_jiffies, |
1171 | }, | 1173 | }, |
1172 | { | 1174 | { |
1173 | .ctl_name = NET_NF_CONNTRACK_TCP_TIMEOUT_SYN_RECV, | ||
1174 | .procname = "nf_conntrack_tcp_timeout_syn_recv", | 1175 | .procname = "nf_conntrack_tcp_timeout_syn_recv", |
1175 | .data = &nf_ct_tcp_timeout_syn_recv, | 1176 | .data = &nf_ct_tcp_timeout_syn_recv, |
1176 | .maxlen = sizeof(unsigned int), | 1177 | .maxlen = sizeof(unsigned int), |
@@ -1178,7 +1179,6 @@ static struct ctl_table tcp_sysctl_table[] = { | |||
1178 | .proc_handler = &proc_dointvec_jiffies, | 1179 | .proc_handler = &proc_dointvec_jiffies, |
1179 | }, | 1180 | }, |
1180 | { | 1181 | { |
1181 | .ctl_name = NET_NF_CONNTRACK_TCP_TIMEOUT_ESTABLISHED, | ||
1182 | .procname = "nf_conntrack_tcp_timeout_established", | 1182 | .procname = "nf_conntrack_tcp_timeout_established", |
1183 | .data = &nf_ct_tcp_timeout_established, | 1183 | .data = &nf_ct_tcp_timeout_established, |
1184 | .maxlen = sizeof(unsigned int), | 1184 | .maxlen = sizeof(unsigned int), |
@@ -1186,7 +1186,6 @@ static struct ctl_table tcp_sysctl_table[] = { | |||
1186 | .proc_handler = &proc_dointvec_jiffies, | 1186 | .proc_handler = &proc_dointvec_jiffies, |
1187 | }, | 1187 | }, |
1188 | { | 1188 | { |
1189 | .ctl_name = NET_NF_CONNTRACK_TCP_TIMEOUT_FIN_WAIT, | ||
1190 | .procname = "nf_conntrack_tcp_timeout_fin_wait", | 1189 | .procname = "nf_conntrack_tcp_timeout_fin_wait", |
1191 | .data = &nf_ct_tcp_timeout_fin_wait, | 1190 | .data = &nf_ct_tcp_timeout_fin_wait, |
1192 | .maxlen = sizeof(unsigned int), | 1191 | .maxlen = sizeof(unsigned int), |
@@ -1194,7 +1193,6 @@ static struct ctl_table tcp_sysctl_table[] = { | |||
1194 | .proc_handler = &proc_dointvec_jiffies, | 1193 | .proc_handler = &proc_dointvec_jiffies, |
1195 | }, | 1194 | }, |
1196 | { | 1195 | { |
1197 | .ctl_name = NET_NF_CONNTRACK_TCP_TIMEOUT_CLOSE_WAIT, | ||
1198 | .procname = "nf_conntrack_tcp_timeout_close_wait", | 1196 | .procname = "nf_conntrack_tcp_timeout_close_wait", |
1199 | .data = &nf_ct_tcp_timeout_close_wait, | 1197 | .data = &nf_ct_tcp_timeout_close_wait, |
1200 | .maxlen = sizeof(unsigned int), | 1198 | .maxlen = sizeof(unsigned int), |
@@ -1202,7 +1200,6 @@ static struct ctl_table tcp_sysctl_table[] = { | |||
1202 | .proc_handler = &proc_dointvec_jiffies, | 1200 | .proc_handler = &proc_dointvec_jiffies, |
1203 | }, | 1201 | }, |
1204 | { | 1202 | { |
1205 | .ctl_name = NET_NF_CONNTRACK_TCP_TIMEOUT_LAST_ACK, | ||
1206 | .procname = "nf_conntrack_tcp_timeout_last_ack", | 1203 | .procname = "nf_conntrack_tcp_timeout_last_ack", |
1207 | .data = &nf_ct_tcp_timeout_last_ack, | 1204 | .data = &nf_ct_tcp_timeout_last_ack, |
1208 | .maxlen = sizeof(unsigned int), | 1205 | .maxlen = sizeof(unsigned int), |
@@ -1210,7 +1207,6 @@ static struct ctl_table tcp_sysctl_table[] = { | |||
1210 | .proc_handler = &proc_dointvec_jiffies, | 1207 | .proc_handler = &proc_dointvec_jiffies, |
1211 | }, | 1208 | }, |
1212 | { | 1209 | { |
1213 | .ctl_name = NET_NF_CONNTRACK_TCP_TIMEOUT_TIME_WAIT, | ||
1214 | .procname = "nf_conntrack_tcp_timeout_time_wait", | 1210 | .procname = "nf_conntrack_tcp_timeout_time_wait", |
1215 | .data = &nf_ct_tcp_timeout_time_wait, | 1211 | .data = &nf_ct_tcp_timeout_time_wait, |
1216 | .maxlen = sizeof(unsigned int), | 1212 | .maxlen = sizeof(unsigned int), |
@@ -1218,7 +1214,6 @@ static struct ctl_table tcp_sysctl_table[] = { | |||
1218 | .proc_handler = &proc_dointvec_jiffies, | 1214 | .proc_handler = &proc_dointvec_jiffies, |
1219 | }, | 1215 | }, |
1220 | { | 1216 | { |
1221 | .ctl_name = NET_NF_CONNTRACK_TCP_TIMEOUT_CLOSE, | ||
1222 | .procname = "nf_conntrack_tcp_timeout_close", | 1217 | .procname = "nf_conntrack_tcp_timeout_close", |
1223 | .data = &nf_ct_tcp_timeout_close, | 1218 | .data = &nf_ct_tcp_timeout_close, |
1224 | .maxlen = sizeof(unsigned int), | 1219 | .maxlen = sizeof(unsigned int), |
@@ -1226,7 +1221,6 @@ static struct ctl_table tcp_sysctl_table[] = { | |||
1226 | .proc_handler = &proc_dointvec_jiffies, | 1221 | .proc_handler = &proc_dointvec_jiffies, |
1227 | }, | 1222 | }, |
1228 | { | 1223 | { |
1229 | .ctl_name = NET_NF_CONNTRACK_TCP_TIMEOUT_MAX_RETRANS, | ||
1230 | .procname = "nf_conntrack_tcp_timeout_max_retrans", | 1224 | .procname = "nf_conntrack_tcp_timeout_max_retrans", |
1231 | .data = &nf_ct_tcp_timeout_max_retrans, | 1225 | .data = &nf_ct_tcp_timeout_max_retrans, |
1232 | .maxlen = sizeof(unsigned int), | 1226 | .maxlen = sizeof(unsigned int), |
@@ -1265,7 +1259,6 @@ static struct ctl_table tcp_sysctl_table[] = { | |||
1265 | #ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT | 1259 | #ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT |
1266 | static struct ctl_table tcp_compat_sysctl_table[] = { | 1260 | static struct ctl_table tcp_compat_sysctl_table[] = { |
1267 | { | 1261 | { |
1268 | .ctl_name = NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_SYN_SENT, | ||
1269 | .procname = "ip_conntrack_tcp_timeout_syn_sent", | 1262 | .procname = "ip_conntrack_tcp_timeout_syn_sent", |
1270 | .data = &nf_ct_tcp_timeout_syn_sent, | 1263 | .data = &nf_ct_tcp_timeout_syn_sent, |
1271 | .maxlen = sizeof(unsigned int), | 1264 | .maxlen = sizeof(unsigned int), |
@@ -1273,7 +1266,6 @@ static struct ctl_table tcp_compat_sysctl_table[] = { | |||
1273 | .proc_handler = &proc_dointvec_jiffies, | 1266 | .proc_handler = &proc_dointvec_jiffies, |
1274 | }, | 1267 | }, |
1275 | { | 1268 | { |
1276 | .ctl_name = NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_SYN_RECV, | ||
1277 | .procname = "ip_conntrack_tcp_timeout_syn_recv", | 1269 | .procname = "ip_conntrack_tcp_timeout_syn_recv", |
1278 | .data = &nf_ct_tcp_timeout_syn_recv, | 1270 | .data = &nf_ct_tcp_timeout_syn_recv, |
1279 | .maxlen = sizeof(unsigned int), | 1271 | .maxlen = sizeof(unsigned int), |
@@ -1281,7 +1273,6 @@ static struct ctl_table tcp_compat_sysctl_table[] = { | |||
1281 | .proc_handler = &proc_dointvec_jiffies, | 1273 | .proc_handler = &proc_dointvec_jiffies, |
1282 | }, | 1274 | }, |
1283 | { | 1275 | { |
1284 | .ctl_name = NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_ESTABLISHED, | ||
1285 | .procname = "ip_conntrack_tcp_timeout_established", | 1276 | .procname = "ip_conntrack_tcp_timeout_established", |
1286 | .data = &nf_ct_tcp_timeout_established, | 1277 | .data = &nf_ct_tcp_timeout_established, |
1287 | .maxlen = sizeof(unsigned int), | 1278 | .maxlen = sizeof(unsigned int), |
@@ -1289,7 +1280,6 @@ static struct ctl_table tcp_compat_sysctl_table[] = { | |||
1289 | .proc_handler = &proc_dointvec_jiffies, | 1280 | .proc_handler = &proc_dointvec_jiffies, |
1290 | }, | 1281 | }, |
1291 | { | 1282 | { |
1292 | .ctl_name = NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_FIN_WAIT, | ||
1293 | .procname = "ip_conntrack_tcp_timeout_fin_wait", | 1283 | .procname = "ip_conntrack_tcp_timeout_fin_wait", |
1294 | .data = &nf_ct_tcp_timeout_fin_wait, | 1284 | .data = &nf_ct_tcp_timeout_fin_wait, |
1295 | .maxlen = sizeof(unsigned int), | 1285 | .maxlen = sizeof(unsigned int), |
@@ -1297,7 +1287,6 @@ static struct ctl_table tcp_compat_sysctl_table[] = { | |||
1297 | .proc_handler = &proc_dointvec_jiffies, | 1287 | .proc_handler = &proc_dointvec_jiffies, |
1298 | }, | 1288 | }, |
1299 | { | 1289 | { |
1300 | .ctl_name = NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_CLOSE_WAIT, | ||
1301 | .procname = "ip_conntrack_tcp_timeout_close_wait", | 1290 | .procname = "ip_conntrack_tcp_timeout_close_wait", |
1302 | .data = &nf_ct_tcp_timeout_close_wait, | 1291 | .data = &nf_ct_tcp_timeout_close_wait, |
1303 | .maxlen = sizeof(unsigned int), | 1292 | .maxlen = sizeof(unsigned int), |
@@ -1305,7 +1294,6 @@ static struct ctl_table tcp_compat_sysctl_table[] = { | |||
1305 | .proc_handler = &proc_dointvec_jiffies, | 1294 | .proc_handler = &proc_dointvec_jiffies, |
1306 | }, | 1295 | }, |
1307 | { | 1296 | { |
1308 | .ctl_name = NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_LAST_ACK, | ||
1309 | .procname = "ip_conntrack_tcp_timeout_last_ack", | 1297 | .procname = "ip_conntrack_tcp_timeout_last_ack", |
1310 | .data = &nf_ct_tcp_timeout_last_ack, | 1298 | .data = &nf_ct_tcp_timeout_last_ack, |
1311 | .maxlen = sizeof(unsigned int), | 1299 | .maxlen = sizeof(unsigned int), |
@@ -1313,7 +1301,6 @@ static struct ctl_table tcp_compat_sysctl_table[] = { | |||
1313 | .proc_handler = &proc_dointvec_jiffies, | 1301 | .proc_handler = &proc_dointvec_jiffies, |
1314 | }, | 1302 | }, |
1315 | { | 1303 | { |
1316 | .ctl_name = NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_TIME_WAIT, | ||
1317 | .procname = "ip_conntrack_tcp_timeout_time_wait", | 1304 | .procname = "ip_conntrack_tcp_timeout_time_wait", |
1318 | .data = &nf_ct_tcp_timeout_time_wait, | 1305 | .data = &nf_ct_tcp_timeout_time_wait, |
1319 | .maxlen = sizeof(unsigned int), | 1306 | .maxlen = sizeof(unsigned int), |
@@ -1321,7 +1308,6 @@ static struct ctl_table tcp_compat_sysctl_table[] = { | |||
1321 | .proc_handler = &proc_dointvec_jiffies, | 1308 | .proc_handler = &proc_dointvec_jiffies, |
1322 | }, | 1309 | }, |
1323 | { | 1310 | { |
1324 | .ctl_name = NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_CLOSE, | ||
1325 | .procname = "ip_conntrack_tcp_timeout_close", | 1311 | .procname = "ip_conntrack_tcp_timeout_close", |
1326 | .data = &nf_ct_tcp_timeout_close, | 1312 | .data = &nf_ct_tcp_timeout_close, |
1327 | .maxlen = sizeof(unsigned int), | 1313 | .maxlen = sizeof(unsigned int), |
@@ -1329,7 +1315,6 @@ static struct ctl_table tcp_compat_sysctl_table[] = { | |||
1329 | .proc_handler = &proc_dointvec_jiffies, | 1315 | .proc_handler = &proc_dointvec_jiffies, |
1330 | }, | 1316 | }, |
1331 | { | 1317 | { |
1332 | .ctl_name = NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_MAX_RETRANS, | ||
1333 | .procname = "ip_conntrack_tcp_timeout_max_retrans", | 1318 | .procname = "ip_conntrack_tcp_timeout_max_retrans", |
1334 | .data = &nf_ct_tcp_timeout_max_retrans, | 1319 | .data = &nf_ct_tcp_timeout_max_retrans, |
1335 | .maxlen = sizeof(unsigned int), | 1320 | .maxlen = sizeof(unsigned int), |
diff --git a/net/netfilter/nf_conntrack_proto_udp.c b/net/netfilter/nf_conntrack_proto_udp.c index ba80e1a1ea17..b3e7ecb080e6 100644 --- a/net/netfilter/nf_conntrack_proto_udp.c +++ b/net/netfilter/nf_conntrack_proto_udp.c | |||
@@ -146,7 +146,6 @@ static unsigned int udp_sysctl_table_users; | |||
146 | static struct ctl_table_header *udp_sysctl_header; | 146 | static struct ctl_table_header *udp_sysctl_header; |
147 | static struct ctl_table udp_sysctl_table[] = { | 147 | static struct ctl_table udp_sysctl_table[] = { |
148 | { | 148 | { |
149 | .ctl_name = NET_NF_CONNTRACK_UDP_TIMEOUT, | ||
150 | .procname = "nf_conntrack_udp_timeout", | 149 | .procname = "nf_conntrack_udp_timeout", |
151 | .data = &nf_ct_udp_timeout, | 150 | .data = &nf_ct_udp_timeout, |
152 | .maxlen = sizeof(unsigned int), | 151 | .maxlen = sizeof(unsigned int), |
@@ -154,7 +153,6 @@ static struct ctl_table udp_sysctl_table[] = { | |||
154 | .proc_handler = &proc_dointvec_jiffies, | 153 | .proc_handler = &proc_dointvec_jiffies, |
155 | }, | 154 | }, |
156 | { | 155 | { |
157 | .ctl_name = NET_NF_CONNTRACK_UDP_TIMEOUT_STREAM, | ||
158 | .procname = "nf_conntrack_udp_timeout_stream", | 156 | .procname = "nf_conntrack_udp_timeout_stream", |
159 | .data = &nf_ct_udp_timeout_stream, | 157 | .data = &nf_ct_udp_timeout_stream, |
160 | .maxlen = sizeof(unsigned int), | 158 | .maxlen = sizeof(unsigned int), |
@@ -168,7 +166,6 @@ static struct ctl_table udp_sysctl_table[] = { | |||
168 | #ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT | 166 | #ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT |
169 | static struct ctl_table udp_compat_sysctl_table[] = { | 167 | static struct ctl_table udp_compat_sysctl_table[] = { |
170 | { | 168 | { |
171 | .ctl_name = NET_IPV4_NF_CONNTRACK_UDP_TIMEOUT, | ||
172 | .procname = "ip_conntrack_udp_timeout", | 169 | .procname = "ip_conntrack_udp_timeout", |
173 | .data = &nf_ct_udp_timeout, | 170 | .data = &nf_ct_udp_timeout, |
174 | .maxlen = sizeof(unsigned int), | 171 | .maxlen = sizeof(unsigned int), |
@@ -176,7 +173,6 @@ static struct ctl_table udp_compat_sysctl_table[] = { | |||
176 | .proc_handler = &proc_dointvec_jiffies, | 173 | .proc_handler = &proc_dointvec_jiffies, |
177 | }, | 174 | }, |
178 | { | 175 | { |
179 | .ctl_name = NET_IPV4_NF_CONNTRACK_UDP_TIMEOUT_STREAM, | ||
180 | .procname = "ip_conntrack_udp_timeout_stream", | 176 | .procname = "ip_conntrack_udp_timeout_stream", |
181 | .data = &nf_ct_udp_timeout_stream, | 177 | .data = &nf_ct_udp_timeout_stream, |
182 | .maxlen = sizeof(unsigned int), | 178 | .maxlen = sizeof(unsigned int), |
diff --git a/net/netfilter/nf_conntrack_sane.c b/net/netfilter/nf_conntrack_sane.c index 355d371bac93..b5a16c6e21c2 100644 --- a/net/netfilter/nf_conntrack_sane.c +++ b/net/netfilter/nf_conntrack_sane.c | |||
@@ -56,7 +56,7 @@ struct sane_reply_net_start { | |||
56 | /* other fields aren't interesting for conntrack */ | 56 | /* other fields aren't interesting for conntrack */ |
57 | }; | 57 | }; |
58 | 58 | ||
59 | static int help(struct sk_buff **pskb, | 59 | static int help(struct sk_buff *skb, |
60 | unsigned int protoff, | 60 | unsigned int protoff, |
61 | struct nf_conn *ct, | 61 | struct nf_conn *ct, |
62 | enum ip_conntrack_info ctinfo) | 62 | enum ip_conntrack_info ctinfo) |
@@ -80,19 +80,19 @@ static int help(struct sk_buff **pskb, | |||
80 | return NF_ACCEPT; | 80 | return NF_ACCEPT; |
81 | 81 | ||
82 | /* Not a full tcp header? */ | 82 | /* Not a full tcp header? */ |
83 | th = skb_header_pointer(*pskb, protoff, sizeof(_tcph), &_tcph); | 83 | th = skb_header_pointer(skb, protoff, sizeof(_tcph), &_tcph); |
84 | if (th == NULL) | 84 | if (th == NULL) |
85 | return NF_ACCEPT; | 85 | return NF_ACCEPT; |
86 | 86 | ||
87 | /* No data? */ | 87 | /* No data? */ |
88 | dataoff = protoff + th->doff * 4; | 88 | dataoff = protoff + th->doff * 4; |
89 | if (dataoff >= (*pskb)->len) | 89 | if (dataoff >= skb->len) |
90 | return NF_ACCEPT; | 90 | return NF_ACCEPT; |
91 | 91 | ||
92 | datalen = (*pskb)->len - dataoff; | 92 | datalen = skb->len - dataoff; |
93 | 93 | ||
94 | spin_lock_bh(&nf_sane_lock); | 94 | spin_lock_bh(&nf_sane_lock); |
95 | sb_ptr = skb_header_pointer(*pskb, dataoff, datalen, sane_buffer); | 95 | sb_ptr = skb_header_pointer(skb, dataoff, datalen, sane_buffer); |
96 | BUG_ON(sb_ptr == NULL); | 96 | BUG_ON(sb_ptr == NULL); |
97 | 97 | ||
98 | if (dir == IP_CT_DIR_ORIGINAL) { | 98 | if (dir == IP_CT_DIR_ORIGINAL) { |
diff --git a/net/netfilter/nf_conntrack_sip.c b/net/netfilter/nf_conntrack_sip.c index d449fa47491c..8f8b5a48df38 100644 --- a/net/netfilter/nf_conntrack_sip.c +++ b/net/netfilter/nf_conntrack_sip.c | |||
@@ -36,13 +36,13 @@ static unsigned int sip_timeout __read_mostly = SIP_TIMEOUT; | |||
36 | module_param(sip_timeout, uint, 0600); | 36 | module_param(sip_timeout, uint, 0600); |
37 | MODULE_PARM_DESC(sip_timeout, "timeout for the master SIP session"); | 37 | MODULE_PARM_DESC(sip_timeout, "timeout for the master SIP session"); |
38 | 38 | ||
39 | unsigned int (*nf_nat_sip_hook)(struct sk_buff **pskb, | 39 | unsigned int (*nf_nat_sip_hook)(struct sk_buff *skb, |
40 | enum ip_conntrack_info ctinfo, | 40 | enum ip_conntrack_info ctinfo, |
41 | struct nf_conn *ct, | 41 | struct nf_conn *ct, |
42 | const char **dptr) __read_mostly; | 42 | const char **dptr) __read_mostly; |
43 | EXPORT_SYMBOL_GPL(nf_nat_sip_hook); | 43 | EXPORT_SYMBOL_GPL(nf_nat_sip_hook); |
44 | 44 | ||
45 | unsigned int (*nf_nat_sdp_hook)(struct sk_buff **pskb, | 45 | unsigned int (*nf_nat_sdp_hook)(struct sk_buff *skb, |
46 | enum ip_conntrack_info ctinfo, | 46 | enum ip_conntrack_info ctinfo, |
47 | struct nf_conntrack_expect *exp, | 47 | struct nf_conntrack_expect *exp, |
48 | const char *dptr) __read_mostly; | 48 | const char *dptr) __read_mostly; |
@@ -363,7 +363,7 @@ int ct_sip_get_info(struct nf_conn *ct, | |||
363 | } | 363 | } |
364 | EXPORT_SYMBOL_GPL(ct_sip_get_info); | 364 | EXPORT_SYMBOL_GPL(ct_sip_get_info); |
365 | 365 | ||
366 | static int set_expected_rtp(struct sk_buff **pskb, | 366 | static int set_expected_rtp(struct sk_buff *skb, |
367 | struct nf_conn *ct, | 367 | struct nf_conn *ct, |
368 | enum ip_conntrack_info ctinfo, | 368 | enum ip_conntrack_info ctinfo, |
369 | union nf_conntrack_address *addr, | 369 | union nf_conntrack_address *addr, |
@@ -385,7 +385,7 @@ static int set_expected_rtp(struct sk_buff **pskb, | |||
385 | 385 | ||
386 | nf_nat_sdp = rcu_dereference(nf_nat_sdp_hook); | 386 | nf_nat_sdp = rcu_dereference(nf_nat_sdp_hook); |
387 | if (nf_nat_sdp && ct->status & IPS_NAT_MASK) | 387 | if (nf_nat_sdp && ct->status & IPS_NAT_MASK) |
388 | ret = nf_nat_sdp(pskb, ctinfo, exp, dptr); | 388 | ret = nf_nat_sdp(skb, ctinfo, exp, dptr); |
389 | else { | 389 | else { |
390 | if (nf_ct_expect_related(exp) != 0) | 390 | if (nf_ct_expect_related(exp) != 0) |
391 | ret = NF_DROP; | 391 | ret = NF_DROP; |
@@ -397,7 +397,7 @@ static int set_expected_rtp(struct sk_buff **pskb, | |||
397 | return ret; | 397 | return ret; |
398 | } | 398 | } |
399 | 399 | ||
400 | static int sip_help(struct sk_buff **pskb, | 400 | static int sip_help(struct sk_buff *skb, |
401 | unsigned int protoff, | 401 | unsigned int protoff, |
402 | struct nf_conn *ct, | 402 | struct nf_conn *ct, |
403 | enum ip_conntrack_info ctinfo) | 403 | enum ip_conntrack_info ctinfo) |
@@ -414,13 +414,13 @@ static int sip_help(struct sk_buff **pskb, | |||
414 | 414 | ||
415 | /* No Data ? */ | 415 | /* No Data ? */ |
416 | dataoff = protoff + sizeof(struct udphdr); | 416 | dataoff = protoff + sizeof(struct udphdr); |
417 | if (dataoff >= (*pskb)->len) | 417 | if (dataoff >= skb->len) |
418 | return NF_ACCEPT; | 418 | return NF_ACCEPT; |
419 | 419 | ||
420 | nf_ct_refresh(ct, *pskb, sip_timeout * HZ); | 420 | nf_ct_refresh(ct, skb, sip_timeout * HZ); |
421 | 421 | ||
422 | if (!skb_is_nonlinear(*pskb)) | 422 | if (!skb_is_nonlinear(skb)) |
423 | dptr = (*pskb)->data + dataoff; | 423 | dptr = skb->data + dataoff; |
424 | else { | 424 | else { |
425 | pr_debug("Copy of skbuff not supported yet.\n"); | 425 | pr_debug("Copy of skbuff not supported yet.\n"); |
426 | goto out; | 426 | goto out; |
@@ -428,13 +428,13 @@ static int sip_help(struct sk_buff **pskb, | |||
428 | 428 | ||
429 | nf_nat_sip = rcu_dereference(nf_nat_sip_hook); | 429 | nf_nat_sip = rcu_dereference(nf_nat_sip_hook); |
430 | if (nf_nat_sip && ct->status & IPS_NAT_MASK) { | 430 | if (nf_nat_sip && ct->status & IPS_NAT_MASK) { |
431 | if (!nf_nat_sip(pskb, ctinfo, ct, &dptr)) { | 431 | if (!nf_nat_sip(skb, ctinfo, ct, &dptr)) { |
432 | ret = NF_DROP; | 432 | ret = NF_DROP; |
433 | goto out; | 433 | goto out; |
434 | } | 434 | } |
435 | } | 435 | } |
436 | 436 | ||
437 | datalen = (*pskb)->len - dataoff; | 437 | datalen = skb->len - dataoff; |
438 | if (datalen < sizeof("SIP/2.0 200") - 1) | 438 | if (datalen < sizeof("SIP/2.0 200") - 1) |
439 | goto out; | 439 | goto out; |
440 | 440 | ||
@@ -464,7 +464,7 @@ static int sip_help(struct sk_buff **pskb, | |||
464 | ret = NF_DROP; | 464 | ret = NF_DROP; |
465 | goto out; | 465 | goto out; |
466 | } | 466 | } |
467 | ret = set_expected_rtp(pskb, ct, ctinfo, &addr, | 467 | ret = set_expected_rtp(skb, ct, ctinfo, &addr, |
468 | htons(port), dptr); | 468 | htons(port), dptr); |
469 | } | 469 | } |
470 | } | 470 | } |
diff --git a/net/netfilter/nf_conntrack_tftp.c b/net/netfilter/nf_conntrack_tftp.c index cc19506cf2f8..e894aa1ff3ad 100644 --- a/net/netfilter/nf_conntrack_tftp.c +++ b/net/netfilter/nf_conntrack_tftp.c | |||
@@ -29,12 +29,12 @@ static int ports_c; | |||
29 | module_param_array(ports, ushort, &ports_c, 0400); | 29 | module_param_array(ports, ushort, &ports_c, 0400); |
30 | MODULE_PARM_DESC(ports, "Port numbers of TFTP servers"); | 30 | MODULE_PARM_DESC(ports, "Port numbers of TFTP servers"); |
31 | 31 | ||
32 | unsigned int (*nf_nat_tftp_hook)(struct sk_buff **pskb, | 32 | unsigned int (*nf_nat_tftp_hook)(struct sk_buff *skb, |
33 | enum ip_conntrack_info ctinfo, | 33 | enum ip_conntrack_info ctinfo, |
34 | struct nf_conntrack_expect *exp) __read_mostly; | 34 | struct nf_conntrack_expect *exp) __read_mostly; |
35 | EXPORT_SYMBOL_GPL(nf_nat_tftp_hook); | 35 | EXPORT_SYMBOL_GPL(nf_nat_tftp_hook); |
36 | 36 | ||
37 | static int tftp_help(struct sk_buff **pskb, | 37 | static int tftp_help(struct sk_buff *skb, |
38 | unsigned int protoff, | 38 | unsigned int protoff, |
39 | struct nf_conn *ct, | 39 | struct nf_conn *ct, |
40 | enum ip_conntrack_info ctinfo) | 40 | enum ip_conntrack_info ctinfo) |
@@ -46,7 +46,7 @@ static int tftp_help(struct sk_buff **pskb, | |||
46 | int family = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.l3num; | 46 | int family = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.l3num; |
47 | typeof(nf_nat_tftp_hook) nf_nat_tftp; | 47 | typeof(nf_nat_tftp_hook) nf_nat_tftp; |
48 | 48 | ||
49 | tfh = skb_header_pointer(*pskb, protoff + sizeof(struct udphdr), | 49 | tfh = skb_header_pointer(skb, protoff + sizeof(struct udphdr), |
50 | sizeof(_tftph), &_tftph); | 50 | sizeof(_tftph), &_tftph); |
51 | if (tfh == NULL) | 51 | if (tfh == NULL) |
52 | return NF_ACCEPT; | 52 | return NF_ACCEPT; |
@@ -70,7 +70,7 @@ static int tftp_help(struct sk_buff **pskb, | |||
70 | 70 | ||
71 | nf_nat_tftp = rcu_dereference(nf_nat_tftp_hook); | 71 | nf_nat_tftp = rcu_dereference(nf_nat_tftp_hook); |
72 | if (nf_nat_tftp && ct->status & IPS_NAT_MASK) | 72 | if (nf_nat_tftp && ct->status & IPS_NAT_MASK) |
73 | ret = nf_nat_tftp(pskb, ctinfo, exp); | 73 | ret = nf_nat_tftp(skb, ctinfo, exp); |
74 | else if (nf_ct_expect_related(exp) != 0) | 74 | else if (nf_ct_expect_related(exp) != 0) |
75 | ret = NF_DROP; | 75 | ret = NF_DROP; |
76 | nf_ct_expect_put(exp); | 76 | nf_ct_expect_put(exp); |
diff --git a/net/netfilter/nf_internals.h b/net/netfilter/nf_internals.h index 0df7fff196a7..196269c1e586 100644 --- a/net/netfilter/nf_internals.h +++ b/net/netfilter/nf_internals.h | |||
@@ -14,7 +14,7 @@ | |||
14 | 14 | ||
15 | /* core.c */ | 15 | /* core.c */ |
16 | extern unsigned int nf_iterate(struct list_head *head, | 16 | extern unsigned int nf_iterate(struct list_head *head, |
17 | struct sk_buff **skb, | 17 | struct sk_buff *skb, |
18 | int hook, | 18 | int hook, |
19 | const struct net_device *indev, | 19 | const struct net_device *indev, |
20 | const struct net_device *outdev, | 20 | const struct net_device *outdev, |
diff --git a/net/netfilter/nf_queue.c b/net/netfilter/nf_queue.c index a481a349f7bf..0cef1433d660 100644 --- a/net/netfilter/nf_queue.c +++ b/net/netfilter/nf_queue.c | |||
@@ -256,14 +256,14 @@ void nf_reinject(struct sk_buff *skb, struct nf_info *info, | |||
256 | 256 | ||
257 | if (verdict == NF_ACCEPT) { | 257 | if (verdict == NF_ACCEPT) { |
258 | afinfo = nf_get_afinfo(info->pf); | 258 | afinfo = nf_get_afinfo(info->pf); |
259 | if (!afinfo || afinfo->reroute(&skb, info) < 0) | 259 | if (!afinfo || afinfo->reroute(skb, info) < 0) |
260 | verdict = NF_DROP; | 260 | verdict = NF_DROP; |
261 | } | 261 | } |
262 | 262 | ||
263 | if (verdict == NF_ACCEPT) { | 263 | if (verdict == NF_ACCEPT) { |
264 | next_hook: | 264 | next_hook: |
265 | verdict = nf_iterate(&nf_hooks[info->pf][info->hook], | 265 | verdict = nf_iterate(&nf_hooks[info->pf][info->hook], |
266 | &skb, info->hook, | 266 | skb, info->hook, |
267 | info->indev, info->outdev, &elem, | 267 | info->indev, info->outdev, &elem, |
268 | info->okfn, INT_MIN); | 268 | info->okfn, INT_MIN); |
269 | } | 269 | } |
diff --git a/net/netfilter/nfnetlink_queue.c b/net/netfilter/nfnetlink_queue.c index 49f0480afe09..3ceeffcf6f9d 100644 --- a/net/netfilter/nfnetlink_queue.c +++ b/net/netfilter/nfnetlink_queue.c | |||
@@ -617,6 +617,7 @@ static int | |||
617 | nfqnl_mangle(void *data, int data_len, struct nfqnl_queue_entry *e) | 617 | nfqnl_mangle(void *data, int data_len, struct nfqnl_queue_entry *e) |
618 | { | 618 | { |
619 | int diff; | 619 | int diff; |
620 | int err; | ||
620 | 621 | ||
621 | diff = data_len - e->skb->len; | 622 | diff = data_len - e->skb->len; |
622 | if (diff < 0) { | 623 | if (diff < 0) { |
@@ -626,25 +627,18 @@ nfqnl_mangle(void *data, int data_len, struct nfqnl_queue_entry *e) | |||
626 | if (data_len > 0xFFFF) | 627 | if (data_len > 0xFFFF) |
627 | return -EINVAL; | 628 | return -EINVAL; |
628 | if (diff > skb_tailroom(e->skb)) { | 629 | if (diff > skb_tailroom(e->skb)) { |
629 | struct sk_buff *newskb; | 630 | err = pskb_expand_head(e->skb, 0, |
630 | 631 | diff - skb_tailroom(e->skb), | |
631 | newskb = skb_copy_expand(e->skb, | 632 | GFP_ATOMIC); |
632 | skb_headroom(e->skb), | 633 | if (err) { |
633 | diff, | ||
634 | GFP_ATOMIC); | ||
635 | if (newskb == NULL) { | ||
636 | printk(KERN_WARNING "nf_queue: OOM " | 634 | printk(KERN_WARNING "nf_queue: OOM " |
637 | "in mangle, dropping packet\n"); | 635 | "in mangle, dropping packet\n"); |
638 | return -ENOMEM; | 636 | return err; |
639 | } | 637 | } |
640 | if (e->skb->sk) | ||
641 | skb_set_owner_w(newskb, e->skb->sk); | ||
642 | kfree_skb(e->skb); | ||
643 | e->skb = newskb; | ||
644 | } | 638 | } |
645 | skb_put(e->skb, diff); | 639 | skb_put(e->skb, diff); |
646 | } | 640 | } |
647 | if (!skb_make_writable(&e->skb, data_len)) | 641 | if (!skb_make_writable(e->skb, data_len)) |
648 | return -ENOMEM; | 642 | return -ENOMEM; |
649 | skb_copy_to_linear_data(e->skb, data, data_len); | 643 | skb_copy_to_linear_data(e->skb, data, data_len); |
650 | e->skb->ip_summed = CHECKSUM_NONE; | 644 | e->skb->ip_summed = CHECKSUM_NONE; |
diff --git a/net/netfilter/xt_CLASSIFY.c b/net/netfilter/xt_CLASSIFY.c index 07a1b9665005..77eeae658d42 100644 --- a/net/netfilter/xt_CLASSIFY.c +++ b/net/netfilter/xt_CLASSIFY.c | |||
@@ -27,7 +27,7 @@ MODULE_ALIAS("ipt_CLASSIFY"); | |||
27 | MODULE_ALIAS("ip6t_CLASSIFY"); | 27 | MODULE_ALIAS("ip6t_CLASSIFY"); |
28 | 28 | ||
29 | static unsigned int | 29 | static unsigned int |
30 | target(struct sk_buff **pskb, | 30 | target(struct sk_buff *skb, |
31 | const struct net_device *in, | 31 | const struct net_device *in, |
32 | const struct net_device *out, | 32 | const struct net_device *out, |
33 | unsigned int hooknum, | 33 | unsigned int hooknum, |
@@ -36,7 +36,7 @@ target(struct sk_buff **pskb, | |||
36 | { | 36 | { |
37 | const struct xt_classify_target_info *clinfo = targinfo; | 37 | const struct xt_classify_target_info *clinfo = targinfo; |
38 | 38 | ||
39 | (*pskb)->priority = clinfo->priority; | 39 | skb->priority = clinfo->priority; |
40 | return XT_CONTINUE; | 40 | return XT_CONTINUE; |
41 | } | 41 | } |
42 | 42 | ||
diff --git a/net/netfilter/xt_CONNMARK.c b/net/netfilter/xt_CONNMARK.c index 7043c2757e09..856793e8db7a 100644 --- a/net/netfilter/xt_CONNMARK.c +++ b/net/netfilter/xt_CONNMARK.c | |||
@@ -23,7 +23,7 @@ | |||
23 | #include <linux/ip.h> | 23 | #include <linux/ip.h> |
24 | #include <net/checksum.h> | 24 | #include <net/checksum.h> |
25 | 25 | ||
26 | MODULE_AUTHOR("Henrik Nordstrom <hno@marasytems.com>"); | 26 | MODULE_AUTHOR("Henrik Nordstrom <hno@marasystems.com>"); |
27 | MODULE_DESCRIPTION("IP tables CONNMARK matching module"); | 27 | MODULE_DESCRIPTION("IP tables CONNMARK matching module"); |
28 | MODULE_LICENSE("GPL"); | 28 | MODULE_LICENSE("GPL"); |
29 | MODULE_ALIAS("ipt_CONNMARK"); | 29 | MODULE_ALIAS("ipt_CONNMARK"); |
@@ -34,7 +34,7 @@ MODULE_ALIAS("ip6t_CONNMARK"); | |||
34 | #include <net/netfilter/nf_conntrack_ecache.h> | 34 | #include <net/netfilter/nf_conntrack_ecache.h> |
35 | 35 | ||
36 | static unsigned int | 36 | static unsigned int |
37 | target(struct sk_buff **pskb, | 37 | target(struct sk_buff *skb, |
38 | const struct net_device *in, | 38 | const struct net_device *in, |
39 | const struct net_device *out, | 39 | const struct net_device *out, |
40 | unsigned int hooknum, | 40 | unsigned int hooknum, |
@@ -48,28 +48,28 @@ target(struct sk_buff **pskb, | |||
48 | u_int32_t mark; | 48 | u_int32_t mark; |
49 | u_int32_t newmark; | 49 | u_int32_t newmark; |
50 | 50 | ||
51 | ct = nf_ct_get(*pskb, &ctinfo); | 51 | ct = nf_ct_get(skb, &ctinfo); |
52 | if (ct) { | 52 | if (ct) { |
53 | switch(markinfo->mode) { | 53 | switch(markinfo->mode) { |
54 | case XT_CONNMARK_SET: | 54 | case XT_CONNMARK_SET: |
55 | newmark = (ct->mark & ~markinfo->mask) | markinfo->mark; | 55 | newmark = (ct->mark & ~markinfo->mask) | markinfo->mark; |
56 | if (newmark != ct->mark) { | 56 | if (newmark != ct->mark) { |
57 | ct->mark = newmark; | 57 | ct->mark = newmark; |
58 | nf_conntrack_event_cache(IPCT_MARK, *pskb); | 58 | nf_conntrack_event_cache(IPCT_MARK, skb); |
59 | } | 59 | } |
60 | break; | 60 | break; |
61 | case XT_CONNMARK_SAVE: | 61 | case XT_CONNMARK_SAVE: |
62 | newmark = (ct->mark & ~markinfo->mask) | | 62 | newmark = (ct->mark & ~markinfo->mask) | |
63 | ((*pskb)->mark & markinfo->mask); | 63 | (skb->mark & markinfo->mask); |
64 | if (ct->mark != newmark) { | 64 | if (ct->mark != newmark) { |
65 | ct->mark = newmark; | 65 | ct->mark = newmark; |
66 | nf_conntrack_event_cache(IPCT_MARK, *pskb); | 66 | nf_conntrack_event_cache(IPCT_MARK, skb); |
67 | } | 67 | } |
68 | break; | 68 | break; |
69 | case XT_CONNMARK_RESTORE: | 69 | case XT_CONNMARK_RESTORE: |
70 | mark = (*pskb)->mark; | 70 | mark = skb->mark; |
71 | diff = (ct->mark ^ mark) & markinfo->mask; | 71 | diff = (ct->mark ^ mark) & markinfo->mask; |
72 | (*pskb)->mark = mark ^ diff; | 72 | skb->mark = mark ^ diff; |
73 | break; | 73 | break; |
74 | } | 74 | } |
75 | } | 75 | } |
diff --git a/net/netfilter/xt_CONNSECMARK.c b/net/netfilter/xt_CONNSECMARK.c index 63d73138c1b9..021b5c8d20e2 100644 --- a/net/netfilter/xt_CONNSECMARK.c +++ b/net/netfilter/xt_CONNSECMARK.c | |||
@@ -61,12 +61,11 @@ static void secmark_restore(struct sk_buff *skb) | |||
61 | } | 61 | } |
62 | } | 62 | } |
63 | 63 | ||
64 | static unsigned int target(struct sk_buff **pskb, const struct net_device *in, | 64 | static unsigned int target(struct sk_buff *skb, const struct net_device *in, |
65 | const struct net_device *out, unsigned int hooknum, | 65 | const struct net_device *out, unsigned int hooknum, |
66 | const struct xt_target *target, | 66 | const struct xt_target *target, |
67 | const void *targinfo) | 67 | const void *targinfo) |
68 | { | 68 | { |
69 | struct sk_buff *skb = *pskb; | ||
70 | const struct xt_connsecmark_target_info *info = targinfo; | 69 | const struct xt_connsecmark_target_info *info = targinfo; |
71 | 70 | ||
72 | switch (info->mode) { | 71 | switch (info->mode) { |
diff --git a/net/netfilter/xt_DSCP.c b/net/netfilter/xt_DSCP.c index 798ab731009d..6322a933ab71 100644 --- a/net/netfilter/xt_DSCP.c +++ b/net/netfilter/xt_DSCP.c | |||
@@ -25,7 +25,7 @@ MODULE_LICENSE("GPL"); | |||
25 | MODULE_ALIAS("ipt_DSCP"); | 25 | MODULE_ALIAS("ipt_DSCP"); |
26 | MODULE_ALIAS("ip6t_DSCP"); | 26 | MODULE_ALIAS("ip6t_DSCP"); |
27 | 27 | ||
28 | static unsigned int target(struct sk_buff **pskb, | 28 | static unsigned int target(struct sk_buff *skb, |
29 | const struct net_device *in, | 29 | const struct net_device *in, |
30 | const struct net_device *out, | 30 | const struct net_device *out, |
31 | unsigned int hooknum, | 31 | unsigned int hooknum, |
@@ -33,20 +33,20 @@ static unsigned int target(struct sk_buff **pskb, | |||
33 | const void *targinfo) | 33 | const void *targinfo) |
34 | { | 34 | { |
35 | const struct xt_DSCP_info *dinfo = targinfo; | 35 | const struct xt_DSCP_info *dinfo = targinfo; |
36 | u_int8_t dscp = ipv4_get_dsfield(ip_hdr(*pskb)) >> XT_DSCP_SHIFT; | 36 | u_int8_t dscp = ipv4_get_dsfield(ip_hdr(skb)) >> XT_DSCP_SHIFT; |
37 | 37 | ||
38 | if (dscp != dinfo->dscp) { | 38 | if (dscp != dinfo->dscp) { |
39 | if (!skb_make_writable(pskb, sizeof(struct iphdr))) | 39 | if (!skb_make_writable(skb, sizeof(struct iphdr))) |
40 | return NF_DROP; | 40 | return NF_DROP; |
41 | 41 | ||
42 | ipv4_change_dsfield(ip_hdr(*pskb), (__u8)(~XT_DSCP_MASK), | 42 | ipv4_change_dsfield(ip_hdr(skb), (__u8)(~XT_DSCP_MASK), |
43 | dinfo->dscp << XT_DSCP_SHIFT); | 43 | dinfo->dscp << XT_DSCP_SHIFT); |
44 | 44 | ||
45 | } | 45 | } |
46 | return XT_CONTINUE; | 46 | return XT_CONTINUE; |
47 | } | 47 | } |
48 | 48 | ||
49 | static unsigned int target6(struct sk_buff **pskb, | 49 | static unsigned int target6(struct sk_buff *skb, |
50 | const struct net_device *in, | 50 | const struct net_device *in, |
51 | const struct net_device *out, | 51 | const struct net_device *out, |
52 | unsigned int hooknum, | 52 | unsigned int hooknum, |
@@ -54,13 +54,13 @@ static unsigned int target6(struct sk_buff **pskb, | |||
54 | const void *targinfo) | 54 | const void *targinfo) |
55 | { | 55 | { |
56 | const struct xt_DSCP_info *dinfo = targinfo; | 56 | const struct xt_DSCP_info *dinfo = targinfo; |
57 | u_int8_t dscp = ipv6_get_dsfield(ipv6_hdr(*pskb)) >> XT_DSCP_SHIFT; | 57 | u_int8_t dscp = ipv6_get_dsfield(ipv6_hdr(skb)) >> XT_DSCP_SHIFT; |
58 | 58 | ||
59 | if (dscp != dinfo->dscp) { | 59 | if (dscp != dinfo->dscp) { |
60 | if (!skb_make_writable(pskb, sizeof(struct ipv6hdr))) | 60 | if (!skb_make_writable(skb, sizeof(struct ipv6hdr))) |
61 | return NF_DROP; | 61 | return NF_DROP; |
62 | 62 | ||
63 | ipv6_change_dsfield(ipv6_hdr(*pskb), (__u8)(~XT_DSCP_MASK), | 63 | ipv6_change_dsfield(ipv6_hdr(skb), (__u8)(~XT_DSCP_MASK), |
64 | dinfo->dscp << XT_DSCP_SHIFT); | 64 | dinfo->dscp << XT_DSCP_SHIFT); |
65 | } | 65 | } |
66 | return XT_CONTINUE; | 66 | return XT_CONTINUE; |
diff --git a/net/netfilter/xt_MARK.c b/net/netfilter/xt_MARK.c index f30fe0baf7de..bc6503d77d75 100644 --- a/net/netfilter/xt_MARK.c +++ b/net/netfilter/xt_MARK.c | |||
@@ -22,7 +22,7 @@ MODULE_ALIAS("ipt_MARK"); | |||
22 | MODULE_ALIAS("ip6t_MARK"); | 22 | MODULE_ALIAS("ip6t_MARK"); |
23 | 23 | ||
24 | static unsigned int | 24 | static unsigned int |
25 | target_v0(struct sk_buff **pskb, | 25 | target_v0(struct sk_buff *skb, |
26 | const struct net_device *in, | 26 | const struct net_device *in, |
27 | const struct net_device *out, | 27 | const struct net_device *out, |
28 | unsigned int hooknum, | 28 | unsigned int hooknum, |
@@ -31,12 +31,12 @@ target_v0(struct sk_buff **pskb, | |||
31 | { | 31 | { |
32 | const struct xt_mark_target_info *markinfo = targinfo; | 32 | const struct xt_mark_target_info *markinfo = targinfo; |
33 | 33 | ||
34 | (*pskb)->mark = markinfo->mark; | 34 | skb->mark = markinfo->mark; |
35 | return XT_CONTINUE; | 35 | return XT_CONTINUE; |
36 | } | 36 | } |
37 | 37 | ||
38 | static unsigned int | 38 | static unsigned int |
39 | target_v1(struct sk_buff **pskb, | 39 | target_v1(struct sk_buff *skb, |
40 | const struct net_device *in, | 40 | const struct net_device *in, |
41 | const struct net_device *out, | 41 | const struct net_device *out, |
42 | unsigned int hooknum, | 42 | unsigned int hooknum, |
@@ -52,15 +52,15 @@ target_v1(struct sk_buff **pskb, | |||
52 | break; | 52 | break; |
53 | 53 | ||
54 | case XT_MARK_AND: | 54 | case XT_MARK_AND: |
55 | mark = (*pskb)->mark & markinfo->mark; | 55 | mark = skb->mark & markinfo->mark; |
56 | break; | 56 | break; |
57 | 57 | ||
58 | case XT_MARK_OR: | 58 | case XT_MARK_OR: |
59 | mark = (*pskb)->mark | markinfo->mark; | 59 | mark = skb->mark | markinfo->mark; |
60 | break; | 60 | break; |
61 | } | 61 | } |
62 | 62 | ||
63 | (*pskb)->mark = mark; | 63 | skb->mark = mark; |
64 | return XT_CONTINUE; | 64 | return XT_CONTINUE; |
65 | } | 65 | } |
66 | 66 | ||
diff --git a/net/netfilter/xt_NFLOG.c b/net/netfilter/xt_NFLOG.c index d3594c7ccb26..9fb449ffbf8b 100644 --- a/net/netfilter/xt_NFLOG.c +++ b/net/netfilter/xt_NFLOG.c | |||
@@ -20,7 +20,7 @@ MODULE_ALIAS("ipt_NFLOG"); | |||
20 | MODULE_ALIAS("ip6t_NFLOG"); | 20 | MODULE_ALIAS("ip6t_NFLOG"); |
21 | 21 | ||
22 | static unsigned int | 22 | static unsigned int |
23 | nflog_target(struct sk_buff **pskb, | 23 | nflog_target(struct sk_buff *skb, |
24 | const struct net_device *in, const struct net_device *out, | 24 | const struct net_device *in, const struct net_device *out, |
25 | unsigned int hooknum, const struct xt_target *target, | 25 | unsigned int hooknum, const struct xt_target *target, |
26 | const void *targinfo) | 26 | const void *targinfo) |
@@ -33,7 +33,7 @@ nflog_target(struct sk_buff **pskb, | |||
33 | li.u.ulog.group = info->group; | 33 | li.u.ulog.group = info->group; |
34 | li.u.ulog.qthreshold = info->threshold; | 34 | li.u.ulog.qthreshold = info->threshold; |
35 | 35 | ||
36 | nf_log_packet(target->family, hooknum, *pskb, in, out, &li, | 36 | nf_log_packet(target->family, hooknum, skb, in, out, &li, |
37 | "%s", info->prefix); | 37 | "%s", info->prefix); |
38 | return XT_CONTINUE; | 38 | return XT_CONTINUE; |
39 | } | 39 | } |
diff --git a/net/netfilter/xt_NFQUEUE.c b/net/netfilter/xt_NFQUEUE.c index 13f59f3e8c38..c3984e9f766a 100644 --- a/net/netfilter/xt_NFQUEUE.c +++ b/net/netfilter/xt_NFQUEUE.c | |||
@@ -24,7 +24,7 @@ MODULE_ALIAS("ip6t_NFQUEUE"); | |||
24 | MODULE_ALIAS("arpt_NFQUEUE"); | 24 | MODULE_ALIAS("arpt_NFQUEUE"); |
25 | 25 | ||
26 | static unsigned int | 26 | static unsigned int |
27 | target(struct sk_buff **pskb, | 27 | target(struct sk_buff *skb, |
28 | const struct net_device *in, | 28 | const struct net_device *in, |
29 | const struct net_device *out, | 29 | const struct net_device *out, |
30 | unsigned int hooknum, | 30 | unsigned int hooknum, |
diff --git a/net/netfilter/xt_NOTRACK.c b/net/netfilter/xt_NOTRACK.c index fec1aefb1c32..4976ce186615 100644 --- a/net/netfilter/xt_NOTRACK.c +++ b/net/netfilter/xt_NOTRACK.c | |||
@@ -12,7 +12,7 @@ MODULE_ALIAS("ipt_NOTRACK"); | |||
12 | MODULE_ALIAS("ip6t_NOTRACK"); | 12 | MODULE_ALIAS("ip6t_NOTRACK"); |
13 | 13 | ||
14 | static unsigned int | 14 | static unsigned int |
15 | target(struct sk_buff **pskb, | 15 | target(struct sk_buff *skb, |
16 | const struct net_device *in, | 16 | const struct net_device *in, |
17 | const struct net_device *out, | 17 | const struct net_device *out, |
18 | unsigned int hooknum, | 18 | unsigned int hooknum, |
@@ -20,16 +20,16 @@ target(struct sk_buff **pskb, | |||
20 | const void *targinfo) | 20 | const void *targinfo) |
21 | { | 21 | { |
22 | /* Previously seen (loopback)? Ignore. */ | 22 | /* Previously seen (loopback)? Ignore. */ |
23 | if ((*pskb)->nfct != NULL) | 23 | if (skb->nfct != NULL) |
24 | return XT_CONTINUE; | 24 | return XT_CONTINUE; |
25 | 25 | ||
26 | /* Attach fake conntrack entry. | 26 | /* Attach fake conntrack entry. |
27 | If there is a real ct entry correspondig to this packet, | 27 | If there is a real ct entry correspondig to this packet, |
28 | it'll hang aroun till timing out. We don't deal with it | 28 | it'll hang aroun till timing out. We don't deal with it |
29 | for performance reasons. JK */ | 29 | for performance reasons. JK */ |
30 | (*pskb)->nfct = &nf_conntrack_untracked.ct_general; | 30 | skb->nfct = &nf_conntrack_untracked.ct_general; |
31 | (*pskb)->nfctinfo = IP_CT_NEW; | 31 | skb->nfctinfo = IP_CT_NEW; |
32 | nf_conntrack_get((*pskb)->nfct); | 32 | nf_conntrack_get(skb->nfct); |
33 | 33 | ||
34 | return XT_CONTINUE; | 34 | return XT_CONTINUE; |
35 | } | 35 | } |
diff --git a/net/netfilter/xt_SECMARK.c b/net/netfilter/xt_SECMARK.c index c83779a941a1..235806eb6ecd 100644 --- a/net/netfilter/xt_SECMARK.c +++ b/net/netfilter/xt_SECMARK.c | |||
@@ -28,7 +28,7 @@ MODULE_ALIAS("ip6t_SECMARK"); | |||
28 | 28 | ||
29 | static u8 mode; | 29 | static u8 mode; |
30 | 30 | ||
31 | static unsigned int target(struct sk_buff **pskb, const struct net_device *in, | 31 | static unsigned int target(struct sk_buff *skb, const struct net_device *in, |
32 | const struct net_device *out, unsigned int hooknum, | 32 | const struct net_device *out, unsigned int hooknum, |
33 | const struct xt_target *target, | 33 | const struct xt_target *target, |
34 | const void *targinfo) | 34 | const void *targinfo) |
@@ -47,7 +47,7 @@ static unsigned int target(struct sk_buff **pskb, const struct net_device *in, | |||
47 | BUG(); | 47 | BUG(); |
48 | } | 48 | } |
49 | 49 | ||
50 | (*pskb)->secmark = secmark; | 50 | skb->secmark = secmark; |
51 | return XT_CONTINUE; | 51 | return XT_CONTINUE; |
52 | } | 52 | } |
53 | 53 | ||
diff --git a/net/netfilter/xt_TCPMSS.c b/net/netfilter/xt_TCPMSS.c index d40f7e4b1289..07435a602b11 100644 --- a/net/netfilter/xt_TCPMSS.c +++ b/net/netfilter/xt_TCPMSS.c | |||
@@ -39,7 +39,7 @@ optlen(const u_int8_t *opt, unsigned int offset) | |||
39 | } | 39 | } |
40 | 40 | ||
41 | static int | 41 | static int |
42 | tcpmss_mangle_packet(struct sk_buff **pskb, | 42 | tcpmss_mangle_packet(struct sk_buff *skb, |
43 | const struct xt_tcpmss_info *info, | 43 | const struct xt_tcpmss_info *info, |
44 | unsigned int tcphoff, | 44 | unsigned int tcphoff, |
45 | unsigned int minlen) | 45 | unsigned int minlen) |
@@ -50,11 +50,11 @@ tcpmss_mangle_packet(struct sk_buff **pskb, | |||
50 | u16 newmss; | 50 | u16 newmss; |
51 | u8 *opt; | 51 | u8 *opt; |
52 | 52 | ||
53 | if (!skb_make_writable(pskb, (*pskb)->len)) | 53 | if (!skb_make_writable(skb, skb->len)) |
54 | return -1; | 54 | return -1; |
55 | 55 | ||
56 | tcplen = (*pskb)->len - tcphoff; | 56 | tcplen = skb->len - tcphoff; |
57 | tcph = (struct tcphdr *)(skb_network_header(*pskb) + tcphoff); | 57 | tcph = (struct tcphdr *)(skb_network_header(skb) + tcphoff); |
58 | 58 | ||
59 | /* Since it passed flags test in tcp match, we know it is is | 59 | /* Since it passed flags test in tcp match, we know it is is |
60 | not a fragment, and has data >= tcp header length. SYN | 60 | not a fragment, and has data >= tcp header length. SYN |
@@ -64,19 +64,19 @@ tcpmss_mangle_packet(struct sk_buff **pskb, | |||
64 | if (tcplen != tcph->doff*4) { | 64 | if (tcplen != tcph->doff*4) { |
65 | if (net_ratelimit()) | 65 | if (net_ratelimit()) |
66 | printk(KERN_ERR "xt_TCPMSS: bad length (%u bytes)\n", | 66 | printk(KERN_ERR "xt_TCPMSS: bad length (%u bytes)\n", |
67 | (*pskb)->len); | 67 | skb->len); |
68 | return -1; | 68 | return -1; |
69 | } | 69 | } |
70 | 70 | ||
71 | if (info->mss == XT_TCPMSS_CLAMP_PMTU) { | 71 | if (info->mss == XT_TCPMSS_CLAMP_PMTU) { |
72 | if (dst_mtu((*pskb)->dst) <= minlen) { | 72 | if (dst_mtu(skb->dst) <= minlen) { |
73 | if (net_ratelimit()) | 73 | if (net_ratelimit()) |
74 | printk(KERN_ERR "xt_TCPMSS: " | 74 | printk(KERN_ERR "xt_TCPMSS: " |
75 | "unknown or invalid path-MTU (%u)\n", | 75 | "unknown or invalid path-MTU (%u)\n", |
76 | dst_mtu((*pskb)->dst)); | 76 | dst_mtu(skb->dst)); |
77 | return -1; | 77 | return -1; |
78 | } | 78 | } |
79 | newmss = dst_mtu((*pskb)->dst) - minlen; | 79 | newmss = dst_mtu(skb->dst) - minlen; |
80 | } else | 80 | } else |
81 | newmss = info->mss; | 81 | newmss = info->mss; |
82 | 82 | ||
@@ -95,7 +95,7 @@ tcpmss_mangle_packet(struct sk_buff **pskb, | |||
95 | opt[i+2] = (newmss & 0xff00) >> 8; | 95 | opt[i+2] = (newmss & 0xff00) >> 8; |
96 | opt[i+3] = newmss & 0x00ff; | 96 | opt[i+3] = newmss & 0x00ff; |
97 | 97 | ||
98 | nf_proto_csum_replace2(&tcph->check, *pskb, | 98 | nf_proto_csum_replace2(&tcph->check, skb, |
99 | htons(oldmss), htons(newmss), 0); | 99 | htons(oldmss), htons(newmss), 0); |
100 | return 0; | 100 | return 0; |
101 | } | 101 | } |
@@ -104,57 +104,53 @@ tcpmss_mangle_packet(struct sk_buff **pskb, | |||
104 | /* | 104 | /* |
105 | * MSS Option not found ?! add it.. | 105 | * MSS Option not found ?! add it.. |
106 | */ | 106 | */ |
107 | if (skb_tailroom((*pskb)) < TCPOLEN_MSS) { | 107 | if (skb_tailroom(skb) < TCPOLEN_MSS) { |
108 | struct sk_buff *newskb; | 108 | if (pskb_expand_head(skb, 0, |
109 | 109 | TCPOLEN_MSS - skb_tailroom(skb), | |
110 | newskb = skb_copy_expand(*pskb, skb_headroom(*pskb), | 110 | GFP_ATOMIC)) |
111 | TCPOLEN_MSS, GFP_ATOMIC); | ||
112 | if (!newskb) | ||
113 | return -1; | 111 | return -1; |
114 | kfree_skb(*pskb); | 112 | tcph = (struct tcphdr *)(skb_network_header(skb) + tcphoff); |
115 | *pskb = newskb; | ||
116 | tcph = (struct tcphdr *)(skb_network_header(*pskb) + tcphoff); | ||
117 | } | 113 | } |
118 | 114 | ||
119 | skb_put((*pskb), TCPOLEN_MSS); | 115 | skb_put(skb, TCPOLEN_MSS); |
120 | 116 | ||
121 | opt = (u_int8_t *)tcph + sizeof(struct tcphdr); | 117 | opt = (u_int8_t *)tcph + sizeof(struct tcphdr); |
122 | memmove(opt + TCPOLEN_MSS, opt, tcplen - sizeof(struct tcphdr)); | 118 | memmove(opt + TCPOLEN_MSS, opt, tcplen - sizeof(struct tcphdr)); |
123 | 119 | ||
124 | nf_proto_csum_replace2(&tcph->check, *pskb, | 120 | nf_proto_csum_replace2(&tcph->check, skb, |
125 | htons(tcplen), htons(tcplen + TCPOLEN_MSS), 1); | 121 | htons(tcplen), htons(tcplen + TCPOLEN_MSS), 1); |
126 | opt[0] = TCPOPT_MSS; | 122 | opt[0] = TCPOPT_MSS; |
127 | opt[1] = TCPOLEN_MSS; | 123 | opt[1] = TCPOLEN_MSS; |
128 | opt[2] = (newmss & 0xff00) >> 8; | 124 | opt[2] = (newmss & 0xff00) >> 8; |
129 | opt[3] = newmss & 0x00ff; | 125 | opt[3] = newmss & 0x00ff; |
130 | 126 | ||
131 | nf_proto_csum_replace4(&tcph->check, *pskb, 0, *((__be32 *)opt), 0); | 127 | nf_proto_csum_replace4(&tcph->check, skb, 0, *((__be32 *)opt), 0); |
132 | 128 | ||
133 | oldval = ((__be16 *)tcph)[6]; | 129 | oldval = ((__be16 *)tcph)[6]; |
134 | tcph->doff += TCPOLEN_MSS/4; | 130 | tcph->doff += TCPOLEN_MSS/4; |
135 | nf_proto_csum_replace2(&tcph->check, *pskb, | 131 | nf_proto_csum_replace2(&tcph->check, skb, |
136 | oldval, ((__be16 *)tcph)[6], 0); | 132 | oldval, ((__be16 *)tcph)[6], 0); |
137 | return TCPOLEN_MSS; | 133 | return TCPOLEN_MSS; |
138 | } | 134 | } |
139 | 135 | ||
140 | static unsigned int | 136 | static unsigned int |
141 | xt_tcpmss_target4(struct sk_buff **pskb, | 137 | xt_tcpmss_target4(struct sk_buff *skb, |
142 | const struct net_device *in, | 138 | const struct net_device *in, |
143 | const struct net_device *out, | 139 | const struct net_device *out, |
144 | unsigned int hooknum, | 140 | unsigned int hooknum, |
145 | const struct xt_target *target, | 141 | const struct xt_target *target, |
146 | const void *targinfo) | 142 | const void *targinfo) |
147 | { | 143 | { |
148 | struct iphdr *iph = ip_hdr(*pskb); | 144 | struct iphdr *iph = ip_hdr(skb); |
149 | __be16 newlen; | 145 | __be16 newlen; |
150 | int ret; | 146 | int ret; |
151 | 147 | ||
152 | ret = tcpmss_mangle_packet(pskb, targinfo, iph->ihl * 4, | 148 | ret = tcpmss_mangle_packet(skb, targinfo, iph->ihl * 4, |
153 | sizeof(*iph) + sizeof(struct tcphdr)); | 149 | sizeof(*iph) + sizeof(struct tcphdr)); |
154 | if (ret < 0) | 150 | if (ret < 0) |
155 | return NF_DROP; | 151 | return NF_DROP; |
156 | if (ret > 0) { | 152 | if (ret > 0) { |
157 | iph = ip_hdr(*pskb); | 153 | iph = ip_hdr(skb); |
158 | newlen = htons(ntohs(iph->tot_len) + ret); | 154 | newlen = htons(ntohs(iph->tot_len) + ret); |
159 | nf_csum_replace2(&iph->check, iph->tot_len, newlen); | 155 | nf_csum_replace2(&iph->check, iph->tot_len, newlen); |
160 | iph->tot_len = newlen; | 156 | iph->tot_len = newlen; |
@@ -164,30 +160,30 @@ xt_tcpmss_target4(struct sk_buff **pskb, | |||
164 | 160 | ||
165 | #if defined(CONFIG_IP6_NF_IPTABLES) || defined(CONFIG_IP6_NF_IPTABLES_MODULE) | 161 | #if defined(CONFIG_IP6_NF_IPTABLES) || defined(CONFIG_IP6_NF_IPTABLES_MODULE) |
166 | static unsigned int | 162 | static unsigned int |
167 | xt_tcpmss_target6(struct sk_buff **pskb, | 163 | xt_tcpmss_target6(struct sk_buff *skb, |
168 | const struct net_device *in, | 164 | const struct net_device *in, |
169 | const struct net_device *out, | 165 | const struct net_device *out, |
170 | unsigned int hooknum, | 166 | unsigned int hooknum, |
171 | const struct xt_target *target, | 167 | const struct xt_target *target, |
172 | const void *targinfo) | 168 | const void *targinfo) |
173 | { | 169 | { |
174 | struct ipv6hdr *ipv6h = ipv6_hdr(*pskb); | 170 | struct ipv6hdr *ipv6h = ipv6_hdr(skb); |
175 | u8 nexthdr; | 171 | u8 nexthdr; |
176 | int tcphoff; | 172 | int tcphoff; |
177 | int ret; | 173 | int ret; |
178 | 174 | ||
179 | nexthdr = ipv6h->nexthdr; | 175 | nexthdr = ipv6h->nexthdr; |
180 | tcphoff = ipv6_skip_exthdr(*pskb, sizeof(*ipv6h), &nexthdr); | 176 | tcphoff = ipv6_skip_exthdr(skb, sizeof(*ipv6h), &nexthdr); |
181 | if (tcphoff < 0) { | 177 | if (tcphoff < 0) { |
182 | WARN_ON(1); | 178 | WARN_ON(1); |
183 | return NF_DROP; | 179 | return NF_DROP; |
184 | } | 180 | } |
185 | ret = tcpmss_mangle_packet(pskb, targinfo, tcphoff, | 181 | ret = tcpmss_mangle_packet(skb, targinfo, tcphoff, |
186 | sizeof(*ipv6h) + sizeof(struct tcphdr)); | 182 | sizeof(*ipv6h) + sizeof(struct tcphdr)); |
187 | if (ret < 0) | 183 | if (ret < 0) |
188 | return NF_DROP; | 184 | return NF_DROP; |
189 | if (ret > 0) { | 185 | if (ret > 0) { |
190 | ipv6h = ipv6_hdr(*pskb); | 186 | ipv6h = ipv6_hdr(skb); |
191 | ipv6h->payload_len = htons(ntohs(ipv6h->payload_len) + ret); | 187 | ipv6h->payload_len = htons(ntohs(ipv6h->payload_len) + ret); |
192 | } | 188 | } |
193 | return XT_CONTINUE; | 189 | return XT_CONTINUE; |
diff --git a/net/netfilter/xt_TRACE.c b/net/netfilter/xt_TRACE.c index 4df2dedcc0b5..26c5d08ab2c2 100644 --- a/net/netfilter/xt_TRACE.c +++ b/net/netfilter/xt_TRACE.c | |||
@@ -10,14 +10,14 @@ MODULE_ALIAS("ipt_TRACE"); | |||
10 | MODULE_ALIAS("ip6t_TRACE"); | 10 | MODULE_ALIAS("ip6t_TRACE"); |
11 | 11 | ||
12 | static unsigned int | 12 | static unsigned int |
13 | target(struct sk_buff **pskb, | 13 | target(struct sk_buff *skb, |
14 | const struct net_device *in, | 14 | const struct net_device *in, |
15 | const struct net_device *out, | 15 | const struct net_device *out, |
16 | unsigned int hooknum, | 16 | unsigned int hooknum, |
17 | const struct xt_target *target, | 17 | const struct xt_target *target, |
18 | const void *targinfo) | 18 | const void *targinfo) |
19 | { | 19 | { |
20 | (*pskb)->nf_trace = 1; | 20 | skb->nf_trace = 1; |
21 | return XT_CONTINUE; | 21 | return XT_CONTINUE; |
22 | } | 22 | } |
23 | 23 | ||
diff --git a/net/netfilter/xt_connbytes.c b/net/netfilter/xt_connbytes.c index af79423bc8e8..9ec50139b9a1 100644 --- a/net/netfilter/xt_connbytes.c +++ b/net/netfilter/xt_connbytes.c | |||
@@ -2,13 +2,13 @@ | |||
2 | * GPL (C) 2002 Martin Devera (devik@cdi.cz). | 2 | * GPL (C) 2002 Martin Devera (devik@cdi.cz). |
3 | */ | 3 | */ |
4 | #include <linux/module.h> | 4 | #include <linux/module.h> |
5 | #include <linux/bitops.h> | ||
5 | #include <linux/skbuff.h> | 6 | #include <linux/skbuff.h> |
6 | #include <linux/netfilter/x_tables.h> | 7 | #include <linux/netfilter/x_tables.h> |
7 | #include <linux/netfilter/xt_connbytes.h> | 8 | #include <linux/netfilter/xt_connbytes.h> |
8 | #include <net/netfilter/nf_conntrack.h> | 9 | #include <net/netfilter/nf_conntrack.h> |
9 | 10 | ||
10 | #include <asm/div64.h> | 11 | #include <asm/div64.h> |
11 | #include <asm/bitops.h> | ||
12 | 12 | ||
13 | MODULE_LICENSE("GPL"); | 13 | MODULE_LICENSE("GPL"); |
14 | MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>"); | 14 | MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>"); |
diff --git a/net/netfilter/xt_connmark.c b/net/netfilter/xt_connmark.c index 1071fc54d6d3..9f67920af41f 100644 --- a/net/netfilter/xt_connmark.c +++ b/net/netfilter/xt_connmark.c | |||
@@ -25,7 +25,7 @@ | |||
25 | #include <linux/netfilter/x_tables.h> | 25 | #include <linux/netfilter/x_tables.h> |
26 | #include <linux/netfilter/xt_connmark.h> | 26 | #include <linux/netfilter/xt_connmark.h> |
27 | 27 | ||
28 | MODULE_AUTHOR("Henrik Nordstrom <hno@marasytems.com>"); | 28 | MODULE_AUTHOR("Henrik Nordstrom <hno@marasystems.com>"); |
29 | MODULE_DESCRIPTION("IP tables connmark match module"); | 29 | MODULE_DESCRIPTION("IP tables connmark match module"); |
30 | MODULE_LICENSE("GPL"); | 30 | MODULE_LICENSE("GPL"); |
31 | MODULE_ALIAS("ipt_connmark"); | 31 | MODULE_ALIAS("ipt_connmark"); |
diff --git a/net/netfilter/xt_limit.c b/net/netfilter/xt_limit.c index 4fcca797150f..f263a77e57b7 100644 --- a/net/netfilter/xt_limit.c +++ b/net/netfilter/xt_limit.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* (C) 1999 Jérôme de Vivie <devivie@info.enserb.u-bordeaux.fr> | 1 | /* (C) 1999 Jérôme de Vivie <devivie@info.enserb.u-bordeaux.fr> |
2 | * (C) 1999 Hervé Eychenne <eychenne@info.enserb.u-bordeaux.fr> | 2 | * (C) 1999 Hervé Eychenne <eychenne@info.enserb.u-bordeaux.fr> |
3 | * | 3 | * |
4 | * This program is free software; you can redistribute it and/or modify | 4 | * This program is free software; you can redistribute it and/or modify |
5 | * it under the terms of the GNU General Public License version 2 as | 5 | * it under the terms of the GNU General Public License version 2 as |
diff --git a/net/netfilter/xt_sctp.c b/net/netfilter/xt_sctp.c index f907770fd4e9..3358273a47b7 100644 --- a/net/netfilter/xt_sctp.c +++ b/net/netfilter/xt_sctp.c | |||
@@ -42,21 +42,21 @@ match_flags(const struct xt_sctp_flag_info *flag_info, | |||
42 | static inline bool | 42 | static inline bool |
43 | match_packet(const struct sk_buff *skb, | 43 | match_packet(const struct sk_buff *skb, |
44 | unsigned int offset, | 44 | unsigned int offset, |
45 | const u_int32_t *chunkmap, | 45 | const struct xt_sctp_info *info, |
46 | int chunk_match_type, | ||
47 | const struct xt_sctp_flag_info *flag_info, | ||
48 | const int flag_count, | ||
49 | bool *hotdrop) | 46 | bool *hotdrop) |
50 | { | 47 | { |
51 | u_int32_t chunkmapcopy[256 / sizeof (u_int32_t)]; | 48 | u_int32_t chunkmapcopy[256 / sizeof (u_int32_t)]; |
52 | sctp_chunkhdr_t _sch, *sch; | 49 | sctp_chunkhdr_t _sch, *sch; |
50 | int chunk_match_type = info->chunk_match_type; | ||
51 | const struct xt_sctp_flag_info *flag_info = info->flag_info; | ||
52 | int flag_count = info->flag_count; | ||
53 | 53 | ||
54 | #ifdef DEBUG_SCTP | 54 | #ifdef DEBUG_SCTP |
55 | int i = 0; | 55 | int i = 0; |
56 | #endif | 56 | #endif |
57 | 57 | ||
58 | if (chunk_match_type == SCTP_CHUNK_MATCH_ALL) | 58 | if (chunk_match_type == SCTP_CHUNK_MATCH_ALL) |
59 | SCTP_CHUNKMAP_COPY(chunkmapcopy, chunkmap); | 59 | SCTP_CHUNKMAP_COPY(chunkmapcopy, info->chunkmap); |
60 | 60 | ||
61 | do { | 61 | do { |
62 | sch = skb_header_pointer(skb, offset, sizeof(_sch), &_sch); | 62 | sch = skb_header_pointer(skb, offset, sizeof(_sch), &_sch); |
@@ -73,7 +73,7 @@ match_packet(const struct sk_buff *skb, | |||
73 | 73 | ||
74 | duprintf("skb->len: %d\toffset: %d\n", skb->len, offset); | 74 | duprintf("skb->len: %d\toffset: %d\n", skb->len, offset); |
75 | 75 | ||
76 | if (SCTP_CHUNKMAP_IS_SET(chunkmap, sch->type)) { | 76 | if (SCTP_CHUNKMAP_IS_SET(info->chunkmap, sch->type)) { |
77 | switch (chunk_match_type) { | 77 | switch (chunk_match_type) { |
78 | case SCTP_CHUNK_MATCH_ANY: | 78 | case SCTP_CHUNK_MATCH_ANY: |
79 | if (match_flags(flag_info, flag_count, | 79 | if (match_flags(flag_info, flag_count, |
@@ -104,7 +104,7 @@ match_packet(const struct sk_buff *skb, | |||
104 | 104 | ||
105 | switch (chunk_match_type) { | 105 | switch (chunk_match_type) { |
106 | case SCTP_CHUNK_MATCH_ALL: | 106 | case SCTP_CHUNK_MATCH_ALL: |
107 | return SCTP_CHUNKMAP_IS_CLEAR(chunkmap); | 107 | return SCTP_CHUNKMAP_IS_CLEAR(info->chunkmap); |
108 | case SCTP_CHUNK_MATCH_ANY: | 108 | case SCTP_CHUNK_MATCH_ANY: |
109 | return false; | 109 | return false; |
110 | case SCTP_CHUNK_MATCH_ONLY: | 110 | case SCTP_CHUNK_MATCH_ONLY: |
@@ -148,9 +148,7 @@ match(const struct sk_buff *skb, | |||
148 | && ntohs(sh->dest) <= info->dpts[1], | 148 | && ntohs(sh->dest) <= info->dpts[1], |
149 | XT_SCTP_DEST_PORTS, info->flags, info->invflags) | 149 | XT_SCTP_DEST_PORTS, info->flags, info->invflags) |
150 | && SCCHECK(match_packet(skb, protoff + sizeof (sctp_sctphdr_t), | 150 | && SCCHECK(match_packet(skb, protoff + sizeof (sctp_sctphdr_t), |
151 | info->chunkmap, info->chunk_match_type, | 151 | info, hotdrop), |
152 | info->flag_info, info->flag_count, | ||
153 | hotdrop), | ||
154 | XT_SCTP_CHUNK_TYPES, info->flags, info->invflags); | 152 | XT_SCTP_CHUNK_TYPES, info->flags, info->invflags); |
155 | } | 153 | } |
156 | 154 | ||
diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c index c776bcd9f825..98e313e5e594 100644 --- a/net/netlink/af_netlink.c +++ b/net/netlink/af_netlink.c | |||
@@ -1378,6 +1378,8 @@ netlink_kernel_create(struct net *net, int unit, unsigned int groups, | |||
1378 | nl_table[unit].cb_mutex = cb_mutex; | 1378 | nl_table[unit].cb_mutex = cb_mutex; |
1379 | nl_table[unit].module = module; | 1379 | nl_table[unit].module = module; |
1380 | nl_table[unit].registered = 1; | 1380 | nl_table[unit].registered = 1; |
1381 | } else { | ||
1382 | kfree(listeners); | ||
1381 | } | 1383 | } |
1382 | netlink_table_ungrab(); | 1384 | netlink_table_ungrab(); |
1383 | 1385 | ||
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c index e11000a8e950..d0936506b731 100644 --- a/net/packet/af_packet.c +++ b/net/packet/af_packet.c | |||
@@ -1623,11 +1623,6 @@ static struct vm_operations_struct packet_mmap_ops = { | |||
1623 | .close =packet_mm_close, | 1623 | .close =packet_mm_close, |
1624 | }; | 1624 | }; |
1625 | 1625 | ||
1626 | static inline struct page *pg_vec_endpage(char *one_pg_vec, unsigned int order) | ||
1627 | { | ||
1628 | return virt_to_page(one_pg_vec + (PAGE_SIZE << order) - 1); | ||
1629 | } | ||
1630 | |||
1631 | static void free_pg_vec(char **pg_vec, unsigned int order, unsigned int len) | 1626 | static void free_pg_vec(char **pg_vec, unsigned int order, unsigned int len) |
1632 | { | 1627 | { |
1633 | int i; | 1628 | int i; |
diff --git a/net/rfkill/rfkill-input.c b/net/rfkill/rfkill-input.c index eaabf087c59b..d1e9d68f8ba0 100644 --- a/net/rfkill/rfkill-input.c +++ b/net/rfkill/rfkill-input.c | |||
@@ -146,18 +146,18 @@ static void rfkill_disconnect(struct input_handle *handle) | |||
146 | static const struct input_device_id rfkill_ids[] = { | 146 | static const struct input_device_id rfkill_ids[] = { |
147 | { | 147 | { |
148 | .flags = INPUT_DEVICE_ID_MATCH_EVBIT | INPUT_DEVICE_ID_MATCH_KEYBIT, | 148 | .flags = INPUT_DEVICE_ID_MATCH_EVBIT | INPUT_DEVICE_ID_MATCH_KEYBIT, |
149 | .evbit = { BIT(EV_KEY) }, | 149 | .evbit = { BIT_MASK(EV_KEY) }, |
150 | .keybit = { [LONG(KEY_WLAN)] = BIT(KEY_WLAN) }, | 150 | .keybit = { [BIT_WORD(KEY_WLAN)] = BIT_MASK(KEY_WLAN) }, |
151 | }, | 151 | }, |
152 | { | 152 | { |
153 | .flags = INPUT_DEVICE_ID_MATCH_EVBIT | INPUT_DEVICE_ID_MATCH_KEYBIT, | 153 | .flags = INPUT_DEVICE_ID_MATCH_EVBIT | INPUT_DEVICE_ID_MATCH_KEYBIT, |
154 | .evbit = { BIT(EV_KEY) }, | 154 | .evbit = { BIT_MASK(EV_KEY) }, |
155 | .keybit = { [LONG(KEY_BLUETOOTH)] = BIT(KEY_BLUETOOTH) }, | 155 | .keybit = { [BIT_WORD(KEY_BLUETOOTH)] = BIT_MASK(KEY_BLUETOOTH) }, |
156 | }, | 156 | }, |
157 | { | 157 | { |
158 | .flags = INPUT_DEVICE_ID_MATCH_EVBIT | INPUT_DEVICE_ID_MATCH_KEYBIT, | 158 | .flags = INPUT_DEVICE_ID_MATCH_EVBIT | INPUT_DEVICE_ID_MATCH_KEYBIT, |
159 | .evbit = { BIT(EV_KEY) }, | 159 | .evbit = { BIT_MASK(EV_KEY) }, |
160 | .keybit = { [LONG(KEY_UWB)] = BIT(KEY_UWB) }, | 160 | .keybit = { [BIT_WORD(KEY_UWB)] = BIT_MASK(KEY_UWB) }, |
161 | }, | 161 | }, |
162 | { } | 162 | { } |
163 | }; | 163 | }; |
diff --git a/net/rxrpc/af_rxrpc.c b/net/rxrpc/af_rxrpc.c index 0803f305ed08..c680017f5c8e 100644 --- a/net/rxrpc/af_rxrpc.c +++ b/net/rxrpc/af_rxrpc.c | |||
@@ -14,6 +14,7 @@ | |||
14 | #include <linux/skbuff.h> | 14 | #include <linux/skbuff.h> |
15 | #include <linux/poll.h> | 15 | #include <linux/poll.h> |
16 | #include <linux/proc_fs.h> | 16 | #include <linux/proc_fs.h> |
17 | #include <linux/key-type.h> | ||
17 | #include <net/net_namespace.h> | 18 | #include <net/net_namespace.h> |
18 | #include <net/sock.h> | 19 | #include <net/sock.h> |
19 | #include <net/af_rxrpc.h> | 20 | #include <net/af_rxrpc.h> |
diff --git a/net/rxrpc/ar-key.c b/net/rxrpc/ar-key.c index 7e049ff6ae60..9a8ff684da79 100644 --- a/net/rxrpc/ar-key.c +++ b/net/rxrpc/ar-key.c | |||
@@ -15,7 +15,7 @@ | |||
15 | #include <linux/module.h> | 15 | #include <linux/module.h> |
16 | #include <linux/net.h> | 16 | #include <linux/net.h> |
17 | #include <linux/skbuff.h> | 17 | #include <linux/skbuff.h> |
18 | #include <linux/key.h> | 18 | #include <linux/key-type.h> |
19 | #include <linux/crypto.h> | 19 | #include <linux/crypto.h> |
20 | #include <net/sock.h> | 20 | #include <net/sock.h> |
21 | #include <net/af_rxrpc.h> | 21 | #include <net/af_rxrpc.h> |
@@ -40,7 +40,6 @@ struct key_type key_type_rxrpc = { | |||
40 | .destroy = rxrpc_destroy, | 40 | .destroy = rxrpc_destroy, |
41 | .describe = rxrpc_describe, | 41 | .describe = rxrpc_describe, |
42 | }; | 42 | }; |
43 | |||
44 | EXPORT_SYMBOL(key_type_rxrpc); | 43 | EXPORT_SYMBOL(key_type_rxrpc); |
45 | 44 | ||
46 | /* | 45 | /* |
@@ -330,5 +329,32 @@ error: | |||
330 | _leave(" = -ENOMEM [ins %d]", ret); | 329 | _leave(" = -ENOMEM [ins %d]", ret); |
331 | return -ENOMEM; | 330 | return -ENOMEM; |
332 | } | 331 | } |
333 | |||
334 | EXPORT_SYMBOL(rxrpc_get_server_data_key); | 332 | EXPORT_SYMBOL(rxrpc_get_server_data_key); |
333 | |||
334 | /** | ||
335 | * rxrpc_get_null_key - Generate a null RxRPC key | ||
336 | * @keyname: The name to give the key. | ||
337 | * | ||
338 | * Generate a null RxRPC key that can be used to indicate anonymous security is | ||
339 | * required for a particular domain. | ||
340 | */ | ||
341 | struct key *rxrpc_get_null_key(const char *keyname) | ||
342 | { | ||
343 | struct key *key; | ||
344 | int ret; | ||
345 | |||
346 | key = key_alloc(&key_type_rxrpc, keyname, 0, 0, current, | ||
347 | KEY_POS_SEARCH, KEY_ALLOC_NOT_IN_QUOTA); | ||
348 | if (IS_ERR(key)) | ||
349 | return key; | ||
350 | |||
351 | ret = key_instantiate_and_link(key, NULL, 0, NULL, NULL); | ||
352 | if (ret < 0) { | ||
353 | key_revoke(key); | ||
354 | key_put(key); | ||
355 | return ERR_PTR(ret); | ||
356 | } | ||
357 | |||
358 | return key; | ||
359 | } | ||
360 | EXPORT_SYMBOL(rxrpc_get_null_key); | ||
diff --git a/net/sched/Kconfig b/net/sched/Kconfig index 92435a882fac..9c15c4888d12 100644 --- a/net/sched/Kconfig +++ b/net/sched/Kconfig | |||
@@ -2,9 +2,7 @@ | |||
2 | # Traffic control configuration. | 2 | # Traffic control configuration. |
3 | # | 3 | # |
4 | 4 | ||
5 | menu "QoS and/or fair queueing" | 5 | menuconfig NET_SCHED |
6 | |||
7 | config NET_SCHED | ||
8 | bool "QoS and/or fair queueing" | 6 | bool "QoS and/or fair queueing" |
9 | select NET_SCH_FIFO | 7 | select NET_SCH_FIFO |
10 | ---help--- | 8 | ---help--- |
@@ -41,9 +39,6 @@ config NET_SCHED | |||
41 | The available schedulers are listed in the following questions; you | 39 | The available schedulers are listed in the following questions; you |
42 | can say Y to as many as you like. If unsure, say N now. | 40 | can say Y to as many as you like. If unsure, say N now. |
43 | 41 | ||
44 | config NET_SCH_FIFO | ||
45 | bool | ||
46 | |||
47 | if NET_SCHED | 42 | if NET_SCHED |
48 | 43 | ||
49 | comment "Queueing/Scheduling" | 44 | comment "Queueing/Scheduling" |
@@ -500,4 +495,5 @@ config NET_CLS_IND | |||
500 | 495 | ||
501 | endif # NET_SCHED | 496 | endif # NET_SCHED |
502 | 497 | ||
503 | endmenu | 498 | config NET_SCH_FIFO |
499 | bool | ||
diff --git a/net/sched/act_ipt.c b/net/sched/act_ipt.c index 6b407ece953c..fa006e06ce33 100644 --- a/net/sched/act_ipt.c +++ b/net/sched/act_ipt.c | |||
@@ -202,11 +202,7 @@ static int tcf_ipt(struct sk_buff *skb, struct tc_action *a, | |||
202 | /* yes, we have to worry about both in and out dev | 202 | /* yes, we have to worry about both in and out dev |
203 | worry later - danger - this API seems to have changed | 203 | worry later - danger - this API seems to have changed |
204 | from earlier kernels */ | 204 | from earlier kernels */ |
205 | 205 | ret = ipt->tcfi_t->u.kernel.target->target(skb, skb->dev, NULL, | |
206 | /* iptables targets take a double skb pointer in case the skb | ||
207 | * needs to be replaced. We don't own the skb, so this must not | ||
208 | * happen. The pskb_expand_head above should make sure of this */ | ||
209 | ret = ipt->tcfi_t->u.kernel.target->target(&skb, skb->dev, NULL, | ||
210 | ipt->tcfi_hook, | 206 | ipt->tcfi_hook, |
211 | ipt->tcfi_t->u.kernel.target, | 207 | ipt->tcfi_t->u.kernel.target, |
212 | ipt->tcfi_t->data); | 208 | ipt->tcfi_t->data); |
diff --git a/net/sched/em_meta.c b/net/sched/em_meta.c index e9989610712c..ceda8890ab0e 100644 --- a/net/sched/em_meta.c +++ b/net/sched/em_meta.c | |||
@@ -55,7 +55,7 @@ | |||
55 | * ppp0..9. | 55 | * ppp0..9. |
56 | * | 56 | * |
57 | * NOTE: Certain meta values depend on other subsystems and are | 57 | * NOTE: Certain meta values depend on other subsystems and are |
58 | * only available if that subsytem is enabled in the kernel. | 58 | * only available if that subsystem is enabled in the kernel. |
59 | */ | 59 | */ |
60 | 60 | ||
61 | #include <linux/module.h> | 61 | #include <linux/module.h> |
diff --git a/net/sched/sch_generic.c b/net/sched/sch_generic.c index 95ae11956f35..fa1a6f45dc41 100644 --- a/net/sched/sch_generic.c +++ b/net/sched/sch_generic.c | |||
@@ -249,10 +249,11 @@ static void dev_watchdog_down(struct net_device *dev) | |||
249 | */ | 249 | */ |
250 | void netif_carrier_on(struct net_device *dev) | 250 | void netif_carrier_on(struct net_device *dev) |
251 | { | 251 | { |
252 | if (test_and_clear_bit(__LINK_STATE_NOCARRIER, &dev->state)) | 252 | if (test_and_clear_bit(__LINK_STATE_NOCARRIER, &dev->state)) { |
253 | linkwatch_fire_event(dev); | 253 | linkwatch_fire_event(dev); |
254 | if (netif_running(dev)) | 254 | if (netif_running(dev)) |
255 | __netdev_watchdog_up(dev); | 255 | __netdev_watchdog_up(dev); |
256 | } | ||
256 | } | 257 | } |
257 | 258 | ||
258 | /** | 259 | /** |
@@ -555,6 +556,7 @@ void dev_deactivate(struct net_device *dev) | |||
555 | { | 556 | { |
556 | struct Qdisc *qdisc; | 557 | struct Qdisc *qdisc; |
557 | struct sk_buff *skb; | 558 | struct sk_buff *skb; |
559 | int running; | ||
558 | 560 | ||
559 | spin_lock_bh(&dev->queue_lock); | 561 | spin_lock_bh(&dev->queue_lock); |
560 | qdisc = dev->qdisc; | 562 | qdisc = dev->qdisc; |
@@ -570,12 +572,31 @@ void dev_deactivate(struct net_device *dev) | |||
570 | 572 | ||
571 | dev_watchdog_down(dev); | 573 | dev_watchdog_down(dev); |
572 | 574 | ||
573 | /* Wait for outstanding dev_queue_xmit calls. */ | 575 | /* Wait for outstanding qdisc-less dev_queue_xmit calls. */ |
574 | synchronize_rcu(); | 576 | synchronize_rcu(); |
575 | 577 | ||
576 | /* Wait for outstanding qdisc_run calls. */ | 578 | /* Wait for outstanding qdisc_run calls. */ |
577 | while (test_bit(__LINK_STATE_QDISC_RUNNING, &dev->state)) | 579 | do { |
578 | yield(); | 580 | while (test_bit(__LINK_STATE_QDISC_RUNNING, &dev->state)) |
581 | yield(); | ||
582 | |||
583 | /* | ||
584 | * Double-check inside queue lock to ensure that all effects | ||
585 | * of the queue run are visible when we return. | ||
586 | */ | ||
587 | spin_lock_bh(&dev->queue_lock); | ||
588 | running = test_bit(__LINK_STATE_QDISC_RUNNING, &dev->state); | ||
589 | spin_unlock_bh(&dev->queue_lock); | ||
590 | |||
591 | /* | ||
592 | * The running flag should never be set at this point because | ||
593 | * we've already set dev->qdisc to noop_qdisc *inside* the same | ||
594 | * pair of spin locks. That is, if any qdisc_run starts after | ||
595 | * our initial test it should see the noop_qdisc and then | ||
596 | * clear the RUNNING bit before dropping the queue lock. So | ||
597 | * if it is set here then we've found a bug. | ||
598 | */ | ||
599 | } while (WARN_ON_ONCE(running)); | ||
579 | } | 600 | } |
580 | 601 | ||
581 | void dev_init_scheduler(struct net_device *dev) | 602 | void dev_init_scheduler(struct net_device *dev) |
diff --git a/net/sched/sch_ingress.c b/net/sched/sch_ingress.c index 2d32fd27496e..3f8335e6ea2e 100644 --- a/net/sched/sch_ingress.c +++ b/net/sched/sch_ingress.c | |||
@@ -205,20 +205,19 @@ static unsigned int ingress_drop(struct Qdisc *sch) | |||
205 | #ifndef CONFIG_NET_CLS_ACT | 205 | #ifndef CONFIG_NET_CLS_ACT |
206 | #ifdef CONFIG_NETFILTER | 206 | #ifdef CONFIG_NETFILTER |
207 | static unsigned int | 207 | static unsigned int |
208 | ing_hook(unsigned int hook, struct sk_buff **pskb, | 208 | ing_hook(unsigned int hook, struct sk_buff *skb, |
209 | const struct net_device *indev, | 209 | const struct net_device *indev, |
210 | const struct net_device *outdev, | 210 | const struct net_device *outdev, |
211 | int (*okfn)(struct sk_buff *)) | 211 | int (*okfn)(struct sk_buff *)) |
212 | { | 212 | { |
213 | 213 | ||
214 | struct Qdisc *q; | 214 | struct Qdisc *q; |
215 | struct sk_buff *skb = *pskb; | ||
216 | struct net_device *dev = skb->dev; | 215 | struct net_device *dev = skb->dev; |
217 | int fwres=NF_ACCEPT; | 216 | int fwres=NF_ACCEPT; |
218 | 217 | ||
219 | DPRINTK("ing_hook: skb %s dev=%s len=%u\n", | 218 | DPRINTK("ing_hook: skb %s dev=%s len=%u\n", |
220 | skb->sk ? "(owned)" : "(unowned)", | 219 | skb->sk ? "(owned)" : "(unowned)", |
221 | skb->dev ? (*pskb)->dev->name : "(no dev)", | 220 | skb->dev ? skb->dev->name : "(no dev)", |
222 | skb->len); | 221 | skb->len); |
223 | 222 | ||
224 | if (dev->qdisc_ingress) { | 223 | if (dev->qdisc_ingress) { |
diff --git a/net/sched/sch_teql.c b/net/sched/sch_teql.c index be57cf317a7f..421281d9dd1d 100644 --- a/net/sched/sch_teql.c +++ b/net/sched/sch_teql.c | |||
@@ -266,7 +266,7 @@ static int teql_master_xmit(struct sk_buff *skb, struct net_device *dev) | |||
266 | int busy; | 266 | int busy; |
267 | int nores; | 267 | int nores; |
268 | int len = skb->len; | 268 | int len = skb->len; |
269 | int subq = skb->queue_mapping; | 269 | int subq = skb_get_queue_mapping(skb); |
270 | struct sk_buff *skb_res = NULL; | 270 | struct sk_buff *skb_res = NULL; |
271 | 271 | ||
272 | start = master->slaves; | 272 | start = master->slaves; |
@@ -284,7 +284,7 @@ restart: | |||
284 | if (slave->qdisc_sleeping != q) | 284 | if (slave->qdisc_sleeping != q) |
285 | continue; | 285 | continue; |
286 | if (netif_queue_stopped(slave) || | 286 | if (netif_queue_stopped(slave) || |
287 | netif_subqueue_stopped(slave, subq) || | 287 | __netif_subqueue_stopped(slave, subq) || |
288 | !netif_running(slave)) { | 288 | !netif_running(slave)) { |
289 | busy = 1; | 289 | busy = 1; |
290 | continue; | 290 | continue; |
@@ -294,7 +294,7 @@ restart: | |||
294 | case 0: | 294 | case 0: |
295 | if (netif_tx_trylock(slave)) { | 295 | if (netif_tx_trylock(slave)) { |
296 | if (!netif_queue_stopped(slave) && | 296 | if (!netif_queue_stopped(slave) && |
297 | !netif_subqueue_stopped(slave, subq) && | 297 | !__netif_subqueue_stopped(slave, subq) && |
298 | slave->hard_start_xmit(skb, slave) == 0) { | 298 | slave->hard_start_xmit(skb, slave) == 0) { |
299 | netif_tx_unlock(slave); | 299 | netif_tx_unlock(slave); |
300 | master->slaves = NEXT_SLAVE(q); | 300 | master->slaves = NEXT_SLAVE(q); |
diff --git a/net/sctp/auth.c b/net/sctp/auth.c index 781810724714..cbd64b216cce 100644 --- a/net/sctp/auth.c +++ b/net/sctp/auth.c | |||
@@ -726,7 +726,8 @@ void sctp_auth_calculate_hmac(const struct sctp_association *asoc, | |||
726 | 726 | ||
727 | /* set up scatter list */ | 727 | /* set up scatter list */ |
728 | end = skb_tail_pointer(skb); | 728 | end = skb_tail_pointer(skb); |
729 | sg.page = virt_to_page(auth); | 729 | sg_init_table(&sg, 1); |
730 | sg_set_page(&sg, virt_to_page(auth)); | ||
730 | sg.offset = (unsigned long)(auth) % PAGE_SIZE; | 731 | sg.offset = (unsigned long)(auth) % PAGE_SIZE; |
731 | sg.length = end - (unsigned char *)auth; | 732 | sg.length = end - (unsigned char *)auth; |
732 | 733 | ||
diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c index 9de3ddaa2768..eb4deaf58914 100644 --- a/net/sctp/ipv6.c +++ b/net/sctp/ipv6.c | |||
@@ -954,9 +954,9 @@ static struct inet_protosw sctpv6_stream_protosw = { | |||
954 | .flags = SCTP_PROTOSW_FLAG, | 954 | .flags = SCTP_PROTOSW_FLAG, |
955 | }; | 955 | }; |
956 | 956 | ||
957 | static int sctp6_rcv(struct sk_buff **pskb) | 957 | static int sctp6_rcv(struct sk_buff *skb) |
958 | { | 958 | { |
959 | return sctp_rcv(*pskb) ? -1 : 0; | 959 | return sctp_rcv(skb) ? -1 : 0; |
960 | } | 960 | } |
961 | 961 | ||
962 | static struct inet6_protocol sctpv6_protocol = { | 962 | static struct inet6_protocol sctpv6_protocol = { |
diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c index 81b26c5ffd4b..f5cd96f5fe74 100644 --- a/net/sctp/protocol.c +++ b/net/sctp/protocol.c | |||
@@ -1228,7 +1228,6 @@ SCTP_STATIC __init int sctp_init(void) | |||
1228 | if (status) | 1228 | if (status) |
1229 | goto err_v6_add_protocol; | 1229 | goto err_v6_add_protocol; |
1230 | 1230 | ||
1231 | __unsafe(THIS_MODULE); | ||
1232 | status = 0; | 1231 | status = 0; |
1233 | out: | 1232 | out: |
1234 | return status; | 1233 | return status; |
diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c index f983a369d4e2..658476c4d587 100644 --- a/net/sctp/sm_make_chunk.c +++ b/net/sctp/sm_make_chunk.c | |||
@@ -56,7 +56,7 @@ | |||
56 | #include <linux/ipv6.h> | 56 | #include <linux/ipv6.h> |
57 | #include <linux/net.h> | 57 | #include <linux/net.h> |
58 | #include <linux/inet.h> | 58 | #include <linux/inet.h> |
59 | #include <asm/scatterlist.h> | 59 | #include <linux/scatterlist.h> |
60 | #include <linux/crypto.h> | 60 | #include <linux/crypto.h> |
61 | #include <net/sock.h> | 61 | #include <net/sock.h> |
62 | 62 | ||
@@ -1513,7 +1513,8 @@ static sctp_cookie_param_t *sctp_pack_cookie(const struct sctp_endpoint *ep, | |||
1513 | struct hash_desc desc; | 1513 | struct hash_desc desc; |
1514 | 1514 | ||
1515 | /* Sign the message. */ | 1515 | /* Sign the message. */ |
1516 | sg.page = virt_to_page(&cookie->c); | 1516 | sg_init_table(&sg, 1); |
1517 | sg_set_page(&sg, virt_to_page(&cookie->c)); | ||
1517 | sg.offset = (unsigned long)(&cookie->c) % PAGE_SIZE; | 1518 | sg.offset = (unsigned long)(&cookie->c) % PAGE_SIZE; |
1518 | sg.length = bodysize; | 1519 | sg.length = bodysize; |
1519 | keylen = SCTP_SECRET_SIZE; | 1520 | keylen = SCTP_SECRET_SIZE; |
@@ -1585,7 +1586,8 @@ struct sctp_association *sctp_unpack_cookie( | |||
1585 | 1586 | ||
1586 | /* Check the signature. */ | 1587 | /* Check the signature. */ |
1587 | keylen = SCTP_SECRET_SIZE; | 1588 | keylen = SCTP_SECRET_SIZE; |
1588 | sg.page = virt_to_page(bear_cookie); | 1589 | sg_init_table(&sg, 1); |
1590 | sg_set_page(&sg, virt_to_page(bear_cookie)); | ||
1589 | sg.offset = (unsigned long)(bear_cookie) % PAGE_SIZE; | 1591 | sg.offset = (unsigned long)(bear_cookie) % PAGE_SIZE; |
1590 | sg.length = bodysize; | 1592 | sg.length = bodysize; |
1591 | key = (char *)ep->secret_key[ep->current_key]; | 1593 | key = (char *)ep->secret_key[ep->current_key]; |
diff --git a/net/socket.c b/net/socket.c index 379b3a390755..540013ea8620 100644 --- a/net/socket.c +++ b/net/socket.c | |||
@@ -258,7 +258,7 @@ static void sock_destroy_inode(struct inode *inode) | |||
258 | container_of(inode, struct socket_alloc, vfs_inode)); | 258 | container_of(inode, struct socket_alloc, vfs_inode)); |
259 | } | 259 | } |
260 | 260 | ||
261 | static void init_once(void *foo, struct kmem_cache *cachep, unsigned long flags) | 261 | static void init_once(struct kmem_cache *cachep, void *foo) |
262 | { | 262 | { |
263 | struct socket_alloc *ei = (struct socket_alloc *)foo; | 263 | struct socket_alloc *ei = (struct socket_alloc *)foo; |
264 | 264 | ||
@@ -364,26 +364,26 @@ static int sock_alloc_fd(struct file **filep) | |||
364 | 364 | ||
365 | static int sock_attach_fd(struct socket *sock, struct file *file) | 365 | static int sock_attach_fd(struct socket *sock, struct file *file) |
366 | { | 366 | { |
367 | struct dentry *dentry; | ||
367 | struct qstr name = { .name = "" }; | 368 | struct qstr name = { .name = "" }; |
368 | 369 | ||
369 | file->f_path.dentry = d_alloc(sock_mnt->mnt_sb->s_root, &name); | 370 | dentry = d_alloc(sock_mnt->mnt_sb->s_root, &name); |
370 | if (unlikely(!file->f_path.dentry)) | 371 | if (unlikely(!dentry)) |
371 | return -ENOMEM; | 372 | return -ENOMEM; |
372 | 373 | ||
373 | file->f_path.dentry->d_op = &sockfs_dentry_operations; | 374 | dentry->d_op = &sockfs_dentry_operations; |
374 | /* | 375 | /* |
375 | * We dont want to push this dentry into global dentry hash table. | 376 | * We dont want to push this dentry into global dentry hash table. |
376 | * We pretend dentry is already hashed, by unsetting DCACHE_UNHASHED | 377 | * We pretend dentry is already hashed, by unsetting DCACHE_UNHASHED |
377 | * This permits a working /proc/$pid/fd/XXX on sockets | 378 | * This permits a working /proc/$pid/fd/XXX on sockets |
378 | */ | 379 | */ |
379 | file->f_path.dentry->d_flags &= ~DCACHE_UNHASHED; | 380 | dentry->d_flags &= ~DCACHE_UNHASHED; |
380 | d_instantiate(file->f_path.dentry, SOCK_INODE(sock)); | 381 | d_instantiate(dentry, SOCK_INODE(sock)); |
381 | file->f_path.mnt = mntget(sock_mnt); | ||
382 | file->f_mapping = file->f_path.dentry->d_inode->i_mapping; | ||
383 | 382 | ||
384 | sock->file = file; | 383 | sock->file = file; |
385 | file->f_op = SOCK_INODE(sock)->i_fop = &socket_file_ops; | 384 | init_file(file, sock_mnt, dentry, FMODE_READ | FMODE_WRITE, |
386 | file->f_mode = FMODE_READ | FMODE_WRITE; | 385 | &socket_file_ops); |
386 | SOCK_INODE(sock)->i_fop = &socket_file_ops; | ||
387 | file->f_flags = O_RDWR; | 387 | file->f_flags = O_RDWR; |
388 | file->f_pos = 0; | 388 | file->f_pos = 0; |
389 | file->private_data = sock; | 389 | file->private_data = sock; |
diff --git a/net/sunrpc/Makefile b/net/sunrpc/Makefile index 8ebfc4db7f51..5c69a725e530 100644 --- a/net/sunrpc/Makefile +++ b/net/sunrpc/Makefile | |||
@@ -5,6 +5,7 @@ | |||
5 | 5 | ||
6 | obj-$(CONFIG_SUNRPC) += sunrpc.o | 6 | obj-$(CONFIG_SUNRPC) += sunrpc.o |
7 | obj-$(CONFIG_SUNRPC_GSS) += auth_gss/ | 7 | obj-$(CONFIG_SUNRPC_GSS) += auth_gss/ |
8 | obj-$(CONFIG_SUNRPC_XPRT_RDMA) += xprtrdma/ | ||
8 | 9 | ||
9 | sunrpc-y := clnt.o xprt.o socklib.o xprtsock.o sched.o \ | 10 | sunrpc-y := clnt.o xprt.o socklib.o xprtsock.o sched.o \ |
10 | auth.o auth_null.o auth_unix.o \ | 11 | auth.o auth_null.o auth_unix.o \ |
diff --git a/net/sunrpc/auth_gss/gss_krb5_crypto.c b/net/sunrpc/auth_gss/gss_krb5_crypto.c index bfb6a29633dd..32be431affcf 100644 --- a/net/sunrpc/auth_gss/gss_krb5_crypto.c +++ b/net/sunrpc/auth_gss/gss_krb5_crypto.c | |||
@@ -197,9 +197,9 @@ encryptor(struct scatterlist *sg, void *data) | |||
197 | int i = (page_pos + outbuf->page_base) >> PAGE_CACHE_SHIFT; | 197 | int i = (page_pos + outbuf->page_base) >> PAGE_CACHE_SHIFT; |
198 | in_page = desc->pages[i]; | 198 | in_page = desc->pages[i]; |
199 | } else { | 199 | } else { |
200 | in_page = sg->page; | 200 | in_page = sg_page(sg); |
201 | } | 201 | } |
202 | desc->infrags[desc->fragno].page = in_page; | 202 | sg_set_page(&desc->infrags[desc->fragno], in_page); |
203 | desc->fragno++; | 203 | desc->fragno++; |
204 | desc->fraglen += sg->length; | 204 | desc->fraglen += sg->length; |
205 | desc->pos += sg->length; | 205 | desc->pos += sg->length; |
@@ -215,11 +215,11 @@ encryptor(struct scatterlist *sg, void *data) | |||
215 | if (ret) | 215 | if (ret) |
216 | return ret; | 216 | return ret; |
217 | if (fraglen) { | 217 | if (fraglen) { |
218 | desc->outfrags[0].page = sg->page; | 218 | sg_set_page(&desc->outfrags[0], sg_page(sg)); |
219 | desc->outfrags[0].offset = sg->offset + sg->length - fraglen; | 219 | desc->outfrags[0].offset = sg->offset + sg->length - fraglen; |
220 | desc->outfrags[0].length = fraglen; | 220 | desc->outfrags[0].length = fraglen; |
221 | desc->infrags[0] = desc->outfrags[0]; | 221 | desc->infrags[0] = desc->outfrags[0]; |
222 | desc->infrags[0].page = in_page; | 222 | sg_set_page(&desc->infrags[0], in_page); |
223 | desc->fragno = 1; | 223 | desc->fragno = 1; |
224 | desc->fraglen = fraglen; | 224 | desc->fraglen = fraglen; |
225 | } else { | 225 | } else { |
@@ -287,7 +287,7 @@ decryptor(struct scatterlist *sg, void *data) | |||
287 | if (ret) | 287 | if (ret) |
288 | return ret; | 288 | return ret; |
289 | if (fraglen) { | 289 | if (fraglen) { |
290 | desc->frags[0].page = sg->page; | 290 | sg_set_page(&desc->frags[0], sg_page(sg)); |
291 | desc->frags[0].offset = sg->offset + sg->length - fraglen; | 291 | desc->frags[0].offset = sg->offset + sg->length - fraglen; |
292 | desc->frags[0].length = fraglen; | 292 | desc->frags[0].length = fraglen; |
293 | desc->fragno = 1; | 293 | desc->fragno = 1; |
diff --git a/net/sunrpc/auth_gss/gss_krb5_wrap.c b/net/sunrpc/auth_gss/gss_krb5_wrap.c index 42b3220bed39..8bd074df27d3 100644 --- a/net/sunrpc/auth_gss/gss_krb5_wrap.c +++ b/net/sunrpc/auth_gss/gss_krb5_wrap.c | |||
@@ -42,7 +42,7 @@ gss_krb5_remove_padding(struct xdr_buf *buf, int blocksize) | |||
42 | { | 42 | { |
43 | u8 *ptr; | 43 | u8 *ptr; |
44 | u8 pad; | 44 | u8 pad; |
45 | int len = buf->len; | 45 | size_t len = buf->len; |
46 | 46 | ||
47 | if (len <= buf->head[0].iov_len) { | 47 | if (len <= buf->head[0].iov_len) { |
48 | pad = *(u8 *)(buf->head[0].iov_base + len - 1); | 48 | pad = *(u8 *)(buf->head[0].iov_base + len - 1); |
@@ -53,9 +53,9 @@ gss_krb5_remove_padding(struct xdr_buf *buf, int blocksize) | |||
53 | } else | 53 | } else |
54 | len -= buf->head[0].iov_len; | 54 | len -= buf->head[0].iov_len; |
55 | if (len <= buf->page_len) { | 55 | if (len <= buf->page_len) { |
56 | int last = (buf->page_base + len - 1) | 56 | unsigned int last = (buf->page_base + len - 1) |
57 | >>PAGE_CACHE_SHIFT; | 57 | >>PAGE_CACHE_SHIFT; |
58 | int offset = (buf->page_base + len - 1) | 58 | unsigned int offset = (buf->page_base + len - 1) |
59 | & (PAGE_CACHE_SIZE - 1); | 59 | & (PAGE_CACHE_SIZE - 1); |
60 | ptr = kmap_atomic(buf->pages[last], KM_USER0); | 60 | ptr = kmap_atomic(buf->pages[last], KM_USER0); |
61 | pad = *(ptr + offset); | 61 | pad = *(ptr + offset); |
diff --git a/net/sunrpc/auth_gss/svcauth_gss.c b/net/sunrpc/auth_gss/svcauth_gss.c index 7da7050f06c3..73940df6c460 100644 --- a/net/sunrpc/auth_gss/svcauth_gss.c +++ b/net/sunrpc/auth_gss/svcauth_gss.c | |||
@@ -631,7 +631,8 @@ svc_safe_putnetobj(struct kvec *resv, struct xdr_netobj *o) | |||
631 | return 0; | 631 | return 0; |
632 | } | 632 | } |
633 | 633 | ||
634 | /* Verify the checksum on the header and return SVC_OK on success. | 634 | /* |
635 | * Verify the checksum on the header and return SVC_OK on success. | ||
635 | * Otherwise, return SVC_DROP (in the case of a bad sequence number) | 636 | * Otherwise, return SVC_DROP (in the case of a bad sequence number) |
636 | * or return SVC_DENIED and indicate error in authp. | 637 | * or return SVC_DENIED and indicate error in authp. |
637 | */ | 638 | */ |
@@ -961,6 +962,78 @@ gss_write_init_verf(struct svc_rqst *rqstp, struct rsi *rsip) | |||
961 | } | 962 | } |
962 | 963 | ||
963 | /* | 964 | /* |
965 | * Having read the cred already and found we're in the context | ||
966 | * initiation case, read the verifier and initiate (or check the results | ||
967 | * of) upcalls to userspace for help with context initiation. If | ||
968 | * the upcall results are available, write the verifier and result. | ||
969 | * Otherwise, drop the request pending an answer to the upcall. | ||
970 | */ | ||
971 | static int svcauth_gss_handle_init(struct svc_rqst *rqstp, | ||
972 | struct rpc_gss_wire_cred *gc, __be32 *authp) | ||
973 | { | ||
974 | struct kvec *argv = &rqstp->rq_arg.head[0]; | ||
975 | struct kvec *resv = &rqstp->rq_res.head[0]; | ||
976 | struct xdr_netobj tmpobj; | ||
977 | struct rsi *rsip, rsikey; | ||
978 | |||
979 | /* Read the verifier; should be NULL: */ | ||
980 | *authp = rpc_autherr_badverf; | ||
981 | if (argv->iov_len < 2 * 4) | ||
982 | return SVC_DENIED; | ||
983 | if (svc_getnl(argv) != RPC_AUTH_NULL) | ||
984 | return SVC_DENIED; | ||
985 | if (svc_getnl(argv) != 0) | ||
986 | return SVC_DENIED; | ||
987 | |||
988 | /* Martial context handle and token for upcall: */ | ||
989 | *authp = rpc_autherr_badcred; | ||
990 | if (gc->gc_proc == RPC_GSS_PROC_INIT && gc->gc_ctx.len != 0) | ||
991 | return SVC_DENIED; | ||
992 | memset(&rsikey, 0, sizeof(rsikey)); | ||
993 | if (dup_netobj(&rsikey.in_handle, &gc->gc_ctx)) | ||
994 | return SVC_DROP; | ||
995 | *authp = rpc_autherr_badverf; | ||
996 | if (svc_safe_getnetobj(argv, &tmpobj)) { | ||
997 | kfree(rsikey.in_handle.data); | ||
998 | return SVC_DENIED; | ||
999 | } | ||
1000 | if (dup_netobj(&rsikey.in_token, &tmpobj)) { | ||
1001 | kfree(rsikey.in_handle.data); | ||
1002 | return SVC_DROP; | ||
1003 | } | ||
1004 | |||
1005 | /* Perform upcall, or find upcall result: */ | ||
1006 | rsip = rsi_lookup(&rsikey); | ||
1007 | rsi_free(&rsikey); | ||
1008 | if (!rsip) | ||
1009 | return SVC_DROP; | ||
1010 | switch (cache_check(&rsi_cache, &rsip->h, &rqstp->rq_chandle)) { | ||
1011 | case -EAGAIN: | ||
1012 | case -ETIMEDOUT: | ||
1013 | case -ENOENT: | ||
1014 | /* No upcall result: */ | ||
1015 | return SVC_DROP; | ||
1016 | case 0: | ||
1017 | /* Got an answer to the upcall; use it: */ | ||
1018 | if (gss_write_init_verf(rqstp, rsip)) | ||
1019 | return SVC_DROP; | ||
1020 | if (resv->iov_len + 4 > PAGE_SIZE) | ||
1021 | return SVC_DROP; | ||
1022 | svc_putnl(resv, RPC_SUCCESS); | ||
1023 | if (svc_safe_putnetobj(resv, &rsip->out_handle)) | ||
1024 | return SVC_DROP; | ||
1025 | if (resv->iov_len + 3 * 4 > PAGE_SIZE) | ||
1026 | return SVC_DROP; | ||
1027 | svc_putnl(resv, rsip->major_status); | ||
1028 | svc_putnl(resv, rsip->minor_status); | ||
1029 | svc_putnl(resv, GSS_SEQ_WIN); | ||
1030 | if (svc_safe_putnetobj(resv, &rsip->out_token)) | ||
1031 | return SVC_DROP; | ||
1032 | } | ||
1033 | return SVC_COMPLETE; | ||
1034 | } | ||
1035 | |||
1036 | /* | ||
964 | * Accept an rpcsec packet. | 1037 | * Accept an rpcsec packet. |
965 | * If context establishment, punt to user space | 1038 | * If context establishment, punt to user space |
966 | * If data exchange, verify/decrypt | 1039 | * If data exchange, verify/decrypt |
@@ -974,11 +1047,9 @@ svcauth_gss_accept(struct svc_rqst *rqstp, __be32 *authp) | |||
974 | struct kvec *argv = &rqstp->rq_arg.head[0]; | 1047 | struct kvec *argv = &rqstp->rq_arg.head[0]; |
975 | struct kvec *resv = &rqstp->rq_res.head[0]; | 1048 | struct kvec *resv = &rqstp->rq_res.head[0]; |
976 | u32 crlen; | 1049 | u32 crlen; |
977 | struct xdr_netobj tmpobj; | ||
978 | struct gss_svc_data *svcdata = rqstp->rq_auth_data; | 1050 | struct gss_svc_data *svcdata = rqstp->rq_auth_data; |
979 | struct rpc_gss_wire_cred *gc; | 1051 | struct rpc_gss_wire_cred *gc; |
980 | struct rsc *rsci = NULL; | 1052 | struct rsc *rsci = NULL; |
981 | struct rsi *rsip, rsikey; | ||
982 | __be32 *rpcstart; | 1053 | __be32 *rpcstart; |
983 | __be32 *reject_stat = resv->iov_base + resv->iov_len; | 1054 | __be32 *reject_stat = resv->iov_base + resv->iov_len; |
984 | int ret; | 1055 | int ret; |
@@ -1023,30 +1094,14 @@ svcauth_gss_accept(struct svc_rqst *rqstp, __be32 *authp) | |||
1023 | if ((gc->gc_proc != RPC_GSS_PROC_DATA) && (rqstp->rq_proc != 0)) | 1094 | if ((gc->gc_proc != RPC_GSS_PROC_DATA) && (rqstp->rq_proc != 0)) |
1024 | goto auth_err; | 1095 | goto auth_err; |
1025 | 1096 | ||
1026 | /* | ||
1027 | * We've successfully parsed the credential. Let's check out the | ||
1028 | * verifier. An AUTH_NULL verifier is allowed (and required) for | ||
1029 | * INIT and CONTINUE_INIT requests. AUTH_RPCSEC_GSS is required for | ||
1030 | * PROC_DATA and PROC_DESTROY. | ||
1031 | * | ||
1032 | * AUTH_NULL verifier is 0 (AUTH_NULL), 0 (length). | ||
1033 | * AUTH_RPCSEC_GSS verifier is: | ||
1034 | * 6 (AUTH_RPCSEC_GSS), length, checksum. | ||
1035 | * checksum is calculated over rpcheader from xid up to here. | ||
1036 | */ | ||
1037 | *authp = rpc_autherr_badverf; | 1097 | *authp = rpc_autherr_badverf; |
1038 | switch (gc->gc_proc) { | 1098 | switch (gc->gc_proc) { |
1039 | case RPC_GSS_PROC_INIT: | 1099 | case RPC_GSS_PROC_INIT: |
1040 | case RPC_GSS_PROC_CONTINUE_INIT: | 1100 | case RPC_GSS_PROC_CONTINUE_INIT: |
1041 | if (argv->iov_len < 2 * 4) | 1101 | return svcauth_gss_handle_init(rqstp, gc, authp); |
1042 | goto auth_err; | ||
1043 | if (svc_getnl(argv) != RPC_AUTH_NULL) | ||
1044 | goto auth_err; | ||
1045 | if (svc_getnl(argv) != 0) | ||
1046 | goto auth_err; | ||
1047 | break; | ||
1048 | case RPC_GSS_PROC_DATA: | 1102 | case RPC_GSS_PROC_DATA: |
1049 | case RPC_GSS_PROC_DESTROY: | 1103 | case RPC_GSS_PROC_DESTROY: |
1104 | /* Look up the context, and check the verifier: */ | ||
1050 | *authp = rpcsec_gsserr_credproblem; | 1105 | *authp = rpcsec_gsserr_credproblem; |
1051 | rsci = gss_svc_searchbyctx(&gc->gc_ctx); | 1106 | rsci = gss_svc_searchbyctx(&gc->gc_ctx); |
1052 | if (!rsci) | 1107 | if (!rsci) |
@@ -1067,51 +1122,6 @@ svcauth_gss_accept(struct svc_rqst *rqstp, __be32 *authp) | |||
1067 | 1122 | ||
1068 | /* now act upon the command: */ | 1123 | /* now act upon the command: */ |
1069 | switch (gc->gc_proc) { | 1124 | switch (gc->gc_proc) { |
1070 | case RPC_GSS_PROC_INIT: | ||
1071 | case RPC_GSS_PROC_CONTINUE_INIT: | ||
1072 | *authp = rpc_autherr_badcred; | ||
1073 | if (gc->gc_proc == RPC_GSS_PROC_INIT && gc->gc_ctx.len != 0) | ||
1074 | goto auth_err; | ||
1075 | memset(&rsikey, 0, sizeof(rsikey)); | ||
1076 | if (dup_netobj(&rsikey.in_handle, &gc->gc_ctx)) | ||
1077 | goto drop; | ||
1078 | *authp = rpc_autherr_badverf; | ||
1079 | if (svc_safe_getnetobj(argv, &tmpobj)) { | ||
1080 | kfree(rsikey.in_handle.data); | ||
1081 | goto auth_err; | ||
1082 | } | ||
1083 | if (dup_netobj(&rsikey.in_token, &tmpobj)) { | ||
1084 | kfree(rsikey.in_handle.data); | ||
1085 | goto drop; | ||
1086 | } | ||
1087 | |||
1088 | rsip = rsi_lookup(&rsikey); | ||
1089 | rsi_free(&rsikey); | ||
1090 | if (!rsip) { | ||
1091 | goto drop; | ||
1092 | } | ||
1093 | switch(cache_check(&rsi_cache, &rsip->h, &rqstp->rq_chandle)) { | ||
1094 | case -EAGAIN: | ||
1095 | case -ETIMEDOUT: | ||
1096 | case -ENOENT: | ||
1097 | goto drop; | ||
1098 | case 0: | ||
1099 | if (gss_write_init_verf(rqstp, rsip)) | ||
1100 | goto drop; | ||
1101 | if (resv->iov_len + 4 > PAGE_SIZE) | ||
1102 | goto drop; | ||
1103 | svc_putnl(resv, RPC_SUCCESS); | ||
1104 | if (svc_safe_putnetobj(resv, &rsip->out_handle)) | ||
1105 | goto drop; | ||
1106 | if (resv->iov_len + 3 * 4 > PAGE_SIZE) | ||
1107 | goto drop; | ||
1108 | svc_putnl(resv, rsip->major_status); | ||
1109 | svc_putnl(resv, rsip->minor_status); | ||
1110 | svc_putnl(resv, GSS_SEQ_WIN); | ||
1111 | if (svc_safe_putnetobj(resv, &rsip->out_token)) | ||
1112 | goto drop; | ||
1113 | } | ||
1114 | goto complete; | ||
1115 | case RPC_GSS_PROC_DESTROY: | 1125 | case RPC_GSS_PROC_DESTROY: |
1116 | if (gss_write_verf(rqstp, rsci->mechctx, gc->gc_seq)) | 1126 | if (gss_write_verf(rqstp, rsci->mechctx, gc->gc_seq)) |
1117 | goto auth_err; | 1127 | goto auth_err; |
@@ -1158,7 +1168,7 @@ svcauth_gss_accept(struct svc_rqst *rqstp, __be32 *authp) | |||
1158 | goto out; | 1168 | goto out; |
1159 | } | 1169 | } |
1160 | auth_err: | 1170 | auth_err: |
1161 | /* Restore write pointer to original value: */ | 1171 | /* Restore write pointer to its original value: */ |
1162 | xdr_ressize_check(rqstp, reject_stat); | 1172 | xdr_ressize_check(rqstp, reject_stat); |
1163 | ret = SVC_DENIED; | 1173 | ret = SVC_DENIED; |
1164 | goto out; | 1174 | goto out; |
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c index 52429b1ffcc1..76be83ee4b04 100644 --- a/net/sunrpc/clnt.c +++ b/net/sunrpc/clnt.c | |||
@@ -127,7 +127,14 @@ static struct rpc_clnt * rpc_new_client(struct rpc_xprt *xprt, char *servname, s | |||
127 | struct rpc_clnt *clnt = NULL; | 127 | struct rpc_clnt *clnt = NULL; |
128 | struct rpc_auth *auth; | 128 | struct rpc_auth *auth; |
129 | int err; | 129 | int err; |
130 | int len; | 130 | size_t len; |
131 | |||
132 | /* sanity check the name before trying to print it */ | ||
133 | err = -EINVAL; | ||
134 | len = strlen(servname); | ||
135 | if (len > RPC_MAXNETNAMELEN) | ||
136 | goto out_no_rpciod; | ||
137 | len++; | ||
131 | 138 | ||
132 | dprintk("RPC: creating %s client for %s (xprt %p)\n", | 139 | dprintk("RPC: creating %s client for %s (xprt %p)\n", |
133 | program->name, servname, xprt); | 140 | program->name, servname, xprt); |
@@ -148,7 +155,6 @@ static struct rpc_clnt * rpc_new_client(struct rpc_xprt *xprt, char *servname, s | |||
148 | clnt->cl_parent = clnt; | 155 | clnt->cl_parent = clnt; |
149 | 156 | ||
150 | clnt->cl_server = clnt->cl_inline_name; | 157 | clnt->cl_server = clnt->cl_inline_name; |
151 | len = strlen(servname) + 1; | ||
152 | if (len > sizeof(clnt->cl_inline_name)) { | 158 | if (len > sizeof(clnt->cl_inline_name)) { |
153 | char *buf = kmalloc(len, GFP_KERNEL); | 159 | char *buf = kmalloc(len, GFP_KERNEL); |
154 | if (buf != 0) | 160 | if (buf != 0) |
@@ -234,8 +240,8 @@ struct rpc_clnt *rpc_create(struct rpc_create_args *args) | |||
234 | { | 240 | { |
235 | struct rpc_xprt *xprt; | 241 | struct rpc_xprt *xprt; |
236 | struct rpc_clnt *clnt; | 242 | struct rpc_clnt *clnt; |
237 | struct rpc_xprtsock_create xprtargs = { | 243 | struct xprt_create xprtargs = { |
238 | .proto = args->protocol, | 244 | .ident = args->protocol, |
239 | .srcaddr = args->saddress, | 245 | .srcaddr = args->saddress, |
240 | .dstaddr = args->address, | 246 | .dstaddr = args->address, |
241 | .addrlen = args->addrsize, | 247 | .addrlen = args->addrsize, |
@@ -253,7 +259,7 @@ struct rpc_clnt *rpc_create(struct rpc_create_args *args) | |||
253 | */ | 259 | */ |
254 | if (args->servername == NULL) { | 260 | if (args->servername == NULL) { |
255 | struct sockaddr_in *addr = | 261 | struct sockaddr_in *addr = |
256 | (struct sockaddr_in *) &args->address; | 262 | (struct sockaddr_in *) args->address; |
257 | snprintf(servername, sizeof(servername), NIPQUAD_FMT, | 263 | snprintf(servername, sizeof(servername), NIPQUAD_FMT, |
258 | NIPQUAD(addr->sin_addr.s_addr)); | 264 | NIPQUAD(addr->sin_addr.s_addr)); |
259 | args->servername = servername; | 265 | args->servername = servername; |
@@ -269,9 +275,6 @@ struct rpc_clnt *rpc_create(struct rpc_create_args *args) | |||
269 | if (args->flags & RPC_CLNT_CREATE_NONPRIVPORT) | 275 | if (args->flags & RPC_CLNT_CREATE_NONPRIVPORT) |
270 | xprt->resvport = 0; | 276 | xprt->resvport = 0; |
271 | 277 | ||
272 | dprintk("RPC: creating %s client for %s (xprt %p)\n", | ||
273 | args->program->name, args->servername, xprt); | ||
274 | |||
275 | clnt = rpc_new_client(xprt, args->servername, args->program, | 278 | clnt = rpc_new_client(xprt, args->servername, args->program, |
276 | args->version, args->authflavor); | 279 | args->version, args->authflavor); |
277 | if (IS_ERR(clnt)) | 280 | if (IS_ERR(clnt)) |
@@ -439,7 +442,7 @@ rpc_release_client(struct rpc_clnt *clnt) | |||
439 | */ | 442 | */ |
440 | struct rpc_clnt *rpc_bind_new_program(struct rpc_clnt *old, | 443 | struct rpc_clnt *rpc_bind_new_program(struct rpc_clnt *old, |
441 | struct rpc_program *program, | 444 | struct rpc_program *program, |
442 | int vers) | 445 | u32 vers) |
443 | { | 446 | { |
444 | struct rpc_clnt *clnt; | 447 | struct rpc_clnt *clnt; |
445 | struct rpc_version *version; | 448 | struct rpc_version *version; |
@@ -843,8 +846,7 @@ call_allocate(struct rpc_task *task) | |||
843 | dprintk("RPC: %5u rpc_buffer allocation failed\n", task->tk_pid); | 846 | dprintk("RPC: %5u rpc_buffer allocation failed\n", task->tk_pid); |
844 | 847 | ||
845 | if (RPC_IS_ASYNC(task) || !signalled()) { | 848 | if (RPC_IS_ASYNC(task) || !signalled()) { |
846 | xprt_release(task); | 849 | task->tk_action = call_allocate; |
847 | task->tk_action = call_reserve; | ||
848 | rpc_delay(task, HZ>>4); | 850 | rpc_delay(task, HZ>>4); |
849 | return; | 851 | return; |
850 | } | 852 | } |
@@ -871,6 +873,7 @@ rpc_xdr_buf_init(struct xdr_buf *buf, void *start, size_t len) | |||
871 | buf->head[0].iov_len = len; | 873 | buf->head[0].iov_len = len; |
872 | buf->tail[0].iov_len = 0; | 874 | buf->tail[0].iov_len = 0; |
873 | buf->page_len = 0; | 875 | buf->page_len = 0; |
876 | buf->flags = 0; | ||
874 | buf->len = 0; | 877 | buf->len = 0; |
875 | buf->buflen = len; | 878 | buf->buflen = len; |
876 | } | 879 | } |
@@ -937,7 +940,7 @@ call_bind(struct rpc_task *task) | |||
937 | static void | 940 | static void |
938 | call_bind_status(struct rpc_task *task) | 941 | call_bind_status(struct rpc_task *task) |
939 | { | 942 | { |
940 | int status = -EACCES; | 943 | int status = -EIO; |
941 | 944 | ||
942 | if (task->tk_status >= 0) { | 945 | if (task->tk_status >= 0) { |
943 | dprint_status(task); | 946 | dprint_status(task); |
@@ -947,9 +950,20 @@ call_bind_status(struct rpc_task *task) | |||
947 | } | 950 | } |
948 | 951 | ||
949 | switch (task->tk_status) { | 952 | switch (task->tk_status) { |
953 | case -EAGAIN: | ||
954 | dprintk("RPC: %5u rpcbind waiting for another request " | ||
955 | "to finish\n", task->tk_pid); | ||
956 | /* avoid busy-waiting here -- could be a network outage. */ | ||
957 | rpc_delay(task, 5*HZ); | ||
958 | goto retry_timeout; | ||
950 | case -EACCES: | 959 | case -EACCES: |
951 | dprintk("RPC: %5u remote rpcbind: RPC program/version " | 960 | dprintk("RPC: %5u remote rpcbind: RPC program/version " |
952 | "unavailable\n", task->tk_pid); | 961 | "unavailable\n", task->tk_pid); |
962 | /* fail immediately if this is an RPC ping */ | ||
963 | if (task->tk_msg.rpc_proc->p_proc == 0) { | ||
964 | status = -EOPNOTSUPP; | ||
965 | break; | ||
966 | } | ||
953 | rpc_delay(task, 3*HZ); | 967 | rpc_delay(task, 3*HZ); |
954 | goto retry_timeout; | 968 | goto retry_timeout; |
955 | case -ETIMEDOUT: | 969 | case -ETIMEDOUT: |
@@ -957,6 +971,7 @@ call_bind_status(struct rpc_task *task) | |||
957 | task->tk_pid); | 971 | task->tk_pid); |
958 | goto retry_timeout; | 972 | goto retry_timeout; |
959 | case -EPFNOSUPPORT: | 973 | case -EPFNOSUPPORT: |
974 | /* server doesn't support any rpcbind version we know of */ | ||
960 | dprintk("RPC: %5u remote rpcbind service unavailable\n", | 975 | dprintk("RPC: %5u remote rpcbind service unavailable\n", |
961 | task->tk_pid); | 976 | task->tk_pid); |
962 | break; | 977 | break; |
@@ -969,7 +984,6 @@ call_bind_status(struct rpc_task *task) | |||
969 | default: | 984 | default: |
970 | dprintk("RPC: %5u unrecognized rpcbind error (%d)\n", | 985 | dprintk("RPC: %5u unrecognized rpcbind error (%d)\n", |
971 | task->tk_pid, -task->tk_status); | 986 | task->tk_pid, -task->tk_status); |
972 | status = -EIO; | ||
973 | } | 987 | } |
974 | 988 | ||
975 | rpc_exit(task, status); | 989 | rpc_exit(task, status); |
@@ -1257,7 +1271,6 @@ call_refresh(struct rpc_task *task) | |||
1257 | { | 1271 | { |
1258 | dprint_status(task); | 1272 | dprint_status(task); |
1259 | 1273 | ||
1260 | xprt_release(task); /* Must do to obtain new XID */ | ||
1261 | task->tk_action = call_refreshresult; | 1274 | task->tk_action = call_refreshresult; |
1262 | task->tk_status = 0; | 1275 | task->tk_status = 0; |
1263 | task->tk_client->cl_stats->rpcauthrefresh++; | 1276 | task->tk_client->cl_stats->rpcauthrefresh++; |
@@ -1375,6 +1388,8 @@ call_verify(struct rpc_task *task) | |||
1375 | dprintk("RPC: %5u %s: retry stale creds\n", | 1388 | dprintk("RPC: %5u %s: retry stale creds\n", |
1376 | task->tk_pid, __FUNCTION__); | 1389 | task->tk_pid, __FUNCTION__); |
1377 | rpcauth_invalcred(task); | 1390 | rpcauth_invalcred(task); |
1391 | /* Ensure we obtain a new XID! */ | ||
1392 | xprt_release(task); | ||
1378 | task->tk_action = call_refresh; | 1393 | task->tk_action = call_refresh; |
1379 | goto out_retry; | 1394 | goto out_retry; |
1380 | case RPC_AUTH_BADCRED: | 1395 | case RPC_AUTH_BADCRED: |
@@ -1523,13 +1538,18 @@ void rpc_show_tasks(void) | |||
1523 | spin_lock(&clnt->cl_lock); | 1538 | spin_lock(&clnt->cl_lock); |
1524 | list_for_each_entry(t, &clnt->cl_tasks, tk_task) { | 1539 | list_for_each_entry(t, &clnt->cl_tasks, tk_task) { |
1525 | const char *rpc_waitq = "none"; | 1540 | const char *rpc_waitq = "none"; |
1541 | int proc; | ||
1542 | |||
1543 | if (t->tk_msg.rpc_proc) | ||
1544 | proc = t->tk_msg.rpc_proc->p_proc; | ||
1545 | else | ||
1546 | proc = -1; | ||
1526 | 1547 | ||
1527 | if (RPC_IS_QUEUED(t)) | 1548 | if (RPC_IS_QUEUED(t)) |
1528 | rpc_waitq = rpc_qname(t->u.tk_wait.rpc_waitq); | 1549 | rpc_waitq = rpc_qname(t->u.tk_wait.rpc_waitq); |
1529 | 1550 | ||
1530 | printk("%5u %04d %04x %6d %8p %6d %8p %8ld %8s %8p %8p\n", | 1551 | printk("%5u %04d %04x %6d %8p %6d %8p %8ld %8s %8p %8p\n", |
1531 | t->tk_pid, | 1552 | t->tk_pid, proc, |
1532 | (t->tk_msg.rpc_proc ? t->tk_msg.rpc_proc->p_proc : -1), | ||
1533 | t->tk_flags, t->tk_status, | 1553 | t->tk_flags, t->tk_status, |
1534 | t->tk_client, | 1554 | t->tk_client, |
1535 | (t->tk_client ? t->tk_client->cl_prog : 0), | 1555 | (t->tk_client ? t->tk_client->cl_prog : 0), |
diff --git a/net/sunrpc/rpc_pipe.c b/net/sunrpc/rpc_pipe.c index 669e12a4ed18..18f0a8dcc095 100644 --- a/net/sunrpc/rpc_pipe.c +++ b/net/sunrpc/rpc_pipe.c | |||
@@ -14,7 +14,7 @@ | |||
14 | #include <linux/pagemap.h> | 14 | #include <linux/pagemap.h> |
15 | #include <linux/mount.h> | 15 | #include <linux/mount.h> |
16 | #include <linux/namei.h> | 16 | #include <linux/namei.h> |
17 | #include <linux/dnotify.h> | 17 | #include <linux/fsnotify.h> |
18 | #include <linux/kernel.h> | 18 | #include <linux/kernel.h> |
19 | 19 | ||
20 | #include <asm/ioctls.h> | 20 | #include <asm/ioctls.h> |
@@ -329,6 +329,7 @@ rpc_show_info(struct seq_file *m, void *v) | |||
329 | clnt->cl_prog, clnt->cl_vers); | 329 | clnt->cl_prog, clnt->cl_vers); |
330 | seq_printf(m, "address: %s\n", rpc_peeraddr2str(clnt, RPC_DISPLAY_ADDR)); | 330 | seq_printf(m, "address: %s\n", rpc_peeraddr2str(clnt, RPC_DISPLAY_ADDR)); |
331 | seq_printf(m, "protocol: %s\n", rpc_peeraddr2str(clnt, RPC_DISPLAY_PROTO)); | 331 | seq_printf(m, "protocol: %s\n", rpc_peeraddr2str(clnt, RPC_DISPLAY_PROTO)); |
332 | seq_printf(m, "port: %s\n", rpc_peeraddr2str(clnt, RPC_DISPLAY_PORT)); | ||
332 | return 0; | 333 | return 0; |
333 | } | 334 | } |
334 | 335 | ||
@@ -585,6 +586,7 @@ rpc_populate(struct dentry *parent, | |||
585 | if (S_ISDIR(mode)) | 586 | if (S_ISDIR(mode)) |
586 | inc_nlink(dir); | 587 | inc_nlink(dir); |
587 | d_add(dentry, inode); | 588 | d_add(dentry, inode); |
589 | fsnotify_create(dir, dentry); | ||
588 | } | 590 | } |
589 | mutex_unlock(&dir->i_mutex); | 591 | mutex_unlock(&dir->i_mutex); |
590 | return 0; | 592 | return 0; |
@@ -606,7 +608,7 @@ __rpc_mkdir(struct inode *dir, struct dentry *dentry) | |||
606 | inode->i_ino = iunique(dir->i_sb, 100); | 608 | inode->i_ino = iunique(dir->i_sb, 100); |
607 | d_instantiate(dentry, inode); | 609 | d_instantiate(dentry, inode); |
608 | inc_nlink(dir); | 610 | inc_nlink(dir); |
609 | inode_dir_notify(dir, DN_CREATE); | 611 | fsnotify_mkdir(dir, dentry); |
610 | return 0; | 612 | return 0; |
611 | out_err: | 613 | out_err: |
612 | printk(KERN_WARNING "%s: %s failed to allocate inode for dentry %s\n", | 614 | printk(KERN_WARNING "%s: %s failed to allocate inode for dentry %s\n", |
@@ -748,7 +750,7 @@ rpc_mkpipe(struct dentry *parent, const char *name, void *private, struct rpc_pi | |||
748 | rpci->flags = flags; | 750 | rpci->flags = flags; |
749 | rpci->ops = ops; | 751 | rpci->ops = ops; |
750 | rpci->nkern_readwriters = 1; | 752 | rpci->nkern_readwriters = 1; |
751 | inode_dir_notify(dir, DN_CREATE); | 753 | fsnotify_create(dir, dentry); |
752 | dget(dentry); | 754 | dget(dentry); |
753 | out: | 755 | out: |
754 | mutex_unlock(&dir->i_mutex); | 756 | mutex_unlock(&dir->i_mutex); |
@@ -840,7 +842,7 @@ static struct file_system_type rpc_pipe_fs_type = { | |||
840 | }; | 842 | }; |
841 | 843 | ||
842 | static void | 844 | static void |
843 | init_once(void * foo, struct kmem_cache * cachep, unsigned long flags) | 845 | init_once(struct kmem_cache * cachep, void *foo) |
844 | { | 846 | { |
845 | struct rpc_inode *rpci = (struct rpc_inode *) foo; | 847 | struct rpc_inode *rpci = (struct rpc_inode *) foo; |
846 | 848 | ||
diff --git a/net/sunrpc/rpcb_clnt.c b/net/sunrpc/rpcb_clnt.c index d1740dbab991..a05493aedb68 100644 --- a/net/sunrpc/rpcb_clnt.c +++ b/net/sunrpc/rpcb_clnt.c | |||
@@ -16,11 +16,14 @@ | |||
16 | 16 | ||
17 | #include <linux/types.h> | 17 | #include <linux/types.h> |
18 | #include <linux/socket.h> | 18 | #include <linux/socket.h> |
19 | #include <linux/in.h> | ||
20 | #include <linux/in6.h> | ||
19 | #include <linux/kernel.h> | 21 | #include <linux/kernel.h> |
20 | #include <linux/errno.h> | 22 | #include <linux/errno.h> |
21 | 23 | ||
22 | #include <linux/sunrpc/clnt.h> | 24 | #include <linux/sunrpc/clnt.h> |
23 | #include <linux/sunrpc/sched.h> | 25 | #include <linux/sunrpc/sched.h> |
26 | #include <linux/sunrpc/xprtsock.h> | ||
24 | 27 | ||
25 | #ifdef RPC_DEBUG | 28 | #ifdef RPC_DEBUG |
26 | # define RPCDBG_FACILITY RPCDBG_BIND | 29 | # define RPCDBG_FACILITY RPCDBG_BIND |
@@ -91,26 +94,6 @@ enum { | |||
91 | #define RPCB_MAXADDRLEN (128u) | 94 | #define RPCB_MAXADDRLEN (128u) |
92 | 95 | ||
93 | /* | 96 | /* |
94 | * r_netid | ||
95 | * | ||
96 | * Quoting RFC 3530, section 2.2: | ||
97 | * | ||
98 | * For TCP over IPv4 the value of r_netid is the string "tcp". For UDP | ||
99 | * over IPv4 the value of r_netid is the string "udp". | ||
100 | * | ||
101 | * ... | ||
102 | * | ||
103 | * For TCP over IPv6 the value of r_netid is the string "tcp6". For UDP | ||
104 | * over IPv6 the value of r_netid is the string "udp6". | ||
105 | */ | ||
106 | #define RPCB_NETID_UDP "\165\144\160" /* "udp" */ | ||
107 | #define RPCB_NETID_TCP "\164\143\160" /* "tcp" */ | ||
108 | #define RPCB_NETID_UDP6 "\165\144\160\066" /* "udp6" */ | ||
109 | #define RPCB_NETID_TCP6 "\164\143\160\066" /* "tcp6" */ | ||
110 | |||
111 | #define RPCB_MAXNETIDLEN (4u) | ||
112 | |||
113 | /* | ||
114 | * r_owner | 97 | * r_owner |
115 | * | 98 | * |
116 | * The "owner" is allowed to unset a service in the rpcbind database. | 99 | * The "owner" is allowed to unset a service in the rpcbind database. |
@@ -120,7 +103,7 @@ enum { | |||
120 | #define RPCB_MAXOWNERLEN sizeof(RPCB_OWNER_STRING) | 103 | #define RPCB_MAXOWNERLEN sizeof(RPCB_OWNER_STRING) |
121 | 104 | ||
122 | static void rpcb_getport_done(struct rpc_task *, void *); | 105 | static void rpcb_getport_done(struct rpc_task *, void *); |
123 | extern struct rpc_program rpcb_program; | 106 | static struct rpc_program rpcb_program; |
124 | 107 | ||
125 | struct rpcbind_args { | 108 | struct rpcbind_args { |
126 | struct rpc_xprt * r_xprt; | 109 | struct rpc_xprt * r_xprt; |
@@ -137,10 +120,13 @@ struct rpcbind_args { | |||
137 | static struct rpc_procinfo rpcb_procedures2[]; | 120 | static struct rpc_procinfo rpcb_procedures2[]; |
138 | static struct rpc_procinfo rpcb_procedures3[]; | 121 | static struct rpc_procinfo rpcb_procedures3[]; |
139 | 122 | ||
140 | static struct rpcb_info { | 123 | struct rpcb_info { |
141 | int rpc_vers; | 124 | int rpc_vers; |
142 | struct rpc_procinfo * rpc_proc; | 125 | struct rpc_procinfo * rpc_proc; |
143 | } rpcb_next_version[]; | 126 | }; |
127 | |||
128 | static struct rpcb_info rpcb_next_version[]; | ||
129 | static struct rpcb_info rpcb_next_version6[]; | ||
144 | 130 | ||
145 | static void rpcb_getport_prepare(struct rpc_task *task, void *calldata) | 131 | static void rpcb_getport_prepare(struct rpc_task *task, void *calldata) |
146 | { | 132 | { |
@@ -190,7 +176,17 @@ static struct rpc_clnt *rpcb_create(char *hostname, struct sockaddr *srvaddr, | |||
190 | RPC_CLNT_CREATE_INTR), | 176 | RPC_CLNT_CREATE_INTR), |
191 | }; | 177 | }; |
192 | 178 | ||
193 | ((struct sockaddr_in *)srvaddr)->sin_port = htons(RPCBIND_PORT); | 179 | switch (srvaddr->sa_family) { |
180 | case AF_INET: | ||
181 | ((struct sockaddr_in *)srvaddr)->sin_port = htons(RPCBIND_PORT); | ||
182 | break; | ||
183 | case AF_INET6: | ||
184 | ((struct sockaddr_in6 *)srvaddr)->sin6_port = htons(RPCBIND_PORT); | ||
185 | break; | ||
186 | default: | ||
187 | return NULL; | ||
188 | } | ||
189 | |||
194 | if (!privileged) | 190 | if (!privileged) |
195 | args.flags |= RPC_CLNT_CREATE_NONPRIVPORT; | 191 | args.flags |= RPC_CLNT_CREATE_NONPRIVPORT; |
196 | return rpc_create(&args); | 192 | return rpc_create(&args); |
@@ -234,7 +230,7 @@ int rpcb_register(u32 prog, u32 vers, int prot, unsigned short port, int *okay) | |||
234 | prog, vers, prot, port); | 230 | prog, vers, prot, port); |
235 | 231 | ||
236 | rpcb_clnt = rpcb_create("localhost", (struct sockaddr *) &sin, | 232 | rpcb_clnt = rpcb_create("localhost", (struct sockaddr *) &sin, |
237 | IPPROTO_UDP, 2, 1); | 233 | XPRT_TRANSPORT_UDP, 2, 1); |
238 | if (IS_ERR(rpcb_clnt)) | 234 | if (IS_ERR(rpcb_clnt)) |
239 | return PTR_ERR(rpcb_clnt); | 235 | return PTR_ERR(rpcb_clnt); |
240 | 236 | ||
@@ -316,6 +312,7 @@ void rpcb_getport_async(struct rpc_task *task) | |||
316 | struct rpc_task *child; | 312 | struct rpc_task *child; |
317 | struct sockaddr addr; | 313 | struct sockaddr addr; |
318 | int status; | 314 | int status; |
315 | struct rpcb_info *info; | ||
319 | 316 | ||
320 | dprintk("RPC: %5u %s(%s, %u, %u, %d)\n", | 317 | dprintk("RPC: %5u %s(%s, %u, %u, %d)\n", |
321 | task->tk_pid, __FUNCTION__, | 318 | task->tk_pid, __FUNCTION__, |
@@ -325,7 +322,7 @@ void rpcb_getport_async(struct rpc_task *task) | |||
325 | BUG_ON(clnt->cl_parent != clnt); | 322 | BUG_ON(clnt->cl_parent != clnt); |
326 | 323 | ||
327 | if (xprt_test_and_set_binding(xprt)) { | 324 | if (xprt_test_and_set_binding(xprt)) { |
328 | status = -EACCES; /* tell caller to check again */ | 325 | status = -EAGAIN; /* tell caller to check again */ |
329 | dprintk("RPC: %5u %s: waiting for another binder\n", | 326 | dprintk("RPC: %5u %s: waiting for another binder\n", |
330 | task->tk_pid, __FUNCTION__); | 327 | task->tk_pid, __FUNCTION__); |
331 | goto bailout_nowake; | 328 | goto bailout_nowake; |
@@ -343,18 +340,43 @@ void rpcb_getport_async(struct rpc_task *task) | |||
343 | goto bailout_nofree; | 340 | goto bailout_nofree; |
344 | } | 341 | } |
345 | 342 | ||
346 | if (rpcb_next_version[xprt->bind_index].rpc_proc == NULL) { | 343 | rpc_peeraddr(clnt, (void *)&addr, sizeof(addr)); |
344 | |||
345 | /* Don't ever use rpcbind v2 for AF_INET6 requests */ | ||
346 | switch (addr.sa_family) { | ||
347 | case AF_INET: | ||
348 | info = rpcb_next_version; | ||
349 | break; | ||
350 | case AF_INET6: | ||
351 | info = rpcb_next_version6; | ||
352 | break; | ||
353 | default: | ||
354 | status = -EAFNOSUPPORT; | ||
355 | dprintk("RPC: %5u %s: bad address family\n", | ||
356 | task->tk_pid, __FUNCTION__); | ||
357 | goto bailout_nofree; | ||
358 | } | ||
359 | if (info[xprt->bind_index].rpc_proc == NULL) { | ||
347 | xprt->bind_index = 0; | 360 | xprt->bind_index = 0; |
348 | status = -EACCES; /* tell caller to try again later */ | 361 | status = -EPFNOSUPPORT; |
349 | dprintk("RPC: %5u %s: no more getport versions available\n", | 362 | dprintk("RPC: %5u %s: no more getport versions available\n", |
350 | task->tk_pid, __FUNCTION__); | 363 | task->tk_pid, __FUNCTION__); |
351 | goto bailout_nofree; | 364 | goto bailout_nofree; |
352 | } | 365 | } |
353 | bind_version = rpcb_next_version[xprt->bind_index].rpc_vers; | 366 | bind_version = info[xprt->bind_index].rpc_vers; |
354 | 367 | ||
355 | dprintk("RPC: %5u %s: trying rpcbind version %u\n", | 368 | dprintk("RPC: %5u %s: trying rpcbind version %u\n", |
356 | task->tk_pid, __FUNCTION__, bind_version); | 369 | task->tk_pid, __FUNCTION__, bind_version); |
357 | 370 | ||
371 | rpcb_clnt = rpcb_create(clnt->cl_server, &addr, xprt->prot, | ||
372 | bind_version, 0); | ||
373 | if (IS_ERR(rpcb_clnt)) { | ||
374 | status = PTR_ERR(rpcb_clnt); | ||
375 | dprintk("RPC: %5u %s: rpcb_create failed, error %ld\n", | ||
376 | task->tk_pid, __FUNCTION__, PTR_ERR(rpcb_clnt)); | ||
377 | goto bailout_nofree; | ||
378 | } | ||
379 | |||
358 | map = kzalloc(sizeof(struct rpcbind_args), GFP_ATOMIC); | 380 | map = kzalloc(sizeof(struct rpcbind_args), GFP_ATOMIC); |
359 | if (!map) { | 381 | if (!map) { |
360 | status = -ENOMEM; | 382 | status = -ENOMEM; |
@@ -367,28 +389,19 @@ void rpcb_getport_async(struct rpc_task *task) | |||
367 | map->r_prot = xprt->prot; | 389 | map->r_prot = xprt->prot; |
368 | map->r_port = 0; | 390 | map->r_port = 0; |
369 | map->r_xprt = xprt_get(xprt); | 391 | map->r_xprt = xprt_get(xprt); |
370 | map->r_netid = (xprt->prot == IPPROTO_TCP) ? RPCB_NETID_TCP : | 392 | map->r_netid = rpc_peeraddr2str(clnt, RPC_DISPLAY_NETID); |
371 | RPCB_NETID_UDP; | 393 | memcpy(map->r_addr, |
372 | memcpy(&map->r_addr, rpc_peeraddr2str(clnt, RPC_DISPLAY_ADDR), | 394 | rpc_peeraddr2str(rpcb_clnt, RPC_DISPLAY_UNIVERSAL_ADDR), |
373 | sizeof(map->r_addr)); | 395 | sizeof(map->r_addr)); |
374 | map->r_owner = RPCB_OWNER_STRING; /* ignored for GETADDR */ | 396 | map->r_owner = RPCB_OWNER_STRING; /* ignored for GETADDR */ |
375 | 397 | ||
376 | rpc_peeraddr(clnt, (void *)&addr, sizeof(addr)); | ||
377 | rpcb_clnt = rpcb_create(clnt->cl_server, &addr, xprt->prot, bind_version, 0); | ||
378 | if (IS_ERR(rpcb_clnt)) { | ||
379 | status = PTR_ERR(rpcb_clnt); | ||
380 | dprintk("RPC: %5u %s: rpcb_create failed, error %ld\n", | ||
381 | task->tk_pid, __FUNCTION__, PTR_ERR(rpcb_clnt)); | ||
382 | goto bailout; | ||
383 | } | ||
384 | |||
385 | child = rpc_run_task(rpcb_clnt, RPC_TASK_ASYNC, &rpcb_getport_ops, map); | 398 | child = rpc_run_task(rpcb_clnt, RPC_TASK_ASYNC, &rpcb_getport_ops, map); |
386 | rpc_release_client(rpcb_clnt); | 399 | rpc_release_client(rpcb_clnt); |
387 | if (IS_ERR(child)) { | 400 | if (IS_ERR(child)) { |
388 | status = -EIO; | 401 | status = -EIO; |
389 | dprintk("RPC: %5u %s: rpc_run_task failed\n", | 402 | dprintk("RPC: %5u %s: rpc_run_task failed\n", |
390 | task->tk_pid, __FUNCTION__); | 403 | task->tk_pid, __FUNCTION__); |
391 | goto bailout_nofree; | 404 | goto bailout; |
392 | } | 405 | } |
393 | rpc_put_task(child); | 406 | rpc_put_task(child); |
394 | 407 | ||
@@ -403,6 +416,7 @@ bailout_nofree: | |||
403 | bailout_nowake: | 416 | bailout_nowake: |
404 | task->tk_status = status; | 417 | task->tk_status = status; |
405 | } | 418 | } |
419 | EXPORT_SYMBOL_GPL(rpcb_getport_async); | ||
406 | 420 | ||
407 | /* | 421 | /* |
408 | * Rpcbind child task calls this callback via tk_exit. | 422 | * Rpcbind child task calls this callback via tk_exit. |
@@ -413,6 +427,10 @@ static void rpcb_getport_done(struct rpc_task *child, void *data) | |||
413 | struct rpc_xprt *xprt = map->r_xprt; | 427 | struct rpc_xprt *xprt = map->r_xprt; |
414 | int status = child->tk_status; | 428 | int status = child->tk_status; |
415 | 429 | ||
430 | /* Garbage reply: retry with a lesser rpcbind version */ | ||
431 | if (status == -EIO) | ||
432 | status = -EPROTONOSUPPORT; | ||
433 | |||
416 | /* rpcbind server doesn't support this rpcbind protocol version */ | 434 | /* rpcbind server doesn't support this rpcbind protocol version */ |
417 | if (status == -EPROTONOSUPPORT) | 435 | if (status == -EPROTONOSUPPORT) |
418 | xprt->bind_index++; | 436 | xprt->bind_index++; |
@@ -490,16 +508,24 @@ static int rpcb_decode_getaddr(struct rpc_rqst *req, __be32 *p, | |||
490 | unsigned short *portp) | 508 | unsigned short *portp) |
491 | { | 509 | { |
492 | char *addr; | 510 | char *addr; |
493 | int addr_len, c, i, f, first, val; | 511 | u32 addr_len; |
512 | int c, i, f, first, val; | ||
494 | 513 | ||
495 | *portp = 0; | 514 | *portp = 0; |
496 | addr_len = (unsigned int) ntohl(*p++); | 515 | addr_len = ntohl(*p++); |
497 | if (addr_len > RPCB_MAXADDRLEN) /* sanity */ | 516 | |
498 | return -EINVAL; | 517 | /* |
499 | 518 | * Simple sanity check. The smallest possible universal | |
500 | dprintk("RPC: rpcb_decode_getaddr returned string: '%s'\n", | 519 | * address is an IPv4 address string containing 11 bytes. |
501 | (char *) p); | 520 | */ |
502 | 521 | if (addr_len < 11 || addr_len > RPCB_MAXADDRLEN) | |
522 | goto out_err; | ||
523 | |||
524 | /* | ||
525 | * Start at the end and walk backwards until the first dot | ||
526 | * is encountered. When the second dot is found, we have | ||
527 | * both parts of the port number. | ||
528 | */ | ||
503 | addr = (char *)p; | 529 | addr = (char *)p; |
504 | val = 0; | 530 | val = 0; |
505 | first = 1; | 531 | first = 1; |
@@ -521,8 +547,19 @@ static int rpcb_decode_getaddr(struct rpc_rqst *req, __be32 *p, | |||
521 | } | 547 | } |
522 | } | 548 | } |
523 | 549 | ||
550 | /* | ||
551 | * Simple sanity check. If we never saw a dot in the reply, | ||
552 | * then this was probably just garbage. | ||
553 | */ | ||
554 | if (first) | ||
555 | goto out_err; | ||
556 | |||
524 | dprintk("RPC: rpcb_decode_getaddr port=%u\n", *portp); | 557 | dprintk("RPC: rpcb_decode_getaddr port=%u\n", *portp); |
525 | return 0; | 558 | return 0; |
559 | |||
560 | out_err: | ||
561 | dprintk("RPC: rpcbind server returned malformed reply\n"); | ||
562 | return -EIO; | ||
526 | } | 563 | } |
527 | 564 | ||
528 | #define RPCB_program_sz (1u) | 565 | #define RPCB_program_sz (1u) |
@@ -531,7 +568,7 @@ static int rpcb_decode_getaddr(struct rpc_rqst *req, __be32 *p, | |||
531 | #define RPCB_port_sz (1u) | 568 | #define RPCB_port_sz (1u) |
532 | #define RPCB_boolean_sz (1u) | 569 | #define RPCB_boolean_sz (1u) |
533 | 570 | ||
534 | #define RPCB_netid_sz (1+XDR_QUADLEN(RPCB_MAXNETIDLEN)) | 571 | #define RPCB_netid_sz (1+XDR_QUADLEN(RPCBIND_MAXNETIDLEN)) |
535 | #define RPCB_addr_sz (1+XDR_QUADLEN(RPCB_MAXADDRLEN)) | 572 | #define RPCB_addr_sz (1+XDR_QUADLEN(RPCB_MAXADDRLEN)) |
536 | #define RPCB_ownerstring_sz (1+XDR_QUADLEN(RPCB_MAXOWNERLEN)) | 573 | #define RPCB_ownerstring_sz (1+XDR_QUADLEN(RPCB_MAXOWNERLEN)) |
537 | 574 | ||
@@ -593,6 +630,14 @@ static struct rpcb_info rpcb_next_version[] = { | |||
593 | { 0, NULL }, | 630 | { 0, NULL }, |
594 | }; | 631 | }; |
595 | 632 | ||
633 | static struct rpcb_info rpcb_next_version6[] = { | ||
634 | #ifdef CONFIG_SUNRPC_BIND34 | ||
635 | { 4, &rpcb_procedures4[RPCBPROC_GETVERSADDR] }, | ||
636 | { 3, &rpcb_procedures3[RPCBPROC_GETADDR] }, | ||
637 | #endif | ||
638 | { 0, NULL }, | ||
639 | }; | ||
640 | |||
596 | static struct rpc_version rpcb_version2 = { | 641 | static struct rpc_version rpcb_version2 = { |
597 | .number = 2, | 642 | .number = 2, |
598 | .nrprocs = RPCB_HIGHPROC_2, | 643 | .nrprocs = RPCB_HIGHPROC_2, |
@@ -621,7 +666,7 @@ static struct rpc_version *rpcb_version[] = { | |||
621 | 666 | ||
622 | static struct rpc_stat rpcb_stats; | 667 | static struct rpc_stat rpcb_stats; |
623 | 668 | ||
624 | struct rpc_program rpcb_program = { | 669 | static struct rpc_program rpcb_program = { |
625 | .name = "rpcbind", | 670 | .name = "rpcbind", |
626 | .number = RPCBIND_PROGRAM, | 671 | .number = RPCBIND_PROGRAM, |
627 | .nrvers = ARRAY_SIZE(rpcb_version), | 672 | .nrvers = ARRAY_SIZE(rpcb_version), |
diff --git a/net/sunrpc/sched.c b/net/sunrpc/sched.c index 954d7ec86c7e..c98873f39aec 100644 --- a/net/sunrpc/sched.c +++ b/net/sunrpc/sched.c | |||
@@ -777,6 +777,7 @@ void *rpc_malloc(struct rpc_task *task, size_t size) | |||
777 | task->tk_pid, size, buf); | 777 | task->tk_pid, size, buf); |
778 | return &buf->data; | 778 | return &buf->data; |
779 | } | 779 | } |
780 | EXPORT_SYMBOL_GPL(rpc_malloc); | ||
780 | 781 | ||
781 | /** | 782 | /** |
782 | * rpc_free - free buffer allocated via rpc_malloc | 783 | * rpc_free - free buffer allocated via rpc_malloc |
@@ -802,6 +803,7 @@ void rpc_free(void *buffer) | |||
802 | else | 803 | else |
803 | kfree(buf); | 804 | kfree(buf); |
804 | } | 805 | } |
806 | EXPORT_SYMBOL_GPL(rpc_free); | ||
805 | 807 | ||
806 | /* | 808 | /* |
807 | * Creation and deletion of RPC task structures | 809 | * Creation and deletion of RPC task structures |
@@ -845,7 +847,7 @@ void rpc_init_task(struct rpc_task *task, struct rpc_clnt *clnt, int flags, cons | |||
845 | task->tk_start = jiffies; | 847 | task->tk_start = jiffies; |
846 | 848 | ||
847 | dprintk("RPC: new task initialized, procpid %u\n", | 849 | dprintk("RPC: new task initialized, procpid %u\n", |
848 | current->pid); | 850 | task_pid_nr(current)); |
849 | } | 851 | } |
850 | 852 | ||
851 | static struct rpc_task * | 853 | static struct rpc_task * |
diff --git a/net/sunrpc/socklib.c b/net/sunrpc/socklib.c index 1d377d1ab7f4..97ac45f034d6 100644 --- a/net/sunrpc/socklib.c +++ b/net/sunrpc/socklib.c | |||
@@ -34,6 +34,7 @@ size_t xdr_skb_read_bits(struct xdr_skb_reader *desc, void *to, size_t len) | |||
34 | desc->offset += len; | 34 | desc->offset += len; |
35 | return len; | 35 | return len; |
36 | } | 36 | } |
37 | EXPORT_SYMBOL_GPL(xdr_skb_read_bits); | ||
37 | 38 | ||
38 | /** | 39 | /** |
39 | * xdr_skb_read_and_csum_bits - copy and checksum from skb to buffer | 40 | * xdr_skb_read_and_csum_bits - copy and checksum from skb to buffer |
@@ -137,6 +138,7 @@ copy_tail: | |||
137 | out: | 138 | out: |
138 | return copied; | 139 | return copied; |
139 | } | 140 | } |
141 | EXPORT_SYMBOL_GPL(xdr_partial_copy_from_skb); | ||
140 | 142 | ||
141 | /** | 143 | /** |
142 | * csum_partial_copy_to_xdr - checksum and copy data | 144 | * csum_partial_copy_to_xdr - checksum and copy data |
@@ -179,3 +181,4 @@ no_checksum: | |||
179 | return -1; | 181 | return -1; |
180 | return 0; | 182 | return 0; |
181 | } | 183 | } |
184 | EXPORT_SYMBOL_GPL(csum_partial_copy_to_xdr); | ||
diff --git a/net/sunrpc/sunrpc_syms.c b/net/sunrpc/sunrpc_syms.c index 384c4ad5ab86..33d89e842c85 100644 --- a/net/sunrpc/sunrpc_syms.c +++ b/net/sunrpc/sunrpc_syms.c | |||
@@ -20,7 +20,7 @@ | |||
20 | #include <linux/sunrpc/auth.h> | 20 | #include <linux/sunrpc/auth.h> |
21 | #include <linux/workqueue.h> | 21 | #include <linux/workqueue.h> |
22 | #include <linux/sunrpc/rpc_pipe_fs.h> | 22 | #include <linux/sunrpc/rpc_pipe_fs.h> |
23 | 23 | #include <linux/sunrpc/xprtsock.h> | |
24 | 24 | ||
25 | /* RPC scheduler */ | 25 | /* RPC scheduler */ |
26 | EXPORT_SYMBOL(rpc_execute); | 26 | EXPORT_SYMBOL(rpc_execute); |
diff --git a/net/sunrpc/svc.c b/net/sunrpc/svc.c index 55ea6df069de..a4a6bf7deaa4 100644 --- a/net/sunrpc/svc.c +++ b/net/sunrpc/svc.c | |||
@@ -777,6 +777,30 @@ svc_register(struct svc_serv *serv, int proto, unsigned short port) | |||
777 | } | 777 | } |
778 | 778 | ||
779 | /* | 779 | /* |
780 | * Printk the given error with the address of the client that caused it. | ||
781 | */ | ||
782 | static int | ||
783 | __attribute__ ((format (printf, 2, 3))) | ||
784 | svc_printk(struct svc_rqst *rqstp, const char *fmt, ...) | ||
785 | { | ||
786 | va_list args; | ||
787 | int r; | ||
788 | char buf[RPC_MAX_ADDRBUFLEN]; | ||
789 | |||
790 | if (!net_ratelimit()) | ||
791 | return 0; | ||
792 | |||
793 | printk(KERN_WARNING "svc: %s: ", | ||
794 | svc_print_addr(rqstp, buf, sizeof(buf))); | ||
795 | |||
796 | va_start(args, fmt); | ||
797 | r = vprintk(fmt, args); | ||
798 | va_end(args); | ||
799 | |||
800 | return r; | ||
801 | } | ||
802 | |||
803 | /* | ||
780 | * Process the RPC request. | 804 | * Process the RPC request. |
781 | */ | 805 | */ |
782 | int | 806 | int |
@@ -963,14 +987,13 @@ svc_process(struct svc_rqst *rqstp) | |||
963 | return 0; | 987 | return 0; |
964 | 988 | ||
965 | err_short_len: | 989 | err_short_len: |
966 | if (net_ratelimit()) | 990 | svc_printk(rqstp, "short len %Zd, dropping request\n", |
967 | printk("svc: short len %Zd, dropping request\n", argv->iov_len); | 991 | argv->iov_len); |
968 | 992 | ||
969 | goto dropit; /* drop request */ | 993 | goto dropit; /* drop request */ |
970 | 994 | ||
971 | err_bad_dir: | 995 | err_bad_dir: |
972 | if (net_ratelimit()) | 996 | svc_printk(rqstp, "bad direction %d, dropping request\n", dir); |
973 | printk("svc: bad direction %d, dropping request\n", dir); | ||
974 | 997 | ||
975 | serv->sv_stats->rpcbadfmt++; | 998 | serv->sv_stats->rpcbadfmt++; |
976 | goto dropit; /* drop request */ | 999 | goto dropit; /* drop request */ |
@@ -1000,8 +1023,7 @@ err_bad_prog: | |||
1000 | goto sendit; | 1023 | goto sendit; |
1001 | 1024 | ||
1002 | err_bad_vers: | 1025 | err_bad_vers: |
1003 | if (net_ratelimit()) | 1026 | svc_printk(rqstp, "unknown version (%d for prog %d, %s)\n", |
1004 | printk("svc: unknown version (%d for prog %d, %s)\n", | ||
1005 | vers, prog, progp->pg_name); | 1027 | vers, prog, progp->pg_name); |
1006 | 1028 | ||
1007 | serv->sv_stats->rpcbadfmt++; | 1029 | serv->sv_stats->rpcbadfmt++; |
@@ -1011,16 +1033,14 @@ err_bad_vers: | |||
1011 | goto sendit; | 1033 | goto sendit; |
1012 | 1034 | ||
1013 | err_bad_proc: | 1035 | err_bad_proc: |
1014 | if (net_ratelimit()) | 1036 | svc_printk(rqstp, "unknown procedure (%d)\n", proc); |
1015 | printk("svc: unknown procedure (%d)\n", proc); | ||
1016 | 1037 | ||
1017 | serv->sv_stats->rpcbadfmt++; | 1038 | serv->sv_stats->rpcbadfmt++; |
1018 | svc_putnl(resv, RPC_PROC_UNAVAIL); | 1039 | svc_putnl(resv, RPC_PROC_UNAVAIL); |
1019 | goto sendit; | 1040 | goto sendit; |
1020 | 1041 | ||
1021 | err_garbage: | 1042 | err_garbage: |
1022 | if (net_ratelimit()) | 1043 | svc_printk(rqstp, "failed to decode args\n"); |
1023 | printk("svc: failed to decode args\n"); | ||
1024 | 1044 | ||
1025 | rpc_stat = rpc_garbage_args; | 1045 | rpc_stat = rpc_garbage_args; |
1026 | err_bad: | 1046 | err_bad: |
diff --git a/net/sunrpc/sysctl.c b/net/sunrpc/sysctl.c index 738db32a287d..864b541bbf51 100644 --- a/net/sunrpc/sysctl.c +++ b/net/sunrpc/sysctl.c | |||
@@ -114,7 +114,6 @@ done: | |||
114 | 114 | ||
115 | static ctl_table debug_table[] = { | 115 | static ctl_table debug_table[] = { |
116 | { | 116 | { |
117 | .ctl_name = CTL_RPCDEBUG, | ||
118 | .procname = "rpc_debug", | 117 | .procname = "rpc_debug", |
119 | .data = &rpc_debug, | 118 | .data = &rpc_debug, |
120 | .maxlen = sizeof(int), | 119 | .maxlen = sizeof(int), |
@@ -122,7 +121,6 @@ static ctl_table debug_table[] = { | |||
122 | .proc_handler = &proc_dodebug | 121 | .proc_handler = &proc_dodebug |
123 | }, | 122 | }, |
124 | { | 123 | { |
125 | .ctl_name = CTL_NFSDEBUG, | ||
126 | .procname = "nfs_debug", | 124 | .procname = "nfs_debug", |
127 | .data = &nfs_debug, | 125 | .data = &nfs_debug, |
128 | .maxlen = sizeof(int), | 126 | .maxlen = sizeof(int), |
@@ -130,7 +128,6 @@ static ctl_table debug_table[] = { | |||
130 | .proc_handler = &proc_dodebug | 128 | .proc_handler = &proc_dodebug |
131 | }, | 129 | }, |
132 | { | 130 | { |
133 | .ctl_name = CTL_NFSDDEBUG, | ||
134 | .procname = "nfsd_debug", | 131 | .procname = "nfsd_debug", |
135 | .data = &nfsd_debug, | 132 | .data = &nfsd_debug, |
136 | .maxlen = sizeof(int), | 133 | .maxlen = sizeof(int), |
@@ -138,7 +135,6 @@ static ctl_table debug_table[] = { | |||
138 | .proc_handler = &proc_dodebug | 135 | .proc_handler = &proc_dodebug |
139 | }, | 136 | }, |
140 | { | 137 | { |
141 | .ctl_name = CTL_NLMDEBUG, | ||
142 | .procname = "nlm_debug", | 138 | .procname = "nlm_debug", |
143 | .data = &nlm_debug, | 139 | .data = &nlm_debug, |
144 | .maxlen = sizeof(int), | 140 | .maxlen = sizeof(int), |
diff --git a/net/sunrpc/timer.c b/net/sunrpc/timer.c index 8142fdb8a930..31becbf09263 100644 --- a/net/sunrpc/timer.c +++ b/net/sunrpc/timer.c | |||
@@ -17,6 +17,7 @@ | |||
17 | 17 | ||
18 | #include <linux/types.h> | 18 | #include <linux/types.h> |
19 | #include <linux/unistd.h> | 19 | #include <linux/unistd.h> |
20 | #include <linux/module.h> | ||
20 | 21 | ||
21 | #include <linux/sunrpc/clnt.h> | 22 | #include <linux/sunrpc/clnt.h> |
22 | 23 | ||
@@ -40,6 +41,7 @@ rpc_init_rtt(struct rpc_rtt *rt, unsigned long timeo) | |||
40 | rt->ntimeouts[i] = 0; | 41 | rt->ntimeouts[i] = 0; |
41 | } | 42 | } |
42 | } | 43 | } |
44 | EXPORT_SYMBOL_GPL(rpc_init_rtt); | ||
43 | 45 | ||
44 | /* | 46 | /* |
45 | * NB: When computing the smoothed RTT and standard deviation, | 47 | * NB: When computing the smoothed RTT and standard deviation, |
@@ -75,6 +77,7 @@ rpc_update_rtt(struct rpc_rtt *rt, unsigned timer, long m) | |||
75 | if (*sdrtt < RPC_RTO_MIN) | 77 | if (*sdrtt < RPC_RTO_MIN) |
76 | *sdrtt = RPC_RTO_MIN; | 78 | *sdrtt = RPC_RTO_MIN; |
77 | } | 79 | } |
80 | EXPORT_SYMBOL_GPL(rpc_update_rtt); | ||
78 | 81 | ||
79 | /* | 82 | /* |
80 | * Estimate rto for an nfs rpc sent via. an unreliable datagram. | 83 | * Estimate rto for an nfs rpc sent via. an unreliable datagram. |
@@ -103,3 +106,4 @@ rpc_calc_rto(struct rpc_rtt *rt, unsigned timer) | |||
103 | 106 | ||
104 | return res; | 107 | return res; |
105 | } | 108 | } |
109 | EXPORT_SYMBOL_GPL(rpc_calc_rto); | ||
diff --git a/net/sunrpc/xdr.c b/net/sunrpc/xdr.c index 6a59180e1667..3d1f7cdf9dd0 100644 --- a/net/sunrpc/xdr.c +++ b/net/sunrpc/xdr.c | |||
@@ -1059,7 +1059,7 @@ xdr_process_buf(struct xdr_buf *buf, unsigned int offset, unsigned int len, | |||
1059 | do { | 1059 | do { |
1060 | if (thislen > page_len) | 1060 | if (thislen > page_len) |
1061 | thislen = page_len; | 1061 | thislen = page_len; |
1062 | sg->page = buf->pages[i]; | 1062 | sg_set_page(sg, buf->pages[i]); |
1063 | sg->offset = page_offset; | 1063 | sg->offset = page_offset; |
1064 | sg->length = thislen; | 1064 | sg->length = thislen; |
1065 | ret = actor(sg, data); | 1065 | ret = actor(sg, data); |
diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c index c8c2edccad7e..282a9a2ec90c 100644 --- a/net/sunrpc/xprt.c +++ b/net/sunrpc/xprt.c | |||
@@ -62,6 +62,9 @@ static inline void do_xprt_reserve(struct rpc_task *); | |||
62 | static void xprt_connect_status(struct rpc_task *task); | 62 | static void xprt_connect_status(struct rpc_task *task); |
63 | static int __xprt_get_cong(struct rpc_xprt *, struct rpc_task *); | 63 | static int __xprt_get_cong(struct rpc_xprt *, struct rpc_task *); |
64 | 64 | ||
65 | static spinlock_t xprt_list_lock = SPIN_LOCK_UNLOCKED; | ||
66 | static LIST_HEAD(xprt_list); | ||
67 | |||
65 | /* | 68 | /* |
66 | * The transport code maintains an estimate on the maximum number of out- | 69 | * The transport code maintains an estimate on the maximum number of out- |
67 | * standing RPC requests, using a smoothed version of the congestion | 70 | * standing RPC requests, using a smoothed version of the congestion |
@@ -81,6 +84,78 @@ static int __xprt_get_cong(struct rpc_xprt *, struct rpc_task *); | |||
81 | #define RPCXPRT_CONGESTED(xprt) ((xprt)->cong >= (xprt)->cwnd) | 84 | #define RPCXPRT_CONGESTED(xprt) ((xprt)->cong >= (xprt)->cwnd) |
82 | 85 | ||
83 | /** | 86 | /** |
87 | * xprt_register_transport - register a transport implementation | ||
88 | * @transport: transport to register | ||
89 | * | ||
90 | * If a transport implementation is loaded as a kernel module, it can | ||
91 | * call this interface to make itself known to the RPC client. | ||
92 | * | ||
93 | * Returns: | ||
94 | * 0: transport successfully registered | ||
95 | * -EEXIST: transport already registered | ||
96 | * -EINVAL: transport module being unloaded | ||
97 | */ | ||
98 | int xprt_register_transport(struct xprt_class *transport) | ||
99 | { | ||
100 | struct xprt_class *t; | ||
101 | int result; | ||
102 | |||
103 | result = -EEXIST; | ||
104 | spin_lock(&xprt_list_lock); | ||
105 | list_for_each_entry(t, &xprt_list, list) { | ||
106 | /* don't register the same transport class twice */ | ||
107 | if (t->ident == transport->ident) | ||
108 | goto out; | ||
109 | } | ||
110 | |||
111 | result = -EINVAL; | ||
112 | if (try_module_get(THIS_MODULE)) { | ||
113 | list_add_tail(&transport->list, &xprt_list); | ||
114 | printk(KERN_INFO "RPC: Registered %s transport module.\n", | ||
115 | transport->name); | ||
116 | result = 0; | ||
117 | } | ||
118 | |||
119 | out: | ||
120 | spin_unlock(&xprt_list_lock); | ||
121 | return result; | ||
122 | } | ||
123 | EXPORT_SYMBOL_GPL(xprt_register_transport); | ||
124 | |||
125 | /** | ||
126 | * xprt_unregister_transport - unregister a transport implementation | ||
127 | * transport: transport to unregister | ||
128 | * | ||
129 | * Returns: | ||
130 | * 0: transport successfully unregistered | ||
131 | * -ENOENT: transport never registered | ||
132 | */ | ||
133 | int xprt_unregister_transport(struct xprt_class *transport) | ||
134 | { | ||
135 | struct xprt_class *t; | ||
136 | int result; | ||
137 | |||
138 | result = 0; | ||
139 | spin_lock(&xprt_list_lock); | ||
140 | list_for_each_entry(t, &xprt_list, list) { | ||
141 | if (t == transport) { | ||
142 | printk(KERN_INFO | ||
143 | "RPC: Unregistered %s transport module.\n", | ||
144 | transport->name); | ||
145 | list_del_init(&transport->list); | ||
146 | module_put(THIS_MODULE); | ||
147 | goto out; | ||
148 | } | ||
149 | } | ||
150 | result = -ENOENT; | ||
151 | |||
152 | out: | ||
153 | spin_unlock(&xprt_list_lock); | ||
154 | return result; | ||
155 | } | ||
156 | EXPORT_SYMBOL_GPL(xprt_unregister_transport); | ||
157 | |||
158 | /** | ||
84 | * xprt_reserve_xprt - serialize write access to transports | 159 | * xprt_reserve_xprt - serialize write access to transports |
85 | * @task: task that is requesting access to the transport | 160 | * @task: task that is requesting access to the transport |
86 | * | 161 | * |
@@ -118,6 +193,7 @@ out_sleep: | |||
118 | rpc_sleep_on(&xprt->sending, task, NULL, NULL); | 193 | rpc_sleep_on(&xprt->sending, task, NULL, NULL); |
119 | return 0; | 194 | return 0; |
120 | } | 195 | } |
196 | EXPORT_SYMBOL_GPL(xprt_reserve_xprt); | ||
121 | 197 | ||
122 | static void xprt_clear_locked(struct rpc_xprt *xprt) | 198 | static void xprt_clear_locked(struct rpc_xprt *xprt) |
123 | { | 199 | { |
@@ -167,6 +243,7 @@ out_sleep: | |||
167 | rpc_sleep_on(&xprt->sending, task, NULL, NULL); | 243 | rpc_sleep_on(&xprt->sending, task, NULL, NULL); |
168 | return 0; | 244 | return 0; |
169 | } | 245 | } |
246 | EXPORT_SYMBOL_GPL(xprt_reserve_xprt_cong); | ||
170 | 247 | ||
171 | static inline int xprt_lock_write(struct rpc_xprt *xprt, struct rpc_task *task) | 248 | static inline int xprt_lock_write(struct rpc_xprt *xprt, struct rpc_task *task) |
172 | { | 249 | { |
@@ -246,6 +323,7 @@ void xprt_release_xprt(struct rpc_xprt *xprt, struct rpc_task *task) | |||
246 | __xprt_lock_write_next(xprt); | 323 | __xprt_lock_write_next(xprt); |
247 | } | 324 | } |
248 | } | 325 | } |
326 | EXPORT_SYMBOL_GPL(xprt_release_xprt); | ||
249 | 327 | ||
250 | /** | 328 | /** |
251 | * xprt_release_xprt_cong - allow other requests to use a transport | 329 | * xprt_release_xprt_cong - allow other requests to use a transport |
@@ -262,6 +340,7 @@ void xprt_release_xprt_cong(struct rpc_xprt *xprt, struct rpc_task *task) | |||
262 | __xprt_lock_write_next_cong(xprt); | 340 | __xprt_lock_write_next_cong(xprt); |
263 | } | 341 | } |
264 | } | 342 | } |
343 | EXPORT_SYMBOL_GPL(xprt_release_xprt_cong); | ||
265 | 344 | ||
266 | static inline void xprt_release_write(struct rpc_xprt *xprt, struct rpc_task *task) | 345 | static inline void xprt_release_write(struct rpc_xprt *xprt, struct rpc_task *task) |
267 | { | 346 | { |
@@ -314,6 +393,7 @@ void xprt_release_rqst_cong(struct rpc_task *task) | |||
314 | { | 393 | { |
315 | __xprt_put_cong(task->tk_xprt, task->tk_rqstp); | 394 | __xprt_put_cong(task->tk_xprt, task->tk_rqstp); |
316 | } | 395 | } |
396 | EXPORT_SYMBOL_GPL(xprt_release_rqst_cong); | ||
317 | 397 | ||
318 | /** | 398 | /** |
319 | * xprt_adjust_cwnd - adjust transport congestion window | 399 | * xprt_adjust_cwnd - adjust transport congestion window |
@@ -345,6 +425,7 @@ void xprt_adjust_cwnd(struct rpc_task *task, int result) | |||
345 | xprt->cwnd = cwnd; | 425 | xprt->cwnd = cwnd; |
346 | __xprt_put_cong(xprt, req); | 426 | __xprt_put_cong(xprt, req); |
347 | } | 427 | } |
428 | EXPORT_SYMBOL_GPL(xprt_adjust_cwnd); | ||
348 | 429 | ||
349 | /** | 430 | /** |
350 | * xprt_wake_pending_tasks - wake all tasks on a transport's pending queue | 431 | * xprt_wake_pending_tasks - wake all tasks on a transport's pending queue |
@@ -359,6 +440,7 @@ void xprt_wake_pending_tasks(struct rpc_xprt *xprt, int status) | |||
359 | else | 440 | else |
360 | rpc_wake_up(&xprt->pending); | 441 | rpc_wake_up(&xprt->pending); |
361 | } | 442 | } |
443 | EXPORT_SYMBOL_GPL(xprt_wake_pending_tasks); | ||
362 | 444 | ||
363 | /** | 445 | /** |
364 | * xprt_wait_for_buffer_space - wait for transport output buffer to clear | 446 | * xprt_wait_for_buffer_space - wait for transport output buffer to clear |
@@ -373,6 +455,7 @@ void xprt_wait_for_buffer_space(struct rpc_task *task) | |||
373 | task->tk_timeout = req->rq_timeout; | 455 | task->tk_timeout = req->rq_timeout; |
374 | rpc_sleep_on(&xprt->pending, task, NULL, NULL); | 456 | rpc_sleep_on(&xprt->pending, task, NULL, NULL); |
375 | } | 457 | } |
458 | EXPORT_SYMBOL_GPL(xprt_wait_for_buffer_space); | ||
376 | 459 | ||
377 | /** | 460 | /** |
378 | * xprt_write_space - wake the task waiting for transport output buffer space | 461 | * xprt_write_space - wake the task waiting for transport output buffer space |
@@ -393,6 +476,7 @@ void xprt_write_space(struct rpc_xprt *xprt) | |||
393 | } | 476 | } |
394 | spin_unlock_bh(&xprt->transport_lock); | 477 | spin_unlock_bh(&xprt->transport_lock); |
395 | } | 478 | } |
479 | EXPORT_SYMBOL_GPL(xprt_write_space); | ||
396 | 480 | ||
397 | /** | 481 | /** |
398 | * xprt_set_retrans_timeout_def - set a request's retransmit timeout | 482 | * xprt_set_retrans_timeout_def - set a request's retransmit timeout |
@@ -406,6 +490,7 @@ void xprt_set_retrans_timeout_def(struct rpc_task *task) | |||
406 | { | 490 | { |
407 | task->tk_timeout = task->tk_rqstp->rq_timeout; | 491 | task->tk_timeout = task->tk_rqstp->rq_timeout; |
408 | } | 492 | } |
493 | EXPORT_SYMBOL_GPL(xprt_set_retrans_timeout_def); | ||
409 | 494 | ||
410 | /* | 495 | /* |
411 | * xprt_set_retrans_timeout_rtt - set a request's retransmit timeout | 496 | * xprt_set_retrans_timeout_rtt - set a request's retransmit timeout |
@@ -425,6 +510,7 @@ void xprt_set_retrans_timeout_rtt(struct rpc_task *task) | |||
425 | if (task->tk_timeout > max_timeout || task->tk_timeout == 0) | 510 | if (task->tk_timeout > max_timeout || task->tk_timeout == 0) |
426 | task->tk_timeout = max_timeout; | 511 | task->tk_timeout = max_timeout; |
427 | } | 512 | } |
513 | EXPORT_SYMBOL_GPL(xprt_set_retrans_timeout_rtt); | ||
428 | 514 | ||
429 | static void xprt_reset_majortimeo(struct rpc_rqst *req) | 515 | static void xprt_reset_majortimeo(struct rpc_rqst *req) |
430 | { | 516 | { |
@@ -500,6 +586,7 @@ void xprt_disconnect(struct rpc_xprt *xprt) | |||
500 | xprt_wake_pending_tasks(xprt, -ENOTCONN); | 586 | xprt_wake_pending_tasks(xprt, -ENOTCONN); |
501 | spin_unlock_bh(&xprt->transport_lock); | 587 | spin_unlock_bh(&xprt->transport_lock); |
502 | } | 588 | } |
589 | EXPORT_SYMBOL_GPL(xprt_disconnect); | ||
503 | 590 | ||
504 | static void | 591 | static void |
505 | xprt_init_autodisconnect(unsigned long data) | 592 | xprt_init_autodisconnect(unsigned long data) |
@@ -610,6 +697,7 @@ struct rpc_rqst *xprt_lookup_rqst(struct rpc_xprt *xprt, __be32 xid) | |||
610 | xprt->stat.bad_xids++; | 697 | xprt->stat.bad_xids++; |
611 | return NULL; | 698 | return NULL; |
612 | } | 699 | } |
700 | EXPORT_SYMBOL_GPL(xprt_lookup_rqst); | ||
613 | 701 | ||
614 | /** | 702 | /** |
615 | * xprt_update_rtt - update an RPC client's RTT state after receiving a reply | 703 | * xprt_update_rtt - update an RPC client's RTT state after receiving a reply |
@@ -629,6 +717,7 @@ void xprt_update_rtt(struct rpc_task *task) | |||
629 | rpc_set_timeo(rtt, timer, req->rq_ntrans - 1); | 717 | rpc_set_timeo(rtt, timer, req->rq_ntrans - 1); |
630 | } | 718 | } |
631 | } | 719 | } |
720 | EXPORT_SYMBOL_GPL(xprt_update_rtt); | ||
632 | 721 | ||
633 | /** | 722 | /** |
634 | * xprt_complete_rqst - called when reply processing is complete | 723 | * xprt_complete_rqst - called when reply processing is complete |
@@ -653,6 +742,7 @@ void xprt_complete_rqst(struct rpc_task *task, int copied) | |||
653 | req->rq_received = req->rq_private_buf.len = copied; | 742 | req->rq_received = req->rq_private_buf.len = copied; |
654 | rpc_wake_up_task(task); | 743 | rpc_wake_up_task(task); |
655 | } | 744 | } |
745 | EXPORT_SYMBOL_GPL(xprt_complete_rqst); | ||
656 | 746 | ||
657 | static void xprt_timer(struct rpc_task *task) | 747 | static void xprt_timer(struct rpc_task *task) |
658 | { | 748 | { |
@@ -889,23 +979,25 @@ void xprt_set_timeout(struct rpc_timeout *to, unsigned int retr, unsigned long i | |||
889 | * @args: rpc transport creation arguments | 979 | * @args: rpc transport creation arguments |
890 | * | 980 | * |
891 | */ | 981 | */ |
892 | struct rpc_xprt *xprt_create_transport(struct rpc_xprtsock_create *args) | 982 | struct rpc_xprt *xprt_create_transport(struct xprt_create *args) |
893 | { | 983 | { |
894 | struct rpc_xprt *xprt; | 984 | struct rpc_xprt *xprt; |
895 | struct rpc_rqst *req; | 985 | struct rpc_rqst *req; |
986 | struct xprt_class *t; | ||
896 | 987 | ||
897 | switch (args->proto) { | 988 | spin_lock(&xprt_list_lock); |
898 | case IPPROTO_UDP: | 989 | list_for_each_entry(t, &xprt_list, list) { |
899 | xprt = xs_setup_udp(args); | 990 | if (t->ident == args->ident) { |
900 | break; | 991 | spin_unlock(&xprt_list_lock); |
901 | case IPPROTO_TCP: | 992 | goto found; |
902 | xprt = xs_setup_tcp(args); | 993 | } |
903 | break; | ||
904 | default: | ||
905 | printk(KERN_ERR "RPC: unrecognized transport protocol: %d\n", | ||
906 | args->proto); | ||
907 | return ERR_PTR(-EIO); | ||
908 | } | 994 | } |
995 | spin_unlock(&xprt_list_lock); | ||
996 | printk(KERN_ERR "RPC: transport (%d) not supported\n", args->ident); | ||
997 | return ERR_PTR(-EIO); | ||
998 | |||
999 | found: | ||
1000 | xprt = t->setup(args); | ||
909 | if (IS_ERR(xprt)) { | 1001 | if (IS_ERR(xprt)) { |
910 | dprintk("RPC: xprt_create_transport: failed, %ld\n", | 1002 | dprintk("RPC: xprt_create_transport: failed, %ld\n", |
911 | -PTR_ERR(xprt)); | 1003 | -PTR_ERR(xprt)); |
diff --git a/net/sunrpc/xprtrdma/Makefile b/net/sunrpc/xprtrdma/Makefile new file mode 100644 index 000000000000..264f0feeb513 --- /dev/null +++ b/net/sunrpc/xprtrdma/Makefile | |||
@@ -0,0 +1,3 @@ | |||
1 | obj-$(CONFIG_SUNRPC_XPRT_RDMA) += xprtrdma.o | ||
2 | |||
3 | xprtrdma-y := transport.o rpc_rdma.o verbs.o | ||
diff --git a/net/sunrpc/xprtrdma/rpc_rdma.c b/net/sunrpc/xprtrdma/rpc_rdma.c new file mode 100644 index 000000000000..12db63580427 --- /dev/null +++ b/net/sunrpc/xprtrdma/rpc_rdma.c | |||
@@ -0,0 +1,868 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2003-2007 Network Appliance, Inc. All rights reserved. | ||
3 | * | ||
4 | * This software is available to you under a choice of one of two | ||
5 | * licenses. You may choose to be licensed under the terms of the GNU | ||
6 | * General Public License (GPL) Version 2, available from the file | ||
7 | * COPYING in the main directory of this source tree, or the BSD-type | ||
8 | * license below: | ||
9 | * | ||
10 | * Redistribution and use in source and binary forms, with or without | ||
11 | * modification, are permitted provided that the following conditions | ||
12 | * are met: | ||
13 | * | ||
14 | * Redistributions of source code must retain the above copyright | ||
15 | * notice, this list of conditions and the following disclaimer. | ||
16 | * | ||
17 | * Redistributions in binary form must reproduce the above | ||
18 | * copyright notice, this list of conditions and the following | ||
19 | * disclaimer in the documentation and/or other materials provided | ||
20 | * with the distribution. | ||
21 | * | ||
22 | * Neither the name of the Network Appliance, Inc. nor the names of | ||
23 | * its contributors may be used to endorse or promote products | ||
24 | * derived from this software without specific prior written | ||
25 | * permission. | ||
26 | * | ||
27 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
28 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
29 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
30 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
31 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
32 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
33 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
34 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
35 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
36 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
37 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
38 | */ | ||
39 | |||
40 | /* | ||
41 | * rpc_rdma.c | ||
42 | * | ||
43 | * This file contains the guts of the RPC RDMA protocol, and | ||
44 | * does marshaling/unmarshaling, etc. It is also where interfacing | ||
45 | * to the Linux RPC framework lives. | ||
46 | */ | ||
47 | |||
48 | #include "xprt_rdma.h" | ||
49 | |||
50 | #include <linux/highmem.h> | ||
51 | |||
52 | #ifdef RPC_DEBUG | ||
53 | # define RPCDBG_FACILITY RPCDBG_TRANS | ||
54 | #endif | ||
55 | |||
56 | enum rpcrdma_chunktype { | ||
57 | rpcrdma_noch = 0, | ||
58 | rpcrdma_readch, | ||
59 | rpcrdma_areadch, | ||
60 | rpcrdma_writech, | ||
61 | rpcrdma_replych | ||
62 | }; | ||
63 | |||
64 | #ifdef RPC_DEBUG | ||
65 | static const char transfertypes[][12] = { | ||
66 | "pure inline", /* no chunks */ | ||
67 | " read chunk", /* some argument via rdma read */ | ||
68 | "*read chunk", /* entire request via rdma read */ | ||
69 | "write chunk", /* some result via rdma write */ | ||
70 | "reply chunk" /* entire reply via rdma write */ | ||
71 | }; | ||
72 | #endif | ||
73 | |||
74 | /* | ||
75 | * Chunk assembly from upper layer xdr_buf. | ||
76 | * | ||
77 | * Prepare the passed-in xdr_buf into representation as RPC/RDMA chunk | ||
78 | * elements. Segments are then coalesced when registered, if possible | ||
79 | * within the selected memreg mode. | ||
80 | * | ||
81 | * Note, this routine is never called if the connection's memory | ||
82 | * registration strategy is 0 (bounce buffers). | ||
83 | */ | ||
84 | |||
85 | static int | ||
86 | rpcrdma_convert_iovs(struct xdr_buf *xdrbuf, int pos, | ||
87 | enum rpcrdma_chunktype type, struct rpcrdma_mr_seg *seg, int nsegs) | ||
88 | { | ||
89 | int len, n = 0, p; | ||
90 | |||
91 | if (pos == 0 && xdrbuf->head[0].iov_len) { | ||
92 | seg[n].mr_page = NULL; | ||
93 | seg[n].mr_offset = xdrbuf->head[0].iov_base; | ||
94 | seg[n].mr_len = xdrbuf->head[0].iov_len; | ||
95 | pos += xdrbuf->head[0].iov_len; | ||
96 | ++n; | ||
97 | } | ||
98 | |||
99 | if (xdrbuf->page_len && (xdrbuf->pages[0] != NULL)) { | ||
100 | if (n == nsegs) | ||
101 | return 0; | ||
102 | seg[n].mr_page = xdrbuf->pages[0]; | ||
103 | seg[n].mr_offset = (void *)(unsigned long) xdrbuf->page_base; | ||
104 | seg[n].mr_len = min_t(u32, | ||
105 | PAGE_SIZE - xdrbuf->page_base, xdrbuf->page_len); | ||
106 | len = xdrbuf->page_len - seg[n].mr_len; | ||
107 | pos += len; | ||
108 | ++n; | ||
109 | p = 1; | ||
110 | while (len > 0) { | ||
111 | if (n == nsegs) | ||
112 | return 0; | ||
113 | seg[n].mr_page = xdrbuf->pages[p]; | ||
114 | seg[n].mr_offset = NULL; | ||
115 | seg[n].mr_len = min_t(u32, PAGE_SIZE, len); | ||
116 | len -= seg[n].mr_len; | ||
117 | ++n; | ||
118 | ++p; | ||
119 | } | ||
120 | } | ||
121 | |||
122 | if (pos < xdrbuf->len && xdrbuf->tail[0].iov_len) { | ||
123 | if (n == nsegs) | ||
124 | return 0; | ||
125 | seg[n].mr_page = NULL; | ||
126 | seg[n].mr_offset = xdrbuf->tail[0].iov_base; | ||
127 | seg[n].mr_len = xdrbuf->tail[0].iov_len; | ||
128 | pos += xdrbuf->tail[0].iov_len; | ||
129 | ++n; | ||
130 | } | ||
131 | |||
132 | if (pos < xdrbuf->len) | ||
133 | dprintk("RPC: %s: marshaled only %d of %d\n", | ||
134 | __func__, pos, xdrbuf->len); | ||
135 | |||
136 | return n; | ||
137 | } | ||
138 | |||
139 | /* | ||
140 | * Create read/write chunk lists, and reply chunks, for RDMA | ||
141 | * | ||
142 | * Assume check against THRESHOLD has been done, and chunks are required. | ||
143 | * Assume only encoding one list entry for read|write chunks. The NFSv3 | ||
144 | * protocol is simple enough to allow this as it only has a single "bulk | ||
145 | * result" in each procedure - complicated NFSv4 COMPOUNDs are not. (The | ||
146 | * RDMA/Sessions NFSv4 proposal addresses this for future v4 revs.) | ||
147 | * | ||
148 | * When used for a single reply chunk (which is a special write | ||
149 | * chunk used for the entire reply, rather than just the data), it | ||
150 | * is used primarily for READDIR and READLINK which would otherwise | ||
151 | * be severely size-limited by a small rdma inline read max. The server | ||
152 | * response will come back as an RDMA Write, followed by a message | ||
153 | * of type RDMA_NOMSG carrying the xid and length. As a result, reply | ||
154 | * chunks do not provide data alignment, however they do not require | ||
155 | * "fixup" (moving the response to the upper layer buffer) either. | ||
156 | * | ||
157 | * Encoding key for single-list chunks (HLOO = Handle32 Length32 Offset64): | ||
158 | * | ||
159 | * Read chunklist (a linked list): | ||
160 | * N elements, position P (same P for all chunks of same arg!): | ||
161 | * 1 - PHLOO - 1 - PHLOO - ... - 1 - PHLOO - 0 | ||
162 | * | ||
163 | * Write chunklist (a list of (one) counted array): | ||
164 | * N elements: | ||
165 | * 1 - N - HLOO - HLOO - ... - HLOO - 0 | ||
166 | * | ||
167 | * Reply chunk (a counted array): | ||
168 | * N elements: | ||
169 | * 1 - N - HLOO - HLOO - ... - HLOO | ||
170 | */ | ||
171 | |||
172 | static unsigned int | ||
173 | rpcrdma_create_chunks(struct rpc_rqst *rqst, struct xdr_buf *target, | ||
174 | struct rpcrdma_msg *headerp, enum rpcrdma_chunktype type) | ||
175 | { | ||
176 | struct rpcrdma_req *req = rpcr_to_rdmar(rqst); | ||
177 | struct rpcrdma_xprt *r_xprt = rpcx_to_rdmax(rqst->rq_task->tk_xprt); | ||
178 | int nsegs, nchunks = 0; | ||
179 | int pos; | ||
180 | struct rpcrdma_mr_seg *seg = req->rl_segments; | ||
181 | struct rpcrdma_read_chunk *cur_rchunk = NULL; | ||
182 | struct rpcrdma_write_array *warray = NULL; | ||
183 | struct rpcrdma_write_chunk *cur_wchunk = NULL; | ||
184 | u32 *iptr = headerp->rm_body.rm_chunks; | ||
185 | |||
186 | if (type == rpcrdma_readch || type == rpcrdma_areadch) { | ||
187 | /* a read chunk - server will RDMA Read our memory */ | ||
188 | cur_rchunk = (struct rpcrdma_read_chunk *) iptr; | ||
189 | } else { | ||
190 | /* a write or reply chunk - server will RDMA Write our memory */ | ||
191 | *iptr++ = xdr_zero; /* encode a NULL read chunk list */ | ||
192 | if (type == rpcrdma_replych) | ||
193 | *iptr++ = xdr_zero; /* a NULL write chunk list */ | ||
194 | warray = (struct rpcrdma_write_array *) iptr; | ||
195 | cur_wchunk = (struct rpcrdma_write_chunk *) (warray + 1); | ||
196 | } | ||
197 | |||
198 | if (type == rpcrdma_replych || type == rpcrdma_areadch) | ||
199 | pos = 0; | ||
200 | else | ||
201 | pos = target->head[0].iov_len; | ||
202 | |||
203 | nsegs = rpcrdma_convert_iovs(target, pos, type, seg, RPCRDMA_MAX_SEGS); | ||
204 | if (nsegs == 0) | ||
205 | return 0; | ||
206 | |||
207 | do { | ||
208 | /* bind/register the memory, then build chunk from result. */ | ||
209 | int n = rpcrdma_register_external(seg, nsegs, | ||
210 | cur_wchunk != NULL, r_xprt); | ||
211 | if (n <= 0) | ||
212 | goto out; | ||
213 | if (cur_rchunk) { /* read */ | ||
214 | cur_rchunk->rc_discrim = xdr_one; | ||
215 | /* all read chunks have the same "position" */ | ||
216 | cur_rchunk->rc_position = htonl(pos); | ||
217 | cur_rchunk->rc_target.rs_handle = htonl(seg->mr_rkey); | ||
218 | cur_rchunk->rc_target.rs_length = htonl(seg->mr_len); | ||
219 | xdr_encode_hyper( | ||
220 | (u32 *)&cur_rchunk->rc_target.rs_offset, | ||
221 | seg->mr_base); | ||
222 | dprintk("RPC: %s: read chunk " | ||
223 | "elem %d@0x%llx:0x%x pos %d (%s)\n", __func__, | ||
224 | seg->mr_len, seg->mr_base, seg->mr_rkey, pos, | ||
225 | n < nsegs ? "more" : "last"); | ||
226 | cur_rchunk++; | ||
227 | r_xprt->rx_stats.read_chunk_count++; | ||
228 | } else { /* write/reply */ | ||
229 | cur_wchunk->wc_target.rs_handle = htonl(seg->mr_rkey); | ||
230 | cur_wchunk->wc_target.rs_length = htonl(seg->mr_len); | ||
231 | xdr_encode_hyper( | ||
232 | (u32 *)&cur_wchunk->wc_target.rs_offset, | ||
233 | seg->mr_base); | ||
234 | dprintk("RPC: %s: %s chunk " | ||
235 | "elem %d@0x%llx:0x%x (%s)\n", __func__, | ||
236 | (type == rpcrdma_replych) ? "reply" : "write", | ||
237 | seg->mr_len, seg->mr_base, seg->mr_rkey, | ||
238 | n < nsegs ? "more" : "last"); | ||
239 | cur_wchunk++; | ||
240 | if (type == rpcrdma_replych) | ||
241 | r_xprt->rx_stats.reply_chunk_count++; | ||
242 | else | ||
243 | r_xprt->rx_stats.write_chunk_count++; | ||
244 | r_xprt->rx_stats.total_rdma_request += seg->mr_len; | ||
245 | } | ||
246 | nchunks++; | ||
247 | seg += n; | ||
248 | nsegs -= n; | ||
249 | } while (nsegs); | ||
250 | |||
251 | /* success. all failures return above */ | ||
252 | req->rl_nchunks = nchunks; | ||
253 | |||
254 | BUG_ON(nchunks == 0); | ||
255 | |||
256 | /* | ||
257 | * finish off header. If write, marshal discrim and nchunks. | ||
258 | */ | ||
259 | if (cur_rchunk) { | ||
260 | iptr = (u32 *) cur_rchunk; | ||
261 | *iptr++ = xdr_zero; /* finish the read chunk list */ | ||
262 | *iptr++ = xdr_zero; /* encode a NULL write chunk list */ | ||
263 | *iptr++ = xdr_zero; /* encode a NULL reply chunk */ | ||
264 | } else { | ||
265 | warray->wc_discrim = xdr_one; | ||
266 | warray->wc_nchunks = htonl(nchunks); | ||
267 | iptr = (u32 *) cur_wchunk; | ||
268 | if (type == rpcrdma_writech) { | ||
269 | *iptr++ = xdr_zero; /* finish the write chunk list */ | ||
270 | *iptr++ = xdr_zero; /* encode a NULL reply chunk */ | ||
271 | } | ||
272 | } | ||
273 | |||
274 | /* | ||
275 | * Return header size. | ||
276 | */ | ||
277 | return (unsigned char *)iptr - (unsigned char *)headerp; | ||
278 | |||
279 | out: | ||
280 | for (pos = 0; nchunks--;) | ||
281 | pos += rpcrdma_deregister_external( | ||
282 | &req->rl_segments[pos], r_xprt, NULL); | ||
283 | return 0; | ||
284 | } | ||
285 | |||
286 | /* | ||
287 | * Copy write data inline. | ||
288 | * This function is used for "small" requests. Data which is passed | ||
289 | * to RPC via iovecs (or page list) is copied directly into the | ||
290 | * pre-registered memory buffer for this request. For small amounts | ||
291 | * of data, this is efficient. The cutoff value is tunable. | ||
292 | */ | ||
293 | static int | ||
294 | rpcrdma_inline_pullup(struct rpc_rqst *rqst, int pad) | ||
295 | { | ||
296 | int i, npages, curlen; | ||
297 | int copy_len; | ||
298 | unsigned char *srcp, *destp; | ||
299 | struct rpcrdma_xprt *r_xprt = rpcx_to_rdmax(rqst->rq_xprt); | ||
300 | |||
301 | destp = rqst->rq_svec[0].iov_base; | ||
302 | curlen = rqst->rq_svec[0].iov_len; | ||
303 | destp += curlen; | ||
304 | /* | ||
305 | * Do optional padding where it makes sense. Alignment of write | ||
306 | * payload can help the server, if our setting is accurate. | ||
307 | */ | ||
308 | pad -= (curlen + 36/*sizeof(struct rpcrdma_msg_padded)*/); | ||
309 | if (pad < 0 || rqst->rq_slen - curlen < RPCRDMA_INLINE_PAD_THRESH) | ||
310 | pad = 0; /* don't pad this request */ | ||
311 | |||
312 | dprintk("RPC: %s: pad %d destp 0x%p len %d hdrlen %d\n", | ||
313 | __func__, pad, destp, rqst->rq_slen, curlen); | ||
314 | |||
315 | copy_len = rqst->rq_snd_buf.page_len; | ||
316 | r_xprt->rx_stats.pullup_copy_count += copy_len; | ||
317 | npages = PAGE_ALIGN(rqst->rq_snd_buf.page_base+copy_len) >> PAGE_SHIFT; | ||
318 | for (i = 0; copy_len && i < npages; i++) { | ||
319 | if (i == 0) | ||
320 | curlen = PAGE_SIZE - rqst->rq_snd_buf.page_base; | ||
321 | else | ||
322 | curlen = PAGE_SIZE; | ||
323 | if (curlen > copy_len) | ||
324 | curlen = copy_len; | ||
325 | dprintk("RPC: %s: page %d destp 0x%p len %d curlen %d\n", | ||
326 | __func__, i, destp, copy_len, curlen); | ||
327 | srcp = kmap_atomic(rqst->rq_snd_buf.pages[i], | ||
328 | KM_SKB_SUNRPC_DATA); | ||
329 | if (i == 0) | ||
330 | memcpy(destp, srcp+rqst->rq_snd_buf.page_base, curlen); | ||
331 | else | ||
332 | memcpy(destp, srcp, curlen); | ||
333 | kunmap_atomic(srcp, KM_SKB_SUNRPC_DATA); | ||
334 | rqst->rq_svec[0].iov_len += curlen; | ||
335 | destp += curlen; | ||
336 | copy_len -= curlen; | ||
337 | } | ||
338 | if (rqst->rq_snd_buf.tail[0].iov_len) { | ||
339 | curlen = rqst->rq_snd_buf.tail[0].iov_len; | ||
340 | if (destp != rqst->rq_snd_buf.tail[0].iov_base) { | ||
341 | memcpy(destp, | ||
342 | rqst->rq_snd_buf.tail[0].iov_base, curlen); | ||
343 | r_xprt->rx_stats.pullup_copy_count += curlen; | ||
344 | } | ||
345 | dprintk("RPC: %s: tail destp 0x%p len %d curlen %d\n", | ||
346 | __func__, destp, copy_len, curlen); | ||
347 | rqst->rq_svec[0].iov_len += curlen; | ||
348 | } | ||
349 | /* header now contains entire send message */ | ||
350 | return pad; | ||
351 | } | ||
352 | |||
353 | /* | ||
354 | * Marshal a request: the primary job of this routine is to choose | ||
355 | * the transfer modes. See comments below. | ||
356 | * | ||
357 | * Uses multiple RDMA IOVs for a request: | ||
358 | * [0] -- RPC RDMA header, which uses memory from the *start* of the | ||
359 | * preregistered buffer that already holds the RPC data in | ||
360 | * its middle. | ||
361 | * [1] -- the RPC header/data, marshaled by RPC and the NFS protocol. | ||
362 | * [2] -- optional padding. | ||
363 | * [3] -- if padded, header only in [1] and data here. | ||
364 | */ | ||
365 | |||
366 | int | ||
367 | rpcrdma_marshal_req(struct rpc_rqst *rqst) | ||
368 | { | ||
369 | struct rpc_xprt *xprt = rqst->rq_task->tk_xprt; | ||
370 | struct rpcrdma_xprt *r_xprt = rpcx_to_rdmax(xprt); | ||
371 | struct rpcrdma_req *req = rpcr_to_rdmar(rqst); | ||
372 | char *base; | ||
373 | size_t hdrlen, rpclen, padlen; | ||
374 | enum rpcrdma_chunktype rtype, wtype; | ||
375 | struct rpcrdma_msg *headerp; | ||
376 | |||
377 | /* | ||
378 | * rpclen gets amount of data in first buffer, which is the | ||
379 | * pre-registered buffer. | ||
380 | */ | ||
381 | base = rqst->rq_svec[0].iov_base; | ||
382 | rpclen = rqst->rq_svec[0].iov_len; | ||
383 | |||
384 | /* build RDMA header in private area at front */ | ||
385 | headerp = (struct rpcrdma_msg *) req->rl_base; | ||
386 | /* don't htonl XID, it's already done in request */ | ||
387 | headerp->rm_xid = rqst->rq_xid; | ||
388 | headerp->rm_vers = xdr_one; | ||
389 | headerp->rm_credit = htonl(r_xprt->rx_buf.rb_max_requests); | ||
390 | headerp->rm_type = __constant_htonl(RDMA_MSG); | ||
391 | |||
392 | /* | ||
393 | * Chunks needed for results? | ||
394 | * | ||
395 | * o If the expected result is under the inline threshold, all ops | ||
396 | * return as inline (but see later). | ||
397 | * o Large non-read ops return as a single reply chunk. | ||
398 | * o Large read ops return data as write chunk(s), header as inline. | ||
399 | * | ||
400 | * Note: the NFS code sending down multiple result segments implies | ||
401 | * the op is one of read, readdir[plus], readlink or NFSv4 getacl. | ||
402 | */ | ||
403 | |||
404 | /* | ||
405 | * This code can handle read chunks, write chunks OR reply | ||
406 | * chunks -- only one type. If the request is too big to fit | ||
407 | * inline, then we will choose read chunks. If the request is | ||
408 | * a READ, then use write chunks to separate the file data | ||
409 | * into pages; otherwise use reply chunks. | ||
410 | */ | ||
411 | if (rqst->rq_rcv_buf.buflen <= RPCRDMA_INLINE_READ_THRESHOLD(rqst)) | ||
412 | wtype = rpcrdma_noch; | ||
413 | else if (rqst->rq_rcv_buf.page_len == 0) | ||
414 | wtype = rpcrdma_replych; | ||
415 | else if (rqst->rq_rcv_buf.flags & XDRBUF_READ) | ||
416 | wtype = rpcrdma_writech; | ||
417 | else | ||
418 | wtype = rpcrdma_replych; | ||
419 | |||
420 | /* | ||
421 | * Chunks needed for arguments? | ||
422 | * | ||
423 | * o If the total request is under the inline threshold, all ops | ||
424 | * are sent as inline. | ||
425 | * o Large non-write ops are sent with the entire message as a | ||
426 | * single read chunk (protocol 0-position special case). | ||
427 | * o Large write ops transmit data as read chunk(s), header as | ||
428 | * inline. | ||
429 | * | ||
430 | * Note: the NFS code sending down multiple argument segments | ||
431 | * implies the op is a write. | ||
432 | * TBD check NFSv4 setacl | ||
433 | */ | ||
434 | if (rqst->rq_snd_buf.len <= RPCRDMA_INLINE_WRITE_THRESHOLD(rqst)) | ||
435 | rtype = rpcrdma_noch; | ||
436 | else if (rqst->rq_snd_buf.page_len == 0) | ||
437 | rtype = rpcrdma_areadch; | ||
438 | else | ||
439 | rtype = rpcrdma_readch; | ||
440 | |||
441 | /* The following simplification is not true forever */ | ||
442 | if (rtype != rpcrdma_noch && wtype == rpcrdma_replych) | ||
443 | wtype = rpcrdma_noch; | ||
444 | BUG_ON(rtype != rpcrdma_noch && wtype != rpcrdma_noch); | ||
445 | |||
446 | if (r_xprt->rx_ia.ri_memreg_strategy == RPCRDMA_BOUNCEBUFFERS && | ||
447 | (rtype != rpcrdma_noch || wtype != rpcrdma_noch)) { | ||
448 | /* forced to "pure inline"? */ | ||
449 | dprintk("RPC: %s: too much data (%d/%d) for inline\n", | ||
450 | __func__, rqst->rq_rcv_buf.len, rqst->rq_snd_buf.len); | ||
451 | return -1; | ||
452 | } | ||
453 | |||
454 | hdrlen = 28; /*sizeof *headerp;*/ | ||
455 | padlen = 0; | ||
456 | |||
457 | /* | ||
458 | * Pull up any extra send data into the preregistered buffer. | ||
459 | * When padding is in use and applies to the transfer, insert | ||
460 | * it and change the message type. | ||
461 | */ | ||
462 | if (rtype == rpcrdma_noch) { | ||
463 | |||
464 | padlen = rpcrdma_inline_pullup(rqst, | ||
465 | RPCRDMA_INLINE_PAD_VALUE(rqst)); | ||
466 | |||
467 | if (padlen) { | ||
468 | headerp->rm_type = __constant_htonl(RDMA_MSGP); | ||
469 | headerp->rm_body.rm_padded.rm_align = | ||
470 | htonl(RPCRDMA_INLINE_PAD_VALUE(rqst)); | ||
471 | headerp->rm_body.rm_padded.rm_thresh = | ||
472 | __constant_htonl(RPCRDMA_INLINE_PAD_THRESH); | ||
473 | headerp->rm_body.rm_padded.rm_pempty[0] = xdr_zero; | ||
474 | headerp->rm_body.rm_padded.rm_pempty[1] = xdr_zero; | ||
475 | headerp->rm_body.rm_padded.rm_pempty[2] = xdr_zero; | ||
476 | hdrlen += 2 * sizeof(u32); /* extra words in padhdr */ | ||
477 | BUG_ON(wtype != rpcrdma_noch); | ||
478 | |||
479 | } else { | ||
480 | headerp->rm_body.rm_nochunks.rm_empty[0] = xdr_zero; | ||
481 | headerp->rm_body.rm_nochunks.rm_empty[1] = xdr_zero; | ||
482 | headerp->rm_body.rm_nochunks.rm_empty[2] = xdr_zero; | ||
483 | /* new length after pullup */ | ||
484 | rpclen = rqst->rq_svec[0].iov_len; | ||
485 | /* | ||
486 | * Currently we try to not actually use read inline. | ||
487 | * Reply chunks have the desirable property that | ||
488 | * they land, packed, directly in the target buffers | ||
489 | * without headers, so they require no fixup. The | ||
490 | * additional RDMA Write op sends the same amount | ||
491 | * of data, streams on-the-wire and adds no overhead | ||
492 | * on receive. Therefore, we request a reply chunk | ||
493 | * for non-writes wherever feasible and efficient. | ||
494 | */ | ||
495 | if (wtype == rpcrdma_noch && | ||
496 | r_xprt->rx_ia.ri_memreg_strategy > RPCRDMA_REGISTER) | ||
497 | wtype = rpcrdma_replych; | ||
498 | } | ||
499 | } | ||
500 | |||
501 | /* | ||
502 | * Marshal chunks. This routine will return the header length | ||
503 | * consumed by marshaling. | ||
504 | */ | ||
505 | if (rtype != rpcrdma_noch) { | ||
506 | hdrlen = rpcrdma_create_chunks(rqst, | ||
507 | &rqst->rq_snd_buf, headerp, rtype); | ||
508 | wtype = rtype; /* simplify dprintk */ | ||
509 | |||
510 | } else if (wtype != rpcrdma_noch) { | ||
511 | hdrlen = rpcrdma_create_chunks(rqst, | ||
512 | &rqst->rq_rcv_buf, headerp, wtype); | ||
513 | } | ||
514 | |||
515 | if (hdrlen == 0) | ||
516 | return -1; | ||
517 | |||
518 | dprintk("RPC: %s: %s: hdrlen %zd rpclen %zd padlen %zd\n" | ||
519 | " headerp 0x%p base 0x%p lkey 0x%x\n", | ||
520 | __func__, transfertypes[wtype], hdrlen, rpclen, padlen, | ||
521 | headerp, base, req->rl_iov.lkey); | ||
522 | |||
523 | /* | ||
524 | * initialize send_iov's - normally only two: rdma chunk header and | ||
525 | * single preregistered RPC header buffer, but if padding is present, | ||
526 | * then use a preregistered (and zeroed) pad buffer between the RPC | ||
527 | * header and any write data. In all non-rdma cases, any following | ||
528 | * data has been copied into the RPC header buffer. | ||
529 | */ | ||
530 | req->rl_send_iov[0].addr = req->rl_iov.addr; | ||
531 | req->rl_send_iov[0].length = hdrlen; | ||
532 | req->rl_send_iov[0].lkey = req->rl_iov.lkey; | ||
533 | |||
534 | req->rl_send_iov[1].addr = req->rl_iov.addr + (base - req->rl_base); | ||
535 | req->rl_send_iov[1].length = rpclen; | ||
536 | req->rl_send_iov[1].lkey = req->rl_iov.lkey; | ||
537 | |||
538 | req->rl_niovs = 2; | ||
539 | |||
540 | if (padlen) { | ||
541 | struct rpcrdma_ep *ep = &r_xprt->rx_ep; | ||
542 | |||
543 | req->rl_send_iov[2].addr = ep->rep_pad.addr; | ||
544 | req->rl_send_iov[2].length = padlen; | ||
545 | req->rl_send_iov[2].lkey = ep->rep_pad.lkey; | ||
546 | |||
547 | req->rl_send_iov[3].addr = req->rl_send_iov[1].addr + rpclen; | ||
548 | req->rl_send_iov[3].length = rqst->rq_slen - rpclen; | ||
549 | req->rl_send_iov[3].lkey = req->rl_iov.lkey; | ||
550 | |||
551 | req->rl_niovs = 4; | ||
552 | } | ||
553 | |||
554 | return 0; | ||
555 | } | ||
556 | |||
557 | /* | ||
558 | * Chase down a received write or reply chunklist to get length | ||
559 | * RDMA'd by server. See map at rpcrdma_create_chunks()! :-) | ||
560 | */ | ||
561 | static int | ||
562 | rpcrdma_count_chunks(struct rpcrdma_rep *rep, int max, int wrchunk, u32 **iptrp) | ||
563 | { | ||
564 | unsigned int i, total_len; | ||
565 | struct rpcrdma_write_chunk *cur_wchunk; | ||
566 | |||
567 | i = ntohl(**iptrp); /* get array count */ | ||
568 | if (i > max) | ||
569 | return -1; | ||
570 | cur_wchunk = (struct rpcrdma_write_chunk *) (*iptrp + 1); | ||
571 | total_len = 0; | ||
572 | while (i--) { | ||
573 | struct rpcrdma_segment *seg = &cur_wchunk->wc_target; | ||
574 | ifdebug(FACILITY) { | ||
575 | u64 off; | ||
576 | xdr_decode_hyper((u32 *)&seg->rs_offset, &off); | ||
577 | dprintk("RPC: %s: chunk %d@0x%llx:0x%x\n", | ||
578 | __func__, | ||
579 | ntohl(seg->rs_length), | ||
580 | off, | ||
581 | ntohl(seg->rs_handle)); | ||
582 | } | ||
583 | total_len += ntohl(seg->rs_length); | ||
584 | ++cur_wchunk; | ||
585 | } | ||
586 | /* check and adjust for properly terminated write chunk */ | ||
587 | if (wrchunk) { | ||
588 | u32 *w = (u32 *) cur_wchunk; | ||
589 | if (*w++ != xdr_zero) | ||
590 | return -1; | ||
591 | cur_wchunk = (struct rpcrdma_write_chunk *) w; | ||
592 | } | ||
593 | if ((char *) cur_wchunk > rep->rr_base + rep->rr_len) | ||
594 | return -1; | ||
595 | |||
596 | *iptrp = (u32 *) cur_wchunk; | ||
597 | return total_len; | ||
598 | } | ||
599 | |||
600 | /* | ||
601 | * Scatter inline received data back into provided iov's. | ||
602 | */ | ||
603 | static void | ||
604 | rpcrdma_inline_fixup(struct rpc_rqst *rqst, char *srcp, int copy_len) | ||
605 | { | ||
606 | int i, npages, curlen, olen; | ||
607 | char *destp; | ||
608 | |||
609 | curlen = rqst->rq_rcv_buf.head[0].iov_len; | ||
610 | if (curlen > copy_len) { /* write chunk header fixup */ | ||
611 | curlen = copy_len; | ||
612 | rqst->rq_rcv_buf.head[0].iov_len = curlen; | ||
613 | } | ||
614 | |||
615 | dprintk("RPC: %s: srcp 0x%p len %d hdrlen %d\n", | ||
616 | __func__, srcp, copy_len, curlen); | ||
617 | |||
618 | /* Shift pointer for first receive segment only */ | ||
619 | rqst->rq_rcv_buf.head[0].iov_base = srcp; | ||
620 | srcp += curlen; | ||
621 | copy_len -= curlen; | ||
622 | |||
623 | olen = copy_len; | ||
624 | i = 0; | ||
625 | rpcx_to_rdmax(rqst->rq_xprt)->rx_stats.fixup_copy_count += olen; | ||
626 | if (copy_len && rqst->rq_rcv_buf.page_len) { | ||
627 | npages = PAGE_ALIGN(rqst->rq_rcv_buf.page_base + | ||
628 | rqst->rq_rcv_buf.page_len) >> PAGE_SHIFT; | ||
629 | for (; i < npages; i++) { | ||
630 | if (i == 0) | ||
631 | curlen = PAGE_SIZE - rqst->rq_rcv_buf.page_base; | ||
632 | else | ||
633 | curlen = PAGE_SIZE; | ||
634 | if (curlen > copy_len) | ||
635 | curlen = copy_len; | ||
636 | dprintk("RPC: %s: page %d" | ||
637 | " srcp 0x%p len %d curlen %d\n", | ||
638 | __func__, i, srcp, copy_len, curlen); | ||
639 | destp = kmap_atomic(rqst->rq_rcv_buf.pages[i], | ||
640 | KM_SKB_SUNRPC_DATA); | ||
641 | if (i == 0) | ||
642 | memcpy(destp + rqst->rq_rcv_buf.page_base, | ||
643 | srcp, curlen); | ||
644 | else | ||
645 | memcpy(destp, srcp, curlen); | ||
646 | flush_dcache_page(rqst->rq_rcv_buf.pages[i]); | ||
647 | kunmap_atomic(destp, KM_SKB_SUNRPC_DATA); | ||
648 | srcp += curlen; | ||
649 | copy_len -= curlen; | ||
650 | if (copy_len == 0) | ||
651 | break; | ||
652 | } | ||
653 | rqst->rq_rcv_buf.page_len = olen - copy_len; | ||
654 | } else | ||
655 | rqst->rq_rcv_buf.page_len = 0; | ||
656 | |||
657 | if (copy_len && rqst->rq_rcv_buf.tail[0].iov_len) { | ||
658 | curlen = copy_len; | ||
659 | if (curlen > rqst->rq_rcv_buf.tail[0].iov_len) | ||
660 | curlen = rqst->rq_rcv_buf.tail[0].iov_len; | ||
661 | if (rqst->rq_rcv_buf.tail[0].iov_base != srcp) | ||
662 | memcpy(rqst->rq_rcv_buf.tail[0].iov_base, srcp, curlen); | ||
663 | dprintk("RPC: %s: tail srcp 0x%p len %d curlen %d\n", | ||
664 | __func__, srcp, copy_len, curlen); | ||
665 | rqst->rq_rcv_buf.tail[0].iov_len = curlen; | ||
666 | copy_len -= curlen; ++i; | ||
667 | } else | ||
668 | rqst->rq_rcv_buf.tail[0].iov_len = 0; | ||
669 | |||
670 | if (copy_len) | ||
671 | dprintk("RPC: %s: %d bytes in" | ||
672 | " %d extra segments (%d lost)\n", | ||
673 | __func__, olen, i, copy_len); | ||
674 | |||
675 | /* TBD avoid a warning from call_decode() */ | ||
676 | rqst->rq_private_buf = rqst->rq_rcv_buf; | ||
677 | } | ||
678 | |||
679 | /* | ||
680 | * This function is called when an async event is posted to | ||
681 | * the connection which changes the connection state. All it | ||
682 | * does at this point is mark the connection up/down, the rpc | ||
683 | * timers do the rest. | ||
684 | */ | ||
685 | void | ||
686 | rpcrdma_conn_func(struct rpcrdma_ep *ep) | ||
687 | { | ||
688 | struct rpc_xprt *xprt = ep->rep_xprt; | ||
689 | |||
690 | spin_lock_bh(&xprt->transport_lock); | ||
691 | if (ep->rep_connected > 0) { | ||
692 | if (!xprt_test_and_set_connected(xprt)) | ||
693 | xprt_wake_pending_tasks(xprt, 0); | ||
694 | } else { | ||
695 | if (xprt_test_and_clear_connected(xprt)) | ||
696 | xprt_wake_pending_tasks(xprt, ep->rep_connected); | ||
697 | } | ||
698 | spin_unlock_bh(&xprt->transport_lock); | ||
699 | } | ||
700 | |||
701 | /* | ||
702 | * This function is called when memory window unbind which we are waiting | ||
703 | * for completes. Just use rr_func (zeroed by upcall) to signal completion. | ||
704 | */ | ||
705 | static void | ||
706 | rpcrdma_unbind_func(struct rpcrdma_rep *rep) | ||
707 | { | ||
708 | wake_up(&rep->rr_unbind); | ||
709 | } | ||
710 | |||
711 | /* | ||
712 | * Called as a tasklet to do req/reply match and complete a request | ||
713 | * Errors must result in the RPC task either being awakened, or | ||
714 | * allowed to timeout, to discover the errors at that time. | ||
715 | */ | ||
716 | void | ||
717 | rpcrdma_reply_handler(struct rpcrdma_rep *rep) | ||
718 | { | ||
719 | struct rpcrdma_msg *headerp; | ||
720 | struct rpcrdma_req *req; | ||
721 | struct rpc_rqst *rqst; | ||
722 | struct rpc_xprt *xprt = rep->rr_xprt; | ||
723 | struct rpcrdma_xprt *r_xprt = rpcx_to_rdmax(xprt); | ||
724 | u32 *iptr; | ||
725 | int i, rdmalen, status; | ||
726 | |||
727 | /* Check status. If bad, signal disconnect and return rep to pool */ | ||
728 | if (rep->rr_len == ~0U) { | ||
729 | rpcrdma_recv_buffer_put(rep); | ||
730 | if (r_xprt->rx_ep.rep_connected == 1) { | ||
731 | r_xprt->rx_ep.rep_connected = -EIO; | ||
732 | rpcrdma_conn_func(&r_xprt->rx_ep); | ||
733 | } | ||
734 | return; | ||
735 | } | ||
736 | if (rep->rr_len < 28) { | ||
737 | dprintk("RPC: %s: short/invalid reply\n", __func__); | ||
738 | goto repost; | ||
739 | } | ||
740 | headerp = (struct rpcrdma_msg *) rep->rr_base; | ||
741 | if (headerp->rm_vers != xdr_one) { | ||
742 | dprintk("RPC: %s: invalid version %d\n", | ||
743 | __func__, ntohl(headerp->rm_vers)); | ||
744 | goto repost; | ||
745 | } | ||
746 | |||
747 | /* Get XID and try for a match. */ | ||
748 | spin_lock(&xprt->transport_lock); | ||
749 | rqst = xprt_lookup_rqst(xprt, headerp->rm_xid); | ||
750 | if (rqst == NULL) { | ||
751 | spin_unlock(&xprt->transport_lock); | ||
752 | dprintk("RPC: %s: reply 0x%p failed " | ||
753 | "to match any request xid 0x%08x len %d\n", | ||
754 | __func__, rep, headerp->rm_xid, rep->rr_len); | ||
755 | repost: | ||
756 | r_xprt->rx_stats.bad_reply_count++; | ||
757 | rep->rr_func = rpcrdma_reply_handler; | ||
758 | if (rpcrdma_ep_post_recv(&r_xprt->rx_ia, &r_xprt->rx_ep, rep)) | ||
759 | rpcrdma_recv_buffer_put(rep); | ||
760 | |||
761 | return; | ||
762 | } | ||
763 | |||
764 | /* get request object */ | ||
765 | req = rpcr_to_rdmar(rqst); | ||
766 | |||
767 | dprintk("RPC: %s: reply 0x%p completes request 0x%p\n" | ||
768 | " RPC request 0x%p xid 0x%08x\n", | ||
769 | __func__, rep, req, rqst, headerp->rm_xid); | ||
770 | |||
771 | BUG_ON(!req || req->rl_reply); | ||
772 | |||
773 | /* from here on, the reply is no longer an orphan */ | ||
774 | req->rl_reply = rep; | ||
775 | |||
776 | /* check for expected message types */ | ||
777 | /* The order of some of these tests is important. */ | ||
778 | switch (headerp->rm_type) { | ||
779 | case __constant_htonl(RDMA_MSG): | ||
780 | /* never expect read chunks */ | ||
781 | /* never expect reply chunks (two ways to check) */ | ||
782 | /* never expect write chunks without having offered RDMA */ | ||
783 | if (headerp->rm_body.rm_chunks[0] != xdr_zero || | ||
784 | (headerp->rm_body.rm_chunks[1] == xdr_zero && | ||
785 | headerp->rm_body.rm_chunks[2] != xdr_zero) || | ||
786 | (headerp->rm_body.rm_chunks[1] != xdr_zero && | ||
787 | req->rl_nchunks == 0)) | ||
788 | goto badheader; | ||
789 | if (headerp->rm_body.rm_chunks[1] != xdr_zero) { | ||
790 | /* count any expected write chunks in read reply */ | ||
791 | /* start at write chunk array count */ | ||
792 | iptr = &headerp->rm_body.rm_chunks[2]; | ||
793 | rdmalen = rpcrdma_count_chunks(rep, | ||
794 | req->rl_nchunks, 1, &iptr); | ||
795 | /* check for validity, and no reply chunk after */ | ||
796 | if (rdmalen < 0 || *iptr++ != xdr_zero) | ||
797 | goto badheader; | ||
798 | rep->rr_len -= | ||
799 | ((unsigned char *)iptr - (unsigned char *)headerp); | ||
800 | status = rep->rr_len + rdmalen; | ||
801 | r_xprt->rx_stats.total_rdma_reply += rdmalen; | ||
802 | } else { | ||
803 | /* else ordinary inline */ | ||
804 | iptr = (u32 *)((unsigned char *)headerp + 28); | ||
805 | rep->rr_len -= 28; /*sizeof *headerp;*/ | ||
806 | status = rep->rr_len; | ||
807 | } | ||
808 | /* Fix up the rpc results for upper layer */ | ||
809 | rpcrdma_inline_fixup(rqst, (char *)iptr, rep->rr_len); | ||
810 | break; | ||
811 | |||
812 | case __constant_htonl(RDMA_NOMSG): | ||
813 | /* never expect read or write chunks, always reply chunks */ | ||
814 | if (headerp->rm_body.rm_chunks[0] != xdr_zero || | ||
815 | headerp->rm_body.rm_chunks[1] != xdr_zero || | ||
816 | headerp->rm_body.rm_chunks[2] != xdr_one || | ||
817 | req->rl_nchunks == 0) | ||
818 | goto badheader; | ||
819 | iptr = (u32 *)((unsigned char *)headerp + 28); | ||
820 | rdmalen = rpcrdma_count_chunks(rep, req->rl_nchunks, 0, &iptr); | ||
821 | if (rdmalen < 0) | ||
822 | goto badheader; | ||
823 | r_xprt->rx_stats.total_rdma_reply += rdmalen; | ||
824 | /* Reply chunk buffer already is the reply vector - no fixup. */ | ||
825 | status = rdmalen; | ||
826 | break; | ||
827 | |||
828 | badheader: | ||
829 | default: | ||
830 | dprintk("%s: invalid rpcrdma reply header (type %d):" | ||
831 | " chunks[012] == %d %d %d" | ||
832 | " expected chunks <= %d\n", | ||
833 | __func__, ntohl(headerp->rm_type), | ||
834 | headerp->rm_body.rm_chunks[0], | ||
835 | headerp->rm_body.rm_chunks[1], | ||
836 | headerp->rm_body.rm_chunks[2], | ||
837 | req->rl_nchunks); | ||
838 | status = -EIO; | ||
839 | r_xprt->rx_stats.bad_reply_count++; | ||
840 | break; | ||
841 | } | ||
842 | |||
843 | /* If using mw bind, start the deregister process now. */ | ||
844 | /* (Note: if mr_free(), cannot perform it here, in tasklet context) */ | ||
845 | if (req->rl_nchunks) switch (r_xprt->rx_ia.ri_memreg_strategy) { | ||
846 | case RPCRDMA_MEMWINDOWS: | ||
847 | for (i = 0; req->rl_nchunks-- > 1;) | ||
848 | i += rpcrdma_deregister_external( | ||
849 | &req->rl_segments[i], r_xprt, NULL); | ||
850 | /* Optionally wait (not here) for unbinds to complete */ | ||
851 | rep->rr_func = rpcrdma_unbind_func; | ||
852 | (void) rpcrdma_deregister_external(&req->rl_segments[i], | ||
853 | r_xprt, rep); | ||
854 | break; | ||
855 | case RPCRDMA_MEMWINDOWS_ASYNC: | ||
856 | for (i = 0; req->rl_nchunks--;) | ||
857 | i += rpcrdma_deregister_external(&req->rl_segments[i], | ||
858 | r_xprt, NULL); | ||
859 | break; | ||
860 | default: | ||
861 | break; | ||
862 | } | ||
863 | |||
864 | dprintk("RPC: %s: xprt_complete_rqst(0x%p, 0x%p, %d)\n", | ||
865 | __func__, xprt, rqst, status); | ||
866 | xprt_complete_rqst(rqst->rq_task, status); | ||
867 | spin_unlock(&xprt->transport_lock); | ||
868 | } | ||
diff --git a/net/sunrpc/xprtrdma/transport.c b/net/sunrpc/xprtrdma/transport.c new file mode 100644 index 000000000000..dc55cc974c90 --- /dev/null +++ b/net/sunrpc/xprtrdma/transport.c | |||
@@ -0,0 +1,800 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2003-2007 Network Appliance, Inc. All rights reserved. | ||
3 | * | ||
4 | * This software is available to you under a choice of one of two | ||
5 | * licenses. You may choose to be licensed under the terms of the GNU | ||
6 | * General Public License (GPL) Version 2, available from the file | ||
7 | * COPYING in the main directory of this source tree, or the BSD-type | ||
8 | * license below: | ||
9 | * | ||
10 | * Redistribution and use in source and binary forms, with or without | ||
11 | * modification, are permitted provided that the following conditions | ||
12 | * are met: | ||
13 | * | ||
14 | * Redistributions of source code must retain the above copyright | ||
15 | * notice, this list of conditions and the following disclaimer. | ||
16 | * | ||
17 | * Redistributions in binary form must reproduce the above | ||
18 | * copyright notice, this list of conditions and the following | ||
19 | * disclaimer in the documentation and/or other materials provided | ||
20 | * with the distribution. | ||
21 | * | ||
22 | * Neither the name of the Network Appliance, Inc. nor the names of | ||
23 | * its contributors may be used to endorse or promote products | ||
24 | * derived from this software without specific prior written | ||
25 | * permission. | ||
26 | * | ||
27 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
28 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
29 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
30 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
31 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
32 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
33 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
34 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
35 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
36 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
37 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
38 | */ | ||
39 | |||
40 | /* | ||
41 | * transport.c | ||
42 | * | ||
43 | * This file contains the top-level implementation of an RPC RDMA | ||
44 | * transport. | ||
45 | * | ||
46 | * Naming convention: functions beginning with xprt_ are part of the | ||
47 | * transport switch. All others are RPC RDMA internal. | ||
48 | */ | ||
49 | |||
50 | #include <linux/module.h> | ||
51 | #include <linux/init.h> | ||
52 | #include <linux/seq_file.h> | ||
53 | |||
54 | #include "xprt_rdma.h" | ||
55 | |||
56 | #ifdef RPC_DEBUG | ||
57 | # define RPCDBG_FACILITY RPCDBG_TRANS | ||
58 | #endif | ||
59 | |||
60 | MODULE_LICENSE("Dual BSD/GPL"); | ||
61 | |||
62 | MODULE_DESCRIPTION("RPC/RDMA Transport for Linux kernel NFS"); | ||
63 | MODULE_AUTHOR("Network Appliance, Inc."); | ||
64 | |||
65 | /* | ||
66 | * tunables | ||
67 | */ | ||
68 | |||
69 | static unsigned int xprt_rdma_slot_table_entries = RPCRDMA_DEF_SLOT_TABLE; | ||
70 | static unsigned int xprt_rdma_max_inline_read = RPCRDMA_DEF_INLINE; | ||
71 | static unsigned int xprt_rdma_max_inline_write = RPCRDMA_DEF_INLINE; | ||
72 | static unsigned int xprt_rdma_inline_write_padding; | ||
73 | #if !RPCRDMA_PERSISTENT_REGISTRATION | ||
74 | static unsigned int xprt_rdma_memreg_strategy = RPCRDMA_REGISTER; /* FMR? */ | ||
75 | #else | ||
76 | static unsigned int xprt_rdma_memreg_strategy = RPCRDMA_ALLPHYSICAL; | ||
77 | #endif | ||
78 | |||
79 | #ifdef RPC_DEBUG | ||
80 | |||
81 | static unsigned int min_slot_table_size = RPCRDMA_MIN_SLOT_TABLE; | ||
82 | static unsigned int max_slot_table_size = RPCRDMA_MAX_SLOT_TABLE; | ||
83 | static unsigned int zero; | ||
84 | static unsigned int max_padding = PAGE_SIZE; | ||
85 | static unsigned int min_memreg = RPCRDMA_BOUNCEBUFFERS; | ||
86 | static unsigned int max_memreg = RPCRDMA_LAST - 1; | ||
87 | |||
88 | static struct ctl_table_header *sunrpc_table_header; | ||
89 | |||
90 | static ctl_table xr_tunables_table[] = { | ||
91 | { | ||
92 | .ctl_name = CTL_SLOTTABLE_RDMA, | ||
93 | .procname = "rdma_slot_table_entries", | ||
94 | .data = &xprt_rdma_slot_table_entries, | ||
95 | .maxlen = sizeof(unsigned int), | ||
96 | .mode = 0644, | ||
97 | .proc_handler = &proc_dointvec_minmax, | ||
98 | .strategy = &sysctl_intvec, | ||
99 | .extra1 = &min_slot_table_size, | ||
100 | .extra2 = &max_slot_table_size | ||
101 | }, | ||
102 | { | ||
103 | .ctl_name = CTL_RDMA_MAXINLINEREAD, | ||
104 | .procname = "rdma_max_inline_read", | ||
105 | .data = &xprt_rdma_max_inline_read, | ||
106 | .maxlen = sizeof(unsigned int), | ||
107 | .mode = 0644, | ||
108 | .proc_handler = &proc_dointvec, | ||
109 | .strategy = &sysctl_intvec, | ||
110 | }, | ||
111 | { | ||
112 | .ctl_name = CTL_RDMA_MAXINLINEWRITE, | ||
113 | .procname = "rdma_max_inline_write", | ||
114 | .data = &xprt_rdma_max_inline_write, | ||
115 | .maxlen = sizeof(unsigned int), | ||
116 | .mode = 0644, | ||
117 | .proc_handler = &proc_dointvec, | ||
118 | .strategy = &sysctl_intvec, | ||
119 | }, | ||
120 | { | ||
121 | .ctl_name = CTL_RDMA_WRITEPADDING, | ||
122 | .procname = "rdma_inline_write_padding", | ||
123 | .data = &xprt_rdma_inline_write_padding, | ||
124 | .maxlen = sizeof(unsigned int), | ||
125 | .mode = 0644, | ||
126 | .proc_handler = &proc_dointvec_minmax, | ||
127 | .strategy = &sysctl_intvec, | ||
128 | .extra1 = &zero, | ||
129 | .extra2 = &max_padding, | ||
130 | }, | ||
131 | { | ||
132 | .ctl_name = CTL_RDMA_MEMREG, | ||
133 | .procname = "rdma_memreg_strategy", | ||
134 | .data = &xprt_rdma_memreg_strategy, | ||
135 | .maxlen = sizeof(unsigned int), | ||
136 | .mode = 0644, | ||
137 | .proc_handler = &proc_dointvec_minmax, | ||
138 | .strategy = &sysctl_intvec, | ||
139 | .extra1 = &min_memreg, | ||
140 | .extra2 = &max_memreg, | ||
141 | }, | ||
142 | { | ||
143 | .ctl_name = 0, | ||
144 | }, | ||
145 | }; | ||
146 | |||
147 | static ctl_table sunrpc_table[] = { | ||
148 | { | ||
149 | .ctl_name = CTL_SUNRPC, | ||
150 | .procname = "sunrpc", | ||
151 | .mode = 0555, | ||
152 | .child = xr_tunables_table | ||
153 | }, | ||
154 | { | ||
155 | .ctl_name = 0, | ||
156 | }, | ||
157 | }; | ||
158 | |||
159 | #endif | ||
160 | |||
161 | static struct rpc_xprt_ops xprt_rdma_procs; /* forward reference */ | ||
162 | |||
163 | static void | ||
164 | xprt_rdma_format_addresses(struct rpc_xprt *xprt) | ||
165 | { | ||
166 | struct sockaddr_in *addr = (struct sockaddr_in *) | ||
167 | &rpcx_to_rdmad(xprt).addr; | ||
168 | char *buf; | ||
169 | |||
170 | buf = kzalloc(20, GFP_KERNEL); | ||
171 | if (buf) | ||
172 | snprintf(buf, 20, NIPQUAD_FMT, NIPQUAD(addr->sin_addr.s_addr)); | ||
173 | xprt->address_strings[RPC_DISPLAY_ADDR] = buf; | ||
174 | |||
175 | buf = kzalloc(8, GFP_KERNEL); | ||
176 | if (buf) | ||
177 | snprintf(buf, 8, "%u", ntohs(addr->sin_port)); | ||
178 | xprt->address_strings[RPC_DISPLAY_PORT] = buf; | ||
179 | |||
180 | xprt->address_strings[RPC_DISPLAY_PROTO] = "rdma"; | ||
181 | |||
182 | buf = kzalloc(48, GFP_KERNEL); | ||
183 | if (buf) | ||
184 | snprintf(buf, 48, "addr="NIPQUAD_FMT" port=%u proto=%s", | ||
185 | NIPQUAD(addr->sin_addr.s_addr), | ||
186 | ntohs(addr->sin_port), "rdma"); | ||
187 | xprt->address_strings[RPC_DISPLAY_ALL] = buf; | ||
188 | |||
189 | buf = kzalloc(10, GFP_KERNEL); | ||
190 | if (buf) | ||
191 | snprintf(buf, 10, "%02x%02x%02x%02x", | ||
192 | NIPQUAD(addr->sin_addr.s_addr)); | ||
193 | xprt->address_strings[RPC_DISPLAY_HEX_ADDR] = buf; | ||
194 | |||
195 | buf = kzalloc(8, GFP_KERNEL); | ||
196 | if (buf) | ||
197 | snprintf(buf, 8, "%4hx", ntohs(addr->sin_port)); | ||
198 | xprt->address_strings[RPC_DISPLAY_HEX_PORT] = buf; | ||
199 | |||
200 | buf = kzalloc(30, GFP_KERNEL); | ||
201 | if (buf) | ||
202 | snprintf(buf, 30, NIPQUAD_FMT".%u.%u", | ||
203 | NIPQUAD(addr->sin_addr.s_addr), | ||
204 | ntohs(addr->sin_port) >> 8, | ||
205 | ntohs(addr->sin_port) & 0xff); | ||
206 | xprt->address_strings[RPC_DISPLAY_UNIVERSAL_ADDR] = buf; | ||
207 | |||
208 | /* netid */ | ||
209 | xprt->address_strings[RPC_DISPLAY_NETID] = "rdma"; | ||
210 | } | ||
211 | |||
212 | static void | ||
213 | xprt_rdma_free_addresses(struct rpc_xprt *xprt) | ||
214 | { | ||
215 | kfree(xprt->address_strings[RPC_DISPLAY_ADDR]); | ||
216 | kfree(xprt->address_strings[RPC_DISPLAY_PORT]); | ||
217 | kfree(xprt->address_strings[RPC_DISPLAY_ALL]); | ||
218 | kfree(xprt->address_strings[RPC_DISPLAY_HEX_ADDR]); | ||
219 | kfree(xprt->address_strings[RPC_DISPLAY_HEX_PORT]); | ||
220 | kfree(xprt->address_strings[RPC_DISPLAY_UNIVERSAL_ADDR]); | ||
221 | } | ||
222 | |||
223 | static void | ||
224 | xprt_rdma_connect_worker(struct work_struct *work) | ||
225 | { | ||
226 | struct rpcrdma_xprt *r_xprt = | ||
227 | container_of(work, struct rpcrdma_xprt, rdma_connect.work); | ||
228 | struct rpc_xprt *xprt = &r_xprt->xprt; | ||
229 | int rc = 0; | ||
230 | |||
231 | if (!xprt->shutdown) { | ||
232 | xprt_clear_connected(xprt); | ||
233 | |||
234 | dprintk("RPC: %s: %sconnect\n", __func__, | ||
235 | r_xprt->rx_ep.rep_connected != 0 ? "re" : ""); | ||
236 | rc = rpcrdma_ep_connect(&r_xprt->rx_ep, &r_xprt->rx_ia); | ||
237 | if (rc) | ||
238 | goto out; | ||
239 | } | ||
240 | goto out_clear; | ||
241 | |||
242 | out: | ||
243 | xprt_wake_pending_tasks(xprt, rc); | ||
244 | |||
245 | out_clear: | ||
246 | dprintk("RPC: %s: exit\n", __func__); | ||
247 | xprt_clear_connecting(xprt); | ||
248 | } | ||
249 | |||
250 | /* | ||
251 | * xprt_rdma_destroy | ||
252 | * | ||
253 | * Destroy the xprt. | ||
254 | * Free all memory associated with the object, including its own. | ||
255 | * NOTE: none of the *destroy methods free memory for their top-level | ||
256 | * objects, even though they may have allocated it (they do free | ||
257 | * private memory). It's up to the caller to handle it. In this | ||
258 | * case (RDMA transport), all structure memory is inlined with the | ||
259 | * struct rpcrdma_xprt. | ||
260 | */ | ||
261 | static void | ||
262 | xprt_rdma_destroy(struct rpc_xprt *xprt) | ||
263 | { | ||
264 | struct rpcrdma_xprt *r_xprt = rpcx_to_rdmax(xprt); | ||
265 | int rc; | ||
266 | |||
267 | dprintk("RPC: %s: called\n", __func__); | ||
268 | |||
269 | cancel_delayed_work(&r_xprt->rdma_connect); | ||
270 | flush_scheduled_work(); | ||
271 | |||
272 | xprt_clear_connected(xprt); | ||
273 | |||
274 | rpcrdma_buffer_destroy(&r_xprt->rx_buf); | ||
275 | rc = rpcrdma_ep_destroy(&r_xprt->rx_ep, &r_xprt->rx_ia); | ||
276 | if (rc) | ||
277 | dprintk("RPC: %s: rpcrdma_ep_destroy returned %i\n", | ||
278 | __func__, rc); | ||
279 | rpcrdma_ia_close(&r_xprt->rx_ia); | ||
280 | |||
281 | xprt_rdma_free_addresses(xprt); | ||
282 | |||
283 | kfree(xprt->slot); | ||
284 | xprt->slot = NULL; | ||
285 | kfree(xprt); | ||
286 | |||
287 | dprintk("RPC: %s: returning\n", __func__); | ||
288 | |||
289 | module_put(THIS_MODULE); | ||
290 | } | ||
291 | |||
292 | /** | ||
293 | * xprt_setup_rdma - Set up transport to use RDMA | ||
294 | * | ||
295 | * @args: rpc transport arguments | ||
296 | */ | ||
297 | static struct rpc_xprt * | ||
298 | xprt_setup_rdma(struct xprt_create *args) | ||
299 | { | ||
300 | struct rpcrdma_create_data_internal cdata; | ||
301 | struct rpc_xprt *xprt; | ||
302 | struct rpcrdma_xprt *new_xprt; | ||
303 | struct rpcrdma_ep *new_ep; | ||
304 | struct sockaddr_in *sin; | ||
305 | int rc; | ||
306 | |||
307 | if (args->addrlen > sizeof(xprt->addr)) { | ||
308 | dprintk("RPC: %s: address too large\n", __func__); | ||
309 | return ERR_PTR(-EBADF); | ||
310 | } | ||
311 | |||
312 | xprt = kzalloc(sizeof(struct rpcrdma_xprt), GFP_KERNEL); | ||
313 | if (xprt == NULL) { | ||
314 | dprintk("RPC: %s: couldn't allocate rpcrdma_xprt\n", | ||
315 | __func__); | ||
316 | return ERR_PTR(-ENOMEM); | ||
317 | } | ||
318 | |||
319 | xprt->max_reqs = xprt_rdma_slot_table_entries; | ||
320 | xprt->slot = kcalloc(xprt->max_reqs, | ||
321 | sizeof(struct rpc_rqst), GFP_KERNEL); | ||
322 | if (xprt->slot == NULL) { | ||
323 | kfree(xprt); | ||
324 | dprintk("RPC: %s: couldn't allocate %d slots\n", | ||
325 | __func__, xprt->max_reqs); | ||
326 | return ERR_PTR(-ENOMEM); | ||
327 | } | ||
328 | |||
329 | /* 60 second timeout, no retries */ | ||
330 | xprt_set_timeout(&xprt->timeout, 0, 60UL * HZ); | ||
331 | xprt->bind_timeout = (60U * HZ); | ||
332 | xprt->connect_timeout = (60U * HZ); | ||
333 | xprt->reestablish_timeout = (5U * HZ); | ||
334 | xprt->idle_timeout = (5U * 60 * HZ); | ||
335 | |||
336 | xprt->resvport = 0; /* privileged port not needed */ | ||
337 | xprt->tsh_size = 0; /* RPC-RDMA handles framing */ | ||
338 | xprt->max_payload = RPCRDMA_MAX_DATA_SEGS * PAGE_SIZE; | ||
339 | xprt->ops = &xprt_rdma_procs; | ||
340 | |||
341 | /* | ||
342 | * Set up RDMA-specific connect data. | ||
343 | */ | ||
344 | |||
345 | /* Put server RDMA address in local cdata */ | ||
346 | memcpy(&cdata.addr, args->dstaddr, args->addrlen); | ||
347 | |||
348 | /* Ensure xprt->addr holds valid server TCP (not RDMA) | ||
349 | * address, for any side protocols which peek at it */ | ||
350 | xprt->prot = IPPROTO_TCP; | ||
351 | xprt->addrlen = args->addrlen; | ||
352 | memcpy(&xprt->addr, &cdata.addr, xprt->addrlen); | ||
353 | |||
354 | sin = (struct sockaddr_in *)&cdata.addr; | ||
355 | if (ntohs(sin->sin_port) != 0) | ||
356 | xprt_set_bound(xprt); | ||
357 | |||
358 | dprintk("RPC: %s: %u.%u.%u.%u:%u\n", __func__, | ||
359 | NIPQUAD(sin->sin_addr.s_addr), ntohs(sin->sin_port)); | ||
360 | |||
361 | /* Set max requests */ | ||
362 | cdata.max_requests = xprt->max_reqs; | ||
363 | |||
364 | /* Set some length limits */ | ||
365 | cdata.rsize = RPCRDMA_MAX_SEGS * PAGE_SIZE; /* RDMA write max */ | ||
366 | cdata.wsize = RPCRDMA_MAX_SEGS * PAGE_SIZE; /* RDMA read max */ | ||
367 | |||
368 | cdata.inline_wsize = xprt_rdma_max_inline_write; | ||
369 | if (cdata.inline_wsize > cdata.wsize) | ||
370 | cdata.inline_wsize = cdata.wsize; | ||
371 | |||
372 | cdata.inline_rsize = xprt_rdma_max_inline_read; | ||
373 | if (cdata.inline_rsize > cdata.rsize) | ||
374 | cdata.inline_rsize = cdata.rsize; | ||
375 | |||
376 | cdata.padding = xprt_rdma_inline_write_padding; | ||
377 | |||
378 | /* | ||
379 | * Create new transport instance, which includes initialized | ||
380 | * o ia | ||
381 | * o endpoint | ||
382 | * o buffers | ||
383 | */ | ||
384 | |||
385 | new_xprt = rpcx_to_rdmax(xprt); | ||
386 | |||
387 | rc = rpcrdma_ia_open(new_xprt, (struct sockaddr *) &cdata.addr, | ||
388 | xprt_rdma_memreg_strategy); | ||
389 | if (rc) | ||
390 | goto out1; | ||
391 | |||
392 | /* | ||
393 | * initialize and create ep | ||
394 | */ | ||
395 | new_xprt->rx_data = cdata; | ||
396 | new_ep = &new_xprt->rx_ep; | ||
397 | new_ep->rep_remote_addr = cdata.addr; | ||
398 | |||
399 | rc = rpcrdma_ep_create(&new_xprt->rx_ep, | ||
400 | &new_xprt->rx_ia, &new_xprt->rx_data); | ||
401 | if (rc) | ||
402 | goto out2; | ||
403 | |||
404 | /* | ||
405 | * Allocate pre-registered send and receive buffers for headers and | ||
406 | * any inline data. Also specify any padding which will be provided | ||
407 | * from a preregistered zero buffer. | ||
408 | */ | ||
409 | rc = rpcrdma_buffer_create(&new_xprt->rx_buf, new_ep, &new_xprt->rx_ia, | ||
410 | &new_xprt->rx_data); | ||
411 | if (rc) | ||
412 | goto out3; | ||
413 | |||
414 | /* | ||
415 | * Register a callback for connection events. This is necessary because | ||
416 | * connection loss notification is async. We also catch connection loss | ||
417 | * when reaping receives. | ||
418 | */ | ||
419 | INIT_DELAYED_WORK(&new_xprt->rdma_connect, xprt_rdma_connect_worker); | ||
420 | new_ep->rep_func = rpcrdma_conn_func; | ||
421 | new_ep->rep_xprt = xprt; | ||
422 | |||
423 | xprt_rdma_format_addresses(xprt); | ||
424 | |||
425 | if (!try_module_get(THIS_MODULE)) | ||
426 | goto out4; | ||
427 | |||
428 | return xprt; | ||
429 | |||
430 | out4: | ||
431 | xprt_rdma_free_addresses(xprt); | ||
432 | rc = -EINVAL; | ||
433 | out3: | ||
434 | (void) rpcrdma_ep_destroy(new_ep, &new_xprt->rx_ia); | ||
435 | out2: | ||
436 | rpcrdma_ia_close(&new_xprt->rx_ia); | ||
437 | out1: | ||
438 | kfree(xprt->slot); | ||
439 | kfree(xprt); | ||
440 | return ERR_PTR(rc); | ||
441 | } | ||
442 | |||
443 | /* | ||
444 | * Close a connection, during shutdown or timeout/reconnect | ||
445 | */ | ||
446 | static void | ||
447 | xprt_rdma_close(struct rpc_xprt *xprt) | ||
448 | { | ||
449 | struct rpcrdma_xprt *r_xprt = rpcx_to_rdmax(xprt); | ||
450 | |||
451 | dprintk("RPC: %s: closing\n", __func__); | ||
452 | xprt_disconnect(xprt); | ||
453 | (void) rpcrdma_ep_disconnect(&r_xprt->rx_ep, &r_xprt->rx_ia); | ||
454 | } | ||
455 | |||
456 | static void | ||
457 | xprt_rdma_set_port(struct rpc_xprt *xprt, u16 port) | ||
458 | { | ||
459 | struct sockaddr_in *sap; | ||
460 | |||
461 | sap = (struct sockaddr_in *)&xprt->addr; | ||
462 | sap->sin_port = htons(port); | ||
463 | sap = (struct sockaddr_in *)&rpcx_to_rdmad(xprt).addr; | ||
464 | sap->sin_port = htons(port); | ||
465 | dprintk("RPC: %s: %u\n", __func__, port); | ||
466 | } | ||
467 | |||
468 | static void | ||
469 | xprt_rdma_connect(struct rpc_task *task) | ||
470 | { | ||
471 | struct rpc_xprt *xprt = (struct rpc_xprt *)task->tk_xprt; | ||
472 | struct rpcrdma_xprt *r_xprt = rpcx_to_rdmax(xprt); | ||
473 | |||
474 | if (!xprt_test_and_set_connecting(xprt)) { | ||
475 | if (r_xprt->rx_ep.rep_connected != 0) { | ||
476 | /* Reconnect */ | ||
477 | schedule_delayed_work(&r_xprt->rdma_connect, | ||
478 | xprt->reestablish_timeout); | ||
479 | } else { | ||
480 | schedule_delayed_work(&r_xprt->rdma_connect, 0); | ||
481 | if (!RPC_IS_ASYNC(task)) | ||
482 | flush_scheduled_work(); | ||
483 | } | ||
484 | } | ||
485 | } | ||
486 | |||
487 | static int | ||
488 | xprt_rdma_reserve_xprt(struct rpc_task *task) | ||
489 | { | ||
490 | struct rpc_xprt *xprt = task->tk_xprt; | ||
491 | struct rpcrdma_xprt *r_xprt = rpcx_to_rdmax(xprt); | ||
492 | int credits = atomic_read(&r_xprt->rx_buf.rb_credits); | ||
493 | |||
494 | /* == RPC_CWNDSCALE @ init, but *after* setup */ | ||
495 | if (r_xprt->rx_buf.rb_cwndscale == 0UL) { | ||
496 | r_xprt->rx_buf.rb_cwndscale = xprt->cwnd; | ||
497 | dprintk("RPC: %s: cwndscale %lu\n", __func__, | ||
498 | r_xprt->rx_buf.rb_cwndscale); | ||
499 | BUG_ON(r_xprt->rx_buf.rb_cwndscale <= 0); | ||
500 | } | ||
501 | xprt->cwnd = credits * r_xprt->rx_buf.rb_cwndscale; | ||
502 | return xprt_reserve_xprt_cong(task); | ||
503 | } | ||
504 | |||
505 | /* | ||
506 | * The RDMA allocate/free functions need the task structure as a place | ||
507 | * to hide the struct rpcrdma_req, which is necessary for the actual send/recv | ||
508 | * sequence. For this reason, the recv buffers are attached to send | ||
509 | * buffers for portions of the RPC. Note that the RPC layer allocates | ||
510 | * both send and receive buffers in the same call. We may register | ||
511 | * the receive buffer portion when using reply chunks. | ||
512 | */ | ||
513 | static void * | ||
514 | xprt_rdma_allocate(struct rpc_task *task, size_t size) | ||
515 | { | ||
516 | struct rpc_xprt *xprt = task->tk_xprt; | ||
517 | struct rpcrdma_req *req, *nreq; | ||
518 | |||
519 | req = rpcrdma_buffer_get(&rpcx_to_rdmax(xprt)->rx_buf); | ||
520 | BUG_ON(NULL == req); | ||
521 | |||
522 | if (size > req->rl_size) { | ||
523 | dprintk("RPC: %s: size %zd too large for buffer[%zd]: " | ||
524 | "prog %d vers %d proc %d\n", | ||
525 | __func__, size, req->rl_size, | ||
526 | task->tk_client->cl_prog, task->tk_client->cl_vers, | ||
527 | task->tk_msg.rpc_proc->p_proc); | ||
528 | /* | ||
529 | * Outgoing length shortage. Our inline write max must have | ||
530 | * been configured to perform direct i/o. | ||
531 | * | ||
532 | * This is therefore a large metadata operation, and the | ||
533 | * allocate call was made on the maximum possible message, | ||
534 | * e.g. containing long filename(s) or symlink data. In | ||
535 | * fact, while these metadata operations *might* carry | ||
536 | * large outgoing payloads, they rarely *do*. However, we | ||
537 | * have to commit to the request here, so reallocate and | ||
538 | * register it now. The data path will never require this | ||
539 | * reallocation. | ||
540 | * | ||
541 | * If the allocation or registration fails, the RPC framework | ||
542 | * will (doggedly) retry. | ||
543 | */ | ||
544 | if (rpcx_to_rdmax(xprt)->rx_ia.ri_memreg_strategy == | ||
545 | RPCRDMA_BOUNCEBUFFERS) { | ||
546 | /* forced to "pure inline" */ | ||
547 | dprintk("RPC: %s: too much data (%zd) for inline " | ||
548 | "(r/w max %d/%d)\n", __func__, size, | ||
549 | rpcx_to_rdmad(xprt).inline_rsize, | ||
550 | rpcx_to_rdmad(xprt).inline_wsize); | ||
551 | size = req->rl_size; | ||
552 | rpc_exit(task, -EIO); /* fail the operation */ | ||
553 | rpcx_to_rdmax(xprt)->rx_stats.failed_marshal_count++; | ||
554 | goto out; | ||
555 | } | ||
556 | if (task->tk_flags & RPC_TASK_SWAPPER) | ||
557 | nreq = kmalloc(sizeof *req + size, GFP_ATOMIC); | ||
558 | else | ||
559 | nreq = kmalloc(sizeof *req + size, GFP_NOFS); | ||
560 | if (nreq == NULL) | ||
561 | goto outfail; | ||
562 | |||
563 | if (rpcrdma_register_internal(&rpcx_to_rdmax(xprt)->rx_ia, | ||
564 | nreq->rl_base, size + sizeof(struct rpcrdma_req) | ||
565 | - offsetof(struct rpcrdma_req, rl_base), | ||
566 | &nreq->rl_handle, &nreq->rl_iov)) { | ||
567 | kfree(nreq); | ||
568 | goto outfail; | ||
569 | } | ||
570 | rpcx_to_rdmax(xprt)->rx_stats.hardway_register_count += size; | ||
571 | nreq->rl_size = size; | ||
572 | nreq->rl_niovs = 0; | ||
573 | nreq->rl_nchunks = 0; | ||
574 | nreq->rl_buffer = (struct rpcrdma_buffer *)req; | ||
575 | nreq->rl_reply = req->rl_reply; | ||
576 | memcpy(nreq->rl_segments, | ||
577 | req->rl_segments, sizeof nreq->rl_segments); | ||
578 | /* flag the swap with an unused field */ | ||
579 | nreq->rl_iov.length = 0; | ||
580 | req->rl_reply = NULL; | ||
581 | req = nreq; | ||
582 | } | ||
583 | dprintk("RPC: %s: size %zd, request 0x%p\n", __func__, size, req); | ||
584 | out: | ||
585 | return req->rl_xdr_buf; | ||
586 | |||
587 | outfail: | ||
588 | rpcrdma_buffer_put(req); | ||
589 | rpcx_to_rdmax(xprt)->rx_stats.failed_marshal_count++; | ||
590 | return NULL; | ||
591 | } | ||
592 | |||
593 | /* | ||
594 | * This function returns all RDMA resources to the pool. | ||
595 | */ | ||
596 | static void | ||
597 | xprt_rdma_free(void *buffer) | ||
598 | { | ||
599 | struct rpcrdma_req *req; | ||
600 | struct rpcrdma_xprt *r_xprt; | ||
601 | struct rpcrdma_rep *rep; | ||
602 | int i; | ||
603 | |||
604 | if (buffer == NULL) | ||
605 | return; | ||
606 | |||
607 | req = container_of(buffer, struct rpcrdma_req, rl_xdr_buf[0]); | ||
608 | r_xprt = container_of(req->rl_buffer, struct rpcrdma_xprt, rx_buf); | ||
609 | rep = req->rl_reply; | ||
610 | |||
611 | dprintk("RPC: %s: called on 0x%p%s\n", | ||
612 | __func__, rep, (rep && rep->rr_func) ? " (with waiter)" : ""); | ||
613 | |||
614 | /* | ||
615 | * Finish the deregistration. When using mw bind, this was | ||
616 | * begun in rpcrdma_reply_handler(). In all other modes, we | ||
617 | * do it here, in thread context. The process is considered | ||
618 | * complete when the rr_func vector becomes NULL - this | ||
619 | * was put in place during rpcrdma_reply_handler() - the wait | ||
620 | * call below will not block if the dereg is "done". If | ||
621 | * interrupted, our framework will clean up. | ||
622 | */ | ||
623 | for (i = 0; req->rl_nchunks;) { | ||
624 | --req->rl_nchunks; | ||
625 | i += rpcrdma_deregister_external( | ||
626 | &req->rl_segments[i], r_xprt, NULL); | ||
627 | } | ||
628 | |||
629 | if (rep && wait_event_interruptible(rep->rr_unbind, !rep->rr_func)) { | ||
630 | rep->rr_func = NULL; /* abandon the callback */ | ||
631 | req->rl_reply = NULL; | ||
632 | } | ||
633 | |||
634 | if (req->rl_iov.length == 0) { /* see allocate above */ | ||
635 | struct rpcrdma_req *oreq = (struct rpcrdma_req *)req->rl_buffer; | ||
636 | oreq->rl_reply = req->rl_reply; | ||
637 | (void) rpcrdma_deregister_internal(&r_xprt->rx_ia, | ||
638 | req->rl_handle, | ||
639 | &req->rl_iov); | ||
640 | kfree(req); | ||
641 | req = oreq; | ||
642 | } | ||
643 | |||
644 | /* Put back request+reply buffers */ | ||
645 | rpcrdma_buffer_put(req); | ||
646 | } | ||
647 | |||
648 | /* | ||
649 | * send_request invokes the meat of RPC RDMA. It must do the following: | ||
650 | * 1. Marshal the RPC request into an RPC RDMA request, which means | ||
651 | * putting a header in front of data, and creating IOVs for RDMA | ||
652 | * from those in the request. | ||
653 | * 2. In marshaling, detect opportunities for RDMA, and use them. | ||
654 | * 3. Post a recv message to set up asynch completion, then send | ||
655 | * the request (rpcrdma_ep_post). | ||
656 | * 4. No partial sends are possible in the RPC-RDMA protocol (as in UDP). | ||
657 | */ | ||
658 | |||
659 | static int | ||
660 | xprt_rdma_send_request(struct rpc_task *task) | ||
661 | { | ||
662 | struct rpc_rqst *rqst = task->tk_rqstp; | ||
663 | struct rpc_xprt *xprt = task->tk_xprt; | ||
664 | struct rpcrdma_req *req = rpcr_to_rdmar(rqst); | ||
665 | struct rpcrdma_xprt *r_xprt = rpcx_to_rdmax(xprt); | ||
666 | |||
667 | /* marshal the send itself */ | ||
668 | if (req->rl_niovs == 0 && rpcrdma_marshal_req(rqst) != 0) { | ||
669 | r_xprt->rx_stats.failed_marshal_count++; | ||
670 | dprintk("RPC: %s: rpcrdma_marshal_req failed\n", | ||
671 | __func__); | ||
672 | return -EIO; | ||
673 | } | ||
674 | |||
675 | if (req->rl_reply == NULL) /* e.g. reconnection */ | ||
676 | rpcrdma_recv_buffer_get(req); | ||
677 | |||
678 | if (req->rl_reply) { | ||
679 | req->rl_reply->rr_func = rpcrdma_reply_handler; | ||
680 | /* this need only be done once, but... */ | ||
681 | req->rl_reply->rr_xprt = xprt; | ||
682 | } | ||
683 | |||
684 | if (rpcrdma_ep_post(&r_xprt->rx_ia, &r_xprt->rx_ep, req)) { | ||
685 | xprt_disconnect(xprt); | ||
686 | return -ENOTCONN; /* implies disconnect */ | ||
687 | } | ||
688 | |||
689 | rqst->rq_bytes_sent = 0; | ||
690 | return 0; | ||
691 | } | ||
692 | |||
693 | static void xprt_rdma_print_stats(struct rpc_xprt *xprt, struct seq_file *seq) | ||
694 | { | ||
695 | struct rpcrdma_xprt *r_xprt = rpcx_to_rdmax(xprt); | ||
696 | long idle_time = 0; | ||
697 | |||
698 | if (xprt_connected(xprt)) | ||
699 | idle_time = (long)(jiffies - xprt->last_used) / HZ; | ||
700 | |||
701 | seq_printf(seq, | ||
702 | "\txprt:\trdma %u %lu %lu %lu %ld %lu %lu %lu %Lu %Lu " | ||
703 | "%lu %lu %lu %Lu %Lu %Lu %Lu %lu %lu %lu\n", | ||
704 | |||
705 | 0, /* need a local port? */ | ||
706 | xprt->stat.bind_count, | ||
707 | xprt->stat.connect_count, | ||
708 | xprt->stat.connect_time, | ||
709 | idle_time, | ||
710 | xprt->stat.sends, | ||
711 | xprt->stat.recvs, | ||
712 | xprt->stat.bad_xids, | ||
713 | xprt->stat.req_u, | ||
714 | xprt->stat.bklog_u, | ||
715 | |||
716 | r_xprt->rx_stats.read_chunk_count, | ||
717 | r_xprt->rx_stats.write_chunk_count, | ||
718 | r_xprt->rx_stats.reply_chunk_count, | ||
719 | r_xprt->rx_stats.total_rdma_request, | ||
720 | r_xprt->rx_stats.total_rdma_reply, | ||
721 | r_xprt->rx_stats.pullup_copy_count, | ||
722 | r_xprt->rx_stats.fixup_copy_count, | ||
723 | r_xprt->rx_stats.hardway_register_count, | ||
724 | r_xprt->rx_stats.failed_marshal_count, | ||
725 | r_xprt->rx_stats.bad_reply_count); | ||
726 | } | ||
727 | |||
728 | /* | ||
729 | * Plumbing for rpc transport switch and kernel module | ||
730 | */ | ||
731 | |||
732 | static struct rpc_xprt_ops xprt_rdma_procs = { | ||
733 | .reserve_xprt = xprt_rdma_reserve_xprt, | ||
734 | .release_xprt = xprt_release_xprt_cong, /* sunrpc/xprt.c */ | ||
735 | .release_request = xprt_release_rqst_cong, /* ditto */ | ||
736 | .set_retrans_timeout = xprt_set_retrans_timeout_def, /* ditto */ | ||
737 | .rpcbind = rpcb_getport_async, /* sunrpc/rpcb_clnt.c */ | ||
738 | .set_port = xprt_rdma_set_port, | ||
739 | .connect = xprt_rdma_connect, | ||
740 | .buf_alloc = xprt_rdma_allocate, | ||
741 | .buf_free = xprt_rdma_free, | ||
742 | .send_request = xprt_rdma_send_request, | ||
743 | .close = xprt_rdma_close, | ||
744 | .destroy = xprt_rdma_destroy, | ||
745 | .print_stats = xprt_rdma_print_stats | ||
746 | }; | ||
747 | |||
748 | static struct xprt_class xprt_rdma = { | ||
749 | .list = LIST_HEAD_INIT(xprt_rdma.list), | ||
750 | .name = "rdma", | ||
751 | .owner = THIS_MODULE, | ||
752 | .ident = XPRT_TRANSPORT_RDMA, | ||
753 | .setup = xprt_setup_rdma, | ||
754 | }; | ||
755 | |||
756 | static void __exit xprt_rdma_cleanup(void) | ||
757 | { | ||
758 | int rc; | ||
759 | |||
760 | dprintk("RPCRDMA Module Removed, deregister RPC RDMA transport\n"); | ||
761 | #ifdef RPC_DEBUG | ||
762 | if (sunrpc_table_header) { | ||
763 | unregister_sysctl_table(sunrpc_table_header); | ||
764 | sunrpc_table_header = NULL; | ||
765 | } | ||
766 | #endif | ||
767 | rc = xprt_unregister_transport(&xprt_rdma); | ||
768 | if (rc) | ||
769 | dprintk("RPC: %s: xprt_unregister returned %i\n", | ||
770 | __func__, rc); | ||
771 | } | ||
772 | |||
773 | static int __init xprt_rdma_init(void) | ||
774 | { | ||
775 | int rc; | ||
776 | |||
777 | rc = xprt_register_transport(&xprt_rdma); | ||
778 | |||
779 | if (rc) | ||
780 | return rc; | ||
781 | |||
782 | dprintk(KERN_INFO "RPCRDMA Module Init, register RPC RDMA transport\n"); | ||
783 | |||
784 | dprintk(KERN_INFO "Defaults:\n"); | ||
785 | dprintk(KERN_INFO "\tSlots %d\n" | ||
786 | "\tMaxInlineRead %d\n\tMaxInlineWrite %d\n", | ||
787 | xprt_rdma_slot_table_entries, | ||
788 | xprt_rdma_max_inline_read, xprt_rdma_max_inline_write); | ||
789 | dprintk(KERN_INFO "\tPadding %d\n\tMemreg %d\n", | ||
790 | xprt_rdma_inline_write_padding, xprt_rdma_memreg_strategy); | ||
791 | |||
792 | #ifdef RPC_DEBUG | ||
793 | if (!sunrpc_table_header) | ||
794 | sunrpc_table_header = register_sysctl_table(sunrpc_table); | ||
795 | #endif | ||
796 | return 0; | ||
797 | } | ||
798 | |||
799 | module_init(xprt_rdma_init); | ||
800 | module_exit(xprt_rdma_cleanup); | ||
diff --git a/net/sunrpc/xprtrdma/verbs.c b/net/sunrpc/xprtrdma/verbs.c new file mode 100644 index 000000000000..44b0fb942e8d --- /dev/null +++ b/net/sunrpc/xprtrdma/verbs.c | |||
@@ -0,0 +1,1627 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2003-2007 Network Appliance, Inc. All rights reserved. | ||
3 | * | ||
4 | * This software is available to you under a choice of one of two | ||
5 | * licenses. You may choose to be licensed under the terms of the GNU | ||
6 | * General Public License (GPL) Version 2, available from the file | ||
7 | * COPYING in the main directory of this source tree, or the BSD-type | ||
8 | * license below: | ||
9 | * | ||
10 | * Redistribution and use in source and binary forms, with or without | ||
11 | * modification, are permitted provided that the following conditions | ||
12 | * are met: | ||
13 | * | ||
14 | * Redistributions of source code must retain the above copyright | ||
15 | * notice, this list of conditions and the following disclaimer. | ||
16 | * | ||
17 | * Redistributions in binary form must reproduce the above | ||
18 | * copyright notice, this list of conditions and the following | ||
19 | * disclaimer in the documentation and/or other materials provided | ||
20 | * with the distribution. | ||
21 | * | ||
22 | * Neither the name of the Network Appliance, Inc. nor the names of | ||
23 | * its contributors may be used to endorse or promote products | ||
24 | * derived from this software without specific prior written | ||
25 | * permission. | ||
26 | * | ||
27 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
28 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
29 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
30 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
31 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
32 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
33 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
34 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
35 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
36 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
37 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
38 | */ | ||
39 | |||
40 | /* | ||
41 | * verbs.c | ||
42 | * | ||
43 | * Encapsulates the major functions managing: | ||
44 | * o adapters | ||
45 | * o endpoints | ||
46 | * o connections | ||
47 | * o buffer memory | ||
48 | */ | ||
49 | |||
50 | #include <linux/pci.h> /* for Tavor hack below */ | ||
51 | |||
52 | #include "xprt_rdma.h" | ||
53 | |||
54 | /* | ||
55 | * Globals/Macros | ||
56 | */ | ||
57 | |||
58 | #ifdef RPC_DEBUG | ||
59 | # define RPCDBG_FACILITY RPCDBG_TRANS | ||
60 | #endif | ||
61 | |||
62 | /* | ||
63 | * internal functions | ||
64 | */ | ||
65 | |||
66 | /* | ||
67 | * handle replies in tasklet context, using a single, global list | ||
68 | * rdma tasklet function -- just turn around and call the func | ||
69 | * for all replies on the list | ||
70 | */ | ||
71 | |||
72 | static DEFINE_SPINLOCK(rpcrdma_tk_lock_g); | ||
73 | static LIST_HEAD(rpcrdma_tasklets_g); | ||
74 | |||
75 | static void | ||
76 | rpcrdma_run_tasklet(unsigned long data) | ||
77 | { | ||
78 | struct rpcrdma_rep *rep; | ||
79 | void (*func)(struct rpcrdma_rep *); | ||
80 | unsigned long flags; | ||
81 | |||
82 | data = data; | ||
83 | spin_lock_irqsave(&rpcrdma_tk_lock_g, flags); | ||
84 | while (!list_empty(&rpcrdma_tasklets_g)) { | ||
85 | rep = list_entry(rpcrdma_tasklets_g.next, | ||
86 | struct rpcrdma_rep, rr_list); | ||
87 | list_del(&rep->rr_list); | ||
88 | func = rep->rr_func; | ||
89 | rep->rr_func = NULL; | ||
90 | spin_unlock_irqrestore(&rpcrdma_tk_lock_g, flags); | ||
91 | |||
92 | if (func) | ||
93 | func(rep); | ||
94 | else | ||
95 | rpcrdma_recv_buffer_put(rep); | ||
96 | |||
97 | spin_lock_irqsave(&rpcrdma_tk_lock_g, flags); | ||
98 | } | ||
99 | spin_unlock_irqrestore(&rpcrdma_tk_lock_g, flags); | ||
100 | } | ||
101 | |||
102 | static DECLARE_TASKLET(rpcrdma_tasklet_g, rpcrdma_run_tasklet, 0UL); | ||
103 | |||
104 | static inline void | ||
105 | rpcrdma_schedule_tasklet(struct rpcrdma_rep *rep) | ||
106 | { | ||
107 | unsigned long flags; | ||
108 | |||
109 | spin_lock_irqsave(&rpcrdma_tk_lock_g, flags); | ||
110 | list_add_tail(&rep->rr_list, &rpcrdma_tasklets_g); | ||
111 | spin_unlock_irqrestore(&rpcrdma_tk_lock_g, flags); | ||
112 | tasklet_schedule(&rpcrdma_tasklet_g); | ||
113 | } | ||
114 | |||
115 | static void | ||
116 | rpcrdma_qp_async_error_upcall(struct ib_event *event, void *context) | ||
117 | { | ||
118 | struct rpcrdma_ep *ep = context; | ||
119 | |||
120 | dprintk("RPC: %s: QP error %X on device %s ep %p\n", | ||
121 | __func__, event->event, event->device->name, context); | ||
122 | if (ep->rep_connected == 1) { | ||
123 | ep->rep_connected = -EIO; | ||
124 | ep->rep_func(ep); | ||
125 | wake_up_all(&ep->rep_connect_wait); | ||
126 | } | ||
127 | } | ||
128 | |||
129 | static void | ||
130 | rpcrdma_cq_async_error_upcall(struct ib_event *event, void *context) | ||
131 | { | ||
132 | struct rpcrdma_ep *ep = context; | ||
133 | |||
134 | dprintk("RPC: %s: CQ error %X on device %s ep %p\n", | ||
135 | __func__, event->event, event->device->name, context); | ||
136 | if (ep->rep_connected == 1) { | ||
137 | ep->rep_connected = -EIO; | ||
138 | ep->rep_func(ep); | ||
139 | wake_up_all(&ep->rep_connect_wait); | ||
140 | } | ||
141 | } | ||
142 | |||
143 | static inline | ||
144 | void rpcrdma_event_process(struct ib_wc *wc) | ||
145 | { | ||
146 | struct rpcrdma_rep *rep = | ||
147 | (struct rpcrdma_rep *)(unsigned long) wc->wr_id; | ||
148 | |||
149 | dprintk("RPC: %s: event rep %p status %X opcode %X length %u\n", | ||
150 | __func__, rep, wc->status, wc->opcode, wc->byte_len); | ||
151 | |||
152 | if (!rep) /* send or bind completion that we don't care about */ | ||
153 | return; | ||
154 | |||
155 | if (IB_WC_SUCCESS != wc->status) { | ||
156 | dprintk("RPC: %s: %s WC status %X, connection lost\n", | ||
157 | __func__, (wc->opcode & IB_WC_RECV) ? "recv" : "send", | ||
158 | wc->status); | ||
159 | rep->rr_len = ~0U; | ||
160 | rpcrdma_schedule_tasklet(rep); | ||
161 | return; | ||
162 | } | ||
163 | |||
164 | switch (wc->opcode) { | ||
165 | case IB_WC_RECV: | ||
166 | rep->rr_len = wc->byte_len; | ||
167 | ib_dma_sync_single_for_cpu( | ||
168 | rdmab_to_ia(rep->rr_buffer)->ri_id->device, | ||
169 | rep->rr_iov.addr, rep->rr_len, DMA_FROM_DEVICE); | ||
170 | /* Keep (only) the most recent credits, after check validity */ | ||
171 | if (rep->rr_len >= 16) { | ||
172 | struct rpcrdma_msg *p = | ||
173 | (struct rpcrdma_msg *) rep->rr_base; | ||
174 | unsigned int credits = ntohl(p->rm_credit); | ||
175 | if (credits == 0) { | ||
176 | dprintk("RPC: %s: server" | ||
177 | " dropped credits to 0!\n", __func__); | ||
178 | /* don't deadlock */ | ||
179 | credits = 1; | ||
180 | } else if (credits > rep->rr_buffer->rb_max_requests) { | ||
181 | dprintk("RPC: %s: server" | ||
182 | " over-crediting: %d (%d)\n", | ||
183 | __func__, credits, | ||
184 | rep->rr_buffer->rb_max_requests); | ||
185 | credits = rep->rr_buffer->rb_max_requests; | ||
186 | } | ||
187 | atomic_set(&rep->rr_buffer->rb_credits, credits); | ||
188 | } | ||
189 | /* fall through */ | ||
190 | case IB_WC_BIND_MW: | ||
191 | rpcrdma_schedule_tasklet(rep); | ||
192 | break; | ||
193 | default: | ||
194 | dprintk("RPC: %s: unexpected WC event %X\n", | ||
195 | __func__, wc->opcode); | ||
196 | break; | ||
197 | } | ||
198 | } | ||
199 | |||
200 | static inline int | ||
201 | rpcrdma_cq_poll(struct ib_cq *cq) | ||
202 | { | ||
203 | struct ib_wc wc; | ||
204 | int rc; | ||
205 | |||
206 | for (;;) { | ||
207 | rc = ib_poll_cq(cq, 1, &wc); | ||
208 | if (rc < 0) { | ||
209 | dprintk("RPC: %s: ib_poll_cq failed %i\n", | ||
210 | __func__, rc); | ||
211 | return rc; | ||
212 | } | ||
213 | if (rc == 0) | ||
214 | break; | ||
215 | |||
216 | rpcrdma_event_process(&wc); | ||
217 | } | ||
218 | |||
219 | return 0; | ||
220 | } | ||
221 | |||
222 | /* | ||
223 | * rpcrdma_cq_event_upcall | ||
224 | * | ||
225 | * This upcall handles recv, send, bind and unbind events. | ||
226 | * It is reentrant but processes single events in order to maintain | ||
227 | * ordering of receives to keep server credits. | ||
228 | * | ||
229 | * It is the responsibility of the scheduled tasklet to return | ||
230 | * recv buffers to the pool. NOTE: this affects synchronization of | ||
231 | * connection shutdown. That is, the structures required for | ||
232 | * the completion of the reply handler must remain intact until | ||
233 | * all memory has been reclaimed. | ||
234 | * | ||
235 | * Note that send events are suppressed and do not result in an upcall. | ||
236 | */ | ||
237 | static void | ||
238 | rpcrdma_cq_event_upcall(struct ib_cq *cq, void *context) | ||
239 | { | ||
240 | int rc; | ||
241 | |||
242 | rc = rpcrdma_cq_poll(cq); | ||
243 | if (rc) | ||
244 | return; | ||
245 | |||
246 | rc = ib_req_notify_cq(cq, IB_CQ_NEXT_COMP); | ||
247 | if (rc) { | ||
248 | dprintk("RPC: %s: ib_req_notify_cq failed %i\n", | ||
249 | __func__, rc); | ||
250 | return; | ||
251 | } | ||
252 | |||
253 | rpcrdma_cq_poll(cq); | ||
254 | } | ||
255 | |||
256 | #ifdef RPC_DEBUG | ||
257 | static const char * const conn[] = { | ||
258 | "address resolved", | ||
259 | "address error", | ||
260 | "route resolved", | ||
261 | "route error", | ||
262 | "connect request", | ||
263 | "connect response", | ||
264 | "connect error", | ||
265 | "unreachable", | ||
266 | "rejected", | ||
267 | "established", | ||
268 | "disconnected", | ||
269 | "device removal" | ||
270 | }; | ||
271 | #endif | ||
272 | |||
273 | static int | ||
274 | rpcrdma_conn_upcall(struct rdma_cm_id *id, struct rdma_cm_event *event) | ||
275 | { | ||
276 | struct rpcrdma_xprt *xprt = id->context; | ||
277 | struct rpcrdma_ia *ia = &xprt->rx_ia; | ||
278 | struct rpcrdma_ep *ep = &xprt->rx_ep; | ||
279 | struct sockaddr_in *addr = (struct sockaddr_in *) &ep->rep_remote_addr; | ||
280 | struct ib_qp_attr attr; | ||
281 | struct ib_qp_init_attr iattr; | ||
282 | int connstate = 0; | ||
283 | |||
284 | switch (event->event) { | ||
285 | case RDMA_CM_EVENT_ADDR_RESOLVED: | ||
286 | case RDMA_CM_EVENT_ROUTE_RESOLVED: | ||
287 | complete(&ia->ri_done); | ||
288 | break; | ||
289 | case RDMA_CM_EVENT_ADDR_ERROR: | ||
290 | ia->ri_async_rc = -EHOSTUNREACH; | ||
291 | dprintk("RPC: %s: CM address resolution error, ep 0x%p\n", | ||
292 | __func__, ep); | ||
293 | complete(&ia->ri_done); | ||
294 | break; | ||
295 | case RDMA_CM_EVENT_ROUTE_ERROR: | ||
296 | ia->ri_async_rc = -ENETUNREACH; | ||
297 | dprintk("RPC: %s: CM route resolution error, ep 0x%p\n", | ||
298 | __func__, ep); | ||
299 | complete(&ia->ri_done); | ||
300 | break; | ||
301 | case RDMA_CM_EVENT_ESTABLISHED: | ||
302 | connstate = 1; | ||
303 | ib_query_qp(ia->ri_id->qp, &attr, | ||
304 | IB_QP_MAX_QP_RD_ATOMIC | IB_QP_MAX_DEST_RD_ATOMIC, | ||
305 | &iattr); | ||
306 | dprintk("RPC: %s: %d responder resources" | ||
307 | " (%d initiator)\n", | ||
308 | __func__, attr.max_dest_rd_atomic, attr.max_rd_atomic); | ||
309 | goto connected; | ||
310 | case RDMA_CM_EVENT_CONNECT_ERROR: | ||
311 | connstate = -ENOTCONN; | ||
312 | goto connected; | ||
313 | case RDMA_CM_EVENT_UNREACHABLE: | ||
314 | connstate = -ENETDOWN; | ||
315 | goto connected; | ||
316 | case RDMA_CM_EVENT_REJECTED: | ||
317 | connstate = -ECONNREFUSED; | ||
318 | goto connected; | ||
319 | case RDMA_CM_EVENT_DISCONNECTED: | ||
320 | connstate = -ECONNABORTED; | ||
321 | goto connected; | ||
322 | case RDMA_CM_EVENT_DEVICE_REMOVAL: | ||
323 | connstate = -ENODEV; | ||
324 | connected: | ||
325 | dprintk("RPC: %s: %s: %u.%u.%u.%u:%u" | ||
326 | " (ep 0x%p event 0x%x)\n", | ||
327 | __func__, | ||
328 | (event->event <= 11) ? conn[event->event] : | ||
329 | "unknown connection error", | ||
330 | NIPQUAD(addr->sin_addr.s_addr), | ||
331 | ntohs(addr->sin_port), | ||
332 | ep, event->event); | ||
333 | atomic_set(&rpcx_to_rdmax(ep->rep_xprt)->rx_buf.rb_credits, 1); | ||
334 | dprintk("RPC: %s: %sconnected\n", | ||
335 | __func__, connstate > 0 ? "" : "dis"); | ||
336 | ep->rep_connected = connstate; | ||
337 | ep->rep_func(ep); | ||
338 | wake_up_all(&ep->rep_connect_wait); | ||
339 | break; | ||
340 | default: | ||
341 | ia->ri_async_rc = -EINVAL; | ||
342 | dprintk("RPC: %s: unexpected CM event %X\n", | ||
343 | __func__, event->event); | ||
344 | complete(&ia->ri_done); | ||
345 | break; | ||
346 | } | ||
347 | |||
348 | return 0; | ||
349 | } | ||
350 | |||
351 | static struct rdma_cm_id * | ||
352 | rpcrdma_create_id(struct rpcrdma_xprt *xprt, | ||
353 | struct rpcrdma_ia *ia, struct sockaddr *addr) | ||
354 | { | ||
355 | struct rdma_cm_id *id; | ||
356 | int rc; | ||
357 | |||
358 | id = rdma_create_id(rpcrdma_conn_upcall, xprt, RDMA_PS_TCP); | ||
359 | if (IS_ERR(id)) { | ||
360 | rc = PTR_ERR(id); | ||
361 | dprintk("RPC: %s: rdma_create_id() failed %i\n", | ||
362 | __func__, rc); | ||
363 | return id; | ||
364 | } | ||
365 | |||
366 | ia->ri_async_rc = 0; | ||
367 | rc = rdma_resolve_addr(id, NULL, addr, RDMA_RESOLVE_TIMEOUT); | ||
368 | if (rc) { | ||
369 | dprintk("RPC: %s: rdma_resolve_addr() failed %i\n", | ||
370 | __func__, rc); | ||
371 | goto out; | ||
372 | } | ||
373 | wait_for_completion(&ia->ri_done); | ||
374 | rc = ia->ri_async_rc; | ||
375 | if (rc) | ||
376 | goto out; | ||
377 | |||
378 | ia->ri_async_rc = 0; | ||
379 | rc = rdma_resolve_route(id, RDMA_RESOLVE_TIMEOUT); | ||
380 | if (rc) { | ||
381 | dprintk("RPC: %s: rdma_resolve_route() failed %i\n", | ||
382 | __func__, rc); | ||
383 | goto out; | ||
384 | } | ||
385 | wait_for_completion(&ia->ri_done); | ||
386 | rc = ia->ri_async_rc; | ||
387 | if (rc) | ||
388 | goto out; | ||
389 | |||
390 | return id; | ||
391 | |||
392 | out: | ||
393 | rdma_destroy_id(id); | ||
394 | return ERR_PTR(rc); | ||
395 | } | ||
396 | |||
397 | /* | ||
398 | * Drain any cq, prior to teardown. | ||
399 | */ | ||
400 | static void | ||
401 | rpcrdma_clean_cq(struct ib_cq *cq) | ||
402 | { | ||
403 | struct ib_wc wc; | ||
404 | int count = 0; | ||
405 | |||
406 | while (1 == ib_poll_cq(cq, 1, &wc)) | ||
407 | ++count; | ||
408 | |||
409 | if (count) | ||
410 | dprintk("RPC: %s: flushed %d events (last 0x%x)\n", | ||
411 | __func__, count, wc.opcode); | ||
412 | } | ||
413 | |||
414 | /* | ||
415 | * Exported functions. | ||
416 | */ | ||
417 | |||
418 | /* | ||
419 | * Open and initialize an Interface Adapter. | ||
420 | * o initializes fields of struct rpcrdma_ia, including | ||
421 | * interface and provider attributes and protection zone. | ||
422 | */ | ||
423 | int | ||
424 | rpcrdma_ia_open(struct rpcrdma_xprt *xprt, struct sockaddr *addr, int memreg) | ||
425 | { | ||
426 | int rc; | ||
427 | struct rpcrdma_ia *ia = &xprt->rx_ia; | ||
428 | |||
429 | init_completion(&ia->ri_done); | ||
430 | |||
431 | ia->ri_id = rpcrdma_create_id(xprt, ia, addr); | ||
432 | if (IS_ERR(ia->ri_id)) { | ||
433 | rc = PTR_ERR(ia->ri_id); | ||
434 | goto out1; | ||
435 | } | ||
436 | |||
437 | ia->ri_pd = ib_alloc_pd(ia->ri_id->device); | ||
438 | if (IS_ERR(ia->ri_pd)) { | ||
439 | rc = PTR_ERR(ia->ri_pd); | ||
440 | dprintk("RPC: %s: ib_alloc_pd() failed %i\n", | ||
441 | __func__, rc); | ||
442 | goto out2; | ||
443 | } | ||
444 | |||
445 | /* | ||
446 | * Optionally obtain an underlying physical identity mapping in | ||
447 | * order to do a memory window-based bind. This base registration | ||
448 | * is protected from remote access - that is enabled only by binding | ||
449 | * for the specific bytes targeted during each RPC operation, and | ||
450 | * revoked after the corresponding completion similar to a storage | ||
451 | * adapter. | ||
452 | */ | ||
453 | if (memreg > RPCRDMA_REGISTER) { | ||
454 | int mem_priv = IB_ACCESS_LOCAL_WRITE; | ||
455 | switch (memreg) { | ||
456 | #if RPCRDMA_PERSISTENT_REGISTRATION | ||
457 | case RPCRDMA_ALLPHYSICAL: | ||
458 | mem_priv |= IB_ACCESS_REMOTE_WRITE; | ||
459 | mem_priv |= IB_ACCESS_REMOTE_READ; | ||
460 | break; | ||
461 | #endif | ||
462 | case RPCRDMA_MEMWINDOWS_ASYNC: | ||
463 | case RPCRDMA_MEMWINDOWS: | ||
464 | mem_priv |= IB_ACCESS_MW_BIND; | ||
465 | break; | ||
466 | default: | ||
467 | break; | ||
468 | } | ||
469 | ia->ri_bind_mem = ib_get_dma_mr(ia->ri_pd, mem_priv); | ||
470 | if (IS_ERR(ia->ri_bind_mem)) { | ||
471 | printk(KERN_ALERT "%s: ib_get_dma_mr for " | ||
472 | "phys register failed with %lX\n\t" | ||
473 | "Will continue with degraded performance\n", | ||
474 | __func__, PTR_ERR(ia->ri_bind_mem)); | ||
475 | memreg = RPCRDMA_REGISTER; | ||
476 | ia->ri_bind_mem = NULL; | ||
477 | } | ||
478 | } | ||
479 | |||
480 | /* Else will do memory reg/dereg for each chunk */ | ||
481 | ia->ri_memreg_strategy = memreg; | ||
482 | |||
483 | return 0; | ||
484 | out2: | ||
485 | rdma_destroy_id(ia->ri_id); | ||
486 | out1: | ||
487 | return rc; | ||
488 | } | ||
489 | |||
490 | /* | ||
491 | * Clean up/close an IA. | ||
492 | * o if event handles and PD have been initialized, free them. | ||
493 | * o close the IA | ||
494 | */ | ||
495 | void | ||
496 | rpcrdma_ia_close(struct rpcrdma_ia *ia) | ||
497 | { | ||
498 | int rc; | ||
499 | |||
500 | dprintk("RPC: %s: entering\n", __func__); | ||
501 | if (ia->ri_bind_mem != NULL) { | ||
502 | rc = ib_dereg_mr(ia->ri_bind_mem); | ||
503 | dprintk("RPC: %s: ib_dereg_mr returned %i\n", | ||
504 | __func__, rc); | ||
505 | } | ||
506 | if (ia->ri_id != NULL && !IS_ERR(ia->ri_id) && ia->ri_id->qp) | ||
507 | rdma_destroy_qp(ia->ri_id); | ||
508 | if (ia->ri_pd != NULL && !IS_ERR(ia->ri_pd)) { | ||
509 | rc = ib_dealloc_pd(ia->ri_pd); | ||
510 | dprintk("RPC: %s: ib_dealloc_pd returned %i\n", | ||
511 | __func__, rc); | ||
512 | } | ||
513 | if (ia->ri_id != NULL && !IS_ERR(ia->ri_id)) | ||
514 | rdma_destroy_id(ia->ri_id); | ||
515 | } | ||
516 | |||
517 | /* | ||
518 | * Create unconnected endpoint. | ||
519 | */ | ||
520 | int | ||
521 | rpcrdma_ep_create(struct rpcrdma_ep *ep, struct rpcrdma_ia *ia, | ||
522 | struct rpcrdma_create_data_internal *cdata) | ||
523 | { | ||
524 | struct ib_device_attr devattr; | ||
525 | int rc; | ||
526 | |||
527 | rc = ib_query_device(ia->ri_id->device, &devattr); | ||
528 | if (rc) { | ||
529 | dprintk("RPC: %s: ib_query_device failed %d\n", | ||
530 | __func__, rc); | ||
531 | return rc; | ||
532 | } | ||
533 | |||
534 | /* check provider's send/recv wr limits */ | ||
535 | if (cdata->max_requests > devattr.max_qp_wr) | ||
536 | cdata->max_requests = devattr.max_qp_wr; | ||
537 | |||
538 | ep->rep_attr.event_handler = rpcrdma_qp_async_error_upcall; | ||
539 | ep->rep_attr.qp_context = ep; | ||
540 | /* send_cq and recv_cq initialized below */ | ||
541 | ep->rep_attr.srq = NULL; | ||
542 | ep->rep_attr.cap.max_send_wr = cdata->max_requests; | ||
543 | switch (ia->ri_memreg_strategy) { | ||
544 | case RPCRDMA_MEMWINDOWS_ASYNC: | ||
545 | case RPCRDMA_MEMWINDOWS: | ||
546 | /* Add room for mw_binds+unbinds - overkill! */ | ||
547 | ep->rep_attr.cap.max_send_wr++; | ||
548 | ep->rep_attr.cap.max_send_wr *= (2 * RPCRDMA_MAX_SEGS); | ||
549 | if (ep->rep_attr.cap.max_send_wr > devattr.max_qp_wr) | ||
550 | return -EINVAL; | ||
551 | break; | ||
552 | default: | ||
553 | break; | ||
554 | } | ||
555 | ep->rep_attr.cap.max_recv_wr = cdata->max_requests; | ||
556 | ep->rep_attr.cap.max_send_sge = (cdata->padding ? 4 : 2); | ||
557 | ep->rep_attr.cap.max_recv_sge = 1; | ||
558 | ep->rep_attr.cap.max_inline_data = 0; | ||
559 | ep->rep_attr.sq_sig_type = IB_SIGNAL_REQ_WR; | ||
560 | ep->rep_attr.qp_type = IB_QPT_RC; | ||
561 | ep->rep_attr.port_num = ~0; | ||
562 | |||
563 | dprintk("RPC: %s: requested max: dtos: send %d recv %d; " | ||
564 | "iovs: send %d recv %d\n", | ||
565 | __func__, | ||
566 | ep->rep_attr.cap.max_send_wr, | ||
567 | ep->rep_attr.cap.max_recv_wr, | ||
568 | ep->rep_attr.cap.max_send_sge, | ||
569 | ep->rep_attr.cap.max_recv_sge); | ||
570 | |||
571 | /* set trigger for requesting send completion */ | ||
572 | ep->rep_cqinit = ep->rep_attr.cap.max_send_wr/2 /* - 1*/; | ||
573 | switch (ia->ri_memreg_strategy) { | ||
574 | case RPCRDMA_MEMWINDOWS_ASYNC: | ||
575 | case RPCRDMA_MEMWINDOWS: | ||
576 | ep->rep_cqinit -= RPCRDMA_MAX_SEGS; | ||
577 | break; | ||
578 | default: | ||
579 | break; | ||
580 | } | ||
581 | if (ep->rep_cqinit <= 2) | ||
582 | ep->rep_cqinit = 0; | ||
583 | INIT_CQCOUNT(ep); | ||
584 | ep->rep_ia = ia; | ||
585 | init_waitqueue_head(&ep->rep_connect_wait); | ||
586 | |||
587 | /* | ||
588 | * Create a single cq for receive dto and mw_bind (only ever | ||
589 | * care about unbind, really). Send completions are suppressed. | ||
590 | * Use single threaded tasklet upcalls to maintain ordering. | ||
591 | */ | ||
592 | ep->rep_cq = ib_create_cq(ia->ri_id->device, rpcrdma_cq_event_upcall, | ||
593 | rpcrdma_cq_async_error_upcall, NULL, | ||
594 | ep->rep_attr.cap.max_recv_wr + | ||
595 | ep->rep_attr.cap.max_send_wr + 1, 0); | ||
596 | if (IS_ERR(ep->rep_cq)) { | ||
597 | rc = PTR_ERR(ep->rep_cq); | ||
598 | dprintk("RPC: %s: ib_create_cq failed: %i\n", | ||
599 | __func__, rc); | ||
600 | goto out1; | ||
601 | } | ||
602 | |||
603 | rc = ib_req_notify_cq(ep->rep_cq, IB_CQ_NEXT_COMP); | ||
604 | if (rc) { | ||
605 | dprintk("RPC: %s: ib_req_notify_cq failed: %i\n", | ||
606 | __func__, rc); | ||
607 | goto out2; | ||
608 | } | ||
609 | |||
610 | ep->rep_attr.send_cq = ep->rep_cq; | ||
611 | ep->rep_attr.recv_cq = ep->rep_cq; | ||
612 | |||
613 | /* Initialize cma parameters */ | ||
614 | |||
615 | /* RPC/RDMA does not use private data */ | ||
616 | ep->rep_remote_cma.private_data = NULL; | ||
617 | ep->rep_remote_cma.private_data_len = 0; | ||
618 | |||
619 | /* Client offers RDMA Read but does not initiate */ | ||
620 | switch (ia->ri_memreg_strategy) { | ||
621 | case RPCRDMA_BOUNCEBUFFERS: | ||
622 | ep->rep_remote_cma.responder_resources = 0; | ||
623 | break; | ||
624 | case RPCRDMA_MTHCAFMR: | ||
625 | case RPCRDMA_REGISTER: | ||
626 | ep->rep_remote_cma.responder_resources = cdata->max_requests * | ||
627 | (RPCRDMA_MAX_DATA_SEGS / 8); | ||
628 | break; | ||
629 | case RPCRDMA_MEMWINDOWS: | ||
630 | case RPCRDMA_MEMWINDOWS_ASYNC: | ||
631 | #if RPCRDMA_PERSISTENT_REGISTRATION | ||
632 | case RPCRDMA_ALLPHYSICAL: | ||
633 | #endif | ||
634 | ep->rep_remote_cma.responder_resources = cdata->max_requests * | ||
635 | (RPCRDMA_MAX_DATA_SEGS / 2); | ||
636 | break; | ||
637 | default: | ||
638 | break; | ||
639 | } | ||
640 | if (ep->rep_remote_cma.responder_resources > devattr.max_qp_rd_atom) | ||
641 | ep->rep_remote_cma.responder_resources = devattr.max_qp_rd_atom; | ||
642 | ep->rep_remote_cma.initiator_depth = 0; | ||
643 | |||
644 | ep->rep_remote_cma.retry_count = 7; | ||
645 | ep->rep_remote_cma.flow_control = 0; | ||
646 | ep->rep_remote_cma.rnr_retry_count = 0; | ||
647 | |||
648 | return 0; | ||
649 | |||
650 | out2: | ||
651 | if (ib_destroy_cq(ep->rep_cq)) | ||
652 | ; | ||
653 | out1: | ||
654 | return rc; | ||
655 | } | ||
656 | |||
657 | /* | ||
658 | * rpcrdma_ep_destroy | ||
659 | * | ||
660 | * Disconnect and destroy endpoint. After this, the only | ||
661 | * valid operations on the ep are to free it (if dynamically | ||
662 | * allocated) or re-create it. | ||
663 | * | ||
664 | * The caller's error handling must be sure to not leak the endpoint | ||
665 | * if this function fails. | ||
666 | */ | ||
667 | int | ||
668 | rpcrdma_ep_destroy(struct rpcrdma_ep *ep, struct rpcrdma_ia *ia) | ||
669 | { | ||
670 | int rc; | ||
671 | |||
672 | dprintk("RPC: %s: entering, connected is %d\n", | ||
673 | __func__, ep->rep_connected); | ||
674 | |||
675 | if (ia->ri_id->qp) { | ||
676 | rc = rpcrdma_ep_disconnect(ep, ia); | ||
677 | if (rc) | ||
678 | dprintk("RPC: %s: rpcrdma_ep_disconnect" | ||
679 | " returned %i\n", __func__, rc); | ||
680 | } | ||
681 | |||
682 | ep->rep_func = NULL; | ||
683 | |||
684 | /* padding - could be done in rpcrdma_buffer_destroy... */ | ||
685 | if (ep->rep_pad_mr) { | ||
686 | rpcrdma_deregister_internal(ia, ep->rep_pad_mr, &ep->rep_pad); | ||
687 | ep->rep_pad_mr = NULL; | ||
688 | } | ||
689 | |||
690 | if (ia->ri_id->qp) { | ||
691 | rdma_destroy_qp(ia->ri_id); | ||
692 | ia->ri_id->qp = NULL; | ||
693 | } | ||
694 | |||
695 | rpcrdma_clean_cq(ep->rep_cq); | ||
696 | rc = ib_destroy_cq(ep->rep_cq); | ||
697 | if (rc) | ||
698 | dprintk("RPC: %s: ib_destroy_cq returned %i\n", | ||
699 | __func__, rc); | ||
700 | |||
701 | return rc; | ||
702 | } | ||
703 | |||
704 | /* | ||
705 | * Connect unconnected endpoint. | ||
706 | */ | ||
707 | int | ||
708 | rpcrdma_ep_connect(struct rpcrdma_ep *ep, struct rpcrdma_ia *ia) | ||
709 | { | ||
710 | struct rdma_cm_id *id; | ||
711 | int rc = 0; | ||
712 | int retry_count = 0; | ||
713 | int reconnect = (ep->rep_connected != 0); | ||
714 | |||
715 | if (reconnect) { | ||
716 | struct rpcrdma_xprt *xprt; | ||
717 | retry: | ||
718 | rc = rpcrdma_ep_disconnect(ep, ia); | ||
719 | if (rc && rc != -ENOTCONN) | ||
720 | dprintk("RPC: %s: rpcrdma_ep_disconnect" | ||
721 | " status %i\n", __func__, rc); | ||
722 | rpcrdma_clean_cq(ep->rep_cq); | ||
723 | |||
724 | xprt = container_of(ia, struct rpcrdma_xprt, rx_ia); | ||
725 | id = rpcrdma_create_id(xprt, ia, | ||
726 | (struct sockaddr *)&xprt->rx_data.addr); | ||
727 | if (IS_ERR(id)) { | ||
728 | rc = PTR_ERR(id); | ||
729 | goto out; | ||
730 | } | ||
731 | /* TEMP TEMP TEMP - fail if new device: | ||
732 | * Deregister/remarshal *all* requests! | ||
733 | * Close and recreate adapter, pd, etc! | ||
734 | * Re-determine all attributes still sane! | ||
735 | * More stuff I haven't thought of! | ||
736 | * Rrrgh! | ||
737 | */ | ||
738 | if (ia->ri_id->device != id->device) { | ||
739 | printk("RPC: %s: can't reconnect on " | ||
740 | "different device!\n", __func__); | ||
741 | rdma_destroy_id(id); | ||
742 | rc = -ENETDOWN; | ||
743 | goto out; | ||
744 | } | ||
745 | /* END TEMP */ | ||
746 | rdma_destroy_id(ia->ri_id); | ||
747 | ia->ri_id = id; | ||
748 | } | ||
749 | |||
750 | rc = rdma_create_qp(ia->ri_id, ia->ri_pd, &ep->rep_attr); | ||
751 | if (rc) { | ||
752 | dprintk("RPC: %s: rdma_create_qp failed %i\n", | ||
753 | __func__, rc); | ||
754 | goto out; | ||
755 | } | ||
756 | |||
757 | /* XXX Tavor device performs badly with 2K MTU! */ | ||
758 | if (strnicmp(ia->ri_id->device->dma_device->bus->name, "pci", 3) == 0) { | ||
759 | struct pci_dev *pcid = to_pci_dev(ia->ri_id->device->dma_device); | ||
760 | if (pcid->device == PCI_DEVICE_ID_MELLANOX_TAVOR && | ||
761 | (pcid->vendor == PCI_VENDOR_ID_MELLANOX || | ||
762 | pcid->vendor == PCI_VENDOR_ID_TOPSPIN)) { | ||
763 | struct ib_qp_attr attr = { | ||
764 | .path_mtu = IB_MTU_1024 | ||
765 | }; | ||
766 | rc = ib_modify_qp(ia->ri_id->qp, &attr, IB_QP_PATH_MTU); | ||
767 | } | ||
768 | } | ||
769 | |||
770 | /* Theoretically a client initiator_depth > 0 is not needed, | ||
771 | * but many peers fail to complete the connection unless they | ||
772 | * == responder_resources! */ | ||
773 | if (ep->rep_remote_cma.initiator_depth != | ||
774 | ep->rep_remote_cma.responder_resources) | ||
775 | ep->rep_remote_cma.initiator_depth = | ||
776 | ep->rep_remote_cma.responder_resources; | ||
777 | |||
778 | ep->rep_connected = 0; | ||
779 | |||
780 | rc = rdma_connect(ia->ri_id, &ep->rep_remote_cma); | ||
781 | if (rc) { | ||
782 | dprintk("RPC: %s: rdma_connect() failed with %i\n", | ||
783 | __func__, rc); | ||
784 | goto out; | ||
785 | } | ||
786 | |||
787 | if (reconnect) | ||
788 | return 0; | ||
789 | |||
790 | wait_event_interruptible(ep->rep_connect_wait, ep->rep_connected != 0); | ||
791 | |||
792 | /* | ||
793 | * Check state. A non-peer reject indicates no listener | ||
794 | * (ECONNREFUSED), which may be a transient state. All | ||
795 | * others indicate a transport condition which has already | ||
796 | * undergone a best-effort. | ||
797 | */ | ||
798 | if (ep->rep_connected == -ECONNREFUSED | ||
799 | && ++retry_count <= RDMA_CONNECT_RETRY_MAX) { | ||
800 | dprintk("RPC: %s: non-peer_reject, retry\n", __func__); | ||
801 | goto retry; | ||
802 | } | ||
803 | if (ep->rep_connected <= 0) { | ||
804 | /* Sometimes, the only way to reliably connect to remote | ||
805 | * CMs is to use same nonzero values for ORD and IRD. */ | ||
806 | ep->rep_remote_cma.initiator_depth = | ||
807 | ep->rep_remote_cma.responder_resources; | ||
808 | if (ep->rep_remote_cma.initiator_depth == 0) | ||
809 | ++ep->rep_remote_cma.initiator_depth; | ||
810 | if (ep->rep_remote_cma.responder_resources == 0) | ||
811 | ++ep->rep_remote_cma.responder_resources; | ||
812 | if (retry_count++ == 0) | ||
813 | goto retry; | ||
814 | rc = ep->rep_connected; | ||
815 | } else { | ||
816 | dprintk("RPC: %s: connected\n", __func__); | ||
817 | } | ||
818 | |||
819 | out: | ||
820 | if (rc) | ||
821 | ep->rep_connected = rc; | ||
822 | return rc; | ||
823 | } | ||
824 | |||
825 | /* | ||
826 | * rpcrdma_ep_disconnect | ||
827 | * | ||
828 | * This is separate from destroy to facilitate the ability | ||
829 | * to reconnect without recreating the endpoint. | ||
830 | * | ||
831 | * This call is not reentrant, and must not be made in parallel | ||
832 | * on the same endpoint. | ||
833 | */ | ||
834 | int | ||
835 | rpcrdma_ep_disconnect(struct rpcrdma_ep *ep, struct rpcrdma_ia *ia) | ||
836 | { | ||
837 | int rc; | ||
838 | |||
839 | rpcrdma_clean_cq(ep->rep_cq); | ||
840 | rc = rdma_disconnect(ia->ri_id); | ||
841 | if (!rc) { | ||
842 | /* returns without wait if not connected */ | ||
843 | wait_event_interruptible(ep->rep_connect_wait, | ||
844 | ep->rep_connected != 1); | ||
845 | dprintk("RPC: %s: after wait, %sconnected\n", __func__, | ||
846 | (ep->rep_connected == 1) ? "still " : "dis"); | ||
847 | } else { | ||
848 | dprintk("RPC: %s: rdma_disconnect %i\n", __func__, rc); | ||
849 | ep->rep_connected = rc; | ||
850 | } | ||
851 | return rc; | ||
852 | } | ||
853 | |||
854 | /* | ||
855 | * Initialize buffer memory | ||
856 | */ | ||
857 | int | ||
858 | rpcrdma_buffer_create(struct rpcrdma_buffer *buf, struct rpcrdma_ep *ep, | ||
859 | struct rpcrdma_ia *ia, struct rpcrdma_create_data_internal *cdata) | ||
860 | { | ||
861 | char *p; | ||
862 | size_t len; | ||
863 | int i, rc; | ||
864 | |||
865 | buf->rb_max_requests = cdata->max_requests; | ||
866 | spin_lock_init(&buf->rb_lock); | ||
867 | atomic_set(&buf->rb_credits, 1); | ||
868 | |||
869 | /* Need to allocate: | ||
870 | * 1. arrays for send and recv pointers | ||
871 | * 2. arrays of struct rpcrdma_req to fill in pointers | ||
872 | * 3. array of struct rpcrdma_rep for replies | ||
873 | * 4. padding, if any | ||
874 | * 5. mw's, if any | ||
875 | * Send/recv buffers in req/rep need to be registered | ||
876 | */ | ||
877 | |||
878 | len = buf->rb_max_requests * | ||
879 | (sizeof(struct rpcrdma_req *) + sizeof(struct rpcrdma_rep *)); | ||
880 | len += cdata->padding; | ||
881 | switch (ia->ri_memreg_strategy) { | ||
882 | case RPCRDMA_MTHCAFMR: | ||
883 | /* TBD we are perhaps overallocating here */ | ||
884 | len += (buf->rb_max_requests + 1) * RPCRDMA_MAX_SEGS * | ||
885 | sizeof(struct rpcrdma_mw); | ||
886 | break; | ||
887 | case RPCRDMA_MEMWINDOWS_ASYNC: | ||
888 | case RPCRDMA_MEMWINDOWS: | ||
889 | len += (buf->rb_max_requests + 1) * RPCRDMA_MAX_SEGS * | ||
890 | sizeof(struct rpcrdma_mw); | ||
891 | break; | ||
892 | default: | ||
893 | break; | ||
894 | } | ||
895 | |||
896 | /* allocate 1, 4 and 5 in one shot */ | ||
897 | p = kzalloc(len, GFP_KERNEL); | ||
898 | if (p == NULL) { | ||
899 | dprintk("RPC: %s: req_t/rep_t/pad kzalloc(%zd) failed\n", | ||
900 | __func__, len); | ||
901 | rc = -ENOMEM; | ||
902 | goto out; | ||
903 | } | ||
904 | buf->rb_pool = p; /* for freeing it later */ | ||
905 | |||
906 | buf->rb_send_bufs = (struct rpcrdma_req **) p; | ||
907 | p = (char *) &buf->rb_send_bufs[buf->rb_max_requests]; | ||
908 | buf->rb_recv_bufs = (struct rpcrdma_rep **) p; | ||
909 | p = (char *) &buf->rb_recv_bufs[buf->rb_max_requests]; | ||
910 | |||
911 | /* | ||
912 | * Register the zeroed pad buffer, if any. | ||
913 | */ | ||
914 | if (cdata->padding) { | ||
915 | rc = rpcrdma_register_internal(ia, p, cdata->padding, | ||
916 | &ep->rep_pad_mr, &ep->rep_pad); | ||
917 | if (rc) | ||
918 | goto out; | ||
919 | } | ||
920 | p += cdata->padding; | ||
921 | |||
922 | /* | ||
923 | * Allocate the fmr's, or mw's for mw_bind chunk registration. | ||
924 | * We "cycle" the mw's in order to minimize rkey reuse, | ||
925 | * and also reduce unbind-to-bind collision. | ||
926 | */ | ||
927 | INIT_LIST_HEAD(&buf->rb_mws); | ||
928 | switch (ia->ri_memreg_strategy) { | ||
929 | case RPCRDMA_MTHCAFMR: | ||
930 | { | ||
931 | struct rpcrdma_mw *r = (struct rpcrdma_mw *)p; | ||
932 | struct ib_fmr_attr fa = { | ||
933 | RPCRDMA_MAX_DATA_SEGS, 1, PAGE_SHIFT | ||
934 | }; | ||
935 | /* TBD we are perhaps overallocating here */ | ||
936 | for (i = (buf->rb_max_requests+1) * RPCRDMA_MAX_SEGS; i; i--) { | ||
937 | r->r.fmr = ib_alloc_fmr(ia->ri_pd, | ||
938 | IB_ACCESS_REMOTE_WRITE | IB_ACCESS_REMOTE_READ, | ||
939 | &fa); | ||
940 | if (IS_ERR(r->r.fmr)) { | ||
941 | rc = PTR_ERR(r->r.fmr); | ||
942 | dprintk("RPC: %s: ib_alloc_fmr" | ||
943 | " failed %i\n", __func__, rc); | ||
944 | goto out; | ||
945 | } | ||
946 | list_add(&r->mw_list, &buf->rb_mws); | ||
947 | ++r; | ||
948 | } | ||
949 | } | ||
950 | break; | ||
951 | case RPCRDMA_MEMWINDOWS_ASYNC: | ||
952 | case RPCRDMA_MEMWINDOWS: | ||
953 | { | ||
954 | struct rpcrdma_mw *r = (struct rpcrdma_mw *)p; | ||
955 | /* Allocate one extra request's worth, for full cycling */ | ||
956 | for (i = (buf->rb_max_requests+1) * RPCRDMA_MAX_SEGS; i; i--) { | ||
957 | r->r.mw = ib_alloc_mw(ia->ri_pd); | ||
958 | if (IS_ERR(r->r.mw)) { | ||
959 | rc = PTR_ERR(r->r.mw); | ||
960 | dprintk("RPC: %s: ib_alloc_mw" | ||
961 | " failed %i\n", __func__, rc); | ||
962 | goto out; | ||
963 | } | ||
964 | list_add(&r->mw_list, &buf->rb_mws); | ||
965 | ++r; | ||
966 | } | ||
967 | } | ||
968 | break; | ||
969 | default: | ||
970 | break; | ||
971 | } | ||
972 | |||
973 | /* | ||
974 | * Allocate/init the request/reply buffers. Doing this | ||
975 | * using kmalloc for now -- one for each buf. | ||
976 | */ | ||
977 | for (i = 0; i < buf->rb_max_requests; i++) { | ||
978 | struct rpcrdma_req *req; | ||
979 | struct rpcrdma_rep *rep; | ||
980 | |||
981 | len = cdata->inline_wsize + sizeof(struct rpcrdma_req); | ||
982 | /* RPC layer requests *double* size + 1K RPC_SLACK_SPACE! */ | ||
983 | /* Typical ~2400b, so rounding up saves work later */ | ||
984 | if (len < 4096) | ||
985 | len = 4096; | ||
986 | req = kmalloc(len, GFP_KERNEL); | ||
987 | if (req == NULL) { | ||
988 | dprintk("RPC: %s: request buffer %d alloc" | ||
989 | " failed\n", __func__, i); | ||
990 | rc = -ENOMEM; | ||
991 | goto out; | ||
992 | } | ||
993 | memset(req, 0, sizeof(struct rpcrdma_req)); | ||
994 | buf->rb_send_bufs[i] = req; | ||
995 | buf->rb_send_bufs[i]->rl_buffer = buf; | ||
996 | |||
997 | rc = rpcrdma_register_internal(ia, req->rl_base, | ||
998 | len - offsetof(struct rpcrdma_req, rl_base), | ||
999 | &buf->rb_send_bufs[i]->rl_handle, | ||
1000 | &buf->rb_send_bufs[i]->rl_iov); | ||
1001 | if (rc) | ||
1002 | goto out; | ||
1003 | |||
1004 | buf->rb_send_bufs[i]->rl_size = len-sizeof(struct rpcrdma_req); | ||
1005 | |||
1006 | len = cdata->inline_rsize + sizeof(struct rpcrdma_rep); | ||
1007 | rep = kmalloc(len, GFP_KERNEL); | ||
1008 | if (rep == NULL) { | ||
1009 | dprintk("RPC: %s: reply buffer %d alloc failed\n", | ||
1010 | __func__, i); | ||
1011 | rc = -ENOMEM; | ||
1012 | goto out; | ||
1013 | } | ||
1014 | memset(rep, 0, sizeof(struct rpcrdma_rep)); | ||
1015 | buf->rb_recv_bufs[i] = rep; | ||
1016 | buf->rb_recv_bufs[i]->rr_buffer = buf; | ||
1017 | init_waitqueue_head(&rep->rr_unbind); | ||
1018 | |||
1019 | rc = rpcrdma_register_internal(ia, rep->rr_base, | ||
1020 | len - offsetof(struct rpcrdma_rep, rr_base), | ||
1021 | &buf->rb_recv_bufs[i]->rr_handle, | ||
1022 | &buf->rb_recv_bufs[i]->rr_iov); | ||
1023 | if (rc) | ||
1024 | goto out; | ||
1025 | |||
1026 | } | ||
1027 | dprintk("RPC: %s: max_requests %d\n", | ||
1028 | __func__, buf->rb_max_requests); | ||
1029 | /* done */ | ||
1030 | return 0; | ||
1031 | out: | ||
1032 | rpcrdma_buffer_destroy(buf); | ||
1033 | return rc; | ||
1034 | } | ||
1035 | |||
1036 | /* | ||
1037 | * Unregister and destroy buffer memory. Need to deal with | ||
1038 | * partial initialization, so it's callable from failed create. | ||
1039 | * Must be called before destroying endpoint, as registrations | ||
1040 | * reference it. | ||
1041 | */ | ||
1042 | void | ||
1043 | rpcrdma_buffer_destroy(struct rpcrdma_buffer *buf) | ||
1044 | { | ||
1045 | int rc, i; | ||
1046 | struct rpcrdma_ia *ia = rdmab_to_ia(buf); | ||
1047 | |||
1048 | /* clean up in reverse order from create | ||
1049 | * 1. recv mr memory (mr free, then kfree) | ||
1050 | * 1a. bind mw memory | ||
1051 | * 2. send mr memory (mr free, then kfree) | ||
1052 | * 3. padding (if any) [moved to rpcrdma_ep_destroy] | ||
1053 | * 4. arrays | ||
1054 | */ | ||
1055 | dprintk("RPC: %s: entering\n", __func__); | ||
1056 | |||
1057 | for (i = 0; i < buf->rb_max_requests; i++) { | ||
1058 | if (buf->rb_recv_bufs && buf->rb_recv_bufs[i]) { | ||
1059 | rpcrdma_deregister_internal(ia, | ||
1060 | buf->rb_recv_bufs[i]->rr_handle, | ||
1061 | &buf->rb_recv_bufs[i]->rr_iov); | ||
1062 | kfree(buf->rb_recv_bufs[i]); | ||
1063 | } | ||
1064 | if (buf->rb_send_bufs && buf->rb_send_bufs[i]) { | ||
1065 | while (!list_empty(&buf->rb_mws)) { | ||
1066 | struct rpcrdma_mw *r; | ||
1067 | r = list_entry(buf->rb_mws.next, | ||
1068 | struct rpcrdma_mw, mw_list); | ||
1069 | list_del(&r->mw_list); | ||
1070 | switch (ia->ri_memreg_strategy) { | ||
1071 | case RPCRDMA_MTHCAFMR: | ||
1072 | rc = ib_dealloc_fmr(r->r.fmr); | ||
1073 | if (rc) | ||
1074 | dprintk("RPC: %s:" | ||
1075 | " ib_dealloc_fmr" | ||
1076 | " failed %i\n", | ||
1077 | __func__, rc); | ||
1078 | break; | ||
1079 | case RPCRDMA_MEMWINDOWS_ASYNC: | ||
1080 | case RPCRDMA_MEMWINDOWS: | ||
1081 | rc = ib_dealloc_mw(r->r.mw); | ||
1082 | if (rc) | ||
1083 | dprintk("RPC: %s:" | ||
1084 | " ib_dealloc_mw" | ||
1085 | " failed %i\n", | ||
1086 | __func__, rc); | ||
1087 | break; | ||
1088 | default: | ||
1089 | break; | ||
1090 | } | ||
1091 | } | ||
1092 | rpcrdma_deregister_internal(ia, | ||
1093 | buf->rb_send_bufs[i]->rl_handle, | ||
1094 | &buf->rb_send_bufs[i]->rl_iov); | ||
1095 | kfree(buf->rb_send_bufs[i]); | ||
1096 | } | ||
1097 | } | ||
1098 | |||
1099 | kfree(buf->rb_pool); | ||
1100 | } | ||
1101 | |||
1102 | /* | ||
1103 | * Get a set of request/reply buffers. | ||
1104 | * | ||
1105 | * Reply buffer (if needed) is attached to send buffer upon return. | ||
1106 | * Rule: | ||
1107 | * rb_send_index and rb_recv_index MUST always be pointing to the | ||
1108 | * *next* available buffer (non-NULL). They are incremented after | ||
1109 | * removing buffers, and decremented *before* returning them. | ||
1110 | */ | ||
1111 | struct rpcrdma_req * | ||
1112 | rpcrdma_buffer_get(struct rpcrdma_buffer *buffers) | ||
1113 | { | ||
1114 | struct rpcrdma_req *req; | ||
1115 | unsigned long flags; | ||
1116 | |||
1117 | spin_lock_irqsave(&buffers->rb_lock, flags); | ||
1118 | if (buffers->rb_send_index == buffers->rb_max_requests) { | ||
1119 | spin_unlock_irqrestore(&buffers->rb_lock, flags); | ||
1120 | dprintk("RPC: %s: out of request buffers\n", __func__); | ||
1121 | return ((struct rpcrdma_req *)NULL); | ||
1122 | } | ||
1123 | |||
1124 | req = buffers->rb_send_bufs[buffers->rb_send_index]; | ||
1125 | if (buffers->rb_send_index < buffers->rb_recv_index) { | ||
1126 | dprintk("RPC: %s: %d extra receives outstanding (ok)\n", | ||
1127 | __func__, | ||
1128 | buffers->rb_recv_index - buffers->rb_send_index); | ||
1129 | req->rl_reply = NULL; | ||
1130 | } else { | ||
1131 | req->rl_reply = buffers->rb_recv_bufs[buffers->rb_recv_index]; | ||
1132 | buffers->rb_recv_bufs[buffers->rb_recv_index++] = NULL; | ||
1133 | } | ||
1134 | buffers->rb_send_bufs[buffers->rb_send_index++] = NULL; | ||
1135 | if (!list_empty(&buffers->rb_mws)) { | ||
1136 | int i = RPCRDMA_MAX_SEGS - 1; | ||
1137 | do { | ||
1138 | struct rpcrdma_mw *r; | ||
1139 | r = list_entry(buffers->rb_mws.next, | ||
1140 | struct rpcrdma_mw, mw_list); | ||
1141 | list_del(&r->mw_list); | ||
1142 | req->rl_segments[i].mr_chunk.rl_mw = r; | ||
1143 | } while (--i >= 0); | ||
1144 | } | ||
1145 | spin_unlock_irqrestore(&buffers->rb_lock, flags); | ||
1146 | return req; | ||
1147 | } | ||
1148 | |||
1149 | /* | ||
1150 | * Put request/reply buffers back into pool. | ||
1151 | * Pre-decrement counter/array index. | ||
1152 | */ | ||
1153 | void | ||
1154 | rpcrdma_buffer_put(struct rpcrdma_req *req) | ||
1155 | { | ||
1156 | struct rpcrdma_buffer *buffers = req->rl_buffer; | ||
1157 | struct rpcrdma_ia *ia = rdmab_to_ia(buffers); | ||
1158 | int i; | ||
1159 | unsigned long flags; | ||
1160 | |||
1161 | BUG_ON(req->rl_nchunks != 0); | ||
1162 | spin_lock_irqsave(&buffers->rb_lock, flags); | ||
1163 | buffers->rb_send_bufs[--buffers->rb_send_index] = req; | ||
1164 | req->rl_niovs = 0; | ||
1165 | if (req->rl_reply) { | ||
1166 | buffers->rb_recv_bufs[--buffers->rb_recv_index] = req->rl_reply; | ||
1167 | init_waitqueue_head(&req->rl_reply->rr_unbind); | ||
1168 | req->rl_reply->rr_func = NULL; | ||
1169 | req->rl_reply = NULL; | ||
1170 | } | ||
1171 | switch (ia->ri_memreg_strategy) { | ||
1172 | case RPCRDMA_MTHCAFMR: | ||
1173 | case RPCRDMA_MEMWINDOWS_ASYNC: | ||
1174 | case RPCRDMA_MEMWINDOWS: | ||
1175 | /* | ||
1176 | * Cycle mw's back in reverse order, and "spin" them. | ||
1177 | * This delays and scrambles reuse as much as possible. | ||
1178 | */ | ||
1179 | i = 1; | ||
1180 | do { | ||
1181 | struct rpcrdma_mw **mw; | ||
1182 | mw = &req->rl_segments[i].mr_chunk.rl_mw; | ||
1183 | list_add_tail(&(*mw)->mw_list, &buffers->rb_mws); | ||
1184 | *mw = NULL; | ||
1185 | } while (++i < RPCRDMA_MAX_SEGS); | ||
1186 | list_add_tail(&req->rl_segments[0].mr_chunk.rl_mw->mw_list, | ||
1187 | &buffers->rb_mws); | ||
1188 | req->rl_segments[0].mr_chunk.rl_mw = NULL; | ||
1189 | break; | ||
1190 | default: | ||
1191 | break; | ||
1192 | } | ||
1193 | spin_unlock_irqrestore(&buffers->rb_lock, flags); | ||
1194 | } | ||
1195 | |||
1196 | /* | ||
1197 | * Recover reply buffers from pool. | ||
1198 | * This happens when recovering from error conditions. | ||
1199 | * Post-increment counter/array index. | ||
1200 | */ | ||
1201 | void | ||
1202 | rpcrdma_recv_buffer_get(struct rpcrdma_req *req) | ||
1203 | { | ||
1204 | struct rpcrdma_buffer *buffers = req->rl_buffer; | ||
1205 | unsigned long flags; | ||
1206 | |||
1207 | if (req->rl_iov.length == 0) /* special case xprt_rdma_allocate() */ | ||
1208 | buffers = ((struct rpcrdma_req *) buffers)->rl_buffer; | ||
1209 | spin_lock_irqsave(&buffers->rb_lock, flags); | ||
1210 | if (buffers->rb_recv_index < buffers->rb_max_requests) { | ||
1211 | req->rl_reply = buffers->rb_recv_bufs[buffers->rb_recv_index]; | ||
1212 | buffers->rb_recv_bufs[buffers->rb_recv_index++] = NULL; | ||
1213 | } | ||
1214 | spin_unlock_irqrestore(&buffers->rb_lock, flags); | ||
1215 | } | ||
1216 | |||
1217 | /* | ||
1218 | * Put reply buffers back into pool when not attached to | ||
1219 | * request. This happens in error conditions, and when | ||
1220 | * aborting unbinds. Pre-decrement counter/array index. | ||
1221 | */ | ||
1222 | void | ||
1223 | rpcrdma_recv_buffer_put(struct rpcrdma_rep *rep) | ||
1224 | { | ||
1225 | struct rpcrdma_buffer *buffers = rep->rr_buffer; | ||
1226 | unsigned long flags; | ||
1227 | |||
1228 | rep->rr_func = NULL; | ||
1229 | spin_lock_irqsave(&buffers->rb_lock, flags); | ||
1230 | buffers->rb_recv_bufs[--buffers->rb_recv_index] = rep; | ||
1231 | spin_unlock_irqrestore(&buffers->rb_lock, flags); | ||
1232 | } | ||
1233 | |||
1234 | /* | ||
1235 | * Wrappers for internal-use kmalloc memory registration, used by buffer code. | ||
1236 | */ | ||
1237 | |||
1238 | int | ||
1239 | rpcrdma_register_internal(struct rpcrdma_ia *ia, void *va, int len, | ||
1240 | struct ib_mr **mrp, struct ib_sge *iov) | ||
1241 | { | ||
1242 | struct ib_phys_buf ipb; | ||
1243 | struct ib_mr *mr; | ||
1244 | int rc; | ||
1245 | |||
1246 | /* | ||
1247 | * All memory passed here was kmalloc'ed, therefore phys-contiguous. | ||
1248 | */ | ||
1249 | iov->addr = ib_dma_map_single(ia->ri_id->device, | ||
1250 | va, len, DMA_BIDIRECTIONAL); | ||
1251 | iov->length = len; | ||
1252 | |||
1253 | if (ia->ri_bind_mem != NULL) { | ||
1254 | *mrp = NULL; | ||
1255 | iov->lkey = ia->ri_bind_mem->lkey; | ||
1256 | return 0; | ||
1257 | } | ||
1258 | |||
1259 | ipb.addr = iov->addr; | ||
1260 | ipb.size = iov->length; | ||
1261 | mr = ib_reg_phys_mr(ia->ri_pd, &ipb, 1, | ||
1262 | IB_ACCESS_LOCAL_WRITE, &iov->addr); | ||
1263 | |||
1264 | dprintk("RPC: %s: phys convert: 0x%llx " | ||
1265 | "registered 0x%llx length %d\n", | ||
1266 | __func__, (unsigned long long)ipb.addr, | ||
1267 | (unsigned long long)iov->addr, len); | ||
1268 | |||
1269 | if (IS_ERR(mr)) { | ||
1270 | *mrp = NULL; | ||
1271 | rc = PTR_ERR(mr); | ||
1272 | dprintk("RPC: %s: failed with %i\n", __func__, rc); | ||
1273 | } else { | ||
1274 | *mrp = mr; | ||
1275 | iov->lkey = mr->lkey; | ||
1276 | rc = 0; | ||
1277 | } | ||
1278 | |||
1279 | return rc; | ||
1280 | } | ||
1281 | |||
1282 | int | ||
1283 | rpcrdma_deregister_internal(struct rpcrdma_ia *ia, | ||
1284 | struct ib_mr *mr, struct ib_sge *iov) | ||
1285 | { | ||
1286 | int rc; | ||
1287 | |||
1288 | ib_dma_unmap_single(ia->ri_id->device, | ||
1289 | iov->addr, iov->length, DMA_BIDIRECTIONAL); | ||
1290 | |||
1291 | if (NULL == mr) | ||
1292 | return 0; | ||
1293 | |||
1294 | rc = ib_dereg_mr(mr); | ||
1295 | if (rc) | ||
1296 | dprintk("RPC: %s: ib_dereg_mr failed %i\n", __func__, rc); | ||
1297 | return rc; | ||
1298 | } | ||
1299 | |||
1300 | /* | ||
1301 | * Wrappers for chunk registration, shared by read/write chunk code. | ||
1302 | */ | ||
1303 | |||
1304 | static void | ||
1305 | rpcrdma_map_one(struct rpcrdma_ia *ia, struct rpcrdma_mr_seg *seg, int writing) | ||
1306 | { | ||
1307 | seg->mr_dir = writing ? DMA_FROM_DEVICE : DMA_TO_DEVICE; | ||
1308 | seg->mr_dmalen = seg->mr_len; | ||
1309 | if (seg->mr_page) | ||
1310 | seg->mr_dma = ib_dma_map_page(ia->ri_id->device, | ||
1311 | seg->mr_page, offset_in_page(seg->mr_offset), | ||
1312 | seg->mr_dmalen, seg->mr_dir); | ||
1313 | else | ||
1314 | seg->mr_dma = ib_dma_map_single(ia->ri_id->device, | ||
1315 | seg->mr_offset, | ||
1316 | seg->mr_dmalen, seg->mr_dir); | ||
1317 | } | ||
1318 | |||
1319 | static void | ||
1320 | rpcrdma_unmap_one(struct rpcrdma_ia *ia, struct rpcrdma_mr_seg *seg) | ||
1321 | { | ||
1322 | if (seg->mr_page) | ||
1323 | ib_dma_unmap_page(ia->ri_id->device, | ||
1324 | seg->mr_dma, seg->mr_dmalen, seg->mr_dir); | ||
1325 | else | ||
1326 | ib_dma_unmap_single(ia->ri_id->device, | ||
1327 | seg->mr_dma, seg->mr_dmalen, seg->mr_dir); | ||
1328 | } | ||
1329 | |||
1330 | int | ||
1331 | rpcrdma_register_external(struct rpcrdma_mr_seg *seg, | ||
1332 | int nsegs, int writing, struct rpcrdma_xprt *r_xprt) | ||
1333 | { | ||
1334 | struct rpcrdma_ia *ia = &r_xprt->rx_ia; | ||
1335 | int mem_priv = (writing ? IB_ACCESS_REMOTE_WRITE : | ||
1336 | IB_ACCESS_REMOTE_READ); | ||
1337 | struct rpcrdma_mr_seg *seg1 = seg; | ||
1338 | int i; | ||
1339 | int rc = 0; | ||
1340 | |||
1341 | switch (ia->ri_memreg_strategy) { | ||
1342 | |||
1343 | #if RPCRDMA_PERSISTENT_REGISTRATION | ||
1344 | case RPCRDMA_ALLPHYSICAL: | ||
1345 | rpcrdma_map_one(ia, seg, writing); | ||
1346 | seg->mr_rkey = ia->ri_bind_mem->rkey; | ||
1347 | seg->mr_base = seg->mr_dma; | ||
1348 | seg->mr_nsegs = 1; | ||
1349 | nsegs = 1; | ||
1350 | break; | ||
1351 | #endif | ||
1352 | |||
1353 | /* Registration using fast memory registration */ | ||
1354 | case RPCRDMA_MTHCAFMR: | ||
1355 | { | ||
1356 | u64 physaddrs[RPCRDMA_MAX_DATA_SEGS]; | ||
1357 | int len, pageoff = offset_in_page(seg->mr_offset); | ||
1358 | seg1->mr_offset -= pageoff; /* start of page */ | ||
1359 | seg1->mr_len += pageoff; | ||
1360 | len = -pageoff; | ||
1361 | if (nsegs > RPCRDMA_MAX_DATA_SEGS) | ||
1362 | nsegs = RPCRDMA_MAX_DATA_SEGS; | ||
1363 | for (i = 0; i < nsegs;) { | ||
1364 | rpcrdma_map_one(ia, seg, writing); | ||
1365 | physaddrs[i] = seg->mr_dma; | ||
1366 | len += seg->mr_len; | ||
1367 | ++seg; | ||
1368 | ++i; | ||
1369 | /* Check for holes */ | ||
1370 | if ((i < nsegs && offset_in_page(seg->mr_offset)) || | ||
1371 | offset_in_page((seg-1)->mr_offset+(seg-1)->mr_len)) | ||
1372 | break; | ||
1373 | } | ||
1374 | nsegs = i; | ||
1375 | rc = ib_map_phys_fmr(seg1->mr_chunk.rl_mw->r.fmr, | ||
1376 | physaddrs, nsegs, seg1->mr_dma); | ||
1377 | if (rc) { | ||
1378 | dprintk("RPC: %s: failed ib_map_phys_fmr " | ||
1379 | "%u@0x%llx+%i (%d)... status %i\n", __func__, | ||
1380 | len, (unsigned long long)seg1->mr_dma, | ||
1381 | pageoff, nsegs, rc); | ||
1382 | while (nsegs--) | ||
1383 | rpcrdma_unmap_one(ia, --seg); | ||
1384 | } else { | ||
1385 | seg1->mr_rkey = seg1->mr_chunk.rl_mw->r.fmr->rkey; | ||
1386 | seg1->mr_base = seg1->mr_dma + pageoff; | ||
1387 | seg1->mr_nsegs = nsegs; | ||
1388 | seg1->mr_len = len; | ||
1389 | } | ||
1390 | } | ||
1391 | break; | ||
1392 | |||
1393 | /* Registration using memory windows */ | ||
1394 | case RPCRDMA_MEMWINDOWS_ASYNC: | ||
1395 | case RPCRDMA_MEMWINDOWS: | ||
1396 | { | ||
1397 | struct ib_mw_bind param; | ||
1398 | rpcrdma_map_one(ia, seg, writing); | ||
1399 | param.mr = ia->ri_bind_mem; | ||
1400 | param.wr_id = 0ULL; /* no send cookie */ | ||
1401 | param.addr = seg->mr_dma; | ||
1402 | param.length = seg->mr_len; | ||
1403 | param.send_flags = 0; | ||
1404 | param.mw_access_flags = mem_priv; | ||
1405 | |||
1406 | DECR_CQCOUNT(&r_xprt->rx_ep); | ||
1407 | rc = ib_bind_mw(ia->ri_id->qp, | ||
1408 | seg->mr_chunk.rl_mw->r.mw, ¶m); | ||
1409 | if (rc) { | ||
1410 | dprintk("RPC: %s: failed ib_bind_mw " | ||
1411 | "%u@0x%llx status %i\n", | ||
1412 | __func__, seg->mr_len, | ||
1413 | (unsigned long long)seg->mr_dma, rc); | ||
1414 | rpcrdma_unmap_one(ia, seg); | ||
1415 | } else { | ||
1416 | seg->mr_rkey = seg->mr_chunk.rl_mw->r.mw->rkey; | ||
1417 | seg->mr_base = param.addr; | ||
1418 | seg->mr_nsegs = 1; | ||
1419 | nsegs = 1; | ||
1420 | } | ||
1421 | } | ||
1422 | break; | ||
1423 | |||
1424 | /* Default registration each time */ | ||
1425 | default: | ||
1426 | { | ||
1427 | struct ib_phys_buf ipb[RPCRDMA_MAX_DATA_SEGS]; | ||
1428 | int len = 0; | ||
1429 | if (nsegs > RPCRDMA_MAX_DATA_SEGS) | ||
1430 | nsegs = RPCRDMA_MAX_DATA_SEGS; | ||
1431 | for (i = 0; i < nsegs;) { | ||
1432 | rpcrdma_map_one(ia, seg, writing); | ||
1433 | ipb[i].addr = seg->mr_dma; | ||
1434 | ipb[i].size = seg->mr_len; | ||
1435 | len += seg->mr_len; | ||
1436 | ++seg; | ||
1437 | ++i; | ||
1438 | /* Check for holes */ | ||
1439 | if ((i < nsegs && offset_in_page(seg->mr_offset)) || | ||
1440 | offset_in_page((seg-1)->mr_offset+(seg-1)->mr_len)) | ||
1441 | break; | ||
1442 | } | ||
1443 | nsegs = i; | ||
1444 | seg1->mr_base = seg1->mr_dma; | ||
1445 | seg1->mr_chunk.rl_mr = ib_reg_phys_mr(ia->ri_pd, | ||
1446 | ipb, nsegs, mem_priv, &seg1->mr_base); | ||
1447 | if (IS_ERR(seg1->mr_chunk.rl_mr)) { | ||
1448 | rc = PTR_ERR(seg1->mr_chunk.rl_mr); | ||
1449 | dprintk("RPC: %s: failed ib_reg_phys_mr " | ||
1450 | "%u@0x%llx (%d)... status %i\n", | ||
1451 | __func__, len, | ||
1452 | (unsigned long long)seg1->mr_dma, nsegs, rc); | ||
1453 | while (nsegs--) | ||
1454 | rpcrdma_unmap_one(ia, --seg); | ||
1455 | } else { | ||
1456 | seg1->mr_rkey = seg1->mr_chunk.rl_mr->rkey; | ||
1457 | seg1->mr_nsegs = nsegs; | ||
1458 | seg1->mr_len = len; | ||
1459 | } | ||
1460 | } | ||
1461 | break; | ||
1462 | } | ||
1463 | if (rc) | ||
1464 | return -1; | ||
1465 | |||
1466 | return nsegs; | ||
1467 | } | ||
1468 | |||
1469 | int | ||
1470 | rpcrdma_deregister_external(struct rpcrdma_mr_seg *seg, | ||
1471 | struct rpcrdma_xprt *r_xprt, void *r) | ||
1472 | { | ||
1473 | struct rpcrdma_ia *ia = &r_xprt->rx_ia; | ||
1474 | struct rpcrdma_mr_seg *seg1 = seg; | ||
1475 | int nsegs = seg->mr_nsegs, rc; | ||
1476 | |||
1477 | switch (ia->ri_memreg_strategy) { | ||
1478 | |||
1479 | #if RPCRDMA_PERSISTENT_REGISTRATION | ||
1480 | case RPCRDMA_ALLPHYSICAL: | ||
1481 | BUG_ON(nsegs != 1); | ||
1482 | rpcrdma_unmap_one(ia, seg); | ||
1483 | rc = 0; | ||
1484 | break; | ||
1485 | #endif | ||
1486 | |||
1487 | case RPCRDMA_MTHCAFMR: | ||
1488 | { | ||
1489 | LIST_HEAD(l); | ||
1490 | list_add(&seg->mr_chunk.rl_mw->r.fmr->list, &l); | ||
1491 | rc = ib_unmap_fmr(&l); | ||
1492 | while (seg1->mr_nsegs--) | ||
1493 | rpcrdma_unmap_one(ia, seg++); | ||
1494 | } | ||
1495 | if (rc) | ||
1496 | dprintk("RPC: %s: failed ib_unmap_fmr," | ||
1497 | " status %i\n", __func__, rc); | ||
1498 | break; | ||
1499 | |||
1500 | case RPCRDMA_MEMWINDOWS_ASYNC: | ||
1501 | case RPCRDMA_MEMWINDOWS: | ||
1502 | { | ||
1503 | struct ib_mw_bind param; | ||
1504 | BUG_ON(nsegs != 1); | ||
1505 | param.mr = ia->ri_bind_mem; | ||
1506 | param.addr = 0ULL; /* unbind */ | ||
1507 | param.length = 0; | ||
1508 | param.mw_access_flags = 0; | ||
1509 | if (r) { | ||
1510 | param.wr_id = (u64) (unsigned long) r; | ||
1511 | param.send_flags = IB_SEND_SIGNALED; | ||
1512 | INIT_CQCOUNT(&r_xprt->rx_ep); | ||
1513 | } else { | ||
1514 | param.wr_id = 0ULL; | ||
1515 | param.send_flags = 0; | ||
1516 | DECR_CQCOUNT(&r_xprt->rx_ep); | ||
1517 | } | ||
1518 | rc = ib_bind_mw(ia->ri_id->qp, | ||
1519 | seg->mr_chunk.rl_mw->r.mw, ¶m); | ||
1520 | rpcrdma_unmap_one(ia, seg); | ||
1521 | } | ||
1522 | if (rc) | ||
1523 | dprintk("RPC: %s: failed ib_(un)bind_mw," | ||
1524 | " status %i\n", __func__, rc); | ||
1525 | else | ||
1526 | r = NULL; /* will upcall on completion */ | ||
1527 | break; | ||
1528 | |||
1529 | default: | ||
1530 | rc = ib_dereg_mr(seg1->mr_chunk.rl_mr); | ||
1531 | seg1->mr_chunk.rl_mr = NULL; | ||
1532 | while (seg1->mr_nsegs--) | ||
1533 | rpcrdma_unmap_one(ia, seg++); | ||
1534 | if (rc) | ||
1535 | dprintk("RPC: %s: failed ib_dereg_mr," | ||
1536 | " status %i\n", __func__, rc); | ||
1537 | break; | ||
1538 | } | ||
1539 | if (r) { | ||
1540 | struct rpcrdma_rep *rep = r; | ||
1541 | void (*func)(struct rpcrdma_rep *) = rep->rr_func; | ||
1542 | rep->rr_func = NULL; | ||
1543 | func(rep); /* dereg done, callback now */ | ||
1544 | } | ||
1545 | return nsegs; | ||
1546 | } | ||
1547 | |||
1548 | /* | ||
1549 | * Prepost any receive buffer, then post send. | ||
1550 | * | ||
1551 | * Receive buffer is donated to hardware, reclaimed upon recv completion. | ||
1552 | */ | ||
1553 | int | ||
1554 | rpcrdma_ep_post(struct rpcrdma_ia *ia, | ||
1555 | struct rpcrdma_ep *ep, | ||
1556 | struct rpcrdma_req *req) | ||
1557 | { | ||
1558 | struct ib_send_wr send_wr, *send_wr_fail; | ||
1559 | struct rpcrdma_rep *rep = req->rl_reply; | ||
1560 | int rc; | ||
1561 | |||
1562 | if (rep) { | ||
1563 | rc = rpcrdma_ep_post_recv(ia, ep, rep); | ||
1564 | if (rc) | ||
1565 | goto out; | ||
1566 | req->rl_reply = NULL; | ||
1567 | } | ||
1568 | |||
1569 | send_wr.next = NULL; | ||
1570 | send_wr.wr_id = 0ULL; /* no send cookie */ | ||
1571 | send_wr.sg_list = req->rl_send_iov; | ||
1572 | send_wr.num_sge = req->rl_niovs; | ||
1573 | send_wr.opcode = IB_WR_SEND; | ||
1574 | send_wr.imm_data = 0; | ||
1575 | if (send_wr.num_sge == 4) /* no need to sync any pad (constant) */ | ||
1576 | ib_dma_sync_single_for_device(ia->ri_id->device, | ||
1577 | req->rl_send_iov[3].addr, req->rl_send_iov[3].length, | ||
1578 | DMA_TO_DEVICE); | ||
1579 | ib_dma_sync_single_for_device(ia->ri_id->device, | ||
1580 | req->rl_send_iov[1].addr, req->rl_send_iov[1].length, | ||
1581 | DMA_TO_DEVICE); | ||
1582 | ib_dma_sync_single_for_device(ia->ri_id->device, | ||
1583 | req->rl_send_iov[0].addr, req->rl_send_iov[0].length, | ||
1584 | DMA_TO_DEVICE); | ||
1585 | |||
1586 | if (DECR_CQCOUNT(ep) > 0) | ||
1587 | send_wr.send_flags = 0; | ||
1588 | else { /* Provider must take a send completion every now and then */ | ||
1589 | INIT_CQCOUNT(ep); | ||
1590 | send_wr.send_flags = IB_SEND_SIGNALED; | ||
1591 | } | ||
1592 | |||
1593 | rc = ib_post_send(ia->ri_id->qp, &send_wr, &send_wr_fail); | ||
1594 | if (rc) | ||
1595 | dprintk("RPC: %s: ib_post_send returned %i\n", __func__, | ||
1596 | rc); | ||
1597 | out: | ||
1598 | return rc; | ||
1599 | } | ||
1600 | |||
1601 | /* | ||
1602 | * (Re)post a receive buffer. | ||
1603 | */ | ||
1604 | int | ||
1605 | rpcrdma_ep_post_recv(struct rpcrdma_ia *ia, | ||
1606 | struct rpcrdma_ep *ep, | ||
1607 | struct rpcrdma_rep *rep) | ||
1608 | { | ||
1609 | struct ib_recv_wr recv_wr, *recv_wr_fail; | ||
1610 | int rc; | ||
1611 | |||
1612 | recv_wr.next = NULL; | ||
1613 | recv_wr.wr_id = (u64) (unsigned long) rep; | ||
1614 | recv_wr.sg_list = &rep->rr_iov; | ||
1615 | recv_wr.num_sge = 1; | ||
1616 | |||
1617 | ib_dma_sync_single_for_cpu(ia->ri_id->device, | ||
1618 | rep->rr_iov.addr, rep->rr_iov.length, DMA_BIDIRECTIONAL); | ||
1619 | |||
1620 | DECR_CQCOUNT(ep); | ||
1621 | rc = ib_post_recv(ia->ri_id->qp, &recv_wr, &recv_wr_fail); | ||
1622 | |||
1623 | if (rc) | ||
1624 | dprintk("RPC: %s: ib_post_recv returned %i\n", __func__, | ||
1625 | rc); | ||
1626 | return rc; | ||
1627 | } | ||
diff --git a/net/sunrpc/xprtrdma/xprt_rdma.h b/net/sunrpc/xprtrdma/xprt_rdma.h new file mode 100644 index 000000000000..2427822f8bd4 --- /dev/null +++ b/net/sunrpc/xprtrdma/xprt_rdma.h | |||
@@ -0,0 +1,330 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2003-2007 Network Appliance, Inc. All rights reserved. | ||
3 | * | ||
4 | * This software is available to you under a choice of one of two | ||
5 | * licenses. You may choose to be licensed under the terms of the GNU | ||
6 | * General Public License (GPL) Version 2, available from the file | ||
7 | * COPYING in the main directory of this source tree, or the BSD-type | ||
8 | * license below: | ||
9 | * | ||
10 | * Redistribution and use in source and binary forms, with or without | ||
11 | * modification, are permitted provided that the following conditions | ||
12 | * are met: | ||
13 | * | ||
14 | * Redistributions of source code must retain the above copyright | ||
15 | * notice, this list of conditions and the following disclaimer. | ||
16 | * | ||
17 | * Redistributions in binary form must reproduce the above | ||
18 | * copyright notice, this list of conditions and the following | ||
19 | * disclaimer in the documentation and/or other materials provided | ||
20 | * with the distribution. | ||
21 | * | ||
22 | * Neither the name of the Network Appliance, Inc. nor the names of | ||
23 | * its contributors may be used to endorse or promote products | ||
24 | * derived from this software without specific prior written | ||
25 | * permission. | ||
26 | * | ||
27 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
28 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
29 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
30 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
31 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
32 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
33 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
34 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
35 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
36 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
37 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
38 | */ | ||
39 | |||
40 | #ifndef _LINUX_SUNRPC_XPRT_RDMA_H | ||
41 | #define _LINUX_SUNRPC_XPRT_RDMA_H | ||
42 | |||
43 | #include <linux/wait.h> /* wait_queue_head_t, etc */ | ||
44 | #include <linux/spinlock.h> /* spinlock_t, etc */ | ||
45 | #include <asm/atomic.h> /* atomic_t, etc */ | ||
46 | |||
47 | #include <rdma/rdma_cm.h> /* RDMA connection api */ | ||
48 | #include <rdma/ib_verbs.h> /* RDMA verbs api */ | ||
49 | |||
50 | #include <linux/sunrpc/clnt.h> /* rpc_xprt */ | ||
51 | #include <linux/sunrpc/rpc_rdma.h> /* RPC/RDMA protocol */ | ||
52 | #include <linux/sunrpc/xprtrdma.h> /* xprt parameters */ | ||
53 | |||
54 | /* | ||
55 | * Interface Adapter -- one per transport instance | ||
56 | */ | ||
57 | struct rpcrdma_ia { | ||
58 | struct rdma_cm_id *ri_id; | ||
59 | struct ib_pd *ri_pd; | ||
60 | struct ib_mr *ri_bind_mem; | ||
61 | struct completion ri_done; | ||
62 | int ri_async_rc; | ||
63 | enum rpcrdma_memreg ri_memreg_strategy; | ||
64 | }; | ||
65 | |||
66 | /* | ||
67 | * RDMA Endpoint -- one per transport instance | ||
68 | */ | ||
69 | |||
70 | struct rpcrdma_ep { | ||
71 | atomic_t rep_cqcount; | ||
72 | int rep_cqinit; | ||
73 | int rep_connected; | ||
74 | struct rpcrdma_ia *rep_ia; | ||
75 | struct ib_cq *rep_cq; | ||
76 | struct ib_qp_init_attr rep_attr; | ||
77 | wait_queue_head_t rep_connect_wait; | ||
78 | struct ib_sge rep_pad; /* holds zeroed pad */ | ||
79 | struct ib_mr *rep_pad_mr; /* holds zeroed pad */ | ||
80 | void (*rep_func)(struct rpcrdma_ep *); | ||
81 | struct rpc_xprt *rep_xprt; /* for rep_func */ | ||
82 | struct rdma_conn_param rep_remote_cma; | ||
83 | struct sockaddr_storage rep_remote_addr; | ||
84 | }; | ||
85 | |||
86 | #define INIT_CQCOUNT(ep) atomic_set(&(ep)->rep_cqcount, (ep)->rep_cqinit) | ||
87 | #define DECR_CQCOUNT(ep) atomic_sub_return(1, &(ep)->rep_cqcount) | ||
88 | |||
89 | /* | ||
90 | * struct rpcrdma_rep -- this structure encapsulates state required to recv | ||
91 | * and complete a reply, asychronously. It needs several pieces of | ||
92 | * state: | ||
93 | * o recv buffer (posted to provider) | ||
94 | * o ib_sge (also donated to provider) | ||
95 | * o status of reply (length, success or not) | ||
96 | * o bookkeeping state to get run by tasklet (list, etc) | ||
97 | * | ||
98 | * These are allocated during initialization, per-transport instance; | ||
99 | * however, the tasklet execution list itself is global, as it should | ||
100 | * always be pretty short. | ||
101 | * | ||
102 | * N of these are associated with a transport instance, and stored in | ||
103 | * struct rpcrdma_buffer. N is the max number of outstanding requests. | ||
104 | */ | ||
105 | |||
106 | /* temporary static scatter/gather max */ | ||
107 | #define RPCRDMA_MAX_DATA_SEGS (8) /* max scatter/gather */ | ||
108 | #define RPCRDMA_MAX_SEGS (RPCRDMA_MAX_DATA_SEGS + 2) /* head+tail = 2 */ | ||
109 | #define MAX_RPCRDMAHDR (\ | ||
110 | /* max supported RPC/RDMA header */ \ | ||
111 | sizeof(struct rpcrdma_msg) + (2 * sizeof(u32)) + \ | ||
112 | (sizeof(struct rpcrdma_read_chunk) * RPCRDMA_MAX_SEGS) + sizeof(u32)) | ||
113 | |||
114 | struct rpcrdma_buffer; | ||
115 | |||
116 | struct rpcrdma_rep { | ||
117 | unsigned int rr_len; /* actual received reply length */ | ||
118 | struct rpcrdma_buffer *rr_buffer; /* home base for this structure */ | ||
119 | struct rpc_xprt *rr_xprt; /* needed for request/reply matching */ | ||
120 | void (*rr_func)(struct rpcrdma_rep *);/* called by tasklet in softint */ | ||
121 | struct list_head rr_list; /* tasklet list */ | ||
122 | wait_queue_head_t rr_unbind; /* optional unbind wait */ | ||
123 | struct ib_sge rr_iov; /* for posting */ | ||
124 | struct ib_mr *rr_handle; /* handle for mem in rr_iov */ | ||
125 | char rr_base[MAX_RPCRDMAHDR]; /* minimal inline receive buffer */ | ||
126 | }; | ||
127 | |||
128 | /* | ||
129 | * struct rpcrdma_req -- structure central to the request/reply sequence. | ||
130 | * | ||
131 | * N of these are associated with a transport instance, and stored in | ||
132 | * struct rpcrdma_buffer. N is the max number of outstanding requests. | ||
133 | * | ||
134 | * It includes pre-registered buffer memory for send AND recv. | ||
135 | * The recv buffer, however, is not owned by this structure, and | ||
136 | * is "donated" to the hardware when a recv is posted. When a | ||
137 | * reply is handled, the recv buffer used is given back to the | ||
138 | * struct rpcrdma_req associated with the request. | ||
139 | * | ||
140 | * In addition to the basic memory, this structure includes an array | ||
141 | * of iovs for send operations. The reason is that the iovs passed to | ||
142 | * ib_post_{send,recv} must not be modified until the work request | ||
143 | * completes. | ||
144 | * | ||
145 | * NOTES: | ||
146 | * o RPCRDMA_MAX_SEGS is the max number of addressible chunk elements we | ||
147 | * marshal. The number needed varies depending on the iov lists that | ||
148 | * are passed to us, the memory registration mode we are in, and if | ||
149 | * physical addressing is used, the layout. | ||
150 | */ | ||
151 | |||
152 | struct rpcrdma_mr_seg { /* chunk descriptors */ | ||
153 | union { /* chunk memory handles */ | ||
154 | struct ib_mr *rl_mr; /* if registered directly */ | ||
155 | struct rpcrdma_mw { /* if registered from region */ | ||
156 | union { | ||
157 | struct ib_mw *mw; | ||
158 | struct ib_fmr *fmr; | ||
159 | } r; | ||
160 | struct list_head mw_list; | ||
161 | } *rl_mw; | ||
162 | } mr_chunk; | ||
163 | u64 mr_base; /* registration result */ | ||
164 | u32 mr_rkey; /* registration result */ | ||
165 | u32 mr_len; /* length of chunk or segment */ | ||
166 | int mr_nsegs; /* number of segments in chunk or 0 */ | ||
167 | enum dma_data_direction mr_dir; /* segment mapping direction */ | ||
168 | dma_addr_t mr_dma; /* segment mapping address */ | ||
169 | size_t mr_dmalen; /* segment mapping length */ | ||
170 | struct page *mr_page; /* owning page, if any */ | ||
171 | char *mr_offset; /* kva if no page, else offset */ | ||
172 | }; | ||
173 | |||
174 | struct rpcrdma_req { | ||
175 | size_t rl_size; /* actual length of buffer */ | ||
176 | unsigned int rl_niovs; /* 0, 2 or 4 */ | ||
177 | unsigned int rl_nchunks; /* non-zero if chunks */ | ||
178 | struct rpcrdma_buffer *rl_buffer; /* home base for this structure */ | ||
179 | struct rpcrdma_rep *rl_reply;/* holder for reply buffer */ | ||
180 | struct rpcrdma_mr_seg rl_segments[RPCRDMA_MAX_SEGS];/* chunk segments */ | ||
181 | struct ib_sge rl_send_iov[4]; /* for active requests */ | ||
182 | struct ib_sge rl_iov; /* for posting */ | ||
183 | struct ib_mr *rl_handle; /* handle for mem in rl_iov */ | ||
184 | char rl_base[MAX_RPCRDMAHDR]; /* start of actual buffer */ | ||
185 | __u32 rl_xdr_buf[0]; /* start of returned rpc rq_buffer */ | ||
186 | }; | ||
187 | #define rpcr_to_rdmar(r) \ | ||
188 | container_of((r)->rq_buffer, struct rpcrdma_req, rl_xdr_buf[0]) | ||
189 | |||
190 | /* | ||
191 | * struct rpcrdma_buffer -- holds list/queue of pre-registered memory for | ||
192 | * inline requests/replies, and client/server credits. | ||
193 | * | ||
194 | * One of these is associated with a transport instance | ||
195 | */ | ||
196 | struct rpcrdma_buffer { | ||
197 | spinlock_t rb_lock; /* protects indexes */ | ||
198 | atomic_t rb_credits; /* most recent server credits */ | ||
199 | unsigned long rb_cwndscale; /* cached framework rpc_cwndscale */ | ||
200 | int rb_max_requests;/* client max requests */ | ||
201 | struct list_head rb_mws; /* optional memory windows/fmrs */ | ||
202 | int rb_send_index; | ||
203 | struct rpcrdma_req **rb_send_bufs; | ||
204 | int rb_recv_index; | ||
205 | struct rpcrdma_rep **rb_recv_bufs; | ||
206 | char *rb_pool; | ||
207 | }; | ||
208 | #define rdmab_to_ia(b) (&container_of((b), struct rpcrdma_xprt, rx_buf)->rx_ia) | ||
209 | |||
210 | /* | ||
211 | * Internal structure for transport instance creation. This | ||
212 | * exists primarily for modularity. | ||
213 | * | ||
214 | * This data should be set with mount options | ||
215 | */ | ||
216 | struct rpcrdma_create_data_internal { | ||
217 | struct sockaddr_storage addr; /* RDMA server address */ | ||
218 | unsigned int max_requests; /* max requests (slots) in flight */ | ||
219 | unsigned int rsize; /* mount rsize - max read hdr+data */ | ||
220 | unsigned int wsize; /* mount wsize - max write hdr+data */ | ||
221 | unsigned int inline_rsize; /* max non-rdma read data payload */ | ||
222 | unsigned int inline_wsize; /* max non-rdma write data payload */ | ||
223 | unsigned int padding; /* non-rdma write header padding */ | ||
224 | }; | ||
225 | |||
226 | #define RPCRDMA_INLINE_READ_THRESHOLD(rq) \ | ||
227 | (rpcx_to_rdmad(rq->rq_task->tk_xprt).inline_rsize) | ||
228 | |||
229 | #define RPCRDMA_INLINE_WRITE_THRESHOLD(rq)\ | ||
230 | (rpcx_to_rdmad(rq->rq_task->tk_xprt).inline_wsize) | ||
231 | |||
232 | #define RPCRDMA_INLINE_PAD_VALUE(rq)\ | ||
233 | rpcx_to_rdmad(rq->rq_task->tk_xprt).padding | ||
234 | |||
235 | /* | ||
236 | * Statistics for RPCRDMA | ||
237 | */ | ||
238 | struct rpcrdma_stats { | ||
239 | unsigned long read_chunk_count; | ||
240 | unsigned long write_chunk_count; | ||
241 | unsigned long reply_chunk_count; | ||
242 | |||
243 | unsigned long long total_rdma_request; | ||
244 | unsigned long long total_rdma_reply; | ||
245 | |||
246 | unsigned long long pullup_copy_count; | ||
247 | unsigned long long fixup_copy_count; | ||
248 | unsigned long hardway_register_count; | ||
249 | unsigned long failed_marshal_count; | ||
250 | unsigned long bad_reply_count; | ||
251 | }; | ||
252 | |||
253 | /* | ||
254 | * RPCRDMA transport -- encapsulates the structures above for | ||
255 | * integration with RPC. | ||
256 | * | ||
257 | * The contained structures are embedded, not pointers, | ||
258 | * for convenience. This structure need not be visible externally. | ||
259 | * | ||
260 | * It is allocated and initialized during mount, and released | ||
261 | * during unmount. | ||
262 | */ | ||
263 | struct rpcrdma_xprt { | ||
264 | struct rpc_xprt xprt; | ||
265 | struct rpcrdma_ia rx_ia; | ||
266 | struct rpcrdma_ep rx_ep; | ||
267 | struct rpcrdma_buffer rx_buf; | ||
268 | struct rpcrdma_create_data_internal rx_data; | ||
269 | struct delayed_work rdma_connect; | ||
270 | struct rpcrdma_stats rx_stats; | ||
271 | }; | ||
272 | |||
273 | #define rpcx_to_rdmax(x) container_of(x, struct rpcrdma_xprt, xprt) | ||
274 | #define rpcx_to_rdmad(x) (rpcx_to_rdmax(x)->rx_data) | ||
275 | |||
276 | /* | ||
277 | * Interface Adapter calls - xprtrdma/verbs.c | ||
278 | */ | ||
279 | int rpcrdma_ia_open(struct rpcrdma_xprt *, struct sockaddr *, int); | ||
280 | void rpcrdma_ia_close(struct rpcrdma_ia *); | ||
281 | |||
282 | /* | ||
283 | * Endpoint calls - xprtrdma/verbs.c | ||
284 | */ | ||
285 | int rpcrdma_ep_create(struct rpcrdma_ep *, struct rpcrdma_ia *, | ||
286 | struct rpcrdma_create_data_internal *); | ||
287 | int rpcrdma_ep_destroy(struct rpcrdma_ep *, struct rpcrdma_ia *); | ||
288 | int rpcrdma_ep_connect(struct rpcrdma_ep *, struct rpcrdma_ia *); | ||
289 | int rpcrdma_ep_disconnect(struct rpcrdma_ep *, struct rpcrdma_ia *); | ||
290 | |||
291 | int rpcrdma_ep_post(struct rpcrdma_ia *, struct rpcrdma_ep *, | ||
292 | struct rpcrdma_req *); | ||
293 | int rpcrdma_ep_post_recv(struct rpcrdma_ia *, struct rpcrdma_ep *, | ||
294 | struct rpcrdma_rep *); | ||
295 | |||
296 | /* | ||
297 | * Buffer calls - xprtrdma/verbs.c | ||
298 | */ | ||
299 | int rpcrdma_buffer_create(struct rpcrdma_buffer *, struct rpcrdma_ep *, | ||
300 | struct rpcrdma_ia *, | ||
301 | struct rpcrdma_create_data_internal *); | ||
302 | void rpcrdma_buffer_destroy(struct rpcrdma_buffer *); | ||
303 | |||
304 | struct rpcrdma_req *rpcrdma_buffer_get(struct rpcrdma_buffer *); | ||
305 | void rpcrdma_buffer_put(struct rpcrdma_req *); | ||
306 | void rpcrdma_recv_buffer_get(struct rpcrdma_req *); | ||
307 | void rpcrdma_recv_buffer_put(struct rpcrdma_rep *); | ||
308 | |||
309 | int rpcrdma_register_internal(struct rpcrdma_ia *, void *, int, | ||
310 | struct ib_mr **, struct ib_sge *); | ||
311 | int rpcrdma_deregister_internal(struct rpcrdma_ia *, | ||
312 | struct ib_mr *, struct ib_sge *); | ||
313 | |||
314 | int rpcrdma_register_external(struct rpcrdma_mr_seg *, | ||
315 | int, int, struct rpcrdma_xprt *); | ||
316 | int rpcrdma_deregister_external(struct rpcrdma_mr_seg *, | ||
317 | struct rpcrdma_xprt *, void *); | ||
318 | |||
319 | /* | ||
320 | * RPC/RDMA connection management calls - xprtrdma/rpc_rdma.c | ||
321 | */ | ||
322 | void rpcrdma_conn_func(struct rpcrdma_ep *); | ||
323 | void rpcrdma_reply_handler(struct rpcrdma_rep *); | ||
324 | |||
325 | /* | ||
326 | * RPC/RDMA protocol calls - xprtrdma/rpc_rdma.c | ||
327 | */ | ||
328 | int rpcrdma_marshal_req(struct rpc_rqst *); | ||
329 | |||
330 | #endif /* _LINUX_SUNRPC_XPRT_RDMA_H */ | ||
diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c index 282efd447a61..02298f529dad 100644 --- a/net/sunrpc/xprtsock.c +++ b/net/sunrpc/xprtsock.c | |||
@@ -13,10 +13,14 @@ | |||
13 | * (C) 1999 Trond Myklebust <trond.myklebust@fys.uio.no> | 13 | * (C) 1999 Trond Myklebust <trond.myklebust@fys.uio.no> |
14 | * | 14 | * |
15 | * IP socket transport implementation, (C) 2005 Chuck Lever <cel@netapp.com> | 15 | * IP socket transport implementation, (C) 2005 Chuck Lever <cel@netapp.com> |
16 | * | ||
17 | * IPv6 support contributed by Gilles Quillard, Bull Open Source, 2005. | ||
18 | * <gilles.quillard@bull.net> | ||
16 | */ | 19 | */ |
17 | 20 | ||
18 | #include <linux/types.h> | 21 | #include <linux/types.h> |
19 | #include <linux/slab.h> | 22 | #include <linux/slab.h> |
23 | #include <linux/module.h> | ||
20 | #include <linux/capability.h> | 24 | #include <linux/capability.h> |
21 | #include <linux/pagemap.h> | 25 | #include <linux/pagemap.h> |
22 | #include <linux/errno.h> | 26 | #include <linux/errno.h> |
@@ -28,6 +32,7 @@ | |||
28 | #include <linux/tcp.h> | 32 | #include <linux/tcp.h> |
29 | #include <linux/sunrpc/clnt.h> | 33 | #include <linux/sunrpc/clnt.h> |
30 | #include <linux/sunrpc/sched.h> | 34 | #include <linux/sunrpc/sched.h> |
35 | #include <linux/sunrpc/xprtsock.h> | ||
31 | #include <linux/file.h> | 36 | #include <linux/file.h> |
32 | 37 | ||
33 | #include <net/sock.h> | 38 | #include <net/sock.h> |
@@ -260,14 +265,29 @@ struct sock_xprt { | |||
260 | #define TCP_RCV_COPY_XID (1UL << 2) | 265 | #define TCP_RCV_COPY_XID (1UL << 2) |
261 | #define TCP_RCV_COPY_DATA (1UL << 3) | 266 | #define TCP_RCV_COPY_DATA (1UL << 3) |
262 | 267 | ||
263 | static void xs_format_peer_addresses(struct rpc_xprt *xprt) | 268 | static inline struct sockaddr *xs_addr(struct rpc_xprt *xprt) |
269 | { | ||
270 | return (struct sockaddr *) &xprt->addr; | ||
271 | } | ||
272 | |||
273 | static inline struct sockaddr_in *xs_addr_in(struct rpc_xprt *xprt) | ||
264 | { | 274 | { |
265 | struct sockaddr_in *addr = (struct sockaddr_in *) &xprt->addr; | 275 | return (struct sockaddr_in *) &xprt->addr; |
276 | } | ||
277 | |||
278 | static inline struct sockaddr_in6 *xs_addr_in6(struct rpc_xprt *xprt) | ||
279 | { | ||
280 | return (struct sockaddr_in6 *) &xprt->addr; | ||
281 | } | ||
282 | |||
283 | static void xs_format_ipv4_peer_addresses(struct rpc_xprt *xprt) | ||
284 | { | ||
285 | struct sockaddr_in *addr = xs_addr_in(xprt); | ||
266 | char *buf; | 286 | char *buf; |
267 | 287 | ||
268 | buf = kzalloc(20, GFP_KERNEL); | 288 | buf = kzalloc(20, GFP_KERNEL); |
269 | if (buf) { | 289 | if (buf) { |
270 | snprintf(buf, 20, "%u.%u.%u.%u", | 290 | snprintf(buf, 20, NIPQUAD_FMT, |
271 | NIPQUAD(addr->sin_addr.s_addr)); | 291 | NIPQUAD(addr->sin_addr.s_addr)); |
272 | } | 292 | } |
273 | xprt->address_strings[RPC_DISPLAY_ADDR] = buf; | 293 | xprt->address_strings[RPC_DISPLAY_ADDR] = buf; |
@@ -279,26 +299,123 @@ static void xs_format_peer_addresses(struct rpc_xprt *xprt) | |||
279 | } | 299 | } |
280 | xprt->address_strings[RPC_DISPLAY_PORT] = buf; | 300 | xprt->address_strings[RPC_DISPLAY_PORT] = buf; |
281 | 301 | ||
282 | if (xprt->prot == IPPROTO_UDP) | 302 | buf = kzalloc(8, GFP_KERNEL); |
283 | xprt->address_strings[RPC_DISPLAY_PROTO] = "udp"; | 303 | if (buf) { |
284 | else | 304 | if (xprt->prot == IPPROTO_UDP) |
285 | xprt->address_strings[RPC_DISPLAY_PROTO] = "tcp"; | 305 | snprintf(buf, 8, "udp"); |
306 | else | ||
307 | snprintf(buf, 8, "tcp"); | ||
308 | } | ||
309 | xprt->address_strings[RPC_DISPLAY_PROTO] = buf; | ||
286 | 310 | ||
287 | buf = kzalloc(48, GFP_KERNEL); | 311 | buf = kzalloc(48, GFP_KERNEL); |
288 | if (buf) { | 312 | if (buf) { |
289 | snprintf(buf, 48, "addr=%u.%u.%u.%u port=%u proto=%s", | 313 | snprintf(buf, 48, "addr="NIPQUAD_FMT" port=%u proto=%s", |
290 | NIPQUAD(addr->sin_addr.s_addr), | 314 | NIPQUAD(addr->sin_addr.s_addr), |
291 | ntohs(addr->sin_port), | 315 | ntohs(addr->sin_port), |
292 | xprt->prot == IPPROTO_UDP ? "udp" : "tcp"); | 316 | xprt->prot == IPPROTO_UDP ? "udp" : "tcp"); |
293 | } | 317 | } |
294 | xprt->address_strings[RPC_DISPLAY_ALL] = buf; | 318 | xprt->address_strings[RPC_DISPLAY_ALL] = buf; |
319 | |||
320 | buf = kzalloc(10, GFP_KERNEL); | ||
321 | if (buf) { | ||
322 | snprintf(buf, 10, "%02x%02x%02x%02x", | ||
323 | NIPQUAD(addr->sin_addr.s_addr)); | ||
324 | } | ||
325 | xprt->address_strings[RPC_DISPLAY_HEX_ADDR] = buf; | ||
326 | |||
327 | buf = kzalloc(8, GFP_KERNEL); | ||
328 | if (buf) { | ||
329 | snprintf(buf, 8, "%4hx", | ||
330 | ntohs(addr->sin_port)); | ||
331 | } | ||
332 | xprt->address_strings[RPC_DISPLAY_HEX_PORT] = buf; | ||
333 | |||
334 | buf = kzalloc(30, GFP_KERNEL); | ||
335 | if (buf) { | ||
336 | snprintf(buf, 30, NIPQUAD_FMT".%u.%u", | ||
337 | NIPQUAD(addr->sin_addr.s_addr), | ||
338 | ntohs(addr->sin_port) >> 8, | ||
339 | ntohs(addr->sin_port) & 0xff); | ||
340 | } | ||
341 | xprt->address_strings[RPC_DISPLAY_UNIVERSAL_ADDR] = buf; | ||
342 | |||
343 | xprt->address_strings[RPC_DISPLAY_NETID] = | ||
344 | kstrdup(xprt->prot == IPPROTO_UDP ? | ||
345 | RPCBIND_NETID_UDP : RPCBIND_NETID_TCP, GFP_KERNEL); | ||
346 | } | ||
347 | |||
348 | static void xs_format_ipv6_peer_addresses(struct rpc_xprt *xprt) | ||
349 | { | ||
350 | struct sockaddr_in6 *addr = xs_addr_in6(xprt); | ||
351 | char *buf; | ||
352 | |||
353 | buf = kzalloc(40, GFP_KERNEL); | ||
354 | if (buf) { | ||
355 | snprintf(buf, 40, NIP6_FMT, | ||
356 | NIP6(addr->sin6_addr)); | ||
357 | } | ||
358 | xprt->address_strings[RPC_DISPLAY_ADDR] = buf; | ||
359 | |||
360 | buf = kzalloc(8, GFP_KERNEL); | ||
361 | if (buf) { | ||
362 | snprintf(buf, 8, "%u", | ||
363 | ntohs(addr->sin6_port)); | ||
364 | } | ||
365 | xprt->address_strings[RPC_DISPLAY_PORT] = buf; | ||
366 | |||
367 | buf = kzalloc(8, GFP_KERNEL); | ||
368 | if (buf) { | ||
369 | if (xprt->prot == IPPROTO_UDP) | ||
370 | snprintf(buf, 8, "udp"); | ||
371 | else | ||
372 | snprintf(buf, 8, "tcp"); | ||
373 | } | ||
374 | xprt->address_strings[RPC_DISPLAY_PROTO] = buf; | ||
375 | |||
376 | buf = kzalloc(64, GFP_KERNEL); | ||
377 | if (buf) { | ||
378 | snprintf(buf, 64, "addr="NIP6_FMT" port=%u proto=%s", | ||
379 | NIP6(addr->sin6_addr), | ||
380 | ntohs(addr->sin6_port), | ||
381 | xprt->prot == IPPROTO_UDP ? "udp" : "tcp"); | ||
382 | } | ||
383 | xprt->address_strings[RPC_DISPLAY_ALL] = buf; | ||
384 | |||
385 | buf = kzalloc(36, GFP_KERNEL); | ||
386 | if (buf) { | ||
387 | snprintf(buf, 36, NIP6_SEQFMT, | ||
388 | NIP6(addr->sin6_addr)); | ||
389 | } | ||
390 | xprt->address_strings[RPC_DISPLAY_HEX_ADDR] = buf; | ||
391 | |||
392 | buf = kzalloc(8, GFP_KERNEL); | ||
393 | if (buf) { | ||
394 | snprintf(buf, 8, "%4hx", | ||
395 | ntohs(addr->sin6_port)); | ||
396 | } | ||
397 | xprt->address_strings[RPC_DISPLAY_HEX_PORT] = buf; | ||
398 | |||
399 | buf = kzalloc(50, GFP_KERNEL); | ||
400 | if (buf) { | ||
401 | snprintf(buf, 50, NIP6_FMT".%u.%u", | ||
402 | NIP6(addr->sin6_addr), | ||
403 | ntohs(addr->sin6_port) >> 8, | ||
404 | ntohs(addr->sin6_port) & 0xff); | ||
405 | } | ||
406 | xprt->address_strings[RPC_DISPLAY_UNIVERSAL_ADDR] = buf; | ||
407 | |||
408 | xprt->address_strings[RPC_DISPLAY_NETID] = | ||
409 | kstrdup(xprt->prot == IPPROTO_UDP ? | ||
410 | RPCBIND_NETID_UDP6 : RPCBIND_NETID_TCP6, GFP_KERNEL); | ||
295 | } | 411 | } |
296 | 412 | ||
297 | static void xs_free_peer_addresses(struct rpc_xprt *xprt) | 413 | static void xs_free_peer_addresses(struct rpc_xprt *xprt) |
298 | { | 414 | { |
299 | kfree(xprt->address_strings[RPC_DISPLAY_ADDR]); | 415 | int i; |
300 | kfree(xprt->address_strings[RPC_DISPLAY_PORT]); | 416 | |
301 | kfree(xprt->address_strings[RPC_DISPLAY_ALL]); | 417 | for (i = 0; i < RPC_DISPLAY_MAX; i++) |
418 | kfree(xprt->address_strings[i]); | ||
302 | } | 419 | } |
303 | 420 | ||
304 | #define XS_SENDMSG_FLAGS (MSG_DONTWAIT | MSG_NOSIGNAL) | 421 | #define XS_SENDMSG_FLAGS (MSG_DONTWAIT | MSG_NOSIGNAL) |
@@ -463,19 +580,20 @@ static int xs_udp_send_request(struct rpc_task *task) | |||
463 | 580 | ||
464 | req->rq_xtime = jiffies; | 581 | req->rq_xtime = jiffies; |
465 | status = xs_sendpages(transport->sock, | 582 | status = xs_sendpages(transport->sock, |
466 | (struct sockaddr *) &xprt->addr, | 583 | xs_addr(xprt), |
467 | xprt->addrlen, xdr, | 584 | xprt->addrlen, xdr, |
468 | req->rq_bytes_sent); | 585 | req->rq_bytes_sent); |
469 | 586 | ||
470 | dprintk("RPC: xs_udp_send_request(%u) = %d\n", | 587 | dprintk("RPC: xs_udp_send_request(%u) = %d\n", |
471 | xdr->len - req->rq_bytes_sent, status); | 588 | xdr->len - req->rq_bytes_sent, status); |
472 | 589 | ||
473 | if (likely(status >= (int) req->rq_slen)) | 590 | if (status >= 0) { |
474 | return 0; | 591 | task->tk_bytes_sent += status; |
475 | 592 | if (status >= req->rq_slen) | |
476 | /* Still some bytes left; set up for a retry later. */ | 593 | return 0; |
477 | if (status > 0) | 594 | /* Still some bytes left; set up for a retry later. */ |
478 | status = -EAGAIN; | 595 | status = -EAGAIN; |
596 | } | ||
479 | 597 | ||
480 | switch (status) { | 598 | switch (status) { |
481 | case -ENETUNREACH: | 599 | case -ENETUNREACH: |
@@ -523,7 +641,8 @@ static int xs_tcp_send_request(struct rpc_task *task) | |||
523 | struct rpc_xprt *xprt = req->rq_xprt; | 641 | struct rpc_xprt *xprt = req->rq_xprt; |
524 | struct sock_xprt *transport = container_of(xprt, struct sock_xprt, xprt); | 642 | struct sock_xprt *transport = container_of(xprt, struct sock_xprt, xprt); |
525 | struct xdr_buf *xdr = &req->rq_snd_buf; | 643 | struct xdr_buf *xdr = &req->rq_snd_buf; |
526 | int status, retry = 0; | 644 | int status; |
645 | unsigned int retry = 0; | ||
527 | 646 | ||
528 | xs_encode_tcp_record_marker(&req->rq_snd_buf); | 647 | xs_encode_tcp_record_marker(&req->rq_snd_buf); |
529 | 648 | ||
@@ -661,6 +780,7 @@ static void xs_destroy(struct rpc_xprt *xprt) | |||
661 | xs_free_peer_addresses(xprt); | 780 | xs_free_peer_addresses(xprt); |
662 | kfree(xprt->slot); | 781 | kfree(xprt->slot); |
663 | kfree(xprt); | 782 | kfree(xprt); |
783 | module_put(THIS_MODULE); | ||
664 | } | 784 | } |
665 | 785 | ||
666 | static inline struct rpc_xprt *xprt_from_sock(struct sock *sk) | 786 | static inline struct rpc_xprt *xprt_from_sock(struct sock *sk) |
@@ -1139,14 +1259,23 @@ static unsigned short xs_get_random_port(void) | |||
1139 | */ | 1259 | */ |
1140 | static void xs_set_port(struct rpc_xprt *xprt, unsigned short port) | 1260 | static void xs_set_port(struct rpc_xprt *xprt, unsigned short port) |
1141 | { | 1261 | { |
1142 | struct sockaddr_in *sap = (struct sockaddr_in *) &xprt->addr; | 1262 | struct sockaddr *addr = xs_addr(xprt); |
1143 | 1263 | ||
1144 | dprintk("RPC: setting port for xprt %p to %u\n", xprt, port); | 1264 | dprintk("RPC: setting port for xprt %p to %u\n", xprt, port); |
1145 | 1265 | ||
1146 | sap->sin_port = htons(port); | 1266 | switch (addr->sa_family) { |
1267 | case AF_INET: | ||
1268 | ((struct sockaddr_in *)addr)->sin_port = htons(port); | ||
1269 | break; | ||
1270 | case AF_INET6: | ||
1271 | ((struct sockaddr_in6 *)addr)->sin6_port = htons(port); | ||
1272 | break; | ||
1273 | default: | ||
1274 | BUG(); | ||
1275 | } | ||
1147 | } | 1276 | } |
1148 | 1277 | ||
1149 | static int xs_bind(struct sock_xprt *transport, struct socket *sock) | 1278 | static int xs_bind4(struct sock_xprt *transport, struct socket *sock) |
1150 | { | 1279 | { |
1151 | struct sockaddr_in myaddr = { | 1280 | struct sockaddr_in myaddr = { |
1152 | .sin_family = AF_INET, | 1281 | .sin_family = AF_INET, |
@@ -1174,8 +1303,42 @@ static int xs_bind(struct sock_xprt *transport, struct socket *sock) | |||
1174 | else | 1303 | else |
1175 | port--; | 1304 | port--; |
1176 | } while (err == -EADDRINUSE && port != transport->port); | 1305 | } while (err == -EADDRINUSE && port != transport->port); |
1177 | dprintk("RPC: xs_bind "NIPQUAD_FMT":%u: %s (%d)\n", | 1306 | dprintk("RPC: %s "NIPQUAD_FMT":%u: %s (%d)\n", |
1178 | NIPQUAD(myaddr.sin_addr), port, err ? "failed" : "ok", err); | 1307 | __FUNCTION__, NIPQUAD(myaddr.sin_addr), |
1308 | port, err ? "failed" : "ok", err); | ||
1309 | return err; | ||
1310 | } | ||
1311 | |||
1312 | static int xs_bind6(struct sock_xprt *transport, struct socket *sock) | ||
1313 | { | ||
1314 | struct sockaddr_in6 myaddr = { | ||
1315 | .sin6_family = AF_INET6, | ||
1316 | }; | ||
1317 | struct sockaddr_in6 *sa; | ||
1318 | int err; | ||
1319 | unsigned short port = transport->port; | ||
1320 | |||
1321 | if (!transport->xprt.resvport) | ||
1322 | port = 0; | ||
1323 | sa = (struct sockaddr_in6 *)&transport->addr; | ||
1324 | myaddr.sin6_addr = sa->sin6_addr; | ||
1325 | do { | ||
1326 | myaddr.sin6_port = htons(port); | ||
1327 | err = kernel_bind(sock, (struct sockaddr *) &myaddr, | ||
1328 | sizeof(myaddr)); | ||
1329 | if (!transport->xprt.resvport) | ||
1330 | break; | ||
1331 | if (err == 0) { | ||
1332 | transport->port = port; | ||
1333 | break; | ||
1334 | } | ||
1335 | if (port <= xprt_min_resvport) | ||
1336 | port = xprt_max_resvport; | ||
1337 | else | ||
1338 | port--; | ||
1339 | } while (err == -EADDRINUSE && port != transport->port); | ||
1340 | dprintk("RPC: xs_bind6 "NIP6_FMT":%u: %s (%d)\n", | ||
1341 | NIP6(myaddr.sin6_addr), port, err ? "failed" : "ok", err); | ||
1179 | return err; | 1342 | return err; |
1180 | } | 1343 | } |
1181 | 1344 | ||
@@ -1183,38 +1346,69 @@ static int xs_bind(struct sock_xprt *transport, struct socket *sock) | |||
1183 | static struct lock_class_key xs_key[2]; | 1346 | static struct lock_class_key xs_key[2]; |
1184 | static struct lock_class_key xs_slock_key[2]; | 1347 | static struct lock_class_key xs_slock_key[2]; |
1185 | 1348 | ||
1186 | static inline void xs_reclassify_socket(struct socket *sock) | 1349 | static inline void xs_reclassify_socket4(struct socket *sock) |
1187 | { | 1350 | { |
1188 | struct sock *sk = sock->sk; | 1351 | struct sock *sk = sock->sk; |
1352 | |||
1189 | BUG_ON(sock_owned_by_user(sk)); | 1353 | BUG_ON(sock_owned_by_user(sk)); |
1190 | switch (sk->sk_family) { | 1354 | sock_lock_init_class_and_name(sk, "slock-AF_INET-RPC", |
1191 | case AF_INET: | 1355 | &xs_slock_key[0], "sk_lock-AF_INET-RPC", &xs_key[0]); |
1192 | sock_lock_init_class_and_name(sk, "slock-AF_INET-NFS", | 1356 | } |
1193 | &xs_slock_key[0], "sk_lock-AF_INET-NFS", &xs_key[0]); | ||
1194 | break; | ||
1195 | 1357 | ||
1196 | case AF_INET6: | 1358 | static inline void xs_reclassify_socket6(struct socket *sock) |
1197 | sock_lock_init_class_and_name(sk, "slock-AF_INET6-NFS", | 1359 | { |
1198 | &xs_slock_key[1], "sk_lock-AF_INET6-NFS", &xs_key[1]); | 1360 | struct sock *sk = sock->sk; |
1199 | break; | ||
1200 | 1361 | ||
1201 | default: | 1362 | BUG_ON(sock_owned_by_user(sk)); |
1202 | BUG(); | 1363 | sock_lock_init_class_and_name(sk, "slock-AF_INET6-RPC", |
1203 | } | 1364 | &xs_slock_key[1], "sk_lock-AF_INET6-RPC", &xs_key[1]); |
1204 | } | 1365 | } |
1205 | #else | 1366 | #else |
1206 | static inline void xs_reclassify_socket(struct socket *sock) | 1367 | static inline void xs_reclassify_socket4(struct socket *sock) |
1368 | { | ||
1369 | } | ||
1370 | |||
1371 | static inline void xs_reclassify_socket6(struct socket *sock) | ||
1207 | { | 1372 | { |
1208 | } | 1373 | } |
1209 | #endif | 1374 | #endif |
1210 | 1375 | ||
1376 | static void xs_udp_finish_connecting(struct rpc_xprt *xprt, struct socket *sock) | ||
1377 | { | ||
1378 | struct sock_xprt *transport = container_of(xprt, struct sock_xprt, xprt); | ||
1379 | |||
1380 | if (!transport->inet) { | ||
1381 | struct sock *sk = sock->sk; | ||
1382 | |||
1383 | write_lock_bh(&sk->sk_callback_lock); | ||
1384 | |||
1385 | sk->sk_user_data = xprt; | ||
1386 | transport->old_data_ready = sk->sk_data_ready; | ||
1387 | transport->old_state_change = sk->sk_state_change; | ||
1388 | transport->old_write_space = sk->sk_write_space; | ||
1389 | sk->sk_data_ready = xs_udp_data_ready; | ||
1390 | sk->sk_write_space = xs_udp_write_space; | ||
1391 | sk->sk_no_check = UDP_CSUM_NORCV; | ||
1392 | sk->sk_allocation = GFP_ATOMIC; | ||
1393 | |||
1394 | xprt_set_connected(xprt); | ||
1395 | |||
1396 | /* Reset to new socket */ | ||
1397 | transport->sock = sock; | ||
1398 | transport->inet = sk; | ||
1399 | |||
1400 | write_unlock_bh(&sk->sk_callback_lock); | ||
1401 | } | ||
1402 | xs_udp_do_set_buffer_size(xprt); | ||
1403 | } | ||
1404 | |||
1211 | /** | 1405 | /** |
1212 | * xs_udp_connect_worker - set up a UDP socket | 1406 | * xs_udp_connect_worker4 - set up a UDP socket |
1213 | * @work: RPC transport to connect | 1407 | * @work: RPC transport to connect |
1214 | * | 1408 | * |
1215 | * Invoked by a work queue tasklet. | 1409 | * Invoked by a work queue tasklet. |
1216 | */ | 1410 | */ |
1217 | static void xs_udp_connect_worker(struct work_struct *work) | 1411 | static void xs_udp_connect_worker4(struct work_struct *work) |
1218 | { | 1412 | { |
1219 | struct sock_xprt *transport = | 1413 | struct sock_xprt *transport = |
1220 | container_of(work, struct sock_xprt, connect_worker.work); | 1414 | container_of(work, struct sock_xprt, connect_worker.work); |
@@ -1232,9 +1426,9 @@ static void xs_udp_connect_worker(struct work_struct *work) | |||
1232 | dprintk("RPC: can't create UDP transport socket (%d).\n", -err); | 1426 | dprintk("RPC: can't create UDP transport socket (%d).\n", -err); |
1233 | goto out; | 1427 | goto out; |
1234 | } | 1428 | } |
1235 | xs_reclassify_socket(sock); | 1429 | xs_reclassify_socket4(sock); |
1236 | 1430 | ||
1237 | if (xs_bind(transport, sock)) { | 1431 | if (xs_bind4(transport, sock)) { |
1238 | sock_release(sock); | 1432 | sock_release(sock); |
1239 | goto out; | 1433 | goto out; |
1240 | } | 1434 | } |
@@ -1242,29 +1436,48 @@ static void xs_udp_connect_worker(struct work_struct *work) | |||
1242 | dprintk("RPC: worker connecting xprt %p to address: %s\n", | 1436 | dprintk("RPC: worker connecting xprt %p to address: %s\n", |
1243 | xprt, xprt->address_strings[RPC_DISPLAY_ALL]); | 1437 | xprt, xprt->address_strings[RPC_DISPLAY_ALL]); |
1244 | 1438 | ||
1245 | if (!transport->inet) { | 1439 | xs_udp_finish_connecting(xprt, sock); |
1246 | struct sock *sk = sock->sk; | 1440 | status = 0; |
1441 | out: | ||
1442 | xprt_wake_pending_tasks(xprt, status); | ||
1443 | xprt_clear_connecting(xprt); | ||
1444 | } | ||
1247 | 1445 | ||
1248 | write_lock_bh(&sk->sk_callback_lock); | 1446 | /** |
1447 | * xs_udp_connect_worker6 - set up a UDP socket | ||
1448 | * @work: RPC transport to connect | ||
1449 | * | ||
1450 | * Invoked by a work queue tasklet. | ||
1451 | */ | ||
1452 | static void xs_udp_connect_worker6(struct work_struct *work) | ||
1453 | { | ||
1454 | struct sock_xprt *transport = | ||
1455 | container_of(work, struct sock_xprt, connect_worker.work); | ||
1456 | struct rpc_xprt *xprt = &transport->xprt; | ||
1457 | struct socket *sock = transport->sock; | ||
1458 | int err, status = -EIO; | ||
1249 | 1459 | ||
1250 | sk->sk_user_data = xprt; | 1460 | if (xprt->shutdown || !xprt_bound(xprt)) |
1251 | transport->old_data_ready = sk->sk_data_ready; | 1461 | goto out; |
1252 | transport->old_state_change = sk->sk_state_change; | ||
1253 | transport->old_write_space = sk->sk_write_space; | ||
1254 | sk->sk_data_ready = xs_udp_data_ready; | ||
1255 | sk->sk_write_space = xs_udp_write_space; | ||
1256 | sk->sk_no_check = UDP_CSUM_NORCV; | ||
1257 | sk->sk_allocation = GFP_ATOMIC; | ||
1258 | 1462 | ||
1259 | xprt_set_connected(xprt); | 1463 | /* Start by resetting any existing state */ |
1464 | xs_close(xprt); | ||
1260 | 1465 | ||
1261 | /* Reset to new socket */ | 1466 | if ((err = sock_create_kern(PF_INET6, SOCK_DGRAM, IPPROTO_UDP, &sock)) < 0) { |
1262 | transport->sock = sock; | 1467 | dprintk("RPC: can't create UDP transport socket (%d).\n", -err); |
1263 | transport->inet = sk; | 1468 | goto out; |
1469 | } | ||
1470 | xs_reclassify_socket6(sock); | ||
1264 | 1471 | ||
1265 | write_unlock_bh(&sk->sk_callback_lock); | 1472 | if (xs_bind6(transport, sock) < 0) { |
1473 | sock_release(sock); | ||
1474 | goto out; | ||
1266 | } | 1475 | } |
1267 | xs_udp_do_set_buffer_size(xprt); | 1476 | |
1477 | dprintk("RPC: worker connecting xprt %p to address: %s\n", | ||
1478 | xprt, xprt->address_strings[RPC_DISPLAY_ALL]); | ||
1479 | |||
1480 | xs_udp_finish_connecting(xprt, sock); | ||
1268 | status = 0; | 1481 | status = 0; |
1269 | out: | 1482 | out: |
1270 | xprt_wake_pending_tasks(xprt, status); | 1483 | xprt_wake_pending_tasks(xprt, status); |
@@ -1295,13 +1508,52 @@ static void xs_tcp_reuse_connection(struct rpc_xprt *xprt) | |||
1295 | result); | 1508 | result); |
1296 | } | 1509 | } |
1297 | 1510 | ||
1511 | static int xs_tcp_finish_connecting(struct rpc_xprt *xprt, struct socket *sock) | ||
1512 | { | ||
1513 | struct sock_xprt *transport = container_of(xprt, struct sock_xprt, xprt); | ||
1514 | |||
1515 | if (!transport->inet) { | ||
1516 | struct sock *sk = sock->sk; | ||
1517 | |||
1518 | write_lock_bh(&sk->sk_callback_lock); | ||
1519 | |||
1520 | sk->sk_user_data = xprt; | ||
1521 | transport->old_data_ready = sk->sk_data_ready; | ||
1522 | transport->old_state_change = sk->sk_state_change; | ||
1523 | transport->old_write_space = sk->sk_write_space; | ||
1524 | sk->sk_data_ready = xs_tcp_data_ready; | ||
1525 | sk->sk_state_change = xs_tcp_state_change; | ||
1526 | sk->sk_write_space = xs_tcp_write_space; | ||
1527 | sk->sk_allocation = GFP_ATOMIC; | ||
1528 | |||
1529 | /* socket options */ | ||
1530 | sk->sk_userlocks |= SOCK_BINDPORT_LOCK; | ||
1531 | sock_reset_flag(sk, SOCK_LINGER); | ||
1532 | tcp_sk(sk)->linger2 = 0; | ||
1533 | tcp_sk(sk)->nonagle |= TCP_NAGLE_OFF; | ||
1534 | |||
1535 | xprt_clear_connected(xprt); | ||
1536 | |||
1537 | /* Reset to new socket */ | ||
1538 | transport->sock = sock; | ||
1539 | transport->inet = sk; | ||
1540 | |||
1541 | write_unlock_bh(&sk->sk_callback_lock); | ||
1542 | } | ||
1543 | |||
1544 | /* Tell the socket layer to start connecting... */ | ||
1545 | xprt->stat.connect_count++; | ||
1546 | xprt->stat.connect_start = jiffies; | ||
1547 | return kernel_connect(sock, xs_addr(xprt), xprt->addrlen, O_NONBLOCK); | ||
1548 | } | ||
1549 | |||
1298 | /** | 1550 | /** |
1299 | * xs_tcp_connect_worker - connect a TCP socket to a remote endpoint | 1551 | * xs_tcp_connect_worker4 - connect a TCP socket to a remote endpoint |
1300 | * @work: RPC transport to connect | 1552 | * @work: RPC transport to connect |
1301 | * | 1553 | * |
1302 | * Invoked by a work queue tasklet. | 1554 | * Invoked by a work queue tasklet. |
1303 | */ | 1555 | */ |
1304 | static void xs_tcp_connect_worker(struct work_struct *work) | 1556 | static void xs_tcp_connect_worker4(struct work_struct *work) |
1305 | { | 1557 | { |
1306 | struct sock_xprt *transport = | 1558 | struct sock_xprt *transport = |
1307 | container_of(work, struct sock_xprt, connect_worker.work); | 1559 | container_of(work, struct sock_xprt, connect_worker.work); |
@@ -1315,13 +1567,12 @@ static void xs_tcp_connect_worker(struct work_struct *work) | |||
1315 | if (!sock) { | 1567 | if (!sock) { |
1316 | /* start from scratch */ | 1568 | /* start from scratch */ |
1317 | if ((err = sock_create_kern(PF_INET, SOCK_STREAM, IPPROTO_TCP, &sock)) < 0) { | 1569 | if ((err = sock_create_kern(PF_INET, SOCK_STREAM, IPPROTO_TCP, &sock)) < 0) { |
1318 | dprintk("RPC: can't create TCP transport " | 1570 | dprintk("RPC: can't create TCP transport socket (%d).\n", -err); |
1319 | "socket (%d).\n", -err); | ||
1320 | goto out; | 1571 | goto out; |
1321 | } | 1572 | } |
1322 | xs_reclassify_socket(sock); | 1573 | xs_reclassify_socket4(sock); |
1323 | 1574 | ||
1324 | if (xs_bind(transport, sock)) { | 1575 | if (xs_bind4(transport, sock) < 0) { |
1325 | sock_release(sock); | 1576 | sock_release(sock); |
1326 | goto out; | 1577 | goto out; |
1327 | } | 1578 | } |
@@ -1332,43 +1583,70 @@ static void xs_tcp_connect_worker(struct work_struct *work) | |||
1332 | dprintk("RPC: worker connecting xprt %p to address: %s\n", | 1583 | dprintk("RPC: worker connecting xprt %p to address: %s\n", |
1333 | xprt, xprt->address_strings[RPC_DISPLAY_ALL]); | 1584 | xprt, xprt->address_strings[RPC_DISPLAY_ALL]); |
1334 | 1585 | ||
1335 | if (!transport->inet) { | 1586 | status = xs_tcp_finish_connecting(xprt, sock); |
1336 | struct sock *sk = sock->sk; | 1587 | dprintk("RPC: %p connect status %d connected %d sock state %d\n", |
1337 | 1588 | xprt, -status, xprt_connected(xprt), | |
1338 | write_lock_bh(&sk->sk_callback_lock); | 1589 | sock->sk->sk_state); |
1590 | if (status < 0) { | ||
1591 | switch (status) { | ||
1592 | case -EINPROGRESS: | ||
1593 | case -EALREADY: | ||
1594 | goto out_clear; | ||
1595 | case -ECONNREFUSED: | ||
1596 | case -ECONNRESET: | ||
1597 | /* retry with existing socket, after a delay */ | ||
1598 | break; | ||
1599 | default: | ||
1600 | /* get rid of existing socket, and retry */ | ||
1601 | xs_close(xprt); | ||
1602 | break; | ||
1603 | } | ||
1604 | } | ||
1605 | out: | ||
1606 | xprt_wake_pending_tasks(xprt, status); | ||
1607 | out_clear: | ||
1608 | xprt_clear_connecting(xprt); | ||
1609 | } | ||
1339 | 1610 | ||
1340 | sk->sk_user_data = xprt; | 1611 | /** |
1341 | transport->old_data_ready = sk->sk_data_ready; | 1612 | * xs_tcp_connect_worker6 - connect a TCP socket to a remote endpoint |
1342 | transport->old_state_change = sk->sk_state_change; | 1613 | * @work: RPC transport to connect |
1343 | transport->old_write_space = sk->sk_write_space; | 1614 | * |
1344 | sk->sk_data_ready = xs_tcp_data_ready; | 1615 | * Invoked by a work queue tasklet. |
1345 | sk->sk_state_change = xs_tcp_state_change; | 1616 | */ |
1346 | sk->sk_write_space = xs_tcp_write_space; | 1617 | static void xs_tcp_connect_worker6(struct work_struct *work) |
1347 | sk->sk_allocation = GFP_ATOMIC; | 1618 | { |
1619 | struct sock_xprt *transport = | ||
1620 | container_of(work, struct sock_xprt, connect_worker.work); | ||
1621 | struct rpc_xprt *xprt = &transport->xprt; | ||
1622 | struct socket *sock = transport->sock; | ||
1623 | int err, status = -EIO; | ||
1348 | 1624 | ||
1349 | /* socket options */ | 1625 | if (xprt->shutdown || !xprt_bound(xprt)) |
1350 | sk->sk_userlocks |= SOCK_BINDPORT_LOCK; | 1626 | goto out; |
1351 | sock_reset_flag(sk, SOCK_LINGER); | ||
1352 | tcp_sk(sk)->linger2 = 0; | ||
1353 | tcp_sk(sk)->nonagle |= TCP_NAGLE_OFF; | ||
1354 | 1627 | ||
1355 | xprt_clear_connected(xprt); | 1628 | if (!sock) { |
1629 | /* start from scratch */ | ||
1630 | if ((err = sock_create_kern(PF_INET6, SOCK_STREAM, IPPROTO_TCP, &sock)) < 0) { | ||
1631 | dprintk("RPC: can't create TCP transport socket (%d).\n", -err); | ||
1632 | goto out; | ||
1633 | } | ||
1634 | xs_reclassify_socket6(sock); | ||
1356 | 1635 | ||
1357 | /* Reset to new socket */ | 1636 | if (xs_bind6(transport, sock) < 0) { |
1358 | transport->sock = sock; | 1637 | sock_release(sock); |
1359 | transport->inet = sk; | 1638 | goto out; |
1639 | } | ||
1640 | } else | ||
1641 | /* "close" the socket, preserving the local port */ | ||
1642 | xs_tcp_reuse_connection(xprt); | ||
1360 | 1643 | ||
1361 | write_unlock_bh(&sk->sk_callback_lock); | 1644 | dprintk("RPC: worker connecting xprt %p to address: %s\n", |
1362 | } | 1645 | xprt, xprt->address_strings[RPC_DISPLAY_ALL]); |
1363 | 1646 | ||
1364 | /* Tell the socket layer to start connecting... */ | 1647 | status = xs_tcp_finish_connecting(xprt, sock); |
1365 | xprt->stat.connect_count++; | ||
1366 | xprt->stat.connect_start = jiffies; | ||
1367 | status = kernel_connect(sock, (struct sockaddr *) &xprt->addr, | ||
1368 | xprt->addrlen, O_NONBLOCK); | ||
1369 | dprintk("RPC: %p connect status %d connected %d sock state %d\n", | 1648 | dprintk("RPC: %p connect status %d connected %d sock state %d\n", |
1370 | xprt, -status, xprt_connected(xprt), | 1649 | xprt, -status, xprt_connected(xprt), sock->sk->sk_state); |
1371 | sock->sk->sk_state); | ||
1372 | if (status < 0) { | 1650 | if (status < 0) { |
1373 | switch (status) { | 1651 | switch (status) { |
1374 | case -EINPROGRESS: | 1652 | case -EINPROGRESS: |
@@ -1508,7 +1786,8 @@ static struct rpc_xprt_ops xs_tcp_ops = { | |||
1508 | .print_stats = xs_tcp_print_stats, | 1786 | .print_stats = xs_tcp_print_stats, |
1509 | }; | 1787 | }; |
1510 | 1788 | ||
1511 | static struct rpc_xprt *xs_setup_xprt(struct rpc_xprtsock_create *args, unsigned int slot_table_size) | 1789 | static struct rpc_xprt *xs_setup_xprt(struct xprt_create *args, |
1790 | unsigned int slot_table_size) | ||
1512 | { | 1791 | { |
1513 | struct rpc_xprt *xprt; | 1792 | struct rpc_xprt *xprt; |
1514 | struct sock_xprt *new; | 1793 | struct sock_xprt *new; |
@@ -1549,8 +1828,9 @@ static struct rpc_xprt *xs_setup_xprt(struct rpc_xprtsock_create *args, unsigned | |||
1549 | * @args: rpc transport creation arguments | 1828 | * @args: rpc transport creation arguments |
1550 | * | 1829 | * |
1551 | */ | 1830 | */ |
1552 | struct rpc_xprt *xs_setup_udp(struct rpc_xprtsock_create *args) | 1831 | struct rpc_xprt *xs_setup_udp(struct xprt_create *args) |
1553 | { | 1832 | { |
1833 | struct sockaddr *addr = args->dstaddr; | ||
1554 | struct rpc_xprt *xprt; | 1834 | struct rpc_xprt *xprt; |
1555 | struct sock_xprt *transport; | 1835 | struct sock_xprt *transport; |
1556 | 1836 | ||
@@ -1559,15 +1839,11 @@ struct rpc_xprt *xs_setup_udp(struct rpc_xprtsock_create *args) | |||
1559 | return xprt; | 1839 | return xprt; |
1560 | transport = container_of(xprt, struct sock_xprt, xprt); | 1840 | transport = container_of(xprt, struct sock_xprt, xprt); |
1561 | 1841 | ||
1562 | if (ntohs(((struct sockaddr_in *)args->dstaddr)->sin_port) != 0) | ||
1563 | xprt_set_bound(xprt); | ||
1564 | |||
1565 | xprt->prot = IPPROTO_UDP; | 1842 | xprt->prot = IPPROTO_UDP; |
1566 | xprt->tsh_size = 0; | 1843 | xprt->tsh_size = 0; |
1567 | /* XXX: header size can vary due to auth type, IPv6, etc. */ | 1844 | /* XXX: header size can vary due to auth type, IPv6, etc. */ |
1568 | xprt->max_payload = (1U << 16) - (MAX_HEADER << 3); | 1845 | xprt->max_payload = (1U << 16) - (MAX_HEADER << 3); |
1569 | 1846 | ||
1570 | INIT_DELAYED_WORK(&transport->connect_worker, xs_udp_connect_worker); | ||
1571 | xprt->bind_timeout = XS_BIND_TO; | 1847 | xprt->bind_timeout = XS_BIND_TO; |
1572 | xprt->connect_timeout = XS_UDP_CONN_TO; | 1848 | xprt->connect_timeout = XS_UDP_CONN_TO; |
1573 | xprt->reestablish_timeout = XS_UDP_REEST_TO; | 1849 | xprt->reestablish_timeout = XS_UDP_REEST_TO; |
@@ -1580,11 +1856,37 @@ struct rpc_xprt *xs_setup_udp(struct rpc_xprtsock_create *args) | |||
1580 | else | 1856 | else |
1581 | xprt_set_timeout(&xprt->timeout, 5, 5 * HZ); | 1857 | xprt_set_timeout(&xprt->timeout, 5, 5 * HZ); |
1582 | 1858 | ||
1583 | xs_format_peer_addresses(xprt); | 1859 | switch (addr->sa_family) { |
1860 | case AF_INET: | ||
1861 | if (((struct sockaddr_in *)addr)->sin_port != htons(0)) | ||
1862 | xprt_set_bound(xprt); | ||
1863 | |||
1864 | INIT_DELAYED_WORK(&transport->connect_worker, | ||
1865 | xs_udp_connect_worker4); | ||
1866 | xs_format_ipv4_peer_addresses(xprt); | ||
1867 | break; | ||
1868 | case AF_INET6: | ||
1869 | if (((struct sockaddr_in6 *)addr)->sin6_port != htons(0)) | ||
1870 | xprt_set_bound(xprt); | ||
1871 | |||
1872 | INIT_DELAYED_WORK(&transport->connect_worker, | ||
1873 | xs_udp_connect_worker6); | ||
1874 | xs_format_ipv6_peer_addresses(xprt); | ||
1875 | break; | ||
1876 | default: | ||
1877 | kfree(xprt); | ||
1878 | return ERR_PTR(-EAFNOSUPPORT); | ||
1879 | } | ||
1880 | |||
1584 | dprintk("RPC: set up transport to address %s\n", | 1881 | dprintk("RPC: set up transport to address %s\n", |
1585 | xprt->address_strings[RPC_DISPLAY_ALL]); | 1882 | xprt->address_strings[RPC_DISPLAY_ALL]); |
1586 | 1883 | ||
1587 | return xprt; | 1884 | if (try_module_get(THIS_MODULE)) |
1885 | return xprt; | ||
1886 | |||
1887 | kfree(xprt->slot); | ||
1888 | kfree(xprt); | ||
1889 | return ERR_PTR(-EINVAL); | ||
1588 | } | 1890 | } |
1589 | 1891 | ||
1590 | /** | 1892 | /** |
@@ -1592,8 +1894,9 @@ struct rpc_xprt *xs_setup_udp(struct rpc_xprtsock_create *args) | |||
1592 | * @args: rpc transport creation arguments | 1894 | * @args: rpc transport creation arguments |
1593 | * | 1895 | * |
1594 | */ | 1896 | */ |
1595 | struct rpc_xprt *xs_setup_tcp(struct rpc_xprtsock_create *args) | 1897 | struct rpc_xprt *xs_setup_tcp(struct xprt_create *args) |
1596 | { | 1898 | { |
1899 | struct sockaddr *addr = args->dstaddr; | ||
1597 | struct rpc_xprt *xprt; | 1900 | struct rpc_xprt *xprt; |
1598 | struct sock_xprt *transport; | 1901 | struct sock_xprt *transport; |
1599 | 1902 | ||
@@ -1602,14 +1905,10 @@ struct rpc_xprt *xs_setup_tcp(struct rpc_xprtsock_create *args) | |||
1602 | return xprt; | 1905 | return xprt; |
1603 | transport = container_of(xprt, struct sock_xprt, xprt); | 1906 | transport = container_of(xprt, struct sock_xprt, xprt); |
1604 | 1907 | ||
1605 | if (ntohs(((struct sockaddr_in *)args->dstaddr)->sin_port) != 0) | ||
1606 | xprt_set_bound(xprt); | ||
1607 | |||
1608 | xprt->prot = IPPROTO_TCP; | 1908 | xprt->prot = IPPROTO_TCP; |
1609 | xprt->tsh_size = sizeof(rpc_fraghdr) / sizeof(u32); | 1909 | xprt->tsh_size = sizeof(rpc_fraghdr) / sizeof(u32); |
1610 | xprt->max_payload = RPC_MAX_FRAGMENT_SIZE; | 1910 | xprt->max_payload = RPC_MAX_FRAGMENT_SIZE; |
1611 | 1911 | ||
1612 | INIT_DELAYED_WORK(&transport->connect_worker, xs_tcp_connect_worker); | ||
1613 | xprt->bind_timeout = XS_BIND_TO; | 1912 | xprt->bind_timeout = XS_BIND_TO; |
1614 | xprt->connect_timeout = XS_TCP_CONN_TO; | 1913 | xprt->connect_timeout = XS_TCP_CONN_TO; |
1615 | xprt->reestablish_timeout = XS_TCP_INIT_REEST_TO; | 1914 | xprt->reestablish_timeout = XS_TCP_INIT_REEST_TO; |
@@ -1622,15 +1921,55 @@ struct rpc_xprt *xs_setup_tcp(struct rpc_xprtsock_create *args) | |||
1622 | else | 1921 | else |
1623 | xprt_set_timeout(&xprt->timeout, 2, 60 * HZ); | 1922 | xprt_set_timeout(&xprt->timeout, 2, 60 * HZ); |
1624 | 1923 | ||
1625 | xs_format_peer_addresses(xprt); | 1924 | switch (addr->sa_family) { |
1925 | case AF_INET: | ||
1926 | if (((struct sockaddr_in *)addr)->sin_port != htons(0)) | ||
1927 | xprt_set_bound(xprt); | ||
1928 | |||
1929 | INIT_DELAYED_WORK(&transport->connect_worker, xs_tcp_connect_worker4); | ||
1930 | xs_format_ipv4_peer_addresses(xprt); | ||
1931 | break; | ||
1932 | case AF_INET6: | ||
1933 | if (((struct sockaddr_in6 *)addr)->sin6_port != htons(0)) | ||
1934 | xprt_set_bound(xprt); | ||
1935 | |||
1936 | INIT_DELAYED_WORK(&transport->connect_worker, xs_tcp_connect_worker6); | ||
1937 | xs_format_ipv6_peer_addresses(xprt); | ||
1938 | break; | ||
1939 | default: | ||
1940 | kfree(xprt); | ||
1941 | return ERR_PTR(-EAFNOSUPPORT); | ||
1942 | } | ||
1943 | |||
1626 | dprintk("RPC: set up transport to address %s\n", | 1944 | dprintk("RPC: set up transport to address %s\n", |
1627 | xprt->address_strings[RPC_DISPLAY_ALL]); | 1945 | xprt->address_strings[RPC_DISPLAY_ALL]); |
1628 | 1946 | ||
1629 | return xprt; | 1947 | if (try_module_get(THIS_MODULE)) |
1948 | return xprt; | ||
1949 | |||
1950 | kfree(xprt->slot); | ||
1951 | kfree(xprt); | ||
1952 | return ERR_PTR(-EINVAL); | ||
1630 | } | 1953 | } |
1631 | 1954 | ||
1955 | static struct xprt_class xs_udp_transport = { | ||
1956 | .list = LIST_HEAD_INIT(xs_udp_transport.list), | ||
1957 | .name = "udp", | ||
1958 | .owner = THIS_MODULE, | ||
1959 | .ident = IPPROTO_UDP, | ||
1960 | .setup = xs_setup_udp, | ||
1961 | }; | ||
1962 | |||
1963 | static struct xprt_class xs_tcp_transport = { | ||
1964 | .list = LIST_HEAD_INIT(xs_tcp_transport.list), | ||
1965 | .name = "tcp", | ||
1966 | .owner = THIS_MODULE, | ||
1967 | .ident = IPPROTO_TCP, | ||
1968 | .setup = xs_setup_tcp, | ||
1969 | }; | ||
1970 | |||
1632 | /** | 1971 | /** |
1633 | * init_socket_xprt - set up xprtsock's sysctls | 1972 | * init_socket_xprt - set up xprtsock's sysctls, register with RPC client |
1634 | * | 1973 | * |
1635 | */ | 1974 | */ |
1636 | int init_socket_xprt(void) | 1975 | int init_socket_xprt(void) |
@@ -1640,11 +1979,14 @@ int init_socket_xprt(void) | |||
1640 | sunrpc_table_header = register_sysctl_table(sunrpc_table); | 1979 | sunrpc_table_header = register_sysctl_table(sunrpc_table); |
1641 | #endif | 1980 | #endif |
1642 | 1981 | ||
1982 | xprt_register_transport(&xs_udp_transport); | ||
1983 | xprt_register_transport(&xs_tcp_transport); | ||
1984 | |||
1643 | return 0; | 1985 | return 0; |
1644 | } | 1986 | } |
1645 | 1987 | ||
1646 | /** | 1988 | /** |
1647 | * cleanup_socket_xprt - remove xprtsock's sysctls | 1989 | * cleanup_socket_xprt - remove xprtsock's sysctls, unregister |
1648 | * | 1990 | * |
1649 | */ | 1991 | */ |
1650 | void cleanup_socket_xprt(void) | 1992 | void cleanup_socket_xprt(void) |
@@ -1655,4 +1997,7 @@ void cleanup_socket_xprt(void) | |||
1655 | sunrpc_table_header = NULL; | 1997 | sunrpc_table_header = NULL; |
1656 | } | 1998 | } |
1657 | #endif | 1999 | #endif |
2000 | |||
2001 | xprt_unregister_transport(&xs_udp_transport); | ||
2002 | xprt_unregister_transport(&xs_tcp_transport); | ||
1658 | } | 2003 | } |
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c index 2b57eaf66abc..9163ec526c2a 100644 --- a/net/unix/af_unix.c +++ b/net/unix/af_unix.c | |||
@@ -334,7 +334,7 @@ static void unix_write_space(struct sock *sk) | |||
334 | read_lock(&sk->sk_callback_lock); | 334 | read_lock(&sk->sk_callback_lock); |
335 | if (unix_writable(sk)) { | 335 | if (unix_writable(sk)) { |
336 | if (sk->sk_sleep && waitqueue_active(sk->sk_sleep)) | 336 | if (sk->sk_sleep && waitqueue_active(sk->sk_sleep)) |
337 | wake_up_interruptible(sk->sk_sleep); | 337 | wake_up_interruptible_sync(sk->sk_sleep); |
338 | sk_wake_async(sk, 2, POLL_OUT); | 338 | sk_wake_async(sk, 2, POLL_OUT); |
339 | } | 339 | } |
340 | read_unlock(&sk->sk_callback_lock); | 340 | read_unlock(&sk->sk_callback_lock); |
@@ -483,7 +483,7 @@ static int unix_listen(struct socket *sock, int backlog) | |||
483 | sk->sk_max_ack_backlog = backlog; | 483 | sk->sk_max_ack_backlog = backlog; |
484 | sk->sk_state = TCP_LISTEN; | 484 | sk->sk_state = TCP_LISTEN; |
485 | /* set credentials so connect can copy them */ | 485 | /* set credentials so connect can copy them */ |
486 | sk->sk_peercred.pid = current->tgid; | 486 | sk->sk_peercred.pid = task_tgid_vnr(current); |
487 | sk->sk_peercred.uid = current->euid; | 487 | sk->sk_peercred.uid = current->euid; |
488 | sk->sk_peercred.gid = current->egid; | 488 | sk->sk_peercred.gid = current->egid; |
489 | err = 0; | 489 | err = 0; |
@@ -1133,7 +1133,7 @@ restart: | |||
1133 | unix_peer(newsk) = sk; | 1133 | unix_peer(newsk) = sk; |
1134 | newsk->sk_state = TCP_ESTABLISHED; | 1134 | newsk->sk_state = TCP_ESTABLISHED; |
1135 | newsk->sk_type = sk->sk_type; | 1135 | newsk->sk_type = sk->sk_type; |
1136 | newsk->sk_peercred.pid = current->tgid; | 1136 | newsk->sk_peercred.pid = task_tgid_vnr(current); |
1137 | newsk->sk_peercred.uid = current->euid; | 1137 | newsk->sk_peercred.uid = current->euid; |
1138 | newsk->sk_peercred.gid = current->egid; | 1138 | newsk->sk_peercred.gid = current->egid; |
1139 | newu = unix_sk(newsk); | 1139 | newu = unix_sk(newsk); |
@@ -1194,7 +1194,7 @@ static int unix_socketpair(struct socket *socka, struct socket *sockb) | |||
1194 | sock_hold(skb); | 1194 | sock_hold(skb); |
1195 | unix_peer(ska)=skb; | 1195 | unix_peer(ska)=skb; |
1196 | unix_peer(skb)=ska; | 1196 | unix_peer(skb)=ska; |
1197 | ska->sk_peercred.pid = skb->sk_peercred.pid = current->tgid; | 1197 | ska->sk_peercred.pid = skb->sk_peercred.pid = task_tgid_vnr(current); |
1198 | ska->sk_peercred.uid = skb->sk_peercred.uid = current->euid; | 1198 | ska->sk_peercred.uid = skb->sk_peercred.uid = current->euid; |
1199 | ska->sk_peercred.gid = skb->sk_peercred.gid = current->egid; | 1199 | ska->sk_peercred.gid = skb->sk_peercred.gid = current->egid; |
1200 | 1200 | ||
@@ -1639,7 +1639,7 @@ static int unix_dgram_recvmsg(struct kiocb *iocb, struct socket *sock, | |||
1639 | if (!skb) | 1639 | if (!skb) |
1640 | goto out_unlock; | 1640 | goto out_unlock; |
1641 | 1641 | ||
1642 | wake_up_interruptible(&u->peer_wait); | 1642 | wake_up_interruptible_sync(&u->peer_wait); |
1643 | 1643 | ||
1644 | if (msg->msg_name) | 1644 | if (msg->msg_name) |
1645 | unix_copy_addr(msg, skb->sk); | 1645 | unix_copy_addr(msg, skb->sk); |
diff --git a/net/xfrm/xfrm_algo.c b/net/xfrm/xfrm_algo.c index 5ced62c19c63..313d4bed3aa9 100644 --- a/net/xfrm/xfrm_algo.c +++ b/net/xfrm/xfrm_algo.c | |||
@@ -13,6 +13,7 @@ | |||
13 | #include <linux/kernel.h> | 13 | #include <linux/kernel.h> |
14 | #include <linux/pfkeyv2.h> | 14 | #include <linux/pfkeyv2.h> |
15 | #include <linux/crypto.h> | 15 | #include <linux/crypto.h> |
16 | #include <linux/scatterlist.h> | ||
16 | #include <net/xfrm.h> | 17 | #include <net/xfrm.h> |
17 | #if defined(CONFIG_INET_AH) || defined(CONFIG_INET_AH_MODULE) || defined(CONFIG_INET6_AH) || defined(CONFIG_INET6_AH_MODULE) | 18 | #if defined(CONFIG_INET_AH) || defined(CONFIG_INET_AH_MODULE) || defined(CONFIG_INET6_AH) || defined(CONFIG_INET6_AH_MODULE) |
18 | #include <net/ah.h> | 19 | #include <net/ah.h> |
@@ -552,7 +553,7 @@ int skb_icv_walk(const struct sk_buff *skb, struct hash_desc *desc, | |||
552 | if (copy > len) | 553 | if (copy > len) |
553 | copy = len; | 554 | copy = len; |
554 | 555 | ||
555 | sg.page = virt_to_page(skb->data + offset); | 556 | sg_set_page(&sg, virt_to_page(skb->data + offset)); |
556 | sg.offset = (unsigned long)(skb->data + offset) % PAGE_SIZE; | 557 | sg.offset = (unsigned long)(skb->data + offset) % PAGE_SIZE; |
557 | sg.length = copy; | 558 | sg.length = copy; |
558 | 559 | ||
@@ -577,7 +578,7 @@ int skb_icv_walk(const struct sk_buff *skb, struct hash_desc *desc, | |||
577 | if (copy > len) | 578 | if (copy > len) |
578 | copy = len; | 579 | copy = len; |
579 | 580 | ||
580 | sg.page = frag->page; | 581 | sg_set_page(&sg, frag->page); |
581 | sg.offset = frag->page_offset + offset-start; | 582 | sg.offset = frag->page_offset + offset-start; |
582 | sg.length = copy; | 583 | sg.length = copy; |
583 | 584 | ||
diff --git a/net/xfrm/xfrm_input.c b/net/xfrm/xfrm_input.c index 113f44429982..cb97fda1b6df 100644 --- a/net/xfrm/xfrm_input.c +++ b/net/xfrm/xfrm_input.c | |||
@@ -49,13 +49,16 @@ EXPORT_SYMBOL(secpath_dup); | |||
49 | int xfrm_parse_spi(struct sk_buff *skb, u8 nexthdr, __be32 *spi, __be32 *seq) | 49 | int xfrm_parse_spi(struct sk_buff *skb, u8 nexthdr, __be32 *spi, __be32 *seq) |
50 | { | 50 | { |
51 | int offset, offset_seq; | 51 | int offset, offset_seq; |
52 | int hlen; | ||
52 | 53 | ||
53 | switch (nexthdr) { | 54 | switch (nexthdr) { |
54 | case IPPROTO_AH: | 55 | case IPPROTO_AH: |
56 | hlen = sizeof(struct ip_auth_hdr); | ||
55 | offset = offsetof(struct ip_auth_hdr, spi); | 57 | offset = offsetof(struct ip_auth_hdr, spi); |
56 | offset_seq = offsetof(struct ip_auth_hdr, seq_no); | 58 | offset_seq = offsetof(struct ip_auth_hdr, seq_no); |
57 | break; | 59 | break; |
58 | case IPPROTO_ESP: | 60 | case IPPROTO_ESP: |
61 | hlen = sizeof(struct ip_esp_hdr); | ||
59 | offset = offsetof(struct ip_esp_hdr, spi); | 62 | offset = offsetof(struct ip_esp_hdr, spi); |
60 | offset_seq = offsetof(struct ip_esp_hdr, seq_no); | 63 | offset_seq = offsetof(struct ip_esp_hdr, seq_no); |
61 | break; | 64 | break; |
@@ -69,7 +72,7 @@ int xfrm_parse_spi(struct sk_buff *skb, u8 nexthdr, __be32 *spi, __be32 *seq) | |||
69 | return 1; | 72 | return 1; |
70 | } | 73 | } |
71 | 74 | ||
72 | if (!pskb_may_pull(skb, 16)) | 75 | if (!pskb_may_pull(skb, hlen)) |
73 | return -EINVAL; | 76 | return -EINVAL; |
74 | 77 | ||
75 | *spi = *(__be32*)(skb_transport_header(skb) + offset); | 78 | *spi = *(__be32*)(skb_transport_header(skb) + offset); |
diff --git a/net/xfrm/xfrm_output.c b/net/xfrm/xfrm_output.c index 0eb3377602e9..f4bfd6c45651 100644 --- a/net/xfrm/xfrm_output.c +++ b/net/xfrm/xfrm_output.c | |||
@@ -63,7 +63,7 @@ int xfrm_output(struct sk_buff *skb) | |||
63 | xfrm_replay_notify(x, XFRM_REPLAY_UPDATE); | 63 | xfrm_replay_notify(x, XFRM_REPLAY_UPDATE); |
64 | } | 64 | } |
65 | 65 | ||
66 | err = x->mode->output(x, skb); | 66 | err = x->outer_mode->output(x, skb); |
67 | if (err) | 67 | if (err) |
68 | goto error; | 68 | goto error; |
69 | 69 | ||
@@ -82,7 +82,7 @@ int xfrm_output(struct sk_buff *skb) | |||
82 | } | 82 | } |
83 | dst = skb->dst; | 83 | dst = skb->dst; |
84 | x = dst->xfrm; | 84 | x = dst->xfrm; |
85 | } while (x && (x->props.mode != XFRM_MODE_TUNNEL)); | 85 | } while (x && !(x->outer_mode->flags & XFRM_MODE_FLAG_TUNNEL)); |
86 | 86 | ||
87 | err = 0; | 87 | err = 0; |
88 | 88 | ||
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c index af27c193697c..b702bd8a3893 100644 --- a/net/xfrm/xfrm_policy.c +++ b/net/xfrm/xfrm_policy.c | |||
@@ -49,8 +49,6 @@ static DEFINE_SPINLOCK(xfrm_policy_gc_lock); | |||
49 | 49 | ||
50 | static struct xfrm_policy_afinfo *xfrm_policy_get_afinfo(unsigned short family); | 50 | static struct xfrm_policy_afinfo *xfrm_policy_get_afinfo(unsigned short family); |
51 | static void xfrm_policy_put_afinfo(struct xfrm_policy_afinfo *afinfo); | 51 | static void xfrm_policy_put_afinfo(struct xfrm_policy_afinfo *afinfo); |
52 | static struct xfrm_policy_afinfo *xfrm_policy_lock_afinfo(unsigned int family); | ||
53 | static void xfrm_policy_unlock_afinfo(struct xfrm_policy_afinfo *afinfo); | ||
54 | 52 | ||
55 | static inline int | 53 | static inline int |
56 | __xfrm4_selector_match(struct xfrm_selector *sel, struct flowi *fl) | 54 | __xfrm4_selector_match(struct xfrm_selector *sel, struct flowi *fl) |
@@ -86,72 +84,6 @@ int xfrm_selector_match(struct xfrm_selector *sel, struct flowi *fl, | |||
86 | return 0; | 84 | return 0; |
87 | } | 85 | } |
88 | 86 | ||
89 | int xfrm_register_type(struct xfrm_type *type, unsigned short family) | ||
90 | { | ||
91 | struct xfrm_policy_afinfo *afinfo = xfrm_policy_lock_afinfo(family); | ||
92 | struct xfrm_type **typemap; | ||
93 | int err = 0; | ||
94 | |||
95 | if (unlikely(afinfo == NULL)) | ||
96 | return -EAFNOSUPPORT; | ||
97 | typemap = afinfo->type_map; | ||
98 | |||
99 | if (likely(typemap[type->proto] == NULL)) | ||
100 | typemap[type->proto] = type; | ||
101 | else | ||
102 | err = -EEXIST; | ||
103 | xfrm_policy_unlock_afinfo(afinfo); | ||
104 | return err; | ||
105 | } | ||
106 | EXPORT_SYMBOL(xfrm_register_type); | ||
107 | |||
108 | int xfrm_unregister_type(struct xfrm_type *type, unsigned short family) | ||
109 | { | ||
110 | struct xfrm_policy_afinfo *afinfo = xfrm_policy_lock_afinfo(family); | ||
111 | struct xfrm_type **typemap; | ||
112 | int err = 0; | ||
113 | |||
114 | if (unlikely(afinfo == NULL)) | ||
115 | return -EAFNOSUPPORT; | ||
116 | typemap = afinfo->type_map; | ||
117 | |||
118 | if (unlikely(typemap[type->proto] != type)) | ||
119 | err = -ENOENT; | ||
120 | else | ||
121 | typemap[type->proto] = NULL; | ||
122 | xfrm_policy_unlock_afinfo(afinfo); | ||
123 | return err; | ||
124 | } | ||
125 | EXPORT_SYMBOL(xfrm_unregister_type); | ||
126 | |||
127 | struct xfrm_type *xfrm_get_type(u8 proto, unsigned short family) | ||
128 | { | ||
129 | struct xfrm_policy_afinfo *afinfo; | ||
130 | struct xfrm_type **typemap; | ||
131 | struct xfrm_type *type; | ||
132 | int modload_attempted = 0; | ||
133 | |||
134 | retry: | ||
135 | afinfo = xfrm_policy_get_afinfo(family); | ||
136 | if (unlikely(afinfo == NULL)) | ||
137 | return NULL; | ||
138 | typemap = afinfo->type_map; | ||
139 | |||
140 | type = typemap[proto]; | ||
141 | if (unlikely(type && !try_module_get(type->owner))) | ||
142 | type = NULL; | ||
143 | if (!type && !modload_attempted) { | ||
144 | xfrm_policy_put_afinfo(afinfo); | ||
145 | request_module("xfrm-type-%d-%d", | ||
146 | (int) family, (int) proto); | ||
147 | modload_attempted = 1; | ||
148 | goto retry; | ||
149 | } | ||
150 | |||
151 | xfrm_policy_put_afinfo(afinfo); | ||
152 | return type; | ||
153 | } | ||
154 | |||
155 | int xfrm_dst_lookup(struct xfrm_dst **dst, struct flowi *fl, | 87 | int xfrm_dst_lookup(struct xfrm_dst **dst, struct flowi *fl, |
156 | unsigned short family) | 88 | unsigned short family) |
157 | { | 89 | { |
@@ -170,94 +102,6 @@ int xfrm_dst_lookup(struct xfrm_dst **dst, struct flowi *fl, | |||
170 | } | 102 | } |
171 | EXPORT_SYMBOL(xfrm_dst_lookup); | 103 | EXPORT_SYMBOL(xfrm_dst_lookup); |
172 | 104 | ||
173 | void xfrm_put_type(struct xfrm_type *type) | ||
174 | { | ||
175 | module_put(type->owner); | ||
176 | } | ||
177 | |||
178 | int xfrm_register_mode(struct xfrm_mode *mode, int family) | ||
179 | { | ||
180 | struct xfrm_policy_afinfo *afinfo; | ||
181 | struct xfrm_mode **modemap; | ||
182 | int err; | ||
183 | |||
184 | if (unlikely(mode->encap >= XFRM_MODE_MAX)) | ||
185 | return -EINVAL; | ||
186 | |||
187 | afinfo = xfrm_policy_lock_afinfo(family); | ||
188 | if (unlikely(afinfo == NULL)) | ||
189 | return -EAFNOSUPPORT; | ||
190 | |||
191 | err = -EEXIST; | ||
192 | modemap = afinfo->mode_map; | ||
193 | if (likely(modemap[mode->encap] == NULL)) { | ||
194 | modemap[mode->encap] = mode; | ||
195 | err = 0; | ||
196 | } | ||
197 | |||
198 | xfrm_policy_unlock_afinfo(afinfo); | ||
199 | return err; | ||
200 | } | ||
201 | EXPORT_SYMBOL(xfrm_register_mode); | ||
202 | |||
203 | int xfrm_unregister_mode(struct xfrm_mode *mode, int family) | ||
204 | { | ||
205 | struct xfrm_policy_afinfo *afinfo; | ||
206 | struct xfrm_mode **modemap; | ||
207 | int err; | ||
208 | |||
209 | if (unlikely(mode->encap >= XFRM_MODE_MAX)) | ||
210 | return -EINVAL; | ||
211 | |||
212 | afinfo = xfrm_policy_lock_afinfo(family); | ||
213 | if (unlikely(afinfo == NULL)) | ||
214 | return -EAFNOSUPPORT; | ||
215 | |||
216 | err = -ENOENT; | ||
217 | modemap = afinfo->mode_map; | ||
218 | if (likely(modemap[mode->encap] == mode)) { | ||
219 | modemap[mode->encap] = NULL; | ||
220 | err = 0; | ||
221 | } | ||
222 | |||
223 | xfrm_policy_unlock_afinfo(afinfo); | ||
224 | return err; | ||
225 | } | ||
226 | EXPORT_SYMBOL(xfrm_unregister_mode); | ||
227 | |||
228 | struct xfrm_mode *xfrm_get_mode(unsigned int encap, int family) | ||
229 | { | ||
230 | struct xfrm_policy_afinfo *afinfo; | ||
231 | struct xfrm_mode *mode; | ||
232 | int modload_attempted = 0; | ||
233 | |||
234 | if (unlikely(encap >= XFRM_MODE_MAX)) | ||
235 | return NULL; | ||
236 | |||
237 | retry: | ||
238 | afinfo = xfrm_policy_get_afinfo(family); | ||
239 | if (unlikely(afinfo == NULL)) | ||
240 | return NULL; | ||
241 | |||
242 | mode = afinfo->mode_map[encap]; | ||
243 | if (unlikely(mode && !try_module_get(mode->owner))) | ||
244 | mode = NULL; | ||
245 | if (!mode && !modload_attempted) { | ||
246 | xfrm_policy_put_afinfo(afinfo); | ||
247 | request_module("xfrm-mode-%d-%d", family, encap); | ||
248 | modload_attempted = 1; | ||
249 | goto retry; | ||
250 | } | ||
251 | |||
252 | xfrm_policy_put_afinfo(afinfo); | ||
253 | return mode; | ||
254 | } | ||
255 | |||
256 | void xfrm_put_mode(struct xfrm_mode *mode) | ||
257 | { | ||
258 | module_put(mode->owner); | ||
259 | } | ||
260 | |||
261 | static inline unsigned long make_jiffies(long secs) | 105 | static inline unsigned long make_jiffies(long secs) |
262 | { | 106 | { |
263 | if (secs >= (MAX_SCHEDULE_TIMEOUT-1)/HZ) | 107 | if (secs >= (MAX_SCHEDULE_TIMEOUT-1)/HZ) |
@@ -2096,7 +1940,8 @@ int xfrm_bundle_ok(struct xfrm_policy *pol, struct xfrm_dst *first, | |||
2096 | if (xdst->genid != dst->xfrm->genid) | 1940 | if (xdst->genid != dst->xfrm->genid) |
2097 | return 0; | 1941 | return 0; |
2098 | 1942 | ||
2099 | if (strict && fl && dst->xfrm->props.mode != XFRM_MODE_TUNNEL && | 1943 | if (strict && fl && |
1944 | !(dst->xfrm->outer_mode->flags & XFRM_MODE_FLAG_TUNNEL) && | ||
2100 | !xfrm_state_addr_flow_check(dst->xfrm, fl, family)) | 1945 | !xfrm_state_addr_flow_check(dst->xfrm, fl, family)) |
2101 | return 0; | 1946 | return 0; |
2102 | 1947 | ||
@@ -2213,23 +2058,6 @@ static void xfrm_policy_put_afinfo(struct xfrm_policy_afinfo *afinfo) | |||
2213 | read_unlock(&xfrm_policy_afinfo_lock); | 2058 | read_unlock(&xfrm_policy_afinfo_lock); |
2214 | } | 2059 | } |
2215 | 2060 | ||
2216 | static struct xfrm_policy_afinfo *xfrm_policy_lock_afinfo(unsigned int family) | ||
2217 | { | ||
2218 | struct xfrm_policy_afinfo *afinfo; | ||
2219 | if (unlikely(family >= NPROTO)) | ||
2220 | return NULL; | ||
2221 | write_lock_bh(&xfrm_policy_afinfo_lock); | ||
2222 | afinfo = xfrm_policy_afinfo[family]; | ||
2223 | if (unlikely(!afinfo)) | ||
2224 | write_unlock_bh(&xfrm_policy_afinfo_lock); | ||
2225 | return afinfo; | ||
2226 | } | ||
2227 | |||
2228 | static void xfrm_policy_unlock_afinfo(struct xfrm_policy_afinfo *afinfo) | ||
2229 | { | ||
2230 | write_unlock_bh(&xfrm_policy_afinfo_lock); | ||
2231 | } | ||
2232 | |||
2233 | static int xfrm_dev_event(struct notifier_block *this, unsigned long event, void *ptr) | 2061 | static int xfrm_dev_event(struct notifier_block *this, unsigned long event, void *ptr) |
2234 | { | 2062 | { |
2235 | struct net_device *dev = ptr; | 2063 | struct net_device *dev = ptr; |
@@ -2464,7 +2292,8 @@ static int xfrm_policy_migrate(struct xfrm_policy *pol, | |||
2464 | if (!migrate_tmpl_match(mp, &pol->xfrm_vec[i])) | 2292 | if (!migrate_tmpl_match(mp, &pol->xfrm_vec[i])) |
2465 | continue; | 2293 | continue; |
2466 | n++; | 2294 | n++; |
2467 | if (pol->xfrm_vec[i].mode != XFRM_MODE_TUNNEL) | 2295 | if (pol->xfrm_vec[i].mode != XFRM_MODE_TUNNEL && |
2296 | pol->xfrm_vec[i].mode != XFRM_MODE_BEET) | ||
2468 | continue; | 2297 | continue; |
2469 | /* update endpoints */ | 2298 | /* update endpoints */ |
2470 | memcpy(&pol->xfrm_vec[i].id.daddr, &mp->new_daddr, | 2299 | memcpy(&pol->xfrm_vec[i].id.daddr, &mp->new_daddr, |
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c index 344f0a6abec5..224b44e31a07 100644 --- a/net/xfrm/xfrm_state.c +++ b/net/xfrm/xfrm_state.c | |||
@@ -57,6 +57,9 @@ static unsigned int xfrm_state_hashmax __read_mostly = 1 * 1024 * 1024; | |||
57 | static unsigned int xfrm_state_num; | 57 | static unsigned int xfrm_state_num; |
58 | static unsigned int xfrm_state_genid; | 58 | static unsigned int xfrm_state_genid; |
59 | 59 | ||
60 | static struct xfrm_state_afinfo *xfrm_state_get_afinfo(unsigned int family); | ||
61 | static void xfrm_state_put_afinfo(struct xfrm_state_afinfo *afinfo); | ||
62 | |||
60 | static inline unsigned int xfrm_dst_hash(xfrm_address_t *daddr, | 63 | static inline unsigned int xfrm_dst_hash(xfrm_address_t *daddr, |
61 | xfrm_address_t *saddr, | 64 | xfrm_address_t *saddr, |
62 | u32 reqid, | 65 | u32 reqid, |
@@ -187,6 +190,184 @@ int __xfrm_state_delete(struct xfrm_state *x); | |||
187 | int km_query(struct xfrm_state *x, struct xfrm_tmpl *t, struct xfrm_policy *pol); | 190 | int km_query(struct xfrm_state *x, struct xfrm_tmpl *t, struct xfrm_policy *pol); |
188 | void km_state_expired(struct xfrm_state *x, int hard, u32 pid); | 191 | void km_state_expired(struct xfrm_state *x, int hard, u32 pid); |
189 | 192 | ||
193 | static struct xfrm_state_afinfo *xfrm_state_lock_afinfo(unsigned int family) | ||
194 | { | ||
195 | struct xfrm_state_afinfo *afinfo; | ||
196 | if (unlikely(family >= NPROTO)) | ||
197 | return NULL; | ||
198 | write_lock_bh(&xfrm_state_afinfo_lock); | ||
199 | afinfo = xfrm_state_afinfo[family]; | ||
200 | if (unlikely(!afinfo)) | ||
201 | write_unlock_bh(&xfrm_state_afinfo_lock); | ||
202 | return afinfo; | ||
203 | } | ||
204 | |||
205 | static void xfrm_state_unlock_afinfo(struct xfrm_state_afinfo *afinfo) | ||
206 | { | ||
207 | write_unlock_bh(&xfrm_state_afinfo_lock); | ||
208 | } | ||
209 | |||
210 | int xfrm_register_type(struct xfrm_type *type, unsigned short family) | ||
211 | { | ||
212 | struct xfrm_state_afinfo *afinfo = xfrm_state_lock_afinfo(family); | ||
213 | struct xfrm_type **typemap; | ||
214 | int err = 0; | ||
215 | |||
216 | if (unlikely(afinfo == NULL)) | ||
217 | return -EAFNOSUPPORT; | ||
218 | typemap = afinfo->type_map; | ||
219 | |||
220 | if (likely(typemap[type->proto] == NULL)) | ||
221 | typemap[type->proto] = type; | ||
222 | else | ||
223 | err = -EEXIST; | ||
224 | xfrm_state_unlock_afinfo(afinfo); | ||
225 | return err; | ||
226 | } | ||
227 | EXPORT_SYMBOL(xfrm_register_type); | ||
228 | |||
229 | int xfrm_unregister_type(struct xfrm_type *type, unsigned short family) | ||
230 | { | ||
231 | struct xfrm_state_afinfo *afinfo = xfrm_state_lock_afinfo(family); | ||
232 | struct xfrm_type **typemap; | ||
233 | int err = 0; | ||
234 | |||
235 | if (unlikely(afinfo == NULL)) | ||
236 | return -EAFNOSUPPORT; | ||
237 | typemap = afinfo->type_map; | ||
238 | |||
239 | if (unlikely(typemap[type->proto] != type)) | ||
240 | err = -ENOENT; | ||
241 | else | ||
242 | typemap[type->proto] = NULL; | ||
243 | xfrm_state_unlock_afinfo(afinfo); | ||
244 | return err; | ||
245 | } | ||
246 | EXPORT_SYMBOL(xfrm_unregister_type); | ||
247 | |||
248 | static struct xfrm_type *xfrm_get_type(u8 proto, unsigned short family) | ||
249 | { | ||
250 | struct xfrm_state_afinfo *afinfo; | ||
251 | struct xfrm_type **typemap; | ||
252 | struct xfrm_type *type; | ||
253 | int modload_attempted = 0; | ||
254 | |||
255 | retry: | ||
256 | afinfo = xfrm_state_get_afinfo(family); | ||
257 | if (unlikely(afinfo == NULL)) | ||
258 | return NULL; | ||
259 | typemap = afinfo->type_map; | ||
260 | |||
261 | type = typemap[proto]; | ||
262 | if (unlikely(type && !try_module_get(type->owner))) | ||
263 | type = NULL; | ||
264 | if (!type && !modload_attempted) { | ||
265 | xfrm_state_put_afinfo(afinfo); | ||
266 | request_module("xfrm-type-%d-%d", family, proto); | ||
267 | modload_attempted = 1; | ||
268 | goto retry; | ||
269 | } | ||
270 | |||
271 | xfrm_state_put_afinfo(afinfo); | ||
272 | return type; | ||
273 | } | ||
274 | |||
275 | static void xfrm_put_type(struct xfrm_type *type) | ||
276 | { | ||
277 | module_put(type->owner); | ||
278 | } | ||
279 | |||
280 | int xfrm_register_mode(struct xfrm_mode *mode, int family) | ||
281 | { | ||
282 | struct xfrm_state_afinfo *afinfo; | ||
283 | struct xfrm_mode **modemap; | ||
284 | int err; | ||
285 | |||
286 | if (unlikely(mode->encap >= XFRM_MODE_MAX)) | ||
287 | return -EINVAL; | ||
288 | |||
289 | afinfo = xfrm_state_lock_afinfo(family); | ||
290 | if (unlikely(afinfo == NULL)) | ||
291 | return -EAFNOSUPPORT; | ||
292 | |||
293 | err = -EEXIST; | ||
294 | modemap = afinfo->mode_map; | ||
295 | if (modemap[mode->encap]) | ||
296 | goto out; | ||
297 | |||
298 | err = -ENOENT; | ||
299 | if (!try_module_get(afinfo->owner)) | ||
300 | goto out; | ||
301 | |||
302 | mode->afinfo = afinfo; | ||
303 | modemap[mode->encap] = mode; | ||
304 | err = 0; | ||
305 | |||
306 | out: | ||
307 | xfrm_state_unlock_afinfo(afinfo); | ||
308 | return err; | ||
309 | } | ||
310 | EXPORT_SYMBOL(xfrm_register_mode); | ||
311 | |||
312 | int xfrm_unregister_mode(struct xfrm_mode *mode, int family) | ||
313 | { | ||
314 | struct xfrm_state_afinfo *afinfo; | ||
315 | struct xfrm_mode **modemap; | ||
316 | int err; | ||
317 | |||
318 | if (unlikely(mode->encap >= XFRM_MODE_MAX)) | ||
319 | return -EINVAL; | ||
320 | |||
321 | afinfo = xfrm_state_lock_afinfo(family); | ||
322 | if (unlikely(afinfo == NULL)) | ||
323 | return -EAFNOSUPPORT; | ||
324 | |||
325 | err = -ENOENT; | ||
326 | modemap = afinfo->mode_map; | ||
327 | if (likely(modemap[mode->encap] == mode)) { | ||
328 | modemap[mode->encap] = NULL; | ||
329 | module_put(mode->afinfo->owner); | ||
330 | err = 0; | ||
331 | } | ||
332 | |||
333 | xfrm_state_unlock_afinfo(afinfo); | ||
334 | return err; | ||
335 | } | ||
336 | EXPORT_SYMBOL(xfrm_unregister_mode); | ||
337 | |||
338 | static struct xfrm_mode *xfrm_get_mode(unsigned int encap, int family) | ||
339 | { | ||
340 | struct xfrm_state_afinfo *afinfo; | ||
341 | struct xfrm_mode *mode; | ||
342 | int modload_attempted = 0; | ||
343 | |||
344 | if (unlikely(encap >= XFRM_MODE_MAX)) | ||
345 | return NULL; | ||
346 | |||
347 | retry: | ||
348 | afinfo = xfrm_state_get_afinfo(family); | ||
349 | if (unlikely(afinfo == NULL)) | ||
350 | return NULL; | ||
351 | |||
352 | mode = afinfo->mode_map[encap]; | ||
353 | if (unlikely(mode && !try_module_get(mode->owner))) | ||
354 | mode = NULL; | ||
355 | if (!mode && !modload_attempted) { | ||
356 | xfrm_state_put_afinfo(afinfo); | ||
357 | request_module("xfrm-mode-%d-%d", family, encap); | ||
358 | modload_attempted = 1; | ||
359 | goto retry; | ||
360 | } | ||
361 | |||
362 | xfrm_state_put_afinfo(afinfo); | ||
363 | return mode; | ||
364 | } | ||
365 | |||
366 | static void xfrm_put_mode(struct xfrm_mode *mode) | ||
367 | { | ||
368 | module_put(mode->owner); | ||
369 | } | ||
370 | |||
190 | static void xfrm_state_gc_destroy(struct xfrm_state *x) | 371 | static void xfrm_state_gc_destroy(struct xfrm_state *x) |
191 | { | 372 | { |
192 | del_timer_sync(&x->timer); | 373 | del_timer_sync(&x->timer); |
@@ -196,8 +377,10 @@ static void xfrm_state_gc_destroy(struct xfrm_state *x) | |||
196 | kfree(x->calg); | 377 | kfree(x->calg); |
197 | kfree(x->encap); | 378 | kfree(x->encap); |
198 | kfree(x->coaddr); | 379 | kfree(x->coaddr); |
199 | if (x->mode) | 380 | if (x->inner_mode) |
200 | xfrm_put_mode(x->mode); | 381 | xfrm_put_mode(x->inner_mode); |
382 | if (x->outer_mode) | ||
383 | xfrm_put_mode(x->outer_mode); | ||
201 | if (x->type) { | 384 | if (x->type) { |
202 | x->type->destructor(x); | 385 | x->type->destructor(x); |
203 | xfrm_put_type(x->type); | 386 | xfrm_put_type(x->type); |
@@ -1699,7 +1882,7 @@ int xfrm_state_unregister_afinfo(struct xfrm_state_afinfo *afinfo) | |||
1699 | } | 1882 | } |
1700 | EXPORT_SYMBOL(xfrm_state_unregister_afinfo); | 1883 | EXPORT_SYMBOL(xfrm_state_unregister_afinfo); |
1701 | 1884 | ||
1702 | struct xfrm_state_afinfo *xfrm_state_get_afinfo(unsigned short family) | 1885 | static struct xfrm_state_afinfo *xfrm_state_get_afinfo(unsigned int family) |
1703 | { | 1886 | { |
1704 | struct xfrm_state_afinfo *afinfo; | 1887 | struct xfrm_state_afinfo *afinfo; |
1705 | if (unlikely(family >= NPROTO)) | 1888 | if (unlikely(family >= NPROTO)) |
@@ -1711,14 +1894,11 @@ struct xfrm_state_afinfo *xfrm_state_get_afinfo(unsigned short family) | |||
1711 | return afinfo; | 1894 | return afinfo; |
1712 | } | 1895 | } |
1713 | 1896 | ||
1714 | void xfrm_state_put_afinfo(struct xfrm_state_afinfo *afinfo) | 1897 | static void xfrm_state_put_afinfo(struct xfrm_state_afinfo *afinfo) |
1715 | { | 1898 | { |
1716 | read_unlock(&xfrm_state_afinfo_lock); | 1899 | read_unlock(&xfrm_state_afinfo_lock); |
1717 | } | 1900 | } |
1718 | 1901 | ||
1719 | EXPORT_SYMBOL(xfrm_state_get_afinfo); | ||
1720 | EXPORT_SYMBOL(xfrm_state_put_afinfo); | ||
1721 | |||
1722 | /* Temporarily located here until net/xfrm/xfrm_tunnel.c is created */ | 1902 | /* Temporarily located here until net/xfrm/xfrm_tunnel.c is created */ |
1723 | void xfrm_state_delete_tunnel(struct xfrm_state *x) | 1903 | void xfrm_state_delete_tunnel(struct xfrm_state *x) |
1724 | { | 1904 | { |
@@ -1769,6 +1949,14 @@ int xfrm_init_state(struct xfrm_state *x) | |||
1769 | goto error; | 1949 | goto error; |
1770 | 1950 | ||
1771 | err = -EPROTONOSUPPORT; | 1951 | err = -EPROTONOSUPPORT; |
1952 | x->inner_mode = xfrm_get_mode(x->props.mode, x->sel.family); | ||
1953 | if (x->inner_mode == NULL) | ||
1954 | goto error; | ||
1955 | |||
1956 | if (!(x->inner_mode->flags & XFRM_MODE_FLAG_TUNNEL) && | ||
1957 | family != x->sel.family) | ||
1958 | goto error; | ||
1959 | |||
1772 | x->type = xfrm_get_type(x->id.proto, family); | 1960 | x->type = xfrm_get_type(x->id.proto, family); |
1773 | if (x->type == NULL) | 1961 | if (x->type == NULL) |
1774 | goto error; | 1962 | goto error; |
@@ -1777,8 +1965,8 @@ int xfrm_init_state(struct xfrm_state *x) | |||
1777 | if (err) | 1965 | if (err) |
1778 | goto error; | 1966 | goto error; |
1779 | 1967 | ||
1780 | x->mode = xfrm_get_mode(x->props.mode, family); | 1968 | x->outer_mode = xfrm_get_mode(x->props.mode, family); |
1781 | if (x->mode == NULL) | 1969 | if (x->outer_mode == NULL) |
1782 | goto error; | 1970 | goto error; |
1783 | 1971 | ||
1784 | x->km.state = XFRM_STATE_VALID; | 1972 | x->km.state = XFRM_STATE_VALID; |