mirror of https://gitee.com/openkylin/linux.git
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:
commit
460fbf82c0
|
@ -1584,7 +1584,6 @@ u32 secure_ipv6_port_ephemeral(const __u32 *saddr, const __u32 *daddr, __u16 dpo
|
||||||
|
|
||||||
return twothirdsMD4Transform(daddr, hash);
|
return twothirdsMD4Transform(daddr, hash);
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(secure_ipv6_port_ephemeral);
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(CONFIG_IP_DCCP) || defined(CONFIG_IP_DCCP_MODULE)
|
#if defined(CONFIG_IP_DCCP) || defined(CONFIG_IP_DCCP_MODULE)
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*****************************************************************************
|
/*****************************************************************************
|
||||||
*
|
*
|
||||||
* Filename: irda-usb.c
|
* Filename: irda-usb.c
|
||||||
* Version: 0.9b
|
* Version: 0.10
|
||||||
* Description: IrDA-USB Driver
|
* Description: IrDA-USB Driver
|
||||||
* Status: Experimental
|
* Status: Experimental
|
||||||
* Author: Dag Brattli <dag@brattli.net>
|
* Author: Dag Brattli <dag@brattli.net>
|
||||||
|
@ -9,6 +9,9 @@
|
||||||
* Copyright (C) 2000, Roman Weissgaerber <weissg@vienna.at>
|
* Copyright (C) 2000, Roman Weissgaerber <weissg@vienna.at>
|
||||||
* Copyright (C) 2001, Dag Brattli <dag@brattli.net>
|
* Copyright (C) 2001, Dag Brattli <dag@brattli.net>
|
||||||
* Copyright (C) 2001, Jean Tourrilhes <jt@hpl.hp.com>
|
* 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
|
* 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
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
@ -61,6 +64,7 @@
|
||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
#include <linux/rtnetlink.h>
|
#include <linux/rtnetlink.h>
|
||||||
#include <linux/usb.h>
|
#include <linux/usb.h>
|
||||||
|
#include <linux/firmware.h>
|
||||||
|
|
||||||
#include "irda-usb.h"
|
#include "irda-usb.h"
|
||||||
|
|
||||||
|
@ -78,8 +82,12 @@ static struct usb_device_id dongles[] = {
|
||||||
{ USB_DEVICE(0x50f, 0x180), .driver_info = IUC_SPEED_BUG | IUC_NO_WINDOW },
|
{ USB_DEVICE(0x50f, 0x180), .driver_info = IUC_SPEED_BUG | IUC_NO_WINDOW },
|
||||||
/* Extended Systems, Inc., XTNDAccess IrDA USB (ESI-9685) */
|
/* Extended Systems, Inc., XTNDAccess IrDA USB (ESI-9685) */
|
||||||
{ USB_DEVICE(0x8e9, 0x100), .driver_info = IUC_SPEED_BUG | IUC_NO_WINDOW },
|
{ 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 |
|
{ .match_flags = USB_DEVICE_ID_MATCH_INT_CLASS |
|
||||||
USB_DEVICE_ID_MATCH_INT_SUBCLASS,
|
USB_DEVICE_ID_MATCH_INT_SUBCLASS,
|
||||||
.bInterfaceClass = USB_CLASS_APP_SPEC,
|
.bInterfaceClass = USB_CLASS_APP_SPEC,
|
||||||
.bInterfaceSubClass = USB_CLASS_IRDA,
|
.bInterfaceSubClass = USB_CLASS_IRDA,
|
||||||
.driver_info = IUC_DEFAULT, },
|
.driver_info = IUC_DEFAULT, },
|
||||||
|
@ -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 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_disconnect(struct usb_interface *intf);
|
||||||
static void irda_usb_change_speed_xbofs(struct irda_usb_cb *self);
|
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,
|
__u8 *header,
|
||||||
int force)
|
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) {
|
if (self->new_speed != -1) {
|
||||||
/* Hum... Ugly hack :-(
|
/* Hum... Ugly hack :-(
|
||||||
* Some device are not compliant with the spec and change
|
* Some device are not compliant with the spec and change
|
||||||
|
@ -191,7 +217,11 @@ static void irda_usb_build_header(struct irda_usb_cb *self,
|
||||||
*header = SPEED_4000000;
|
*header = SPEED_4000000;
|
||||||
self->new_xbofs = 0;
|
self->new_xbofs = 0;
|
||||||
break;
|
break;
|
||||||
}
|
case 16000000:
|
||||||
|
*header = SPEED_16000000;
|
||||||
|
self->new_xbofs = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
} else
|
} else
|
||||||
/* No change */
|
/* No change */
|
||||||
*header = 0;
|
*header = 0;
|
||||||
|
@ -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
|
* 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 */
|
/* Set the new speed and xbofs in this fake frame */
|
||||||
irda_usb_build_header(self, frame, 1);
|
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 */
|
/* Submit the 0 length IrDA frame to trigger new speed settings */
|
||||||
usb_fill_bulk_urb(urb, self->usbdev,
|
usb_fill_bulk_urb(urb, self->usbdev,
|
||||||
usb_sndbulkpipe(self->usbdev, self->bulk_out_ep),
|
usb_sndbulkpipe(self->usbdev, self->bulk_out_ep),
|
||||||
frame, IRDA_USB_SPEED_MTU,
|
frame, IRDA_USB_SPEED_MTU,
|
||||||
speed_bulk_callback, self);
|
speed_bulk_callback, self);
|
||||||
urb->transfer_buffer_length = USB_IRDA_HEADER;
|
urb->transfer_buffer_length = self->header_length;
|
||||||
urb->transfer_flags = 0;
|
urb->transfer_flags = 0;
|
||||||
|
|
||||||
/* Irq disabled -> GFP_ATOMIC */
|
/* 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().
|
* allocation will be done lower in skb_push().
|
||||||
* Also, we don't use directly skb_cow(), because it require
|
* Also, we don't use directly skb_cow(), because it require
|
||||||
* headroom >= 16, which force unnecessary copies - Jean II */
|
* 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__);
|
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__);
|
IRDA_WARNING("%s(), failed skb_cow() !!!\n", __FUNCTION__);
|
||||||
goto drop;
|
goto drop;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Change setting for next frame */
|
/* 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 */
|
/* FIXME: Make macro out of this one */
|
||||||
((struct irda_skb_cb *)skb->cb)->context = self;
|
((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 */
|
/* 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__);
|
IRDA_WARNING("%s(), empty frame!\n", __FUNCTION__);
|
||||||
goto done;
|
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);
|
docopy = (urb->actual_length < IRDA_RX_COPY_THRESHOLD);
|
||||||
|
|
||||||
/* Allocate a new skb */
|
/* Allocate a new skb */
|
||||||
newskb = dev_alloc_skb(docopy ? urb->actual_length : IRDA_SKB_MAX_MTU);
|
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) {
|
if (!newskb) {
|
||||||
self->stats.rx_dropped++;
|
self->stats.rx_dropped++;
|
||||||
/* We could deliver the current skb, but this would stall
|
/* 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 */
|
/* Set proper length on skb & remove USB-IrDA header */
|
||||||
skb_put(dataskb, urb->actual_length);
|
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 */
|
/* Ask the networking layer to queue the packet for the IrDA stack */
|
||||||
dataskb->dev = self->netdev;
|
dataskb->dev = self->netdev;
|
||||||
|
@ -937,6 +1022,191 @@ static int irda_usb_is_receiving(struct irda_usb_cb *self)
|
||||||
return 0; /* For now */
|
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 **********************/
|
/********************** IRDA DEVICE CALLBACKS **********************/
|
||||||
/*
|
/*
|
||||||
* Main calls from the IrDA/Network subsystem.
|
* Main calls from the IrDA/Network subsystem.
|
||||||
|
@ -972,6 +1242,11 @@ static int irda_usb_net_open(struct net_device *netdev)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(self->needspatch) {
|
||||||
|
IRDA_WARNING("%s(), device needs patch\n", __FUNCTION__) ;
|
||||||
|
return -EIO ;
|
||||||
|
}
|
||||||
|
|
||||||
/* Initialise default speed and xbofs value
|
/* Initialise default speed and xbofs value
|
||||||
* (IrLAP will change that soon) */
|
* (IrLAP will change that soon) */
|
||||||
self->speed = -1;
|
self->speed = -1;
|
||||||
|
@ -1050,7 +1325,7 @@ static int irda_usb_net_close(struct net_device *netdev)
|
||||||
del_timer(&self->rx_defer_timer);
|
del_timer(&self->rx_defer_timer);
|
||||||
|
|
||||||
/* Deallocate all the Rx path buffers (URBs and skb) */
|
/* 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 urb *urb = self->rx_urb[i];
|
||||||
struct sk_buff *skb = (struct sk_buff *) urb->context;
|
struct sk_buff *skb = (struct sk_buff *) urb->context;
|
||||||
/* Cancel the receive command */
|
/* Cancel the receive command */
|
||||||
|
@ -1426,8 +1701,22 @@ static int irda_usb_probe(struct usb_interface *intf,
|
||||||
spin_lock_init(&self->lock);
|
spin_lock_init(&self->lock);
|
||||||
init_timer(&self->rx_defer_timer);
|
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 */
|
/* 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);
|
self->rx_urb[i] = usb_alloc_urb(0, GFP_KERNEL);
|
||||||
if (!self->rx_urb[i]) {
|
if (!self->rx_urb[i]) {
|
||||||
goto err_out_1;
|
goto err_out_1;
|
||||||
|
@ -1479,17 +1768,28 @@ static int irda_usb_probe(struct usb_interface *intf,
|
||||||
goto err_out_3;
|
goto err_out_3;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self->usbdev = dev;
|
||||||
|
|
||||||
/* Find IrDA class descriptor */
|
/* Find IrDA class descriptor */
|
||||||
irda_desc = irda_usb_find_class_desc(intf);
|
irda_desc = irda_usb_find_class_desc(intf);
|
||||||
ret = -ENODEV;
|
ret = -ENODEV;
|
||||||
if (irda_desc == NULL)
|
if (irda_desc == NULL)
|
||||||
goto err_out_3;
|
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->irda_desc = irda_desc;
|
||||||
self->present = 1;
|
self->present = 1;
|
||||||
self->netopen = 0;
|
self->netopen = 0;
|
||||||
self->capability = id->driver_info;
|
|
||||||
self->usbdev = dev;
|
|
||||||
self->usbintf = intf;
|
self->usbintf = intf;
|
||||||
|
|
||||||
/* Allocate the buffer for speed changes */
|
/* 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);
|
IRDA_MESSAGE("IrDA: Registered device %s\n", net->name);
|
||||||
usb_set_intfdata(intf, self);
|
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;
|
return 0;
|
||||||
|
|
||||||
err_out_4:
|
err_out_4:
|
||||||
|
@ -1518,7 +1840,7 @@ static int irda_usb_probe(struct usb_interface *intf,
|
||||||
err_out_2:
|
err_out_2:
|
||||||
usb_free_urb(self->tx_urb);
|
usb_free_urb(self->tx_urb);
|
||||||
err_out_1:
|
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])
|
if (self->rx_urb[i])
|
||||||
usb_free_urb(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_device_detach(self->netdev);*/
|
||||||
netif_stop_queue(self->netdev);
|
netif_stop_queue(self->netdev);
|
||||||
/* Stop all the receive URBs. Must be synchronous. */
|
/* 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]);
|
usb_kill_urb(self->rx_urb[i]);
|
||||||
/* Cancel Tx and speed URB.
|
/* Cancel Tx and speed URB.
|
||||||
* Make sure it's synchronous to avoid races. */
|
* Make sure it's synchronous to avoid races. */
|
||||||
|
@ -1586,8 +1908,9 @@ static void irda_usb_disconnect(struct usb_interface *intf)
|
||||||
self->usbintf = NULL;
|
self->usbintf = NULL;
|
||||||
|
|
||||||
/* Clean up our urbs */
|
/* 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]);
|
usb_free_urb(self->rx_urb[i]);
|
||||||
|
kfree(self->rx_urb);
|
||||||
/* Clean up Tx and speed URB */
|
/* Clean up Tx and speed URB */
|
||||||
usb_free_urb(self->tx_urb);
|
usb_free_urb(self->tx_urb);
|
||||||
usb_free_urb(self->speed_urb);
|
usb_free_urb(self->speed_urb);
|
||||||
|
@ -1648,6 +1971,6 @@ module_exit(usb_irda_cleanup);
|
||||||
*/
|
*/
|
||||||
module_param(qos_mtt_bits, int, 0);
|
module_param(qos_mtt_bits, int, 0);
|
||||||
MODULE_PARM_DESC(qos_mtt_bits, "Minimum Turn Time");
|
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_DESCRIPTION("IrDA-USB Dongle Driver");
|
||||||
MODULE_LICENSE("GPL");
|
MODULE_LICENSE("GPL");
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*****************************************************************************
|
/*****************************************************************************
|
||||||
*
|
*
|
||||||
* Filename: irda-usb.h
|
* Filename: irda-usb.h
|
||||||
* Version: 0.9b
|
* Version: 0.10
|
||||||
* Description: IrDA-USB Driver
|
* Description: IrDA-USB Driver
|
||||||
* Status: Experimental
|
* Status: Experimental
|
||||||
* Author: Dag Brattli <dag@brattli.net>
|
* Author: Dag Brattli <dag@brattli.net>
|
||||||
|
@ -9,6 +9,9 @@
|
||||||
* Copyright (C) 2001, Roman Weissgaerber <weissg@vienna.at>
|
* Copyright (C) 2001, Roman Weissgaerber <weissg@vienna.at>
|
||||||
* Copyright (C) 2000, Dag Brattli <dag@brattli.net>
|
* Copyright (C) 2000, Dag Brattli <dag@brattli.net>
|
||||||
* Copyright (C) 2001, Jean Tourrilhes <jt@hpl.hp.com>
|
* 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
|
* 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
|
* 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.h>
|
||||||
#include <net/irda/irda_device.h> /* struct irlap_cb */
|
#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 RX_COPY_THRESHOLD 200
|
||||||
#define IRDA_USB_MAX_MTU 2051
|
#define IRDA_USB_MAX_MTU 2051
|
||||||
#define IRDA_USB_SPEED_MTU 64 /* Weird, but work like this */
|
#define IRDA_USB_SPEED_MTU 64 /* Weird, but work like this */
|
||||||
|
@ -79,15 +85,16 @@
|
||||||
/* Inbound header */
|
/* Inbound header */
|
||||||
#define MEDIA_BUSY 0x80
|
#define MEDIA_BUSY 0x80
|
||||||
|
|
||||||
#define SPEED_2400 0x01
|
#define SPEED_2400 0x01
|
||||||
#define SPEED_9600 0x02
|
#define SPEED_9600 0x02
|
||||||
#define SPEED_19200 0x03
|
#define SPEED_19200 0x03
|
||||||
#define SPEED_38400 0x04
|
#define SPEED_38400 0x04
|
||||||
#define SPEED_57600 0x05
|
#define SPEED_57600 0x05
|
||||||
#define SPEED_115200 0x06
|
#define SPEED_115200 0x06
|
||||||
#define SPEED_576000 0x07
|
#define SPEED_576000 0x07
|
||||||
#define SPEED_1152000 0x08
|
#define SPEED_1152000 0x08
|
||||||
#define SPEED_4000000 0x09
|
#define SPEED_4000000 0x09
|
||||||
|
#define SPEED_16000000 0x0a
|
||||||
|
|
||||||
/* Basic capabilities */
|
/* Basic capabilities */
|
||||||
#define IUC_DEFAULT 0x00 /* Basic device compliant with 1.0 spec */
|
#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_SMALL_PKT 0x10 /* Device doesn't behave with big Rx packets */
|
||||||
#define IUC_MAX_WINDOW 0x20 /* Device underestimate the Rx window */
|
#define IUC_MAX_WINDOW 0x20 /* Device underestimate the Rx window */
|
||||||
#define IUC_MAX_XBOFS 0x40 /* Device need more xbofs than advertised */
|
#define IUC_MAX_XBOFS 0x40 /* Device need more xbofs than advertised */
|
||||||
|
#define IUC_STIR_4210 0x80 /* SigmaTel 4210/4220/4116 VFIR */
|
||||||
|
|
||||||
/* USB class definitions */
|
/* USB class definitions */
|
||||||
#define USB_IRDA_HEADER 0x01
|
#define USB_IRDA_HEADER 0x01
|
||||||
#define USB_CLASS_IRDA 0x02 /* USB_CLASS_APP_SPEC subclass */
|
#define USB_CLASS_IRDA 0x02 /* USB_CLASS_APP_SPEC subclass */
|
||||||
#define USB_DT_IRDA 0x21
|
#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 {
|
struct irda_class_desc {
|
||||||
__u8 bLength;
|
__u8 bLength;
|
||||||
|
@ -123,6 +133,7 @@ struct irda_class_desc {
|
||||||
* (6.2.5, USB-IrDA class spec 1.0) */
|
* (6.2.5, USB-IrDA class spec 1.0) */
|
||||||
|
|
||||||
#define IU_REQ_GET_CLASS_DESC 0x06
|
#define IU_REQ_GET_CLASS_DESC 0x06
|
||||||
|
#define STIR421X_MAX_PATCH_DOWNLOAD_SIZE 1023
|
||||||
|
|
||||||
struct irda_usb_cb {
|
struct irda_usb_cb {
|
||||||
struct irda_class_desc *irda_desc;
|
struct irda_class_desc *irda_desc;
|
||||||
|
@ -136,7 +147,8 @@ struct irda_usb_cb {
|
||||||
__u16 bulk_out_mtu; /* Max Tx packet size in bytes */
|
__u16 bulk_out_mtu; /* Max Tx packet size in bytes */
|
||||||
__u8 bulk_int_ep; /* Interrupt Endpoint assignments */
|
__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 *idle_rx_urb; /* Pointer to idle URB in Rx path */
|
||||||
struct urb *tx_urb; /* URB used to send data frames */
|
struct urb *tx_urb; /* URB used to send data frames */
|
||||||
struct urb *speed_urb; /* URB used to send speed commands */
|
struct urb *speed_urb; /* URB used to send speed commands */
|
||||||
|
@ -157,6 +169,9 @@ struct irda_usb_cb {
|
||||||
__u32 speed; /* Current speed */
|
__u32 speed; /* Current speed */
|
||||||
__s32 new_speed; /* speed we need to set */
|
__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 */
|
struct timer_list rx_defer_timer; /* Wait for Rx error to clear */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
* Copyright (c) 2002 Daniele Peri
|
* Copyright (c) 2002 Daniele Peri
|
||||||
* All Rights Reserved.
|
* All Rights Reserved.
|
||||||
* Copyright (c) 2002 Jean Tourrilhes
|
* Copyright (c) 2002 Jean Tourrilhes
|
||||||
|
* Copyright (c) 2006 Linus Walleij
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* Based on smc-ircc.c:
|
* Based on smc-ircc.c:
|
||||||
|
@ -61,6 +62,9 @@
|
||||||
|
|
||||||
#include <linux/spinlock.h>
|
#include <linux/spinlock.h>
|
||||||
#include <linux/pm.h>
|
#include <linux/pm.h>
|
||||||
|
#ifdef CONFIG_PCI
|
||||||
|
#include <linux/pci.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <net/irda/wrapper.h>
|
#include <net/irda/wrapper.h>
|
||||||
#include <net/irda/irda.h>
|
#include <net/irda/irda.h>
|
||||||
|
@ -100,6 +104,22 @@ MODULE_PARM_DESC(ircc_transceiver, "Transceiver type");
|
||||||
|
|
||||||
/* Types */
|
/* 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 {
|
struct smsc_transceiver {
|
||||||
char *name;
|
char *name;
|
||||||
void (*set_for_speed)(int fir_base, u32 speed);
|
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_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_fdc(unsigned short cfg_base);
|
||||||
static int __init smsc_superio_lpc(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 */
|
/* Transceivers specific functions */
|
||||||
|
|
||||||
|
@ -353,6 +383,13 @@ static int __init smsc_ircc_init(void)
|
||||||
return ret;
|
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;
|
dev_count = 0;
|
||||||
|
|
||||||
if (ircc_fir > 0 && ircc_sir > 0) {
|
if (ircc_fir > 0 && ircc_sir > 0) {
|
||||||
|
@ -2285,6 +2322,280 @@ static int __init smsc_superio_lpc(unsigned short cfg_base)
|
||||||
return ret;
|
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
|
* Transceivers specific functions
|
||||||
|
|
|
@ -87,6 +87,7 @@ static void write_msg(struct console *con, const char *msg, unsigned int len)
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct console netconsole = {
|
static struct console netconsole = {
|
||||||
|
.name = "netcon",
|
||||||
.flags = CON_ENABLED | CON_PRINTBUFFER,
|
.flags = CON_ENABLED | CON_PRINTBUFFER,
|
||||||
.write = write_msg
|
.write = write_msg
|
||||||
};
|
};
|
||||||
|
|
|
@ -497,33 +497,40 @@ static void tg3_write_mem(struct tg3 *tp, u32 off, u32 val)
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
|
||||||
spin_lock_irqsave(&tp->indirect_lock, flags);
|
spin_lock_irqsave(&tp->indirect_lock, flags);
|
||||||
pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_BASE_ADDR, off);
|
if (tp->tg3_flags & TG3_FLAG_SRAM_USE_CONFIG) {
|
||||||
pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_DATA, val);
|
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. */
|
/* Always leave this as zero. */
|
||||||
pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_BASE_ADDR, 0);
|
pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_BASE_ADDR, 0);
|
||||||
|
} else {
|
||||||
|
tw32_f(TG3PCI_MEM_WIN_BASE_ADDR, off);
|
||||||
|
tw32_f(TG3PCI_MEM_WIN_DATA, val);
|
||||||
|
|
||||||
|
/* Always leave this as zero. */
|
||||||
|
tw32_f(TG3PCI_MEM_WIN_BASE_ADDR, 0);
|
||||||
|
}
|
||||||
spin_unlock_irqrestore(&tp->indirect_lock, flags);
|
spin_unlock_irqrestore(&tp->indirect_lock, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void tg3_read_mem(struct tg3 *tp, u32 off, u32 *val)
|
static void tg3_read_mem(struct tg3 *tp, u32 off, u32 *val)
|
||||||
{
|
{
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
|
||||||
spin_lock_irqsave(&tp->indirect_lock, flags);
|
spin_lock_irqsave(&tp->indirect_lock, flags);
|
||||||
pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_BASE_ADDR, off);
|
if (tp->tg3_flags & TG3_FLAG_SRAM_USE_CONFIG) {
|
||||||
pci_read_config_dword(tp->pdev, TG3PCI_MEM_WIN_DATA, val);
|
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. */
|
/* Always leave this as zero. */
|
||||||
pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_BASE_ADDR, 0);
|
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);
|
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. */
|
/* Finally, set the new power state. */
|
||||||
pci_write_config_word(tp->pdev, pm + PCI_PM_CTRL, power_control);
|
pci_write_config_word(tp->pdev, pm + PCI_PM_CTRL, power_control);
|
||||||
udelay(100); /* Delay after power state change */
|
udelay(100); /* Delay after power state change */
|
||||||
|
|
||||||
tg3_write_sig_post_reset(tp, RESET_KIND_SHUTDOWN);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5828,10 +5835,14 @@ static int tg3_reset_hw(struct tg3 *tp)
|
||||||
GRC_MODE_NO_TX_PHDR_CSUM |
|
GRC_MODE_NO_TX_PHDR_CSUM |
|
||||||
GRC_MODE_NO_RX_PHDR_CSUM);
|
GRC_MODE_NO_RX_PHDR_CSUM);
|
||||||
tp->grc_mode |= GRC_MODE_HOST_SENDBDS;
|
tp->grc_mode |= GRC_MODE_HOST_SENDBDS;
|
||||||
if (tp->tg3_flags & TG3_FLAG_NO_TX_PSEUDO_CSUM)
|
|
||||||
tp->grc_mode |= GRC_MODE_NO_TX_PHDR_CSUM;
|
/* Pseudo-header checksum is done by hardware logic and not
|
||||||
if (tp->tg3_flags & TG3_FLAG_NO_RX_PSEUDO_CSUM)
|
* the offload processers, so make the chip do the pseudo-
|
||||||
tp->grc_mode |= GRC_MODE_NO_RX_PHDR_CSUM;
|
* 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;
|
||||||
|
|
||||||
tw32(GRC_MODE,
|
tw32(GRC_MODE,
|
||||||
tp->grc_mode |
|
tp->grc_mode |
|
||||||
|
@ -6535,11 +6546,11 @@ static void tg3_timer(unsigned long __opaque)
|
||||||
if (tp->tg3_flags & TG3_FLAG_ENABLE_ASF) {
|
if (tp->tg3_flags & TG3_FLAG_ENABLE_ASF) {
|
||||||
u32 val;
|
u32 val;
|
||||||
|
|
||||||
tg3_write_mem_fast(tp, NIC_SRAM_FW_CMD_MBOX,
|
tg3_write_mem(tp, NIC_SRAM_FW_CMD_MBOX,
|
||||||
FWCMD_NICDRV_ALIVE2);
|
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 */
|
/* 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 = tr32(GRC_RX_CPU_EVENT);
|
||||||
val |= (1 << 14);
|
val |= (1 << 14);
|
||||||
tw32(GRC_RX_CPU_EVENT, val);
|
tw32(GRC_RX_CPU_EVENT, val);
|
||||||
|
@ -8034,9 +8045,13 @@ static int tg3_test_nvram(struct tg3 *tp)
|
||||||
for (i = 0; i < size; i++)
|
for (i = 0; i < size; i++)
|
||||||
csum8 += buf8[i];
|
csum8 += buf8[i];
|
||||||
|
|
||||||
if (csum8 == 0)
|
if (csum8 == 0) {
|
||||||
return 0;
|
err = 0;
|
||||||
return -EIO;
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
err = -EIO;
|
||||||
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Bootstrap checksum at offset 0x10 */
|
/* 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;
|
tp->led_ctrl = LED_CTRL_MODE_PHY_1;
|
||||||
|
|
||||||
/* Do not even try poking around in here on Sun parts. */
|
/* 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;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
tg3_read_mem(tp, NIC_SRAM_DATA_SIG, &val);
|
tg3_read_mem(tp, NIC_SRAM_DATA_SIG, &val);
|
||||||
if (val == NIC_SRAM_DATA_SIG_MAGIC) {
|
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->pdev->subsystem_vendor == PCI_VENDOR_ID_DELL)
|
||||||
tp->led_ctrl = LED_CTRL_MODE_PHY_2;
|
tp->led_ctrl = LED_CTRL_MODE_PHY_2;
|
||||||
|
|
||||||
if ((GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5700) &&
|
if (nic_cfg & NIC_SRAM_DATA_CFG_EEPROM_WP)
|
||||||
(GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5701) &&
|
|
||||||
(nic_cfg & NIC_SRAM_DATA_CFG_EEPROM_WP))
|
|
||||||
tp->tg3_flags |= TG3_FLAG_EEPROM_WRITE_PROT;
|
tp->tg3_flags |= TG3_FLAG_EEPROM_WRITE_PROT;
|
||||||
|
|
||||||
if (nic_cfg & NIC_SRAM_DATA_CFG_ASF_ENABLE) {
|
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);
|
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().
|
/* Get eeprom hw config before calling tg3_set_power_state().
|
||||||
* In particular, the TG3_FLAG_EEPROM_WRITE_PROT flag must be
|
* In particular, the TG3_FLAG_EEPROM_WRITE_PROT flag must be
|
||||||
* determined before calling tg3_set_power_state() so that
|
* 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)
|
if (tp->pci_chip_rev_id == CHIPREV_ID_5700_B0)
|
||||||
tp->tg3_flags |= TG3_FLAG_BROKEN_CHECKSUMS;
|
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
|
/* Derive initial jumbo mode from MTU assigned in
|
||||||
* ether_setup() via the alloc_etherdev() call
|
* ether_setup() via the alloc_etherdev() call
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -2171,8 +2171,7 @@ struct tg3 {
|
||||||
#define TG3_FLAG_PCIX_MODE 0x00020000
|
#define TG3_FLAG_PCIX_MODE 0x00020000
|
||||||
#define TG3_FLAG_PCI_HIGH_SPEED 0x00040000
|
#define TG3_FLAG_PCI_HIGH_SPEED 0x00040000
|
||||||
#define TG3_FLAG_PCI_32BIT 0x00080000
|
#define TG3_FLAG_PCI_32BIT 0x00080000
|
||||||
#define TG3_FLAG_NO_TX_PSEUDO_CSUM 0x00100000
|
#define TG3_FLAG_SRAM_USE_CONFIG 0x00100000
|
||||||
#define TG3_FLAG_NO_RX_PSEUDO_CSUM 0x00200000
|
|
||||||
#define TG3_FLAG_SERDES_WOL_CAP 0x00400000
|
#define TG3_FLAG_SERDES_WOL_CAP 0x00400000
|
||||||
#define TG3_FLAG_JUMBO_RING_ENABLE 0x00800000
|
#define TG3_FLAG_JUMBO_RING_ENABLE 0x00800000
|
||||||
#define TG3_FLAG_10_100_ONLY 0x01000000
|
#define TG3_FLAG_10_100_ONLY 0x01000000
|
||||||
|
|
|
@ -110,6 +110,8 @@ struct nf_info
|
||||||
/* Function to register/unregister hook points. */
|
/* Function to register/unregister hook points. */
|
||||||
int nf_register_hook(struct nf_hook_ops *reg);
|
int nf_register_hook(struct nf_hook_ops *reg);
|
||||||
void nf_unregister_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
|
/* Functions to register get/setsockopt ranges (non-inclusive). You
|
||||||
need to check permissions yourself! */
|
need to check permissions yourself! */
|
||||||
|
@ -281,16 +283,42 @@ extern void nf_invalidate_cache(int pf);
|
||||||
Returns true or false. */
|
Returns true or false. */
|
||||||
extern int skb_make_writable(struct sk_buff **pskb, unsigned int writable_len);
|
extern int skb_make_writable(struct sk_buff **pskb, unsigned int writable_len);
|
||||||
|
|
||||||
struct nf_queue_rerouter {
|
struct nf_afinfo {
|
||||||
void (*save)(const struct sk_buff *skb, struct nf_info *info);
|
unsigned short family;
|
||||||
int (*reroute)(struct sk_buff **skb, const struct nf_info *info);
|
unsigned int (*checksum)(struct sk_buff *skb, unsigned int hook,
|
||||||
int rer_size;
|
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);
|
static inline unsigned int
|
||||||
extern int nf_unregister_queue_rerouter(int pf);
|
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>
|
#include <net/flow.h>
|
||||||
extern void (*ip_nat_decode_session)(struct sk_buff *, struct flowi *);
|
extern void (*ip_nat_decode_session)(struct sk_buff *, struct flowi *);
|
||||||
|
|
|
@ -80,6 +80,8 @@ enum nf_ip_hook_priorities {
|
||||||
#ifdef __KERNEL__
|
#ifdef __KERNEL__
|
||||||
extern int ip_route_me_harder(struct sk_buff **pskb);
|
extern int ip_route_me_harder(struct sk_buff **pskb);
|
||||||
extern int ip_xfrm_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 /*__KERNEL__*/
|
||||||
|
|
||||||
#endif /*__LINUX_IP_NETFILTER_H*/
|
#endif /*__LINUX_IP_NETFILTER_H*/
|
||||||
|
|
|
@ -3,6 +3,8 @@
|
||||||
|
|
||||||
#ifdef __KERNEL__
|
#ifdef __KERNEL__
|
||||||
|
|
||||||
|
#include <linux/netfilter_ipv4/ip_conntrack_helper_h323_asn1.h>
|
||||||
|
|
||||||
#define RAS_PORT 1719
|
#define RAS_PORT 1719
|
||||||
#define Q931_PORT 1720
|
#define Q931_PORT 1720
|
||||||
#define H323_RTP_CHANNEL_MAX 4 /* Audio, video, FAX and other */
|
#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
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -73,6 +73,9 @@ enum nf_ip6_hook_priorities {
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef CONFIG_NETFILTER
|
#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 int ipv6_netfilter_init(void);
|
||||||
extern void ipv6_netfilter_fini(void);
|
extern void ipv6_netfilter_fini(void);
|
||||||
#else /* CONFIG_NETFILTER */
|
#else /* CONFIG_NETFILTER */
|
||||||
|
|
|
@ -48,31 +48,7 @@ static inline int inet6_sk_ehashfn(const struct sock *sk)
|
||||||
return inet6_ehashfn(laddr, lport, faddr, fport);
|
return inet6_ehashfn(laddr, lport, faddr, fport);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void __inet6_hash(struct inet_hashinfo *hashinfo,
|
extern void __inet6_hash(struct inet_hashinfo *hashinfo, struct sock *sk);
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Sockets in TCP_CLOSE state are _always_ taken out of the hash, so
|
* 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.
|
* The sockhash lock must be held as a reader here.
|
||||||
*/
|
*/
|
||||||
static inline struct sock *
|
extern struct sock *__inet6_lookup_established(struct inet_hashinfo *hashinfo,
|
||||||
__inet6_lookup_established(struct inet_hashinfo *hashinfo,
|
|
||||||
const struct in6_addr *saddr,
|
const struct in6_addr *saddr,
|
||||||
const u16 sport,
|
const u16 sport,
|
||||||
const struct in6_addr *daddr,
|
const struct in6_addr *daddr,
|
||||||
const u16 hnum,
|
const u16 hnum,
|
||||||
const int dif)
|
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
extern struct sock *inet6_lookup_listener(struct inet_hashinfo *hashinfo,
|
extern struct sock *inet6_lookup_listener(struct inet_hashinfo *hashinfo,
|
||||||
const struct in6_addr *daddr,
|
const struct in6_addr *daddr,
|
||||||
|
|
|
@ -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_mr_input(struct sk_buff *skb);
|
||||||
extern int ip_output(struct sk_buff *skb);
|
extern int ip_output(struct sk_buff *skb);
|
||||||
extern int ip_mc_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 int ip_do_nat(struct sk_buff *skb);
|
||||||
extern void ip_send_check(struct iphdr *ip);
|
extern void ip_send_check(struct iphdr *ip);
|
||||||
extern int ip_queue_xmit(struct sk_buff *skb, int ipfragok);
|
extern int ip_queue_xmit(struct sk_buff *skb, int ipfragok);
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
static inline __be16 x25_type_trans(struct sk_buff *skb, struct net_device *dev)
|
static inline __be16 x25_type_trans(struct sk_buff *skb, struct net_device *dev)
|
||||||
{
|
{
|
||||||
skb->mac.raw = skb->data;
|
skb->mac.raw = skb->data;
|
||||||
|
skb->dev = dev;
|
||||||
skb->pkt_type = PACKET_HOST;
|
skb->pkt_type = PACKET_HOST;
|
||||||
|
|
||||||
return htons(ETH_P_X25);
|
return htons(ETH_P_X25);
|
||||||
|
|
|
@ -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)
|
if ((err = hci_send_sco(conn->hcon, skb)) < 0)
|
||||||
goto fail;
|
return err;
|
||||||
|
|
||||||
return count;
|
return count;
|
||||||
|
|
||||||
|
|
|
@ -765,6 +765,15 @@ static unsigned int br_nf_local_out(unsigned int hook, struct sk_buff **pskb,
|
||||||
return NF_STOLEN;
|
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 ********************************************/
|
/* PF_BRIDGE/POST_ROUTING ********************************************/
|
||||||
static unsigned int br_nf_post_routing(unsigned int hook, struct sk_buff **pskb,
|
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;
|
realoutdev = nf_bridge->netoutdev;
|
||||||
#endif
|
#endif
|
||||||
NF_HOOK(pf, NF_IP_POST_ROUTING, skb, NULL, realoutdev,
|
NF_HOOK(pf, NF_IP_POST_ROUTING, skb, NULL, realoutdev,
|
||||||
br_dev_queue_push_xmit);
|
br_nf_dev_queue_xmit);
|
||||||
|
|
||||||
return NF_STOLEN;
|
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 &&
|
if ((out->hard_start_xmit == br_dev_xmit &&
|
||||||
okfn != br_nf_forward_finish &&
|
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)
|
#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
|
||||||
|| ((out->priv_flags & IFF_802_1Q_VLAN) &&
|
|| ((out->priv_flags & IFF_802_1Q_VLAN) &&
|
||||||
VLAN_DEV_INFO(out)->real_dev->hard_start_xmit == br_dev_xmit)
|
VLAN_DEV_INFO(out)->real_dev->hard_start_xmit == br_dev_xmit)
|
||||||
|
|
|
@ -3042,11 +3042,11 @@ void netdev_run_todo(void)
|
||||||
|
|
||||||
switch(dev->reg_state) {
|
switch(dev->reg_state) {
|
||||||
case NETREG_REGISTERING:
|
case NETREG_REGISTERING:
|
||||||
|
dev->reg_state = NETREG_REGISTERED;
|
||||||
err = netdev_register_sysfs(dev);
|
err = netdev_register_sysfs(dev);
|
||||||
if (err)
|
if (err)
|
||||||
printk(KERN_ERR "%s: failed sysfs registration (%d)\n",
|
printk(KERN_ERR "%s: failed sysfs registration (%d)\n",
|
||||||
dev->name, err);
|
dev->name, err);
|
||||||
dev->reg_state = NETREG_REGISTERED;
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case NETREG_UNREGISTERING:
|
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(*dev) + NETDEV_ALIGN_CONST) & ~NETDEV_ALIGN_CONST;
|
||||||
alloc_size += sizeof_priv + NETDEV_ALIGN_CONST;
|
alloc_size += sizeof_priv + NETDEV_ALIGN_CONST;
|
||||||
|
|
||||||
p = kmalloc(alloc_size, GFP_KERNEL);
|
p = kzalloc(alloc_size, GFP_KERNEL);
|
||||||
if (!p) {
|
if (!p) {
|
||||||
printk(KERN_ERR "alloc_dev: Unable to allocate device.\n");
|
printk(KERN_ERR "alloc_dev: Unable to allocate device.\n");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
memset(p, 0, alloc_size);
|
|
||||||
|
|
||||||
dev = (struct net_device *)
|
dev = (struct net_device *)
|
||||||
(((long)p + NETDEV_ALIGN_CONST) & ~NETDEV_ALIGN_CONST);
|
(((long)p + NETDEV_ALIGN_CONST) & ~NETDEV_ALIGN_CONST);
|
||||||
|
|
|
@ -55,15 +55,12 @@ int alloc_divert_blk(struct net_device *dev)
|
||||||
|
|
||||||
dev->divert = NULL;
|
dev->divert = NULL;
|
||||||
if (dev->type == ARPHRD_ETHER) {
|
if (dev->type == ARPHRD_ETHER) {
|
||||||
dev->divert = (struct divert_blk *)
|
dev->divert = kzalloc(alloc_size, GFP_KERNEL);
|
||||||
kmalloc(alloc_size, GFP_KERNEL);
|
|
||||||
if (dev->divert == NULL) {
|
if (dev->divert == NULL) {
|
||||||
printk(KERN_INFO "divert: unable to allocate divert_blk for %s\n",
|
printk(KERN_INFO "divert: unable to allocate divert_blk for %s\n",
|
||||||
dev->name);
|
dev->name);
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
memset(dev->divert, 0, sizeof(struct divert_blk));
|
|
||||||
dev_hold(dev);
|
dev_hold(dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -318,12 +318,10 @@ static void __devinit flow_cache_cpu_prepare(int cpu)
|
||||||
/* NOTHING */;
|
/* NOTHING */;
|
||||||
|
|
||||||
flow_table(cpu) = (struct flow_cache_entry **)
|
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))
|
if (!flow_table(cpu))
|
||||||
panic("NET: failed to allocate flow cache order %lu\n", order);
|
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_hash_rnd_recalc(cpu) = 1;
|
||||||
flow_count(cpu) = 0;
|
flow_count(cpu) = 0;
|
||||||
|
|
||||||
|
|
|
@ -159,11 +159,10 @@ int gen_new_estimator(struct gnet_stats_basic *bstats,
|
||||||
if (parm->interval < -2 || parm->interval > 3)
|
if (parm->interval < -2 || parm->interval > 3)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
est = kmalloc(sizeof(*est), GFP_KERNEL);
|
est = kzalloc(sizeof(*est), GFP_KERNEL);
|
||||||
if (est == NULL)
|
if (est == NULL)
|
||||||
return -ENOBUFS;
|
return -ENOBUFS;
|
||||||
|
|
||||||
memset(est, 0, sizeof(*est));
|
|
||||||
est->interval = parm->interval + 2;
|
est->interval = parm->interval + 2;
|
||||||
est->bstats = bstats;
|
est->bstats = bstats;
|
||||||
est->rate_est = rate_est;
|
est->rate_est = rate_est;
|
||||||
|
|
|
@ -284,14 +284,11 @@ static struct neighbour **neigh_hash_alloc(unsigned int entries)
|
||||||
struct neighbour **ret;
|
struct neighbour **ret;
|
||||||
|
|
||||||
if (size <= PAGE_SIZE) {
|
if (size <= PAGE_SIZE) {
|
||||||
ret = kmalloc(size, GFP_ATOMIC);
|
ret = kzalloc(size, GFP_ATOMIC);
|
||||||
} else {
|
} else {
|
||||||
ret = (struct neighbour **)
|
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;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1089,8 +1086,7 @@ static void neigh_hh_init(struct neighbour *n, struct dst_entry *dst,
|
||||||
if (hh->hh_type == protocol)
|
if (hh->hh_type == protocol)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (!hh && (hh = kmalloc(sizeof(*hh), GFP_ATOMIC)) != NULL) {
|
if (!hh && (hh = kzalloc(sizeof(*hh), GFP_ATOMIC)) != NULL) {
|
||||||
memset(hh, 0, sizeof(struct hh_cache));
|
|
||||||
rwlock_init(&hh->hh_lock);
|
rwlock_init(&hh->hh_lock);
|
||||||
hh->hh_type = protocol;
|
hh->hh_type = protocol;
|
||||||
atomic_set(&hh->hh_refcnt, 0);
|
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);
|
tbl->hash_buckets = neigh_hash_alloc(tbl->hash_mask + 1);
|
||||||
|
|
||||||
phsize = (PNEIGH_HASHMASK + 1) * sizeof(struct pneigh_entry *);
|
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)
|
if (!tbl->hash_buckets || !tbl->phash_buckets)
|
||||||
panic("cannot allocate neighbour cache hashes");
|
panic("cannot allocate neighbour cache hashes");
|
||||||
|
|
||||||
memset(tbl->phash_buckets, 0, phsize);
|
|
||||||
|
|
||||||
get_random_bytes(&tbl->hash_rnd, sizeof(tbl->hash_rnd));
|
get_random_bytes(&tbl->hash_rnd, sizeof(tbl->hash_rnd));
|
||||||
|
|
||||||
rwlock_init(&tbl->lock);
|
rwlock_init(&tbl->lock);
|
||||||
|
|
|
@ -165,7 +165,7 @@ static ssize_t show_operstate(struct class_device *dev, char *buf)
|
||||||
operstate = IF_OPER_DOWN;
|
operstate = IF_OPER_DOWN;
|
||||||
read_unlock(&dev_base_lock);
|
read_unlock(&dev_base_lock);
|
||||||
|
|
||||||
if (operstate >= sizeof(operstates))
|
if (operstate >= ARRAY_SIZE(operstates))
|
||||||
return -EINVAL; /* should not happen */
|
return -EINVAL; /* should not happen */
|
||||||
|
|
||||||
return sprintf(buf, "%s\n", operstates[operstate]);
|
return sprintf(buf, "%s\n", operstates[operstate]);
|
||||||
|
|
|
@ -38,13 +38,11 @@ int reqsk_queue_alloc(struct request_sock_queue *queue,
|
||||||
{
|
{
|
||||||
const int lopt_size = sizeof(struct listen_sock) +
|
const int lopt_size = sizeof(struct listen_sock) +
|
||||||
nr_table_entries * sizeof(struct request_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)
|
if (lopt == NULL)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
memset(lopt, 0, lopt_size);
|
|
||||||
|
|
||||||
for (lopt->max_qlen_log = 6;
|
for (lopt->max_qlen_log = 6;
|
||||||
(1 << lopt->max_qlen_log) < sysctl_max_syn_backlog;
|
(1 << lopt->max_qlen_log) < sysctl_max_syn_backlog;
|
||||||
lopt->max_qlen_log++);
|
lopt->max_qlen_log++);
|
||||||
|
|
|
@ -50,7 +50,7 @@
|
||||||
* Patrick McHardy <kaber@trash.net>
|
* Patrick McHardy <kaber@trash.net>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define VERSION "0.406"
|
#define VERSION "0.407"
|
||||||
|
|
||||||
#include <linux/config.h>
|
#include <linux/config.h>
|
||||||
#include <asm/uaccess.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));
|
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)
|
static void __leaf_info_free_rcu(struct rcu_head *head)
|
||||||
{
|
{
|
||||||
kfree(container_of(head, struct leaf_info, rcu));
|
kfree(container_of(head, struct leaf_info, rcu));
|
||||||
|
@ -357,7 +352,12 @@ static void __tnode_free_rcu(struct rcu_head *head)
|
||||||
|
|
||||||
static inline void tnode_free(struct tnode *tn)
|
static inline void tnode_free(struct tnode *tn)
|
||||||
{
|
{
|
||||||
call_rcu(&tn->rcu, __tnode_free_rcu);
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct leaf *leaf_new(void)
|
static struct leaf *leaf_new(void)
|
||||||
|
|
|
@ -304,13 +304,17 @@ static void ip_expire(unsigned long arg)
|
||||||
|
|
||||||
/* Creation primitives. */
|
/* 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;
|
struct ipq *qp;
|
||||||
#ifdef CONFIG_SMP
|
#ifdef CONFIG_SMP
|
||||||
struct hlist_node *n;
|
struct hlist_node *n;
|
||||||
#endif
|
#endif
|
||||||
|
unsigned int hash;
|
||||||
|
|
||||||
write_lock(&ipfrag_lock);
|
write_lock(&ipfrag_lock);
|
||||||
|
hash = ipqhashfn(qp_in->id, qp_in->saddr, qp_in->daddr,
|
||||||
|
qp_in->protocol);
|
||||||
#ifdef CONFIG_SMP
|
#ifdef CONFIG_SMP
|
||||||
/* With SMP race we have to recheck hash table, because
|
/* With SMP race we have to recheck hash table, because
|
||||||
* such entry could be created on other cpu, while we
|
* 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. */
|
/* 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;
|
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);
|
spin_lock_init(&qp->lock);
|
||||||
atomic_set(&qp->refcnt, 1);
|
atomic_set(&qp->refcnt, 1);
|
||||||
|
|
||||||
return ip_frag_intern(hash, qp);
|
return ip_frag_intern(qp);
|
||||||
|
|
||||||
out_nomem:
|
out_nomem:
|
||||||
LIMIT_NETDEBUG(KERN_ERR "ip_frag_create: no memory left !\n");
|
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 saddr = iph->saddr;
|
||||||
__u32 daddr = iph->daddr;
|
__u32 daddr = iph->daddr;
|
||||||
__u8 protocol = iph->protocol;
|
__u8 protocol = iph->protocol;
|
||||||
unsigned int hash = ipqhashfn(id, saddr, daddr, protocol);
|
unsigned int hash;
|
||||||
struct ipq *qp;
|
struct ipq *qp;
|
||||||
struct hlist_node *n;
|
struct hlist_node *n;
|
||||||
|
|
||||||
read_lock(&ipfrag_lock);
|
read_lock(&ipfrag_lock);
|
||||||
|
hash = ipqhashfn(id, saddr, daddr, protocol);
|
||||||
hlist_for_each_entry(qp, n, &ipq_hash[hash], list) {
|
hlist_for_each_entry(qp, n, &ipq_hash[hash], list) {
|
||||||
if(qp->id == id &&
|
if(qp->id == id &&
|
||||||
qp->saddr == saddr &&
|
qp->saddr == saddr &&
|
||||||
|
@ -405,7 +410,7 @@ static inline struct ipq *ip_find(struct iphdr *iph, u32 user)
|
||||||
}
|
}
|
||||||
read_unlock(&ipfrag_lock);
|
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? */
|
/* Is the fragment too far ahead to be part of ipq? */
|
||||||
|
|
|
@ -656,7 +656,7 @@ static int ipgre_rcv(struct sk_buff *skb)
|
||||||
read_unlock(&ipgre_lock);
|
read_unlock(&ipgre_lock);
|
||||||
return(0);
|
return(0);
|
||||||
}
|
}
|
||||||
icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PROT_UNREACH, 0);
|
icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0);
|
||||||
|
|
||||||
drop:
|
drop:
|
||||||
read_unlock(&ipgre_lock);
|
read_unlock(&ipgre_lock);
|
||||||
|
|
|
@ -86,8 +86,6 @@
|
||||||
|
|
||||||
int sysctl_ip_default_ttl = IPDEFTTL;
|
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. */
|
/* Generate a checksum for an outgoing IP datagram. */
|
||||||
__inline__ void ip_send_check(struct iphdr *iph)
|
__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.
|
* 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;
|
struct iphdr *iph;
|
||||||
int raw = 0;
|
int raw = 0;
|
||||||
|
@ -673,6 +671,8 @@ static int ip_fragment(struct sk_buff *skb, int (*output)(struct sk_buff*))
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
EXPORT_SYMBOL(ip_fragment);
|
||||||
|
|
||||||
int
|
int
|
||||||
ip_generic_getfrag(void *from, char *to, int offset, int len, int odd, struct sk_buff *skb)
|
ip_generic_getfrag(void *from, char *to, int offset, int len, int odd, struct sk_buff *skb)
|
||||||
{
|
{
|
||||||
|
|
|
@ -474,9 +474,6 @@ static int ipip_rcv(struct sk_buff *skb)
|
||||||
struct iphdr *iph;
|
struct iphdr *iph;
|
||||||
struct ip_tunnel *tunnel;
|
struct ip_tunnel *tunnel;
|
||||||
|
|
||||||
if (!pskb_may_pull(skb, sizeof(struct iphdr)))
|
|
||||||
goto out;
|
|
||||||
|
|
||||||
iph = skb->nh.iph;
|
iph = skb->nh.iph;
|
||||||
|
|
||||||
read_lock(&ipip_lock);
|
read_lock(&ipip_lock);
|
||||||
|
@ -508,7 +505,6 @@ static int ipip_rcv(struct sk_buff *skb)
|
||||||
}
|
}
|
||||||
read_unlock(&ipip_lock);
|
read_unlock(&ipip_lock);
|
||||||
|
|
||||||
out:
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -133,7 +133,7 @@ struct ip_rt_info {
|
||||||
u_int8_t tos;
|
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);
|
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);
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct nf_queue_rerouter ip_reroute = {
|
unsigned int nf_ip_checksum(struct sk_buff *skb, unsigned int hook,
|
||||||
.rer_size = sizeof(struct ip_rt_info),
|
unsigned int dataoff, u_int8_t protocol)
|
||||||
.save = queue_save,
|
{
|
||||||
.reroute = queue_reroute,
|
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)
|
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)
|
static void ipv4_netfilter_fini(void)
|
||||||
{
|
{
|
||||||
nf_unregister_queue_rerouter(PF_INET);
|
nf_unregister_afinfo(&nf_ip_afinfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
module_init(ipv4_netfilter_init);
|
module_init(ipv4_netfilter_init);
|
||||||
|
|
|
@ -69,6 +69,7 @@ config IP_NF_CONNTRACK_NETLINK
|
||||||
tristate 'Connection tracking netlink interface (EXPERIMENTAL)'
|
tristate 'Connection tracking netlink interface (EXPERIMENTAL)'
|
||||||
depends on EXPERIMENTAL && IP_NF_CONNTRACK && NETFILTER_NETLINK
|
depends on EXPERIMENTAL && IP_NF_CONNTRACK && NETFILTER_NETLINK
|
||||||
depends on IP_NF_CONNTRACK!=y || NETFILTER_NETLINK!=m
|
depends on IP_NF_CONNTRACK!=y || NETFILTER_NETLINK!=m
|
||||||
|
depends on IP_NF_NAT=n || IP_NF_NAT
|
||||||
help
|
help
|
||||||
This option enables support for a netlink-based userspace interface
|
This option enables support for a netlink-based userspace interface
|
||||||
|
|
||||||
|
|
|
@ -181,33 +181,26 @@ static struct nf_hook_ops arpt_ops[] = {
|
||||||
|
|
||||||
static int __init arptable_filter_init(void)
|
static int __init arptable_filter_init(void)
|
||||||
{
|
{
|
||||||
int ret, i;
|
int ret;
|
||||||
|
|
||||||
/* Register table */
|
/* Register table */
|
||||||
ret = arpt_register_table(&packet_filter, &initial_table.repl);
|
ret = arpt_register_table(&packet_filter, &initial_table.repl);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
for (i = 0; i < ARRAY_SIZE(arpt_ops); i++)
|
ret = nf_register_hooks(arpt_ops, ARRAY_SIZE(arpt_ops));
|
||||||
if ((ret = nf_register_hook(&arpt_ops[i])) < 0)
|
if (ret < 0)
|
||||||
goto cleanup_hooks;
|
goto cleanup_table;
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
cleanup_hooks:
|
cleanup_table:
|
||||||
while (--i >= 0)
|
|
||||||
nf_unregister_hook(&arpt_ops[i]);
|
|
||||||
|
|
||||||
arpt_unregister_table(&packet_filter);
|
arpt_unregister_table(&packet_filter);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __exit arptable_filter_fini(void)
|
static void __exit arptable_filter_fini(void)
|
||||||
{
|
{
|
||||||
unsigned int i;
|
nf_unregister_hooks(arpt_ops, ARRAY_SIZE(arpt_ops));
|
||||||
|
|
||||||
for (i = 0; i < ARRAY_SIZE(arpt_ops); i++)
|
|
||||||
nf_unregister_hook(&arpt_ops[i]);
|
|
||||||
|
|
||||||
arpt_unregister_table(&packet_filter);
|
arpt_unregister_table(&packet_filter);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,37 +9,6 @@
|
||||||
* Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
|
* Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
|
||||||
*
|
*
|
||||||
* For more information, please see http://nath323.sourceforge.net/
|
* 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>
|
#include <linux/config.h>
|
||||||
|
@ -54,8 +23,6 @@
|
||||||
#include <linux/netfilter_ipv4/ip_conntrack_h323.h>
|
#include <linux/netfilter_ipv4/ip_conntrack_h323.h>
|
||||||
#include <linux/moduleparam.h>
|
#include <linux/moduleparam.h>
|
||||||
|
|
||||||
#include "ip_conntrack_helper_h323_asn1.h"
|
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
#define DEBUGP printk
|
#define DEBUGP printk
|
||||||
#else
|
#else
|
||||||
|
@ -63,6 +30,10 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Parameters */
|
/* 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;
|
static int gkrouted_only = 1;
|
||||||
module_param(gkrouted_only, int, 0600);
|
module_param(gkrouted_only, int, 0600);
|
||||||
MODULE_PARM_DESC(gkrouted_only, "only accept calls from gatekeeper");
|
MODULE_PARM_DESC(gkrouted_only, "only accept calls from gatekeeper");
|
||||||
|
@ -222,8 +193,8 @@ static int get_tpkt_data(struct sk_buff **pskb, struct ip_conntrack *ct,
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************/
|
/****************************************************************************/
|
||||||
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)
|
u_int32_t * ip, u_int16_t * port)
|
||||||
{
|
{
|
||||||
unsigned char *p;
|
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);
|
DEBUGP("ip_ct_ras: RRQ TTL = %u seconds\n", rrq->timeToLive);
|
||||||
info->timeout = rrq->timeToLive;
|
info->timeout = rrq->timeToLive;
|
||||||
} else
|
} else
|
||||||
info->timeout = 0;
|
info->timeout = default_rrq_ttl;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -1713,18 +1684,17 @@ static int __init init(void)
|
||||||
module_init(init);
|
module_init(init);
|
||||||
module_exit(fini);
|
module_exit(fini);
|
||||||
|
|
||||||
EXPORT_SYMBOL(get_h245_addr);
|
EXPORT_SYMBOL_GPL(get_h225_addr);
|
||||||
EXPORT_SYMBOL(get_h225_addr);
|
EXPORT_SYMBOL_GPL(ip_conntrack_h245_expect);
|
||||||
EXPORT_SYMBOL(ip_conntrack_h245_expect);
|
EXPORT_SYMBOL_GPL(ip_conntrack_q931_expect);
|
||||||
EXPORT_SYMBOL(ip_conntrack_q931_expect);
|
EXPORT_SYMBOL_GPL(set_h245_addr_hook);
|
||||||
EXPORT_SYMBOL(set_h245_addr_hook);
|
EXPORT_SYMBOL_GPL(set_h225_addr_hook);
|
||||||
EXPORT_SYMBOL(set_h225_addr_hook);
|
EXPORT_SYMBOL_GPL(set_sig_addr_hook);
|
||||||
EXPORT_SYMBOL(set_sig_addr_hook);
|
EXPORT_SYMBOL_GPL(set_ras_addr_hook);
|
||||||
EXPORT_SYMBOL(set_ras_addr_hook);
|
EXPORT_SYMBOL_GPL(nat_rtp_rtcp_hook);
|
||||||
EXPORT_SYMBOL(nat_rtp_rtcp_hook);
|
EXPORT_SYMBOL_GPL(nat_t120_hook);
|
||||||
EXPORT_SYMBOL(nat_t120_hook);
|
EXPORT_SYMBOL_GPL(nat_h245_hook);
|
||||||
EXPORT_SYMBOL(nat_h245_hook);
|
EXPORT_SYMBOL_GPL(nat_q931_hook);
|
||||||
EXPORT_SYMBOL(nat_q931_hook);
|
|
||||||
|
|
||||||
MODULE_AUTHOR("Jing Min Zhao <zhaojingmin@users.sourceforge.net>");
|
MODULE_AUTHOR("Jing Min Zhao <zhaojingmin@users.sourceforge.net>");
|
||||||
MODULE_DESCRIPTION("H.323 connection tracking helper");
|
MODULE_DESCRIPTION("H.323 connection tracking helper");
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
#else
|
#else
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#endif
|
#endif
|
||||||
#include "ip_conntrack_helper_h323_asn1.h"
|
#include <linux/netfilter_ipv4/ip_conntrack_helper_h323_asn1.h>
|
||||||
|
|
||||||
/* Trace Flag */
|
/* Trace Flag */
|
||||||
#ifndef H323_TRACE
|
#ifndef H323_TRACE
|
||||||
|
|
|
@ -224,25 +224,14 @@ icmp_error(struct sk_buff *skb, enum ip_conntrack_info *ctinfo,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* See ip_conntrack_proto_tcp.c */
|
/* See ip_conntrack_proto_tcp.c */
|
||||||
if (hooknum != NF_IP_PRE_ROUTING)
|
if (hooknum == NF_IP_PRE_ROUTING &&
|
||||||
goto checksum_skipped;
|
nf_ip_checksum(skb, hooknum, skb->nh.iph->ihl * 4, 0)) {
|
||||||
|
if (LOG_INVALID(IPPROTO_ICMP))
|
||||||
switch (skb->ip_summed) {
|
nf_log_packet(PF_INET, 0, skb, NULL, NULL, NULL,
|
||||||
case CHECKSUM_HW:
|
"ip_ct_icmp: bad ICMP checksum ");
|
||||||
if (!(u16)csum_fold(skb->csum))
|
return -NF_ACCEPT;
|
||||||
break;
|
|
||||||
/* fall through */
|
|
||||||
case CHECKSUM_NONE:
|
|
||||||
skb->csum = 0;
|
|
||||||
if (__skb_checksum_complete(skb)) {
|
|
||||||
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
|
* 18 is the highest 'known' ICMP type. Anything else is a mystery
|
||||||
*
|
*
|
||||||
|
|
|
@ -870,11 +870,8 @@ static int tcp_error(struct sk_buff *skb,
|
||||||
* and moreover root might send raw packets.
|
* and moreover root might send raw packets.
|
||||||
*/
|
*/
|
||||||
/* FIXME: Source route IP option packets --RR */
|
/* FIXME: Source route IP option packets --RR */
|
||||||
if (hooknum == NF_IP_PRE_ROUTING
|
if (hooknum == NF_IP_PRE_ROUTING &&
|
||||||
&& skb->ip_summed != CHECKSUM_UNNECESSARY
|
nf_ip_checksum(skb, hooknum, iph->ihl * 4, IPPROTO_TCP)) {
|
||||||
&& 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 (LOG_INVALID(IPPROTO_TCP))
|
if (LOG_INVALID(IPPROTO_TCP))
|
||||||
nf_log_packet(PF_INET, 0, skb, NULL, NULL, NULL,
|
nf_log_packet(PF_INET, 0, skb, NULL, NULL, NULL,
|
||||||
"ip_ct_tcp: bad TCP checksum ");
|
"ip_ct_tcp: bad TCP checksum ");
|
||||||
|
|
|
@ -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
|
* because the semantic of CHECKSUM_HW is different there
|
||||||
* and moreover root might send raw packets.
|
* and moreover root might send raw packets.
|
||||||
* FIXME: Source route IP option packets --RR */
|
* FIXME: Source route IP option packets --RR */
|
||||||
if (hooknum == NF_IP_PRE_ROUTING
|
if (hooknum == NF_IP_PRE_ROUTING &&
|
||||||
&& skb->ip_summed != CHECKSUM_UNNECESSARY
|
nf_ip_checksum(skb, hooknum, iph->ihl * 4, IPPROTO_UDP)) {
|
||||||
&& 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 (LOG_INVALID(IPPROTO_UDP))
|
if (LOG_INVALID(IPPROTO_UDP))
|
||||||
nf_log_packet(PF_INET, 0, skb, NULL, NULL, NULL,
|
nf_log_packet(PF_INET, 0, skb, NULL, NULL, NULL,
|
||||||
"ip_ct_udp: bad UDP checksum ");
|
"ip_ct_udp: bad UDP checksum ");
|
||||||
|
|
|
@ -469,70 +469,63 @@ static unsigned int ip_conntrack_local(unsigned int hooknum,
|
||||||
|
|
||||||
/* Connection tracking may drop packets, but never alters them, so
|
/* Connection tracking may drop packets, but never alters them, so
|
||||||
make it the first hook. */
|
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,
|
.hook = ip_conntrack_defrag,
|
||||||
.pf = PF_INET,
|
.owner = THIS_MODULE,
|
||||||
.hooknum = NF_IP_PRE_ROUTING,
|
.pf = PF_INET,
|
||||||
.priority = NF_IP_PRI_CONNTRACK_DEFRAG,
|
.hooknum = NF_IP_PRE_ROUTING,
|
||||||
};
|
.priority = NF_IP_PRI_CONNTRACK_DEFRAG,
|
||||||
|
},
|
||||||
static struct nf_hook_ops ip_conntrack_in_ops = {
|
{
|
||||||
.hook = ip_conntrack_in,
|
.hook = ip_conntrack_in,
|
||||||
.owner = THIS_MODULE,
|
.owner = THIS_MODULE,
|
||||||
.pf = PF_INET,
|
.pf = PF_INET,
|
||||||
.hooknum = NF_IP_PRE_ROUTING,
|
.hooknum = NF_IP_PRE_ROUTING,
|
||||||
.priority = NF_IP_PRI_CONNTRACK,
|
.priority = NF_IP_PRI_CONNTRACK,
|
||||||
};
|
},
|
||||||
|
{
|
||||||
static struct nf_hook_ops ip_conntrack_defrag_local_out_ops = {
|
.hook = ip_conntrack_defrag,
|
||||||
.hook = ip_conntrack_defrag,
|
.owner = THIS_MODULE,
|
||||||
.owner = THIS_MODULE,
|
.pf = PF_INET,
|
||||||
.pf = PF_INET,
|
.hooknum = NF_IP_LOCAL_OUT,
|
||||||
.hooknum = NF_IP_LOCAL_OUT,
|
.priority = NF_IP_PRI_CONNTRACK_DEFRAG,
|
||||||
.priority = NF_IP_PRI_CONNTRACK_DEFRAG,
|
},
|
||||||
};
|
{
|
||||||
|
.hook = ip_conntrack_local,
|
||||||
static struct nf_hook_ops ip_conntrack_local_out_ops = {
|
.owner = THIS_MODULE,
|
||||||
.hook = ip_conntrack_local,
|
.pf = PF_INET,
|
||||||
.owner = THIS_MODULE,
|
.hooknum = NF_IP_LOCAL_OUT,
|
||||||
.pf = PF_INET,
|
.priority = NF_IP_PRI_CONNTRACK,
|
||||||
.hooknum = NF_IP_LOCAL_OUT,
|
},
|
||||||
.priority = NF_IP_PRI_CONNTRACK,
|
{
|
||||||
};
|
.hook = ip_conntrack_help,
|
||||||
|
.owner = THIS_MODULE,
|
||||||
/* helpers */
|
.pf = PF_INET,
|
||||||
static struct nf_hook_ops ip_conntrack_helper_out_ops = {
|
.hooknum = NF_IP_POST_ROUTING,
|
||||||
.hook = ip_conntrack_help,
|
.priority = NF_IP_PRI_CONNTRACK_HELPER,
|
||||||
.owner = THIS_MODULE,
|
},
|
||||||
.pf = PF_INET,
|
{
|
||||||
.hooknum = NF_IP_POST_ROUTING,
|
.hook = ip_conntrack_help,
|
||||||
.priority = NF_IP_PRI_CONNTRACK_HELPER,
|
.owner = THIS_MODULE,
|
||||||
};
|
.pf = PF_INET,
|
||||||
|
.hooknum = NF_IP_LOCAL_IN,
|
||||||
static struct nf_hook_ops ip_conntrack_helper_in_ops = {
|
.priority = NF_IP_PRI_CONNTRACK_HELPER,
|
||||||
.hook = ip_conntrack_help,
|
},
|
||||||
.owner = THIS_MODULE,
|
{
|
||||||
.pf = PF_INET,
|
.hook = ip_confirm,
|
||||||
.hooknum = NF_IP_LOCAL_IN,
|
.owner = THIS_MODULE,
|
||||||
.priority = NF_IP_PRI_CONNTRACK_HELPER,
|
.pf = PF_INET,
|
||||||
};
|
.hooknum = NF_IP_POST_ROUTING,
|
||||||
|
.priority = NF_IP_PRI_CONNTRACK_CONFIRM,
|
||||||
/* Refragmenter; last chance. */
|
},
|
||||||
static struct nf_hook_ops ip_conntrack_out_ops = {
|
{
|
||||||
.hook = ip_confirm,
|
.hook = ip_confirm,
|
||||||
.owner = THIS_MODULE,
|
.owner = THIS_MODULE,
|
||||||
.pf = PF_INET,
|
.pf = PF_INET,
|
||||||
.hooknum = NF_IP_POST_ROUTING,
|
.hooknum = NF_IP_LOCAL_IN,
|
||||||
.priority = NF_IP_PRI_CONNTRACK_CONFIRM,
|
.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 */
|
/* Sysctl support */
|
||||||
|
@ -783,122 +776,6 @@ static ctl_table ip_ct_net_table[] = {
|
||||||
EXPORT_SYMBOL(ip_ct_log_invalid);
|
EXPORT_SYMBOL(ip_ct_log_invalid);
|
||||||
#endif /* CONFIG_SYSCTL */
|
#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
|
/* FIXME: Allow NULL functions and sub in pointers to generic for
|
||||||
them. --RR */
|
them. --RR */
|
||||||
int ip_conntrack_protocol_register(struct ip_conntrack_protocol *proto)
|
int ip_conntrack_protocol_register(struct ip_conntrack_protocol *proto)
|
||||||
|
@ -921,7 +798,7 @@ void ip_conntrack_protocol_unregister(struct ip_conntrack_protocol *proto)
|
||||||
write_lock_bh(&ip_conntrack_lock);
|
write_lock_bh(&ip_conntrack_lock);
|
||||||
ip_ct_protos[proto->proto] = &ip_conntrack_generic_protocol;
|
ip_ct_protos[proto->proto] = &ip_conntrack_generic_protocol;
|
||||||
write_unlock_bh(&ip_conntrack_lock);
|
write_unlock_bh(&ip_conntrack_lock);
|
||||||
|
|
||||||
/* Somebody could be still looking at the proto in bh. */
|
/* Somebody could be still looking at the proto in bh. */
|
||||||
synchronize_net();
|
synchronize_net();
|
||||||
|
|
||||||
|
@ -931,12 +808,77 @@ void ip_conntrack_protocol_unregister(struct ip_conntrack_protocol *proto)
|
||||||
|
|
||||||
static int __init ip_conntrack_standalone_init(void)
|
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)
|
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);
|
module_init(ip_conntrack_standalone_init);
|
||||||
|
|
|
@ -7,24 +7,6 @@
|
||||||
*
|
*
|
||||||
* Based on the 'brute force' H.323 NAT module by
|
* Based on the 'brute force' H.323 NAT module by
|
||||||
* Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
|
* 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>
|
#include <linux/module.h>
|
||||||
|
@ -41,65 +23,12 @@
|
||||||
#include <linux/netfilter_ipv4/ip_conntrack_h323.h>
|
#include <linux/netfilter_ipv4/ip_conntrack_h323.h>
|
||||||
#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
|
#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
|
||||||
|
|
||||||
#include "ip_conntrack_helper_h323_asn1.h"
|
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
#define DEBUGP printk
|
#define DEBUGP printk
|
||||||
#else
|
#else
|
||||||
#define DEBUGP(format, args...)
|
#define DEBUGP(format, args...)
|
||||||
#endif
|
#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,
|
static int set_addr(struct sk_buff **pskb,
|
||||||
unsigned char **data, int dataoff,
|
unsigned char **data, int dataoff,
|
||||||
|
|
|
@ -279,7 +279,7 @@ static struct ipt_target ipt_dnat_reg = {
|
||||||
.target = ipt_dnat_target,
|
.target = ipt_dnat_target,
|
||||||
.targetsize = sizeof(struct ip_nat_multi_range_compat),
|
.targetsize = sizeof(struct ip_nat_multi_range_compat),
|
||||||
.table = "nat",
|
.table = "nat",
|
||||||
.hooks = 1 << NF_IP_PRE_ROUTING,
|
.hooks = (1 << NF_IP_PRE_ROUTING) | (1 << NF_IP_LOCAL_OUT),
|
||||||
.checkentry = ipt_dnat_checkentry,
|
.checkentry = ipt_dnat_checkentry,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -299,69 +299,63 @@ ip_nat_adjust(unsigned int hooknum,
|
||||||
|
|
||||||
/* We must be after connection tracking and before packet filtering. */
|
/* We must be after connection tracking and before packet filtering. */
|
||||||
|
|
||||||
/* Before packet filtering, change destination */
|
static struct nf_hook_ops ip_nat_ops[] = {
|
||||||
static struct nf_hook_ops ip_nat_in_ops = {
|
/* Before packet filtering, change destination */
|
||||||
.hook = ip_nat_in,
|
{
|
||||||
.owner = THIS_MODULE,
|
.hook = ip_nat_in,
|
||||||
.pf = PF_INET,
|
.owner = THIS_MODULE,
|
||||||
.hooknum = NF_IP_PRE_ROUTING,
|
.pf = PF_INET,
|
||||||
.priority = NF_IP_PRI_NAT_DST,
|
.hooknum = NF_IP_PRE_ROUTING,
|
||||||
|
.priority = NF_IP_PRI_NAT_DST,
|
||||||
|
},
|
||||||
|
/* After packet filtering, change source */
|
||||||
|
{
|
||||||
|
.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 */
|
||||||
|
{
|
||||||
|
.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 */
|
||||||
|
{
|
||||||
|
.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 */
|
||||||
|
{
|
||||||
|
.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 */
|
||||||
|
{
|
||||||
|
.hook = ip_nat_adjust,
|
||||||
|
.owner = THIS_MODULE,
|
||||||
|
.pf = PF_INET,
|
||||||
|
.hooknum = NF_IP_LOCAL_IN,
|
||||||
|
.priority = NF_IP_PRI_NAT_SEQ_ADJUST,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
/* After packet filtering, change source */
|
static int __init ip_nat_standalone_init(void)
|
||||||
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 = {
|
|
||||||
.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)
|
|
||||||
{
|
{
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
need_conntrack();
|
need_conntrack();
|
||||||
|
|
||||||
if (!init) goto cleanup;
|
|
||||||
|
|
||||||
#ifdef CONFIG_XFRM
|
#ifdef CONFIG_XFRM
|
||||||
BUG_ON(ip_nat_decode_session != NULL);
|
BUG_ON(ip_nat_decode_session != NULL);
|
||||||
ip_nat_decode_session = nat_decode_session;
|
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");
|
printk("ip_nat_init: can't setup rules.\n");
|
||||||
goto cleanup_decode_session;
|
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) {
|
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;
|
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;
|
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:
|
cleanup_rule_init:
|
||||||
ip_nat_rule_cleanup();
|
ip_nat_rule_cleanup();
|
||||||
cleanup_decode_session:
|
cleanup_decode_session:
|
||||||
|
@ -425,14 +382,14 @@ static int init_or_cleanup(int init)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int __init ip_nat_standalone_init(void)
|
|
||||||
{
|
|
||||||
return init_or_cleanup(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void __exit ip_nat_standalone_fini(void)
|
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);
|
module_init(ip_nat_standalone_init);
|
||||||
|
|
|
@ -662,15 +662,11 @@ static struct nf_queue_handler nfqh = {
|
||||||
.outfn = &ipq_enqueue_packet,
|
.outfn = &ipq_enqueue_packet,
|
||||||
};
|
};
|
||||||
|
|
||||||
static int
|
static int __init ip_queue_init(void)
|
||||||
init_or_cleanup(int init)
|
|
||||||
{
|
{
|
||||||
int status = -ENOMEM;
|
int status = -ENOMEM;
|
||||||
struct proc_dir_entry *proc;
|
struct proc_dir_entry *proc;
|
||||||
|
|
||||||
if (!init)
|
|
||||||
goto cleanup;
|
|
||||||
|
|
||||||
netlink_register_notifier(&ipq_nl_notifier);
|
netlink_register_notifier(&ipq_nl_notifier);
|
||||||
ipqnl = netlink_kernel_create(NETLINK_FIREWALL, 0, ipq_rcv_sk,
|
ipqnl = netlink_kernel_create(NETLINK_FIREWALL, 0, ipq_rcv_sk,
|
||||||
THIS_MODULE);
|
THIS_MODULE);
|
||||||
|
@ -697,11 +693,6 @@ init_or_cleanup(int init)
|
||||||
}
|
}
|
||||||
return status;
|
return status;
|
||||||
|
|
||||||
cleanup:
|
|
||||||
nf_unregister_queue_handlers(&nfqh);
|
|
||||||
synchronize_net();
|
|
||||||
ipq_flush(NF_DROP);
|
|
||||||
|
|
||||||
cleanup_sysctl:
|
cleanup_sysctl:
|
||||||
unregister_sysctl_table(ipq_sysctl_header);
|
unregister_sysctl_table(ipq_sysctl_header);
|
||||||
unregister_netdevice_notifier(&ipq_dev_notifier);
|
unregister_netdevice_notifier(&ipq_dev_notifier);
|
||||||
|
@ -717,15 +708,21 @@ init_or_cleanup(int init)
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int __init ip_queue_init(void)
|
|
||||||
{
|
|
||||||
|
|
||||||
return init_or_cleanup(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void __exit ip_queue_fini(void)
|
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");
|
MODULE_DESCRIPTION("IPv4 packet queue handler");
|
||||||
|
|
|
@ -725,22 +725,17 @@ static struct file_operations clusterip_proc_fops = {
|
||||||
|
|
||||||
#endif /* CONFIG_PROC_FS */
|
#endif /* CONFIG_PROC_FS */
|
||||||
|
|
||||||
static int init_or_cleanup(int fini)
|
static int __init ipt_clusterip_init(void)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if (fini)
|
ret = ipt_register_target(&clusterip_tgt);
|
||||||
goto cleanup;
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
if (ipt_register_target(&clusterip_tgt)) {
|
ret = nf_register_hook(&cip_arp_ops);
|
||||||
ret = -EINVAL;
|
if (ret < 0)
|
||||||
goto cleanup_none;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (nf_register_hook(&cip_arp_ops) < 0) {
|
|
||||||
ret = -EINVAL;
|
|
||||||
goto cleanup_target;
|
goto cleanup_target;
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef CONFIG_PROC_FS
|
#ifdef CONFIG_PROC_FS
|
||||||
clusterip_procdir = proc_mkdir("ipt_CLUSTERIP", proc_net);
|
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",
|
printk(KERN_NOTICE "ClusterIP Version %s loaded successfully\n",
|
||||||
CLUSTERIP_VERSION);
|
CLUSTERIP_VERSION);
|
||||||
|
|
||||||
return 0;
|
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",
|
printk(KERN_NOTICE "ClusterIP Version %s unloading\n",
|
||||||
CLUSTERIP_VERSION);
|
CLUSTERIP_VERSION);
|
||||||
#ifdef CONFIG_PROC_FS
|
#ifdef CONFIG_PROC_FS
|
||||||
remove_proc_entry(clusterip_procdir->name, clusterip_procdir->parent);
|
remove_proc_entry(clusterip_procdir->name, clusterip_procdir->parent);
|
||||||
#endif
|
#endif
|
||||||
cleanup_hook:
|
|
||||||
nf_unregister_hook(&cip_arp_ops);
|
nf_unregister_hook(&cip_arp_ops);
|
||||||
cleanup_target:
|
|
||||||
ipt_unregister_target(&clusterip_tgt);
|
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);
|
module_init(ipt_clusterip_init);
|
||||||
|
|
|
@ -106,7 +106,6 @@ static void send_reset(struct sk_buff *oldskb, int hook)
|
||||||
struct rtable *rt;
|
struct rtable *rt;
|
||||||
u_int16_t tmp_port;
|
u_int16_t tmp_port;
|
||||||
u_int32_t tmp_addr;
|
u_int32_t tmp_addr;
|
||||||
unsigned int tcplen;
|
|
||||||
int needs_ack;
|
int needs_ack;
|
||||||
int hh_len;
|
int hh_len;
|
||||||
|
|
||||||
|
@ -124,13 +123,7 @@ static void send_reset(struct sk_buff *oldskb, int hook)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* Check checksum */
|
/* Check checksum */
|
||||||
tcplen = oldskb->len - iph->ihl * 4;
|
if (nf_ip_checksum(oldskb, hook, iph->ihl * 4, IPPROTO_TCP))
|
||||||
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)))
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if ((rt = route_reverse(oldskb, oth, hook)) == NULL)
|
if ((rt = route_reverse(oldskb, oth, hook)) == NULL)
|
||||||
|
|
|
@ -157,37 +157,20 @@ static int __init iptable_filter_init(void)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
/* Register hooks */
|
/* Register hooks */
|
||||||
ret = nf_register_hook(&ipt_ops[0]);
|
ret = nf_register_hooks(ipt_ops, ARRAY_SIZE(ipt_ops));
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
goto cleanup_table;
|
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;
|
return ret;
|
||||||
|
|
||||||
cleanup_hook1:
|
|
||||||
nf_unregister_hook(&ipt_ops[1]);
|
|
||||||
cleanup_hook0:
|
|
||||||
nf_unregister_hook(&ipt_ops[0]);
|
|
||||||
cleanup_table:
|
cleanup_table:
|
||||||
ipt_unregister_table(&packet_filter);
|
ipt_unregister_table(&packet_filter);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __exit iptable_filter_fini(void)
|
static void __exit iptable_filter_fini(void)
|
||||||
{
|
{
|
||||||
unsigned int i;
|
nf_unregister_hooks(ipt_ops, ARRAY_SIZE(ipt_ops));
|
||||||
|
|
||||||
for (i = 0; i < sizeof(ipt_ops)/sizeof(struct nf_hook_ops); i++)
|
|
||||||
nf_unregister_hook(&ipt_ops[i]);
|
|
||||||
|
|
||||||
ipt_unregister_table(&packet_filter);
|
ipt_unregister_table(&packet_filter);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -211,49 +211,20 @@ static int __init iptable_mangle_init(void)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
/* Register hooks */
|
/* Register hooks */
|
||||||
ret = nf_register_hook(&ipt_ops[0]);
|
ret = nf_register_hooks(ipt_ops, ARRAY_SIZE(ipt_ops));
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
goto cleanup_table;
|
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;
|
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:
|
cleanup_table:
|
||||||
ipt_unregister_table(&packet_mangler);
|
ipt_unregister_table(&packet_mangler);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __exit iptable_mangle_fini(void)
|
static void __exit iptable_mangle_fini(void)
|
||||||
{
|
{
|
||||||
unsigned int i;
|
nf_unregister_hooks(ipt_ops, ARRAY_SIZE(ipt_ops));
|
||||||
|
|
||||||
for (i = 0; i < sizeof(ipt_ops)/sizeof(struct nf_hook_ops); i++)
|
|
||||||
nf_unregister_hook(&ipt_ops[i]);
|
|
||||||
|
|
||||||
ipt_unregister_table(&packet_mangler);
|
ipt_unregister_table(&packet_mangler);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -101,18 +101,18 @@ ipt_hook(unsigned int hook,
|
||||||
/* 'raw' is the very first table. */
|
/* 'raw' is the very first table. */
|
||||||
static struct nf_hook_ops ipt_ops[] = {
|
static struct nf_hook_ops ipt_ops[] = {
|
||||||
{
|
{
|
||||||
.hook = ipt_hook,
|
.hook = ipt_hook,
|
||||||
.pf = PF_INET,
|
.pf = PF_INET,
|
||||||
.hooknum = NF_IP_PRE_ROUTING,
|
.hooknum = NF_IP_PRE_ROUTING,
|
||||||
.priority = NF_IP_PRI_RAW,
|
.priority = NF_IP_PRI_RAW,
|
||||||
.owner = THIS_MODULE,
|
.owner = THIS_MODULE,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
.hook = ipt_hook,
|
.hook = ipt_hook,
|
||||||
.pf = PF_INET,
|
.pf = PF_INET,
|
||||||
.hooknum = NF_IP_LOCAL_OUT,
|
.hooknum = NF_IP_LOCAL_OUT,
|
||||||
.priority = NF_IP_PRI_RAW,
|
.priority = NF_IP_PRI_RAW,
|
||||||
.owner = THIS_MODULE,
|
.owner = THIS_MODULE,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -126,31 +126,20 @@ static int __init iptable_raw_init(void)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
/* Register hooks */
|
/* Register hooks */
|
||||||
ret = nf_register_hook(&ipt_ops[0]);
|
ret = nf_register_hooks(ipt_ops, ARRAY_SIZE(ipt_ops));
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
goto cleanup_table;
|
goto cleanup_table;
|
||||||
|
|
||||||
ret = nf_register_hook(&ipt_ops[1]);
|
|
||||||
if (ret < 0)
|
|
||||||
goto cleanup_hook0;
|
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
cleanup_hook0:
|
|
||||||
nf_unregister_hook(&ipt_ops[0]);
|
|
||||||
cleanup_table:
|
cleanup_table:
|
||||||
ipt_unregister_table(&packet_raw);
|
ipt_unregister_table(&packet_raw);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __exit iptable_raw_fini(void)
|
static void __exit iptable_raw_fini(void)
|
||||||
{
|
{
|
||||||
unsigned int i;
|
nf_unregister_hooks(ipt_ops, ARRAY_SIZE(ipt_ops));
|
||||||
|
|
||||||
for (i = 0; i < sizeof(ipt_ops)/sizeof(struct nf_hook_ops); i++)
|
|
||||||
nf_unregister_hook(&ipt_ops[i]);
|
|
||||||
|
|
||||||
ipt_unregister_table(&packet_raw);
|
ipt_unregister_table(&packet_raw);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -210,71 +210,63 @@ static unsigned int ipv4_conntrack_local(unsigned int hooknum,
|
||||||
|
|
||||||
/* Connection tracking may drop packets, but never alters them, so
|
/* Connection tracking may drop packets, but never alters them, so
|
||||||
make it the first hook. */
|
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,
|
.hook = ipv4_conntrack_defrag,
|
||||||
.pf = PF_INET,
|
.owner = THIS_MODULE,
|
||||||
.hooknum = NF_IP_PRE_ROUTING,
|
.pf = PF_INET,
|
||||||
.priority = NF_IP_PRI_CONNTRACK_DEFRAG,
|
.hooknum = NF_IP_PRE_ROUTING,
|
||||||
};
|
.priority = NF_IP_PRI_CONNTRACK_DEFRAG,
|
||||||
|
},
|
||||||
static struct nf_hook_ops ipv4_conntrack_in_ops = {
|
{
|
||||||
.hook = ipv4_conntrack_in,
|
.hook = ipv4_conntrack_in,
|
||||||
.owner = THIS_MODULE,
|
.owner = THIS_MODULE,
|
||||||
.pf = PF_INET,
|
.pf = PF_INET,
|
||||||
.hooknum = NF_IP_PRE_ROUTING,
|
.hooknum = NF_IP_PRE_ROUTING,
|
||||||
.priority = NF_IP_PRI_CONNTRACK,
|
.priority = NF_IP_PRI_CONNTRACK,
|
||||||
};
|
},
|
||||||
|
{
|
||||||
static struct nf_hook_ops ipv4_conntrack_defrag_local_out_ops = {
|
.hook = ipv4_conntrack_defrag,
|
||||||
.hook = ipv4_conntrack_defrag,
|
.owner = THIS_MODULE,
|
||||||
.owner = THIS_MODULE,
|
.pf = PF_INET,
|
||||||
.pf = PF_INET,
|
.hooknum = NF_IP_LOCAL_OUT,
|
||||||
.hooknum = NF_IP_LOCAL_OUT,
|
.priority = NF_IP_PRI_CONNTRACK_DEFRAG,
|
||||||
.priority = NF_IP_PRI_CONNTRACK_DEFRAG,
|
},
|
||||||
};
|
{
|
||||||
|
.hook = ipv4_conntrack_local,
|
||||||
static struct nf_hook_ops ipv4_conntrack_local_out_ops = {
|
.owner = THIS_MODULE,
|
||||||
.hook = ipv4_conntrack_local,
|
.pf = PF_INET,
|
||||||
.owner = THIS_MODULE,
|
.hooknum = NF_IP_LOCAL_OUT,
|
||||||
.pf = PF_INET,
|
.priority = NF_IP_PRI_CONNTRACK,
|
||||||
.hooknum = NF_IP_LOCAL_OUT,
|
},
|
||||||
.priority = NF_IP_PRI_CONNTRACK,
|
{
|
||||||
};
|
.hook = ipv4_conntrack_help,
|
||||||
|
.owner = THIS_MODULE,
|
||||||
/* helpers */
|
.pf = PF_INET,
|
||||||
static struct nf_hook_ops ipv4_conntrack_helper_out_ops = {
|
.hooknum = NF_IP_POST_ROUTING,
|
||||||
.hook = ipv4_conntrack_help,
|
.priority = NF_IP_PRI_CONNTRACK_HELPER,
|
||||||
.owner = THIS_MODULE,
|
},
|
||||||
.pf = PF_INET,
|
{
|
||||||
.hooknum = NF_IP_POST_ROUTING,
|
.hook = ipv4_conntrack_help,
|
||||||
.priority = NF_IP_PRI_CONNTRACK_HELPER,
|
.owner = THIS_MODULE,
|
||||||
};
|
.pf = PF_INET,
|
||||||
|
.hooknum = NF_IP_LOCAL_IN,
|
||||||
static struct nf_hook_ops ipv4_conntrack_helper_in_ops = {
|
.priority = NF_IP_PRI_CONNTRACK_HELPER,
|
||||||
.hook = ipv4_conntrack_help,
|
},
|
||||||
.owner = THIS_MODULE,
|
{
|
||||||
.pf = PF_INET,
|
.hook = ipv4_confirm,
|
||||||
.hooknum = NF_IP_LOCAL_IN,
|
.owner = THIS_MODULE,
|
||||||
.priority = NF_IP_PRI_CONNTRACK_HELPER,
|
.pf = PF_INET,
|
||||||
};
|
.hooknum = NF_IP_POST_ROUTING,
|
||||||
|
.priority = NF_IP_PRI_CONNTRACK_CONFIRM,
|
||||||
|
},
|
||||||
/* Refragmenter; last chance. */
|
{
|
||||||
static struct nf_hook_ops ipv4_conntrack_out_ops = {
|
.hook = ipv4_confirm,
|
||||||
.hook = ipv4_confirm,
|
.owner = THIS_MODULE,
|
||||||
.owner = THIS_MODULE,
|
.pf = PF_INET,
|
||||||
.pf = PF_INET,
|
.hooknum = NF_IP_LOCAL_IN,
|
||||||
.hooknum = NF_IP_POST_ROUTING,
|
.priority = NF_IP_PRI_CONNTRACK_CONFIRM,
|
||||||
.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
|
#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_tcp4;
|
||||||
extern struct nf_conntrack_protocol nf_conntrack_protocol_udp4;
|
extern struct nf_conntrack_protocol nf_conntrack_protocol_udp4;
|
||||||
extern struct nf_conntrack_protocol nf_conntrack_protocol_icmp;
|
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;
|
int ret = 0;
|
||||||
|
|
||||||
if (!init) goto cleanup;
|
need_conntrack();
|
||||||
|
|
||||||
ret = nf_register_sockopt(&so_getorigdst);
|
ret = nf_register_sockopt(&so_getorigdst);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
printk(KERN_ERR "Unable to register netfilter socket option\n");
|
printk(KERN_ERR "Unable to register netfilter socket option\n");
|
||||||
goto cleanup_nothing;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = nf_conntrack_protocol_register(&nf_conntrack_protocol_tcp4);
|
ret = nf_conntrack_protocol_register(&nf_conntrack_protocol_tcp4);
|
||||||
|
@ -476,84 +472,26 @@ static int init_or_cleanup(int init)
|
||||||
goto cleanup_icmp;
|
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) {
|
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;
|
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
|
#ifdef CONFIG_SYSCTL
|
||||||
nf_ct_ipv4_sysctl_header = register_sysctl_table(nf_ct_net_table, 0);
|
nf_ct_ipv4_sysctl_header = register_sysctl_table(nf_ct_net_table, 0);
|
||||||
if (nf_ct_ipv4_sysctl_header == NULL) {
|
if (nf_ct_ipv4_sysctl_header == NULL) {
|
||||||
printk("nf_conntrack: can't register to sysctl.\n");
|
printk("nf_conntrack: can't register to sysctl.\n");
|
||||||
ret = -ENOMEM;
|
ret = -ENOMEM;
|
||||||
goto cleanup_localinops;
|
goto cleanup_hooks;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
cleanup:
|
|
||||||
synchronize_net();
|
|
||||||
#ifdef CONFIG_SYSCTL
|
#ifdef CONFIG_SYSCTL
|
||||||
unregister_sysctl_table(nf_ct_ipv4_sysctl_header);
|
cleanup_hooks:
|
||||||
cleanup_localinops:
|
nf_unregister_hooks(ipv4_conntrack_ops, ARRAY_SIZE(ipv4_conntrack_ops));
|
||||||
#endif
|
#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:
|
cleanup_ipv4:
|
||||||
nf_conntrack_l3proto_unregister(&nf_conntrack_l3proto_ipv4);
|
nf_conntrack_l3proto_unregister(&nf_conntrack_l3proto_ipv4);
|
||||||
cleanup_icmp:
|
cleanup_icmp:
|
||||||
|
@ -564,22 +502,21 @@ static int init_or_cleanup(int init)
|
||||||
nf_conntrack_protocol_unregister(&nf_conntrack_protocol_tcp4);
|
nf_conntrack_protocol_unregister(&nf_conntrack_protocol_tcp4);
|
||||||
cleanup_sockopt:
|
cleanup_sockopt:
|
||||||
nf_unregister_sockopt(&so_getorigdst);
|
nf_unregister_sockopt(&so_getorigdst);
|
||||||
cleanup_nothing:
|
|
||||||
return ret;
|
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)
|
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);
|
module_init(nf_conntrack_l3proto_ipv4_init);
|
||||||
|
|
|
@ -235,30 +235,14 @@ icmp_error(struct sk_buff *skb, unsigned int dataoff,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* See ip_conntrack_proto_tcp.c */
|
/* See ip_conntrack_proto_tcp.c */
|
||||||
if (hooknum != NF_IP_PRE_ROUTING)
|
if (hooknum == NF_IP_PRE_ROUTING &&
|
||||||
goto checksum_skipped;
|
nf_ip_checksum(skb, hooknum, dataoff, 0)) {
|
||||||
|
|
||||||
switch (skb->ip_summed) {
|
|
||||||
case CHECKSUM_HW:
|
|
||||||
if (!(u16)csum_fold(skb->csum))
|
|
||||||
break;
|
|
||||||
if (LOG_INVALID(IPPROTO_ICMP))
|
if (LOG_INVALID(IPPROTO_ICMP))
|
||||||
nf_log_packet(PF_INET, 0, skb, NULL, NULL, NULL,
|
nf_log_packet(PF_INET, 0, skb, NULL, NULL, NULL,
|
||||||
"nf_ct_icmp: bad HW ICMP checksum ");
|
"nf_ct_icmp: bad HW ICMP checksum ");
|
||||||
return -NF_ACCEPT;
|
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
|
* 18 is the highest 'known' ICMP type. Anything else is a mystery
|
||||||
*
|
*
|
||||||
|
|
|
@ -8,6 +8,8 @@
|
||||||
#include <linux/mutex.h>
|
#include <linux/mutex.h>
|
||||||
#include <linux/netdevice.h>
|
#include <linux/netdevice.h>
|
||||||
#include <linux/skbuff.h>
|
#include <linux/skbuff.h>
|
||||||
|
#include <net/icmp.h>
|
||||||
|
#include <net/ip.h>
|
||||||
#include <net/protocol.h>
|
#include <net/protocol.h>
|
||||||
#include <net/xfrm.h>
|
#include <net/xfrm.h>
|
||||||
|
|
||||||
|
@ -70,10 +72,16 @@ static int tunnel4_rcv(struct sk_buff *skb)
|
||||||
{
|
{
|
||||||
struct xfrm_tunnel *handler;
|
struct xfrm_tunnel *handler;
|
||||||
|
|
||||||
|
if (!pskb_may_pull(skb, sizeof(struct iphdr)))
|
||||||
|
goto drop;
|
||||||
|
|
||||||
for (handler = tunnel4_handlers; handler; handler = handler->next)
|
for (handler = tunnel4_handlers; handler; handler = handler->next)
|
||||||
if (!handler->handler(skb))
|
if (!handler->handler(skb))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0);
|
||||||
|
|
||||||
|
drop:
|
||||||
kfree_skb(skb);
|
kfree_skb(skb);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,8 +37,6 @@ static int xfrm4_parse_spi(struct sk_buff *skb, u8 nexthdr, u32 *spi, u32 *seq)
|
||||||
{
|
{
|
||||||
switch (nexthdr) {
|
switch (nexthdr) {
|
||||||
case IPPROTO_IPIP:
|
case IPPROTO_IPIP:
|
||||||
if (!pskb_may_pull(skb, sizeof(struct iphdr)))
|
|
||||||
return -EINVAL;
|
|
||||||
*spi = skb->nh.iph->saddr;
|
*spi = skb->nh.iph->saddr;
|
||||||
*seq = 0;
|
*seq = 0;
|
||||||
return 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))
|
if (unlikely(x->km.state != XFRM_STATE_VALID))
|
||||||
goto drop_unlock;
|
goto drop_unlock;
|
||||||
|
|
||||||
if (x->encap->encap_type != encap_type)
|
if ((x->encap ? x->encap->encap_type : 0) != encap_type)
|
||||||
goto drop_unlock;
|
goto drop_unlock;
|
||||||
|
|
||||||
if (x->props.replay_window && xfrm_replay_check(x, seq))
|
if (x->props.replay_window && xfrm_replay_check(x, seq))
|
||||||
|
|
|
@ -23,6 +23,86 @@
|
||||||
#include <net/inet6_hashtables.h>
|
#include <net/inet6_hashtables.h>
|
||||||
#include <net/ip.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,
|
struct sock *inet6_lookup_listener(struct inet_hashinfo *hashinfo,
|
||||||
const struct in6_addr *daddr,
|
const struct in6_addr *daddr,
|
||||||
const unsigned short hnum, const int dif)
|
const unsigned short hnum, const int dif)
|
||||||
|
|
|
@ -519,9 +519,6 @@ ip6ip6_rcv(struct sk_buff *skb)
|
||||||
struct ipv6hdr *ipv6h;
|
struct ipv6hdr *ipv6h;
|
||||||
struct ip6_tnl *t;
|
struct ip6_tnl *t;
|
||||||
|
|
||||||
if (!pskb_may_pull(skb, sizeof (*ipv6h)))
|
|
||||||
goto discard;
|
|
||||||
|
|
||||||
ipv6h = skb->nh.ipv6h;
|
ipv6h = skb->nh.ipv6h;
|
||||||
|
|
||||||
read_lock(&ip6ip6_lock);
|
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 ((t = ip6ip6_tnl_lookup(&ipv6h->saddr, &ipv6h->daddr)) != NULL) {
|
||||||
if (!xfrm6_policy_check(NULL, XFRM_POLICY_IN, skb)) {
|
if (!xfrm6_policy_check(NULL, XFRM_POLICY_IN, skb)) {
|
||||||
read_unlock(&ip6ip6_lock);
|
read_unlock(&ip6ip6_lock);
|
||||||
kfree_skb(skb);
|
goto discard;
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(t->parms.flags & IP6_TNL_F_CAP_RCV)) {
|
if (!(t->parms.flags & IP6_TNL_F_CAP_RCV)) {
|
||||||
|
@ -557,9 +553,11 @@ ip6ip6_rcv(struct sk_buff *skb)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
read_unlock(&ip6ip6_lock);
|
read_unlock(&ip6ip6_lock);
|
||||||
icmpv6_send(skb, ICMPV6_DEST_UNREACH, ICMPV6_ADDR_UNREACH, 0, skb->dev);
|
|
||||||
discard:
|
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
|
discard:
|
||||||
|
kfree_skb(skb);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline struct ipv6_txoptions *create_tel(__u8 encap_limit)
|
static inline struct ipv6_txoptions *create_tel(__u8 encap_limit)
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
#include <net/ipv6.h>
|
#include <net/ipv6.h>
|
||||||
#include <net/ip6_route.h>
|
#include <net/ip6_route.h>
|
||||||
#include <net/xfrm.h>
|
#include <net/xfrm.h>
|
||||||
|
#include <net/ip6_checksum.h>
|
||||||
|
|
||||||
int ip6_route_me_harder(struct sk_buff *skb)
|
int ip6_route_me_harder(struct sk_buff *skb)
|
||||||
{
|
{
|
||||||
|
@ -54,7 +55,7 @@ struct ip6_rt_info {
|
||||||
struct in6_addr saddr;
|
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);
|
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);
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct nf_queue_rerouter ip6_reroute = {
|
unsigned int nf_ip6_checksum(struct sk_buff *skb, unsigned int hook,
|
||||||
.rer_size = sizeof(struct ip6_rt_info),
|
unsigned int dataoff, u_int8_t protocol)
|
||||||
.save = &save,
|
{
|
||||||
.reroute = &reroute,
|
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)
|
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
|
/* 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)
|
void ipv6_netfilter_fini(void)
|
||||||
{
|
{
|
||||||
nf_unregister_queue_rerouter(PF_INET6);
|
nf_unregister_afinfo(&nf_ip6_afinfo);
|
||||||
}
|
}
|
||||||
|
|
|
@ -658,15 +658,11 @@ static struct nf_queue_handler nfqh = {
|
||||||
.outfn = &ipq_enqueue_packet,
|
.outfn = &ipq_enqueue_packet,
|
||||||
};
|
};
|
||||||
|
|
||||||
static int
|
static int __init ip6_queue_init(void)
|
||||||
init_or_cleanup(int init)
|
|
||||||
{
|
{
|
||||||
int status = -ENOMEM;
|
int status = -ENOMEM;
|
||||||
struct proc_dir_entry *proc;
|
struct proc_dir_entry *proc;
|
||||||
|
|
||||||
if (!init)
|
|
||||||
goto cleanup;
|
|
||||||
|
|
||||||
netlink_register_notifier(&ipq_nl_notifier);
|
netlink_register_notifier(&ipq_nl_notifier);
|
||||||
ipqnl = netlink_kernel_create(NETLINK_IP6_FW, 0, ipq_rcv_sk,
|
ipqnl = netlink_kernel_create(NETLINK_IP6_FW, 0, ipq_rcv_sk,
|
||||||
THIS_MODULE);
|
THIS_MODULE);
|
||||||
|
@ -693,11 +689,6 @@ init_or_cleanup(int init)
|
||||||
}
|
}
|
||||||
return status;
|
return status;
|
||||||
|
|
||||||
cleanup:
|
|
||||||
nf_unregister_queue_handlers(&nfqh);
|
|
||||||
synchronize_net();
|
|
||||||
ipq_flush(NF_DROP);
|
|
||||||
|
|
||||||
cleanup_sysctl:
|
cleanup_sysctl:
|
||||||
unregister_sysctl_table(ipq_sysctl_header);
|
unregister_sysctl_table(ipq_sysctl_header);
|
||||||
unregister_netdevice_notifier(&ipq_dev_notifier);
|
unregister_netdevice_notifier(&ipq_dev_notifier);
|
||||||
|
@ -713,15 +704,21 @@ init_or_cleanup(int init)
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int __init ip6_queue_init(void)
|
|
||||||
{
|
|
||||||
|
|
||||||
return init_or_cleanup(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void __exit ip6_queue_fini(void)
|
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");
|
MODULE_DESCRIPTION("IPv6 packet queue handler");
|
||||||
|
|
|
@ -177,37 +177,20 @@ static int __init ip6table_filter_init(void)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
/* Register hooks */
|
/* Register hooks */
|
||||||
ret = nf_register_hook(&ip6t_ops[0]);
|
ret = nf_register_hooks(ip6t_ops, ARRAY_SIZE(ip6t_ops));
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
goto cleanup_table;
|
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;
|
return ret;
|
||||||
|
|
||||||
cleanup_hook1:
|
|
||||||
nf_unregister_hook(&ip6t_ops[1]);
|
|
||||||
cleanup_hook0:
|
|
||||||
nf_unregister_hook(&ip6t_ops[0]);
|
|
||||||
cleanup_table:
|
cleanup_table:
|
||||||
ip6t_unregister_table(&packet_filter);
|
ip6t_unregister_table(&packet_filter);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __exit ip6table_filter_fini(void)
|
static void __exit ip6table_filter_fini(void)
|
||||||
{
|
{
|
||||||
unsigned int i;
|
nf_unregister_hooks(ip6t_ops, ARRAY_SIZE(ip6t_ops));
|
||||||
|
|
||||||
for (i = 0; i < sizeof(ip6t_ops)/sizeof(struct nf_hook_ops); i++)
|
|
||||||
nf_unregister_hook(&ip6t_ops[i]);
|
|
||||||
|
|
||||||
ip6t_unregister_table(&packet_filter);
|
ip6t_unregister_table(&packet_filter);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -238,49 +238,20 @@ static int __init ip6table_mangle_init(void)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
/* Register hooks */
|
/* Register hooks */
|
||||||
ret = nf_register_hook(&ip6t_ops[0]);
|
ret = nf_register_hooks(ip6t_ops, ARRAY_SIZE(ip6t_ops));
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
goto cleanup_table;
|
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;
|
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:
|
cleanup_table:
|
||||||
ip6t_unregister_table(&packet_mangler);
|
ip6t_unregister_table(&packet_mangler);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __exit ip6table_mangle_fini(void)
|
static void __exit ip6table_mangle_fini(void)
|
||||||
{
|
{
|
||||||
unsigned int i;
|
nf_unregister_hooks(ip6t_ops, ARRAY_SIZE(ip6t_ops));
|
||||||
|
|
||||||
for (i = 0; i < sizeof(ip6t_ops)/sizeof(struct nf_hook_ops); i++)
|
|
||||||
nf_unregister_hook(&ip6t_ops[i]);
|
|
||||||
|
|
||||||
ip6t_unregister_table(&packet_mangler);
|
ip6t_unregister_table(&packet_mangler);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -152,31 +152,20 @@ static int __init ip6table_raw_init(void)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
/* Register hooks */
|
/* Register hooks */
|
||||||
ret = nf_register_hook(&ip6t_ops[0]);
|
ret = nf_register_hooks(ip6t_ops, ARRAY_SIZE(ip6t_ops));
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
goto cleanup_table;
|
goto cleanup_table;
|
||||||
|
|
||||||
ret = nf_register_hook(&ip6t_ops[1]);
|
|
||||||
if (ret < 0)
|
|
||||||
goto cleanup_hook0;
|
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
cleanup_hook0:
|
|
||||||
nf_unregister_hook(&ip6t_ops[0]);
|
|
||||||
cleanup_table:
|
cleanup_table:
|
||||||
ip6t_unregister_table(&packet_raw);
|
ip6t_unregister_table(&packet_raw);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __exit ip6table_raw_fini(void)
|
static void __exit ip6table_raw_fini(void)
|
||||||
{
|
{
|
||||||
unsigned int i;
|
nf_unregister_hooks(ip6t_ops, ARRAY_SIZE(ip6t_ops));
|
||||||
|
|
||||||
for (i = 0; i < sizeof(ip6t_ops)/sizeof(struct nf_hook_ops); i++)
|
|
||||||
nf_unregister_hook(&ip6t_ops[i]);
|
|
||||||
|
|
||||||
ip6t_unregister_table(&packet_raw);
|
ip6t_unregister_table(&packet_raw);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -286,55 +286,49 @@ static unsigned int ipv6_conntrack_local(unsigned int hooknum,
|
||||||
return ipv6_conntrack_in(hooknum, pskb, in, out, okfn);
|
return ipv6_conntrack_in(hooknum, pskb, in, out, okfn);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Connection tracking may drop packets, but never alters them, so
|
static struct nf_hook_ops ipv6_conntrack_ops[] = {
|
||||||
make it the first hook. */
|
{
|
||||||
static struct nf_hook_ops ipv6_conntrack_defrag_ops = {
|
.hook = ipv6_defrag,
|
||||||
.hook = ipv6_defrag,
|
.owner = THIS_MODULE,
|
||||||
.owner = THIS_MODULE,
|
.pf = PF_INET6,
|
||||||
.pf = PF_INET6,
|
.hooknum = NF_IP6_PRE_ROUTING,
|
||||||
.hooknum = NF_IP6_PRE_ROUTING,
|
.priority = NF_IP6_PRI_CONNTRACK_DEFRAG,
|
||||||
.priority = NF_IP6_PRI_CONNTRACK_DEFRAG,
|
},
|
||||||
};
|
{
|
||||||
|
.hook = ipv6_conntrack_in,
|
||||||
static struct nf_hook_ops ipv6_conntrack_in_ops = {
|
.owner = THIS_MODULE,
|
||||||
.hook = ipv6_conntrack_in,
|
.pf = PF_INET6,
|
||||||
.owner = THIS_MODULE,
|
.hooknum = NF_IP6_PRE_ROUTING,
|
||||||
.pf = PF_INET6,
|
.priority = NF_IP6_PRI_CONNTRACK,
|
||||||
.hooknum = NF_IP6_PRE_ROUTING,
|
},
|
||||||
.priority = NF_IP6_PRI_CONNTRACK,
|
{
|
||||||
};
|
.hook = ipv6_conntrack_local,
|
||||||
|
.owner = THIS_MODULE,
|
||||||
static struct nf_hook_ops ipv6_conntrack_local_out_ops = {
|
.pf = PF_INET6,
|
||||||
.hook = ipv6_conntrack_local,
|
.hooknum = NF_IP6_LOCAL_OUT,
|
||||||
.owner = THIS_MODULE,
|
.priority = NF_IP6_PRI_CONNTRACK,
|
||||||
.pf = PF_INET6,
|
},
|
||||||
.hooknum = NF_IP6_LOCAL_OUT,
|
{
|
||||||
.priority = NF_IP6_PRI_CONNTRACK,
|
.hook = ipv6_defrag,
|
||||||
};
|
.owner = THIS_MODULE,
|
||||||
|
.pf = PF_INET6,
|
||||||
static struct nf_hook_ops ipv6_conntrack_defrag_local_out_ops = {
|
.hooknum = NF_IP6_LOCAL_OUT,
|
||||||
.hook = ipv6_defrag,
|
.priority = NF_IP6_PRI_CONNTRACK_DEFRAG,
|
||||||
.owner = THIS_MODULE,
|
},
|
||||||
.pf = PF_INET6,
|
{
|
||||||
.hooknum = NF_IP6_LOCAL_OUT,
|
.hook = ipv6_confirm,
|
||||||
.priority = NF_IP6_PRI_CONNTRACK_DEFRAG,
|
.owner = THIS_MODULE,
|
||||||
};
|
.pf = PF_INET6,
|
||||||
|
.hooknum = NF_IP6_POST_ROUTING,
|
||||||
/* Refragmenter; last chance. */
|
.priority = NF_IP6_PRI_LAST,
|
||||||
static struct nf_hook_ops ipv6_conntrack_out_ops = {
|
},
|
||||||
.hook = ipv6_confirm,
|
{
|
||||||
.owner = THIS_MODULE,
|
.hook = ipv6_confirm,
|
||||||
.pf = PF_INET6,
|
.owner = THIS_MODULE,
|
||||||
.hooknum = NF_IP6_POST_ROUTING,
|
.pf = PF_INET6,
|
||||||
.priority = NF_IP6_PRI_LAST,
|
.hooknum = NF_IP6_LOCAL_IN,
|
||||||
};
|
.priority = NF_IP6_PRI_LAST-1,
|
||||||
|
},
|
||||||
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
|
#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 struct nf_conntrack_protocol nf_conntrack_protocol_icmpv6;
|
||||||
extern int nf_ct_frag6_init(void);
|
extern int nf_ct_frag6_init(void);
|
||||||
extern void nf_ct_frag6_cleanup(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;
|
int ret = 0;
|
||||||
|
|
||||||
if (!init) goto cleanup;
|
need_conntrack();
|
||||||
|
|
||||||
ret = nf_ct_frag6_init();
|
ret = nf_ct_frag6_init();
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
printk("nf_conntrack_ipv6: can't initialize frag6.\n");
|
printk("nf_conntrack_ipv6: can't initialize frag6.\n");
|
||||||
goto cleanup_nothing;
|
return ret;
|
||||||
}
|
}
|
||||||
ret = nf_conntrack_protocol_register(&nf_conntrack_protocol_tcp6);
|
ret = nf_conntrack_protocol_register(&nf_conntrack_protocol_tcp6);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
|
@ -505,71 +504,27 @@ static int init_or_cleanup(int init)
|
||||||
goto cleanup_icmpv6;
|
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) {
|
if (ret < 0) {
|
||||||
printk("nf_conntrack_ipv6: can't register pre-routing defrag "
|
printk("nf_conntrack_ipv6: can't register pre-routing defrag "
|
||||||
"hook.\n");
|
"hook.\n");
|
||||||
goto cleanup_ipv6;
|
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
|
#ifdef CONFIG_SYSCTL
|
||||||
nf_ct_ipv6_sysctl_header = register_sysctl_table(nf_ct_net_table, 0);
|
nf_ct_ipv6_sysctl_header = register_sysctl_table(nf_ct_net_table, 0);
|
||||||
if (nf_ct_ipv6_sysctl_header == NULL) {
|
if (nf_ct_ipv6_sysctl_header == NULL) {
|
||||||
printk("nf_conntrack: can't register to sysctl.\n");
|
printk("nf_conntrack: can't register to sysctl.\n");
|
||||||
ret = -ENOMEM;
|
ret = -ENOMEM;
|
||||||
goto cleanup_localinops;
|
goto cleanup_hooks;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
cleanup:
|
|
||||||
synchronize_net();
|
|
||||||
#ifdef CONFIG_SYSCTL
|
#ifdef CONFIG_SYSCTL
|
||||||
unregister_sysctl_table(nf_ct_ipv6_sysctl_header);
|
cleanup_hooks:
|
||||||
cleanup_localinops:
|
nf_unregister_hooks(ipv6_conntrack_ops, ARRAY_SIZE(ipv6_conntrack_ops));
|
||||||
#endif
|
#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:
|
cleanup_ipv6:
|
||||||
nf_conntrack_l3proto_unregister(&nf_conntrack_l3proto_ipv6);
|
nf_conntrack_l3proto_unregister(&nf_conntrack_l3proto_ipv6);
|
||||||
cleanup_icmpv6:
|
cleanup_icmpv6:
|
||||||
|
@ -580,23 +535,21 @@ static int init_or_cleanup(int init)
|
||||||
nf_conntrack_protocol_unregister(&nf_conntrack_protocol_tcp6);
|
nf_conntrack_protocol_unregister(&nf_conntrack_protocol_tcp6);
|
||||||
cleanup_frag6:
|
cleanup_frag6:
|
||||||
nf_ct_frag6_cleanup();
|
nf_ct_frag6_cleanup();
|
||||||
cleanup_nothing:
|
|
||||||
return ret;
|
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)
|
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);
|
module_init(nf_conntrack_l3proto_ipv6_init);
|
||||||
|
|
|
@ -233,21 +233,13 @@ icmpv6_error(struct sk_buff *skb, unsigned int dataoff,
|
||||||
return -NF_ACCEPT;
|
return -NF_ACCEPT;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hooknum != NF_IP6_PRE_ROUTING)
|
if (hooknum == NF_IP6_PRE_ROUTING &&
|
||||||
goto skipped;
|
nf_ip6_checksum(skb, hooknum, dataoff, IPPROTO_ICMPV6)) {
|
||||||
|
|
||||||
/* 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))) {
|
|
||||||
nf_log_packet(PF_INET6, 0, skb, NULL, NULL, NULL,
|
nf_log_packet(PF_INET6, 0, skb, NULL, NULL, NULL,
|
||||||
"nf_ct_icmpv6: ICMPv6 checksum failed\n");
|
"nf_ct_icmpv6: ICMPv6 checksum failed\n");
|
||||||
return -NF_ACCEPT;
|
return -NF_ACCEPT;
|
||||||
}
|
}
|
||||||
|
|
||||||
skipped:
|
|
||||||
|
|
||||||
/* is not error message ? */
|
/* is not error message ? */
|
||||||
if (icmp6h->icmp6_type >= 128)
|
if (icmp6h->icmp6_type >= 128)
|
||||||
return NF_ACCEPT;
|
return NF_ACCEPT;
|
||||||
|
|
|
@ -397,7 +397,7 @@ static int ipip6_rcv(struct sk_buff *skb)
|
||||||
return 0;
|
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);
|
kfree_skb(skb);
|
||||||
read_unlock(&ipip6_lock);
|
read_unlock(&ipip6_lock);
|
||||||
out:
|
out:
|
||||||
|
|
|
@ -19,11 +19,13 @@
|
||||||
* YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
|
* YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <linux/icmpv6.h>
|
||||||
#include <linux/init.h>
|
#include <linux/init.h>
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/mutex.h>
|
#include <linux/mutex.h>
|
||||||
#include <linux/netdevice.h>
|
#include <linux/netdevice.h>
|
||||||
#include <linux/skbuff.h>
|
#include <linux/skbuff.h>
|
||||||
|
#include <net/ipv6.h>
|
||||||
#include <net/protocol.h>
|
#include <net/protocol.h>
|
||||||
#include <net/xfrm.h>
|
#include <net/xfrm.h>
|
||||||
|
|
||||||
|
@ -87,10 +89,16 @@ static int tunnel6_rcv(struct sk_buff **pskb)
|
||||||
struct sk_buff *skb = *pskb;
|
struct sk_buff *skb = *pskb;
|
||||||
struct xfrm6_tunnel *handler;
|
struct xfrm6_tunnel *handler;
|
||||||
|
|
||||||
|
if (!pskb_may_pull(skb, sizeof(struct ipv6hdr)))
|
||||||
|
goto drop;
|
||||||
|
|
||||||
for (handler = tunnel6_handlers; handler; handler = handler->next)
|
for (handler = tunnel6_handlers; handler; handler = handler->next)
|
||||||
if (!handler->handler(skb))
|
if (!handler->handler(skb))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
icmpv6_send(skb, ICMPV6_DEST_UNREACH, ICMPV6_PORT_UNREACH, 0, skb->dev);
|
||||||
|
|
||||||
|
drop:
|
||||||
kfree_skb(skb);
|
kfree_skb(skb);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,6 +27,29 @@
|
||||||
|
|
||||||
#include "nf_internals.h"
|
#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
|
/* 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
|
* 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
|
* 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);
|
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(®[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(®[i]);
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(nf_unregister_hooks);
|
||||||
|
|
||||||
unsigned int nf_iterate(struct list_head *head,
|
unsigned int nf_iterate(struct list_head *head,
|
||||||
struct sk_buff **skb,
|
struct sk_buff **skb,
|
||||||
int hook,
|
int hook,
|
||||||
|
|
|
@ -799,8 +799,7 @@ static int tcp_error(struct sk_buff *skb,
|
||||||
unsigned int dataoff,
|
unsigned int dataoff,
|
||||||
enum ip_conntrack_info *ctinfo,
|
enum ip_conntrack_info *ctinfo,
|
||||||
int pf,
|
int pf,
|
||||||
unsigned int hooknum,
|
unsigned int hooknum)
|
||||||
int(*csum)(const struct sk_buff *,unsigned int))
|
|
||||||
{
|
{
|
||||||
struct tcphdr _tcph, *th;
|
struct tcphdr _tcph, *th;
|
||||||
unsigned int tcplen = skb->len - dataoff;
|
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 */
|
/* FIXME: Source route IP option packets --RR */
|
||||||
if (((pf == PF_INET && hooknum == NF_IP_PRE_ROUTING) ||
|
if (((pf == PF_INET && hooknum == NF_IP_PRE_ROUTING) ||
|
||||||
(pf == PF_INET6 && hooknum == NF_IP6_PRE_ROUTING))
|
(pf == PF_INET6 && hooknum == NF_IP6_PRE_ROUTING)) &&
|
||||||
&& skb->ip_summed != CHECKSUM_UNNECESSARY
|
nf_checksum(skb, hooknum, dataoff, IPPROTO_TCP, pf)) {
|
||||||
&& csum(skb, dataoff)) {
|
|
||||||
if (LOG_INVALID(IPPROTO_TCP))
|
if (LOG_INVALID(IPPROTO_TCP))
|
||||||
nf_log_packet(pf, 0, skb, NULL, NULL, NULL,
|
nf_log_packet(pf, 0, skb, NULL, NULL, NULL,
|
||||||
"nf_ct_tcp: bad TCP checksum ");
|
"nf_ct_tcp: bad TCP checksum ");
|
||||||
|
@ -851,44 +849,6 @@ static int tcp_error(struct sk_buff *skb,
|
||||||
return NF_ACCEPT;
|
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. */
|
/* Returns verdict for packet, or -1 for invalid. */
|
||||||
static int tcp_packet(struct nf_conn *conntrack,
|
static int tcp_packet(struct nf_conn *conntrack,
|
||||||
const struct sk_buff *skb,
|
const struct sk_buff *skb,
|
||||||
|
@ -1218,7 +1178,7 @@ struct nf_conntrack_protocol nf_conntrack_protocol_tcp4 =
|
||||||
.print_conntrack = tcp_print_conntrack,
|
.print_conntrack = tcp_print_conntrack,
|
||||||
.packet = tcp_packet,
|
.packet = tcp_packet,
|
||||||
.new = tcp_new,
|
.new = tcp_new,
|
||||||
.error = tcp_error4,
|
.error = tcp_error,
|
||||||
#if defined(CONFIG_NF_CT_NETLINK) || \
|
#if defined(CONFIG_NF_CT_NETLINK) || \
|
||||||
defined(CONFIG_NF_CT_NETLINK_MODULE)
|
defined(CONFIG_NF_CT_NETLINK_MODULE)
|
||||||
.to_nfattr = tcp_to_nfattr,
|
.to_nfattr = tcp_to_nfattr,
|
||||||
|
@ -1239,7 +1199,7 @@ struct nf_conntrack_protocol nf_conntrack_protocol_tcp6 =
|
||||||
.print_conntrack = tcp_print_conntrack,
|
.print_conntrack = tcp_print_conntrack,
|
||||||
.packet = tcp_packet,
|
.packet = tcp_packet,
|
||||||
.new = tcp_new,
|
.new = tcp_new,
|
||||||
.error = tcp_error6,
|
.error = tcp_error,
|
||||||
#if defined(CONFIG_NF_CT_NETLINK) || \
|
#if defined(CONFIG_NF_CT_NETLINK) || \
|
||||||
defined(CONFIG_NF_CT_NETLINK_MODULE)
|
defined(CONFIG_NF_CT_NETLINK_MODULE)
|
||||||
.to_nfattr = tcp_to_nfattr,
|
.to_nfattr = tcp_to_nfattr,
|
||||||
|
|
|
@ -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,
|
static int udp_error(struct sk_buff *skb, unsigned int dataoff,
|
||||||
enum ip_conntrack_info *ctinfo,
|
enum ip_conntrack_info *ctinfo,
|
||||||
int pf,
|
int pf,
|
||||||
unsigned int hooknum,
|
unsigned int hooknum)
|
||||||
int (*csum)(const struct sk_buff *, unsigned int))
|
|
||||||
{
|
{
|
||||||
unsigned int udplen = skb->len - dataoff;
|
unsigned int udplen = skb->len - dataoff;
|
||||||
struct udphdr _hdr, *hdr;
|
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.
|
* and moreover root might send raw packets.
|
||||||
* FIXME: Source route IP option packets --RR */
|
* FIXME: Source route IP option packets --RR */
|
||||||
if (((pf == PF_INET && hooknum == NF_IP_PRE_ROUTING) ||
|
if (((pf == PF_INET && hooknum == NF_IP_PRE_ROUTING) ||
|
||||||
(pf == PF_INET6 && hooknum == NF_IP6_PRE_ROUTING))
|
(pf == PF_INET6 && hooknum == NF_IP6_PRE_ROUTING)) &&
|
||||||
&& skb->ip_summed != CHECKSUM_UNNECESSARY
|
nf_checksum(skb, hooknum, dataoff, IPPROTO_UDP, pf)) {
|
||||||
&& csum(skb, dataoff)) {
|
|
||||||
if (LOG_INVALID(IPPROTO_UDP))
|
if (LOG_INVALID(IPPROTO_UDP))
|
||||||
nf_log_packet(pf, 0, skb, NULL, NULL, NULL,
|
nf_log_packet(pf, 0, skb, NULL, NULL, NULL,
|
||||||
"nf_ct_udp: bad UDP checksum ");
|
"nf_ct_udp: bad UDP checksum ");
|
||||||
|
@ -148,44 +146,6 @@ static int udp_error(struct sk_buff *skb, unsigned int dataoff,
|
||||||
return NF_ACCEPT;
|
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 =
|
struct nf_conntrack_protocol nf_conntrack_protocol_udp4 =
|
||||||
{
|
{
|
||||||
.l3proto = PF_INET,
|
.l3proto = PF_INET,
|
||||||
|
@ -197,7 +157,7 @@ struct nf_conntrack_protocol nf_conntrack_protocol_udp4 =
|
||||||
.print_conntrack = udp_print_conntrack,
|
.print_conntrack = udp_print_conntrack,
|
||||||
.packet = udp_packet,
|
.packet = udp_packet,
|
||||||
.new = udp_new,
|
.new = udp_new,
|
||||||
.error = udp_error4,
|
.error = udp_error,
|
||||||
#if defined(CONFIG_NF_CT_NETLINK) || \
|
#if defined(CONFIG_NF_CT_NETLINK) || \
|
||||||
defined(CONFIG_NF_CT_NETLINK_MODULE)
|
defined(CONFIG_NF_CT_NETLINK_MODULE)
|
||||||
.tuple_to_nfattr = nf_ct_port_tuple_to_nfattr,
|
.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,
|
.print_conntrack = udp_print_conntrack,
|
||||||
.packet = udp_packet,
|
.packet = udp_packet,
|
||||||
.new = udp_new,
|
.new = udp_new,
|
||||||
.error = udp_error6,
|
.error = udp_error,
|
||||||
#if defined(CONFIG_NF_CT_NETLINK) || \
|
#if defined(CONFIG_NF_CT_NETLINK) || \
|
||||||
defined(CONFIG_NF_CT_NETLINK_MODULE)
|
defined(CONFIG_NF_CT_NETLINK_MODULE)
|
||||||
.tuple_to_nfattr = nf_ct_port_tuple_to_nfattr,
|
.tuple_to_nfattr = nf_ct_port_tuple_to_nfattr,
|
||||||
|
|
|
@ -649,63 +649,6 @@ static ctl_table nf_ct_net_table[] = {
|
||||||
EXPORT_SYMBOL(nf_ct_log_invalid);
|
EXPORT_SYMBOL(nf_ct_log_invalid);
|
||||||
#endif /* CONFIG_SYSCTL */
|
#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 nf_conntrack_l3proto_register(struct nf_conntrack_l3proto *proto)
|
||||||
{
|
{
|
||||||
int ret = 0;
|
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)
|
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)
|
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);
|
module_init(nf_conntrack_standalone_init);
|
||||||
|
|
|
@ -17,7 +17,6 @@
|
||||||
* for queueing and must reinject all packets it receives, no matter what.
|
* for queueing and must reinject all packets it receives, no matter what.
|
||||||
*/
|
*/
|
||||||
static struct nf_queue_handler *queue_handler[NPROTO];
|
static struct nf_queue_handler *queue_handler[NPROTO];
|
||||||
static struct nf_queue_rerouter *queue_rerouter[NPROTO];
|
|
||||||
|
|
||||||
static DEFINE_RWLOCK(queue_handler_lock);
|
static DEFINE_RWLOCK(queue_handler_lock);
|
||||||
|
|
||||||
|
@ -59,32 +58,6 @@ int nf_unregister_queue_handler(int pf)
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(nf_unregister_queue_handler);
|
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)
|
void nf_unregister_queue_handlers(struct nf_queue_handler *qh)
|
||||||
{
|
{
|
||||||
int pf;
|
int pf;
|
||||||
|
@ -116,7 +89,7 @@ int nf_queue(struct sk_buff **skb,
|
||||||
struct net_device *physindev = NULL;
|
struct net_device *physindev = NULL;
|
||||||
struct net_device *physoutdev = NULL;
|
struct net_device *physoutdev = NULL;
|
||||||
#endif
|
#endif
|
||||||
struct nf_queue_rerouter *rerouter;
|
struct nf_afinfo *afinfo;
|
||||||
|
|
||||||
/* QUEUE == DROP if noone is waiting, to be safe. */
|
/* QUEUE == DROP if noone is waiting, to be safe. */
|
||||||
read_lock(&queue_handler_lock);
|
read_lock(&queue_handler_lock);
|
||||||
|
@ -126,7 +99,14 @@ int nf_queue(struct sk_buff **skb,
|
||||||
return 1;
|
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 (!info) {
|
||||||
if (net_ratelimit())
|
if (net_ratelimit())
|
||||||
printk(KERN_ERR "OOM queueing packet %p\n",
|
printk(KERN_ERR "OOM queueing packet %p\n",
|
||||||
|
@ -158,10 +138,7 @@ int nf_queue(struct sk_buff **skb,
|
||||||
if (physoutdev) dev_hold(physoutdev);
|
if (physoutdev) dev_hold(physoutdev);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
rerouter = rcu_dereference(queue_rerouter[pf]);
|
afinfo->saveroute(*skb, info);
|
||||||
if (rerouter)
|
|
||||||
rerouter->save(*skb, info);
|
|
||||||
|
|
||||||
status = queue_handler[pf]->outfn(*skb, info, queuenum,
|
status = queue_handler[pf]->outfn(*skb, info, queuenum,
|
||||||
queue_handler[pf]->data);
|
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 *elem = &info->elem->list;
|
||||||
struct list_head *i;
|
struct list_head *i;
|
||||||
struct nf_queue_rerouter *rerouter;
|
struct nf_afinfo *afinfo;
|
||||||
|
|
||||||
rcu_read_lock();
|
rcu_read_lock();
|
||||||
|
|
||||||
|
@ -228,8 +205,8 @@ void nf_reinject(struct sk_buff *skb, struct nf_info *info,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (verdict == NF_ACCEPT) {
|
if (verdict == NF_ACCEPT) {
|
||||||
rerouter = rcu_dereference(queue_rerouter[info->pf]);
|
afinfo = nf_get_afinfo(info->pf);
|
||||||
if (rerouter && rerouter->reroute(&skb, info) < 0)
|
if (!afinfo || afinfo->reroute(&skb, info) < 0)
|
||||||
verdict = NF_DROP;
|
verdict = NF_DROP;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1033,17 +1033,13 @@ static struct file_operations nful_file_ops = {
|
||||||
|
|
||||||
#endif /* PROC_FS */
|
#endif /* PROC_FS */
|
||||||
|
|
||||||
static int
|
static int __init nfnetlink_log_init(void)
|
||||||
init_or_cleanup(int init)
|
|
||||||
{
|
{
|
||||||
int i, status = -ENOMEM;
|
int i, status = -ENOMEM;
|
||||||
#ifdef CONFIG_PROC_FS
|
#ifdef CONFIG_PROC_FS
|
||||||
struct proc_dir_entry *proc_nful;
|
struct proc_dir_entry *proc_nful;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (!init)
|
|
||||||
goto cleanup;
|
|
||||||
|
|
||||||
for (i = 0; i < INSTANCE_BUCKETS; i++)
|
for (i = 0; i < INSTANCE_BUCKETS; i++)
|
||||||
INIT_HLIST_HEAD(&instance_table[i]);
|
INIT_HLIST_HEAD(&instance_table[i]);
|
||||||
|
|
||||||
|
@ -1066,30 +1062,25 @@ init_or_cleanup(int init)
|
||||||
goto cleanup_subsys;
|
goto cleanup_subsys;
|
||||||
proc_nful->proc_fops = &nful_file_ops;
|
proc_nful->proc_fops = &nful_file_ops;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return status;
|
return status;
|
||||||
|
|
||||||
cleanup:
|
|
||||||
nf_log_unregister_logger(&nfulnl_logger);
|
|
||||||
#ifdef CONFIG_PROC_FS
|
#ifdef CONFIG_PROC_FS
|
||||||
remove_proc_entry("nfnetlink_log", proc_net_netfilter);
|
|
||||||
cleanup_subsys:
|
cleanup_subsys:
|
||||||
#endif
|
|
||||||
nfnetlink_subsys_unregister(&nfulnl_subsys);
|
nfnetlink_subsys_unregister(&nfulnl_subsys);
|
||||||
|
#endif
|
||||||
cleanup_netlink_notifier:
|
cleanup_netlink_notifier:
|
||||||
netlink_unregister_notifier(&nfulnl_rtnl_notifier);
|
netlink_unregister_notifier(&nfulnl_rtnl_notifier);
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int __init nfnetlink_log_init(void)
|
|
||||||
{
|
|
||||||
|
|
||||||
return init_or_cleanup(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void __exit nfnetlink_log_fini(void)
|
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");
|
MODULE_DESCRIPTION("netfilter userspace logging");
|
||||||
|
|
|
@ -1071,17 +1071,13 @@ static struct file_operations nfqnl_file_ops = {
|
||||||
|
|
||||||
#endif /* PROC_FS */
|
#endif /* PROC_FS */
|
||||||
|
|
||||||
static int
|
static int __init nfnetlink_queue_init(void)
|
||||||
init_or_cleanup(int init)
|
|
||||||
{
|
{
|
||||||
int i, status = -ENOMEM;
|
int i, status = -ENOMEM;
|
||||||
#ifdef CONFIG_PROC_FS
|
#ifdef CONFIG_PROC_FS
|
||||||
struct proc_dir_entry *proc_nfqueue;
|
struct proc_dir_entry *proc_nfqueue;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (!init)
|
|
||||||
goto cleanup;
|
|
||||||
|
|
||||||
for (i = 0; i < INSTANCE_BUCKETS; i++)
|
for (i = 0; i < INSTANCE_BUCKETS; i++)
|
||||||
INIT_HLIST_HEAD(&instance_table[i]);
|
INIT_HLIST_HEAD(&instance_table[i]);
|
||||||
|
|
||||||
|
@ -1101,31 +1097,26 @@ init_or_cleanup(int init)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
register_netdevice_notifier(&nfqnl_dev_notifier);
|
register_netdevice_notifier(&nfqnl_dev_notifier);
|
||||||
|
|
||||||
return status;
|
return status;
|
||||||
|
|
||||||
cleanup:
|
|
||||||
nf_unregister_queue_handlers(&nfqh);
|
|
||||||
unregister_netdevice_notifier(&nfqnl_dev_notifier);
|
|
||||||
#ifdef CONFIG_PROC_FS
|
#ifdef CONFIG_PROC_FS
|
||||||
remove_proc_entry("nfnetlink_queue", proc_net_netfilter);
|
|
||||||
cleanup_subsys:
|
cleanup_subsys:
|
||||||
#endif
|
|
||||||
nfnetlink_subsys_unregister(&nfqnl_subsys);
|
nfnetlink_subsys_unregister(&nfqnl_subsys);
|
||||||
|
#endif
|
||||||
cleanup_netlink_notifier:
|
cleanup_netlink_notifier:
|
||||||
netlink_unregister_notifier(&nfqnl_rtnl_notifier);
|
netlink_unregister_notifier(&nfqnl_rtnl_notifier);
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int __init nfnetlink_queue_init(void)
|
|
||||||
{
|
|
||||||
|
|
||||||
return init_or_cleanup(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void __exit nfnetlink_queue_fini(void)
|
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");
|
MODULE_DESCRIPTION("netfilter packet queue handler");
|
||||||
|
|
|
@ -66,7 +66,7 @@ static __inline__ struct tcf_police * tcf_police_lookup(u32 index)
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_NET_CLS_ACT
|
#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)
|
int type, struct tc_action *a)
|
||||||
{
|
{
|
||||||
struct tcf_police *p;
|
struct tcf_police *p;
|
||||||
|
@ -113,7 +113,7 @@ static int tcf_generic_walker(struct sk_buff *skb, struct netlink_callback *cb,
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int
|
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);
|
struct tcf_police *p = tcf_police_lookup(index);
|
||||||
|
|
||||||
|
@ -387,9 +387,9 @@ static struct tc_action_ops act_police_ops = {
|
||||||
.act = tcf_act_police,
|
.act = tcf_act_police,
|
||||||
.dump = tcf_act_police_dump,
|
.dump = tcf_act_police_dump,
|
||||||
.cleanup = tcf_act_police_cleanup,
|
.cleanup = tcf_act_police_cleanup,
|
||||||
.lookup = tcf_hash_search,
|
.lookup = tcf_act_police_hash_search,
|
||||||
.init = tcf_act_police_locate,
|
.init = tcf_act_police_locate,
|
||||||
.walk = tcf_generic_walker
|
.walk = tcf_act_police_walker
|
||||||
};
|
};
|
||||||
|
|
||||||
static int __init
|
static int __init
|
||||||
|
|
Loading…
Reference in New Issue