Merge master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6

* master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6: (35 commits)
  [IPV6]: Deinline few large functions in inet6 code
  [IPV4] ip_fragment: Always compute hash with ipfrag_lock held.
  [NETFILTER]: Fix DNAT in LOCAL_OUT
  [X25]: Restore skb->dev setting in x25_type_trans().
  [NET]: Fix hotplug race during device registration.
  [IPV6]: Unexport secure_ipv6_port_ephemeral
  [NETFILTER]: Fix build with CONFIG_NETFILTER=y/m on IA64
  [NET]: More kzalloc conversions.
  [NET] kzalloc: use in alloc_netdev
  [PKT_SCHED] act_police: Rename methods.
  [TG3]: Speed up SRAM access (2nd version)
  [TG3]: Kill some less useful flags
  [NETFILTER]: H.323 helper: remove changelog
  [NETFILTER]: Convert conntrack/ipt_REJECT to new checksumming functions
  [NETFILTER]: Add address family specific checksum helpers
  [NETFILTER]: Introduce infrastructure for address family specific operations
  [NETFILTER]: Fix IP_NF_CONNTRACK_NETLINK dependency
  [NETFILTER]: H.323 helper: add parameter 'default_rrq_ttl'
  [NETFILTER]: H.323 helper: make get_h245_addr() static
  [NETFILTER]: H.323 helper: change EXPORT_SYMBOL to EXPORT_SYMBOL_GPL
  ...
This commit is contained in:
Linus Torvalds 2006-04-10 08:46:00 -07:00
commit 460fbf82c0
71 changed files with 1659 additions and 1388 deletions

View File

@ -1584,7 +1584,6 @@ u32 secure_ipv6_port_ephemeral(const __u32 *saddr, const __u32 *daddr, __u16 dpo
return twothirdsMD4Transform(daddr, hash);
}
EXPORT_SYMBOL(secure_ipv6_port_ephemeral);
#endif
#if defined(CONFIG_IP_DCCP) || defined(CONFIG_IP_DCCP_MODULE)

View File

@ -1,7 +1,7 @@
/*****************************************************************************
*
* Filename: irda-usb.c
* Version: 0.9b
* Version: 0.10
* Description: IrDA-USB Driver
* Status: Experimental
* Author: Dag Brattli <dag@brattli.net>
@ -9,6 +9,9 @@
* Copyright (C) 2000, Roman Weissgaerber <weissg@vienna.at>
* Copyright (C) 2001, Dag Brattli <dag@brattli.net>
* Copyright (C) 2001, Jean Tourrilhes <jt@hpl.hp.com>
* Copyright (C) 2004, SigmaTel, Inc. <irquality@sigmatel.com>
* Copyright (C) 2005, Milan Beno <beno@pobox.sk>
* Copyright (C) 2006, Nick Fedchik <nick@fedchik.org.ua>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -61,6 +64,7 @@
#include <linux/slab.h>
#include <linux/rtnetlink.h>
#include <linux/usb.h>
#include <linux/firmware.h>
#include "irda-usb.h"
@ -78,6 +82,10 @@ static struct usb_device_id dongles[] = {
{ USB_DEVICE(0x50f, 0x180), .driver_info = IUC_SPEED_BUG | IUC_NO_WINDOW },
/* Extended Systems, Inc., XTNDAccess IrDA USB (ESI-9685) */
{ USB_DEVICE(0x8e9, 0x100), .driver_info = IUC_SPEED_BUG | IUC_NO_WINDOW },
/* SigmaTel STIR4210/4220/4116 USB IrDA (VFIR) Bridge */
{ USB_DEVICE(0x66f, 0x4210), .driver_info = IUC_STIR_4210 | IUC_SPEED_BUG },
{ USB_DEVICE(0x66f, 0x4220), .driver_info = IUC_STIR_4210 | IUC_SPEED_BUG },
{ USB_DEVICE(0x66f, 0x4116), .driver_info = IUC_STIR_4210 | IUC_SPEED_BUG },
{ .match_flags = USB_DEVICE_ID_MATCH_INT_CLASS |
USB_DEVICE_ID_MATCH_INT_SUBCLASS,
.bInterfaceClass = USB_CLASS_APP_SPEC,
@ -99,6 +107,7 @@ MODULE_DEVICE_TABLE(usb, dongles);
/*------------------------------------------------------------------*/
static void irda_usb_init_qos(struct irda_usb_cb *self) ;
static struct irda_class_desc *irda_usb_find_class_desc(struct usb_interface *intf);
static void irda_usb_disconnect(struct usb_interface *intf);
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,
__u8 *header,
int force)
{
/* Set the negotiated link speed */
/* Here we check if we have an STIR421x chip,
* and if either speed or xbofs (or both) needs
* to be changed.
*/
if (self->capability & IUC_STIR_4210 &&
((self->new_speed != -1) || (self->new_xbofs != -1))) {
/* With STIR421x, speed and xBOFs must be set at the same
* time, even if only one of them changes.
*/
if (self->new_speed == -1)
self->new_speed = self->speed ;
if (self->new_xbofs == -1)
self->new_xbofs = self->xbofs ;
}
/* Set the link speed */
if (self->new_speed != -1) {
/* Hum... Ugly hack :-(
* Some device are not compliant with the spec and change
@ -191,6 +217,10 @@ static void irda_usb_build_header(struct irda_usb_cb *self,
*header = SPEED_4000000;
self->new_xbofs = 0;
break;
case 16000000:
*header = SPEED_16000000;
self->new_xbofs = 0;
break;
}
} else
/* No change */
@ -235,6 +265,32 @@ static void irda_usb_build_header(struct irda_usb_cb *self,
}
}
/*
* calculate turnaround time for SigmaTel header
*/
static __u8 get_turnaround_time(struct sk_buff *skb)
{
int turnaround_time = irda_get_mtt(skb);
if ( turnaround_time == 0 )
return 0;
else if ( turnaround_time <= 10 )
return 1;
else if ( turnaround_time <= 50 )
return 2;
else if ( turnaround_time <= 100 )
return 3;
else if ( turnaround_time <= 500 )
return 4;
else if ( turnaround_time <= 1000 )
return 5;
else if ( turnaround_time <= 5000 )
return 6;
else
return 7;
}
/*------------------------------------------------------------------*/
/*
* 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)
/* Set the new speed and xbofs in this fake frame */
irda_usb_build_header(self, frame, 1);
if ( self->capability & IUC_STIR_4210 ) {
if (frame[0] == 0) return ; // do nothing if no change
frame[1] = 0; // other parameters don't change here
frame[2] = 0;
}
/* Submit the 0 length IrDA frame to trigger new speed settings */
usb_fill_bulk_urb(urb, self->usbdev,
usb_sndbulkpipe(self->usbdev, self->bulk_out_ep),
frame, IRDA_USB_SPEED_MTU,
speed_bulk_callback, self);
urb->transfer_buffer_length = USB_IRDA_HEADER;
urb->transfer_buffer_length = self->header_length;
urb->transfer_flags = 0;
/* Irq disabled -> GFP_ATOMIC */
@ -383,16 +445,35 @@ static int irda_usb_hard_xmit(struct sk_buff *skb, struct net_device *netdev)
* allocation will be done lower in skb_push().
* Also, we don't use directly skb_cow(), because it require
* headroom >= 16, which force unnecessary copies - Jean II */
if (skb_headroom(skb) < USB_IRDA_HEADER) {
if (skb_headroom(skb) < self->header_length) {
IRDA_DEBUG(0, "%s(), Insuficient skb headroom.\n", __FUNCTION__);
if (skb_cow(skb, USB_IRDA_HEADER)) {
if (skb_cow(skb, self->header_length)) {
IRDA_WARNING("%s(), failed skb_cow() !!!\n", __FUNCTION__);
goto drop;
}
}
/* Change setting for next frame */
irda_usb_build_header(self, skb_push(skb, USB_IRDA_HEADER), 0);
if ( self->capability & IUC_STIR_4210 ) {
__u8 turnaround_time;
__u8* frame;
turnaround_time = get_turnaround_time( skb );
frame= skb_push(skb, self->header_length);
irda_usb_build_header(self, frame, 0);
frame[2] = turnaround_time;
if ((skb->len != 0) &&
((skb->len % 128) == 0) &&
((skb->len % 512) != 0)) {
/* add extra byte for special SigmaTel feature */
frame[1] = 1;
skb_put(skb, 1);
} else {
frame[1] = 0;
}
} else {
irda_usb_build_header(self, skb_push(skb, self->header_length), 0);
}
/* FIXME: Make macro out of this one */
((struct irda_skb_cb *)skb->cb)->context = self;
@ -795,7 +876,7 @@ static void irda_usb_receive(struct urb *urb, struct pt_regs *regs)
}
/* Check for empty frames */
if (urb->actual_length <= USB_IRDA_HEADER) {
if (urb->actual_length <= self->header_length) {
IRDA_WARNING("%s(), empty frame!\n", __FUNCTION__);
goto done;
}
@ -816,7 +897,11 @@ static void irda_usb_receive(struct urb *urb, struct pt_regs *regs)
docopy = (urb->actual_length < IRDA_RX_COPY_THRESHOLD);
/* Allocate a new skb */
if ( self->capability & IUC_STIR_4210 )
newskb = dev_alloc_skb(docopy ? urb->actual_length : IRDA_SKB_MAX_MTU + USB_IRDA_SIGMATEL_HEADER);
else
newskb = dev_alloc_skb(docopy ? urb->actual_length : IRDA_SKB_MAX_MTU);
if (!newskb) {
self->stats.rx_dropped++;
/* 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)
/* Set proper length on skb & remove USB-IrDA header */
skb_put(dataskb, urb->actual_length);
skb_pull(dataskb, USB_IRDA_HEADER);
skb_pull(dataskb, self->header_length);
/* Ask the networking layer to queue the packet for the IrDA stack */
dataskb->dev = self->netdev;
@ -937,6 +1022,191 @@ static int irda_usb_is_receiving(struct irda_usb_cb *self)
return 0; /* For now */
}
#define STIR421X_PATCH_PRODUCT_VERSION_STR "Product Version: "
#define STIR421X_PATCH_COMPONENT_VERSION_STR "Component Version: "
#define STIR421X_PATCH_DATA_TAG_STR "STMP"
#define STIR421X_PATCH_FILE_VERSION_MAX_OFFSET 512 /* version info is before here */
#define STIR421X_PATCH_FILE_IMAGE_MAX_OFFSET 512 /* patch image starts before here */
#define STIR421X_PATCH_FILE_END_OF_HEADER_TAG 0x1A /* marks end of patch file header (PC DOS text file EOF character) */
/*
* Known firmware patches for STIR421x dongles
*/
static char * stir421x_patches[] = {
"42101001.sb",
"42101002.sb",
};
static int stir421x_get_patch_version(unsigned char * patch, const unsigned long patch_len)
{
unsigned int version_offset;
unsigned long version_major, version_minor, version_build;
unsigned char * version_start;
int version_found = 0;
for (version_offset = 0;
version_offset < STIR421X_PATCH_FILE_END_OF_HEADER_TAG;
version_offset++) {
if (!memcmp(patch + version_offset,
STIR421X_PATCH_PRODUCT_VERSION_STR,
sizeof(STIR421X_PATCH_PRODUCT_VERSION_STR) - 1)) {
version_found = 1;
version_start = patch +
version_offset +
sizeof(STIR421X_PATCH_PRODUCT_VERSION_STR) - 1;
break;
}
}
/* We couldn't find a product version on this patch */
if (!version_found)
return -EINVAL;
/* Let's check if the product version is dotted */
if (version_start[3] != '.' ||
version_start[7] != '.')
return -EINVAL;
version_major = simple_strtoul(version_start, NULL, 10);
version_minor = simple_strtoul(version_start + 4, NULL, 10);
version_build = simple_strtoul(version_start + 8, NULL, 10);
IRDA_DEBUG(2, "%s(), Major: %ld Minor: %ld Build: %ld\n",
__FUNCTION__,
version_major, version_minor, version_build);
return (((version_major) << 12) +
((version_minor) << 8) +
((version_build / 10) << 4) +
(version_build % 10));
}
static int stir421x_upload_patch (struct irda_usb_cb *self,
unsigned char * patch,
const unsigned int patch_len)
{
int retval = 0;
int actual_len;
unsigned int i = 0, download_amount = 0;
unsigned char * patch_chunk;
IRDA_DEBUG (2, "%s(), Uploading STIR421x Patch\n", __FUNCTION__);
patch_chunk = kzalloc(STIR421X_MAX_PATCH_DOWNLOAD_SIZE, GFP_KERNEL);
if (patch_chunk == NULL)
return -ENOMEM;
/* break up patch into 1023-byte sections */
for (i = 0; retval >= 0 && i < patch_len; i += download_amount) {
download_amount = patch_len - i;
if (download_amount > STIR421X_MAX_PATCH_DOWNLOAD_SIZE)
download_amount = STIR421X_MAX_PATCH_DOWNLOAD_SIZE;
/* download the patch section */
memcpy(patch_chunk, patch + i, download_amount);
retval = usb_bulk_msg (self->usbdev,
usb_sndbulkpipe (self->usbdev,
self->bulk_out_ep),
patch_chunk, download_amount,
&actual_len, msecs_to_jiffies (500));
IRDA_DEBUG (2, "%s(), Sent %u bytes\n", __FUNCTION__,
actual_len);
if (retval == 0)
mdelay(10);
}
kfree(patch_chunk);
if (i != patch_len) {
IRDA_ERROR ("%s(), Pushed %d bytes (!= patch_len (%d))\n",
__FUNCTION__, i, patch_len);
retval = -EIO;
}
if (retval < 0)
/* todo - mark device as not ready */
IRDA_ERROR ("%s(), STIR421x patch upload failed (%d)\n",
__FUNCTION__, retval);
return retval;
}
static int stir421x_patch_device(struct irda_usb_cb *self)
{
unsigned int i, patch_found = 0, data_found = 0, data_offset;
int patch_version, ret = 0;
const struct firmware *fw_entry;
for (i = 0; i < ARRAY_SIZE(stir421x_patches); i++) {
if(request_firmware(&fw_entry, stir421x_patches[i], &self->usbdev->dev) != 0) {
IRDA_ERROR( "%s(), Patch %s is not available\n", __FUNCTION__, stir421x_patches[i]);
continue;
}
/* We found a patch from userspace */
patch_version = stir421x_get_patch_version (fw_entry->data, fw_entry->size);
if (patch_version < 0) {
/* Couldn't fetch a version, let's move on to the next file */
IRDA_ERROR("%s(), version parsing failed\n", __FUNCTION__);
ret = patch_version;
release_firmware(fw_entry);
continue;
}
if (patch_version != self->usbdev->descriptor.bcdDevice) {
/* Patch version and device don't match */
IRDA_ERROR ("%s(), wrong patch version (%d <-> %d)\n",
__FUNCTION__,
patch_version, self->usbdev->descriptor.bcdDevice);
ret = -EINVAL;
release_firmware(fw_entry);
continue;
}
/* If we're here, we've found a correct patch */
patch_found = 1;
break;
}
/* We couldn't find a valid firmware, let's leave */
if (!patch_found)
return ret;
/* The actual image starts after the "STMP" keyword */
for (data_offset = 0; data_offset < STIR421X_PATCH_FILE_IMAGE_MAX_OFFSET; data_offset++) {
if (!memcmp(fw_entry->data + data_offset,
STIR421X_PATCH_DATA_TAG_STR,
sizeof(STIR421X_PATCH_FILE_IMAGE_MAX_OFFSET))) {
IRDA_DEBUG(2, "%s(), found patch data for STIR421x at offset %d\n",
__FUNCTION__, data_offset);
data_found = 1;
break;
}
}
/* We couldn't find "STMP" from the header */
if (!data_found)
return -EINVAL;
/* Let's upload the patch to the target */
ret = stir421x_upload_patch(self,
&fw_entry->data[data_offset + sizeof(STIR421X_PATCH_FILE_IMAGE_MAX_OFFSET)],
fw_entry->size - (data_offset + sizeof(STIR421X_PATCH_FILE_IMAGE_MAX_OFFSET)));
release_firmware(fw_entry);
return ret;
}
/********************** IRDA DEVICE CALLBACKS **********************/
/*
* Main calls from the IrDA/Network subsystem.
@ -972,6 +1242,11 @@ static int irda_usb_net_open(struct net_device *netdev)
return -1;
}
if(self->needspatch) {
IRDA_WARNING("%s(), device needs patch\n", __FUNCTION__) ;
return -EIO ;
}
/* Initialise default speed and xbofs value
* (IrLAP will change that soon) */
self->speed = -1;
@ -1050,7 +1325,7 @@ static int irda_usb_net_close(struct net_device *netdev)
del_timer(&self->rx_defer_timer);
/* Deallocate all the Rx path buffers (URBs and skb) */
for (i = 0; i < IU_MAX_RX_URBS; i++) {
for (i = 0; i < self->max_rx_urb; i++) {
struct urb *urb = self->rx_urb[i];
struct sk_buff *skb = (struct sk_buff *) urb->context;
/* Cancel the receive command */
@ -1426,8 +1701,22 @@ static int irda_usb_probe(struct usb_interface *intf,
spin_lock_init(&self->lock);
init_timer(&self->rx_defer_timer);
self->capability = id->driver_info;
self->needspatch = ((self->capability & IUC_STIR_4210) != 0) ;
/* Create all of the needed urbs */
for (i = 0; i < IU_MAX_RX_URBS; i++) {
if (self->capability & IUC_STIR_4210) {
self->max_rx_urb = IU_SIGMATEL_MAX_RX_URBS;
self->header_length = USB_IRDA_SIGMATEL_HEADER;
} else {
self->max_rx_urb = IU_MAX_RX_URBS;
self->header_length = USB_IRDA_HEADER;
}
self->rx_urb = kzalloc(self->max_rx_urb * sizeof(struct urb *),
GFP_KERNEL);
for (i = 0; i < self->max_rx_urb; i++) {
self->rx_urb[i] = usb_alloc_urb(0, GFP_KERNEL);
if (!self->rx_urb[i]) {
goto err_out_1;
@ -1479,17 +1768,28 @@ static int irda_usb_probe(struct usb_interface *intf,
goto err_out_3;
}
self->usbdev = dev;
/* Find IrDA class descriptor */
irda_desc = irda_usb_find_class_desc(intf);
ret = -ENODEV;
if (irda_desc == NULL)
goto err_out_3;
if (self->needspatch) {
ret = usb_control_msg (self->usbdev, usb_sndctrlpipe (self->usbdev, 0),
0x02, 0x40, 0, 0, 0, 0, msecs_to_jiffies(500));
if (ret < 0) {
IRDA_DEBUG (0, "usb_control_msg failed %d\n", ret);
goto err_out_3;
} else {
mdelay(10);
}
}
self->irda_desc = irda_desc;
self->present = 1;
self->netopen = 0;
self->capability = id->driver_info;
self->usbdev = dev;
self->usbintf = intf;
/* Allocate the buffer for speed changes */
@ -1508,6 +1808,28 @@ static int irda_usb_probe(struct usb_interface *intf,
IRDA_MESSAGE("IrDA: Registered device %s\n", net->name);
usb_set_intfdata(intf, self);
if (self->needspatch) {
/* Now we fetch and upload the firmware patch */
ret = stir421x_patch_device(self);
self->needspatch = (ret < 0);
if (ret < 0) {
printk("patch_device failed\n");
goto err_out_4;
}
/* replace IrDA class descriptor with what patched device is now reporting */
irda_desc = irda_usb_find_class_desc (self->usbintf);
if (irda_desc == NULL) {
ret = -ENODEV;
goto err_out_4;
}
if (self->irda_desc)
kfree (self->irda_desc);
self->irda_desc = irda_desc;
irda_usb_init_qos(self);
}
return 0;
err_out_4:
@ -1518,7 +1840,7 @@ static int irda_usb_probe(struct usb_interface *intf,
err_out_2:
usb_free_urb(self->tx_urb);
err_out_1:
for (i = 0; i < IU_MAX_RX_URBS; i++) {
for (i = 0; i < self->max_rx_urb; i++) {
if (self->rx_urb[i])
usb_free_urb(self->rx_urb[i]);
}
@ -1571,7 +1893,7 @@ static void irda_usb_disconnect(struct usb_interface *intf)
/*netif_device_detach(self->netdev);*/
netif_stop_queue(self->netdev);
/* Stop all the receive URBs. Must be synchronous. */
for (i = 0; i < IU_MAX_RX_URBS; i++)
for (i = 0; i < self->max_rx_urb; i++)
usb_kill_urb(self->rx_urb[i]);
/* Cancel Tx and speed URB.
* Make sure it's synchronous to avoid races. */
@ -1586,8 +1908,9 @@ static void irda_usb_disconnect(struct usb_interface *intf)
self->usbintf = NULL;
/* Clean up our urbs */
for (i = 0; i < IU_MAX_RX_URBS; i++)
for (i = 0; i < self->max_rx_urb; i++)
usb_free_urb(self->rx_urb[i]);
kfree(self->rx_urb);
/* Clean up Tx and speed URB */
usb_free_urb(self->tx_urb);
usb_free_urb(self->speed_urb);
@ -1648,6 +1971,6 @@ module_exit(usb_irda_cleanup);
*/
module_param(qos_mtt_bits, int, 0);
MODULE_PARM_DESC(qos_mtt_bits, "Minimum Turn Time");
MODULE_AUTHOR("Roman Weissgaerber <weissg@vienna.at>, Dag Brattli <dag@brattli.net> and Jean Tourrilhes <jt@hpl.hp.com>");
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>");
MODULE_DESCRIPTION("IrDA-USB Dongle Driver");
MODULE_LICENSE("GPL");

View File

@ -1,7 +1,7 @@
/*****************************************************************************
*
* Filename: irda-usb.h
* Version: 0.9b
* Version: 0.10
* Description: IrDA-USB Driver
* Status: Experimental
* Author: Dag Brattli <dag@brattli.net>
@ -9,6 +9,9 @@
* Copyright (C) 2001, Roman Weissgaerber <weissg@vienna.at>
* Copyright (C) 2000, Dag Brattli <dag@brattli.net>
* Copyright (C) 2001, Jean Tourrilhes <jt@hpl.hp.com>
* Copyright (C) 2004, SigmaTel, Inc. <irquality@sigmatel.com>
* Copyright (C) 2005, Milan Beno <beno@pobox.sk>
* Copyright (C) 2006, Nick FEdchik <nick@fedchik.org.ua>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -31,6 +34,9 @@
#include <net/irda/irda.h>
#include <net/irda/irda_device.h> /* struct irlap_cb */
#define PATCH_FILE_SIZE_MAX 65536
#define PATCH_FILE_SIZE_MIN 80
#define RX_COPY_THRESHOLD 200
#define IRDA_USB_MAX_MTU 2051
#define IRDA_USB_SPEED_MTU 64 /* Weird, but work like this */
@ -88,6 +94,7 @@
#define SPEED_576000 0x07
#define SPEED_1152000 0x08
#define SPEED_4000000 0x09
#define SPEED_16000000 0x0a
/* Basic capabilities */
#define IUC_DEFAULT 0x00 /* Basic device compliant with 1.0 spec */
@ -100,11 +107,14 @@
#define IUC_SMALL_PKT 0x10 /* Device doesn't behave with big Rx packets */
#define IUC_MAX_WINDOW 0x20 /* Device underestimate the Rx window */
#define IUC_MAX_XBOFS 0x40 /* Device need more xbofs than advertised */
#define IUC_STIR_4210 0x80 /* SigmaTel 4210/4220/4116 VFIR */
/* USB class definitions */
#define USB_IRDA_HEADER 0x01
#define USB_CLASS_IRDA 0x02 /* USB_CLASS_APP_SPEC subclass */
#define USB_DT_IRDA 0x21
#define USB_IRDA_SIGMATEL_HEADER 0x03
#define IU_SIGMATEL_MAX_RX_URBS (IU_MAX_ACTIVE_RX_URBS + USB_IRDA_SIGMATEL_HEADER)
struct irda_class_desc {
__u8 bLength;
@ -123,6 +133,7 @@ struct irda_class_desc {
* (6.2.5, USB-IrDA class spec 1.0) */
#define IU_REQ_GET_CLASS_DESC 0x06
#define STIR421X_MAX_PATCH_DOWNLOAD_SIZE 1023
struct irda_usb_cb {
struct irda_class_desc *irda_desc;
@ -136,7 +147,8 @@ struct irda_usb_cb {
__u16 bulk_out_mtu; /* Max Tx packet size in bytes */
__u8 bulk_int_ep; /* Interrupt Endpoint assignments */
struct urb *rx_urb[IU_MAX_RX_URBS]; /* URBs used to receive data frames */
__u8 max_rx_urb;
struct urb **rx_urb; /* URBs used to receive data frames */
struct urb *idle_rx_urb; /* Pointer to idle URB in Rx path */
struct urb *tx_urb; /* URB used to send data frames */
struct urb *speed_urb; /* URB used to send speed commands */
@ -157,6 +169,9 @@ struct irda_usb_cb {
__u32 speed; /* Current speed */
__s32 new_speed; /* speed we need to set */
__u8 header_length; /* USB-IrDA frame header size */
int needspatch; /* device needs firmware patch */
struct timer_list rx_defer_timer; /* Wait for Rx error to clear */
};

View File

@ -11,6 +11,7 @@
* Copyright (c) 2002 Daniele Peri
* All Rights Reserved.
* Copyright (c) 2002 Jean Tourrilhes
* Copyright (c) 2006 Linus Walleij
*
*
* Based on smc-ircc.c:
@ -61,6 +62,9 @@
#include <linux/spinlock.h>
#include <linux/pm.h>
#ifdef CONFIG_PCI
#include <linux/pci.h>
#endif
#include <net/irda/wrapper.h>
#include <net/irda/irda.h>
@ -100,6 +104,22 @@ MODULE_PARM_DESC(ircc_transceiver, "Transceiver type");
/* Types */
#ifdef CONFIG_PCI
struct smsc_ircc_subsystem_configuration {
unsigned short vendor; /* PCI vendor ID */
unsigned short device; /* PCI vendor ID */
unsigned short subvendor; /* PCI subsystem vendor ID */
unsigned short subdevice; /* PCI sybsystem device ID */
unsigned short sir_io; /* I/O port for SIR */
unsigned short fir_io; /* I/O port for FIR */
unsigned char fir_irq; /* FIR IRQ */
unsigned char fir_dma; /* FIR DMA */
unsigned short cfg_base; /* I/O port for chip configuration */
int (*preconfigure)(struct pci_dev *dev, struct smsc_ircc_subsystem_configuration *conf); /* Preconfig function */
const char *name; /* name shown as info */
};
#endif
struct smsc_transceiver {
char *name;
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
static int __init smsc_superio_paged(const struct smsc_chip *chips, unsigned short cfg_base, char *type);
static int __init smsc_superio_fdc(unsigned short cfg_base);
static int __init smsc_superio_lpc(unsigned short cfg_base);
#ifdef CONFIG_PCI
static int __init preconfigure_smsc_chip(struct smsc_ircc_subsystem_configuration *conf);
static int __init preconfigure_through_82801(struct pci_dev *dev, struct smsc_ircc_subsystem_configuration *conf);
static int __init preconfigure_through_ali(struct pci_dev *dev, struct smsc_ircc_subsystem_configuration *conf);
static int __init smsc_ircc_preconfigure_subsystems(unsigned short ircc_cfg,
unsigned short ircc_fir,
unsigned short ircc_sir,
unsigned char ircc_dma,
unsigned char ircc_irq);
#endif
/* Transceivers specific functions */
@ -353,6 +383,13 @@ static int __init smsc_ircc_init(void)
return ret;
}
#ifdef CONFIG_PCI
if (smsc_ircc_preconfigure_subsystems(ircc_cfg, ircc_fir, ircc_sir, ircc_dma, ircc_irq) < 0) {
/* Ignore errors from preconfiguration */
IRDA_ERROR("%s, Preconfiguration failed !\n", driver_name);
}
#endif
dev_count = 0;
if (ircc_fir > 0 && ircc_sir > 0) {
@ -2285,6 +2322,280 @@ static int __init smsc_superio_lpc(unsigned short cfg_base)
return ret;
}
/*
* Look for some specific subsystem setups that need
* pre-configuration not properly done by the BIOS (especially laptops)
* This code is based in part on smcinit.c, tosh1800-smcinit.c
* and tosh2450-smcinit.c. The table lists the device entries
* for ISA bridges with an LPC (Local Peripheral Configurator)
* that are in turn used to configure the SMSC device with default
* SIR and FIR I/O ports, DMA and IRQ.
*/
#ifdef CONFIG_PCI
#define PCIID_VENDOR_INTEL 0x8086
#define PCIID_VENDOR_ALI 0x10b9
static struct smsc_ircc_subsystem_configuration subsystem_configurations[] __devinitdata = {
{
.vendor = PCIID_VENDOR_INTEL, /* Intel 82801DBM LPC bridge */
.device = 0x24cc,
.subvendor = 0x103c,
.subdevice = 0x088c,
.sir_io = 0x02f8, /* Quite certain these are the same for nc8000 as for nc6000 */
.fir_io = 0x0130,
.fir_irq = 0x09,
.fir_dma = 0x03,
.cfg_base = 0x004e,
.preconfigure = preconfigure_through_82801,
.name = "HP nc8000",
},
{
.vendor = PCIID_VENDOR_INTEL, /* Intel 82801DBM LPC bridge */
.device = 0x24cc,
.subvendor = 0x103c,
.subdevice = 0x0890,
.sir_io = 0x02f8,
.fir_io = 0x0130,
.fir_irq = 0x09,
.fir_dma = 0x03,
.cfg_base = 0x004e,
.preconfigure = preconfigure_through_82801,
.name = "HP nc6000",
},
{
.vendor = PCIID_VENDOR_INTEL, /* Intel 82801DB/DBL (ICH4/ICH4-L) LPC Interface Bridge */
.device = 0x24c0,
.subvendor = 0x1179,
.subdevice = 0xffff, /* 0xffff is "any", Not sure, 0x0001 or 0x0002 */
.sir_io = 0x03f8,
.fir_io = 0x0130,
.fir_irq = 0x07,
.fir_dma = 0x01,
.cfg_base = 0x002e,
.preconfigure = preconfigure_through_82801,
.name = "Toshiba Satellite 2450",
},
{
.vendor = PCIID_VENDOR_INTEL, /* Intel 82801CAM ISA bridge */
.device = 0x248c, /* Some use 24cc? */
.subvendor = 0x1179,
.subdevice = 0xffff, /* 0xffff is "any", Not sure, 0x0001 or 0x0002 */
.sir_io = 0x03f8,
.fir_io = 0x0130,
.fir_irq = 0x03,
.fir_dma = 0x03,
.cfg_base = 0x002e,
.preconfigure = preconfigure_through_82801,
.name = "Toshiba Satellite 5100/5200, Tecra 9100",
},
{
.vendor = PCIID_VENDOR_ALI, /* ALi M1533/M1535 PCI to ISA Bridge [Aladdin IV/V/V+] */
.device = 0x1533,
.subvendor = 0x1179,
.subdevice = 0xffff, /* 0xffff is "any", Not sure, 0x0001 or 0x0002 */
.sir_io = 0x02e8,
.fir_io = 0x02f8,
.fir_irq = 0x07,
.fir_dma = 0x03,
.cfg_base = 0x002e,
.preconfigure = preconfigure_through_ali,
.name = "Toshiba Satellite 1800",
},
{ } // Terminator
};
/*
* This sets up the basic SMSC parameters (FIR port, SIR port, FIR DMA, FIR IRQ)
* through the chip configuration port.
*/
static int __init preconfigure_smsc_chip(struct smsc_ircc_subsystem_configuration *conf)
{
unsigned short iobase = conf->cfg_base;
unsigned char tmpbyte;
outb(LPC47N227_CFGACCESSKEY, iobase); // enter configuration state
outb(SMSCSIOFLAT_DEVICEID_REG, iobase); // set for device ID
tmpbyte = inb(iobase +1); // Read device ID
IRDA_DEBUG(0, "Detected Chip id: 0x%02x, setting up registers...\n",tmpbyte);
/* Disable UART1 and set up SIR I/O port */
outb(0x24, iobase); // select CR24 - UART1 base addr
outb(0x00, iobase + 1); // disable UART1
outb(SMSCSIOFLAT_UART2BASEADDR_REG, iobase); // select CR25 - UART2 base addr
outb( (conf->sir_io >> 2), iobase + 1); // bits 2-9 of 0x3f8
tmpbyte = inb(iobase + 1);
if (tmpbyte != (conf->sir_io >> 2) ) {
IRDA_WARNING("ERROR: could not configure SIR ioport.\n");
return -ENXIO;
}
/* Set up FIR IRQ channel for UART2 */
outb(SMSCSIOFLAT_UARTIRQSELECT_REG, iobase); // select CR28 - UART1,2 IRQ select
tmpbyte = inb(iobase + 1);
tmpbyte &= SMSCSIOFLAT_UART1IRQSELECT_MASK; // Do not touch the UART1 portion
tmpbyte |= (conf->fir_irq & SMSCSIOFLAT_UART2IRQSELECT_MASK);
outb(tmpbyte, iobase + 1);
tmpbyte = inb(iobase + 1) & SMSCSIOFLAT_UART2IRQSELECT_MASK;
if (tmpbyte != conf->fir_irq) {
IRDA_WARNING("ERROR: could not configure FIR IRQ channel.\n");
return -ENXIO;
}
/* Set up FIR I/O port */
outb(SMSCSIOFLAT_FIRBASEADDR_REG, iobase); // CR2B - SCE (FIR) base addr
outb((conf->fir_io >> 3), iobase + 1);
tmpbyte = inb(iobase + 1);
if (tmpbyte != (conf->fir_io >> 3) ) {
IRDA_WARNING("ERROR: could not configure FIR I/O port.\n");
return -ENXIO;
}
/* Set up FIR DMA channel */
outb(SMSCSIOFLAT_FIRDMASELECT_REG, iobase); // CR2C - SCE (FIR) DMA select
outb((conf->fir_dma & LPC47N227_FIRDMASELECT_MASK), iobase + 1); // DMA
tmpbyte = inb(iobase + 1) & LPC47N227_FIRDMASELECT_MASK;
if (tmpbyte != (conf->fir_dma & LPC47N227_FIRDMASELECT_MASK)) {
IRDA_WARNING("ERROR: could not configure FIR DMA channel.\n");
return -ENXIO;
}
outb(SMSCSIOFLAT_UARTMODE0C_REG, iobase); // CR0C - UART mode
tmpbyte = inb(iobase + 1);
tmpbyte &= ~SMSCSIOFLAT_UART2MODE_MASK | SMSCSIOFLAT_UART2MODE_VAL_IRDA;
outb(tmpbyte, iobase + 1); // enable IrDA (HPSIR) mode, high speed
outb(LPC47N227_APMBOOTDRIVE_REG, iobase); // CR07 - Auto Pwr Mgt/boot drive sel
tmpbyte = inb(iobase + 1);
outb(tmpbyte | LPC47N227_UART2AUTOPWRDOWN_MASK, iobase + 1); // enable UART2 autopower down
/* This one was not part of tosh1800 */
outb(0x0a, iobase); // CR0a - ecp fifo / ir mux
tmpbyte = inb(iobase + 1);
outb(tmpbyte | 0x40, iobase + 1); // send active device to ir port
outb(LPC47N227_UART12POWER_REG, iobase); // CR02 - UART 1,2 power
tmpbyte = inb(iobase + 1);
outb(tmpbyte | LPC47N227_UART2POWERDOWN_MASK, iobase + 1); // UART2 power up mode, UART1 power down
outb(LPC47N227_FDCPOWERVALIDCONF_REG, iobase); // CR00 - FDC Power/valid config cycle
tmpbyte = inb(iobase + 1);
outb(tmpbyte | LPC47N227_VALID_MASK, iobase + 1); // valid config cycle done
outb(LPC47N227_CFGEXITKEY, iobase); // Exit configuration
return 0;
}
/* 82801CAM registers */
#define VID 0x00
#define DID 0x02
#define PIRQA_ROUT 0x60
#define PCI_DMA_C 0x90
#define COM_DEC 0xe0
#define LPC_EN 0xe6
#define GEN2_DEC 0xec
/*
* Sets up the I/O range using the 82801CAM ISA bridge, 82801DBM LPC bridge or
* Intel 82801DB/DBL (ICH4/ICH4-L) LPC Interface Bridge. They all work the same way!
*/
static int __init preconfigure_through_82801(struct pci_dev *dev,
struct smsc_ircc_subsystem_configuration *conf)
{
unsigned short tmpword;
int ret;
IRDA_MESSAGE("Setting up the SMSC device via the 82801 controller.\n");
pci_write_config_byte(dev, COM_DEC, 0x10);
/* Enable LPC */
pci_read_config_word(dev, LPC_EN, &tmpword); /* LPC_EN register */
tmpword &= 0xfffd; /* mask bit 1 */
tmpword |= 0x0001; /* set bit 0 : COMA addr range enable */
pci_write_config_word(dev, LPC_EN, tmpword);
/* Setup DMA */
pci_write_config_word(dev, PCI_DMA_C, 0xc0c0); /* LPC I/F DMA on, channel 3 -- rtm (?? PCI DMA ?) */
pci_write_config_word(dev, GEN2_DEC, 0x131); /* LPC I/F 2nd decode range */
/* Pre-configure chip */
ret = preconfigure_smsc_chip(conf);
/* Disable LPC */
pci_read_config_word(dev, LPC_EN, &tmpword); /* LPC_EN register */
tmpword &= 0xfffc; /* mask bit 1 and bit 0, COMA addr range disable */
pci_write_config_word(dev, LPC_EN, tmpword);
return ret;
}
static int __init preconfigure_through_ali(struct pci_dev *dev,
struct smsc_ircc_subsystem_configuration *conf)
{
/* TODO: put in ALi 1533 configuration here. */
IRDA_MESSAGE("SORRY: %s has an unsupported bridge controller (ALi): not pre-configured.\n", conf->name);
return -ENODEV;
}
static int __init smsc_ircc_preconfigure_subsystems(unsigned short ircc_cfg,
unsigned short ircc_fir,
unsigned short ircc_sir,
unsigned char ircc_dma,
unsigned char ircc_irq)
{
struct pci_dev *dev = NULL;
unsigned short ss_vendor = 0x0000;
unsigned short ss_device = 0x0000;
int ret = 0;
dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev);
while (dev != NULL) {
struct smsc_ircc_subsystem_configuration *conf;
/*
* Cache the subsystem vendor/device: some manufacturers fail to set
* this for all components, so we save it in case there is just
* 0x0000 0x0000 on the device we want to check.
*/
if (dev->subsystem_vendor != 0x0000U) {
ss_vendor = dev->subsystem_vendor;
ss_device = dev->subsystem_device;
}
conf = subsystem_configurations;
for( ; conf->subvendor; conf++) {
if(conf->vendor == dev->vendor &&
conf->device == dev->device &&
conf->subvendor == ss_vendor && /* Sometimes these are cached values */
(conf->subdevice == ss_device || conf->subdevice == 0xffff)) {
struct smsc_ircc_subsystem_configuration tmpconf;
memcpy(&tmpconf, conf, sizeof(struct smsc_ircc_subsystem_configuration));
/* Override the default values with anything passed in as parameter */
if (ircc_cfg != 0)
tmpconf.cfg_base = ircc_cfg;
if (ircc_fir != 0)
tmpconf.fir_io = ircc_fir;
if (ircc_sir != 0)
tmpconf.sir_io = ircc_sir;
if (ircc_dma != 0xff)
tmpconf.fir_dma = ircc_dma;
if (ircc_irq != 0xff)
tmpconf.fir_irq = ircc_irq;
IRDA_MESSAGE("Detected unconfigured %s SMSC IrDA chip, pre-configuring device.\n", conf->name);
if (conf->preconfigure)
ret = conf->preconfigure(dev, &tmpconf);
else
ret = -ENODEV;
}
}
dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev);
}
return ret;
}
#endif // CONFIG_PCI
/************************************************
*
* Transceivers specific functions

View File

@ -87,6 +87,7 @@ static void write_msg(struct console *con, const char *msg, unsigned int len)
}
static struct console netconsole = {
.name = "netcon",
.flags = CON_ENABLED | CON_PRINTBUFFER,
.write = write_msg
};

View File

@ -497,21 +497,20 @@ static void tg3_write_mem(struct tg3 *tp, u32 off, u32 val)
unsigned long flags;
spin_lock_irqsave(&tp->indirect_lock, flags);
if (tp->tg3_flags & TG3_FLAG_SRAM_USE_CONFIG) {
pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_BASE_ADDR, off);
pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_DATA, val);
/* Always leave this as zero. */
pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_BASE_ADDR, 0);
spin_unlock_irqrestore(&tp->indirect_lock, flags);
}
} else {
tw32_f(TG3PCI_MEM_WIN_BASE_ADDR, off);
tw32_f(TG3PCI_MEM_WIN_DATA, val);
static void tg3_write_mem_fast(struct tg3 *tp, u32 off, u32 val)
{
/* If no workaround is needed, write to mem space directly */
if (tp->write32 != tg3_write_indirect_reg32)
tw32(NIC_SRAM_WIN_BASE + off, val);
else
tg3_write_mem(tp, off, val);
/* Always leave this as zero. */
tw32_f(TG3PCI_MEM_WIN_BASE_ADDR, 0);
}
spin_unlock_irqrestore(&tp->indirect_lock, flags);
}
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)
unsigned long flags;
spin_lock_irqsave(&tp->indirect_lock, flags);
if (tp->tg3_flags & TG3_FLAG_SRAM_USE_CONFIG) {
pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_BASE_ADDR, off);
pci_read_config_dword(tp->pdev, TG3PCI_MEM_WIN_DATA, val);
/* Always leave this as zero. */
pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_BASE_ADDR, 0);
} else {
tw32_f(TG3PCI_MEM_WIN_BASE_ADDR, off);
*val = tr32(TG3PCI_MEM_WIN_DATA);
/* Always leave this as zero. */
tw32_f(TG3PCI_MEM_WIN_BASE_ADDR, 0);
}
spin_unlock_irqrestore(&tp->indirect_lock, flags);
}
@ -1367,12 +1374,12 @@ static int tg3_set_power_state(struct tg3 *tp, pci_power_t state)
}
}
tg3_write_sig_post_reset(tp, RESET_KIND_SHUTDOWN);
/* Finally, set the new power state. */
pci_write_config_word(tp->pdev, pm + PCI_PM_CTRL, power_control);
udelay(100); /* Delay after power state change */
tg3_write_sig_post_reset(tp, RESET_KIND_SHUTDOWN);
return 0;
}
@ -5828,10 +5835,14 @@ static int tg3_reset_hw(struct tg3 *tp)
GRC_MODE_NO_TX_PHDR_CSUM |
GRC_MODE_NO_RX_PHDR_CSUM);
tp->grc_mode |= GRC_MODE_HOST_SENDBDS;
if (tp->tg3_flags & TG3_FLAG_NO_TX_PSEUDO_CSUM)
/* Pseudo-header checksum is done by hardware logic and not
* the offload processers, so make the chip do the pseudo-
* header checksums on receive. For transmit it is more
* convenient to do the pseudo-header checksum in software
* as Linux does that on transmit for us in all cases.
*/
tp->grc_mode |= GRC_MODE_NO_TX_PHDR_CSUM;
if (tp->tg3_flags & TG3_FLAG_NO_RX_PSEUDO_CSUM)
tp->grc_mode |= GRC_MODE_NO_RX_PHDR_CSUM;
tw32(GRC_MODE,
tp->grc_mode |
@ -6535,11 +6546,11 @@ static void tg3_timer(unsigned long __opaque)
if (tp->tg3_flags & TG3_FLAG_ENABLE_ASF) {
u32 val;
tg3_write_mem_fast(tp, NIC_SRAM_FW_CMD_MBOX,
tg3_write_mem(tp, NIC_SRAM_FW_CMD_MBOX,
FWCMD_NICDRV_ALIVE2);
tg3_write_mem_fast(tp, NIC_SRAM_FW_CMD_LEN_MBOX, 4);
tg3_write_mem(tp, NIC_SRAM_FW_CMD_LEN_MBOX, 4);
/* 5 seconds timeout */
tg3_write_mem_fast(tp, NIC_SRAM_FW_CMD_DATA_MBOX, 5);
tg3_write_mem(tp, NIC_SRAM_FW_CMD_DATA_MBOX, 5);
val = tr32(GRC_RX_CPU_EVENT);
val |= (1 << 14);
tw32(GRC_RX_CPU_EVENT, val);
@ -8034,9 +8045,13 @@ static int tg3_test_nvram(struct tg3 *tp)
for (i = 0; i < size; i++)
csum8 += buf8[i];
if (csum8 == 0)
return 0;
return -EIO;
if (csum8 == 0) {
err = 0;
goto out;
}
err = -EIO;
goto out;
}
/* Bootstrap checksum at offset 0x10 */
@ -9531,8 +9546,11 @@ static void __devinit tg3_get_eeprom_hw_cfg(struct tg3 *tp)
tp->led_ctrl = LED_CTRL_MODE_PHY_1;
/* Do not even try poking around in here on Sun parts. */
if (tp->tg3_flags2 & TG3_FLG2_SUN_570X)
if (tp->tg3_flags2 & TG3_FLG2_SUN_570X) {
/* All SUN chips are built-in LOMs. */
tp->tg3_flags |= TG3_FLAG_EEPROM_WRITE_PROT;
return;
}
tg3_read_mem(tp, NIC_SRAM_DATA_SIG, &val);
if (val == NIC_SRAM_DATA_SIG_MAGIC) {
@ -9630,9 +9648,7 @@ static void __devinit tg3_get_eeprom_hw_cfg(struct tg3 *tp)
tp->pdev->subsystem_vendor == PCI_VENDOR_ID_DELL)
tp->led_ctrl = LED_CTRL_MODE_PHY_2;
if ((GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5700) &&
(GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5701) &&
(nic_cfg & NIC_SRAM_DATA_CFG_EEPROM_WP))
if (nic_cfg & NIC_SRAM_DATA_CFG_EEPROM_WP)
tp->tg3_flags |= TG3_FLAG_EEPROM_WRITE_PROT;
if (nic_cfg & NIC_SRAM_DATA_CFG_ASF_ENABLE) {
@ -10257,6 +10273,13 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
pci_write_config_word(tp->pdev, PCI_COMMAND, pci_cmd);
}
if (tp->write32 == tg3_write_indirect_reg32 ||
((tp->tg3_flags & TG3_FLAG_PCIX_MODE) &&
(GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700 ||
GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5701)) ||
(tp->tg3_flags2 & TG3_FLG2_SUN_570X))
tp->tg3_flags |= TG3_FLAG_SRAM_USE_CONFIG;
/* Get eeprom hw config before calling tg3_set_power_state().
* In particular, the TG3_FLAG_EEPROM_WRITE_PROT flag must be
* determined before calling tg3_set_power_state() so that
@ -10299,15 +10322,6 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
if (tp->pci_chip_rev_id == CHIPREV_ID_5700_B0)
tp->tg3_flags |= TG3_FLAG_BROKEN_CHECKSUMS;
/* Pseudo-header checksum is done by hardware logic and not
* the offload processers, so make the chip do the pseudo-
* header checksums on receive. For transmit it is more
* convenient to do the pseudo-header checksum in software
* as Linux does that on transmit for us in all cases.
*/
tp->tg3_flags |= TG3_FLAG_NO_TX_PSEUDO_CSUM;
tp->tg3_flags &= ~TG3_FLAG_NO_RX_PSEUDO_CSUM;
/* Derive initial jumbo mode from MTU assigned in
* ether_setup() via the alloc_etherdev() call
*/

View File

@ -2171,8 +2171,7 @@ struct tg3 {
#define TG3_FLAG_PCIX_MODE 0x00020000
#define TG3_FLAG_PCI_HIGH_SPEED 0x00040000
#define TG3_FLAG_PCI_32BIT 0x00080000
#define TG3_FLAG_NO_TX_PSEUDO_CSUM 0x00100000
#define TG3_FLAG_NO_RX_PSEUDO_CSUM 0x00200000
#define TG3_FLAG_SRAM_USE_CONFIG 0x00100000
#define TG3_FLAG_SERDES_WOL_CAP 0x00400000
#define TG3_FLAG_JUMBO_RING_ENABLE 0x00800000
#define TG3_FLAG_10_100_ONLY 0x01000000

View File

@ -110,6 +110,8 @@ struct nf_info
/* Function to register/unregister hook points. */
int nf_register_hook(struct nf_hook_ops *reg);
void nf_unregister_hook(struct nf_hook_ops *reg);
int nf_register_hooks(struct nf_hook_ops *reg, unsigned int n);
void nf_unregister_hooks(struct nf_hook_ops *reg, unsigned int n);
/* Functions to register get/setsockopt ranges (non-inclusive). You
need to check permissions yourself! */
@ -281,16 +283,42 @@ extern void nf_invalidate_cache(int pf);
Returns true or false. */
extern int skb_make_writable(struct sk_buff **pskb, unsigned int writable_len);
struct nf_queue_rerouter {
void (*save)(const struct sk_buff *skb, struct nf_info *info);
int (*reroute)(struct sk_buff **skb, const struct nf_info *info);
int rer_size;
struct nf_afinfo {
unsigned short family;
unsigned int (*checksum)(struct sk_buff *skb, unsigned int hook,
unsigned int dataoff, u_int8_t protocol);
void (*saveroute)(const struct sk_buff *skb,
struct nf_info *info);
int (*reroute)(struct sk_buff **skb,
const struct nf_info *info);
int route_key_size;
};
#define nf_info_reroute(x) ((void *)x + sizeof(struct nf_info))
extern struct nf_afinfo *nf_afinfo[];
static inline struct nf_afinfo *nf_get_afinfo(unsigned short family)
{
return rcu_dereference(nf_afinfo[family]);
}
extern int nf_register_queue_rerouter(int pf, struct nf_queue_rerouter *rer);
extern int nf_unregister_queue_rerouter(int pf);
static inline unsigned int
nf_checksum(struct sk_buff *skb, unsigned int hook, unsigned int dataoff,
u_int8_t protocol, unsigned short family)
{
struct nf_afinfo *afinfo;
unsigned int csum = 0;
rcu_read_lock();
afinfo = nf_get_afinfo(family);
if (afinfo)
csum = afinfo->checksum(skb, hook, dataoff, protocol);
rcu_read_unlock();
return csum;
}
extern int nf_register_afinfo(struct nf_afinfo *afinfo);
extern void nf_unregister_afinfo(struct nf_afinfo *afinfo);
#define nf_info_reroute(x) ((void *)x + sizeof(struct nf_info))
#include <net/flow.h>
extern void (*ip_nat_decode_session)(struct sk_buff *, struct flowi *);

View File

@ -80,6 +80,8 @@ enum nf_ip_hook_priorities {
#ifdef __KERNEL__
extern int ip_route_me_harder(struct sk_buff **pskb);
extern int ip_xfrm_me_harder(struct sk_buff **pskb);
extern unsigned int nf_ip_checksum(struct sk_buff *skb, unsigned int hook,
unsigned int dataoff, u_int8_t protocol);
#endif /*__KERNEL__*/
#endif /*__LINUX_IP_NETFILTER_H*/

View File

@ -3,6 +3,8 @@
#ifdef __KERNEL__
#include <linux/netfilter_ipv4/ip_conntrack_helper_h323_asn1.h>
#define RAS_PORT 1719
#define Q931_PORT 1720
#define H323_RTP_CHANNEL_MAX 4 /* Audio, video, FAX and other */
@ -25,6 +27,56 @@ struct ip_ct_h323_master {
};
};
struct ip_conntrack_expect;
extern int get_h225_addr(unsigned char *data, TransportAddress * addr,
u_int32_t * ip, u_int16_t * port);
extern void ip_conntrack_h245_expect(struct ip_conntrack *new,
struct ip_conntrack_expect *this);
extern void ip_conntrack_q931_expect(struct ip_conntrack *new,
struct ip_conntrack_expect *this);
extern int (*set_h245_addr_hook) (struct sk_buff ** pskb,
unsigned char **data, int dataoff,
H245_TransportAddress * addr,
u_int32_t ip, u_int16_t port);
extern int (*set_h225_addr_hook) (struct sk_buff ** pskb,
unsigned char **data, int dataoff,
TransportAddress * addr,
u_int32_t ip, u_int16_t port);
extern int (*set_sig_addr_hook) (struct sk_buff ** pskb,
struct ip_conntrack * ct,
enum ip_conntrack_info ctinfo,
unsigned char **data,
TransportAddress * addr, int count);
extern int (*set_ras_addr_hook) (struct sk_buff ** pskb,
struct ip_conntrack * ct,
enum ip_conntrack_info ctinfo,
unsigned char **data,
TransportAddress * addr, int count);
extern int (*nat_rtp_rtcp_hook) (struct sk_buff ** pskb,
struct ip_conntrack * ct,
enum ip_conntrack_info ctinfo,
unsigned char **data, int dataoff,
H245_TransportAddress * addr,
u_int16_t port, u_int16_t rtp_port,
struct ip_conntrack_expect * rtp_exp,
struct ip_conntrack_expect * rtcp_exp);
extern int (*nat_t120_hook) (struct sk_buff ** pskb, struct ip_conntrack * ct,
enum ip_conntrack_info ctinfo,
unsigned char **data, int dataoff,
H245_TransportAddress * addr, u_int16_t port,
struct ip_conntrack_expect * exp);
extern int (*nat_h245_hook) (struct sk_buff ** pskb, struct ip_conntrack * ct,
enum ip_conntrack_info ctinfo,
unsigned char **data, int dataoff,
TransportAddress * addr, u_int16_t port,
struct ip_conntrack_expect * exp);
extern int (*nat_q931_hook) (struct sk_buff ** pskb, struct ip_conntrack * ct,
enum ip_conntrack_info ctinfo,
unsigned char **data, TransportAddress * addr,
int idx, u_int16_t port,
struct ip_conntrack_expect * exp);
#endif
#endif

View File

@ -73,6 +73,9 @@ enum nf_ip6_hook_priorities {
};
#ifdef CONFIG_NETFILTER
extern unsigned int nf_ip6_checksum(struct sk_buff *skb, unsigned int hook,
unsigned int dataoff, u_int8_t protocol);
extern int ipv6_netfilter_init(void);
extern void ipv6_netfilter_fini(void);
#else /* CONFIG_NETFILTER */

View File

@ -48,31 +48,7 @@ static inline int inet6_sk_ehashfn(const struct sock *sk)
return inet6_ehashfn(laddr, lport, faddr, fport);
}
static inline void __inet6_hash(struct inet_hashinfo *hashinfo,
struct sock *sk)
{
struct hlist_head *list;
rwlock_t *lock;
BUG_TRAP(sk_unhashed(sk));
if (sk->sk_state == TCP_LISTEN) {
list = &hashinfo->listening_hash[inet_sk_listen_hashfn(sk)];
lock = &hashinfo->lhash_lock;
inet_listen_wlock(hashinfo);
} else {
unsigned int hash;
sk->sk_hash = hash = inet6_sk_ehashfn(sk);
hash &= (hashinfo->ehash_size - 1);
list = &hashinfo->ehash[hash].chain;
lock = &hashinfo->ehash[hash].lock;
write_lock(lock);
}
__sk_add_node(sk, list);
sock_prot_inc_use(sk->sk_prot);
write_unlock(lock);
}
extern void __inet6_hash(struct inet_hashinfo *hashinfo, struct sock *sk);
/*
* 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,
*
* The sockhash lock must be held as a reader here.
*/
static inline struct sock *
__inet6_lookup_established(struct inet_hashinfo *hashinfo,
extern struct sock *__inet6_lookup_established(struct inet_hashinfo *hashinfo,
const struct in6_addr *saddr,
const u16 sport,
const struct in6_addr *daddr,
const u16 hnum,
const int dif)
{
struct sock *sk;
const struct hlist_node *node;
const __u32 ports = INET_COMBINED_PORTS(sport, hnum);
/* Optimize here for direct hit, only listening connections can
* have wildcards anyways.
*/
unsigned int hash = inet6_ehashfn(daddr, hnum, saddr, sport);
struct inet_ehash_bucket *head = inet_ehash_bucket(hashinfo, hash);
prefetch(head->chain.first);
read_lock(&head->lock);
sk_for_each(sk, node, &head->chain) {
/* For IPV6 do the cheaper port and family tests first. */
if (INET6_MATCH(sk, hash, saddr, daddr, ports, dif))
goto hit; /* You sunk my battleship! */
}
/* Must check for a TIME_WAIT'er before going to listener hash. */
sk_for_each(sk, node, &(head + hashinfo->ehash_size)->chain) {
const struct inet_timewait_sock *tw = inet_twsk(sk);
if(*((__u32 *)&(tw->tw_dport)) == ports &&
sk->sk_family == PF_INET6) {
const struct inet6_timewait_sock *tw6 = inet6_twsk(sk);
if (ipv6_addr_equal(&tw6->tw_v6_daddr, saddr) &&
ipv6_addr_equal(&tw6->tw_v6_rcv_saddr, daddr) &&
(!sk->sk_bound_dev_if || sk->sk_bound_dev_if == dif))
goto hit;
}
}
read_unlock(&head->lock);
return NULL;
hit:
sock_hold(sk);
read_unlock(&head->lock);
return sk;
}
const int dif);
extern struct sock *inet6_lookup_listener(struct inet_hashinfo *hashinfo,
const struct in6_addr *daddr,

View File

@ -95,6 +95,7 @@ extern int ip_local_deliver(struct sk_buff *skb);
extern int ip_mr_input(struct sk_buff *skb);
extern int ip_output(struct sk_buff *skb);
extern int ip_mc_output(struct sk_buff *skb);
extern int ip_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *));
extern int ip_do_nat(struct sk_buff *skb);
extern void ip_send_check(struct iphdr *ip);
extern int ip_queue_xmit(struct sk_buff *skb, int ipfragok);

View File

@ -8,6 +8,7 @@
static inline __be16 x25_type_trans(struct sk_buff *skb, struct net_device *dev)
{
skb->mac.raw = skb->data;
skb->dev = dev;
skb->pkt_type = PACKET_HOST;
return htons(ETH_P_X25);

View File

@ -255,7 +255,7 @@ static inline int sco_send_frame(struct sock *sk, struct msghdr *msg, int len)
}
if ((err = hci_send_sco(conn->hcon, skb)) < 0)
goto fail;
return err;
return count;

View File

@ -765,6 +765,15 @@ static unsigned int br_nf_local_out(unsigned int hook, struct sk_buff **pskb,
return NF_STOLEN;
}
static int br_nf_dev_queue_xmit(struct sk_buff *skb)
{
if (skb->protocol == htons(ETH_P_IP) &&
skb->len > skb->dev->mtu &&
!(skb_shinfo(skb)->ufo_size || skb_shinfo(skb)->tso_size))
return ip_fragment(skb, br_dev_queue_push_xmit);
else
return br_dev_queue_push_xmit(skb);
}
/* PF_BRIDGE/POST_ROUTING ********************************************/
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,
realoutdev = nf_bridge->netoutdev;
#endif
NF_HOOK(pf, NF_IP_POST_ROUTING, skb, NULL, realoutdev,
br_dev_queue_push_xmit);
br_nf_dev_queue_xmit);
return NF_STOLEN;
@ -869,7 +878,7 @@ static unsigned int ip_sabotage_out(unsigned int hook, struct sk_buff **pskb,
if ((out->hard_start_xmit == br_dev_xmit &&
okfn != br_nf_forward_finish &&
okfn != br_nf_local_out_finish && okfn != br_dev_queue_push_xmit)
okfn != br_nf_local_out_finish && okfn != br_nf_dev_queue_xmit)
#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
|| ((out->priv_flags & IFF_802_1Q_VLAN) &&
VLAN_DEV_INFO(out)->real_dev->hard_start_xmit == br_dev_xmit)

View File

@ -3042,11 +3042,11 @@ void netdev_run_todo(void)
switch(dev->reg_state) {
case NETREG_REGISTERING:
dev->reg_state = NETREG_REGISTERED;
err = netdev_register_sysfs(dev);
if (err)
printk(KERN_ERR "%s: failed sysfs registration (%d)\n",
dev->name, err);
dev->reg_state = NETREG_REGISTERED;
break;
case NETREG_UNREGISTERING:
@ -3100,12 +3100,11 @@ struct net_device *alloc_netdev(int sizeof_priv, const char *name,
alloc_size = (sizeof(*dev) + NETDEV_ALIGN_CONST) & ~NETDEV_ALIGN_CONST;
alloc_size += sizeof_priv + NETDEV_ALIGN_CONST;
p = kmalloc(alloc_size, GFP_KERNEL);
p = kzalloc(alloc_size, GFP_KERNEL);
if (!p) {
printk(KERN_ERR "alloc_dev: Unable to allocate device.\n");
return NULL;
}
memset(p, 0, alloc_size);
dev = (struct net_device *)
(((long)p + NETDEV_ALIGN_CONST) & ~NETDEV_ALIGN_CONST);

View File

@ -55,15 +55,12 @@ int alloc_divert_blk(struct net_device *dev)
dev->divert = NULL;
if (dev->type == ARPHRD_ETHER) {
dev->divert = (struct divert_blk *)
kmalloc(alloc_size, GFP_KERNEL);
dev->divert = kzalloc(alloc_size, GFP_KERNEL);
if (dev->divert == NULL) {
printk(KERN_INFO "divert: unable to allocate divert_blk for %s\n",
dev->name);
return -ENOMEM;
}
memset(dev->divert, 0, sizeof(struct divert_blk));
dev_hold(dev);
}

View File

@ -318,12 +318,10 @@ static void __devinit flow_cache_cpu_prepare(int cpu)
/* NOTHING */;
flow_table(cpu) = (struct flow_cache_entry **)
__get_free_pages(GFP_KERNEL, order);
__get_free_pages(GFP_KERNEL|__GFP_ZERO, order);
if (!flow_table(cpu))
panic("NET: failed to allocate flow cache order %lu\n", order);
memset(flow_table(cpu), 0, PAGE_SIZE << order);
flow_hash_rnd_recalc(cpu) = 1;
flow_count(cpu) = 0;

View File

@ -159,11 +159,10 @@ int gen_new_estimator(struct gnet_stats_basic *bstats,
if (parm->interval < -2 || parm->interval > 3)
return -EINVAL;
est = kmalloc(sizeof(*est), GFP_KERNEL);
est = kzalloc(sizeof(*est), GFP_KERNEL);
if (est == NULL)
return -ENOBUFS;
memset(est, 0, sizeof(*est));
est->interval = parm->interval + 2;
est->bstats = bstats;
est->rate_est = rate_est;

View File

@ -284,14 +284,11 @@ static struct neighbour **neigh_hash_alloc(unsigned int entries)
struct neighbour **ret;
if (size <= PAGE_SIZE) {
ret = kmalloc(size, GFP_ATOMIC);
ret = kzalloc(size, GFP_ATOMIC);
} else {
ret = (struct neighbour **)
__get_free_pages(GFP_ATOMIC, get_order(size));
__get_free_pages(GFP_ATOMIC|__GFP_ZERO, get_order(size));
}
if (ret)
memset(ret, 0, size);
return ret;
}
@ -1089,8 +1086,7 @@ static void neigh_hh_init(struct neighbour *n, struct dst_entry *dst,
if (hh->hh_type == protocol)
break;
if (!hh && (hh = kmalloc(sizeof(*hh), GFP_ATOMIC)) != NULL) {
memset(hh, 0, sizeof(struct hh_cache));
if (!hh && (hh = kzalloc(sizeof(*hh), GFP_ATOMIC)) != NULL) {
rwlock_init(&hh->hh_lock);
hh->hh_type = protocol;
atomic_set(&hh->hh_refcnt, 0);
@ -1366,13 +1362,11 @@ void neigh_table_init(struct neigh_table *tbl)
tbl->hash_buckets = neigh_hash_alloc(tbl->hash_mask + 1);
phsize = (PNEIGH_HASHMASK + 1) * sizeof(struct pneigh_entry *);
tbl->phash_buckets = kmalloc(phsize, GFP_KERNEL);
tbl->phash_buckets = kzalloc(phsize, GFP_KERNEL);
if (!tbl->hash_buckets || !tbl->phash_buckets)
panic("cannot allocate neighbour cache hashes");
memset(tbl->phash_buckets, 0, phsize);
get_random_bytes(&tbl->hash_rnd, sizeof(tbl->hash_rnd));
rwlock_init(&tbl->lock);

View File

@ -165,7 +165,7 @@ static ssize_t show_operstate(struct class_device *dev, char *buf)
operstate = IF_OPER_DOWN;
read_unlock(&dev_base_lock);
if (operstate >= sizeof(operstates))
if (operstate >= ARRAY_SIZE(operstates))
return -EINVAL; /* should not happen */
return sprintf(buf, "%s\n", operstates[operstate]);

View File

@ -38,13 +38,11 @@ int reqsk_queue_alloc(struct request_sock_queue *queue,
{
const int lopt_size = sizeof(struct listen_sock) +
nr_table_entries * sizeof(struct request_sock *);
struct listen_sock *lopt = kmalloc(lopt_size, GFP_KERNEL);
struct listen_sock *lopt = kzalloc(lopt_size, GFP_KERNEL);
if (lopt == NULL)
return -ENOMEM;
memset(lopt, 0, lopt_size);
for (lopt->max_qlen_log = 6;
(1 << lopt->max_qlen_log) < sysctl_max_syn_backlog;
lopt->max_qlen_log++);

View File

@ -50,7 +50,7 @@
* Patrick McHardy <kaber@trash.net>
*/
#define VERSION "0.406"
#define VERSION "0.407"
#include <linux/config.h>
#include <asm/uaccess.h>
@ -314,11 +314,6 @@ static void __leaf_free_rcu(struct rcu_head *head)
kfree(container_of(head, struct leaf, rcu));
}
static inline void free_leaf(struct leaf *leaf)
{
call_rcu(&leaf->rcu, __leaf_free_rcu);
}
static void __leaf_info_free_rcu(struct rcu_head *head)
{
kfree(container_of(head, struct leaf_info, rcu));
@ -357,6 +352,11 @@ static void __tnode_free_rcu(struct rcu_head *head)
static inline void tnode_free(struct tnode *tn)
{
if(IS_LEAF(tn)) {
struct leaf *l = (struct leaf *) tn;
call_rcu_bh(&l->rcu, __leaf_free_rcu);
}
else
call_rcu(&tn->rcu, __tnode_free_rcu);
}

View File

@ -304,13 +304,17 @@ static void ip_expire(unsigned long arg)
/* Creation primitives. */
static struct ipq *ip_frag_intern(unsigned int hash, struct ipq *qp_in)
static struct ipq *ip_frag_intern(struct ipq *qp_in)
{
struct ipq *qp;
#ifdef CONFIG_SMP
struct hlist_node *n;
#endif
unsigned int hash;
write_lock(&ipfrag_lock);
hash = ipqhashfn(qp_in->id, qp_in->saddr, qp_in->daddr,
qp_in->protocol);
#ifdef CONFIG_SMP
/* With SMP race we have to recheck hash table, because
* 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)
}
/* Add an entry to the 'ipq' queue for a newly received IP datagram. */
static struct ipq *ip_frag_create(unsigned hash, struct iphdr *iph, u32 user)
static struct ipq *ip_frag_create(struct iphdr *iph, u32 user)
{
struct ipq *qp;
@ -371,7 +375,7 @@ static struct ipq *ip_frag_create(unsigned hash, struct iphdr *iph, u32 user)
spin_lock_init(&qp->lock);
atomic_set(&qp->refcnt, 1);
return ip_frag_intern(hash, qp);
return ip_frag_intern(qp);
out_nomem:
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)
__u32 saddr = iph->saddr;
__u32 daddr = iph->daddr;
__u8 protocol = iph->protocol;
unsigned int hash = ipqhashfn(id, saddr, daddr, protocol);
unsigned int hash;
struct ipq *qp;
struct hlist_node *n;
read_lock(&ipfrag_lock);
hash = ipqhashfn(id, saddr, daddr, protocol);
hlist_for_each_entry(qp, n, &ipq_hash[hash], list) {
if(qp->id == id &&
qp->saddr == saddr &&
@ -405,7 +410,7 @@ static inline struct ipq *ip_find(struct iphdr *iph, u32 user)
}
read_unlock(&ipfrag_lock);
return ip_frag_create(hash, iph, user);
return ip_frag_create(iph, user);
}
/* Is the fragment too far ahead to be part of ipq? */

View File

@ -656,7 +656,7 @@ static int ipgre_rcv(struct sk_buff *skb)
read_unlock(&ipgre_lock);
return(0);
}
icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PROT_UNREACH, 0);
icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0);
drop:
read_unlock(&ipgre_lock);

View File

@ -86,8 +86,6 @@
int sysctl_ip_default_ttl = IPDEFTTL;
static int ip_fragment(struct sk_buff *skb, int (*output)(struct sk_buff*));
/* Generate a checksum for an outgoing IP datagram. */
__inline__ void ip_send_check(struct iphdr *iph)
{
@ -421,7 +419,7 @@ static void ip_copy_metadata(struct sk_buff *to, struct sk_buff *from)
* single device frame, and queue such a frame for sending.
*/
static int ip_fragment(struct sk_buff *skb, int (*output)(struct sk_buff*))
int ip_fragment(struct sk_buff *skb, int (*output)(struct sk_buff*))
{
struct iphdr *iph;
int raw = 0;
@ -673,6 +671,8 @@ static int ip_fragment(struct sk_buff *skb, int (*output)(struct sk_buff*))
return err;
}
EXPORT_SYMBOL(ip_fragment);
int
ip_generic_getfrag(void *from, char *to, int offset, int len, int odd, struct sk_buff *skb)
{

View File

@ -474,9 +474,6 @@ static int ipip_rcv(struct sk_buff *skb)
struct iphdr *iph;
struct ip_tunnel *tunnel;
if (!pskb_may_pull(skb, sizeof(struct iphdr)))
goto out;
iph = skb->nh.iph;
read_lock(&ipip_lock);
@ -508,7 +505,6 @@ static int ipip_rcv(struct sk_buff *skb)
}
read_unlock(&ipip_lock);
out:
return -1;
}

View File

@ -133,7 +133,7 @@ struct ip_rt_info {
u_int8_t tos;
};
static void queue_save(const struct sk_buff *skb, struct nf_info *info)
static void nf_ip_saveroute(const struct sk_buff *skb, struct nf_info *info)
{
struct ip_rt_info *rt_info = nf_info_reroute(info);
@ -146,7 +146,7 @@ static void queue_save(const struct sk_buff *skb, struct nf_info *info)
}
}
static int queue_reroute(struct sk_buff **pskb, const struct nf_info *info)
static int nf_ip_reroute(struct sk_buff **pskb, const struct nf_info *info)
{
const struct ip_rt_info *rt_info = nf_info_reroute(info);
@ -161,20 +161,54 @@ static int queue_reroute(struct sk_buff **pskb, const struct nf_info *info)
return 0;
}
static struct nf_queue_rerouter ip_reroute = {
.rer_size = sizeof(struct ip_rt_info),
.save = queue_save,
.reroute = queue_reroute,
unsigned int nf_ip_checksum(struct sk_buff *skb, unsigned int hook,
unsigned int dataoff, u_int8_t protocol)
{
struct iphdr *iph = skb->nh.iph;
unsigned int csum = 0;
switch (skb->ip_summed) {
case CHECKSUM_HW:
if (hook != NF_IP_PRE_ROUTING && hook != NF_IP_LOCAL_IN)
break;
if ((protocol == 0 && !(u16)csum_fold(skb->csum)) ||
!csum_tcpudp_magic(iph->saddr, iph->daddr,
skb->len - dataoff, protocol,
skb->csum)) {
skb->ip_summed = CHECKSUM_UNNECESSARY;
break;
}
/* fall through */
case CHECKSUM_NONE:
if (protocol == 0)
skb->csum = 0;
else
skb->csum = csum_tcpudp_nofold(iph->saddr, iph->daddr,
skb->len - dataoff,
protocol, 0);
csum = __skb_checksum_complete(skb);
}
return csum;
}
EXPORT_SYMBOL(nf_ip_checksum);
static struct nf_afinfo nf_ip_afinfo = {
.family = AF_INET,
.checksum = nf_ip_checksum,
.saveroute = nf_ip_saveroute,
.reroute = nf_ip_reroute,
.route_key_size = sizeof(struct ip_rt_info),
};
static int ipv4_netfilter_init(void)
{
return nf_register_queue_rerouter(PF_INET, &ip_reroute);
return nf_register_afinfo(&nf_ip_afinfo);
}
static void ipv4_netfilter_fini(void)
{
nf_unregister_queue_rerouter(PF_INET);
nf_unregister_afinfo(&nf_ip_afinfo);
}
module_init(ipv4_netfilter_init);

View File

@ -69,6 +69,7 @@ config IP_NF_CONNTRACK_NETLINK
tristate 'Connection tracking netlink interface (EXPERIMENTAL)'
depends on EXPERIMENTAL && IP_NF_CONNTRACK && NETFILTER_NETLINK
depends on IP_NF_CONNTRACK!=y || NETFILTER_NETLINK!=m
depends on IP_NF_NAT=n || IP_NF_NAT
help
This option enables support for a netlink-based userspace interface

View File

@ -181,33 +181,26 @@ static struct nf_hook_ops arpt_ops[] = {
static int __init arptable_filter_init(void)
{
int ret, i;
int ret;
/* Register table */
ret = arpt_register_table(&packet_filter, &initial_table.repl);
if (ret < 0)
return ret;
for (i = 0; i < ARRAY_SIZE(arpt_ops); i++)
if ((ret = nf_register_hook(&arpt_ops[i])) < 0)
goto cleanup_hooks;
ret = nf_register_hooks(arpt_ops, ARRAY_SIZE(arpt_ops));
if (ret < 0)
goto cleanup_table;
return ret;
cleanup_hooks:
while (--i >= 0)
nf_unregister_hook(&arpt_ops[i]);
cleanup_table:
arpt_unregister_table(&packet_filter);
return ret;
}
static void __exit arptable_filter_fini(void)
{
unsigned int i;
for (i = 0; i < ARRAY_SIZE(arpt_ops); i++)
nf_unregister_hook(&arpt_ops[i]);
nf_unregister_hooks(arpt_ops, ARRAY_SIZE(arpt_ops));
arpt_unregister_table(&packet_filter);
}

View File

@ -9,37 +9,6 @@
* Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
*
* For more information, please see http://nath323.sourceforge.net/
*
* Changes:
* 2006-02-01 - initial version 0.1
*
* 2006-02-20 - version 0.2
* 1. Changed source format to follow kernel conventions
* 2. Deleted some unnecessary structures
* 3. Minor fixes
*
* 2006-03-10 - version 0.3
* 1. Added support for multiple TPKTs in one packet (suggested by
* Patrick McHardy)
* 2. Avoid excessive stack usage (based on Patrick McHardy's patch)
* 3. Added support for non-linear skb (based on Patrick McHardy's patch)
* 4. Fixed missing H.245 module owner (Patrick McHardy)
* 5. Avoid long RAS expectation chains (Patrick McHardy)
* 6. Fixed incorrect __exit attribute (Patrick McHardy)
* 7. Eliminated unnecessary return code
* 8. Fixed incorrect use of NAT data from conntrack code (suggested by
* Patrick McHardy)
* 9. Fixed TTL calculation error in RCF
* 10. Added TTL support in RRQ
* 11. Better support for separate TPKT header and data
*
* 2006-03-15 - version 0.4
* 1. Added support for T.120 channels
* 2. Added parameter gkrouted_only (suggested by Patrick McHardy)
* 3. Splitted ASN.1 code and data (suggested by Patrick McHardy)
* 4. Sort ASN.1 data to avoid forwarding declarations (suggested by
* Patrick McHardy)
* 5. Reset next TPKT data length in get_tpkt_data()
*/
#include <linux/config.h>
@ -54,8 +23,6 @@
#include <linux/netfilter_ipv4/ip_conntrack_h323.h>
#include <linux/moduleparam.h>
#include "ip_conntrack_helper_h323_asn1.h"
#if 0
#define DEBUGP printk
#else
@ -63,6 +30,10 @@
#endif
/* Parameters */
static unsigned int default_rrq_ttl = 300;
module_param(default_rrq_ttl, uint, 0600);
MODULE_PARM_DESC(default_rrq_ttl, "use this TTL if it's missing in RRQ");
static int gkrouted_only = 1;
module_param(gkrouted_only, int, 0600);
MODULE_PARM_DESC(gkrouted_only, "only accept calls from gatekeeper");
@ -222,7 +193,7 @@ static int get_tpkt_data(struct sk_buff **pskb, struct ip_conntrack *ct,
}
/****************************************************************************/
int get_h245_addr(unsigned char *data, H245_TransportAddress * addr,
static int get_h245_addr(unsigned char *data, H245_TransportAddress * addr,
u_int32_t * ip, u_int16_t * port)
{
unsigned char *p;
@ -1302,7 +1273,7 @@ static int process_rrq(struct sk_buff **pskb, struct ip_conntrack *ct,
DEBUGP("ip_ct_ras: RRQ TTL = %u seconds\n", rrq->timeToLive);
info->timeout = rrq->timeToLive;
} else
info->timeout = 0;
info->timeout = default_rrq_ttl;
return 0;
}
@ -1713,18 +1684,17 @@ static int __init init(void)
module_init(init);
module_exit(fini);
EXPORT_SYMBOL(get_h245_addr);
EXPORT_SYMBOL(get_h225_addr);
EXPORT_SYMBOL(ip_conntrack_h245_expect);
EXPORT_SYMBOL(ip_conntrack_q931_expect);
EXPORT_SYMBOL(set_h245_addr_hook);
EXPORT_SYMBOL(set_h225_addr_hook);
EXPORT_SYMBOL(set_sig_addr_hook);
EXPORT_SYMBOL(set_ras_addr_hook);
EXPORT_SYMBOL(nat_rtp_rtcp_hook);
EXPORT_SYMBOL(nat_t120_hook);
EXPORT_SYMBOL(nat_h245_hook);
EXPORT_SYMBOL(nat_q931_hook);
EXPORT_SYMBOL_GPL(get_h225_addr);
EXPORT_SYMBOL_GPL(ip_conntrack_h245_expect);
EXPORT_SYMBOL_GPL(ip_conntrack_q931_expect);
EXPORT_SYMBOL_GPL(set_h245_addr_hook);
EXPORT_SYMBOL_GPL(set_h225_addr_hook);
EXPORT_SYMBOL_GPL(set_sig_addr_hook);
EXPORT_SYMBOL_GPL(set_ras_addr_hook);
EXPORT_SYMBOL_GPL(nat_rtp_rtcp_hook);
EXPORT_SYMBOL_GPL(nat_t120_hook);
EXPORT_SYMBOL_GPL(nat_h245_hook);
EXPORT_SYMBOL_GPL(nat_q931_hook);
MODULE_AUTHOR("Jing Min Zhao <zhaojingmin@users.sourceforge.net>");
MODULE_DESCRIPTION("H.323 connection tracking helper");

View File

@ -15,7 +15,7 @@
#else
#include <stdio.h>
#endif
#include "ip_conntrack_helper_h323_asn1.h"
#include <linux/netfilter_ipv4/ip_conntrack_helper_h323_asn1.h>
/* Trace Flag */
#ifndef H323_TRACE

View File

@ -224,25 +224,14 @@ icmp_error(struct sk_buff *skb, enum ip_conntrack_info *ctinfo,
}
/* See ip_conntrack_proto_tcp.c */
if (hooknum != NF_IP_PRE_ROUTING)
goto checksum_skipped;
switch (skb->ip_summed) {
case CHECKSUM_HW:
if (!(u16)csum_fold(skb->csum))
break;
/* fall through */
case CHECKSUM_NONE:
skb->csum = 0;
if (__skb_checksum_complete(skb)) {
if (hooknum == NF_IP_PRE_ROUTING &&
nf_ip_checksum(skb, hooknum, skb->nh.iph->ihl * 4, 0)) {
if (LOG_INVALID(IPPROTO_ICMP))
nf_log_packet(PF_INET, 0, skb, NULL, NULL, NULL,
"ip_ct_icmp: bad ICMP checksum ");
return -NF_ACCEPT;
}
}
checksum_skipped:
/*
* 18 is the highest 'known' ICMP type. Anything else is a mystery
*

View File

@ -870,11 +870,8 @@ static int tcp_error(struct sk_buff *skb,
* and moreover root might send raw packets.
*/
/* FIXME: Source route IP option packets --RR */
if (hooknum == NF_IP_PRE_ROUTING
&& skb->ip_summed != CHECKSUM_UNNECESSARY
&& csum_tcpudp_magic(iph->saddr, iph->daddr, tcplen, IPPROTO_TCP,
skb->ip_summed == CHECKSUM_HW ? skb->csum
: skb_checksum(skb, iph->ihl*4, tcplen, 0))) {
if (hooknum == NF_IP_PRE_ROUTING &&
nf_ip_checksum(skb, hooknum, iph->ihl * 4, IPPROTO_TCP)) {
if (LOG_INVALID(IPPROTO_TCP))
nf_log_packet(PF_INET, 0, skb, NULL, NULL, NULL,
"ip_ct_tcp: bad TCP checksum ");

View File

@ -120,11 +120,8 @@ static int udp_error(struct sk_buff *skb, enum ip_conntrack_info *ctinfo,
* because the semantic of CHECKSUM_HW is different there
* and moreover root might send raw packets.
* FIXME: Source route IP option packets --RR */
if (hooknum == NF_IP_PRE_ROUTING
&& skb->ip_summed != CHECKSUM_UNNECESSARY
&& csum_tcpudp_magic(iph->saddr, iph->daddr, udplen, IPPROTO_UDP,
skb->ip_summed == CHECKSUM_HW ? skb->csum
: skb_checksum(skb, iph->ihl*4, udplen, 0))) {
if (hooknum == NF_IP_PRE_ROUTING &&
nf_ip_checksum(skb, hooknum, iph->ihl * 4, IPPROTO_UDP)) {
if (LOG_INVALID(IPPROTO_UDP))
nf_log_packet(PF_INET, 0, skb, NULL, NULL, NULL,
"ip_ct_udp: bad UDP checksum ");

View File

@ -469,70 +469,63 @@ static unsigned int ip_conntrack_local(unsigned int hooknum,
/* Connection tracking may drop packets, but never alters them, so
make it the first hook. */
static struct nf_hook_ops ip_conntrack_defrag_ops = {
static struct nf_hook_ops ip_conntrack_ops[] = {
{
.hook = ip_conntrack_defrag,
.owner = THIS_MODULE,
.pf = PF_INET,
.hooknum = NF_IP_PRE_ROUTING,
.priority = NF_IP_PRI_CONNTRACK_DEFRAG,
};
static struct nf_hook_ops ip_conntrack_in_ops = {
},
{
.hook = ip_conntrack_in,
.owner = THIS_MODULE,
.pf = PF_INET,
.hooknum = NF_IP_PRE_ROUTING,
.priority = NF_IP_PRI_CONNTRACK,
};
static struct nf_hook_ops ip_conntrack_defrag_local_out_ops = {
},
{
.hook = ip_conntrack_defrag,
.owner = THIS_MODULE,
.pf = PF_INET,
.hooknum = NF_IP_LOCAL_OUT,
.priority = NF_IP_PRI_CONNTRACK_DEFRAG,
};
static struct nf_hook_ops ip_conntrack_local_out_ops = {
},
{
.hook = ip_conntrack_local,
.owner = THIS_MODULE,
.pf = PF_INET,
.hooknum = NF_IP_LOCAL_OUT,
.priority = NF_IP_PRI_CONNTRACK,
};
/* helpers */
static struct nf_hook_ops ip_conntrack_helper_out_ops = {
},
{
.hook = ip_conntrack_help,
.owner = THIS_MODULE,
.pf = PF_INET,
.hooknum = NF_IP_POST_ROUTING,
.priority = NF_IP_PRI_CONNTRACK_HELPER,
};
static struct nf_hook_ops ip_conntrack_helper_in_ops = {
},
{
.hook = ip_conntrack_help,
.owner = THIS_MODULE,
.pf = PF_INET,
.hooknum = NF_IP_LOCAL_IN,
.priority = NF_IP_PRI_CONNTRACK_HELPER,
};
/* Refragmenter; last chance. */
static struct nf_hook_ops ip_conntrack_out_ops = {
},
{
.hook = ip_confirm,
.owner = THIS_MODULE,
.pf = PF_INET,
.hooknum = NF_IP_POST_ROUTING,
.priority = NF_IP_PRI_CONNTRACK_CONFIRM,
};
static struct nf_hook_ops ip_conntrack_local_in_ops = {
},
{
.hook = ip_confirm,
.owner = THIS_MODULE,
.pf = PF_INET,
.hooknum = NF_IP_LOCAL_IN,
.priority = NF_IP_PRI_CONNTRACK_CONFIRM,
},
};
/* Sysctl support */
@ -783,122 +776,6 @@ static ctl_table ip_ct_net_table[] = {
EXPORT_SYMBOL(ip_ct_log_invalid);
#endif /* CONFIG_SYSCTL */
static int init_or_cleanup(int init)
{
#ifdef CONFIG_PROC_FS
struct proc_dir_entry *proc, *proc_exp, *proc_stat;
#endif
int ret = 0;
if (!init) goto cleanup;
ret = ip_conntrack_init();
if (ret < 0)
goto cleanup_nothing;
#ifdef CONFIG_PROC_FS
ret = -ENOMEM;
proc = proc_net_fops_create("ip_conntrack", 0440, &ct_file_ops);
if (!proc) goto cleanup_init;
proc_exp = proc_net_fops_create("ip_conntrack_expect", 0440,
&exp_file_ops);
if (!proc_exp) goto cleanup_proc;
proc_stat = create_proc_entry("ip_conntrack", S_IRUGO, proc_net_stat);
if (!proc_stat)
goto cleanup_proc_exp;
proc_stat->proc_fops = &ct_cpu_seq_fops;
proc_stat->owner = THIS_MODULE;
#endif
ret = nf_register_hook(&ip_conntrack_defrag_ops);
if (ret < 0) {
printk("ip_conntrack: can't register pre-routing defrag hook.\n");
goto cleanup_proc_stat;
}
ret = nf_register_hook(&ip_conntrack_defrag_local_out_ops);
if (ret < 0) {
printk("ip_conntrack: can't register local_out defrag hook.\n");
goto cleanup_defragops;
}
ret = nf_register_hook(&ip_conntrack_in_ops);
if (ret < 0) {
printk("ip_conntrack: can't register pre-routing hook.\n");
goto cleanup_defraglocalops;
}
ret = nf_register_hook(&ip_conntrack_local_out_ops);
if (ret < 0) {
printk("ip_conntrack: can't register local out hook.\n");
goto cleanup_inops;
}
ret = nf_register_hook(&ip_conntrack_helper_in_ops);
if (ret < 0) {
printk("ip_conntrack: can't register local in helper hook.\n");
goto cleanup_inandlocalops;
}
ret = nf_register_hook(&ip_conntrack_helper_out_ops);
if (ret < 0) {
printk("ip_conntrack: can't register postrouting helper hook.\n");
goto cleanup_helperinops;
}
ret = nf_register_hook(&ip_conntrack_out_ops);
if (ret < 0) {
printk("ip_conntrack: can't register post-routing hook.\n");
goto cleanup_helperoutops;
}
ret = nf_register_hook(&ip_conntrack_local_in_ops);
if (ret < 0) {
printk("ip_conntrack: can't register local in hook.\n");
goto cleanup_inoutandlocalops;
}
#ifdef CONFIG_SYSCTL
ip_ct_sysctl_header = register_sysctl_table(ip_ct_net_table, 0);
if (ip_ct_sysctl_header == NULL) {
printk("ip_conntrack: can't register to sysctl.\n");
ret = -ENOMEM;
goto cleanup_localinops;
}
#endif
return ret;
cleanup:
synchronize_net();
#ifdef CONFIG_SYSCTL
unregister_sysctl_table(ip_ct_sysctl_header);
cleanup_localinops:
#endif
nf_unregister_hook(&ip_conntrack_local_in_ops);
cleanup_inoutandlocalops:
nf_unregister_hook(&ip_conntrack_out_ops);
cleanup_helperoutops:
nf_unregister_hook(&ip_conntrack_helper_out_ops);
cleanup_helperinops:
nf_unregister_hook(&ip_conntrack_helper_in_ops);
cleanup_inandlocalops:
nf_unregister_hook(&ip_conntrack_local_out_ops);
cleanup_inops:
nf_unregister_hook(&ip_conntrack_in_ops);
cleanup_defraglocalops:
nf_unregister_hook(&ip_conntrack_defrag_local_out_ops);
cleanup_defragops:
nf_unregister_hook(&ip_conntrack_defrag_ops);
cleanup_proc_stat:
#ifdef CONFIG_PROC_FS
remove_proc_entry("ip_conntrack", proc_net_stat);
cleanup_proc_exp:
proc_net_remove("ip_conntrack_expect");
cleanup_proc:
proc_net_remove("ip_conntrack");
cleanup_init:
#endif /* CONFIG_PROC_FS */
ip_conntrack_cleanup();
cleanup_nothing:
return ret;
}
/* FIXME: Allow NULL functions and sub in pointers to generic for
them. --RR */
int ip_conntrack_protocol_register(struct ip_conntrack_protocol *proto)
@ -931,12 +808,77 @@ void ip_conntrack_protocol_unregister(struct ip_conntrack_protocol *proto)
static int __init ip_conntrack_standalone_init(void)
{
return init_or_cleanup(1);
#ifdef CONFIG_PROC_FS
struct proc_dir_entry *proc, *proc_exp, *proc_stat;
#endif
int ret = 0;
ret = ip_conntrack_init();
if (ret < 0)
return ret;
#ifdef CONFIG_PROC_FS
ret = -ENOMEM;
proc = proc_net_fops_create("ip_conntrack", 0440, &ct_file_ops);
if (!proc) goto cleanup_init;
proc_exp = proc_net_fops_create("ip_conntrack_expect", 0440,
&exp_file_ops);
if (!proc_exp) goto cleanup_proc;
proc_stat = create_proc_entry("ip_conntrack", S_IRUGO, proc_net_stat);
if (!proc_stat)
goto cleanup_proc_exp;
proc_stat->proc_fops = &ct_cpu_seq_fops;
proc_stat->owner = THIS_MODULE;
#endif
ret = nf_register_hooks(ip_conntrack_ops, ARRAY_SIZE(ip_conntrack_ops));
if (ret < 0) {
printk("ip_conntrack: can't register hooks.\n");
goto cleanup_proc_stat;
}
#ifdef CONFIG_SYSCTL
ip_ct_sysctl_header = register_sysctl_table(ip_ct_net_table, 0);
if (ip_ct_sysctl_header == NULL) {
printk("ip_conntrack: can't register to sysctl.\n");
ret = -ENOMEM;
goto cleanup_hooks;
}
#endif
return ret;
#ifdef CONFIG_SYSCTL
cleanup_hooks:
nf_unregister_hooks(ip_conntrack_ops, ARRAY_SIZE(ip_conntrack_ops));
#endif
cleanup_proc_stat:
#ifdef CONFIG_PROC_FS
remove_proc_entry("ip_conntrack", proc_net_stat);
cleanup_proc_exp:
proc_net_remove("ip_conntrack_expect");
cleanup_proc:
proc_net_remove("ip_conntrack");
cleanup_init:
#endif /* CONFIG_PROC_FS */
ip_conntrack_cleanup();
return ret;
}
static void __exit ip_conntrack_standalone_fini(void)
{
init_or_cleanup(0);
synchronize_net();
#ifdef CONFIG_SYSCTL
unregister_sysctl_table(ip_ct_sysctl_header);
#endif
nf_unregister_hooks(ip_conntrack_ops, ARRAY_SIZE(ip_conntrack_ops));
#ifdef CONFIG_PROC_FS
remove_proc_entry("ip_conntrack", proc_net_stat);
proc_net_remove("ip_conntrack_expect");
proc_net_remove("ip_conntrack");
#endif /* CONFIG_PROC_FS */
ip_conntrack_cleanup();
}
module_init(ip_conntrack_standalone_init);

View File

@ -7,24 +7,6 @@
*
* Based on the 'brute force' H.323 NAT module by
* Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
*
* Changes:
* 2006-02-01 - initial version 0.1
*
* 2006-02-20 - version 0.2
* 1. Changed source format to follow kernel conventions
* 2. Deleted some unnecessary structures
* 3. Minor fixes
*
* 2006-03-10 - version 0.3
* 1. Added support for multiple TPKTs in one packet (suggested by
* Patrick McHardy)
* 2. Added support for non-linear skb (based on Patrick McHardy's patch)
* 3. Eliminated unnecessary return code
*
* 2006-03-15 - version 0.4
* 1. Added support for T.120 channels
* 2. Added parameter gkrouted_only (suggested by Patrick McHardy)
*/
#include <linux/module.h>
@ -41,65 +23,12 @@
#include <linux/netfilter_ipv4/ip_conntrack_h323.h>
#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
#include "ip_conntrack_helper_h323_asn1.h"
#if 0
#define DEBUGP printk
#else
#define DEBUGP(format, args...)
#endif
extern int get_h245_addr(unsigned char *data, H245_TransportAddress * addr,
u_int32_t * ip, u_int16_t * port);
extern int get_h225_addr(unsigned char *data, TransportAddress * addr,
u_int32_t * ip, u_int16_t * port);
extern void ip_conntrack_h245_expect(struct ip_conntrack *new,
struct ip_conntrack_expect *this);
extern void ip_conntrack_q931_expect(struct ip_conntrack *new,
struct ip_conntrack_expect *this);
extern int (*set_h245_addr_hook) (struct sk_buff ** pskb,
unsigned char **data, int dataoff,
H245_TransportAddress * addr,
u_int32_t ip, u_int16_t port);
extern int (*set_h225_addr_hook) (struct sk_buff ** pskb,
unsigned char **data, int dataoff,
TransportAddress * addr,
u_int32_t ip, u_int16_t port);
extern int (*set_sig_addr_hook) (struct sk_buff ** pskb,
struct ip_conntrack * ct,
enum ip_conntrack_info ctinfo,
unsigned char **data,
TransportAddress * addr, int count);
extern int (*set_ras_addr_hook) (struct sk_buff ** pskb,
struct ip_conntrack * ct,
enum ip_conntrack_info ctinfo,
unsigned char **data,
TransportAddress * addr, int count);
extern int (*nat_rtp_rtcp_hook) (struct sk_buff ** pskb,
struct ip_conntrack * ct,
enum ip_conntrack_info ctinfo,
unsigned char **data, int dataoff,
H245_TransportAddress * addr,
u_int16_t port, u_int16_t rtp_port,
struct ip_conntrack_expect * rtp_exp,
struct ip_conntrack_expect * rtcp_exp);
extern int (*nat_t120_hook) (struct sk_buff ** pskb, struct ip_conntrack * ct,
enum ip_conntrack_info ctinfo,
unsigned char **data, int dataoff,
H245_TransportAddress * addr, u_int16_t port,
struct ip_conntrack_expect * exp);
extern int (*nat_h245_hook) (struct sk_buff ** pskb, struct ip_conntrack * ct,
enum ip_conntrack_info ctinfo,
unsigned char **data, int dataoff,
TransportAddress * addr, u_int16_t port,
struct ip_conntrack_expect * exp);
extern int (*nat_q931_hook) (struct sk_buff ** pskb, struct ip_conntrack * ct,
enum ip_conntrack_info ctinfo,
unsigned char **data, TransportAddress * addr,
int idx, u_int16_t port,
struct ip_conntrack_expect * exp);
/****************************************************************************/
static int set_addr(struct sk_buff **pskb,
unsigned char **data, int dataoff,

View File

@ -279,7 +279,7 @@ static struct ipt_target ipt_dnat_reg = {
.target = ipt_dnat_target,
.targetsize = sizeof(struct ip_nat_multi_range_compat),
.table = "nat",
.hooks = 1 << NF_IP_PRE_ROUTING,
.hooks = (1 << NF_IP_PRE_ROUTING) | (1 << NF_IP_LOCAL_OUT),
.checkentry = ipt_dnat_checkentry,
};

View File

@ -299,69 +299,63 @@ ip_nat_adjust(unsigned int hooknum,
/* We must be after connection tracking and before packet filtering. */
static struct nf_hook_ops ip_nat_ops[] = {
/* Before packet filtering, change destination */
static struct nf_hook_ops ip_nat_in_ops = {
{
.hook = ip_nat_in,
.owner = THIS_MODULE,
.pf = PF_INET,
.hooknum = NF_IP_PRE_ROUTING,
.priority = NF_IP_PRI_NAT_DST,
};
},
/* After packet filtering, change source */
static struct nf_hook_ops ip_nat_out_ops = {
{
.hook = ip_nat_out,
.owner = THIS_MODULE,
.pf = PF_INET,
.hooknum = NF_IP_POST_ROUTING,
.priority = NF_IP_PRI_NAT_SRC,
};
},
/* After conntrack, adjust sequence number */
static struct nf_hook_ops ip_nat_adjust_out_ops = {
{
.hook = ip_nat_adjust,
.owner = THIS_MODULE,
.pf = PF_INET,
.hooknum = NF_IP_POST_ROUTING,
.priority = NF_IP_PRI_NAT_SEQ_ADJUST,
};
},
/* Before packet filtering, change destination */
static struct nf_hook_ops ip_nat_local_out_ops = {
{
.hook = ip_nat_local_fn,
.owner = THIS_MODULE,
.pf = PF_INET,
.hooknum = NF_IP_LOCAL_OUT,
.priority = NF_IP_PRI_NAT_DST,
};
/* After packet filtering, change source for reply packets of LOCAL_OUT DNAT */
static struct nf_hook_ops ip_nat_local_in_ops = {
},
/* After packet filtering, change source */
{
.hook = ip_nat_fn,
.owner = THIS_MODULE,
.pf = PF_INET,
.hooknum = NF_IP_LOCAL_IN,
.priority = NF_IP_PRI_NAT_SRC,
};
},
/* After conntrack, adjust sequence number */
static struct nf_hook_ops ip_nat_adjust_in_ops = {
{
.hook = ip_nat_adjust,
.owner = THIS_MODULE,
.pf = PF_INET,
.hooknum = NF_IP_LOCAL_IN,
.priority = NF_IP_PRI_NAT_SEQ_ADJUST,
},
};
static int init_or_cleanup(int init)
static int __init ip_nat_standalone_init(void)
{
int ret = 0;
need_conntrack();
if (!init) goto cleanup;
#ifdef CONFIG_XFRM
BUG_ON(ip_nat_decode_session != NULL);
ip_nat_decode_session = nat_decode_session;
@ -371,50 +365,13 @@ static int init_or_cleanup(int init)
printk("ip_nat_init: can't setup rules.\n");
goto cleanup_decode_session;
}
ret = nf_register_hook(&ip_nat_in_ops);
ret = nf_register_hooks(ip_nat_ops, ARRAY_SIZE(ip_nat_ops));
if (ret < 0) {
printk("ip_nat_init: can't register in hook.\n");
printk("ip_nat_init: can't register hooks.\n");
goto cleanup_rule_init;
}
ret = nf_register_hook(&ip_nat_out_ops);
if (ret < 0) {
printk("ip_nat_init: can't register out hook.\n");
goto cleanup_inops;
}
ret = nf_register_hook(&ip_nat_adjust_in_ops);
if (ret < 0) {
printk("ip_nat_init: can't register adjust in hook.\n");
goto cleanup_outops;
}
ret = nf_register_hook(&ip_nat_adjust_out_ops);
if (ret < 0) {
printk("ip_nat_init: can't register adjust out hook.\n");
goto cleanup_adjustin_ops;
}
ret = nf_register_hook(&ip_nat_local_out_ops);
if (ret < 0) {
printk("ip_nat_init: can't register local out hook.\n");
goto cleanup_adjustout_ops;
}
ret = nf_register_hook(&ip_nat_local_in_ops);
if (ret < 0) {
printk("ip_nat_init: can't register local in hook.\n");
goto cleanup_localoutops;
}
return ret;
cleanup:
nf_unregister_hook(&ip_nat_local_in_ops);
cleanup_localoutops:
nf_unregister_hook(&ip_nat_local_out_ops);
cleanup_adjustout_ops:
nf_unregister_hook(&ip_nat_adjust_out_ops);
cleanup_adjustin_ops:
nf_unregister_hook(&ip_nat_adjust_in_ops);
cleanup_outops:
nf_unregister_hook(&ip_nat_out_ops);
cleanup_inops:
nf_unregister_hook(&ip_nat_in_ops);
cleanup_rule_init:
ip_nat_rule_cleanup();
cleanup_decode_session:
@ -425,14 +382,14 @@ static int init_or_cleanup(int init)
return ret;
}
static int __init ip_nat_standalone_init(void)
{
return init_or_cleanup(1);
}
static void __exit ip_nat_standalone_fini(void)
{
init_or_cleanup(0);
nf_unregister_hooks(ip_nat_ops, ARRAY_SIZE(ip_nat_ops));
ip_nat_rule_cleanup();
#ifdef CONFIG_XFRM
ip_nat_decode_session = NULL;
synchronize_net();
#endif
}
module_init(ip_nat_standalone_init);

View File

@ -662,15 +662,11 @@ static struct nf_queue_handler nfqh = {
.outfn = &ipq_enqueue_packet,
};
static int
init_or_cleanup(int init)
static int __init ip_queue_init(void)
{
int status = -ENOMEM;
struct proc_dir_entry *proc;
if (!init)
goto cleanup;
netlink_register_notifier(&ipq_nl_notifier);
ipqnl = netlink_kernel_create(NETLINK_FIREWALL, 0, ipq_rcv_sk,
THIS_MODULE);
@ -697,11 +693,6 @@ init_or_cleanup(int init)
}
return status;
cleanup:
nf_unregister_queue_handlers(&nfqh);
synchronize_net();
ipq_flush(NF_DROP);
cleanup_sysctl:
unregister_sysctl_table(ipq_sysctl_header);
unregister_netdevice_notifier(&ipq_dev_notifier);
@ -717,15 +708,21 @@ init_or_cleanup(int init)
return status;
}
static int __init ip_queue_init(void)
{
return init_or_cleanup(1);
}
static void __exit ip_queue_fini(void)
{
init_or_cleanup(0);
nf_unregister_queue_handlers(&nfqh);
synchronize_net();
ipq_flush(NF_DROP);
unregister_sysctl_table(ipq_sysctl_header);
unregister_netdevice_notifier(&ipq_dev_notifier);
proc_net_remove(IPQ_PROC_FS_NAME);
sock_release(ipqnl->sk_socket);
mutex_lock(&ipqnl_mutex);
mutex_unlock(&ipqnl_mutex);
netlink_unregister_notifier(&ipq_nl_notifier);
}
MODULE_DESCRIPTION("IPv4 packet queue handler");

View File

@ -725,22 +725,17 @@ static struct file_operations clusterip_proc_fops = {
#endif /* CONFIG_PROC_FS */
static int init_or_cleanup(int fini)
static int __init ipt_clusterip_init(void)
{
int ret;
if (fini)
goto cleanup;
ret = ipt_register_target(&clusterip_tgt);
if (ret < 0)
return ret;
if (ipt_register_target(&clusterip_tgt)) {
ret = -EINVAL;
goto cleanup_none;
}
if (nf_register_hook(&cip_arp_ops) < 0) {
ret = -EINVAL;
ret = nf_register_hook(&cip_arp_ops);
if (ret < 0)
goto cleanup_target;
}
#ifdef CONFIG_PROC_FS
clusterip_procdir = proc_mkdir("ipt_CLUSTERIP", proc_net);
@ -753,31 +748,24 @@ static int init_or_cleanup(int fini)
printk(KERN_NOTICE "ClusterIP Version %s loaded successfully\n",
CLUSTERIP_VERSION);
return 0;
cleanup:
cleanup_hook:
nf_unregister_hook(&cip_arp_ops);
cleanup_target:
ipt_unregister_target(&clusterip_tgt);
return ret;
}
static void __exit ipt_clusterip_fini(void)
{
printk(KERN_NOTICE "ClusterIP Version %s unloading\n",
CLUSTERIP_VERSION);
#ifdef CONFIG_PROC_FS
remove_proc_entry(clusterip_procdir->name, clusterip_procdir->parent);
#endif
cleanup_hook:
nf_unregister_hook(&cip_arp_ops);
cleanup_target:
ipt_unregister_target(&clusterip_tgt);
cleanup_none:
return -EINVAL;
}
static int __init ipt_clusterip_init(void)
{
return init_or_cleanup(0);
}
static void __exit ipt_clusterip_fini(void)
{
init_or_cleanup(1);
}
module_init(ipt_clusterip_init);

View File

@ -106,7 +106,6 @@ static void send_reset(struct sk_buff *oldskb, int hook)
struct rtable *rt;
u_int16_t tmp_port;
u_int32_t tmp_addr;
unsigned int tcplen;
int needs_ack;
int hh_len;
@ -124,13 +123,7 @@ static void send_reset(struct sk_buff *oldskb, int hook)
return;
/* Check checksum */
tcplen = oldskb->len - iph->ihl * 4;
if (((hook != NF_IP_LOCAL_IN && oldskb->ip_summed != CHECKSUM_HW) ||
(hook == NF_IP_LOCAL_IN &&
oldskb->ip_summed != CHECKSUM_UNNECESSARY)) &&
csum_tcpudp_magic(iph->saddr, iph->daddr, tcplen, IPPROTO_TCP,
oldskb->ip_summed == CHECKSUM_HW ? oldskb->csum :
skb_checksum(oldskb, iph->ihl * 4, tcplen, 0)))
if (nf_ip_checksum(oldskb, hook, iph->ihl * 4, IPPROTO_TCP))
return;
if ((rt = route_reverse(oldskb, oth, hook)) == NULL)

View File

@ -157,37 +157,20 @@ static int __init iptable_filter_init(void)
return ret;
/* Register hooks */
ret = nf_register_hook(&ipt_ops[0]);
ret = nf_register_hooks(ipt_ops, ARRAY_SIZE(ipt_ops));
if (ret < 0)
goto cleanup_table;
ret = nf_register_hook(&ipt_ops[1]);
if (ret < 0)
goto cleanup_hook0;
ret = nf_register_hook(&ipt_ops[2]);
if (ret < 0)
goto cleanup_hook1;
return ret;
cleanup_hook1:
nf_unregister_hook(&ipt_ops[1]);
cleanup_hook0:
nf_unregister_hook(&ipt_ops[0]);
cleanup_table:
ipt_unregister_table(&packet_filter);
return ret;
}
static void __exit iptable_filter_fini(void)
{
unsigned int i;
for (i = 0; i < sizeof(ipt_ops)/sizeof(struct nf_hook_ops); i++)
nf_unregister_hook(&ipt_ops[i]);
nf_unregister_hooks(ipt_ops, ARRAY_SIZE(ipt_ops));
ipt_unregister_table(&packet_filter);
}

View File

@ -211,49 +211,20 @@ static int __init iptable_mangle_init(void)
return ret;
/* Register hooks */
ret = nf_register_hook(&ipt_ops[0]);
ret = nf_register_hooks(ipt_ops, ARRAY_SIZE(ipt_ops));
if (ret < 0)
goto cleanup_table;
ret = nf_register_hook(&ipt_ops[1]);
if (ret < 0)
goto cleanup_hook0;
ret = nf_register_hook(&ipt_ops[2]);
if (ret < 0)
goto cleanup_hook1;
ret = nf_register_hook(&ipt_ops[3]);
if (ret < 0)
goto cleanup_hook2;
ret = nf_register_hook(&ipt_ops[4]);
if (ret < 0)
goto cleanup_hook3;
return ret;
cleanup_hook3:
nf_unregister_hook(&ipt_ops[3]);
cleanup_hook2:
nf_unregister_hook(&ipt_ops[2]);
cleanup_hook1:
nf_unregister_hook(&ipt_ops[1]);
cleanup_hook0:
nf_unregister_hook(&ipt_ops[0]);
cleanup_table:
ipt_unregister_table(&packet_mangler);
return ret;
}
static void __exit iptable_mangle_fini(void)
{
unsigned int i;
for (i = 0; i < sizeof(ipt_ops)/sizeof(struct nf_hook_ops); i++)
nf_unregister_hook(&ipt_ops[i]);
nf_unregister_hooks(ipt_ops, ARRAY_SIZE(ipt_ops));
ipt_unregister_table(&packet_mangler);
}

View File

@ -126,31 +126,20 @@ static int __init iptable_raw_init(void)
return ret;
/* Register hooks */
ret = nf_register_hook(&ipt_ops[0]);
ret = nf_register_hooks(ipt_ops, ARRAY_SIZE(ipt_ops));
if (ret < 0)
goto cleanup_table;
ret = nf_register_hook(&ipt_ops[1]);
if (ret < 0)
goto cleanup_hook0;
return ret;
cleanup_hook0:
nf_unregister_hook(&ipt_ops[0]);
cleanup_table:
ipt_unregister_table(&packet_raw);
return ret;
}
static void __exit iptable_raw_fini(void)
{
unsigned int i;
for (i = 0; i < sizeof(ipt_ops)/sizeof(struct nf_hook_ops); i++)
nf_unregister_hook(&ipt_ops[i]);
nf_unregister_hooks(ipt_ops, ARRAY_SIZE(ipt_ops));
ipt_unregister_table(&packet_raw);
}

View File

@ -210,71 +210,63 @@ static unsigned int ipv4_conntrack_local(unsigned int hooknum,
/* Connection tracking may drop packets, but never alters them, so
make it the first hook. */
static struct nf_hook_ops ipv4_conntrack_defrag_ops = {
static struct nf_hook_ops ipv4_conntrack_ops[] = {
{
.hook = ipv4_conntrack_defrag,
.owner = THIS_MODULE,
.pf = PF_INET,
.hooknum = NF_IP_PRE_ROUTING,
.priority = NF_IP_PRI_CONNTRACK_DEFRAG,
};
static struct nf_hook_ops ipv4_conntrack_in_ops = {
},
{
.hook = ipv4_conntrack_in,
.owner = THIS_MODULE,
.pf = PF_INET,
.hooknum = NF_IP_PRE_ROUTING,
.priority = NF_IP_PRI_CONNTRACK,
};
static struct nf_hook_ops ipv4_conntrack_defrag_local_out_ops = {
},
{
.hook = ipv4_conntrack_defrag,
.owner = THIS_MODULE,
.pf = PF_INET,
.hooknum = NF_IP_LOCAL_OUT,
.priority = NF_IP_PRI_CONNTRACK_DEFRAG,
};
static struct nf_hook_ops ipv4_conntrack_local_out_ops = {
},
{
.hook = ipv4_conntrack_local,
.owner = THIS_MODULE,
.pf = PF_INET,
.hooknum = NF_IP_LOCAL_OUT,
.priority = NF_IP_PRI_CONNTRACK,
};
/* helpers */
static struct nf_hook_ops ipv4_conntrack_helper_out_ops = {
},
{
.hook = ipv4_conntrack_help,
.owner = THIS_MODULE,
.pf = PF_INET,
.hooknum = NF_IP_POST_ROUTING,
.priority = NF_IP_PRI_CONNTRACK_HELPER,
};
static struct nf_hook_ops ipv4_conntrack_helper_in_ops = {
},
{
.hook = ipv4_conntrack_help,
.owner = THIS_MODULE,
.pf = PF_INET,
.hooknum = NF_IP_LOCAL_IN,
.priority = NF_IP_PRI_CONNTRACK_HELPER,
};
/* Refragmenter; last chance. */
static struct nf_hook_ops ipv4_conntrack_out_ops = {
},
{
.hook = ipv4_confirm,
.owner = THIS_MODULE,
.pf = PF_INET,
.hooknum = NF_IP_POST_ROUTING,
.priority = NF_IP_PRI_CONNTRACK_CONFIRM,
};
static struct nf_hook_ops ipv4_conntrack_local_in_ops = {
},
{
.hook = ipv4_confirm,
.owner = THIS_MODULE,
.pf = PF_INET,
.hooknum = NF_IP_LOCAL_IN,
.priority = NF_IP_PRI_CONNTRACK_CONFIRM,
},
};
#ifdef CONFIG_SYSCTL
@ -440,16 +432,20 @@ struct nf_conntrack_l3proto nf_conntrack_l3proto_ipv4 = {
extern struct nf_conntrack_protocol nf_conntrack_protocol_tcp4;
extern struct nf_conntrack_protocol nf_conntrack_protocol_udp4;
extern struct nf_conntrack_protocol nf_conntrack_protocol_icmp;
static int init_or_cleanup(int init)
MODULE_ALIAS("nf_conntrack-" __stringify(AF_INET));
MODULE_LICENSE("GPL");
static int __init nf_conntrack_l3proto_ipv4_init(void)
{
int ret = 0;
if (!init) goto cleanup;
need_conntrack();
ret = nf_register_sockopt(&so_getorigdst);
if (ret < 0) {
printk(KERN_ERR "Unable to register netfilter socket option\n");
goto cleanup_nothing;
return ret;
}
ret = nf_conntrack_protocol_register(&nf_conntrack_protocol_tcp4);
@ -476,84 +472,26 @@ static int init_or_cleanup(int init)
goto cleanup_icmp;
}
ret = nf_register_hook(&ipv4_conntrack_defrag_ops);
ret = nf_register_hooks(ipv4_conntrack_ops,
ARRAY_SIZE(ipv4_conntrack_ops));
if (ret < 0) {
printk("nf_conntrack_ipv4: can't register pre-routing defrag hook.\n");
printk("nf_conntrack_ipv4: can't register hooks.\n");
goto cleanup_ipv4;
}
ret = nf_register_hook(&ipv4_conntrack_defrag_local_out_ops);
if (ret < 0) {
printk("nf_conntrack_ipv4: can't register local_out defrag hook.\n");
goto cleanup_defragops;
}
ret = nf_register_hook(&ipv4_conntrack_in_ops);
if (ret < 0) {
printk("nf_conntrack_ipv4: can't register pre-routing hook.\n");
goto cleanup_defraglocalops;
}
ret = nf_register_hook(&ipv4_conntrack_local_out_ops);
if (ret < 0) {
printk("nf_conntrack_ipv4: can't register local out hook.\n");
goto cleanup_inops;
}
ret = nf_register_hook(&ipv4_conntrack_helper_in_ops);
if (ret < 0) {
printk("nf_conntrack_ipv4: can't register local helper hook.\n");
goto cleanup_inandlocalops;
}
ret = nf_register_hook(&ipv4_conntrack_helper_out_ops);
if (ret < 0) {
printk("nf_conntrack_ipv4: can't register postrouting helper hook.\n");
goto cleanup_helperinops;
}
ret = nf_register_hook(&ipv4_conntrack_out_ops);
if (ret < 0) {
printk("nf_conntrack_ipv4: can't register post-routing hook.\n");
goto cleanup_helperoutops;
}
ret = nf_register_hook(&ipv4_conntrack_local_in_ops);
if (ret < 0) {
printk("nf_conntrack_ipv4: can't register local in hook.\n");
goto cleanup_inoutandlocalops;
}
#ifdef CONFIG_SYSCTL
nf_ct_ipv4_sysctl_header = register_sysctl_table(nf_ct_net_table, 0);
if (nf_ct_ipv4_sysctl_header == NULL) {
printk("nf_conntrack: can't register to sysctl.\n");
ret = -ENOMEM;
goto cleanup_localinops;
goto cleanup_hooks;
}
#endif
return ret;
cleanup:
synchronize_net();
#ifdef CONFIG_SYSCTL
unregister_sysctl_table(nf_ct_ipv4_sysctl_header);
cleanup_localinops:
cleanup_hooks:
nf_unregister_hooks(ipv4_conntrack_ops, ARRAY_SIZE(ipv4_conntrack_ops));
#endif
nf_unregister_hook(&ipv4_conntrack_local_in_ops);
cleanup_inoutandlocalops:
nf_unregister_hook(&ipv4_conntrack_out_ops);
cleanup_helperoutops:
nf_unregister_hook(&ipv4_conntrack_helper_out_ops);
cleanup_helperinops:
nf_unregister_hook(&ipv4_conntrack_helper_in_ops);
cleanup_inandlocalops:
nf_unregister_hook(&ipv4_conntrack_local_out_ops);
cleanup_inops:
nf_unregister_hook(&ipv4_conntrack_in_ops);
cleanup_defraglocalops:
nf_unregister_hook(&ipv4_conntrack_defrag_local_out_ops);
cleanup_defragops:
nf_unregister_hook(&ipv4_conntrack_defrag_ops);
cleanup_ipv4:
nf_conntrack_l3proto_unregister(&nf_conntrack_l3proto_ipv4);
cleanup_icmp:
@ -564,22 +502,21 @@ static int init_or_cleanup(int init)
nf_conntrack_protocol_unregister(&nf_conntrack_protocol_tcp4);
cleanup_sockopt:
nf_unregister_sockopt(&so_getorigdst);
cleanup_nothing:
return ret;
}
MODULE_ALIAS("nf_conntrack-" __stringify(AF_INET));
MODULE_LICENSE("GPL");
static int __init nf_conntrack_l3proto_ipv4_init(void)
{
need_conntrack();
return init_or_cleanup(1);
}
static void __exit nf_conntrack_l3proto_ipv4_fini(void)
{
init_or_cleanup(0);
synchronize_net();
#ifdef CONFIG_SYSCTL
unregister_sysctl_table(nf_ct_ipv4_sysctl_header);
#endif
nf_unregister_hooks(ipv4_conntrack_ops, ARRAY_SIZE(ipv4_conntrack_ops));
nf_conntrack_l3proto_unregister(&nf_conntrack_l3proto_ipv4);
nf_conntrack_protocol_unregister(&nf_conntrack_protocol_icmp);
nf_conntrack_protocol_unregister(&nf_conntrack_protocol_udp4);
nf_conntrack_protocol_unregister(&nf_conntrack_protocol_tcp4);
nf_unregister_sockopt(&so_getorigdst);
}
module_init(nf_conntrack_l3proto_ipv4_init);

View File

@ -235,30 +235,14 @@ icmp_error(struct sk_buff *skb, unsigned int dataoff,
}
/* See ip_conntrack_proto_tcp.c */
if (hooknum != NF_IP_PRE_ROUTING)
goto checksum_skipped;
switch (skb->ip_summed) {
case CHECKSUM_HW:
if (!(u16)csum_fold(skb->csum))
break;
if (hooknum == NF_IP_PRE_ROUTING &&
nf_ip_checksum(skb, hooknum, dataoff, 0)) {
if (LOG_INVALID(IPPROTO_ICMP))
nf_log_packet(PF_INET, 0, skb, NULL, NULL, NULL,
"nf_ct_icmp: bad HW ICMP checksum ");
return -NF_ACCEPT;
case CHECKSUM_NONE:
if ((u16)csum_fold(skb_checksum(skb, 0, skb->len, 0))) {
if (LOG_INVALID(IPPROTO_ICMP))
nf_log_packet(PF_INET, 0, skb, NULL, NULL,
NULL,
"nf_ct_icmp: bad ICMP checksum ");
return -NF_ACCEPT;
}
default:
break;
}
checksum_skipped:
/*
* 18 is the highest 'known' ICMP type. Anything else is a mystery
*

View File

@ -8,6 +8,8 @@
#include <linux/mutex.h>
#include <linux/netdevice.h>
#include <linux/skbuff.h>
#include <net/icmp.h>
#include <net/ip.h>
#include <net/protocol.h>
#include <net/xfrm.h>
@ -70,10 +72,16 @@ static int tunnel4_rcv(struct sk_buff *skb)
{
struct xfrm_tunnel *handler;
if (!pskb_may_pull(skb, sizeof(struct iphdr)))
goto drop;
for (handler = tunnel4_handlers; handler; handler = handler->next)
if (!handler->handler(skb))
return 0;
icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0);
drop:
kfree_skb(skb);
return 0;
}

View File

@ -37,8 +37,6 @@ static int xfrm4_parse_spi(struct sk_buff *skb, u8 nexthdr, u32 *spi, u32 *seq)
{
switch (nexthdr) {
case IPPROTO_IPIP:
if (!pskb_may_pull(skb, sizeof(struct iphdr)))
return -EINVAL;
*spi = skb->nh.iph->saddr;
*seq = 0;
return 0;
@ -90,7 +88,7 @@ int xfrm4_rcv_encap(struct sk_buff *skb, __u16 encap_type)
if (unlikely(x->km.state != XFRM_STATE_VALID))
goto drop_unlock;
if (x->encap->encap_type != encap_type)
if ((x->encap ? x->encap->encap_type : 0) != encap_type)
goto drop_unlock;
if (x->props.replay_window && xfrm_replay_check(x, seq))

View File

@ -23,6 +23,86 @@
#include <net/inet6_hashtables.h>
#include <net/ip.h>
void __inet6_hash(struct inet_hashinfo *hashinfo,
struct sock *sk)
{
struct hlist_head *list;
rwlock_t *lock;
BUG_TRAP(sk_unhashed(sk));
if (sk->sk_state == TCP_LISTEN) {
list = &hashinfo->listening_hash[inet_sk_listen_hashfn(sk)];
lock = &hashinfo->lhash_lock;
inet_listen_wlock(hashinfo);
} else {
unsigned int hash;
sk->sk_hash = hash = inet6_sk_ehashfn(sk);
hash &= (hashinfo->ehash_size - 1);
list = &hashinfo->ehash[hash].chain;
lock = &hashinfo->ehash[hash].lock;
write_lock(lock);
}
__sk_add_node(sk, list);
sock_prot_inc_use(sk->sk_prot);
write_unlock(lock);
}
EXPORT_SYMBOL(__inet6_hash);
/*
* Sockets in TCP_CLOSE state are _always_ taken out of the hash, so
* we need not check it for TCP lookups anymore, thanks Alexey. -DaveM
*
* The sockhash lock must be held as a reader here.
*/
struct sock *__inet6_lookup_established(struct inet_hashinfo *hashinfo,
const struct in6_addr *saddr,
const u16 sport,
const struct in6_addr *daddr,
const u16 hnum,
const int dif)
{
struct sock *sk;
const struct hlist_node *node;
const __u32 ports = INET_COMBINED_PORTS(sport, hnum);
/* Optimize here for direct hit, only listening connections can
* have wildcards anyways.
*/
unsigned int hash = inet6_ehashfn(daddr, hnum, saddr, sport);
struct inet_ehash_bucket *head = inet_ehash_bucket(hashinfo, hash);
prefetch(head->chain.first);
read_lock(&head->lock);
sk_for_each(sk, node, &head->chain) {
/* For IPV6 do the cheaper port and family tests first. */
if (INET6_MATCH(sk, hash, saddr, daddr, ports, dif))
goto hit; /* You sunk my battleship! */
}
/* Must check for a TIME_WAIT'er before going to listener hash. */
sk_for_each(sk, node, &(head + hashinfo->ehash_size)->chain) {
const struct inet_timewait_sock *tw = inet_twsk(sk);
if(*((__u32 *)&(tw->tw_dport)) == ports &&
sk->sk_family == PF_INET6) {
const struct inet6_timewait_sock *tw6 = inet6_twsk(sk);
if (ipv6_addr_equal(&tw6->tw_v6_daddr, saddr) &&
ipv6_addr_equal(&tw6->tw_v6_rcv_saddr, daddr) &&
(!sk->sk_bound_dev_if || sk->sk_bound_dev_if == dif))
goto hit;
}
}
read_unlock(&head->lock);
return NULL;
hit:
sock_hold(sk);
read_unlock(&head->lock);
return sk;
}
EXPORT_SYMBOL(__inet6_lookup_established);
struct sock *inet6_lookup_listener(struct inet_hashinfo *hashinfo,
const struct in6_addr *daddr,
const unsigned short hnum, const int dif)

View File

@ -519,9 +519,6 @@ ip6ip6_rcv(struct sk_buff *skb)
struct ipv6hdr *ipv6h;
struct ip6_tnl *t;
if (!pskb_may_pull(skb, sizeof (*ipv6h)))
goto discard;
ipv6h = skb->nh.ipv6h;
read_lock(&ip6ip6_lock);
@ -529,8 +526,7 @@ ip6ip6_rcv(struct sk_buff *skb)
if ((t = ip6ip6_tnl_lookup(&ipv6h->saddr, &ipv6h->daddr)) != NULL) {
if (!xfrm6_policy_check(NULL, XFRM_POLICY_IN, skb)) {
read_unlock(&ip6ip6_lock);
kfree_skb(skb);
return 0;
goto discard;
}
if (!(t->parms.flags & IP6_TNL_F_CAP_RCV)) {
@ -557,9 +553,11 @@ ip6ip6_rcv(struct sk_buff *skb)
return 0;
}
read_unlock(&ip6ip6_lock);
icmpv6_send(skb, ICMPV6_DEST_UNREACH, ICMPV6_ADDR_UNREACH, 0, skb->dev);
discard:
return 1;
discard:
kfree_skb(skb);
return 0;
}
static inline struct ipv6_txoptions *create_tel(__u8 encap_limit)

View File

@ -7,6 +7,7 @@
#include <net/ipv6.h>
#include <net/ip6_route.h>
#include <net/xfrm.h>
#include <net/ip6_checksum.h>
int ip6_route_me_harder(struct sk_buff *skb)
{
@ -54,7 +55,7 @@ struct ip6_rt_info {
struct in6_addr saddr;
};
static void save(const struct sk_buff *skb, struct nf_info *info)
static void nf_ip6_saveroute(const struct sk_buff *skb, struct nf_info *info)
{
struct ip6_rt_info *rt_info = nf_info_reroute(info);
@ -66,7 +67,7 @@ static void save(const struct sk_buff *skb, struct nf_info *info)
}
}
static int reroute(struct sk_buff **pskb, const struct nf_info *info)
static int nf_ip6_reroute(struct sk_buff **pskb, const struct nf_info *info)
{
struct ip6_rt_info *rt_info = nf_info_reroute(info);
@ -79,15 +80,50 @@ static int reroute(struct sk_buff **pskb, const struct nf_info *info)
return 0;
}
static struct nf_queue_rerouter ip6_reroute = {
.rer_size = sizeof(struct ip6_rt_info),
.save = &save,
.reroute = &reroute,
unsigned int nf_ip6_checksum(struct sk_buff *skb, unsigned int hook,
unsigned int dataoff, u_int8_t protocol)
{
struct ipv6hdr *ip6h = skb->nh.ipv6h;
unsigned int csum = 0;
switch (skb->ip_summed) {
case CHECKSUM_HW:
if (hook != NF_IP6_PRE_ROUTING && hook != NF_IP6_LOCAL_IN)
break;
if (!csum_ipv6_magic(&ip6h->saddr, &ip6h->daddr,
skb->len - dataoff, protocol,
csum_sub(skb->csum,
skb_checksum(skb, 0,
dataoff, 0)))) {
skb->ip_summed = CHECKSUM_UNNECESSARY;
break;
}
/* fall through */
case CHECKSUM_NONE:
skb->csum = ~csum_ipv6_magic(&ip6h->saddr, &ip6h->daddr,
skb->len - dataoff,
protocol,
csum_sub(0,
skb_checksum(skb, 0,
dataoff, 0)));
csum = __skb_checksum_complete(skb);
}
return csum;
}
EXPORT_SYMBOL(nf_ip6_checksum);
static struct nf_afinfo nf_ip6_afinfo = {
.family = AF_INET6,
.checksum = nf_ip6_checksum,
.saveroute = nf_ip6_saveroute,
.reroute = nf_ip6_reroute,
.route_key_size = sizeof(struct ip6_rt_info),
};
int __init ipv6_netfilter_init(void)
{
return nf_register_queue_rerouter(PF_INET6, &ip6_reroute);
return nf_register_afinfo(&nf_ip6_afinfo);
}
/* This can be called from inet6_init() on errors, so it cannot
@ -95,5 +131,5 @@ int __init ipv6_netfilter_init(void)
*/
void ipv6_netfilter_fini(void)
{
nf_unregister_queue_rerouter(PF_INET6);
nf_unregister_afinfo(&nf_ip6_afinfo);
}

View File

@ -658,15 +658,11 @@ static struct nf_queue_handler nfqh = {
.outfn = &ipq_enqueue_packet,
};
static int
init_or_cleanup(int init)
static int __init ip6_queue_init(void)
{
int status = -ENOMEM;
struct proc_dir_entry *proc;
if (!init)
goto cleanup;
netlink_register_notifier(&ipq_nl_notifier);
ipqnl = netlink_kernel_create(NETLINK_IP6_FW, 0, ipq_rcv_sk,
THIS_MODULE);
@ -693,11 +689,6 @@ init_or_cleanup(int init)
}
return status;
cleanup:
nf_unregister_queue_handlers(&nfqh);
synchronize_net();
ipq_flush(NF_DROP);
cleanup_sysctl:
unregister_sysctl_table(ipq_sysctl_header);
unregister_netdevice_notifier(&ipq_dev_notifier);
@ -713,15 +704,21 @@ init_or_cleanup(int init)
return status;
}
static int __init ip6_queue_init(void)
{
return init_or_cleanup(1);
}
static void __exit ip6_queue_fini(void)
{
init_or_cleanup(0);
nf_unregister_queue_handlers(&nfqh);
synchronize_net();
ipq_flush(NF_DROP);
unregister_sysctl_table(ipq_sysctl_header);
unregister_netdevice_notifier(&ipq_dev_notifier);
proc_net_remove(IPQ_PROC_FS_NAME);
sock_release(ipqnl->sk_socket);
mutex_lock(&ipqnl_mutex);
mutex_unlock(&ipqnl_mutex);
netlink_unregister_notifier(&ipq_nl_notifier);
}
MODULE_DESCRIPTION("IPv6 packet queue handler");

View File

@ -177,37 +177,20 @@ static int __init ip6table_filter_init(void)
return ret;
/* Register hooks */
ret = nf_register_hook(&ip6t_ops[0]);
ret = nf_register_hooks(ip6t_ops, ARRAY_SIZE(ip6t_ops));
if (ret < 0)
goto cleanup_table;
ret = nf_register_hook(&ip6t_ops[1]);
if (ret < 0)
goto cleanup_hook0;
ret = nf_register_hook(&ip6t_ops[2]);
if (ret < 0)
goto cleanup_hook1;
return ret;
cleanup_hook1:
nf_unregister_hook(&ip6t_ops[1]);
cleanup_hook0:
nf_unregister_hook(&ip6t_ops[0]);
cleanup_table:
ip6t_unregister_table(&packet_filter);
return ret;
}
static void __exit ip6table_filter_fini(void)
{
unsigned int i;
for (i = 0; i < sizeof(ip6t_ops)/sizeof(struct nf_hook_ops); i++)
nf_unregister_hook(&ip6t_ops[i]);
nf_unregister_hooks(ip6t_ops, ARRAY_SIZE(ip6t_ops));
ip6t_unregister_table(&packet_filter);
}

View File

@ -238,49 +238,20 @@ static int __init ip6table_mangle_init(void)
return ret;
/* Register hooks */
ret = nf_register_hook(&ip6t_ops[0]);
ret = nf_register_hooks(ip6t_ops, ARRAY_SIZE(ip6t_ops));
if (ret < 0)
goto cleanup_table;
ret = nf_register_hook(&ip6t_ops[1]);
if (ret < 0)
goto cleanup_hook0;
ret = nf_register_hook(&ip6t_ops[2]);
if (ret < 0)
goto cleanup_hook1;
ret = nf_register_hook(&ip6t_ops[3]);
if (ret < 0)
goto cleanup_hook2;
ret = nf_register_hook(&ip6t_ops[4]);
if (ret < 0)
goto cleanup_hook3;
return ret;
cleanup_hook3:
nf_unregister_hook(&ip6t_ops[3]);
cleanup_hook2:
nf_unregister_hook(&ip6t_ops[2]);
cleanup_hook1:
nf_unregister_hook(&ip6t_ops[1]);
cleanup_hook0:
nf_unregister_hook(&ip6t_ops[0]);
cleanup_table:
ip6t_unregister_table(&packet_mangler);
return ret;
}
static void __exit ip6table_mangle_fini(void)
{
unsigned int i;
for (i = 0; i < sizeof(ip6t_ops)/sizeof(struct nf_hook_ops); i++)
nf_unregister_hook(&ip6t_ops[i]);
nf_unregister_hooks(ip6t_ops, ARRAY_SIZE(ip6t_ops));
ip6t_unregister_table(&packet_mangler);
}

View File

@ -152,31 +152,20 @@ static int __init ip6table_raw_init(void)
return ret;
/* Register hooks */
ret = nf_register_hook(&ip6t_ops[0]);
ret = nf_register_hooks(ip6t_ops, ARRAY_SIZE(ip6t_ops));
if (ret < 0)
goto cleanup_table;
ret = nf_register_hook(&ip6t_ops[1]);
if (ret < 0)
goto cleanup_hook0;
return ret;
cleanup_hook0:
nf_unregister_hook(&ip6t_ops[0]);
cleanup_table:
ip6t_unregister_table(&packet_raw);
return ret;
}
static void __exit ip6table_raw_fini(void)
{
unsigned int i;
for (i = 0; i < sizeof(ip6t_ops)/sizeof(struct nf_hook_ops); i++)
nf_unregister_hook(&ip6t_ops[i]);
nf_unregister_hooks(ip6t_ops, ARRAY_SIZE(ip6t_ops));
ip6t_unregister_table(&packet_raw);
}

View File

@ -286,55 +286,49 @@ static unsigned int ipv6_conntrack_local(unsigned int hooknum,
return ipv6_conntrack_in(hooknum, pskb, in, out, okfn);
}
/* Connection tracking may drop packets, but never alters them, so
make it the first hook. */
static struct nf_hook_ops ipv6_conntrack_defrag_ops = {
static struct nf_hook_ops ipv6_conntrack_ops[] = {
{
.hook = ipv6_defrag,
.owner = THIS_MODULE,
.pf = PF_INET6,
.hooknum = NF_IP6_PRE_ROUTING,
.priority = NF_IP6_PRI_CONNTRACK_DEFRAG,
};
static struct nf_hook_ops ipv6_conntrack_in_ops = {
},
{
.hook = ipv6_conntrack_in,
.owner = THIS_MODULE,
.pf = PF_INET6,
.hooknum = NF_IP6_PRE_ROUTING,
.priority = NF_IP6_PRI_CONNTRACK,
};
static struct nf_hook_ops ipv6_conntrack_local_out_ops = {
},
{
.hook = ipv6_conntrack_local,
.owner = THIS_MODULE,
.pf = PF_INET6,
.hooknum = NF_IP6_LOCAL_OUT,
.priority = NF_IP6_PRI_CONNTRACK,
};
static struct nf_hook_ops ipv6_conntrack_defrag_local_out_ops = {
},
{
.hook = ipv6_defrag,
.owner = THIS_MODULE,
.pf = PF_INET6,
.hooknum = NF_IP6_LOCAL_OUT,
.priority = NF_IP6_PRI_CONNTRACK_DEFRAG,
};
/* Refragmenter; last chance. */
static struct nf_hook_ops ipv6_conntrack_out_ops = {
},
{
.hook = ipv6_confirm,
.owner = THIS_MODULE,
.pf = PF_INET6,
.hooknum = NF_IP6_POST_ROUTING,
.priority = NF_IP6_PRI_LAST,
};
static struct nf_hook_ops ipv6_conntrack_local_in_ops = {
},
{
.hook = ipv6_confirm,
.owner = THIS_MODULE,
.pf = PF_INET6,
.hooknum = NF_IP6_LOCAL_IN,
.priority = NF_IP6_PRI_LAST-1,
},
};
#ifdef CONFIG_SYSCTL
@ -470,16 +464,21 @@ extern struct nf_conntrack_protocol nf_conntrack_protocol_udp6;
extern struct nf_conntrack_protocol nf_conntrack_protocol_icmpv6;
extern int nf_ct_frag6_init(void);
extern void nf_ct_frag6_cleanup(void);
static int init_or_cleanup(int init)
MODULE_ALIAS("nf_conntrack-" __stringify(AF_INET6));
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Yasuyuki KOZAKAI @USAGI <yasuyuki.kozakai@toshiba.co.jp>");
static int __init nf_conntrack_l3proto_ipv6_init(void)
{
int ret = 0;
if (!init) goto cleanup;
need_conntrack();
ret = nf_ct_frag6_init();
if (ret < 0) {
printk("nf_conntrack_ipv6: can't initialize frag6.\n");
goto cleanup_nothing;
return ret;
}
ret = nf_conntrack_protocol_register(&nf_conntrack_protocol_tcp6);
if (ret < 0) {
@ -505,71 +504,27 @@ static int init_or_cleanup(int init)
goto cleanup_icmpv6;
}
ret = nf_register_hook(&ipv6_conntrack_defrag_ops);
ret = nf_register_hooks(ipv6_conntrack_ops,
ARRAY_SIZE(ipv6_conntrack_ops));
if (ret < 0) {
printk("nf_conntrack_ipv6: can't register pre-routing defrag "
"hook.\n");
goto cleanup_ipv6;
}
ret = nf_register_hook(&ipv6_conntrack_defrag_local_out_ops);
if (ret < 0) {
printk("nf_conntrack_ipv6: can't register local_out defrag "
"hook.\n");
goto cleanup_defragops;
}
ret = nf_register_hook(&ipv6_conntrack_in_ops);
if (ret < 0) {
printk("nf_conntrack_ipv6: can't register pre-routing hook.\n");
goto cleanup_defraglocalops;
}
ret = nf_register_hook(&ipv6_conntrack_local_out_ops);
if (ret < 0) {
printk("nf_conntrack_ipv6: can't register local out hook.\n");
goto cleanup_inops;
}
ret = nf_register_hook(&ipv6_conntrack_out_ops);
if (ret < 0) {
printk("nf_conntrack_ipv6: can't register post-routing hook.\n");
goto cleanup_inandlocalops;
}
ret = nf_register_hook(&ipv6_conntrack_local_in_ops);
if (ret < 0) {
printk("nf_conntrack_ipv6: can't register local in hook.\n");
goto cleanup_inoutandlocalops;
}
#ifdef CONFIG_SYSCTL
nf_ct_ipv6_sysctl_header = register_sysctl_table(nf_ct_net_table, 0);
if (nf_ct_ipv6_sysctl_header == NULL) {
printk("nf_conntrack: can't register to sysctl.\n");
ret = -ENOMEM;
goto cleanup_localinops;
goto cleanup_hooks;
}
#endif
return ret;
cleanup:
synchronize_net();
#ifdef CONFIG_SYSCTL
unregister_sysctl_table(nf_ct_ipv6_sysctl_header);
cleanup_localinops:
cleanup_hooks:
nf_unregister_hooks(ipv6_conntrack_ops, ARRAY_SIZE(ipv6_conntrack_ops));
#endif
nf_unregister_hook(&ipv6_conntrack_local_in_ops);
cleanup_inoutandlocalops:
nf_unregister_hook(&ipv6_conntrack_out_ops);
cleanup_inandlocalops:
nf_unregister_hook(&ipv6_conntrack_local_out_ops);
cleanup_inops:
nf_unregister_hook(&ipv6_conntrack_in_ops);
cleanup_defraglocalops:
nf_unregister_hook(&ipv6_conntrack_defrag_local_out_ops);
cleanup_defragops:
nf_unregister_hook(&ipv6_conntrack_defrag_ops);
cleanup_ipv6:
nf_conntrack_l3proto_unregister(&nf_conntrack_l3proto_ipv6);
cleanup_icmpv6:
@ -580,23 +535,21 @@ static int init_or_cleanup(int init)
nf_conntrack_protocol_unregister(&nf_conntrack_protocol_tcp6);
cleanup_frag6:
nf_ct_frag6_cleanup();
cleanup_nothing:
return ret;
}
MODULE_ALIAS("nf_conntrack-" __stringify(AF_INET6));
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Yasuyuki KOZAKAI @USAGI <yasuyuki.kozakai@toshiba.co.jp>");
static int __init nf_conntrack_l3proto_ipv6_init(void)
{
need_conntrack();
return init_or_cleanup(1);
}
static void __exit nf_conntrack_l3proto_ipv6_fini(void)
{
init_or_cleanup(0);
synchronize_net();
#ifdef CONFIG_SYSCTL
unregister_sysctl_table(nf_ct_ipv6_sysctl_header);
#endif
nf_unregister_hooks(ipv6_conntrack_ops, ARRAY_SIZE(ipv6_conntrack_ops));
nf_conntrack_l3proto_unregister(&nf_conntrack_l3proto_ipv6);
nf_conntrack_protocol_unregister(&nf_conntrack_protocol_icmpv6);
nf_conntrack_protocol_unregister(&nf_conntrack_protocol_udp6);
nf_conntrack_protocol_unregister(&nf_conntrack_protocol_tcp6);
nf_ct_frag6_cleanup();
}
module_init(nf_conntrack_l3proto_ipv6_init);

View File

@ -233,21 +233,13 @@ icmpv6_error(struct sk_buff *skb, unsigned int dataoff,
return -NF_ACCEPT;
}
if (hooknum != NF_IP6_PRE_ROUTING)
goto skipped;
/* Ignore it if the checksum's bogus. */
if (csum_ipv6_magic(&skb->nh.ipv6h->saddr, &skb->nh.ipv6h->daddr,
skb->len - dataoff, IPPROTO_ICMPV6,
skb_checksum(skb, dataoff,
skb->len - dataoff, 0))) {
if (hooknum == NF_IP6_PRE_ROUTING &&
nf_ip6_checksum(skb, hooknum, dataoff, IPPROTO_ICMPV6)) {
nf_log_packet(PF_INET6, 0, skb, NULL, NULL, NULL,
"nf_ct_icmpv6: ICMPv6 checksum failed\n");
return -NF_ACCEPT;
}
skipped:
/* is not error message ? */
if (icmp6h->icmp6_type >= 128)
return NF_ACCEPT;

View File

@ -397,7 +397,7 @@ static int ipip6_rcv(struct sk_buff *skb)
return 0;
}
icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PROT_UNREACH, 0);
icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0);
kfree_skb(skb);
read_unlock(&ipip6_lock);
out:

View File

@ -19,11 +19,13 @@
* YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
*/
#include <linux/icmpv6.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/mutex.h>
#include <linux/netdevice.h>
#include <linux/skbuff.h>
#include <net/ipv6.h>
#include <net/protocol.h>
#include <net/xfrm.h>
@ -87,10 +89,16 @@ static int tunnel6_rcv(struct sk_buff **pskb)
struct sk_buff *skb = *pskb;
struct xfrm6_tunnel *handler;
if (!pskb_may_pull(skb, sizeof(struct ipv6hdr)))
goto drop;
for (handler = tunnel6_handlers; handler; handler = handler->next)
if (!handler->handler(skb))
return 0;
icmpv6_send(skb, ICMPV6_DEST_UNREACH, ICMPV6_PORT_UNREACH, 0, skb->dev);
drop:
kfree_skb(skb);
return 0;
}

View File

@ -27,6 +27,29 @@
#include "nf_internals.h"
static DEFINE_SPINLOCK(afinfo_lock);
struct nf_afinfo *nf_afinfo[NPROTO];
EXPORT_SYMBOL(nf_afinfo);
int nf_register_afinfo(struct nf_afinfo *afinfo)
{
spin_lock(&afinfo_lock);
rcu_assign_pointer(nf_afinfo[afinfo->family], afinfo);
spin_unlock(&afinfo_lock);
return 0;
}
EXPORT_SYMBOL_GPL(nf_register_afinfo);
void nf_unregister_afinfo(struct nf_afinfo *afinfo)
{
spin_lock(&afinfo_lock);
rcu_assign_pointer(nf_afinfo[afinfo->family], NULL);
spin_unlock(&afinfo_lock);
synchronize_rcu();
}
EXPORT_SYMBOL_GPL(nf_unregister_afinfo);
/* In this code, we can be waiting indefinitely for userspace to
* service a packet if a hook returns NF_QUEUE. We could keep a count
* of skbuffs queued for userspace, and not deregister a hook unless
@ -63,6 +86,34 @@ void nf_unregister_hook(struct nf_hook_ops *reg)
}
EXPORT_SYMBOL(nf_unregister_hook);
int nf_register_hooks(struct nf_hook_ops *reg, unsigned int n)
{
unsigned int i;
int err = 0;
for (i = 0; i < n; i++) {
err = nf_register_hook(&reg[i]);
if (err)
goto err;
}
return err;
err:
if (i > 0)
nf_unregister_hooks(reg, i);
return err;
}
EXPORT_SYMBOL(nf_register_hooks);
void nf_unregister_hooks(struct nf_hook_ops *reg, unsigned int n)
{
unsigned int i;
for (i = 0; i < n; i++)
nf_unregister_hook(&reg[i]);
}
EXPORT_SYMBOL(nf_unregister_hooks);
unsigned int nf_iterate(struct list_head *head,
struct sk_buff **skb,
int hook,

View File

@ -799,8 +799,7 @@ static int tcp_error(struct sk_buff *skb,
unsigned int dataoff,
enum ip_conntrack_info *ctinfo,
int pf,
unsigned int hooknum,
int(*csum)(const struct sk_buff *,unsigned int))
unsigned int hooknum)
{
struct tcphdr _tcph, *th;
unsigned int tcplen = skb->len - dataoff;
@ -830,9 +829,8 @@ static int tcp_error(struct sk_buff *skb,
*/
/* FIXME: Source route IP option packets --RR */
if (((pf == PF_INET && hooknum == NF_IP_PRE_ROUTING) ||
(pf == PF_INET6 && hooknum == NF_IP6_PRE_ROUTING))
&& skb->ip_summed != CHECKSUM_UNNECESSARY
&& csum(skb, dataoff)) {
(pf == PF_INET6 && hooknum == NF_IP6_PRE_ROUTING)) &&
nf_checksum(skb, hooknum, dataoff, IPPROTO_TCP, pf)) {
if (LOG_INVALID(IPPROTO_TCP))
nf_log_packet(pf, 0, skb, NULL, NULL, NULL,
"nf_ct_tcp: bad TCP checksum ");
@ -851,44 +849,6 @@ static int tcp_error(struct sk_buff *skb,
return NF_ACCEPT;
}
static int csum4(const struct sk_buff *skb, unsigned int dataoff)
{
return csum_tcpudp_magic(skb->nh.iph->saddr, skb->nh.iph->daddr,
skb->len - dataoff, IPPROTO_TCP,
skb->ip_summed == CHECKSUM_HW ? skb->csum
: skb_checksum(skb, dataoff,
skb->len - dataoff, 0));
}
static int csum6(const struct sk_buff *skb, unsigned int dataoff)
{
return csum_ipv6_magic(&skb->nh.ipv6h->saddr, &skb->nh.ipv6h->daddr,
skb->len - dataoff, IPPROTO_TCP,
skb->ip_summed == CHECKSUM_HW
? csum_sub(skb->csum,
skb_checksum(skb, 0, dataoff, 0))
: skb_checksum(skb, dataoff, skb->len - dataoff,
0));
}
static int tcp_error4(struct sk_buff *skb,
unsigned int dataoff,
enum ip_conntrack_info *ctinfo,
int pf,
unsigned int hooknum)
{
return tcp_error(skb, dataoff, ctinfo, pf, hooknum, csum4);
}
static int tcp_error6(struct sk_buff *skb,
unsigned int dataoff,
enum ip_conntrack_info *ctinfo,
int pf,
unsigned int hooknum)
{
return tcp_error(skb, dataoff, ctinfo, pf, hooknum, csum6);
}
/* Returns verdict for packet, or -1 for invalid. */
static int tcp_packet(struct nf_conn *conntrack,
const struct sk_buff *skb,
@ -1218,7 +1178,7 @@ struct nf_conntrack_protocol nf_conntrack_protocol_tcp4 =
.print_conntrack = tcp_print_conntrack,
.packet = tcp_packet,
.new = tcp_new,
.error = tcp_error4,
.error = tcp_error,
#if defined(CONFIG_NF_CT_NETLINK) || \
defined(CONFIG_NF_CT_NETLINK_MODULE)
.to_nfattr = tcp_to_nfattr,
@ -1239,7 +1199,7 @@ struct nf_conntrack_protocol nf_conntrack_protocol_tcp6 =
.print_conntrack = tcp_print_conntrack,
.packet = tcp_packet,
.new = tcp_new,
.error = tcp_error6,
.error = tcp_error,
#if defined(CONFIG_NF_CT_NETLINK) || \
defined(CONFIG_NF_CT_NETLINK_MODULE)
.to_nfattr = tcp_to_nfattr,

View File

@ -103,8 +103,7 @@ static int udp_new(struct nf_conn *conntrack, const struct sk_buff *skb,
static int udp_error(struct sk_buff *skb, unsigned int dataoff,
enum ip_conntrack_info *ctinfo,
int pf,
unsigned int hooknum,
int (*csum)(const struct sk_buff *, unsigned int))
unsigned int hooknum)
{
unsigned int udplen = skb->len - dataoff;
struct udphdr _hdr, *hdr;
@ -136,9 +135,8 @@ static int udp_error(struct sk_buff *skb, unsigned int dataoff,
* and moreover root might send raw packets.
* FIXME: Source route IP option packets --RR */
if (((pf == PF_INET && hooknum == NF_IP_PRE_ROUTING) ||
(pf == PF_INET6 && hooknum == NF_IP6_PRE_ROUTING))
&& skb->ip_summed != CHECKSUM_UNNECESSARY
&& csum(skb, dataoff)) {
(pf == PF_INET6 && hooknum == NF_IP6_PRE_ROUTING)) &&
nf_checksum(skb, hooknum, dataoff, IPPROTO_UDP, pf)) {
if (LOG_INVALID(IPPROTO_UDP))
nf_log_packet(pf, 0, skb, NULL, NULL, NULL,
"nf_ct_udp: bad UDP checksum ");
@ -148,44 +146,6 @@ static int udp_error(struct sk_buff *skb, unsigned int dataoff,
return NF_ACCEPT;
}
static int csum4(const struct sk_buff *skb, unsigned int dataoff)
{
return csum_tcpudp_magic(skb->nh.iph->saddr, skb->nh.iph->daddr,
skb->len - dataoff, IPPROTO_UDP,
skb->ip_summed == CHECKSUM_HW ? skb->csum
: skb_checksum(skb, dataoff,
skb->len - dataoff, 0));
}
static int csum6(const struct sk_buff *skb, unsigned int dataoff)
{
return csum_ipv6_magic(&skb->nh.ipv6h->saddr, &skb->nh.ipv6h->daddr,
skb->len - dataoff, IPPROTO_UDP,
skb->ip_summed == CHECKSUM_HW
? csum_sub(skb->csum,
skb_checksum(skb, 0, dataoff, 0))
: skb_checksum(skb, dataoff, skb->len - dataoff,
0));
}
static int udp_error4(struct sk_buff *skb,
unsigned int dataoff,
enum ip_conntrack_info *ctinfo,
int pf,
unsigned int hooknum)
{
return udp_error(skb, dataoff, ctinfo, pf, hooknum, csum4);
}
static int udp_error6(struct sk_buff *skb,
unsigned int dataoff,
enum ip_conntrack_info *ctinfo,
int pf,
unsigned int hooknum)
{
return udp_error(skb, dataoff, ctinfo, pf, hooknum, csum6);
}
struct nf_conntrack_protocol nf_conntrack_protocol_udp4 =
{
.l3proto = PF_INET,
@ -197,7 +157,7 @@ struct nf_conntrack_protocol nf_conntrack_protocol_udp4 =
.print_conntrack = udp_print_conntrack,
.packet = udp_packet,
.new = udp_new,
.error = udp_error4,
.error = udp_error,
#if defined(CONFIG_NF_CT_NETLINK) || \
defined(CONFIG_NF_CT_NETLINK_MODULE)
.tuple_to_nfattr = nf_ct_port_tuple_to_nfattr,
@ -216,7 +176,7 @@ struct nf_conntrack_protocol nf_conntrack_protocol_udp6 =
.print_conntrack = udp_print_conntrack,
.packet = udp_packet,
.new = udp_new,
.error = udp_error6,
.error = udp_error,
#if defined(CONFIG_NF_CT_NETLINK) || \
defined(CONFIG_NF_CT_NETLINK_MODULE)
.tuple_to_nfattr = nf_ct_port_tuple_to_nfattr,

View File

@ -649,63 +649,6 @@ static ctl_table nf_ct_net_table[] = {
EXPORT_SYMBOL(nf_ct_log_invalid);
#endif /* CONFIG_SYSCTL */
static int init_or_cleanup(int init)
{
#ifdef CONFIG_PROC_FS
struct proc_dir_entry *proc, *proc_exp, *proc_stat;
#endif
int ret = 0;
if (!init) goto cleanup;
ret = nf_conntrack_init();
if (ret < 0)
goto cleanup_nothing;
#ifdef CONFIG_PROC_FS
proc = proc_net_fops_create("nf_conntrack", 0440, &ct_file_ops);
if (!proc) goto cleanup_init;
proc_exp = proc_net_fops_create("nf_conntrack_expect", 0440,
&exp_file_ops);
if (!proc_exp) goto cleanup_proc;
proc_stat = create_proc_entry("nf_conntrack", S_IRUGO, proc_net_stat);
if (!proc_stat)
goto cleanup_proc_exp;
proc_stat->proc_fops = &ct_cpu_seq_fops;
proc_stat->owner = THIS_MODULE;
#endif
#ifdef CONFIG_SYSCTL
nf_ct_sysctl_header = register_sysctl_table(nf_ct_net_table, 0);
if (nf_ct_sysctl_header == NULL) {
printk("nf_conntrack: can't register to sysctl.\n");
ret = -ENOMEM;
goto cleanup_proc_stat;
}
#endif
return ret;
cleanup:
#ifdef CONFIG_SYSCTL
unregister_sysctl_table(nf_ct_sysctl_header);
cleanup_proc_stat:
#endif
#ifdef CONFIG_PROC_FS
remove_proc_entry("nf_conntrack", proc_net_stat);
cleanup_proc_exp:
proc_net_remove("nf_conntrack_expect");
cleanup_proc:
proc_net_remove("nf_conntrack");
cleanup_init:
#endif /* CNFIG_PROC_FS */
nf_conntrack_cleanup();
cleanup_nothing:
return ret;
}
int nf_conntrack_l3proto_register(struct nf_conntrack_l3proto *proto)
{
int ret = 0;
@ -808,12 +751,66 @@ void nf_conntrack_protocol_unregister(struct nf_conntrack_protocol *proto)
static int __init nf_conntrack_standalone_init(void)
{
return init_or_cleanup(1);
#ifdef CONFIG_PROC_FS
struct proc_dir_entry *proc, *proc_exp, *proc_stat;
#endif
int ret = 0;
ret = nf_conntrack_init();
if (ret < 0)
return ret;
#ifdef CONFIG_PROC_FS
proc = proc_net_fops_create("nf_conntrack", 0440, &ct_file_ops);
if (!proc) goto cleanup_init;
proc_exp = proc_net_fops_create("nf_conntrack_expect", 0440,
&exp_file_ops);
if (!proc_exp) goto cleanup_proc;
proc_stat = create_proc_entry("nf_conntrack", S_IRUGO, proc_net_stat);
if (!proc_stat)
goto cleanup_proc_exp;
proc_stat->proc_fops = &ct_cpu_seq_fops;
proc_stat->owner = THIS_MODULE;
#endif
#ifdef CONFIG_SYSCTL
nf_ct_sysctl_header = register_sysctl_table(nf_ct_net_table, 0);
if (nf_ct_sysctl_header == NULL) {
printk("nf_conntrack: can't register to sysctl.\n");
ret = -ENOMEM;
goto cleanup_proc_stat;
}
#endif
return ret;
#ifdef CONFIG_SYSCTL
cleanup_proc_stat:
#endif
#ifdef CONFIG_PROC_FS
remove_proc_entry("nf_conntrack", proc_net_stat);
cleanup_proc_exp:
proc_net_remove("nf_conntrack_expect");
cleanup_proc:
proc_net_remove("nf_conntrack");
cleanup_init:
#endif /* CNFIG_PROC_FS */
nf_conntrack_cleanup();
return ret;
}
static void __exit nf_conntrack_standalone_fini(void)
{
init_or_cleanup(0);
#ifdef CONFIG_SYSCTL
unregister_sysctl_table(nf_ct_sysctl_header);
#endif
#ifdef CONFIG_PROC_FS
remove_proc_entry("nf_conntrack", proc_net_stat);
proc_net_remove("nf_conntrack_expect");
proc_net_remove("nf_conntrack");
#endif /* CNFIG_PROC_FS */
nf_conntrack_cleanup();
}
module_init(nf_conntrack_standalone_init);

View File

@ -17,7 +17,6 @@
* for queueing and must reinject all packets it receives, no matter what.
*/
static struct nf_queue_handler *queue_handler[NPROTO];
static struct nf_queue_rerouter *queue_rerouter[NPROTO];
static DEFINE_RWLOCK(queue_handler_lock);
@ -59,32 +58,6 @@ int nf_unregister_queue_handler(int pf)
}
EXPORT_SYMBOL(nf_unregister_queue_handler);
int nf_register_queue_rerouter(int pf, struct nf_queue_rerouter *rer)
{
if (pf >= NPROTO)
return -EINVAL;
write_lock_bh(&queue_handler_lock);
rcu_assign_pointer(queue_rerouter[pf], rer);
write_unlock_bh(&queue_handler_lock);
return 0;
}
EXPORT_SYMBOL_GPL(nf_register_queue_rerouter);
int nf_unregister_queue_rerouter(int pf)
{
if (pf >= NPROTO)
return -EINVAL;
write_lock_bh(&queue_handler_lock);
rcu_assign_pointer(queue_rerouter[pf], NULL);
write_unlock_bh(&queue_handler_lock);
synchronize_rcu();
return 0;
}
EXPORT_SYMBOL_GPL(nf_unregister_queue_rerouter);
void nf_unregister_queue_handlers(struct nf_queue_handler *qh)
{
int pf;
@ -116,7 +89,7 @@ int nf_queue(struct sk_buff **skb,
struct net_device *physindev = NULL;
struct net_device *physoutdev = NULL;
#endif
struct nf_queue_rerouter *rerouter;
struct nf_afinfo *afinfo;
/* QUEUE == DROP if noone is waiting, to be safe. */
read_lock(&queue_handler_lock);
@ -126,7 +99,14 @@ int nf_queue(struct sk_buff **skb,
return 1;
}
info = kmalloc(sizeof(*info)+queue_rerouter[pf]->rer_size, GFP_ATOMIC);
afinfo = nf_get_afinfo(pf);
if (!afinfo) {
read_unlock(&queue_handler_lock);
kfree_skb(*skb);
return 1;
}
info = kmalloc(sizeof(*info) + afinfo->route_key_size, GFP_ATOMIC);
if (!info) {
if (net_ratelimit())
printk(KERN_ERR "OOM queueing packet %p\n",
@ -158,10 +138,7 @@ int nf_queue(struct sk_buff **skb,
if (physoutdev) dev_hold(physoutdev);
}
#endif
rerouter = rcu_dereference(queue_rerouter[pf]);
if (rerouter)
rerouter->save(*skb, info);
afinfo->saveroute(*skb, info);
status = queue_handler[pf]->outfn(*skb, info, queuenum,
queue_handler[pf]->data);
@ -190,7 +167,7 @@ void nf_reinject(struct sk_buff *skb, struct nf_info *info,
{
struct list_head *elem = &info->elem->list;
struct list_head *i;
struct nf_queue_rerouter *rerouter;
struct nf_afinfo *afinfo;
rcu_read_lock();
@ -228,8 +205,8 @@ void nf_reinject(struct sk_buff *skb, struct nf_info *info,
}
if (verdict == NF_ACCEPT) {
rerouter = rcu_dereference(queue_rerouter[info->pf]);
if (rerouter && rerouter->reroute(&skb, info) < 0)
afinfo = nf_get_afinfo(info->pf);
if (!afinfo || afinfo->reroute(&skb, info) < 0)
verdict = NF_DROP;
}

View File

@ -1033,17 +1033,13 @@ static struct file_operations nful_file_ops = {
#endif /* PROC_FS */
static int
init_or_cleanup(int init)
static int __init nfnetlink_log_init(void)
{
int i, status = -ENOMEM;
#ifdef CONFIG_PROC_FS
struct proc_dir_entry *proc_nful;
#endif
if (!init)
goto cleanup;
for (i = 0; i < INSTANCE_BUCKETS; i++)
INIT_HLIST_HEAD(&instance_table[i]);
@ -1066,30 +1062,25 @@ init_or_cleanup(int init)
goto cleanup_subsys;
proc_nful->proc_fops = &nful_file_ops;
#endif
return status;
cleanup:
nf_log_unregister_logger(&nfulnl_logger);
#ifdef CONFIG_PROC_FS
remove_proc_entry("nfnetlink_log", proc_net_netfilter);
cleanup_subsys:
#endif
nfnetlink_subsys_unregister(&nfulnl_subsys);
#endif
cleanup_netlink_notifier:
netlink_unregister_notifier(&nfulnl_rtnl_notifier);
return status;
}
static int __init nfnetlink_log_init(void)
{
return init_or_cleanup(1);
}
static void __exit nfnetlink_log_fini(void)
{
init_or_cleanup(0);
nf_log_unregister_logger(&nfulnl_logger);
#ifdef CONFIG_PROC_FS
remove_proc_entry("nfnetlink_log", proc_net_netfilter);
#endif
nfnetlink_subsys_unregister(&nfulnl_subsys);
netlink_unregister_notifier(&nfulnl_rtnl_notifier);
}
MODULE_DESCRIPTION("netfilter userspace logging");

View File

@ -1071,17 +1071,13 @@ static struct file_operations nfqnl_file_ops = {
#endif /* PROC_FS */
static int
init_or_cleanup(int init)
static int __init nfnetlink_queue_init(void)
{
int i, status = -ENOMEM;
#ifdef CONFIG_PROC_FS
struct proc_dir_entry *proc_nfqueue;
#endif
if (!init)
goto cleanup;
for (i = 0; i < INSTANCE_BUCKETS; i++)
INIT_HLIST_HEAD(&instance_table[i]);
@ -1101,31 +1097,26 @@ init_or_cleanup(int init)
#endif
register_netdevice_notifier(&nfqnl_dev_notifier);
return status;
cleanup:
nf_unregister_queue_handlers(&nfqh);
unregister_netdevice_notifier(&nfqnl_dev_notifier);
#ifdef CONFIG_PROC_FS
remove_proc_entry("nfnetlink_queue", proc_net_netfilter);
cleanup_subsys:
#endif
nfnetlink_subsys_unregister(&nfqnl_subsys);
#endif
cleanup_netlink_notifier:
netlink_unregister_notifier(&nfqnl_rtnl_notifier);
return status;
}
static int __init nfnetlink_queue_init(void)
{
return init_or_cleanup(1);
}
static void __exit nfnetlink_queue_fini(void)
{
init_or_cleanup(0);
nf_unregister_queue_handlers(&nfqh);
unregister_netdevice_notifier(&nfqnl_dev_notifier);
#ifdef CONFIG_PROC_FS
remove_proc_entry("nfnetlink_queue", proc_net_netfilter);
#endif
nfnetlink_subsys_unregister(&nfqnl_subsys);
netlink_unregister_notifier(&nfqnl_rtnl_notifier);
}
MODULE_DESCRIPTION("netfilter packet queue handler");

View File

@ -66,7 +66,7 @@ static __inline__ struct tcf_police * tcf_police_lookup(u32 index)
}
#ifdef CONFIG_NET_CLS_ACT
static int tcf_generic_walker(struct sk_buff *skb, struct netlink_callback *cb,
static int tcf_act_police_walker(struct sk_buff *skb, struct netlink_callback *cb,
int type, struct tc_action *a)
{
struct tcf_police *p;
@ -113,7 +113,7 @@ static int tcf_generic_walker(struct sk_buff *skb, struct netlink_callback *cb,
}
static inline int
tcf_hash_search(struct tc_action *a, u32 index)
tcf_act_police_hash_search(struct tc_action *a, u32 index)
{
struct tcf_police *p = tcf_police_lookup(index);
@ -387,9 +387,9 @@ static struct tc_action_ops act_police_ops = {
.act = tcf_act_police,
.dump = tcf_act_police_dump,
.cleanup = tcf_act_police_cleanup,
.lookup = tcf_hash_search,
.lookup = tcf_act_police_hash_search,
.init = tcf_act_police_locate,
.walk = tcf_generic_walker
.walk = tcf_act_police_walker
};
static int __init