Commit 46ce6729 authored by Linus Torvalds's avatar Linus Torvalds

Merge bk://kernel.bkbits.net/davem/net-2.6

into ppc970.osdl.org:/home/torvalds/v2.6/linux
parents 70ca2c43 96781d94
...@@ -60,8 +60,8 @@ ...@@ -60,8 +60,8 @@
#define DRV_MODULE_NAME "tg3" #define DRV_MODULE_NAME "tg3"
#define PFX DRV_MODULE_NAME ": " #define PFX DRV_MODULE_NAME ": "
#define DRV_MODULE_VERSION "3.13" #define DRV_MODULE_VERSION "3.14"
#define DRV_MODULE_RELDATE "November 1, 2004" #define DRV_MODULE_RELDATE "November 15, 2004"
#define TG3_DEF_MAC_MODE 0 #define TG3_DEF_MAC_MODE 0
#define TG3_DEF_RX_MODE 0 #define TG3_DEF_RX_MODE 0
...@@ -206,6 +206,14 @@ static struct pci_device_id tg3_pci_tbl[] = { ...@@ -206,6 +206,14 @@ static struct pci_device_id tg3_pci_tbl[] = {
PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
{ PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5751F, { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5751F,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
{ PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5753,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
{ PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5753M,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
{ PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5753F,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
{ PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5781,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
{ PCI_VENDOR_ID_SYSKONNECT, PCI_DEVICE_ID_SYSKONNECT_9DXX, { PCI_VENDOR_ID_SYSKONNECT, PCI_DEVICE_ID_SYSKONNECT_9DXX,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
{ PCI_VENDOR_ID_SYSKONNECT, PCI_DEVICE_ID_SYSKONNECT_9MXX, { PCI_VENDOR_ID_SYSKONNECT, PCI_DEVICE_ID_SYSKONNECT_9MXX,
...@@ -881,34 +889,54 @@ static void tg3_frob_aux_power(struct tg3 *tp) ...@@ -881,34 +889,54 @@ static void tg3_frob_aux_power(struct tg3 *tp)
GRC_LCLCTRL_GPIO_OUTPUT1)); GRC_LCLCTRL_GPIO_OUTPUT1));
udelay(100); udelay(100);
} else { } else {
int no_gpio2;
u32 grc_local_ctrl;
if (tp_peer != tp && if (tp_peer != tp &&
(tp_peer->tg3_flags & TG3_FLAG_INIT_COMPLETE) != 0) (tp_peer->tg3_flags & TG3_FLAG_INIT_COMPLETE) != 0)
return; return;
/* On 5753 and variants, GPIO2 cannot be used. */
no_gpio2 = (tp->nic_sram_data_cfg &
NIC_SRAM_DATA_CFG_NO_GPIO2) != 0;
grc_local_ctrl = GRC_LCLCTRL_GPIO_OE0 |
GRC_LCLCTRL_GPIO_OE1 |
GRC_LCLCTRL_GPIO_OE2 |
GRC_LCLCTRL_GPIO_OUTPUT1 |
GRC_LCLCTRL_GPIO_OUTPUT2;
if (no_gpio2) {
grc_local_ctrl &= ~(GRC_LCLCTRL_GPIO_OE2 |
GRC_LCLCTRL_GPIO_OUTPUT2);
}
tw32_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl | tw32_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl |
(GRC_LCLCTRL_GPIO_OE0 | grc_local_ctrl);
GRC_LCLCTRL_GPIO_OE1 |
GRC_LCLCTRL_GPIO_OE2 |
GRC_LCLCTRL_GPIO_OUTPUT1 |
GRC_LCLCTRL_GPIO_OUTPUT2));
udelay(100); udelay(100);
grc_local_ctrl = GRC_LCLCTRL_GPIO_OE0 |
GRC_LCLCTRL_GPIO_OE1 |
GRC_LCLCTRL_GPIO_OE2 |
GRC_LCLCTRL_GPIO_OUTPUT0 |
GRC_LCLCTRL_GPIO_OUTPUT1 |
GRC_LCLCTRL_GPIO_OUTPUT2;
if (no_gpio2) {
grc_local_ctrl &= ~(GRC_LCLCTRL_GPIO_OE2 |
GRC_LCLCTRL_GPIO_OUTPUT2);
}
tw32_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl | tw32_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl |
(GRC_LCLCTRL_GPIO_OE0 | grc_local_ctrl);
GRC_LCLCTRL_GPIO_OE1 |
GRC_LCLCTRL_GPIO_OE2 |
GRC_LCLCTRL_GPIO_OUTPUT0 |
GRC_LCLCTRL_GPIO_OUTPUT1 |
GRC_LCLCTRL_GPIO_OUTPUT2));
udelay(100); udelay(100);
tw32_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl | grc_local_ctrl = GRC_LCLCTRL_GPIO_OE0 |
(GRC_LCLCTRL_GPIO_OE0 | GRC_LCLCTRL_GPIO_OE1 |
GRC_LCLCTRL_GPIO_OE1 | GRC_LCLCTRL_GPIO_OE2 |
GRC_LCLCTRL_GPIO_OE2 | GRC_LCLCTRL_GPIO_OUTPUT0 |
GRC_LCLCTRL_GPIO_OUTPUT0 | GRC_LCLCTRL_GPIO_OUTPUT1;
GRC_LCLCTRL_GPIO_OUTPUT1)); if (!no_gpio2) {
udelay(100); tw32_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl |
grc_local_ctrl);
udelay(100);
}
} }
} else { } else {
if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5700 && if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5700 &&
...@@ -7619,7 +7647,8 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) ...@@ -7619,7 +7647,8 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
tp->pdev->device == PCI_DEVICE_ID_TIGON3_5901_2 || tp->pdev->device == PCI_DEVICE_ID_TIGON3_5901_2 ||
tp->pdev->device == PCI_DEVICE_ID_TIGON3_5705F)) || tp->pdev->device == PCI_DEVICE_ID_TIGON3_5705F)) ||
(tp->pdev->vendor == PCI_VENDOR_ID_BROADCOM && (tp->pdev->vendor == PCI_VENDOR_ID_BROADCOM &&
tp->pdev->device == PCI_DEVICE_ID_TIGON3_5751F)) (tp->pdev->device == PCI_DEVICE_ID_TIGON3_5751F ||
tp->pdev->device == PCI_DEVICE_ID_TIGON3_5753F)))
tp->tg3_flags |= TG3_FLAG_10_100_ONLY; tp->tg3_flags |= TG3_FLAG_10_100_ONLY;
err = tg3_phy_probe(tp); err = tg3_phy_probe(tp);
...@@ -7926,7 +7955,8 @@ static int __devinit tg3_test_dma(struct tg3 *tp) ...@@ -7926,7 +7955,8 @@ static int __devinit tg3_test_dma(struct tg3 *tp)
#endif #endif
if (tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS) { if (tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS) {
tp->dma_rwctrl |= 0x001f0000; /* DMA read watermark not used on PCIE */
tp->dma_rwctrl |= 0x00180000;
} else if (!(tp->tg3_flags & TG3_FLAG_PCIX_MODE)) { } else if (!(tp->tg3_flags & TG3_FLAG_PCIX_MODE)) {
if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705 || if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705 ||
GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750) GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750)
......
...@@ -1436,6 +1436,7 @@ ...@@ -1436,6 +1436,7 @@
#define NIC_SRAM_DATA_CFG_EEPROM_WP 0x00000100 #define NIC_SRAM_DATA_CFG_EEPROM_WP 0x00000100
#define NIC_SRAM_DATA_CFG_MINI_PCI 0x00001000 #define NIC_SRAM_DATA_CFG_MINI_PCI 0x00001000
#define NIC_SRAM_DATA_CFG_FIBER_WOL 0x00004000 #define NIC_SRAM_DATA_CFG_FIBER_WOL 0x00004000
#define NIC_SRAM_DATA_CFG_NO_GPIO2 0x00100000
#define NIC_SRAM_DATA_PHY_ID 0x00000b74 #define NIC_SRAM_DATA_PHY_ID 0x00000b74
#define NIC_SRAM_DATA_PHY_ID1_MASK 0xffff0000 #define NIC_SRAM_DATA_PHY_ID1_MASK 0xffff0000
......
...@@ -925,6 +925,9 @@ extern unsigned long netdev_fc_xoff; ...@@ -925,6 +925,9 @@ extern unsigned long netdev_fc_xoff;
extern atomic_t netdev_dropping; extern atomic_t netdev_dropping;
extern int netdev_set_master(struct net_device *dev, struct net_device *master); extern int netdev_set_master(struct net_device *dev, struct net_device *master);
extern int skb_checksum_help(struct sk_buff *skb, int inward); extern int skb_checksum_help(struct sk_buff *skb, int inward);
/* rx skb timestamps */
extern void net_enable_timestamp(void);
extern void net_disable_timestamp(void);
#ifdef CONFIG_SYSCTL #ifdef CONFIG_SYSCTL
extern char *net_sysctl_strdup(const char *s); extern char *net_sysctl_strdup(const char *s);
......
...@@ -173,6 +173,7 @@ extern void nf_reinject(struct sk_buff *skb, ...@@ -173,6 +173,7 @@ extern void nf_reinject(struct sk_buff *skb,
unsigned int verdict); unsigned int verdict);
extern void (*ip_ct_attach)(struct sk_buff *, struct sk_buff *); extern void (*ip_ct_attach)(struct sk_buff *, struct sk_buff *);
extern void nf_ct_attach(struct sk_buff *, struct sk_buff *);
#ifdef CONFIG_NETFILTER_DEBUG #ifdef CONFIG_NETFILTER_DEBUG
extern void nf_dump_skb(int pf, struct sk_buff *skb); extern void nf_dump_skb(int pf, struct sk_buff *skb);
...@@ -183,6 +184,7 @@ extern void nf_invalidate_cache(int pf); ...@@ -183,6 +184,7 @@ extern void nf_invalidate_cache(int pf);
#else /* !CONFIG_NETFILTER */ #else /* !CONFIG_NETFILTER */
#define NF_HOOK(pf, hook, skb, indev, outdev, okfn) (okfn)(skb) #define NF_HOOK(pf, hook, skb, indev, outdev, okfn) (okfn)(skb)
static inline void nf_ct_attach(struct sk_buff *new, struct sk_buff *skb) {}
#endif /*CONFIG_NETFILTER*/ #endif /*CONFIG_NETFILTER*/
#endif /*__KERNEL__*/ #endif /*__KERNEL__*/
......
...@@ -18,7 +18,7 @@ struct ip_nat_protocol ...@@ -18,7 +18,7 @@ struct ip_nat_protocol
/* Do a packet translation according to the ip_nat_proto_manip /* Do a packet translation according to the ip_nat_proto_manip
* and manip type. Return true if succeeded. */ * and manip type. Return true if succeeded. */
int (*manip_pkt)(struct sk_buff **pskb, int (*manip_pkt)(struct sk_buff **pskb,
unsigned int hdroff, unsigned int iphdroff,
const struct ip_conntrack_manip *manip, const struct ip_conntrack_manip *manip,
enum ip_nat_manip_type maniptype); enum ip_nat_manip_type maniptype);
......
...@@ -1918,11 +1918,15 @@ ...@@ -1918,11 +1918,15 @@
#define PCI_DEVICE_ID_TIGON3_5704S 0x16a8 #define PCI_DEVICE_ID_TIGON3_5704S 0x16a8
#define PCI_DEVICE_ID_TIGON3_5702A3 0x16c6 #define PCI_DEVICE_ID_TIGON3_5702A3 0x16c6
#define PCI_DEVICE_ID_TIGON3_5703A3 0x16c7 #define PCI_DEVICE_ID_TIGON3_5703A3 0x16c7
#define PCI_DEVICE_ID_TIGON3_5781 0x16dd
#define PCI_DEVICE_ID_TIGON3_5753 0x16f7
#define PCI_DEVICE_ID_TIGON3_5753M 0x16fd
#define PCI_DEVICE_ID_TIGON3_5753F 0x16fe
#define PCI_DEVICE_ID_TIGON3_5901 0x170d #define PCI_DEVICE_ID_TIGON3_5901 0x170d
#define PCI_DEVICE_ID_BCM4401B1 0x170c
#define PCI_DEVICE_ID_TIGON3_5901_2 0x170e #define PCI_DEVICE_ID_TIGON3_5901_2 0x170e
#define PCI_DEVICE_ID_BCM4401 0x4401 #define PCI_DEVICE_ID_BCM4401 0x4401
#define PCI_DEVICE_ID_BCM4401B0 0x4402 #define PCI_DEVICE_ID_BCM4401B0 0x4402
#define PCI_DEVICE_ID_BCM4401B1 0x170c
#define PCI_VENDOR_ID_ENE 0x1524 #define PCI_VENDOR_ID_ENE 0x1524
#define PCI_DEVICE_ID_ENE_1211 0x1211 #define PCI_DEVICE_ID_ENE_1211 0x1211
......
...@@ -1270,19 +1270,7 @@ static inline void sk_eat_skb(struct sock *sk, struct sk_buff *skb) ...@@ -1270,19 +1270,7 @@ static inline void sk_eat_skb(struct sock *sk, struct sk_buff *skb)
__kfree_skb(skb); __kfree_skb(skb);
} }
extern atomic_t netstamp_needed;
extern void sock_enable_timestamp(struct sock *sk); extern void sock_enable_timestamp(struct sock *sk);
static inline void net_timestamp(struct timeval *stamp)
{
if (atomic_read(&netstamp_needed))
do_gettimeofday(stamp);
else {
stamp->tv_sec = 0;
stamp->tv_usec = 0;
}
}
extern int sock_get_timestamp(struct sock *, struct timeval __user *); extern int sock_get_timestamp(struct sock *, struct timeval __user *);
/* /*
......
...@@ -1001,6 +1001,29 @@ int call_netdevice_notifiers(unsigned long val, void *v) ...@@ -1001,6 +1001,29 @@ int call_netdevice_notifiers(unsigned long val, void *v)
return notifier_call_chain(&netdev_chain, val, v); return notifier_call_chain(&netdev_chain, val, v);
} }
/* When > 0 there are consumers of rx skb time stamps */
static atomic_t netstamp_needed = ATOMIC_INIT(0);
void net_enable_timestamp(void)
{
atomic_inc(&netstamp_needed);
}
void net_disable_timestamp(void)
{
atomic_dec(&netstamp_needed);
}
static inline void net_timestamp(struct timeval *stamp)
{
if (atomic_read(&netstamp_needed))
do_gettimeofday(stamp);
else {
stamp->tv_sec = 0;
stamp->tv_usec = 0;
}
}
/* /*
* Support routine. Sends outgoing frames to any network * Support routine. Sends outgoing frames to any network
* taps currently in use. * taps currently in use.
...@@ -3215,6 +3238,8 @@ EXPORT_SYMBOL(skb_checksum_help); ...@@ -3215,6 +3238,8 @@ EXPORT_SYMBOL(skb_checksum_help);
EXPORT_SYMBOL(synchronize_net); EXPORT_SYMBOL(synchronize_net);
EXPORT_SYMBOL(unregister_netdevice); EXPORT_SYMBOL(unregister_netdevice);
EXPORT_SYMBOL(unregister_netdevice_notifier); EXPORT_SYMBOL(unregister_netdevice_notifier);
EXPORT_SYMBOL(net_enable_timestamp);
EXPORT_SYMBOL(net_disable_timestamp);
#if defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE) #if defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE)
EXPORT_SYMBOL(br_handle_frame_hook); EXPORT_SYMBOL(br_handle_frame_hook);
......
...@@ -802,12 +802,21 @@ EXPORT_SYMBOL(nf_log_register); ...@@ -802,12 +802,21 @@ EXPORT_SYMBOL(nf_log_register);
EXPORT_SYMBOL(nf_log_unregister); EXPORT_SYMBOL(nf_log_unregister);
EXPORT_SYMBOL(nf_log_packet); EXPORT_SYMBOL(nf_log_packet);
/* This does not belong here, but ipt_REJECT needs it if connection /* This does not belong here, but locally generated errors need it if connection
tracking in use: without this, connection may not be in hash table, tracking in use: without this, connection may not be in hash table, and hence
and hence manufactured ICMP or RST packets will not be associated manufactured ICMP or RST packets will not be associated with it. */
with it. */
void (*ip_ct_attach)(struct sk_buff *, struct sk_buff *); void (*ip_ct_attach)(struct sk_buff *, struct sk_buff *);
void nf_ct_attach(struct sk_buff *new, struct sk_buff *skb)
{
void (*attach)(struct sk_buff *, struct sk_buff *);
if (skb->nfct && (attach = ip_ct_attach) != NULL) {
mb(); /* Just to be sure: must be read before executing this */
attach(new, skb);
}
}
void __init netfilter_init(void) void __init netfilter_init(void)
{ {
int i, h; int i, h;
...@@ -819,6 +828,7 @@ void __init netfilter_init(void) ...@@ -819,6 +828,7 @@ void __init netfilter_init(void)
} }
EXPORT_SYMBOL(ip_ct_attach); EXPORT_SYMBOL(ip_ct_attach);
EXPORT_SYMBOL(nf_ct_attach);
EXPORT_SYMBOL(nf_getsockopt); EXPORT_SYMBOL(nf_getsockopt);
EXPORT_SYMBOL(nf_hook_slow); EXPORT_SYMBOL(nf_hook_slow);
EXPORT_SYMBOL(nf_hooks); EXPORT_SYMBOL(nf_hooks);
......
...@@ -179,7 +179,7 @@ static void sock_disable_timestamp(struct sock *sk) ...@@ -179,7 +179,7 @@ static void sock_disable_timestamp(struct sock *sk)
{ {
if (sock_flag(sk, SOCK_TIMESTAMP)) { if (sock_flag(sk, SOCK_TIMESTAMP)) {
sock_reset_flag(sk, SOCK_TIMESTAMP); sock_reset_flag(sk, SOCK_TIMESTAMP);
atomic_dec(&netstamp_needed); net_disable_timestamp();
} }
} }
...@@ -1226,9 +1226,6 @@ void fastcall release_sock(struct sock *sk) ...@@ -1226,9 +1226,6 @@ void fastcall release_sock(struct sock *sk)
} }
EXPORT_SYMBOL(release_sock); EXPORT_SYMBOL(release_sock);
/* When > 0 there are consumers of rx skb time stamps */
atomic_t netstamp_needed = ATOMIC_INIT(0);
int sock_get_timestamp(struct sock *sk, struct timeval __user *userstamp) int sock_get_timestamp(struct sock *sk, struct timeval __user *userstamp)
{ {
if (!sock_flag(sk, SOCK_TIMESTAMP)) if (!sock_flag(sk, SOCK_TIMESTAMP))
...@@ -1246,7 +1243,7 @@ void sock_enable_timestamp(struct sock *sk) ...@@ -1246,7 +1243,7 @@ void sock_enable_timestamp(struct sock *sk)
{ {
if (!sock_flag(sk, SOCK_TIMESTAMP)) { if (!sock_flag(sk, SOCK_TIMESTAMP)) {
sock_set_flag(sk, SOCK_TIMESTAMP); sock_set_flag(sk, SOCK_TIMESTAMP);
atomic_inc(&netstamp_needed); net_enable_timestamp();
} }
} }
EXPORT_SYMBOL(sock_enable_timestamp); EXPORT_SYMBOL(sock_enable_timestamp);
......
...@@ -338,6 +338,8 @@ int icmp_glue_bits(void *from, char *to, int offset, int len, int odd, ...@@ -338,6 +338,8 @@ int icmp_glue_bits(void *from, char *to, int offset, int len, int odd,
to, len, 0); to, len, 0);
skb->csum = csum_block_add(skb->csum, csum, odd); skb->csum = csum_block_add(skb->csum, csum, odd);
if (icmp_pointers[icmp_param->data.icmph.type].error)
nf_ct_attach(skb, icmp_param->skb);
return 0; return 0;
} }
......
...@@ -128,16 +128,13 @@ in_range(const struct ip_conntrack_tuple *tuple, ...@@ -128,16 +128,13 @@ in_range(const struct ip_conntrack_tuple *tuple,
unsigned int i; unsigned int i;
for (i = 0; i < mr->rangesize; i++) { for (i = 0; i < mr->rangesize; i++) {
/* If we are allowed to map IPs, then we must be in the /* If we are supposed to map IPs, then we must be in the
range specified, otherwise we must be unchanged. */ range specified. */
if (mr->range[i].flags & IP_NAT_RANGE_MAP_IPS) { if (mr->range[i].flags & IP_NAT_RANGE_MAP_IPS) {
if (ntohl(tuple->src.ip) < ntohl(mr->range[i].min_ip) if (ntohl(tuple->src.ip) < ntohl(mr->range[i].min_ip)
|| (ntohl(tuple->src.ip) || (ntohl(tuple->src.ip)
> ntohl(mr->range[i].max_ip))) > ntohl(mr->range[i].max_ip)))
continue; continue;
} else {
if (tuple->src.ip != tuple->src.ip)
continue;
} }
if (!(mr->range[i].flags & IP_NAT_RANGE_PROTO_SPECIFIED) if (!(mr->range[i].flags & IP_NAT_RANGE_PROTO_SPECIFIED)
...@@ -687,7 +684,7 @@ manip_pkt(u_int16_t proto, ...@@ -687,7 +684,7 @@ manip_pkt(u_int16_t proto,
iph = (void *)(*pskb)->data + iphdroff; iph = (void *)(*pskb)->data + iphdroff;
/* Manipulate protcol part. */ /* Manipulate protcol part. */
if (!ip_nat_find_proto(proto)->manip_pkt(pskb, iphdroff + iph->ihl*4, if (!ip_nat_find_proto(proto)->manip_pkt(pskb, iphdroff,
manip, maniptype)) manip, maniptype))
return 0; return 0;
......
...@@ -53,11 +53,13 @@ icmp_unique_tuple(struct ip_conntrack_tuple *tuple, ...@@ -53,11 +53,13 @@ icmp_unique_tuple(struct ip_conntrack_tuple *tuple,
static int static int
icmp_manip_pkt(struct sk_buff **pskb, icmp_manip_pkt(struct sk_buff **pskb,
unsigned int hdroff, unsigned int iphdroff,
const struct ip_conntrack_manip *manip, const struct ip_conntrack_manip *manip,
enum ip_nat_manip_type maniptype) enum ip_nat_manip_type maniptype)
{ {
struct iphdr *iph = (struct iphdr *)((*pskb)->data + iphdroff);
struct icmphdr *hdr; struct icmphdr *hdr;
unsigned int hdroff = iphdroff + iph->ihl*4;
if (!skb_ip_make_writable(pskb, hdroff + sizeof(*hdr))) if (!skb_ip_make_writable(pskb, hdroff + sizeof(*hdr)))
return 0; return 0;
......
...@@ -84,11 +84,13 @@ tcp_unique_tuple(struct ip_conntrack_tuple *tuple, ...@@ -84,11 +84,13 @@ tcp_unique_tuple(struct ip_conntrack_tuple *tuple,
static int static int
tcp_manip_pkt(struct sk_buff **pskb, tcp_manip_pkt(struct sk_buff **pskb,
unsigned int hdroff, unsigned int iphdroff,
const struct ip_conntrack_manip *manip, const struct ip_conntrack_manip *manip,
enum ip_nat_manip_type maniptype) enum ip_nat_manip_type maniptype)
{ {
struct iphdr *iph = (struct iphdr *)((*pskb)->data + iphdroff);
struct tcphdr *hdr; struct tcphdr *hdr;
unsigned int hdroff = iphdroff + iph->ihl*4;
u_int32_t oldip; u_int32_t oldip;
u_int16_t *portptr, oldport; u_int16_t *portptr, oldport;
int hdrsize = 8; /* TCP connection tracking guarantees this much */ int hdrsize = 8; /* TCP connection tracking guarantees this much */
...@@ -106,11 +108,11 @@ tcp_manip_pkt(struct sk_buff **pskb, ...@@ -106,11 +108,11 @@ tcp_manip_pkt(struct sk_buff **pskb,
if (maniptype == IP_NAT_MANIP_SRC) { if (maniptype == IP_NAT_MANIP_SRC) {
/* Get rid of src ip and src pt */ /* Get rid of src ip and src pt */
oldip = (*pskb)->nh.iph->saddr; oldip = iph->saddr;
portptr = &hdr->source; portptr = &hdr->source;
} else { } else {
/* Get rid of dst ip and dst pt */ /* Get rid of dst ip and dst pt */
oldip = (*pskb)->nh.iph->daddr; oldip = iph->daddr;
portptr = &hdr->dest; portptr = &hdr->dest;
} }
......
...@@ -83,11 +83,13 @@ udp_unique_tuple(struct ip_conntrack_tuple *tuple, ...@@ -83,11 +83,13 @@ udp_unique_tuple(struct ip_conntrack_tuple *tuple,
static int static int
udp_manip_pkt(struct sk_buff **pskb, udp_manip_pkt(struct sk_buff **pskb,
unsigned int hdroff, unsigned int iphdroff,
const struct ip_conntrack_manip *manip, const struct ip_conntrack_manip *manip,
enum ip_nat_manip_type maniptype) enum ip_nat_manip_type maniptype)
{ {
struct iphdr *iph = (struct iphdr *)((*pskb)->data + iphdroff);
struct udphdr *hdr; struct udphdr *hdr;
unsigned int hdroff = iphdroff + iph->ihl*4;
u_int32_t oldip; u_int32_t oldip;
u_int16_t *portptr; u_int16_t *portptr;
...@@ -97,11 +99,11 @@ udp_manip_pkt(struct sk_buff **pskb, ...@@ -97,11 +99,11 @@ udp_manip_pkt(struct sk_buff **pskb,
hdr = (void *)(*pskb)->data + hdroff; hdr = (void *)(*pskb)->data + hdroff;
if (maniptype == IP_NAT_MANIP_SRC) { if (maniptype == IP_NAT_MANIP_SRC) {
/* Get rid of src ip and src pt */ /* Get rid of src ip and src pt */
oldip = (*pskb)->nh.iph->saddr; oldip = iph->saddr;
portptr = &hdr->source; portptr = &hdr->source;
} else { } else {
/* Get rid of dst ip and dst pt */ /* Get rid of dst ip and dst pt */
oldip = (*pskb)->nh.iph->daddr; oldip = iph->daddr;
portptr = &hdr->dest; portptr = &hdr->dest;
} }
if (hdr->check) /* 0 is a special case meaning no checksum */ if (hdr->check) /* 0 is a special case meaning no checksum */
......
...@@ -39,7 +39,7 @@ static int unknown_unique_tuple(struct ip_conntrack_tuple *tuple, ...@@ -39,7 +39,7 @@ static int unknown_unique_tuple(struct ip_conntrack_tuple *tuple,
static int static int
unknown_manip_pkt(struct sk_buff **pskb, unknown_manip_pkt(struct sk_buff **pskb,
unsigned int hdroff, unsigned int iphdroff,
const struct ip_conntrack_manip *manip, const struct ip_conntrack_manip *manip,
enum ip_nat_manip_type maniptype) enum ip_nat_manip_type maniptype)
{ {
......
...@@ -162,6 +162,7 @@ static inline void ...@@ -162,6 +162,7 @@ static inline void
__ipq_reset(void) __ipq_reset(void)
{ {
peer_pid = 0; peer_pid = 0;
net_disable_timestamp();
__ipq_set_mode(IPQ_COPY_NONE, 0); __ipq_set_mode(IPQ_COPY_NONE, 0);
__ipq_flush(NF_DROP); __ipq_flush(NF_DROP);
} }
...@@ -257,7 +258,8 @@ ipq_build_packet_message(struct ipq_queue_entry *entry, int *errp) ...@@ -257,7 +258,8 @@ ipq_build_packet_message(struct ipq_queue_entry *entry, int *errp)
} }
if (data_len) if (data_len)
memcpy(pmsg->payload, entry->skb->data, data_len); if (skb_copy_bits(entry->skb, 0, pmsg->payload, data_len))
BUG();
nlh->nlmsg_len = skb->tail - old_tail; nlh->nlmsg_len = skb->tail - old_tail;
return skb; return skb;
...@@ -362,6 +364,8 @@ ipq_mangle_ipv4(ipq_verdict_msg_t *v, struct ipq_queue_entry *e) ...@@ -362,6 +364,8 @@ ipq_mangle_ipv4(ipq_verdict_msg_t *v, struct ipq_queue_entry *e)
} }
skb_put(e->skb, diff); skb_put(e->skb, diff);
} }
if (!skb_ip_make_writable(&e->skb, v->data_len))
return -ENOMEM;
memcpy(e->skb->data, v->payload, v->data_len); memcpy(e->skb->data, v->payload, v->data_len);
e->skb->nfcache |= NFC_ALTERED; e->skb->nfcache |= NFC_ALTERED;
...@@ -514,9 +518,10 @@ ipq_rcv_skb(struct sk_buff *skb) ...@@ -514,9 +518,10 @@ ipq_rcv_skb(struct sk_buff *skb)
write_unlock_bh(&queue_lock); write_unlock_bh(&queue_lock);
RCV_SKB_FAIL(-EBUSY); RCV_SKB_FAIL(-EBUSY);
} }
} } else {
else net_enable_timestamp();
peer_pid = pid; peer_pid = pid;
}
write_unlock_bh(&queue_lock); write_unlock_bh(&queue_lock);
......
...@@ -1292,7 +1292,7 @@ do_ipt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len) ...@@ -1292,7 +1292,7 @@ do_ipt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
sizeof(info.underflow)); sizeof(info.underflow));
info.num_entries = t->private->number; info.num_entries = t->private->number;
info.size = t->private->size; info.size = t->private->size;
strcpy(info.name, name); memcpy(info.name, name, sizeof(info.name));
if (copy_to_user(user, &info, *len) != 0) if (copy_to_user(user, &info, *len) != 0)
ret = -EFAULT; ret = -EFAULT;
......
...@@ -118,49 +118,57 @@ masquerade_target(struct sk_buff **pskb, ...@@ -118,49 +118,57 @@ masquerade_target(struct sk_buff **pskb,
} }
static inline int static inline int
device_cmp(const struct ip_conntrack *i, void *_ina) device_cmp(const struct ip_conntrack *i, void *ifindex)
{ {
int ret = 0; int ret;
struct in_ifaddr *ina = _ina;
READ_LOCK(&masq_lock); READ_LOCK(&masq_lock);
/* If it's masquerading out this interface with a different address, ret = (i->nat.masq_index == (int)(long)ifindex);
or we don't know the new address of this interface. */
if (i->nat.masq_index == ina->ifa_dev->dev->ifindex
&& i->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip != ina->ifa_address)
ret = 1;
READ_UNLOCK(&masq_lock); READ_UNLOCK(&masq_lock);
return ret; return ret;
} }
static inline int static int masq_device_event(struct notifier_block *this,
connect_unassure(const struct ip_conntrack *i, void *_ina) unsigned long event,
void *ptr)
{ {
struct in_ifaddr *ina = _ina; struct net_device *dev = ptr;
if (event == NETDEV_DOWN) {
/* Device was downed. Search entire table for
conntracks which were associated with that device,
and forget them. */
IP_NF_ASSERT(dev->ifindex != 0);
/* We reset the ASSURED bit on all connections, so they will ip_ct_selective_cleanup(device_cmp, (void *)(long)dev->ifindex);
* get reaped under memory pressure. */ }
if (i->nat.masq_index == ina->ifa_dev->dev->ifindex)
clear_bit(IPS_ASSURED_BIT, (unsigned long *)&i->status); return NOTIFY_DONE;
return 0;
} }
static int masq_inet_event(struct notifier_block *this, static int masq_inet_event(struct notifier_block *this,
unsigned long event, unsigned long event,
void *ptr) void *ptr)
{ {
/* For some configurations, interfaces often come back with struct net_device *dev = ((struct in_ifaddr *)ptr)->ifa_dev->dev;
* the same address. If not, clean up old conntrack
* entries. */ if (event == NETDEV_DOWN) {
if (event == NETDEV_UP) /* IP address was deleted. Search entire table for
ip_ct_selective_cleanup(device_cmp, ptr); conntracks which were associated with that device,
else if (event == NETDEV_DOWN) and forget them. */
ip_ct_selective_cleanup(connect_unassure, ptr); IP_NF_ASSERT(dev->ifindex != 0);
ip_ct_selective_cleanup(device_cmp, (void *)(long)dev->ifindex);
}
return NOTIFY_DONE; return NOTIFY_DONE;
} }
static struct notifier_block masq_dev_notifier = {
.notifier_call = masq_device_event,
};
static struct notifier_block masq_inet_notifier = { static struct notifier_block masq_inet_notifier = {
.notifier_call = masq_inet_event, .notifier_call = masq_inet_event,
}; };
...@@ -178,9 +186,12 @@ static int __init init(void) ...@@ -178,9 +186,12 @@ static int __init init(void)
ret = ipt_register_target(&masquerade); ret = ipt_register_target(&masquerade);
if (ret == 0) if (ret == 0) {
/* Register for device down reports */
register_netdevice_notifier(&masq_dev_notifier);
/* Register IP address change reports */ /* Register IP address change reports */
register_inetaddr_notifier(&masq_inet_notifier); register_inetaddr_notifier(&masq_inet_notifier);
}
return ret; return ret;
} }
...@@ -188,6 +199,7 @@ static int __init init(void) ...@@ -188,6 +199,7 @@ static int __init init(void)
static void __exit fini(void) static void __exit fini(void)
{ {
ipt_unregister_target(&masquerade); ipt_unregister_target(&masquerade);
unregister_netdevice_notifier(&masq_dev_notifier);
unregister_inetaddr_notifier(&masq_inet_notifier); unregister_inetaddr_notifier(&masq_inet_notifier);
} }
......
...@@ -38,20 +38,6 @@ MODULE_DESCRIPTION("iptables REJECT target module"); ...@@ -38,20 +38,6 @@ MODULE_DESCRIPTION("iptables REJECT target module");
#define DEBUGP(format, args...) #define DEBUGP(format, args...)
#endif #endif
/* If the original packet is part of a connection, but the connection
is not confirmed, our manufactured reply will not be associated
with it, so we need to do this manually. */
static void connection_attach(struct sk_buff *new_skb, struct sk_buff *skb)
{
void (*attach)(struct sk_buff *, struct sk_buff *);
/* Avoid module unload race with ip_ct_attach being NULLed out */
if (skb->nfct && (attach = ip_ct_attach) != NULL) {
mb(); /* Just to be sure: must be read before executing this */
attach(new_skb, skb);
}
}
static inline struct rtable *route_reverse(struct sk_buff *skb, int hook) static inline struct rtable *route_reverse(struct sk_buff *skb, int hook)
{ {
struct iphdr *iph = skb->nh.iph; struct iphdr *iph = skb->nh.iph;
...@@ -209,7 +195,7 @@ static void send_reset(struct sk_buff *oldskb, int hook) ...@@ -209,7 +195,7 @@ static void send_reset(struct sk_buff *oldskb, int hook)
if (nskb->len > dst_pmtu(nskb->dst)) if (nskb->len > dst_pmtu(nskb->dst))
goto free_nskb; goto free_nskb;
connection_attach(nskb, oldskb); nf_ct_attach(nskb, oldskb);
NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, nskb, NULL, nskb->dst->dev, NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, nskb, NULL, nskb->dst->dev,
ip_finish_output); ip_finish_output);
...@@ -360,7 +346,7 @@ static void send_unreach(struct sk_buff *skb_in, int code) ...@@ -360,7 +346,7 @@ static void send_unreach(struct sk_buff *skb_in, int code)
icmph->checksum = ip_compute_csum((unsigned char *)icmph, icmph->checksum = ip_compute_csum((unsigned char *)icmph,
length - sizeof(struct iphdr)); length - sizeof(struct iphdr));
connection_attach(nskb, skb_in); nf_ct_attach(nskb, skb_in);
NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, nskb, NULL, nskb->dst->dev, NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, nskb, NULL, nskb->dst->dev,
ip_finish_output); ip_finish_output);
......
...@@ -3387,6 +3387,29 @@ int unregister_inet6addr_notifier(struct notifier_block *nb) ...@@ -3387,6 +3387,29 @@ int unregister_inet6addr_notifier(struct notifier_block *nb)
void __init addrconf_init(void) void __init addrconf_init(void)
{ {
/* The addrconf netdev notifier requires that loopback_dev
* has it's ipv6 private information allocated and setup
* before it can bring up and give link-local addresses
* to other devices which are up.
*
* Unfortunately, loopback_dev is not necessarily the first
* entry in the global dev_base list of net devices. In fact,
* it is likely to be the very last entry on that list.
* So this causes the notifier registry below to try and
* give link-local addresses to all devices besides loopback_dev
* first, then loopback_dev, which cases all the non-loopback_dev
* devices to fail to get a link-local address.
*
* So, as a temporary fix, register loopback_dev first by hand.
* Longer term, all of the dependencies ipv6 has upon the loopback
* device and it being up should be removed.
*/
rtnl_lock();
addrconf_notify(&ipv6_dev_notf, NETDEV_REGISTER, &loopback_dev);
if (loopback_dev.flags & IFF_UP)
addrconf_notify(&ipv6_dev_notf, NETDEV_UP, &loopback_dev);
rtnl_unlock();
register_netdevice_notifier(&ipv6_dev_notf); register_netdevice_notifier(&ipv6_dev_notf);
#ifdef CONFIG_IPV6_PRIVACY #ifdef CONFIG_IPV6_PRIVACY
......
...@@ -167,6 +167,7 @@ static inline void ...@@ -167,6 +167,7 @@ static inline void
__ipq_reset(void) __ipq_reset(void)
{ {
peer_pid = 0; peer_pid = 0;
net_disable_timestamp();
__ipq_set_mode(IPQ_COPY_NONE, 0); __ipq_set_mode(IPQ_COPY_NONE, 0);
__ipq_flush(NF_DROP); __ipq_flush(NF_DROP);
} }
...@@ -262,7 +263,8 @@ ipq_build_packet_message(struct ipq_queue_entry *entry, int *errp) ...@@ -262,7 +263,8 @@ ipq_build_packet_message(struct ipq_queue_entry *entry, int *errp)
} }
if (data_len) if (data_len)
memcpy(pmsg->payload, entry->skb->data, data_len); if (skb_copy_bits(entry->skb, 0, pmsg->payload, data_len))
BUG();
nlh->nlmsg_len = skb->tail - old_tail; nlh->nlmsg_len = skb->tail - old_tail;
return skb; return skb;
...@@ -366,6 +368,8 @@ ipq_mangle_ipv6(ipq_verdict_msg_t *v, struct ipq_queue_entry *e) ...@@ -366,6 +368,8 @@ ipq_mangle_ipv6(ipq_verdict_msg_t *v, struct ipq_queue_entry *e)
} }
skb_put(e->skb, diff); skb_put(e->skb, diff);
} }
if (!skb_ip_make_writable(&e->skb, v->data_len))
return -ENOMEM;
memcpy(e->skb->data, v->payload, v->data_len); memcpy(e->skb->data, v->payload, v->data_len);
e->skb->nfcache |= NFC_ALTERED; e->skb->nfcache |= NFC_ALTERED;
...@@ -517,9 +521,10 @@ ipq_rcv_skb(struct sk_buff *skb) ...@@ -517,9 +521,10 @@ ipq_rcv_skb(struct sk_buff *skb)
write_unlock_bh(&queue_lock); write_unlock_bh(&queue_lock);
RCV_SKB_FAIL(-EBUSY); RCV_SKB_FAIL(-EBUSY);
} }
} } else {
else net_enable_timestamp();
peer_pid = pid; peer_pid = pid;
}
write_unlock_bh(&queue_lock); write_unlock_bh(&queue_lock);
......
...@@ -69,7 +69,7 @@ ip6t_eui64_checkentry(const char *tablename, ...@@ -69,7 +69,7 @@ ip6t_eui64_checkentry(const char *tablename,
{ {
if (hook_mask if (hook_mask
& ~((1 << NF_IP6_PRE_ROUTING) | (1 << NF_IP6_LOCAL_IN) | & ~((1 << NF_IP6_PRE_ROUTING) | (1 << NF_IP6_LOCAL_IN) |
(1 << NF_IP6_PRE_ROUTING) )) { (1 << NF_IP6_FORWARD))) {
printk("ip6t_eui64: only valid for PRE_ROUTING, LOCAL_IN or FORWARD.\n"); printk("ip6t_eui64: only valid for PRE_ROUTING, LOCAL_IN or FORWARD.\n");
return 0; return 0;
} }
......
...@@ -51,7 +51,7 @@ ipv6header_match(const struct sk_buff *skb, ...@@ -51,7 +51,7 @@ ipv6header_match(const struct sk_buff *skb,
temp = 0; temp = 0;
while (ip6t_ext_hdr(nexthdr)) { while (ip6t_ext_hdr(nexthdr)) {
struct ipv6_opt_hdr *hdr; struct ipv6_opt_hdr _hdr, *hp;
int hdrlen; int hdrlen;
/* Is there enough space for the next ext header? */ /* Is there enough space for the next ext header? */
...@@ -68,15 +68,16 @@ ipv6header_match(const struct sk_buff *skb, ...@@ -68,15 +68,16 @@ ipv6header_match(const struct sk_buff *skb,
break; break;
} }
hdr=(struct ipv6_opt_hdr *)skb->data+ptr; hp = skb_header_pointer(skb, ptr, sizeof(_hdr), &_hdr);
BUG_ON(hp == NULL);
/* Calculate the header length */ /* Calculate the header length */
if (nexthdr == NEXTHDR_FRAGMENT) { if (nexthdr == NEXTHDR_FRAGMENT) {
hdrlen = 8; hdrlen = 8;
} else if (nexthdr == NEXTHDR_AUTH) } else if (nexthdr == NEXTHDR_AUTH)
hdrlen = (hdr->hdrlen+2)<<2; hdrlen = (hp->hdrlen+2)<<2;
else else
hdrlen = ipv6_optlen(hdr); hdrlen = ipv6_optlen(hp);
/* set the flag */ /* set the flag */
switch (nexthdr){ switch (nexthdr){
...@@ -100,7 +101,7 @@ ipv6header_match(const struct sk_buff *skb, ...@@ -100,7 +101,7 @@ ipv6header_match(const struct sk_buff *skb,
break; break;
} }
nexthdr = hdr->nexthdr; nexthdr = hp->nexthdr;
len -= hdrlen; len -= hdrlen;
ptr += hdrlen; ptr += hdrlen;
if (ptr > skb->len) if (ptr > skb->len)
...@@ -111,10 +112,14 @@ ipv6header_match(const struct sk_buff *skb, ...@@ -111,10 +112,14 @@ ipv6header_match(const struct sk_buff *skb,
temp |= MASK_PROTO; temp |= MASK_PROTO;
if (info->modeflag) if (info->modeflag)
return (!( (temp & info->matchflags) return !((temp ^ info->matchflags ^ info->invflags)
^ info->matchflags) ^ info->invflags); & info->matchflags);
else else {
return (!( temp ^ info->matchflags) ^ info->invflags); if (info->invflags)
return temp != info->matchflags;
else
return temp == info->matchflags;
}
} }
static int static int
...@@ -124,11 +129,18 @@ ipv6header_checkentry(const char *tablename, ...@@ -124,11 +129,18 @@ ipv6header_checkentry(const char *tablename,
unsigned int matchsize, unsigned int matchsize,
unsigned int hook_mask) unsigned int hook_mask)
{ {
const struct ip6t_ipv6header_info *info = matchinfo;
/* Check for obvious errors */ /* Check for obvious errors */
/* This match is valid in all hooks! */ /* This match is valid in all hooks! */
if (matchsize != IP6T_ALIGN(sizeof(struct ip6t_ipv6header_info))) if (matchsize != IP6T_ALIGN(sizeof(struct ip6t_ipv6header_info)))
return 0; return 0;
/* invflags is 0 or 0xff in hard mode */
if ((!info->modeflag) && info->invflags != 0x00
&& info->invflags != 0xFF)
return 0;
return 1; return 1;
} }
......
...@@ -79,7 +79,7 @@ static int xfrm6_tunnel_check_size(struct sk_buff *skb) ...@@ -79,7 +79,7 @@ static int xfrm6_tunnel_check_size(struct sk_buff *skb)
int mtu, ret = 0; int mtu, ret = 0;
struct dst_entry *dst = skb->dst; struct dst_entry *dst = skb->dst;
mtu = dst_pmtu(dst) - sizeof(struct ipv6hdr); mtu = dst_pmtu(dst) - dst->header_len - dst->trailer_len;
if (mtu < IPV6_MIN_MTU) if (mtu < IPV6_MIN_MTU)
mtu = IPV6_MIN_MTU; mtu = IPV6_MIN_MTU;
......
...@@ -471,9 +471,16 @@ static int netlink_bind(struct socket *sock, struct sockaddr *addr, int addr_len ...@@ -471,9 +471,16 @@ static int netlink_bind(struct socket *sock, struct sockaddr *addr, int addr_len
return err; return err;
} }
nlk->groups = nladdr->nl_groups; if (!nladdr->nl_groups && !nlk->groups)
if (nladdr->nl_groups) return 0;
netlink_table_grab();
if (nlk->groups && !nladdr->nl_groups)
__sk_del_bind_node(sk);
else if (!nlk->groups && nladdr->nl_groups)
sk_add_bind_node(sk, &nl_table[sk->sk_protocol].mc_list); sk_add_bind_node(sk, &nl_table[sk->sk_protocol].mc_list);
nlk->groups = nladdr->nl_groups;
netlink_table_ungrab();
return 0; return 0;
} }
......
...@@ -78,7 +78,10 @@ ...@@ -78,7 +78,10 @@
#include <asm/uaccess.h> #include <asm/uaccess.h>
extern struct notifier_block sctp_inetaddr_notifier; extern int sctp_inetaddr_event(struct notifier_block *, unsigned long, void *);
static struct notifier_block sctp_inet6addr_notifier = {
.notifier_call = sctp_inetaddr_event,
};
/* ICMP error handler. */ /* ICMP error handler. */
void sctp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, void sctp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
...@@ -983,7 +986,7 @@ int sctp_v6_init(void) ...@@ -983,7 +986,7 @@ int sctp_v6_init(void)
sctp_register_af(&sctp_ipv6_specific); sctp_register_af(&sctp_ipv6_specific);
/* Register notifier for inet6 address additions/deletions. */ /* Register notifier for inet6 address additions/deletions. */
register_inet6addr_notifier(&sctp_inetaddr_notifier); register_inet6addr_notifier(&sctp_inet6addr_notifier);
rc = 0; rc = 0;
out: out:
return rc; return rc;
...@@ -999,6 +1002,6 @@ void sctp_v6_exit(void) ...@@ -999,6 +1002,6 @@ void sctp_v6_exit(void)
inet6_del_protocol(&sctpv6_protocol, IPPROTO_SCTP); inet6_del_protocol(&sctpv6_protocol, IPPROTO_SCTP);
inet6_unregister_protosw(&sctpv6_seqpacket_protosw); inet6_unregister_protosw(&sctpv6_seqpacket_protosw);
inet6_unregister_protosw(&sctpv6_stream_protosw); inet6_unregister_protosw(&sctpv6_stream_protosw);
unregister_inet6addr_notifier(&sctp_inetaddr_notifier); unregister_inet6addr_notifier(&sctp_inet6addr_notifier);
sk_free_slab(&sctpv6_prot); sk_free_slab(&sctpv6_prot);
} }
...@@ -622,8 +622,8 @@ static void sctp_v4_seq_dump_addr(struct seq_file *seq, union sctp_addr *addr) ...@@ -622,8 +622,8 @@ static void sctp_v4_seq_dump_addr(struct seq_file *seq, union sctp_addr *addr)
/* Event handler for inet address addition/deletion events. /* Event handler for inet address addition/deletion events.
* Basically, whenever there is an event, we re-build our local address list. * Basically, whenever there is an event, we re-build our local address list.
*/ */
static int sctp_inetaddr_event(struct notifier_block *this, unsigned long ev, int sctp_inetaddr_event(struct notifier_block *this, unsigned long ev,
void *ptr) void *ptr)
{ {
unsigned long flags; unsigned long flags;
...@@ -824,7 +824,7 @@ static struct sctp_pf sctp_pf_inet = { ...@@ -824,7 +824,7 @@ static struct sctp_pf sctp_pf_inet = {
}; };
/* Notifier for inetaddr addition/deletion events. */ /* Notifier for inetaddr addition/deletion events. */
struct notifier_block sctp_inetaddr_notifier = { static struct notifier_block sctp_inetaddr_notifier = {
.notifier_call = sctp_inetaddr_event, .notifier_call = sctp_inetaddr_event,
}; };
......
...@@ -1535,9 +1535,11 @@ static int unix_dgram_recvmsg(struct kiocb *iocb, struct socket *sock, ...@@ -1535,9 +1535,11 @@ static int unix_dgram_recvmsg(struct kiocb *iocb, struct socket *sock,
msg->msg_namelen = 0; msg->msg_namelen = 0;
down(&u->readsem);
skb = skb_recv_datagram(sk, flags, noblock, &err); skb = skb_recv_datagram(sk, flags, noblock, &err);
if (!skb) if (!skb)
goto out; goto out_unlock;
wake_up_interruptible(&u->peer_wait); wake_up_interruptible(&u->peer_wait);
...@@ -1587,6 +1589,8 @@ static int unix_dgram_recvmsg(struct kiocb *iocb, struct socket *sock, ...@@ -1587,6 +1589,8 @@ static int unix_dgram_recvmsg(struct kiocb *iocb, struct socket *sock,
out_free: out_free:
skb_free_datagram(sk,skb); skb_free_datagram(sk,skb);
out_unlock:
up(&u->readsem);
out: out:
return err; return err;
} }
......
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