diff options
author | Jeff Garzik <jgarzik@pobox.com> | 2005-11-05 15:39:24 -0500 |
---|---|---|
committer | Jeff Garzik <jgarzik@pobox.com> | 2005-11-05 15:39:24 -0500 |
commit | 7211bb9b64f17b23834d91fc3d0c1d78671ee9a8 (patch) | |
tree | 541909f86c31fee97cd70d28ec2fe5c23e1ceb02 /net | |
parent | f1e691a24955ea987f021f378324fb5003b1b208 (diff) | |
parent | 70d9d825e0a5a78ec1dacaaaf5c72ff5b0206fab (diff) |
Merge branch 'master'
Diffstat (limited to 'net')
40 files changed, 1025 insertions, 609 deletions
diff --git a/net/bluetooth/af_bluetooth.c b/net/bluetooth/af_bluetooth.c index 12b43345b54f..03532062a46a 100644 --- a/net/bluetooth/af_bluetooth.c +++ b/net/bluetooth/af_bluetooth.c | |||
@@ -308,12 +308,6 @@ static struct net_proto_family bt_sock_family_ops = { | |||
308 | .create = bt_sock_create, | 308 | .create = bt_sock_create, |
309 | }; | 309 | }; |
310 | 310 | ||
311 | extern int hci_sock_init(void); | ||
312 | extern int hci_sock_cleanup(void); | ||
313 | |||
314 | extern int bt_sysfs_init(void); | ||
315 | extern int bt_sysfs_cleanup(void); | ||
316 | |||
317 | static int __init bt_init(void) | 311 | static int __init bt_init(void) |
318 | { | 312 | { |
319 | BT_INFO("Core ver %s", VERSION); | 313 | BT_INFO("Core ver %s", VERSION); |
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index 55dc42eac92c..cf0df1c8c933 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c | |||
@@ -87,7 +87,7 @@ int hci_unregister_notifier(struct notifier_block *nb) | |||
87 | return notifier_chain_unregister(&hci_notifier, nb); | 87 | return notifier_chain_unregister(&hci_notifier, nb); |
88 | } | 88 | } |
89 | 89 | ||
90 | void hci_notify(struct hci_dev *hdev, int event) | 90 | static void hci_notify(struct hci_dev *hdev, int event) |
91 | { | 91 | { |
92 | notifier_call_chain(&hci_notifier, event, hdev); | 92 | notifier_call_chain(&hci_notifier, event, hdev); |
93 | } | 93 | } |
@@ -1347,7 +1347,7 @@ static inline void hci_scodata_packet(struct hci_dev *hdev, struct sk_buff *skb) | |||
1347 | kfree_skb(skb); | 1347 | kfree_skb(skb); |
1348 | } | 1348 | } |
1349 | 1349 | ||
1350 | void hci_rx_task(unsigned long arg) | 1350 | static void hci_rx_task(unsigned long arg) |
1351 | { | 1351 | { |
1352 | struct hci_dev *hdev = (struct hci_dev *) arg; | 1352 | struct hci_dev *hdev = (struct hci_dev *) arg; |
1353 | struct sk_buff *skb; | 1353 | struct sk_buff *skb; |
diff --git a/net/bluetooth/hci_sock.c b/net/bluetooth/hci_sock.c index 32ef7975a139..799e448750ad 100644 --- a/net/bluetooth/hci_sock.c +++ b/net/bluetooth/hci_sock.c | |||
@@ -66,20 +66,20 @@ static struct hci_sec_filter hci_sec_filter = { | |||
66 | /* Packet types */ | 66 | /* Packet types */ |
67 | 0x10, | 67 | 0x10, |
68 | /* Events */ | 68 | /* Events */ |
69 | { 0x1000d9fe, 0x0000300c }, | 69 | { 0x1000d9fe, 0x0000b00c }, |
70 | /* Commands */ | 70 | /* Commands */ |
71 | { | 71 | { |
72 | { 0x0 }, | 72 | { 0x0 }, |
73 | /* OGF_LINK_CTL */ | 73 | /* OGF_LINK_CTL */ |
74 | { 0xbe000006, 0x00000001, 0x0000, 0x00 }, | 74 | { 0xbe000006, 0x00000001, 0x000000, 0x00 }, |
75 | /* OGF_LINK_POLICY */ | 75 | /* OGF_LINK_POLICY */ |
76 | { 0x00005200, 0x00000000, 0x0000, 0x00 }, | 76 | { 0x00005200, 0x00000000, 0x000000, 0x00 }, |
77 | /* OGF_HOST_CTL */ | 77 | /* OGF_HOST_CTL */ |
78 | { 0xaab00200, 0x2b402aaa, 0x0154, 0x00 }, | 78 | { 0xaab00200, 0x2b402aaa, 0x020154, 0x00 }, |
79 | /* OGF_INFO_PARAM */ | 79 | /* OGF_INFO_PARAM */ |
80 | { 0x000002be, 0x00000000, 0x0000, 0x00 }, | 80 | { 0x000002be, 0x00000000, 0x000000, 0x00 }, |
81 | /* OGF_STATUS_PARAM */ | 81 | /* OGF_STATUS_PARAM */ |
82 | { 0x000000ea, 0x00000000, 0x0000, 0x00 } | 82 | { 0x000000ea, 0x00000000, 0x000000, 0x00 } |
83 | } | 83 | } |
84 | }; | 84 | }; |
85 | 85 | ||
diff --git a/net/bluetooth/hidp/Kconfig b/net/bluetooth/hidp/Kconfig index 4e958f7d9418..edfea772fb67 100644 --- a/net/bluetooth/hidp/Kconfig +++ b/net/bluetooth/hidp/Kconfig | |||
@@ -1,6 +1,6 @@ | |||
1 | config BT_HIDP | 1 | config BT_HIDP |
2 | tristate "HIDP protocol support" | 2 | tristate "HIDP protocol support" |
3 | depends on BT && BT_L2CAP | 3 | depends on BT && BT_L2CAP && (BROKEN || !S390) |
4 | select INPUT | 4 | select INPUT |
5 | help | 5 | help |
6 | HIDP (Human Interface Device Protocol) is a transport layer | 6 | HIDP (Human Interface Device Protocol) is a transport layer |
diff --git a/net/bluetooth/hidp/core.c b/net/bluetooth/hidp/core.c index de8af5f42394..860444a7fc0f 100644 --- a/net/bluetooth/hidp/core.c +++ b/net/bluetooth/hidp/core.c | |||
@@ -520,7 +520,7 @@ static int hidp_session(void *arg) | |||
520 | 520 | ||
521 | if (session->input) { | 521 | if (session->input) { |
522 | input_unregister_device(session->input); | 522 | input_unregister_device(session->input); |
523 | kfree(session->input); | 523 | session->input = NULL; |
524 | } | 524 | } |
525 | 525 | ||
526 | up_write(&hidp_session_sem); | 526 | up_write(&hidp_session_sem); |
@@ -536,6 +536,8 @@ static inline void hidp_setup_input(struct hidp_session *session, struct hidp_co | |||
536 | 536 | ||
537 | input->private = session; | 537 | input->private = session; |
538 | 538 | ||
539 | input->name = "Bluetooth HID Boot Protocol Device"; | ||
540 | |||
539 | input->id.bustype = BUS_BLUETOOTH; | 541 | input->id.bustype = BUS_BLUETOOTH; |
540 | input->id.vendor = req->vendor; | 542 | input->id.vendor = req->vendor; |
541 | input->id.product = req->product; | 543 | input->id.product = req->product; |
@@ -582,16 +584,15 @@ int hidp_add_connection(struct hidp_connadd_req *req, struct socket *ctrl_sock, | |||
582 | return -ENOTUNIQ; | 584 | return -ENOTUNIQ; |
583 | 585 | ||
584 | session = kmalloc(sizeof(struct hidp_session), GFP_KERNEL); | 586 | session = kmalloc(sizeof(struct hidp_session), GFP_KERNEL); |
585 | if (!session) | 587 | if (!session) |
586 | return -ENOMEM; | 588 | return -ENOMEM; |
587 | memset(session, 0, sizeof(struct hidp_session)); | 589 | memset(session, 0, sizeof(struct hidp_session)); |
588 | 590 | ||
589 | session->input = kmalloc(sizeof(struct input_dev), GFP_KERNEL); | 591 | session->input = input_allocate_device(); |
590 | if (!session->input) { | 592 | if (!session->input) { |
591 | kfree(session); | 593 | kfree(session); |
592 | return -ENOMEM; | 594 | return -ENOMEM; |
593 | } | 595 | } |
594 | memset(session->input, 0, sizeof(struct input_dev)); | ||
595 | 596 | ||
596 | down_write(&hidp_session_sem); | 597 | down_write(&hidp_session_sem); |
597 | 598 | ||
@@ -651,8 +652,10 @@ unlink: | |||
651 | 652 | ||
652 | __hidp_unlink_session(session); | 653 | __hidp_unlink_session(session); |
653 | 654 | ||
654 | if (session->input) | 655 | if (session->input) { |
655 | input_unregister_device(session->input); | 656 | input_unregister_device(session->input); |
657 | session->input = NULL; /* don't try to free it here */ | ||
658 | } | ||
656 | 659 | ||
657 | failed: | 660 | failed: |
658 | up_write(&hidp_session_sem); | 661 | up_write(&hidp_session_sem); |
diff --git a/net/bluetooth/rfcomm/Makefile b/net/bluetooth/rfcomm/Makefile index aecec45ec68d..fe07988a3705 100644 --- a/net/bluetooth/rfcomm/Makefile +++ b/net/bluetooth/rfcomm/Makefile | |||
@@ -4,5 +4,5 @@ | |||
4 | 4 | ||
5 | obj-$(CONFIG_BT_RFCOMM) += rfcomm.o | 5 | obj-$(CONFIG_BT_RFCOMM) += rfcomm.o |
6 | 6 | ||
7 | rfcomm-y := core.o sock.o crc.o | 7 | rfcomm-y := core.o sock.o |
8 | rfcomm-$(CONFIG_BT_RFCOMM_TTY) += tty.o | 8 | rfcomm-$(CONFIG_BT_RFCOMM_TTY) += tty.o |
diff --git a/net/bluetooth/rfcomm/core.c b/net/bluetooth/rfcomm/core.c index 35adce6482b6..c3d56ead840c 100644 --- a/net/bluetooth/rfcomm/core.c +++ b/net/bluetooth/rfcomm/core.c | |||
@@ -133,6 +133,49 @@ static inline void rfcomm_session_put(struct rfcomm_session *s) | |||
133 | 133 | ||
134 | /* ---- RFCOMM FCS computation ---- */ | 134 | /* ---- RFCOMM FCS computation ---- */ |
135 | 135 | ||
136 | /* reversed, 8-bit, poly=0x07 */ | ||
137 | static unsigned char rfcomm_crc_table[256] = { | ||
138 | 0x00, 0x91, 0xe3, 0x72, 0x07, 0x96, 0xe4, 0x75, | ||
139 | 0x0e, 0x9f, 0xed, 0x7c, 0x09, 0x98, 0xea, 0x7b, | ||
140 | 0x1c, 0x8d, 0xff, 0x6e, 0x1b, 0x8a, 0xf8, 0x69, | ||
141 | 0x12, 0x83, 0xf1, 0x60, 0x15, 0x84, 0xf6, 0x67, | ||
142 | |||
143 | 0x38, 0xa9, 0xdb, 0x4a, 0x3f, 0xae, 0xdc, 0x4d, | ||
144 | 0x36, 0xa7, 0xd5, 0x44, 0x31, 0xa0, 0xd2, 0x43, | ||
145 | 0x24, 0xb5, 0xc7, 0x56, 0x23, 0xb2, 0xc0, 0x51, | ||
146 | 0x2a, 0xbb, 0xc9, 0x58, 0x2d, 0xbc, 0xce, 0x5f, | ||
147 | |||
148 | 0x70, 0xe1, 0x93, 0x02, 0x77, 0xe6, 0x94, 0x05, | ||
149 | 0x7e, 0xef, 0x9d, 0x0c, 0x79, 0xe8, 0x9a, 0x0b, | ||
150 | 0x6c, 0xfd, 0x8f, 0x1e, 0x6b, 0xfa, 0x88, 0x19, | ||
151 | 0x62, 0xf3, 0x81, 0x10, 0x65, 0xf4, 0x86, 0x17, | ||
152 | |||
153 | 0x48, 0xd9, 0xab, 0x3a, 0x4f, 0xde, 0xac, 0x3d, | ||
154 | 0x46, 0xd7, 0xa5, 0x34, 0x41, 0xd0, 0xa2, 0x33, | ||
155 | 0x54, 0xc5, 0xb7, 0x26, 0x53, 0xc2, 0xb0, 0x21, | ||
156 | 0x5a, 0xcb, 0xb9, 0x28, 0x5d, 0xcc, 0xbe, 0x2f, | ||
157 | |||
158 | 0xe0, 0x71, 0x03, 0x92, 0xe7, 0x76, 0x04, 0x95, | ||
159 | 0xee, 0x7f, 0x0d, 0x9c, 0xe9, 0x78, 0x0a, 0x9b, | ||
160 | 0xfc, 0x6d, 0x1f, 0x8e, 0xfb, 0x6a, 0x18, 0x89, | ||
161 | 0xf2, 0x63, 0x11, 0x80, 0xf5, 0x64, 0x16, 0x87, | ||
162 | |||
163 | 0xd8, 0x49, 0x3b, 0xaa, 0xdf, 0x4e, 0x3c, 0xad, | ||
164 | 0xd6, 0x47, 0x35, 0xa4, 0xd1, 0x40, 0x32, 0xa3, | ||
165 | 0xc4, 0x55, 0x27, 0xb6, 0xc3, 0x52, 0x20, 0xb1, | ||
166 | 0xca, 0x5b, 0x29, 0xb8, 0xcd, 0x5c, 0x2e, 0xbf, | ||
167 | |||
168 | 0x90, 0x01, 0x73, 0xe2, 0x97, 0x06, 0x74, 0xe5, | ||
169 | 0x9e, 0x0f, 0x7d, 0xec, 0x99, 0x08, 0x7a, 0xeb, | ||
170 | 0x8c, 0x1d, 0x6f, 0xfe, 0x8b, 0x1a, 0x68, 0xf9, | ||
171 | 0x82, 0x13, 0x61, 0xf0, 0x85, 0x14, 0x66, 0xf7, | ||
172 | |||
173 | 0xa8, 0x39, 0x4b, 0xda, 0xaf, 0x3e, 0x4c, 0xdd, | ||
174 | 0xa6, 0x37, 0x45, 0xd4, 0xa1, 0x30, 0x42, 0xd3, | ||
175 | 0xb4, 0x25, 0x57, 0xc6, 0xb3, 0x22, 0x50, 0xc1, | ||
176 | 0xba, 0x2b, 0x59, 0xc8, 0xbd, 0x2c, 0x5e, 0xcf | ||
177 | }; | ||
178 | |||
136 | /* CRC on 2 bytes */ | 179 | /* CRC on 2 bytes */ |
137 | #define __crc(data) (rfcomm_crc_table[rfcomm_crc_table[0xff ^ data[0]] ^ data[1]]) | 180 | #define __crc(data) (rfcomm_crc_table[rfcomm_crc_table[0xff ^ data[0]] ^ data[1]]) |
138 | 181 | ||
diff --git a/net/bluetooth/rfcomm/crc.c b/net/bluetooth/rfcomm/crc.c deleted file mode 100644 index 1011bc4a8692..000000000000 --- a/net/bluetooth/rfcomm/crc.c +++ /dev/null | |||
@@ -1,71 +0,0 @@ | |||
1 | /* | ||
2 | RFCOMM implementation for Linux Bluetooth stack (BlueZ). | ||
3 | Copyright (C) 2002 Maxim Krasnyansky <maxk@qualcomm.com> | ||
4 | Copyright (C) 2002 Marcel Holtmann <marcel@holtmann.org> | ||
5 | |||
6 | This program is free software; you can redistribute it and/or modify | ||
7 | it under the terms of the GNU General Public License version 2 as | ||
8 | published by the Free Software Foundation; | ||
9 | |||
10 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS | ||
11 | OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
12 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. | ||
13 | IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY | ||
14 | CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES | ||
15 | WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
16 | ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
17 | OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
18 | |||
19 | ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS, | ||
20 | COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS | ||
21 | SOFTWARE IS DISCLAIMED. | ||
22 | */ | ||
23 | |||
24 | /* | ||
25 | * RFCOMM FCS calculation. | ||
26 | * | ||
27 | * $Id: crc.c,v 1.2 2002/09/21 09:54:32 holtmann Exp $ | ||
28 | */ | ||
29 | |||
30 | /* reversed, 8-bit, poly=0x07 */ | ||
31 | unsigned char rfcomm_crc_table[256] = { | ||
32 | 0x00, 0x91, 0xe3, 0x72, 0x07, 0x96, 0xe4, 0x75, | ||
33 | 0x0e, 0x9f, 0xed, 0x7c, 0x09, 0x98, 0xea, 0x7b, | ||
34 | 0x1c, 0x8d, 0xff, 0x6e, 0x1b, 0x8a, 0xf8, 0x69, | ||
35 | 0x12, 0x83, 0xf1, 0x60, 0x15, 0x84, 0xf6, 0x67, | ||
36 | |||
37 | 0x38, 0xa9, 0xdb, 0x4a, 0x3f, 0xae, 0xdc, 0x4d, | ||
38 | 0x36, 0xa7, 0xd5, 0x44, 0x31, 0xa0, 0xd2, 0x43, | ||
39 | 0x24, 0xb5, 0xc7, 0x56, 0x23, 0xb2, 0xc0, 0x51, | ||
40 | 0x2a, 0xbb, 0xc9, 0x58, 0x2d, 0xbc, 0xce, 0x5f, | ||
41 | |||
42 | 0x70, 0xe1, 0x93, 0x02, 0x77, 0xe6, 0x94, 0x05, | ||
43 | 0x7e, 0xef, 0x9d, 0x0c, 0x79, 0xe8, 0x9a, 0x0b, | ||
44 | 0x6c, 0xfd, 0x8f, 0x1e, 0x6b, 0xfa, 0x88, 0x19, | ||
45 | 0x62, 0xf3, 0x81, 0x10, 0x65, 0xf4, 0x86, 0x17, | ||
46 | |||
47 | 0x48, 0xd9, 0xab, 0x3a, 0x4f, 0xde, 0xac, 0x3d, | ||
48 | 0x46, 0xd7, 0xa5, 0x34, 0x41, 0xd0, 0xa2, 0x33, | ||
49 | 0x54, 0xc5, 0xb7, 0x26, 0x53, 0xc2, 0xb0, 0x21, | ||
50 | 0x5a, 0xcb, 0xb9, 0x28, 0x5d, 0xcc, 0xbe, 0x2f, | ||
51 | |||
52 | 0xe0, 0x71, 0x03, 0x92, 0xe7, 0x76, 0x04, 0x95, | ||
53 | 0xee, 0x7f, 0x0d, 0x9c, 0xe9, 0x78, 0x0a, 0x9b, | ||
54 | 0xfc, 0x6d, 0x1f, 0x8e, 0xfb, 0x6a, 0x18, 0x89, | ||
55 | 0xf2, 0x63, 0x11, 0x80, 0xf5, 0x64, 0x16, 0x87, | ||
56 | |||
57 | 0xd8, 0x49, 0x3b, 0xaa, 0xdf, 0x4e, 0x3c, 0xad, | ||
58 | 0xd6, 0x47, 0x35, 0xa4, 0xd1, 0x40, 0x32, 0xa3, | ||
59 | 0xc4, 0x55, 0x27, 0xb6, 0xc3, 0x52, 0x20, 0xb1, | ||
60 | 0xca, 0x5b, 0x29, 0xb8, 0xcd, 0x5c, 0x2e, 0xbf, | ||
61 | |||
62 | 0x90, 0x01, 0x73, 0xe2, 0x97, 0x06, 0x74, 0xe5, | ||
63 | 0x9e, 0x0f, 0x7d, 0xec, 0x99, 0x08, 0x7a, 0xeb, | ||
64 | 0x8c, 0x1d, 0x6f, 0xfe, 0x8b, 0x1a, 0x68, 0xf9, | ||
65 | 0x82, 0x13, 0x61, 0xf0, 0x85, 0x14, 0x66, 0xf7, | ||
66 | |||
67 | 0xa8, 0x39, 0x4b, 0xda, 0xaf, 0x3e, 0x4c, 0xdd, | ||
68 | 0xa6, 0x37, 0x45, 0xd4, 0xa1, 0x30, 0x42, 0xd3, | ||
69 | 0xb4, 0x25, 0x57, 0xc6, 0xb3, 0x22, 0x50, 0xc1, | ||
70 | 0xba, 0x2b, 0x59, 0xc8, 0xbd, 0x2c, 0x5e, 0xcf | ||
71 | }; | ||
diff --git a/net/bridge/br_fdb.c b/net/bridge/br_fdb.c index 24396b914d11..1f08a59b51ea 100644 --- a/net/bridge/br_fdb.c +++ b/net/bridge/br_fdb.c | |||
@@ -86,8 +86,8 @@ void br_fdb_changeaddr(struct net_bridge_port *p, const unsigned char *newaddr) | |||
86 | struct net_bridge_port *op; | 86 | struct net_bridge_port *op; |
87 | list_for_each_entry(op, &br->port_list, list) { | 87 | list_for_each_entry(op, &br->port_list, list) { |
88 | if (op != p && | 88 | if (op != p && |
89 | !memcmp(op->dev->dev_addr, | 89 | !compare_ether_addr(op->dev->dev_addr, |
90 | f->addr.addr, ETH_ALEN)) { | 90 | f->addr.addr)) { |
91 | f->dst = op; | 91 | f->dst = op; |
92 | goto insert; | 92 | goto insert; |
93 | } | 93 | } |
@@ -151,8 +151,8 @@ void br_fdb_delete_by_port(struct net_bridge *br, struct net_bridge_port *p) | |||
151 | struct net_bridge_port *op; | 151 | struct net_bridge_port *op; |
152 | list_for_each_entry(op, &br->port_list, list) { | 152 | list_for_each_entry(op, &br->port_list, list) { |
153 | if (op != p && | 153 | if (op != p && |
154 | !memcmp(op->dev->dev_addr, | 154 | !compare_ether_addr(op->dev->dev_addr, |
155 | f->addr.addr, ETH_ALEN)) { | 155 | f->addr.addr)) { |
156 | f->dst = op; | 156 | f->dst = op; |
157 | goto skip_delete; | 157 | goto skip_delete; |
158 | } | 158 | } |
@@ -174,7 +174,7 @@ struct net_bridge_fdb_entry *__br_fdb_get(struct net_bridge *br, | |||
174 | struct net_bridge_fdb_entry *fdb; | 174 | struct net_bridge_fdb_entry *fdb; |
175 | 175 | ||
176 | hlist_for_each_entry_rcu(fdb, h, &br->hash[br_mac_hash(addr)], hlist) { | 176 | hlist_for_each_entry_rcu(fdb, h, &br->hash[br_mac_hash(addr)], hlist) { |
177 | if (!memcmp(fdb->addr.addr, addr, ETH_ALEN)) { | 177 | if (!compare_ether_addr(fdb->addr.addr, addr)) { |
178 | if (unlikely(has_expired(br, fdb))) | 178 | if (unlikely(has_expired(br, fdb))) |
179 | break; | 179 | break; |
180 | return fdb; | 180 | return fdb; |
@@ -264,7 +264,7 @@ static inline struct net_bridge_fdb_entry *fdb_find(struct hlist_head *head, | |||
264 | struct net_bridge_fdb_entry *fdb; | 264 | struct net_bridge_fdb_entry *fdb; |
265 | 265 | ||
266 | hlist_for_each_entry_rcu(fdb, h, head, hlist) { | 266 | hlist_for_each_entry_rcu(fdb, h, head, hlist) { |
267 | if (!memcmp(fdb->addr.addr, addr, ETH_ALEN)) | 267 | if (!compare_ether_addr(fdb->addr.addr, addr)) |
268 | return fdb; | 268 | return fdb; |
269 | } | 269 | } |
270 | return NULL; | 270 | return NULL; |
diff --git a/net/bridge/br_input.c b/net/bridge/br_input.c index 9a45e6279c57..b88220a64cd8 100644 --- a/net/bridge/br_input.c +++ b/net/bridge/br_input.c | |||
@@ -128,7 +128,7 @@ int br_handle_frame(struct net_bridge_port *p, struct sk_buff **pskb) | |||
128 | dest = eth_hdr(skb)->h_dest; | 128 | dest = eth_hdr(skb)->h_dest; |
129 | } | 129 | } |
130 | 130 | ||
131 | if (!memcmp(p->br->dev->dev_addr, dest, ETH_ALEN)) | 131 | if (!compare_ether_addr(p->br->dev->dev_addr, dest)) |
132 | skb->pkt_type = PACKET_HOST; | 132 | skb->pkt_type = PACKET_HOST; |
133 | 133 | ||
134 | NF_HOOK(PF_BRIDGE, NF_BR_PRE_ROUTING, skb, skb->dev, NULL, | 134 | NF_HOOK(PF_BRIDGE, NF_BR_PRE_ROUTING, skb, skb->dev, NULL, |
diff --git a/net/bridge/br_stp_if.c b/net/bridge/br_stp_if.c index 0da11ff05fa3..ac09b6a23523 100644 --- a/net/bridge/br_stp_if.c +++ b/net/bridge/br_stp_if.c | |||
@@ -15,6 +15,7 @@ | |||
15 | 15 | ||
16 | #include <linux/kernel.h> | 16 | #include <linux/kernel.h> |
17 | #include <linux/smp_lock.h> | 17 | #include <linux/smp_lock.h> |
18 | #include <linux/etherdevice.h> | ||
18 | 19 | ||
19 | #include "br_private.h" | 20 | #include "br_private.h" |
20 | #include "br_private_stp.h" | 21 | #include "br_private_stp.h" |
@@ -133,10 +134,10 @@ static void br_stp_change_bridge_id(struct net_bridge *br, | |||
133 | memcpy(br->dev->dev_addr, addr, ETH_ALEN); | 134 | memcpy(br->dev->dev_addr, addr, ETH_ALEN); |
134 | 135 | ||
135 | list_for_each_entry(p, &br->port_list, list) { | 136 | list_for_each_entry(p, &br->port_list, list) { |
136 | if (!memcmp(p->designated_bridge.addr, oldaddr, ETH_ALEN)) | 137 | if (!compare_ether_addr(p->designated_bridge.addr, oldaddr)) |
137 | memcpy(p->designated_bridge.addr, addr, ETH_ALEN); | 138 | memcpy(p->designated_bridge.addr, addr, ETH_ALEN); |
138 | 139 | ||
139 | if (!memcmp(p->designated_root.addr, oldaddr, ETH_ALEN)) | 140 | if (!compare_ether_addr(p->designated_root.addr, oldaddr)) |
140 | memcpy(p->designated_root.addr, addr, ETH_ALEN); | 141 | memcpy(p->designated_root.addr, addr, ETH_ALEN); |
141 | 142 | ||
142 | } | 143 | } |
@@ -157,12 +158,12 @@ void br_stp_recalculate_bridge_id(struct net_bridge *br) | |||
157 | 158 | ||
158 | list_for_each_entry(p, &br->port_list, list) { | 159 | list_for_each_entry(p, &br->port_list, list) { |
159 | if (addr == br_mac_zero || | 160 | if (addr == br_mac_zero || |
160 | memcmp(p->dev->dev_addr, addr, ETH_ALEN) < 0) | 161 | compare_ether_addr(p->dev->dev_addr, addr) < 0) |
161 | addr = p->dev->dev_addr; | 162 | addr = p->dev->dev_addr; |
162 | 163 | ||
163 | } | 164 | } |
164 | 165 | ||
165 | if (memcmp(br->bridge_id.addr, addr, ETH_ALEN)) | 166 | if (compare_ether_addr(br->bridge_id.addr, addr)) |
166 | br_stp_change_bridge_id(br, addr); | 167 | br_stp_change_bridge_id(br, addr); |
167 | } | 168 | } |
168 | 169 | ||
diff --git a/net/core/datagram.c b/net/core/datagram.c index 81987df536eb..d219435d086c 100644 --- a/net/core/datagram.c +++ b/net/core/datagram.c | |||
@@ -213,6 +213,10 @@ int skb_copy_datagram_iovec(const struct sk_buff *skb, int offset, | |||
213 | { | 213 | { |
214 | int i, err, fraglen, end = 0; | 214 | int i, err, fraglen, end = 0; |
215 | struct sk_buff *next = skb_shinfo(skb)->frag_list; | 215 | struct sk_buff *next = skb_shinfo(skb)->frag_list; |
216 | |||
217 | if (!len) | ||
218 | return 0; | ||
219 | |||
216 | next_skb: | 220 | next_skb: |
217 | fraglen = skb_headlen(skb); | 221 | fraglen = skb_headlen(skb); |
218 | i = -1; | 222 | i = -1; |
diff --git a/net/core/dev.c b/net/core/dev.c index a44eeef24edf..8d1541595277 100644 --- a/net/core/dev.c +++ b/net/core/dev.c | |||
@@ -2717,6 +2717,20 @@ int register_netdevice(struct net_device *dev) | |||
2717 | dev->name); | 2717 | dev->name); |
2718 | dev->features &= ~NETIF_F_TSO; | 2718 | dev->features &= ~NETIF_F_TSO; |
2719 | } | 2719 | } |
2720 | if (dev->features & NETIF_F_UFO) { | ||
2721 | if (!(dev->features & NETIF_F_HW_CSUM)) { | ||
2722 | printk(KERN_ERR "%s: Dropping NETIF_F_UFO since no " | ||
2723 | "NETIF_F_HW_CSUM feature.\n", | ||
2724 | dev->name); | ||
2725 | dev->features &= ~NETIF_F_UFO; | ||
2726 | } | ||
2727 | if (!(dev->features & NETIF_F_SG)) { | ||
2728 | printk(KERN_ERR "%s: Dropping NETIF_F_UFO since no " | ||
2729 | "NETIF_F_SG feature.\n", | ||
2730 | dev->name); | ||
2731 | dev->features &= ~NETIF_F_UFO; | ||
2732 | } | ||
2733 | } | ||
2720 | 2734 | ||
2721 | /* | 2735 | /* |
2722 | * nil rebuild_header routine, | 2736 | * nil rebuild_header routine, |
diff --git a/net/core/ethtool.c b/net/core/ethtool.c index 404b761e82ce..0350586e9195 100644 --- a/net/core/ethtool.c +++ b/net/core/ethtool.c | |||
@@ -93,6 +93,20 @@ int ethtool_op_get_perm_addr(struct net_device *dev, struct ethtool_perm_addr *a | |||
93 | } | 93 | } |
94 | 94 | ||
95 | 95 | ||
96 | u32 ethtool_op_get_ufo(struct net_device *dev) | ||
97 | { | ||
98 | return (dev->features & NETIF_F_UFO) != 0; | ||
99 | } | ||
100 | |||
101 | int ethtool_op_set_ufo(struct net_device *dev, u32 data) | ||
102 | { | ||
103 | if (data) | ||
104 | dev->features |= NETIF_F_UFO; | ||
105 | else | ||
106 | dev->features &= ~NETIF_F_UFO; | ||
107 | return 0; | ||
108 | } | ||
109 | |||
96 | /* Handlers for each ethtool command */ | 110 | /* Handlers for each ethtool command */ |
97 | 111 | ||
98 | static int ethtool_get_settings(struct net_device *dev, void __user *useraddr) | 112 | static int ethtool_get_settings(struct net_device *dev, void __user *useraddr) |
@@ -483,6 +497,11 @@ static int __ethtool_set_sg(struct net_device *dev, u32 data) | |||
483 | return err; | 497 | return err; |
484 | } | 498 | } |
485 | 499 | ||
500 | if (!data && dev->ethtool_ops->set_ufo) { | ||
501 | err = dev->ethtool_ops->set_ufo(dev, 0); | ||
502 | if (err) | ||
503 | return err; | ||
504 | } | ||
486 | return dev->ethtool_ops->set_sg(dev, data); | 505 | return dev->ethtool_ops->set_sg(dev, data); |
487 | } | 506 | } |
488 | 507 | ||
@@ -569,6 +588,32 @@ static int ethtool_set_tso(struct net_device *dev, char __user *useraddr) | |||
569 | return dev->ethtool_ops->set_tso(dev, edata.data); | 588 | return dev->ethtool_ops->set_tso(dev, edata.data); |
570 | } | 589 | } |
571 | 590 | ||
591 | static int ethtool_get_ufo(struct net_device *dev, char __user *useraddr) | ||
592 | { | ||
593 | struct ethtool_value edata = { ETHTOOL_GTSO }; | ||
594 | |||
595 | if (!dev->ethtool_ops->get_ufo) | ||
596 | return -EOPNOTSUPP; | ||
597 | edata.data = dev->ethtool_ops->get_ufo(dev); | ||
598 | if (copy_to_user(useraddr, &edata, sizeof(edata))) | ||
599 | return -EFAULT; | ||
600 | return 0; | ||
601 | } | ||
602 | static int ethtool_set_ufo(struct net_device *dev, char __user *useraddr) | ||
603 | { | ||
604 | struct ethtool_value edata; | ||
605 | |||
606 | if (!dev->ethtool_ops->set_ufo) | ||
607 | return -EOPNOTSUPP; | ||
608 | if (copy_from_user(&edata, useraddr, sizeof(edata))) | ||
609 | return -EFAULT; | ||
610 | if (edata.data && !(dev->features & NETIF_F_SG)) | ||
611 | return -EINVAL; | ||
612 | if (edata.data && !(dev->features & NETIF_F_HW_CSUM)) | ||
613 | return -EINVAL; | ||
614 | return dev->ethtool_ops->set_ufo(dev, edata.data); | ||
615 | } | ||
616 | |||
572 | static int ethtool_self_test(struct net_device *dev, char __user *useraddr) | 617 | static int ethtool_self_test(struct net_device *dev, char __user *useraddr) |
573 | { | 618 | { |
574 | struct ethtool_test test; | 619 | struct ethtool_test test; |
@@ -854,6 +899,12 @@ int dev_ethtool(struct ifreq *ifr) | |||
854 | case ETHTOOL_GPERMADDR: | 899 | case ETHTOOL_GPERMADDR: |
855 | rc = ethtool_get_perm_addr(dev, useraddr); | 900 | rc = ethtool_get_perm_addr(dev, useraddr); |
856 | break; | 901 | break; |
902 | case ETHTOOL_GUFO: | ||
903 | rc = ethtool_get_ufo(dev, useraddr); | ||
904 | break; | ||
905 | case ETHTOOL_SUFO: | ||
906 | rc = ethtool_set_ufo(dev, useraddr); | ||
907 | break; | ||
857 | default: | 908 | default: |
858 | rc = -EOPNOTSUPP; | 909 | rc = -EOPNOTSUPP; |
859 | } | 910 | } |
@@ -882,3 +933,5 @@ EXPORT_SYMBOL(ethtool_op_set_sg); | |||
882 | EXPORT_SYMBOL(ethtool_op_set_tso); | 933 | EXPORT_SYMBOL(ethtool_op_set_tso); |
883 | EXPORT_SYMBOL(ethtool_op_set_tx_csum); | 934 | EXPORT_SYMBOL(ethtool_op_set_tx_csum); |
884 | EXPORT_SYMBOL(ethtool_op_set_tx_hw_csum); | 935 | EXPORT_SYMBOL(ethtool_op_set_tx_hw_csum); |
936 | EXPORT_SYMBOL(ethtool_op_set_ufo); | ||
937 | EXPORT_SYMBOL(ethtool_op_get_ufo); | ||
diff --git a/net/core/skbuff.c b/net/core/skbuff.c index ef9d46b91eb9..95501e40100e 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c | |||
@@ -176,6 +176,8 @@ struct sk_buff *__alloc_skb(unsigned int size, gfp_t gfp_mask, | |||
176 | skb_shinfo(skb)->tso_size = 0; | 176 | skb_shinfo(skb)->tso_size = 0; |
177 | skb_shinfo(skb)->tso_segs = 0; | 177 | skb_shinfo(skb)->tso_segs = 0; |
178 | skb_shinfo(skb)->frag_list = NULL; | 178 | skb_shinfo(skb)->frag_list = NULL; |
179 | skb_shinfo(skb)->ufo_size = 0; | ||
180 | skb_shinfo(skb)->ip6_frag_id = 0; | ||
179 | out: | 181 | out: |
180 | return skb; | 182 | return skb; |
181 | nodata: | 183 | nodata: |
@@ -1696,6 +1698,78 @@ unsigned int skb_find_text(struct sk_buff *skb, unsigned int from, | |||
1696 | return textsearch_find(config, state); | 1698 | return textsearch_find(config, state); |
1697 | } | 1699 | } |
1698 | 1700 | ||
1701 | /** | ||
1702 | * skb_append_datato_frags: - append the user data to a skb | ||
1703 | * @sk: sock structure | ||
1704 | * @skb: skb structure to be appened with user data. | ||
1705 | * @getfrag: call back function to be used for getting the user data | ||
1706 | * @from: pointer to user message iov | ||
1707 | * @length: length of the iov message | ||
1708 | * | ||
1709 | * Description: This procedure append the user data in the fragment part | ||
1710 | * of the skb if any page alloc fails user this procedure returns -ENOMEM | ||
1711 | */ | ||
1712 | int skb_append_datato_frags(struct sock *sk, struct sk_buff *skb, | ||
1713 | int getfrag(void *from, char *to, int offset, | ||
1714 | int len, int odd, struct sk_buff *skb), | ||
1715 | void *from, int length) | ||
1716 | { | ||
1717 | int frg_cnt = 0; | ||
1718 | skb_frag_t *frag = NULL; | ||
1719 | struct page *page = NULL; | ||
1720 | int copy, left; | ||
1721 | int offset = 0; | ||
1722 | int ret; | ||
1723 | |||
1724 | do { | ||
1725 | /* Return error if we don't have space for new frag */ | ||
1726 | frg_cnt = skb_shinfo(skb)->nr_frags; | ||
1727 | if (frg_cnt >= MAX_SKB_FRAGS) | ||
1728 | return -EFAULT; | ||
1729 | |||
1730 | /* allocate a new page for next frag */ | ||
1731 | page = alloc_pages(sk->sk_allocation, 0); | ||
1732 | |||
1733 | /* If alloc_page fails just return failure and caller will | ||
1734 | * free previous allocated pages by doing kfree_skb() | ||
1735 | */ | ||
1736 | if (page == NULL) | ||
1737 | return -ENOMEM; | ||
1738 | |||
1739 | /* initialize the next frag */ | ||
1740 | sk->sk_sndmsg_page = page; | ||
1741 | sk->sk_sndmsg_off = 0; | ||
1742 | skb_fill_page_desc(skb, frg_cnt, page, 0, 0); | ||
1743 | skb->truesize += PAGE_SIZE; | ||
1744 | atomic_add(PAGE_SIZE, &sk->sk_wmem_alloc); | ||
1745 | |||
1746 | /* get the new initialized frag */ | ||
1747 | frg_cnt = skb_shinfo(skb)->nr_frags; | ||
1748 | frag = &skb_shinfo(skb)->frags[frg_cnt - 1]; | ||
1749 | |||
1750 | /* copy the user data to page */ | ||
1751 | left = PAGE_SIZE - frag->page_offset; | ||
1752 | copy = (length > left)? left : length; | ||
1753 | |||
1754 | ret = getfrag(from, (page_address(frag->page) + | ||
1755 | frag->page_offset + frag->size), | ||
1756 | offset, copy, 0, skb); | ||
1757 | if (ret < 0) | ||
1758 | return -EFAULT; | ||
1759 | |||
1760 | /* copy was successful so update the size parameters */ | ||
1761 | sk->sk_sndmsg_off += copy; | ||
1762 | frag->size += copy; | ||
1763 | skb->len += copy; | ||
1764 | skb->data_len += copy; | ||
1765 | offset += copy; | ||
1766 | length -= copy; | ||
1767 | |||
1768 | } while (length > 0); | ||
1769 | |||
1770 | return 0; | ||
1771 | } | ||
1772 | |||
1699 | void __init skb_init(void) | 1773 | void __init skb_init(void) |
1700 | { | 1774 | { |
1701 | skbuff_head_cache = kmem_cache_create("skbuff_head_cache", | 1775 | skbuff_head_cache = kmem_cache_create("skbuff_head_cache", |
@@ -1747,3 +1821,4 @@ EXPORT_SYMBOL(skb_prepare_seq_read); | |||
1747 | EXPORT_SYMBOL(skb_seq_read); | 1821 | EXPORT_SYMBOL(skb_seq_read); |
1748 | EXPORT_SYMBOL(skb_abort_seq_read); | 1822 | EXPORT_SYMBOL(skb_abort_seq_read); |
1749 | EXPORT_SYMBOL(skb_find_text); | 1823 | EXPORT_SYMBOL(skb_find_text); |
1824 | EXPORT_SYMBOL(skb_append_datato_frags); | ||
diff --git a/net/dccp/dccp.h b/net/dccp/dccp.h index 5871c027f9dc..f97b85d55ad8 100644 --- a/net/dccp/dccp.h +++ b/net/dccp/dccp.h | |||
@@ -118,7 +118,6 @@ DECLARE_SNMP_STAT(struct dccp_mib, dccp_statistics); | |||
118 | #define DCCP_ADD_STATS_USER(field, val) \ | 118 | #define DCCP_ADD_STATS_USER(field, val) \ |
119 | SNMP_ADD_STATS_USER(dccp_statistics, field, val) | 119 | SNMP_ADD_STATS_USER(dccp_statistics, field, val) |
120 | 120 | ||
121 | extern int dccp_transmit_skb(struct sock *sk, struct sk_buff *skb); | ||
122 | extern int dccp_retransmit_skb(struct sock *sk, struct sk_buff *skb); | 121 | extern int dccp_retransmit_skb(struct sock *sk, struct sk_buff *skb); |
123 | 122 | ||
124 | extern int dccp_send_response(struct sock *sk); | 123 | extern int dccp_send_response(struct sock *sk); |
diff --git a/net/dccp/output.c b/net/dccp/output.c index d59f86f7ceab..74ff87025878 100644 --- a/net/dccp/output.c +++ b/net/dccp/output.c | |||
@@ -12,6 +12,7 @@ | |||
12 | 12 | ||
13 | #include <linux/config.h> | 13 | #include <linux/config.h> |
14 | #include <linux/dccp.h> | 14 | #include <linux/dccp.h> |
15 | #include <linux/kernel.h> | ||
15 | #include <linux/skbuff.h> | 16 | #include <linux/skbuff.h> |
16 | 17 | ||
17 | #include <net/sock.h> | 18 | #include <net/sock.h> |
@@ -25,13 +26,20 @@ static inline void dccp_event_ack_sent(struct sock *sk) | |||
25 | inet_csk_clear_xmit_timer(sk, ICSK_TIME_DACK); | 26 | inet_csk_clear_xmit_timer(sk, ICSK_TIME_DACK); |
26 | } | 27 | } |
27 | 28 | ||
29 | static inline void dccp_skb_entail(struct sock *sk, struct sk_buff *skb) | ||
30 | { | ||
31 | skb_set_owner_w(skb, sk); | ||
32 | WARN_ON(sk->sk_send_head); | ||
33 | sk->sk_send_head = skb; | ||
34 | } | ||
35 | |||
28 | /* | 36 | /* |
29 | * All SKB's seen here are completely headerless. It is our | 37 | * All SKB's seen here are completely headerless. It is our |
30 | * job to build the DCCP header, and pass the packet down to | 38 | * job to build the DCCP header, and pass the packet down to |
31 | * IP so it can do the same plus pass the packet off to the | 39 | * IP so it can do the same plus pass the packet off to the |
32 | * device. | 40 | * device. |
33 | */ | 41 | */ |
34 | int dccp_transmit_skb(struct sock *sk, struct sk_buff *skb) | 42 | static int dccp_transmit_skb(struct sock *sk, struct sk_buff *skb) |
35 | { | 43 | { |
36 | if (likely(skb != NULL)) { | 44 | if (likely(skb != NULL)) { |
37 | const struct inet_sock *inet = inet_sk(sk); | 45 | const struct inet_sock *inet = inet_sk(sk); |
@@ -50,10 +58,21 @@ int dccp_transmit_skb(struct sock *sk, struct sk_buff *skb) | |||
50 | switch (dcb->dccpd_type) { | 58 | switch (dcb->dccpd_type) { |
51 | case DCCP_PKT_DATA: | 59 | case DCCP_PKT_DATA: |
52 | set_ack = 0; | 60 | set_ack = 0; |
61 | /* fall through */ | ||
62 | case DCCP_PKT_DATAACK: | ||
53 | break; | 63 | break; |
64 | |||
54 | case DCCP_PKT_SYNC: | 65 | case DCCP_PKT_SYNC: |
55 | case DCCP_PKT_SYNCACK: | 66 | case DCCP_PKT_SYNCACK: |
56 | ackno = dcb->dccpd_seq; | 67 | ackno = dcb->dccpd_seq; |
68 | /* fall through */ | ||
69 | default: | ||
70 | /* | ||
71 | * Only data packets should come through with skb->sk | ||
72 | * set. | ||
73 | */ | ||
74 | WARN_ON(skb->sk); | ||
75 | skb_set_owner_w(skb, sk); | ||
57 | break; | 76 | break; |
58 | } | 77 | } |
59 | 78 | ||
@@ -63,9 +82,6 @@ int dccp_transmit_skb(struct sock *sk, struct sk_buff *skb) | |||
63 | skb->h.raw = skb_push(skb, dccp_header_size); | 82 | skb->h.raw = skb_push(skb, dccp_header_size); |
64 | dh = dccp_hdr(skb); | 83 | dh = dccp_hdr(skb); |
65 | 84 | ||
66 | if (!skb->sk) | ||
67 | skb_set_owner_w(skb, sk); | ||
68 | |||
69 | /* Build DCCP header and checksum it. */ | 85 | /* Build DCCP header and checksum it. */ |
70 | memset(dh, 0, dccp_header_size); | 86 | memset(dh, 0, dccp_header_size); |
71 | dh->dccph_type = dcb->dccpd_type; | 87 | dh->dccph_type = dcb->dccpd_type; |
@@ -393,10 +409,8 @@ int dccp_connect(struct sock *sk) | |||
393 | 409 | ||
394 | DCCP_SKB_CB(skb)->dccpd_type = DCCP_PKT_REQUEST; | 410 | DCCP_SKB_CB(skb)->dccpd_type = DCCP_PKT_REQUEST; |
395 | skb->csum = 0; | 411 | skb->csum = 0; |
396 | skb_set_owner_w(skb, sk); | ||
397 | 412 | ||
398 | BUG_TRAP(sk->sk_send_head == NULL); | 413 | dccp_skb_entail(sk, skb); |
399 | sk->sk_send_head = skb; | ||
400 | dccp_transmit_skb(sk, skb_clone(skb, GFP_KERNEL)); | 414 | dccp_transmit_skb(sk, skb_clone(skb, GFP_KERNEL)); |
401 | DCCP_INC_STATS(DCCP_MIB_ACTIVEOPENS); | 415 | DCCP_INC_STATS(DCCP_MIB_ACTIVEOPENS); |
402 | 416 | ||
@@ -425,7 +439,6 @@ void dccp_send_ack(struct sock *sk) | |||
425 | skb_reserve(skb, MAX_DCCP_HEADER); | 439 | skb_reserve(skb, MAX_DCCP_HEADER); |
426 | skb->csum = 0; | 440 | skb->csum = 0; |
427 | DCCP_SKB_CB(skb)->dccpd_type = DCCP_PKT_ACK; | 441 | DCCP_SKB_CB(skb)->dccpd_type = DCCP_PKT_ACK; |
428 | skb_set_owner_w(skb, sk); | ||
429 | dccp_transmit_skb(sk, skb); | 442 | dccp_transmit_skb(sk, skb); |
430 | } | 443 | } |
431 | } | 444 | } |
@@ -482,7 +495,6 @@ void dccp_send_sync(struct sock *sk, const u64 seq, | |||
482 | DCCP_SKB_CB(skb)->dccpd_type = pkt_type; | 495 | DCCP_SKB_CB(skb)->dccpd_type = pkt_type; |
483 | DCCP_SKB_CB(skb)->dccpd_seq = seq; | 496 | DCCP_SKB_CB(skb)->dccpd_seq = seq; |
484 | 497 | ||
485 | skb_set_owner_w(skb, sk); | ||
486 | dccp_transmit_skb(sk, skb); | 498 | dccp_transmit_skb(sk, skb); |
487 | } | 499 | } |
488 | 500 | ||
@@ -507,10 +519,8 @@ void dccp_send_close(struct sock *sk, const int active) | |||
507 | DCCP_SKB_CB(skb)->dccpd_type = dp->dccps_role == DCCP_ROLE_CLIENT ? | 519 | DCCP_SKB_CB(skb)->dccpd_type = dp->dccps_role == DCCP_ROLE_CLIENT ? |
508 | DCCP_PKT_CLOSE : DCCP_PKT_CLOSEREQ; | 520 | DCCP_PKT_CLOSE : DCCP_PKT_CLOSEREQ; |
509 | 521 | ||
510 | skb_set_owner_w(skb, sk); | ||
511 | if (active) { | 522 | if (active) { |
512 | BUG_TRAP(sk->sk_send_head == NULL); | 523 | dccp_skb_entail(sk, skb); |
513 | sk->sk_send_head = skb; | ||
514 | dccp_transmit_skb(sk, skb_clone(skb, prio)); | 524 | dccp_transmit_skb(sk, skb_clone(skb, prio)); |
515 | } else | 525 | } else |
516 | dccp_transmit_skb(sk, skb); | 526 | dccp_transmit_skb(sk, skb); |
diff --git a/net/ethernet/eth.c b/net/ethernet/eth.c index 68a5ca866442..e24577367274 100644 --- a/net/ethernet/eth.c +++ b/net/ethernet/eth.c | |||
@@ -146,19 +146,6 @@ int eth_rebuild_header(struct sk_buff *skb) | |||
146 | return 0; | 146 | return 0; |
147 | } | 147 | } |
148 | 148 | ||
149 | static inline unsigned int compare_eth_addr(const unsigned char *__a, const unsigned char *__b) | ||
150 | { | ||
151 | const unsigned short *dest = (unsigned short *) __a; | ||
152 | const unsigned short *devaddr = (unsigned short *) __b; | ||
153 | unsigned int res; | ||
154 | |||
155 | BUILD_BUG_ON(ETH_ALEN != 6); | ||
156 | res = ((dest[0] ^ devaddr[0]) | | ||
157 | (dest[1] ^ devaddr[1]) | | ||
158 | (dest[2] ^ devaddr[2])) != 0; | ||
159 | |||
160 | return res; | ||
161 | } | ||
162 | 149 | ||
163 | /* | 150 | /* |
164 | * Determine the packet's protocol ID. The rule here is that we | 151 | * Determine the packet's protocol ID. The rule here is that we |
@@ -176,7 +163,7 @@ __be16 eth_type_trans(struct sk_buff *skb, struct net_device *dev) | |||
176 | eth = eth_hdr(skb); | 163 | eth = eth_hdr(skb); |
177 | 164 | ||
178 | if (*eth->h_dest&1) { | 165 | if (*eth->h_dest&1) { |
179 | if (!compare_eth_addr(eth->h_dest, dev->broadcast)) | 166 | if (!compare_ether_addr(eth->h_dest, dev->broadcast)) |
180 | skb->pkt_type = PACKET_BROADCAST; | 167 | skb->pkt_type = PACKET_BROADCAST; |
181 | else | 168 | else |
182 | skb->pkt_type = PACKET_MULTICAST; | 169 | skb->pkt_type = PACKET_MULTICAST; |
@@ -191,7 +178,7 @@ __be16 eth_type_trans(struct sk_buff *skb, struct net_device *dev) | |||
191 | */ | 178 | */ |
192 | 179 | ||
193 | else if(1 /*dev->flags&IFF_PROMISC*/) { | 180 | else if(1 /*dev->flags&IFF_PROMISC*/) { |
194 | if (unlikely(compare_eth_addr(eth->h_dest, dev->dev_addr))) | 181 | if (unlikely(compare_ether_addr(eth->h_dest, dev->dev_addr))) |
195 | skb->pkt_type = PACKET_OTHERHOST; | 182 | skb->pkt_type = PACKET_OTHERHOST; |
196 | } | 183 | } |
197 | 184 | ||
diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c index e61bc7177eb1..990633c09dfe 100644 --- a/net/ipv4/fib_frontend.c +++ b/net/ipv4/fib_frontend.c | |||
@@ -591,7 +591,7 @@ static int fib_inetaddr_event(struct notifier_block *this, unsigned long event, | |||
591 | break; | 591 | break; |
592 | case NETDEV_DOWN: | 592 | case NETDEV_DOWN: |
593 | fib_del_ifaddr(ifa); | 593 | fib_del_ifaddr(ifa); |
594 | if (ifa->ifa_dev && ifa->ifa_dev->ifa_list == NULL) { | 594 | if (ifa->ifa_dev->ifa_list == NULL) { |
595 | /* Last address was deleted from this interface. | 595 | /* Last address was deleted from this interface. |
596 | Disable IP. | 596 | Disable IP. |
597 | */ | 597 | */ |
diff --git a/net/ipv4/igmp.c b/net/ipv4/igmp.c index 8b6d3939e1e6..c6247fc84060 100644 --- a/net/ipv4/igmp.c +++ b/net/ipv4/igmp.c | |||
@@ -1908,8 +1908,11 @@ int ip_mc_msfilter(struct sock *sk, struct ip_msfilter *msf, int ifindex) | |||
1908 | sock_kfree_s(sk, newpsl, IP_SFLSIZE(newpsl->sl_max)); | 1908 | sock_kfree_s(sk, newpsl, IP_SFLSIZE(newpsl->sl_max)); |
1909 | goto done; | 1909 | goto done; |
1910 | } | 1910 | } |
1911 | } else | 1911 | } else { |
1912 | newpsl = NULL; | 1912 | newpsl = NULL; |
1913 | (void) ip_mc_add_src(in_dev, &msf->imsf_multiaddr, | ||
1914 | msf->imsf_fmode, 0, NULL, 0); | ||
1915 | } | ||
1913 | psl = pmc->sflist; | 1916 | psl = pmc->sflist; |
1914 | if (psl) { | 1917 | if (psl) { |
1915 | (void) ip_mc_del_src(in_dev, &msf->imsf_multiaddr, pmc->sfmode, | 1918 | (void) ip_mc_del_src(in_dev, &msf->imsf_multiaddr, pmc->sfmode, |
diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c index 87e350069abb..17758234a3e3 100644 --- a/net/ipv4/ip_output.c +++ b/net/ipv4/ip_output.c | |||
@@ -275,7 +275,8 @@ int ip_output(struct sk_buff *skb) | |||
275 | { | 275 | { |
276 | IP_INC_STATS(IPSTATS_MIB_OUTREQUESTS); | 276 | IP_INC_STATS(IPSTATS_MIB_OUTREQUESTS); |
277 | 277 | ||
278 | if (skb->len > dst_mtu(skb->dst) && !skb_shinfo(skb)->tso_size) | 278 | if (skb->len > dst_mtu(skb->dst) && |
279 | !(skb_shinfo(skb)->ufo_size || skb_shinfo(skb)->tso_size)) | ||
279 | return ip_fragment(skb, ip_finish_output); | 280 | return ip_fragment(skb, ip_finish_output); |
280 | else | 281 | else |
281 | return ip_finish_output(skb); | 282 | return ip_finish_output(skb); |
@@ -688,6 +689,60 @@ csum_page(struct page *page, int offset, int copy) | |||
688 | return csum; | 689 | return csum; |
689 | } | 690 | } |
690 | 691 | ||
692 | inline int ip_ufo_append_data(struct sock *sk, | ||
693 | int getfrag(void *from, char *to, int offset, int len, | ||
694 | int odd, struct sk_buff *skb), | ||
695 | void *from, int length, int hh_len, int fragheaderlen, | ||
696 | int transhdrlen, int mtu,unsigned int flags) | ||
697 | { | ||
698 | struct sk_buff *skb; | ||
699 | int err; | ||
700 | |||
701 | /* There is support for UDP fragmentation offload by network | ||
702 | * device, so create one single skb packet containing complete | ||
703 | * udp datagram | ||
704 | */ | ||
705 | if ((skb = skb_peek_tail(&sk->sk_write_queue)) == NULL) { | ||
706 | skb = sock_alloc_send_skb(sk, | ||
707 | hh_len + fragheaderlen + transhdrlen + 20, | ||
708 | (flags & MSG_DONTWAIT), &err); | ||
709 | |||
710 | if (skb == NULL) | ||
711 | return err; | ||
712 | |||
713 | /* reserve space for Hardware header */ | ||
714 | skb_reserve(skb, hh_len); | ||
715 | |||
716 | /* create space for UDP/IP header */ | ||
717 | skb_put(skb,fragheaderlen + transhdrlen); | ||
718 | |||
719 | /* initialize network header pointer */ | ||
720 | skb->nh.raw = skb->data; | ||
721 | |||
722 | /* initialize protocol header pointer */ | ||
723 | skb->h.raw = skb->data + fragheaderlen; | ||
724 | |||
725 | skb->ip_summed = CHECKSUM_HW; | ||
726 | skb->csum = 0; | ||
727 | sk->sk_sndmsg_off = 0; | ||
728 | } | ||
729 | |||
730 | err = skb_append_datato_frags(sk,skb, getfrag, from, | ||
731 | (length - transhdrlen)); | ||
732 | if (!err) { | ||
733 | /* specify the length of each IP datagram fragment*/ | ||
734 | skb_shinfo(skb)->ufo_size = (mtu - fragheaderlen); | ||
735 | __skb_queue_tail(&sk->sk_write_queue, skb); | ||
736 | |||
737 | return 0; | ||
738 | } | ||
739 | /* There is not enough support do UFO , | ||
740 | * so follow normal path | ||
741 | */ | ||
742 | kfree_skb(skb); | ||
743 | return err; | ||
744 | } | ||
745 | |||
691 | /* | 746 | /* |
692 | * ip_append_data() and ip_append_page() can make one large IP datagram | 747 | * ip_append_data() and ip_append_page() can make one large IP datagram |
693 | * from many pieces of data. Each pieces will be holded on the socket | 748 | * from many pieces of data. Each pieces will be holded on the socket |
@@ -777,6 +832,15 @@ int ip_append_data(struct sock *sk, | |||
777 | csummode = CHECKSUM_HW; | 832 | csummode = CHECKSUM_HW; |
778 | 833 | ||
779 | inet->cork.length += length; | 834 | inet->cork.length += length; |
835 | if (((length > mtu) && (sk->sk_protocol == IPPROTO_UDP)) && | ||
836 | (rt->u.dst.dev->features & NETIF_F_UFO)) { | ||
837 | |||
838 | if(ip_ufo_append_data(sk, getfrag, from, length, hh_len, | ||
839 | fragheaderlen, transhdrlen, mtu, flags)) | ||
840 | goto error; | ||
841 | |||
842 | return 0; | ||
843 | } | ||
780 | 844 | ||
781 | /* So, what's going on in the loop below? | 845 | /* So, what's going on in the loop below? |
782 | * | 846 | * |
@@ -1008,14 +1072,23 @@ ssize_t ip_append_page(struct sock *sk, struct page *page, | |||
1008 | return -EINVAL; | 1072 | return -EINVAL; |
1009 | 1073 | ||
1010 | inet->cork.length += size; | 1074 | inet->cork.length += size; |
1075 | if ((sk->sk_protocol == IPPROTO_UDP) && | ||
1076 | (rt->u.dst.dev->features & NETIF_F_UFO)) | ||
1077 | skb_shinfo(skb)->ufo_size = (mtu - fragheaderlen); | ||
1078 | |||
1011 | 1079 | ||
1012 | while (size > 0) { | 1080 | while (size > 0) { |
1013 | int i; | 1081 | int i; |
1014 | 1082 | ||
1015 | /* Check if the remaining data fits into current packet. */ | 1083 | if (skb_shinfo(skb)->ufo_size) |
1016 | len = mtu - skb->len; | 1084 | len = size; |
1017 | if (len < size) | 1085 | else { |
1018 | len = maxfraglen - skb->len; | 1086 | |
1087 | /* Check if the remaining data fits into current packet. */ | ||
1088 | len = mtu - skb->len; | ||
1089 | if (len < size) | ||
1090 | len = maxfraglen - skb->len; | ||
1091 | } | ||
1019 | if (len <= 0) { | 1092 | if (len <= 0) { |
1020 | struct sk_buff *skb_prev; | 1093 | struct sk_buff *skb_prev; |
1021 | char *data; | 1094 | char *data; |
diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c index a7969286e6e7..3c2e9639bba6 100644 --- a/net/ipv4/netfilter/arp_tables.c +++ b/net/ipv4/netfilter/arp_tables.c | |||
@@ -347,58 +347,106 @@ unsigned int arpt_do_table(struct sk_buff **pskb, | |||
347 | return verdict; | 347 | return verdict; |
348 | } | 348 | } |
349 | 349 | ||
350 | static inline void *find_inlist_lock_noload(struct list_head *head, | 350 | /* |
351 | const char *name, | 351 | * These are weird, but module loading must not be done with mutex |
352 | int *error, | 352 | * held (since they will register), and we have to have a single |
353 | struct semaphore *mutex) | 353 | * function to use try_then_request_module(). |
354 | */ | ||
355 | |||
356 | /* Find table by name, grabs mutex & ref. Returns ERR_PTR() on error. */ | ||
357 | static inline struct arpt_table *find_table_lock(const char *name) | ||
354 | { | 358 | { |
355 | void *ret; | 359 | struct arpt_table *t; |
356 | 360 | ||
357 | *error = down_interruptible(mutex); | 361 | if (down_interruptible(&arpt_mutex) != 0) |
358 | if (*error != 0) | 362 | return ERR_PTR(-EINTR); |
359 | return NULL; | ||
360 | 363 | ||
361 | ret = list_named_find(head, name); | 364 | list_for_each_entry(t, &arpt_tables, list) |
362 | if (!ret) { | 365 | if (strcmp(t->name, name) == 0 && try_module_get(t->me)) |
363 | *error = -ENOENT; | 366 | return t; |
364 | up(mutex); | 367 | up(&arpt_mutex); |
365 | } | 368 | return NULL; |
366 | return ret; | ||
367 | } | 369 | } |
368 | 370 | ||
369 | #ifndef CONFIG_KMOD | 371 | |
370 | #define find_inlist_lock(h,n,p,e,m) find_inlist_lock_noload((h),(n),(e),(m)) | 372 | /* Find target, grabs ref. Returns ERR_PTR() on error. */ |
371 | #else | 373 | static inline struct arpt_target *find_target(const char *name, u8 revision) |
372 | static void * | ||
373 | find_inlist_lock(struct list_head *head, | ||
374 | const char *name, | ||
375 | const char *prefix, | ||
376 | int *error, | ||
377 | struct semaphore *mutex) | ||
378 | { | 374 | { |
379 | void *ret; | 375 | struct arpt_target *t; |
376 | int err = 0; | ||
380 | 377 | ||
381 | ret = find_inlist_lock_noload(head, name, error, mutex); | 378 | if (down_interruptible(&arpt_mutex) != 0) |
382 | if (!ret) { | 379 | return ERR_PTR(-EINTR); |
383 | duprintf("find_inlist: loading `%s%s'.\n", prefix, name); | 380 | |
384 | request_module("%s%s", prefix, name); | 381 | list_for_each_entry(t, &arpt_target, list) { |
385 | ret = find_inlist_lock_noload(head, name, error, mutex); | 382 | if (strcmp(t->name, name) == 0) { |
383 | if (t->revision == revision) { | ||
384 | if (try_module_get(t->me)) { | ||
385 | up(&arpt_mutex); | ||
386 | return t; | ||
387 | } | ||
388 | } else | ||
389 | err = -EPROTOTYPE; /* Found something. */ | ||
390 | } | ||
386 | } | 391 | } |
392 | up(&arpt_mutex); | ||
393 | return ERR_PTR(err); | ||
394 | } | ||
387 | 395 | ||
388 | return ret; | 396 | struct arpt_target *arpt_find_target(const char *name, u8 revision) |
397 | { | ||
398 | struct arpt_target *target; | ||
399 | |||
400 | target = try_then_request_module(find_target(name, revision), | ||
401 | "arpt_%s", name); | ||
402 | if (IS_ERR(target) || !target) | ||
403 | return NULL; | ||
404 | return target; | ||
389 | } | 405 | } |
390 | #endif | ||
391 | 406 | ||
392 | static inline struct arpt_table *arpt_find_table_lock(const char *name, int *error, struct semaphore *mutex) | 407 | static int target_revfn(const char *name, u8 revision, int *bestp) |
393 | { | 408 | { |
394 | return find_inlist_lock(&arpt_tables, name, "arptable_", error, mutex); | 409 | struct arpt_target *t; |
410 | int have_rev = 0; | ||
411 | |||
412 | list_for_each_entry(t, &arpt_target, list) { | ||
413 | if (strcmp(t->name, name) == 0) { | ||
414 | if (t->revision > *bestp) | ||
415 | *bestp = t->revision; | ||
416 | if (t->revision == revision) | ||
417 | have_rev =1; | ||
418 | } | ||
419 | } | ||
420 | return have_rev; | ||
395 | } | 421 | } |
396 | 422 | ||
397 | static struct arpt_target *arpt_find_target_lock(const char *name, int *error, struct semaphore *mutex) | 423 | /* Returns true or false (if no such extension at all) */ |
424 | static inline int find_revision(const char *name, u8 revision, | ||
425 | int (*revfn)(const char *, u8, int *), | ||
426 | int *err) | ||
398 | { | 427 | { |
399 | return find_inlist_lock(&arpt_target, name, "arpt_", error, mutex); | 428 | int have_rev, best = -1; |
429 | |||
430 | if (down_interruptible(&arpt_mutex) != 0) { | ||
431 | *err = -EINTR; | ||
432 | return 1; | ||
433 | } | ||
434 | have_rev = revfn(name, revision, &best); | ||
435 | up(&arpt_mutex); | ||
436 | |||
437 | /* Nothing at all? Return 0 to try loading module. */ | ||
438 | if (best == -1) { | ||
439 | *err = -ENOENT; | ||
440 | return 0; | ||
441 | } | ||
442 | |||
443 | *err = best; | ||
444 | if (!have_rev) | ||
445 | *err = -EPROTONOSUPPORT; | ||
446 | return 1; | ||
400 | } | 447 | } |
401 | 448 | ||
449 | |||
402 | /* All zeroes == unconditional rule. */ | 450 | /* All zeroes == unconditional rule. */ |
403 | static inline int unconditional(const struct arpt_arp *arp) | 451 | static inline int unconditional(const struct arpt_arp *arp) |
404 | { | 452 | { |
@@ -544,17 +592,15 @@ static inline int check_entry(struct arpt_entry *e, const char *name, unsigned i | |||
544 | } | 592 | } |
545 | 593 | ||
546 | t = arpt_get_target(e); | 594 | t = arpt_get_target(e); |
547 | target = arpt_find_target_lock(t->u.user.name, &ret, &arpt_mutex); | 595 | target = try_then_request_module(find_target(t->u.user.name, |
548 | if (!target) { | 596 | t->u.user.revision), |
597 | "arpt_%s", t->u.user.name); | ||
598 | if (IS_ERR(target) || !target) { | ||
549 | duprintf("check_entry: `%s' not found\n", t->u.user.name); | 599 | duprintf("check_entry: `%s' not found\n", t->u.user.name); |
600 | ret = target ? PTR_ERR(target) : -ENOENT; | ||
550 | goto out; | 601 | goto out; |
551 | } | 602 | } |
552 | if (!try_module_get((target->me))) { | ||
553 | ret = -ENOENT; | ||
554 | goto out_unlock; | ||
555 | } | ||
556 | t->u.kernel.target = target; | 603 | t->u.kernel.target = target; |
557 | up(&arpt_mutex); | ||
558 | 604 | ||
559 | if (t->u.kernel.target == &arpt_standard_target) { | 605 | if (t->u.kernel.target == &arpt_standard_target) { |
560 | if (!standard_check(t, size)) { | 606 | if (!standard_check(t, size)) { |
@@ -576,8 +622,6 @@ static inline int check_entry(struct arpt_entry *e, const char *name, unsigned i | |||
576 | (*i)++; | 622 | (*i)++; |
577 | return 0; | 623 | return 0; |
578 | 624 | ||
579 | out_unlock: | ||
580 | up(&arpt_mutex); | ||
581 | out: | 625 | out: |
582 | return ret; | 626 | return ret; |
583 | } | 627 | } |
@@ -846,8 +890,8 @@ static int get_entries(const struct arpt_get_entries *entries, | |||
846 | int ret; | 890 | int ret; |
847 | struct arpt_table *t; | 891 | struct arpt_table *t; |
848 | 892 | ||
849 | t = arpt_find_table_lock(entries->name, &ret, &arpt_mutex); | 893 | t = find_table_lock(entries->name); |
850 | if (t) { | 894 | if (t || !IS_ERR(t)) { |
851 | duprintf("t->private->number = %u\n", | 895 | duprintf("t->private->number = %u\n", |
852 | t->private->number); | 896 | t->private->number); |
853 | if (entries->size == t->private->size) | 897 | if (entries->size == t->private->size) |
@@ -859,10 +903,10 @@ static int get_entries(const struct arpt_get_entries *entries, | |||
859 | entries->size); | 903 | entries->size); |
860 | ret = -EINVAL; | 904 | ret = -EINVAL; |
861 | } | 905 | } |
906 | module_put(t->me); | ||
862 | up(&arpt_mutex); | 907 | up(&arpt_mutex); |
863 | } else | 908 | } else |
864 | duprintf("get_entries: Can't find %s!\n", | 909 | ret = t ? PTR_ERR(t) : -ENOENT; |
865 | entries->name); | ||
866 | 910 | ||
867 | return ret; | 911 | return ret; |
868 | } | 912 | } |
@@ -913,22 +957,19 @@ static int do_replace(void __user *user, unsigned int len) | |||
913 | 957 | ||
914 | duprintf("arp_tables: Translated table\n"); | 958 | duprintf("arp_tables: Translated table\n"); |
915 | 959 | ||
916 | t = arpt_find_table_lock(tmp.name, &ret, &arpt_mutex); | 960 | t = try_then_request_module(find_table_lock(tmp.name), |
917 | if (!t) | 961 | "arptable_%s", tmp.name); |
962 | if (!t || IS_ERR(t)) { | ||
963 | ret = t ? PTR_ERR(t) : -ENOENT; | ||
918 | goto free_newinfo_counters_untrans; | 964 | goto free_newinfo_counters_untrans; |
965 | } | ||
919 | 966 | ||
920 | /* You lied! */ | 967 | /* You lied! */ |
921 | if (tmp.valid_hooks != t->valid_hooks) { | 968 | if (tmp.valid_hooks != t->valid_hooks) { |
922 | duprintf("Valid hook crap: %08X vs %08X\n", | 969 | duprintf("Valid hook crap: %08X vs %08X\n", |
923 | tmp.valid_hooks, t->valid_hooks); | 970 | tmp.valid_hooks, t->valid_hooks); |
924 | ret = -EINVAL; | 971 | ret = -EINVAL; |
925 | goto free_newinfo_counters_untrans_unlock; | 972 | goto put_module; |
926 | } | ||
927 | |||
928 | /* Get a reference in advance, we're not allowed fail later */ | ||
929 | if (!try_module_get(t->me)) { | ||
930 | ret = -EBUSY; | ||
931 | goto free_newinfo_counters_untrans_unlock; | ||
932 | } | 973 | } |
933 | 974 | ||
934 | oldinfo = replace_table(t, tmp.num_counters, newinfo, &ret); | 975 | oldinfo = replace_table(t, tmp.num_counters, newinfo, &ret); |
@@ -959,7 +1000,6 @@ static int do_replace(void __user *user, unsigned int len) | |||
959 | 1000 | ||
960 | put_module: | 1001 | put_module: |
961 | module_put(t->me); | 1002 | module_put(t->me); |
962 | free_newinfo_counters_untrans_unlock: | ||
963 | up(&arpt_mutex); | 1003 | up(&arpt_mutex); |
964 | free_newinfo_counters_untrans: | 1004 | free_newinfo_counters_untrans: |
965 | ARPT_ENTRY_ITERATE(newinfo->entries, newinfo->size, cleanup_entry, NULL); | 1005 | ARPT_ENTRY_ITERATE(newinfo->entries, newinfo->size, cleanup_entry, NULL); |
@@ -989,7 +1029,7 @@ static int do_add_counters(void __user *user, unsigned int len) | |||
989 | unsigned int i; | 1029 | unsigned int i; |
990 | struct arpt_counters_info tmp, *paddc; | 1030 | struct arpt_counters_info tmp, *paddc; |
991 | struct arpt_table *t; | 1031 | struct arpt_table *t; |
992 | int ret; | 1032 | int ret = 0; |
993 | 1033 | ||
994 | if (copy_from_user(&tmp, user, sizeof(tmp)) != 0) | 1034 | if (copy_from_user(&tmp, user, sizeof(tmp)) != 0) |
995 | return -EFAULT; | 1035 | return -EFAULT; |
@@ -1006,9 +1046,11 @@ static int do_add_counters(void __user *user, unsigned int len) | |||
1006 | goto free; | 1046 | goto free; |
1007 | } | 1047 | } |
1008 | 1048 | ||
1009 | t = arpt_find_table_lock(tmp.name, &ret, &arpt_mutex); | 1049 | t = find_table_lock(tmp.name); |
1010 | if (!t) | 1050 | if (!t || IS_ERR(t)) { |
1051 | ret = t ? PTR_ERR(t) : -ENOENT; | ||
1011 | goto free; | 1052 | goto free; |
1053 | } | ||
1012 | 1054 | ||
1013 | write_lock_bh(&t->lock); | 1055 | write_lock_bh(&t->lock); |
1014 | if (t->private->number != paddc->num_counters) { | 1056 | if (t->private->number != paddc->num_counters) { |
@@ -1025,6 +1067,7 @@ static int do_add_counters(void __user *user, unsigned int len) | |||
1025 | unlock_up_free: | 1067 | unlock_up_free: |
1026 | write_unlock_bh(&t->lock); | 1068 | write_unlock_bh(&t->lock); |
1027 | up(&arpt_mutex); | 1069 | up(&arpt_mutex); |
1070 | module_put(t->me); | ||
1028 | free: | 1071 | free: |
1029 | vfree(paddc); | 1072 | vfree(paddc); |
1030 | 1073 | ||
@@ -1079,8 +1122,10 @@ static int do_arpt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len | |||
1079 | break; | 1122 | break; |
1080 | } | 1123 | } |
1081 | name[ARPT_TABLE_MAXNAMELEN-1] = '\0'; | 1124 | name[ARPT_TABLE_MAXNAMELEN-1] = '\0'; |
1082 | t = arpt_find_table_lock(name, &ret, &arpt_mutex); | 1125 | |
1083 | if (t) { | 1126 | t = try_then_request_module(find_table_lock(name), |
1127 | "arptable_%s", name); | ||
1128 | if (t && !IS_ERR(t)) { | ||
1084 | struct arpt_getinfo info; | 1129 | struct arpt_getinfo info; |
1085 | 1130 | ||
1086 | info.valid_hooks = t->valid_hooks; | 1131 | info.valid_hooks = t->valid_hooks; |
@@ -1096,9 +1141,10 @@ static int do_arpt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len | |||
1096 | ret = -EFAULT; | 1141 | ret = -EFAULT; |
1097 | else | 1142 | else |
1098 | ret = 0; | 1143 | ret = 0; |
1099 | |||
1100 | up(&arpt_mutex); | 1144 | up(&arpt_mutex); |
1101 | } | 1145 | module_put(t->me); |
1146 | } else | ||
1147 | ret = t ? PTR_ERR(t) : -ENOENT; | ||
1102 | } | 1148 | } |
1103 | break; | 1149 | break; |
1104 | 1150 | ||
@@ -1119,6 +1165,24 @@ static int do_arpt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len | |||
1119 | break; | 1165 | break; |
1120 | } | 1166 | } |
1121 | 1167 | ||
1168 | case ARPT_SO_GET_REVISION_TARGET: { | ||
1169 | struct arpt_get_revision rev; | ||
1170 | |||
1171 | if (*len != sizeof(rev)) { | ||
1172 | ret = -EINVAL; | ||
1173 | break; | ||
1174 | } | ||
1175 | if (copy_from_user(&rev, user, sizeof(rev)) != 0) { | ||
1176 | ret = -EFAULT; | ||
1177 | break; | ||
1178 | } | ||
1179 | |||
1180 | try_then_request_module(find_revision(rev.name, rev.revision, | ||
1181 | target_revfn, &ret), | ||
1182 | "arpt_%s", rev.name); | ||
1183 | break; | ||
1184 | } | ||
1185 | |||
1122 | default: | 1186 | default: |
1123 | duprintf("do_arpt_get_ctl: unknown request %i\n", cmd); | 1187 | duprintf("do_arpt_get_ctl: unknown request %i\n", cmd); |
1124 | ret = -EINVAL; | 1188 | ret = -EINVAL; |
@@ -1136,12 +1200,9 @@ int arpt_register_target(struct arpt_target *target) | |||
1136 | if (ret != 0) | 1200 | if (ret != 0) |
1137 | return ret; | 1201 | return ret; |
1138 | 1202 | ||
1139 | if (!list_named_insert(&arpt_target, target)) { | 1203 | list_add(&target->list, &arpt_target); |
1140 | duprintf("arpt_register_target: `%s' already in list!\n", | ||
1141 | target->name); | ||
1142 | ret = -EINVAL; | ||
1143 | } | ||
1144 | up(&arpt_mutex); | 1204 | up(&arpt_mutex); |
1205 | |||
1145 | return ret; | 1206 | return ret; |
1146 | } | 1207 | } |
1147 | 1208 | ||
diff --git a/net/ipv4/netfilter/ipt_addrtype.c b/net/ipv4/netfilter/ipt_addrtype.c index f5909a4c3fc7..e19c2a52d00c 100644 --- a/net/ipv4/netfilter/ipt_addrtype.c +++ b/net/ipv4/netfilter/ipt_addrtype.c | |||
@@ -48,7 +48,7 @@ static int checkentry(const char *tablename, const struct ipt_ip *ip, | |||
48 | unsigned int hook_mask) | 48 | unsigned int hook_mask) |
49 | { | 49 | { |
50 | if (matchsize != IPT_ALIGN(sizeof(struct ipt_addrtype_info))) { | 50 | if (matchsize != IPT_ALIGN(sizeof(struct ipt_addrtype_info))) { |
51 | printk(KERN_ERR "ipt_addrtype: invalid size (%u != %Zu)\n.", | 51 | printk(KERN_ERR "ipt_addrtype: invalid size (%u != %Zu)\n", |
52 | matchsize, IPT_ALIGN(sizeof(struct ipt_addrtype_info))); | 52 | matchsize, IPT_ALIGN(sizeof(struct ipt_addrtype_info))); |
53 | return 0; | 53 | return 0; |
54 | } | 54 | } |
diff --git a/net/ipv4/tcp_bic.c b/net/ipv4/tcp_bic.c index 6d80e063c187..ae35e0609047 100644 --- a/net/ipv4/tcp_bic.c +++ b/net/ipv4/tcp_bic.c | |||
@@ -27,7 +27,7 @@ | |||
27 | */ | 27 | */ |
28 | 28 | ||
29 | static int fast_convergence = 1; | 29 | static int fast_convergence = 1; |
30 | static int max_increment = 32; | 30 | static int max_increment = 16; |
31 | static int low_window = 14; | 31 | static int low_window = 14; |
32 | static int beta = 819; /* = 819/1024 (BICTCP_BETA_SCALE) */ | 32 | static int beta = 819; /* = 819/1024 (BICTCP_BETA_SCALE) */ |
33 | static int low_utilization_threshold = 153; | 33 | static int low_utilization_threshold = 153; |
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index a970b4727ce8..2c5f57299d63 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c | |||
@@ -75,7 +75,7 @@ | |||
75 | #ifdef CONFIG_IPV6_PRIVACY | 75 | #ifdef CONFIG_IPV6_PRIVACY |
76 | #include <linux/random.h> | 76 | #include <linux/random.h> |
77 | #include <linux/crypto.h> | 77 | #include <linux/crypto.h> |
78 | #include <asm/scatterlist.h> | 78 | #include <linux/scatterlist.h> |
79 | #endif | 79 | #endif |
80 | 80 | ||
81 | #include <asm/uaccess.h> | 81 | #include <asm/uaccess.h> |
@@ -1217,12 +1217,8 @@ static int __ipv6_regen_rndid(struct inet6_dev *idev) | |||
1217 | struct net_device *dev; | 1217 | struct net_device *dev; |
1218 | struct scatterlist sg[2]; | 1218 | struct scatterlist sg[2]; |
1219 | 1219 | ||
1220 | sg[0].page = virt_to_page(idev->entropy); | 1220 | sg_set_buf(&sg[0], idev->entropy, 8); |
1221 | sg[0].offset = offset_in_page(idev->entropy); | 1221 | sg_set_buf(&sg[1], idev->work_eui64, 8); |
1222 | sg[0].length = 8; | ||
1223 | sg[1].page = virt_to_page(idev->work_eui64); | ||
1224 | sg[1].offset = offset_in_page(idev->work_eui64); | ||
1225 | sg[1].length = 8; | ||
1226 | 1222 | ||
1227 | dev = idev->dev; | 1223 | dev = idev->dev; |
1228 | 1224 | ||
@@ -2167,7 +2163,7 @@ static int addrconf_ifdown(struct net_device *dev, int how) | |||
2167 | 2163 | ||
2168 | /* Step 5: netlink notification of this interface */ | 2164 | /* Step 5: netlink notification of this interface */ |
2169 | idev->tstamp = jiffies; | 2165 | idev->tstamp = jiffies; |
2170 | inet6_ifinfo_notify(RTM_NEWLINK, idev); | 2166 | inet6_ifinfo_notify(RTM_DELLINK, idev); |
2171 | 2167 | ||
2172 | /* Shot the device (if unregistered) */ | 2168 | /* Shot the device (if unregistered) */ |
2173 | 2169 | ||
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index 563b442ffab8..614296a920c6 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c | |||
@@ -147,7 +147,8 @@ static int ip6_output2(struct sk_buff *skb) | |||
147 | 147 | ||
148 | int ip6_output(struct sk_buff *skb) | 148 | int ip6_output(struct sk_buff *skb) |
149 | { | 149 | { |
150 | if (skb->len > dst_mtu(skb->dst) || dst_allfrag(skb->dst)) | 150 | if ((skb->len > dst_mtu(skb->dst) && !skb_shinfo(skb)->ufo_size) || |
151 | dst_allfrag(skb->dst)) | ||
151 | return ip6_fragment(skb, ip6_output2); | 152 | return ip6_fragment(skb, ip6_output2); |
152 | else | 153 | else |
153 | return ip6_output2(skb); | 154 | return ip6_output2(skb); |
@@ -768,6 +769,65 @@ out_err_release: | |||
768 | *dst = NULL; | 769 | *dst = NULL; |
769 | return err; | 770 | return err; |
770 | } | 771 | } |
772 | inline int ip6_ufo_append_data(struct sock *sk, | ||
773 | int getfrag(void *from, char *to, int offset, int len, | ||
774 | int odd, struct sk_buff *skb), | ||
775 | void *from, int length, int hh_len, int fragheaderlen, | ||
776 | int transhdrlen, int mtu,unsigned int flags) | ||
777 | |||
778 | { | ||
779 | struct sk_buff *skb; | ||
780 | int err; | ||
781 | |||
782 | /* There is support for UDP large send offload by network | ||
783 | * device, so create one single skb packet containing complete | ||
784 | * udp datagram | ||
785 | */ | ||
786 | if ((skb = skb_peek_tail(&sk->sk_write_queue)) == NULL) { | ||
787 | skb = sock_alloc_send_skb(sk, | ||
788 | hh_len + fragheaderlen + transhdrlen + 20, | ||
789 | (flags & MSG_DONTWAIT), &err); | ||
790 | if (skb == NULL) | ||
791 | return -ENOMEM; | ||
792 | |||
793 | /* reserve space for Hardware header */ | ||
794 | skb_reserve(skb, hh_len); | ||
795 | |||
796 | /* create space for UDP/IP header */ | ||
797 | skb_put(skb,fragheaderlen + transhdrlen); | ||
798 | |||
799 | /* initialize network header pointer */ | ||
800 | skb->nh.raw = skb->data; | ||
801 | |||
802 | /* initialize protocol header pointer */ | ||
803 | skb->h.raw = skb->data + fragheaderlen; | ||
804 | |||
805 | skb->ip_summed = CHECKSUM_HW; | ||
806 | skb->csum = 0; | ||
807 | sk->sk_sndmsg_off = 0; | ||
808 | } | ||
809 | |||
810 | err = skb_append_datato_frags(sk,skb, getfrag, from, | ||
811 | (length - transhdrlen)); | ||
812 | if (!err) { | ||
813 | struct frag_hdr fhdr; | ||
814 | |||
815 | /* specify the length of each IP datagram fragment*/ | ||
816 | skb_shinfo(skb)->ufo_size = (mtu - fragheaderlen) - | ||
817 | sizeof(struct frag_hdr); | ||
818 | ipv6_select_ident(skb, &fhdr); | ||
819 | skb_shinfo(skb)->ip6_frag_id = fhdr.identification; | ||
820 | __skb_queue_tail(&sk->sk_write_queue, skb); | ||
821 | |||
822 | return 0; | ||
823 | } | ||
824 | /* There is not enough support do UPD LSO, | ||
825 | * so follow normal path | ||
826 | */ | ||
827 | kfree_skb(skb); | ||
828 | |||
829 | return err; | ||
830 | } | ||
771 | 831 | ||
772 | int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to, | 832 | int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to, |
773 | int offset, int len, int odd, struct sk_buff *skb), | 833 | int offset, int len, int odd, struct sk_buff *skb), |
@@ -860,6 +920,15 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to, | |||
860 | */ | 920 | */ |
861 | 921 | ||
862 | inet->cork.length += length; | 922 | inet->cork.length += length; |
923 | if (((length > mtu) && (sk->sk_protocol == IPPROTO_UDP)) && | ||
924 | (rt->u.dst.dev->features & NETIF_F_UFO)) { | ||
925 | |||
926 | if(ip6_ufo_append_data(sk, getfrag, from, length, hh_len, | ||
927 | fragheaderlen, transhdrlen, mtu, flags)) | ||
928 | goto error; | ||
929 | |||
930 | return 0; | ||
931 | } | ||
863 | 932 | ||
864 | if ((skb = skb_peek_tail(&sk->sk_write_queue)) == NULL) | 933 | if ((skb = skb_peek_tail(&sk->sk_write_queue)) == NULL) |
865 | goto alloc_new_skb; | 934 | goto alloc_new_skb; |
diff --git a/net/ipv6/mcast.c b/net/ipv6/mcast.c index 39a96c768102..f15e04ad026e 100644 --- a/net/ipv6/mcast.c +++ b/net/ipv6/mcast.c | |||
@@ -164,7 +164,7 @@ static int ip6_mc_leave_src(struct sock *sk, struct ipv6_mc_socklist *iml, | |||
164 | #define MLDV2_MASK(value, nb) ((nb)>=32 ? (value) : ((1<<(nb))-1) & (value)) | 164 | #define MLDV2_MASK(value, nb) ((nb)>=32 ? (value) : ((1<<(nb))-1) & (value)) |
165 | #define MLDV2_EXP(thresh, nbmant, nbexp, value) \ | 165 | #define MLDV2_EXP(thresh, nbmant, nbexp, value) \ |
166 | ((value) < (thresh) ? (value) : \ | 166 | ((value) < (thresh) ? (value) : \ |
167 | ((MLDV2_MASK(value, nbmant) | (1<<(nbmant+nbexp))) << \ | 167 | ((MLDV2_MASK(value, nbmant) | (1<<(nbmant))) << \ |
168 | (MLDV2_MASK((value) >> (nbmant), nbexp) + (nbexp)))) | 168 | (MLDV2_MASK((value) >> (nbmant), nbexp) + (nbexp)))) |
169 | 169 | ||
170 | #define MLDV2_QQIC(value) MLDV2_EXP(0x80, 4, 3, value) | 170 | #define MLDV2_QQIC(value) MLDV2_EXP(0x80, 4, 3, value) |
@@ -545,8 +545,10 @@ int ip6_mc_msfilter(struct sock *sk, struct group_filter *gsf) | |||
545 | sock_kfree_s(sk, newpsl, IP6_SFLSIZE(newpsl->sl_max)); | 545 | sock_kfree_s(sk, newpsl, IP6_SFLSIZE(newpsl->sl_max)); |
546 | goto done; | 546 | goto done; |
547 | } | 547 | } |
548 | } else | 548 | } else { |
549 | newpsl = NULL; | 549 | newpsl = NULL; |
550 | (void) ip6_mc_add_src(idev, group, gsf->gf_fmode, 0, NULL, 0); | ||
551 | } | ||
550 | psl = pmc->sflist; | 552 | psl = pmc->sflist; |
551 | if (psl) { | 553 | if (psl) { |
552 | (void) ip6_mc_del_src(idev, group, pmc->sfmode, | 554 | (void) ip6_mc_del_src(idev, group, pmc->sfmode, |
@@ -1087,7 +1089,7 @@ static void mld_marksources(struct ifmcaddr6 *pmc, int nsrcs, | |||
1087 | 1089 | ||
1088 | int igmp6_event_query(struct sk_buff *skb) | 1090 | int igmp6_event_query(struct sk_buff *skb) |
1089 | { | 1091 | { |
1090 | struct mld2_query *mlh2 = (struct mld2_query *) skb->h.raw; | 1092 | struct mld2_query *mlh2 = NULL; |
1091 | struct ifmcaddr6 *ma; | 1093 | struct ifmcaddr6 *ma; |
1092 | struct in6_addr *group; | 1094 | struct in6_addr *group; |
1093 | unsigned long max_delay; | 1095 | unsigned long max_delay; |
@@ -1140,6 +1142,13 @@ int igmp6_event_query(struct sk_buff *skb) | |||
1140 | /* clear deleted report items */ | 1142 | /* clear deleted report items */ |
1141 | mld_clear_delrec(idev); | 1143 | mld_clear_delrec(idev); |
1142 | } else if (len >= 28) { | 1144 | } else if (len >= 28) { |
1145 | int srcs_offset = sizeof(struct mld2_query) - | ||
1146 | sizeof(struct icmp6hdr); | ||
1147 | if (!pskb_may_pull(skb, srcs_offset)) { | ||
1148 | in6_dev_put(idev); | ||
1149 | return -EINVAL; | ||
1150 | } | ||
1151 | mlh2 = (struct mld2_query *) skb->h.raw; | ||
1143 | max_delay = (MLDV2_MRC(ntohs(mlh2->mrc))*HZ)/1000; | 1152 | max_delay = (MLDV2_MRC(ntohs(mlh2->mrc))*HZ)/1000; |
1144 | if (!max_delay) | 1153 | if (!max_delay) |
1145 | max_delay = 1; | 1154 | max_delay = 1; |
@@ -1156,7 +1165,15 @@ int igmp6_event_query(struct sk_buff *skb) | |||
1156 | return 0; | 1165 | return 0; |
1157 | } | 1166 | } |
1158 | /* mark sources to include, if group & source-specific */ | 1167 | /* mark sources to include, if group & source-specific */ |
1159 | mark = mlh2->nsrcs != 0; | 1168 | if (mlh2->nsrcs != 0) { |
1169 | if (!pskb_may_pull(skb, srcs_offset + | ||
1170 | mlh2->nsrcs * sizeof(struct in6_addr))) { | ||
1171 | in6_dev_put(idev); | ||
1172 | return -EINVAL; | ||
1173 | } | ||
1174 | mlh2 = (struct mld2_query *) skb->h.raw; | ||
1175 | mark = 1; | ||
1176 | } | ||
1160 | } else { | 1177 | } else { |
1161 | in6_dev_put(idev); | 1178 | in6_dev_put(idev); |
1162 | return -EINVAL; | 1179 | return -EINVAL; |
diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c index 21deec25a12b..7d492226c16e 100644 --- a/net/ipv6/netfilter/ip6_tables.c +++ b/net/ipv6/netfilter/ip6_tables.c | |||
@@ -2,7 +2,7 @@ | |||
2 | * Packet matching code. | 2 | * Packet matching code. |
3 | * | 3 | * |
4 | * Copyright (C) 1999 Paul `Rusty' Russell & Michael J. Neuling | 4 | * Copyright (C) 1999 Paul `Rusty' Russell & Michael J. Neuling |
5 | * Copyright (C) 2000-2002 Netfilter core team <coreteam@netfilter.org> | 5 | * Copyright (C) 2000-2005 Netfilter Core Team <coreteam@netfilter.org> |
6 | * | 6 | * |
7 | * This program is free software; you can redistribute it and/or modify | 7 | * This program is free software; you can redistribute it and/or modify |
8 | * it under the terms of the GNU General Public License version 2 as | 8 | * it under the terms of the GNU General Public License version 2 as |
@@ -23,7 +23,6 @@ | |||
23 | #include <linux/tcp.h> | 23 | #include <linux/tcp.h> |
24 | #include <linux/udp.h> | 24 | #include <linux/udp.h> |
25 | #include <linux/icmpv6.h> | 25 | #include <linux/icmpv6.h> |
26 | #include <net/ip.h> | ||
27 | #include <net/ipv6.h> | 26 | #include <net/ipv6.h> |
28 | #include <asm/uaccess.h> | 27 | #include <asm/uaccess.h> |
29 | #include <asm/semaphore.h> | 28 | #include <asm/semaphore.h> |
@@ -80,13 +79,12 @@ static DECLARE_MUTEX(ip6t_mutex); | |||
80 | #define inline | 79 | #define inline |
81 | #endif | 80 | #endif |
82 | 81 | ||
83 | /* Locking is simple: we assume at worst case there will be one packet | 82 | /* |
84 | in user context and one from bottom halves (or soft irq if Alexey's | ||
85 | softnet patch was applied). | ||
86 | |||
87 | We keep a set of rules for each CPU, so we can avoid write-locking | 83 | We keep a set of rules for each CPU, so we can avoid write-locking |
88 | them; doing a readlock_bh() stops packets coming through if we're | 84 | them in the softirq when updating the counters and therefore |
89 | in user context. | 85 | only need to read-lock in the softirq; doing a write_lock_bh() in user |
86 | context stops packets coming through and allows user context to read | ||
87 | the counters or update the rules. | ||
90 | 88 | ||
91 | To be cache friendly on SMP, we arrange them like so: | 89 | To be cache friendly on SMP, we arrange them like so: |
92 | [ n-entries ] | 90 | [ n-entries ] |
@@ -356,7 +354,7 @@ ip6t_do_table(struct sk_buff **pskb, | |||
356 | struct ip6t_table *table, | 354 | struct ip6t_table *table, |
357 | void *userdata) | 355 | void *userdata) |
358 | { | 356 | { |
359 | static const char nulldevname[IFNAMSIZ]; | 357 | static const char nulldevname[IFNAMSIZ] __attribute__((aligned(sizeof(long)))); |
360 | int offset = 0; | 358 | int offset = 0; |
361 | unsigned int protoff = 0; | 359 | unsigned int protoff = 0; |
362 | int hotdrop = 0; | 360 | int hotdrop = 0; |
@@ -369,7 +367,6 @@ ip6t_do_table(struct sk_buff **pskb, | |||
369 | /* Initialization */ | 367 | /* Initialization */ |
370 | indev = in ? in->name : nulldevname; | 368 | indev = in ? in->name : nulldevname; |
371 | outdev = out ? out->name : nulldevname; | 369 | outdev = out ? out->name : nulldevname; |
372 | |||
373 | /* We handle fragments by dealing with the first fragment as | 370 | /* We handle fragments by dealing with the first fragment as |
374 | * if it was a normal packet. All other fragments are treated | 371 | * if it was a normal packet. All other fragments are treated |
375 | * normally, except that they will NEVER match rules that ask | 372 | * normally, except that they will NEVER match rules that ask |
@@ -497,75 +494,145 @@ ip6t_do_table(struct sk_buff **pskb, | |||
497 | #endif | 494 | #endif |
498 | } | 495 | } |
499 | 496 | ||
500 | /* If it succeeds, returns element and locks mutex */ | 497 | /* |
501 | static inline void * | 498 | * These are weird, but module loading must not be done with mutex |
502 | find_inlist_lock_noload(struct list_head *head, | 499 | * held (since they will register), and we have to have a single |
503 | const char *name, | 500 | * function to use try_then_request_module(). |
504 | int *error, | 501 | */ |
505 | struct semaphore *mutex) | 502 | |
503 | /* Find table by name, grabs mutex & ref. Returns ERR_PTR() on error. */ | ||
504 | static inline struct ip6t_table *find_table_lock(const char *name) | ||
506 | { | 505 | { |
507 | void *ret; | 506 | struct ip6t_table *t; |
508 | 507 | ||
509 | #if 1 | 508 | if (down_interruptible(&ip6t_mutex) != 0) |
510 | duprintf("find_inlist: searching for `%s' in %s.\n", | 509 | return ERR_PTR(-EINTR); |
511 | name, head == &ip6t_target ? "ip6t_target" | ||
512 | : head == &ip6t_match ? "ip6t_match" | ||
513 | : head == &ip6t_tables ? "ip6t_tables" : "UNKNOWN"); | ||
514 | #endif | ||
515 | 510 | ||
516 | *error = down_interruptible(mutex); | 511 | list_for_each_entry(t, &ip6t_tables, list) |
517 | if (*error != 0) | 512 | if (strcmp(t->name, name) == 0 && try_module_get(t->me)) |
518 | return NULL; | 513 | return t; |
514 | up(&ip6t_mutex); | ||
515 | return NULL; | ||
516 | } | ||
517 | |||
518 | /* Find match, grabs ref. Returns ERR_PTR() on error. */ | ||
519 | static inline struct ip6t_match *find_match(const char *name, u8 revision) | ||
520 | { | ||
521 | struct ip6t_match *m; | ||
522 | int err = 0; | ||
519 | 523 | ||
520 | ret = list_named_find(head, name); | 524 | if (down_interruptible(&ip6t_mutex) != 0) |
521 | if (!ret) { | 525 | return ERR_PTR(-EINTR); |
522 | *error = -ENOENT; | 526 | |
523 | up(mutex); | 527 | list_for_each_entry(m, &ip6t_match, list) { |
528 | if (strcmp(m->name, name) == 0) { | ||
529 | if (m->revision == revision) { | ||
530 | if (try_module_get(m->me)) { | ||
531 | up(&ip6t_mutex); | ||
532 | return m; | ||
533 | } | ||
534 | } else | ||
535 | err = -EPROTOTYPE; /* Found something. */ | ||
536 | } | ||
524 | } | 537 | } |
525 | return ret; | 538 | up(&ip6t_mutex); |
539 | return ERR_PTR(err); | ||
526 | } | 540 | } |
527 | 541 | ||
528 | #ifndef CONFIG_KMOD | 542 | /* Find target, grabs ref. Returns ERR_PTR() on error. */ |
529 | #define find_inlist_lock(h,n,p,e,m) find_inlist_lock_noload((h),(n),(e),(m)) | 543 | static inline struct ip6t_target *find_target(const char *name, u8 revision) |
530 | #else | ||
531 | static void * | ||
532 | find_inlist_lock(struct list_head *head, | ||
533 | const char *name, | ||
534 | const char *prefix, | ||
535 | int *error, | ||
536 | struct semaphore *mutex) | ||
537 | { | 544 | { |
538 | void *ret; | 545 | struct ip6t_target *t; |
546 | int err = 0; | ||
539 | 547 | ||
540 | ret = find_inlist_lock_noload(head, name, error, mutex); | 548 | if (down_interruptible(&ip6t_mutex) != 0) |
541 | if (!ret) { | 549 | return ERR_PTR(-EINTR); |
542 | duprintf("find_inlist: loading `%s%s'.\n", prefix, name); | 550 | |
543 | request_module("%s%s", prefix, name); | 551 | list_for_each_entry(t, &ip6t_target, list) { |
544 | ret = find_inlist_lock_noload(head, name, error, mutex); | 552 | if (strcmp(t->name, name) == 0) { |
553 | if (t->revision == revision) { | ||
554 | if (try_module_get(t->me)) { | ||
555 | up(&ip6t_mutex); | ||
556 | return t; | ||
557 | } | ||
558 | } else | ||
559 | err = -EPROTOTYPE; /* Found something. */ | ||
560 | } | ||
545 | } | 561 | } |
562 | up(&ip6t_mutex); | ||
563 | return ERR_PTR(err); | ||
564 | } | ||
546 | 565 | ||
547 | return ret; | 566 | struct ip6t_target *ip6t_find_target(const char *name, u8 revision) |
567 | { | ||
568 | struct ip6t_target *target; | ||
569 | |||
570 | target = try_then_request_module(find_target(name, revision), | ||
571 | "ip6t_%s", name); | ||
572 | if (IS_ERR(target) || !target) | ||
573 | return NULL; | ||
574 | return target; | ||
548 | } | 575 | } |
549 | #endif | ||
550 | 576 | ||
551 | static inline struct ip6t_table * | 577 | static int match_revfn(const char *name, u8 revision, int *bestp) |
552 | ip6t_find_table_lock(const char *name, int *error, struct semaphore *mutex) | ||
553 | { | 578 | { |
554 | return find_inlist_lock(&ip6t_tables, name, "ip6table_", error, mutex); | 579 | struct ip6t_match *m; |
580 | int have_rev = 0; | ||
581 | |||
582 | list_for_each_entry(m, &ip6t_match, list) { | ||
583 | if (strcmp(m->name, name) == 0) { | ||
584 | if (m->revision > *bestp) | ||
585 | *bestp = m->revision; | ||
586 | if (m->revision == revision) | ||
587 | have_rev = 1; | ||
588 | } | ||
589 | } | ||
590 | return have_rev; | ||
555 | } | 591 | } |
556 | 592 | ||
557 | static inline struct ip6t_match * | 593 | static int target_revfn(const char *name, u8 revision, int *bestp) |
558 | find_match_lock(const char *name, int *error, struct semaphore *mutex) | ||
559 | { | 594 | { |
560 | return find_inlist_lock(&ip6t_match, name, "ip6t_", error, mutex); | 595 | struct ip6t_target *t; |
596 | int have_rev = 0; | ||
597 | |||
598 | list_for_each_entry(t, &ip6t_target, list) { | ||
599 | if (strcmp(t->name, name) == 0) { | ||
600 | if (t->revision > *bestp) | ||
601 | *bestp = t->revision; | ||
602 | if (t->revision == revision) | ||
603 | have_rev = 1; | ||
604 | } | ||
605 | } | ||
606 | return have_rev; | ||
561 | } | 607 | } |
562 | 608 | ||
563 | static struct ip6t_target * | 609 | /* Returns true or fals (if no such extension at all) */ |
564 | ip6t_find_target_lock(const char *name, int *error, struct semaphore *mutex) | 610 | static inline int find_revision(const char *name, u8 revision, |
611 | int (*revfn)(const char *, u8, int *), | ||
612 | int *err) | ||
565 | { | 613 | { |
566 | return find_inlist_lock(&ip6t_target, name, "ip6t_", error, mutex); | 614 | int have_rev, best = -1; |
615 | |||
616 | if (down_interruptible(&ip6t_mutex) != 0) { | ||
617 | *err = -EINTR; | ||
618 | return 1; | ||
619 | } | ||
620 | have_rev = revfn(name, revision, &best); | ||
621 | up(&ip6t_mutex); | ||
622 | |||
623 | /* Nothing at all? Return 0 to try loading module. */ | ||
624 | if (best == -1) { | ||
625 | *err = -ENOENT; | ||
626 | return 0; | ||
627 | } | ||
628 | |||
629 | *err = best; | ||
630 | if (!have_rev) | ||
631 | *err = -EPROTONOSUPPORT; | ||
632 | return 1; | ||
567 | } | 633 | } |
568 | 634 | ||
635 | |||
569 | /* All zeroes == unconditional rule. */ | 636 | /* All zeroes == unconditional rule. */ |
570 | static inline int | 637 | static inline int |
571 | unconditional(const struct ip6t_ip6 *ipv6) | 638 | unconditional(const struct ip6t_ip6 *ipv6) |
@@ -725,20 +792,16 @@ check_match(struct ip6t_entry_match *m, | |||
725 | unsigned int hookmask, | 792 | unsigned int hookmask, |
726 | unsigned int *i) | 793 | unsigned int *i) |
727 | { | 794 | { |
728 | int ret; | ||
729 | struct ip6t_match *match; | 795 | struct ip6t_match *match; |
730 | 796 | ||
731 | match = find_match_lock(m->u.user.name, &ret, &ip6t_mutex); | 797 | match = try_then_request_module(find_match(m->u.user.name, |
732 | if (!match) { | 798 | m->u.user.revision), |
733 | // duprintf("check_match: `%s' not found\n", m->u.name); | 799 | "ip6t_%s", m->u.user.name); |
734 | return ret; | 800 | if (IS_ERR(match) || !match) { |
735 | } | 801 | duprintf("check_match: `%s' not found\n", m->u.user.name); |
736 | if (!try_module_get(match->me)) { | 802 | return match ? PTR_ERR(match) : -ENOENT; |
737 | up(&ip6t_mutex); | ||
738 | return -ENOENT; | ||
739 | } | 803 | } |
740 | m->u.kernel.match = match; | 804 | m->u.kernel.match = match; |
741 | up(&ip6t_mutex); | ||
742 | 805 | ||
743 | if (m->u.kernel.match->checkentry | 806 | if (m->u.kernel.match->checkentry |
744 | && !m->u.kernel.match->checkentry(name, ipv6, m->data, | 807 | && !m->u.kernel.match->checkentry(name, ipv6, m->data, |
@@ -776,22 +839,16 @@ check_entry(struct ip6t_entry *e, const char *name, unsigned int size, | |||
776 | goto cleanup_matches; | 839 | goto cleanup_matches; |
777 | 840 | ||
778 | t = ip6t_get_target(e); | 841 | t = ip6t_get_target(e); |
779 | target = ip6t_find_target_lock(t->u.user.name, &ret, &ip6t_mutex); | 842 | target = try_then_request_module(find_target(t->u.user.name, |
780 | if (!target) { | 843 | t->u.user.revision), |
844 | "ip6t_%s", t->u.user.name); | ||
845 | if (IS_ERR(target) || !target) { | ||
781 | duprintf("check_entry: `%s' not found\n", t->u.user.name); | 846 | duprintf("check_entry: `%s' not found\n", t->u.user.name); |
782 | goto cleanup_matches; | 847 | ret = target ? PTR_ERR(target) : -ENOENT; |
783 | } | ||
784 | if (!try_module_get(target->me)) { | ||
785 | up(&ip6t_mutex); | ||
786 | ret = -ENOENT; | ||
787 | goto cleanup_matches; | 848 | goto cleanup_matches; |
788 | } | 849 | } |
789 | t->u.kernel.target = target; | 850 | t->u.kernel.target = target; |
790 | up(&ip6t_mutex); | 851 | |
791 | if (!t->u.kernel.target) { | ||
792 | ret = -EBUSY; | ||
793 | goto cleanup_matches; | ||
794 | } | ||
795 | if (t->u.kernel.target == &ip6t_standard_target) { | 852 | if (t->u.kernel.target == &ip6t_standard_target) { |
796 | if (!standard_check(t, size)) { | 853 | if (!standard_check(t, size)) { |
797 | ret = -EINVAL; | 854 | ret = -EINVAL; |
@@ -1118,8 +1175,8 @@ get_entries(const struct ip6t_get_entries *entries, | |||
1118 | int ret; | 1175 | int ret; |
1119 | struct ip6t_table *t; | 1176 | struct ip6t_table *t; |
1120 | 1177 | ||
1121 | t = ip6t_find_table_lock(entries->name, &ret, &ip6t_mutex); | 1178 | t = find_table_lock(entries->name); |
1122 | if (t) { | 1179 | if (t && !IS_ERR(t)) { |
1123 | duprintf("t->private->number = %u\n", | 1180 | duprintf("t->private->number = %u\n", |
1124 | t->private->number); | 1181 | t->private->number); |
1125 | if (entries->size == t->private->size) | 1182 | if (entries->size == t->private->size) |
@@ -1131,10 +1188,10 @@ get_entries(const struct ip6t_get_entries *entries, | |||
1131 | entries->size); | 1188 | entries->size); |
1132 | ret = -EINVAL; | 1189 | ret = -EINVAL; |
1133 | } | 1190 | } |
1191 | module_put(t->me); | ||
1134 | up(&ip6t_mutex); | 1192 | up(&ip6t_mutex); |
1135 | } else | 1193 | } else |
1136 | duprintf("get_entries: Can't find %s!\n", | 1194 | ret = t ? PTR_ERR(t) : -ENOENT; |
1137 | entries->name); | ||
1138 | 1195 | ||
1139 | return ret; | 1196 | return ret; |
1140 | } | 1197 | } |
@@ -1182,22 +1239,19 @@ do_replace(void __user *user, unsigned int len) | |||
1182 | 1239 | ||
1183 | duprintf("ip_tables: Translated table\n"); | 1240 | duprintf("ip_tables: Translated table\n"); |
1184 | 1241 | ||
1185 | t = ip6t_find_table_lock(tmp.name, &ret, &ip6t_mutex); | 1242 | t = try_then_request_module(find_table_lock(tmp.name), |
1186 | if (!t) | 1243 | "ip6table_%s", tmp.name); |
1244 | if (!t || IS_ERR(t)) { | ||
1245 | ret = t ? PTR_ERR(t) : -ENOENT; | ||
1187 | goto free_newinfo_counters_untrans; | 1246 | goto free_newinfo_counters_untrans; |
1247 | } | ||
1188 | 1248 | ||
1189 | /* You lied! */ | 1249 | /* You lied! */ |
1190 | if (tmp.valid_hooks != t->valid_hooks) { | 1250 | if (tmp.valid_hooks != t->valid_hooks) { |
1191 | duprintf("Valid hook crap: %08X vs %08X\n", | 1251 | duprintf("Valid hook crap: %08X vs %08X\n", |
1192 | tmp.valid_hooks, t->valid_hooks); | 1252 | tmp.valid_hooks, t->valid_hooks); |
1193 | ret = -EINVAL; | 1253 | ret = -EINVAL; |
1194 | goto free_newinfo_counters_untrans_unlock; | 1254 | goto put_module; |
1195 | } | ||
1196 | |||
1197 | /* Get a reference in advance, we're not allowed fail later */ | ||
1198 | if (!try_module_get(t->me)) { | ||
1199 | ret = -EBUSY; | ||
1200 | goto free_newinfo_counters_untrans_unlock; | ||
1201 | } | 1255 | } |
1202 | 1256 | ||
1203 | oldinfo = replace_table(t, tmp.num_counters, newinfo, &ret); | 1257 | oldinfo = replace_table(t, tmp.num_counters, newinfo, &ret); |
@@ -1219,7 +1273,6 @@ do_replace(void __user *user, unsigned int len) | |||
1219 | /* Decrease module usage counts and free resource */ | 1273 | /* Decrease module usage counts and free resource */ |
1220 | IP6T_ENTRY_ITERATE(oldinfo->entries, oldinfo->size, cleanup_entry,NULL); | 1274 | IP6T_ENTRY_ITERATE(oldinfo->entries, oldinfo->size, cleanup_entry,NULL); |
1221 | vfree(oldinfo); | 1275 | vfree(oldinfo); |
1222 | /* Silent error: too late now. */ | ||
1223 | if (copy_to_user(tmp.counters, counters, | 1276 | if (copy_to_user(tmp.counters, counters, |
1224 | sizeof(struct ip6t_counters) * tmp.num_counters) != 0) | 1277 | sizeof(struct ip6t_counters) * tmp.num_counters) != 0) |
1225 | ret = -EFAULT; | 1278 | ret = -EFAULT; |
@@ -1229,7 +1282,6 @@ do_replace(void __user *user, unsigned int len) | |||
1229 | 1282 | ||
1230 | put_module: | 1283 | put_module: |
1231 | module_put(t->me); | 1284 | module_put(t->me); |
1232 | free_newinfo_counters_untrans_unlock: | ||
1233 | up(&ip6t_mutex); | 1285 | up(&ip6t_mutex); |
1234 | free_newinfo_counters_untrans: | 1286 | free_newinfo_counters_untrans: |
1235 | IP6T_ENTRY_ITERATE(newinfo->entries, newinfo->size, cleanup_entry,NULL); | 1287 | IP6T_ENTRY_ITERATE(newinfo->entries, newinfo->size, cleanup_entry,NULL); |
@@ -1268,7 +1320,7 @@ do_add_counters(void __user *user, unsigned int len) | |||
1268 | unsigned int i; | 1320 | unsigned int i; |
1269 | struct ip6t_counters_info tmp, *paddc; | 1321 | struct ip6t_counters_info tmp, *paddc; |
1270 | struct ip6t_table *t; | 1322 | struct ip6t_table *t; |
1271 | int ret; | 1323 | int ret = 0; |
1272 | 1324 | ||
1273 | if (copy_from_user(&tmp, user, sizeof(tmp)) != 0) | 1325 | if (copy_from_user(&tmp, user, sizeof(tmp)) != 0) |
1274 | return -EFAULT; | 1326 | return -EFAULT; |
@@ -1285,9 +1337,11 @@ do_add_counters(void __user *user, unsigned int len) | |||
1285 | goto free; | 1337 | goto free; |
1286 | } | 1338 | } |
1287 | 1339 | ||
1288 | t = ip6t_find_table_lock(tmp.name, &ret, &ip6t_mutex); | 1340 | t = find_table_lock(tmp.name); |
1289 | if (!t) | 1341 | if (!t || IS_ERR(t)) { |
1342 | ret = t ? PTR_ERR(t) : -ENOENT; | ||
1290 | goto free; | 1343 | goto free; |
1344 | } | ||
1291 | 1345 | ||
1292 | write_lock_bh(&t->lock); | 1346 | write_lock_bh(&t->lock); |
1293 | if (t->private->number != paddc->num_counters) { | 1347 | if (t->private->number != paddc->num_counters) { |
@@ -1304,6 +1358,7 @@ do_add_counters(void __user *user, unsigned int len) | |||
1304 | unlock_up_free: | 1358 | unlock_up_free: |
1305 | write_unlock_bh(&t->lock); | 1359 | write_unlock_bh(&t->lock); |
1306 | up(&ip6t_mutex); | 1360 | up(&ip6t_mutex); |
1361 | module_put(t->me); | ||
1307 | free: | 1362 | free: |
1308 | vfree(paddc); | 1363 | vfree(paddc); |
1309 | 1364 | ||
@@ -1360,8 +1415,10 @@ do_ip6t_get_ctl(struct sock *sk, int cmd, void __user *user, int *len) | |||
1360 | break; | 1415 | break; |
1361 | } | 1416 | } |
1362 | name[IP6T_TABLE_MAXNAMELEN-1] = '\0'; | 1417 | name[IP6T_TABLE_MAXNAMELEN-1] = '\0'; |
1363 | t = ip6t_find_table_lock(name, &ret, &ip6t_mutex); | 1418 | |
1364 | if (t) { | 1419 | t = try_then_request_module(find_table_lock(name), |
1420 | "ip6table_%s", name); | ||
1421 | if (t && !IS_ERR(t)) { | ||
1365 | struct ip6t_getinfo info; | 1422 | struct ip6t_getinfo info; |
1366 | 1423 | ||
1367 | info.valid_hooks = t->valid_hooks; | 1424 | info.valid_hooks = t->valid_hooks; |
@@ -1377,9 +1434,10 @@ do_ip6t_get_ctl(struct sock *sk, int cmd, void __user *user, int *len) | |||
1377 | ret = -EFAULT; | 1434 | ret = -EFAULT; |
1378 | else | 1435 | else |
1379 | ret = 0; | 1436 | ret = 0; |
1380 | |||
1381 | up(&ip6t_mutex); | 1437 | up(&ip6t_mutex); |
1382 | } | 1438 | module_put(t->me); |
1439 | } else | ||
1440 | ret = t ? PTR_ERR(t) : -ENOENT; | ||
1383 | } | 1441 | } |
1384 | break; | 1442 | break; |
1385 | 1443 | ||
@@ -1400,6 +1458,31 @@ do_ip6t_get_ctl(struct sock *sk, int cmd, void __user *user, int *len) | |||
1400 | break; | 1458 | break; |
1401 | } | 1459 | } |
1402 | 1460 | ||
1461 | case IP6T_SO_GET_REVISION_MATCH: | ||
1462 | case IP6T_SO_GET_REVISION_TARGET: { | ||
1463 | struct ip6t_get_revision rev; | ||
1464 | int (*revfn)(const char *, u8, int *); | ||
1465 | |||
1466 | if (*len != sizeof(rev)) { | ||
1467 | ret = -EINVAL; | ||
1468 | break; | ||
1469 | } | ||
1470 | if (copy_from_user(&rev, user, sizeof(rev)) != 0) { | ||
1471 | ret = -EFAULT; | ||
1472 | break; | ||
1473 | } | ||
1474 | |||
1475 | if (cmd == IP6T_SO_GET_REVISION_TARGET) | ||
1476 | revfn = target_revfn; | ||
1477 | else | ||
1478 | revfn = match_revfn; | ||
1479 | |||
1480 | try_then_request_module(find_revision(rev.name, rev.revision, | ||
1481 | revfn, &ret), | ||
1482 | "ip6t_%s", rev.name); | ||
1483 | break; | ||
1484 | } | ||
1485 | |||
1403 | default: | 1486 | default: |
1404 | duprintf("do_ip6t_get_ctl: unknown request %i\n", cmd); | 1487 | duprintf("do_ip6t_get_ctl: unknown request %i\n", cmd); |
1405 | ret = -EINVAL; | 1488 | ret = -EINVAL; |
@@ -1417,12 +1500,7 @@ ip6t_register_target(struct ip6t_target *target) | |||
1417 | ret = down_interruptible(&ip6t_mutex); | 1500 | ret = down_interruptible(&ip6t_mutex); |
1418 | if (ret != 0) | 1501 | if (ret != 0) |
1419 | return ret; | 1502 | return ret; |
1420 | 1503 | list_add(&target->list, &ip6t_target); | |
1421 | if (!list_named_insert(&ip6t_target, target)) { | ||
1422 | duprintf("ip6t_register_target: `%s' already in list!\n", | ||
1423 | target->name); | ||
1424 | ret = -EINVAL; | ||
1425 | } | ||
1426 | up(&ip6t_mutex); | 1504 | up(&ip6t_mutex); |
1427 | return ret; | 1505 | return ret; |
1428 | } | 1506 | } |
@@ -1444,11 +1522,7 @@ ip6t_register_match(struct ip6t_match *match) | |||
1444 | if (ret != 0) | 1522 | if (ret != 0) |
1445 | return ret; | 1523 | return ret; |
1446 | 1524 | ||
1447 | if (!list_named_insert(&ip6t_match, match)) { | 1525 | list_add(&match->list, &ip6t_match); |
1448 | duprintf("ip6t_register_match: `%s' already in list!\n", | ||
1449 | match->name); | ||
1450 | ret = -EINVAL; | ||
1451 | } | ||
1452 | up(&ip6t_mutex); | 1526 | up(&ip6t_mutex); |
1453 | 1527 | ||
1454 | return ret; | 1528 | return ret; |
diff --git a/net/ipv6/netfilter/ip6t_MARK.c b/net/ipv6/netfilter/ip6t_MARK.c index 81924fcc5857..0c7584f92172 100644 --- a/net/ipv6/netfilter/ip6t_MARK.c +++ b/net/ipv6/netfilter/ip6t_MARK.c | |||
@@ -56,8 +56,12 @@ checkentry(const char *tablename, | |||
56 | return 1; | 56 | return 1; |
57 | } | 57 | } |
58 | 58 | ||
59 | static struct ip6t_target ip6t_mark_reg | 59 | static struct ip6t_target ip6t_mark_reg = { |
60 | = { { NULL, NULL }, "MARK", target, checkentry, NULL, THIS_MODULE }; | 60 | .name = "MARK", |
61 | .target = target, | ||
62 | .checkentry = checkentry, | ||
63 | .me = THIS_MODULE | ||
64 | }; | ||
61 | 65 | ||
62 | static int __init init(void) | 66 | static int __init init(void) |
63 | { | 67 | { |
diff --git a/net/ipv6/route.c b/net/ipv6/route.c index 5d5bbb49ec78..227e99ed510c 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c | |||
@@ -483,7 +483,7 @@ restart: | |||
483 | goto out; | 483 | goto out; |
484 | } | 484 | } |
485 | 485 | ||
486 | rt = rt6_device_match(rt, skb->dev->ifindex, 0); | 486 | rt = rt6_device_match(rt, skb->dev->ifindex, strict); |
487 | BACKTRACK(); | 487 | BACKTRACK(); |
488 | 488 | ||
489 | if (!rt->rt6i_nexthop && !(rt->rt6i_flags & RTF_NONEXTHOP)) { | 489 | if (!rt->rt6i_nexthop && !(rt->rt6i_flags & RTF_NONEXTHOP)) { |
diff --git a/net/rose/rose_timer.c b/net/rose/rose_timer.c index 50ae0371dab8..b6c8f38cc26c 100644 --- a/net/rose/rose_timer.c +++ b/net/rose/rose_timer.c | |||
@@ -138,6 +138,7 @@ static void rose_heartbeat_expiry(unsigned long param) | |||
138 | is accepted() it isn't 'dead' so doesn't get removed. */ | 138 | is accepted() it isn't 'dead' so doesn't get removed. */ |
139 | if (sock_flag(sk, SOCK_DESTROY) || | 139 | if (sock_flag(sk, SOCK_DESTROY) || |
140 | (sk->sk_state == TCP_LISTEN && sock_flag(sk, SOCK_DEAD))) { | 140 | (sk->sk_state == TCP_LISTEN && sock_flag(sk, SOCK_DEAD))) { |
141 | bh_unlock_sock(sk); | ||
141 | rose_destroy_socket(sk); | 142 | rose_destroy_socket(sk); |
142 | return; | 143 | return; |
143 | } | 144 | } |
diff --git a/net/sched/Kconfig b/net/sched/Kconfig index 81510da31792..7f34e7fd767c 100644 --- a/net/sched/Kconfig +++ b/net/sched/Kconfig | |||
@@ -2,13 +2,15 @@ | |||
2 | # Traffic control configuration. | 2 | # Traffic control configuration. |
3 | # | 3 | # |
4 | 4 | ||
5 | menuconfig NET_SCHED | 5 | menu "QoS and/or fair queueing" |
6 | |||
7 | config NET_SCHED | ||
6 | bool "QoS and/or fair queueing" | 8 | bool "QoS and/or fair queueing" |
7 | ---help--- | 9 | ---help--- |
8 | When the kernel has several packets to send out over a network | 10 | When the kernel has several packets to send out over a network |
9 | device, it has to decide which ones to send first, which ones to | 11 | device, it has to decide which ones to send first, which ones to |
10 | delay, and which ones to drop. This is the job of the packet | 12 | delay, and which ones to drop. This is the job of the queueing |
11 | scheduler, and several different algorithms for how to do this | 13 | disciplines, several different algorithms for how to do this |
12 | "fairly" have been proposed. | 14 | "fairly" have been proposed. |
13 | 15 | ||
14 | If you say N here, you will get the standard packet scheduler, which | 16 | If you say N here, you will get the standard packet scheduler, which |
@@ -23,13 +25,13 @@ menuconfig NET_SCHED | |||
23 | To administer these schedulers, you'll need the user-level utilities | 25 | To administer these schedulers, you'll need the user-level utilities |
24 | from the package iproute2+tc at <ftp://ftp.tux.org/pub/net/ip-routing/>. | 26 | from the package iproute2+tc at <ftp://ftp.tux.org/pub/net/ip-routing/>. |
25 | That package also contains some documentation; for more, check out | 27 | That package also contains some documentation; for more, check out |
26 | <http://snafu.freedom.org/linux2.2/iproute-notes.html>. | 28 | <http://linux-net.osdl.org/index.php/Iproute2>. |
27 | 29 | ||
28 | This Quality of Service (QoS) support will enable you to use | 30 | This Quality of Service (QoS) support will enable you to use |
29 | Differentiated Services (diffserv) and Resource Reservation Protocol | 31 | Differentiated Services (diffserv) and Resource Reservation Protocol |
30 | (RSVP) on your Linux router if you also say Y to "QoS support", | 32 | (RSVP) on your Linux router if you also say Y to the corresponding |
31 | "Packet classifier API" and to some classifiers below. Documentation | 33 | classifiers below. Documentation and software is at |
32 | and software is at <http://diffserv.sourceforge.net/>. | 34 | <http://diffserv.sourceforge.net/>. |
33 | 35 | ||
34 | If you say Y here and to "/proc file system" below, you will be able | 36 | If you say Y here and to "/proc file system" below, you will be able |
35 | to read status information about packet schedulers from the file | 37 | to read status information about packet schedulers from the file |
@@ -42,7 +44,7 @@ choice | |||
42 | prompt "Packet scheduler clock source" | 44 | prompt "Packet scheduler clock source" |
43 | depends on NET_SCHED | 45 | depends on NET_SCHED |
44 | default NET_SCH_CLK_JIFFIES | 46 | default NET_SCH_CLK_JIFFIES |
45 | help | 47 | ---help--- |
46 | Packet schedulers need a monotonic clock that increments at a static | 48 | Packet schedulers need a monotonic clock that increments at a static |
47 | rate. The kernel provides several suitable interfaces, each with | 49 | rate. The kernel provides several suitable interfaces, each with |
48 | different properties: | 50 | different properties: |
@@ -56,7 +58,7 @@ choice | |||
56 | 58 | ||
57 | config NET_SCH_CLK_JIFFIES | 59 | config NET_SCH_CLK_JIFFIES |
58 | bool "Timer interrupt" | 60 | bool "Timer interrupt" |
59 | help | 61 | ---help--- |
60 | Say Y here if you want to use the timer interrupt (jiffies) as clock | 62 | Say Y here if you want to use the timer interrupt (jiffies) as clock |
61 | source. This clock source is fast, synchronized on all processors and | 63 | source. This clock source is fast, synchronized on all processors and |
62 | handles cpu clock frequency changes, but its resolution is too low | 64 | handles cpu clock frequency changes, but its resolution is too low |
@@ -64,7 +66,7 @@ config NET_SCH_CLK_JIFFIES | |||
64 | 66 | ||
65 | config NET_SCH_CLK_GETTIMEOFDAY | 67 | config NET_SCH_CLK_GETTIMEOFDAY |
66 | bool "gettimeofday" | 68 | bool "gettimeofday" |
67 | help | 69 | ---help--- |
68 | Say Y here if you want to use gettimeofday as clock source. This clock | 70 | Say Y here if you want to use gettimeofday as clock source. This clock |
69 | source has high resolution, is synchronized on all processors and | 71 | source has high resolution, is synchronized on all processors and |
70 | handles cpu clock frequency changes, but it is slow. | 72 | handles cpu clock frequency changes, but it is slow. |
@@ -77,7 +79,7 @@ config NET_SCH_CLK_GETTIMEOFDAY | |||
77 | config NET_SCH_CLK_CPU | 79 | config NET_SCH_CLK_CPU |
78 | bool "CPU cycle counter" | 80 | bool "CPU cycle counter" |
79 | depends on ((X86_TSC || X86_64) && !SMP) || ALPHA || SPARC64 || PPC64 || IA64 | 81 | depends on ((X86_TSC || X86_64) && !SMP) || ALPHA || SPARC64 || PPC64 || IA64 |
80 | help | 82 | ---help--- |
81 | Say Y here if you want to use the CPU's cycle counter as clock source. | 83 | Say Y here if you want to use the CPU's cycle counter as clock source. |
82 | This is a cheap and high resolution clock source, but on some | 84 | This is a cheap and high resolution clock source, but on some |
83 | architectures it is not synchronized on all processors and doesn't | 85 | architectures it is not synchronized on all processors and doesn't |
@@ -95,134 +97,129 @@ config NET_SCH_CLK_CPU | |||
95 | 97 | ||
96 | endchoice | 98 | endchoice |
97 | 99 | ||
100 | comment "Queueing/Scheduling" | ||
101 | depends on NET_SCHED | ||
102 | |||
98 | config NET_SCH_CBQ | 103 | config NET_SCH_CBQ |
99 | tristate "CBQ packet scheduler" | 104 | tristate "Class Based Queueing (CBQ)" |
100 | depends on NET_SCHED | 105 | depends on NET_SCHED |
101 | ---help--- | 106 | ---help--- |
102 | Say Y here if you want to use the Class-Based Queueing (CBQ) packet | 107 | Say Y here if you want to use the Class-Based Queueing (CBQ) packet |
103 | scheduling algorithm for some of your network devices. This | 108 | scheduling algorithm. This algorithm classifies the waiting packets |
104 | algorithm classifies the waiting packets into a tree-like hierarchy | 109 | into a tree-like hierarchy of classes; the leaves of this tree are |
105 | of classes; the leaves of this tree are in turn scheduled by | 110 | in turn scheduled by separate algorithms. |
106 | separate algorithms (called "disciplines" in this context). | ||
107 | 111 | ||
108 | See the top of <file:net/sched/sch_cbq.c> for references about the | 112 | See the top of <file:net/sched/sch_cbq.c> for more details. |
109 | CBQ algorithm. | ||
110 | 113 | ||
111 | CBQ is a commonly used scheduler, so if you're unsure, you should | 114 | CBQ is a commonly used scheduler, so if you're unsure, you should |
112 | say Y here. Then say Y to all the queueing algorithms below that you | 115 | say Y here. Then say Y to all the queueing algorithms below that you |
113 | want to use as CBQ disciplines. Then say Y to "Packet classifier | 116 | want to use as leaf disciplines. |
114 | API" and say Y to all the classifiers you want to use; a classifier | ||
115 | is a routine that allows you to sort your outgoing traffic into | ||
116 | classes based on a certain criterion. | ||
117 | 117 | ||
118 | To compile this code as a module, choose M here: the | 118 | To compile this code as a module, choose M here: the |
119 | module will be called sch_cbq. | 119 | module will be called sch_cbq. |
120 | 120 | ||
121 | config NET_SCH_HTB | 121 | config NET_SCH_HTB |
122 | tristate "HTB packet scheduler" | 122 | tristate "Hierarchical Token Bucket (HTB)" |
123 | depends on NET_SCHED | 123 | depends on NET_SCHED |
124 | ---help--- | 124 | ---help--- |
125 | Say Y here if you want to use the Hierarchical Token Buckets (HTB) | 125 | Say Y here if you want to use the Hierarchical Token Buckets (HTB) |
126 | packet scheduling algorithm for some of your network devices. See | 126 | packet scheduling algorithm. See |
127 | <http://luxik.cdi.cz/~devik/qos/htb/> for complete manual and | 127 | <http://luxik.cdi.cz/~devik/qos/htb/> for complete manual and |
128 | in-depth articles. | 128 | in-depth articles. |
129 | 129 | ||
130 | HTB is very similar to the CBQ regarding its goals however is has | 130 | HTB is very similar to CBQ regarding its goals however is has |
131 | different properties and different algorithm. | 131 | different properties and different algorithm. |
132 | 132 | ||
133 | To compile this code as a module, choose M here: the | 133 | To compile this code as a module, choose M here: the |
134 | module will be called sch_htb. | 134 | module will be called sch_htb. |
135 | 135 | ||
136 | config NET_SCH_HFSC | 136 | config NET_SCH_HFSC |
137 | tristate "HFSC packet scheduler" | 137 | tristate "Hierarchical Fair Service Curve (HFSC)" |
138 | depends on NET_SCHED | 138 | depends on NET_SCHED |
139 | ---help--- | 139 | ---help--- |
140 | Say Y here if you want to use the Hierarchical Fair Service Curve | 140 | Say Y here if you want to use the Hierarchical Fair Service Curve |
141 | (HFSC) packet scheduling algorithm for some of your network devices. | 141 | (HFSC) packet scheduling algorithm. |
142 | 142 | ||
143 | To compile this code as a module, choose M here: the | 143 | To compile this code as a module, choose M here: the |
144 | module will be called sch_hfsc. | 144 | module will be called sch_hfsc. |
145 | 145 | ||
146 | #tristate ' H-PFQ packet scheduler' CONFIG_NET_SCH_HPFQ | ||
147 | config NET_SCH_ATM | 146 | config NET_SCH_ATM |
148 | tristate "ATM pseudo-scheduler" | 147 | tristate "ATM Virtual Circuits (ATM)" |
149 | depends on NET_SCHED && ATM | 148 | depends on NET_SCHED && ATM |
150 | ---help--- | 149 | ---help--- |
151 | Say Y here if you want to use the ATM pseudo-scheduler. This | 150 | Say Y here if you want to use the ATM pseudo-scheduler. This |
152 | provides a framework for invoking classifiers (aka "filters"), which | 151 | provides a framework for invoking classifiers, which in turn |
153 | in turn select classes of this queuing discipline. Each class maps | 152 | select classes of this queuing discipline. Each class maps |
154 | the flow(s) it is handling to a given virtual circuit (see the top of | 153 | the flow(s) it is handling to a given virtual circuit. |
155 | <file:net/sched/sch_atm.c>). | 154 | |
155 | See the top of <file:net/sched/sch_atm.c>) for more details. | ||
156 | 156 | ||
157 | To compile this code as a module, choose M here: the | 157 | To compile this code as a module, choose M here: the |
158 | module will be called sch_atm. | 158 | module will be called sch_atm. |
159 | 159 | ||
160 | config NET_SCH_PRIO | 160 | config NET_SCH_PRIO |
161 | tristate "The simplest PRIO pseudoscheduler" | 161 | tristate "Multi Band Priority Queueing (PRIO)" |
162 | depends on NET_SCHED | 162 | depends on NET_SCHED |
163 | help | 163 | ---help--- |
164 | Say Y here if you want to use an n-band priority queue packet | 164 | Say Y here if you want to use an n-band priority queue packet |
165 | "scheduler" for some of your network devices or as a leaf discipline | 165 | scheduler. |
166 | for the CBQ scheduling algorithm. If unsure, say Y. | ||
167 | 166 | ||
168 | To compile this code as a module, choose M here: the | 167 | To compile this code as a module, choose M here: the |
169 | module will be called sch_prio. | 168 | module will be called sch_prio. |
170 | 169 | ||
171 | config NET_SCH_RED | 170 | config NET_SCH_RED |
172 | tristate "RED queue" | 171 | tristate "Random Early Detection (RED)" |
173 | depends on NET_SCHED | 172 | depends on NET_SCHED |
174 | help | 173 | ---help--- |
175 | Say Y here if you want to use the Random Early Detection (RED) | 174 | Say Y here if you want to use the Random Early Detection (RED) |
176 | packet scheduling algorithm for some of your network devices (see | 175 | packet scheduling algorithm. |
177 | the top of <file:net/sched/sch_red.c> for details and references | 176 | |
178 | about the algorithm). | 177 | See the top of <file:net/sched/sch_red.c> for more details. |
179 | 178 | ||
180 | To compile this code as a module, choose M here: the | 179 | To compile this code as a module, choose M here: the |
181 | module will be called sch_red. | 180 | module will be called sch_red. |
182 | 181 | ||
183 | config NET_SCH_SFQ | 182 | config NET_SCH_SFQ |
184 | tristate "SFQ queue" | 183 | tristate "Stochastic Fairness Queueing (SFQ)" |
185 | depends on NET_SCHED | 184 | depends on NET_SCHED |
186 | ---help--- | 185 | ---help--- |
187 | Say Y here if you want to use the Stochastic Fairness Queueing (SFQ) | 186 | Say Y here if you want to use the Stochastic Fairness Queueing (SFQ) |
188 | packet scheduling algorithm for some of your network devices or as a | 187 | packet scheduling algorithm . |
189 | leaf discipline for the CBQ scheduling algorithm (see the top of | 188 | |
190 | <file:net/sched/sch_sfq.c> for details and references about the SFQ | 189 | See the top of <file:net/sched/sch_sfq.c> for more details. |
191 | algorithm). | ||
192 | 190 | ||
193 | To compile this code as a module, choose M here: the | 191 | To compile this code as a module, choose M here: the |
194 | module will be called sch_sfq. | 192 | module will be called sch_sfq. |
195 | 193 | ||
196 | config NET_SCH_TEQL | 194 | config NET_SCH_TEQL |
197 | tristate "TEQL queue" | 195 | tristate "True Link Equalizer (TEQL)" |
198 | depends on NET_SCHED | 196 | depends on NET_SCHED |
199 | ---help--- | 197 | ---help--- |
200 | Say Y here if you want to use the True Link Equalizer (TLE) packet | 198 | Say Y here if you want to use the True Link Equalizer (TLE) packet |
201 | scheduling algorithm for some of your network devices or as a leaf | 199 | scheduling algorithm. This queueing discipline allows the combination |
202 | discipline for the CBQ scheduling algorithm. This queueing | 200 | of several physical devices into one virtual device. |
203 | discipline allows the combination of several physical devices into | 201 | |
204 | one virtual device. (see the top of <file:net/sched/sch_teql.c> for | 202 | See the top of <file:net/sched/sch_teql.c> for more details. |
205 | details). | ||
206 | 203 | ||
207 | To compile this code as a module, choose M here: the | 204 | To compile this code as a module, choose M here: the |
208 | module will be called sch_teql. | 205 | module will be called sch_teql. |
209 | 206 | ||
210 | config NET_SCH_TBF | 207 | config NET_SCH_TBF |
211 | tristate "TBF queue" | 208 | tristate "Token Bucket Filter (TBF)" |
212 | depends on NET_SCHED | 209 | depends on NET_SCHED |
213 | help | 210 | ---help--- |
214 | Say Y here if you want to use the Simple Token Bucket Filter (TBF) | 211 | Say Y here if you want to use the Token Bucket Filter (TBF) packet |
215 | packet scheduling algorithm for some of your network devices or as a | 212 | scheduling algorithm. |
216 | leaf discipline for the CBQ scheduling algorithm (see the top of | 213 | |
217 | <file:net/sched/sch_tbf.c> for a description of the TBF algorithm). | 214 | See the top of <file:net/sched/sch_tbf.c> for more details. |
218 | 215 | ||
219 | To compile this code as a module, choose M here: the | 216 | To compile this code as a module, choose M here: the |
220 | module will be called sch_tbf. | 217 | module will be called sch_tbf. |
221 | 218 | ||
222 | config NET_SCH_GRED | 219 | config NET_SCH_GRED |
223 | tristate "GRED queue" | 220 | tristate "Generic Random Early Detection (GRED)" |
224 | depends on NET_SCHED | 221 | depends on NET_SCHED |
225 | help | 222 | ---help--- |
226 | Say Y here if you want to use the Generic Random Early Detection | 223 | Say Y here if you want to use the Generic Random Early Detection |
227 | (GRED) packet scheduling algorithm for some of your network devices | 224 | (GRED) packet scheduling algorithm for some of your network devices |
228 | (see the top of <file:net/sched/sch_red.c> for details and | 225 | (see the top of <file:net/sched/sch_red.c> for details and |
@@ -232,9 +229,9 @@ config NET_SCH_GRED | |||
232 | module will be called sch_gred. | 229 | module will be called sch_gred. |
233 | 230 | ||
234 | config NET_SCH_DSMARK | 231 | config NET_SCH_DSMARK |
235 | tristate "Diffserv field marker" | 232 | tristate "Differentiated Services marker (DSMARK)" |
236 | depends on NET_SCHED | 233 | depends on NET_SCHED |
237 | help | 234 | ---help--- |
238 | Say Y if you want to schedule packets according to the | 235 | Say Y if you want to schedule packets according to the |
239 | Differentiated Services architecture proposed in RFC 2475. | 236 | Differentiated Services architecture proposed in RFC 2475. |
240 | Technical information on this method, with pointers to associated | 237 | Technical information on this method, with pointers to associated |
@@ -244,9 +241,9 @@ config NET_SCH_DSMARK | |||
244 | module will be called sch_dsmark. | 241 | module will be called sch_dsmark. |
245 | 242 | ||
246 | config NET_SCH_NETEM | 243 | config NET_SCH_NETEM |
247 | tristate "Network emulator" | 244 | tristate "Network emulator (NETEM)" |
248 | depends on NET_SCHED | 245 | depends on NET_SCHED |
249 | help | 246 | ---help--- |
250 | Say Y if you want to emulate network delay, loss, and packet | 247 | Say Y if you want to emulate network delay, loss, and packet |
251 | re-ordering. This is often useful to simulate networks when | 248 | re-ordering. This is often useful to simulate networks when |
252 | testing applications or protocols. | 249 | testing applications or protocols. |
@@ -259,58 +256,23 @@ config NET_SCH_NETEM | |||
259 | config NET_SCH_INGRESS | 256 | config NET_SCH_INGRESS |
260 | tristate "Ingress Qdisc" | 257 | tristate "Ingress Qdisc" |
261 | depends on NET_SCHED | 258 | depends on NET_SCHED |
262 | help | 259 | ---help--- |
263 | If you say Y here, you will be able to police incoming bandwidth | 260 | Say Y here if you want to use classifiers for incoming packets. |
264 | and drop packets when this bandwidth exceeds your desired rate. | ||
265 | If unsure, say Y. | 261 | If unsure, say Y. |
266 | 262 | ||
267 | To compile this code as a module, choose M here: the | 263 | To compile this code as a module, choose M here: the |
268 | module will be called sch_ingress. | 264 | module will be called sch_ingress. |
269 | 265 | ||
270 | config NET_QOS | 266 | comment "Classification" |
271 | bool "QoS support" | ||
272 | depends on NET_SCHED | 267 | depends on NET_SCHED |
273 | ---help--- | ||
274 | Say Y here if you want to include Quality Of Service scheduling | ||
275 | features, which means that you will be able to request certain | ||
276 | rate-of-flow limits for your network devices. | ||
277 | |||
278 | This Quality of Service (QoS) support will enable you to use | ||
279 | Differentiated Services (diffserv) and Resource Reservation Protocol | ||
280 | (RSVP) on your Linux router if you also say Y to "Packet classifier | ||
281 | API" and to some classifiers below. Documentation and software is at | ||
282 | <http://diffserv.sourceforge.net/>. | ||
283 | |||
284 | Note that the answer to this question won't directly affect the | ||
285 | kernel: saying N will just cause the configurator to skip all | ||
286 | the questions about QoS support. | ||
287 | |||
288 | config NET_ESTIMATOR | ||
289 | bool "Rate estimator" | ||
290 | depends on NET_QOS | ||
291 | help | ||
292 | In order for Quality of Service scheduling to work, the current | ||
293 | rate-of-flow for a network device has to be estimated; if you say Y | ||
294 | here, the kernel will do just that. | ||
295 | 268 | ||
296 | config NET_CLS | 269 | config NET_CLS |
297 | bool "Packet classifier API" | 270 | boolean |
298 | depends on NET_SCHED | ||
299 | ---help--- | ||
300 | The CBQ scheduling algorithm requires that network packets which are | ||
301 | scheduled to be sent out over a network device be classified | ||
302 | according to some criterion. If you say Y here, you will get a | ||
303 | choice of several different packet classifiers with the following | ||
304 | questions. | ||
305 | |||
306 | This will enable you to use Differentiated Services (diffserv) and | ||
307 | Resource Reservation Protocol (RSVP) on your Linux router. | ||
308 | Documentation and software is at | ||
309 | <http://diffserv.sourceforge.net/>. | ||
310 | 271 | ||
311 | config NET_CLS_BASIC | 272 | config NET_CLS_BASIC |
312 | tristate "Basic classifier" | 273 | tristate "Elementary classification (BASIC)" |
313 | depends on NET_CLS | 274 | depends NET_SCHED |
275 | select NET_CLS | ||
314 | ---help--- | 276 | ---help--- |
315 | Say Y here if you want to be able to classify packets using | 277 | Say Y here if you want to be able to classify packets using |
316 | only extended matches and actions. | 278 | only extended matches and actions. |
@@ -319,24 +281,25 @@ config NET_CLS_BASIC | |||
319 | module will be called cls_basic. | 281 | module will be called cls_basic. |
320 | 282 | ||
321 | config NET_CLS_TCINDEX | 283 | config NET_CLS_TCINDEX |
322 | tristate "TC index classifier" | 284 | tristate "Traffic-Control Index (TCINDEX)" |
323 | depends on NET_CLS | 285 | depends NET_SCHED |
324 | help | 286 | select NET_CLS |
325 | If you say Y here, you will be able to classify outgoing packets | 287 | ---help--- |
326 | according to the tc_index field of the skb. You will want this | 288 | Say Y here if you want to be able to classify packets based on |
327 | feature if you want to implement Differentiated Services using | 289 | traffic control indices. You will want this feature if you want |
328 | sch_dsmark. If unsure, say Y. | 290 | to implement Differentiated Services together with DSMARK. |
329 | 291 | ||
330 | To compile this code as a module, choose M here: the | 292 | To compile this code as a module, choose M here: the |
331 | module will be called cls_tcindex. | 293 | module will be called cls_tcindex. |
332 | 294 | ||
333 | config NET_CLS_ROUTE4 | 295 | config NET_CLS_ROUTE4 |
334 | tristate "Routing table based classifier" | 296 | tristate "Routing decision (ROUTE)" |
335 | depends on NET_CLS | 297 | depends NET_SCHED |
336 | select NET_CLS_ROUTE | 298 | select NET_CLS_ROUTE |
337 | help | 299 | select NET_CLS |
338 | If you say Y here, you will be able to classify outgoing packets | 300 | ---help--- |
339 | according to the route table entry they matched. If unsure, say Y. | 301 | If you say Y here, you will be able to classify packets |
302 | according to the route table entry they matched. | ||
340 | 303 | ||
341 | To compile this code as a module, choose M here: the | 304 | To compile this code as a module, choose M here: the |
342 | module will be called cls_route. | 305 | module will be called cls_route. |
@@ -346,58 +309,45 @@ config NET_CLS_ROUTE | |||
346 | default n | 309 | default n |
347 | 310 | ||
348 | config NET_CLS_FW | 311 | config NET_CLS_FW |
349 | tristate "Firewall based classifier" | 312 | tristate "Netfilter mark (FW)" |
350 | depends on NET_CLS | 313 | depends NET_SCHED |
351 | help | 314 | select NET_CLS |
352 | If you say Y here, you will be able to classify outgoing packets | 315 | ---help--- |
353 | according to firewall criteria you specified. | 316 | If you say Y here, you will be able to classify packets |
317 | according to netfilter/firewall marks. | ||
354 | 318 | ||
355 | To compile this code as a module, choose M here: the | 319 | To compile this code as a module, choose M here: the |
356 | module will be called cls_fw. | 320 | module will be called cls_fw. |
357 | 321 | ||
358 | config NET_CLS_U32 | 322 | config NET_CLS_U32 |
359 | tristate "U32 classifier" | 323 | tristate "Universal 32bit comparisons w/ hashing (U32)" |
360 | depends on NET_CLS | 324 | depends NET_SCHED |
361 | help | 325 | select NET_CLS |
362 | If you say Y here, you will be able to classify outgoing packets | 326 | ---help--- |
363 | according to their destination address. If unsure, say Y. | 327 | Say Y here to be able to classify packetes using a universal |
328 | 32bit pieces based comparison scheme. | ||
364 | 329 | ||
365 | To compile this code as a module, choose M here: the | 330 | To compile this code as a module, choose M here: the |
366 | module will be called cls_u32. | 331 | module will be called cls_u32. |
367 | 332 | ||
368 | config CLS_U32_PERF | 333 | config CLS_U32_PERF |
369 | bool "U32 classifier performance counters" | 334 | bool "Performance counters support" |
370 | depends on NET_CLS_U32 | 335 | depends on NET_CLS_U32 |
371 | help | 336 | ---help--- |
372 | gathers stats that could be used to tune u32 classifier performance. | 337 | Say Y here to make u32 gather additional statistics useful for |
373 | Requires a new iproute2 | 338 | fine tuning u32 classifiers. |
374 | You MUST NOT turn this on if you dont have an update iproute2. | ||
375 | |||
376 | config NET_CLS_IND | ||
377 | bool "classify input device (slows things u32/fw) " | ||
378 | depends on NET_CLS_U32 || NET_CLS_FW | ||
379 | help | ||
380 | This option will be killed eventually when a | ||
381 | metadata action appears because it slows things a little | ||
382 | Available only for u32 and fw classifiers. | ||
383 | Requires a new iproute2 | ||
384 | You MUST NOT turn this on if you dont have an update iproute2. | ||
385 | 339 | ||
386 | config CLS_U32_MARK | 340 | config CLS_U32_MARK |
387 | bool "Use nfmark as a key in U32 classifier" | 341 | bool "Netfilter marks support" |
388 | depends on NET_CLS_U32 && NETFILTER | 342 | depends on NET_CLS_U32 && NETFILTER |
389 | help | 343 | ---help--- |
390 | This allows you to match mark in a u32 filter. | 344 | Say Y here to be able to use netfilter marks as u32 key. |
391 | Example: | ||
392 | tc filter add dev eth0 protocol ip parent 1:0 prio 5 u32 \ | ||
393 | match mark 0x0090 0xffff \ | ||
394 | match ip dst 4.4.4.4 \ | ||
395 | flowid 1:90 | ||
396 | You must use a new iproute2 to use this feature. | ||
397 | 345 | ||
398 | config NET_CLS_RSVP | 346 | config NET_CLS_RSVP |
399 | tristate "Special RSVP classifier" | 347 | tristate "IPv4 Resource Reservation Protocol (RSVP)" |
400 | depends on NET_CLS && NET_QOS | 348 | depends on NET_SCHED |
349 | select NET_CLS | ||
350 | select NET_ESTIMATOR | ||
401 | ---help--- | 351 | ---help--- |
402 | The Resource Reservation Protocol (RSVP) permits end systems to | 352 | The Resource Reservation Protocol (RSVP) permits end systems to |
403 | request a minimum and maximum data flow rate for a connection; this | 353 | request a minimum and maximum data flow rate for a connection; this |
@@ -410,31 +360,33 @@ config NET_CLS_RSVP | |||
410 | module will be called cls_rsvp. | 360 | module will be called cls_rsvp. |
411 | 361 | ||
412 | config NET_CLS_RSVP6 | 362 | config NET_CLS_RSVP6 |
413 | tristate "Special RSVP classifier for IPv6" | 363 | tristate "IPv6 Resource Reservation Protocol (RSVP6)" |
414 | depends on NET_CLS && NET_QOS | 364 | depends on NET_SCHED |
365 | select NET_CLS | ||
366 | select NET_ESTIMATOR | ||
415 | ---help--- | 367 | ---help--- |
416 | The Resource Reservation Protocol (RSVP) permits end systems to | 368 | The Resource Reservation Protocol (RSVP) permits end systems to |
417 | request a minimum and maximum data flow rate for a connection; this | 369 | request a minimum and maximum data flow rate for a connection; this |
418 | is important for real time data such as streaming sound or video. | 370 | is important for real time data such as streaming sound or video. |
419 | 371 | ||
420 | Say Y here if you want to be able to classify outgoing packets based | 372 | Say Y here if you want to be able to classify outgoing packets based |
421 | on their RSVP requests and you are using the new Internet Protocol | 373 | on their RSVP requests and you are using the IPv6. |
422 | IPv6 as opposed to the older and more common IPv4. | ||
423 | 374 | ||
424 | To compile this code as a module, choose M here: the | 375 | To compile this code as a module, choose M here: the |
425 | module will be called cls_rsvp6. | 376 | module will be called cls_rsvp6. |
426 | 377 | ||
427 | config NET_EMATCH | 378 | config NET_EMATCH |
428 | bool "Extended Matches" | 379 | bool "Extended Matches" |
429 | depends on NET_CLS | 380 | depends NET_SCHED |
381 | select NET_CLS | ||
430 | ---help--- | 382 | ---help--- |
431 | Say Y here if you want to use extended matches on top of classifiers | 383 | Say Y here if you want to use extended matches on top of classifiers |
432 | and select the extended matches below. | 384 | and select the extended matches below. |
433 | 385 | ||
434 | Extended matches are small classification helpers not worth writing | 386 | Extended matches are small classification helpers not worth writing |
435 | a separate classifier. | 387 | a separate classifier for. |
436 | 388 | ||
437 | You must have a recent version of the iproute2 tools in order to use | 389 | A recent version of the iproute2 package is required to use |
438 | extended matches. | 390 | extended matches. |
439 | 391 | ||
440 | config NET_EMATCH_STACK | 392 | config NET_EMATCH_STACK |
@@ -468,7 +420,7 @@ config NET_EMATCH_NBYTE | |||
468 | module will be called em_nbyte. | 420 | module will be called em_nbyte. |
469 | 421 | ||
470 | config NET_EMATCH_U32 | 422 | config NET_EMATCH_U32 |
471 | tristate "U32 hashing key" | 423 | tristate "U32 key" |
472 | depends on NET_EMATCH | 424 | depends on NET_EMATCH |
473 | ---help--- | 425 | ---help--- |
474 | Say Y here if you want to be able to classify packets using | 426 | Say Y here if you want to be able to classify packets using |
@@ -496,76 +448,120 @@ config NET_EMATCH_TEXT | |||
496 | select TEXTSEARCH_BM | 448 | select TEXTSEARCH_BM |
497 | select TEXTSEARCH_FSM | 449 | select TEXTSEARCH_FSM |
498 | ---help--- | 450 | ---help--- |
499 | Say Y here if you want to be ablt to classify packets based on | 451 | Say Y here if you want to be able to classify packets based on |
500 | textsearch comparisons. | 452 | textsearch comparisons. |
501 | 453 | ||
502 | To compile this code as a module, choose M here: the | 454 | To compile this code as a module, choose M here: the |
503 | module will be called em_text. | 455 | module will be called em_text. |
504 | 456 | ||
505 | config NET_CLS_ACT | 457 | config NET_CLS_ACT |
506 | bool "Packet ACTION" | 458 | bool "Actions" |
507 | depends on EXPERIMENTAL && NET_CLS && NET_QOS | 459 | depends on EXPERIMENTAL && NET_SCHED |
460 | select NET_ESTIMATOR | ||
508 | ---help--- | 461 | ---help--- |
509 | This option requires you have a new iproute2. It enables | 462 | Say Y here if you want to use traffic control actions. Actions |
510 | tc extensions which can be used with tc classifiers. | 463 | get attached to classifiers and are invoked after a successful |
511 | You MUST NOT turn this on if you dont have an update iproute2. | 464 | classification. They are used to overwrite the classification |
465 | result, instantly drop or redirect packets, etc. | ||
466 | |||
467 | A recent version of the iproute2 package is required to use | ||
468 | extended matches. | ||
512 | 469 | ||
513 | config NET_ACT_POLICE | 470 | config NET_ACT_POLICE |
514 | tristate "Policing Actions" | 471 | tristate "Traffic Policing" |
515 | depends on NET_CLS_ACT | 472 | depends on NET_CLS_ACT |
516 | ---help--- | 473 | ---help--- |
517 | If you are using a newer iproute2 select this one, otherwise use one | 474 | Say Y here if you want to do traffic policing, i.e. strict |
518 | below to select a policer. | 475 | bandwidth limiting. This action replaces the existing policing |
519 | You MUST NOT turn this on if you dont have an update iproute2. | 476 | module. |
477 | |||
478 | To compile this code as a module, choose M here: the | ||
479 | module will be called police. | ||
520 | 480 | ||
521 | config NET_ACT_GACT | 481 | config NET_ACT_GACT |
522 | tristate "generic Actions" | 482 | tristate "Generic actions" |
523 | depends on NET_CLS_ACT | 483 | depends on NET_CLS_ACT |
524 | ---help--- | 484 | ---help--- |
525 | You must have new iproute2 to use this feature. | 485 | Say Y here to take generic actions such as dropping and |
526 | This adds simple filtering actions like drop, accept etc. | 486 | accepting packets. |
487 | |||
488 | To compile this code as a module, choose M here: the | ||
489 | module will be called gact. | ||
527 | 490 | ||
528 | config GACT_PROB | 491 | config GACT_PROB |
529 | bool "generic Actions probability" | 492 | bool "Probability support" |
530 | depends on NET_ACT_GACT | 493 | depends on NET_ACT_GACT |
531 | ---help--- | 494 | ---help--- |
532 | Allows generic actions to be randomly or deterministically used. | 495 | Say Y here to use the generic action randomly or deterministically. |
533 | 496 | ||
534 | config NET_ACT_MIRRED | 497 | config NET_ACT_MIRRED |
535 | tristate "Packet In/Egress redirecton/mirror Actions" | 498 | tristate "Redirecting and Mirroring" |
536 | depends on NET_CLS_ACT | 499 | depends on NET_CLS_ACT |
537 | ---help--- | 500 | ---help--- |
538 | requires new iproute2 | 501 | Say Y here to allow packets to be mirrored or redirected to |
539 | This allows packets to be mirrored or redirected to netdevices | 502 | other devices. |
503 | |||
504 | To compile this code as a module, choose M here: the | ||
505 | module will be called mirred. | ||
540 | 506 | ||
541 | config NET_ACT_IPT | 507 | config NET_ACT_IPT |
542 | tristate "iptables Actions" | 508 | tristate "IPtables targets" |
543 | depends on NET_CLS_ACT && NETFILTER && IP_NF_IPTABLES | 509 | depends on NET_CLS_ACT && NETFILTER && IP_NF_IPTABLES |
544 | ---help--- | 510 | ---help--- |
545 | requires new iproute2 | 511 | Say Y here to be able to invoke iptables targets after succesful |
546 | This allows iptables targets to be used by tc filters | 512 | classification. |
513 | |||
514 | To compile this code as a module, choose M here: the | ||
515 | module will be called ipt. | ||
547 | 516 | ||
548 | config NET_ACT_PEDIT | 517 | config NET_ACT_PEDIT |
549 | tristate "Generic Packet Editor Actions" | 518 | tristate "Packet Editing" |
550 | depends on NET_CLS_ACT | 519 | depends on NET_CLS_ACT |
551 | ---help--- | 520 | ---help--- |
552 | requires new iproute2 | 521 | Say Y here if you want to mangle the content of packets. |
553 | This allows for packets to be generically edited | ||
554 | 522 | ||
555 | config NET_CLS_POLICE | 523 | To compile this code as a module, choose M here: the |
556 | bool "Traffic policing (needed for in/egress)" | 524 | module will be called pedit. |
557 | depends on NET_CLS && NET_QOS && NET_CLS_ACT!=y | ||
558 | help | ||
559 | Say Y to support traffic policing (bandwidth limits). Needed for | ||
560 | ingress and egress rate limiting. | ||
561 | 525 | ||
562 | config NET_ACT_SIMP | 526 | config NET_ACT_SIMP |
563 | tristate "Simple action" | 527 | tristate "Simple Example (Debug)" |
564 | depends on NET_CLS_ACT | 528 | depends on NET_CLS_ACT |
565 | ---help--- | 529 | ---help--- |
566 | You must have new iproute2 to use this feature. | 530 | Say Y here to add a simple action for demonstration purposes. |
567 | This adds a very simple action for demonstration purposes | 531 | It is meant as an example and for debugging purposes. It will |
568 | The idea is to give action authors a basic example to look at. | 532 | print a configured policy string followed by the packet count |
569 | All this action will do is print on the console the configured | 533 | to the console for every packet that passes by. |
570 | policy string followed by _ then packet count. | 534 | |
535 | If unsure, say N. | ||
536 | |||
537 | To compile this code as a module, choose M here: the | ||
538 | module will be called simple. | ||
539 | |||
540 | config NET_CLS_POLICE | ||
541 | bool "Traffic Policing (obsolete)" | ||
542 | depends on NET_SCHED && NET_CLS_ACT!=y | ||
543 | select NET_ESTIMATOR | ||
544 | ---help--- | ||
545 | Say Y here if you want to do traffic policing, i.e. strict | ||
546 | bandwidth limiting. This option is obsoleted by the traffic | ||
547 | policer implemented as action, it stays here for compatibility | ||
548 | reasons. | ||
549 | |||
550 | config NET_CLS_IND | ||
551 | bool "Incoming device classification" | ||
552 | depends on NET_SCHED && (NET_CLS_U32 || NET_CLS_FW) | ||
553 | ---help--- | ||
554 | Say Y here to extend the u32 and fw classifier to support | ||
555 | classification based on the incoming device. This option is | ||
556 | likely to disappear in favour of the metadata ematch. | ||
557 | |||
558 | config NET_ESTIMATOR | ||
559 | bool "Rate estimator" | ||
560 | depends on NET_SCHED | ||
561 | ---help--- | ||
562 | Say Y here to allow using rate estimators to estimate the current | ||
563 | rate-of-flow for network devices, queues, etc. This module is | ||
564 | automaticaly selected if needed but can be selected manually for | ||
565 | statstical purposes. | ||
571 | 566 | ||
567 | endmenu | ||
diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c index 10e82ec2ebd3..660c61bdf164 100644 --- a/net/sctp/sm_make_chunk.c +++ b/net/sctp/sm_make_chunk.c | |||
@@ -554,7 +554,7 @@ struct sctp_chunk *sctp_make_datafrag_empty(struct sctp_association *asoc, | |||
554 | dp.ppid = sinfo->sinfo_ppid; | 554 | dp.ppid = sinfo->sinfo_ppid; |
555 | 555 | ||
556 | /* Set the flags for an unordered send. */ | 556 | /* Set the flags for an unordered send. */ |
557 | if (sinfo->sinfo_flags & MSG_UNORDERED) { | 557 | if (sinfo->sinfo_flags & SCTP_UNORDERED) { |
558 | flags |= SCTP_DATA_UNORDERED; | 558 | flags |= SCTP_DATA_UNORDERED; |
559 | dp.ssn = 0; | 559 | dp.ssn = 0; |
560 | } else | 560 | } else |
diff --git a/net/sctp/socket.c b/net/sctp/socket.c index 02e068d3450d..b529af5e6f2a 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c | |||
@@ -1010,6 +1010,19 @@ static int __sctp_connect(struct sock* sk, | |||
1010 | err = -EAGAIN; | 1010 | err = -EAGAIN; |
1011 | goto out_free; | 1011 | goto out_free; |
1012 | } | 1012 | } |
1013 | } else { | ||
1014 | /* | ||
1015 | * If an unprivileged user inherits a 1-many | ||
1016 | * style socket with open associations on a | ||
1017 | * privileged port, it MAY be permitted to | ||
1018 | * accept new associations, but it SHOULD NOT | ||
1019 | * be permitted to open new associations. | ||
1020 | */ | ||
1021 | if (ep->base.bind_addr.port < PROT_SOCK && | ||
1022 | !capable(CAP_NET_BIND_SERVICE)) { | ||
1023 | err = -EACCES; | ||
1024 | goto out_free; | ||
1025 | } | ||
1013 | } | 1026 | } |
1014 | 1027 | ||
1015 | scope = sctp_scope(&to); | 1028 | scope = sctp_scope(&to); |
@@ -1389,27 +1402,27 @@ SCTP_STATIC int sctp_sendmsg(struct kiocb *iocb, struct sock *sk, | |||
1389 | SCTP_DEBUG_PRINTK("msg_len: %zu, sinfo_flags: 0x%x\n", | 1402 | SCTP_DEBUG_PRINTK("msg_len: %zu, sinfo_flags: 0x%x\n", |
1390 | msg_len, sinfo_flags); | 1403 | msg_len, sinfo_flags); |
1391 | 1404 | ||
1392 | /* MSG_EOF or MSG_ABORT cannot be set on a TCP-style socket. */ | 1405 | /* SCTP_EOF or SCTP_ABORT cannot be set on a TCP-style socket. */ |
1393 | if (sctp_style(sk, TCP) && (sinfo_flags & (MSG_EOF | MSG_ABORT))) { | 1406 | if (sctp_style(sk, TCP) && (sinfo_flags & (SCTP_EOF | SCTP_ABORT))) { |
1394 | err = -EINVAL; | 1407 | err = -EINVAL; |
1395 | goto out_nounlock; | 1408 | goto out_nounlock; |
1396 | } | 1409 | } |
1397 | 1410 | ||
1398 | /* If MSG_EOF is set, no data can be sent. Disallow sending zero | 1411 | /* If SCTP_EOF is set, no data can be sent. Disallow sending zero |
1399 | * length messages when MSG_EOF|MSG_ABORT is not set. | 1412 | * length messages when SCTP_EOF|SCTP_ABORT is not set. |
1400 | * If MSG_ABORT is set, the message length could be non zero with | 1413 | * If SCTP_ABORT is set, the message length could be non zero with |
1401 | * the msg_iov set to the user abort reason. | 1414 | * the msg_iov set to the user abort reason. |
1402 | */ | 1415 | */ |
1403 | if (((sinfo_flags & MSG_EOF) && (msg_len > 0)) || | 1416 | if (((sinfo_flags & SCTP_EOF) && (msg_len > 0)) || |
1404 | (!(sinfo_flags & (MSG_EOF|MSG_ABORT)) && (msg_len == 0))) { | 1417 | (!(sinfo_flags & (SCTP_EOF|SCTP_ABORT)) && (msg_len == 0))) { |
1405 | err = -EINVAL; | 1418 | err = -EINVAL; |
1406 | goto out_nounlock; | 1419 | goto out_nounlock; |
1407 | } | 1420 | } |
1408 | 1421 | ||
1409 | /* If MSG_ADDR_OVER is set, there must be an address | 1422 | /* If SCTP_ADDR_OVER is set, there must be an address |
1410 | * specified in msg_name. | 1423 | * specified in msg_name. |
1411 | */ | 1424 | */ |
1412 | if ((sinfo_flags & MSG_ADDR_OVER) && (!msg->msg_name)) { | 1425 | if ((sinfo_flags & SCTP_ADDR_OVER) && (!msg->msg_name)) { |
1413 | err = -EINVAL; | 1426 | err = -EINVAL; |
1414 | goto out_nounlock; | 1427 | goto out_nounlock; |
1415 | } | 1428 | } |
@@ -1458,14 +1471,14 @@ SCTP_STATIC int sctp_sendmsg(struct kiocb *iocb, struct sock *sk, | |||
1458 | goto out_unlock; | 1471 | goto out_unlock; |
1459 | } | 1472 | } |
1460 | 1473 | ||
1461 | if (sinfo_flags & MSG_EOF) { | 1474 | if (sinfo_flags & SCTP_EOF) { |
1462 | SCTP_DEBUG_PRINTK("Shutting down association: %p\n", | 1475 | SCTP_DEBUG_PRINTK("Shutting down association: %p\n", |
1463 | asoc); | 1476 | asoc); |
1464 | sctp_primitive_SHUTDOWN(asoc, NULL); | 1477 | sctp_primitive_SHUTDOWN(asoc, NULL); |
1465 | err = 0; | 1478 | err = 0; |
1466 | goto out_unlock; | 1479 | goto out_unlock; |
1467 | } | 1480 | } |
1468 | if (sinfo_flags & MSG_ABORT) { | 1481 | if (sinfo_flags & SCTP_ABORT) { |
1469 | SCTP_DEBUG_PRINTK("Aborting association: %p\n", asoc); | 1482 | SCTP_DEBUG_PRINTK("Aborting association: %p\n", asoc); |
1470 | sctp_primitive_ABORT(asoc, msg); | 1483 | sctp_primitive_ABORT(asoc, msg); |
1471 | err = 0; | 1484 | err = 0; |
@@ -1477,7 +1490,7 @@ SCTP_STATIC int sctp_sendmsg(struct kiocb *iocb, struct sock *sk, | |||
1477 | if (!asoc) { | 1490 | if (!asoc) { |
1478 | SCTP_DEBUG_PRINTK("There is no association yet.\n"); | 1491 | SCTP_DEBUG_PRINTK("There is no association yet.\n"); |
1479 | 1492 | ||
1480 | if (sinfo_flags & (MSG_EOF | MSG_ABORT)) { | 1493 | if (sinfo_flags & (SCTP_EOF | SCTP_ABORT)) { |
1481 | err = -EINVAL; | 1494 | err = -EINVAL; |
1482 | goto out_unlock; | 1495 | goto out_unlock; |
1483 | } | 1496 | } |
@@ -1515,6 +1528,19 @@ SCTP_STATIC int sctp_sendmsg(struct kiocb *iocb, struct sock *sk, | |||
1515 | err = -EAGAIN; | 1528 | err = -EAGAIN; |
1516 | goto out_unlock; | 1529 | goto out_unlock; |
1517 | } | 1530 | } |
1531 | } else { | ||
1532 | /* | ||
1533 | * If an unprivileged user inherits a one-to-many | ||
1534 | * style socket with open associations on a privileged | ||
1535 | * port, it MAY be permitted to accept new associations, | ||
1536 | * but it SHOULD NOT be permitted to open new | ||
1537 | * associations. | ||
1538 | */ | ||
1539 | if (ep->base.bind_addr.port < PROT_SOCK && | ||
1540 | !capable(CAP_NET_BIND_SERVICE)) { | ||
1541 | err = -EACCES; | ||
1542 | goto out_unlock; | ||
1543 | } | ||
1518 | } | 1544 | } |
1519 | 1545 | ||
1520 | scope = sctp_scope(&to); | 1546 | scope = sctp_scope(&to); |
@@ -1611,10 +1637,10 @@ SCTP_STATIC int sctp_sendmsg(struct kiocb *iocb, struct sock *sk, | |||
1611 | 1637 | ||
1612 | /* If an address is passed with the sendto/sendmsg call, it is used | 1638 | /* If an address is passed with the sendto/sendmsg call, it is used |
1613 | * to override the primary destination address in the TCP model, or | 1639 | * to override the primary destination address in the TCP model, or |
1614 | * when MSG_ADDR_OVER flag is set in the UDP model. | 1640 | * when SCTP_ADDR_OVER flag is set in the UDP model. |
1615 | */ | 1641 | */ |
1616 | if ((sctp_style(sk, TCP) && msg_name) || | 1642 | if ((sctp_style(sk, TCP) && msg_name) || |
1617 | (sinfo_flags & MSG_ADDR_OVER)) { | 1643 | (sinfo_flags & SCTP_ADDR_OVER)) { |
1618 | chunk_tp = sctp_assoc_lookup_paddr(asoc, &to); | 1644 | chunk_tp = sctp_assoc_lookup_paddr(asoc, &to); |
1619 | if (!chunk_tp) { | 1645 | if (!chunk_tp) { |
1620 | err = -EINVAL; | 1646 | err = -EINVAL; |
@@ -2306,16 +2332,14 @@ static int sctp_setsockopt_maxseg(struct sock *sk, char __user *optval, int optl | |||
2306 | return -EINVAL; | 2332 | return -EINVAL; |
2307 | if (get_user(val, (int __user *)optval)) | 2333 | if (get_user(val, (int __user *)optval)) |
2308 | return -EFAULT; | 2334 | return -EFAULT; |
2309 | if ((val < 8) || (val > SCTP_MAX_CHUNK_LEN)) | 2335 | if ((val != 0) && ((val < 8) || (val > SCTP_MAX_CHUNK_LEN))) |
2310 | return -EINVAL; | 2336 | return -EINVAL; |
2311 | sp->user_frag = val; | 2337 | sp->user_frag = val; |
2312 | 2338 | ||
2313 | if (val) { | 2339 | /* Update the frag_point of the existing associations. */ |
2314 | /* Update the frag_point of the existing associations. */ | 2340 | list_for_each(pos, &(sp->ep->asocs)) { |
2315 | list_for_each(pos, &(sp->ep->asocs)) { | 2341 | asoc = list_entry(pos, struct sctp_association, asocs); |
2316 | asoc = list_entry(pos, struct sctp_association, asocs); | 2342 | asoc->frag_point = sctp_frag_point(sp, asoc->pmtu); |
2317 | asoc->frag_point = sctp_frag_point(sp, asoc->pmtu); | ||
2318 | } | ||
2319 | } | 2343 | } |
2320 | 2344 | ||
2321 | return 0; | 2345 | return 0; |
@@ -2384,14 +2408,14 @@ static int sctp_setsockopt_peer_primary_addr(struct sock *sk, char __user *optva | |||
2384 | static int sctp_setsockopt_adaption_layer(struct sock *sk, char __user *optval, | 2408 | static int sctp_setsockopt_adaption_layer(struct sock *sk, char __user *optval, |
2385 | int optlen) | 2409 | int optlen) |
2386 | { | 2410 | { |
2387 | __u32 val; | 2411 | struct sctp_setadaption adaption; |
2388 | 2412 | ||
2389 | if (optlen < sizeof(__u32)) | 2413 | if (optlen != sizeof(struct sctp_setadaption)) |
2390 | return -EINVAL; | 2414 | return -EINVAL; |
2391 | if (copy_from_user(&val, optval, sizeof(__u32))) | 2415 | if (copy_from_user(&adaption, optval, optlen)) |
2392 | return -EFAULT; | 2416 | return -EFAULT; |
2393 | 2417 | ||
2394 | sctp_sk(sk)->adaption_ind = val; | 2418 | sctp_sk(sk)->adaption_ind = adaption.ssb_adaption_ind; |
2395 | 2419 | ||
2396 | return 0; | 2420 | return 0; |
2397 | } | 2421 | } |
@@ -3672,17 +3696,15 @@ static int sctp_getsockopt_primary_addr(struct sock *sk, int len, | |||
3672 | static int sctp_getsockopt_adaption_layer(struct sock *sk, int len, | 3696 | static int sctp_getsockopt_adaption_layer(struct sock *sk, int len, |
3673 | char __user *optval, int __user *optlen) | 3697 | char __user *optval, int __user *optlen) |
3674 | { | 3698 | { |
3675 | __u32 val; | 3699 | struct sctp_setadaption adaption; |
3676 | 3700 | ||
3677 | if (len < sizeof(__u32)) | 3701 | if (len != sizeof(struct sctp_setadaption)) |
3678 | return -EINVAL; | 3702 | return -EINVAL; |
3679 | 3703 | ||
3680 | len = sizeof(__u32); | 3704 | adaption.ssb_adaption_ind = sctp_sk(sk)->adaption_ind; |
3681 | val = sctp_sk(sk)->adaption_ind; | 3705 | if (copy_to_user(optval, &adaption, len)) |
3682 | if (put_user(len, optlen)) | ||
3683 | return -EFAULT; | ||
3684 | if (copy_to_user(optval, &val, len)) | ||
3685 | return -EFAULT; | 3706 | return -EFAULT; |
3707 | |||
3686 | return 0; | 3708 | return 0; |
3687 | } | 3709 | } |
3688 | 3710 | ||
@@ -4640,8 +4662,8 @@ SCTP_STATIC int sctp_msghdr_parse(const struct msghdr *msg, | |||
4640 | 4662 | ||
4641 | /* Minimally, validate the sinfo_flags. */ | 4663 | /* Minimally, validate the sinfo_flags. */ |
4642 | if (cmsgs->info->sinfo_flags & | 4664 | if (cmsgs->info->sinfo_flags & |
4643 | ~(MSG_UNORDERED | MSG_ADDR_OVER | | 4665 | ~(SCTP_UNORDERED | SCTP_ADDR_OVER | |
4644 | MSG_ABORT | MSG_EOF)) | 4666 | SCTP_ABORT | SCTP_EOF)) |
4645 | return -EINVAL; | 4667 | return -EINVAL; |
4646 | break; | 4668 | break; |
4647 | 4669 | ||
diff --git a/net/sctp/ulpevent.c b/net/sctp/ulpevent.c index 057e7fac3af0..e049f41faa47 100644 --- a/net/sctp/ulpevent.c +++ b/net/sctp/ulpevent.c | |||
@@ -698,7 +698,7 @@ struct sctp_ulpevent *sctp_ulpevent_make_rcvmsg(struct sctp_association *asoc, | |||
698 | event->ssn = ntohs(chunk->subh.data_hdr->ssn); | 698 | event->ssn = ntohs(chunk->subh.data_hdr->ssn); |
699 | event->ppid = chunk->subh.data_hdr->ppid; | 699 | event->ppid = chunk->subh.data_hdr->ppid; |
700 | if (chunk->chunk_hdr->flags & SCTP_DATA_UNORDERED) { | 700 | if (chunk->chunk_hdr->flags & SCTP_DATA_UNORDERED) { |
701 | event->flags |= MSG_UNORDERED; | 701 | event->flags |= SCTP_UNORDERED; |
702 | event->cumtsn = sctp_tsnmap_get_ctsn(&asoc->peer.tsn_map); | 702 | event->cumtsn = sctp_tsnmap_get_ctsn(&asoc->peer.tsn_map); |
703 | } | 703 | } |
704 | event->tsn = ntohl(chunk->subh.data_hdr->tsn); | 704 | event->tsn = ntohl(chunk->subh.data_hdr->tsn); |
@@ -824,7 +824,7 @@ void sctp_ulpevent_read_sndrcvinfo(const struct sctp_ulpevent *event, | |||
824 | * | 824 | * |
825 | * recvmsg() flags: | 825 | * recvmsg() flags: |
826 | * | 826 | * |
827 | * MSG_UNORDERED - This flag is present when the message was sent | 827 | * SCTP_UNORDERED - This flag is present when the message was sent |
828 | * non-ordered. | 828 | * non-ordered. |
829 | */ | 829 | */ |
830 | sinfo.sinfo_flags = event->flags; | 830 | sinfo.sinfo_flags = event->flags; |
@@ -839,7 +839,7 @@ void sctp_ulpevent_read_sndrcvinfo(const struct sctp_ulpevent *event, | |||
839 | * This field will hold the current cumulative TSN as | 839 | * This field will hold the current cumulative TSN as |
840 | * known by the underlying SCTP layer. Note this field is | 840 | * known by the underlying SCTP layer. Note this field is |
841 | * ignored when sending and only valid for a receive | 841 | * ignored when sending and only valid for a receive |
842 | * operation when sinfo_flags are set to MSG_UNORDERED. | 842 | * operation when sinfo_flags are set to SCTP_UNORDERED. |
843 | */ | 843 | */ |
844 | sinfo.sinfo_cumtsn = event->cumtsn; | 844 | sinfo.sinfo_cumtsn = event->cumtsn; |
845 | /* sinfo_assoc_id: sizeof (sctp_assoc_t) | 845 | /* sinfo_assoc_id: sizeof (sctp_assoc_t) |
diff --git a/net/sunrpc/auth.c b/net/sunrpc/auth.c index a415d99c394d..8c7756036e95 100644 --- a/net/sunrpc/auth.c +++ b/net/sunrpc/auth.c | |||
@@ -299,11 +299,10 @@ put_rpccred(struct rpc_cred *cred) | |||
299 | void | 299 | void |
300 | rpcauth_unbindcred(struct rpc_task *task) | 300 | rpcauth_unbindcred(struct rpc_task *task) |
301 | { | 301 | { |
302 | struct rpc_auth *auth = task->tk_auth; | ||
303 | struct rpc_cred *cred = task->tk_msg.rpc_cred; | 302 | struct rpc_cred *cred = task->tk_msg.rpc_cred; |
304 | 303 | ||
305 | dprintk("RPC: %4d releasing %s cred %p\n", | 304 | dprintk("RPC: %4d releasing %s cred %p\n", |
306 | task->tk_pid, auth->au_ops->au_name, cred); | 305 | task->tk_pid, task->tk_auth->au_ops->au_name, cred); |
307 | 306 | ||
308 | put_rpccred(cred); | 307 | put_rpccred(cred); |
309 | task->tk_msg.rpc_cred = NULL; | 308 | task->tk_msg.rpc_cred = NULL; |
@@ -312,22 +311,22 @@ rpcauth_unbindcred(struct rpc_task *task) | |||
312 | u32 * | 311 | u32 * |
313 | rpcauth_marshcred(struct rpc_task *task, u32 *p) | 312 | rpcauth_marshcred(struct rpc_task *task, u32 *p) |
314 | { | 313 | { |
315 | struct rpc_auth *auth = task->tk_auth; | ||
316 | struct rpc_cred *cred = task->tk_msg.rpc_cred; | 314 | struct rpc_cred *cred = task->tk_msg.rpc_cred; |
317 | 315 | ||
318 | dprintk("RPC: %4d marshaling %s cred %p\n", | 316 | dprintk("RPC: %4d marshaling %s cred %p\n", |
319 | task->tk_pid, auth->au_ops->au_name, cred); | 317 | task->tk_pid, task->tk_auth->au_ops->au_name, cred); |
318 | |||
320 | return cred->cr_ops->crmarshal(task, p); | 319 | return cred->cr_ops->crmarshal(task, p); |
321 | } | 320 | } |
322 | 321 | ||
323 | u32 * | 322 | u32 * |
324 | rpcauth_checkverf(struct rpc_task *task, u32 *p) | 323 | rpcauth_checkverf(struct rpc_task *task, u32 *p) |
325 | { | 324 | { |
326 | struct rpc_auth *auth = task->tk_auth; | ||
327 | struct rpc_cred *cred = task->tk_msg.rpc_cred; | 325 | struct rpc_cred *cred = task->tk_msg.rpc_cred; |
328 | 326 | ||
329 | dprintk("RPC: %4d validating %s cred %p\n", | 327 | dprintk("RPC: %4d validating %s cred %p\n", |
330 | task->tk_pid, auth->au_ops->au_name, cred); | 328 | task->tk_pid, task->tk_auth->au_ops->au_name, cred); |
329 | |||
331 | return cred->cr_ops->crvalidate(task, p); | 330 | return cred->cr_ops->crvalidate(task, p); |
332 | } | 331 | } |
333 | 332 | ||
@@ -363,12 +362,12 @@ rpcauth_unwrap_resp(struct rpc_task *task, kxdrproc_t decode, void *rqstp, | |||
363 | int | 362 | int |
364 | rpcauth_refreshcred(struct rpc_task *task) | 363 | rpcauth_refreshcred(struct rpc_task *task) |
365 | { | 364 | { |
366 | struct rpc_auth *auth = task->tk_auth; | ||
367 | struct rpc_cred *cred = task->tk_msg.rpc_cred; | 365 | struct rpc_cred *cred = task->tk_msg.rpc_cred; |
368 | int err; | 366 | int err; |
369 | 367 | ||
370 | dprintk("RPC: %4d refreshing %s cred %p\n", | 368 | dprintk("RPC: %4d refreshing %s cred %p\n", |
371 | task->tk_pid, auth->au_ops->au_name, cred); | 369 | task->tk_pid, task->tk_auth->au_ops->au_name, cred); |
370 | |||
372 | err = cred->cr_ops->crrefresh(task); | 371 | err = cred->cr_ops->crrefresh(task); |
373 | if (err < 0) | 372 | if (err < 0) |
374 | task->tk_status = err; | 373 | task->tk_status = err; |
diff --git a/net/sunrpc/auth_gss/gss_krb5_crypto.c b/net/sunrpc/auth_gss/gss_krb5_crypto.c index 3f3d5437f02d..97c981fa6b8e 100644 --- a/net/sunrpc/auth_gss/gss_krb5_crypto.c +++ b/net/sunrpc/auth_gss/gss_krb5_crypto.c | |||
@@ -37,7 +37,7 @@ | |||
37 | #include <linux/types.h> | 37 | #include <linux/types.h> |
38 | #include <linux/mm.h> | 38 | #include <linux/mm.h> |
39 | #include <linux/slab.h> | 39 | #include <linux/slab.h> |
40 | #include <asm/scatterlist.h> | 40 | #include <linux/scatterlist.h> |
41 | #include <linux/crypto.h> | 41 | #include <linux/crypto.h> |
42 | #include <linux/highmem.h> | 42 | #include <linux/highmem.h> |
43 | #include <linux/pagemap.h> | 43 | #include <linux/pagemap.h> |
@@ -75,9 +75,7 @@ krb5_encrypt( | |||
75 | memcpy(local_iv, iv, crypto_tfm_alg_ivsize(tfm)); | 75 | memcpy(local_iv, iv, crypto_tfm_alg_ivsize(tfm)); |
76 | 76 | ||
77 | memcpy(out, in, length); | 77 | memcpy(out, in, length); |
78 | sg[0].page = virt_to_page(out); | 78 | sg_set_buf(sg, out, length); |
79 | sg[0].offset = offset_in_page(out); | ||
80 | sg[0].length = length; | ||
81 | 79 | ||
82 | ret = crypto_cipher_encrypt_iv(tfm, sg, sg, length, local_iv); | 80 | ret = crypto_cipher_encrypt_iv(tfm, sg, sg, length, local_iv); |
83 | 81 | ||
@@ -117,9 +115,7 @@ krb5_decrypt( | |||
117 | memcpy(local_iv,iv, crypto_tfm_alg_ivsize(tfm)); | 115 | memcpy(local_iv,iv, crypto_tfm_alg_ivsize(tfm)); |
118 | 116 | ||
119 | memcpy(out, in, length); | 117 | memcpy(out, in, length); |
120 | sg[0].page = virt_to_page(out); | 118 | sg_set_buf(sg, out, length); |
121 | sg[0].offset = offset_in_page(out); | ||
122 | sg[0].length = length; | ||
123 | 119 | ||
124 | ret = crypto_cipher_decrypt_iv(tfm, sg, sg, length, local_iv); | 120 | ret = crypto_cipher_decrypt_iv(tfm, sg, sg, length, local_iv); |
125 | 121 | ||
@@ -132,13 +128,6 @@ out: | |||
132 | 128 | ||
133 | EXPORT_SYMBOL(krb5_decrypt); | 129 | EXPORT_SYMBOL(krb5_decrypt); |
134 | 130 | ||
135 | static void | ||
136 | buf_to_sg(struct scatterlist *sg, char *ptr, int len) { | ||
137 | sg->page = virt_to_page(ptr); | ||
138 | sg->offset = offset_in_page(ptr); | ||
139 | sg->length = len; | ||
140 | } | ||
141 | |||
142 | static int | 131 | static int |
143 | process_xdr_buf(struct xdr_buf *buf, int offset, int len, | 132 | process_xdr_buf(struct xdr_buf *buf, int offset, int len, |
144 | int (*actor)(struct scatterlist *, void *), void *data) | 133 | int (*actor)(struct scatterlist *, void *), void *data) |
@@ -152,7 +141,7 @@ process_xdr_buf(struct xdr_buf *buf, int offset, int len, | |||
152 | thislen = buf->head[0].iov_len - offset; | 141 | thislen = buf->head[0].iov_len - offset; |
153 | if (thislen > len) | 142 | if (thislen > len) |
154 | thislen = len; | 143 | thislen = len; |
155 | buf_to_sg(sg, buf->head[0].iov_base + offset, thislen); | 144 | sg_set_buf(sg, buf->head[0].iov_base + offset, thislen); |
156 | ret = actor(sg, data); | 145 | ret = actor(sg, data); |
157 | if (ret) | 146 | if (ret) |
158 | goto out; | 147 | goto out; |
@@ -195,7 +184,7 @@ process_xdr_buf(struct xdr_buf *buf, int offset, int len, | |||
195 | thislen = buf->tail[0].iov_len - offset; | 184 | thislen = buf->tail[0].iov_len - offset; |
196 | if (thislen > len) | 185 | if (thislen > len) |
197 | thislen = len; | 186 | thislen = len; |
198 | buf_to_sg(sg, buf->tail[0].iov_base + offset, thislen); | 187 | sg_set_buf(sg, buf->tail[0].iov_base + offset, thislen); |
199 | ret = actor(sg, data); | 188 | ret = actor(sg, data); |
200 | len -= thislen; | 189 | len -= thislen; |
201 | } | 190 | } |
@@ -241,7 +230,7 @@ make_checksum(s32 cksumtype, char *header, int hdrlen, struct xdr_buf *body, | |||
241 | goto out; | 230 | goto out; |
242 | 231 | ||
243 | crypto_digest_init(tfm); | 232 | crypto_digest_init(tfm); |
244 | buf_to_sg(sg, header, hdrlen); | 233 | sg_set_buf(sg, header, hdrlen); |
245 | crypto_digest_update(tfm, sg, 1); | 234 | crypto_digest_update(tfm, sg, 1); |
246 | process_xdr_buf(body, body_offset, body->len - body_offset, | 235 | process_xdr_buf(body, body_offset, body->len - body_offset, |
247 | checksummer, tfm); | 236 | checksummer, tfm); |
diff --git a/net/sunrpc/sunrpc_syms.c b/net/sunrpc/sunrpc_syms.c index 2387e7b823ff..a03d4b600c92 100644 --- a/net/sunrpc/sunrpc_syms.c +++ b/net/sunrpc/sunrpc_syms.c | |||
@@ -63,8 +63,6 @@ EXPORT_SYMBOL(rpc_mkpipe); | |||
63 | /* Client transport */ | 63 | /* Client transport */ |
64 | EXPORT_SYMBOL(xprt_create_proto); | 64 | EXPORT_SYMBOL(xprt_create_proto); |
65 | EXPORT_SYMBOL(xprt_set_timeout); | 65 | EXPORT_SYMBOL(xprt_set_timeout); |
66 | EXPORT_SYMBOL(xprt_udp_slot_table_entries); | ||
67 | EXPORT_SYMBOL(xprt_tcp_slot_table_entries); | ||
68 | 66 | ||
69 | /* Client credential cache */ | 67 | /* Client credential cache */ |
70 | EXPORT_SYMBOL(rpcauth_register); | 68 | EXPORT_SYMBOL(rpcauth_register); |
diff --git a/net/sunrpc/sysctl.c b/net/sunrpc/sysctl.c index d0c9f460e411..1065904841fd 100644 --- a/net/sunrpc/sysctl.c +++ b/net/sunrpc/sysctl.c | |||
@@ -119,13 +119,6 @@ done: | |||
119 | return 0; | 119 | return 0; |
120 | } | 120 | } |
121 | 121 | ||
122 | unsigned int xprt_udp_slot_table_entries = RPC_DEF_SLOT_TABLE; | ||
123 | unsigned int xprt_tcp_slot_table_entries = RPC_DEF_SLOT_TABLE; | ||
124 | unsigned int xprt_min_resvport = RPC_DEF_MIN_RESVPORT; | ||
125 | EXPORT_SYMBOL(xprt_min_resvport); | ||
126 | unsigned int xprt_max_resvport = RPC_DEF_MAX_RESVPORT; | ||
127 | EXPORT_SYMBOL(xprt_max_resvport); | ||
128 | |||
129 | 122 | ||
130 | static unsigned int min_slot_table_size = RPC_MIN_SLOT_TABLE; | 123 | static unsigned int min_slot_table_size = RPC_MIN_SLOT_TABLE; |
131 | static unsigned int max_slot_table_size = RPC_MAX_SLOT_TABLE; | 124 | static unsigned int max_slot_table_size = RPC_MAX_SLOT_TABLE; |
diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c index 2e1529217e65..0a51fd46a848 100644 --- a/net/sunrpc/xprtsock.c +++ b/net/sunrpc/xprtsock.c | |||
@@ -36,6 +36,15 @@ | |||
36 | #include <net/tcp.h> | 36 | #include <net/tcp.h> |
37 | 37 | ||
38 | /* | 38 | /* |
39 | * xprtsock tunables | ||
40 | */ | ||
41 | unsigned int xprt_udp_slot_table_entries = RPC_DEF_SLOT_TABLE; | ||
42 | unsigned int xprt_tcp_slot_table_entries = RPC_DEF_SLOT_TABLE; | ||
43 | |||
44 | unsigned int xprt_min_resvport = RPC_DEF_MIN_RESVPORT; | ||
45 | unsigned int xprt_max_resvport = RPC_DEF_MAX_RESVPORT; | ||
46 | |||
47 | /* | ||
39 | * How many times to try sending a request on a socket before waiting | 48 | * How many times to try sending a request on a socket before waiting |
40 | * for the socket buffer to clear. | 49 | * for the socket buffer to clear. |
41 | */ | 50 | */ |