aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/bluetooth/hci_ldisc.c10
-rw-r--r--drivers/bluetooth/hci_uart.h5
-rw-r--r--drivers/net/irda/Kconfig14
-rw-r--r--drivers/net/irda/Makefile1
-rw-r--r--drivers/net/irda/kingsun-sir.c657
-rw-r--r--include/linux/netdevice.h2
-rw-r--r--include/linux/netfilter/x_tables.h8
-rw-r--r--include/linux/netfilter_arp/arp_tables.h41
-rw-r--r--include/linux/netfilter_ipv4/ip_tables.h22
-rw-r--r--include/linux/netfilter_ipv6/ip6_tables.h22
-rw-r--r--include/net/netfilter/nf_conntrack.h7
-rw-r--r--include/net/netfilter/nf_conntrack_l3proto.h3
-rw-r--r--include/net/netfilter/nf_nat_rule.h11
-rw-r--r--include/net/udp.h9
-rw-r--r--include/net/udplite.h2
-rw-r--r--net/bluetooth/hidp/core.c10
-rw-r--r--net/core/link_watch.c166
-rw-r--r--net/ipv4/netfilter/arptable_filter.c140
-rw-r--r--net/ipv4/netfilter/iptable_filter.c73
-rw-r--r--net/ipv4/netfilter/iptable_mangle.c99
-rw-r--r--net/ipv4/netfilter/iptable_raw.c79
-rw-r--r--net/ipv4/netfilter/nf_nat_rule.c86
-rw-r--r--net/ipv4/netfilter/nf_nat_standalone.c11
-rw-r--r--net/ipv4/udp.c85
-rw-r--r--net/ipv4/udp_impl.h6
-rw-r--r--net/ipv4/udplite.c7
-rw-r--r--net/ipv6/addrconf.c4
-rw-r--r--net/ipv6/exthdrs.c16
-rw-r--r--net/ipv6/ip6_output.c13
-rw-r--r--net/ipv6/netfilter/ip6table_filter.c70
-rw-r--r--net/ipv6/netfilter/ip6table_mangle.c96
-rw-r--r--net/ipv6/netfilter/ip6table_raw.c52
-rw-r--r--net/ipv6/udp.c21
-rw-r--r--net/ipv6/udp_impl.h2
-rw-r--r--net/ipv6/udplite.c2
-rw-r--r--net/mac80211/ieee80211_sta.c2
-rw-r--r--net/netfilter/nf_conntrack_core.c14
-rw-r--r--net/netfilter/nf_conntrack_netlink.c40
-rw-r--r--net/netfilter/xt_conntrack.c54
-rw-r--r--net/sched/sch_generic.c41
-rw-r--r--net/sched/sch_teql.c5
-rw-r--r--net/sctp/socket.c19
-rw-r--r--net/sctp/ulpevent.c11
43 files changed, 1312 insertions, 726 deletions
diff --git a/drivers/bluetooth/hci_ldisc.c b/drivers/bluetooth/hci_ldisc.c
index 0f4203b499af..6055b9c0ac0f 100644
--- a/drivers/bluetooth/hci_ldisc.c
+++ b/drivers/bluetooth/hci_ldisc.c
@@ -307,7 +307,9 @@ static void hci_uart_tty_close(struct tty_struct *tty)
307 307
308 if (hu) { 308 if (hu) {
309 struct hci_dev *hdev = hu->hdev; 309 struct hci_dev *hdev = hu->hdev;
310 hci_uart_close(hdev); 310
311 if (hdev)
312 hci_uart_close(hdev);
311 313
312 if (test_and_clear_bit(HCI_UART_PROTO_SET, &hu->flags)) { 314 if (test_and_clear_bit(HCI_UART_PROTO_SET, &hu->flags)) {
313 hu->proto->close(hu); 315 hu->proto->close(hu);
@@ -473,12 +475,18 @@ static int hci_uart_tty_ioctl(struct tty_struct *tty, struct file * file,
473 tty->low_latency = 1; 475 tty->low_latency = 1;
474 } else 476 } else
475 return -EBUSY; 477 return -EBUSY;
478 break;
476 479
477 case HCIUARTGETPROTO: 480 case HCIUARTGETPROTO:
478 if (test_bit(HCI_UART_PROTO_SET, &hu->flags)) 481 if (test_bit(HCI_UART_PROTO_SET, &hu->flags))
479 return hu->proto->id; 482 return hu->proto->id;
480 return -EUNATCH; 483 return -EUNATCH;
481 484
485 case HCIUARTGETDEVICE:
486 if (test_bit(HCI_UART_PROTO_SET, &hu->flags))
487 return hu->hdev->id;
488 return -EUNATCH;
489
482 default: 490 default:
483 err = n_tty_ioctl(tty, file, cmd, arg); 491 err = n_tty_ioctl(tty, file, cmd, arg);
484 break; 492 break;
diff --git a/drivers/bluetooth/hci_uart.h b/drivers/bluetooth/hci_uart.h
index b250e6789dee..1097ce72393f 100644
--- a/drivers/bluetooth/hci_uart.h
+++ b/drivers/bluetooth/hci_uart.h
@@ -28,8 +28,9 @@
28#endif 28#endif
29 29
30/* Ioctls */ 30/* Ioctls */
31#define HCIUARTSETPROTO _IOW('U', 200, int) 31#define HCIUARTSETPROTO _IOW('U', 200, int)
32#define HCIUARTGETPROTO _IOR('U', 201, int) 32#define HCIUARTGETPROTO _IOR('U', 201, int)
33#define HCIUARTGETDEVICE _IOR('U', 202, int)
33 34
34/* UART protocols */ 35/* UART protocols */
35#define HCI_UART_MAX_PROTO 4 36#define HCI_UART_MAX_PROTO 4
diff --git a/drivers/net/irda/Kconfig b/drivers/net/irda/Kconfig
index 7c8ccc09b601..829da9a1d113 100644
--- a/drivers/net/irda/Kconfig
+++ b/drivers/net/irda/Kconfig
@@ -141,6 +141,20 @@ config ACT200L_DONGLE
141 To activate support for ACTiSYS IR-200L dongle you will have to 141 To activate support for ACTiSYS IR-200L dongle you will have to
142 start irattach like this: "irattach -d act200l". 142 start irattach like this: "irattach -d act200l".
143 143
144config KINGSUN_DONGLE
145 tristate "KingSun/DonShine DS-620 IrDA-USB dongle"
146 depends on IRDA && USB && EXPERIMENTAL
147 help
148 Say Y or M here if you want to build support for the KingSun/DonShine
149 DS-620 IrDA-USB bridge device driver.
150
151 This USB bridge does not conform to the IrDA-USB device class
152 specification, and therefore needs its own specific driver. This
153 dongle supports SIR speed only (9600 bps).
154
155 To compile it as a module, choose M here: the module will be called
156 kingsun-sir.
157
144comment "Old SIR device drivers" 158comment "Old SIR device drivers"
145 159
146config IRPORT_SIR 160config IRPORT_SIR
diff --git a/drivers/net/irda/Makefile b/drivers/net/irda/Makefile
index 5be09f1b9ee2..233a2f923730 100644
--- a/drivers/net/irda/Makefile
+++ b/drivers/net/irda/Makefile
@@ -45,6 +45,7 @@ obj-$(CONFIG_MCP2120_DONGLE) += mcp2120-sir.o
45obj-$(CONFIG_ACT200L_DONGLE) += act200l-sir.o 45obj-$(CONFIG_ACT200L_DONGLE) += act200l-sir.o
46obj-$(CONFIG_MA600_DONGLE) += ma600-sir.o 46obj-$(CONFIG_MA600_DONGLE) += ma600-sir.o
47obj-$(CONFIG_TOIM3232_DONGLE) += toim3232-sir.o 47obj-$(CONFIG_TOIM3232_DONGLE) += toim3232-sir.o
48obj-$(CONFIG_KINGSUN_DONGLE) += kingsun-sir.o
48 49
49# The SIR helper module 50# The SIR helper module
50sir-dev-objs := sir_dev.o sir_dongle.o 51sir-dev-objs := sir_dev.o sir_dongle.o
diff --git a/drivers/net/irda/kingsun-sir.c b/drivers/net/irda/kingsun-sir.c
new file mode 100644
index 000000000000..217429122e79
--- /dev/null
+++ b/drivers/net/irda/kingsun-sir.c
@@ -0,0 +1,657 @@
1/*****************************************************************************
2*
3* Filename: kingsun-sir.c
4* Version: 0.1.1
5* Description: Irda KingSun/DonShine USB Dongle
6* Status: Experimental
7* Author: Alex Villac�s Lasso <a_villacis@palosanto.com>
8*
9* Based on stir4200 and mcs7780 drivers, with (strange?) differences
10*
11* This program is free software; you can redistribute it and/or modify
12* it under the terms of the GNU General Public License as published by
13* the Free Software Foundation; either version 2 of the License.
14*
15* This program is distributed in the hope that it will be useful,
16* but WITHOUT ANY WARRANTY; without even the implied warranty of
17* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18* GNU General Public License for more details.
19*
20* You should have received a copy of the GNU General Public License
21* along with this program; if not, write to the Free Software
22* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23*
24*****************************************************************************/
25
26/*
27 * This is my current (2007-04-25) understanding of how this dongle is supposed
28 * to work. This is based on reverse-engineering and examination of the packet
29 * data sent and received by the WinXP driver using USBSnoopy. Feel free to
30 * update here as more of this dongle is known:
31 *
32 * General: Unlike the other USB IrDA dongles, this particular dongle exposes,
33 * not two bulk (in and out) endpoints, but two *interrupt* ones. This dongle,
34 * like the bulk based ones (stir4200.c and mcs7780.c), requires polling in
35 * order to receive data.
36 * Transmission: Just like stir4200, this dongle uses a raw stream of data,
37 * which needs to be wrapped and escaped in a similar way as in stir4200.c.
38 * Reception: Poll-based, as in stir4200. Each read returns the contents of a
39 * 8-byte buffer, of which the first byte (LSB) indicates the number of bytes
40 * (1-7) of valid data contained within the remaining 7 bytes. For example, if
41 * the buffer had the following contents:
42 * 06 ff ff ff c0 01 04 aa
43 * This means that (06) there are 6 bytes of valid data. The byte 0xaa at the
44 * end is garbage (left over from a previous reception) and is discarded.
45 * If a read returns an "impossible" value as the length of valid data (such as
46 * 0x36) in the first byte, then the buffer is uninitialized (as is the case of
47 * first plug-in) and its contents should be discarded. There is currently no
48 * evidence that the top 5 bits of the 1st byte of the buffer can have values
49 * other than 0 once reception begins.
50 * Once valid bytes are collected, the assembled stream is a sequence of
51 * wrapped IrDA frames that is unwrapped and unescaped as in stir4200.c.
52 * BIG FAT WARNING: the dongle does *not* reset the RX buffer in any way after
53 * a successful read from the host, which means that in absence of further
54 * reception, repeated reads from the dongle will return the exact same
55 * contents repeatedly. Attempts to be smart and cache a previous read seem
56 * to result in corrupted packets, so this driver depends on the unwrap logic
57 * to sort out any repeated reads.
58 * Speed change: no commands observed so far to change speed, assumed fixed
59 * 9600bps (SIR).
60 */
61
62#include <linux/module.h>
63#include <linux/moduleparam.h>
64#include <linux/kernel.h>
65#include <linux/types.h>
66#include <linux/errno.h>
67#include <linux/init.h>
68#include <linux/slab.h>
69#include <linux/module.h>
70#include <linux/kref.h>
71#include <linux/usb.h>
72#include <linux/device.h>
73#include <linux/crc32.h>
74
75#include <asm/unaligned.h>
76#include <asm/byteorder.h>
77#include <asm/uaccess.h>
78
79#include <net/irda/irda.h>
80#include <net/irda/wrapper.h>
81#include <net/irda/crc.h>
82
83/*
84 * According to lsusb, 0x07c0 is assigned to
85 * "Code Mercenaries Hard- und Software GmbH"
86 */
87#define KING_VENDOR_ID 0x07c0
88#define KING_PRODUCT_ID 0x4200
89
90/* These are the currently known USB ids */
91static struct usb_device_id dongles[] = {
92 /* KingSun Co,Ltd IrDA/USB Bridge */
93 { USB_DEVICE(KING_VENDOR_ID, KING_PRODUCT_ID) },
94 { }
95};
96
97MODULE_DEVICE_TABLE(usb, dongles);
98
99#define KINGSUN_MTT 0x07
100
101#define KINGSUN_FIFO_SIZE 4096
102#define KINGSUN_EP_IN 0
103#define KINGSUN_EP_OUT 1
104
105struct kingsun_cb {
106 struct usb_device *usbdev; /* init: probe_irda */
107 struct net_device *netdev; /* network layer */
108 struct irlap_cb *irlap; /* The link layer we are binded to */
109 struct net_device_stats stats; /* network statistics */
110 struct qos_info qos;
111
112 __u8 *in_buf; /* receive buffer */
113 __u8 *out_buf; /* transmit buffer */
114 __u8 max_rx; /* max. atomic read from dongle
115 (usually 8), also size of in_buf */
116 __u8 max_tx; /* max. atomic write to dongle
117 (usually 8) */
118
119 iobuff_t rx_buff; /* receive unwrap state machine */
120 struct timeval rx_time;
121 spinlock_t lock;
122 int receiving;
123
124 __u8 ep_in;
125 __u8 ep_out;
126
127 struct urb *tx_urb;
128 struct urb *rx_urb;
129};
130
131/* Callback transmission routine */
132static void kingsun_send_irq(struct urb *urb)
133{
134 struct kingsun_cb *kingsun = urb->context;
135 struct net_device *netdev = kingsun->netdev;
136
137 /* in process of stopping, just drop data */
138 if (!netif_running(kingsun->netdev)) {
139 err("kingsun_send_irq: Network not running!");
140 return;
141 }
142
143 /* unlink, shutdown, unplug, other nasties */
144 if (urb->status != 0) {
145 err("kingsun_send_irq: urb asynchronously failed - %d",
146 urb->status);
147 }
148 netif_wake_queue(netdev);
149}
150
151/*
152 * Called from net/core when new frame is available.
153 */
154static int kingsun_hard_xmit(struct sk_buff *skb, struct net_device *netdev)
155{
156 struct kingsun_cb *kingsun;
157 int wraplen;
158 int ret = 0;
159
160 if (skb == NULL || netdev == NULL)
161 return -EINVAL;
162
163 netif_stop_queue(netdev);
164
165 /* the IRDA wrapping routines don't deal with non linear skb */
166 SKB_LINEAR_ASSERT(skb);
167
168 kingsun = netdev_priv(netdev);
169
170 spin_lock(&kingsun->lock);
171
172 /* Append data to the end of whatever data remains to be transmitted */
173 wraplen = async_wrap_skb(skb,
174 kingsun->out_buf,
175 KINGSUN_FIFO_SIZE);
176
177 /* Calculate how much data can be transmitted in this urb */
178 usb_fill_int_urb(kingsun->tx_urb, kingsun->usbdev,
179 usb_sndintpipe(kingsun->usbdev, kingsun->ep_out),
180 kingsun->out_buf, wraplen, kingsun_send_irq,
181 kingsun, 1);
182
183 if ((ret = usb_submit_urb(kingsun->tx_urb, GFP_ATOMIC))) {
184 err("kingsun_hard_xmit: failed tx_urb submit: %d", ret);
185 switch (ret) {
186 case -ENODEV:
187 case -EPIPE:
188 break;
189 default:
190 kingsun->stats.tx_errors++;
191 netif_start_queue(netdev);
192 }
193 } else {
194 kingsun->stats.tx_packets++;
195 kingsun->stats.tx_bytes += skb->len;
196 }
197
198 dev_kfree_skb(skb);
199 spin_unlock(&kingsun->lock);
200
201 return ret;
202}
203
204/* Receive callback function */
205static void kingsun_rcv_irq(struct urb *urb)
206{
207 struct kingsun_cb *kingsun = urb->context;
208 int ret;
209
210 /* in process of stopping, just drop data */
211 if (!netif_running(kingsun->netdev)) {
212 kingsun->receiving = 0;
213 return;
214 }
215
216 /* unlink, shutdown, unplug, other nasties */
217 if (urb->status != 0) {
218 err("kingsun_rcv_irq: urb asynchronously failed - %d",
219 urb->status);
220 kingsun->receiving = 0;
221 return;
222 }
223
224 if (urb->actual_length == kingsun->max_rx) {
225 __u8 *bytes = urb->transfer_buffer;
226 int i;
227
228 /* The very first byte in the buffer indicates the length of
229 valid data in the read. This byte must be in the range
230 1..kingsun->max_rx -1 . Values outside this range indicate
231 an uninitialized Rx buffer when the dongle has just been
232 plugged in. */
233 if (bytes[0] >= 1 && bytes[0] < kingsun->max_rx) {
234 for (i = 1; i <= bytes[0]; i++) {
235 async_unwrap_char(kingsun->netdev,
236 &kingsun->stats,
237 &kingsun->rx_buff, bytes[i]);
238 }
239 kingsun->netdev->last_rx = jiffies;
240 do_gettimeofday(&kingsun->rx_time);
241 kingsun->receiving =
242 (kingsun->rx_buff.state != OUTSIDE_FRAME)
243 ? 1 : 0;
244 }
245 } else if (urb->actual_length > 0) {
246 err("%s(): Unexpected response length, expected %d got %d",
247 __FUNCTION__, kingsun->max_rx, urb->actual_length);
248 }
249 /* This urb has already been filled in kingsun_net_open */
250 ret = usb_submit_urb(urb, GFP_ATOMIC);
251}
252
253/*
254 * Function kingsun_net_open (dev)
255 *
256 * Network device is taken up. Usually this is done by "ifconfig irda0 up"
257 */
258static int kingsun_net_open(struct net_device *netdev)
259{
260 struct kingsun_cb *kingsun = netdev_priv(netdev);
261 int err = -ENOMEM;
262 char hwname[16];
263
264 /* At this point, urbs are NULL, and skb is NULL (see kingsun_probe) */
265 kingsun->receiving = 0;
266
267 /* Initialize for SIR to copy data directly into skb. */
268 kingsun->rx_buff.in_frame = FALSE;
269 kingsun->rx_buff.state = OUTSIDE_FRAME;
270 kingsun->rx_buff.truesize = IRDA_SKB_MAX_MTU;
271 kingsun->rx_buff.skb = dev_alloc_skb(IRDA_SKB_MAX_MTU);
272 if (!kingsun->rx_buff.skb)
273 goto free_mem;
274
275 skb_reserve(kingsun->rx_buff.skb, 1);
276 kingsun->rx_buff.head = kingsun->rx_buff.skb->data;
277 do_gettimeofday(&kingsun->rx_time);
278
279 kingsun->rx_urb = usb_alloc_urb(0, GFP_KERNEL);
280 if (!kingsun->rx_urb)
281 goto free_mem;
282
283 kingsun->tx_urb = usb_alloc_urb(0, GFP_KERNEL);
284 if (!kingsun->tx_urb)
285 goto free_mem;
286
287 /*
288 * Now that everything should be initialized properly,
289 * Open new IrLAP layer instance to take care of us...
290 */
291 sprintf(hwname, "usb#%d", kingsun->usbdev->devnum);
292 kingsun->irlap = irlap_open(netdev, &kingsun->qos, hwname);
293 if (!kingsun->irlap) {
294 err("kingsun-sir: irlap_open failed");
295 goto free_mem;
296 }
297
298 /* Start first reception */
299 usb_fill_int_urb(kingsun->rx_urb, kingsun->usbdev,
300 usb_rcvintpipe(kingsun->usbdev, kingsun->ep_in),
301 kingsun->in_buf, kingsun->max_rx,
302 kingsun_rcv_irq, kingsun, 1);
303 kingsun->rx_urb->status = 0;
304 err = usb_submit_urb(kingsun->rx_urb, GFP_KERNEL);
305 if (err) {
306 err("kingsun-sir: first urb-submit failed: %d", err);
307 goto close_irlap;
308 }
309
310 netif_start_queue(netdev);
311
312 /* Situation at this point:
313 - all work buffers allocated
314 - urbs allocated and ready to fill
315 - max rx packet known (in max_rx)
316 - unwrap state machine initialized, in state outside of any frame
317 - receive request in progress
318 - IrLAP layer started, about to hand over packets to send
319 */
320
321 return 0;
322
323 close_irlap:
324 irlap_close(kingsun->irlap);
325 free_mem:
326 if (kingsun->tx_urb) {
327 usb_free_urb(kingsun->tx_urb);
328 kingsun->tx_urb = NULL;
329 }
330 if (kingsun->rx_urb) {
331 usb_free_urb(kingsun->rx_urb);
332 kingsun->rx_urb = NULL;
333 }
334 if (kingsun->rx_buff.skb) {
335 kfree_skb(kingsun->rx_buff.skb);
336 kingsun->rx_buff.skb = NULL;
337 kingsun->rx_buff.head = NULL;
338 }
339 return err;
340}
341
342/*
343 * Function kingsun_net_close (kingsun)
344 *
345 * Network device is taken down. Usually this is done by
346 * "ifconfig irda0 down"
347 */
348static int kingsun_net_close(struct net_device *netdev)
349{
350 struct kingsun_cb *kingsun = netdev_priv(netdev);
351
352 /* Stop transmit processing */
353 netif_stop_queue(netdev);
354
355 /* Mop up receive && transmit urb's */
356 usb_kill_urb(kingsun->tx_urb);
357 usb_kill_urb(kingsun->rx_urb);
358
359 usb_free_urb(kingsun->tx_urb);
360 usb_free_urb(kingsun->rx_urb);
361
362 kingsun->tx_urb = NULL;
363 kingsun->rx_urb = NULL;
364
365 kfree_skb(kingsun->rx_buff.skb);
366 kingsun->rx_buff.skb = NULL;
367 kingsun->rx_buff.head = NULL;
368 kingsun->rx_buff.in_frame = FALSE;
369 kingsun->rx_buff.state = OUTSIDE_FRAME;
370 kingsun->receiving = 0;
371
372 /* Stop and remove instance of IrLAP */
373 if (kingsun->irlap)
374 irlap_close(kingsun->irlap);
375
376 kingsun->irlap = NULL;
377
378 return 0;
379}
380
381/*
382 * IOCTLs : Extra out-of-band network commands...
383 */
384static int kingsun_net_ioctl(struct net_device *netdev, struct ifreq *rq,
385 int cmd)
386{
387 struct if_irda_req *irq = (struct if_irda_req *) rq;
388 struct kingsun_cb *kingsun = netdev_priv(netdev);
389 int ret = 0;
390
391 switch (cmd) {
392 case SIOCSBANDWIDTH: /* Set bandwidth */
393 if (!capable(CAP_NET_ADMIN))
394 return -EPERM;
395
396 /* Check if the device is still there */
397 if (netif_device_present(kingsun->netdev))
398 /* No observed commands for speed change */
399 ret = -EOPNOTSUPP;
400 break;
401
402 case SIOCSMEDIABUSY: /* Set media busy */
403 if (!capable(CAP_NET_ADMIN))
404 return -EPERM;
405
406 /* Check if the IrDA stack is still there */
407 if (netif_running(kingsun->netdev))
408 irda_device_set_media_busy(kingsun->netdev, TRUE);
409 break;
410
411 case SIOCGRECEIVING:
412 /* Only approximately true */
413 irq->ifr_receiving = kingsun->receiving;
414 break;
415
416 default:
417 ret = -EOPNOTSUPP;
418 }
419
420 return ret;
421}
422
423/*
424 * Get device stats (for /proc/net/dev and ifconfig)
425 */
426static struct net_device_stats *
427kingsun_net_get_stats(struct net_device *netdev)
428{
429 struct kingsun_cb *kingsun = netdev_priv(netdev);
430 return &kingsun->stats;
431}
432
433/*
434 * This routine is called by the USB subsystem for each new device
435 * in the system. We need to check if the device is ours, and in
436 * this case start handling it.
437 */
438static int kingsun_probe(struct usb_interface *intf,
439 const struct usb_device_id *id)
440{
441 struct usb_host_interface *interface;
442 struct usb_endpoint_descriptor *endpoint;
443
444 struct usb_device *dev = interface_to_usbdev(intf);
445 struct kingsun_cb *kingsun = NULL;
446 struct net_device *net = NULL;
447 int ret = -ENOMEM;
448 int pipe, maxp_in, maxp_out;
449 __u8 ep_in;
450 __u8 ep_out;
451
452 /* Check that there really are two interrupt endpoints.
453 Check based on the one in drivers/usb/input/usbmouse.c
454 */
455 interface = intf->cur_altsetting;
456 if (interface->desc.bNumEndpoints != 2) {
457 err("kingsun-sir: expected 2 endpoints, found %d",
458 interface->desc.bNumEndpoints);
459 return -ENODEV;
460 }
461 endpoint = &interface->endpoint[KINGSUN_EP_IN].desc;
462 if (!usb_endpoint_is_int_in(endpoint)) {
463 err("kingsun-sir: endpoint 0 is not interrupt IN");
464 return -ENODEV;
465 }
466
467 ep_in = endpoint->bEndpointAddress;
468 pipe = usb_rcvintpipe(dev, ep_in);
469 maxp_in = usb_maxpacket(dev, pipe, usb_pipeout(pipe));
470 if (maxp_in > 255 || maxp_in <= 1) {
471 err("%s: endpoint 0 has max packet size %d not in range",
472 __FILE__, maxp_in);
473 return -ENODEV;
474 }
475
476 endpoint = &interface->endpoint[KINGSUN_EP_OUT].desc;
477 if (!usb_endpoint_is_int_out(endpoint)) {
478 err("kingsun-sir: endpoint 1 is not interrupt OUT");
479 return -ENODEV;
480 }
481
482 ep_out = endpoint->bEndpointAddress;
483 pipe = usb_sndintpipe(dev, ep_out);
484 maxp_out = usb_maxpacket(dev, pipe, usb_pipeout(pipe));
485
486 /* Allocate network device container. */
487 net = alloc_irdadev(sizeof(*kingsun));
488 if(!net)
489 goto err_out1;
490
491 SET_MODULE_OWNER(net);
492 SET_NETDEV_DEV(net, &intf->dev);
493 kingsun = netdev_priv(net);
494 kingsun->irlap = NULL;
495 kingsun->tx_urb = NULL;
496 kingsun->rx_urb = NULL;
497 kingsun->ep_in = ep_in;
498 kingsun->ep_out = ep_out;
499 kingsun->in_buf = NULL;
500 kingsun->out_buf = NULL;
501 kingsun->max_rx = (__u8)maxp_in;
502 kingsun->max_tx = (__u8)maxp_out;
503 kingsun->netdev = net;
504 kingsun->usbdev = dev;
505 kingsun->rx_buff.in_frame = FALSE;
506 kingsun->rx_buff.state = OUTSIDE_FRAME;
507 kingsun->rx_buff.skb = NULL;
508 kingsun->receiving = 0;
509 spin_lock_init(&kingsun->lock);
510
511 /* Allocate input buffer */
512 kingsun->in_buf = (__u8 *)kmalloc(kingsun->max_rx, GFP_KERNEL);
513 if (!kingsun->in_buf)
514 goto free_mem;
515
516 /* Allocate output buffer */
517 kingsun->out_buf = (__u8 *)kmalloc(KINGSUN_FIFO_SIZE, GFP_KERNEL);
518 if (!kingsun->out_buf)
519 goto free_mem;
520
521 printk(KERN_INFO "KingSun/DonShine IRDA/USB found at address %d, "
522 "Vendor: %x, Product: %x\n",
523 dev->devnum, le16_to_cpu(dev->descriptor.idVendor),
524 le16_to_cpu(dev->descriptor.idProduct));
525
526 /* Initialize QoS for this device */
527 irda_init_max_qos_capabilies(&kingsun->qos);
528
529 /* That's the Rx capability. */
530 kingsun->qos.baud_rate.bits &= IR_9600;
531 kingsun->qos.min_turn_time.bits &= KINGSUN_MTT;
532 irda_qos_bits_to_value(&kingsun->qos);
533
534 /* Override the network functions we need to use */
535 net->hard_start_xmit = kingsun_hard_xmit;
536 net->open = kingsun_net_open;
537 net->stop = kingsun_net_close;
538 net->get_stats = kingsun_net_get_stats;
539 net->do_ioctl = kingsun_net_ioctl;
540
541 ret = register_netdev(net);
542 if (ret != 0)
543 goto free_mem;
544
545 info("IrDA: Registered KingSun/DonShine device %s", net->name);
546
547 usb_set_intfdata(intf, kingsun);
548
549 /* Situation at this point:
550 - all work buffers allocated
551 - urbs not allocated, set to NULL
552 - max rx packet known (in max_rx)
553 - unwrap state machine (partially) initialized, but skb == NULL
554 */
555
556 return 0;
557
558free_mem:
559 if (kingsun->out_buf) kfree(kingsun->out_buf);
560 if (kingsun->in_buf) kfree(kingsun->in_buf);
561 free_netdev(net);
562err_out1:
563 return ret;
564}
565
566/*
567 * The current device is removed, the USB layer tell us to shut it down...
568 */
569static void kingsun_disconnect(struct usb_interface *intf)
570{
571 struct kingsun_cb *kingsun = usb_get_intfdata(intf);
572
573 if (!kingsun)
574 return;
575
576 unregister_netdev(kingsun->netdev);
577
578 /* Mop up receive && transmit urb's */
579 if (kingsun->tx_urb != NULL) {
580 usb_kill_urb(kingsun->tx_urb);
581 usb_free_urb(kingsun->tx_urb);
582 kingsun->tx_urb = NULL;
583 }
584 if (kingsun->rx_urb != NULL) {
585 usb_kill_urb(kingsun->rx_urb);
586 usb_free_urb(kingsun->rx_urb);
587 kingsun->rx_urb = NULL;
588 }
589
590 kfree(kingsun->out_buf);
591 kfree(kingsun->in_buf);
592 free_netdev(kingsun->netdev);
593
594 usb_set_intfdata(intf, NULL);
595}
596
597#ifdef CONFIG_PM
598/* USB suspend, so power off the transmitter/receiver */
599static int kingsun_suspend(struct usb_interface *intf, pm_message_t message)
600{
601 struct kingsun_cb *kingsun = usb_get_intfdata(intf);
602
603 netif_device_detach(kingsun->netdev);
604 if (kingsun->tx_urb != NULL) usb_kill_urb(kingsun->tx_urb);
605 if (kingsun->rx_urb != NULL) usb_kill_urb(kingsun->rx_urb);
606 return 0;
607}
608
609/* Coming out of suspend, so reset hardware */
610static int kingsun_resume(struct usb_interface *intf)
611{
612 struct kingsun_cb *kingsun = usb_get_intfdata(intf);
613
614 if (kingsun->rx_urb != NULL)
615 usb_submit_urb(kingsun->rx_urb, GFP_KERNEL);
616 netif_device_attach(kingsun->netdev);
617
618 return 0;
619}
620#endif
621
622/*
623 * USB device callbacks
624 */
625static struct usb_driver irda_driver = {
626 .name = "kingsun-sir",
627 .probe = kingsun_probe,
628 .disconnect = kingsun_disconnect,
629 .id_table = dongles,
630#ifdef CONFIG_PM
631 .suspend = kingsun_suspend,
632 .resume = kingsun_resume,
633#endif
634};
635
636/*
637 * Module insertion
638 */
639static int __init kingsun_init(void)
640{
641 return usb_register(&irda_driver);
642}
643module_init(kingsun_init);
644
645/*
646 * Module removal
647 */
648static void __exit kingsun_cleanup(void)
649{
650 /* Deregister the driver and remove all pending instances */
651 usb_deregister(&irda_driver);
652}
653module_exit(kingsun_cleanup);
654
655MODULE_AUTHOR("Alex Villac�s Lasso <a_villacis@palosanto.com>");
656MODULE_DESCRIPTION("IrDA-USB Dongle Driver for KingSun/DonShine");
657MODULE_LICENSE("GPL");
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 30446222b396..f671cd2f133f 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -467,6 +467,8 @@ struct net_device
467 /* device index hash chain */ 467 /* device index hash chain */
468 struct hlist_node index_hlist; 468 struct hlist_node index_hlist;
469 469
470 struct net_device *link_watch_next;
471
470 /* register/unregister state machine */ 472 /* register/unregister state machine */
471 enum { NETREG_UNINITIALIZED=0, 473 enum { NETREG_UNINITIALIZED=0,
472 NETREG_REGISTERED, /* completed register_netdevice */ 474 NETREG_REGISTERED, /* completed register_netdevice */
diff --git a/include/linux/netfilter/x_tables.h b/include/linux/netfilter/x_tables.h
index 022edfa97ed9..7e733a6ba4f6 100644
--- a/include/linux/netfilter/x_tables.h
+++ b/include/linux/netfilter/x_tables.h
@@ -54,6 +54,14 @@ struct xt_entry_target
54 unsigned char data[0]; 54 unsigned char data[0];
55}; 55};
56 56
57#define XT_TARGET_INIT(__name, __size) \
58{ \
59 .target.u.user = { \
60 .target_size = XT_ALIGN(__size), \
61 .name = __name, \
62 }, \
63}
64
57struct xt_standard_target 65struct xt_standard_target
58{ 66{
59 struct xt_entry_target target; 67 struct xt_entry_target target;
diff --git a/include/linux/netfilter_arp/arp_tables.h b/include/linux/netfilter_arp/arp_tables.h
index 24c8786d12e9..584cd1b18f12 100644
--- a/include/linux/netfilter_arp/arp_tables.h
+++ b/include/linux/netfilter_arp/arp_tables.h
@@ -238,6 +238,47 @@ static __inline__ struct arpt_entry_target *arpt_get_target(struct arpt_entry *e
238 */ 238 */
239#ifdef __KERNEL__ 239#ifdef __KERNEL__
240 240
241/* Standard entry. */
242struct arpt_standard
243{
244 struct arpt_entry entry;
245 struct arpt_standard_target target;
246};
247
248struct arpt_error_target
249{
250 struct arpt_entry_target target;
251 char errorname[ARPT_FUNCTION_MAXNAMELEN];
252};
253
254struct arpt_error
255{
256 struct arpt_entry entry;
257 struct arpt_error_target target;
258};
259
260#define ARPT_ENTRY_INIT(__size) \
261{ \
262 .target_offset = sizeof(struct arpt_entry), \
263 .next_offset = (__size), \
264}
265
266#define ARPT_STANDARD_INIT(__verdict) \
267{ \
268 .entry = ARPT_ENTRY_INIT(sizeof(struct arpt_standard)), \
269 .target = XT_TARGET_INIT(ARPT_STANDARD_TARGET, \
270 sizeof(struct arpt_standard_target)), \
271 .target.verdict = -(__verdict) - 1, \
272}
273
274#define ARPT_ERROR_INIT \
275{ \
276 .entry = ARPT_ENTRY_INIT(sizeof(struct arpt_error)), \
277 .target = XT_TARGET_INIT(ARPT_ERROR_TARGET, \
278 sizeof(struct arpt_error_target)), \
279 .target.errorname = "ERROR", \
280}
281
241#define arpt_register_target(tgt) \ 282#define arpt_register_target(tgt) \
242({ (tgt)->family = NF_ARP; \ 283({ (tgt)->family = NF_ARP; \
243 xt_register_target(tgt); }) 284 xt_register_target(tgt); })
diff --git a/include/linux/netfilter_ipv4/ip_tables.h b/include/linux/netfilter_ipv4/ip_tables.h
index 9527296595cd..2f46dd728ee1 100644
--- a/include/linux/netfilter_ipv4/ip_tables.h
+++ b/include/linux/netfilter_ipv4/ip_tables.h
@@ -295,6 +295,28 @@ struct ipt_error
295 struct ipt_error_target target; 295 struct ipt_error_target target;
296}; 296};
297 297
298#define IPT_ENTRY_INIT(__size) \
299{ \
300 .target_offset = sizeof(struct ipt_entry), \
301 .next_offset = (__size), \
302}
303
304#define IPT_STANDARD_INIT(__verdict) \
305{ \
306 .entry = IPT_ENTRY_INIT(sizeof(struct ipt_standard)), \
307 .target = XT_TARGET_INIT(IPT_STANDARD_TARGET, \
308 sizeof(struct xt_standard_target)), \
309 .target.verdict = -(__verdict) - 1, \
310}
311
312#define IPT_ERROR_INIT \
313{ \
314 .entry = IPT_ENTRY_INIT(sizeof(struct ipt_error)), \
315 .target = XT_TARGET_INIT(IPT_ERROR_TARGET, \
316 sizeof(struct ipt_error_target)), \
317 .target.errorname = "ERROR", \
318}
319
298extern unsigned int ipt_do_table(struct sk_buff **pskb, 320extern unsigned int ipt_do_table(struct sk_buff **pskb,
299 unsigned int hook, 321 unsigned int hook,
300 const struct net_device *in, 322 const struct net_device *in,
diff --git a/include/linux/netfilter_ipv6/ip6_tables.h b/include/linux/netfilter_ipv6/ip6_tables.h
index 61aa10412fc8..4686f8342cbd 100644
--- a/include/linux/netfilter_ipv6/ip6_tables.h
+++ b/include/linux/netfilter_ipv6/ip6_tables.h
@@ -123,6 +123,28 @@ struct ip6t_error
123 struct ip6t_error_target target; 123 struct ip6t_error_target target;
124}; 124};
125 125
126#define IP6T_ENTRY_INIT(__size) \
127{ \
128 .target_offset = sizeof(struct ip6t_entry), \
129 .next_offset = (__size), \
130}
131
132#define IP6T_STANDARD_INIT(__verdict) \
133{ \
134 .entry = IP6T_ENTRY_INIT(sizeof(struct ip6t_standard)), \
135 .target = XT_TARGET_INIT(IP6T_STANDARD_TARGET, \
136 sizeof(struct ip6t_standard_target)), \
137 .target.verdict = -(__verdict) - 1, \
138}
139
140#define IP6T_ERROR_INIT \
141{ \
142 .entry = IP6T_ENTRY_INIT(sizeof(struct ip6t_error)), \
143 .target = XT_TARGET_INIT(IP6T_ERROR_TARGET, \
144 sizeof(struct ip6t_error_target)), \
145 .target.errorname = "ERROR", \
146}
147
126/* 148/*
127 * New IP firewall options for [gs]etsockopt at the RAW IP level. 149 * New IP firewall options for [gs]etsockopt at the RAW IP level.
128 * Unlike BSD Linux inherits IP options so you don't have to use 150 * Unlike BSD Linux inherits IP options so you don't have to use
diff --git a/include/net/netfilter/nf_conntrack.h b/include/net/netfilter/nf_conntrack.h
index 1c6b8bd09b9a..4732432f8eb0 100644
--- a/include/net/netfilter/nf_conntrack.h
+++ b/include/net/netfilter/nf_conntrack.h
@@ -183,13 +183,6 @@ extern void nf_conntrack_hash_insert(struct nf_conn *ct);
183 183
184extern void nf_conntrack_flush(void); 184extern void nf_conntrack_flush(void);
185 185
186extern struct nf_conntrack_helper *
187nf_ct_helper_find_get( const struct nf_conntrack_tuple *tuple);
188extern void nf_ct_helper_put(struct nf_conntrack_helper *helper);
189
190extern struct nf_conntrack_helper *
191__nf_conntrack_helper_find_byname(const char *name);
192
193extern int nf_ct_invert_tuplepr(struct nf_conntrack_tuple *inverse, 186extern int nf_ct_invert_tuplepr(struct nf_conntrack_tuple *inverse,
194 const struct nf_conntrack_tuple *orig); 187 const struct nf_conntrack_tuple *orig);
195 188
diff --git a/include/net/netfilter/nf_conntrack_l3proto.h b/include/net/netfilter/nf_conntrack_l3proto.h
index f32f714e5d92..96a58d8e1d3f 100644
--- a/include/net/netfilter/nf_conntrack_l3proto.h
+++ b/include/net/netfilter/nf_conntrack_l3proto.h
@@ -56,9 +56,6 @@ struct nf_conntrack_l3proto
56 */ 56 */
57 int (*new)(struct nf_conn *conntrack, const struct sk_buff *skb); 57 int (*new)(struct nf_conn *conntrack, const struct sk_buff *skb);
58 58
59 /* Called when a conntrack entry is destroyed */
60 void (*destroy)(struct nf_conn *conntrack);
61
62 /* 59 /*
63 * Called before tracking. 60 * Called before tracking.
64 * *dataoff: offset of protocol header (TCP, UDP,...) in *pskb 61 * *dataoff: offset of protocol header (TCP, UDP,...) in *pskb
diff --git a/include/net/netfilter/nf_nat_rule.h b/include/net/netfilter/nf_nat_rule.h
index e76565459ad9..f9743187d57f 100644
--- a/include/net/netfilter/nf_nat_rule.h
+++ b/include/net/netfilter/nf_nat_rule.h
@@ -10,16 +10,11 @@ extern int nf_nat_rule_find(struct sk_buff **pskb,
10 unsigned int hooknum, 10 unsigned int hooknum,
11 const struct net_device *in, 11 const struct net_device *in,
12 const struct net_device *out, 12 const struct net_device *out,
13 struct nf_conn *ct, 13 struct nf_conn *ct);
14 struct nf_nat_info *info);
15 14
16extern unsigned int 15extern unsigned int
17alloc_null_binding(struct nf_conn *ct, 16alloc_null_binding(struct nf_conn *ct, unsigned int hooknum);
18 struct nf_nat_info *info,
19 unsigned int hooknum);
20 17
21extern unsigned int 18extern unsigned int
22alloc_null_binding_confirmed(struct nf_conn *ct, 19alloc_null_binding_confirmed(struct nf_conn *ct, unsigned int hooknum);
23 struct nf_nat_info *info,
24 unsigned int hooknum);
25#endif /* _NF_NAT_RULE_H */ 20#endif /* _NF_NAT_RULE_H */
diff --git a/include/net/udp.h b/include/net/udp.h
index 98755ebaf163..496f89d45c8b 100644
--- a/include/net/udp.h
+++ b/include/net/udp.h
@@ -119,9 +119,16 @@ static inline void udp_lib_close(struct sock *sk, long timeout)
119} 119}
120 120
121 121
122struct udp_get_port_ops {
123 int (*saddr_cmp)(const struct sock *sk1, const struct sock *sk2);
124 int (*saddr_any)(const struct sock *sk);
125 unsigned int (*hash_port_and_rcv_saddr)(__u16 port,
126 const struct sock *sk);
127};
128
122/* net/ipv4/udp.c */ 129/* net/ipv4/udp.c */
123extern int udp_get_port(struct sock *sk, unsigned short snum, 130extern int udp_get_port(struct sock *sk, unsigned short snum,
124 int (*saddr_cmp)(const struct sock *, const struct sock *)); 131 const struct udp_get_port_ops *ops);
125extern void udp_err(struct sk_buff *, u32); 132extern void udp_err(struct sk_buff *, u32);
126 133
127extern int udp_sendmsg(struct kiocb *iocb, struct sock *sk, 134extern int udp_sendmsg(struct kiocb *iocb, struct sock *sk,
diff --git a/include/net/udplite.h b/include/net/udplite.h
index 635b0eafca95..50b4b424d1ca 100644
--- a/include/net/udplite.h
+++ b/include/net/udplite.h
@@ -120,5 +120,5 @@ static inline __wsum udplite_csum_outgoing(struct sock *sk, struct sk_buff *skb)
120 120
121extern void udplite4_register(void); 121extern void udplite4_register(void);
122extern int udplite_get_port(struct sock *sk, unsigned short snum, 122extern int udplite_get_port(struct sock *sk, unsigned short snum,
123 int (*scmp)(const struct sock *, const struct sock *)); 123 const struct udp_get_port_ops *ops);
124#endif /* _UDPLITE_H */ 124#endif /* _UDPLITE_H */
diff --git a/net/bluetooth/hidp/core.c b/net/bluetooth/hidp/core.c
index d342e89b8bdd..0ea40ab4dbae 100644
--- a/net/bluetooth/hidp/core.c
+++ b/net/bluetooth/hidp/core.c
@@ -174,7 +174,7 @@ static inline int hidp_queue_event(struct hidp_session *session, struct input_de
174 174
175static int hidp_hidinput_event(struct input_dev *dev, unsigned int type, unsigned int code, int value) 175static int hidp_hidinput_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
176{ 176{
177 struct hid_device *hid = dev->private; 177 struct hid_device *hid = input_get_drvdata(dev);
178 struct hidp_session *session = hid->driver_data; 178 struct hidp_session *session = hid->driver_data;
179 179
180 return hidp_queue_event(session, dev, type, code, value); 180 return hidp_queue_event(session, dev, type, code, value);
@@ -182,7 +182,7 @@ static int hidp_hidinput_event(struct input_dev *dev, unsigned int type, unsigne
182 182
183static int hidp_input_event(struct input_dev *dev, unsigned int type, unsigned int code, int value) 183static int hidp_input_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
184{ 184{
185 struct hidp_session *session = dev->private; 185 struct hidp_session *session = input_get_drvdata(dev);
186 186
187 return hidp_queue_event(session, dev, type, code, value); 187 return hidp_queue_event(session, dev, type, code, value);
188} 188}
@@ -630,7 +630,7 @@ static inline void hidp_setup_input(struct hidp_session *session, struct hidp_co
630 struct input_dev *input = session->input; 630 struct input_dev *input = session->input;
631 int i; 631 int i;
632 632
633 input->private = session; 633 input_set_drvdata(input, session);
634 634
635 input->name = "Bluetooth HID Boot Protocol Device"; 635 input->name = "Bluetooth HID Boot Protocol Device";
636 636
@@ -663,7 +663,7 @@ static inline void hidp_setup_input(struct hidp_session *session, struct hidp_co
663 input->relbit[0] |= BIT(REL_WHEEL); 663 input->relbit[0] |= BIT(REL_WHEEL);
664 } 664 }
665 665
666 input->cdev.dev = hidp_get_device(session); 666 input->dev.parent = hidp_get_device(session);
667 667
668 input->event = hidp_input_event; 668 input->event = hidp_input_event;
669 669
@@ -864,7 +864,7 @@ failed:
864 if (session->hid) 864 if (session->hid)
865 hid_free_device(session->hid); 865 hid_free_device(session->hid);
866 866
867 kfree(session->input); 867 input_free_device(session->input);
868 kfree(session); 868 kfree(session);
869 return err; 869 return err;
870} 870}
diff --git a/net/core/link_watch.c b/net/core/link_watch.c
index e3c26a9ccad6..a5e372b9ec4d 100644
--- a/net/core/link_watch.c
+++ b/net/core/link_watch.c
@@ -19,7 +19,6 @@
19#include <linux/rtnetlink.h> 19#include <linux/rtnetlink.h>
20#include <linux/jiffies.h> 20#include <linux/jiffies.h>
21#include <linux/spinlock.h> 21#include <linux/spinlock.h>
22#include <linux/list.h>
23#include <linux/slab.h> 22#include <linux/slab.h>
24#include <linux/workqueue.h> 23#include <linux/workqueue.h>
25#include <linux/bitops.h> 24#include <linux/bitops.h>
@@ -27,8 +26,7 @@
27 26
28 27
29enum lw_bits { 28enum lw_bits {
30 LW_RUNNING = 0, 29 LW_URGENT = 0,
31 LW_SE_USED
32}; 30};
33 31
34static unsigned long linkwatch_flags; 32static unsigned long linkwatch_flags;
@@ -37,17 +35,9 @@ static unsigned long linkwatch_nextevent;
37static void linkwatch_event(struct work_struct *dummy); 35static void linkwatch_event(struct work_struct *dummy);
38static DECLARE_DELAYED_WORK(linkwatch_work, linkwatch_event); 36static DECLARE_DELAYED_WORK(linkwatch_work, linkwatch_event);
39 37
40static LIST_HEAD(lweventlist); 38static struct net_device *lweventlist;
41static DEFINE_SPINLOCK(lweventlist_lock); 39static DEFINE_SPINLOCK(lweventlist_lock);
42 40
43struct lw_event {
44 struct list_head list;
45 struct net_device *dev;
46};
47
48/* Avoid kmalloc() for most systems */
49static struct lw_event singleevent;
50
51static unsigned char default_operstate(const struct net_device *dev) 41static unsigned char default_operstate(const struct net_device *dev)
52{ 42{
53 if (!netif_carrier_ok(dev)) 43 if (!netif_carrier_ok(dev))
@@ -87,25 +77,102 @@ static void rfc2863_policy(struct net_device *dev)
87} 77}
88 78
89 79
90/* Must be called with the rtnl semaphore held */ 80static int linkwatch_urgent_event(struct net_device *dev)
91void linkwatch_run_queue(void)
92{ 81{
93 struct list_head head, *n, *next; 82 return netif_running(dev) && netif_carrier_ok(dev) &&
83 dev->qdisc != dev->qdisc_sleeping;
84}
85
86
87static void linkwatch_add_event(struct net_device *dev)
88{
89 unsigned long flags;
90
91 spin_lock_irqsave(&lweventlist_lock, flags);
92 dev->link_watch_next = lweventlist;
93 lweventlist = dev;
94 spin_unlock_irqrestore(&lweventlist_lock, flags);
95}
96
97
98static void linkwatch_schedule_work(int urgent)
99{
100 unsigned long delay = linkwatch_nextevent - jiffies;
101
102 if (test_bit(LW_URGENT, &linkwatch_flags))
103 return;
104
105 /* Minimise down-time: drop delay for up event. */
106 if (urgent) {
107 if (test_and_set_bit(LW_URGENT, &linkwatch_flags))
108 return;
109 delay = 0;
110 }
111
112 /* If we wrap around we'll delay it by at most HZ. */
113 if (delay > HZ)
114 delay = 0;
115
116 /*
117 * This is true if we've scheduled it immeditately or if we don't
118 * need an immediate execution and it's already pending.
119 */
120 if (schedule_delayed_work(&linkwatch_work, delay) == !delay)
121 return;
122
123 /* Don't bother if there is nothing urgent. */
124 if (!test_bit(LW_URGENT, &linkwatch_flags))
125 return;
126
127 /* It's already running which is good enough. */
128 if (!cancel_delayed_work(&linkwatch_work))
129 return;
130
131 /* Otherwise we reschedule it again for immediate exection. */
132 schedule_delayed_work(&linkwatch_work, 0);
133}
134
135
136static void __linkwatch_run_queue(int urgent_only)
137{
138 struct net_device *next;
139
140 /*
141 * Limit the number of linkwatch events to one
142 * per second so that a runaway driver does not
143 * cause a storm of messages on the netlink
144 * socket. This limit does not apply to up events
145 * while the device qdisc is down.
146 */
147 if (!urgent_only)
148 linkwatch_nextevent = jiffies + HZ;
149 /* Limit wrap-around effect on delay. */
150 else if (time_after(linkwatch_nextevent, jiffies + HZ))
151 linkwatch_nextevent = jiffies;
152
153 clear_bit(LW_URGENT, &linkwatch_flags);
94 154
95 spin_lock_irq(&lweventlist_lock); 155 spin_lock_irq(&lweventlist_lock);
96 list_replace_init(&lweventlist, &head); 156 next = lweventlist;
157 lweventlist = NULL;
97 spin_unlock_irq(&lweventlist_lock); 158 spin_unlock_irq(&lweventlist_lock);
98 159
99 list_for_each_safe(n, next, &head) { 160 while (next) {
100 struct lw_event *event = list_entry(n, struct lw_event, list); 161 struct net_device *dev = next;
101 struct net_device *dev = event->dev;
102 162
103 if (event == &singleevent) { 163 next = dev->link_watch_next;
104 clear_bit(LW_SE_USED, &linkwatch_flags); 164
105 } else { 165 if (urgent_only && !linkwatch_urgent_event(dev)) {
106 kfree(event); 166 linkwatch_add_event(dev);
167 continue;
107 } 168 }
108 169
170 /*
171 * Make sure the above read is complete since it can be
172 * rewritten as soon as we clear the bit below.
173 */
174 smp_mb__before_clear_bit();
175
109 /* We are about to handle this device, 176 /* We are about to handle this device,
110 * so new events can be accepted 177 * so new events can be accepted
111 */ 178 */
@@ -124,58 +191,39 @@ void linkwatch_run_queue(void)
124 191
125 dev_put(dev); 192 dev_put(dev);
126 } 193 }
194
195 if (lweventlist)
196 linkwatch_schedule_work(0);
127} 197}
128 198
129 199
130static void linkwatch_event(struct work_struct *dummy) 200/* Must be called with the rtnl semaphore held */
201void linkwatch_run_queue(void)
131{ 202{
132 /* Limit the number of linkwatch events to one 203 __linkwatch_run_queue(0);
133 * per second so that a runaway driver does not 204}
134 * cause a storm of messages on the netlink
135 * socket
136 */
137 linkwatch_nextevent = jiffies + HZ;
138 clear_bit(LW_RUNNING, &linkwatch_flags);
139 205
206
207static void linkwatch_event(struct work_struct *dummy)
208{
140 rtnl_lock(); 209 rtnl_lock();
141 linkwatch_run_queue(); 210 __linkwatch_run_queue(time_after(linkwatch_nextevent, jiffies));
142 rtnl_unlock(); 211 rtnl_unlock();
143} 212}
144 213
145 214
146void linkwatch_fire_event(struct net_device *dev) 215void linkwatch_fire_event(struct net_device *dev)
147{ 216{
148 if (!test_and_set_bit(__LINK_STATE_LINKWATCH_PENDING, &dev->state)) { 217 int urgent = linkwatch_urgent_event(dev);
149 unsigned long flags;
150 struct lw_event *event;
151
152 if (test_and_set_bit(LW_SE_USED, &linkwatch_flags)) {
153 event = kmalloc(sizeof(struct lw_event), GFP_ATOMIC);
154
155 if (unlikely(event == NULL)) {
156 clear_bit(__LINK_STATE_LINKWATCH_PENDING, &dev->state);
157 return;
158 }
159 } else {
160 event = &singleevent;
161 }
162 218
219 if (!test_and_set_bit(__LINK_STATE_LINKWATCH_PENDING, &dev->state)) {
163 dev_hold(dev); 220 dev_hold(dev);
164 event->dev = dev;
165
166 spin_lock_irqsave(&lweventlist_lock, flags);
167 list_add_tail(&event->list, &lweventlist);
168 spin_unlock_irqrestore(&lweventlist_lock, flags);
169 221
170 if (!test_and_set_bit(LW_RUNNING, &linkwatch_flags)) { 222 linkwatch_add_event(dev);
171 unsigned long delay = linkwatch_nextevent - jiffies; 223 } else if (!urgent)
224 return;
172 225
173 /* If we wrap around we'll delay it by at most HZ. */ 226 linkwatch_schedule_work(urgent);
174 if (delay > HZ)
175 delay = 0;
176 schedule_delayed_work(&linkwatch_work, delay);
177 }
178 }
179} 227}
180 228
181EXPORT_SYMBOL(linkwatch_fire_event); 229EXPORT_SYMBOL(linkwatch_fire_event);
diff --git a/net/ipv4/netfilter/arptable_filter.c b/net/ipv4/netfilter/arptable_filter.c
index 7edea2a1696c..75c023062533 100644
--- a/net/ipv4/netfilter/arptable_filter.c
+++ b/net/ipv4/netfilter/arptable_filter.c
@@ -15,128 +15,34 @@ MODULE_DESCRIPTION("arptables filter table");
15#define FILTER_VALID_HOOKS ((1 << NF_ARP_IN) | (1 << NF_ARP_OUT) | \ 15#define FILTER_VALID_HOOKS ((1 << NF_ARP_IN) | (1 << NF_ARP_OUT) | \
16 (1 << NF_ARP_FORWARD)) 16 (1 << NF_ARP_FORWARD))
17 17
18/* Standard entry. */
19struct arpt_standard
20{
21 struct arpt_entry entry;
22 struct arpt_standard_target target;
23};
24
25struct arpt_error_target
26{
27 struct arpt_entry_target target;
28 char errorname[ARPT_FUNCTION_MAXNAMELEN];
29};
30
31struct arpt_error
32{
33 struct arpt_entry entry;
34 struct arpt_error_target target;
35};
36
37static struct 18static struct
38{ 19{
39 struct arpt_replace repl; 20 struct arpt_replace repl;
40 struct arpt_standard entries[3]; 21 struct arpt_standard entries[3];
41 struct arpt_error term; 22 struct arpt_error term;
42} initial_table __initdata 23} initial_table __initdata = {
43= { { "filter", FILTER_VALID_HOOKS, 4, 24 .repl = {
44 sizeof(struct arpt_standard) * 3 + sizeof(struct arpt_error), 25 .name = "filter",
45 { [NF_ARP_IN] = 0, 26 .valid_hooks = FILTER_VALID_HOOKS,
46 [NF_ARP_OUT] = sizeof(struct arpt_standard), 27 .num_entries = 4,
47 [NF_ARP_FORWARD] = 2 * sizeof(struct arpt_standard), }, 28 .size = sizeof(struct arpt_standard) * 3 + sizeof(struct arpt_error),
48 { [NF_ARP_IN] = 0, 29 .hook_entry = {
49 [NF_ARP_OUT] = sizeof(struct arpt_standard), 30 [NF_ARP_IN] = 0,
50 [NF_ARP_FORWARD] = 2 * sizeof(struct arpt_standard), }, 31 [NF_ARP_OUT] = sizeof(struct arpt_standard),
51 0, NULL, { } }, 32 [NF_ARP_FORWARD] = 2 * sizeof(struct arpt_standard),
52 { 33 },
53 /* ARP_IN */ 34 .underflow = {
54 { 35 [NF_ARP_IN] = 0,
55 { 36 [NF_ARP_OUT] = sizeof(struct arpt_standard),
56 { 37 [NF_ARP_FORWARD] = 2 * sizeof(struct arpt_standard),
57 { 0 }, { 0 }, { 0 }, { 0 }, 38 },
58 0, 0, 39 },
59 { { 0, }, { 0, } }, 40 .entries = {
60 { { 0, }, { 0, } }, 41 ARPT_STANDARD_INIT(NF_ACCEPT), /* ARP_IN */
61 0, 0, 42 ARPT_STANDARD_INIT(NF_ACCEPT), /* ARP_OUT */
62 0, 0, 43 ARPT_STANDARD_INIT(NF_ACCEPT), /* ARP_FORWARD */
63 0, 0, 44 },
64 "", "", { 0 }, { 0 }, 45 .term = ARPT_ERROR_INIT,
65 0, 0
66 },
67 sizeof(struct arpt_entry),
68 sizeof(struct arpt_standard),
69 0,
70 { 0, 0 }, { } },
71 { { { { ARPT_ALIGN(sizeof(struct arpt_standard_target)), "" } }, { } },
72 -NF_ACCEPT - 1 }
73 },
74 /* ARP_OUT */
75 {
76 {
77 {
78 { 0 }, { 0 }, { 0 }, { 0 },
79 0, 0,
80 { { 0, }, { 0, } },
81 { { 0, }, { 0, } },
82 0, 0,
83 0, 0,
84 0, 0,
85 "", "", { 0 }, { 0 },
86 0, 0
87 },
88 sizeof(struct arpt_entry),
89 sizeof(struct arpt_standard),
90 0,
91 { 0, 0 }, { } },
92 { { { { ARPT_ALIGN(sizeof(struct arpt_standard_target)), "" } }, { } },
93 -NF_ACCEPT - 1 }
94 },
95 /* ARP_FORWARD */
96 {
97 {
98 {
99 { 0 }, { 0 }, { 0 }, { 0 },
100 0, 0,
101 { { 0, }, { 0, } },
102 { { 0, }, { 0, } },
103 0, 0,
104 0, 0,
105 0, 0,
106 "", "", { 0 }, { 0 },
107 0, 0
108 },
109 sizeof(struct arpt_entry),
110 sizeof(struct arpt_standard),
111 0,
112 { 0, 0 }, { } },
113 { { { { ARPT_ALIGN(sizeof(struct arpt_standard_target)), "" } }, { } },
114 -NF_ACCEPT - 1 }
115 }
116 },
117 /* ERROR */
118 {
119 {
120 {
121 { 0 }, { 0 }, { 0 }, { 0 },
122 0, 0,
123 { { 0, }, { 0, } },
124 { { 0, }, { 0, } },
125 0, 0,
126 0, 0,
127 0, 0,
128 "", "", { 0 }, { 0 },
129 0, 0
130 },
131 sizeof(struct arpt_entry),
132 sizeof(struct arpt_error),
133 0,
134 { 0, 0 }, { } },
135 { { { { ARPT_ALIGN(sizeof(struct arpt_error_target)), ARPT_ERROR_TARGET } },
136 { } },
137 "ERROR"
138 }
139 }
140}; 46};
141 47
142static struct arpt_table packet_filter = { 48static struct arpt_table packet_filter = {
diff --git a/net/ipv4/netfilter/iptable_filter.c b/net/ipv4/netfilter/iptable_filter.c
index 42728909eba0..4f51c1d7d2d6 100644
--- a/net/ipv4/netfilter/iptable_filter.c
+++ b/net/ipv4/netfilter/iptable_filter.c
@@ -26,53 +26,29 @@ static struct
26 struct ipt_replace repl; 26 struct ipt_replace repl;
27 struct ipt_standard entries[3]; 27 struct ipt_standard entries[3];
28 struct ipt_error term; 28 struct ipt_error term;
29} initial_table __initdata 29} initial_table __initdata = {
30= { { "filter", FILTER_VALID_HOOKS, 4, 30 .repl = {
31 sizeof(struct ipt_standard) * 3 + sizeof(struct ipt_error), 31 .name = "filter",
32 { [NF_IP_LOCAL_IN] = 0, 32 .valid_hooks = FILTER_VALID_HOOKS,
33 [NF_IP_FORWARD] = sizeof(struct ipt_standard), 33 .num_entries = 4,
34 [NF_IP_LOCAL_OUT] = sizeof(struct ipt_standard) * 2 }, 34 .size = sizeof(struct ipt_standard) * 3 + sizeof(struct ipt_error),
35 { [NF_IP_LOCAL_IN] = 0, 35 .hook_entry = {
36 [NF_IP_FORWARD] = sizeof(struct ipt_standard), 36 [NF_IP_LOCAL_IN] = 0,
37 [NF_IP_LOCAL_OUT] = sizeof(struct ipt_standard) * 2 }, 37 [NF_IP_FORWARD] = sizeof(struct ipt_standard),
38 0, NULL, { } }, 38 [NF_IP_LOCAL_OUT] = sizeof(struct ipt_standard) * 2,
39 { 39 },
40 /* LOCAL_IN */ 40 .underflow = {
41 { { { { 0 }, { 0 }, { 0 }, { 0 }, "", "", { 0 }, { 0 }, 0, 0, 0 }, 41 [NF_IP_LOCAL_IN] = 0,
42 0, 42 [NF_IP_FORWARD] = sizeof(struct ipt_standard),
43 sizeof(struct ipt_entry), 43 [NF_IP_LOCAL_OUT] = sizeof(struct ipt_standard) * 2,
44 sizeof(struct ipt_standard), 44 },
45 0, { 0, 0 }, { } }, 45 },
46 { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } }, 46 .entries = {
47 -NF_ACCEPT - 1 } }, 47 IPT_STANDARD_INIT(NF_ACCEPT), /* LOCAL_IN */
48 /* FORWARD */ 48 IPT_STANDARD_INIT(NF_ACCEPT), /* FORWARD */
49 { { { { 0 }, { 0 }, { 0 }, { 0 }, "", "", { 0 }, { 0 }, 0, 0, 0 }, 49 IPT_STANDARD_INIT(NF_ACCEPT), /* LOCAL_OUT */
50 0, 50 },
51 sizeof(struct ipt_entry), 51 .term = IPT_ERROR_INIT, /* ERROR */
52 sizeof(struct ipt_standard),
53 0, { 0, 0 }, { } },
54 { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
55 -NF_ACCEPT - 1 } },
56 /* LOCAL_OUT */
57 { { { { 0 }, { 0 }, { 0 }, { 0 }, "", "", { 0 }, { 0 }, 0, 0, 0 },
58 0,
59 sizeof(struct ipt_entry),
60 sizeof(struct ipt_standard),
61 0, { 0, 0 }, { } },
62 { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
63 -NF_ACCEPT - 1 } }
64 },
65 /* ERROR */
66 { { { { 0 }, { 0 }, { 0 }, { 0 }, "", "", { 0 }, { 0 }, 0, 0, 0 },
67 0,
68 sizeof(struct ipt_entry),
69 sizeof(struct ipt_error),
70 0, { 0, 0 }, { } },
71 { { { { IPT_ALIGN(sizeof(struct ipt_error_target)), IPT_ERROR_TARGET } },
72 { } },
73 "ERROR"
74 }
75 }
76}; 52};
77 53
78static struct xt_table packet_filter = { 54static struct xt_table packet_filter = {
@@ -105,7 +81,8 @@ ipt_local_out_hook(unsigned int hook,
105 if ((*pskb)->len < sizeof(struct iphdr) 81 if ((*pskb)->len < sizeof(struct iphdr)
106 || ip_hdrlen(*pskb) < sizeof(struct iphdr)) { 82 || ip_hdrlen(*pskb) < sizeof(struct iphdr)) {
107 if (net_ratelimit()) 83 if (net_ratelimit())
108 printk("ipt_hook: happy cracking.\n"); 84 printk("iptable_filter: ignoring short SOCK_RAW "
85 "packet.\n");
109 return NF_ACCEPT; 86 return NF_ACCEPT;
110 } 87 }
111 88
diff --git a/net/ipv4/netfilter/iptable_mangle.c b/net/ipv4/netfilter/iptable_mangle.c
index 9278802f2742..902446f7cbca 100644
--- a/net/ipv4/netfilter/iptable_mangle.c
+++ b/net/ipv4/netfilter/iptable_mangle.c
@@ -33,73 +33,35 @@ static struct
33 struct ipt_replace repl; 33 struct ipt_replace repl;
34 struct ipt_standard entries[5]; 34 struct ipt_standard entries[5];
35 struct ipt_error term; 35 struct ipt_error term;
36} initial_table __initdata 36} initial_table __initdata = {
37= { { "mangle", MANGLE_VALID_HOOKS, 6, 37 .repl = {
38 sizeof(struct ipt_standard) * 5 + sizeof(struct ipt_error), 38 .name = "mangle",
39 { [NF_IP_PRE_ROUTING] = 0, 39 .valid_hooks = MANGLE_VALID_HOOKS,
40 [NF_IP_LOCAL_IN] = sizeof(struct ipt_standard), 40 .num_entries = 6,
41 [NF_IP_FORWARD] = sizeof(struct ipt_standard) * 2, 41 .size = sizeof(struct ipt_standard) * 5 + sizeof(struct ipt_error),
42 [NF_IP_LOCAL_OUT] = sizeof(struct ipt_standard) * 3, 42 .hook_entry = {
43 [NF_IP_POST_ROUTING] = sizeof(struct ipt_standard) * 4 }, 43 [NF_IP_PRE_ROUTING] = 0,
44 { [NF_IP_PRE_ROUTING] = 0, 44 [NF_IP_LOCAL_IN] = sizeof(struct ipt_standard),
45 [NF_IP_LOCAL_IN] = sizeof(struct ipt_standard), 45 [NF_IP_FORWARD] = sizeof(struct ipt_standard) * 2,
46 [NF_IP_FORWARD] = sizeof(struct ipt_standard) * 2, 46 [NF_IP_LOCAL_OUT] = sizeof(struct ipt_standard) * 3,
47 [NF_IP_LOCAL_OUT] = sizeof(struct ipt_standard) * 3, 47 [NF_IP_POST_ROUTING] = sizeof(struct ipt_standard) * 4,
48 [NF_IP_POST_ROUTING] = sizeof(struct ipt_standard) * 4 }, 48 },
49 0, NULL, { } }, 49 .underflow = {
50 { 50 [NF_IP_PRE_ROUTING] = 0,
51 /* PRE_ROUTING */ 51 [NF_IP_LOCAL_IN] = sizeof(struct ipt_standard),
52 { { { { 0 }, { 0 }, { 0 }, { 0 }, "", "", { 0 }, { 0 }, 0, 0, 0 }, 52 [NF_IP_FORWARD] = sizeof(struct ipt_standard) * 2,
53 0, 53 [NF_IP_LOCAL_OUT] = sizeof(struct ipt_standard) * 3,
54 sizeof(struct ipt_entry), 54 [NF_IP_POST_ROUTING] = sizeof(struct ipt_standard) * 4,
55 sizeof(struct ipt_standard), 55 },
56 0, { 0, 0 }, { } }, 56 },
57 { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } }, 57 .entries = {
58 -NF_ACCEPT - 1 } }, 58 IPT_STANDARD_INIT(NF_ACCEPT), /* PRE_ROUTING */
59 /* LOCAL_IN */ 59 IPT_STANDARD_INIT(NF_ACCEPT), /* LOCAL_IN */
60 { { { { 0 }, { 0 }, { 0 }, { 0 }, "", "", { 0 }, { 0 }, 0, 0, 0 }, 60 IPT_STANDARD_INIT(NF_ACCEPT), /* FORWARD */
61 0, 61 IPT_STANDARD_INIT(NF_ACCEPT), /* LOCAL_OUT */
62 sizeof(struct ipt_entry), 62 IPT_STANDARD_INIT(NF_ACCEPT), /* POST_ROUTING */
63 sizeof(struct ipt_standard), 63 },
64 0, { 0, 0 }, { } }, 64 .term = IPT_ERROR_INIT, /* ERROR */
65 { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
66 -NF_ACCEPT - 1 } },
67 /* FORWARD */
68 { { { { 0 }, { 0 }, { 0 }, { 0 }, "", "", { 0 }, { 0 }, 0, 0, 0 },
69 0,
70 sizeof(struct ipt_entry),
71 sizeof(struct ipt_standard),
72 0, { 0, 0 }, { } },
73 { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
74 -NF_ACCEPT - 1 } },
75 /* LOCAL_OUT */
76 { { { { 0 }, { 0 }, { 0 }, { 0 }, "", "", { 0 }, { 0 }, 0, 0, 0 },
77 0,
78 sizeof(struct ipt_entry),
79 sizeof(struct ipt_standard),
80 0, { 0, 0 }, { } },
81 { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
82 -NF_ACCEPT - 1 } },
83 /* POST_ROUTING */
84 { { { { 0 }, { 0 }, { 0 }, { 0 }, "", "", { 0 }, { 0 }, 0, 0, 0 },
85 0,
86 sizeof(struct ipt_entry),
87 sizeof(struct ipt_standard),
88 0, { 0, 0 }, { } },
89 { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
90 -NF_ACCEPT - 1 } },
91 },
92 /* ERROR */
93 { { { { 0 }, { 0 }, { 0 }, { 0 }, "", "", { 0 }, { 0 }, 0, 0, 0 },
94 0,
95 sizeof(struct ipt_entry),
96 sizeof(struct ipt_error),
97 0, { 0, 0 }, { } },
98 { { { { IPT_ALIGN(sizeof(struct ipt_error_target)), IPT_ERROR_TARGET } },
99 { } },
100 "ERROR"
101 }
102 }
103}; 65};
104 66
105static struct xt_table packet_mangler = { 67static struct xt_table packet_mangler = {
@@ -138,7 +100,8 @@ ipt_local_hook(unsigned int hook,
138 if ((*pskb)->len < sizeof(struct iphdr) 100 if ((*pskb)->len < sizeof(struct iphdr)
139 || ip_hdrlen(*pskb) < sizeof(struct iphdr)) { 101 || ip_hdrlen(*pskb) < sizeof(struct iphdr)) {
140 if (net_ratelimit()) 102 if (net_ratelimit())
141 printk("ipt_hook: happy cracking.\n"); 103 printk("iptable_mangle: ignoring short SOCK_RAW "
104 "packet.\n");
142 return NF_ACCEPT; 105 return NF_ACCEPT;
143 } 106 }
144 107
diff --git a/net/ipv4/netfilter/iptable_raw.c b/net/ipv4/netfilter/iptable_raw.c
index 18c3d4c9ff51..d6e503395684 100644
--- a/net/ipv4/netfilter/iptable_raw.c
+++ b/net/ipv4/netfilter/iptable_raw.c
@@ -5,6 +5,7 @@
5 */ 5 */
6#include <linux/module.h> 6#include <linux/module.h>
7#include <linux/netfilter_ipv4/ip_tables.h> 7#include <linux/netfilter_ipv4/ip_tables.h>
8#include <net/ip.h>
8 9
9#define RAW_VALID_HOOKS ((1 << NF_IP_PRE_ROUTING) | (1 << NF_IP_LOCAL_OUT)) 10#define RAW_VALID_HOOKS ((1 << NF_IP_PRE_ROUTING) | (1 << NF_IP_LOCAL_OUT))
10 11
@@ -21,62 +22,18 @@ static struct
21 .size = sizeof(struct ipt_standard) * 2 + sizeof(struct ipt_error), 22 .size = sizeof(struct ipt_standard) * 2 + sizeof(struct ipt_error),
22 .hook_entry = { 23 .hook_entry = {
23 [NF_IP_PRE_ROUTING] = 0, 24 [NF_IP_PRE_ROUTING] = 0,
24 [NF_IP_LOCAL_OUT] = sizeof(struct ipt_standard) }, 25 [NF_IP_LOCAL_OUT] = sizeof(struct ipt_standard)
26 },
25 .underflow = { 27 .underflow = {
26 [NF_IP_PRE_ROUTING] = 0, 28 [NF_IP_PRE_ROUTING] = 0,
27 [NF_IP_LOCAL_OUT] = sizeof(struct ipt_standard) }, 29 [NF_IP_LOCAL_OUT] = sizeof(struct ipt_standard)
30 },
28 }, 31 },
29 .entries = { 32 .entries = {
30 /* PRE_ROUTING */ 33 IPT_STANDARD_INIT(NF_ACCEPT), /* PRE_ROUTING */
31 { 34 IPT_STANDARD_INIT(NF_ACCEPT), /* LOCAL_OUT */
32 .entry = {
33 .target_offset = sizeof(struct ipt_entry),
34 .next_offset = sizeof(struct ipt_standard),
35 },
36 .target = {
37 .target = {
38 .u = {
39 .target_size = IPT_ALIGN(sizeof(struct ipt_standard_target)),
40 },
41 },
42 .verdict = -NF_ACCEPT - 1,
43 },
44 },
45
46 /* LOCAL_OUT */
47 {
48 .entry = {
49 .target_offset = sizeof(struct ipt_entry),
50 .next_offset = sizeof(struct ipt_standard),
51 },
52 .target = {
53 .target = {
54 .u = {
55 .target_size = IPT_ALIGN(sizeof(struct ipt_standard_target)),
56 },
57 },
58 .verdict = -NF_ACCEPT - 1,
59 },
60 },
61 }, 35 },
62 /* ERROR */ 36 .term = IPT_ERROR_INIT, /* ERROR */
63 .term = {
64 .entry = {
65 .target_offset = sizeof(struct ipt_entry),
66 .next_offset = sizeof(struct ipt_error),
67 },
68 .target = {
69 .target = {
70 .u = {
71 .user = {
72 .target_size = IPT_ALIGN(sizeof(struct ipt_error_target)),
73 .name = IPT_ERROR_TARGET,
74 },
75 },
76 },
77 .errorname = "ERROR",
78 },
79 }
80}; 37};
81 38
82static struct xt_table packet_raw = { 39static struct xt_table packet_raw = {
@@ -98,6 +55,24 @@ ipt_hook(unsigned int hook,
98 return ipt_do_table(pskb, hook, in, out, &packet_raw); 55 return ipt_do_table(pskb, hook, in, out, &packet_raw);
99} 56}
100 57
58static unsigned int
59ipt_local_hook(unsigned int hook,
60 struct sk_buff **pskb,
61 const struct net_device *in,
62 const struct net_device *out,
63 int (*okfn)(struct sk_buff *))
64{
65 /* root is playing with raw sockets. */
66 if ((*pskb)->len < sizeof(struct iphdr) ||
67 ip_hdrlen(*pskb) < sizeof(struct iphdr)) {
68 if (net_ratelimit())
69 printk("iptable_raw: ignoring short SOCK_RAW"
70 "packet.\n");
71 return NF_ACCEPT;
72 }
73 return ipt_do_table(pskb, hook, in, out, &packet_raw);
74}
75
101/* 'raw' is the very first table. */ 76/* 'raw' is the very first table. */
102static struct nf_hook_ops ipt_ops[] = { 77static struct nf_hook_ops ipt_ops[] = {
103 { 78 {
@@ -108,7 +83,7 @@ static struct nf_hook_ops ipt_ops[] = {
108 .owner = THIS_MODULE, 83 .owner = THIS_MODULE,
109 }, 84 },
110 { 85 {
111 .hook = ipt_hook, 86 .hook = ipt_local_hook,
112 .pf = PF_INET, 87 .pf = PF_INET,
113 .hooknum = NF_IP_LOCAL_OUT, 88 .hooknum = NF_IP_LOCAL_OUT,
114 .priority = NF_IP_PRI_RAW, 89 .priority = NF_IP_PRI_RAW,
diff --git a/net/ipv4/netfilter/nf_nat_rule.c b/net/ipv4/netfilter/nf_nat_rule.c
index 2534f718ab92..6740736c5e79 100644
--- a/net/ipv4/netfilter/nf_nat_rule.c
+++ b/net/ipv4/netfilter/nf_nat_rule.c
@@ -46,77 +46,20 @@ static struct
46 .hook_entry = { 46 .hook_entry = {
47 [NF_IP_PRE_ROUTING] = 0, 47 [NF_IP_PRE_ROUTING] = 0,
48 [NF_IP_POST_ROUTING] = sizeof(struct ipt_standard), 48 [NF_IP_POST_ROUTING] = sizeof(struct ipt_standard),
49 [NF_IP_LOCAL_OUT] = sizeof(struct ipt_standard) * 2 }, 49 [NF_IP_LOCAL_OUT] = sizeof(struct ipt_standard) * 2
50 },
50 .underflow = { 51 .underflow = {
51 [NF_IP_PRE_ROUTING] = 0, 52 [NF_IP_PRE_ROUTING] = 0,
52 [NF_IP_POST_ROUTING] = sizeof(struct ipt_standard), 53 [NF_IP_POST_ROUTING] = sizeof(struct ipt_standard),
53 [NF_IP_LOCAL_OUT] = sizeof(struct ipt_standard) * 2 }, 54 [NF_IP_LOCAL_OUT] = sizeof(struct ipt_standard) * 2
55 },
54 }, 56 },
55 .entries = { 57 .entries = {
56 /* PRE_ROUTING */ 58 IPT_STANDARD_INIT(NF_ACCEPT), /* PRE_ROUTING */
57 { 59 IPT_STANDARD_INIT(NF_ACCEPT), /* POST_ROUTING */
58 .entry = { 60 IPT_STANDARD_INIT(NF_ACCEPT), /* LOCAL_OUT */
59 .target_offset = sizeof(struct ipt_entry),
60 .next_offset = sizeof(struct ipt_standard),
61 },
62 .target = {
63 .target = {
64 .u = {
65 .target_size = IPT_ALIGN(sizeof(struct ipt_standard_target)),
66 },
67 },
68 .verdict = -NF_ACCEPT - 1,
69 },
70 },
71 /* POST_ROUTING */
72 {
73 .entry = {
74 .target_offset = sizeof(struct ipt_entry),
75 .next_offset = sizeof(struct ipt_standard),
76 },
77 .target = {
78 .target = {
79 .u = {
80 .target_size = IPT_ALIGN(sizeof(struct ipt_standard_target)),
81 },
82 },
83 .verdict = -NF_ACCEPT - 1,
84 },
85 },
86 /* LOCAL_OUT */
87 {
88 .entry = {
89 .target_offset = sizeof(struct ipt_entry),
90 .next_offset = sizeof(struct ipt_standard),
91 },
92 .target = {
93 .target = {
94 .u = {
95 .target_size = IPT_ALIGN(sizeof(struct ipt_standard_target)),
96 },
97 },
98 .verdict = -NF_ACCEPT - 1,
99 },
100 },
101 }, 61 },
102 /* ERROR */ 62 .term = IPT_ERROR_INIT, /* ERROR */
103 .term = {
104 .entry = {
105 .target_offset = sizeof(struct ipt_entry),
106 .next_offset = sizeof(struct ipt_error),
107 },
108 .target = {
109 .target = {
110 .u = {
111 .user = {
112 .target_size = IPT_ALIGN(sizeof(struct ipt_error_target)),
113 .name = IPT_ERROR_TARGET,
114 },
115 },
116 },
117 .errorname = "ERROR",
118 },
119 }
120}; 63};
121 64
122static struct xt_table nat_table = { 65static struct xt_table nat_table = {
@@ -230,9 +173,7 @@ static int ipt_dnat_checkentry(const char *tablename,
230} 173}
231 174
232inline unsigned int 175inline unsigned int
233alloc_null_binding(struct nf_conn *ct, 176alloc_null_binding(struct nf_conn *ct, unsigned int hooknum)
234 struct nf_nat_info *info,
235 unsigned int hooknum)
236{ 177{
237 /* Force range to this IP; let proto decide mapping for 178 /* Force range to this IP; let proto decide mapping for
238 per-proto parts (hence not IP_NAT_RANGE_PROTO_SPECIFIED). 179 per-proto parts (hence not IP_NAT_RANGE_PROTO_SPECIFIED).
@@ -251,9 +192,7 @@ alloc_null_binding(struct nf_conn *ct,
251} 192}
252 193
253unsigned int 194unsigned int
254alloc_null_binding_confirmed(struct nf_conn *ct, 195alloc_null_binding_confirmed(struct nf_conn *ct, unsigned int hooknum)
255 struct nf_nat_info *info,
256 unsigned int hooknum)
257{ 196{
258 __be32 ip 197 __be32 ip
259 = (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC 198 = (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC
@@ -275,8 +214,7 @@ int nf_nat_rule_find(struct sk_buff **pskb,
275 unsigned int hooknum, 214 unsigned int hooknum,
276 const struct net_device *in, 215 const struct net_device *in,
277 const struct net_device *out, 216 const struct net_device *out,
278 struct nf_conn *ct, 217 struct nf_conn *ct)
279 struct nf_nat_info *info)
280{ 218{
281 int ret; 219 int ret;
282 220
@@ -285,7 +223,7 @@ int nf_nat_rule_find(struct sk_buff **pskb,
285 if (ret == NF_ACCEPT) { 223 if (ret == NF_ACCEPT) {
286 if (!nf_nat_initialized(ct, HOOK2MANIP(hooknum))) 224 if (!nf_nat_initialized(ct, HOOK2MANIP(hooknum)))
287 /* NUL mapping */ 225 /* NUL mapping */
288 ret = alloc_null_binding(ct, info, hooknum); 226 ret = alloc_null_binding(ct, hooknum);
289 } 227 }
290 return ret; 228 return ret;
291} 229}
diff --git a/net/ipv4/netfilter/nf_nat_standalone.c b/net/ipv4/netfilter/nf_nat_standalone.c
index 64bbed2ba780..55dac36dbc85 100644
--- a/net/ipv4/netfilter/nf_nat_standalone.c
+++ b/net/ipv4/netfilter/nf_nat_standalone.c
@@ -80,7 +80,6 @@ nf_nat_fn(unsigned int hooknum,
80 struct nf_conn *ct; 80 struct nf_conn *ct;
81 enum ip_conntrack_info ctinfo; 81 enum ip_conntrack_info ctinfo;
82 struct nf_conn_nat *nat; 82 struct nf_conn_nat *nat;
83 struct nf_nat_info *info;
84 /* maniptype == SRC for postrouting. */ 83 /* maniptype == SRC for postrouting. */
85 enum nf_nat_manip_type maniptype = HOOK2MANIP(hooknum); 84 enum nf_nat_manip_type maniptype = HOOK2MANIP(hooknum);
86 85
@@ -129,7 +128,6 @@ nf_nat_fn(unsigned int hooknum,
129 } 128 }
130 /* Fall thru... (Only ICMPs can be IP_CT_IS_REPLY) */ 129 /* Fall thru... (Only ICMPs can be IP_CT_IS_REPLY) */
131 case IP_CT_NEW: 130 case IP_CT_NEW:
132 info = &nat->info;
133 131
134 /* Seen it before? This can happen for loopback, retrans, 132 /* Seen it before? This can happen for loopback, retrans,
135 or local packets.. */ 133 or local packets.. */
@@ -138,14 +136,13 @@ nf_nat_fn(unsigned int hooknum,
138 136
139 if (unlikely(nf_ct_is_confirmed(ct))) 137 if (unlikely(nf_ct_is_confirmed(ct)))
140 /* NAT module was loaded late */ 138 /* NAT module was loaded late */
141 ret = alloc_null_binding_confirmed(ct, info, 139 ret = alloc_null_binding_confirmed(ct, hooknum);
142 hooknum);
143 else if (hooknum == NF_IP_LOCAL_IN) 140 else if (hooknum == NF_IP_LOCAL_IN)
144 /* LOCAL_IN hook doesn't have a chain! */ 141 /* LOCAL_IN hook doesn't have a chain! */
145 ret = alloc_null_binding(ct, info, hooknum); 142 ret = alloc_null_binding(ct, hooknum);
146 else 143 else
147 ret = nf_nat_rule_find(pskb, hooknum, in, out, 144 ret = nf_nat_rule_find(pskb, hooknum, in, out,
148 ct, info); 145 ct);
149 146
150 if (ret != NF_ACCEPT) { 147 if (ret != NF_ACCEPT) {
151 return ret; 148 return ret;
@@ -160,10 +157,8 @@ nf_nat_fn(unsigned int hooknum,
160 /* ESTABLISHED */ 157 /* ESTABLISHED */
161 NF_CT_ASSERT(ctinfo == IP_CT_ESTABLISHED || 158 NF_CT_ASSERT(ctinfo == IP_CT_ESTABLISHED ||
162 ctinfo == (IP_CT_ESTABLISHED+IP_CT_IS_REPLY)); 159 ctinfo == (IP_CT_ESTABLISHED+IP_CT_IS_REPLY));
163 info = &nat->info;
164 } 160 }
165 161
166 NF_CT_ASSERT(info);
167 return nf_nat_packet(ct, ctinfo, hooknum, pskb); 162 return nf_nat_packet(ct, ctinfo, hooknum, pskb);
168} 163}
169 164
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
index 66026df1cc76..4c7e95fa090d 100644
--- a/net/ipv4/udp.c
+++ b/net/ipv4/udp.c
@@ -118,15 +118,15 @@ static int udp_port_rover;
118 * Note about this hash function : 118 * Note about this hash function :
119 * Typical use is probably daddr = 0, only dport is going to vary hash 119 * Typical use is probably daddr = 0, only dport is going to vary hash
120 */ 120 */
121static inline unsigned int hash_port_and_addr(__u16 port, __be32 addr) 121static inline unsigned int udp_hash_port(__u16 port)
122{ 122{
123 addr ^= addr >> 16; 123 return port;
124 addr ^= addr >> 8;
125 return port ^ addr;
126} 124}
127 125
128static inline int __udp_lib_port_inuse(unsigned int hash, int port, 126static inline int __udp_lib_port_inuse(unsigned int hash, int port,
129 __be32 daddr, struct hlist_head udptable[]) 127 const struct sock *this_sk,
128 struct hlist_head udptable[],
129 const struct udp_get_port_ops *ops)
130{ 130{
131 struct sock *sk; 131 struct sock *sk;
132 struct hlist_node *node; 132 struct hlist_node *node;
@@ -138,7 +138,10 @@ static inline int __udp_lib_port_inuse(unsigned int hash, int port,
138 inet = inet_sk(sk); 138 inet = inet_sk(sk);
139 if (inet->num != port) 139 if (inet->num != port)
140 continue; 140 continue;
141 if (inet->rcv_saddr == daddr) 141 if (this_sk) {
142 if (ops->saddr_cmp(sk, this_sk))
143 return 1;
144 } else if (ops->saddr_any(sk))
142 return 1; 145 return 1;
143 } 146 }
144 return 0; 147 return 0;
@@ -151,12 +154,11 @@ static inline int __udp_lib_port_inuse(unsigned int hash, int port,
151 * @snum: port number to look up 154 * @snum: port number to look up
152 * @udptable: hash list table, must be of UDP_HTABLE_SIZE 155 * @udptable: hash list table, must be of UDP_HTABLE_SIZE
153 * @port_rover: pointer to record of last unallocated port 156 * @port_rover: pointer to record of last unallocated port
154 * @saddr_comp: AF-dependent comparison of bound local IP addresses 157 * @ops: AF-dependent address operations
155 */ 158 */
156int __udp_lib_get_port(struct sock *sk, unsigned short snum, 159int __udp_lib_get_port(struct sock *sk, unsigned short snum,
157 struct hlist_head udptable[], int *port_rover, 160 struct hlist_head udptable[], int *port_rover,
158 int (*saddr_comp)(const struct sock *sk1, 161 const struct udp_get_port_ops *ops)
159 const struct sock *sk2 ) )
160{ 162{
161 struct hlist_node *node; 163 struct hlist_node *node;
162 struct hlist_head *head; 164 struct hlist_head *head;
@@ -176,8 +178,7 @@ int __udp_lib_get_port(struct sock *sk, unsigned short snum,
176 for (i = 0; i < UDP_HTABLE_SIZE; i++, result++) { 178 for (i = 0; i < UDP_HTABLE_SIZE; i++, result++) {
177 int size; 179 int size;
178 180
179 hash = hash_port_and_addr(result, 181 hash = ops->hash_port_and_rcv_saddr(result, sk);
180 inet_sk(sk)->rcv_saddr);
181 head = &udptable[hash & (UDP_HTABLE_SIZE - 1)]; 182 head = &udptable[hash & (UDP_HTABLE_SIZE - 1)];
182 if (hlist_empty(head)) { 183 if (hlist_empty(head)) {
183 if (result > sysctl_local_port_range[1]) 184 if (result > sysctl_local_port_range[1])
@@ -203,17 +204,16 @@ int __udp_lib_get_port(struct sock *sk, unsigned short snum,
203 result = sysctl_local_port_range[0] 204 result = sysctl_local_port_range[0]
204 + ((result - sysctl_local_port_range[0]) & 205 + ((result - sysctl_local_port_range[0]) &
205 (UDP_HTABLE_SIZE - 1)); 206 (UDP_HTABLE_SIZE - 1));
206 hash = hash_port_and_addr(result, 0); 207 hash = udp_hash_port(result);
207 if (__udp_lib_port_inuse(hash, result, 208 if (__udp_lib_port_inuse(hash, result,
208 0, udptable)) 209 NULL, udptable, ops))
209 continue; 210 continue;
210 if (!inet_sk(sk)->rcv_saddr) 211 if (ops->saddr_any(sk))
211 break; 212 break;
212 213
213 hash = hash_port_and_addr(result, 214 hash = ops->hash_port_and_rcv_saddr(result, sk);
214 inet_sk(sk)->rcv_saddr);
215 if (! __udp_lib_port_inuse(hash, result, 215 if (! __udp_lib_port_inuse(hash, result,
216 inet_sk(sk)->rcv_saddr, udptable)) 216 sk, udptable, ops))
217 break; 217 break;
218 } 218 }
219 if (i >= (1 << 16) / UDP_HTABLE_SIZE) 219 if (i >= (1 << 16) / UDP_HTABLE_SIZE)
@@ -221,7 +221,7 @@ int __udp_lib_get_port(struct sock *sk, unsigned short snum,
221gotit: 221gotit:
222 *port_rover = snum = result; 222 *port_rover = snum = result;
223 } else { 223 } else {
224 hash = hash_port_and_addr(snum, 0); 224 hash = udp_hash_port(snum);
225 head = &udptable[hash & (UDP_HTABLE_SIZE - 1)]; 225 head = &udptable[hash & (UDP_HTABLE_SIZE - 1)];
226 226
227 sk_for_each(sk2, node, head) 227 sk_for_each(sk2, node, head)
@@ -231,12 +231,11 @@ gotit:
231 (!sk2->sk_reuse || !sk->sk_reuse) && 231 (!sk2->sk_reuse || !sk->sk_reuse) &&
232 (!sk2->sk_bound_dev_if || !sk->sk_bound_dev_if || 232 (!sk2->sk_bound_dev_if || !sk->sk_bound_dev_if ||
233 sk2->sk_bound_dev_if == sk->sk_bound_dev_if) && 233 sk2->sk_bound_dev_if == sk->sk_bound_dev_if) &&
234 (*saddr_comp)(sk, sk2)) 234 ops->saddr_cmp(sk, sk2))
235 goto fail; 235 goto fail;
236 236
237 if (inet_sk(sk)->rcv_saddr) { 237 if (!ops->saddr_any(sk)) {
238 hash = hash_port_and_addr(snum, 238 hash = ops->hash_port_and_rcv_saddr(snum, sk);
239 inet_sk(sk)->rcv_saddr);
240 head = &udptable[hash & (UDP_HTABLE_SIZE - 1)]; 239 head = &udptable[hash & (UDP_HTABLE_SIZE - 1)];
241 240
242 sk_for_each(sk2, node, head) 241 sk_for_each(sk2, node, head)
@@ -248,7 +247,7 @@ gotit:
248 !sk->sk_bound_dev_if || 247 !sk->sk_bound_dev_if ||
249 sk2->sk_bound_dev_if == 248 sk2->sk_bound_dev_if ==
250 sk->sk_bound_dev_if) && 249 sk->sk_bound_dev_if) &&
251 (*saddr_comp)(sk, sk2)) 250 ops->saddr_cmp(sk, sk2))
252 goto fail; 251 goto fail;
253 } 252 }
254 } 253 }
@@ -266,12 +265,12 @@ fail:
266} 265}
267 266
268int udp_get_port(struct sock *sk, unsigned short snum, 267int udp_get_port(struct sock *sk, unsigned short snum,
269 int (*scmp)(const struct sock *, const struct sock *)) 268 const struct udp_get_port_ops *ops)
270{ 269{
271 return __udp_lib_get_port(sk, snum, udp_hash, &udp_port_rover, scmp); 270 return __udp_lib_get_port(sk, snum, udp_hash, &udp_port_rover, ops);
272} 271}
273 272
274int ipv4_rcv_saddr_equal(const struct sock *sk1, const struct sock *sk2) 273static int ipv4_rcv_saddr_equal(const struct sock *sk1, const struct sock *sk2)
275{ 274{
276 struct inet_sock *inet1 = inet_sk(sk1), *inet2 = inet_sk(sk2); 275 struct inet_sock *inet1 = inet_sk(sk1), *inet2 = inet_sk(sk2);
277 276
@@ -280,9 +279,33 @@ int ipv4_rcv_saddr_equal(const struct sock *sk1, const struct sock *sk2)
280 inet1->rcv_saddr == inet2->rcv_saddr )); 279 inet1->rcv_saddr == inet2->rcv_saddr ));
281} 280}
282 281
282static int ipv4_rcv_saddr_any(const struct sock *sk)
283{
284 return !inet_sk(sk)->rcv_saddr;
285}
286
287static inline unsigned int ipv4_hash_port_and_addr(__u16 port, __be32 addr)
288{
289 addr ^= addr >> 16;
290 addr ^= addr >> 8;
291 return port ^ addr;
292}
293
294static unsigned int ipv4_hash_port_and_rcv_saddr(__u16 port,
295 const struct sock *sk)
296{
297 return ipv4_hash_port_and_addr(port, inet_sk(sk)->rcv_saddr);
298}
299
300const struct udp_get_port_ops udp_ipv4_ops = {
301 .saddr_cmp = ipv4_rcv_saddr_equal,
302 .saddr_any = ipv4_rcv_saddr_any,
303 .hash_port_and_rcv_saddr = ipv4_hash_port_and_rcv_saddr,
304};
305
283static inline int udp_v4_get_port(struct sock *sk, unsigned short snum) 306static inline int udp_v4_get_port(struct sock *sk, unsigned short snum)
284{ 307{
285 return udp_get_port(sk, snum, ipv4_rcv_saddr_equal); 308 return udp_get_port(sk, snum, &udp_ipv4_ops);
286} 309}
287 310
288/* UDP is nearly always wildcards out the wazoo, it makes no sense to try 311/* UDP is nearly always wildcards out the wazoo, it makes no sense to try
@@ -297,8 +320,8 @@ static struct sock *__udp4_lib_lookup(__be32 saddr, __be16 sport,
297 unsigned int hash, hashwild; 320 unsigned int hash, hashwild;
298 int score, best = -1, hport = ntohs(dport); 321 int score, best = -1, hport = ntohs(dport);
299 322
300 hash = hash_port_and_addr(hport, daddr); 323 hash = ipv4_hash_port_and_addr(hport, daddr);
301 hashwild = hash_port_and_addr(hport, 0); 324 hashwild = udp_hash_port(hport);
302 325
303 read_lock(&udp_hash_lock); 326 read_lock(&udp_hash_lock);
304 327
@@ -1198,8 +1221,8 @@ static int __udp4_lib_mcast_deliver(struct sk_buff *skb,
1198 struct sock *sk, *skw, *sknext; 1221 struct sock *sk, *skw, *sknext;
1199 int dif; 1222 int dif;
1200 int hport = ntohs(uh->dest); 1223 int hport = ntohs(uh->dest);
1201 unsigned int hash = hash_port_and_addr(hport, daddr); 1224 unsigned int hash = ipv4_hash_port_and_addr(hport, daddr);
1202 unsigned int hashwild = hash_port_and_addr(hport, 0); 1225 unsigned int hashwild = udp_hash_port(hport);
1203 1226
1204 dif = skb->dev->ifindex; 1227 dif = skb->dev->ifindex;
1205 1228
diff --git a/net/ipv4/udp_impl.h b/net/ipv4/udp_impl.h
index 820a477cfaa6..06d94195e644 100644
--- a/net/ipv4/udp_impl.h
+++ b/net/ipv4/udp_impl.h
@@ -5,14 +5,14 @@
5#include <net/protocol.h> 5#include <net/protocol.h>
6#include <net/inet_common.h> 6#include <net/inet_common.h>
7 7
8extern const struct udp_get_port_ops udp_ipv4_ops;
9
8extern int __udp4_lib_rcv(struct sk_buff *, struct hlist_head [], int ); 10extern int __udp4_lib_rcv(struct sk_buff *, struct hlist_head [], int );
9extern void __udp4_lib_err(struct sk_buff *, u32, struct hlist_head []); 11extern void __udp4_lib_err(struct sk_buff *, u32, struct hlist_head []);
10 12
11extern int __udp_lib_get_port(struct sock *sk, unsigned short snum, 13extern int __udp_lib_get_port(struct sock *sk, unsigned short snum,
12 struct hlist_head udptable[], int *port_rover, 14 struct hlist_head udptable[], int *port_rover,
13 int (*)(const struct sock*,const struct sock*)); 15 const struct udp_get_port_ops *ops);
14extern int ipv4_rcv_saddr_equal(const struct sock *, const struct sock *);
15
16 16
17extern int udp_setsockopt(struct sock *sk, int level, int optname, 17extern int udp_setsockopt(struct sock *sk, int level, int optname,
18 char __user *optval, int optlen); 18 char __user *optval, int optlen);
diff --git a/net/ipv4/udplite.c b/net/ipv4/udplite.c
index f34fd686a8f1..3653b32dce2d 100644
--- a/net/ipv4/udplite.c
+++ b/net/ipv4/udplite.c
@@ -19,14 +19,15 @@ struct hlist_head udplite_hash[UDP_HTABLE_SIZE];
19static int udplite_port_rover; 19static int udplite_port_rover;
20 20
21int udplite_get_port(struct sock *sk, unsigned short p, 21int udplite_get_port(struct sock *sk, unsigned short p,
22 int (*c)(const struct sock *, const struct sock *)) 22 const struct udp_get_port_ops *ops)
23{ 23{
24 return __udp_lib_get_port(sk, p, udplite_hash, &udplite_port_rover, c); 24 return __udp_lib_get_port(sk, p, udplite_hash,
25 &udplite_port_rover, ops);
25} 26}
26 27
27static int udplite_v4_get_port(struct sock *sk, unsigned short snum) 28static int udplite_v4_get_port(struct sock *sk, unsigned short snum)
28{ 29{
29 return udplite_get_port(sk, snum, ipv4_rcv_saddr_equal); 30 return udplite_get_port(sk, snum, &udp_ipv4_ops);
30} 31}
31 32
32static int udplite_rcv(struct sk_buff *skb) 33static int udplite_rcv(struct sk_buff *skb)
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index d02685c6bc69..c7ea248fae2e 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -4204,6 +4204,10 @@ int __init addrconf_init(void)
4204 return err; 4204 return err;
4205 4205
4206 ip6_null_entry.rt6i_idev = in6_dev_get(&loopback_dev); 4206 ip6_null_entry.rt6i_idev = in6_dev_get(&loopback_dev);
4207#ifdef CONFIG_IPV6_MULTIPLE_TABLES
4208 ip6_prohibit_entry.rt6i_idev = in6_dev_get(&loopback_dev);
4209 ip6_blk_hole_entry.rt6i_idev = in6_dev_get(&loopback_dev);
4210#endif
4207 4211
4208 register_netdevice_notifier(&ipv6_dev_notf); 4212 register_netdevice_notifier(&ipv6_dev_notf);
4209 4213
diff --git a/net/ipv6/exthdrs.c b/net/ipv6/exthdrs.c
index 6d8e4ac7bdad..14be0b9b77a5 100644
--- a/net/ipv6/exthdrs.c
+++ b/net/ipv6/exthdrs.c
@@ -660,6 +660,14 @@ EXPORT_SYMBOL_GPL(ipv6_invert_rthdr);
660 Hop-by-hop options. 660 Hop-by-hop options.
661 **********************************/ 661 **********************************/
662 662
663/*
664 * Note: we cannot rely on skb->dst before we assign it in ip6_route_input().
665 */
666static inline struct inet6_dev *ipv6_skb_idev(struct sk_buff *skb)
667{
668 return skb->dst ? ip6_dst_idev(skb->dst) : __in6_dev_get(skb->dev);
669}
670
663/* Router Alert as of RFC 2711 */ 671/* Router Alert as of RFC 2711 */
664 672
665static int ipv6_hop_ra(struct sk_buff **skbp, int optoff) 673static int ipv6_hop_ra(struct sk_buff **skbp, int optoff)
@@ -688,25 +696,25 @@ static int ipv6_hop_jumbo(struct sk_buff **skbp, int optoff)
688 if (nh[optoff + 1] != 4 || (optoff & 3) != 2) { 696 if (nh[optoff + 1] != 4 || (optoff & 3) != 2) {
689 LIMIT_NETDEBUG(KERN_DEBUG "ipv6_hop_jumbo: wrong jumbo opt length/alignment %d\n", 697 LIMIT_NETDEBUG(KERN_DEBUG "ipv6_hop_jumbo: wrong jumbo opt length/alignment %d\n",
690 nh[optoff+1]); 698 nh[optoff+1]);
691 IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), 699 IP6_INC_STATS_BH(ipv6_skb_idev(skb),
692 IPSTATS_MIB_INHDRERRORS); 700 IPSTATS_MIB_INHDRERRORS);
693 goto drop; 701 goto drop;
694 } 702 }
695 703
696 pkt_len = ntohl(*(__be32 *)(nh + optoff + 2)); 704 pkt_len = ntohl(*(__be32 *)(nh + optoff + 2));
697 if (pkt_len <= IPV6_MAXPLEN) { 705 if (pkt_len <= IPV6_MAXPLEN) {
698 IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), IPSTATS_MIB_INHDRERRORS); 706 IP6_INC_STATS_BH(ipv6_skb_idev(skb), IPSTATS_MIB_INHDRERRORS);
699 icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, optoff+2); 707 icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, optoff+2);
700 return 0; 708 return 0;
701 } 709 }
702 if (ipv6_hdr(skb)->payload_len) { 710 if (ipv6_hdr(skb)->payload_len) {
703 IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), IPSTATS_MIB_INHDRERRORS); 711 IP6_INC_STATS_BH(ipv6_skb_idev(skb), IPSTATS_MIB_INHDRERRORS);
704 icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, optoff); 712 icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, optoff);
705 return 0; 713 return 0;
706 } 714 }
707 715
708 if (pkt_len > skb->len - sizeof(struct ipv6hdr)) { 716 if (pkt_len > skb->len - sizeof(struct ipv6hdr)) {
709 IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), IPSTATS_MIB_INTRUNCATEDPKTS); 717 IP6_INC_STATS_BH(ipv6_skb_idev(skb), IPSTATS_MIB_INTRUNCATEDPKTS);
710 goto drop; 718 goto drop;
711 } 719 }
712 720
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
index f508171bab73..4704b5fc3085 100644
--- a/net/ipv6/ip6_output.c
+++ b/net/ipv6/ip6_output.c
@@ -463,10 +463,17 @@ int ip6_forward(struct sk_buff *skb)
463 */ 463 */
464 if (xrlim_allow(dst, 1*HZ)) 464 if (xrlim_allow(dst, 1*HZ))
465 ndisc_send_redirect(skb, n, target); 465 ndisc_send_redirect(skb, n, target);
466 } else if (ipv6_addr_type(&hdr->saddr)&(IPV6_ADDR_MULTICAST|IPV6_ADDR_LOOPBACK 466 } else {
467 |IPV6_ADDR_LINKLOCAL)) { 467 int addrtype = ipv6_addr_type(&hdr->saddr);
468
468 /* This check is security critical. */ 469 /* This check is security critical. */
469 goto error; 470 if (addrtype & (IPV6_ADDR_MULTICAST|IPV6_ADDR_LOOPBACK))
471 goto error;
472 if (addrtype & IPV6_ADDR_LINKLOCAL) {
473 icmpv6_send(skb, ICMPV6_DEST_UNREACH,
474 ICMPV6_NOT_NEIGHBOUR, 0, skb->dev);
475 goto error;
476 }
470 } 477 }
471 478
472 if (skb->len > dst_mtu(dst)) { 479 if (skb->len > dst_mtu(dst)) {
diff --git a/net/ipv6/netfilter/ip6table_filter.c b/net/ipv6/netfilter/ip6table_filter.c
index 76f0cf66f95c..7e32e2aaf7f7 100644
--- a/net/ipv6/netfilter/ip6table_filter.c
+++ b/net/ipv6/netfilter/ip6table_filter.c
@@ -24,53 +24,29 @@ static struct
24 struct ip6t_replace repl; 24 struct ip6t_replace repl;
25 struct ip6t_standard entries[3]; 25 struct ip6t_standard entries[3];
26 struct ip6t_error term; 26 struct ip6t_error term;
27} initial_table __initdata 27} initial_table __initdata = {
28= { { "filter", FILTER_VALID_HOOKS, 4, 28 .repl = {
29 sizeof(struct ip6t_standard) * 3 + sizeof(struct ip6t_error), 29 .name = "filter",
30 { [NF_IP6_LOCAL_IN] = 0, 30 .valid_hooks = FILTER_VALID_HOOKS,
31 [NF_IP6_FORWARD] = sizeof(struct ip6t_standard), 31 .num_entries = 4,
32 [NF_IP6_LOCAL_OUT] = sizeof(struct ip6t_standard) * 2 }, 32 .size = sizeof(struct ip6t_standard) * 3 + sizeof(struct ip6t_error),
33 { [NF_IP6_LOCAL_IN] = 0, 33 .hook_entry = {
34 [NF_IP6_FORWARD] = sizeof(struct ip6t_standard), 34 [NF_IP6_LOCAL_IN] = 0,
35 [NF_IP6_LOCAL_OUT] = sizeof(struct ip6t_standard) * 2 }, 35 [NF_IP6_FORWARD] = sizeof(struct ip6t_standard),
36 0, NULL, { } }, 36 [NF_IP6_LOCAL_OUT] = sizeof(struct ip6t_standard) * 2
37 { 37 },
38 /* LOCAL_IN */ 38 .underflow = {
39 { { { { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, "", "", { 0 }, { 0 }, 0, 0, 0 }, 39 [NF_IP6_LOCAL_IN] = 0,
40 0, 40 [NF_IP6_FORWARD] = sizeof(struct ip6t_standard),
41 sizeof(struct ip6t_entry), 41 [NF_IP6_LOCAL_OUT] = sizeof(struct ip6t_standard) * 2
42 sizeof(struct ip6t_standard), 42 },
43 0, { 0, 0 }, { } }, 43 },
44 { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } }, 44 .entries = {
45 -NF_ACCEPT - 1 } }, 45 IP6T_STANDARD_INIT(NF_ACCEPT), /* LOCAL_IN */
46 /* FORWARD */ 46 IP6T_STANDARD_INIT(NF_ACCEPT), /* FORWARD */
47 { { { { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, "", "", { 0 }, { 0 }, 0, 0, 0 }, 47 IP6T_STANDARD_INIT(NF_ACCEPT), /* LOCAL_OUT */
48 0, 48 },
49 sizeof(struct ip6t_entry), 49 .term = IP6T_ERROR_INIT, /* ERROR */
50 sizeof(struct ip6t_standard),
51 0, { 0, 0 }, { } },
52 { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
53 -NF_ACCEPT - 1 } },
54 /* LOCAL_OUT */
55 { { { { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, "", "", { 0 }, { 0 }, 0, 0, 0 },
56 0,
57 sizeof(struct ip6t_entry),
58 sizeof(struct ip6t_standard),
59 0, { 0, 0 }, { } },
60 { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
61 -NF_ACCEPT - 1 } }
62 },
63 /* ERROR */
64 { { { { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, "", "", { 0 }, { 0 }, 0, 0, 0 },
65 0,
66 sizeof(struct ip6t_entry),
67 sizeof(struct ip6t_error),
68 0, { 0, 0 }, { } },
69 { { { { IP6T_ALIGN(sizeof(struct ip6t_error_target)), IP6T_ERROR_TARGET } },
70 { } },
71 "ERROR"
72 }
73 }
74}; 50};
75 51
76static struct xt_table packet_filter = { 52static struct xt_table packet_filter = {
diff --git a/net/ipv6/netfilter/ip6table_mangle.c b/net/ipv6/netfilter/ip6table_mangle.c
index a9f10e32c163..f2d26495f413 100644
--- a/net/ipv6/netfilter/ip6table_mangle.c
+++ b/net/ipv6/netfilter/ip6table_mangle.c
@@ -32,73 +32,35 @@ static struct
32 struct ip6t_replace repl; 32 struct ip6t_replace repl;
33 struct ip6t_standard entries[5]; 33 struct ip6t_standard entries[5];
34 struct ip6t_error term; 34 struct ip6t_error term;
35} initial_table __initdata 35} initial_table __initdata = {
36= { { "mangle", MANGLE_VALID_HOOKS, 6, 36 .repl = {
37 sizeof(struct ip6t_standard) * 5 + sizeof(struct ip6t_error), 37 .name = "mangle",
38 { [NF_IP6_PRE_ROUTING] = 0, 38 .valid_hooks = MANGLE_VALID_HOOKS,
39 [NF_IP6_LOCAL_IN] = sizeof(struct ip6t_standard), 39 .num_entries = 6,
40 [NF_IP6_FORWARD] = sizeof(struct ip6t_standard) * 2, 40 .size = sizeof(struct ip6t_standard) * 5 + sizeof(struct ip6t_error),
41 [NF_IP6_LOCAL_OUT] = sizeof(struct ip6t_standard) * 3, 41 .hook_entry = {
42 [NF_IP6_POST_ROUTING] = sizeof(struct ip6t_standard) * 4}, 42 [NF_IP6_PRE_ROUTING] = 0,
43 { [NF_IP6_PRE_ROUTING] = 0, 43 [NF_IP6_LOCAL_IN] = sizeof(struct ip6t_standard),
44 [NF_IP6_LOCAL_IN] = sizeof(struct ip6t_standard), 44 [NF_IP6_FORWARD] = sizeof(struct ip6t_standard) * 2,
45 [NF_IP6_FORWARD] = sizeof(struct ip6t_standard) * 2, 45 [NF_IP6_LOCAL_OUT] = sizeof(struct ip6t_standard) * 3,
46 [NF_IP6_LOCAL_OUT] = sizeof(struct ip6t_standard) * 3, 46 [NF_IP6_POST_ROUTING] = sizeof(struct ip6t_standard) * 4,
47 [NF_IP6_POST_ROUTING] = sizeof(struct ip6t_standard) * 4}, 47 },
48 0, NULL, { } }, 48 .underflow = {
49 { 49 [NF_IP6_PRE_ROUTING] = 0,
50 /* PRE_ROUTING */ 50 [NF_IP6_LOCAL_IN] = sizeof(struct ip6t_standard),
51 { { { { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, "", "", { 0 }, { 0 }, 0, 0, 0 }, 51 [NF_IP6_FORWARD] = sizeof(struct ip6t_standard) * 2,
52 0, 52 [NF_IP6_LOCAL_OUT] = sizeof(struct ip6t_standard) * 3,
53 sizeof(struct ip6t_entry), 53 [NF_IP6_POST_ROUTING] = sizeof(struct ip6t_standard) * 4,
54 sizeof(struct ip6t_standard), 54 },
55 0, { 0, 0 }, { } }, 55 },
56 { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } }, 56 .entries = {
57 -NF_ACCEPT - 1 } }, 57 IP6T_STANDARD_INIT(NF_ACCEPT), /* PRE_ROUTING */
58 /* LOCAL_IN */ 58 IP6T_STANDARD_INIT(NF_ACCEPT), /* LOCAL_IN */
59 { { { { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, "", "", { 0 }, { 0 }, 0, 0, 0 }, 59 IP6T_STANDARD_INIT(NF_ACCEPT), /* FORWARD */
60 0, 60 IP6T_STANDARD_INIT(NF_ACCEPT), /* LOCAL_OUT */
61 sizeof(struct ip6t_entry), 61 IP6T_STANDARD_INIT(NF_ACCEPT), /* POST_ROUTING */
62 sizeof(struct ip6t_standard), 62 },
63 0, { 0, 0 }, { } }, 63 .term = IP6T_ERROR_INIT, /* ERROR */
64 { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
65 -NF_ACCEPT - 1 } },
66 /* FORWARD */
67 { { { { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, "", "", { 0 }, { 0 }, 0, 0, 0 },
68 0,
69 sizeof(struct ip6t_entry),
70 sizeof(struct ip6t_standard),
71 0, { 0, 0 }, { } },
72 { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
73 -NF_ACCEPT - 1 } },
74 /* LOCAL_OUT */
75 { { { { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, "", "", { 0 }, { 0 }, 0, 0, 0 },
76 0,
77 sizeof(struct ip6t_entry),
78 sizeof(struct ip6t_standard),
79 0, { 0, 0 }, { } },
80 { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
81 -NF_ACCEPT - 1 } },
82 /* POST_ROUTING */
83 { { { { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, "", "", { 0 }, { 0 }, 0, 0, 0 },
84 0,
85 sizeof(struct ip6t_entry),
86 sizeof(struct ip6t_standard),
87 0, { 0, 0 }, { } },
88 { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
89 -NF_ACCEPT - 1 } }
90 },
91 /* ERROR */
92 { { { { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, "", "", { 0 }, { 0 }, 0, 0, 0 },
93 0,
94 sizeof(struct ip6t_entry),
95 sizeof(struct ip6t_error),
96 0, { 0, 0 }, { } },
97 { { { { IP6T_ALIGN(sizeof(struct ip6t_error_target)), IP6T_ERROR_TARGET } },
98 { } },
99 "ERROR"
100 }
101 }
102}; 64};
103 65
104static struct xt_table packet_mangler = { 66static struct xt_table packet_mangler = {
diff --git a/net/ipv6/netfilter/ip6table_raw.c b/net/ipv6/netfilter/ip6table_raw.c
index a3eb5b8ce18d..0acda45d455d 100644
--- a/net/ipv6/netfilter/ip6table_raw.c
+++ b/net/ipv6/netfilter/ip6table_raw.c
@@ -35,56 +35,10 @@ static struct
35 }, 35 },
36 }, 36 },
37 .entries = { 37 .entries = {
38 /* PRE_ROUTING */ 38 IP6T_STANDARD_INIT(NF_ACCEPT), /* PRE_ROUTING */
39 { 39 IP6T_STANDARD_INIT(NF_ACCEPT), /* LOCAL_OUT */
40 .entry = {
41 .target_offset = sizeof(struct ip6t_entry),
42 .next_offset = sizeof(struct ip6t_standard),
43 },
44 .target = {
45 .target = {
46 .u = {
47 .target_size = IP6T_ALIGN(sizeof(struct ip6t_standard_target)),
48 },
49 },
50 .verdict = -NF_ACCEPT - 1,
51 },
52 },
53
54 /* LOCAL_OUT */
55 {
56 .entry = {
57 .target_offset = sizeof(struct ip6t_entry),
58 .next_offset = sizeof(struct ip6t_standard),
59 },
60 .target = {
61 .target = {
62 .u = {
63 .target_size = IP6T_ALIGN(sizeof(struct ip6t_standard_target)),
64 },
65 },
66 .verdict = -NF_ACCEPT - 1,
67 },
68 },
69 }, 40 },
70 /* ERROR */ 41 .term = IP6T_ERROR_INIT, /* ERROR */
71 .term = {
72 .entry = {
73 .target_offset = sizeof(struct ip6t_entry),
74 .next_offset = sizeof(struct ip6t_error),
75 },
76 .target = {
77 .target = {
78 .u = {
79 .user = {
80 .target_size = IP6T_ALIGN(sizeof(struct ip6t_error_target)),
81 .name = IP6T_ERROR_TARGET,
82 },
83 },
84 },
85 .errorname = "ERROR",
86 },
87 }
88}; 42};
89 43
90static struct xt_table packet_raw = { 44static struct xt_table packet_raw = {
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c
index b083c09e3d2d..a7ae59c954d5 100644
--- a/net/ipv6/udp.c
+++ b/net/ipv6/udp.c
@@ -52,9 +52,28 @@
52 52
53DEFINE_SNMP_STAT(struct udp_mib, udp_stats_in6) __read_mostly; 53DEFINE_SNMP_STAT(struct udp_mib, udp_stats_in6) __read_mostly;
54 54
55static int ipv6_rcv_saddr_any(const struct sock *sk)
56{
57 struct ipv6_pinfo *np = inet6_sk(sk);
58
59 return ipv6_addr_any(&np->rcv_saddr);
60}
61
62static unsigned int ipv6_hash_port_and_rcv_saddr(__u16 port,
63 const struct sock *sk)
64{
65 return port;
66}
67
68const struct udp_get_port_ops udp_ipv6_ops = {
69 .saddr_cmp = ipv6_rcv_saddr_equal,
70 .saddr_any = ipv6_rcv_saddr_any,
71 .hash_port_and_rcv_saddr = ipv6_hash_port_and_rcv_saddr,
72};
73
55static inline int udp_v6_get_port(struct sock *sk, unsigned short snum) 74static inline int udp_v6_get_port(struct sock *sk, unsigned short snum)
56{ 75{
57 return udp_get_port(sk, snum, ipv6_rcv_saddr_equal); 76 return udp_get_port(sk, snum, &udp_ipv6_ops);
58} 77}
59 78
60static struct sock *__udp6_lib_lookup(struct in6_addr *saddr, __be16 sport, 79static struct sock *__udp6_lib_lookup(struct in6_addr *saddr, __be16 sport,
diff --git a/net/ipv6/udp_impl.h b/net/ipv6/udp_impl.h
index 6e252f318f7c..36b0c11a28a3 100644
--- a/net/ipv6/udp_impl.h
+++ b/net/ipv6/udp_impl.h
@@ -6,6 +6,8 @@
6#include <net/addrconf.h> 6#include <net/addrconf.h>
7#include <net/inet_common.h> 7#include <net/inet_common.h>
8 8
9extern const struct udp_get_port_ops udp_ipv6_ops;
10
9extern int __udp6_lib_rcv(struct sk_buff **, struct hlist_head [], int ); 11extern int __udp6_lib_rcv(struct sk_buff **, struct hlist_head [], int );
10extern void __udp6_lib_err(struct sk_buff *, struct inet6_skb_parm *, 12extern void __udp6_lib_err(struct sk_buff *, struct inet6_skb_parm *,
11 int , int , int , __be32 , struct hlist_head []); 13 int , int , int , __be32 , struct hlist_head []);
diff --git a/net/ipv6/udplite.c b/net/ipv6/udplite.c
index f54016a55004..c40a51362f89 100644
--- a/net/ipv6/udplite.c
+++ b/net/ipv6/udplite.c
@@ -37,7 +37,7 @@ static struct inet6_protocol udplitev6_protocol = {
37 37
38static int udplite_v6_get_port(struct sock *sk, unsigned short snum) 38static int udplite_v6_get_port(struct sock *sk, unsigned short snum)
39{ 39{
40 return udplite_get_port(sk, snum, ipv6_rcv_saddr_equal); 40 return udplite_get_port(sk, snum, &udp_ipv6_ops);
41} 41}
42 42
43struct proto udplitev6_prot = { 43struct proto udplitev6_prot = {
diff --git a/net/mac80211/ieee80211_sta.c b/net/mac80211/ieee80211_sta.c
index 822917debeff..3e07e9d6fa42 100644
--- a/net/mac80211/ieee80211_sta.c
+++ b/net/mac80211/ieee80211_sta.c
@@ -17,6 +17,7 @@
17 * scan result table filtering (by capability (privacy, IBSS/BSS, WPA/RSN IE, 17 * scan result table filtering (by capability (privacy, IBSS/BSS, WPA/RSN IE,
18 * SSID) 18 * SSID)
19 */ 19 */
20#include <linux/delay.h>
20#include <linux/if_ether.h> 21#include <linux/if_ether.h>
21#include <linux/skbuff.h> 22#include <linux/skbuff.h>
22#include <linux/netdevice.h> 23#include <linux/netdevice.h>
@@ -27,7 +28,6 @@
27#include <linux/rtnetlink.h> 28#include <linux/rtnetlink.h>
28#include <net/iw_handler.h> 29#include <net/iw_handler.h>
29#include <asm/types.h> 30#include <asm/types.h>
30#include <asm/delay.h>
31 31
32#include <net/mac80211.h> 32#include <net/mac80211.h>
33#include "ieee80211_i.h" 33#include "ieee80211_i.h"
diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c
index e132c8ae8784..e8b5c2d7db62 100644
--- a/net/netfilter/nf_conntrack_core.c
+++ b/net/netfilter/nf_conntrack_core.c
@@ -299,7 +299,6 @@ destroy_conntrack(struct nf_conntrack *nfct)
299{ 299{
300 struct nf_conn *ct = (struct nf_conn *)nfct; 300 struct nf_conn *ct = (struct nf_conn *)nfct;
301 struct nf_conn_help *help = nfct_help(ct); 301 struct nf_conn_help *help = nfct_help(ct);
302 struct nf_conntrack_l3proto *l3proto;
303 struct nf_conntrack_l4proto *l4proto; 302 struct nf_conntrack_l4proto *l4proto;
304 typeof(nf_conntrack_destroyed) destroyed; 303 typeof(nf_conntrack_destroyed) destroyed;
305 304
@@ -317,10 +316,6 @@ destroy_conntrack(struct nf_conntrack *nfct)
317 * destroy_conntrack() MUST NOT be called with a write lock 316 * destroy_conntrack() MUST NOT be called with a write lock
318 * to nf_conntrack_lock!!! -HW */ 317 * to nf_conntrack_lock!!! -HW */
319 rcu_read_lock(); 318 rcu_read_lock();
320 l3proto = __nf_ct_l3proto_find(ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.l3num);
321 if (l3proto && l3proto->destroy)
322 l3proto->destroy(ct);
323
324 l4proto = __nf_ct_l4proto_find(ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.l3num, 319 l4proto = __nf_ct_l4proto_find(ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.l3num,
325 ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.protonum); 320 ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.protonum);
326 if (l4proto && l4proto->destroy) 321 if (l4proto && l4proto->destroy)
@@ -893,8 +888,13 @@ void nf_conntrack_alter_reply(struct nf_conn *ct,
893 NF_CT_DUMP_TUPLE(newreply); 888 NF_CT_DUMP_TUPLE(newreply);
894 889
895 ct->tuplehash[IP_CT_DIR_REPLY].tuple = *newreply; 890 ct->tuplehash[IP_CT_DIR_REPLY].tuple = *newreply;
896 if (!ct->master && help && help->expecting == 0) 891 if (!ct->master && help && help->expecting == 0) {
897 help->helper = __nf_ct_helper_find(newreply); 892 struct nf_conntrack_helper *helper;
893 helper = __nf_ct_helper_find(newreply);
894 if (helper)
895 memset(&help->help, 0, sizeof(help->help));
896 help->helper = helper;
897 }
898 write_unlock_bh(&nf_conntrack_lock); 898 write_unlock_bh(&nf_conntrack_lock);
899} 899}
900EXPORT_SYMBOL_GPL(nf_conntrack_alter_reply); 900EXPORT_SYMBOL_GPL(nf_conntrack_alter_reply);
diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c
index aa1a97ee514b..d6d39e241327 100644
--- a/net/netfilter/nf_conntrack_netlink.c
+++ b/net/netfilter/nf_conntrack_netlink.c
@@ -830,11 +830,6 @@ ctnetlink_change_helper(struct nf_conn *ct, struct nfattr *cda[])
830 char *helpname; 830 char *helpname;
831 int err; 831 int err;
832 832
833 if (!help) {
834 /* FIXME: we need to reallocate and rehash */
835 return -EBUSY;
836 }
837
838 /* don't change helper of sibling connections */ 833 /* don't change helper of sibling connections */
839 if (ct->master) 834 if (ct->master)
840 return -EINVAL; 835 return -EINVAL;
@@ -843,25 +838,34 @@ ctnetlink_change_helper(struct nf_conn *ct, struct nfattr *cda[])
843 if (err < 0) 838 if (err < 0)
844 return err; 839 return err;
845 840
846 helper = __nf_conntrack_helper_find_byname(helpname); 841 if (!strcmp(helpname, "")) {
847 if (!helper) { 842 if (help && help->helper) {
848 if (!strcmp(helpname, ""))
849 helper = NULL;
850 else
851 return -EINVAL;
852 }
853
854 if (help->helper) {
855 if (!helper) {
856 /* we had a helper before ... */ 843 /* we had a helper before ... */
857 nf_ct_remove_expectations(ct); 844 nf_ct_remove_expectations(ct);
858 help->helper = NULL; 845 help->helper = NULL;
859 } else {
860 /* need to zero data of old helper */
861 memset(&help->help, 0, sizeof(help->help));
862 } 846 }
847
848 return 0;
863 } 849 }
864 850
851 if (!help) {
852 /* FIXME: we need to reallocate and rehash */
853 return -EBUSY;
854 }
855
856 helper = __nf_conntrack_helper_find_byname(helpname);
857 if (helper == NULL)
858 return -EINVAL;
859
860 if (help->helper == helper)
861 return 0;
862
863 if (help->helper)
864 /* we had a helper before ... */
865 nf_ct_remove_expectations(ct);
866
867 /* need to zero data of old helper */
868 memset(&help->help, 0, sizeof(help->help));
865 help->helper = helper; 869 help->helper = helper;
866 870
867 return 0; 871 return 0;
diff --git a/net/netfilter/xt_conntrack.c b/net/netfilter/xt_conntrack.c
index f4ea8fe07a53..189ded5f378b 100644
--- a/net/netfilter/xt_conntrack.c
+++ b/net/netfilter/xt_conntrack.c
@@ -134,12 +134,66 @@ static void destroy(const struct xt_match *match, void *matchinfo)
134 nf_ct_l3proto_module_put(match->family); 134 nf_ct_l3proto_module_put(match->family);
135} 135}
136 136
137#ifdef CONFIG_COMPAT
138struct compat_xt_conntrack_info
139{
140 compat_uint_t statemask;
141 compat_uint_t statusmask;
142 struct ip_conntrack_old_tuple tuple[IP_CT_DIR_MAX];
143 struct in_addr sipmsk[IP_CT_DIR_MAX];
144 struct in_addr dipmsk[IP_CT_DIR_MAX];
145 compat_ulong_t expires_min;
146 compat_ulong_t expires_max;
147 u_int8_t flags;
148 u_int8_t invflags;
149};
150
151static void compat_from_user(void *dst, void *src)
152{
153 struct compat_xt_conntrack_info *cm = src;
154 struct xt_conntrack_info m = {
155 .statemask = cm->statemask,
156 .statusmask = cm->statusmask,
157 .expires_min = cm->expires_min,
158 .expires_max = cm->expires_max,
159 .flags = cm->flags,
160 .invflags = cm->invflags,
161 };
162 memcpy(m.tuple, cm->tuple, sizeof(m.tuple));
163 memcpy(m.sipmsk, cm->sipmsk, sizeof(m.sipmsk));
164 memcpy(m.dipmsk, cm->dipmsk, sizeof(m.dipmsk));
165 memcpy(dst, &m, sizeof(m));
166}
167
168static int compat_to_user(void __user *dst, void *src)
169{
170 struct xt_conntrack_info *m = src;
171 struct compat_xt_conntrack_info cm = {
172 .statemask = m->statemask,
173 .statusmask = m->statusmask,
174 .expires_min = m->expires_min,
175 .expires_max = m->expires_max,
176 .flags = m->flags,
177 .invflags = m->invflags,
178 };
179 memcpy(cm.tuple, m->tuple, sizeof(cm.tuple));
180 memcpy(cm.sipmsk, m->sipmsk, sizeof(cm.sipmsk));
181 memcpy(cm.dipmsk, m->dipmsk, sizeof(cm.dipmsk));
182 return copy_to_user(dst, &cm, sizeof(cm)) ? -EFAULT : 0;
183}
184#endif
185
137static struct xt_match conntrack_match = { 186static struct xt_match conntrack_match = {
138 .name = "conntrack", 187 .name = "conntrack",
139 .match = match, 188 .match = match,
140 .checkentry = checkentry, 189 .checkentry = checkentry,
141 .destroy = destroy, 190 .destroy = destroy,
142 .matchsize = sizeof(struct xt_conntrack_info), 191 .matchsize = sizeof(struct xt_conntrack_info),
192#ifdef CONFIG_COMPAT
193 .compatsize = sizeof(struct compat_xt_conntrack_info),
194 .compat_from_user = compat_from_user,
195 .compat_to_user = compat_to_user,
196#endif
143 .family = AF_INET, 197 .family = AF_INET,
144 .me = THIS_MODULE, 198 .me = THIS_MODULE,
145}; 199};
diff --git a/net/sched/sch_generic.c b/net/sched/sch_generic.c
index 3385ee592541..f28bb2dc58d0 100644
--- a/net/sched/sch_generic.c
+++ b/net/sched/sch_generic.c
@@ -71,12 +71,9 @@ void qdisc_unlock_tree(struct net_device *dev)
71 71
72 72
73/* Kick device. 73/* Kick device.
74 Note, that this procedure can be called by a watchdog timer, so that
75 we do not check dev->tbusy flag here.
76 74
77 Returns: 0 - queue is empty. 75 Returns: 0 - queue is empty or throttled.
78 >0 - queue is not empty, but throttled. 76 >0 - queue is not empty.
79 <0 - queue is not empty. Device is throttled, if dev->tbusy != 0.
80 77
81 NOTE: Called under dev->queue_lock with locally disabled BH. 78 NOTE: Called under dev->queue_lock with locally disabled BH.
82*/ 79*/
@@ -115,7 +112,7 @@ static inline int qdisc_restart(struct net_device *dev)
115 kfree_skb(skb); 112 kfree_skb(skb);
116 if (net_ratelimit()) 113 if (net_ratelimit())
117 printk(KERN_DEBUG "Dead loop on netdevice %s, fix it urgently!\n", dev->name); 114 printk(KERN_DEBUG "Dead loop on netdevice %s, fix it urgently!\n", dev->name);
118 return -1; 115 goto out;
119 } 116 }
120 __get_cpu_var(netdev_rx_stat).cpu_collision++; 117 __get_cpu_var(netdev_rx_stat).cpu_collision++;
121 goto requeue; 118 goto requeue;
@@ -135,10 +132,12 @@ static inline int qdisc_restart(struct net_device *dev)
135 netif_tx_unlock(dev); 132 netif_tx_unlock(dev);
136 } 133 }
137 spin_lock(&dev->queue_lock); 134 spin_lock(&dev->queue_lock);
138 return -1; 135 q = dev->qdisc;
136 goto out;
139 } 137 }
140 if (ret == NETDEV_TX_LOCKED && nolock) { 138 if (ret == NETDEV_TX_LOCKED && nolock) {
141 spin_lock(&dev->queue_lock); 139 spin_lock(&dev->queue_lock);
140 q = dev->qdisc;
142 goto collision; 141 goto collision;
143 } 142 }
144 } 143 }
@@ -163,26 +162,28 @@ static inline int qdisc_restart(struct net_device *dev)
163 */ 162 */
164 163
165requeue: 164requeue:
166 if (skb->next) 165 if (unlikely(q == &noop_qdisc))
166 kfree_skb(skb);
167 else if (skb->next)
167 dev->gso_skb = skb; 168 dev->gso_skb = skb;
168 else 169 else
169 q->ops->requeue(skb, q); 170 q->ops->requeue(skb, q);
170 netif_schedule(dev); 171 netif_schedule(dev);
171 return 1; 172 return 0;
172 } 173 }
174
175out:
173 BUG_ON((int) q->q.qlen < 0); 176 BUG_ON((int) q->q.qlen < 0);
174 return q->q.qlen; 177 return q->q.qlen;
175} 178}
176 179
177void __qdisc_run(struct net_device *dev) 180void __qdisc_run(struct net_device *dev)
178{ 181{
179 if (unlikely(dev->qdisc == &noop_qdisc)) 182 do {
180 goto out; 183 if (!qdisc_restart(dev))
181 184 break;
182 while (qdisc_restart(dev) < 0 && !netif_queue_stopped(dev)) 185 } while (!netif_queue_stopped(dev));
183 /* NOTHING */;
184 186
185out:
186 clear_bit(__LINK_STATE_QDISC_RUNNING, &dev->state); 187 clear_bit(__LINK_STATE_QDISC_RUNNING, &dev->state);
187} 188}
188 189
@@ -544,6 +545,7 @@ void dev_activate(struct net_device *dev)
544void dev_deactivate(struct net_device *dev) 545void dev_deactivate(struct net_device *dev)
545{ 546{
546 struct Qdisc *qdisc; 547 struct Qdisc *qdisc;
548 struct sk_buff *skb;
547 549
548 spin_lock_bh(&dev->queue_lock); 550 spin_lock_bh(&dev->queue_lock);
549 qdisc = dev->qdisc; 551 qdisc = dev->qdisc;
@@ -551,8 +553,12 @@ void dev_deactivate(struct net_device *dev)
551 553
552 qdisc_reset(qdisc); 554 qdisc_reset(qdisc);
553 555
556 skb = dev->gso_skb;
557 dev->gso_skb = NULL;
554 spin_unlock_bh(&dev->queue_lock); 558 spin_unlock_bh(&dev->queue_lock);
555 559
560 kfree_skb(skb);
561
556 dev_watchdog_down(dev); 562 dev_watchdog_down(dev);
557 563
558 /* Wait for outstanding dev_queue_xmit calls. */ 564 /* Wait for outstanding dev_queue_xmit calls. */
@@ -561,11 +567,6 @@ void dev_deactivate(struct net_device *dev)
561 /* Wait for outstanding qdisc_run calls. */ 567 /* Wait for outstanding qdisc_run calls. */
562 while (test_bit(__LINK_STATE_QDISC_RUNNING, &dev->state)) 568 while (test_bit(__LINK_STATE_QDISC_RUNNING, &dev->state))
563 yield(); 569 yield();
564
565 if (dev->gso_skb) {
566 kfree_skb(dev->gso_skb);
567 dev->gso_skb = NULL;
568 }
569} 570}
570 571
571void dev_init_scheduler(struct net_device *dev) 572void dev_init_scheduler(struct net_device *dev)
diff --git a/net/sched/sch_teql.c b/net/sched/sch_teql.c
index d24914db7861..f05ad9a30b4c 100644
--- a/net/sched/sch_teql.c
+++ b/net/sched/sch_teql.c
@@ -94,14 +94,13 @@ teql_enqueue(struct sk_buff *skb, struct Qdisc* sch)
94 struct net_device *dev = sch->dev; 94 struct net_device *dev = sch->dev;
95 struct teql_sched_data *q = qdisc_priv(sch); 95 struct teql_sched_data *q = qdisc_priv(sch);
96 96
97 __skb_queue_tail(&q->q, skb); 97 if (q->q.qlen < dev->tx_queue_len) {
98 if (q->q.qlen <= dev->tx_queue_len) { 98 __skb_queue_tail(&q->q, skb);
99 sch->bstats.bytes += skb->len; 99 sch->bstats.bytes += skb->len;
100 sch->bstats.packets++; 100 sch->bstats.packets++;
101 return 0; 101 return 0;
102 } 102 }
103 103
104 __skb_unlink(skb, &q->q);
105 kfree_skb(skb); 104 kfree_skb(skb);
106 sch->qstats.drops++; 105 sch->qstats.drops++;
107 return NET_XMIT_DROP; 106 return NET_XMIT_DROP;
diff --git a/net/sctp/socket.c b/net/sctp/socket.c
index 83a76ba9d7b3..4dcdabf56473 100644
--- a/net/sctp/socket.c
+++ b/net/sctp/socket.c
@@ -4164,6 +4164,7 @@ static int sctp_getsockopt_local_addrs_old(struct sock *sk, int len,
4164 rwlock_t *addr_lock; 4164 rwlock_t *addr_lock;
4165 int err = 0; 4165 int err = 0;
4166 void *addrs; 4166 void *addrs;
4167 void *buf;
4167 int bytes_copied = 0; 4168 int bytes_copied = 0;
4168 4169
4169 if (len != sizeof(struct sctp_getaddrs_old)) 4170 if (len != sizeof(struct sctp_getaddrs_old))
@@ -4217,13 +4218,14 @@ static int sctp_getsockopt_local_addrs_old(struct sock *sk, int len,
4217 } 4218 }
4218 } 4219 }
4219 4220
4221 buf = addrs;
4220 list_for_each(pos, &bp->address_list) { 4222 list_for_each(pos, &bp->address_list) {
4221 addr = list_entry(pos, struct sctp_sockaddr_entry, list); 4223 addr = list_entry(pos, struct sctp_sockaddr_entry, list);
4222 memcpy(&temp, &addr->a, sizeof(temp)); 4224 memcpy(&temp, &addr->a, sizeof(temp));
4223 sctp_get_pf_specific(sk->sk_family)->addr_v4map(sp, &temp); 4225 sctp_get_pf_specific(sk->sk_family)->addr_v4map(sp, &temp);
4224 addrlen = sctp_get_af_specific(temp.sa.sa_family)->sockaddr_len; 4226 addrlen = sctp_get_af_specific(temp.sa.sa_family)->sockaddr_len;
4225 memcpy(addrs, &temp, addrlen); 4227 memcpy(buf, &temp, addrlen);
4226 to += addrlen; 4228 buf += addrlen;
4227 bytes_copied += addrlen; 4229 bytes_copied += addrlen;
4228 cnt ++; 4230 cnt ++;
4229 if (cnt >= getaddrs.addr_num) break; 4231 if (cnt >= getaddrs.addr_num) break;
@@ -4266,6 +4268,7 @@ static int sctp_getsockopt_local_addrs(struct sock *sk, int len,
4266 size_t space_left; 4268 size_t space_left;
4267 int bytes_copied = 0; 4269 int bytes_copied = 0;
4268 void *addrs; 4270 void *addrs;
4271 void *buf;
4269 4272
4270 if (len <= sizeof(struct sctp_getaddrs)) 4273 if (len <= sizeof(struct sctp_getaddrs))
4271 return -EINVAL; 4274 return -EINVAL;
@@ -4316,6 +4319,7 @@ static int sctp_getsockopt_local_addrs(struct sock *sk, int len,
4316 } 4319 }
4317 } 4320 }
4318 4321
4322 buf = addrs;
4319 list_for_each(pos, &bp->address_list) { 4323 list_for_each(pos, &bp->address_list) {
4320 addr = list_entry(pos, struct sctp_sockaddr_entry, list); 4324 addr = list_entry(pos, struct sctp_sockaddr_entry, list);
4321 memcpy(&temp, &addr->a, sizeof(temp)); 4325 memcpy(&temp, &addr->a, sizeof(temp));
@@ -4325,8 +4329,8 @@ static int sctp_getsockopt_local_addrs(struct sock *sk, int len,
4325 err = -ENOMEM; /*fixme: right error?*/ 4329 err = -ENOMEM; /*fixme: right error?*/
4326 goto error; 4330 goto error;
4327 } 4331 }
4328 memcpy(addrs, &temp, addrlen); 4332 memcpy(buf, &temp, addrlen);
4329 to += addrlen; 4333 buf += addrlen;
4330 bytes_copied += addrlen; 4334 bytes_copied += addrlen;
4331 cnt ++; 4335 cnt ++;
4332 space_left -= addrlen; 4336 space_left -= addrlen;
@@ -5227,7 +5231,12 @@ int sctp_inet_listen(struct socket *sock, int backlog)
5227 /* Allocate HMAC for generating cookie. */ 5231 /* Allocate HMAC for generating cookie. */
5228 if (sctp_hmac_alg) { 5232 if (sctp_hmac_alg) {
5229 tfm = crypto_alloc_hash(sctp_hmac_alg, 0, CRYPTO_ALG_ASYNC); 5233 tfm = crypto_alloc_hash(sctp_hmac_alg, 0, CRYPTO_ALG_ASYNC);
5230 if (!tfm) { 5234 if (IS_ERR(tfm)) {
5235 if (net_ratelimit()) {
5236 printk(KERN_INFO
5237 "SCTP: failed to load transform for %s: %ld\n",
5238 sctp_hmac_alg, PTR_ERR(tfm));
5239 }
5231 err = -ENOSYS; 5240 err = -ENOSYS;
5232 goto out; 5241 goto out;
5233 } 5242 }
diff --git a/net/sctp/ulpevent.c b/net/sctp/ulpevent.c
index 661ea2dd78ba..bfecb353ab3d 100644
--- a/net/sctp/ulpevent.c
+++ b/net/sctp/ulpevent.c
@@ -141,11 +141,6 @@ struct sctp_ulpevent *sctp_ulpevent_make_assoc_change(
141 * an ABORT, so we need to include it in the sac_info. 141 * an ABORT, so we need to include it in the sac_info.
142 */ 142 */
143 if (chunk) { 143 if (chunk) {
144 /* sctp_inqu_pop() has allready pulled off the chunk
145 * header. We need to put it back temporarily
146 */
147 skb_push(chunk->skb, sizeof(sctp_chunkhdr_t));
148
149 /* Copy the chunk data to a new skb and reserve enough 144 /* Copy the chunk data to a new skb and reserve enough
150 * head room to use as notification. 145 * head room to use as notification.
151 */ 146 */
@@ -155,9 +150,6 @@ struct sctp_ulpevent *sctp_ulpevent_make_assoc_change(
155 if (!skb) 150 if (!skb)
156 goto fail; 151 goto fail;
157 152
158 /* put back the chunk header now that we have a copy */
159 skb_pull(chunk->skb, sizeof(sctp_chunkhdr_t));
160
161 /* Embed the event fields inside the cloned skb. */ 153 /* Embed the event fields inside the cloned skb. */
162 event = sctp_skb2event(skb); 154 event = sctp_skb2event(skb);
163 sctp_ulpevent_init(event, MSG_NOTIFICATION, skb->truesize); 155 sctp_ulpevent_init(event, MSG_NOTIFICATION, skb->truesize);
@@ -168,7 +160,8 @@ struct sctp_ulpevent *sctp_ulpevent_make_assoc_change(
168 160
169 /* Trim the buffer to the right length. */ 161 /* Trim the buffer to the right length. */
170 skb_trim(skb, sizeof(struct sctp_assoc_change) + 162 skb_trim(skb, sizeof(struct sctp_assoc_change) +
171 ntohs(chunk->chunk_hdr->length)); 163 ntohs(chunk->chunk_hdr->length) -
164 sizeof(sctp_chunkhdr_t));
172 } else { 165 } else {
173 event = sctp_ulpevent_new(sizeof(struct sctp_assoc_change), 166 event = sctp_ulpevent_new(sizeof(struct sctp_assoc_change),
174 MSG_NOTIFICATION, gfp); 167 MSG_NOTIFICATION, gfp);