diff options
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 | ||
144 | config 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 | |||
144 | comment "Old SIR device drivers" | 158 | comment "Old SIR device drivers" |
145 | 159 | ||
146 | config IRPORT_SIR | 160 | config 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 | |||
45 | obj-$(CONFIG_ACT200L_DONGLE) += act200l-sir.o | 45 | obj-$(CONFIG_ACT200L_DONGLE) += act200l-sir.o |
46 | obj-$(CONFIG_MA600_DONGLE) += ma600-sir.o | 46 | obj-$(CONFIG_MA600_DONGLE) += ma600-sir.o |
47 | obj-$(CONFIG_TOIM3232_DONGLE) += toim3232-sir.o | 47 | obj-$(CONFIG_TOIM3232_DONGLE) += toim3232-sir.o |
48 | obj-$(CONFIG_KINGSUN_DONGLE) += kingsun-sir.o | ||
48 | 49 | ||
49 | # The SIR helper module | 50 | # The SIR helper module |
50 | sir-dev-objs := sir_dev.o sir_dongle.o | 51 | sir-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 */ | ||
91 | static struct usb_device_id dongles[] = { | ||
92 | /* KingSun Co,Ltd IrDA/USB Bridge */ | ||
93 | { USB_DEVICE(KING_VENDOR_ID, KING_PRODUCT_ID) }, | ||
94 | { } | ||
95 | }; | ||
96 | |||
97 | MODULE_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 | |||
105 | struct 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 */ | ||
132 | static 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 | */ | ||
154 | static 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 */ | ||
205 | static 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 | */ | ||
258 | static 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 | */ | ||
348 | static 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 | */ | ||
384 | static 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 | */ | ||
426 | static struct net_device_stats * | ||
427 | kingsun_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 | */ | ||
438 | static 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 | |||
558 | free_mem: | ||
559 | if (kingsun->out_buf) kfree(kingsun->out_buf); | ||
560 | if (kingsun->in_buf) kfree(kingsun->in_buf); | ||
561 | free_netdev(net); | ||
562 | err_out1: | ||
563 | return ret; | ||
564 | } | ||
565 | |||
566 | /* | ||
567 | * The current device is removed, the USB layer tell us to shut it down... | ||
568 | */ | ||
569 | static 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 */ | ||
599 | static 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 */ | ||
610 | static 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 | */ | ||
625 | static 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 | */ | ||
639 | static int __init kingsun_init(void) | ||
640 | { | ||
641 | return usb_register(&irda_driver); | ||
642 | } | ||
643 | module_init(kingsun_init); | ||
644 | |||
645 | /* | ||
646 | * Module removal | ||
647 | */ | ||
648 | static void __exit kingsun_cleanup(void) | ||
649 | { | ||
650 | /* Deregister the driver and remove all pending instances */ | ||
651 | usb_deregister(&irda_driver); | ||
652 | } | ||
653 | module_exit(kingsun_cleanup); | ||
654 | |||
655 | MODULE_AUTHOR("Alex Villac�s Lasso <a_villacis@palosanto.com>"); | ||
656 | MODULE_DESCRIPTION("IrDA-USB Dongle Driver for KingSun/DonShine"); | ||
657 | MODULE_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 | |||
57 | struct xt_standard_target | 65 | struct 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. */ | ||
242 | struct arpt_standard | ||
243 | { | ||
244 | struct arpt_entry entry; | ||
245 | struct arpt_standard_target target; | ||
246 | }; | ||
247 | |||
248 | struct arpt_error_target | ||
249 | { | ||
250 | struct arpt_entry_target target; | ||
251 | char errorname[ARPT_FUNCTION_MAXNAMELEN]; | ||
252 | }; | ||
253 | |||
254 | struct 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 | |||
298 | extern unsigned int ipt_do_table(struct sk_buff **pskb, | 320 | extern 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 | ||
184 | extern void nf_conntrack_flush(void); | 184 | extern void nf_conntrack_flush(void); |
185 | 185 | ||
186 | extern struct nf_conntrack_helper * | ||
187 | nf_ct_helper_find_get( const struct nf_conntrack_tuple *tuple); | ||
188 | extern void nf_ct_helper_put(struct nf_conntrack_helper *helper); | ||
189 | |||
190 | extern struct nf_conntrack_helper * | ||
191 | __nf_conntrack_helper_find_byname(const char *name); | ||
192 | |||
193 | extern int nf_ct_invert_tuplepr(struct nf_conntrack_tuple *inverse, | 186 | extern 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 | ||
16 | extern unsigned int | 15 | extern unsigned int |
17 | alloc_null_binding(struct nf_conn *ct, | 16 | alloc_null_binding(struct nf_conn *ct, unsigned int hooknum); |
18 | struct nf_nat_info *info, | ||
19 | unsigned int hooknum); | ||
20 | 17 | ||
21 | extern unsigned int | 18 | extern unsigned int |
22 | alloc_null_binding_confirmed(struct nf_conn *ct, | 19 | alloc_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 | ||
122 | struct 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 */ |
123 | extern int udp_get_port(struct sock *sk, unsigned short snum, | 130 | extern 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); |
125 | extern void udp_err(struct sk_buff *, u32); | 132 | extern void udp_err(struct sk_buff *, u32); |
126 | 133 | ||
127 | extern int udp_sendmsg(struct kiocb *iocb, struct sock *sk, | 134 | extern 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 | ||
121 | extern void udplite4_register(void); | 121 | extern void udplite4_register(void); |
122 | extern int udplite_get_port(struct sock *sk, unsigned short snum, | 122 | extern 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 | ||
175 | static int hidp_hidinput_event(struct input_dev *dev, unsigned int type, unsigned int code, int value) | 175 | static 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 | ||
183 | static int hidp_input_event(struct input_dev *dev, unsigned int type, unsigned int code, int value) | 183 | static 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 | ||
29 | enum lw_bits { | 28 | enum lw_bits { |
30 | LW_RUNNING = 0, | 29 | LW_URGENT = 0, |
31 | LW_SE_USED | ||
32 | }; | 30 | }; |
33 | 31 | ||
34 | static unsigned long linkwatch_flags; | 32 | static unsigned long linkwatch_flags; |
@@ -37,17 +35,9 @@ static unsigned long linkwatch_nextevent; | |||
37 | static void linkwatch_event(struct work_struct *dummy); | 35 | static void linkwatch_event(struct work_struct *dummy); |
38 | static DECLARE_DELAYED_WORK(linkwatch_work, linkwatch_event); | 36 | static DECLARE_DELAYED_WORK(linkwatch_work, linkwatch_event); |
39 | 37 | ||
40 | static LIST_HEAD(lweventlist); | 38 | static struct net_device *lweventlist; |
41 | static DEFINE_SPINLOCK(lweventlist_lock); | 39 | static DEFINE_SPINLOCK(lweventlist_lock); |
42 | 40 | ||
43 | struct lw_event { | ||
44 | struct list_head list; | ||
45 | struct net_device *dev; | ||
46 | }; | ||
47 | |||
48 | /* Avoid kmalloc() for most systems */ | ||
49 | static struct lw_event singleevent; | ||
50 | |||
51 | static unsigned char default_operstate(const struct net_device *dev) | 41 | static 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 */ | 80 | static int linkwatch_urgent_event(struct net_device *dev) |
91 | void 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 | |||
87 | static 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 | |||
98 | static 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 | |||
136 | static 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 | ||
130 | static void linkwatch_event(struct work_struct *dummy) | 200 | /* Must be called with the rtnl semaphore held */ |
201 | void 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 | |||
207 | static 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 | ||
146 | void linkwatch_fire_event(struct net_device *dev) | 215 | void 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 | ||
181 | EXPORT_SYMBOL(linkwatch_fire_event); | 229 | EXPORT_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. */ | ||
19 | struct arpt_standard | ||
20 | { | ||
21 | struct arpt_entry entry; | ||
22 | struct arpt_standard_target target; | ||
23 | }; | ||
24 | |||
25 | struct arpt_error_target | ||
26 | { | ||
27 | struct arpt_entry_target target; | ||
28 | char errorname[ARPT_FUNCTION_MAXNAMELEN]; | ||
29 | }; | ||
30 | |||
31 | struct arpt_error | ||
32 | { | ||
33 | struct arpt_entry entry; | ||
34 | struct arpt_error_target target; | ||
35 | }; | ||
36 | |||
37 | static struct | 18 | static 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 | ||
142 | static struct arpt_table packet_filter = { | 48 | static 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 | ||
78 | static struct xt_table packet_filter = { | 54 | static 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 | ||
105 | static struct xt_table packet_mangler = { | 67 | static 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 | ||
82 | static struct xt_table packet_raw = { | 39 | static 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 | ||
58 | static unsigned int | ||
59 | ipt_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. */ |
102 | static struct nf_hook_ops ipt_ops[] = { | 77 | static 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 | ||
122 | static struct xt_table nat_table = { | 65 | static struct xt_table nat_table = { |
@@ -230,9 +173,7 @@ static int ipt_dnat_checkentry(const char *tablename, | |||
230 | } | 173 | } |
231 | 174 | ||
232 | inline unsigned int | 175 | inline unsigned int |
233 | alloc_null_binding(struct nf_conn *ct, | 176 | alloc_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 | ||
253 | unsigned int | 194 | unsigned int |
254 | alloc_null_binding_confirmed(struct nf_conn *ct, | 195 | alloc_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 | */ |
121 | static inline unsigned int hash_port_and_addr(__u16 port, __be32 addr) | 121 | static 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 | ||
128 | static inline int __udp_lib_port_inuse(unsigned int hash, int port, | 126 | static 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 | */ |
156 | int __udp_lib_get_port(struct sock *sk, unsigned short snum, | 159 | int __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, | |||
221 | gotit: | 221 | gotit: |
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 | ||
268 | int udp_get_port(struct sock *sk, unsigned short snum, | 267 | int 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 | ||
274 | int ipv4_rcv_saddr_equal(const struct sock *sk1, const struct sock *sk2) | 273 | static 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 | ||
282 | static int ipv4_rcv_saddr_any(const struct sock *sk) | ||
283 | { | ||
284 | return !inet_sk(sk)->rcv_saddr; | ||
285 | } | ||
286 | |||
287 | static 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 | |||
294 | static 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 | |||
300 | const 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 | |||
283 | static inline int udp_v4_get_port(struct sock *sk, unsigned short snum) | 306 | static 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 | ||
8 | extern const struct udp_get_port_ops udp_ipv4_ops; | ||
9 | |||
8 | extern int __udp4_lib_rcv(struct sk_buff *, struct hlist_head [], int ); | 10 | extern int __udp4_lib_rcv(struct sk_buff *, struct hlist_head [], int ); |
9 | extern void __udp4_lib_err(struct sk_buff *, u32, struct hlist_head []); | 11 | extern void __udp4_lib_err(struct sk_buff *, u32, struct hlist_head []); |
10 | 12 | ||
11 | extern int __udp_lib_get_port(struct sock *sk, unsigned short snum, | 13 | extern 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); |
14 | extern int ipv4_rcv_saddr_equal(const struct sock *, const struct sock *); | ||
15 | |||
16 | 16 | ||
17 | extern int udp_setsockopt(struct sock *sk, int level, int optname, | 17 | extern 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]; | |||
19 | static int udplite_port_rover; | 19 | static int udplite_port_rover; |
20 | 20 | ||
21 | int udplite_get_port(struct sock *sk, unsigned short p, | 21 | int 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 | ||
27 | static int udplite_v4_get_port(struct sock *sk, unsigned short snum) | 28 | static 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 | ||
32 | static int udplite_rcv(struct sk_buff *skb) | 33 | static 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 | */ | ||
666 | static 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 | ||
665 | static int ipv6_hop_ra(struct sk_buff **skbp, int optoff) | 673 | static 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 | ||
76 | static struct xt_table packet_filter = { | 52 | static 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 | ||
104 | static struct xt_table packet_mangler = { | 66 | static 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 | ||
90 | static struct xt_table packet_raw = { | 44 | static 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 | ||
53 | DEFINE_SNMP_STAT(struct udp_mib, udp_stats_in6) __read_mostly; | 53 | DEFINE_SNMP_STAT(struct udp_mib, udp_stats_in6) __read_mostly; |
54 | 54 | ||
55 | static 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 | |||
62 | static unsigned int ipv6_hash_port_and_rcv_saddr(__u16 port, | ||
63 | const struct sock *sk) | ||
64 | { | ||
65 | return port; | ||
66 | } | ||
67 | |||
68 | const 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 | |||
55 | static inline int udp_v6_get_port(struct sock *sk, unsigned short snum) | 74 | static 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 | ||
60 | static struct sock *__udp6_lib_lookup(struct in6_addr *saddr, __be16 sport, | 79 | static 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 | ||
9 | extern const struct udp_get_port_ops udp_ipv6_ops; | ||
10 | |||
9 | extern int __udp6_lib_rcv(struct sk_buff **, struct hlist_head [], int ); | 11 | extern int __udp6_lib_rcv(struct sk_buff **, struct hlist_head [], int ); |
10 | extern void __udp6_lib_err(struct sk_buff *, struct inet6_skb_parm *, | 12 | extern 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 | ||
38 | static int udplite_v6_get_port(struct sock *sk, unsigned short snum) | 38 | static 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 | ||
43 | struct proto udplitev6_prot = { | 43 | struct 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 | } |
900 | EXPORT_SYMBOL_GPL(nf_conntrack_alter_reply); | 900 | EXPORT_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 | ||
138 | struct 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 | |||
151 | static 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 | |||
168 | static 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 | |||
137 | static struct xt_match conntrack_match = { | 186 | static 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 | ||
165 | requeue: | 164 | requeue: |
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 | |||
175 | out: | ||
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 | ||
177 | void __qdisc_run(struct net_device *dev) | 180 | void __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 | ||
185 | out: | ||
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) | |||
544 | void dev_deactivate(struct net_device *dev) | 545 | void 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 | ||
571 | void dev_init_scheduler(struct net_device *dev) | 572 | void 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); |