Commit ee54d2d8 authored by Linus Torvalds's avatar Linus Torvalds

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: (31 commits)
  [NETFILTER]: xt_conntrack: add compat support
  [NETFILTER]: iptable_raw: ignore short packets sent by SOCK_RAW sockets
  [NETFILTER]: iptable_{filter,mangle}: more descriptive "happy cracking" message
  [NETFILTER]: nf_nat: Clears helper private area when NATing
  [NETFILTER]: ctnetlink: clear helper area and handle unchanged helper
  [NETFILTER]: nf_conntrack: Removes unused destroy operation of l3proto
  [NETFILTER]: nf_conntrack: Removes duplicated declarations
  [NETFILTER]: nf_nat: remove unused argument of function allocating binding
  [NETFILTER]: Clean up table initialization
  [NET_SCHED]: Avoid requeue warning on dev_deactivate
  [NET_SCHED]: Reread dev->qdisc for NETDEV_TX_OK
  [NET_SCHED]: Rationalise return value of qdisc_restart
  [NET]: Fix dev->qdisc race for NETDEV_TX_LOCKED case
  [UDP]: Fix AF-specific references in AF-agnostic code.
  [IrDA]: KingSun/DonShine USB IrDA dongle support.
  [IPV6] ROUTE: Assign rt6i_idev for ip6_{prohibit,blk_hole}_entry.
  [IPV6]: Do no rely on skb->dst before it is assigned.
  [IPV6]: Send ICMPv6 error on scope violations.
  [SCTP]: Do not include ABORT chunk header in the notification.
  [SCTP]: Correctly copy addresses in sctp_copy_laddrs
  ...
parents bf61f8d3 da0dd231
...@@ -307,6 +307,8 @@ static void hci_uart_tty_close(struct tty_struct *tty) ...@@ -307,6 +307,8 @@ static void hci_uart_tty_close(struct tty_struct *tty)
if (hu) { if (hu) {
struct hci_dev *hdev = hu->hdev; struct hci_dev *hdev = hu->hdev;
if (hdev)
hci_uart_close(hdev); hci_uart_close(hdev);
if (test_and_clear_bit(HCI_UART_PROTO_SET, &hu->flags)) { if (test_and_clear_bit(HCI_UART_PROTO_SET, &hu->flags)) {
...@@ -473,12 +475,18 @@ static int hci_uart_tty_ioctl(struct tty_struct *tty, struct file * file, ...@@ -473,12 +475,18 @@ static int hci_uart_tty_ioctl(struct tty_struct *tty, struct file * file,
tty->low_latency = 1; tty->low_latency = 1;
} else } else
return -EBUSY; return -EBUSY;
break;
case HCIUARTGETPROTO: case HCIUARTGETPROTO:
if (test_bit(HCI_UART_PROTO_SET, &hu->flags)) if (test_bit(HCI_UART_PROTO_SET, &hu->flags))
return hu->proto->id; return hu->proto->id;
return -EUNATCH; return -EUNATCH;
case HCIUARTGETDEVICE:
if (test_bit(HCI_UART_PROTO_SET, &hu->flags))
return hu->hdev->id;
return -EUNATCH;
default: default:
err = n_tty_ioctl(tty, file, cmd, arg); err = n_tty_ioctl(tty, file, cmd, arg);
break; break;
......
...@@ -30,6 +30,7 @@ ...@@ -30,6 +30,7 @@
/* Ioctls */ /* Ioctls */
#define HCIUARTSETPROTO _IOW('U', 200, int) #define HCIUARTSETPROTO _IOW('U', 200, int)
#define HCIUARTGETPROTO _IOR('U', 201, int) #define HCIUARTGETPROTO _IOR('U', 201, int)
#define HCIUARTGETDEVICE _IOR('U', 202, int)
/* UART protocols */ /* UART protocols */
#define HCI_UART_MAX_PROTO 4 #define HCI_UART_MAX_PROTO 4
......
...@@ -141,6 +141,20 @@ config ACT200L_DONGLE ...@@ -141,6 +141,20 @@ config ACT200L_DONGLE
To activate support for ACTiSYS IR-200L dongle you will have to To activate support for ACTiSYS IR-200L dongle you will have to
start irattach like this: "irattach -d act200l". start irattach like this: "irattach -d act200l".
config KINGSUN_DONGLE
tristate "KingSun/DonShine DS-620 IrDA-USB dongle"
depends on IRDA && USB && EXPERIMENTAL
help
Say Y or M here if you want to build support for the KingSun/DonShine
DS-620 IrDA-USB bridge device driver.
This USB bridge does not conform to the IrDA-USB device class
specification, and therefore needs its own specific driver. This
dongle supports SIR speed only (9600 bps).
To compile it as a module, choose M here: the module will be called
kingsun-sir.
comment "Old SIR device drivers" comment "Old SIR device drivers"
config IRPORT_SIR config IRPORT_SIR
......
...@@ -45,6 +45,7 @@ obj-$(CONFIG_MCP2120_DONGLE) += mcp2120-sir.o ...@@ -45,6 +45,7 @@ obj-$(CONFIG_MCP2120_DONGLE) += mcp2120-sir.o
obj-$(CONFIG_ACT200L_DONGLE) += act200l-sir.o obj-$(CONFIG_ACT200L_DONGLE) += act200l-sir.o
obj-$(CONFIG_MA600_DONGLE) += ma600-sir.o obj-$(CONFIG_MA600_DONGLE) += ma600-sir.o
obj-$(CONFIG_TOIM3232_DONGLE) += toim3232-sir.o obj-$(CONFIG_TOIM3232_DONGLE) += toim3232-sir.o
obj-$(CONFIG_KINGSUN_DONGLE) += kingsun-sir.o
# The SIR helper module # The SIR helper module
sir-dev-objs := sir_dev.o sir_dongle.o sir-dev-objs := sir_dev.o sir_dongle.o
This diff is collapsed.
...@@ -467,6 +467,8 @@ struct net_device ...@@ -467,6 +467,8 @@ struct net_device
/* device index hash chain */ /* device index hash chain */
struct hlist_node index_hlist; struct hlist_node index_hlist;
struct net_device *link_watch_next;
/* register/unregister state machine */ /* register/unregister state machine */
enum { NETREG_UNINITIALIZED=0, enum { NETREG_UNINITIALIZED=0,
NETREG_REGISTERED, /* completed register_netdevice */ NETREG_REGISTERED, /* completed register_netdevice */
......
...@@ -54,6 +54,14 @@ struct xt_entry_target ...@@ -54,6 +54,14 @@ struct xt_entry_target
unsigned char data[0]; unsigned char data[0];
}; };
#define XT_TARGET_INIT(__name, __size) \
{ \
.target.u.user = { \
.target_size = XT_ALIGN(__size), \
.name = __name, \
}, \
}
struct xt_standard_target struct xt_standard_target
{ {
struct xt_entry_target target; struct xt_entry_target target;
......
...@@ -238,6 +238,47 @@ static __inline__ struct arpt_entry_target *arpt_get_target(struct arpt_entry *e ...@@ -238,6 +238,47 @@ static __inline__ struct arpt_entry_target *arpt_get_target(struct arpt_entry *e
*/ */
#ifdef __KERNEL__ #ifdef __KERNEL__
/* Standard entry. */
struct arpt_standard
{
struct arpt_entry entry;
struct arpt_standard_target target;
};
struct arpt_error_target
{
struct arpt_entry_target target;
char errorname[ARPT_FUNCTION_MAXNAMELEN];
};
struct arpt_error
{
struct arpt_entry entry;
struct arpt_error_target target;
};
#define ARPT_ENTRY_INIT(__size) \
{ \
.target_offset = sizeof(struct arpt_entry), \
.next_offset = (__size), \
}
#define ARPT_STANDARD_INIT(__verdict) \
{ \
.entry = ARPT_ENTRY_INIT(sizeof(struct arpt_standard)), \
.target = XT_TARGET_INIT(ARPT_STANDARD_TARGET, \
sizeof(struct arpt_standard_target)), \
.target.verdict = -(__verdict) - 1, \
}
#define ARPT_ERROR_INIT \
{ \
.entry = ARPT_ENTRY_INIT(sizeof(struct arpt_error)), \
.target = XT_TARGET_INIT(ARPT_ERROR_TARGET, \
sizeof(struct arpt_error_target)), \
.target.errorname = "ERROR", \
}
#define arpt_register_target(tgt) \ #define arpt_register_target(tgt) \
({ (tgt)->family = NF_ARP; \ ({ (tgt)->family = NF_ARP; \
xt_register_target(tgt); }) xt_register_target(tgt); })
......
...@@ -295,6 +295,28 @@ struct ipt_error ...@@ -295,6 +295,28 @@ struct ipt_error
struct ipt_error_target target; struct ipt_error_target target;
}; };
#define IPT_ENTRY_INIT(__size) \
{ \
.target_offset = sizeof(struct ipt_entry), \
.next_offset = (__size), \
}
#define IPT_STANDARD_INIT(__verdict) \
{ \
.entry = IPT_ENTRY_INIT(sizeof(struct ipt_standard)), \
.target = XT_TARGET_INIT(IPT_STANDARD_TARGET, \
sizeof(struct xt_standard_target)), \
.target.verdict = -(__verdict) - 1, \
}
#define IPT_ERROR_INIT \
{ \
.entry = IPT_ENTRY_INIT(sizeof(struct ipt_error)), \
.target = XT_TARGET_INIT(IPT_ERROR_TARGET, \
sizeof(struct ipt_error_target)), \
.target.errorname = "ERROR", \
}
extern unsigned int ipt_do_table(struct sk_buff **pskb, extern unsigned int ipt_do_table(struct sk_buff **pskb,
unsigned int hook, unsigned int hook,
const struct net_device *in, const struct net_device *in,
......
...@@ -123,6 +123,28 @@ struct ip6t_error ...@@ -123,6 +123,28 @@ struct ip6t_error
struct ip6t_error_target target; struct ip6t_error_target target;
}; };
#define IP6T_ENTRY_INIT(__size) \
{ \
.target_offset = sizeof(struct ip6t_entry), \
.next_offset = (__size), \
}
#define IP6T_STANDARD_INIT(__verdict) \
{ \
.entry = IP6T_ENTRY_INIT(sizeof(struct ip6t_standard)), \
.target = XT_TARGET_INIT(IP6T_STANDARD_TARGET, \
sizeof(struct ip6t_standard_target)), \
.target.verdict = -(__verdict) - 1, \
}
#define IP6T_ERROR_INIT \
{ \
.entry = IP6T_ENTRY_INIT(sizeof(struct ip6t_error)), \
.target = XT_TARGET_INIT(IP6T_ERROR_TARGET, \
sizeof(struct ip6t_error_target)), \
.target.errorname = "ERROR", \
}
/* /*
* New IP firewall options for [gs]etsockopt at the RAW IP level. * New IP firewall options for [gs]etsockopt at the RAW IP level.
* Unlike BSD Linux inherits IP options so you don't have to use * Unlike BSD Linux inherits IP options so you don't have to use
......
...@@ -183,13 +183,6 @@ extern void nf_conntrack_hash_insert(struct nf_conn *ct); ...@@ -183,13 +183,6 @@ extern void nf_conntrack_hash_insert(struct nf_conn *ct);
extern void nf_conntrack_flush(void); extern void nf_conntrack_flush(void);
extern struct nf_conntrack_helper *
nf_ct_helper_find_get( const struct nf_conntrack_tuple *tuple);
extern void nf_ct_helper_put(struct nf_conntrack_helper *helper);
extern struct nf_conntrack_helper *
__nf_conntrack_helper_find_byname(const char *name);
extern int nf_ct_invert_tuplepr(struct nf_conntrack_tuple *inverse, extern int nf_ct_invert_tuplepr(struct nf_conntrack_tuple *inverse,
const struct nf_conntrack_tuple *orig); const struct nf_conntrack_tuple *orig);
......
...@@ -56,9 +56,6 @@ struct nf_conntrack_l3proto ...@@ -56,9 +56,6 @@ struct nf_conntrack_l3proto
*/ */
int (*new)(struct nf_conn *conntrack, const struct sk_buff *skb); int (*new)(struct nf_conn *conntrack, const struct sk_buff *skb);
/* Called when a conntrack entry is destroyed */
void (*destroy)(struct nf_conn *conntrack);
/* /*
* Called before tracking. * Called before tracking.
* *dataoff: offset of protocol header (TCP, UDP,...) in *pskb * *dataoff: offset of protocol header (TCP, UDP,...) in *pskb
......
...@@ -10,16 +10,11 @@ extern int nf_nat_rule_find(struct sk_buff **pskb, ...@@ -10,16 +10,11 @@ extern int nf_nat_rule_find(struct sk_buff **pskb,
unsigned int hooknum, unsigned int hooknum,
const struct net_device *in, const struct net_device *in,
const struct net_device *out, const struct net_device *out,
struct nf_conn *ct, struct nf_conn *ct);
struct nf_nat_info *info);
extern unsigned int extern unsigned int
alloc_null_binding(struct nf_conn *ct, alloc_null_binding(struct nf_conn *ct, unsigned int hooknum);
struct nf_nat_info *info,
unsigned int hooknum);
extern unsigned int extern unsigned int
alloc_null_binding_confirmed(struct nf_conn *ct, alloc_null_binding_confirmed(struct nf_conn *ct, unsigned int hooknum);
struct nf_nat_info *info,
unsigned int hooknum);
#endif /* _NF_NAT_RULE_H */ #endif /* _NF_NAT_RULE_H */
...@@ -119,9 +119,16 @@ static inline void udp_lib_close(struct sock *sk, long timeout) ...@@ -119,9 +119,16 @@ static inline void udp_lib_close(struct sock *sk, long timeout)
} }
struct udp_get_port_ops {
int (*saddr_cmp)(const struct sock *sk1, const struct sock *sk2);
int (*saddr_any)(const struct sock *sk);
unsigned int (*hash_port_and_rcv_saddr)(__u16 port,
const struct sock *sk);
};
/* net/ipv4/udp.c */ /* net/ipv4/udp.c */
extern int udp_get_port(struct sock *sk, unsigned short snum, extern int udp_get_port(struct sock *sk, unsigned short snum,
int (*saddr_cmp)(const struct sock *, const struct sock *)); const struct udp_get_port_ops *ops);
extern void udp_err(struct sk_buff *, u32); extern void udp_err(struct sk_buff *, u32);
extern int udp_sendmsg(struct kiocb *iocb, struct sock *sk, extern int udp_sendmsg(struct kiocb *iocb, struct sock *sk,
......
...@@ -120,5 +120,5 @@ static inline __wsum udplite_csum_outgoing(struct sock *sk, struct sk_buff *skb) ...@@ -120,5 +120,5 @@ static inline __wsum udplite_csum_outgoing(struct sock *sk, struct sk_buff *skb)
extern void udplite4_register(void); extern void udplite4_register(void);
extern int udplite_get_port(struct sock *sk, unsigned short snum, extern int udplite_get_port(struct sock *sk, unsigned short snum,
int (*scmp)(const struct sock *, const struct sock *)); const struct udp_get_port_ops *ops);
#endif /* _UDPLITE_H */ #endif /* _UDPLITE_H */
...@@ -174,7 +174,7 @@ static inline int hidp_queue_event(struct hidp_session *session, struct input_de ...@@ -174,7 +174,7 @@ static inline int hidp_queue_event(struct hidp_session *session, struct input_de
static int hidp_hidinput_event(struct input_dev *dev, unsigned int type, unsigned int code, int value) static int hidp_hidinput_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
{ {
struct hid_device *hid = dev->private; struct hid_device *hid = input_get_drvdata(dev);
struct hidp_session *session = hid->driver_data; struct hidp_session *session = hid->driver_data;
return hidp_queue_event(session, dev, type, code, value); return hidp_queue_event(session, dev, type, code, value);
...@@ -182,7 +182,7 @@ static int hidp_hidinput_event(struct input_dev *dev, unsigned int type, unsigne ...@@ -182,7 +182,7 @@ static int hidp_hidinput_event(struct input_dev *dev, unsigned int type, unsigne
static int hidp_input_event(struct input_dev *dev, unsigned int type, unsigned int code, int value) static int hidp_input_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
{ {
struct hidp_session *session = dev->private; struct hidp_session *session = input_get_drvdata(dev);
return hidp_queue_event(session, dev, type, code, value); return hidp_queue_event(session, dev, type, code, value);
} }
...@@ -630,7 +630,7 @@ static inline void hidp_setup_input(struct hidp_session *session, struct hidp_co ...@@ -630,7 +630,7 @@ static inline void hidp_setup_input(struct hidp_session *session, struct hidp_co
struct input_dev *input = session->input; struct input_dev *input = session->input;
int i; int i;
input->private = session; input_set_drvdata(input, session);
input->name = "Bluetooth HID Boot Protocol Device"; input->name = "Bluetooth HID Boot Protocol Device";
...@@ -663,7 +663,7 @@ static inline void hidp_setup_input(struct hidp_session *session, struct hidp_co ...@@ -663,7 +663,7 @@ static inline void hidp_setup_input(struct hidp_session *session, struct hidp_co
input->relbit[0] |= BIT(REL_WHEEL); input->relbit[0] |= BIT(REL_WHEEL);
} }
input->cdev.dev = hidp_get_device(session); input->dev.parent = hidp_get_device(session);
input->event = hidp_input_event; input->event = hidp_input_event;
...@@ -864,7 +864,7 @@ int hidp_add_connection(struct hidp_connadd_req *req, struct socket *ctrl_sock, ...@@ -864,7 +864,7 @@ int hidp_add_connection(struct hidp_connadd_req *req, struct socket *ctrl_sock,
if (session->hid) if (session->hid)
hid_free_device(session->hid); hid_free_device(session->hid);
kfree(session->input); input_free_device(session->input);
kfree(session); kfree(session);
return err; return err;
} }
......
...@@ -19,7 +19,6 @@ ...@@ -19,7 +19,6 @@
#include <linux/rtnetlink.h> #include <linux/rtnetlink.h>
#include <linux/jiffies.h> #include <linux/jiffies.h>
#include <linux/spinlock.h> #include <linux/spinlock.h>
#include <linux/list.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/workqueue.h> #include <linux/workqueue.h>
#include <linux/bitops.h> #include <linux/bitops.h>
...@@ -27,8 +26,7 @@ ...@@ -27,8 +26,7 @@
enum lw_bits { enum lw_bits {
LW_RUNNING = 0, LW_URGENT = 0,
LW_SE_USED
}; };
static unsigned long linkwatch_flags; static unsigned long linkwatch_flags;
...@@ -37,17 +35,9 @@ static unsigned long linkwatch_nextevent; ...@@ -37,17 +35,9 @@ static unsigned long linkwatch_nextevent;
static void linkwatch_event(struct work_struct *dummy); static void linkwatch_event(struct work_struct *dummy);
static DECLARE_DELAYED_WORK(linkwatch_work, linkwatch_event); static DECLARE_DELAYED_WORK(linkwatch_work, linkwatch_event);
static LIST_HEAD(lweventlist); static struct net_device *lweventlist;
static DEFINE_SPINLOCK(lweventlist_lock); static DEFINE_SPINLOCK(lweventlist_lock);
struct lw_event {
struct list_head list;
struct net_device *dev;
};
/* Avoid kmalloc() for most systems */
static struct lw_event singleevent;
static unsigned char default_operstate(const struct net_device *dev) static unsigned char default_operstate(const struct net_device *dev)
{ {
if (!netif_carrier_ok(dev)) if (!netif_carrier_ok(dev))
...@@ -87,25 +77,102 @@ static void rfc2863_policy(struct net_device *dev) ...@@ -87,25 +77,102 @@ static void rfc2863_policy(struct net_device *dev)
} }
/* Must be called with the rtnl semaphore held */ static int linkwatch_urgent_event(struct net_device *dev)
void linkwatch_run_queue(void) {
return netif_running(dev) && netif_carrier_ok(dev) &&
dev->qdisc != dev->qdisc_sleeping;
}
static void linkwatch_add_event(struct net_device *dev)
{
unsigned long flags;
spin_lock_irqsave(&lweventlist_lock, flags);
dev->link_watch_next = lweventlist;
lweventlist = dev;
spin_unlock_irqrestore(&lweventlist_lock, flags);
}
static void linkwatch_schedule_work(int urgent)
{
unsigned long delay = linkwatch_nextevent - jiffies;
if (test_bit(LW_URGENT, &linkwatch_flags))
return;
/* Minimise down-time: drop delay for up event. */
if (urgent) {
if (test_and_set_bit(LW_URGENT, &linkwatch_flags))
return;
delay = 0;
}
/* If we wrap around we'll delay it by at most HZ. */
if (delay > HZ)
delay = 0;
/*
* This is true if we've scheduled it immeditately or if we don't
* need an immediate execution and it's already pending.
*/
if (schedule_delayed_work(&linkwatch_work, delay) == !delay)
return;
/* Don't bother if there is nothing urgent. */
if (!test_bit(LW_URGENT, &linkwatch_flags))
return;
/* It's already running which is good enough. */
if (!cancel_delayed_work(&linkwatch_work))
return;
/* Otherwise we reschedule it again for immediate exection. */
schedule_delayed_work(&linkwatch_work, 0);
}
static void __linkwatch_run_queue(int urgent_only)
{ {
struct list_head head, *n, *next; struct net_device *next;
/*
* Limit the number of linkwatch events to one
* per second so that a runaway driver does not
* cause a storm of messages on the netlink
* socket. This limit does not apply to up events
* while the device qdisc is down.
*/
if (!urgent_only)
linkwatch_nextevent = jiffies + HZ;
/* Limit wrap-around effect on delay. */
else if (time_after(linkwatch_nextevent, jiffies + HZ))
linkwatch_nextevent = jiffies;
clear_bit(LW_URGENT, &linkwatch_flags);
spin_lock_irq(&lweventlist_lock); spin_lock_irq(&lweventlist_lock);
list_replace_init(&lweventlist, &head); next = lweventlist;
lweventlist = NULL;
spin_unlock_irq(&lweventlist_lock); spin_unlock_irq(&lweventlist_lock);
list_for_each_safe(n, next, &head) { while (next) {
struct lw_event *event = list_entry(n, struct lw_event, list); struct net_device *dev = next;
struct net_device *dev = event->dev;
next = dev->link_watch_next;
if (event == &singleevent) { if (urgent_only && !linkwatch_urgent_event(dev)) {
clear_bit(LW_SE_USED, &linkwatch_flags); linkwatch_add_event(dev);
} else { continue;
kfree(event);
} }
/*
* Make sure the above read is complete since it can be
* rewritten as soon as we clear the bit below.
*/
smp_mb__before_clear_bit();
/* We are about to handle this device, /* We are about to handle this device,
* so new events can be accepted * so new events can be accepted
*/ */
...@@ -124,58 +191,39 @@ void linkwatch_run_queue(void) ...@@ -124,58 +191,39 @@ void linkwatch_run_queue(void)
dev_put(dev); dev_put(dev);
} }
if (lweventlist)
linkwatch_schedule_work(0);
} }
static void linkwatch_event(struct work_struct *dummy) /* Must be called with the rtnl semaphore held */
void linkwatch_run_queue(void)
{ {
/* Limit the number of linkwatch events to one __linkwatch_run_queue(0);
* per second so that a runaway driver does not }
* cause a storm of messages on the netlink
* socket
*/
linkwatch_nextevent = jiffies + HZ;
clear_bit(LW_RUNNING, &linkwatch_flags);
static void linkwatch_event(struct work_struct *dummy)
{
rtnl_lock(); rtnl_lock();
linkwatch_run_queue(); __linkwatch_run_queue(time_after(linkwatch_nextevent, jiffies));
rtnl_unlock(); rtnl_unlock();
} }
void linkwatch_fire_event(struct net_device *dev) void linkwatch_fire_event(struct net_device *dev)
{ {
if (!test_and_set_bit(__LINK_STATE_LINKWATCH_PENDING, &dev->state)) { int urgent = linkwatch_urgent_event(dev);
unsigned long flags;
struct lw_event *event;
if (test_and_set_bit(LW_SE_USED, &linkwatch_flags)) {
event = kmalloc(sizeof(struct lw_event), GFP_ATOMIC);
if (unlikely(event == NULL)) {
clear_bit(__LINK_STATE_LINKWATCH_PENDING, &dev->state);
return;
}
} else {
event = &singleevent;
}
if (!test_and_set_bit(__LINK_STATE_LINKWATCH_PENDING, &dev->state)) {
dev_hold(dev); dev_hold(dev);
event->dev = dev;
spin_lock_irqsave(&lweventlist_lock, flags); linkwatch_add_event(dev);
list_add_tail(&event->list, &lweventlist); } else if (!urgent)
spin_unlock_irqrestore(&lweventlist_lock, flags); return;
if (!test_and_set_bit(LW_RUNNING, &linkwatch_flags)) {
unsigned long delay = linkwatch_nextevent - jiffies;
/* If we wrap around we'll delay it by at most HZ. */ linkwatch_schedule_work(urgent);
if (delay > HZ)
delay = 0;
schedule_delayed_work(&linkwatch_work, delay);
}
}
} }
EXPORT_SYMBOL(linkwatch_fire_event); EXPORT_SYMBOL(linkwatch_fire_event);
...@@ -15,128 +15,34 @@ MODULE_DESCRIPTION("arptables filter table"); ...@@ -15,128 +15,34 @@ MODULE_DESCRIPTION("arptables filter table");
#define FILTER_VALID_HOOKS ((1 << NF_ARP_IN) | (1 << NF_ARP_OUT) | \ #define FILTER_VALID_HOOKS ((1 << NF_ARP_IN) | (1 << NF_ARP_OUT) | \
(1 << NF_ARP_FORWARD)) (1 << NF_ARP_FORWARD))
/* Standard entry. */
struct arpt_standard
{
struct arpt_entry entry;
struct arpt_standard_target target;
};
struct arpt_error_target
{
struct arpt_entry_target target;
char errorname[ARPT_FUNCTION_MAXNAMELEN];
};
struct arpt_error
{
struct arpt_entry entry;
struct arpt_error_target target;
};
static struct static struct
{ {
struct arpt_replace repl; struct arpt_replace repl;
struct arpt_standard entries[3]; struct arpt_standard entries[3];
struct arpt_error term; struct arpt_error term;
} initial_table __initdata } initial_table __initdata = {
= { { "filter", FILTER_VALID_HOOKS, 4, .repl = {
sizeof(struct arpt_standard) * 3 + sizeof(struct arpt_error), .name = "filter",
{ [NF_ARP_IN] = 0, .valid_hooks = FILTER_VALID_HOOKS,
[NF_ARP_OUT] = sizeof(struct arpt_standard), .num_entries = 4,
[NF_ARP_FORWARD] = 2 * sizeof(struct arpt_standard), }, .size = sizeof(struct arpt_standard) * 3 + sizeof(struct arpt_error),
{ [NF_ARP_IN] = 0, .hook_entry = {
[NF_ARP_IN] = 0,
[NF_ARP_OUT] = sizeof(struct arpt_standard), [NF_ARP_OUT] = sizeof(struct arpt_standard),
[NF_ARP_FORWARD] = 2 * sizeof(struct arpt_standard), }, [NF_ARP_FORWARD] = 2 * sizeof(struct arpt_standard),
0, NULL, { } },
{
/* ARP_IN */
{
{
{
{ 0 }, { 0 }, { 0 }, { 0 },
0, 0,
{ { 0, }, { 0, } },
{ { 0, }, { 0, } },
0, 0,
0, 0,
0, 0,
"", "", { 0 }, { 0 },
0, 0
},
sizeof(struct arpt_entry),
sizeof(struct arpt_standard),
0,
{ 0, 0 }, { } },
{ { { { ARPT_ALIGN(sizeof(struct arpt_standard_target)), "" } }, { } },
-NF_ACCEPT - 1 }
},
/* ARP_OUT */
{
{
{
{ 0 }, { 0 }, { 0 }, { 0 },
0, 0,
{ { 0, }, { 0, } },
{ { 0, }, { 0, } },
0, 0,
0, 0,
0, 0,
"", "", { 0 }, { 0 },
0, 0
},
sizeof(struct arpt_entry),
sizeof(struct arpt_standard),
0,
{ 0, 0 }, { } },
{ { { { ARPT_ALIGN(sizeof(struct arpt_standard_target)), "" } }, { } },
-NF_ACCEPT - 1 }
}, },
/* ARP_FORWARD */ .underflow = {
{ [NF_ARP_IN] = 0,
{ [NF_ARP_OUT] = sizeof(struct arpt_standard),
{ [NF_ARP_FORWARD] = 2 * sizeof(struct arpt_standard),
{ 0 }, { 0 }, { 0 }, { 0 },
0, 0,
{ { 0, }, { 0, } },
{ { 0, }, { 0, } },
0, 0,
0, 0,
0, 0,
"", "", { 0 }, { 0 },
0, 0
}, },
sizeof(struct arpt_entry),
sizeof(struct arpt_standard),
0,
{ 0, 0 }, { } },
{ { { { ARPT_ALIGN(sizeof(struct arpt_standard_target)), "" } }, { } },
-NF_ACCEPT - 1 }
}
}, },
/* ERROR */ .entries = {
{ ARPT_STANDARD_INIT(NF_ACCEPT), /* ARP_IN */
{ ARPT_STANDARD_INIT(NF_ACCEPT), /* ARP_OUT */
{ ARPT_STANDARD_INIT(NF_ACCEPT), /* ARP_FORWARD */
{ 0 }, { 0 }, { 0 }, { 0 },
0, 0,
{ { 0, }, { 0, } },
{ { 0, }, { 0, } },
0, 0,
0, 0,
0, 0,
"", "", { 0 }, { 0 },
0, 0
}, },
sizeof(struct arpt_entry), .term = ARPT_ERROR_INIT,
sizeof(struct arpt_error),
0,
{ 0, 0 }, { } },
{ { { { ARPT_ALIGN(sizeof(struct arpt_error_target)), ARPT_ERROR_TARGET } },
{ } },
"ERROR"
}
}
}; };
static struct arpt_table packet_filter = { static struct arpt_table packet_filter = {
......
...@@ -26,53 +26,29 @@ static struct ...@@ -26,53 +26,29 @@ static struct
struct ipt_replace repl; struct ipt_replace repl;
struct ipt_standard entries[3]; struct ipt_standard entries[3];
struct ipt_error term; struct ipt_error term;
} initial_table __initdata } initial_table __initdata = {
= { { "filter", FILTER_VALID_HOOKS, 4, .repl = {
sizeof(struct ipt_standard) * 3 + sizeof(struct ipt_error), .name = "filter",
{ [NF_IP_LOCAL_IN] = 0, .valid_hooks = FILTER_VALID_HOOKS,
.num_entries = 4,
.size = sizeof(struct ipt_standard) * 3 + sizeof(struct ipt_error),
.hook_entry = {
[NF_IP_LOCAL_IN] = 0,
[NF_IP_FORWARD] = sizeof(struct ipt_standard), [NF_IP_FORWARD] = sizeof(struct ipt_standard),
[NF_IP_LOCAL_OUT] = sizeof(struct ipt_standard) * 2 }, [NF_IP_LOCAL_OUT] = sizeof(struct ipt_standard) * 2,
{ [NF_IP_LOCAL_IN] = 0, },
.underflow = {
[NF_IP_LOCAL_IN] = 0,
[NF_IP_FORWARD] = sizeof(struct ipt_standard), [NF_IP_FORWARD] = sizeof(struct ipt_standard),
[NF_IP_LOCAL_OUT] = sizeof(struct ipt_standard) * 2 }, [NF_IP_LOCAL_OUT] = sizeof(struct ipt_standard) * 2,
0, NULL, { } },
{
/* LOCAL_IN */
{ { { { 0 }, { 0 }, { 0 }, { 0 }, "", "", { 0 }, { 0 }, 0, 0, 0 },
0,
sizeof(struct ipt_entry),
sizeof(struct ipt_standard),
0, { 0, 0 }, { } },
{ { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
-NF_ACCEPT - 1 } },
/* FORWARD */
{ { { { 0 }, { 0 }, { 0 }, { 0 }, "", "", { 0 }, { 0 }, 0, 0, 0 },
0,
sizeof(struct ipt_entry),
sizeof(struct ipt_standard),
0, { 0, 0 }, { } },
{ { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
-NF_ACCEPT - 1 } },
/* LOCAL_OUT */
{ { { { 0 }, { 0 }, { 0 }, { 0 }, "", "", { 0 }, { 0 }, 0, 0, 0 },
0,
sizeof(struct ipt_entry),
sizeof(struct ipt_standard),
0, { 0, 0 }, { } },
{ { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
-NF_ACCEPT - 1 } }
}, },
/* ERROR */ },
{ { { { 0 }, { 0 }, { 0 }, { 0 }, "", "", { 0 }, { 0 }, 0, 0, 0 }, .entries = {
0, IPT_STANDARD_INIT(NF_ACCEPT), /* LOCAL_IN */
sizeof(struct ipt_entry), IPT_STANDARD_INIT(NF_ACCEPT), /* FORWARD */
sizeof(struct ipt_error), IPT_STANDARD_INIT(NF_ACCEPT), /* LOCAL_OUT */
0, { 0, 0 }, { } }, },
{ { { { IPT_ALIGN(sizeof(struct ipt_error_target)), IPT_ERROR_TARGET } }, .term = IPT_ERROR_INIT, /* ERROR */
{ } },
"ERROR"
}
}
}; };
static struct xt_table packet_filter = { static struct xt_table packet_filter = {
...@@ -105,7 +81,8 @@ ipt_local_out_hook(unsigned int hook, ...@@ -105,7 +81,8 @@ ipt_local_out_hook(unsigned int hook,
if ((*pskb)->len < sizeof(struct iphdr) if ((*pskb)->len < sizeof(struct iphdr)
|| ip_hdrlen(*pskb) < sizeof(struct iphdr)) { || ip_hdrlen(*pskb) < sizeof(struct iphdr)) {
if (net_ratelimit()) if (net_ratelimit())
printk("ipt_hook: happy cracking.\n"); printk("iptable_filter: ignoring short SOCK_RAW "
"packet.\n");
return NF_ACCEPT; return NF_ACCEPT;
} }
......
...@@ -33,73 +33,35 @@ static struct ...@@ -33,73 +33,35 @@ static struct
struct ipt_replace repl; struct ipt_replace repl;
struct ipt_standard entries[5]; struct ipt_standard entries[5];
struct ipt_error term; struct ipt_error term;
} initial_table __initdata } initial_table __initdata = {
= { { "mangle", MANGLE_VALID_HOOKS, 6, .repl = {
sizeof(struct ipt_standard) * 5 + sizeof(struct ipt_error), .name = "mangle",
{ [NF_IP_PRE_ROUTING] = 0, .valid_hooks = MANGLE_VALID_HOOKS,
.num_entries = 6,
.size = sizeof(struct ipt_standard) * 5 + sizeof(struct ipt_error),
.hook_entry = {
[NF_IP_PRE_ROUTING] = 0,
[NF_IP_LOCAL_IN] = sizeof(struct ipt_standard), [NF_IP_LOCAL_IN] = sizeof(struct ipt_standard),
[NF_IP_FORWARD] = sizeof(struct ipt_standard) * 2, [NF_IP_FORWARD] = sizeof(struct ipt_standard) * 2,
[NF_IP_LOCAL_OUT] = sizeof(struct ipt_standard) * 3, [NF_IP_LOCAL_OUT] = sizeof(struct ipt_standard) * 3,
[NF_IP_POST_ROUTING] = sizeof(struct ipt_standard) * 4 }, [NF_IP_POST_ROUTING] = sizeof(struct ipt_standard) * 4,
{ [NF_IP_PRE_ROUTING] = 0, },
.underflow = {
[NF_IP_PRE_ROUTING] = 0,
[NF_IP_LOCAL_IN] = sizeof(struct ipt_standard), [NF_IP_LOCAL_IN] = sizeof(struct ipt_standard),
[NF_IP_FORWARD] = sizeof(struct ipt_standard) * 2, [NF_IP_FORWARD] = sizeof(struct ipt_standard) * 2,
[NF_IP_LOCAL_OUT] = sizeof(struct ipt_standard) * 3, [NF_IP_LOCAL_OUT] = sizeof(struct ipt_standard) * 3,
[NF_IP_POST_ROUTING] = sizeof(struct ipt_standard) * 4 }, [NF_IP_POST_ROUTING] = sizeof(struct ipt_standard) * 4,
0, NULL, { } },
{
/* PRE_ROUTING */
{ { { { 0 }, { 0 }, { 0 }, { 0 }, "", "", { 0 }, { 0 }, 0, 0, 0 },
0,
sizeof(struct ipt_entry),
sizeof(struct ipt_standard),
0, { 0, 0 }, { } },
{ { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
-NF_ACCEPT - 1 } },
/* LOCAL_IN */
{ { { { 0 }, { 0 }, { 0 }, { 0 }, "", "", { 0 }, { 0 }, 0, 0, 0 },
0,
sizeof(struct ipt_entry),
sizeof(struct ipt_standard),
0, { 0, 0 }, { } },
{ { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
-NF_ACCEPT - 1 } },
/* FORWARD */
{ { { { 0 }, { 0 }, { 0 }, { 0 }, "", "", { 0 }, { 0 }, 0, 0, 0 },
0,
sizeof(struct ipt_entry),
sizeof(struct ipt_standard),
0, { 0, 0 }, { } },
{ { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
-NF_ACCEPT - 1 } },
/* LOCAL_OUT */
{ { { { 0 }, { 0 }, { 0 }, { 0 }, "", "", { 0 }, { 0 }, 0, 0, 0 },
0,
sizeof(struct ipt_entry),
sizeof(struct ipt_standard),
0, { 0, 0 }, { } },
{ { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
-NF_ACCEPT - 1 } },
/* POST_ROUTING */
{ { { { 0 }, { 0 }, { 0 }, { 0 }, "", "", { 0 }, { 0 }, 0, 0, 0 },
0,
sizeof(struct ipt_entry),
sizeof(struct ipt_standard),
0, { 0, 0 }, { } },
{ { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
-NF_ACCEPT - 1 } },
}, },
/* ERROR */ },
{ { { { 0 }, { 0 }, { 0 }, { 0 }, "", "", { 0 }, { 0 }, 0, 0, 0 }, .entries = {
0, IPT_STANDARD_INIT(NF_ACCEPT), /* PRE_ROUTING */
sizeof(struct ipt_entry), IPT_STANDARD_INIT(NF_ACCEPT), /* LOCAL_IN */
sizeof(struct ipt_error), IPT_STANDARD_INIT(NF_ACCEPT), /* FORWARD */
0, { 0, 0 }, { } }, IPT_STANDARD_INIT(NF_ACCEPT), /* LOCAL_OUT */
{ { { { IPT_ALIGN(sizeof(struct ipt_error_target)), IPT_ERROR_TARGET } }, IPT_STANDARD_INIT(NF_ACCEPT), /* POST_ROUTING */
{ } }, },
"ERROR" .term = IPT_ERROR_INIT, /* ERROR */
}
}
}; };
static struct xt_table packet_mangler = { static struct xt_table packet_mangler = {
...@@ -138,7 +100,8 @@ ipt_local_hook(unsigned int hook, ...@@ -138,7 +100,8 @@ ipt_local_hook(unsigned int hook,
if ((*pskb)->len < sizeof(struct iphdr) if ((*pskb)->len < sizeof(struct iphdr)
|| ip_hdrlen(*pskb) < sizeof(struct iphdr)) { || ip_hdrlen(*pskb) < sizeof(struct iphdr)) {
if (net_ratelimit()) if (net_ratelimit())
printk("ipt_hook: happy cracking.\n"); printk("iptable_mangle: ignoring short SOCK_RAW "
"packet.\n");
return NF_ACCEPT; return NF_ACCEPT;
} }
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
*/ */
#include <linux/module.h> #include <linux/module.h>
#include <linux/netfilter_ipv4/ip_tables.h> #include <linux/netfilter_ipv4/ip_tables.h>
#include <net/ip.h>
#define RAW_VALID_HOOKS ((1 << NF_IP_PRE_ROUTING) | (1 << NF_IP_LOCAL_OUT)) #define RAW_VALID_HOOKS ((1 << NF_IP_PRE_ROUTING) | (1 << NF_IP_LOCAL_OUT))
...@@ -21,62 +22,18 @@ static struct ...@@ -21,62 +22,18 @@ static struct
.size = sizeof(struct ipt_standard) * 2 + sizeof(struct ipt_error), .size = sizeof(struct ipt_standard) * 2 + sizeof(struct ipt_error),
.hook_entry = { .hook_entry = {
[NF_IP_PRE_ROUTING] = 0, [NF_IP_PRE_ROUTING] = 0,
[NF_IP_LOCAL_OUT] = sizeof(struct ipt_standard) }, [NF_IP_LOCAL_OUT] = sizeof(struct ipt_standard)
},
.underflow = { .underflow = {
[NF_IP_PRE_ROUTING] = 0, [NF_IP_PRE_ROUTING] = 0,
[NF_IP_LOCAL_OUT] = sizeof(struct ipt_standard) }, [NF_IP_LOCAL_OUT] = sizeof(struct ipt_standard)
},
.entries = {
/* PRE_ROUTING */
{
.entry = {
.target_offset = sizeof(struct ipt_entry),
.next_offset = sizeof(struct ipt_standard),
},
.target = {
.target = {
.u = {
.target_size = IPT_ALIGN(sizeof(struct ipt_standard_target)),
},
},
.verdict = -NF_ACCEPT - 1,
},
},
/* LOCAL_OUT */
{
.entry = {
.target_offset = sizeof(struct ipt_entry),
.next_offset = sizeof(struct ipt_standard),
},
.target = {
.target = {
.u = {
.target_size = IPT_ALIGN(sizeof(struct ipt_standard_target)),
},
},
.verdict = -NF_ACCEPT - 1,
},
},
}, },
/* ERROR */
.term = {
.entry = {
.target_offset = sizeof(struct ipt_entry),
.next_offset = sizeof(struct ipt_error),
}, },
.target = { .entries = {
.target = { IPT_STANDARD_INIT(NF_ACCEPT), /* PRE_ROUTING */
.u = { IPT_STANDARD_INIT(NF_ACCEPT), /* LOCAL_OUT */
.user = {
.target_size = IPT_ALIGN(sizeof(struct ipt_error_target)),
.name = IPT_ERROR_TARGET,
},
},
},
.errorname = "ERROR",
}, },
} .term = IPT_ERROR_INIT, /* ERROR */
}; };
static struct xt_table packet_raw = { static struct xt_table packet_raw = {
...@@ -98,6 +55,24 @@ ipt_hook(unsigned int hook, ...@@ -98,6 +55,24 @@ ipt_hook(unsigned int hook,
return ipt_do_table(pskb, hook, in, out, &packet_raw); return ipt_do_table(pskb, hook, in, out, &packet_raw);
} }
static unsigned int
ipt_local_hook(unsigned int hook,
struct sk_buff **pskb,
const struct net_device *in,
const struct net_device *out,
int (*okfn)(struct sk_buff *))
{
/* root is playing with raw sockets. */
if ((*pskb)->len < sizeof(struct iphdr) ||
ip_hdrlen(*pskb) < sizeof(struct iphdr)) {
if (net_ratelimit())
printk("iptable_raw: ignoring short SOCK_RAW"
"packet.\n");
return NF_ACCEPT;
}
return ipt_do_table(pskb, hook, in, out, &packet_raw);
}
/* '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[] = {
{ {
...@@ -108,7 +83,7 @@ static struct nf_hook_ops ipt_ops[] = { ...@@ -108,7 +83,7 @@ static struct nf_hook_ops ipt_ops[] = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
}, },
{ {
.hook = ipt_hook, .hook = ipt_local_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,
......
...@@ -46,77 +46,20 @@ static struct ...@@ -46,77 +46,20 @@ static struct
.hook_entry = { .hook_entry = {
[NF_IP_PRE_ROUTING] = 0, [NF_IP_PRE_ROUTING] = 0,
[NF_IP_POST_ROUTING] = sizeof(struct ipt_standard), [NF_IP_POST_ROUTING] = sizeof(struct ipt_standard),
[NF_IP_LOCAL_OUT] = sizeof(struct ipt_standard) * 2 }, [NF_IP_LOCAL_OUT] = sizeof(struct ipt_standard) * 2
},
.underflow = { .underflow = {
[NF_IP_PRE_ROUTING] = 0, [NF_IP_PRE_ROUTING] = 0,
[NF_IP_POST_ROUTING] = sizeof(struct ipt_standard), [NF_IP_POST_ROUTING] = sizeof(struct ipt_standard),
[NF_IP_LOCAL_OUT] = sizeof(struct ipt_standard) * 2 }, [NF_IP_LOCAL_OUT] = sizeof(struct ipt_standard) * 2
},
.entries = {
/* PRE_ROUTING */
{
.entry = {
.target_offset = sizeof(struct ipt_entry),
.next_offset = sizeof(struct ipt_standard),
},
.target = {
.target = {
.u = {
.target_size = IPT_ALIGN(sizeof(struct ipt_standard_target)),
},
},
.verdict = -NF_ACCEPT - 1,
},
},
/* POST_ROUTING */
{
.entry = {
.target_offset = sizeof(struct ipt_entry),
.next_offset = sizeof(struct ipt_standard),
},
.target = {
.target = {
.u = {
.target_size = IPT_ALIGN(sizeof(struct ipt_standard_target)),
},
},
.verdict = -NF_ACCEPT - 1,
},
}, },
/* LOCAL_OUT */
{
.entry = {
.target_offset = sizeof(struct ipt_entry),
.next_offset = sizeof(struct ipt_standard),
}, },
.target = { .entries = {
.target = { IPT_STANDARD_INIT(NF_ACCEPT), /* PRE_ROUTING */
.u = { IPT_STANDARD_INIT(NF_ACCEPT), /* POST_ROUTING */
.target_size = IPT_ALIGN(sizeof(struct ipt_standard_target)), IPT_STANDARD_INIT(NF_ACCEPT), /* LOCAL_OUT */
},
},
.verdict = -NF_ACCEPT - 1,
},
},
},
/* ERROR */
.term = {
.entry = {
.target_offset = sizeof(struct ipt_entry),
.next_offset = sizeof(struct ipt_error),
},
.target = {
.target = {
.u = {
.user = {
.target_size = IPT_ALIGN(sizeof(struct ipt_error_target)),
.name = IPT_ERROR_TARGET,
},
},
},
.errorname = "ERROR",
}, },
} .term = IPT_ERROR_INIT, /* ERROR */
}; };
static struct xt_table nat_table = { static struct xt_table nat_table = {
...@@ -230,9 +173,7 @@ static int ipt_dnat_checkentry(const char *tablename, ...@@ -230,9 +173,7 @@ static int ipt_dnat_checkentry(const char *tablename,
} }
inline unsigned int inline unsigned int
alloc_null_binding(struct nf_conn *ct, alloc_null_binding(struct nf_conn *ct, unsigned int hooknum)
struct nf_nat_info *info,
unsigned int hooknum)
{ {
/* Force range to this IP; let proto decide mapping for /* Force range to this IP; let proto decide mapping for
per-proto parts (hence not IP_NAT_RANGE_PROTO_SPECIFIED). per-proto parts (hence not IP_NAT_RANGE_PROTO_SPECIFIED).
...@@ -251,9 +192,7 @@ alloc_null_binding(struct nf_conn *ct, ...@@ -251,9 +192,7 @@ alloc_null_binding(struct nf_conn *ct,
} }
unsigned int unsigned int
alloc_null_binding_confirmed(struct nf_conn *ct, alloc_null_binding_confirmed(struct nf_conn *ct, unsigned int hooknum)
struct nf_nat_info *info,
unsigned int hooknum)
{ {
__be32 ip __be32 ip
= (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC = (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC
...@@ -275,8 +214,7 @@ int nf_nat_rule_find(struct sk_buff **pskb, ...@@ -275,8 +214,7 @@ int nf_nat_rule_find(struct sk_buff **pskb,
unsigned int hooknum, unsigned int hooknum,
const struct net_device *in, const struct net_device *in,
const struct net_device *out, const struct net_device *out,
struct nf_conn *ct, struct nf_conn *ct)
struct nf_nat_info *info)
{ {
int ret; int ret;
...@@ -285,7 +223,7 @@ int nf_nat_rule_find(struct sk_buff **pskb, ...@@ -285,7 +223,7 @@ int nf_nat_rule_find(struct sk_buff **pskb,
if (ret == NF_ACCEPT) { if (ret == NF_ACCEPT) {
if (!nf_nat_initialized(ct, HOOK2MANIP(hooknum))) if (!nf_nat_initialized(ct, HOOK2MANIP(hooknum)))
/* NUL mapping */ /* NUL mapping */
ret = alloc_null_binding(ct, info, hooknum); ret = alloc_null_binding(ct, hooknum);
} }
return ret; return ret;
} }
......
...@@ -80,7 +80,6 @@ nf_nat_fn(unsigned int hooknum, ...@@ -80,7 +80,6 @@ nf_nat_fn(unsigned int hooknum,
struct nf_conn *ct; struct nf_conn *ct;
enum ip_conntrack_info ctinfo; enum ip_conntrack_info ctinfo;
struct nf_conn_nat *nat; struct nf_conn_nat *nat;
struct nf_nat_info *info;
/* maniptype == SRC for postrouting. */ /* maniptype == SRC for postrouting. */
enum nf_nat_manip_type maniptype = HOOK2MANIP(hooknum); enum nf_nat_manip_type maniptype = HOOK2MANIP(hooknum);
...@@ -129,7 +128,6 @@ nf_nat_fn(unsigned int hooknum, ...@@ -129,7 +128,6 @@ nf_nat_fn(unsigned int hooknum,
} }
/* Fall thru... (Only ICMPs can be IP_CT_IS_REPLY) */ /* Fall thru... (Only ICMPs can be IP_CT_IS_REPLY) */
case IP_CT_NEW: case IP_CT_NEW:
info = &nat->info;
/* Seen it before? This can happen for loopback, retrans, /* Seen it before? This can happen for loopback, retrans,
or local packets.. */ or local packets.. */
...@@ -138,14 +136,13 @@ nf_nat_fn(unsigned int hooknum, ...@@ -138,14 +136,13 @@ nf_nat_fn(unsigned int hooknum,
if (unlikely(nf_ct_is_confirmed(ct))) if (unlikely(nf_ct_is_confirmed(ct)))
/* NAT module was loaded late */ /* NAT module was loaded late */
ret = alloc_null_binding_confirmed(ct, info, ret = alloc_null_binding_confirmed(ct, hooknum);
hooknum);
else if (hooknum == NF_IP_LOCAL_IN) else if (hooknum == NF_IP_LOCAL_IN)
/* LOCAL_IN hook doesn't have a chain! */ /* LOCAL_IN hook doesn't have a chain! */
ret = alloc_null_binding(ct, info, hooknum); ret = alloc_null_binding(ct, hooknum);
else else
ret = nf_nat_rule_find(pskb, hooknum, in, out, ret = nf_nat_rule_find(pskb, hooknum, in, out,
ct, info); ct);
if (ret != NF_ACCEPT) { if (ret != NF_ACCEPT) {
return ret; return ret;
...@@ -160,10 +157,8 @@ nf_nat_fn(unsigned int hooknum, ...@@ -160,10 +157,8 @@ nf_nat_fn(unsigned int hooknum,
/* ESTABLISHED */ /* ESTABLISHED */
NF_CT_ASSERT(ctinfo == IP_CT_ESTABLISHED || NF_CT_ASSERT(ctinfo == IP_CT_ESTABLISHED ||
ctinfo == (IP_CT_ESTABLISHED+IP_CT_IS_REPLY)); ctinfo == (IP_CT_ESTABLISHED+IP_CT_IS_REPLY));
info = &nat->info;
} }
NF_CT_ASSERT(info);
return nf_nat_packet(ct, ctinfo, hooknum, pskb); return nf_nat_packet(ct, ctinfo, hooknum, pskb);
} }
......
...@@ -118,15 +118,15 @@ static int udp_port_rover; ...@@ -118,15 +118,15 @@ static int udp_port_rover;
* Note about this hash function : * Note about this hash function :
* Typical use is probably daddr = 0, only dport is going to vary hash * Typical use is probably daddr = 0, only dport is going to vary hash
*/ */
static inline unsigned int hash_port_and_addr(__u16 port, __be32 addr) static inline unsigned int udp_hash_port(__u16 port)
{ {
addr ^= addr >> 16; return port;
addr ^= addr >> 8;
return port ^ addr;
} }
static inline int __udp_lib_port_inuse(unsigned int hash, int port, static inline int __udp_lib_port_inuse(unsigned int hash, int port,
__be32 daddr, struct hlist_head udptable[]) const struct sock *this_sk,
struct hlist_head udptable[],
const struct udp_get_port_ops *ops)
{ {
struct sock *sk; struct sock *sk;
struct hlist_node *node; struct hlist_node *node;
...@@ -138,7 +138,10 @@ static inline int __udp_lib_port_inuse(unsigned int hash, int port, ...@@ -138,7 +138,10 @@ static inline int __udp_lib_port_inuse(unsigned int hash, int port,
inet = inet_sk(sk); inet = inet_sk(sk);
if (inet->num != port) if (inet->num != port)
continue; continue;
if (inet->rcv_saddr == daddr) if (this_sk) {
if (ops->saddr_cmp(sk, this_sk))
return 1;
} else if (ops->saddr_any(sk))
return 1; return 1;
} }
return 0; return 0;
...@@ -151,12 +154,11 @@ static inline int __udp_lib_port_inuse(unsigned int hash, int port, ...@@ -151,12 +154,11 @@ static inline int __udp_lib_port_inuse(unsigned int hash, int port,
* @snum: port number to look up * @snum: port number to look up
* @udptable: hash list table, must be of UDP_HTABLE_SIZE * @udptable: hash list table, must be of UDP_HTABLE_SIZE
* @port_rover: pointer to record of last unallocated port * @port_rover: pointer to record of last unallocated port
* @saddr_comp: AF-dependent comparison of bound local IP addresses * @ops: AF-dependent address operations
*/ */
int __udp_lib_get_port(struct sock *sk, unsigned short snum, int __udp_lib_get_port(struct sock *sk, unsigned short snum,
struct hlist_head udptable[], int *port_rover, struct hlist_head udptable[], int *port_rover,
int (*saddr_comp)(const struct sock *sk1, const struct udp_get_port_ops *ops)
const struct sock *sk2 ) )
{ {
struct hlist_node *node; struct hlist_node *node;
struct hlist_head *head; struct hlist_head *head;
...@@ -176,8 +178,7 @@ int __udp_lib_get_port(struct sock *sk, unsigned short snum, ...@@ -176,8 +178,7 @@ int __udp_lib_get_port(struct sock *sk, unsigned short snum,
for (i = 0; i < UDP_HTABLE_SIZE; i++, result++) { for (i = 0; i < UDP_HTABLE_SIZE; i++, result++) {
int size; int size;
hash = hash_port_and_addr(result, hash = ops->hash_port_and_rcv_saddr(result, sk);
inet_sk(sk)->rcv_saddr);
head = &udptable[hash & (UDP_HTABLE_SIZE - 1)]; head = &udptable[hash & (UDP_HTABLE_SIZE - 1)];
if (hlist_empty(head)) { if (hlist_empty(head)) {
if (result > sysctl_local_port_range[1]) if (result > sysctl_local_port_range[1])
...@@ -203,17 +204,16 @@ int __udp_lib_get_port(struct sock *sk, unsigned short snum, ...@@ -203,17 +204,16 @@ int __udp_lib_get_port(struct sock *sk, unsigned short snum,
result = sysctl_local_port_range[0] result = sysctl_local_port_range[0]
+ ((result - sysctl_local_port_range[0]) & + ((result - sysctl_local_port_range[0]) &
(UDP_HTABLE_SIZE - 1)); (UDP_HTABLE_SIZE - 1));
hash = hash_port_and_addr(result, 0); hash = udp_hash_port(result);
if (__udp_lib_port_inuse(hash, result, if (__udp_lib_port_inuse(hash, result,
0, udptable)) NULL, udptable, ops))
continue; continue;
if (!inet_sk(sk)->rcv_saddr) if (ops->saddr_any(sk))
break; break;
hash = hash_port_and_addr(result, hash = ops->hash_port_and_rcv_saddr(result, sk);
inet_sk(sk)->rcv_saddr);
if (! __udp_lib_port_inuse(hash, result, if (! __udp_lib_port_inuse(hash, result,
inet_sk(sk)->rcv_saddr, udptable)) sk, udptable, ops))
break; break;
} }
if (i >= (1 << 16) / UDP_HTABLE_SIZE) if (i >= (1 << 16) / UDP_HTABLE_SIZE)
...@@ -221,7 +221,7 @@ int __udp_lib_get_port(struct sock *sk, unsigned short snum, ...@@ -221,7 +221,7 @@ int __udp_lib_get_port(struct sock *sk, unsigned short snum,
gotit: gotit:
*port_rover = snum = result; *port_rover = snum = result;
} else { } else {
hash = hash_port_and_addr(snum, 0); hash = udp_hash_port(snum);
head = &udptable[hash & (UDP_HTABLE_SIZE - 1)]; head = &udptable[hash & (UDP_HTABLE_SIZE - 1)];
sk_for_each(sk2, node, head) sk_for_each(sk2, node, head)
...@@ -231,12 +231,11 @@ int __udp_lib_get_port(struct sock *sk, unsigned short snum, ...@@ -231,12 +231,11 @@ int __udp_lib_get_port(struct sock *sk, unsigned short snum,
(!sk2->sk_reuse || !sk->sk_reuse) && (!sk2->sk_reuse || !sk->sk_reuse) &&
(!sk2->sk_bound_dev_if || !sk->sk_bound_dev_if || (!sk2->sk_bound_dev_if || !sk->sk_bound_dev_if ||
sk2->sk_bound_dev_if == sk->sk_bound_dev_if) && sk2->sk_bound_dev_if == sk->sk_bound_dev_if) &&
(*saddr_comp)(sk, sk2)) ops->saddr_cmp(sk, sk2))
goto fail; goto fail;
if (inet_sk(sk)->rcv_saddr) { if (!ops->saddr_any(sk)) {
hash = hash_port_and_addr(snum, hash = ops->hash_port_and_rcv_saddr(snum, sk);
inet_sk(sk)->rcv_saddr);
head = &udptable[hash & (UDP_HTABLE_SIZE - 1)]; head = &udptable[hash & (UDP_HTABLE_SIZE - 1)];
sk_for_each(sk2, node, head) sk_for_each(sk2, node, head)
...@@ -248,7 +247,7 @@ int __udp_lib_get_port(struct sock *sk, unsigned short snum, ...@@ -248,7 +247,7 @@ int __udp_lib_get_port(struct sock *sk, unsigned short snum,
!sk->sk_bound_dev_if || !sk->sk_bound_dev_if ||
sk2->sk_bound_dev_if == sk2->sk_bound_dev_if ==
sk->sk_bound_dev_if) && sk->sk_bound_dev_if) &&
(*saddr_comp)(sk, sk2)) ops->saddr_cmp(sk, sk2))
goto fail; goto fail;
} }
} }
...@@ -266,12 +265,12 @@ int __udp_lib_get_port(struct sock *sk, unsigned short snum, ...@@ -266,12 +265,12 @@ int __udp_lib_get_port(struct sock *sk, unsigned short snum,
} }
int udp_get_port(struct sock *sk, unsigned short snum, int udp_get_port(struct sock *sk, unsigned short snum,
int (*scmp)(const struct sock *, const struct sock *)) const struct udp_get_port_ops *ops)
{ {
return __udp_lib_get_port(sk, snum, udp_hash, &udp_port_rover, scmp); return __udp_lib_get_port(sk, snum, udp_hash, &udp_port_rover, ops);
} }
int ipv4_rcv_saddr_equal(const struct sock *sk1, const struct sock *sk2) static int ipv4_rcv_saddr_equal(const struct sock *sk1, const struct sock *sk2)
{ {
struct inet_sock *inet1 = inet_sk(sk1), *inet2 = inet_sk(sk2); struct inet_sock *inet1 = inet_sk(sk1), *inet2 = inet_sk(sk2);
...@@ -280,9 +279,33 @@ int ipv4_rcv_saddr_equal(const struct sock *sk1, const struct sock *sk2) ...@@ -280,9 +279,33 @@ int ipv4_rcv_saddr_equal(const struct sock *sk1, const struct sock *sk2)
inet1->rcv_saddr == inet2->rcv_saddr )); inet1->rcv_saddr == inet2->rcv_saddr ));
} }
static int ipv4_rcv_saddr_any(const struct sock *sk)
{
return !inet_sk(sk)->rcv_saddr;
}
static inline unsigned int ipv4_hash_port_and_addr(__u16 port, __be32 addr)
{
addr ^= addr >> 16;
addr ^= addr >> 8;
return port ^ addr;
}
static unsigned int ipv4_hash_port_and_rcv_saddr(__u16 port,
const struct sock *sk)
{
return ipv4_hash_port_and_addr(port, inet_sk(sk)->rcv_saddr);
}
const struct udp_get_port_ops udp_ipv4_ops = {
.saddr_cmp = ipv4_rcv_saddr_equal,
.saddr_any = ipv4_rcv_saddr_any,
.hash_port_and_rcv_saddr = ipv4_hash_port_and_rcv_saddr,
};
static inline int udp_v4_get_port(struct sock *sk, unsigned short snum) static inline int udp_v4_get_port(struct sock *sk, unsigned short snum)
{ {
return udp_get_port(sk, snum, ipv4_rcv_saddr_equal); return udp_get_port(sk, snum, &udp_ipv4_ops);
} }
/* UDP is nearly always wildcards out the wazoo, it makes no sense to try /* UDP is nearly always wildcards out the wazoo, it makes no sense to try
...@@ -297,8 +320,8 @@ static struct sock *__udp4_lib_lookup(__be32 saddr, __be16 sport, ...@@ -297,8 +320,8 @@ static struct sock *__udp4_lib_lookup(__be32 saddr, __be16 sport,
unsigned int hash, hashwild; unsigned int hash, hashwild;
int score, best = -1, hport = ntohs(dport); int score, best = -1, hport = ntohs(dport);
hash = hash_port_and_addr(hport, daddr); hash = ipv4_hash_port_and_addr(hport, daddr);
hashwild = hash_port_and_addr(hport, 0); hashwild = udp_hash_port(hport);
read_lock(&udp_hash_lock); read_lock(&udp_hash_lock);
...@@ -1198,8 +1221,8 @@ static int __udp4_lib_mcast_deliver(struct sk_buff *skb, ...@@ -1198,8 +1221,8 @@ static int __udp4_lib_mcast_deliver(struct sk_buff *skb,
struct sock *sk, *skw, *sknext; struct sock *sk, *skw, *sknext;
int dif; int dif;
int hport = ntohs(uh->dest); int hport = ntohs(uh->dest);
unsigned int hash = hash_port_and_addr(hport, daddr); unsigned int hash = ipv4_hash_port_and_addr(hport, daddr);
unsigned int hashwild = hash_port_and_addr(hport, 0); unsigned int hashwild = udp_hash_port(hport);
dif = skb->dev->ifindex; dif = skb->dev->ifindex;
......
...@@ -5,14 +5,14 @@ ...@@ -5,14 +5,14 @@
#include <net/protocol.h> #include <net/protocol.h>
#include <net/inet_common.h> #include <net/inet_common.h>
extern const struct udp_get_port_ops udp_ipv4_ops;
extern int __udp4_lib_rcv(struct sk_buff *, struct hlist_head [], int ); extern int __udp4_lib_rcv(struct sk_buff *, struct hlist_head [], int );
extern void __udp4_lib_err(struct sk_buff *, u32, struct hlist_head []); extern void __udp4_lib_err(struct sk_buff *, u32, struct hlist_head []);
extern int __udp_lib_get_port(struct sock *sk, unsigned short snum, extern int __udp_lib_get_port(struct sock *sk, unsigned short snum,
struct hlist_head udptable[], int *port_rover, struct hlist_head udptable[], int *port_rover,
int (*)(const struct sock*,const struct sock*)); const struct udp_get_port_ops *ops);
extern int ipv4_rcv_saddr_equal(const struct sock *, const struct sock *);
extern int udp_setsockopt(struct sock *sk, int level, int optname, extern int udp_setsockopt(struct sock *sk, int level, int optname,
char __user *optval, int optlen); char __user *optval, int optlen);
......
...@@ -19,14 +19,15 @@ struct hlist_head udplite_hash[UDP_HTABLE_SIZE]; ...@@ -19,14 +19,15 @@ struct hlist_head udplite_hash[UDP_HTABLE_SIZE];
static int udplite_port_rover; static int udplite_port_rover;
int udplite_get_port(struct sock *sk, unsigned short p, int udplite_get_port(struct sock *sk, unsigned short p,
int (*c)(const struct sock *, const struct sock *)) const struct udp_get_port_ops *ops)
{ {
return __udp_lib_get_port(sk, p, udplite_hash, &udplite_port_rover, c); return __udp_lib_get_port(sk, p, udplite_hash,
&udplite_port_rover, ops);
} }
static int udplite_v4_get_port(struct sock *sk, unsigned short snum) static int udplite_v4_get_port(struct sock *sk, unsigned short snum)
{ {
return udplite_get_port(sk, snum, ipv4_rcv_saddr_equal); return udplite_get_port(sk, snum, &udp_ipv4_ops);
} }
static int udplite_rcv(struct sk_buff *skb) static int udplite_rcv(struct sk_buff *skb)
......
...@@ -4204,6 +4204,10 @@ int __init addrconf_init(void) ...@@ -4204,6 +4204,10 @@ int __init addrconf_init(void)
return err; return err;
ip6_null_entry.rt6i_idev = in6_dev_get(&loopback_dev); ip6_null_entry.rt6i_idev = in6_dev_get(&loopback_dev);
#ifdef CONFIG_IPV6_MULTIPLE_TABLES
ip6_prohibit_entry.rt6i_idev = in6_dev_get(&loopback_dev);
ip6_blk_hole_entry.rt6i_idev = in6_dev_get(&loopback_dev);
#endif
register_netdevice_notifier(&ipv6_dev_notf); register_netdevice_notifier(&ipv6_dev_notf);
......
...@@ -660,6 +660,14 @@ EXPORT_SYMBOL_GPL(ipv6_invert_rthdr); ...@@ -660,6 +660,14 @@ EXPORT_SYMBOL_GPL(ipv6_invert_rthdr);
Hop-by-hop options. Hop-by-hop options.
**********************************/ **********************************/
/*
* Note: we cannot rely on skb->dst before we assign it in ip6_route_input().
*/
static inline struct inet6_dev *ipv6_skb_idev(struct sk_buff *skb)
{
return skb->dst ? ip6_dst_idev(skb->dst) : __in6_dev_get(skb->dev);
}
/* Router Alert as of RFC 2711 */ /* Router Alert as of RFC 2711 */
static int ipv6_hop_ra(struct sk_buff **skbp, int optoff) static int ipv6_hop_ra(struct sk_buff **skbp, int optoff)
...@@ -688,25 +696,25 @@ static int ipv6_hop_jumbo(struct sk_buff **skbp, int optoff) ...@@ -688,25 +696,25 @@ static int ipv6_hop_jumbo(struct sk_buff **skbp, int optoff)
if (nh[optoff + 1] != 4 || (optoff & 3) != 2) { if (nh[optoff + 1] != 4 || (optoff & 3) != 2) {
LIMIT_NETDEBUG(KERN_DEBUG "ipv6_hop_jumbo: wrong jumbo opt length/alignment %d\n", LIMIT_NETDEBUG(KERN_DEBUG "ipv6_hop_jumbo: wrong jumbo opt length/alignment %d\n",
nh[optoff+1]); nh[optoff+1]);
IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), IP6_INC_STATS_BH(ipv6_skb_idev(skb),
IPSTATS_MIB_INHDRERRORS); IPSTATS_MIB_INHDRERRORS);
goto drop; goto drop;
} }
pkt_len = ntohl(*(__be32 *)(nh + optoff + 2)); pkt_len = ntohl(*(__be32 *)(nh + optoff + 2));
if (pkt_len <= IPV6_MAXPLEN) { if (pkt_len <= IPV6_MAXPLEN) {
IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), IPSTATS_MIB_INHDRERRORS); IP6_INC_STATS_BH(ipv6_skb_idev(skb), IPSTATS_MIB_INHDRERRORS);
icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, optoff+2); icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, optoff+2);
return 0; return 0;
} }
if (ipv6_hdr(skb)->payload_len) { if (ipv6_hdr(skb)->payload_len) {
IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), IPSTATS_MIB_INHDRERRORS); IP6_INC_STATS_BH(ipv6_skb_idev(skb), IPSTATS_MIB_INHDRERRORS);
icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, optoff); icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, optoff);
return 0; return 0;
} }
if (pkt_len > skb->len - sizeof(struct ipv6hdr)) { if (pkt_len > skb->len - sizeof(struct ipv6hdr)) {
IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), IPSTATS_MIB_INTRUNCATEDPKTS); IP6_INC_STATS_BH(ipv6_skb_idev(skb), IPSTATS_MIB_INTRUNCATEDPKTS);
goto drop; goto drop;
} }
......
...@@ -463,10 +463,17 @@ int ip6_forward(struct sk_buff *skb) ...@@ -463,10 +463,17 @@ int ip6_forward(struct sk_buff *skb)
*/ */
if (xrlim_allow(dst, 1*HZ)) if (xrlim_allow(dst, 1*HZ))
ndisc_send_redirect(skb, n, target); ndisc_send_redirect(skb, n, target);
} else if (ipv6_addr_type(&hdr->saddr)&(IPV6_ADDR_MULTICAST|IPV6_ADDR_LOOPBACK } else {
|IPV6_ADDR_LINKLOCAL)) { int addrtype = ipv6_addr_type(&hdr->saddr);
/* This check is security critical. */ /* This check is security critical. */
if (addrtype & (IPV6_ADDR_MULTICAST|IPV6_ADDR_LOOPBACK))
goto error; goto error;
if (addrtype & IPV6_ADDR_LINKLOCAL) {
icmpv6_send(skb, ICMPV6_DEST_UNREACH,
ICMPV6_NOT_NEIGHBOUR, 0, skb->dev);
goto error;
}
} }
if (skb->len > dst_mtu(dst)) { if (skb->len > dst_mtu(dst)) {
......
...@@ -24,53 +24,29 @@ static struct ...@@ -24,53 +24,29 @@ static struct
struct ip6t_replace repl; struct ip6t_replace repl;
struct ip6t_standard entries[3]; struct ip6t_standard entries[3];
struct ip6t_error term; struct ip6t_error term;
} initial_table __initdata } initial_table __initdata = {
= { { "filter", FILTER_VALID_HOOKS, 4, .repl = {
sizeof(struct ip6t_standard) * 3 + sizeof(struct ip6t_error), .name = "filter",
{ [NF_IP6_LOCAL_IN] = 0, .valid_hooks = FILTER_VALID_HOOKS,
.num_entries = 4,
.size = sizeof(struct ip6t_standard) * 3 + sizeof(struct ip6t_error),
.hook_entry = {
[NF_IP6_LOCAL_IN] = 0,
[NF_IP6_FORWARD] = sizeof(struct ip6t_standard), [NF_IP6_FORWARD] = sizeof(struct ip6t_standard),
[NF_IP6_LOCAL_OUT] = sizeof(struct ip6t_standard) * 2 }, [NF_IP6_LOCAL_OUT] = sizeof(struct ip6t_standard) * 2
{ [NF_IP6_LOCAL_IN] = 0, },
.underflow = {
[NF_IP6_LOCAL_IN] = 0,
[NF_IP6_FORWARD] = sizeof(struct ip6t_standard), [NF_IP6_FORWARD] = sizeof(struct ip6t_standard),
[NF_IP6_LOCAL_OUT] = sizeof(struct ip6t_standard) * 2 }, [NF_IP6_LOCAL_OUT] = sizeof(struct ip6t_standard) * 2
0, NULL, { } },
{
/* LOCAL_IN */
{ { { { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, "", "", { 0 }, { 0 }, 0, 0, 0 },
0,
sizeof(struct ip6t_entry),
sizeof(struct ip6t_standard),
0, { 0, 0 }, { } },
{ { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
-NF_ACCEPT - 1 } },
/* FORWARD */
{ { { { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, "", "", { 0 }, { 0 }, 0, 0, 0 },
0,
sizeof(struct ip6t_entry),
sizeof(struct ip6t_standard),
0, { 0, 0 }, { } },
{ { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
-NF_ACCEPT - 1 } },
/* LOCAL_OUT */
{ { { { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, "", "", { 0 }, { 0 }, 0, 0, 0 },
0,
sizeof(struct ip6t_entry),
sizeof(struct ip6t_standard),
0, { 0, 0 }, { } },
{ { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
-NF_ACCEPT - 1 } }
}, },
/* ERROR */ },
{ { { { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, "", "", { 0 }, { 0 }, 0, 0, 0 }, .entries = {
0, IP6T_STANDARD_INIT(NF_ACCEPT), /* LOCAL_IN */
sizeof(struct ip6t_entry), IP6T_STANDARD_INIT(NF_ACCEPT), /* FORWARD */
sizeof(struct ip6t_error), IP6T_STANDARD_INIT(NF_ACCEPT), /* LOCAL_OUT */
0, { 0, 0 }, { } }, },
{ { { { IP6T_ALIGN(sizeof(struct ip6t_error_target)), IP6T_ERROR_TARGET } }, .term = IP6T_ERROR_INIT, /* ERROR */
{ } },
"ERROR"
}
}
}; };
static struct xt_table packet_filter = { static struct xt_table packet_filter = {
......
...@@ -32,73 +32,35 @@ static struct ...@@ -32,73 +32,35 @@ static struct
struct ip6t_replace repl; struct ip6t_replace repl;
struct ip6t_standard entries[5]; struct ip6t_standard entries[5];
struct ip6t_error term; struct ip6t_error term;
} initial_table __initdata } initial_table __initdata = {
= { { "mangle", MANGLE_VALID_HOOKS, 6, .repl = {
sizeof(struct ip6t_standard) * 5 + sizeof(struct ip6t_error), .name = "mangle",
{ [NF_IP6_PRE_ROUTING] = 0, .valid_hooks = MANGLE_VALID_HOOKS,
.num_entries = 6,
.size = sizeof(struct ip6t_standard) * 5 + sizeof(struct ip6t_error),
.hook_entry = {
[NF_IP6_PRE_ROUTING] = 0,
[NF_IP6_LOCAL_IN] = sizeof(struct ip6t_standard), [NF_IP6_LOCAL_IN] = sizeof(struct ip6t_standard),
[NF_IP6_FORWARD] = sizeof(struct ip6t_standard) * 2, [NF_IP6_FORWARD] = sizeof(struct ip6t_standard) * 2,
[NF_IP6_LOCAL_OUT] = sizeof(struct ip6t_standard) * 3, [NF_IP6_LOCAL_OUT] = sizeof(struct ip6t_standard) * 3,
[NF_IP6_POST_ROUTING] = sizeof(struct ip6t_standard) * 4}, [NF_IP6_POST_ROUTING] = sizeof(struct ip6t_standard) * 4,
{ [NF_IP6_PRE_ROUTING] = 0, },
.underflow = {
[NF_IP6_PRE_ROUTING] = 0,
[NF_IP6_LOCAL_IN] = sizeof(struct ip6t_standard), [NF_IP6_LOCAL_IN] = sizeof(struct ip6t_standard),
[NF_IP6_FORWARD] = sizeof(struct ip6t_standard) * 2, [NF_IP6_FORWARD] = sizeof(struct ip6t_standard) * 2,
[NF_IP6_LOCAL_OUT] = sizeof(struct ip6t_standard) * 3, [NF_IP6_LOCAL_OUT] = sizeof(struct ip6t_standard) * 3,
[NF_IP6_POST_ROUTING] = sizeof(struct ip6t_standard) * 4}, [NF_IP6_POST_ROUTING] = sizeof(struct ip6t_standard) * 4,
0, NULL, { } },
{
/* PRE_ROUTING */
{ { { { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, "", "", { 0 }, { 0 }, 0, 0, 0 },
0,
sizeof(struct ip6t_entry),
sizeof(struct ip6t_standard),
0, { 0, 0 }, { } },
{ { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
-NF_ACCEPT - 1 } },
/* LOCAL_IN */
{ { { { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, "", "", { 0 }, { 0 }, 0, 0, 0 },
0,
sizeof(struct ip6t_entry),
sizeof(struct ip6t_standard),
0, { 0, 0 }, { } },
{ { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
-NF_ACCEPT - 1 } },
/* FORWARD */
{ { { { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, "", "", { 0 }, { 0 }, 0, 0, 0 },
0,
sizeof(struct ip6t_entry),
sizeof(struct ip6t_standard),
0, { 0, 0 }, { } },
{ { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
-NF_ACCEPT - 1 } },
/* LOCAL_OUT */
{ { { { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, "", "", { 0 }, { 0 }, 0, 0, 0 },
0,
sizeof(struct ip6t_entry),
sizeof(struct ip6t_standard),
0, { 0, 0 }, { } },
{ { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
-NF_ACCEPT - 1 } },
/* POST_ROUTING */
{ { { { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, "", "", { 0 }, { 0 }, 0, 0, 0 },
0,
sizeof(struct ip6t_entry),
sizeof(struct ip6t_standard),
0, { 0, 0 }, { } },
{ { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
-NF_ACCEPT - 1 } }
}, },
/* ERROR */ },
{ { { { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, "", "", { 0 }, { 0 }, 0, 0, 0 }, .entries = {
0, IP6T_STANDARD_INIT(NF_ACCEPT), /* PRE_ROUTING */
sizeof(struct ip6t_entry), IP6T_STANDARD_INIT(NF_ACCEPT), /* LOCAL_IN */
sizeof(struct ip6t_error), IP6T_STANDARD_INIT(NF_ACCEPT), /* FORWARD */
0, { 0, 0 }, { } }, IP6T_STANDARD_INIT(NF_ACCEPT), /* LOCAL_OUT */
{ { { { IP6T_ALIGN(sizeof(struct ip6t_error_target)), IP6T_ERROR_TARGET } }, IP6T_STANDARD_INIT(NF_ACCEPT), /* POST_ROUTING */
{ } }, },
"ERROR" .term = IP6T_ERROR_INIT, /* ERROR */
}
}
}; };
static struct xt_table packet_mangler = { static struct xt_table packet_mangler = {
......
...@@ -35,56 +35,10 @@ static struct ...@@ -35,56 +35,10 @@ static struct
}, },
}, },
.entries = { .entries = {
/* PRE_ROUTING */ IP6T_STANDARD_INIT(NF_ACCEPT), /* PRE_ROUTING */
{ IP6T_STANDARD_INIT(NF_ACCEPT), /* LOCAL_OUT */
.entry = {
.target_offset = sizeof(struct ip6t_entry),
.next_offset = sizeof(struct ip6t_standard),
},
.target = {
.target = {
.u = {
.target_size = IP6T_ALIGN(sizeof(struct ip6t_standard_target)),
},
},
.verdict = -NF_ACCEPT - 1,
},
},
/* LOCAL_OUT */
{
.entry = {
.target_offset = sizeof(struct ip6t_entry),
.next_offset = sizeof(struct ip6t_standard),
},
.target = {
.target = {
.u = {
.target_size = IP6T_ALIGN(sizeof(struct ip6t_standard_target)),
},
},
.verdict = -NF_ACCEPT - 1,
},
},
},
/* ERROR */
.term = {
.entry = {
.target_offset = sizeof(struct ip6t_entry),
.next_offset = sizeof(struct ip6t_error),
},
.target = {
.target = {
.u = {
.user = {
.target_size = IP6T_ALIGN(sizeof(struct ip6t_error_target)),
.name = IP6T_ERROR_TARGET,
},
},
},
.errorname = "ERROR",
}, },
} .term = IP6T_ERROR_INIT, /* ERROR */
}; };
static struct xt_table packet_raw = { static struct xt_table packet_raw = {
......
...@@ -52,9 +52,28 @@ ...@@ -52,9 +52,28 @@
DEFINE_SNMP_STAT(struct udp_mib, udp_stats_in6) __read_mostly; DEFINE_SNMP_STAT(struct udp_mib, udp_stats_in6) __read_mostly;
static int ipv6_rcv_saddr_any(const struct sock *sk)
{
struct ipv6_pinfo *np = inet6_sk(sk);
return ipv6_addr_any(&np->rcv_saddr);
}
static unsigned int ipv6_hash_port_and_rcv_saddr(__u16 port,
const struct sock *sk)
{
return port;
}
const struct udp_get_port_ops udp_ipv6_ops = {
.saddr_cmp = ipv6_rcv_saddr_equal,
.saddr_any = ipv6_rcv_saddr_any,
.hash_port_and_rcv_saddr = ipv6_hash_port_and_rcv_saddr,
};
static inline int udp_v6_get_port(struct sock *sk, unsigned short snum) static inline int udp_v6_get_port(struct sock *sk, unsigned short snum)
{ {
return udp_get_port(sk, snum, ipv6_rcv_saddr_equal); return udp_get_port(sk, snum, &udp_ipv6_ops);
} }
static struct sock *__udp6_lib_lookup(struct in6_addr *saddr, __be16 sport, static struct sock *__udp6_lib_lookup(struct in6_addr *saddr, __be16 sport,
......
...@@ -6,6 +6,8 @@ ...@@ -6,6 +6,8 @@
#include <net/addrconf.h> #include <net/addrconf.h>
#include <net/inet_common.h> #include <net/inet_common.h>
extern const struct udp_get_port_ops udp_ipv6_ops;
extern int __udp6_lib_rcv(struct sk_buff **, struct hlist_head [], int ); extern int __udp6_lib_rcv(struct sk_buff **, struct hlist_head [], int );
extern void __udp6_lib_err(struct sk_buff *, struct inet6_skb_parm *, extern void __udp6_lib_err(struct sk_buff *, struct inet6_skb_parm *,
int , int , int , __be32 , struct hlist_head []); int , int , int , __be32 , struct hlist_head []);
......
...@@ -37,7 +37,7 @@ static struct inet6_protocol udplitev6_protocol = { ...@@ -37,7 +37,7 @@ static struct inet6_protocol udplitev6_protocol = {
static int udplite_v6_get_port(struct sock *sk, unsigned short snum) static int udplite_v6_get_port(struct sock *sk, unsigned short snum)
{ {
return udplite_get_port(sk, snum, ipv6_rcv_saddr_equal); return udplite_get_port(sk, snum, &udp_ipv6_ops);
} }
struct proto udplitev6_prot = { struct proto udplitev6_prot = {
......
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
* scan result table filtering (by capability (privacy, IBSS/BSS, WPA/RSN IE, * scan result table filtering (by capability (privacy, IBSS/BSS, WPA/RSN IE,
* SSID) * SSID)
*/ */
#include <linux/delay.h>
#include <linux/if_ether.h> #include <linux/if_ether.h>
#include <linux/skbuff.h> #include <linux/skbuff.h>
#include <linux/netdevice.h> #include <linux/netdevice.h>
...@@ -27,7 +28,6 @@ ...@@ -27,7 +28,6 @@
#include <linux/rtnetlink.h> #include <linux/rtnetlink.h>
#include <net/iw_handler.h> #include <net/iw_handler.h>
#include <asm/types.h> #include <asm/types.h>
#include <asm/delay.h>
#include <net/mac80211.h> #include <net/mac80211.h>
#include "ieee80211_i.h" #include "ieee80211_i.h"
......
...@@ -299,7 +299,6 @@ destroy_conntrack(struct nf_conntrack *nfct) ...@@ -299,7 +299,6 @@ destroy_conntrack(struct nf_conntrack *nfct)
{ {
struct nf_conn *ct = (struct nf_conn *)nfct; struct nf_conn *ct = (struct nf_conn *)nfct;
struct nf_conn_help *help = nfct_help(ct); struct nf_conn_help *help = nfct_help(ct);
struct nf_conntrack_l3proto *l3proto;
struct nf_conntrack_l4proto *l4proto; struct nf_conntrack_l4proto *l4proto;
typeof(nf_conntrack_destroyed) destroyed; typeof(nf_conntrack_destroyed) destroyed;
...@@ -317,10 +316,6 @@ destroy_conntrack(struct nf_conntrack *nfct) ...@@ -317,10 +316,6 @@ destroy_conntrack(struct nf_conntrack *nfct)
* destroy_conntrack() MUST NOT be called with a write lock * destroy_conntrack() MUST NOT be called with a write lock
* to nf_conntrack_lock!!! -HW */ * to nf_conntrack_lock!!! -HW */
rcu_read_lock(); rcu_read_lock();
l3proto = __nf_ct_l3proto_find(ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.l3num);
if (l3proto && l3proto->destroy)
l3proto->destroy(ct);
l4proto = __nf_ct_l4proto_find(ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.l3num, l4proto = __nf_ct_l4proto_find(ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.l3num,
ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.protonum); ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.protonum);
if (l4proto && l4proto->destroy) if (l4proto && l4proto->destroy)
...@@ -893,8 +888,13 @@ void nf_conntrack_alter_reply(struct nf_conn *ct, ...@@ -893,8 +888,13 @@ void nf_conntrack_alter_reply(struct nf_conn *ct,
NF_CT_DUMP_TUPLE(newreply); NF_CT_DUMP_TUPLE(newreply);
ct->tuplehash[IP_CT_DIR_REPLY].tuple = *newreply; ct->tuplehash[IP_CT_DIR_REPLY].tuple = *newreply;
if (!ct->master && help && help->expecting == 0) if (!ct->master && help && help->expecting == 0) {
help->helper = __nf_ct_helper_find(newreply); struct nf_conntrack_helper *helper;
helper = __nf_ct_helper_find(newreply);
if (helper)
memset(&help->help, 0, sizeof(help->help));
help->helper = helper;
}
write_unlock_bh(&nf_conntrack_lock); write_unlock_bh(&nf_conntrack_lock);
} }
EXPORT_SYMBOL_GPL(nf_conntrack_alter_reply); EXPORT_SYMBOL_GPL(nf_conntrack_alter_reply);
......
...@@ -830,11 +830,6 @@ ctnetlink_change_helper(struct nf_conn *ct, struct nfattr *cda[]) ...@@ -830,11 +830,6 @@ ctnetlink_change_helper(struct nf_conn *ct, struct nfattr *cda[])
char *helpname; char *helpname;
int err; int err;
if (!help) {
/* FIXME: we need to reallocate and rehash */
return -EBUSY;
}
/* don't change helper of sibling connections */ /* don't change helper of sibling connections */
if (ct->master) if (ct->master)
return -EINVAL; return -EINVAL;
...@@ -843,25 +838,34 @@ ctnetlink_change_helper(struct nf_conn *ct, struct nfattr *cda[]) ...@@ -843,25 +838,34 @@ ctnetlink_change_helper(struct nf_conn *ct, struct nfattr *cda[])
if (err < 0) if (err < 0)
return err; return err;
if (!strcmp(helpname, "")) {
if (help && help->helper) {
/* we had a helper before ... */
nf_ct_remove_expectations(ct);
help->helper = NULL;
}
return 0;
}
if (!help) {
/* FIXME: we need to reallocate and rehash */
return -EBUSY;
}
helper = __nf_conntrack_helper_find_byname(helpname); helper = __nf_conntrack_helper_find_byname(helpname);
if (!helper) { if (helper == NULL)
if (!strcmp(helpname, ""))
helper = NULL;
else
return -EINVAL; return -EINVAL;
}
if (help->helper) { if (help->helper == helper)
if (!helper) { return 0;
if (help->helper)
/* we had a helper before ... */ /* we had a helper before ... */
nf_ct_remove_expectations(ct); nf_ct_remove_expectations(ct);
help->helper = NULL;
} else {
/* need to zero data of old helper */ /* need to zero data of old helper */
memset(&help->help, 0, sizeof(help->help)); memset(&help->help, 0, sizeof(help->help));
}
}
help->helper = helper; help->helper = helper;
return 0; return 0;
......
...@@ -134,12 +134,66 @@ static void destroy(const struct xt_match *match, void *matchinfo) ...@@ -134,12 +134,66 @@ static void destroy(const struct xt_match *match, void *matchinfo)
nf_ct_l3proto_module_put(match->family); nf_ct_l3proto_module_put(match->family);
} }
#ifdef CONFIG_COMPAT
struct compat_xt_conntrack_info
{
compat_uint_t statemask;
compat_uint_t statusmask;
struct ip_conntrack_old_tuple tuple[IP_CT_DIR_MAX];
struct in_addr sipmsk[IP_CT_DIR_MAX];
struct in_addr dipmsk[IP_CT_DIR_MAX];
compat_ulong_t expires_min;
compat_ulong_t expires_max;
u_int8_t flags;
u_int8_t invflags;
};
static void compat_from_user(void *dst, void *src)
{
struct compat_xt_conntrack_info *cm = src;
struct xt_conntrack_info m = {
.statemask = cm->statemask,
.statusmask = cm->statusmask,
.expires_min = cm->expires_min,
.expires_max = cm->expires_max,
.flags = cm->flags,
.invflags = cm->invflags,
};
memcpy(m.tuple, cm->tuple, sizeof(m.tuple));
memcpy(m.sipmsk, cm->sipmsk, sizeof(m.sipmsk));
memcpy(m.dipmsk, cm->dipmsk, sizeof(m.dipmsk));
memcpy(dst, &m, sizeof(m));
}
static int compat_to_user(void __user *dst, void *src)
{
struct xt_conntrack_info *m = src;
struct compat_xt_conntrack_info cm = {
.statemask = m->statemask,
.statusmask = m->statusmask,
.expires_min = m->expires_min,
.expires_max = m->expires_max,
.flags = m->flags,
.invflags = m->invflags,
};
memcpy(cm.tuple, m->tuple, sizeof(cm.tuple));
memcpy(cm.sipmsk, m->sipmsk, sizeof(cm.sipmsk));
memcpy(cm.dipmsk, m->dipmsk, sizeof(cm.dipmsk));
return copy_to_user(dst, &cm, sizeof(cm)) ? -EFAULT : 0;
}
#endif
static struct xt_match conntrack_match = { static struct xt_match conntrack_match = {
.name = "conntrack", .name = "conntrack",
.match = match, .match = match,
.checkentry = checkentry, .checkentry = checkentry,
.destroy = destroy, .destroy = destroy,
.matchsize = sizeof(struct xt_conntrack_info), .matchsize = sizeof(struct xt_conntrack_info),
#ifdef CONFIG_COMPAT
.compatsize = sizeof(struct compat_xt_conntrack_info),
.compat_from_user = compat_from_user,
.compat_to_user = compat_to_user,
#endif
.family = AF_INET, .family = AF_INET,
.me = THIS_MODULE, .me = THIS_MODULE,
}; };
......
...@@ -71,12 +71,9 @@ void qdisc_unlock_tree(struct net_device *dev) ...@@ -71,12 +71,9 @@ void qdisc_unlock_tree(struct net_device *dev)
/* Kick device. /* Kick device.
Note, that this procedure can be called by a watchdog timer, so that
we do not check dev->tbusy flag here.
Returns: 0 - queue is empty. Returns: 0 - queue is empty or throttled.
>0 - queue is not empty, but throttled. >0 - queue is not empty.
<0 - queue is not empty. Device is throttled, if dev->tbusy != 0.
NOTE: Called under dev->queue_lock with locally disabled BH. NOTE: Called under dev->queue_lock with locally disabled BH.
*/ */
...@@ -115,7 +112,7 @@ static inline int qdisc_restart(struct net_device *dev) ...@@ -115,7 +112,7 @@ static inline int qdisc_restart(struct net_device *dev)
kfree_skb(skb); kfree_skb(skb);
if (net_ratelimit()) if (net_ratelimit())
printk(KERN_DEBUG "Dead loop on netdevice %s, fix it urgently!\n", dev->name); printk(KERN_DEBUG "Dead loop on netdevice %s, fix it urgently!\n", dev->name);
return -1; goto out;
} }
__get_cpu_var(netdev_rx_stat).cpu_collision++; __get_cpu_var(netdev_rx_stat).cpu_collision++;
goto requeue; goto requeue;
...@@ -135,10 +132,12 @@ static inline int qdisc_restart(struct net_device *dev) ...@@ -135,10 +132,12 @@ static inline int qdisc_restart(struct net_device *dev)
netif_tx_unlock(dev); netif_tx_unlock(dev);
} }
spin_lock(&dev->queue_lock); spin_lock(&dev->queue_lock);
return -1; q = dev->qdisc;
goto out;
} }
if (ret == NETDEV_TX_LOCKED && nolock) { if (ret == NETDEV_TX_LOCKED && nolock) {
spin_lock(&dev->queue_lock); spin_lock(&dev->queue_lock);
q = dev->qdisc;
goto collision; goto collision;
} }
} }
...@@ -163,26 +162,28 @@ static inline int qdisc_restart(struct net_device *dev) ...@@ -163,26 +162,28 @@ static inline int qdisc_restart(struct net_device *dev)
*/ */
requeue: requeue:
if (skb->next) if (unlikely(q == &noop_qdisc))
kfree_skb(skb);
else if (skb->next)
dev->gso_skb = skb; dev->gso_skb = skb;
else else
q->ops->requeue(skb, q); q->ops->requeue(skb, q);
netif_schedule(dev); netif_schedule(dev);
return 1; return 0;
} }
out:
BUG_ON((int) q->q.qlen < 0); BUG_ON((int) q->q.qlen < 0);
return q->q.qlen; return q->q.qlen;
} }
void __qdisc_run(struct net_device *dev) void __qdisc_run(struct net_device *dev)
{ {
if (unlikely(dev->qdisc == &noop_qdisc)) do {
goto out; if (!qdisc_restart(dev))
break;
while (qdisc_restart(dev) < 0 && !netif_queue_stopped(dev)) } while (!netif_queue_stopped(dev));
/* NOTHING */;
out:
clear_bit(__LINK_STATE_QDISC_RUNNING, &dev->state); clear_bit(__LINK_STATE_QDISC_RUNNING, &dev->state);
} }
...@@ -544,6 +545,7 @@ void dev_activate(struct net_device *dev) ...@@ -544,6 +545,7 @@ void dev_activate(struct net_device *dev)
void dev_deactivate(struct net_device *dev) void dev_deactivate(struct net_device *dev)
{ {
struct Qdisc *qdisc; struct Qdisc *qdisc;
struct sk_buff *skb;
spin_lock_bh(&dev->queue_lock); spin_lock_bh(&dev->queue_lock);
qdisc = dev->qdisc; qdisc = dev->qdisc;
...@@ -551,8 +553,12 @@ void dev_deactivate(struct net_device *dev) ...@@ -551,8 +553,12 @@ void dev_deactivate(struct net_device *dev)
qdisc_reset(qdisc); qdisc_reset(qdisc);
skb = dev->gso_skb;
dev->gso_skb = NULL;
spin_unlock_bh(&dev->queue_lock); spin_unlock_bh(&dev->queue_lock);
kfree_skb(skb);
dev_watchdog_down(dev); dev_watchdog_down(dev);
/* Wait for outstanding dev_queue_xmit calls. */ /* Wait for outstanding dev_queue_xmit calls. */
...@@ -561,11 +567,6 @@ void dev_deactivate(struct net_device *dev) ...@@ -561,11 +567,6 @@ void dev_deactivate(struct net_device *dev)
/* Wait for outstanding qdisc_run calls. */ /* Wait for outstanding qdisc_run calls. */
while (test_bit(__LINK_STATE_QDISC_RUNNING, &dev->state)) while (test_bit(__LINK_STATE_QDISC_RUNNING, &dev->state))
yield(); yield();
if (dev->gso_skb) {
kfree_skb(dev->gso_skb);
dev->gso_skb = NULL;
}
} }
void dev_init_scheduler(struct net_device *dev) void dev_init_scheduler(struct net_device *dev)
......
...@@ -94,14 +94,13 @@ teql_enqueue(struct sk_buff *skb, struct Qdisc* sch) ...@@ -94,14 +94,13 @@ teql_enqueue(struct sk_buff *skb, struct Qdisc* sch)
struct net_device *dev = sch->dev; struct net_device *dev = sch->dev;
struct teql_sched_data *q = qdisc_priv(sch); struct teql_sched_data *q = qdisc_priv(sch);
if (q->q.qlen < dev->tx_queue_len) {
__skb_queue_tail(&q->q, skb); __skb_queue_tail(&q->q, skb);
if (q->q.qlen <= dev->tx_queue_len) {
sch->bstats.bytes += skb->len; sch->bstats.bytes += skb->len;
sch->bstats.packets++; sch->bstats.packets++;
return 0; return 0;
} }
__skb_unlink(skb, &q->q);
kfree_skb(skb); kfree_skb(skb);
sch->qstats.drops++; sch->qstats.drops++;
return NET_XMIT_DROP; return NET_XMIT_DROP;
......
...@@ -4164,6 +4164,7 @@ static int sctp_getsockopt_local_addrs_old(struct sock *sk, int len, ...@@ -4164,6 +4164,7 @@ static int sctp_getsockopt_local_addrs_old(struct sock *sk, int len,
rwlock_t *addr_lock; rwlock_t *addr_lock;
int err = 0; int err = 0;
void *addrs; void *addrs;
void *buf;
int bytes_copied = 0; int bytes_copied = 0;
if (len != sizeof(struct sctp_getaddrs_old)) if (len != sizeof(struct sctp_getaddrs_old))
...@@ -4217,13 +4218,14 @@ static int sctp_getsockopt_local_addrs_old(struct sock *sk, int len, ...@@ -4217,13 +4218,14 @@ static int sctp_getsockopt_local_addrs_old(struct sock *sk, int len,
} }
} }
buf = addrs;
list_for_each(pos, &bp->address_list) { list_for_each(pos, &bp->address_list) {
addr = list_entry(pos, struct sctp_sockaddr_entry, list); addr = list_entry(pos, struct sctp_sockaddr_entry, list);
memcpy(&temp, &addr->a, sizeof(temp)); memcpy(&temp, &addr->a, sizeof(temp));
sctp_get_pf_specific(sk->sk_family)->addr_v4map(sp, &temp); sctp_get_pf_specific(sk->sk_family)->addr_v4map(sp, &temp);
addrlen = sctp_get_af_specific(temp.sa.sa_family)->sockaddr_len; addrlen = sctp_get_af_specific(temp.sa.sa_family)->sockaddr_len;
memcpy(addrs, &temp, addrlen); memcpy(buf, &temp, addrlen);
to += addrlen; buf += addrlen;
bytes_copied += addrlen; bytes_copied += addrlen;
cnt ++; cnt ++;
if (cnt >= getaddrs.addr_num) break; if (cnt >= getaddrs.addr_num) break;
...@@ -4266,6 +4268,7 @@ static int sctp_getsockopt_local_addrs(struct sock *sk, int len, ...@@ -4266,6 +4268,7 @@ static int sctp_getsockopt_local_addrs(struct sock *sk, int len,
size_t space_left; size_t space_left;
int bytes_copied = 0; int bytes_copied = 0;
void *addrs; void *addrs;
void *buf;
if (len <= sizeof(struct sctp_getaddrs)) if (len <= sizeof(struct sctp_getaddrs))
return -EINVAL; return -EINVAL;
...@@ -4316,6 +4319,7 @@ static int sctp_getsockopt_local_addrs(struct sock *sk, int len, ...@@ -4316,6 +4319,7 @@ static int sctp_getsockopt_local_addrs(struct sock *sk, int len,
} }
} }
buf = addrs;
list_for_each(pos, &bp->address_list) { list_for_each(pos, &bp->address_list) {
addr = list_entry(pos, struct sctp_sockaddr_entry, list); addr = list_entry(pos, struct sctp_sockaddr_entry, list);
memcpy(&temp, &addr->a, sizeof(temp)); memcpy(&temp, &addr->a, sizeof(temp));
...@@ -4325,8 +4329,8 @@ static int sctp_getsockopt_local_addrs(struct sock *sk, int len, ...@@ -4325,8 +4329,8 @@ static int sctp_getsockopt_local_addrs(struct sock *sk, int len,
err = -ENOMEM; /*fixme: right error?*/ err = -ENOMEM; /*fixme: right error?*/
goto error; goto error;
} }
memcpy(addrs, &temp, addrlen); memcpy(buf, &temp, addrlen);
to += addrlen; buf += addrlen;
bytes_copied += addrlen; bytes_copied += addrlen;
cnt ++; cnt ++;
space_left -= addrlen; space_left -= addrlen;
...@@ -5227,7 +5231,12 @@ int sctp_inet_listen(struct socket *sock, int backlog) ...@@ -5227,7 +5231,12 @@ int sctp_inet_listen(struct socket *sock, int backlog)
/* Allocate HMAC for generating cookie. */ /* Allocate HMAC for generating cookie. */
if (sctp_hmac_alg) { if (sctp_hmac_alg) {
tfm = crypto_alloc_hash(sctp_hmac_alg, 0, CRYPTO_ALG_ASYNC); tfm = crypto_alloc_hash(sctp_hmac_alg, 0, CRYPTO_ALG_ASYNC);
if (!tfm) { if (IS_ERR(tfm)) {
if (net_ratelimit()) {
printk(KERN_INFO
"SCTP: failed to load transform for %s: %ld\n",
sctp_hmac_alg, PTR_ERR(tfm));
}
err = -ENOSYS; err = -ENOSYS;
goto out; goto out;
} }
......
...@@ -141,11 +141,6 @@ struct sctp_ulpevent *sctp_ulpevent_make_assoc_change( ...@@ -141,11 +141,6 @@ struct sctp_ulpevent *sctp_ulpevent_make_assoc_change(
* an ABORT, so we need to include it in the sac_info. * an ABORT, so we need to include it in the sac_info.
*/ */
if (chunk) { if (chunk) {
/* sctp_inqu_pop() has allready pulled off the chunk
* header. We need to put it back temporarily
*/
skb_push(chunk->skb, sizeof(sctp_chunkhdr_t));
/* Copy the chunk data to a new skb and reserve enough /* Copy the chunk data to a new skb and reserve enough
* head room to use as notification. * head room to use as notification.
*/ */
...@@ -155,9 +150,6 @@ struct sctp_ulpevent *sctp_ulpevent_make_assoc_change( ...@@ -155,9 +150,6 @@ struct sctp_ulpevent *sctp_ulpevent_make_assoc_change(
if (!skb) if (!skb)
goto fail; goto fail;
/* put back the chunk header now that we have a copy */
skb_pull(chunk->skb, sizeof(sctp_chunkhdr_t));
/* Embed the event fields inside the cloned skb. */ /* Embed the event fields inside the cloned skb. */
event = sctp_skb2event(skb); event = sctp_skb2event(skb);
sctp_ulpevent_init(event, MSG_NOTIFICATION, skb->truesize); sctp_ulpevent_init(event, MSG_NOTIFICATION, skb->truesize);
...@@ -168,7 +160,8 @@ struct sctp_ulpevent *sctp_ulpevent_make_assoc_change( ...@@ -168,7 +160,8 @@ struct sctp_ulpevent *sctp_ulpevent_make_assoc_change(
/* Trim the buffer to the right length. */ /* Trim the buffer to the right length. */
skb_trim(skb, sizeof(struct sctp_assoc_change) + skb_trim(skb, sizeof(struct sctp_assoc_change) +
ntohs(chunk->chunk_hdr->length)); ntohs(chunk->chunk_hdr->length) -
sizeof(sctp_chunkhdr_t));
} else { } else {
event = sctp_ulpevent_new(sizeof(struct sctp_assoc_change), event = sctp_ulpevent_new(sizeof(struct sctp_assoc_change),
MSG_NOTIFICATION, gfp); MSG_NOTIFICATION, gfp);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment