aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/char/random.c1
-rw-r--r--drivers/net/irda/irda-usb.c363
-rw-r--r--drivers/net/irda/irda-usb.h43
-rw-r--r--drivers/net/irda/smsc-ircc2.c311
-rw-r--r--drivers/net/netconsole.c1
-rw-r--r--drivers/net/tg3.c100
-rw-r--r--drivers/net/tg3.h3
-rw-r--r--include/linux/netfilter.h42
-rw-r--r--include/linux/netfilter_ipv4.h2
-rw-r--r--include/linux/netfilter_ipv4/ip_conntrack_h323.h52
-rw-r--r--include/linux/netfilter_ipv4/ip_conntrack_helper_h323_asn1.h (renamed from net/ipv4/netfilter/ip_conntrack_helper_h323_asn1.h)0
-rw-r--r--include/linux/netfilter_ipv4/ip_conntrack_helper_h323_types.h (renamed from net/ipv4/netfilter/ip_conntrack_helper_h323_types.h)0
-rw-r--r--include/linux/netfilter_ipv6.h3
-rw-r--r--include/net/inet6_hashtables.h70
-rw-r--r--include/net/ip.h1
-rw-r--r--include/net/x25device.h1
-rw-r--r--net/bluetooth/sco.c2
-rw-r--r--net/bridge/br_netfilter.c13
-rw-r--r--net/core/dev.c5
-rw-r--r--net/core/dv.c5
-rw-r--r--net/core/flow.c4
-rw-r--r--net/core/gen_estimator.c3
-rw-r--r--net/core/neighbour.c14
-rw-r--r--net/core/net-sysfs.c2
-rw-r--r--net/core/request_sock.c4
-rw-r--r--net/ipv4/fib_trie.c14
-rw-r--r--net/ipv4/ip_fragment.c15
-rw-r--r--net/ipv4/ip_gre.c2
-rw-r--r--net/ipv4/ip_output.c6
-rw-r--r--net/ipv4/ipip.c4
-rw-r--r--net/ipv4/netfilter.c50
-rw-r--r--net/ipv4/netfilter/Kconfig1
-rw-r--r--net/ipv4/netfilter/arptable_filter.c19
-rw-r--r--net/ipv4/netfilter/ip_conntrack_helper_h323.c66
-rw-r--r--net/ipv4/netfilter/ip_conntrack_helper_h323_asn1.c2
-rw-r--r--net/ipv4/netfilter/ip_conntrack_proto_icmp.c23
-rw-r--r--net/ipv4/netfilter/ip_conntrack_proto_tcp.c7
-rw-r--r--net/ipv4/netfilter/ip_conntrack_proto_udp.c7
-rw-r--r--net/ipv4/netfilter/ip_conntrack_standalone.c268
-rw-r--r--net/ipv4/netfilter/ip_nat_helper_h323.c71
-rw-r--r--net/ipv4/netfilter/ip_nat_rule.c2
-rw-r--r--net/ipv4/netfilter/ip_nat_standalone.c159
-rw-r--r--net/ipv4/netfilter/ip_queue.c31
-rw-r--r--net/ipv4/netfilter/ipt_CLUSTERIP.c40
-rw-r--r--net/ipv4/netfilter/ipt_REJECT.c9
-rw-r--r--net/ipv4/netfilter/iptable_filter.c21
-rw-r--r--net/ipv4/netfilter/iptable_mangle.c33
-rw-r--r--net/ipv4/netfilter/iptable_raw.c35
-rw-r--r--net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c223
-rw-r--r--net/ipv4/netfilter/nf_conntrack_proto_icmp.c20
-rw-r--r--net/ipv4/tunnel4.c8
-rw-r--r--net/ipv4/xfrm4_input.c4
-rw-r--r--net/ipv6/inet6_hashtables.c80
-rw-r--r--net/ipv6/ip6_tunnel.c12
-rw-r--r--net/ipv6/netfilter.c52
-rw-r--r--net/ipv6/netfilter/ip6_queue.c31
-rw-r--r--net/ipv6/netfilter/ip6table_filter.c21
-rw-r--r--net/ipv6/netfilter/ip6table_mangle.c33
-rw-r--r--net/ipv6/netfilter/ip6table_raw.c15
-rw-r--r--net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c179
-rw-r--r--net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c12
-rw-r--r--net/ipv6/sit.c2
-rw-r--r--net/ipv6/tunnel6.c8
-rw-r--r--net/netfilter/core.c51
-rw-r--r--net/netfilter/nf_conntrack_proto_tcp.c50
-rw-r--r--net/netfilter/nf_conntrack_proto_udp.c50
-rw-r--r--net/netfilter/nf_conntrack_standalone.c115
-rw-r--r--net/netfilter/nf_queue.c49
-rw-r--r--net/netfilter/nfnetlink_log.c25
-rw-r--r--net/netfilter/nfnetlink_queue.c27
-rw-r--r--net/sched/act_police.c8
71 files changed, 1638 insertions, 1367 deletions
diff --git a/drivers/char/random.c b/drivers/char/random.c
index 86be04b241e1..58f3512c52e1 100644
--- a/drivers/char/random.c
+++ b/drivers/char/random.c
@@ -1584,7 +1584,6 @@ u32 secure_ipv6_port_ephemeral(const __u32 *saddr, const __u32 *daddr, __u16 dpo
1584 1584
1585 return twothirdsMD4Transform(daddr, hash); 1585 return twothirdsMD4Transform(daddr, hash);
1586} 1586}
1587EXPORT_SYMBOL(secure_ipv6_port_ephemeral);
1588#endif 1587#endif
1589 1588
1590#if defined(CONFIG_IP_DCCP) || defined(CONFIG_IP_DCCP_MODULE) 1589#if defined(CONFIG_IP_DCCP) || defined(CONFIG_IP_DCCP_MODULE)
diff --git a/drivers/net/irda/irda-usb.c b/drivers/net/irda/irda-usb.c
index 6e2ec56cde0b..606243d11793 100644
--- a/drivers/net/irda/irda-usb.c
+++ b/drivers/net/irda/irda-usb.c
@@ -1,7 +1,7 @@
1/***************************************************************************** 1/*****************************************************************************
2 * 2 *
3 * Filename: irda-usb.c 3 * Filename: irda-usb.c
4 * Version: 0.9b 4 * Version: 0.10
5 * Description: IrDA-USB Driver 5 * Description: IrDA-USB Driver
6 * Status: Experimental 6 * Status: Experimental
7 * Author: Dag Brattli <dag@brattli.net> 7 * Author: Dag Brattli <dag@brattli.net>
@@ -9,6 +9,9 @@
9 * Copyright (C) 2000, Roman Weissgaerber <weissg@vienna.at> 9 * Copyright (C) 2000, Roman Weissgaerber <weissg@vienna.at>
10 * Copyright (C) 2001, Dag Brattli <dag@brattli.net> 10 * Copyright (C) 2001, Dag Brattli <dag@brattli.net>
11 * Copyright (C) 2001, Jean Tourrilhes <jt@hpl.hp.com> 11 * Copyright (C) 2001, Jean Tourrilhes <jt@hpl.hp.com>
12 * Copyright (C) 2004, SigmaTel, Inc. <irquality@sigmatel.com>
13 * Copyright (C) 2005, Milan Beno <beno@pobox.sk>
14 * Copyright (C) 2006, Nick Fedchik <nick@fedchik.org.ua>
12 * 15 *
13 * This program is free software; you can redistribute it and/or modify 16 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by 17 * it under the terms of the GNU General Public License as published by
@@ -61,6 +64,7 @@
61#include <linux/slab.h> 64#include <linux/slab.h>
62#include <linux/rtnetlink.h> 65#include <linux/rtnetlink.h>
63#include <linux/usb.h> 66#include <linux/usb.h>
67#include <linux/firmware.h>
64 68
65#include "irda-usb.h" 69#include "irda-usb.h"
66 70
@@ -78,8 +82,12 @@ static struct usb_device_id dongles[] = {
78 { USB_DEVICE(0x50f, 0x180), .driver_info = IUC_SPEED_BUG | IUC_NO_WINDOW }, 82 { USB_DEVICE(0x50f, 0x180), .driver_info = IUC_SPEED_BUG | IUC_NO_WINDOW },
79 /* Extended Systems, Inc., XTNDAccess IrDA USB (ESI-9685) */ 83 /* Extended Systems, Inc., XTNDAccess IrDA USB (ESI-9685) */
80 { USB_DEVICE(0x8e9, 0x100), .driver_info = IUC_SPEED_BUG | IUC_NO_WINDOW }, 84 { USB_DEVICE(0x8e9, 0x100), .driver_info = IUC_SPEED_BUG | IUC_NO_WINDOW },
85 /* SigmaTel STIR4210/4220/4116 USB IrDA (VFIR) Bridge */
86 { USB_DEVICE(0x66f, 0x4210), .driver_info = IUC_STIR_4210 | IUC_SPEED_BUG },
87 { USB_DEVICE(0x66f, 0x4220), .driver_info = IUC_STIR_4210 | IUC_SPEED_BUG },
88 { USB_DEVICE(0x66f, 0x4116), .driver_info = IUC_STIR_4210 | IUC_SPEED_BUG },
81 { .match_flags = USB_DEVICE_ID_MATCH_INT_CLASS | 89 { .match_flags = USB_DEVICE_ID_MATCH_INT_CLASS |
82 USB_DEVICE_ID_MATCH_INT_SUBCLASS, 90 USB_DEVICE_ID_MATCH_INT_SUBCLASS,
83 .bInterfaceClass = USB_CLASS_APP_SPEC, 91 .bInterfaceClass = USB_CLASS_APP_SPEC,
84 .bInterfaceSubClass = USB_CLASS_IRDA, 92 .bInterfaceSubClass = USB_CLASS_IRDA,
85 .driver_info = IUC_DEFAULT, }, 93 .driver_info = IUC_DEFAULT, },
@@ -99,6 +107,7 @@ MODULE_DEVICE_TABLE(usb, dongles);
99 107
100/*------------------------------------------------------------------*/ 108/*------------------------------------------------------------------*/
101 109
110static void irda_usb_init_qos(struct irda_usb_cb *self) ;
102static struct irda_class_desc *irda_usb_find_class_desc(struct usb_interface *intf); 111static struct irda_class_desc *irda_usb_find_class_desc(struct usb_interface *intf);
103static void irda_usb_disconnect(struct usb_interface *intf); 112static void irda_usb_disconnect(struct usb_interface *intf);
104static void irda_usb_change_speed_xbofs(struct irda_usb_cb *self); 113static void irda_usb_change_speed_xbofs(struct irda_usb_cb *self);
@@ -141,7 +150,24 @@ static void irda_usb_build_header(struct irda_usb_cb *self,
141 __u8 *header, 150 __u8 *header,
142 int force) 151 int force)
143{ 152{
144 /* Set the negotiated link speed */ 153 /* Here we check if we have an STIR421x chip,
154 * and if either speed or xbofs (or both) needs
155 * to be changed.
156 */
157 if (self->capability & IUC_STIR_4210 &&
158 ((self->new_speed != -1) || (self->new_xbofs != -1))) {
159
160 /* With STIR421x, speed and xBOFs must be set at the same
161 * time, even if only one of them changes.
162 */
163 if (self->new_speed == -1)
164 self->new_speed = self->speed ;
165
166 if (self->new_xbofs == -1)
167 self->new_xbofs = self->xbofs ;
168 }
169
170 /* Set the link speed */
145 if (self->new_speed != -1) { 171 if (self->new_speed != -1) {
146 /* Hum... Ugly hack :-( 172 /* Hum... Ugly hack :-(
147 * Some device are not compliant with the spec and change 173 * Some device are not compliant with the spec and change
@@ -191,7 +217,11 @@ static void irda_usb_build_header(struct irda_usb_cb *self,
191 *header = SPEED_4000000; 217 *header = SPEED_4000000;
192 self->new_xbofs = 0; 218 self->new_xbofs = 0;
193 break; 219 break;
194 } 220 case 16000000:
221 *header = SPEED_16000000;
222 self->new_xbofs = 0;
223 break;
224 }
195 } else 225 } else
196 /* No change */ 226 /* No change */
197 *header = 0; 227 *header = 0;
@@ -235,6 +265,32 @@ static void irda_usb_build_header(struct irda_usb_cb *self,
235 } 265 }
236} 266}
237 267
268/*
269* calculate turnaround time for SigmaTel header
270*/
271static __u8 get_turnaround_time(struct sk_buff *skb)
272{
273 int turnaround_time = irda_get_mtt(skb);
274
275 if ( turnaround_time == 0 )
276 return 0;
277 else if ( turnaround_time <= 10 )
278 return 1;
279 else if ( turnaround_time <= 50 )
280 return 2;
281 else if ( turnaround_time <= 100 )
282 return 3;
283 else if ( turnaround_time <= 500 )
284 return 4;
285 else if ( turnaround_time <= 1000 )
286 return 5;
287 else if ( turnaround_time <= 5000 )
288 return 6;
289 else
290 return 7;
291}
292
293
238/*------------------------------------------------------------------*/ 294/*------------------------------------------------------------------*/
239/* 295/*
240 * Send a command to change the speed of the dongle 296 * Send a command to change the speed of the dongle
@@ -262,12 +318,18 @@ static void irda_usb_change_speed_xbofs(struct irda_usb_cb *self)
262 /* Set the new speed and xbofs in this fake frame */ 318 /* Set the new speed and xbofs in this fake frame */
263 irda_usb_build_header(self, frame, 1); 319 irda_usb_build_header(self, frame, 1);
264 320
321 if ( self->capability & IUC_STIR_4210 ) {
322 if (frame[0] == 0) return ; // do nothing if no change
323 frame[1] = 0; // other parameters don't change here
324 frame[2] = 0;
325 }
326
265 /* Submit the 0 length IrDA frame to trigger new speed settings */ 327 /* Submit the 0 length IrDA frame to trigger new speed settings */
266 usb_fill_bulk_urb(urb, self->usbdev, 328 usb_fill_bulk_urb(urb, self->usbdev,
267 usb_sndbulkpipe(self->usbdev, self->bulk_out_ep), 329 usb_sndbulkpipe(self->usbdev, self->bulk_out_ep),
268 frame, IRDA_USB_SPEED_MTU, 330 frame, IRDA_USB_SPEED_MTU,
269 speed_bulk_callback, self); 331 speed_bulk_callback, self);
270 urb->transfer_buffer_length = USB_IRDA_HEADER; 332 urb->transfer_buffer_length = self->header_length;
271 urb->transfer_flags = 0; 333 urb->transfer_flags = 0;
272 334
273 /* Irq disabled -> GFP_ATOMIC */ 335 /* Irq disabled -> GFP_ATOMIC */
@@ -383,16 +445,35 @@ static int irda_usb_hard_xmit(struct sk_buff *skb, struct net_device *netdev)
383 * allocation will be done lower in skb_push(). 445 * allocation will be done lower in skb_push().
384 * Also, we don't use directly skb_cow(), because it require 446 * Also, we don't use directly skb_cow(), because it require
385 * headroom >= 16, which force unnecessary copies - Jean II */ 447 * headroom >= 16, which force unnecessary copies - Jean II */
386 if (skb_headroom(skb) < USB_IRDA_HEADER) { 448 if (skb_headroom(skb) < self->header_length) {
387 IRDA_DEBUG(0, "%s(), Insuficient skb headroom.\n", __FUNCTION__); 449 IRDA_DEBUG(0, "%s(), Insuficient skb headroom.\n", __FUNCTION__);
388 if (skb_cow(skb, USB_IRDA_HEADER)) { 450 if (skb_cow(skb, self->header_length)) {
389 IRDA_WARNING("%s(), failed skb_cow() !!!\n", __FUNCTION__); 451 IRDA_WARNING("%s(), failed skb_cow() !!!\n", __FUNCTION__);
390 goto drop; 452 goto drop;
391 } 453 }
392 } 454 }
393 455
394 /* Change setting for next frame */ 456 /* Change setting for next frame */
395 irda_usb_build_header(self, skb_push(skb, USB_IRDA_HEADER), 0); 457
458 if ( self->capability & IUC_STIR_4210 ) {
459 __u8 turnaround_time;
460 __u8* frame;
461 turnaround_time = get_turnaround_time( skb );
462 frame= skb_push(skb, self->header_length);
463 irda_usb_build_header(self, frame, 0);
464 frame[2] = turnaround_time;
465 if ((skb->len != 0) &&
466 ((skb->len % 128) == 0) &&
467 ((skb->len % 512) != 0)) {
468 /* add extra byte for special SigmaTel feature */
469 frame[1] = 1;
470 skb_put(skb, 1);
471 } else {
472 frame[1] = 0;
473 }
474 } else {
475 irda_usb_build_header(self, skb_push(skb, self->header_length), 0);
476 }
396 477
397 /* FIXME: Make macro out of this one */ 478 /* FIXME: Make macro out of this one */
398 ((struct irda_skb_cb *)skb->cb)->context = self; 479 ((struct irda_skb_cb *)skb->cb)->context = self;
@@ -795,7 +876,7 @@ static void irda_usb_receive(struct urb *urb, struct pt_regs *regs)
795 } 876 }
796 877
797 /* Check for empty frames */ 878 /* Check for empty frames */
798 if (urb->actual_length <= USB_IRDA_HEADER) { 879 if (urb->actual_length <= self->header_length) {
799 IRDA_WARNING("%s(), empty frame!\n", __FUNCTION__); 880 IRDA_WARNING("%s(), empty frame!\n", __FUNCTION__);
800 goto done; 881 goto done;
801 } 882 }
@@ -816,7 +897,11 @@ static void irda_usb_receive(struct urb *urb, struct pt_regs *regs)
816 docopy = (urb->actual_length < IRDA_RX_COPY_THRESHOLD); 897 docopy = (urb->actual_length < IRDA_RX_COPY_THRESHOLD);
817 898
818 /* Allocate a new skb */ 899 /* Allocate a new skb */
819 newskb = dev_alloc_skb(docopy ? urb->actual_length : IRDA_SKB_MAX_MTU); 900 if ( self->capability & IUC_STIR_4210 )
901 newskb = dev_alloc_skb(docopy ? urb->actual_length : IRDA_SKB_MAX_MTU + USB_IRDA_SIGMATEL_HEADER);
902 else
903 newskb = dev_alloc_skb(docopy ? urb->actual_length : IRDA_SKB_MAX_MTU);
904
820 if (!newskb) { 905 if (!newskb) {
821 self->stats.rx_dropped++; 906 self->stats.rx_dropped++;
822 /* We could deliver the current skb, but this would stall 907 /* We could deliver the current skb, but this would stall
@@ -845,7 +930,7 @@ static void irda_usb_receive(struct urb *urb, struct pt_regs *regs)
845 930
846 /* Set proper length on skb & remove USB-IrDA header */ 931 /* Set proper length on skb & remove USB-IrDA header */
847 skb_put(dataskb, urb->actual_length); 932 skb_put(dataskb, urb->actual_length);
848 skb_pull(dataskb, USB_IRDA_HEADER); 933 skb_pull(dataskb, self->header_length);
849 934
850 /* Ask the networking layer to queue the packet for the IrDA stack */ 935 /* Ask the networking layer to queue the packet for the IrDA stack */
851 dataskb->dev = self->netdev; 936 dataskb->dev = self->netdev;
@@ -937,6 +1022,191 @@ static int irda_usb_is_receiving(struct irda_usb_cb *self)
937 return 0; /* For now */ 1022 return 0; /* For now */
938} 1023}
939 1024
1025
1026#define STIR421X_PATCH_PRODUCT_VERSION_STR "Product Version: "
1027#define STIR421X_PATCH_COMPONENT_VERSION_STR "Component Version: "
1028#define STIR421X_PATCH_DATA_TAG_STR "STMP"
1029#define STIR421X_PATCH_FILE_VERSION_MAX_OFFSET 512 /* version info is before here */
1030#define STIR421X_PATCH_FILE_IMAGE_MAX_OFFSET 512 /* patch image starts before here */
1031#define STIR421X_PATCH_FILE_END_OF_HEADER_TAG 0x1A /* marks end of patch file header (PC DOS text file EOF character) */
1032
1033/*
1034 * Known firmware patches for STIR421x dongles
1035 */
1036static char * stir421x_patches[] = {
1037 "42101001.sb",
1038 "42101002.sb",
1039};
1040
1041static int stir421x_get_patch_version(unsigned char * patch, const unsigned long patch_len)
1042{
1043 unsigned int version_offset;
1044 unsigned long version_major, version_minor, version_build;
1045 unsigned char * version_start;
1046 int version_found = 0;
1047
1048 for (version_offset = 0;
1049 version_offset < STIR421X_PATCH_FILE_END_OF_HEADER_TAG;
1050 version_offset++) {
1051 if (!memcmp(patch + version_offset,
1052 STIR421X_PATCH_PRODUCT_VERSION_STR,
1053 sizeof(STIR421X_PATCH_PRODUCT_VERSION_STR) - 1)) {
1054 version_found = 1;
1055 version_start = patch +
1056 version_offset +
1057 sizeof(STIR421X_PATCH_PRODUCT_VERSION_STR) - 1;
1058 break;
1059 }
1060 }
1061
1062 /* We couldn't find a product version on this patch */
1063 if (!version_found)
1064 return -EINVAL;
1065
1066 /* Let's check if the product version is dotted */
1067 if (version_start[3] != '.' ||
1068 version_start[7] != '.')
1069 return -EINVAL;
1070
1071 version_major = simple_strtoul(version_start, NULL, 10);
1072 version_minor = simple_strtoul(version_start + 4, NULL, 10);
1073 version_build = simple_strtoul(version_start + 8, NULL, 10);
1074
1075 IRDA_DEBUG(2, "%s(), Major: %ld Minor: %ld Build: %ld\n",
1076 __FUNCTION__,
1077 version_major, version_minor, version_build);
1078
1079 return (((version_major) << 12) +
1080 ((version_minor) << 8) +
1081 ((version_build / 10) << 4) +
1082 (version_build % 10));
1083
1084}
1085
1086
1087static int stir421x_upload_patch (struct irda_usb_cb *self,
1088 unsigned char * patch,
1089 const unsigned int patch_len)
1090{
1091 int retval = 0;
1092 int actual_len;
1093 unsigned int i = 0, download_amount = 0;
1094 unsigned char * patch_chunk;
1095
1096 IRDA_DEBUG (2, "%s(), Uploading STIR421x Patch\n", __FUNCTION__);
1097
1098 patch_chunk = kzalloc(STIR421X_MAX_PATCH_DOWNLOAD_SIZE, GFP_KERNEL);
1099 if (patch_chunk == NULL)
1100 return -ENOMEM;
1101
1102 /* break up patch into 1023-byte sections */
1103 for (i = 0; retval >= 0 && i < patch_len; i += download_amount) {
1104 download_amount = patch_len - i;
1105 if (download_amount > STIR421X_MAX_PATCH_DOWNLOAD_SIZE)
1106 download_amount = STIR421X_MAX_PATCH_DOWNLOAD_SIZE;
1107
1108 /* download the patch section */
1109 memcpy(patch_chunk, patch + i, download_amount);
1110
1111 retval = usb_bulk_msg (self->usbdev,
1112 usb_sndbulkpipe (self->usbdev,
1113 self->bulk_out_ep),
1114 patch_chunk, download_amount,
1115 &actual_len, msecs_to_jiffies (500));
1116 IRDA_DEBUG (2, "%s(), Sent %u bytes\n", __FUNCTION__,
1117 actual_len);
1118 if (retval == 0)
1119 mdelay(10);
1120 }
1121
1122 kfree(patch_chunk);
1123
1124 if (i != patch_len) {
1125 IRDA_ERROR ("%s(), Pushed %d bytes (!= patch_len (%d))\n",
1126 __FUNCTION__, i, patch_len);
1127 retval = -EIO;
1128 }
1129
1130 if (retval < 0)
1131 /* todo - mark device as not ready */
1132 IRDA_ERROR ("%s(), STIR421x patch upload failed (%d)\n",
1133 __FUNCTION__, retval);
1134
1135 return retval;
1136}
1137
1138
1139static int stir421x_patch_device(struct irda_usb_cb *self)
1140{
1141 unsigned int i, patch_found = 0, data_found = 0, data_offset;
1142 int patch_version, ret = 0;
1143 const struct firmware *fw_entry;
1144
1145 for (i = 0; i < ARRAY_SIZE(stir421x_patches); i++) {
1146 if(request_firmware(&fw_entry, stir421x_patches[i], &self->usbdev->dev) != 0) {
1147 IRDA_ERROR( "%s(), Patch %s is not available\n", __FUNCTION__, stir421x_patches[i]);
1148 continue;
1149 }
1150
1151 /* We found a patch from userspace */
1152 patch_version = stir421x_get_patch_version (fw_entry->data, fw_entry->size);
1153
1154 if (patch_version < 0) {
1155 /* Couldn't fetch a version, let's move on to the next file */
1156 IRDA_ERROR("%s(), version parsing failed\n", __FUNCTION__);
1157 ret = patch_version;
1158 release_firmware(fw_entry);
1159 continue;
1160 }
1161
1162 if (patch_version != self->usbdev->descriptor.bcdDevice) {
1163 /* Patch version and device don't match */
1164 IRDA_ERROR ("%s(), wrong patch version (%d <-> %d)\n",
1165 __FUNCTION__,
1166 patch_version, self->usbdev->descriptor.bcdDevice);
1167 ret = -EINVAL;
1168 release_firmware(fw_entry);
1169 continue;
1170 }
1171
1172 /* If we're here, we've found a correct patch */
1173 patch_found = 1;
1174 break;
1175
1176 }
1177
1178 /* We couldn't find a valid firmware, let's leave */
1179 if (!patch_found)
1180 return ret;
1181
1182 /* The actual image starts after the "STMP" keyword */
1183 for (data_offset = 0; data_offset < STIR421X_PATCH_FILE_IMAGE_MAX_OFFSET; data_offset++) {
1184 if (!memcmp(fw_entry->data + data_offset,
1185 STIR421X_PATCH_DATA_TAG_STR,
1186 sizeof(STIR421X_PATCH_FILE_IMAGE_MAX_OFFSET))) {
1187 IRDA_DEBUG(2, "%s(), found patch data for STIR421x at offset %d\n",
1188 __FUNCTION__, data_offset);
1189 data_found = 1;
1190 break;
1191 }
1192 }
1193
1194 /* We couldn't find "STMP" from the header */
1195 if (!data_found)
1196 return -EINVAL;
1197
1198 /* Let's upload the patch to the target */
1199 ret = stir421x_upload_patch(self,
1200 &fw_entry->data[data_offset + sizeof(STIR421X_PATCH_FILE_IMAGE_MAX_OFFSET)],
1201 fw_entry->size - (data_offset + sizeof(STIR421X_PATCH_FILE_IMAGE_MAX_OFFSET)));
1202
1203 release_firmware(fw_entry);
1204
1205 return ret;
1206
1207}
1208
1209
940/********************** IRDA DEVICE CALLBACKS **********************/ 1210/********************** IRDA DEVICE CALLBACKS **********************/
941/* 1211/*
942 * Main calls from the IrDA/Network subsystem. 1212 * Main calls from the IrDA/Network subsystem.
@@ -972,6 +1242,11 @@ static int irda_usb_net_open(struct net_device *netdev)
972 return -1; 1242 return -1;
973 } 1243 }
974 1244
1245 if(self->needspatch) {
1246 IRDA_WARNING("%s(), device needs patch\n", __FUNCTION__) ;
1247 return -EIO ;
1248 }
1249
975 /* Initialise default speed and xbofs value 1250 /* Initialise default speed and xbofs value
976 * (IrLAP will change that soon) */ 1251 * (IrLAP will change that soon) */
977 self->speed = -1; 1252 self->speed = -1;
@@ -1050,7 +1325,7 @@ static int irda_usb_net_close(struct net_device *netdev)
1050 del_timer(&self->rx_defer_timer); 1325 del_timer(&self->rx_defer_timer);
1051 1326
1052 /* Deallocate all the Rx path buffers (URBs and skb) */ 1327 /* Deallocate all the Rx path buffers (URBs and skb) */
1053 for (i = 0; i < IU_MAX_RX_URBS; i++) { 1328 for (i = 0; i < self->max_rx_urb; i++) {
1054 struct urb *urb = self->rx_urb[i]; 1329 struct urb *urb = self->rx_urb[i];
1055 struct sk_buff *skb = (struct sk_buff *) urb->context; 1330 struct sk_buff *skb = (struct sk_buff *) urb->context;
1056 /* Cancel the receive command */ 1331 /* Cancel the receive command */
@@ -1426,8 +1701,22 @@ static int irda_usb_probe(struct usb_interface *intf,
1426 spin_lock_init(&self->lock); 1701 spin_lock_init(&self->lock);
1427 init_timer(&self->rx_defer_timer); 1702 init_timer(&self->rx_defer_timer);
1428 1703
1704 self->capability = id->driver_info;
1705 self->needspatch = ((self->capability & IUC_STIR_4210) != 0) ;
1706
1429 /* Create all of the needed urbs */ 1707 /* Create all of the needed urbs */
1430 for (i = 0; i < IU_MAX_RX_URBS; i++) { 1708 if (self->capability & IUC_STIR_4210) {
1709 self->max_rx_urb = IU_SIGMATEL_MAX_RX_URBS;
1710 self->header_length = USB_IRDA_SIGMATEL_HEADER;
1711 } else {
1712 self->max_rx_urb = IU_MAX_RX_URBS;
1713 self->header_length = USB_IRDA_HEADER;
1714 }
1715
1716 self->rx_urb = kzalloc(self->max_rx_urb * sizeof(struct urb *),
1717 GFP_KERNEL);
1718
1719 for (i = 0; i < self->max_rx_urb; i++) {
1431 self->rx_urb[i] = usb_alloc_urb(0, GFP_KERNEL); 1720 self->rx_urb[i] = usb_alloc_urb(0, GFP_KERNEL);
1432 if (!self->rx_urb[i]) { 1721 if (!self->rx_urb[i]) {
1433 goto err_out_1; 1722 goto err_out_1;
@@ -1479,17 +1768,28 @@ static int irda_usb_probe(struct usb_interface *intf,
1479 goto err_out_3; 1768 goto err_out_3;
1480 } 1769 }
1481 1770
1771 self->usbdev = dev;
1772
1482 /* Find IrDA class descriptor */ 1773 /* Find IrDA class descriptor */
1483 irda_desc = irda_usb_find_class_desc(intf); 1774 irda_desc = irda_usb_find_class_desc(intf);
1484 ret = -ENODEV; 1775 ret = -ENODEV;
1485 if (irda_desc == NULL) 1776 if (irda_desc == NULL)
1486 goto err_out_3; 1777 goto err_out_3;
1487 1778
1779 if (self->needspatch) {
1780 ret = usb_control_msg (self->usbdev, usb_sndctrlpipe (self->usbdev, 0),
1781 0x02, 0x40, 0, 0, 0, 0, msecs_to_jiffies(500));
1782 if (ret < 0) {
1783 IRDA_DEBUG (0, "usb_control_msg failed %d\n", ret);
1784 goto err_out_3;
1785 } else {
1786 mdelay(10);
1787 }
1788 }
1789
1488 self->irda_desc = irda_desc; 1790 self->irda_desc = irda_desc;
1489 self->present = 1; 1791 self->present = 1;
1490 self->netopen = 0; 1792 self->netopen = 0;
1491 self->capability = id->driver_info;
1492 self->usbdev = dev;
1493 self->usbintf = intf; 1793 self->usbintf = intf;
1494 1794
1495 /* Allocate the buffer for speed changes */ 1795 /* Allocate the buffer for speed changes */
@@ -1508,6 +1808,28 @@ static int irda_usb_probe(struct usb_interface *intf,
1508 1808
1509 IRDA_MESSAGE("IrDA: Registered device %s\n", net->name); 1809 IRDA_MESSAGE("IrDA: Registered device %s\n", net->name);
1510 usb_set_intfdata(intf, self); 1810 usb_set_intfdata(intf, self);
1811
1812 if (self->needspatch) {
1813 /* Now we fetch and upload the firmware patch */
1814 ret = stir421x_patch_device(self);
1815 self->needspatch = (ret < 0);
1816 if (ret < 0) {
1817 printk("patch_device failed\n");
1818 goto err_out_4;
1819 }
1820
1821 /* replace IrDA class descriptor with what patched device is now reporting */
1822 irda_desc = irda_usb_find_class_desc (self->usbintf);
1823 if (irda_desc == NULL) {
1824 ret = -ENODEV;
1825 goto err_out_4;
1826 }
1827 if (self->irda_desc)
1828 kfree (self->irda_desc);
1829 self->irda_desc = irda_desc;
1830 irda_usb_init_qos(self);
1831 }
1832
1511 return 0; 1833 return 0;
1512 1834
1513err_out_4: 1835err_out_4:
@@ -1518,7 +1840,7 @@ err_out_3:
1518err_out_2: 1840err_out_2:
1519 usb_free_urb(self->tx_urb); 1841 usb_free_urb(self->tx_urb);
1520err_out_1: 1842err_out_1:
1521 for (i = 0; i < IU_MAX_RX_URBS; i++) { 1843 for (i = 0; i < self->max_rx_urb; i++) {
1522 if (self->rx_urb[i]) 1844 if (self->rx_urb[i])
1523 usb_free_urb(self->rx_urb[i]); 1845 usb_free_urb(self->rx_urb[i]);
1524 } 1846 }
@@ -1571,7 +1893,7 @@ static void irda_usb_disconnect(struct usb_interface *intf)
1571 /*netif_device_detach(self->netdev);*/ 1893 /*netif_device_detach(self->netdev);*/
1572 netif_stop_queue(self->netdev); 1894 netif_stop_queue(self->netdev);
1573 /* Stop all the receive URBs. Must be synchronous. */ 1895 /* Stop all the receive URBs. Must be synchronous. */
1574 for (i = 0; i < IU_MAX_RX_URBS; i++) 1896 for (i = 0; i < self->max_rx_urb; i++)
1575 usb_kill_urb(self->rx_urb[i]); 1897 usb_kill_urb(self->rx_urb[i]);
1576 /* Cancel Tx and speed URB. 1898 /* Cancel Tx and speed URB.
1577 * Make sure it's synchronous to avoid races. */ 1899 * Make sure it's synchronous to avoid races. */
@@ -1586,8 +1908,9 @@ static void irda_usb_disconnect(struct usb_interface *intf)
1586 self->usbintf = NULL; 1908 self->usbintf = NULL;
1587 1909
1588 /* Clean up our urbs */ 1910 /* Clean up our urbs */
1589 for (i = 0; i < IU_MAX_RX_URBS; i++) 1911 for (i = 0; i < self->max_rx_urb; i++)
1590 usb_free_urb(self->rx_urb[i]); 1912 usb_free_urb(self->rx_urb[i]);
1913 kfree(self->rx_urb);
1591 /* Clean up Tx and speed URB */ 1914 /* Clean up Tx and speed URB */
1592 usb_free_urb(self->tx_urb); 1915 usb_free_urb(self->tx_urb);
1593 usb_free_urb(self->speed_urb); 1916 usb_free_urb(self->speed_urb);
@@ -1648,6 +1971,6 @@ module_exit(usb_irda_cleanup);
1648 */ 1971 */
1649module_param(qos_mtt_bits, int, 0); 1972module_param(qos_mtt_bits, int, 0);
1650MODULE_PARM_DESC(qos_mtt_bits, "Minimum Turn Time"); 1973MODULE_PARM_DESC(qos_mtt_bits, "Minimum Turn Time");
1651MODULE_AUTHOR("Roman Weissgaerber <weissg@vienna.at>, Dag Brattli <dag@brattli.net> and Jean Tourrilhes <jt@hpl.hp.com>"); 1974MODULE_AUTHOR("Roman Weissgaerber <weissg@vienna.at>, Dag Brattli <dag@brattli.net>, Jean Tourrilhes <jt@hpl.hp.com> and Nick Fedchik <nick@fedchik.org.ua>");
1652MODULE_DESCRIPTION("IrDA-USB Dongle Driver"); 1975MODULE_DESCRIPTION("IrDA-USB Dongle Driver");
1653MODULE_LICENSE("GPL"); 1976MODULE_LICENSE("GPL");
diff --git a/drivers/net/irda/irda-usb.h b/drivers/net/irda/irda-usb.h
index 4026af42dd47..d833db52cebf 100644
--- a/drivers/net/irda/irda-usb.h
+++ b/drivers/net/irda/irda-usb.h
@@ -1,7 +1,7 @@
1/***************************************************************************** 1/*****************************************************************************
2 * 2 *
3 * Filename: irda-usb.h 3 * Filename: irda-usb.h
4 * Version: 0.9b 4 * Version: 0.10
5 * Description: IrDA-USB Driver 5 * Description: IrDA-USB Driver
6 * Status: Experimental 6 * Status: Experimental
7 * Author: Dag Brattli <dag@brattli.net> 7 * Author: Dag Brattli <dag@brattli.net>
@@ -9,6 +9,9 @@
9 * Copyright (C) 2001, Roman Weissgaerber <weissg@vienna.at> 9 * Copyright (C) 2001, Roman Weissgaerber <weissg@vienna.at>
10 * Copyright (C) 2000, Dag Brattli <dag@brattli.net> 10 * Copyright (C) 2000, Dag Brattli <dag@brattli.net>
11 * Copyright (C) 2001, Jean Tourrilhes <jt@hpl.hp.com> 11 * Copyright (C) 2001, Jean Tourrilhes <jt@hpl.hp.com>
12 * Copyright (C) 2004, SigmaTel, Inc. <irquality@sigmatel.com>
13 * Copyright (C) 2005, Milan Beno <beno@pobox.sk>
14 * Copyright (C) 2006, Nick FEdchik <nick@fedchik.org.ua>
12 * 15 *
13 * This program is free software; you can redistribute it and/or modify 16 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by 17 * it under the terms of the GNU General Public License as published by
@@ -31,6 +34,9 @@
31#include <net/irda/irda.h> 34#include <net/irda/irda.h>
32#include <net/irda/irda_device.h> /* struct irlap_cb */ 35#include <net/irda/irda_device.h> /* struct irlap_cb */
33 36
37#define PATCH_FILE_SIZE_MAX 65536
38#define PATCH_FILE_SIZE_MIN 80
39
34#define RX_COPY_THRESHOLD 200 40#define RX_COPY_THRESHOLD 200
35#define IRDA_USB_MAX_MTU 2051 41#define IRDA_USB_MAX_MTU 2051
36#define IRDA_USB_SPEED_MTU 64 /* Weird, but work like this */ 42#define IRDA_USB_SPEED_MTU 64 /* Weird, but work like this */
@@ -79,15 +85,16 @@
79/* Inbound header */ 85/* Inbound header */
80#define MEDIA_BUSY 0x80 86#define MEDIA_BUSY 0x80
81 87
82#define SPEED_2400 0x01 88#define SPEED_2400 0x01
83#define SPEED_9600 0x02 89#define SPEED_9600 0x02
84#define SPEED_19200 0x03 90#define SPEED_19200 0x03
85#define SPEED_38400 0x04 91#define SPEED_38400 0x04
86#define SPEED_57600 0x05 92#define SPEED_57600 0x05
87#define SPEED_115200 0x06 93#define SPEED_115200 0x06
88#define SPEED_576000 0x07 94#define SPEED_576000 0x07
89#define SPEED_1152000 0x08 95#define SPEED_1152000 0x08
90#define SPEED_4000000 0x09 96#define SPEED_4000000 0x09
97#define SPEED_16000000 0x0a
91 98
92/* Basic capabilities */ 99/* Basic capabilities */
93#define IUC_DEFAULT 0x00 /* Basic device compliant with 1.0 spec */ 100#define IUC_DEFAULT 0x00 /* Basic device compliant with 1.0 spec */
@@ -100,11 +107,14 @@
100#define IUC_SMALL_PKT 0x10 /* Device doesn't behave with big Rx packets */ 107#define IUC_SMALL_PKT 0x10 /* Device doesn't behave with big Rx packets */
101#define IUC_MAX_WINDOW 0x20 /* Device underestimate the Rx window */ 108#define IUC_MAX_WINDOW 0x20 /* Device underestimate the Rx window */
102#define IUC_MAX_XBOFS 0x40 /* Device need more xbofs than advertised */ 109#define IUC_MAX_XBOFS 0x40 /* Device need more xbofs than advertised */
110#define IUC_STIR_4210 0x80 /* SigmaTel 4210/4220/4116 VFIR */
103 111
104/* USB class definitions */ 112/* USB class definitions */
105#define USB_IRDA_HEADER 0x01 113#define USB_IRDA_HEADER 0x01
106#define USB_CLASS_IRDA 0x02 /* USB_CLASS_APP_SPEC subclass */ 114#define USB_CLASS_IRDA 0x02 /* USB_CLASS_APP_SPEC subclass */
107#define USB_DT_IRDA 0x21 115#define USB_DT_IRDA 0x21
116#define USB_IRDA_SIGMATEL_HEADER 0x03
117#define IU_SIGMATEL_MAX_RX_URBS (IU_MAX_ACTIVE_RX_URBS + USB_IRDA_SIGMATEL_HEADER)
108 118
109struct irda_class_desc { 119struct irda_class_desc {
110 __u8 bLength; 120 __u8 bLength;
@@ -123,6 +133,7 @@ struct irda_class_desc {
123 * (6.2.5, USB-IrDA class spec 1.0) */ 133 * (6.2.5, USB-IrDA class spec 1.0) */
124 134
125#define IU_REQ_GET_CLASS_DESC 0x06 135#define IU_REQ_GET_CLASS_DESC 0x06
136#define STIR421X_MAX_PATCH_DOWNLOAD_SIZE 1023
126 137
127struct irda_usb_cb { 138struct irda_usb_cb {
128 struct irda_class_desc *irda_desc; 139 struct irda_class_desc *irda_desc;
@@ -136,7 +147,8 @@ struct irda_usb_cb {
136 __u16 bulk_out_mtu; /* Max Tx packet size in bytes */ 147 __u16 bulk_out_mtu; /* Max Tx packet size in bytes */
137 __u8 bulk_int_ep; /* Interrupt Endpoint assignments */ 148 __u8 bulk_int_ep; /* Interrupt Endpoint assignments */
138 149
139 struct urb *rx_urb[IU_MAX_RX_URBS]; /* URBs used to receive data frames */ 150 __u8 max_rx_urb;
151 struct urb **rx_urb; /* URBs used to receive data frames */
140 struct urb *idle_rx_urb; /* Pointer to idle URB in Rx path */ 152 struct urb *idle_rx_urb; /* Pointer to idle URB in Rx path */
141 struct urb *tx_urb; /* URB used to send data frames */ 153 struct urb *tx_urb; /* URB used to send data frames */
142 struct urb *speed_urb; /* URB used to send speed commands */ 154 struct urb *speed_urb; /* URB used to send speed commands */
@@ -157,6 +169,9 @@ struct irda_usb_cb {
157 __u32 speed; /* Current speed */ 169 __u32 speed; /* Current speed */
158 __s32 new_speed; /* speed we need to set */ 170 __s32 new_speed; /* speed we need to set */
159 171
172 __u8 header_length; /* USB-IrDA frame header size */
173 int needspatch; /* device needs firmware patch */
174
160 struct timer_list rx_defer_timer; /* Wait for Rx error to clear */ 175 struct timer_list rx_defer_timer; /* Wait for Rx error to clear */
161}; 176};
162 177
diff --git a/drivers/net/irda/smsc-ircc2.c b/drivers/net/irda/smsc-ircc2.c
index ec94ecdb103d..bbcfc8ec35a1 100644
--- a/drivers/net/irda/smsc-ircc2.c
+++ b/drivers/net/irda/smsc-ircc2.c
@@ -11,6 +11,7 @@
11 * Copyright (c) 2002 Daniele Peri 11 * Copyright (c) 2002 Daniele Peri
12 * All Rights Reserved. 12 * All Rights Reserved.
13 * Copyright (c) 2002 Jean Tourrilhes 13 * Copyright (c) 2002 Jean Tourrilhes
14 * Copyright (c) 2006 Linus Walleij
14 * 15 *
15 * 16 *
16 * Based on smc-ircc.c: 17 * Based on smc-ircc.c:
@@ -61,6 +62,9 @@
61 62
62#include <linux/spinlock.h> 63#include <linux/spinlock.h>
63#include <linux/pm.h> 64#include <linux/pm.h>
65#ifdef CONFIG_PCI
66#include <linux/pci.h>
67#endif
64 68
65#include <net/irda/wrapper.h> 69#include <net/irda/wrapper.h>
66#include <net/irda/irda.h> 70#include <net/irda/irda.h>
@@ -100,6 +104,22 @@ MODULE_PARM_DESC(ircc_transceiver, "Transceiver type");
100 104
101/* Types */ 105/* Types */
102 106
107#ifdef CONFIG_PCI
108struct smsc_ircc_subsystem_configuration {
109 unsigned short vendor; /* PCI vendor ID */
110 unsigned short device; /* PCI vendor ID */
111 unsigned short subvendor; /* PCI subsystem vendor ID */
112 unsigned short subdevice; /* PCI sybsystem device ID */
113 unsigned short sir_io; /* I/O port for SIR */
114 unsigned short fir_io; /* I/O port for FIR */
115 unsigned char fir_irq; /* FIR IRQ */
116 unsigned char fir_dma; /* FIR DMA */
117 unsigned short cfg_base; /* I/O port for chip configuration */
118 int (*preconfigure)(struct pci_dev *dev, struct smsc_ircc_subsystem_configuration *conf); /* Preconfig function */
119 const char *name; /* name shown as info */
120};
121#endif
122
103struct smsc_transceiver { 123struct smsc_transceiver {
104 char *name; 124 char *name;
105 void (*set_for_speed)(int fir_base, u32 speed); 125 void (*set_for_speed)(int fir_base, u32 speed);
@@ -202,6 +222,16 @@ static int __init smsc_superio_flat(const struct smsc_chip *chips, unsigned shor
202static int __init smsc_superio_paged(const struct smsc_chip *chips, unsigned short cfg_base, char *type); 222static int __init smsc_superio_paged(const struct smsc_chip *chips, unsigned short cfg_base, char *type);
203static int __init smsc_superio_fdc(unsigned short cfg_base); 223static int __init smsc_superio_fdc(unsigned short cfg_base);
204static int __init smsc_superio_lpc(unsigned short cfg_base); 224static int __init smsc_superio_lpc(unsigned short cfg_base);
225#ifdef CONFIG_PCI
226static int __init preconfigure_smsc_chip(struct smsc_ircc_subsystem_configuration *conf);
227static int __init preconfigure_through_82801(struct pci_dev *dev, struct smsc_ircc_subsystem_configuration *conf);
228static int __init preconfigure_through_ali(struct pci_dev *dev, struct smsc_ircc_subsystem_configuration *conf);
229static int __init smsc_ircc_preconfigure_subsystems(unsigned short ircc_cfg,
230 unsigned short ircc_fir,
231 unsigned short ircc_sir,
232 unsigned char ircc_dma,
233 unsigned char ircc_irq);
234#endif
205 235
206/* Transceivers specific functions */ 236/* Transceivers specific functions */
207 237
@@ -353,6 +383,13 @@ static int __init smsc_ircc_init(void)
353 return ret; 383 return ret;
354 } 384 }
355 385
386#ifdef CONFIG_PCI
387 if (smsc_ircc_preconfigure_subsystems(ircc_cfg, ircc_fir, ircc_sir, ircc_dma, ircc_irq) < 0) {
388 /* Ignore errors from preconfiguration */
389 IRDA_ERROR("%s, Preconfiguration failed !\n", driver_name);
390 }
391#endif
392
356 dev_count = 0; 393 dev_count = 0;
357 394
358 if (ircc_fir > 0 && ircc_sir > 0) { 395 if (ircc_fir > 0 && ircc_sir > 0) {
@@ -2285,6 +2322,280 @@ static int __init smsc_superio_lpc(unsigned short cfg_base)
2285 return ret; 2322 return ret;
2286} 2323}
2287 2324
2325/*
2326 * Look for some specific subsystem setups that need
2327 * pre-configuration not properly done by the BIOS (especially laptops)
2328 * This code is based in part on smcinit.c, tosh1800-smcinit.c
2329 * and tosh2450-smcinit.c. The table lists the device entries
2330 * for ISA bridges with an LPC (Local Peripheral Configurator)
2331 * that are in turn used to configure the SMSC device with default
2332 * SIR and FIR I/O ports, DMA and IRQ.
2333 */
2334#ifdef CONFIG_PCI
2335#define PCIID_VENDOR_INTEL 0x8086
2336#define PCIID_VENDOR_ALI 0x10b9
2337static struct smsc_ircc_subsystem_configuration subsystem_configurations[] __devinitdata = {
2338 {
2339 .vendor = PCIID_VENDOR_INTEL, /* Intel 82801DBM LPC bridge */
2340 .device = 0x24cc,
2341 .subvendor = 0x103c,
2342 .subdevice = 0x088c,
2343 .sir_io = 0x02f8, /* Quite certain these are the same for nc8000 as for nc6000 */
2344 .fir_io = 0x0130,
2345 .fir_irq = 0x09,
2346 .fir_dma = 0x03,
2347 .cfg_base = 0x004e,
2348 .preconfigure = preconfigure_through_82801,
2349 .name = "HP nc8000",
2350 },
2351 {
2352 .vendor = PCIID_VENDOR_INTEL, /* Intel 82801DBM LPC bridge */
2353 .device = 0x24cc,
2354 .subvendor = 0x103c,
2355 .subdevice = 0x0890,
2356 .sir_io = 0x02f8,
2357 .fir_io = 0x0130,
2358 .fir_irq = 0x09,
2359 .fir_dma = 0x03,
2360 .cfg_base = 0x004e,
2361 .preconfigure = preconfigure_through_82801,
2362 .name = "HP nc6000",
2363 },
2364 {
2365 .vendor = PCIID_VENDOR_INTEL, /* Intel 82801DB/DBL (ICH4/ICH4-L) LPC Interface Bridge */
2366 .device = 0x24c0,
2367 .subvendor = 0x1179,
2368 .subdevice = 0xffff, /* 0xffff is "any", Not sure, 0x0001 or 0x0002 */
2369 .sir_io = 0x03f8,
2370 .fir_io = 0x0130,
2371 .fir_irq = 0x07,
2372 .fir_dma = 0x01,
2373 .cfg_base = 0x002e,
2374 .preconfigure = preconfigure_through_82801,
2375 .name = "Toshiba Satellite 2450",
2376 },
2377 {
2378 .vendor = PCIID_VENDOR_INTEL, /* Intel 82801CAM ISA bridge */
2379 .device = 0x248c, /* Some use 24cc? */
2380 .subvendor = 0x1179,
2381 .subdevice = 0xffff, /* 0xffff is "any", Not sure, 0x0001 or 0x0002 */
2382 .sir_io = 0x03f8,
2383 .fir_io = 0x0130,
2384 .fir_irq = 0x03,
2385 .fir_dma = 0x03,
2386 .cfg_base = 0x002e,
2387 .preconfigure = preconfigure_through_82801,
2388 .name = "Toshiba Satellite 5100/5200, Tecra 9100",
2389 },
2390 {
2391 .vendor = PCIID_VENDOR_ALI, /* ALi M1533/M1535 PCI to ISA Bridge [Aladdin IV/V/V+] */
2392 .device = 0x1533,
2393 .subvendor = 0x1179,
2394 .subdevice = 0xffff, /* 0xffff is "any", Not sure, 0x0001 or 0x0002 */
2395 .sir_io = 0x02e8,
2396 .fir_io = 0x02f8,
2397 .fir_irq = 0x07,
2398 .fir_dma = 0x03,
2399 .cfg_base = 0x002e,
2400 .preconfigure = preconfigure_through_ali,
2401 .name = "Toshiba Satellite 1800",
2402 },
2403 { } // Terminator
2404};
2405
2406
2407/*
2408 * This sets up the basic SMSC parameters (FIR port, SIR port, FIR DMA, FIR IRQ)
2409 * through the chip configuration port.
2410 */
2411static int __init preconfigure_smsc_chip(struct smsc_ircc_subsystem_configuration *conf)
2412{
2413 unsigned short iobase = conf->cfg_base;
2414 unsigned char tmpbyte;
2415
2416 outb(LPC47N227_CFGACCESSKEY, iobase); // enter configuration state
2417 outb(SMSCSIOFLAT_DEVICEID_REG, iobase); // set for device ID
2418 tmpbyte = inb(iobase +1); // Read device ID
2419 IRDA_DEBUG(0, "Detected Chip id: 0x%02x, setting up registers...\n",tmpbyte);
2420
2421 /* Disable UART1 and set up SIR I/O port */
2422 outb(0x24, iobase); // select CR24 - UART1 base addr
2423 outb(0x00, iobase + 1); // disable UART1
2424 outb(SMSCSIOFLAT_UART2BASEADDR_REG, iobase); // select CR25 - UART2 base addr
2425 outb( (conf->sir_io >> 2), iobase + 1); // bits 2-9 of 0x3f8
2426 tmpbyte = inb(iobase + 1);
2427 if (tmpbyte != (conf->sir_io >> 2) ) {
2428 IRDA_WARNING("ERROR: could not configure SIR ioport.\n");
2429 return -ENXIO;
2430 }
2431
2432 /* Set up FIR IRQ channel for UART2 */
2433 outb(SMSCSIOFLAT_UARTIRQSELECT_REG, iobase); // select CR28 - UART1,2 IRQ select
2434 tmpbyte = inb(iobase + 1);
2435 tmpbyte &= SMSCSIOFLAT_UART1IRQSELECT_MASK; // Do not touch the UART1 portion
2436 tmpbyte |= (conf->fir_irq & SMSCSIOFLAT_UART2IRQSELECT_MASK);
2437 outb(tmpbyte, iobase + 1);
2438 tmpbyte = inb(iobase + 1) & SMSCSIOFLAT_UART2IRQSELECT_MASK;
2439 if (tmpbyte != conf->fir_irq) {
2440 IRDA_WARNING("ERROR: could not configure FIR IRQ channel.\n");
2441 return -ENXIO;
2442 }
2443
2444 /* Set up FIR I/O port */
2445 outb(SMSCSIOFLAT_FIRBASEADDR_REG, iobase); // CR2B - SCE (FIR) base addr
2446 outb((conf->fir_io >> 3), iobase + 1);
2447 tmpbyte = inb(iobase + 1);
2448 if (tmpbyte != (conf->fir_io >> 3) ) {
2449 IRDA_WARNING("ERROR: could not configure FIR I/O port.\n");
2450 return -ENXIO;
2451 }
2452
2453 /* Set up FIR DMA channel */
2454 outb(SMSCSIOFLAT_FIRDMASELECT_REG, iobase); // CR2C - SCE (FIR) DMA select
2455 outb((conf->fir_dma & LPC47N227_FIRDMASELECT_MASK), iobase + 1); // DMA
2456 tmpbyte = inb(iobase + 1) & LPC47N227_FIRDMASELECT_MASK;
2457 if (tmpbyte != (conf->fir_dma & LPC47N227_FIRDMASELECT_MASK)) {
2458 IRDA_WARNING("ERROR: could not configure FIR DMA channel.\n");
2459 return -ENXIO;
2460 }
2461
2462 outb(SMSCSIOFLAT_UARTMODE0C_REG, iobase); // CR0C - UART mode
2463 tmpbyte = inb(iobase + 1);
2464 tmpbyte &= ~SMSCSIOFLAT_UART2MODE_MASK | SMSCSIOFLAT_UART2MODE_VAL_IRDA;
2465 outb(tmpbyte, iobase + 1); // enable IrDA (HPSIR) mode, high speed
2466
2467 outb(LPC47N227_APMBOOTDRIVE_REG, iobase); // CR07 - Auto Pwr Mgt/boot drive sel
2468 tmpbyte = inb(iobase + 1);
2469 outb(tmpbyte | LPC47N227_UART2AUTOPWRDOWN_MASK, iobase + 1); // enable UART2 autopower down
2470
2471 /* This one was not part of tosh1800 */
2472 outb(0x0a, iobase); // CR0a - ecp fifo / ir mux
2473 tmpbyte = inb(iobase + 1);
2474 outb(tmpbyte | 0x40, iobase + 1); // send active device to ir port
2475
2476 outb(LPC47N227_UART12POWER_REG, iobase); // CR02 - UART 1,2 power
2477 tmpbyte = inb(iobase + 1);
2478 outb(tmpbyte | LPC47N227_UART2POWERDOWN_MASK, iobase + 1); // UART2 power up mode, UART1 power down
2479
2480 outb(LPC47N227_FDCPOWERVALIDCONF_REG, iobase); // CR00 - FDC Power/valid config cycle
2481 tmpbyte = inb(iobase + 1);
2482 outb(tmpbyte | LPC47N227_VALID_MASK, iobase + 1); // valid config cycle done
2483
2484 outb(LPC47N227_CFGEXITKEY, iobase); // Exit configuration
2485
2486 return 0;
2487}
2488
2489/* 82801CAM registers */
2490#define VID 0x00
2491#define DID 0x02
2492#define PIRQA_ROUT 0x60
2493#define PCI_DMA_C 0x90
2494#define COM_DEC 0xe0
2495#define LPC_EN 0xe6
2496#define GEN2_DEC 0xec
2497/*
2498 * Sets up the I/O range using the 82801CAM ISA bridge, 82801DBM LPC bridge or
2499 * Intel 82801DB/DBL (ICH4/ICH4-L) LPC Interface Bridge. They all work the same way!
2500 */
2501static int __init preconfigure_through_82801(struct pci_dev *dev,
2502 struct smsc_ircc_subsystem_configuration *conf)
2503{
2504 unsigned short tmpword;
2505 int ret;
2506
2507 IRDA_MESSAGE("Setting up the SMSC device via the 82801 controller.\n");
2508 pci_write_config_byte(dev, COM_DEC, 0x10);
2509
2510 /* Enable LPC */
2511 pci_read_config_word(dev, LPC_EN, &tmpword); /* LPC_EN register */
2512 tmpword &= 0xfffd; /* mask bit 1 */
2513 tmpword |= 0x0001; /* set bit 0 : COMA addr range enable */
2514 pci_write_config_word(dev, LPC_EN, tmpword);
2515
2516 /* Setup DMA */
2517 pci_write_config_word(dev, PCI_DMA_C, 0xc0c0); /* LPC I/F DMA on, channel 3 -- rtm (?? PCI DMA ?) */
2518 pci_write_config_word(dev, GEN2_DEC, 0x131); /* LPC I/F 2nd decode range */
2519
2520 /* Pre-configure chip */
2521 ret = preconfigure_smsc_chip(conf);
2522
2523 /* Disable LPC */
2524 pci_read_config_word(dev, LPC_EN, &tmpword); /* LPC_EN register */
2525 tmpword &= 0xfffc; /* mask bit 1 and bit 0, COMA addr range disable */
2526 pci_write_config_word(dev, LPC_EN, tmpword);
2527 return ret;
2528}
2529
2530static int __init preconfigure_through_ali(struct pci_dev *dev,
2531 struct smsc_ircc_subsystem_configuration *conf)
2532{
2533 /* TODO: put in ALi 1533 configuration here. */
2534 IRDA_MESSAGE("SORRY: %s has an unsupported bridge controller (ALi): not pre-configured.\n", conf->name);
2535 return -ENODEV;
2536}
2537
2538static int __init smsc_ircc_preconfigure_subsystems(unsigned short ircc_cfg,
2539 unsigned short ircc_fir,
2540 unsigned short ircc_sir,
2541 unsigned char ircc_dma,
2542 unsigned char ircc_irq)
2543{
2544 struct pci_dev *dev = NULL;
2545 unsigned short ss_vendor = 0x0000;
2546 unsigned short ss_device = 0x0000;
2547 int ret = 0;
2548
2549 dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev);
2550
2551 while (dev != NULL) {
2552 struct smsc_ircc_subsystem_configuration *conf;
2553
2554 /*
2555 * Cache the subsystem vendor/device: some manufacturers fail to set
2556 * this for all components, so we save it in case there is just
2557 * 0x0000 0x0000 on the device we want to check.
2558 */
2559 if (dev->subsystem_vendor != 0x0000U) {
2560 ss_vendor = dev->subsystem_vendor;
2561 ss_device = dev->subsystem_device;
2562 }
2563 conf = subsystem_configurations;
2564 for( ; conf->subvendor; conf++) {
2565 if(conf->vendor == dev->vendor &&
2566 conf->device == dev->device &&
2567 conf->subvendor == ss_vendor && /* Sometimes these are cached values */
2568 (conf->subdevice == ss_device || conf->subdevice == 0xffff)) {
2569 struct smsc_ircc_subsystem_configuration tmpconf;
2570
2571 memcpy(&tmpconf, conf, sizeof(struct smsc_ircc_subsystem_configuration));
2572
2573 /* Override the default values with anything passed in as parameter */
2574 if (ircc_cfg != 0)
2575 tmpconf.cfg_base = ircc_cfg;
2576 if (ircc_fir != 0)
2577 tmpconf.fir_io = ircc_fir;
2578 if (ircc_sir != 0)
2579 tmpconf.sir_io = ircc_sir;
2580 if (ircc_dma != 0xff)
2581 tmpconf.fir_dma = ircc_dma;
2582 if (ircc_irq != 0xff)
2583 tmpconf.fir_irq = ircc_irq;
2584
2585 IRDA_MESSAGE("Detected unconfigured %s SMSC IrDA chip, pre-configuring device.\n", conf->name);
2586 if (conf->preconfigure)
2587 ret = conf->preconfigure(dev, &tmpconf);
2588 else
2589 ret = -ENODEV;
2590 }
2591 }
2592 dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev);
2593 }
2594
2595 return ret;
2596}
2597#endif // CONFIG_PCI
2598
2288/************************************************ 2599/************************************************
2289 * 2600 *
2290 * Transceivers specific functions 2601 * Transceivers specific functions
diff --git a/drivers/net/netconsole.c b/drivers/net/netconsole.c
index 75b35ad760de..66e74f740261 100644
--- a/drivers/net/netconsole.c
+++ b/drivers/net/netconsole.c
@@ -87,6 +87,7 @@ static void write_msg(struct console *con, const char *msg, unsigned int len)
87} 87}
88 88
89static struct console netconsole = { 89static struct console netconsole = {
90 .name = "netcon",
90 .flags = CON_ENABLED | CON_PRINTBUFFER, 91 .flags = CON_ENABLED | CON_PRINTBUFFER,
91 .write = write_msg 92 .write = write_msg
92}; 93};
diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c
index 0b5358072172..73e271e59c6a 100644
--- a/drivers/net/tg3.c
+++ b/drivers/net/tg3.c
@@ -497,21 +497,20 @@ static void tg3_write_mem(struct tg3 *tp, u32 off, u32 val)
497 unsigned long flags; 497 unsigned long flags;
498 498
499 spin_lock_irqsave(&tp->indirect_lock, flags); 499 spin_lock_irqsave(&tp->indirect_lock, flags);
500 pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_BASE_ADDR, off); 500 if (tp->tg3_flags & TG3_FLAG_SRAM_USE_CONFIG) {
501 pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_DATA, val); 501 pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_BASE_ADDR, off);
502 pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_DATA, val);
502 503
503 /* Always leave this as zero. */ 504 /* Always leave this as zero. */
504 pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_BASE_ADDR, 0); 505 pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_BASE_ADDR, 0);
505 spin_unlock_irqrestore(&tp->indirect_lock, flags); 506 } else {
506} 507 tw32_f(TG3PCI_MEM_WIN_BASE_ADDR, off);
508 tw32_f(TG3PCI_MEM_WIN_DATA, val);
507 509
508static void tg3_write_mem_fast(struct tg3 *tp, u32 off, u32 val) 510 /* Always leave this as zero. */
509{ 511 tw32_f(TG3PCI_MEM_WIN_BASE_ADDR, 0);
510 /* If no workaround is needed, write to mem space directly */ 512 }
511 if (tp->write32 != tg3_write_indirect_reg32) 513 spin_unlock_irqrestore(&tp->indirect_lock, flags);
512 tw32(NIC_SRAM_WIN_BASE + off, val);
513 else
514 tg3_write_mem(tp, off, val);
515} 514}
516 515
517static void tg3_read_mem(struct tg3 *tp, u32 off, u32 *val) 516static void tg3_read_mem(struct tg3 *tp, u32 off, u32 *val)
@@ -519,11 +518,19 @@ static void tg3_read_mem(struct tg3 *tp, u32 off, u32 *val)
519 unsigned long flags; 518 unsigned long flags;
520 519
521 spin_lock_irqsave(&tp->indirect_lock, flags); 520 spin_lock_irqsave(&tp->indirect_lock, flags);
522 pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_BASE_ADDR, off); 521 if (tp->tg3_flags & TG3_FLAG_SRAM_USE_CONFIG) {
523 pci_read_config_dword(tp->pdev, TG3PCI_MEM_WIN_DATA, val); 522 pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_BASE_ADDR, off);
523 pci_read_config_dword(tp->pdev, TG3PCI_MEM_WIN_DATA, val);
524 524
525 /* Always leave this as zero. */ 525 /* Always leave this as zero. */
526 pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_BASE_ADDR, 0); 526 pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_BASE_ADDR, 0);
527 } else {
528 tw32_f(TG3PCI_MEM_WIN_BASE_ADDR, off);
529 *val = tr32(TG3PCI_MEM_WIN_DATA);
530
531 /* Always leave this as zero. */
532 tw32_f(TG3PCI_MEM_WIN_BASE_ADDR, 0);
533 }
527 spin_unlock_irqrestore(&tp->indirect_lock, flags); 534 spin_unlock_irqrestore(&tp->indirect_lock, flags);
528} 535}
529 536
@@ -1367,12 +1374,12 @@ static int tg3_set_power_state(struct tg3 *tp, pci_power_t state)
1367 } 1374 }
1368 } 1375 }
1369 1376
1377 tg3_write_sig_post_reset(tp, RESET_KIND_SHUTDOWN);
1378
1370 /* Finally, set the new power state. */ 1379 /* Finally, set the new power state. */
1371 pci_write_config_word(tp->pdev, pm + PCI_PM_CTRL, power_control); 1380 pci_write_config_word(tp->pdev, pm + PCI_PM_CTRL, power_control);
1372 udelay(100); /* Delay after power state change */ 1381 udelay(100); /* Delay after power state change */
1373 1382
1374 tg3_write_sig_post_reset(tp, RESET_KIND_SHUTDOWN);
1375
1376 return 0; 1383 return 0;
1377} 1384}
1378 1385
@@ -5828,10 +5835,14 @@ static int tg3_reset_hw(struct tg3 *tp)
5828 GRC_MODE_NO_TX_PHDR_CSUM | 5835 GRC_MODE_NO_TX_PHDR_CSUM |
5829 GRC_MODE_NO_RX_PHDR_CSUM); 5836 GRC_MODE_NO_RX_PHDR_CSUM);
5830 tp->grc_mode |= GRC_MODE_HOST_SENDBDS; 5837 tp->grc_mode |= GRC_MODE_HOST_SENDBDS;
5831 if (tp->tg3_flags & TG3_FLAG_NO_TX_PSEUDO_CSUM) 5838
5832 tp->grc_mode |= GRC_MODE_NO_TX_PHDR_CSUM; 5839 /* Pseudo-header checksum is done by hardware logic and not
5833 if (tp->tg3_flags & TG3_FLAG_NO_RX_PSEUDO_CSUM) 5840 * the offload processers, so make the chip do the pseudo-
5834 tp->grc_mode |= GRC_MODE_NO_RX_PHDR_CSUM; 5841 * header checksums on receive. For transmit it is more
5842 * convenient to do the pseudo-header checksum in software
5843 * as Linux does that on transmit for us in all cases.
5844 */
5845 tp->grc_mode |= GRC_MODE_NO_TX_PHDR_CSUM;
5835 5846
5836 tw32(GRC_MODE, 5847 tw32(GRC_MODE,
5837 tp->grc_mode | 5848 tp->grc_mode |
@@ -6535,11 +6546,11 @@ static void tg3_timer(unsigned long __opaque)
6535 if (tp->tg3_flags & TG3_FLAG_ENABLE_ASF) { 6546 if (tp->tg3_flags & TG3_FLAG_ENABLE_ASF) {
6536 u32 val; 6547 u32 val;
6537 6548
6538 tg3_write_mem_fast(tp, NIC_SRAM_FW_CMD_MBOX, 6549 tg3_write_mem(tp, NIC_SRAM_FW_CMD_MBOX,
6539 FWCMD_NICDRV_ALIVE2); 6550 FWCMD_NICDRV_ALIVE2);
6540 tg3_write_mem_fast(tp, NIC_SRAM_FW_CMD_LEN_MBOX, 4); 6551 tg3_write_mem(tp, NIC_SRAM_FW_CMD_LEN_MBOX, 4);
6541 /* 5 seconds timeout */ 6552 /* 5 seconds timeout */
6542 tg3_write_mem_fast(tp, NIC_SRAM_FW_CMD_DATA_MBOX, 5); 6553 tg3_write_mem(tp, NIC_SRAM_FW_CMD_DATA_MBOX, 5);
6543 val = tr32(GRC_RX_CPU_EVENT); 6554 val = tr32(GRC_RX_CPU_EVENT);
6544 val |= (1 << 14); 6555 val |= (1 << 14);
6545 tw32(GRC_RX_CPU_EVENT, val); 6556 tw32(GRC_RX_CPU_EVENT, val);
@@ -8034,9 +8045,13 @@ static int tg3_test_nvram(struct tg3 *tp)
8034 for (i = 0; i < size; i++) 8045 for (i = 0; i < size; i++)
8035 csum8 += buf8[i]; 8046 csum8 += buf8[i];
8036 8047
8037 if (csum8 == 0) 8048 if (csum8 == 0) {
8038 return 0; 8049 err = 0;
8039 return -EIO; 8050 goto out;
8051 }
8052
8053 err = -EIO;
8054 goto out;
8040 } 8055 }
8041 8056
8042 /* Bootstrap checksum at offset 0x10 */ 8057 /* Bootstrap checksum at offset 0x10 */
@@ -9531,8 +9546,11 @@ static void __devinit tg3_get_eeprom_hw_cfg(struct tg3 *tp)
9531 tp->led_ctrl = LED_CTRL_MODE_PHY_1; 9546 tp->led_ctrl = LED_CTRL_MODE_PHY_1;
9532 9547
9533 /* Do not even try poking around in here on Sun parts. */ 9548 /* Do not even try poking around in here on Sun parts. */
9534 if (tp->tg3_flags2 & TG3_FLG2_SUN_570X) 9549 if (tp->tg3_flags2 & TG3_FLG2_SUN_570X) {
9550 /* All SUN chips are built-in LOMs. */
9551 tp->tg3_flags |= TG3_FLAG_EEPROM_WRITE_PROT;
9535 return; 9552 return;
9553 }
9536 9554
9537 tg3_read_mem(tp, NIC_SRAM_DATA_SIG, &val); 9555 tg3_read_mem(tp, NIC_SRAM_DATA_SIG, &val);
9538 if (val == NIC_SRAM_DATA_SIG_MAGIC) { 9556 if (val == NIC_SRAM_DATA_SIG_MAGIC) {
@@ -9630,9 +9648,7 @@ static void __devinit tg3_get_eeprom_hw_cfg(struct tg3 *tp)
9630 tp->pdev->subsystem_vendor == PCI_VENDOR_ID_DELL) 9648 tp->pdev->subsystem_vendor == PCI_VENDOR_ID_DELL)
9631 tp->led_ctrl = LED_CTRL_MODE_PHY_2; 9649 tp->led_ctrl = LED_CTRL_MODE_PHY_2;
9632 9650
9633 if ((GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5700) && 9651 if (nic_cfg & NIC_SRAM_DATA_CFG_EEPROM_WP)
9634 (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5701) &&
9635 (nic_cfg & NIC_SRAM_DATA_CFG_EEPROM_WP))
9636 tp->tg3_flags |= TG3_FLAG_EEPROM_WRITE_PROT; 9652 tp->tg3_flags |= TG3_FLAG_EEPROM_WRITE_PROT;
9637 9653
9638 if (nic_cfg & NIC_SRAM_DATA_CFG_ASF_ENABLE) { 9654 if (nic_cfg & NIC_SRAM_DATA_CFG_ASF_ENABLE) {
@@ -10257,6 +10273,13 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
10257 pci_write_config_word(tp->pdev, PCI_COMMAND, pci_cmd); 10273 pci_write_config_word(tp->pdev, PCI_COMMAND, pci_cmd);
10258 } 10274 }
10259 10275
10276 if (tp->write32 == tg3_write_indirect_reg32 ||
10277 ((tp->tg3_flags & TG3_FLAG_PCIX_MODE) &&
10278 (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700 ||
10279 GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5701)) ||
10280 (tp->tg3_flags2 & TG3_FLG2_SUN_570X))
10281 tp->tg3_flags |= TG3_FLAG_SRAM_USE_CONFIG;
10282
10260 /* Get eeprom hw config before calling tg3_set_power_state(). 10283 /* Get eeprom hw config before calling tg3_set_power_state().
10261 * In particular, the TG3_FLAG_EEPROM_WRITE_PROT flag must be 10284 * In particular, the TG3_FLAG_EEPROM_WRITE_PROT flag must be
10262 * determined before calling tg3_set_power_state() so that 10285 * determined before calling tg3_set_power_state() so that
@@ -10299,15 +10322,6 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
10299 if (tp->pci_chip_rev_id == CHIPREV_ID_5700_B0) 10322 if (tp->pci_chip_rev_id == CHIPREV_ID_5700_B0)
10300 tp->tg3_flags |= TG3_FLAG_BROKEN_CHECKSUMS; 10323 tp->tg3_flags |= TG3_FLAG_BROKEN_CHECKSUMS;
10301 10324
10302 /* Pseudo-header checksum is done by hardware logic and not
10303 * the offload processers, so make the chip do the pseudo-
10304 * header checksums on receive. For transmit it is more
10305 * convenient to do the pseudo-header checksum in software
10306 * as Linux does that on transmit for us in all cases.
10307 */
10308 tp->tg3_flags |= TG3_FLAG_NO_TX_PSEUDO_CSUM;
10309 tp->tg3_flags &= ~TG3_FLAG_NO_RX_PSEUDO_CSUM;
10310
10311 /* Derive initial jumbo mode from MTU assigned in 10325 /* Derive initial jumbo mode from MTU assigned in
10312 * ether_setup() via the alloc_etherdev() call 10326 * ether_setup() via the alloc_etherdev() call
10313 */ 10327 */
diff --git a/drivers/net/tg3.h b/drivers/net/tg3.h
index c43cc3264202..8c8b987d1250 100644
--- a/drivers/net/tg3.h
+++ b/drivers/net/tg3.h
@@ -2171,8 +2171,7 @@ struct tg3 {
2171#define TG3_FLAG_PCIX_MODE 0x00020000 2171#define TG3_FLAG_PCIX_MODE 0x00020000
2172#define TG3_FLAG_PCI_HIGH_SPEED 0x00040000 2172#define TG3_FLAG_PCI_HIGH_SPEED 0x00040000
2173#define TG3_FLAG_PCI_32BIT 0x00080000 2173#define TG3_FLAG_PCI_32BIT 0x00080000
2174#define TG3_FLAG_NO_TX_PSEUDO_CSUM 0x00100000 2174#define TG3_FLAG_SRAM_USE_CONFIG 0x00100000
2175#define TG3_FLAG_NO_RX_PSEUDO_CSUM 0x00200000
2176#define TG3_FLAG_SERDES_WOL_CAP 0x00400000 2175#define TG3_FLAG_SERDES_WOL_CAP 0x00400000
2177#define TG3_FLAG_JUMBO_RING_ENABLE 0x00800000 2176#define TG3_FLAG_JUMBO_RING_ENABLE 0x00800000
2178#define TG3_FLAG_10_100_ONLY 0x01000000 2177#define TG3_FLAG_10_100_ONLY 0x01000000
diff --git a/include/linux/netfilter.h b/include/linux/netfilter.h
index 412e52ca9720..b31a9bca9361 100644
--- a/include/linux/netfilter.h
+++ b/include/linux/netfilter.h
@@ -110,6 +110,8 @@ struct nf_info
110/* Function to register/unregister hook points. */ 110/* Function to register/unregister hook points. */
111int nf_register_hook(struct nf_hook_ops *reg); 111int nf_register_hook(struct nf_hook_ops *reg);
112void nf_unregister_hook(struct nf_hook_ops *reg); 112void nf_unregister_hook(struct nf_hook_ops *reg);
113int nf_register_hooks(struct nf_hook_ops *reg, unsigned int n);
114void nf_unregister_hooks(struct nf_hook_ops *reg, unsigned int n);
113 115
114/* Functions to register get/setsockopt ranges (non-inclusive). You 116/* Functions to register get/setsockopt ranges (non-inclusive). You
115 need to check permissions yourself! */ 117 need to check permissions yourself! */
@@ -281,16 +283,42 @@ extern void nf_invalidate_cache(int pf);
281 Returns true or false. */ 283 Returns true or false. */
282extern int skb_make_writable(struct sk_buff **pskb, unsigned int writable_len); 284extern int skb_make_writable(struct sk_buff **pskb, unsigned int writable_len);
283 285
284struct nf_queue_rerouter { 286struct nf_afinfo {
285 void (*save)(const struct sk_buff *skb, struct nf_info *info); 287 unsigned short family;
286 int (*reroute)(struct sk_buff **skb, const struct nf_info *info); 288 unsigned int (*checksum)(struct sk_buff *skb, unsigned int hook,
287 int rer_size; 289 unsigned int dataoff, u_int8_t protocol);
290 void (*saveroute)(const struct sk_buff *skb,
291 struct nf_info *info);
292 int (*reroute)(struct sk_buff **skb,
293 const struct nf_info *info);
294 int route_key_size;
288}; 295};
289 296
290#define nf_info_reroute(x) ((void *)x + sizeof(struct nf_info)) 297extern struct nf_afinfo *nf_afinfo[];
298static inline struct nf_afinfo *nf_get_afinfo(unsigned short family)
299{
300 return rcu_dereference(nf_afinfo[family]);
301}
302
303static inline unsigned int
304nf_checksum(struct sk_buff *skb, unsigned int hook, unsigned int dataoff,
305 u_int8_t protocol, unsigned short family)
306{
307 struct nf_afinfo *afinfo;
308 unsigned int csum = 0;
309
310 rcu_read_lock();
311 afinfo = nf_get_afinfo(family);
312 if (afinfo)
313 csum = afinfo->checksum(skb, hook, dataoff, protocol);
314 rcu_read_unlock();
315 return csum;
316}
291 317
292extern int nf_register_queue_rerouter(int pf, struct nf_queue_rerouter *rer); 318extern int nf_register_afinfo(struct nf_afinfo *afinfo);
293extern int nf_unregister_queue_rerouter(int pf); 319extern void nf_unregister_afinfo(struct nf_afinfo *afinfo);
320
321#define nf_info_reroute(x) ((void *)x + sizeof(struct nf_info))
294 322
295#include <net/flow.h> 323#include <net/flow.h>
296extern void (*ip_nat_decode_session)(struct sk_buff *, struct flowi *); 324extern void (*ip_nat_decode_session)(struct sk_buff *, struct flowi *);
diff --git a/include/linux/netfilter_ipv4.h b/include/linux/netfilter_ipv4.h
index 43c09d790b83..85301c5e8d24 100644
--- a/include/linux/netfilter_ipv4.h
+++ b/include/linux/netfilter_ipv4.h
@@ -80,6 +80,8 @@ enum nf_ip_hook_priorities {
80#ifdef __KERNEL__ 80#ifdef __KERNEL__
81extern int ip_route_me_harder(struct sk_buff **pskb); 81extern int ip_route_me_harder(struct sk_buff **pskb);
82extern int ip_xfrm_me_harder(struct sk_buff **pskb); 82extern int ip_xfrm_me_harder(struct sk_buff **pskb);
83extern unsigned int nf_ip_checksum(struct sk_buff *skb, unsigned int hook,
84 unsigned int dataoff, u_int8_t protocol);
83#endif /*__KERNEL__*/ 85#endif /*__KERNEL__*/
84 86
85#endif /*__LINUX_IP_NETFILTER_H*/ 87#endif /*__LINUX_IP_NETFILTER_H*/
diff --git a/include/linux/netfilter_ipv4/ip_conntrack_h323.h b/include/linux/netfilter_ipv4/ip_conntrack_h323.h
index 0987cea53840..eace86bd2adb 100644
--- a/include/linux/netfilter_ipv4/ip_conntrack_h323.h
+++ b/include/linux/netfilter_ipv4/ip_conntrack_h323.h
@@ -3,6 +3,8 @@
3 3
4#ifdef __KERNEL__ 4#ifdef __KERNEL__
5 5
6#include <linux/netfilter_ipv4/ip_conntrack_helper_h323_asn1.h>
7
6#define RAS_PORT 1719 8#define RAS_PORT 1719
7#define Q931_PORT 1720 9#define Q931_PORT 1720
8#define H323_RTP_CHANNEL_MAX 4 /* Audio, video, FAX and other */ 10#define H323_RTP_CHANNEL_MAX 4 /* Audio, video, FAX and other */
@@ -25,6 +27,56 @@ struct ip_ct_h323_master {
25 }; 27 };
26}; 28};
27 29
30struct ip_conntrack_expect;
31
32extern int get_h225_addr(unsigned char *data, TransportAddress * addr,
33 u_int32_t * ip, u_int16_t * port);
34extern void ip_conntrack_h245_expect(struct ip_conntrack *new,
35 struct ip_conntrack_expect *this);
36extern void ip_conntrack_q931_expect(struct ip_conntrack *new,
37 struct ip_conntrack_expect *this);
38extern int (*set_h245_addr_hook) (struct sk_buff ** pskb,
39 unsigned char **data, int dataoff,
40 H245_TransportAddress * addr,
41 u_int32_t ip, u_int16_t port);
42extern int (*set_h225_addr_hook) (struct sk_buff ** pskb,
43 unsigned char **data, int dataoff,
44 TransportAddress * addr,
45 u_int32_t ip, u_int16_t port);
46extern int (*set_sig_addr_hook) (struct sk_buff ** pskb,
47 struct ip_conntrack * ct,
48 enum ip_conntrack_info ctinfo,
49 unsigned char **data,
50 TransportAddress * addr, int count);
51extern int (*set_ras_addr_hook) (struct sk_buff ** pskb,
52 struct ip_conntrack * ct,
53 enum ip_conntrack_info ctinfo,
54 unsigned char **data,
55 TransportAddress * addr, int count);
56extern int (*nat_rtp_rtcp_hook) (struct sk_buff ** pskb,
57 struct ip_conntrack * ct,
58 enum ip_conntrack_info ctinfo,
59 unsigned char **data, int dataoff,
60 H245_TransportAddress * addr,
61 u_int16_t port, u_int16_t rtp_port,
62 struct ip_conntrack_expect * rtp_exp,
63 struct ip_conntrack_expect * rtcp_exp);
64extern int (*nat_t120_hook) (struct sk_buff ** pskb, struct ip_conntrack * ct,
65 enum ip_conntrack_info ctinfo,
66 unsigned char **data, int dataoff,
67 H245_TransportAddress * addr, u_int16_t port,
68 struct ip_conntrack_expect * exp);
69extern int (*nat_h245_hook) (struct sk_buff ** pskb, struct ip_conntrack * ct,
70 enum ip_conntrack_info ctinfo,
71 unsigned char **data, int dataoff,
72 TransportAddress * addr, u_int16_t port,
73 struct ip_conntrack_expect * exp);
74extern int (*nat_q931_hook) (struct sk_buff ** pskb, struct ip_conntrack * ct,
75 enum ip_conntrack_info ctinfo,
76 unsigned char **data, TransportAddress * addr,
77 int idx, u_int16_t port,
78 struct ip_conntrack_expect * exp);
79
28#endif 80#endif
29 81
30#endif 82#endif
diff --git a/net/ipv4/netfilter/ip_conntrack_helper_h323_asn1.h b/include/linux/netfilter_ipv4/ip_conntrack_helper_h323_asn1.h
index 0bd828081c0c..0bd828081c0c 100644
--- a/net/ipv4/netfilter/ip_conntrack_helper_h323_asn1.h
+++ b/include/linux/netfilter_ipv4/ip_conntrack_helper_h323_asn1.h
diff --git a/net/ipv4/netfilter/ip_conntrack_helper_h323_types.h b/include/linux/netfilter_ipv4/ip_conntrack_helper_h323_types.h
index cc98f7aa5abe..cc98f7aa5abe 100644
--- a/net/ipv4/netfilter/ip_conntrack_helper_h323_types.h
+++ b/include/linux/netfilter_ipv4/ip_conntrack_helper_h323_types.h
diff --git a/include/linux/netfilter_ipv6.h b/include/linux/netfilter_ipv6.h
index 14f2bd010884..52a7b9e76428 100644
--- a/include/linux/netfilter_ipv6.h
+++ b/include/linux/netfilter_ipv6.h
@@ -73,6 +73,9 @@ enum nf_ip6_hook_priorities {
73}; 73};
74 74
75#ifdef CONFIG_NETFILTER 75#ifdef CONFIG_NETFILTER
76extern unsigned int nf_ip6_checksum(struct sk_buff *skb, unsigned int hook,
77 unsigned int dataoff, u_int8_t protocol);
78
76extern int ipv6_netfilter_init(void); 79extern int ipv6_netfilter_init(void);
77extern void ipv6_netfilter_fini(void); 80extern void ipv6_netfilter_fini(void);
78#else /* CONFIG_NETFILTER */ 81#else /* CONFIG_NETFILTER */
diff --git a/include/net/inet6_hashtables.h b/include/net/inet6_hashtables.h
index 25f708ff020e..59f0c83d55a2 100644
--- a/include/net/inet6_hashtables.h
+++ b/include/net/inet6_hashtables.h
@@ -48,31 +48,7 @@ static inline int inet6_sk_ehashfn(const struct sock *sk)
48 return inet6_ehashfn(laddr, lport, faddr, fport); 48 return inet6_ehashfn(laddr, lport, faddr, fport);
49} 49}
50 50
51static inline void __inet6_hash(struct inet_hashinfo *hashinfo, 51extern void __inet6_hash(struct inet_hashinfo *hashinfo, struct sock *sk);
52 struct sock *sk)
53{
54 struct hlist_head *list;
55 rwlock_t *lock;
56
57 BUG_TRAP(sk_unhashed(sk));
58
59 if (sk->sk_state == TCP_LISTEN) {
60 list = &hashinfo->listening_hash[inet_sk_listen_hashfn(sk)];
61 lock = &hashinfo->lhash_lock;
62 inet_listen_wlock(hashinfo);
63 } else {
64 unsigned int hash;
65 sk->sk_hash = hash = inet6_sk_ehashfn(sk);
66 hash &= (hashinfo->ehash_size - 1);
67 list = &hashinfo->ehash[hash].chain;
68 lock = &hashinfo->ehash[hash].lock;
69 write_lock(lock);
70 }
71
72 __sk_add_node(sk, list);
73 sock_prot_inc_use(sk->sk_prot);
74 write_unlock(lock);
75}
76 52
77/* 53/*
78 * Sockets in TCP_CLOSE state are _always_ taken out of the hash, so 54 * Sockets in TCP_CLOSE state are _always_ taken out of the hash, so
@@ -80,52 +56,12 @@ static inline void __inet6_hash(struct inet_hashinfo *hashinfo,
80 * 56 *
81 * The sockhash lock must be held as a reader here. 57 * The sockhash lock must be held as a reader here.
82 */ 58 */
83static inline struct sock * 59extern struct sock *__inet6_lookup_established(struct inet_hashinfo *hashinfo,
84 __inet6_lookup_established(struct inet_hashinfo *hashinfo,
85 const struct in6_addr *saddr, 60 const struct in6_addr *saddr,
86 const u16 sport, 61 const u16 sport,
87 const struct in6_addr *daddr, 62 const struct in6_addr *daddr,
88 const u16 hnum, 63 const u16 hnum,
89 const int dif) 64 const int dif);
90{
91 struct sock *sk;
92 const struct hlist_node *node;
93 const __u32 ports = INET_COMBINED_PORTS(sport, hnum);
94 /* Optimize here for direct hit, only listening connections can
95 * have wildcards anyways.
96 */
97 unsigned int hash = inet6_ehashfn(daddr, hnum, saddr, sport);
98 struct inet_ehash_bucket *head = inet_ehash_bucket(hashinfo, hash);
99
100 prefetch(head->chain.first);
101 read_lock(&head->lock);
102 sk_for_each(sk, node, &head->chain) {
103 /* For IPV6 do the cheaper port and family tests first. */
104 if (INET6_MATCH(sk, hash, saddr, daddr, ports, dif))
105 goto hit; /* You sunk my battleship! */
106 }
107 /* Must check for a TIME_WAIT'er before going to listener hash. */
108 sk_for_each(sk, node, &(head + hashinfo->ehash_size)->chain) {
109 const struct inet_timewait_sock *tw = inet_twsk(sk);
110
111 if(*((__u32 *)&(tw->tw_dport)) == ports &&
112 sk->sk_family == PF_INET6) {
113 const struct inet6_timewait_sock *tw6 = inet6_twsk(sk);
114
115 if (ipv6_addr_equal(&tw6->tw_v6_daddr, saddr) &&
116 ipv6_addr_equal(&tw6->tw_v6_rcv_saddr, daddr) &&
117 (!sk->sk_bound_dev_if || sk->sk_bound_dev_if == dif))
118 goto hit;
119 }
120 }
121 read_unlock(&head->lock);
122 return NULL;
123
124hit:
125 sock_hold(sk);
126 read_unlock(&head->lock);
127 return sk;
128}
129 65
130extern struct sock *inet6_lookup_listener(struct inet_hashinfo *hashinfo, 66extern struct sock *inet6_lookup_listener(struct inet_hashinfo *hashinfo,
131 const struct in6_addr *daddr, 67 const struct in6_addr *daddr,
diff --git a/include/net/ip.h b/include/net/ip.h
index 8fe6156ca9b0..3d2e5ca62a5a 100644
--- a/include/net/ip.h
+++ b/include/net/ip.h
@@ -95,6 +95,7 @@ extern int ip_local_deliver(struct sk_buff *skb);
95extern int ip_mr_input(struct sk_buff *skb); 95extern int ip_mr_input(struct sk_buff *skb);
96extern int ip_output(struct sk_buff *skb); 96extern int ip_output(struct sk_buff *skb);
97extern int ip_mc_output(struct sk_buff *skb); 97extern int ip_mc_output(struct sk_buff *skb);
98extern int ip_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *));
98extern int ip_do_nat(struct sk_buff *skb); 99extern int ip_do_nat(struct sk_buff *skb);
99extern void ip_send_check(struct iphdr *ip); 100extern void ip_send_check(struct iphdr *ip);
100extern int ip_queue_xmit(struct sk_buff *skb, int ipfragok); 101extern int ip_queue_xmit(struct sk_buff *skb, int ipfragok);
diff --git a/include/net/x25device.h b/include/net/x25device.h
index 1a318374faef..1d10c879f7e2 100644
--- a/include/net/x25device.h
+++ b/include/net/x25device.h
@@ -8,6 +8,7 @@
8static inline __be16 x25_type_trans(struct sk_buff *skb, struct net_device *dev) 8static inline __be16 x25_type_trans(struct sk_buff *skb, struct net_device *dev)
9{ 9{
10 skb->mac.raw = skb->data; 10 skb->mac.raw = skb->data;
11 skb->dev = dev;
11 skb->pkt_type = PACKET_HOST; 12 skb->pkt_type = PACKET_HOST;
12 13
13 return htons(ETH_P_X25); 14 return htons(ETH_P_X25);
diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c
index 6b61323ce23c..0c2d13ad69bb 100644
--- a/net/bluetooth/sco.c
+++ b/net/bluetooth/sco.c
@@ -255,7 +255,7 @@ static inline int sco_send_frame(struct sock *sk, struct msghdr *msg, int len)
255 } 255 }
256 256
257 if ((err = hci_send_sco(conn->hcon, skb)) < 0) 257 if ((err = hci_send_sco(conn->hcon, skb)) < 0)
258 goto fail; 258 return err;
259 259
260 return count; 260 return count;
261 261
diff --git a/net/bridge/br_netfilter.c b/net/bridge/br_netfilter.c
index f29450b788be..3da9264449f7 100644
--- a/net/bridge/br_netfilter.c
+++ b/net/bridge/br_netfilter.c
@@ -765,6 +765,15 @@ out:
765 return NF_STOLEN; 765 return NF_STOLEN;
766} 766}
767 767
768static int br_nf_dev_queue_xmit(struct sk_buff *skb)
769{
770 if (skb->protocol == htons(ETH_P_IP) &&
771 skb->len > skb->dev->mtu &&
772 !(skb_shinfo(skb)->ufo_size || skb_shinfo(skb)->tso_size))
773 return ip_fragment(skb, br_dev_queue_push_xmit);
774 else
775 return br_dev_queue_push_xmit(skb);
776}
768 777
769/* PF_BRIDGE/POST_ROUTING ********************************************/ 778/* PF_BRIDGE/POST_ROUTING ********************************************/
770static unsigned int br_nf_post_routing(unsigned int hook, struct sk_buff **pskb, 779static unsigned int br_nf_post_routing(unsigned int hook, struct sk_buff **pskb,
@@ -824,7 +833,7 @@ static unsigned int br_nf_post_routing(unsigned int hook, struct sk_buff **pskb,
824 realoutdev = nf_bridge->netoutdev; 833 realoutdev = nf_bridge->netoutdev;
825#endif 834#endif
826 NF_HOOK(pf, NF_IP_POST_ROUTING, skb, NULL, realoutdev, 835 NF_HOOK(pf, NF_IP_POST_ROUTING, skb, NULL, realoutdev,
827 br_dev_queue_push_xmit); 836 br_nf_dev_queue_xmit);
828 837
829 return NF_STOLEN; 838 return NF_STOLEN;
830 839
@@ -869,7 +878,7 @@ static unsigned int ip_sabotage_out(unsigned int hook, struct sk_buff **pskb,
869 878
870 if ((out->hard_start_xmit == br_dev_xmit && 879 if ((out->hard_start_xmit == br_dev_xmit &&
871 okfn != br_nf_forward_finish && 880 okfn != br_nf_forward_finish &&
872 okfn != br_nf_local_out_finish && okfn != br_dev_queue_push_xmit) 881 okfn != br_nf_local_out_finish && okfn != br_nf_dev_queue_xmit)
873#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE) 882#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
874 || ((out->priv_flags & IFF_802_1Q_VLAN) && 883 || ((out->priv_flags & IFF_802_1Q_VLAN) &&
875 VLAN_DEV_INFO(out)->real_dev->hard_start_xmit == br_dev_xmit) 884 VLAN_DEV_INFO(out)->real_dev->hard_start_xmit == br_dev_xmit)
diff --git a/net/core/dev.c b/net/core/dev.c
index 434220d093aa..2731570eba5b 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -3042,11 +3042,11 @@ void netdev_run_todo(void)
3042 3042
3043 switch(dev->reg_state) { 3043 switch(dev->reg_state) {
3044 case NETREG_REGISTERING: 3044 case NETREG_REGISTERING:
3045 dev->reg_state = NETREG_REGISTERED;
3045 err = netdev_register_sysfs(dev); 3046 err = netdev_register_sysfs(dev);
3046 if (err) 3047 if (err)
3047 printk(KERN_ERR "%s: failed sysfs registration (%d)\n", 3048 printk(KERN_ERR "%s: failed sysfs registration (%d)\n",
3048 dev->name, err); 3049 dev->name, err);
3049 dev->reg_state = NETREG_REGISTERED;
3050 break; 3050 break;
3051 3051
3052 case NETREG_UNREGISTERING: 3052 case NETREG_UNREGISTERING:
@@ -3100,12 +3100,11 @@ struct net_device *alloc_netdev(int sizeof_priv, const char *name,
3100 alloc_size = (sizeof(*dev) + NETDEV_ALIGN_CONST) & ~NETDEV_ALIGN_CONST; 3100 alloc_size = (sizeof(*dev) + NETDEV_ALIGN_CONST) & ~NETDEV_ALIGN_CONST;
3101 alloc_size += sizeof_priv + NETDEV_ALIGN_CONST; 3101 alloc_size += sizeof_priv + NETDEV_ALIGN_CONST;
3102 3102
3103 p = kmalloc(alloc_size, GFP_KERNEL); 3103 p = kzalloc(alloc_size, GFP_KERNEL);
3104 if (!p) { 3104 if (!p) {
3105 printk(KERN_ERR "alloc_dev: Unable to allocate device.\n"); 3105 printk(KERN_ERR "alloc_dev: Unable to allocate device.\n");
3106 return NULL; 3106 return NULL;
3107 } 3107 }
3108 memset(p, 0, alloc_size);
3109 3108
3110 dev = (struct net_device *) 3109 dev = (struct net_device *)
3111 (((long)p + NETDEV_ALIGN_CONST) & ~NETDEV_ALIGN_CONST); 3110 (((long)p + NETDEV_ALIGN_CONST) & ~NETDEV_ALIGN_CONST);
diff --git a/net/core/dv.c b/net/core/dv.c
index cf581407538c..29ee77f15932 100644
--- a/net/core/dv.c
+++ b/net/core/dv.c
@@ -55,15 +55,12 @@ int alloc_divert_blk(struct net_device *dev)
55 55
56 dev->divert = NULL; 56 dev->divert = NULL;
57 if (dev->type == ARPHRD_ETHER) { 57 if (dev->type == ARPHRD_ETHER) {
58 dev->divert = (struct divert_blk *) 58 dev->divert = kzalloc(alloc_size, GFP_KERNEL);
59 kmalloc(alloc_size, GFP_KERNEL);
60 if (dev->divert == NULL) { 59 if (dev->divert == NULL) {
61 printk(KERN_INFO "divert: unable to allocate divert_blk for %s\n", 60 printk(KERN_INFO "divert: unable to allocate divert_blk for %s\n",
62 dev->name); 61 dev->name);
63 return -ENOMEM; 62 return -ENOMEM;
64 } 63 }
65
66 memset(dev->divert, 0, sizeof(struct divert_blk));
67 dev_hold(dev); 64 dev_hold(dev);
68 } 65 }
69 66
diff --git a/net/core/flow.c b/net/core/flow.c
index 55789f832eda..885a2f655db0 100644
--- a/net/core/flow.c
+++ b/net/core/flow.c
@@ -318,12 +318,10 @@ static void __devinit flow_cache_cpu_prepare(int cpu)
318 /* NOTHING */; 318 /* NOTHING */;
319 319
320 flow_table(cpu) = (struct flow_cache_entry **) 320 flow_table(cpu) = (struct flow_cache_entry **)
321 __get_free_pages(GFP_KERNEL, order); 321 __get_free_pages(GFP_KERNEL|__GFP_ZERO, order);
322 if (!flow_table(cpu)) 322 if (!flow_table(cpu))
323 panic("NET: failed to allocate flow cache order %lu\n", order); 323 panic("NET: failed to allocate flow cache order %lu\n", order);
324 324
325 memset(flow_table(cpu), 0, PAGE_SIZE << order);
326
327 flow_hash_rnd_recalc(cpu) = 1; 325 flow_hash_rnd_recalc(cpu) = 1;
328 flow_count(cpu) = 0; 326 flow_count(cpu) = 0;
329 327
diff --git a/net/core/gen_estimator.c b/net/core/gen_estimator.c
index b07c029e8219..3cad026764f0 100644
--- a/net/core/gen_estimator.c
+++ b/net/core/gen_estimator.c
@@ -159,11 +159,10 @@ int gen_new_estimator(struct gnet_stats_basic *bstats,
159 if (parm->interval < -2 || parm->interval > 3) 159 if (parm->interval < -2 || parm->interval > 3)
160 return -EINVAL; 160 return -EINVAL;
161 161
162 est = kmalloc(sizeof(*est), GFP_KERNEL); 162 est = kzalloc(sizeof(*est), GFP_KERNEL);
163 if (est == NULL) 163 if (est == NULL)
164 return -ENOBUFS; 164 return -ENOBUFS;
165 165
166 memset(est, 0, sizeof(*est));
167 est->interval = parm->interval + 2; 166 est->interval = parm->interval + 2;
168 est->bstats = bstats; 167 est->bstats = bstats;
169 est->rate_est = rate_est; 168 est->rate_est = rate_est;
diff --git a/net/core/neighbour.c b/net/core/neighbour.c
index 0c8666872d10..2ec8693fb778 100644
--- a/net/core/neighbour.c
+++ b/net/core/neighbour.c
@@ -284,14 +284,11 @@ static struct neighbour **neigh_hash_alloc(unsigned int entries)
284 struct neighbour **ret; 284 struct neighbour **ret;
285 285
286 if (size <= PAGE_SIZE) { 286 if (size <= PAGE_SIZE) {
287 ret = kmalloc(size, GFP_ATOMIC); 287 ret = kzalloc(size, GFP_ATOMIC);
288 } else { 288 } else {
289 ret = (struct neighbour **) 289 ret = (struct neighbour **)
290 __get_free_pages(GFP_ATOMIC, get_order(size)); 290 __get_free_pages(GFP_ATOMIC|__GFP_ZERO, get_order(size));
291 } 291 }
292 if (ret)
293 memset(ret, 0, size);
294
295 return ret; 292 return ret;
296} 293}
297 294
@@ -1089,8 +1086,7 @@ static void neigh_hh_init(struct neighbour *n, struct dst_entry *dst,
1089 if (hh->hh_type == protocol) 1086 if (hh->hh_type == protocol)
1090 break; 1087 break;
1091 1088
1092 if (!hh && (hh = kmalloc(sizeof(*hh), GFP_ATOMIC)) != NULL) { 1089 if (!hh && (hh = kzalloc(sizeof(*hh), GFP_ATOMIC)) != NULL) {
1093 memset(hh, 0, sizeof(struct hh_cache));
1094 rwlock_init(&hh->hh_lock); 1090 rwlock_init(&hh->hh_lock);
1095 hh->hh_type = protocol; 1091 hh->hh_type = protocol;
1096 atomic_set(&hh->hh_refcnt, 0); 1092 atomic_set(&hh->hh_refcnt, 0);
@@ -1366,13 +1362,11 @@ void neigh_table_init(struct neigh_table *tbl)
1366 tbl->hash_buckets = neigh_hash_alloc(tbl->hash_mask + 1); 1362 tbl->hash_buckets = neigh_hash_alloc(tbl->hash_mask + 1);
1367 1363
1368 phsize = (PNEIGH_HASHMASK + 1) * sizeof(struct pneigh_entry *); 1364 phsize = (PNEIGH_HASHMASK + 1) * sizeof(struct pneigh_entry *);
1369 tbl->phash_buckets = kmalloc(phsize, GFP_KERNEL); 1365 tbl->phash_buckets = kzalloc(phsize, GFP_KERNEL);
1370 1366
1371 if (!tbl->hash_buckets || !tbl->phash_buckets) 1367 if (!tbl->hash_buckets || !tbl->phash_buckets)
1372 panic("cannot allocate neighbour cache hashes"); 1368 panic("cannot allocate neighbour cache hashes");
1373 1369
1374 memset(tbl->phash_buckets, 0, phsize);
1375
1376 get_random_bytes(&tbl->hash_rnd, sizeof(tbl->hash_rnd)); 1370 get_random_bytes(&tbl->hash_rnd, sizeof(tbl->hash_rnd));
1377 1371
1378 rwlock_init(&tbl->lock); 1372 rwlock_init(&tbl->lock);
diff --git a/net/core/net-sysfs.c b/net/core/net-sysfs.c
index 21b68464cabb..c12990c9c603 100644
--- a/net/core/net-sysfs.c
+++ b/net/core/net-sysfs.c
@@ -165,7 +165,7 @@ static ssize_t show_operstate(struct class_device *dev, char *buf)
165 operstate = IF_OPER_DOWN; 165 operstate = IF_OPER_DOWN;
166 read_unlock(&dev_base_lock); 166 read_unlock(&dev_base_lock);
167 167
168 if (operstate >= sizeof(operstates)) 168 if (operstate >= ARRAY_SIZE(operstates))
169 return -EINVAL; /* should not happen */ 169 return -EINVAL; /* should not happen */
170 170
171 return sprintf(buf, "%s\n", operstates[operstate]); 171 return sprintf(buf, "%s\n", operstates[operstate]);
diff --git a/net/core/request_sock.c b/net/core/request_sock.c
index 1e44eda1fda9..79ebd75fbe4d 100644
--- a/net/core/request_sock.c
+++ b/net/core/request_sock.c
@@ -38,13 +38,11 @@ int reqsk_queue_alloc(struct request_sock_queue *queue,
38{ 38{
39 const int lopt_size = sizeof(struct listen_sock) + 39 const int lopt_size = sizeof(struct listen_sock) +
40 nr_table_entries * sizeof(struct request_sock *); 40 nr_table_entries * sizeof(struct request_sock *);
41 struct listen_sock *lopt = kmalloc(lopt_size, GFP_KERNEL); 41 struct listen_sock *lopt = kzalloc(lopt_size, GFP_KERNEL);
42 42
43 if (lopt == NULL) 43 if (lopt == NULL)
44 return -ENOMEM; 44 return -ENOMEM;
45 45
46 memset(lopt, 0, lopt_size);
47
48 for (lopt->max_qlen_log = 6; 46 for (lopt->max_qlen_log = 6;
49 (1 << lopt->max_qlen_log) < sysctl_max_syn_backlog; 47 (1 << lopt->max_qlen_log) < sysctl_max_syn_backlog;
50 lopt->max_qlen_log++); 48 lopt->max_qlen_log++);
diff --git a/net/ipv4/fib_trie.c b/net/ipv4/fib_trie.c
index ccd3efc6a173..95a639f2e3db 100644
--- a/net/ipv4/fib_trie.c
+++ b/net/ipv4/fib_trie.c
@@ -50,7 +50,7 @@
50 * Patrick McHardy <kaber@trash.net> 50 * Patrick McHardy <kaber@trash.net>
51 */ 51 */
52 52
53#define VERSION "0.406" 53#define VERSION "0.407"
54 54
55#include <linux/config.h> 55#include <linux/config.h>
56#include <asm/uaccess.h> 56#include <asm/uaccess.h>
@@ -314,11 +314,6 @@ static void __leaf_free_rcu(struct rcu_head *head)
314 kfree(container_of(head, struct leaf, rcu)); 314 kfree(container_of(head, struct leaf, rcu));
315} 315}
316 316
317static inline void free_leaf(struct leaf *leaf)
318{
319 call_rcu(&leaf->rcu, __leaf_free_rcu);
320}
321
322static void __leaf_info_free_rcu(struct rcu_head *head) 317static void __leaf_info_free_rcu(struct rcu_head *head)
323{ 318{
324 kfree(container_of(head, struct leaf_info, rcu)); 319 kfree(container_of(head, struct leaf_info, rcu));
@@ -357,7 +352,12 @@ static void __tnode_free_rcu(struct rcu_head *head)
357 352
358static inline void tnode_free(struct tnode *tn) 353static inline void tnode_free(struct tnode *tn)
359{ 354{
360 call_rcu(&tn->rcu, __tnode_free_rcu); 355 if(IS_LEAF(tn)) {
356 struct leaf *l = (struct leaf *) tn;
357 call_rcu_bh(&l->rcu, __leaf_free_rcu);
358 }
359 else
360 call_rcu(&tn->rcu, __tnode_free_rcu);
361} 361}
362 362
363static struct leaf *leaf_new(void) 363static struct leaf *leaf_new(void)
diff --git a/net/ipv4/ip_fragment.c b/net/ipv4/ip_fragment.c
index 2a8adda15e11..da734c439179 100644
--- a/net/ipv4/ip_fragment.c
+++ b/net/ipv4/ip_fragment.c
@@ -304,13 +304,17 @@ out:
304 304
305/* Creation primitives. */ 305/* Creation primitives. */
306 306
307static struct ipq *ip_frag_intern(unsigned int hash, struct ipq *qp_in) 307static struct ipq *ip_frag_intern(struct ipq *qp_in)
308{ 308{
309 struct ipq *qp; 309 struct ipq *qp;
310#ifdef CONFIG_SMP 310#ifdef CONFIG_SMP
311 struct hlist_node *n; 311 struct hlist_node *n;
312#endif 312#endif
313 unsigned int hash;
314
313 write_lock(&ipfrag_lock); 315 write_lock(&ipfrag_lock);
316 hash = ipqhashfn(qp_in->id, qp_in->saddr, qp_in->daddr,
317 qp_in->protocol);
314#ifdef CONFIG_SMP 318#ifdef CONFIG_SMP
315 /* With SMP race we have to recheck hash table, because 319 /* With SMP race we have to recheck hash table, because
316 * such entry could be created on other cpu, while we 320 * such entry could be created on other cpu, while we
@@ -345,7 +349,7 @@ static struct ipq *ip_frag_intern(unsigned int hash, struct ipq *qp_in)
345} 349}
346 350
347/* Add an entry to the 'ipq' queue for a newly received IP datagram. */ 351/* Add an entry to the 'ipq' queue for a newly received IP datagram. */
348static struct ipq *ip_frag_create(unsigned hash, struct iphdr *iph, u32 user) 352static struct ipq *ip_frag_create(struct iphdr *iph, u32 user)
349{ 353{
350 struct ipq *qp; 354 struct ipq *qp;
351 355
@@ -371,7 +375,7 @@ static struct ipq *ip_frag_create(unsigned hash, struct iphdr *iph, u32 user)
371 spin_lock_init(&qp->lock); 375 spin_lock_init(&qp->lock);
372 atomic_set(&qp->refcnt, 1); 376 atomic_set(&qp->refcnt, 1);
373 377
374 return ip_frag_intern(hash, qp); 378 return ip_frag_intern(qp);
375 379
376out_nomem: 380out_nomem:
377 LIMIT_NETDEBUG(KERN_ERR "ip_frag_create: no memory left !\n"); 381 LIMIT_NETDEBUG(KERN_ERR "ip_frag_create: no memory left !\n");
@@ -387,11 +391,12 @@ static inline struct ipq *ip_find(struct iphdr *iph, u32 user)
387 __u32 saddr = iph->saddr; 391 __u32 saddr = iph->saddr;
388 __u32 daddr = iph->daddr; 392 __u32 daddr = iph->daddr;
389 __u8 protocol = iph->protocol; 393 __u8 protocol = iph->protocol;
390 unsigned int hash = ipqhashfn(id, saddr, daddr, protocol); 394 unsigned int hash;
391 struct ipq *qp; 395 struct ipq *qp;
392 struct hlist_node *n; 396 struct hlist_node *n;
393 397
394 read_lock(&ipfrag_lock); 398 read_lock(&ipfrag_lock);
399 hash = ipqhashfn(id, saddr, daddr, protocol);
395 hlist_for_each_entry(qp, n, &ipq_hash[hash], list) { 400 hlist_for_each_entry(qp, n, &ipq_hash[hash], list) {
396 if(qp->id == id && 401 if(qp->id == id &&
397 qp->saddr == saddr && 402 qp->saddr == saddr &&
@@ -405,7 +410,7 @@ static inline struct ipq *ip_find(struct iphdr *iph, u32 user)
405 } 410 }
406 read_unlock(&ipfrag_lock); 411 read_unlock(&ipfrag_lock);
407 412
408 return ip_frag_create(hash, iph, user); 413 return ip_frag_create(iph, user);
409} 414}
410 415
411/* Is the fragment too far ahead to be part of ipq? */ 416/* Is the fragment too far ahead to be part of ipq? */
diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c
index 9981dcd68f11..ab99bebdcdc8 100644
--- a/net/ipv4/ip_gre.c
+++ b/net/ipv4/ip_gre.c
@@ -656,7 +656,7 @@ static int ipgre_rcv(struct sk_buff *skb)
656 read_unlock(&ipgre_lock); 656 read_unlock(&ipgre_lock);
657 return(0); 657 return(0);
658 } 658 }
659 icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PROT_UNREACH, 0); 659 icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0);
660 660
661drop: 661drop:
662 read_unlock(&ipgre_lock); 662 read_unlock(&ipgre_lock);
diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c
index f75ff1d96551..8dcba3887f04 100644
--- a/net/ipv4/ip_output.c
+++ b/net/ipv4/ip_output.c
@@ -86,8 +86,6 @@
86 86
87int sysctl_ip_default_ttl = IPDEFTTL; 87int sysctl_ip_default_ttl = IPDEFTTL;
88 88
89static int ip_fragment(struct sk_buff *skb, int (*output)(struct sk_buff*));
90
91/* Generate a checksum for an outgoing IP datagram. */ 89/* Generate a checksum for an outgoing IP datagram. */
92__inline__ void ip_send_check(struct iphdr *iph) 90__inline__ void ip_send_check(struct iphdr *iph)
93{ 91{
@@ -421,7 +419,7 @@ static void ip_copy_metadata(struct sk_buff *to, struct sk_buff *from)
421 * single device frame, and queue such a frame for sending. 419 * single device frame, and queue such a frame for sending.
422 */ 420 */
423 421
424static int ip_fragment(struct sk_buff *skb, int (*output)(struct sk_buff*)) 422int ip_fragment(struct sk_buff *skb, int (*output)(struct sk_buff*))
425{ 423{
426 struct iphdr *iph; 424 struct iphdr *iph;
427 int raw = 0; 425 int raw = 0;
@@ -673,6 +671,8 @@ fail:
673 return err; 671 return err;
674} 672}
675 673
674EXPORT_SYMBOL(ip_fragment);
675
676int 676int
677ip_generic_getfrag(void *from, char *to, int offset, int len, int odd, struct sk_buff *skb) 677ip_generic_getfrag(void *from, char *to, int offset, int len, int odd, struct sk_buff *skb)
678{ 678{
diff --git a/net/ipv4/ipip.c b/net/ipv4/ipip.c
index eef07b0916a3..ea398ee43f28 100644
--- a/net/ipv4/ipip.c
+++ b/net/ipv4/ipip.c
@@ -474,9 +474,6 @@ static int ipip_rcv(struct sk_buff *skb)
474 struct iphdr *iph; 474 struct iphdr *iph;
475 struct ip_tunnel *tunnel; 475 struct ip_tunnel *tunnel;
476 476
477 if (!pskb_may_pull(skb, sizeof(struct iphdr)))
478 goto out;
479
480 iph = skb->nh.iph; 477 iph = skb->nh.iph;
481 478
482 read_lock(&ipip_lock); 479 read_lock(&ipip_lock);
@@ -508,7 +505,6 @@ static int ipip_rcv(struct sk_buff *skb)
508 } 505 }
509 read_unlock(&ipip_lock); 506 read_unlock(&ipip_lock);
510 507
511out:
512 return -1; 508 return -1;
513} 509}
514 510
diff --git a/net/ipv4/netfilter.c b/net/ipv4/netfilter.c
index b5ad9ac2fbcc..6a9e34b794bc 100644
--- a/net/ipv4/netfilter.c
+++ b/net/ipv4/netfilter.c
@@ -133,7 +133,7 @@ struct ip_rt_info {
133 u_int8_t tos; 133 u_int8_t tos;
134}; 134};
135 135
136static void queue_save(const struct sk_buff *skb, struct nf_info *info) 136static void nf_ip_saveroute(const struct sk_buff *skb, struct nf_info *info)
137{ 137{
138 struct ip_rt_info *rt_info = nf_info_reroute(info); 138 struct ip_rt_info *rt_info = nf_info_reroute(info);
139 139
@@ -146,7 +146,7 @@ static void queue_save(const struct sk_buff *skb, struct nf_info *info)
146 } 146 }
147} 147}
148 148
149static int queue_reroute(struct sk_buff **pskb, const struct nf_info *info) 149static int nf_ip_reroute(struct sk_buff **pskb, const struct nf_info *info)
150{ 150{
151 const struct ip_rt_info *rt_info = nf_info_reroute(info); 151 const struct ip_rt_info *rt_info = nf_info_reroute(info);
152 152
@@ -161,20 +161,54 @@ static int queue_reroute(struct sk_buff **pskb, const struct nf_info *info)
161 return 0; 161 return 0;
162} 162}
163 163
164static struct nf_queue_rerouter ip_reroute = { 164unsigned int nf_ip_checksum(struct sk_buff *skb, unsigned int hook,
165 .rer_size = sizeof(struct ip_rt_info), 165 unsigned int dataoff, u_int8_t protocol)
166 .save = queue_save, 166{
167 .reroute = queue_reroute, 167 struct iphdr *iph = skb->nh.iph;
168 unsigned int csum = 0;
169
170 switch (skb->ip_summed) {
171 case CHECKSUM_HW:
172 if (hook != NF_IP_PRE_ROUTING && hook != NF_IP_LOCAL_IN)
173 break;
174 if ((protocol == 0 && !(u16)csum_fold(skb->csum)) ||
175 !csum_tcpudp_magic(iph->saddr, iph->daddr,
176 skb->len - dataoff, protocol,
177 skb->csum)) {
178 skb->ip_summed = CHECKSUM_UNNECESSARY;
179 break;
180 }
181 /* fall through */
182 case CHECKSUM_NONE:
183 if (protocol == 0)
184 skb->csum = 0;
185 else
186 skb->csum = csum_tcpudp_nofold(iph->saddr, iph->daddr,
187 skb->len - dataoff,
188 protocol, 0);
189 csum = __skb_checksum_complete(skb);
190 }
191 return csum;
192}
193
194EXPORT_SYMBOL(nf_ip_checksum);
195
196static struct nf_afinfo nf_ip_afinfo = {
197 .family = AF_INET,
198 .checksum = nf_ip_checksum,
199 .saveroute = nf_ip_saveroute,
200 .reroute = nf_ip_reroute,
201 .route_key_size = sizeof(struct ip_rt_info),
168}; 202};
169 203
170static int ipv4_netfilter_init(void) 204static int ipv4_netfilter_init(void)
171{ 205{
172 return nf_register_queue_rerouter(PF_INET, &ip_reroute); 206 return nf_register_afinfo(&nf_ip_afinfo);
173} 207}
174 208
175static void ipv4_netfilter_fini(void) 209static void ipv4_netfilter_fini(void)
176{ 210{
177 nf_unregister_queue_rerouter(PF_INET); 211 nf_unregister_afinfo(&nf_ip_afinfo);
178} 212}
179 213
180module_init(ipv4_netfilter_init); 214module_init(ipv4_netfilter_init);
diff --git a/net/ipv4/netfilter/Kconfig b/net/ipv4/netfilter/Kconfig
index 77855ccd6b43..c60fd5c4ea1e 100644
--- a/net/ipv4/netfilter/Kconfig
+++ b/net/ipv4/netfilter/Kconfig
@@ -69,6 +69,7 @@ config IP_NF_CONNTRACK_NETLINK
69 tristate 'Connection tracking netlink interface (EXPERIMENTAL)' 69 tristate 'Connection tracking netlink interface (EXPERIMENTAL)'
70 depends on EXPERIMENTAL && IP_NF_CONNTRACK && NETFILTER_NETLINK 70 depends on EXPERIMENTAL && IP_NF_CONNTRACK && NETFILTER_NETLINK
71 depends on IP_NF_CONNTRACK!=y || NETFILTER_NETLINK!=m 71 depends on IP_NF_CONNTRACK!=y || NETFILTER_NETLINK!=m
72 depends on IP_NF_NAT=n || IP_NF_NAT
72 help 73 help
73 This option enables support for a netlink-based userspace interface 74 This option enables support for a netlink-based userspace interface
74 75
diff --git a/net/ipv4/netfilter/arptable_filter.c b/net/ipv4/netfilter/arptable_filter.c
index d0d379c7df9a..d7c472faa53b 100644
--- a/net/ipv4/netfilter/arptable_filter.c
+++ b/net/ipv4/netfilter/arptable_filter.c
@@ -181,33 +181,26 @@ static struct nf_hook_ops arpt_ops[] = {
181 181
182static int __init arptable_filter_init(void) 182static int __init arptable_filter_init(void)
183{ 183{
184 int ret, i; 184 int ret;
185 185
186 /* Register table */ 186 /* Register table */
187 ret = arpt_register_table(&packet_filter, &initial_table.repl); 187 ret = arpt_register_table(&packet_filter, &initial_table.repl);
188 if (ret < 0) 188 if (ret < 0)
189 return ret; 189 return ret;
190 190
191 for (i = 0; i < ARRAY_SIZE(arpt_ops); i++) 191 ret = nf_register_hooks(arpt_ops, ARRAY_SIZE(arpt_ops));
192 if ((ret = nf_register_hook(&arpt_ops[i])) < 0) 192 if (ret < 0)
193 goto cleanup_hooks; 193 goto cleanup_table;
194 return ret; 194 return ret;
195 195
196cleanup_hooks: 196cleanup_table:
197 while (--i >= 0)
198 nf_unregister_hook(&arpt_ops[i]);
199
200 arpt_unregister_table(&packet_filter); 197 arpt_unregister_table(&packet_filter);
201 return ret; 198 return ret;
202} 199}
203 200
204static void __exit arptable_filter_fini(void) 201static void __exit arptable_filter_fini(void)
205{ 202{
206 unsigned int i; 203 nf_unregister_hooks(arpt_ops, ARRAY_SIZE(arpt_ops));
207
208 for (i = 0; i < ARRAY_SIZE(arpt_ops); i++)
209 nf_unregister_hook(&arpt_ops[i]);
210
211 arpt_unregister_table(&packet_filter); 204 arpt_unregister_table(&packet_filter);
212} 205}
213 206
diff --git a/net/ipv4/netfilter/ip_conntrack_helper_h323.c b/net/ipv4/netfilter/ip_conntrack_helper_h323.c
index daeb1395faa4..2c2fb700d835 100644
--- a/net/ipv4/netfilter/ip_conntrack_helper_h323.c
+++ b/net/ipv4/netfilter/ip_conntrack_helper_h323.c
@@ -9,37 +9,6 @@
9 * Jozsef Kadlecsik <kadlec@blackhole.kfki.hu> 9 * Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
10 * 10 *
11 * For more information, please see http://nath323.sourceforge.net/ 11 * For more information, please see http://nath323.sourceforge.net/
12 *
13 * Changes:
14 * 2006-02-01 - initial version 0.1
15 *
16 * 2006-02-20 - version 0.2
17 * 1. Changed source format to follow kernel conventions
18 * 2. Deleted some unnecessary structures
19 * 3. Minor fixes
20 *
21 * 2006-03-10 - version 0.3
22 * 1. Added support for multiple TPKTs in one packet (suggested by
23 * Patrick McHardy)
24 * 2. Avoid excessive stack usage (based on Patrick McHardy's patch)
25 * 3. Added support for non-linear skb (based on Patrick McHardy's patch)
26 * 4. Fixed missing H.245 module owner (Patrick McHardy)
27 * 5. Avoid long RAS expectation chains (Patrick McHardy)
28 * 6. Fixed incorrect __exit attribute (Patrick McHardy)
29 * 7. Eliminated unnecessary return code
30 * 8. Fixed incorrect use of NAT data from conntrack code (suggested by
31 * Patrick McHardy)
32 * 9. Fixed TTL calculation error in RCF
33 * 10. Added TTL support in RRQ
34 * 11. Better support for separate TPKT header and data
35 *
36 * 2006-03-15 - version 0.4
37 * 1. Added support for T.120 channels
38 * 2. Added parameter gkrouted_only (suggested by Patrick McHardy)
39 * 3. Splitted ASN.1 code and data (suggested by Patrick McHardy)
40 * 4. Sort ASN.1 data to avoid forwarding declarations (suggested by
41 * Patrick McHardy)
42 * 5. Reset next TPKT data length in get_tpkt_data()
43 */ 12 */
44 13
45#include <linux/config.h> 14#include <linux/config.h>
@@ -54,8 +23,6 @@
54#include <linux/netfilter_ipv4/ip_conntrack_h323.h> 23#include <linux/netfilter_ipv4/ip_conntrack_h323.h>
55#include <linux/moduleparam.h> 24#include <linux/moduleparam.h>
56 25
57#include "ip_conntrack_helper_h323_asn1.h"
58
59#if 0 26#if 0
60#define DEBUGP printk 27#define DEBUGP printk
61#else 28#else
@@ -63,6 +30,10 @@
63#endif 30#endif
64 31
65/* Parameters */ 32/* Parameters */
33static unsigned int default_rrq_ttl = 300;
34module_param(default_rrq_ttl, uint, 0600);
35MODULE_PARM_DESC(default_rrq_ttl, "use this TTL if it's missing in RRQ");
36
66static int gkrouted_only = 1; 37static int gkrouted_only = 1;
67module_param(gkrouted_only, int, 0600); 38module_param(gkrouted_only, int, 0600);
68MODULE_PARM_DESC(gkrouted_only, "only accept calls from gatekeeper"); 39MODULE_PARM_DESC(gkrouted_only, "only accept calls from gatekeeper");
@@ -222,8 +193,8 @@ static int get_tpkt_data(struct sk_buff **pskb, struct ip_conntrack *ct,
222} 193}
223 194
224/****************************************************************************/ 195/****************************************************************************/
225int get_h245_addr(unsigned char *data, H245_TransportAddress * addr, 196static int get_h245_addr(unsigned char *data, H245_TransportAddress * addr,
226 u_int32_t * ip, u_int16_t * port) 197 u_int32_t * ip, u_int16_t * port)
227{ 198{
228 unsigned char *p; 199 unsigned char *p;
229 200
@@ -1302,7 +1273,7 @@ static int process_rrq(struct sk_buff **pskb, struct ip_conntrack *ct,
1302 DEBUGP("ip_ct_ras: RRQ TTL = %u seconds\n", rrq->timeToLive); 1273 DEBUGP("ip_ct_ras: RRQ TTL = %u seconds\n", rrq->timeToLive);
1303 info->timeout = rrq->timeToLive; 1274 info->timeout = rrq->timeToLive;
1304 } else 1275 } else
1305 info->timeout = 0; 1276 info->timeout = default_rrq_ttl;
1306 1277
1307 return 0; 1278 return 0;
1308} 1279}
@@ -1713,18 +1684,17 @@ static int __init init(void)
1713module_init(init); 1684module_init(init);
1714module_exit(fini); 1685module_exit(fini);
1715 1686
1716EXPORT_SYMBOL(get_h245_addr); 1687EXPORT_SYMBOL_GPL(get_h225_addr);
1717EXPORT_SYMBOL(get_h225_addr); 1688EXPORT_SYMBOL_GPL(ip_conntrack_h245_expect);
1718EXPORT_SYMBOL(ip_conntrack_h245_expect); 1689EXPORT_SYMBOL_GPL(ip_conntrack_q931_expect);
1719EXPORT_SYMBOL(ip_conntrack_q931_expect); 1690EXPORT_SYMBOL_GPL(set_h245_addr_hook);
1720EXPORT_SYMBOL(set_h245_addr_hook); 1691EXPORT_SYMBOL_GPL(set_h225_addr_hook);
1721EXPORT_SYMBOL(set_h225_addr_hook); 1692EXPORT_SYMBOL_GPL(set_sig_addr_hook);
1722EXPORT_SYMBOL(set_sig_addr_hook); 1693EXPORT_SYMBOL_GPL(set_ras_addr_hook);
1723EXPORT_SYMBOL(set_ras_addr_hook); 1694EXPORT_SYMBOL_GPL(nat_rtp_rtcp_hook);
1724EXPORT_SYMBOL(nat_rtp_rtcp_hook); 1695EXPORT_SYMBOL_GPL(nat_t120_hook);
1725EXPORT_SYMBOL(nat_t120_hook); 1696EXPORT_SYMBOL_GPL(nat_h245_hook);
1726EXPORT_SYMBOL(nat_h245_hook); 1697EXPORT_SYMBOL_GPL(nat_q931_hook);
1727EXPORT_SYMBOL(nat_q931_hook);
1728 1698
1729MODULE_AUTHOR("Jing Min Zhao <zhaojingmin@users.sourceforge.net>"); 1699MODULE_AUTHOR("Jing Min Zhao <zhaojingmin@users.sourceforge.net>");
1730MODULE_DESCRIPTION("H.323 connection tracking helper"); 1700MODULE_DESCRIPTION("H.323 connection tracking helper");
diff --git a/net/ipv4/netfilter/ip_conntrack_helper_h323_asn1.c b/net/ipv4/netfilter/ip_conntrack_helper_h323_asn1.c
index afa525129b51..48078002e450 100644
--- a/net/ipv4/netfilter/ip_conntrack_helper_h323_asn1.c
+++ b/net/ipv4/netfilter/ip_conntrack_helper_h323_asn1.c
@@ -15,7 +15,7 @@
15#else 15#else
16#include <stdio.h> 16#include <stdio.h>
17#endif 17#endif
18#include "ip_conntrack_helper_h323_asn1.h" 18#include <linux/netfilter_ipv4/ip_conntrack_helper_h323_asn1.h>
19 19
20/* Trace Flag */ 20/* Trace Flag */
21#ifndef H323_TRACE 21#ifndef H323_TRACE
diff --git a/net/ipv4/netfilter/ip_conntrack_proto_icmp.c b/net/ipv4/netfilter/ip_conntrack_proto_icmp.c
index 3021af0910f1..d8b14a9010a6 100644
--- a/net/ipv4/netfilter/ip_conntrack_proto_icmp.c
+++ b/net/ipv4/netfilter/ip_conntrack_proto_icmp.c
@@ -224,25 +224,14 @@ icmp_error(struct sk_buff *skb, enum ip_conntrack_info *ctinfo,
224 } 224 }
225 225
226 /* See ip_conntrack_proto_tcp.c */ 226 /* See ip_conntrack_proto_tcp.c */
227 if (hooknum != NF_IP_PRE_ROUTING) 227 if (hooknum == NF_IP_PRE_ROUTING &&
228 goto checksum_skipped; 228 nf_ip_checksum(skb, hooknum, skb->nh.iph->ihl * 4, 0)) {
229 229 if (LOG_INVALID(IPPROTO_ICMP))
230 switch (skb->ip_summed) { 230 nf_log_packet(PF_INET, 0, skb, NULL, NULL, NULL,
231 case CHECKSUM_HW: 231 "ip_ct_icmp: bad ICMP checksum ");
232 if (!(u16)csum_fold(skb->csum)) 232 return -NF_ACCEPT;
233 break;
234 /* fall through */
235 case CHECKSUM_NONE:
236 skb->csum = 0;
237 if (__skb_checksum_complete(skb)) {
238 if (LOG_INVALID(IPPROTO_ICMP))
239 nf_log_packet(PF_INET, 0, skb, NULL, NULL, NULL,
240 "ip_ct_icmp: bad ICMP checksum ");
241 return -NF_ACCEPT;
242 }
243 } 233 }
244 234
245checksum_skipped:
246 /* 235 /*
247 * 18 is the highest 'known' ICMP type. Anything else is a mystery 236 * 18 is the highest 'known' ICMP type. Anything else is a mystery
248 * 237 *
diff --git a/net/ipv4/netfilter/ip_conntrack_proto_tcp.c b/net/ipv4/netfilter/ip_conntrack_proto_tcp.c
index e0dc37063545..062b252b58ad 100644
--- a/net/ipv4/netfilter/ip_conntrack_proto_tcp.c
+++ b/net/ipv4/netfilter/ip_conntrack_proto_tcp.c
@@ -870,11 +870,8 @@ static int tcp_error(struct sk_buff *skb,
870 * and moreover root might send raw packets. 870 * and moreover root might send raw packets.
871 */ 871 */
872 /* FIXME: Source route IP option packets --RR */ 872 /* FIXME: Source route IP option packets --RR */
873 if (hooknum == NF_IP_PRE_ROUTING 873 if (hooknum == NF_IP_PRE_ROUTING &&
874 && skb->ip_summed != CHECKSUM_UNNECESSARY 874 nf_ip_checksum(skb, hooknum, iph->ihl * 4, IPPROTO_TCP)) {
875 && csum_tcpudp_magic(iph->saddr, iph->daddr, tcplen, IPPROTO_TCP,
876 skb->ip_summed == CHECKSUM_HW ? skb->csum
877 : skb_checksum(skb, iph->ihl*4, tcplen, 0))) {
878 if (LOG_INVALID(IPPROTO_TCP)) 875 if (LOG_INVALID(IPPROTO_TCP))
879 nf_log_packet(PF_INET, 0, skb, NULL, NULL, NULL, 876 nf_log_packet(PF_INET, 0, skb, NULL, NULL, NULL,
880 "ip_ct_tcp: bad TCP checksum "); 877 "ip_ct_tcp: bad TCP checksum ");
diff --git a/net/ipv4/netfilter/ip_conntrack_proto_udp.c b/net/ipv4/netfilter/ip_conntrack_proto_udp.c
index 55b7d3210adf..70899868783b 100644
--- a/net/ipv4/netfilter/ip_conntrack_proto_udp.c
+++ b/net/ipv4/netfilter/ip_conntrack_proto_udp.c
@@ -120,11 +120,8 @@ static int udp_error(struct sk_buff *skb, enum ip_conntrack_info *ctinfo,
120 * because the semantic of CHECKSUM_HW is different there 120 * because the semantic of CHECKSUM_HW is different there
121 * and moreover root might send raw packets. 121 * and moreover root might send raw packets.
122 * FIXME: Source route IP option packets --RR */ 122 * FIXME: Source route IP option packets --RR */
123 if (hooknum == NF_IP_PRE_ROUTING 123 if (hooknum == NF_IP_PRE_ROUTING &&
124 && skb->ip_summed != CHECKSUM_UNNECESSARY 124 nf_ip_checksum(skb, hooknum, iph->ihl * 4, IPPROTO_UDP)) {
125 && csum_tcpudp_magic(iph->saddr, iph->daddr, udplen, IPPROTO_UDP,
126 skb->ip_summed == CHECKSUM_HW ? skb->csum
127 : skb_checksum(skb, iph->ihl*4, udplen, 0))) {
128 if (LOG_INVALID(IPPROTO_UDP)) 125 if (LOG_INVALID(IPPROTO_UDP))
129 nf_log_packet(PF_INET, 0, skb, NULL, NULL, NULL, 126 nf_log_packet(PF_INET, 0, skb, NULL, NULL, NULL,
130 "ip_ct_udp: bad UDP checksum "); 127 "ip_ct_udp: bad UDP checksum ");
diff --git a/net/ipv4/netfilter/ip_conntrack_standalone.c b/net/ipv4/netfilter/ip_conntrack_standalone.c
index 52076026db36..929d61f7be91 100644
--- a/net/ipv4/netfilter/ip_conntrack_standalone.c
+++ b/net/ipv4/netfilter/ip_conntrack_standalone.c
@@ -469,70 +469,63 @@ static unsigned int ip_conntrack_local(unsigned int hooknum,
469 469
470/* Connection tracking may drop packets, but never alters them, so 470/* Connection tracking may drop packets, but never alters them, so
471 make it the first hook. */ 471 make it the first hook. */
472static struct nf_hook_ops ip_conntrack_defrag_ops = { 472static struct nf_hook_ops ip_conntrack_ops[] = {
473 .hook = ip_conntrack_defrag, 473 {
474 .owner = THIS_MODULE, 474 .hook = ip_conntrack_defrag,
475 .pf = PF_INET, 475 .owner = THIS_MODULE,
476 .hooknum = NF_IP_PRE_ROUTING, 476 .pf = PF_INET,
477 .priority = NF_IP_PRI_CONNTRACK_DEFRAG, 477 .hooknum = NF_IP_PRE_ROUTING,
478}; 478 .priority = NF_IP_PRI_CONNTRACK_DEFRAG,
479 479 },
480static struct nf_hook_ops ip_conntrack_in_ops = { 480 {
481 .hook = ip_conntrack_in, 481 .hook = ip_conntrack_in,
482 .owner = THIS_MODULE, 482 .owner = THIS_MODULE,
483 .pf = PF_INET, 483 .pf = PF_INET,
484 .hooknum = NF_IP_PRE_ROUTING, 484 .hooknum = NF_IP_PRE_ROUTING,
485 .priority = NF_IP_PRI_CONNTRACK, 485 .priority = NF_IP_PRI_CONNTRACK,
486}; 486 },
487 487 {
488static struct nf_hook_ops ip_conntrack_defrag_local_out_ops = { 488 .hook = ip_conntrack_defrag,
489 .hook = ip_conntrack_defrag, 489 .owner = THIS_MODULE,
490 .owner = THIS_MODULE, 490 .pf = PF_INET,
491 .pf = PF_INET, 491 .hooknum = NF_IP_LOCAL_OUT,
492 .hooknum = NF_IP_LOCAL_OUT, 492 .priority = NF_IP_PRI_CONNTRACK_DEFRAG,
493 .priority = NF_IP_PRI_CONNTRACK_DEFRAG, 493 },
494}; 494 {
495 495 .hook = ip_conntrack_local,
496static struct nf_hook_ops ip_conntrack_local_out_ops = { 496 .owner = THIS_MODULE,
497 .hook = ip_conntrack_local, 497 .pf = PF_INET,
498 .owner = THIS_MODULE, 498 .hooknum = NF_IP_LOCAL_OUT,
499 .pf = PF_INET, 499 .priority = NF_IP_PRI_CONNTRACK,
500 .hooknum = NF_IP_LOCAL_OUT, 500 },
501 .priority = NF_IP_PRI_CONNTRACK, 501 {
502}; 502 .hook = ip_conntrack_help,
503 503 .owner = THIS_MODULE,
504/* helpers */ 504 .pf = PF_INET,
505static struct nf_hook_ops ip_conntrack_helper_out_ops = { 505 .hooknum = NF_IP_POST_ROUTING,
506 .hook = ip_conntrack_help, 506 .priority = NF_IP_PRI_CONNTRACK_HELPER,
507 .owner = THIS_MODULE, 507 },
508 .pf = PF_INET, 508 {
509 .hooknum = NF_IP_POST_ROUTING, 509 .hook = ip_conntrack_help,
510 .priority = NF_IP_PRI_CONNTRACK_HELPER, 510 .owner = THIS_MODULE,
511}; 511 .pf = PF_INET,
512 512 .hooknum = NF_IP_LOCAL_IN,
513static struct nf_hook_ops ip_conntrack_helper_in_ops = { 513 .priority = NF_IP_PRI_CONNTRACK_HELPER,
514 .hook = ip_conntrack_help, 514 },
515 .owner = THIS_MODULE, 515 {
516 .pf = PF_INET, 516 .hook = ip_confirm,
517 .hooknum = NF_IP_LOCAL_IN, 517 .owner = THIS_MODULE,
518 .priority = NF_IP_PRI_CONNTRACK_HELPER, 518 .pf = PF_INET,
519}; 519 .hooknum = NF_IP_POST_ROUTING,
520 520 .priority = NF_IP_PRI_CONNTRACK_CONFIRM,
521/* Refragmenter; last chance. */ 521 },
522static struct nf_hook_ops ip_conntrack_out_ops = { 522 {
523 .hook = ip_confirm, 523 .hook = ip_confirm,
524 .owner = THIS_MODULE, 524 .owner = THIS_MODULE,
525 .pf = PF_INET, 525 .pf = PF_INET,
526 .hooknum = NF_IP_POST_ROUTING, 526 .hooknum = NF_IP_LOCAL_IN,
527 .priority = NF_IP_PRI_CONNTRACK_CONFIRM, 527 .priority = NF_IP_PRI_CONNTRACK_CONFIRM,
528}; 528 },
529
530static struct nf_hook_ops ip_conntrack_local_in_ops = {
531 .hook = ip_confirm,
532 .owner = THIS_MODULE,
533 .pf = PF_INET,
534 .hooknum = NF_IP_LOCAL_IN,
535 .priority = NF_IP_PRI_CONNTRACK_CONFIRM,
536}; 529};
537 530
538/* Sysctl support */ 531/* Sysctl support */
@@ -783,18 +776,46 @@ static ctl_table ip_ct_net_table[] = {
783EXPORT_SYMBOL(ip_ct_log_invalid); 776EXPORT_SYMBOL(ip_ct_log_invalid);
784#endif /* CONFIG_SYSCTL */ 777#endif /* CONFIG_SYSCTL */
785 778
786static int init_or_cleanup(int init) 779/* FIXME: Allow NULL functions and sub in pointers to generic for
780 them. --RR */
781int ip_conntrack_protocol_register(struct ip_conntrack_protocol *proto)
782{
783 int ret = 0;
784
785 write_lock_bh(&ip_conntrack_lock);
786 if (ip_ct_protos[proto->proto] != &ip_conntrack_generic_protocol) {
787 ret = -EBUSY;
788 goto out;
789 }
790 ip_ct_protos[proto->proto] = proto;
791 out:
792 write_unlock_bh(&ip_conntrack_lock);
793 return ret;
794}
795
796void ip_conntrack_protocol_unregister(struct ip_conntrack_protocol *proto)
797{
798 write_lock_bh(&ip_conntrack_lock);
799 ip_ct_protos[proto->proto] = &ip_conntrack_generic_protocol;
800 write_unlock_bh(&ip_conntrack_lock);
801
802 /* Somebody could be still looking at the proto in bh. */
803 synchronize_net();
804
805 /* Remove all contrack entries for this protocol */
806 ip_ct_iterate_cleanup(kill_proto, &proto->proto);
807}
808
809static int __init ip_conntrack_standalone_init(void)
787{ 810{
788#ifdef CONFIG_PROC_FS 811#ifdef CONFIG_PROC_FS
789 struct proc_dir_entry *proc, *proc_exp, *proc_stat; 812 struct proc_dir_entry *proc, *proc_exp, *proc_stat;
790#endif 813#endif
791 int ret = 0; 814 int ret = 0;
792 815
793 if (!init) goto cleanup;
794
795 ret = ip_conntrack_init(); 816 ret = ip_conntrack_init();
796 if (ret < 0) 817 if (ret < 0)
797 goto cleanup_nothing; 818 return ret;
798 819
799#ifdef CONFIG_PROC_FS 820#ifdef CONFIG_PROC_FS
800 ret = -ENOMEM; 821 ret = -ENOMEM;
@@ -813,78 +834,25 @@ static int init_or_cleanup(int init)
813 proc_stat->owner = THIS_MODULE; 834 proc_stat->owner = THIS_MODULE;
814#endif 835#endif
815 836
816 ret = nf_register_hook(&ip_conntrack_defrag_ops); 837 ret = nf_register_hooks(ip_conntrack_ops, ARRAY_SIZE(ip_conntrack_ops));
817 if (ret < 0) { 838 if (ret < 0) {
818 printk("ip_conntrack: can't register pre-routing defrag hook.\n"); 839 printk("ip_conntrack: can't register hooks.\n");
819 goto cleanup_proc_stat; 840 goto cleanup_proc_stat;
820 } 841 }
821 ret = nf_register_hook(&ip_conntrack_defrag_local_out_ops);
822 if (ret < 0) {
823 printk("ip_conntrack: can't register local_out defrag hook.\n");
824 goto cleanup_defragops;
825 }
826 ret = nf_register_hook(&ip_conntrack_in_ops);
827 if (ret < 0) {
828 printk("ip_conntrack: can't register pre-routing hook.\n");
829 goto cleanup_defraglocalops;
830 }
831 ret = nf_register_hook(&ip_conntrack_local_out_ops);
832 if (ret < 0) {
833 printk("ip_conntrack: can't register local out hook.\n");
834 goto cleanup_inops;
835 }
836 ret = nf_register_hook(&ip_conntrack_helper_in_ops);
837 if (ret < 0) {
838 printk("ip_conntrack: can't register local in helper hook.\n");
839 goto cleanup_inandlocalops;
840 }
841 ret = nf_register_hook(&ip_conntrack_helper_out_ops);
842 if (ret < 0) {
843 printk("ip_conntrack: can't register postrouting helper hook.\n");
844 goto cleanup_helperinops;
845 }
846 ret = nf_register_hook(&ip_conntrack_out_ops);
847 if (ret < 0) {
848 printk("ip_conntrack: can't register post-routing hook.\n");
849 goto cleanup_helperoutops;
850 }
851 ret = nf_register_hook(&ip_conntrack_local_in_ops);
852 if (ret < 0) {
853 printk("ip_conntrack: can't register local in hook.\n");
854 goto cleanup_inoutandlocalops;
855 }
856#ifdef CONFIG_SYSCTL 842#ifdef CONFIG_SYSCTL
857 ip_ct_sysctl_header = register_sysctl_table(ip_ct_net_table, 0); 843 ip_ct_sysctl_header = register_sysctl_table(ip_ct_net_table, 0);
858 if (ip_ct_sysctl_header == NULL) { 844 if (ip_ct_sysctl_header == NULL) {
859 printk("ip_conntrack: can't register to sysctl.\n"); 845 printk("ip_conntrack: can't register to sysctl.\n");
860 ret = -ENOMEM; 846 ret = -ENOMEM;
861 goto cleanup_localinops; 847 goto cleanup_hooks;
862 } 848 }
863#endif 849#endif
864
865 return ret; 850 return ret;
866 851
867 cleanup:
868 synchronize_net();
869#ifdef CONFIG_SYSCTL 852#ifdef CONFIG_SYSCTL
870 unregister_sysctl_table(ip_ct_sysctl_header); 853 cleanup_hooks:
871 cleanup_localinops: 854 nf_unregister_hooks(ip_conntrack_ops, ARRAY_SIZE(ip_conntrack_ops));
872#endif 855#endif
873 nf_unregister_hook(&ip_conntrack_local_in_ops);
874 cleanup_inoutandlocalops:
875 nf_unregister_hook(&ip_conntrack_out_ops);
876 cleanup_helperoutops:
877 nf_unregister_hook(&ip_conntrack_helper_out_ops);
878 cleanup_helperinops:
879 nf_unregister_hook(&ip_conntrack_helper_in_ops);
880 cleanup_inandlocalops:
881 nf_unregister_hook(&ip_conntrack_local_out_ops);
882 cleanup_inops:
883 nf_unregister_hook(&ip_conntrack_in_ops);
884 cleanup_defraglocalops:
885 nf_unregister_hook(&ip_conntrack_defrag_local_out_ops);
886 cleanup_defragops:
887 nf_unregister_hook(&ip_conntrack_defrag_ops);
888 cleanup_proc_stat: 856 cleanup_proc_stat:
889#ifdef CONFIG_PROC_FS 857#ifdef CONFIG_PROC_FS
890 remove_proc_entry("ip_conntrack", proc_net_stat); 858 remove_proc_entry("ip_conntrack", proc_net_stat);
@@ -895,48 +863,22 @@ static int init_or_cleanup(int init)
895 cleanup_init: 863 cleanup_init:
896#endif /* CONFIG_PROC_FS */ 864#endif /* CONFIG_PROC_FS */
897 ip_conntrack_cleanup(); 865 ip_conntrack_cleanup();
898 cleanup_nothing:
899 return ret;
900}
901
902/* FIXME: Allow NULL functions and sub in pointers to generic for
903 them. --RR */
904int ip_conntrack_protocol_register(struct ip_conntrack_protocol *proto)
905{
906 int ret = 0;
907
908 write_lock_bh(&ip_conntrack_lock);
909 if (ip_ct_protos[proto->proto] != &ip_conntrack_generic_protocol) {
910 ret = -EBUSY;
911 goto out;
912 }
913 ip_ct_protos[proto->proto] = proto;
914 out:
915 write_unlock_bh(&ip_conntrack_lock);
916 return ret; 866 return ret;
917} 867}
918 868
919void ip_conntrack_protocol_unregister(struct ip_conntrack_protocol *proto)
920{
921 write_lock_bh(&ip_conntrack_lock);
922 ip_ct_protos[proto->proto] = &ip_conntrack_generic_protocol;
923 write_unlock_bh(&ip_conntrack_lock);
924
925 /* Somebody could be still looking at the proto in bh. */
926 synchronize_net();
927
928 /* Remove all contrack entries for this protocol */
929 ip_ct_iterate_cleanup(kill_proto, &proto->proto);
930}
931
932static int __init ip_conntrack_standalone_init(void)
933{
934 return init_or_cleanup(1);
935}
936
937static void __exit ip_conntrack_standalone_fini(void) 869static void __exit ip_conntrack_standalone_fini(void)
938{ 870{
939 init_or_cleanup(0); 871 synchronize_net();
872#ifdef CONFIG_SYSCTL
873 unregister_sysctl_table(ip_ct_sysctl_header);
874#endif
875 nf_unregister_hooks(ip_conntrack_ops, ARRAY_SIZE(ip_conntrack_ops));
876#ifdef CONFIG_PROC_FS
877 remove_proc_entry("ip_conntrack", proc_net_stat);
878 proc_net_remove("ip_conntrack_expect");
879 proc_net_remove("ip_conntrack");
880#endif /* CONFIG_PROC_FS */
881 ip_conntrack_cleanup();
940} 882}
941 883
942module_init(ip_conntrack_standalone_init); 884module_init(ip_conntrack_standalone_init);
diff --git a/net/ipv4/netfilter/ip_nat_helper_h323.c b/net/ipv4/netfilter/ip_nat_helper_h323.c
index a0bc883928c0..d45663d137a7 100644
--- a/net/ipv4/netfilter/ip_nat_helper_h323.c
+++ b/net/ipv4/netfilter/ip_nat_helper_h323.c
@@ -7,24 +7,6 @@
7 * 7 *
8 * Based on the 'brute force' H.323 NAT module by 8 * Based on the 'brute force' H.323 NAT module by
9 * Jozsef Kadlecsik <kadlec@blackhole.kfki.hu> 9 * Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
10 *
11 * Changes:
12 * 2006-02-01 - initial version 0.1
13 *
14 * 2006-02-20 - version 0.2
15 * 1. Changed source format to follow kernel conventions
16 * 2. Deleted some unnecessary structures
17 * 3. Minor fixes
18 *
19 * 2006-03-10 - version 0.3
20 * 1. Added support for multiple TPKTs in one packet (suggested by
21 * Patrick McHardy)
22 * 2. Added support for non-linear skb (based on Patrick McHardy's patch)
23 * 3. Eliminated unnecessary return code
24 *
25 * 2006-03-15 - version 0.4
26 * 1. Added support for T.120 channels
27 * 2. Added parameter gkrouted_only (suggested by Patrick McHardy)
28 */ 10 */
29 11
30#include <linux/module.h> 12#include <linux/module.h>
@@ -41,65 +23,12 @@
41#include <linux/netfilter_ipv4/ip_conntrack_h323.h> 23#include <linux/netfilter_ipv4/ip_conntrack_h323.h>
42#include <linux/netfilter_ipv4/ip_conntrack_helper.h> 24#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
43 25
44#include "ip_conntrack_helper_h323_asn1.h"
45
46#if 0 26#if 0
47#define DEBUGP printk 27#define DEBUGP printk
48#else 28#else
49#define DEBUGP(format, args...) 29#define DEBUGP(format, args...)
50#endif 30#endif
51 31
52extern int get_h245_addr(unsigned char *data, H245_TransportAddress * addr,
53 u_int32_t * ip, u_int16_t * port);
54extern int get_h225_addr(unsigned char *data, TransportAddress * addr,
55 u_int32_t * ip, u_int16_t * port);
56extern void ip_conntrack_h245_expect(struct ip_conntrack *new,
57 struct ip_conntrack_expect *this);
58extern void ip_conntrack_q931_expect(struct ip_conntrack *new,
59 struct ip_conntrack_expect *this);
60extern int (*set_h245_addr_hook) (struct sk_buff ** pskb,
61 unsigned char **data, int dataoff,
62 H245_TransportAddress * addr,
63 u_int32_t ip, u_int16_t port);
64extern int (*set_h225_addr_hook) (struct sk_buff ** pskb,
65 unsigned char **data, int dataoff,
66 TransportAddress * addr,
67 u_int32_t ip, u_int16_t port);
68extern int (*set_sig_addr_hook) (struct sk_buff ** pskb,
69 struct ip_conntrack * ct,
70 enum ip_conntrack_info ctinfo,
71 unsigned char **data,
72 TransportAddress * addr, int count);
73extern int (*set_ras_addr_hook) (struct sk_buff ** pskb,
74 struct ip_conntrack * ct,
75 enum ip_conntrack_info ctinfo,
76 unsigned char **data,
77 TransportAddress * addr, int count);
78extern int (*nat_rtp_rtcp_hook) (struct sk_buff ** pskb,
79 struct ip_conntrack * ct,
80 enum ip_conntrack_info ctinfo,
81 unsigned char **data, int dataoff,
82 H245_TransportAddress * addr,
83 u_int16_t port, u_int16_t rtp_port,
84 struct ip_conntrack_expect * rtp_exp,
85 struct ip_conntrack_expect * rtcp_exp);
86extern int (*nat_t120_hook) (struct sk_buff ** pskb, struct ip_conntrack * ct,
87 enum ip_conntrack_info ctinfo,
88 unsigned char **data, int dataoff,
89 H245_TransportAddress * addr, u_int16_t port,
90 struct ip_conntrack_expect * exp);
91extern int (*nat_h245_hook) (struct sk_buff ** pskb, struct ip_conntrack * ct,
92 enum ip_conntrack_info ctinfo,
93 unsigned char **data, int dataoff,
94 TransportAddress * addr, u_int16_t port,
95 struct ip_conntrack_expect * exp);
96extern int (*nat_q931_hook) (struct sk_buff ** pskb, struct ip_conntrack * ct,
97 enum ip_conntrack_info ctinfo,
98 unsigned char **data, TransportAddress * addr,
99 int idx, u_int16_t port,
100 struct ip_conntrack_expect * exp);
101
102
103/****************************************************************************/ 32/****************************************************************************/
104static int set_addr(struct sk_buff **pskb, 33static int set_addr(struct sk_buff **pskb,
105 unsigned char **data, int dataoff, 34 unsigned char **data, int dataoff,
diff --git a/net/ipv4/netfilter/ip_nat_rule.c b/net/ipv4/netfilter/ip_nat_rule.c
index efba8c4e42e0..1aba926c1cb0 100644
--- a/net/ipv4/netfilter/ip_nat_rule.c
+++ b/net/ipv4/netfilter/ip_nat_rule.c
@@ -279,7 +279,7 @@ static struct ipt_target ipt_dnat_reg = {
279 .target = ipt_dnat_target, 279 .target = ipt_dnat_target,
280 .targetsize = sizeof(struct ip_nat_multi_range_compat), 280 .targetsize = sizeof(struct ip_nat_multi_range_compat),
281 .table = "nat", 281 .table = "nat",
282 .hooks = 1 << NF_IP_PRE_ROUTING, 282 .hooks = (1 << NF_IP_PRE_ROUTING) | (1 << NF_IP_LOCAL_OUT),
283 .checkentry = ipt_dnat_checkentry, 283 .checkentry = ipt_dnat_checkentry,
284}; 284};
285 285
diff --git a/net/ipv4/netfilter/ip_nat_standalone.c b/net/ipv4/netfilter/ip_nat_standalone.c
index 3505b0de2e04..8f760b28617e 100644
--- a/net/ipv4/netfilter/ip_nat_standalone.c
+++ b/net/ipv4/netfilter/ip_nat_standalone.c
@@ -299,69 +299,63 @@ ip_nat_adjust(unsigned int hooknum,
299 299
300/* We must be after connection tracking and before packet filtering. */ 300/* We must be after connection tracking and before packet filtering. */
301 301
302/* Before packet filtering, change destination */ 302static struct nf_hook_ops ip_nat_ops[] = {
303static struct nf_hook_ops ip_nat_in_ops = { 303 /* Before packet filtering, change destination */
304 .hook = ip_nat_in, 304 {
305 .owner = THIS_MODULE, 305 .hook = ip_nat_in,
306 .pf = PF_INET, 306 .owner = THIS_MODULE,
307 .hooknum = NF_IP_PRE_ROUTING, 307 .pf = PF_INET,
308 .priority = NF_IP_PRI_NAT_DST, 308 .hooknum = NF_IP_PRE_ROUTING,
309 .priority = NF_IP_PRI_NAT_DST,
310 },
311 /* After packet filtering, change source */
312 {
313 .hook = ip_nat_out,
314 .owner = THIS_MODULE,
315 .pf = PF_INET,
316 .hooknum = NF_IP_POST_ROUTING,
317 .priority = NF_IP_PRI_NAT_SRC,
318 },
319 /* After conntrack, adjust sequence number */
320 {
321 .hook = ip_nat_adjust,
322 .owner = THIS_MODULE,
323 .pf = PF_INET,
324 .hooknum = NF_IP_POST_ROUTING,
325 .priority = NF_IP_PRI_NAT_SEQ_ADJUST,
326 },
327 /* Before packet filtering, change destination */
328 {
329 .hook = ip_nat_local_fn,
330 .owner = THIS_MODULE,
331 .pf = PF_INET,
332 .hooknum = NF_IP_LOCAL_OUT,
333 .priority = NF_IP_PRI_NAT_DST,
334 },
335 /* After packet filtering, change source */
336 {
337 .hook = ip_nat_fn,
338 .owner = THIS_MODULE,
339 .pf = PF_INET,
340 .hooknum = NF_IP_LOCAL_IN,
341 .priority = NF_IP_PRI_NAT_SRC,
342 },
343 /* After conntrack, adjust sequence number */
344 {
345 .hook = ip_nat_adjust,
346 .owner = THIS_MODULE,
347 .pf = PF_INET,
348 .hooknum = NF_IP_LOCAL_IN,
349 .priority = NF_IP_PRI_NAT_SEQ_ADJUST,
350 },
309}; 351};
310 352
311/* After packet filtering, change source */ 353static int __init ip_nat_standalone_init(void)
312static struct nf_hook_ops ip_nat_out_ops = {
313 .hook = ip_nat_out,
314 .owner = THIS_MODULE,
315 .pf = PF_INET,
316 .hooknum = NF_IP_POST_ROUTING,
317 .priority = NF_IP_PRI_NAT_SRC,
318};
319
320/* After conntrack, adjust sequence number */
321static struct nf_hook_ops ip_nat_adjust_out_ops = {
322 .hook = ip_nat_adjust,
323 .owner = THIS_MODULE,
324 .pf = PF_INET,
325 .hooknum = NF_IP_POST_ROUTING,
326 .priority = NF_IP_PRI_NAT_SEQ_ADJUST,
327};
328
329/* Before packet filtering, change destination */
330static struct nf_hook_ops ip_nat_local_out_ops = {
331 .hook = ip_nat_local_fn,
332 .owner = THIS_MODULE,
333 .pf = PF_INET,
334 .hooknum = NF_IP_LOCAL_OUT,
335 .priority = NF_IP_PRI_NAT_DST,
336};
337
338/* After packet filtering, change source for reply packets of LOCAL_OUT DNAT */
339static struct nf_hook_ops ip_nat_local_in_ops = {
340 .hook = ip_nat_fn,
341 .owner = THIS_MODULE,
342 .pf = PF_INET,
343 .hooknum = NF_IP_LOCAL_IN,
344 .priority = NF_IP_PRI_NAT_SRC,
345};
346
347/* After conntrack, adjust sequence number */
348static struct nf_hook_ops ip_nat_adjust_in_ops = {
349 .hook = ip_nat_adjust,
350 .owner = THIS_MODULE,
351 .pf = PF_INET,
352 .hooknum = NF_IP_LOCAL_IN,
353 .priority = NF_IP_PRI_NAT_SEQ_ADJUST,
354};
355
356
357static int init_or_cleanup(int init)
358{ 354{
359 int ret = 0; 355 int ret = 0;
360 356
361 need_conntrack(); 357 need_conntrack();
362 358
363 if (!init) goto cleanup;
364
365#ifdef CONFIG_XFRM 359#ifdef CONFIG_XFRM
366 BUG_ON(ip_nat_decode_session != NULL); 360 BUG_ON(ip_nat_decode_session != NULL);
367 ip_nat_decode_session = nat_decode_session; 361 ip_nat_decode_session = nat_decode_session;
@@ -371,50 +365,13 @@ static int init_or_cleanup(int init)
371 printk("ip_nat_init: can't setup rules.\n"); 365 printk("ip_nat_init: can't setup rules.\n");
372 goto cleanup_decode_session; 366 goto cleanup_decode_session;
373 } 367 }
374 ret = nf_register_hook(&ip_nat_in_ops); 368 ret = nf_register_hooks(ip_nat_ops, ARRAY_SIZE(ip_nat_ops));
375 if (ret < 0) { 369 if (ret < 0) {
376 printk("ip_nat_init: can't register in hook.\n"); 370 printk("ip_nat_init: can't register hooks.\n");
377 goto cleanup_rule_init; 371 goto cleanup_rule_init;
378 } 372 }
379 ret = nf_register_hook(&ip_nat_out_ops);
380 if (ret < 0) {
381 printk("ip_nat_init: can't register out hook.\n");
382 goto cleanup_inops;
383 }
384 ret = nf_register_hook(&ip_nat_adjust_in_ops);
385 if (ret < 0) {
386 printk("ip_nat_init: can't register adjust in hook.\n");
387 goto cleanup_outops;
388 }
389 ret = nf_register_hook(&ip_nat_adjust_out_ops);
390 if (ret < 0) {
391 printk("ip_nat_init: can't register adjust out hook.\n");
392 goto cleanup_adjustin_ops;
393 }
394 ret = nf_register_hook(&ip_nat_local_out_ops);
395 if (ret < 0) {
396 printk("ip_nat_init: can't register local out hook.\n");
397 goto cleanup_adjustout_ops;
398 }
399 ret = nf_register_hook(&ip_nat_local_in_ops);
400 if (ret < 0) {
401 printk("ip_nat_init: can't register local in hook.\n");
402 goto cleanup_localoutops;
403 }
404 return ret; 373 return ret;
405 374
406 cleanup:
407 nf_unregister_hook(&ip_nat_local_in_ops);
408 cleanup_localoutops:
409 nf_unregister_hook(&ip_nat_local_out_ops);
410 cleanup_adjustout_ops:
411 nf_unregister_hook(&ip_nat_adjust_out_ops);
412 cleanup_adjustin_ops:
413 nf_unregister_hook(&ip_nat_adjust_in_ops);
414 cleanup_outops:
415 nf_unregister_hook(&ip_nat_out_ops);
416 cleanup_inops:
417 nf_unregister_hook(&ip_nat_in_ops);
418 cleanup_rule_init: 375 cleanup_rule_init:
419 ip_nat_rule_cleanup(); 376 ip_nat_rule_cleanup();
420 cleanup_decode_session: 377 cleanup_decode_session:
@@ -425,14 +382,14 @@ static int init_or_cleanup(int init)
425 return ret; 382 return ret;
426} 383}
427 384
428static int __init ip_nat_standalone_init(void)
429{
430 return init_or_cleanup(1);
431}
432
433static void __exit ip_nat_standalone_fini(void) 385static void __exit ip_nat_standalone_fini(void)
434{ 386{
435 init_or_cleanup(0); 387 nf_unregister_hooks(ip_nat_ops, ARRAY_SIZE(ip_nat_ops));
388 ip_nat_rule_cleanup();
389#ifdef CONFIG_XFRM
390 ip_nat_decode_session = NULL;
391 synchronize_net();
392#endif
436} 393}
437 394
438module_init(ip_nat_standalone_init); 395module_init(ip_nat_standalone_init);
diff --git a/net/ipv4/netfilter/ip_queue.c b/net/ipv4/netfilter/ip_queue.c
index 896a244f8f91..b93f0494362f 100644
--- a/net/ipv4/netfilter/ip_queue.c
+++ b/net/ipv4/netfilter/ip_queue.c
@@ -662,15 +662,11 @@ static struct nf_queue_handler nfqh = {
662 .outfn = &ipq_enqueue_packet, 662 .outfn = &ipq_enqueue_packet,
663}; 663};
664 664
665static int 665static int __init ip_queue_init(void)
666init_or_cleanup(int init)
667{ 666{
668 int status = -ENOMEM; 667 int status = -ENOMEM;
669 struct proc_dir_entry *proc; 668 struct proc_dir_entry *proc;
670 669
671 if (!init)
672 goto cleanup;
673
674 netlink_register_notifier(&ipq_nl_notifier); 670 netlink_register_notifier(&ipq_nl_notifier);
675 ipqnl = netlink_kernel_create(NETLINK_FIREWALL, 0, ipq_rcv_sk, 671 ipqnl = netlink_kernel_create(NETLINK_FIREWALL, 0, ipq_rcv_sk,
676 THIS_MODULE); 672 THIS_MODULE);
@@ -697,11 +693,6 @@ init_or_cleanup(int init)
697 } 693 }
698 return status; 694 return status;
699 695
700cleanup:
701 nf_unregister_queue_handlers(&nfqh);
702 synchronize_net();
703 ipq_flush(NF_DROP);
704
705cleanup_sysctl: 696cleanup_sysctl:
706 unregister_sysctl_table(ipq_sysctl_header); 697 unregister_sysctl_table(ipq_sysctl_header);
707 unregister_netdevice_notifier(&ipq_dev_notifier); 698 unregister_netdevice_notifier(&ipq_dev_notifier);
@@ -717,15 +708,21 @@ cleanup_netlink_notifier:
717 return status; 708 return status;
718} 709}
719 710
720static int __init ip_queue_init(void)
721{
722
723 return init_or_cleanup(1);
724}
725
726static void __exit ip_queue_fini(void) 711static void __exit ip_queue_fini(void)
727{ 712{
728 init_or_cleanup(0); 713 nf_unregister_queue_handlers(&nfqh);
714 synchronize_net();
715 ipq_flush(NF_DROP);
716
717 unregister_sysctl_table(ipq_sysctl_header);
718 unregister_netdevice_notifier(&ipq_dev_notifier);
719 proc_net_remove(IPQ_PROC_FS_NAME);
720
721 sock_release(ipqnl->sk_socket);
722 mutex_lock(&ipqnl_mutex);
723 mutex_unlock(&ipqnl_mutex);
724
725 netlink_unregister_notifier(&ipq_nl_notifier);
729} 726}
730 727
731MODULE_DESCRIPTION("IPv4 packet queue handler"); 728MODULE_DESCRIPTION("IPv4 packet queue handler");
diff --git a/net/ipv4/netfilter/ipt_CLUSTERIP.c b/net/ipv4/netfilter/ipt_CLUSTERIP.c
index e4768a31718b..aad9d28c8d71 100644
--- a/net/ipv4/netfilter/ipt_CLUSTERIP.c
+++ b/net/ipv4/netfilter/ipt_CLUSTERIP.c
@@ -725,22 +725,17 @@ static struct file_operations clusterip_proc_fops = {
725 725
726#endif /* CONFIG_PROC_FS */ 726#endif /* CONFIG_PROC_FS */
727 727
728static int init_or_cleanup(int fini) 728static int __init ipt_clusterip_init(void)
729{ 729{
730 int ret; 730 int ret;
731 731
732 if (fini) 732 ret = ipt_register_target(&clusterip_tgt);
733 goto cleanup; 733 if (ret < 0)
734 734 return ret;
735 if (ipt_register_target(&clusterip_tgt)) {
736 ret = -EINVAL;
737 goto cleanup_none;
738 }
739 735
740 if (nf_register_hook(&cip_arp_ops) < 0) { 736 ret = nf_register_hook(&cip_arp_ops);
741 ret = -EINVAL; 737 if (ret < 0)
742 goto cleanup_target; 738 goto cleanup_target;
743 }
744 739
745#ifdef CONFIG_PROC_FS 740#ifdef CONFIG_PROC_FS
746 clusterip_procdir = proc_mkdir("ipt_CLUSTERIP", proc_net); 741 clusterip_procdir = proc_mkdir("ipt_CLUSTERIP", proc_net);
@@ -753,31 +748,24 @@ static int init_or_cleanup(int fini)
753 748
754 printk(KERN_NOTICE "ClusterIP Version %s loaded successfully\n", 749 printk(KERN_NOTICE "ClusterIP Version %s loaded successfully\n",
755 CLUSTERIP_VERSION); 750 CLUSTERIP_VERSION);
756
757 return 0; 751 return 0;
758 752
759cleanup:
760 printk(KERN_NOTICE "ClusterIP Version %s unloading\n",
761 CLUSTERIP_VERSION);
762#ifdef CONFIG_PROC_FS
763 remove_proc_entry(clusterip_procdir->name, clusterip_procdir->parent);
764#endif
765cleanup_hook: 753cleanup_hook:
766 nf_unregister_hook(&cip_arp_ops); 754 nf_unregister_hook(&cip_arp_ops);
767cleanup_target: 755cleanup_target:
768 ipt_unregister_target(&clusterip_tgt); 756 ipt_unregister_target(&clusterip_tgt);
769cleanup_none: 757 return ret;
770 return -EINVAL;
771}
772
773static int __init ipt_clusterip_init(void)
774{
775 return init_or_cleanup(0);
776} 758}
777 759
778static void __exit ipt_clusterip_fini(void) 760static void __exit ipt_clusterip_fini(void)
779{ 761{
780 init_or_cleanup(1); 762 printk(KERN_NOTICE "ClusterIP Version %s unloading\n",
763 CLUSTERIP_VERSION);
764#ifdef CONFIG_PROC_FS
765 remove_proc_entry(clusterip_procdir->name, clusterip_procdir->parent);
766#endif
767 nf_unregister_hook(&cip_arp_ops);
768 ipt_unregister_target(&clusterip_tgt);
781} 769}
782 770
783module_init(ipt_clusterip_init); 771module_init(ipt_clusterip_init);
diff --git a/net/ipv4/netfilter/ipt_REJECT.c b/net/ipv4/netfilter/ipt_REJECT.c
index 4269a5440d43..0bba3c2bb786 100644
--- a/net/ipv4/netfilter/ipt_REJECT.c
+++ b/net/ipv4/netfilter/ipt_REJECT.c
@@ -106,7 +106,6 @@ static void send_reset(struct sk_buff *oldskb, int hook)
106 struct rtable *rt; 106 struct rtable *rt;
107 u_int16_t tmp_port; 107 u_int16_t tmp_port;
108 u_int32_t tmp_addr; 108 u_int32_t tmp_addr;
109 unsigned int tcplen;
110 int needs_ack; 109 int needs_ack;
111 int hh_len; 110 int hh_len;
112 111
@@ -124,13 +123,7 @@ static void send_reset(struct sk_buff *oldskb, int hook)
124 return; 123 return;
125 124
126 /* Check checksum */ 125 /* Check checksum */
127 tcplen = oldskb->len - iph->ihl * 4; 126 if (nf_ip_checksum(oldskb, hook, iph->ihl * 4, IPPROTO_TCP))
128 if (((hook != NF_IP_LOCAL_IN && oldskb->ip_summed != CHECKSUM_HW) ||
129 (hook == NF_IP_LOCAL_IN &&
130 oldskb->ip_summed != CHECKSUM_UNNECESSARY)) &&
131 csum_tcpudp_magic(iph->saddr, iph->daddr, tcplen, IPPROTO_TCP,
132 oldskb->ip_summed == CHECKSUM_HW ? oldskb->csum :
133 skb_checksum(oldskb, iph->ihl * 4, tcplen, 0)))
134 return; 127 return;
135 128
136 if ((rt = route_reverse(oldskb, oth, hook)) == NULL) 129 if ((rt = route_reverse(oldskb, oth, hook)) == NULL)
diff --git a/net/ipv4/netfilter/iptable_filter.c b/net/ipv4/netfilter/iptable_filter.c
index 3d80aefe9cfa..7f417484bfbf 100644
--- a/net/ipv4/netfilter/iptable_filter.c
+++ b/net/ipv4/netfilter/iptable_filter.c
@@ -157,37 +157,20 @@ static int __init iptable_filter_init(void)
157 return ret; 157 return ret;
158 158
159 /* Register hooks */ 159 /* Register hooks */
160 ret = nf_register_hook(&ipt_ops[0]); 160 ret = nf_register_hooks(ipt_ops, ARRAY_SIZE(ipt_ops));
161 if (ret < 0) 161 if (ret < 0)
162 goto cleanup_table; 162 goto cleanup_table;
163 163
164 ret = nf_register_hook(&ipt_ops[1]);
165 if (ret < 0)
166 goto cleanup_hook0;
167
168 ret = nf_register_hook(&ipt_ops[2]);
169 if (ret < 0)
170 goto cleanup_hook1;
171
172 return ret; 164 return ret;
173 165
174 cleanup_hook1:
175 nf_unregister_hook(&ipt_ops[1]);
176 cleanup_hook0:
177 nf_unregister_hook(&ipt_ops[0]);
178 cleanup_table: 166 cleanup_table:
179 ipt_unregister_table(&packet_filter); 167 ipt_unregister_table(&packet_filter);
180
181 return ret; 168 return ret;
182} 169}
183 170
184static void __exit iptable_filter_fini(void) 171static void __exit iptable_filter_fini(void)
185{ 172{
186 unsigned int i; 173 nf_unregister_hooks(ipt_ops, ARRAY_SIZE(ipt_ops));
187
188 for (i = 0; i < sizeof(ipt_ops)/sizeof(struct nf_hook_ops); i++)
189 nf_unregister_hook(&ipt_ops[i]);
190
191 ipt_unregister_table(&packet_filter); 174 ipt_unregister_table(&packet_filter);
192} 175}
193 176
diff --git a/net/ipv4/netfilter/iptable_mangle.c b/net/ipv4/netfilter/iptable_mangle.c
index 412fc96cc896..397b95cc026b 100644
--- a/net/ipv4/netfilter/iptable_mangle.c
+++ b/net/ipv4/netfilter/iptable_mangle.c
@@ -211,49 +211,20 @@ static int __init iptable_mangle_init(void)
211 return ret; 211 return ret;
212 212
213 /* Register hooks */ 213 /* Register hooks */
214 ret = nf_register_hook(&ipt_ops[0]); 214 ret = nf_register_hooks(ipt_ops, ARRAY_SIZE(ipt_ops));
215 if (ret < 0) 215 if (ret < 0)
216 goto cleanup_table; 216 goto cleanup_table;
217 217
218 ret = nf_register_hook(&ipt_ops[1]);
219 if (ret < 0)
220 goto cleanup_hook0;
221
222 ret = nf_register_hook(&ipt_ops[2]);
223 if (ret < 0)
224 goto cleanup_hook1;
225
226 ret = nf_register_hook(&ipt_ops[3]);
227 if (ret < 0)
228 goto cleanup_hook2;
229
230 ret = nf_register_hook(&ipt_ops[4]);
231 if (ret < 0)
232 goto cleanup_hook3;
233
234 return ret; 218 return ret;
235 219
236 cleanup_hook3:
237 nf_unregister_hook(&ipt_ops[3]);
238 cleanup_hook2:
239 nf_unregister_hook(&ipt_ops[2]);
240 cleanup_hook1:
241 nf_unregister_hook(&ipt_ops[1]);
242 cleanup_hook0:
243 nf_unregister_hook(&ipt_ops[0]);
244 cleanup_table: 220 cleanup_table:
245 ipt_unregister_table(&packet_mangler); 221 ipt_unregister_table(&packet_mangler);
246
247 return ret; 222 return ret;
248} 223}
249 224
250static void __exit iptable_mangle_fini(void) 225static void __exit iptable_mangle_fini(void)
251{ 226{
252 unsigned int i; 227 nf_unregister_hooks(ipt_ops, ARRAY_SIZE(ipt_ops));
253
254 for (i = 0; i < sizeof(ipt_ops)/sizeof(struct nf_hook_ops); i++)
255 nf_unregister_hook(&ipt_ops[i]);
256
257 ipt_unregister_table(&packet_mangler); 228 ipt_unregister_table(&packet_mangler);
258} 229}
259 230
diff --git a/net/ipv4/netfilter/iptable_raw.c b/net/ipv4/netfilter/iptable_raw.c
index 03cc79a6160a..7912cce1e1b8 100644
--- a/net/ipv4/netfilter/iptable_raw.c
+++ b/net/ipv4/netfilter/iptable_raw.c
@@ -101,18 +101,18 @@ ipt_hook(unsigned int hook,
101/* 'raw' is the very first table. */ 101/* 'raw' is the very first table. */
102static struct nf_hook_ops ipt_ops[] = { 102static struct nf_hook_ops ipt_ops[] = {
103 { 103 {
104 .hook = ipt_hook, 104 .hook = ipt_hook,
105 .pf = PF_INET, 105 .pf = PF_INET,
106 .hooknum = NF_IP_PRE_ROUTING, 106 .hooknum = NF_IP_PRE_ROUTING,
107 .priority = NF_IP_PRI_RAW, 107 .priority = NF_IP_PRI_RAW,
108 .owner = THIS_MODULE, 108 .owner = THIS_MODULE,
109 }, 109 },
110 { 110 {
111 .hook = ipt_hook, 111 .hook = ipt_hook,
112 .pf = PF_INET, 112 .pf = PF_INET,
113 .hooknum = NF_IP_LOCAL_OUT, 113 .hooknum = NF_IP_LOCAL_OUT,
114 .priority = NF_IP_PRI_RAW, 114 .priority = NF_IP_PRI_RAW,
115 .owner = THIS_MODULE, 115 .owner = THIS_MODULE,
116 }, 116 },
117}; 117};
118 118
@@ -126,31 +126,20 @@ static int __init iptable_raw_init(void)
126 return ret; 126 return ret;
127 127
128 /* Register hooks */ 128 /* Register hooks */
129 ret = nf_register_hook(&ipt_ops[0]); 129 ret = nf_register_hooks(ipt_ops, ARRAY_SIZE(ipt_ops));
130 if (ret < 0) 130 if (ret < 0)
131 goto cleanup_table; 131 goto cleanup_table;
132 132
133 ret = nf_register_hook(&ipt_ops[1]);
134 if (ret < 0)
135 goto cleanup_hook0;
136
137 return ret; 133 return ret;
138 134
139 cleanup_hook0:
140 nf_unregister_hook(&ipt_ops[0]);
141 cleanup_table: 135 cleanup_table:
142 ipt_unregister_table(&packet_raw); 136 ipt_unregister_table(&packet_raw);
143
144 return ret; 137 return ret;
145} 138}
146 139
147static void __exit iptable_raw_fini(void) 140static void __exit iptable_raw_fini(void)
148{ 141{
149 unsigned int i; 142 nf_unregister_hooks(ipt_ops, ARRAY_SIZE(ipt_ops));
150
151 for (i = 0; i < sizeof(ipt_ops)/sizeof(struct nf_hook_ops); i++)
152 nf_unregister_hook(&ipt_ops[i]);
153
154 ipt_unregister_table(&packet_raw); 143 ipt_unregister_table(&packet_raw);
155} 144}
156 145
diff --git a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
index 4afbc699d3ba..5bc9f64d7b5b 100644
--- a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
+++ b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
@@ -210,71 +210,63 @@ static unsigned int ipv4_conntrack_local(unsigned int hooknum,
210 210
211/* Connection tracking may drop packets, but never alters them, so 211/* Connection tracking may drop packets, but never alters them, so
212 make it the first hook. */ 212 make it the first hook. */
213static struct nf_hook_ops ipv4_conntrack_defrag_ops = { 213static struct nf_hook_ops ipv4_conntrack_ops[] = {
214 .hook = ipv4_conntrack_defrag, 214 {
215 .owner = THIS_MODULE, 215 .hook = ipv4_conntrack_defrag,
216 .pf = PF_INET, 216 .owner = THIS_MODULE,
217 .hooknum = NF_IP_PRE_ROUTING, 217 .pf = PF_INET,
218 .priority = NF_IP_PRI_CONNTRACK_DEFRAG, 218 .hooknum = NF_IP_PRE_ROUTING,
219}; 219 .priority = NF_IP_PRI_CONNTRACK_DEFRAG,
220 220 },
221static struct nf_hook_ops ipv4_conntrack_in_ops = { 221 {
222 .hook = ipv4_conntrack_in, 222 .hook = ipv4_conntrack_in,
223 .owner = THIS_MODULE, 223 .owner = THIS_MODULE,
224 .pf = PF_INET, 224 .pf = PF_INET,
225 .hooknum = NF_IP_PRE_ROUTING, 225 .hooknum = NF_IP_PRE_ROUTING,
226 .priority = NF_IP_PRI_CONNTRACK, 226 .priority = NF_IP_PRI_CONNTRACK,
227}; 227 },
228 228 {
229static struct nf_hook_ops ipv4_conntrack_defrag_local_out_ops = { 229 .hook = ipv4_conntrack_defrag,
230 .hook = ipv4_conntrack_defrag, 230 .owner = THIS_MODULE,
231 .owner = THIS_MODULE, 231 .pf = PF_INET,
232 .pf = PF_INET, 232 .hooknum = NF_IP_LOCAL_OUT,
233 .hooknum = NF_IP_LOCAL_OUT, 233 .priority = NF_IP_PRI_CONNTRACK_DEFRAG,
234 .priority = NF_IP_PRI_CONNTRACK_DEFRAG, 234 },
235}; 235 {
236 236 .hook = ipv4_conntrack_local,
237static struct nf_hook_ops ipv4_conntrack_local_out_ops = { 237 .owner = THIS_MODULE,
238 .hook = ipv4_conntrack_local, 238 .pf = PF_INET,
239 .owner = THIS_MODULE, 239 .hooknum = NF_IP_LOCAL_OUT,
240 .pf = PF_INET, 240 .priority = NF_IP_PRI_CONNTRACK,
241 .hooknum = NF_IP_LOCAL_OUT, 241 },
242 .priority = NF_IP_PRI_CONNTRACK, 242 {
243}; 243 .hook = ipv4_conntrack_help,
244 244 .owner = THIS_MODULE,
245/* helpers */ 245 .pf = PF_INET,
246static struct nf_hook_ops ipv4_conntrack_helper_out_ops = { 246 .hooknum = NF_IP_POST_ROUTING,
247 .hook = ipv4_conntrack_help, 247 .priority = NF_IP_PRI_CONNTRACK_HELPER,
248 .owner = THIS_MODULE, 248 },
249 .pf = PF_INET, 249 {
250 .hooknum = NF_IP_POST_ROUTING, 250 .hook = ipv4_conntrack_help,
251 .priority = NF_IP_PRI_CONNTRACK_HELPER, 251 .owner = THIS_MODULE,
252}; 252 .pf = PF_INET,
253 253 .hooknum = NF_IP_LOCAL_IN,
254static struct nf_hook_ops ipv4_conntrack_helper_in_ops = { 254 .priority = NF_IP_PRI_CONNTRACK_HELPER,
255 .hook = ipv4_conntrack_help, 255 },
256 .owner = THIS_MODULE, 256 {
257 .pf = PF_INET, 257 .hook = ipv4_confirm,
258 .hooknum = NF_IP_LOCAL_IN, 258 .owner = THIS_MODULE,
259 .priority = NF_IP_PRI_CONNTRACK_HELPER, 259 .pf = PF_INET,
260}; 260 .hooknum = NF_IP_POST_ROUTING,
261 261 .priority = NF_IP_PRI_CONNTRACK_CONFIRM,
262 262 },
263/* Refragmenter; last chance. */ 263 {
264static struct nf_hook_ops ipv4_conntrack_out_ops = { 264 .hook = ipv4_confirm,
265 .hook = ipv4_confirm, 265 .owner = THIS_MODULE,
266 .owner = THIS_MODULE, 266 .pf = PF_INET,
267 .pf = PF_INET, 267 .hooknum = NF_IP_LOCAL_IN,
268 .hooknum = NF_IP_POST_ROUTING, 268 .priority = NF_IP_PRI_CONNTRACK_CONFIRM,
269 .priority = NF_IP_PRI_CONNTRACK_CONFIRM, 269 },
270};
271
272static struct nf_hook_ops ipv4_conntrack_local_in_ops = {
273 .hook = ipv4_confirm,
274 .owner = THIS_MODULE,
275 .pf = PF_INET,
276 .hooknum = NF_IP_LOCAL_IN,
277 .priority = NF_IP_PRI_CONNTRACK_CONFIRM,
278}; 270};
279 271
280#ifdef CONFIG_SYSCTL 272#ifdef CONFIG_SYSCTL
@@ -440,16 +432,20 @@ struct nf_conntrack_l3proto nf_conntrack_l3proto_ipv4 = {
440extern struct nf_conntrack_protocol nf_conntrack_protocol_tcp4; 432extern struct nf_conntrack_protocol nf_conntrack_protocol_tcp4;
441extern struct nf_conntrack_protocol nf_conntrack_protocol_udp4; 433extern struct nf_conntrack_protocol nf_conntrack_protocol_udp4;
442extern struct nf_conntrack_protocol nf_conntrack_protocol_icmp; 434extern struct nf_conntrack_protocol nf_conntrack_protocol_icmp;
443static int init_or_cleanup(int init) 435
436MODULE_ALIAS("nf_conntrack-" __stringify(AF_INET));
437MODULE_LICENSE("GPL");
438
439static int __init nf_conntrack_l3proto_ipv4_init(void)
444{ 440{
445 int ret = 0; 441 int ret = 0;
446 442
447 if (!init) goto cleanup; 443 need_conntrack();
448 444
449 ret = nf_register_sockopt(&so_getorigdst); 445 ret = nf_register_sockopt(&so_getorigdst);
450 if (ret < 0) { 446 if (ret < 0) {
451 printk(KERN_ERR "Unable to register netfilter socket option\n"); 447 printk(KERN_ERR "Unable to register netfilter socket option\n");
452 goto cleanup_nothing; 448 return ret;
453 } 449 }
454 450
455 ret = nf_conntrack_protocol_register(&nf_conntrack_protocol_tcp4); 451 ret = nf_conntrack_protocol_register(&nf_conntrack_protocol_tcp4);
@@ -476,84 +472,26 @@ static int init_or_cleanup(int init)
476 goto cleanup_icmp; 472 goto cleanup_icmp;
477 } 473 }
478 474
479 ret = nf_register_hook(&ipv4_conntrack_defrag_ops); 475 ret = nf_register_hooks(ipv4_conntrack_ops,
476 ARRAY_SIZE(ipv4_conntrack_ops));
480 if (ret < 0) { 477 if (ret < 0) {
481 printk("nf_conntrack_ipv4: can't register pre-routing defrag hook.\n"); 478 printk("nf_conntrack_ipv4: can't register hooks.\n");
482 goto cleanup_ipv4; 479 goto cleanup_ipv4;
483 } 480 }
484 ret = nf_register_hook(&ipv4_conntrack_defrag_local_out_ops);
485 if (ret < 0) {
486 printk("nf_conntrack_ipv4: can't register local_out defrag hook.\n");
487 goto cleanup_defragops;
488 }
489
490 ret = nf_register_hook(&ipv4_conntrack_in_ops);
491 if (ret < 0) {
492 printk("nf_conntrack_ipv4: can't register pre-routing hook.\n");
493 goto cleanup_defraglocalops;
494 }
495
496 ret = nf_register_hook(&ipv4_conntrack_local_out_ops);
497 if (ret < 0) {
498 printk("nf_conntrack_ipv4: can't register local out hook.\n");
499 goto cleanup_inops;
500 }
501
502 ret = nf_register_hook(&ipv4_conntrack_helper_in_ops);
503 if (ret < 0) {
504 printk("nf_conntrack_ipv4: can't register local helper hook.\n");
505 goto cleanup_inandlocalops;
506 }
507
508 ret = nf_register_hook(&ipv4_conntrack_helper_out_ops);
509 if (ret < 0) {
510 printk("nf_conntrack_ipv4: can't register postrouting helper hook.\n");
511 goto cleanup_helperinops;
512 }
513
514 ret = nf_register_hook(&ipv4_conntrack_out_ops);
515 if (ret < 0) {
516 printk("nf_conntrack_ipv4: can't register post-routing hook.\n");
517 goto cleanup_helperoutops;
518 }
519
520 ret = nf_register_hook(&ipv4_conntrack_local_in_ops);
521 if (ret < 0) {
522 printk("nf_conntrack_ipv4: can't register local in hook.\n");
523 goto cleanup_inoutandlocalops;
524 }
525
526#ifdef CONFIG_SYSCTL 481#ifdef CONFIG_SYSCTL
527 nf_ct_ipv4_sysctl_header = register_sysctl_table(nf_ct_net_table, 0); 482 nf_ct_ipv4_sysctl_header = register_sysctl_table(nf_ct_net_table, 0);
528 if (nf_ct_ipv4_sysctl_header == NULL) { 483 if (nf_ct_ipv4_sysctl_header == NULL) {
529 printk("nf_conntrack: can't register to sysctl.\n"); 484 printk("nf_conntrack: can't register to sysctl.\n");
530 ret = -ENOMEM; 485 ret = -ENOMEM;
531 goto cleanup_localinops; 486 goto cleanup_hooks;
532 } 487 }
533#endif 488#endif
534 return ret; 489 return ret;
535 490
536 cleanup:
537 synchronize_net();
538#ifdef CONFIG_SYSCTL 491#ifdef CONFIG_SYSCTL
539 unregister_sysctl_table(nf_ct_ipv4_sysctl_header); 492 cleanup_hooks:
540 cleanup_localinops: 493 nf_unregister_hooks(ipv4_conntrack_ops, ARRAY_SIZE(ipv4_conntrack_ops));
541#endif 494#endif
542 nf_unregister_hook(&ipv4_conntrack_local_in_ops);
543 cleanup_inoutandlocalops:
544 nf_unregister_hook(&ipv4_conntrack_out_ops);
545 cleanup_helperoutops:
546 nf_unregister_hook(&ipv4_conntrack_helper_out_ops);
547 cleanup_helperinops:
548 nf_unregister_hook(&ipv4_conntrack_helper_in_ops);
549 cleanup_inandlocalops:
550 nf_unregister_hook(&ipv4_conntrack_local_out_ops);
551 cleanup_inops:
552 nf_unregister_hook(&ipv4_conntrack_in_ops);
553 cleanup_defraglocalops:
554 nf_unregister_hook(&ipv4_conntrack_defrag_local_out_ops);
555 cleanup_defragops:
556 nf_unregister_hook(&ipv4_conntrack_defrag_ops);
557 cleanup_ipv4: 495 cleanup_ipv4:
558 nf_conntrack_l3proto_unregister(&nf_conntrack_l3proto_ipv4); 496 nf_conntrack_l3proto_unregister(&nf_conntrack_l3proto_ipv4);
559 cleanup_icmp: 497 cleanup_icmp:
@@ -564,22 +502,21 @@ static int init_or_cleanup(int init)
564 nf_conntrack_protocol_unregister(&nf_conntrack_protocol_tcp4); 502 nf_conntrack_protocol_unregister(&nf_conntrack_protocol_tcp4);
565 cleanup_sockopt: 503 cleanup_sockopt:
566 nf_unregister_sockopt(&so_getorigdst); 504 nf_unregister_sockopt(&so_getorigdst);
567 cleanup_nothing:
568 return ret; 505 return ret;
569} 506}
570 507
571MODULE_ALIAS("nf_conntrack-" __stringify(AF_INET));
572MODULE_LICENSE("GPL");
573
574static int __init nf_conntrack_l3proto_ipv4_init(void)
575{
576 need_conntrack();
577 return init_or_cleanup(1);
578}
579
580static void __exit nf_conntrack_l3proto_ipv4_fini(void) 508static void __exit nf_conntrack_l3proto_ipv4_fini(void)
581{ 509{
582 init_or_cleanup(0); 510 synchronize_net();
511#ifdef CONFIG_SYSCTL
512 unregister_sysctl_table(nf_ct_ipv4_sysctl_header);
513#endif
514 nf_unregister_hooks(ipv4_conntrack_ops, ARRAY_SIZE(ipv4_conntrack_ops));
515 nf_conntrack_l3proto_unregister(&nf_conntrack_l3proto_ipv4);
516 nf_conntrack_protocol_unregister(&nf_conntrack_protocol_icmp);
517 nf_conntrack_protocol_unregister(&nf_conntrack_protocol_udp4);
518 nf_conntrack_protocol_unregister(&nf_conntrack_protocol_tcp4);
519 nf_unregister_sockopt(&so_getorigdst);
583} 520}
584 521
585module_init(nf_conntrack_l3proto_ipv4_init); 522module_init(nf_conntrack_l3proto_ipv4_init);
diff --git a/net/ipv4/netfilter/nf_conntrack_proto_icmp.c b/net/ipv4/netfilter/nf_conntrack_proto_icmp.c
index 52dc175be39a..4b0d361cc6e6 100644
--- a/net/ipv4/netfilter/nf_conntrack_proto_icmp.c
+++ b/net/ipv4/netfilter/nf_conntrack_proto_icmp.c
@@ -235,30 +235,14 @@ icmp_error(struct sk_buff *skb, unsigned int dataoff,
235 } 235 }
236 236
237 /* See ip_conntrack_proto_tcp.c */ 237 /* See ip_conntrack_proto_tcp.c */
238 if (hooknum != NF_IP_PRE_ROUTING) 238 if (hooknum == NF_IP_PRE_ROUTING &&
239 goto checksum_skipped; 239 nf_ip_checksum(skb, hooknum, dataoff, 0)) {
240
241 switch (skb->ip_summed) {
242 case CHECKSUM_HW:
243 if (!(u16)csum_fold(skb->csum))
244 break;
245 if (LOG_INVALID(IPPROTO_ICMP)) 240 if (LOG_INVALID(IPPROTO_ICMP))
246 nf_log_packet(PF_INET, 0, skb, NULL, NULL, NULL, 241 nf_log_packet(PF_INET, 0, skb, NULL, NULL, NULL,
247 "nf_ct_icmp: bad HW ICMP checksum "); 242 "nf_ct_icmp: bad HW ICMP checksum ");
248 return -NF_ACCEPT; 243 return -NF_ACCEPT;
249 case CHECKSUM_NONE:
250 if ((u16)csum_fold(skb_checksum(skb, 0, skb->len, 0))) {
251 if (LOG_INVALID(IPPROTO_ICMP))
252 nf_log_packet(PF_INET, 0, skb, NULL, NULL,
253 NULL,
254 "nf_ct_icmp: bad ICMP checksum ");
255 return -NF_ACCEPT;
256 }
257 default:
258 break;
259 } 244 }
260 245
261checksum_skipped:
262 /* 246 /*
263 * 18 is the highest 'known' ICMP type. Anything else is a mystery 247 * 18 is the highest 'known' ICMP type. Anything else is a mystery
264 * 248 *
diff --git a/net/ipv4/tunnel4.c b/net/ipv4/tunnel4.c
index 0d7d386dac22..8d30c48f090e 100644
--- a/net/ipv4/tunnel4.c
+++ b/net/ipv4/tunnel4.c
@@ -8,6 +8,8 @@
8#include <linux/mutex.h> 8#include <linux/mutex.h>
9#include <linux/netdevice.h> 9#include <linux/netdevice.h>
10#include <linux/skbuff.h> 10#include <linux/skbuff.h>
11#include <net/icmp.h>
12#include <net/ip.h>
11#include <net/protocol.h> 13#include <net/protocol.h>
12#include <net/xfrm.h> 14#include <net/xfrm.h>
13 15
@@ -70,10 +72,16 @@ static int tunnel4_rcv(struct sk_buff *skb)
70{ 72{
71 struct xfrm_tunnel *handler; 73 struct xfrm_tunnel *handler;
72 74
75 if (!pskb_may_pull(skb, sizeof(struct iphdr)))
76 goto drop;
77
73 for (handler = tunnel4_handlers; handler; handler = handler->next) 78 for (handler = tunnel4_handlers; handler; handler = handler->next)
74 if (!handler->handler(skb)) 79 if (!handler->handler(skb))
75 return 0; 80 return 0;
76 81
82 icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0);
83
84drop:
77 kfree_skb(skb); 85 kfree_skb(skb);
78 return 0; 86 return 0;
79} 87}
diff --git a/net/ipv4/xfrm4_input.c b/net/ipv4/xfrm4_input.c
index e1b8f4b90d80..3e174c83bfe7 100644
--- a/net/ipv4/xfrm4_input.c
+++ b/net/ipv4/xfrm4_input.c
@@ -37,8 +37,6 @@ static int xfrm4_parse_spi(struct sk_buff *skb, u8 nexthdr, u32 *spi, u32 *seq)
37{ 37{
38 switch (nexthdr) { 38 switch (nexthdr) {
39 case IPPROTO_IPIP: 39 case IPPROTO_IPIP:
40 if (!pskb_may_pull(skb, sizeof(struct iphdr)))
41 return -EINVAL;
42 *spi = skb->nh.iph->saddr; 40 *spi = skb->nh.iph->saddr;
43 *seq = 0; 41 *seq = 0;
44 return 0; 42 return 0;
@@ -90,7 +88,7 @@ int xfrm4_rcv_encap(struct sk_buff *skb, __u16 encap_type)
90 if (unlikely(x->km.state != XFRM_STATE_VALID)) 88 if (unlikely(x->km.state != XFRM_STATE_VALID))
91 goto drop_unlock; 89 goto drop_unlock;
92 90
93 if (x->encap->encap_type != encap_type) 91 if ((x->encap ? x->encap->encap_type : 0) != encap_type)
94 goto drop_unlock; 92 goto drop_unlock;
95 93
96 if (x->props.replay_window && xfrm_replay_check(x, seq)) 94 if (x->props.replay_window && xfrm_replay_check(x, seq))
diff --git a/net/ipv6/inet6_hashtables.c b/net/ipv6/inet6_hashtables.c
index bb8ffb8a14c5..2ae84c961678 100644
--- a/net/ipv6/inet6_hashtables.c
+++ b/net/ipv6/inet6_hashtables.c
@@ -23,6 +23,86 @@
23#include <net/inet6_hashtables.h> 23#include <net/inet6_hashtables.h>
24#include <net/ip.h> 24#include <net/ip.h>
25 25
26void __inet6_hash(struct inet_hashinfo *hashinfo,
27 struct sock *sk)
28{
29 struct hlist_head *list;
30 rwlock_t *lock;
31
32 BUG_TRAP(sk_unhashed(sk));
33
34 if (sk->sk_state == TCP_LISTEN) {
35 list = &hashinfo->listening_hash[inet_sk_listen_hashfn(sk)];
36 lock = &hashinfo->lhash_lock;
37 inet_listen_wlock(hashinfo);
38 } else {
39 unsigned int hash;
40 sk->sk_hash = hash = inet6_sk_ehashfn(sk);
41 hash &= (hashinfo->ehash_size - 1);
42 list = &hashinfo->ehash[hash].chain;
43 lock = &hashinfo->ehash[hash].lock;
44 write_lock(lock);
45 }
46
47 __sk_add_node(sk, list);
48 sock_prot_inc_use(sk->sk_prot);
49 write_unlock(lock);
50}
51EXPORT_SYMBOL(__inet6_hash);
52
53/*
54 * Sockets in TCP_CLOSE state are _always_ taken out of the hash, so
55 * we need not check it for TCP lookups anymore, thanks Alexey. -DaveM
56 *
57 * The sockhash lock must be held as a reader here.
58 */
59struct sock *__inet6_lookup_established(struct inet_hashinfo *hashinfo,
60 const struct in6_addr *saddr,
61 const u16 sport,
62 const struct in6_addr *daddr,
63 const u16 hnum,
64 const int dif)
65{
66 struct sock *sk;
67 const struct hlist_node *node;
68 const __u32 ports = INET_COMBINED_PORTS(sport, hnum);
69 /* Optimize here for direct hit, only listening connections can
70 * have wildcards anyways.
71 */
72 unsigned int hash = inet6_ehashfn(daddr, hnum, saddr, sport);
73 struct inet_ehash_bucket *head = inet_ehash_bucket(hashinfo, hash);
74
75 prefetch(head->chain.first);
76 read_lock(&head->lock);
77 sk_for_each(sk, node, &head->chain) {
78 /* For IPV6 do the cheaper port and family tests first. */
79 if (INET6_MATCH(sk, hash, saddr, daddr, ports, dif))
80 goto hit; /* You sunk my battleship! */
81 }
82 /* Must check for a TIME_WAIT'er before going to listener hash. */
83 sk_for_each(sk, node, &(head + hashinfo->ehash_size)->chain) {
84 const struct inet_timewait_sock *tw = inet_twsk(sk);
85
86 if(*((__u32 *)&(tw->tw_dport)) == ports &&
87 sk->sk_family == PF_INET6) {
88 const struct inet6_timewait_sock *tw6 = inet6_twsk(sk);
89
90 if (ipv6_addr_equal(&tw6->tw_v6_daddr, saddr) &&
91 ipv6_addr_equal(&tw6->tw_v6_rcv_saddr, daddr) &&
92 (!sk->sk_bound_dev_if || sk->sk_bound_dev_if == dif))
93 goto hit;
94 }
95 }
96 read_unlock(&head->lock);
97 return NULL;
98
99hit:
100 sock_hold(sk);
101 read_unlock(&head->lock);
102 return sk;
103}
104EXPORT_SYMBOL(__inet6_lookup_established);
105
26struct sock *inet6_lookup_listener(struct inet_hashinfo *hashinfo, 106struct sock *inet6_lookup_listener(struct inet_hashinfo *hashinfo,
27 const struct in6_addr *daddr, 107 const struct in6_addr *daddr,
28 const unsigned short hnum, const int dif) 108 const unsigned short hnum, const int dif)
diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c
index ff9040c92556..a995796b5a57 100644
--- a/net/ipv6/ip6_tunnel.c
+++ b/net/ipv6/ip6_tunnel.c
@@ -519,9 +519,6 @@ ip6ip6_rcv(struct sk_buff *skb)
519 struct ipv6hdr *ipv6h; 519 struct ipv6hdr *ipv6h;
520 struct ip6_tnl *t; 520 struct ip6_tnl *t;
521 521
522 if (!pskb_may_pull(skb, sizeof (*ipv6h)))
523 goto discard;
524
525 ipv6h = skb->nh.ipv6h; 522 ipv6h = skb->nh.ipv6h;
526 523
527 read_lock(&ip6ip6_lock); 524 read_lock(&ip6ip6_lock);
@@ -529,8 +526,7 @@ ip6ip6_rcv(struct sk_buff *skb)
529 if ((t = ip6ip6_tnl_lookup(&ipv6h->saddr, &ipv6h->daddr)) != NULL) { 526 if ((t = ip6ip6_tnl_lookup(&ipv6h->saddr, &ipv6h->daddr)) != NULL) {
530 if (!xfrm6_policy_check(NULL, XFRM_POLICY_IN, skb)) { 527 if (!xfrm6_policy_check(NULL, XFRM_POLICY_IN, skb)) {
531 read_unlock(&ip6ip6_lock); 528 read_unlock(&ip6ip6_lock);
532 kfree_skb(skb); 529 goto discard;
533 return 0;
534 } 530 }
535 531
536 if (!(t->parms.flags & IP6_TNL_F_CAP_RCV)) { 532 if (!(t->parms.flags & IP6_TNL_F_CAP_RCV)) {
@@ -557,9 +553,11 @@ ip6ip6_rcv(struct sk_buff *skb)
557 return 0; 553 return 0;
558 } 554 }
559 read_unlock(&ip6ip6_lock); 555 read_unlock(&ip6ip6_lock);
560 icmpv6_send(skb, ICMPV6_DEST_UNREACH, ICMPV6_ADDR_UNREACH, 0, skb->dev);
561discard:
562 return 1; 556 return 1;
557
558discard:
559 kfree_skb(skb);
560 return 0;
563} 561}
564 562
565static inline struct ipv6_txoptions *create_tel(__u8 encap_limit) 563static inline struct ipv6_txoptions *create_tel(__u8 encap_limit)
diff --git a/net/ipv6/netfilter.c b/net/ipv6/netfilter.c
index d750cfc019dc..395a417ba955 100644
--- a/net/ipv6/netfilter.c
+++ b/net/ipv6/netfilter.c
@@ -7,6 +7,7 @@
7#include <net/ipv6.h> 7#include <net/ipv6.h>
8#include <net/ip6_route.h> 8#include <net/ip6_route.h>
9#include <net/xfrm.h> 9#include <net/xfrm.h>
10#include <net/ip6_checksum.h>
10 11
11int ip6_route_me_harder(struct sk_buff *skb) 12int ip6_route_me_harder(struct sk_buff *skb)
12{ 13{
@@ -54,7 +55,7 @@ struct ip6_rt_info {
54 struct in6_addr saddr; 55 struct in6_addr saddr;
55}; 56};
56 57
57static void save(const struct sk_buff *skb, struct nf_info *info) 58static void nf_ip6_saveroute(const struct sk_buff *skb, struct nf_info *info)
58{ 59{
59 struct ip6_rt_info *rt_info = nf_info_reroute(info); 60 struct ip6_rt_info *rt_info = nf_info_reroute(info);
60 61
@@ -66,7 +67,7 @@ static void save(const struct sk_buff *skb, struct nf_info *info)
66 } 67 }
67} 68}
68 69
69static int reroute(struct sk_buff **pskb, const struct nf_info *info) 70static int nf_ip6_reroute(struct sk_buff **pskb, const struct nf_info *info)
70{ 71{
71 struct ip6_rt_info *rt_info = nf_info_reroute(info); 72 struct ip6_rt_info *rt_info = nf_info_reroute(info);
72 73
@@ -79,15 +80,50 @@ static int reroute(struct sk_buff **pskb, const struct nf_info *info)
79 return 0; 80 return 0;
80} 81}
81 82
82static struct nf_queue_rerouter ip6_reroute = { 83unsigned int nf_ip6_checksum(struct sk_buff *skb, unsigned int hook,
83 .rer_size = sizeof(struct ip6_rt_info), 84 unsigned int dataoff, u_int8_t protocol)
84 .save = &save, 85{
85 .reroute = &reroute, 86 struct ipv6hdr *ip6h = skb->nh.ipv6h;
87 unsigned int csum = 0;
88
89 switch (skb->ip_summed) {
90 case CHECKSUM_HW:
91 if (hook != NF_IP6_PRE_ROUTING && hook != NF_IP6_LOCAL_IN)
92 break;
93 if (!csum_ipv6_magic(&ip6h->saddr, &ip6h->daddr,
94 skb->len - dataoff, protocol,
95 csum_sub(skb->csum,
96 skb_checksum(skb, 0,
97 dataoff, 0)))) {
98 skb->ip_summed = CHECKSUM_UNNECESSARY;
99 break;
100 }
101 /* fall through */
102 case CHECKSUM_NONE:
103 skb->csum = ~csum_ipv6_magic(&ip6h->saddr, &ip6h->daddr,
104 skb->len - dataoff,
105 protocol,
106 csum_sub(0,
107 skb_checksum(skb, 0,
108 dataoff, 0)));
109 csum = __skb_checksum_complete(skb);
110 }
111 return csum;
112}
113
114EXPORT_SYMBOL(nf_ip6_checksum);
115
116static struct nf_afinfo nf_ip6_afinfo = {
117 .family = AF_INET6,
118 .checksum = nf_ip6_checksum,
119 .saveroute = nf_ip6_saveroute,
120 .reroute = nf_ip6_reroute,
121 .route_key_size = sizeof(struct ip6_rt_info),
86}; 122};
87 123
88int __init ipv6_netfilter_init(void) 124int __init ipv6_netfilter_init(void)
89{ 125{
90 return nf_register_queue_rerouter(PF_INET6, &ip6_reroute); 126 return nf_register_afinfo(&nf_ip6_afinfo);
91} 127}
92 128
93/* This can be called from inet6_init() on errors, so it cannot 129/* This can be called from inet6_init() on errors, so it cannot
@@ -95,5 +131,5 @@ int __init ipv6_netfilter_init(void)
95 */ 131 */
96void ipv6_netfilter_fini(void) 132void ipv6_netfilter_fini(void)
97{ 133{
98 nf_unregister_queue_rerouter(PF_INET6); 134 nf_unregister_afinfo(&nf_ip6_afinfo);
99} 135}
diff --git a/net/ipv6/netfilter/ip6_queue.c b/net/ipv6/netfilter/ip6_queue.c
index e81c6a9dab81..b4b7d441af25 100644
--- a/net/ipv6/netfilter/ip6_queue.c
+++ b/net/ipv6/netfilter/ip6_queue.c
@@ -658,15 +658,11 @@ static struct nf_queue_handler nfqh = {
658 .outfn = &ipq_enqueue_packet, 658 .outfn = &ipq_enqueue_packet,
659}; 659};
660 660
661static int 661static int __init ip6_queue_init(void)
662init_or_cleanup(int init)
663{ 662{
664 int status = -ENOMEM; 663 int status = -ENOMEM;
665 struct proc_dir_entry *proc; 664 struct proc_dir_entry *proc;
666 665
667 if (!init)
668 goto cleanup;
669
670 netlink_register_notifier(&ipq_nl_notifier); 666 netlink_register_notifier(&ipq_nl_notifier);
671 ipqnl = netlink_kernel_create(NETLINK_IP6_FW, 0, ipq_rcv_sk, 667 ipqnl = netlink_kernel_create(NETLINK_IP6_FW, 0, ipq_rcv_sk,
672 THIS_MODULE); 668 THIS_MODULE);
@@ -693,11 +689,6 @@ init_or_cleanup(int init)
693 } 689 }
694 return status; 690 return status;
695 691
696cleanup:
697 nf_unregister_queue_handlers(&nfqh);
698 synchronize_net();
699 ipq_flush(NF_DROP);
700
701cleanup_sysctl: 692cleanup_sysctl:
702 unregister_sysctl_table(ipq_sysctl_header); 693 unregister_sysctl_table(ipq_sysctl_header);
703 unregister_netdevice_notifier(&ipq_dev_notifier); 694 unregister_netdevice_notifier(&ipq_dev_notifier);
@@ -713,15 +704,21 @@ cleanup_netlink_notifier:
713 return status; 704 return status;
714} 705}
715 706
716static int __init ip6_queue_init(void)
717{
718
719 return init_or_cleanup(1);
720}
721
722static void __exit ip6_queue_fini(void) 707static void __exit ip6_queue_fini(void)
723{ 708{
724 init_or_cleanup(0); 709 nf_unregister_queue_handlers(&nfqh);
710 synchronize_net();
711 ipq_flush(NF_DROP);
712
713 unregister_sysctl_table(ipq_sysctl_header);
714 unregister_netdevice_notifier(&ipq_dev_notifier);
715 proc_net_remove(IPQ_PROC_FS_NAME);
716
717 sock_release(ipqnl->sk_socket);
718 mutex_lock(&ipqnl_mutex);
719 mutex_unlock(&ipqnl_mutex);
720
721 netlink_unregister_notifier(&ipq_nl_notifier);
725} 722}
726 723
727MODULE_DESCRIPTION("IPv6 packet queue handler"); 724MODULE_DESCRIPTION("IPv6 packet queue handler");
diff --git a/net/ipv6/netfilter/ip6table_filter.c b/net/ipv6/netfilter/ip6table_filter.c
index e5e724d9ee60..60976c0c58e8 100644
--- a/net/ipv6/netfilter/ip6table_filter.c
+++ b/net/ipv6/netfilter/ip6table_filter.c
@@ -177,37 +177,20 @@ static int __init ip6table_filter_init(void)
177 return ret; 177 return ret;
178 178
179 /* Register hooks */ 179 /* Register hooks */
180 ret = nf_register_hook(&ip6t_ops[0]); 180 ret = nf_register_hooks(ip6t_ops, ARRAY_SIZE(ip6t_ops));
181 if (ret < 0) 181 if (ret < 0)
182 goto cleanup_table; 182 goto cleanup_table;
183 183
184 ret = nf_register_hook(&ip6t_ops[1]);
185 if (ret < 0)
186 goto cleanup_hook0;
187
188 ret = nf_register_hook(&ip6t_ops[2]);
189 if (ret < 0)
190 goto cleanup_hook1;
191
192 return ret; 184 return ret;
193 185
194 cleanup_hook1:
195 nf_unregister_hook(&ip6t_ops[1]);
196 cleanup_hook0:
197 nf_unregister_hook(&ip6t_ops[0]);
198 cleanup_table: 186 cleanup_table:
199 ip6t_unregister_table(&packet_filter); 187 ip6t_unregister_table(&packet_filter);
200
201 return ret; 188 return ret;
202} 189}
203 190
204static void __exit ip6table_filter_fini(void) 191static void __exit ip6table_filter_fini(void)
205{ 192{
206 unsigned int i; 193 nf_unregister_hooks(ip6t_ops, ARRAY_SIZE(ip6t_ops));
207
208 for (i = 0; i < sizeof(ip6t_ops)/sizeof(struct nf_hook_ops); i++)
209 nf_unregister_hook(&ip6t_ops[i]);
210
211 ip6t_unregister_table(&packet_filter); 194 ip6t_unregister_table(&packet_filter);
212} 195}
213 196
diff --git a/net/ipv6/netfilter/ip6table_mangle.c b/net/ipv6/netfilter/ip6table_mangle.c
index e1f0f6ae9841..03a13eab1dae 100644
--- a/net/ipv6/netfilter/ip6table_mangle.c
+++ b/net/ipv6/netfilter/ip6table_mangle.c
@@ -238,49 +238,20 @@ static int __init ip6table_mangle_init(void)
238 return ret; 238 return ret;
239 239
240 /* Register hooks */ 240 /* Register hooks */
241 ret = nf_register_hook(&ip6t_ops[0]); 241 ret = nf_register_hooks(ip6t_ops, ARRAY_SIZE(ip6t_ops));
242 if (ret < 0) 242 if (ret < 0)
243 goto cleanup_table; 243 goto cleanup_table;
244 244
245 ret = nf_register_hook(&ip6t_ops[1]);
246 if (ret < 0)
247 goto cleanup_hook0;
248
249 ret = nf_register_hook(&ip6t_ops[2]);
250 if (ret < 0)
251 goto cleanup_hook1;
252
253 ret = nf_register_hook(&ip6t_ops[3]);
254 if (ret < 0)
255 goto cleanup_hook2;
256
257 ret = nf_register_hook(&ip6t_ops[4]);
258 if (ret < 0)
259 goto cleanup_hook3;
260
261 return ret; 245 return ret;
262 246
263 cleanup_hook3:
264 nf_unregister_hook(&ip6t_ops[3]);
265 cleanup_hook2:
266 nf_unregister_hook(&ip6t_ops[2]);
267 cleanup_hook1:
268 nf_unregister_hook(&ip6t_ops[1]);
269 cleanup_hook0:
270 nf_unregister_hook(&ip6t_ops[0]);
271 cleanup_table: 247 cleanup_table:
272 ip6t_unregister_table(&packet_mangler); 248 ip6t_unregister_table(&packet_mangler);
273
274 return ret; 249 return ret;
275} 250}
276 251
277static void __exit ip6table_mangle_fini(void) 252static void __exit ip6table_mangle_fini(void)
278{ 253{
279 unsigned int i; 254 nf_unregister_hooks(ip6t_ops, ARRAY_SIZE(ip6t_ops));
280
281 for (i = 0; i < sizeof(ip6t_ops)/sizeof(struct nf_hook_ops); i++)
282 nf_unregister_hook(&ip6t_ops[i]);
283
284 ip6t_unregister_table(&packet_mangler); 255 ip6t_unregister_table(&packet_mangler);
285} 256}
286 257
diff --git a/net/ipv6/netfilter/ip6table_raw.c b/net/ipv6/netfilter/ip6table_raw.c
index 54d1fffd62ba..61a7c58e99f8 100644
--- a/net/ipv6/netfilter/ip6table_raw.c
+++ b/net/ipv6/netfilter/ip6table_raw.c
@@ -152,31 +152,20 @@ static int __init ip6table_raw_init(void)
152 return ret; 152 return ret;
153 153
154 /* Register hooks */ 154 /* Register hooks */
155 ret = nf_register_hook(&ip6t_ops[0]); 155 ret = nf_register_hooks(ip6t_ops, ARRAY_SIZE(ip6t_ops));
156 if (ret < 0) 156 if (ret < 0)
157 goto cleanup_table; 157 goto cleanup_table;
158 158
159 ret = nf_register_hook(&ip6t_ops[1]);
160 if (ret < 0)
161 goto cleanup_hook0;
162
163 return ret; 159 return ret;
164 160
165 cleanup_hook0:
166 nf_unregister_hook(&ip6t_ops[0]);
167 cleanup_table: 161 cleanup_table:
168 ip6t_unregister_table(&packet_raw); 162 ip6t_unregister_table(&packet_raw);
169
170 return ret; 163 return ret;
171} 164}
172 165
173static void __exit ip6table_raw_fini(void) 166static void __exit ip6table_raw_fini(void)
174{ 167{
175 unsigned int i; 168 nf_unregister_hooks(ip6t_ops, ARRAY_SIZE(ip6t_ops));
176
177 for (i = 0; i < sizeof(ip6t_ops)/sizeof(struct nf_hook_ops); i++)
178 nf_unregister_hook(&ip6t_ops[i]);
179
180 ip6t_unregister_table(&packet_raw); 169 ip6t_unregister_table(&packet_raw);
181} 170}
182 171
diff --git a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
index c8b5a96cbb0f..93bae36f2663 100644
--- a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
+++ b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
@@ -286,55 +286,49 @@ static unsigned int ipv6_conntrack_local(unsigned int hooknum,
286 return ipv6_conntrack_in(hooknum, pskb, in, out, okfn); 286 return ipv6_conntrack_in(hooknum, pskb, in, out, okfn);
287} 287}
288 288
289/* Connection tracking may drop packets, but never alters them, so 289static struct nf_hook_ops ipv6_conntrack_ops[] = {
290 make it the first hook. */ 290 {
291static struct nf_hook_ops ipv6_conntrack_defrag_ops = { 291 .hook = ipv6_defrag,
292 .hook = ipv6_defrag, 292 .owner = THIS_MODULE,
293 .owner = THIS_MODULE, 293 .pf = PF_INET6,
294 .pf = PF_INET6, 294 .hooknum = NF_IP6_PRE_ROUTING,
295 .hooknum = NF_IP6_PRE_ROUTING, 295 .priority = NF_IP6_PRI_CONNTRACK_DEFRAG,
296 .priority = NF_IP6_PRI_CONNTRACK_DEFRAG, 296 },
297}; 297 {
298 298 .hook = ipv6_conntrack_in,
299static struct nf_hook_ops ipv6_conntrack_in_ops = { 299 .owner = THIS_MODULE,
300 .hook = ipv6_conntrack_in, 300 .pf = PF_INET6,
301 .owner = THIS_MODULE, 301 .hooknum = NF_IP6_PRE_ROUTING,
302 .pf = PF_INET6, 302 .priority = NF_IP6_PRI_CONNTRACK,
303 .hooknum = NF_IP6_PRE_ROUTING, 303 },
304 .priority = NF_IP6_PRI_CONNTRACK, 304 {
305}; 305 .hook = ipv6_conntrack_local,
306 306 .owner = THIS_MODULE,
307static struct nf_hook_ops ipv6_conntrack_local_out_ops = { 307 .pf = PF_INET6,
308 .hook = ipv6_conntrack_local, 308 .hooknum = NF_IP6_LOCAL_OUT,
309 .owner = THIS_MODULE, 309 .priority = NF_IP6_PRI_CONNTRACK,
310 .pf = PF_INET6, 310 },
311 .hooknum = NF_IP6_LOCAL_OUT, 311 {
312 .priority = NF_IP6_PRI_CONNTRACK, 312 .hook = ipv6_defrag,
313}; 313 .owner = THIS_MODULE,
314 314 .pf = PF_INET6,
315static struct nf_hook_ops ipv6_conntrack_defrag_local_out_ops = { 315 .hooknum = NF_IP6_LOCAL_OUT,
316 .hook = ipv6_defrag, 316 .priority = NF_IP6_PRI_CONNTRACK_DEFRAG,
317 .owner = THIS_MODULE, 317 },
318 .pf = PF_INET6, 318 {
319 .hooknum = NF_IP6_LOCAL_OUT, 319 .hook = ipv6_confirm,
320 .priority = NF_IP6_PRI_CONNTRACK_DEFRAG, 320 .owner = THIS_MODULE,
321}; 321 .pf = PF_INET6,
322 322 .hooknum = NF_IP6_POST_ROUTING,
323/* Refragmenter; last chance. */ 323 .priority = NF_IP6_PRI_LAST,
324static struct nf_hook_ops ipv6_conntrack_out_ops = { 324 },
325 .hook = ipv6_confirm, 325 {
326 .owner = THIS_MODULE, 326 .hook = ipv6_confirm,
327 .pf = PF_INET6, 327 .owner = THIS_MODULE,
328 .hooknum = NF_IP6_POST_ROUTING, 328 .pf = PF_INET6,
329 .priority = NF_IP6_PRI_LAST, 329 .hooknum = NF_IP6_LOCAL_IN,
330}; 330 .priority = NF_IP6_PRI_LAST-1,
331 331 },
332static struct nf_hook_ops ipv6_conntrack_local_in_ops = {
333 .hook = ipv6_confirm,
334 .owner = THIS_MODULE,
335 .pf = PF_INET6,
336 .hooknum = NF_IP6_LOCAL_IN,
337 .priority = NF_IP6_PRI_LAST-1,
338}; 332};
339 333
340#ifdef CONFIG_SYSCTL 334#ifdef CONFIG_SYSCTL
@@ -470,16 +464,21 @@ extern struct nf_conntrack_protocol nf_conntrack_protocol_udp6;
470extern struct nf_conntrack_protocol nf_conntrack_protocol_icmpv6; 464extern struct nf_conntrack_protocol nf_conntrack_protocol_icmpv6;
471extern int nf_ct_frag6_init(void); 465extern int nf_ct_frag6_init(void);
472extern void nf_ct_frag6_cleanup(void); 466extern void nf_ct_frag6_cleanup(void);
473static int init_or_cleanup(int init) 467
468MODULE_ALIAS("nf_conntrack-" __stringify(AF_INET6));
469MODULE_LICENSE("GPL");
470MODULE_AUTHOR("Yasuyuki KOZAKAI @USAGI <yasuyuki.kozakai@toshiba.co.jp>");
471
472static int __init nf_conntrack_l3proto_ipv6_init(void)
474{ 473{
475 int ret = 0; 474 int ret = 0;
476 475
477 if (!init) goto cleanup; 476 need_conntrack();
478 477
479 ret = nf_ct_frag6_init(); 478 ret = nf_ct_frag6_init();
480 if (ret < 0) { 479 if (ret < 0) {
481 printk("nf_conntrack_ipv6: can't initialize frag6.\n"); 480 printk("nf_conntrack_ipv6: can't initialize frag6.\n");
482 goto cleanup_nothing; 481 return ret;
483 } 482 }
484 ret = nf_conntrack_protocol_register(&nf_conntrack_protocol_tcp6); 483 ret = nf_conntrack_protocol_register(&nf_conntrack_protocol_tcp6);
485 if (ret < 0) { 484 if (ret < 0) {
@@ -505,71 +504,27 @@ static int init_or_cleanup(int init)
505 goto cleanup_icmpv6; 504 goto cleanup_icmpv6;
506 } 505 }
507 506
508 ret = nf_register_hook(&ipv6_conntrack_defrag_ops); 507 ret = nf_register_hooks(ipv6_conntrack_ops,
508 ARRAY_SIZE(ipv6_conntrack_ops));
509 if (ret < 0) { 509 if (ret < 0) {
510 printk("nf_conntrack_ipv6: can't register pre-routing defrag " 510 printk("nf_conntrack_ipv6: can't register pre-routing defrag "
511 "hook.\n"); 511 "hook.\n");
512 goto cleanup_ipv6; 512 goto cleanup_ipv6;
513 } 513 }
514
515 ret = nf_register_hook(&ipv6_conntrack_defrag_local_out_ops);
516 if (ret < 0) {
517 printk("nf_conntrack_ipv6: can't register local_out defrag "
518 "hook.\n");
519 goto cleanup_defragops;
520 }
521
522 ret = nf_register_hook(&ipv6_conntrack_in_ops);
523 if (ret < 0) {
524 printk("nf_conntrack_ipv6: can't register pre-routing hook.\n");
525 goto cleanup_defraglocalops;
526 }
527
528 ret = nf_register_hook(&ipv6_conntrack_local_out_ops);
529 if (ret < 0) {
530 printk("nf_conntrack_ipv6: can't register local out hook.\n");
531 goto cleanup_inops;
532 }
533
534 ret = nf_register_hook(&ipv6_conntrack_out_ops);
535 if (ret < 0) {
536 printk("nf_conntrack_ipv6: can't register post-routing hook.\n");
537 goto cleanup_inandlocalops;
538 }
539
540 ret = nf_register_hook(&ipv6_conntrack_local_in_ops);
541 if (ret < 0) {
542 printk("nf_conntrack_ipv6: can't register local in hook.\n");
543 goto cleanup_inoutandlocalops;
544 }
545
546#ifdef CONFIG_SYSCTL 514#ifdef CONFIG_SYSCTL
547 nf_ct_ipv6_sysctl_header = register_sysctl_table(nf_ct_net_table, 0); 515 nf_ct_ipv6_sysctl_header = register_sysctl_table(nf_ct_net_table, 0);
548 if (nf_ct_ipv6_sysctl_header == NULL) { 516 if (nf_ct_ipv6_sysctl_header == NULL) {
549 printk("nf_conntrack: can't register to sysctl.\n"); 517 printk("nf_conntrack: can't register to sysctl.\n");
550 ret = -ENOMEM; 518 ret = -ENOMEM;
551 goto cleanup_localinops; 519 goto cleanup_hooks;
552 } 520 }
553#endif 521#endif
554 return ret; 522 return ret;
555 523
556 cleanup:
557 synchronize_net();
558#ifdef CONFIG_SYSCTL 524#ifdef CONFIG_SYSCTL
559 unregister_sysctl_table(nf_ct_ipv6_sysctl_header); 525 cleanup_hooks:
560 cleanup_localinops: 526 nf_unregister_hooks(ipv6_conntrack_ops, ARRAY_SIZE(ipv6_conntrack_ops));
561#endif 527#endif
562 nf_unregister_hook(&ipv6_conntrack_local_in_ops);
563 cleanup_inoutandlocalops:
564 nf_unregister_hook(&ipv6_conntrack_out_ops);
565 cleanup_inandlocalops:
566 nf_unregister_hook(&ipv6_conntrack_local_out_ops);
567 cleanup_inops:
568 nf_unregister_hook(&ipv6_conntrack_in_ops);
569 cleanup_defraglocalops:
570 nf_unregister_hook(&ipv6_conntrack_defrag_local_out_ops);
571 cleanup_defragops:
572 nf_unregister_hook(&ipv6_conntrack_defrag_ops);
573 cleanup_ipv6: 528 cleanup_ipv6:
574 nf_conntrack_l3proto_unregister(&nf_conntrack_l3proto_ipv6); 529 nf_conntrack_l3proto_unregister(&nf_conntrack_l3proto_ipv6);
575 cleanup_icmpv6: 530 cleanup_icmpv6:
@@ -580,23 +535,21 @@ static int init_or_cleanup(int init)
580 nf_conntrack_protocol_unregister(&nf_conntrack_protocol_tcp6); 535 nf_conntrack_protocol_unregister(&nf_conntrack_protocol_tcp6);
581 cleanup_frag6: 536 cleanup_frag6:
582 nf_ct_frag6_cleanup(); 537 nf_ct_frag6_cleanup();
583 cleanup_nothing:
584 return ret; 538 return ret;
585} 539}
586 540
587MODULE_ALIAS("nf_conntrack-" __stringify(AF_INET6));
588MODULE_LICENSE("GPL");
589MODULE_AUTHOR("Yasuyuki KOZAKAI @USAGI <yasuyuki.kozakai@toshiba.co.jp>");
590
591static int __init nf_conntrack_l3proto_ipv6_init(void)
592{
593 need_conntrack();
594 return init_or_cleanup(1);
595}
596
597static void __exit nf_conntrack_l3proto_ipv6_fini(void) 541static void __exit nf_conntrack_l3proto_ipv6_fini(void)
598{ 542{
599 init_or_cleanup(0); 543 synchronize_net();
544#ifdef CONFIG_SYSCTL
545 unregister_sysctl_table(nf_ct_ipv6_sysctl_header);
546#endif
547 nf_unregister_hooks(ipv6_conntrack_ops, ARRAY_SIZE(ipv6_conntrack_ops));
548 nf_conntrack_l3proto_unregister(&nf_conntrack_l3proto_ipv6);
549 nf_conntrack_protocol_unregister(&nf_conntrack_protocol_icmpv6);
550 nf_conntrack_protocol_unregister(&nf_conntrack_protocol_udp6);
551 nf_conntrack_protocol_unregister(&nf_conntrack_protocol_tcp6);
552 nf_ct_frag6_cleanup();
600} 553}
601 554
602module_init(nf_conntrack_l3proto_ipv6_init); 555module_init(nf_conntrack_l3proto_ipv6_init);
diff --git a/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c b/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c
index 09945c333055..86c6703265d0 100644
--- a/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c
+++ b/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c
@@ -233,21 +233,13 @@ icmpv6_error(struct sk_buff *skb, unsigned int dataoff,
233 return -NF_ACCEPT; 233 return -NF_ACCEPT;
234 } 234 }
235 235
236 if (hooknum != NF_IP6_PRE_ROUTING) 236 if (hooknum == NF_IP6_PRE_ROUTING &&
237 goto skipped; 237 nf_ip6_checksum(skb, hooknum, dataoff, IPPROTO_ICMPV6)) {
238
239 /* Ignore it if the checksum's bogus. */
240 if (csum_ipv6_magic(&skb->nh.ipv6h->saddr, &skb->nh.ipv6h->daddr,
241 skb->len - dataoff, IPPROTO_ICMPV6,
242 skb_checksum(skb, dataoff,
243 skb->len - dataoff, 0))) {
244 nf_log_packet(PF_INET6, 0, skb, NULL, NULL, NULL, 238 nf_log_packet(PF_INET6, 0, skb, NULL, NULL, NULL,
245 "nf_ct_icmpv6: ICMPv6 checksum failed\n"); 239 "nf_ct_icmpv6: ICMPv6 checksum failed\n");
246 return -NF_ACCEPT; 240 return -NF_ACCEPT;
247 } 241 }
248 242
249skipped:
250
251 /* is not error message ? */ 243 /* is not error message ? */
252 if (icmp6h->icmp6_type >= 128) 244 if (icmp6h->icmp6_type >= 128)
253 return NF_ACCEPT; 245 return NF_ACCEPT;
diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c
index c2d3e17beae6..6578c3080f47 100644
--- a/net/ipv6/sit.c
+++ b/net/ipv6/sit.c
@@ -397,7 +397,7 @@ static int ipip6_rcv(struct sk_buff *skb)
397 return 0; 397 return 0;
398 } 398 }
399 399
400 icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PROT_UNREACH, 0); 400 icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0);
401 kfree_skb(skb); 401 kfree_skb(skb);
402 read_unlock(&ipip6_lock); 402 read_unlock(&ipip6_lock);
403out: 403out:
diff --git a/net/ipv6/tunnel6.c b/net/ipv6/tunnel6.c
index 5659b52284bd..0ef9a35798d1 100644
--- a/net/ipv6/tunnel6.c
+++ b/net/ipv6/tunnel6.c
@@ -19,11 +19,13 @@
19 * YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org> 19 * YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
20 */ 20 */
21 21
22#include <linux/icmpv6.h>
22#include <linux/init.h> 23#include <linux/init.h>
23#include <linux/module.h> 24#include <linux/module.h>
24#include <linux/mutex.h> 25#include <linux/mutex.h>
25#include <linux/netdevice.h> 26#include <linux/netdevice.h>
26#include <linux/skbuff.h> 27#include <linux/skbuff.h>
28#include <net/ipv6.h>
27#include <net/protocol.h> 29#include <net/protocol.h>
28#include <net/xfrm.h> 30#include <net/xfrm.h>
29 31
@@ -87,10 +89,16 @@ static int tunnel6_rcv(struct sk_buff **pskb)
87 struct sk_buff *skb = *pskb; 89 struct sk_buff *skb = *pskb;
88 struct xfrm6_tunnel *handler; 90 struct xfrm6_tunnel *handler;
89 91
92 if (!pskb_may_pull(skb, sizeof(struct ipv6hdr)))
93 goto drop;
94
90 for (handler = tunnel6_handlers; handler; handler = handler->next) 95 for (handler = tunnel6_handlers; handler; handler = handler->next)
91 if (!handler->handler(skb)) 96 if (!handler->handler(skb))
92 return 0; 97 return 0;
93 98
99 icmpv6_send(skb, ICMPV6_DEST_UNREACH, ICMPV6_PORT_UNREACH, 0, skb->dev);
100
101drop:
94 kfree_skb(skb); 102 kfree_skb(skb);
95 return 0; 103 return 0;
96} 104}
diff --git a/net/netfilter/core.c b/net/netfilter/core.c
index 1ceb1a6c254b..8455a32ea5c4 100644
--- a/net/netfilter/core.c
+++ b/net/netfilter/core.c
@@ -27,6 +27,29 @@
27 27
28#include "nf_internals.h" 28#include "nf_internals.h"
29 29
30static DEFINE_SPINLOCK(afinfo_lock);
31
32struct nf_afinfo *nf_afinfo[NPROTO];
33EXPORT_SYMBOL(nf_afinfo);
34
35int nf_register_afinfo(struct nf_afinfo *afinfo)
36{
37 spin_lock(&afinfo_lock);
38 rcu_assign_pointer(nf_afinfo[afinfo->family], afinfo);
39 spin_unlock(&afinfo_lock);
40 return 0;
41}
42EXPORT_SYMBOL_GPL(nf_register_afinfo);
43
44void nf_unregister_afinfo(struct nf_afinfo *afinfo)
45{
46 spin_lock(&afinfo_lock);
47 rcu_assign_pointer(nf_afinfo[afinfo->family], NULL);
48 spin_unlock(&afinfo_lock);
49 synchronize_rcu();
50}
51EXPORT_SYMBOL_GPL(nf_unregister_afinfo);
52
30/* In this code, we can be waiting indefinitely for userspace to 53/* In this code, we can be waiting indefinitely for userspace to
31 * service a packet if a hook returns NF_QUEUE. We could keep a count 54 * service a packet if a hook returns NF_QUEUE. We could keep a count
32 * of skbuffs queued for userspace, and not deregister a hook unless 55 * of skbuffs queued for userspace, and not deregister a hook unless
@@ -63,6 +86,34 @@ void nf_unregister_hook(struct nf_hook_ops *reg)
63} 86}
64EXPORT_SYMBOL(nf_unregister_hook); 87EXPORT_SYMBOL(nf_unregister_hook);
65 88
89int nf_register_hooks(struct nf_hook_ops *reg, unsigned int n)
90{
91 unsigned int i;
92 int err = 0;
93
94 for (i = 0; i < n; i++) {
95 err = nf_register_hook(&reg[i]);
96 if (err)
97 goto err;
98 }
99 return err;
100
101err:
102 if (i > 0)
103 nf_unregister_hooks(reg, i);
104 return err;
105}
106EXPORT_SYMBOL(nf_register_hooks);
107
108void nf_unregister_hooks(struct nf_hook_ops *reg, unsigned int n)
109{
110 unsigned int i;
111
112 for (i = 0; i < n; i++)
113 nf_unregister_hook(&reg[i]);
114}
115EXPORT_SYMBOL(nf_unregister_hooks);
116
66unsigned int nf_iterate(struct list_head *head, 117unsigned int nf_iterate(struct list_head *head,
67 struct sk_buff **skb, 118 struct sk_buff **skb,
68 int hook, 119 int hook,
diff --git a/net/netfilter/nf_conntrack_proto_tcp.c b/net/netfilter/nf_conntrack_proto_tcp.c
index 6492ed66fb3c..69899f27d26a 100644
--- a/net/netfilter/nf_conntrack_proto_tcp.c
+++ b/net/netfilter/nf_conntrack_proto_tcp.c
@@ -799,8 +799,7 @@ static int tcp_error(struct sk_buff *skb,
799 unsigned int dataoff, 799 unsigned int dataoff,
800 enum ip_conntrack_info *ctinfo, 800 enum ip_conntrack_info *ctinfo,
801 int pf, 801 int pf,
802 unsigned int hooknum, 802 unsigned int hooknum)
803 int(*csum)(const struct sk_buff *,unsigned int))
804{ 803{
805 struct tcphdr _tcph, *th; 804 struct tcphdr _tcph, *th;
806 unsigned int tcplen = skb->len - dataoff; 805 unsigned int tcplen = skb->len - dataoff;
@@ -830,9 +829,8 @@ static int tcp_error(struct sk_buff *skb,
830 */ 829 */
831 /* FIXME: Source route IP option packets --RR */ 830 /* FIXME: Source route IP option packets --RR */
832 if (((pf == PF_INET && hooknum == NF_IP_PRE_ROUTING) || 831 if (((pf == PF_INET && hooknum == NF_IP_PRE_ROUTING) ||
833 (pf == PF_INET6 && hooknum == NF_IP6_PRE_ROUTING)) 832 (pf == PF_INET6 && hooknum == NF_IP6_PRE_ROUTING)) &&
834 && skb->ip_summed != CHECKSUM_UNNECESSARY 833 nf_checksum(skb, hooknum, dataoff, IPPROTO_TCP, pf)) {
835 && csum(skb, dataoff)) {
836 if (LOG_INVALID(IPPROTO_TCP)) 834 if (LOG_INVALID(IPPROTO_TCP))
837 nf_log_packet(pf, 0, skb, NULL, NULL, NULL, 835 nf_log_packet(pf, 0, skb, NULL, NULL, NULL,
838 "nf_ct_tcp: bad TCP checksum "); 836 "nf_ct_tcp: bad TCP checksum ");
@@ -851,44 +849,6 @@ static int tcp_error(struct sk_buff *skb,
851 return NF_ACCEPT; 849 return NF_ACCEPT;
852} 850}
853 851
854static int csum4(const struct sk_buff *skb, unsigned int dataoff)
855{
856 return csum_tcpudp_magic(skb->nh.iph->saddr, skb->nh.iph->daddr,
857 skb->len - dataoff, IPPROTO_TCP,
858 skb->ip_summed == CHECKSUM_HW ? skb->csum
859 : skb_checksum(skb, dataoff,
860 skb->len - dataoff, 0));
861}
862
863static int csum6(const struct sk_buff *skb, unsigned int dataoff)
864{
865 return csum_ipv6_magic(&skb->nh.ipv6h->saddr, &skb->nh.ipv6h->daddr,
866 skb->len - dataoff, IPPROTO_TCP,
867 skb->ip_summed == CHECKSUM_HW
868 ? csum_sub(skb->csum,
869 skb_checksum(skb, 0, dataoff, 0))
870 : skb_checksum(skb, dataoff, skb->len - dataoff,
871 0));
872}
873
874static int tcp_error4(struct sk_buff *skb,
875 unsigned int dataoff,
876 enum ip_conntrack_info *ctinfo,
877 int pf,
878 unsigned int hooknum)
879{
880 return tcp_error(skb, dataoff, ctinfo, pf, hooknum, csum4);
881}
882
883static int tcp_error6(struct sk_buff *skb,
884 unsigned int dataoff,
885 enum ip_conntrack_info *ctinfo,
886 int pf,
887 unsigned int hooknum)
888{
889 return tcp_error(skb, dataoff, ctinfo, pf, hooknum, csum6);
890}
891
892/* Returns verdict for packet, or -1 for invalid. */ 852/* Returns verdict for packet, or -1 for invalid. */
893static int tcp_packet(struct nf_conn *conntrack, 853static int tcp_packet(struct nf_conn *conntrack,
894 const struct sk_buff *skb, 854 const struct sk_buff *skb,
@@ -1218,7 +1178,7 @@ struct nf_conntrack_protocol nf_conntrack_protocol_tcp4 =
1218 .print_conntrack = tcp_print_conntrack, 1178 .print_conntrack = tcp_print_conntrack,
1219 .packet = tcp_packet, 1179 .packet = tcp_packet,
1220 .new = tcp_new, 1180 .new = tcp_new,
1221 .error = tcp_error4, 1181 .error = tcp_error,
1222#if defined(CONFIG_NF_CT_NETLINK) || \ 1182#if defined(CONFIG_NF_CT_NETLINK) || \
1223 defined(CONFIG_NF_CT_NETLINK_MODULE) 1183 defined(CONFIG_NF_CT_NETLINK_MODULE)
1224 .to_nfattr = tcp_to_nfattr, 1184 .to_nfattr = tcp_to_nfattr,
@@ -1239,7 +1199,7 @@ struct nf_conntrack_protocol nf_conntrack_protocol_tcp6 =
1239 .print_conntrack = tcp_print_conntrack, 1199 .print_conntrack = tcp_print_conntrack,
1240 .packet = tcp_packet, 1200 .packet = tcp_packet,
1241 .new = tcp_new, 1201 .new = tcp_new,
1242 .error = tcp_error6, 1202 .error = tcp_error,
1243#if defined(CONFIG_NF_CT_NETLINK) || \ 1203#if defined(CONFIG_NF_CT_NETLINK) || \
1244 defined(CONFIG_NF_CT_NETLINK_MODULE) 1204 defined(CONFIG_NF_CT_NETLINK_MODULE)
1245 .to_nfattr = tcp_to_nfattr, 1205 .to_nfattr = tcp_to_nfattr,
diff --git a/net/netfilter/nf_conntrack_proto_udp.c b/net/netfilter/nf_conntrack_proto_udp.c
index 831d206344e0..d93edbfde9e3 100644
--- a/net/netfilter/nf_conntrack_proto_udp.c
+++ b/net/netfilter/nf_conntrack_proto_udp.c
@@ -103,8 +103,7 @@ static int udp_new(struct nf_conn *conntrack, const struct sk_buff *skb,
103static int udp_error(struct sk_buff *skb, unsigned int dataoff, 103static int udp_error(struct sk_buff *skb, unsigned int dataoff,
104 enum ip_conntrack_info *ctinfo, 104 enum ip_conntrack_info *ctinfo,
105 int pf, 105 int pf,
106 unsigned int hooknum, 106 unsigned int hooknum)
107 int (*csum)(const struct sk_buff *, unsigned int))
108{ 107{
109 unsigned int udplen = skb->len - dataoff; 108 unsigned int udplen = skb->len - dataoff;
110 struct udphdr _hdr, *hdr; 109 struct udphdr _hdr, *hdr;
@@ -136,9 +135,8 @@ static int udp_error(struct sk_buff *skb, unsigned int dataoff,
136 * and moreover root might send raw packets. 135 * and moreover root might send raw packets.
137 * FIXME: Source route IP option packets --RR */ 136 * FIXME: Source route IP option packets --RR */
138 if (((pf == PF_INET && hooknum == NF_IP_PRE_ROUTING) || 137 if (((pf == PF_INET && hooknum == NF_IP_PRE_ROUTING) ||
139 (pf == PF_INET6 && hooknum == NF_IP6_PRE_ROUTING)) 138 (pf == PF_INET6 && hooknum == NF_IP6_PRE_ROUTING)) &&
140 && skb->ip_summed != CHECKSUM_UNNECESSARY 139 nf_checksum(skb, hooknum, dataoff, IPPROTO_UDP, pf)) {
141 && csum(skb, dataoff)) {
142 if (LOG_INVALID(IPPROTO_UDP)) 140 if (LOG_INVALID(IPPROTO_UDP))
143 nf_log_packet(pf, 0, skb, NULL, NULL, NULL, 141 nf_log_packet(pf, 0, skb, NULL, NULL, NULL,
144 "nf_ct_udp: bad UDP checksum "); 142 "nf_ct_udp: bad UDP checksum ");
@@ -148,44 +146,6 @@ static int udp_error(struct sk_buff *skb, unsigned int dataoff,
148 return NF_ACCEPT; 146 return NF_ACCEPT;
149} 147}
150 148
151static int csum4(const struct sk_buff *skb, unsigned int dataoff)
152{
153 return csum_tcpudp_magic(skb->nh.iph->saddr, skb->nh.iph->daddr,
154 skb->len - dataoff, IPPROTO_UDP,
155 skb->ip_summed == CHECKSUM_HW ? skb->csum
156 : skb_checksum(skb, dataoff,
157 skb->len - dataoff, 0));
158}
159
160static int csum6(const struct sk_buff *skb, unsigned int dataoff)
161{
162 return csum_ipv6_magic(&skb->nh.ipv6h->saddr, &skb->nh.ipv6h->daddr,
163 skb->len - dataoff, IPPROTO_UDP,
164 skb->ip_summed == CHECKSUM_HW
165 ? csum_sub(skb->csum,
166 skb_checksum(skb, 0, dataoff, 0))
167 : skb_checksum(skb, dataoff, skb->len - dataoff,
168 0));
169}
170
171static int udp_error4(struct sk_buff *skb,
172 unsigned int dataoff,
173 enum ip_conntrack_info *ctinfo,
174 int pf,
175 unsigned int hooknum)
176{
177 return udp_error(skb, dataoff, ctinfo, pf, hooknum, csum4);
178}
179
180static int udp_error6(struct sk_buff *skb,
181 unsigned int dataoff,
182 enum ip_conntrack_info *ctinfo,
183 int pf,
184 unsigned int hooknum)
185{
186 return udp_error(skb, dataoff, ctinfo, pf, hooknum, csum6);
187}
188
189struct nf_conntrack_protocol nf_conntrack_protocol_udp4 = 149struct nf_conntrack_protocol nf_conntrack_protocol_udp4 =
190{ 150{
191 .l3proto = PF_INET, 151 .l3proto = PF_INET,
@@ -197,7 +157,7 @@ struct nf_conntrack_protocol nf_conntrack_protocol_udp4 =
197 .print_conntrack = udp_print_conntrack, 157 .print_conntrack = udp_print_conntrack,
198 .packet = udp_packet, 158 .packet = udp_packet,
199 .new = udp_new, 159 .new = udp_new,
200 .error = udp_error4, 160 .error = udp_error,
201#if defined(CONFIG_NF_CT_NETLINK) || \ 161#if defined(CONFIG_NF_CT_NETLINK) || \
202 defined(CONFIG_NF_CT_NETLINK_MODULE) 162 defined(CONFIG_NF_CT_NETLINK_MODULE)
203 .tuple_to_nfattr = nf_ct_port_tuple_to_nfattr, 163 .tuple_to_nfattr = nf_ct_port_tuple_to_nfattr,
@@ -216,7 +176,7 @@ struct nf_conntrack_protocol nf_conntrack_protocol_udp6 =
216 .print_conntrack = udp_print_conntrack, 176 .print_conntrack = udp_print_conntrack,
217 .packet = udp_packet, 177 .packet = udp_packet,
218 .new = udp_new, 178 .new = udp_new,
219 .error = udp_error6, 179 .error = udp_error,
220#if defined(CONFIG_NF_CT_NETLINK) || \ 180#if defined(CONFIG_NF_CT_NETLINK) || \
221 defined(CONFIG_NF_CT_NETLINK_MODULE) 181 defined(CONFIG_NF_CT_NETLINK_MODULE)
222 .tuple_to_nfattr = nf_ct_port_tuple_to_nfattr, 182 .tuple_to_nfattr = nf_ct_port_tuple_to_nfattr,
diff --git a/net/netfilter/nf_conntrack_standalone.c b/net/netfilter/nf_conntrack_standalone.c
index c72aa3cd22e4..408960c6a544 100644
--- a/net/netfilter/nf_conntrack_standalone.c
+++ b/net/netfilter/nf_conntrack_standalone.c
@@ -649,63 +649,6 @@ static ctl_table nf_ct_net_table[] = {
649EXPORT_SYMBOL(nf_ct_log_invalid); 649EXPORT_SYMBOL(nf_ct_log_invalid);
650#endif /* CONFIG_SYSCTL */ 650#endif /* CONFIG_SYSCTL */
651 651
652static int init_or_cleanup(int init)
653{
654#ifdef CONFIG_PROC_FS
655 struct proc_dir_entry *proc, *proc_exp, *proc_stat;
656#endif
657 int ret = 0;
658
659 if (!init) goto cleanup;
660
661 ret = nf_conntrack_init();
662 if (ret < 0)
663 goto cleanup_nothing;
664
665#ifdef CONFIG_PROC_FS
666 proc = proc_net_fops_create("nf_conntrack", 0440, &ct_file_ops);
667 if (!proc) goto cleanup_init;
668
669 proc_exp = proc_net_fops_create("nf_conntrack_expect", 0440,
670 &exp_file_ops);
671 if (!proc_exp) goto cleanup_proc;
672
673 proc_stat = create_proc_entry("nf_conntrack", S_IRUGO, proc_net_stat);
674 if (!proc_stat)
675 goto cleanup_proc_exp;
676
677 proc_stat->proc_fops = &ct_cpu_seq_fops;
678 proc_stat->owner = THIS_MODULE;
679#endif
680#ifdef CONFIG_SYSCTL
681 nf_ct_sysctl_header = register_sysctl_table(nf_ct_net_table, 0);
682 if (nf_ct_sysctl_header == NULL) {
683 printk("nf_conntrack: can't register to sysctl.\n");
684 ret = -ENOMEM;
685 goto cleanup_proc_stat;
686 }
687#endif
688
689 return ret;
690
691 cleanup:
692#ifdef CONFIG_SYSCTL
693 unregister_sysctl_table(nf_ct_sysctl_header);
694 cleanup_proc_stat:
695#endif
696#ifdef CONFIG_PROC_FS
697 remove_proc_entry("nf_conntrack", proc_net_stat);
698 cleanup_proc_exp:
699 proc_net_remove("nf_conntrack_expect");
700 cleanup_proc:
701 proc_net_remove("nf_conntrack");
702 cleanup_init:
703#endif /* CNFIG_PROC_FS */
704 nf_conntrack_cleanup();
705 cleanup_nothing:
706 return ret;
707}
708
709int nf_conntrack_l3proto_register(struct nf_conntrack_l3proto *proto) 652int nf_conntrack_l3proto_register(struct nf_conntrack_l3proto *proto)
710{ 653{
711 int ret = 0; 654 int ret = 0;
@@ -808,12 +751,66 @@ void nf_conntrack_protocol_unregister(struct nf_conntrack_protocol *proto)
808 751
809static int __init nf_conntrack_standalone_init(void) 752static int __init nf_conntrack_standalone_init(void)
810{ 753{
811 return init_or_cleanup(1); 754#ifdef CONFIG_PROC_FS
755 struct proc_dir_entry *proc, *proc_exp, *proc_stat;
756#endif
757 int ret = 0;
758
759 ret = nf_conntrack_init();
760 if (ret < 0)
761 return ret;
762
763#ifdef CONFIG_PROC_FS
764 proc = proc_net_fops_create("nf_conntrack", 0440, &ct_file_ops);
765 if (!proc) goto cleanup_init;
766
767 proc_exp = proc_net_fops_create("nf_conntrack_expect", 0440,
768 &exp_file_ops);
769 if (!proc_exp) goto cleanup_proc;
770
771 proc_stat = create_proc_entry("nf_conntrack", S_IRUGO, proc_net_stat);
772 if (!proc_stat)
773 goto cleanup_proc_exp;
774
775 proc_stat->proc_fops = &ct_cpu_seq_fops;
776 proc_stat->owner = THIS_MODULE;
777#endif
778#ifdef CONFIG_SYSCTL
779 nf_ct_sysctl_header = register_sysctl_table(nf_ct_net_table, 0);
780 if (nf_ct_sysctl_header == NULL) {
781 printk("nf_conntrack: can't register to sysctl.\n");
782 ret = -ENOMEM;
783 goto cleanup_proc_stat;
784 }
785#endif
786 return ret;
787
788#ifdef CONFIG_SYSCTL
789 cleanup_proc_stat:
790#endif
791#ifdef CONFIG_PROC_FS
792 remove_proc_entry("nf_conntrack", proc_net_stat);
793 cleanup_proc_exp:
794 proc_net_remove("nf_conntrack_expect");
795 cleanup_proc:
796 proc_net_remove("nf_conntrack");
797 cleanup_init:
798#endif /* CNFIG_PROC_FS */
799 nf_conntrack_cleanup();
800 return ret;
812} 801}
813 802
814static void __exit nf_conntrack_standalone_fini(void) 803static void __exit nf_conntrack_standalone_fini(void)
815{ 804{
816 init_or_cleanup(0); 805#ifdef CONFIG_SYSCTL
806 unregister_sysctl_table(nf_ct_sysctl_header);
807#endif
808#ifdef CONFIG_PROC_FS
809 remove_proc_entry("nf_conntrack", proc_net_stat);
810 proc_net_remove("nf_conntrack_expect");
811 proc_net_remove("nf_conntrack");
812#endif /* CNFIG_PROC_FS */
813 nf_conntrack_cleanup();
817} 814}
818 815
819module_init(nf_conntrack_standalone_init); 816module_init(nf_conntrack_standalone_init);
diff --git a/net/netfilter/nf_queue.c b/net/netfilter/nf_queue.c
index d9f0d7ef103b..ee8f70889f47 100644
--- a/net/netfilter/nf_queue.c
+++ b/net/netfilter/nf_queue.c
@@ -17,7 +17,6 @@
17 * for queueing and must reinject all packets it receives, no matter what. 17 * for queueing and must reinject all packets it receives, no matter what.
18 */ 18 */
19static struct nf_queue_handler *queue_handler[NPROTO]; 19static struct nf_queue_handler *queue_handler[NPROTO];
20static struct nf_queue_rerouter *queue_rerouter[NPROTO];
21 20
22static DEFINE_RWLOCK(queue_handler_lock); 21static DEFINE_RWLOCK(queue_handler_lock);
23 22
@@ -59,32 +58,6 @@ int nf_unregister_queue_handler(int pf)
59} 58}
60EXPORT_SYMBOL(nf_unregister_queue_handler); 59EXPORT_SYMBOL(nf_unregister_queue_handler);
61 60
62int nf_register_queue_rerouter(int pf, struct nf_queue_rerouter *rer)
63{
64 if (pf >= NPROTO)
65 return -EINVAL;
66
67 write_lock_bh(&queue_handler_lock);
68 rcu_assign_pointer(queue_rerouter[pf], rer);
69 write_unlock_bh(&queue_handler_lock);
70
71 return 0;
72}
73EXPORT_SYMBOL_GPL(nf_register_queue_rerouter);
74
75int nf_unregister_queue_rerouter(int pf)
76{
77 if (pf >= NPROTO)
78 return -EINVAL;
79
80 write_lock_bh(&queue_handler_lock);
81 rcu_assign_pointer(queue_rerouter[pf], NULL);
82 write_unlock_bh(&queue_handler_lock);
83 synchronize_rcu();
84 return 0;
85}
86EXPORT_SYMBOL_GPL(nf_unregister_queue_rerouter);
87
88void nf_unregister_queue_handlers(struct nf_queue_handler *qh) 61void nf_unregister_queue_handlers(struct nf_queue_handler *qh)
89{ 62{
90 int pf; 63 int pf;
@@ -116,7 +89,7 @@ int nf_queue(struct sk_buff **skb,
116 struct net_device *physindev = NULL; 89 struct net_device *physindev = NULL;
117 struct net_device *physoutdev = NULL; 90 struct net_device *physoutdev = NULL;
118#endif 91#endif
119 struct nf_queue_rerouter *rerouter; 92 struct nf_afinfo *afinfo;
120 93
121 /* QUEUE == DROP if noone is waiting, to be safe. */ 94 /* QUEUE == DROP if noone is waiting, to be safe. */
122 read_lock(&queue_handler_lock); 95 read_lock(&queue_handler_lock);
@@ -126,7 +99,14 @@ int nf_queue(struct sk_buff **skb,
126 return 1; 99 return 1;
127 } 100 }
128 101
129 info = kmalloc(sizeof(*info)+queue_rerouter[pf]->rer_size, GFP_ATOMIC); 102 afinfo = nf_get_afinfo(pf);
103 if (!afinfo) {
104 read_unlock(&queue_handler_lock);
105 kfree_skb(*skb);
106 return 1;
107 }
108
109 info = kmalloc(sizeof(*info) + afinfo->route_key_size, GFP_ATOMIC);
130 if (!info) { 110 if (!info) {
131 if (net_ratelimit()) 111 if (net_ratelimit())
132 printk(KERN_ERR "OOM queueing packet %p\n", 112 printk(KERN_ERR "OOM queueing packet %p\n",
@@ -158,10 +138,7 @@ int nf_queue(struct sk_buff **skb,
158 if (physoutdev) dev_hold(physoutdev); 138 if (physoutdev) dev_hold(physoutdev);
159 } 139 }
160#endif 140#endif
161 rerouter = rcu_dereference(queue_rerouter[pf]); 141 afinfo->saveroute(*skb, info);
162 if (rerouter)
163 rerouter->save(*skb, info);
164
165 status = queue_handler[pf]->outfn(*skb, info, queuenum, 142 status = queue_handler[pf]->outfn(*skb, info, queuenum,
166 queue_handler[pf]->data); 143 queue_handler[pf]->data);
167 144
@@ -190,7 +167,7 @@ void nf_reinject(struct sk_buff *skb, struct nf_info *info,
190{ 167{
191 struct list_head *elem = &info->elem->list; 168 struct list_head *elem = &info->elem->list;
192 struct list_head *i; 169 struct list_head *i;
193 struct nf_queue_rerouter *rerouter; 170 struct nf_afinfo *afinfo;
194 171
195 rcu_read_lock(); 172 rcu_read_lock();
196 173
@@ -228,8 +205,8 @@ void nf_reinject(struct sk_buff *skb, struct nf_info *info,
228 } 205 }
229 206
230 if (verdict == NF_ACCEPT) { 207 if (verdict == NF_ACCEPT) {
231 rerouter = rcu_dereference(queue_rerouter[info->pf]); 208 afinfo = nf_get_afinfo(info->pf);
232 if (rerouter && rerouter->reroute(&skb, info) < 0) 209 if (!afinfo || afinfo->reroute(&skb, info) < 0)
233 verdict = NF_DROP; 210 verdict = NF_DROP;
234 } 211 }
235 212
diff --git a/net/netfilter/nfnetlink_log.c b/net/netfilter/nfnetlink_log.c
index 3e3f5448bacb..c60273cad778 100644
--- a/net/netfilter/nfnetlink_log.c
+++ b/net/netfilter/nfnetlink_log.c
@@ -1033,17 +1033,13 @@ static struct file_operations nful_file_ops = {
1033 1033
1034#endif /* PROC_FS */ 1034#endif /* PROC_FS */
1035 1035
1036static int 1036static int __init nfnetlink_log_init(void)
1037init_or_cleanup(int init)
1038{ 1037{
1039 int i, status = -ENOMEM; 1038 int i, status = -ENOMEM;
1040#ifdef CONFIG_PROC_FS 1039#ifdef CONFIG_PROC_FS
1041 struct proc_dir_entry *proc_nful; 1040 struct proc_dir_entry *proc_nful;
1042#endif 1041#endif
1043 1042
1044 if (!init)
1045 goto cleanup;
1046
1047 for (i = 0; i < INSTANCE_BUCKETS; i++) 1043 for (i = 0; i < INSTANCE_BUCKETS; i++)
1048 INIT_HLIST_HEAD(&instance_table[i]); 1044 INIT_HLIST_HEAD(&instance_table[i]);
1049 1045
@@ -1066,30 +1062,25 @@ init_or_cleanup(int init)
1066 goto cleanup_subsys; 1062 goto cleanup_subsys;
1067 proc_nful->proc_fops = &nful_file_ops; 1063 proc_nful->proc_fops = &nful_file_ops;
1068#endif 1064#endif
1069
1070 return status; 1065 return status;
1071 1066
1072cleanup:
1073 nf_log_unregister_logger(&nfulnl_logger);
1074#ifdef CONFIG_PROC_FS 1067#ifdef CONFIG_PROC_FS
1075 remove_proc_entry("nfnetlink_log", proc_net_netfilter);
1076cleanup_subsys: 1068cleanup_subsys:
1077#endif
1078 nfnetlink_subsys_unregister(&nfulnl_subsys); 1069 nfnetlink_subsys_unregister(&nfulnl_subsys);
1070#endif
1079cleanup_netlink_notifier: 1071cleanup_netlink_notifier:
1080 netlink_unregister_notifier(&nfulnl_rtnl_notifier); 1072 netlink_unregister_notifier(&nfulnl_rtnl_notifier);
1081 return status; 1073 return status;
1082} 1074}
1083 1075
1084static int __init nfnetlink_log_init(void)
1085{
1086
1087 return init_or_cleanup(1);
1088}
1089
1090static void __exit nfnetlink_log_fini(void) 1076static void __exit nfnetlink_log_fini(void)
1091{ 1077{
1092 init_or_cleanup(0); 1078 nf_log_unregister_logger(&nfulnl_logger);
1079#ifdef CONFIG_PROC_FS
1080 remove_proc_entry("nfnetlink_log", proc_net_netfilter);
1081#endif
1082 nfnetlink_subsys_unregister(&nfulnl_subsys);
1083 netlink_unregister_notifier(&nfulnl_rtnl_notifier);
1093} 1084}
1094 1085
1095MODULE_DESCRIPTION("netfilter userspace logging"); 1086MODULE_DESCRIPTION("netfilter userspace logging");
diff --git a/net/netfilter/nfnetlink_queue.c b/net/netfilter/nfnetlink_queue.c
index d0e62f68139f..86a4ac33de34 100644
--- a/net/netfilter/nfnetlink_queue.c
+++ b/net/netfilter/nfnetlink_queue.c
@@ -1071,17 +1071,13 @@ static struct file_operations nfqnl_file_ops = {
1071 1071
1072#endif /* PROC_FS */ 1072#endif /* PROC_FS */
1073 1073
1074static int 1074static int __init nfnetlink_queue_init(void)
1075init_or_cleanup(int init)
1076{ 1075{
1077 int i, status = -ENOMEM; 1076 int i, status = -ENOMEM;
1078#ifdef CONFIG_PROC_FS 1077#ifdef CONFIG_PROC_FS
1079 struct proc_dir_entry *proc_nfqueue; 1078 struct proc_dir_entry *proc_nfqueue;
1080#endif 1079#endif
1081 1080
1082 if (!init)
1083 goto cleanup;
1084
1085 for (i = 0; i < INSTANCE_BUCKETS; i++) 1081 for (i = 0; i < INSTANCE_BUCKETS; i++)
1086 INIT_HLIST_HEAD(&instance_table[i]); 1082 INIT_HLIST_HEAD(&instance_table[i]);
1087 1083
@@ -1101,31 +1097,26 @@ init_or_cleanup(int init)
1101#endif 1097#endif
1102 1098
1103 register_netdevice_notifier(&nfqnl_dev_notifier); 1099 register_netdevice_notifier(&nfqnl_dev_notifier);
1104
1105 return status; 1100 return status;
1106 1101
1107cleanup:
1108 nf_unregister_queue_handlers(&nfqh);
1109 unregister_netdevice_notifier(&nfqnl_dev_notifier);
1110#ifdef CONFIG_PROC_FS 1102#ifdef CONFIG_PROC_FS
1111 remove_proc_entry("nfnetlink_queue", proc_net_netfilter);
1112cleanup_subsys: 1103cleanup_subsys:
1113#endif
1114 nfnetlink_subsys_unregister(&nfqnl_subsys); 1104 nfnetlink_subsys_unregister(&nfqnl_subsys);
1105#endif
1115cleanup_netlink_notifier: 1106cleanup_netlink_notifier:
1116 netlink_unregister_notifier(&nfqnl_rtnl_notifier); 1107 netlink_unregister_notifier(&nfqnl_rtnl_notifier);
1117 return status; 1108 return status;
1118} 1109}
1119 1110
1120static int __init nfnetlink_queue_init(void)
1121{
1122
1123 return init_or_cleanup(1);
1124}
1125
1126static void __exit nfnetlink_queue_fini(void) 1111static void __exit nfnetlink_queue_fini(void)
1127{ 1112{
1128 init_or_cleanup(0); 1113 nf_unregister_queue_handlers(&nfqh);
1114 unregister_netdevice_notifier(&nfqnl_dev_notifier);
1115#ifdef CONFIG_PROC_FS
1116 remove_proc_entry("nfnetlink_queue", proc_net_netfilter);
1117#endif
1118 nfnetlink_subsys_unregister(&nfqnl_subsys);
1119 netlink_unregister_notifier(&nfqnl_rtnl_notifier);
1129} 1120}
1130 1121
1131MODULE_DESCRIPTION("netfilter packet queue handler"); 1122MODULE_DESCRIPTION("netfilter packet queue handler");
diff --git a/net/sched/act_police.c b/net/sched/act_police.c
index fa877f8f652c..24c348fa8922 100644
--- a/net/sched/act_police.c
+++ b/net/sched/act_police.c
@@ -66,7 +66,7 @@ static __inline__ struct tcf_police * tcf_police_lookup(u32 index)
66} 66}
67 67
68#ifdef CONFIG_NET_CLS_ACT 68#ifdef CONFIG_NET_CLS_ACT
69static int tcf_generic_walker(struct sk_buff *skb, struct netlink_callback *cb, 69static int tcf_act_police_walker(struct sk_buff *skb, struct netlink_callback *cb,
70 int type, struct tc_action *a) 70 int type, struct tc_action *a)
71{ 71{
72 struct tcf_police *p; 72 struct tcf_police *p;
@@ -113,7 +113,7 @@ rtattr_failure:
113} 113}
114 114
115static inline int 115static inline int
116tcf_hash_search(struct tc_action *a, u32 index) 116tcf_act_police_hash_search(struct tc_action *a, u32 index)
117{ 117{
118 struct tcf_police *p = tcf_police_lookup(index); 118 struct tcf_police *p = tcf_police_lookup(index);
119 119
@@ -387,9 +387,9 @@ static struct tc_action_ops act_police_ops = {
387 .act = tcf_act_police, 387 .act = tcf_act_police,
388 .dump = tcf_act_police_dump, 388 .dump = tcf_act_police_dump,
389 .cleanup = tcf_act_police_cleanup, 389 .cleanup = tcf_act_police_cleanup,
390 .lookup = tcf_hash_search, 390 .lookup = tcf_act_police_hash_search,
391 .init = tcf_act_police_locate, 391 .init = tcf_act_police_locate,
392 .walk = tcf_generic_walker 392 .walk = tcf_act_police_walker
393}; 393};
394 394
395static int __init 395static int __init