diff options
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 | } |
1587 | EXPORT_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 | ||
110 | static void irda_usb_init_qos(struct irda_usb_cb *self) ; | ||
102 | static struct irda_class_desc *irda_usb_find_class_desc(struct usb_interface *intf); | 111 | static struct irda_class_desc *irda_usb_find_class_desc(struct usb_interface *intf); |
103 | static void irda_usb_disconnect(struct usb_interface *intf); | 112 | static void irda_usb_disconnect(struct usb_interface *intf); |
104 | static void irda_usb_change_speed_xbofs(struct irda_usb_cb *self); | 113 | static 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 | */ | ||
271 | static __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 | */ | ||
1036 | static char * stir421x_patches[] = { | ||
1037 | "42101001.sb", | ||
1038 | "42101002.sb", | ||
1039 | }; | ||
1040 | |||
1041 | static 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 | |||
1087 | static 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 | |||
1139 | static 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 | ||
1513 | err_out_4: | 1835 | err_out_4: |
@@ -1518,7 +1840,7 @@ err_out_3: | |||
1518 | err_out_2: | 1840 | err_out_2: |
1519 | usb_free_urb(self->tx_urb); | 1841 | usb_free_urb(self->tx_urb); |
1520 | err_out_1: | 1842 | err_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 | */ |
1649 | module_param(qos_mtt_bits, int, 0); | 1972 | module_param(qos_mtt_bits, int, 0); |
1650 | MODULE_PARM_DESC(qos_mtt_bits, "Minimum Turn Time"); | 1973 | MODULE_PARM_DESC(qos_mtt_bits, "Minimum Turn Time"); |
1651 | MODULE_AUTHOR("Roman Weissgaerber <weissg@vienna.at>, Dag Brattli <dag@brattli.net> and Jean Tourrilhes <jt@hpl.hp.com>"); | 1974 | MODULE_AUTHOR("Roman Weissgaerber <weissg@vienna.at>, Dag Brattli <dag@brattli.net>, Jean Tourrilhes <jt@hpl.hp.com> and Nick Fedchik <nick@fedchik.org.ua>"); |
1652 | MODULE_DESCRIPTION("IrDA-USB Dongle Driver"); | 1975 | MODULE_DESCRIPTION("IrDA-USB Dongle Driver"); |
1653 | MODULE_LICENSE("GPL"); | 1976 | MODULE_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 | ||
109 | struct irda_class_desc { | 119 | struct 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 | ||
127 | struct irda_usb_cb { | 138 | struct 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 | ||
108 | struct 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 | |||
103 | struct smsc_transceiver { | 123 | struct 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 | |||
202 | static int __init smsc_superio_paged(const struct smsc_chip *chips, unsigned short cfg_base, char *type); | 222 | static int __init smsc_superio_paged(const struct smsc_chip *chips, unsigned short cfg_base, char *type); |
203 | static int __init smsc_superio_fdc(unsigned short cfg_base); | 223 | static int __init smsc_superio_fdc(unsigned short cfg_base); |
204 | static int __init smsc_superio_lpc(unsigned short cfg_base); | 224 | static int __init smsc_superio_lpc(unsigned short cfg_base); |
225 | #ifdef CONFIG_PCI | ||
226 | static int __init preconfigure_smsc_chip(struct smsc_ircc_subsystem_configuration *conf); | ||
227 | static int __init preconfigure_through_82801(struct pci_dev *dev, struct smsc_ircc_subsystem_configuration *conf); | ||
228 | static int __init preconfigure_through_ali(struct pci_dev *dev, struct smsc_ircc_subsystem_configuration *conf); | ||
229 | static 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 | ||
2337 | static 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 | */ | ||
2411 | static 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 | */ | ||
2501 | static 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 | |||
2530 | static 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 | |||
2538 | static 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 | ||
89 | static struct console netconsole = { | 89 | static 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 | ||
508 | static 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 | ||
517 | static void tg3_read_mem(struct tg3 *tp, u32 off, u32 *val) | 516 | static 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. */ |
111 | int nf_register_hook(struct nf_hook_ops *reg); | 111 | int nf_register_hook(struct nf_hook_ops *reg); |
112 | void nf_unregister_hook(struct nf_hook_ops *reg); | 112 | void nf_unregister_hook(struct nf_hook_ops *reg); |
113 | int nf_register_hooks(struct nf_hook_ops *reg, unsigned int n); | ||
114 | void 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. */ |
282 | extern int skb_make_writable(struct sk_buff **pskb, unsigned int writable_len); | 284 | extern int skb_make_writable(struct sk_buff **pskb, unsigned int writable_len); |
283 | 285 | ||
284 | struct nf_queue_rerouter { | 286 | struct 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)) | 297 | extern struct nf_afinfo *nf_afinfo[]; |
298 | static inline struct nf_afinfo *nf_get_afinfo(unsigned short family) | ||
299 | { | ||
300 | return rcu_dereference(nf_afinfo[family]); | ||
301 | } | ||
302 | |||
303 | static inline unsigned int | ||
304 | nf_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 | ||
292 | extern int nf_register_queue_rerouter(int pf, struct nf_queue_rerouter *rer); | 318 | extern int nf_register_afinfo(struct nf_afinfo *afinfo); |
293 | extern int nf_unregister_queue_rerouter(int pf); | 319 | extern 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> |
296 | extern void (*ip_nat_decode_session)(struct sk_buff *, struct flowi *); | 324 | extern 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__ |
81 | extern int ip_route_me_harder(struct sk_buff **pskb); | 81 | extern int ip_route_me_harder(struct sk_buff **pskb); |
82 | extern int ip_xfrm_me_harder(struct sk_buff **pskb); | 82 | extern int ip_xfrm_me_harder(struct sk_buff **pskb); |
83 | extern 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 | ||
30 | struct ip_conntrack_expect; | ||
31 | |||
32 | extern int get_h225_addr(unsigned char *data, TransportAddress * addr, | ||
33 | u_int32_t * ip, u_int16_t * port); | ||
34 | extern void ip_conntrack_h245_expect(struct ip_conntrack *new, | ||
35 | struct ip_conntrack_expect *this); | ||
36 | extern void ip_conntrack_q931_expect(struct ip_conntrack *new, | ||
37 | struct ip_conntrack_expect *this); | ||
38 | extern 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); | ||
42 | extern 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); | ||
46 | extern 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); | ||
51 | extern 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); | ||
56 | extern 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); | ||
64 | extern 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); | ||
69 | extern 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); | ||
74 | extern 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 |
76 | extern unsigned int nf_ip6_checksum(struct sk_buff *skb, unsigned int hook, | ||
77 | unsigned int dataoff, u_int8_t protocol); | ||
78 | |||
76 | extern int ipv6_netfilter_init(void); | 79 | extern int ipv6_netfilter_init(void); |
77 | extern void ipv6_netfilter_fini(void); | 80 | extern 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 | ||
51 | static inline void __inet6_hash(struct inet_hashinfo *hashinfo, | 51 | extern 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 | */ |
83 | static inline struct sock * | 59 | extern 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 | |||
124 | hit: | ||
125 | sock_hold(sk); | ||
126 | read_unlock(&head->lock); | ||
127 | return sk; | ||
128 | } | ||
129 | 65 | ||
130 | extern struct sock *inet6_lookup_listener(struct inet_hashinfo *hashinfo, | 66 | extern 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); | |||
95 | extern int ip_mr_input(struct sk_buff *skb); | 95 | extern int ip_mr_input(struct sk_buff *skb); |
96 | extern int ip_output(struct sk_buff *skb); | 96 | extern int ip_output(struct sk_buff *skb); |
97 | extern int ip_mc_output(struct sk_buff *skb); | 97 | extern int ip_mc_output(struct sk_buff *skb); |
98 | extern int ip_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *)); | ||
98 | extern int ip_do_nat(struct sk_buff *skb); | 99 | extern int ip_do_nat(struct sk_buff *skb); |
99 | extern void ip_send_check(struct iphdr *ip); | 100 | extern void ip_send_check(struct iphdr *ip); |
100 | extern int ip_queue_xmit(struct sk_buff *skb, int ipfragok); | 101 | extern 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 @@ | |||
8 | static inline __be16 x25_type_trans(struct sk_buff *skb, struct net_device *dev) | 8 | static 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 | ||
768 | static 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 ********************************************/ |
770 | static unsigned int br_nf_post_routing(unsigned int hook, struct sk_buff **pskb, | 779 | static 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 | ||
317 | static inline void free_leaf(struct leaf *leaf) | ||
318 | { | ||
319 | call_rcu(&leaf->rcu, __leaf_free_rcu); | ||
320 | } | ||
321 | |||
322 | static void __leaf_info_free_rcu(struct rcu_head *head) | 317 | static 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 | ||
358 | static inline void tnode_free(struct tnode *tn) | 353 | static 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 | ||
363 | static struct leaf *leaf_new(void) | 363 | static 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 | ||
307 | static struct ipq *ip_frag_intern(unsigned int hash, struct ipq *qp_in) | 307 | static 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. */ |
348 | static struct ipq *ip_frag_create(unsigned hash, struct iphdr *iph, u32 user) | 352 | static 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 | ||
376 | out_nomem: | 380 | out_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 | ||
661 | drop: | 661 | drop: |
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 | ||
87 | int sysctl_ip_default_ttl = IPDEFTTL; | 87 | int sysctl_ip_default_ttl = IPDEFTTL; |
88 | 88 | ||
89 | static 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 | ||
424 | static int ip_fragment(struct sk_buff *skb, int (*output)(struct sk_buff*)) | 422 | int 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 | ||
674 | EXPORT_SYMBOL(ip_fragment); | ||
675 | |||
676 | int | 676 | int |
677 | ip_generic_getfrag(void *from, char *to, int offset, int len, int odd, struct sk_buff *skb) | 677 | ip_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 | ||
511 | out: | ||
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 | ||
136 | static void queue_save(const struct sk_buff *skb, struct nf_info *info) | 136 | static 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 | ||
149 | static int queue_reroute(struct sk_buff **pskb, const struct nf_info *info) | 149 | static 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 | ||
164 | static struct nf_queue_rerouter ip_reroute = { | 164 | unsigned 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 | |||
194 | EXPORT_SYMBOL(nf_ip_checksum); | ||
195 | |||
196 | static 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 | ||
170 | static int ipv4_netfilter_init(void) | 204 | static 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 | ||
175 | static void ipv4_netfilter_fini(void) | 209 | static 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 | ||
180 | module_init(ipv4_netfilter_init); | 214 | module_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 | ||
182 | static int __init arptable_filter_init(void) | 182 | static 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 | ||
196 | cleanup_hooks: | 196 | cleanup_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 | ||
204 | static void __exit arptable_filter_fini(void) | 201 | static 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 */ |
33 | static unsigned int default_rrq_ttl = 300; | ||
34 | module_param(default_rrq_ttl, uint, 0600); | ||
35 | MODULE_PARM_DESC(default_rrq_ttl, "use this TTL if it's missing in RRQ"); | ||
36 | |||
66 | static int gkrouted_only = 1; | 37 | static int gkrouted_only = 1; |
67 | module_param(gkrouted_only, int, 0600); | 38 | module_param(gkrouted_only, int, 0600); |
68 | MODULE_PARM_DESC(gkrouted_only, "only accept calls from gatekeeper"); | 39 | MODULE_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 | /****************************************************************************/ |
225 | int get_h245_addr(unsigned char *data, H245_TransportAddress * addr, | 196 | static 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) | |||
1713 | module_init(init); | 1684 | module_init(init); |
1714 | module_exit(fini); | 1685 | module_exit(fini); |
1715 | 1686 | ||
1716 | EXPORT_SYMBOL(get_h245_addr); | 1687 | EXPORT_SYMBOL_GPL(get_h225_addr); |
1717 | EXPORT_SYMBOL(get_h225_addr); | 1688 | EXPORT_SYMBOL_GPL(ip_conntrack_h245_expect); |
1718 | EXPORT_SYMBOL(ip_conntrack_h245_expect); | 1689 | EXPORT_SYMBOL_GPL(ip_conntrack_q931_expect); |
1719 | EXPORT_SYMBOL(ip_conntrack_q931_expect); | 1690 | EXPORT_SYMBOL_GPL(set_h245_addr_hook); |
1720 | EXPORT_SYMBOL(set_h245_addr_hook); | 1691 | EXPORT_SYMBOL_GPL(set_h225_addr_hook); |
1721 | EXPORT_SYMBOL(set_h225_addr_hook); | 1692 | EXPORT_SYMBOL_GPL(set_sig_addr_hook); |
1722 | EXPORT_SYMBOL(set_sig_addr_hook); | 1693 | EXPORT_SYMBOL_GPL(set_ras_addr_hook); |
1723 | EXPORT_SYMBOL(set_ras_addr_hook); | 1694 | EXPORT_SYMBOL_GPL(nat_rtp_rtcp_hook); |
1724 | EXPORT_SYMBOL(nat_rtp_rtcp_hook); | 1695 | EXPORT_SYMBOL_GPL(nat_t120_hook); |
1725 | EXPORT_SYMBOL(nat_t120_hook); | 1696 | EXPORT_SYMBOL_GPL(nat_h245_hook); |
1726 | EXPORT_SYMBOL(nat_h245_hook); | 1697 | EXPORT_SYMBOL_GPL(nat_q931_hook); |
1727 | EXPORT_SYMBOL(nat_q931_hook); | ||
1728 | 1698 | ||
1729 | MODULE_AUTHOR("Jing Min Zhao <zhaojingmin@users.sourceforge.net>"); | 1699 | MODULE_AUTHOR("Jing Min Zhao <zhaojingmin@users.sourceforge.net>"); |
1730 | MODULE_DESCRIPTION("H.323 connection tracking helper"); | 1700 | MODULE_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 | ||
245 | checksum_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. */ |
472 | static struct nf_hook_ops ip_conntrack_defrag_ops = { | 472 | static 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 | }, | |
480 | static 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 | { | |
488 | static 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, | |
496 | static 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, |
505 | static 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, | |
513 | static 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 | }, |
522 | static 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 | |||
530 | static 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[] = { | |||
783 | EXPORT_SYMBOL(ip_ct_log_invalid); | 776 | EXPORT_SYMBOL(ip_ct_log_invalid); |
784 | #endif /* CONFIG_SYSCTL */ | 777 | #endif /* CONFIG_SYSCTL */ |
785 | 778 | ||
786 | static int init_or_cleanup(int init) | 779 | /* FIXME: Allow NULL functions and sub in pointers to generic for |
780 | them. --RR */ | ||
781 | int 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 | |||
796 | void 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 | |||
809 | static 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 */ | ||
904 | int 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 | ||
919 | void 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 | |||
932 | static int __init ip_conntrack_standalone_init(void) | ||
933 | { | ||
934 | return init_or_cleanup(1); | ||
935 | } | ||
936 | |||
937 | static void __exit ip_conntrack_standalone_fini(void) | 869 | static 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 | ||
942 | module_init(ip_conntrack_standalone_init); | 884 | module_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 | ||
52 | extern int get_h245_addr(unsigned char *data, H245_TransportAddress * addr, | ||
53 | u_int32_t * ip, u_int16_t * port); | ||
54 | extern int get_h225_addr(unsigned char *data, TransportAddress * addr, | ||
55 | u_int32_t * ip, u_int16_t * port); | ||
56 | extern void ip_conntrack_h245_expect(struct ip_conntrack *new, | ||
57 | struct ip_conntrack_expect *this); | ||
58 | extern void ip_conntrack_q931_expect(struct ip_conntrack *new, | ||
59 | struct ip_conntrack_expect *this); | ||
60 | extern 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); | ||
64 | extern 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); | ||
68 | extern 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); | ||
73 | extern 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); | ||
78 | extern 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); | ||
86 | extern 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); | ||
91 | extern 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); | ||
96 | extern 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 | /****************************************************************************/ |
104 | static int set_addr(struct sk_buff **pskb, | 33 | static 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 */ | 302 | static struct nf_hook_ops ip_nat_ops[] = { |
303 | static 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 */ | 353 | static int __init ip_nat_standalone_init(void) |
312 | static 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 */ | ||
321 | static 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 */ | ||
330 | static 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 */ | ||
339 | static 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 */ | ||
348 | static 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 | |||
357 | static 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 | ||
428 | static int __init ip_nat_standalone_init(void) | ||
429 | { | ||
430 | return init_or_cleanup(1); | ||
431 | } | ||
432 | |||
433 | static void __exit ip_nat_standalone_fini(void) | 385 | static 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 | ||
438 | module_init(ip_nat_standalone_init); | 395 | module_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 | ||
665 | static int | 665 | static int __init ip_queue_init(void) |
666 | init_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 | ||
700 | cleanup: | ||
701 | nf_unregister_queue_handlers(&nfqh); | ||
702 | synchronize_net(); | ||
703 | ipq_flush(NF_DROP); | ||
704 | |||
705 | cleanup_sysctl: | 696 | cleanup_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 | ||
720 | static int __init ip_queue_init(void) | ||
721 | { | ||
722 | |||
723 | return init_or_cleanup(1); | ||
724 | } | ||
725 | |||
726 | static void __exit ip_queue_fini(void) | 711 | static 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 | ||
731 | MODULE_DESCRIPTION("IPv4 packet queue handler"); | 728 | MODULE_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 | ||
728 | static int init_or_cleanup(int fini) | 728 | static 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 | ||
759 | cleanup: | ||
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 | ||
765 | cleanup_hook: | 753 | cleanup_hook: |
766 | nf_unregister_hook(&cip_arp_ops); | 754 | nf_unregister_hook(&cip_arp_ops); |
767 | cleanup_target: | 755 | cleanup_target: |
768 | ipt_unregister_target(&clusterip_tgt); | 756 | ipt_unregister_target(&clusterip_tgt); |
769 | cleanup_none: | 757 | return ret; |
770 | return -EINVAL; | ||
771 | } | ||
772 | |||
773 | static int __init ipt_clusterip_init(void) | ||
774 | { | ||
775 | return init_or_cleanup(0); | ||
776 | } | 758 | } |
777 | 759 | ||
778 | static void __exit ipt_clusterip_fini(void) | 760 | static 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 | ||
783 | module_init(ipt_clusterip_init); | 771 | module_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 | ||
184 | static void __exit iptable_filter_fini(void) | 171 | static 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 | ||
250 | static void __exit iptable_mangle_fini(void) | 225 | static 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. */ |
102 | static struct nf_hook_ops ipt_ops[] = { | 102 | static 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 | ||
147 | static void __exit iptable_raw_fini(void) | 140 | static 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. */ |
213 | static struct nf_hook_ops ipv4_conntrack_defrag_ops = { | 213 | static 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 | }, | |
221 | static 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 | { | |
229 | static 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, | |
237 | static 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, |
246 | static 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, | |
254 | static 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 | { |
264 | static 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 | |||
272 | static 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 = { | |||
440 | extern struct nf_conntrack_protocol nf_conntrack_protocol_tcp4; | 432 | extern struct nf_conntrack_protocol nf_conntrack_protocol_tcp4; |
441 | extern struct nf_conntrack_protocol nf_conntrack_protocol_udp4; | 433 | extern struct nf_conntrack_protocol nf_conntrack_protocol_udp4; |
442 | extern struct nf_conntrack_protocol nf_conntrack_protocol_icmp; | 434 | extern struct nf_conntrack_protocol nf_conntrack_protocol_icmp; |
443 | static int init_or_cleanup(int init) | 435 | |
436 | MODULE_ALIAS("nf_conntrack-" __stringify(AF_INET)); | ||
437 | MODULE_LICENSE("GPL"); | ||
438 | |||
439 | static 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 | ||
571 | MODULE_ALIAS("nf_conntrack-" __stringify(AF_INET)); | ||
572 | MODULE_LICENSE("GPL"); | ||
573 | |||
574 | static int __init nf_conntrack_l3proto_ipv4_init(void) | ||
575 | { | ||
576 | need_conntrack(); | ||
577 | return init_or_cleanup(1); | ||
578 | } | ||
579 | |||
580 | static void __exit nf_conntrack_l3proto_ipv4_fini(void) | 508 | static 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 | ||
585 | module_init(nf_conntrack_l3proto_ipv4_init); | 522 | module_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 | ||
261 | checksum_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 | |||
84 | drop: | ||
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 | ||
26 | void __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 | } | ||
51 | EXPORT_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 | */ | ||
59 | struct 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 | |||
99 | hit: | ||
100 | sock_hold(sk); | ||
101 | read_unlock(&head->lock); | ||
102 | return sk; | ||
103 | } | ||
104 | EXPORT_SYMBOL(__inet6_lookup_established); | ||
105 | |||
26 | struct sock *inet6_lookup_listener(struct inet_hashinfo *hashinfo, | 106 | struct 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); | ||
561 | discard: | ||
562 | return 1; | 556 | return 1; |
557 | |||
558 | discard: | ||
559 | kfree_skb(skb); | ||
560 | return 0; | ||
563 | } | 561 | } |
564 | 562 | ||
565 | static inline struct ipv6_txoptions *create_tel(__u8 encap_limit) | 563 | static 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 | ||
11 | int ip6_route_me_harder(struct sk_buff *skb) | 12 | int 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 | ||
57 | static void save(const struct sk_buff *skb, struct nf_info *info) | 58 | static 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 | ||
69 | static int reroute(struct sk_buff **pskb, const struct nf_info *info) | 70 | static 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 | ||
82 | static struct nf_queue_rerouter ip6_reroute = { | 83 | unsigned 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 | |||
114 | EXPORT_SYMBOL(nf_ip6_checksum); | ||
115 | |||
116 | static 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 | ||
88 | int __init ipv6_netfilter_init(void) | 124 | int __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 | */ |
96 | void ipv6_netfilter_fini(void) | 132 | void 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 | ||
661 | static int | 661 | static int __init ip6_queue_init(void) |
662 | init_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 | ||
696 | cleanup: | ||
697 | nf_unregister_queue_handlers(&nfqh); | ||
698 | synchronize_net(); | ||
699 | ipq_flush(NF_DROP); | ||
700 | |||
701 | cleanup_sysctl: | 692 | cleanup_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 | ||
716 | static int __init ip6_queue_init(void) | ||
717 | { | ||
718 | |||
719 | return init_or_cleanup(1); | ||
720 | } | ||
721 | |||
722 | static void __exit ip6_queue_fini(void) | 707 | static 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 | ||
727 | MODULE_DESCRIPTION("IPv6 packet queue handler"); | 724 | MODULE_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 | ||
204 | static void __exit ip6table_filter_fini(void) | 191 | static 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 | ||
277 | static void __exit ip6table_mangle_fini(void) | 252 | static 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 | ||
173 | static void __exit ip6table_raw_fini(void) | 166 | static 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 | 289 | static struct nf_hook_ops ipv6_conntrack_ops[] = { |
290 | make it the first hook. */ | 290 | { |
291 | static 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, | |
299 | static 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, | |
307 | static 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, | |
315 | static 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, |
324 | static 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 | }, | |
332 | static 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; | |||
470 | extern struct nf_conntrack_protocol nf_conntrack_protocol_icmpv6; | 464 | extern struct nf_conntrack_protocol nf_conntrack_protocol_icmpv6; |
471 | extern int nf_ct_frag6_init(void); | 465 | extern int nf_ct_frag6_init(void); |
472 | extern void nf_ct_frag6_cleanup(void); | 466 | extern void nf_ct_frag6_cleanup(void); |
473 | static int init_or_cleanup(int init) | 467 | |
468 | MODULE_ALIAS("nf_conntrack-" __stringify(AF_INET6)); | ||
469 | MODULE_LICENSE("GPL"); | ||
470 | MODULE_AUTHOR("Yasuyuki KOZAKAI @USAGI <yasuyuki.kozakai@toshiba.co.jp>"); | ||
471 | |||
472 | static 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 | ||
587 | MODULE_ALIAS("nf_conntrack-" __stringify(AF_INET6)); | ||
588 | MODULE_LICENSE("GPL"); | ||
589 | MODULE_AUTHOR("Yasuyuki KOZAKAI @USAGI <yasuyuki.kozakai@toshiba.co.jp>"); | ||
590 | |||
591 | static int __init nf_conntrack_l3proto_ipv6_init(void) | ||
592 | { | ||
593 | need_conntrack(); | ||
594 | return init_or_cleanup(1); | ||
595 | } | ||
596 | |||
597 | static void __exit nf_conntrack_l3proto_ipv6_fini(void) | 541 | static 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 | ||
602 | module_init(nf_conntrack_l3proto_ipv6_init); | 555 | module_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 | ||
249 | skipped: | ||
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); |
403 | out: | 403 | out: |
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 | |||
101 | drop: | ||
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 | ||
30 | static DEFINE_SPINLOCK(afinfo_lock); | ||
31 | |||
32 | struct nf_afinfo *nf_afinfo[NPROTO]; | ||
33 | EXPORT_SYMBOL(nf_afinfo); | ||
34 | |||
35 | int 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 | } | ||
42 | EXPORT_SYMBOL_GPL(nf_register_afinfo); | ||
43 | |||
44 | void 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 | } | ||
51 | EXPORT_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 | } |
64 | EXPORT_SYMBOL(nf_unregister_hook); | 87 | EXPORT_SYMBOL(nf_unregister_hook); |
65 | 88 | ||
89 | int 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(®[i]); | ||
96 | if (err) | ||
97 | goto err; | ||
98 | } | ||
99 | return err; | ||
100 | |||
101 | err: | ||
102 | if (i > 0) | ||
103 | nf_unregister_hooks(reg, i); | ||
104 | return err; | ||
105 | } | ||
106 | EXPORT_SYMBOL(nf_register_hooks); | ||
107 | |||
108 | void 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(®[i]); | ||
114 | } | ||
115 | EXPORT_SYMBOL(nf_unregister_hooks); | ||
116 | |||
66 | unsigned int nf_iterate(struct list_head *head, | 117 | unsigned 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 | ||
854 | static 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 | |||
863 | static 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 | |||
874 | static 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 | |||
883 | static 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. */ |
893 | static int tcp_packet(struct nf_conn *conntrack, | 853 | static 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, | |||
103 | static int udp_error(struct sk_buff *skb, unsigned int dataoff, | 103 | static 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 | ||
151 | static 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 | |||
160 | static 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 | |||
171 | static 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 | |||
180 | static 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 | |||
189 | struct nf_conntrack_protocol nf_conntrack_protocol_udp4 = | 149 | struct 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[] = { | |||
649 | EXPORT_SYMBOL(nf_ct_log_invalid); | 649 | EXPORT_SYMBOL(nf_ct_log_invalid); |
650 | #endif /* CONFIG_SYSCTL */ | 650 | #endif /* CONFIG_SYSCTL */ |
651 | 651 | ||
652 | static 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 | |||
709 | int nf_conntrack_l3proto_register(struct nf_conntrack_l3proto *proto) | 652 | int 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 | ||
809 | static int __init nf_conntrack_standalone_init(void) | 752 | static 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 | ||
814 | static void __exit nf_conntrack_standalone_fini(void) | 803 | static 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 | ||
819 | module_init(nf_conntrack_standalone_init); | 816 | module_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 | */ |
19 | static struct nf_queue_handler *queue_handler[NPROTO]; | 19 | static struct nf_queue_handler *queue_handler[NPROTO]; |
20 | static struct nf_queue_rerouter *queue_rerouter[NPROTO]; | ||
21 | 20 | ||
22 | static DEFINE_RWLOCK(queue_handler_lock); | 21 | static DEFINE_RWLOCK(queue_handler_lock); |
23 | 22 | ||
@@ -59,32 +58,6 @@ int nf_unregister_queue_handler(int pf) | |||
59 | } | 58 | } |
60 | EXPORT_SYMBOL(nf_unregister_queue_handler); | 59 | EXPORT_SYMBOL(nf_unregister_queue_handler); |
61 | 60 | ||
62 | int 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 | } | ||
73 | EXPORT_SYMBOL_GPL(nf_register_queue_rerouter); | ||
74 | |||
75 | int 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 | } | ||
86 | EXPORT_SYMBOL_GPL(nf_unregister_queue_rerouter); | ||
87 | |||
88 | void nf_unregister_queue_handlers(struct nf_queue_handler *qh) | 61 | void 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 | ||
1036 | static int | 1036 | static int __init nfnetlink_log_init(void) |
1037 | init_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 | ||
1072 | cleanup: | ||
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); | ||
1076 | cleanup_subsys: | 1068 | cleanup_subsys: |
1077 | #endif | ||
1078 | nfnetlink_subsys_unregister(&nfulnl_subsys); | 1069 | nfnetlink_subsys_unregister(&nfulnl_subsys); |
1070 | #endif | ||
1079 | cleanup_netlink_notifier: | 1071 | cleanup_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 | ||
1084 | static int __init nfnetlink_log_init(void) | ||
1085 | { | ||
1086 | |||
1087 | return init_or_cleanup(1); | ||
1088 | } | ||
1089 | |||
1090 | static void __exit nfnetlink_log_fini(void) | 1076 | static 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 | ||
1095 | MODULE_DESCRIPTION("netfilter userspace logging"); | 1086 | MODULE_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 | ||
1074 | static int | 1074 | static int __init nfnetlink_queue_init(void) |
1075 | init_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 | ||
1107 | cleanup: | ||
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); | ||
1112 | cleanup_subsys: | 1103 | cleanup_subsys: |
1113 | #endif | ||
1114 | nfnetlink_subsys_unregister(&nfqnl_subsys); | 1104 | nfnetlink_subsys_unregister(&nfqnl_subsys); |
1105 | #endif | ||
1115 | cleanup_netlink_notifier: | 1106 | cleanup_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 | ||
1120 | static int __init nfnetlink_queue_init(void) | ||
1121 | { | ||
1122 | |||
1123 | return init_or_cleanup(1); | ||
1124 | } | ||
1125 | |||
1126 | static void __exit nfnetlink_queue_fini(void) | 1111 | static 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 | ||
1131 | MODULE_DESCRIPTION("netfilter packet queue handler"); | 1122 | MODULE_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 |
69 | static int tcf_generic_walker(struct sk_buff *skb, struct netlink_callback *cb, | 69 | static 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 | ||
115 | static inline int | 115 | static inline int |
116 | tcf_hash_search(struct tc_action *a, u32 index) | 116 | tcf_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 | ||
395 | static int __init | 395 | static int __init |