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 @@
#define DRV_MODULE_NAME "tg3"
#define PFX DRV_MODULE_NAME ": "
#define DRV_MODULE_VERSION "3.13"
#define DRV_MODULE_RELDATE "November 1, 2004"
#define DRV_MODULE_VERSION "3.14"
#define DRV_MODULE_RELDATE "November 15, 2004"
#define TG3_DEF_MAC_MODE 0
#define TG3_DEF_RX_MODE 0
......@@ -206,6 +206,14 @@ static struct pci_device_id tg3_pci_tbl[] = {
PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
{ PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5751F,
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_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
{ PCI_VENDOR_ID_SYSKONNECT, PCI_DEVICE_ID_SYSKONNECT_9MXX,
......@@ -881,34 +889,54 @@ static void tg3_frob_aux_power(struct tg3 *tp)
GRC_LCLCTRL_GPIO_OUTPUT1));
udelay(100);
} else {
int no_gpio2;
u32 grc_local_ctrl;
if (tp_peer != tp &&
(tp_peer->tg3_flags & TG3_FLAG_INIT_COMPLETE) != 0)
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 |
(GRC_LCLCTRL_GPIO_OE0 |
GRC_LCLCTRL_GPIO_OE1 |
GRC_LCLCTRL_GPIO_OE2 |
GRC_LCLCTRL_GPIO_OUTPUT1 |
GRC_LCLCTRL_GPIO_OUTPUT2));
grc_local_ctrl);
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 |
(GRC_LCLCTRL_GPIO_OE0 |
GRC_LCLCTRL_GPIO_OE1 |
GRC_LCLCTRL_GPIO_OE2 |
GRC_LCLCTRL_GPIO_OUTPUT0 |
GRC_LCLCTRL_GPIO_OUTPUT1 |
GRC_LCLCTRL_GPIO_OUTPUT2));
grc_local_ctrl);
udelay(100);
tw32_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl |
(GRC_LCLCTRL_GPIO_OE0 |
GRC_LCLCTRL_GPIO_OE1 |
GRC_LCLCTRL_GPIO_OE2 |
GRC_LCLCTRL_GPIO_OUTPUT0 |
GRC_LCLCTRL_GPIO_OUTPUT1));
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;
if (!no_gpio2) {
tw32_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl |
grc_local_ctrl);
udelay(100);
}
}
} else {
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)
tp->pdev->device == PCI_DEVICE_ID_TIGON3_5901_2 ||
tp->pdev->device == PCI_DEVICE_ID_TIGON3_5705F)) ||
(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;
err = tg3_phy_probe(tp);
......@@ -7926,7 +7955,8 @@ static int __devinit tg3_test_dma(struct tg3 *tp)
#endif
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)) {
if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705 ||
GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750)
......
......@@ -1436,6 +1436,7 @@
#define NIC_SRAM_DATA_CFG_EEPROM_WP 0x00000100
#define NIC_SRAM_DATA_CFG_MINI_PCI 0x00001000
#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_ID1_MASK 0xffff0000
......
......@@ -925,6 +925,9 @@ extern unsigned long netdev_fc_xoff;
extern atomic_t netdev_dropping;
extern int netdev_set_master(struct net_device *dev, struct net_device *master);
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
extern char *net_sysctl_strdup(const char *s);
......
......@@ -173,6 +173,7 @@ extern void nf_reinject(struct sk_buff *skb,
unsigned int verdict);
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
extern void nf_dump_skb(int pf, struct sk_buff *skb);
......@@ -183,6 +184,7 @@ extern void nf_invalidate_cache(int pf);
#else /* !CONFIG_NETFILTER */
#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 /*__KERNEL__*/
......
......@@ -18,7 +18,7 @@ struct ip_nat_protocol
/* Do a packet translation according to the ip_nat_proto_manip
* and manip type. Return true if succeeded. */
int (*manip_pkt)(struct sk_buff **pskb,
unsigned int hdroff,
unsigned int iphdroff,
const struct ip_conntrack_manip *manip,
enum ip_nat_manip_type maniptype);
......
......@@ -1918,11 +1918,15 @@
#define PCI_DEVICE_ID_TIGON3_5704S 0x16a8
#define PCI_DEVICE_ID_TIGON3_5702A3 0x16c6
#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_BCM4401B1 0x170c
#define PCI_DEVICE_ID_TIGON3_5901_2 0x170e
#define PCI_DEVICE_ID_BCM4401 0x4401
#define PCI_DEVICE_ID_BCM4401B0 0x4402
#define PCI_DEVICE_ID_BCM4401B1 0x170c
#define PCI_VENDOR_ID_ENE 0x1524
#define PCI_DEVICE_ID_ENE_1211 0x1211
......
......@@ -1270,19 +1270,7 @@ static inline void sk_eat_skb(struct sock *sk, struct sk_buff *skb)
__kfree_skb(skb);
}
extern atomic_t netstamp_needed;
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 *);
/*
......
......@@ -1001,6 +1001,29 @@ int call_netdevice_notifiers(unsigned long val, void *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
* taps currently in use.
......@@ -3215,6 +3238,8 @@ EXPORT_SYMBOL(skb_checksum_help);
EXPORT_SYMBOL(synchronize_net);
EXPORT_SYMBOL(unregister_netdevice);
EXPORT_SYMBOL(unregister_netdevice_notifier);
EXPORT_SYMBOL(net_enable_timestamp);
EXPORT_SYMBOL(net_disable_timestamp);
#if defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE)
EXPORT_SYMBOL(br_handle_frame_hook);
......
......@@ -802,12 +802,21 @@ EXPORT_SYMBOL(nf_log_register);
EXPORT_SYMBOL(nf_log_unregister);
EXPORT_SYMBOL(nf_log_packet);
/* This does not belong here, but ipt_REJECT needs it if connection
tracking in use: without this, connection may not be in hash table,
and hence manufactured ICMP or RST packets will not be associated
with it. */
/* 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, and hence
manufactured ICMP or RST packets will not be associated with it. */
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)
{
int i, h;
......@@ -819,6 +828,7 @@ void __init netfilter_init(void)
}
EXPORT_SYMBOL(ip_ct_attach);
EXPORT_SYMBOL(nf_ct_attach);
EXPORT_SYMBOL(nf_getsockopt);
EXPORT_SYMBOL(nf_hook_slow);
EXPORT_SYMBOL(nf_hooks);
......
......@@ -179,7 +179,7 @@ static void sock_disable_timestamp(struct sock *sk)
{
if (sock_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)
}
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)
{
if (!sock_flag(sk, SOCK_TIMESTAMP))
......@@ -1246,7 +1243,7 @@ void sock_enable_timestamp(struct sock *sk)
{
if (!sock_flag(sk, SOCK_TIMESTAMP)) {
sock_set_flag(sk, SOCK_TIMESTAMP);
atomic_inc(&netstamp_needed);
net_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,
to, len, 0);
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;
}
......
......@@ -128,16 +128,13 @@ in_range(const struct ip_conntrack_tuple *tuple,
unsigned int i;
for (i = 0; i < mr->rangesize; i++) {
/* If we are allowed to map IPs, then we must be in the
range specified, otherwise we must be unchanged. */
/* If we are supposed to map IPs, then we must be in the
range specified. */
if (mr->range[i].flags & IP_NAT_RANGE_MAP_IPS) {
if (ntohl(tuple->src.ip) < ntohl(mr->range[i].min_ip)
|| (ntohl(tuple->src.ip)
> ntohl(mr->range[i].max_ip)))
continue;
} else {
if (tuple->src.ip != tuple->src.ip)
continue;
}
if (!(mr->range[i].flags & IP_NAT_RANGE_PROTO_SPECIFIED)
......@@ -687,7 +684,7 @@ manip_pkt(u_int16_t proto,
iph = (void *)(*pskb)->data + iphdroff;
/* 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))
return 0;
......
......@@ -53,11 +53,13 @@ icmp_unique_tuple(struct ip_conntrack_tuple *tuple,
static int
icmp_manip_pkt(struct sk_buff **pskb,
unsigned int hdroff,
unsigned int iphdroff,
const struct ip_conntrack_manip *manip,
enum ip_nat_manip_type maniptype)
{
struct iphdr *iph = (struct iphdr *)((*pskb)->data + iphdroff);
struct icmphdr *hdr;
unsigned int hdroff = iphdroff + iph->ihl*4;
if (!skb_ip_make_writable(pskb, hdroff + sizeof(*hdr)))
return 0;
......
......@@ -84,11 +84,13 @@ tcp_unique_tuple(struct ip_conntrack_tuple *tuple,
static int
tcp_manip_pkt(struct sk_buff **pskb,
unsigned int hdroff,
unsigned int iphdroff,
const struct ip_conntrack_manip *manip,
enum ip_nat_manip_type maniptype)
{
struct iphdr *iph = (struct iphdr *)((*pskb)->data + iphdroff);
struct tcphdr *hdr;
unsigned int hdroff = iphdroff + iph->ihl*4;
u_int32_t oldip;
u_int16_t *portptr, oldport;
int hdrsize = 8; /* TCP connection tracking guarantees this much */
......@@ -106,11 +108,11 @@ tcp_manip_pkt(struct sk_buff **pskb,
if (maniptype == IP_NAT_MANIP_SRC) {
/* Get rid of src ip and src pt */
oldip = (*pskb)->nh.iph->saddr;
oldip = iph->saddr;
portptr = &hdr->source;
} else {
/* Get rid of dst ip and dst pt */
oldip = (*pskb)->nh.iph->daddr;
oldip = iph->daddr;
portptr = &hdr->dest;
}
......
......@@ -83,11 +83,13 @@ udp_unique_tuple(struct ip_conntrack_tuple *tuple,
static int
udp_manip_pkt(struct sk_buff **pskb,
unsigned int hdroff,
unsigned int iphdroff,
const struct ip_conntrack_manip *manip,
enum ip_nat_manip_type maniptype)
{
struct iphdr *iph = (struct iphdr *)((*pskb)->data + iphdroff);
struct udphdr *hdr;
unsigned int hdroff = iphdroff + iph->ihl*4;
u_int32_t oldip;
u_int16_t *portptr;
......@@ -97,11 +99,11 @@ udp_manip_pkt(struct sk_buff **pskb,
hdr = (void *)(*pskb)->data + hdroff;
if (maniptype == IP_NAT_MANIP_SRC) {
/* Get rid of src ip and src pt */
oldip = (*pskb)->nh.iph->saddr;
oldip = iph->saddr;
portptr = &hdr->source;
} else {
/* Get rid of dst ip and dst pt */
oldip = (*pskb)->nh.iph->daddr;
oldip = iph->daddr;
portptr = &hdr->dest;
}
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,
static int
unknown_manip_pkt(struct sk_buff **pskb,
unsigned int hdroff,
unsigned int iphdroff,
const struct ip_conntrack_manip *manip,
enum ip_nat_manip_type maniptype)
{
......
......@@ -162,6 +162,7 @@ static inline void
__ipq_reset(void)
{
peer_pid = 0;
net_disable_timestamp();
__ipq_set_mode(IPQ_COPY_NONE, 0);
__ipq_flush(NF_DROP);
}
......@@ -257,7 +258,8 @@ ipq_build_packet_message(struct ipq_queue_entry *entry, int *errp)
}
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;
return skb;
......@@ -362,6 +364,8 @@ ipq_mangle_ipv4(ipq_verdict_msg_t *v, struct ipq_queue_entry *e)
}
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);
e->skb->nfcache |= NFC_ALTERED;
......@@ -514,9 +518,10 @@ ipq_rcv_skb(struct sk_buff *skb)
write_unlock_bh(&queue_lock);
RCV_SKB_FAIL(-EBUSY);
}
}
else
} else {
net_enable_timestamp();
peer_pid = pid;
}
write_unlock_bh(&queue_lock);
......
......@@ -1292,7 +1292,7 @@ do_ipt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
sizeof(info.underflow));
info.num_entries = t->private->number;
info.size = t->private->size;
strcpy(info.name, name);
memcpy(info.name, name, sizeof(info.name));
if (copy_to_user(user, &info, *len) != 0)
ret = -EFAULT;
......
......@@ -118,49 +118,57 @@ masquerade_target(struct sk_buff **pskb,
}
static inline int
device_cmp(const struct ip_conntrack *i, void *_ina)
device_cmp(const struct ip_conntrack *i, void *ifindex)
{
int ret = 0;
struct in_ifaddr *ina = _ina;
int ret;
READ_LOCK(&masq_lock);
/* If it's masquerading out this interface with a different address,
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;
ret = (i->nat.masq_index == (int)(long)ifindex);
READ_UNLOCK(&masq_lock);
return ret;
}
static inline int
connect_unassure(const struct ip_conntrack *i, void *_ina)
static int masq_device_event(struct notifier_block *this,
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
* 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 0;
ip_ct_selective_cleanup(device_cmp, (void *)(long)dev->ifindex);
}
return NOTIFY_DONE;
}
static int masq_inet_event(struct notifier_block *this,
unsigned long event,
void *ptr)
{
/* For some configurations, interfaces often come back with
* the same address. If not, clean up old conntrack
* entries. */
if (event == NETDEV_UP)
ip_ct_selective_cleanup(device_cmp, ptr);
else if (event == NETDEV_DOWN)
ip_ct_selective_cleanup(connect_unassure, ptr);
struct net_device *dev = ((struct in_ifaddr *)ptr)->ifa_dev->dev;
if (event == NETDEV_DOWN) {
/* IP address was deleted. Search entire table for
conntracks which were associated with that device,
and forget them. */
IP_NF_ASSERT(dev->ifindex != 0);
ip_ct_selective_cleanup(device_cmp, (void *)(long)dev->ifindex);
}
return NOTIFY_DONE;
}
static struct notifier_block masq_dev_notifier = {
.notifier_call = masq_device_event,
};
static struct notifier_block masq_inet_notifier = {
.notifier_call = masq_inet_event,
};
......@@ -178,9 +186,12 @@ static int __init init(void)
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_inetaddr_notifier(&masq_inet_notifier);
}
return ret;
}
......@@ -188,6 +199,7 @@ static int __init init(void)
static void __exit fini(void)
{
ipt_unregister_target(&masquerade);
unregister_netdevice_notifier(&masq_dev_notifier);
unregister_inetaddr_notifier(&masq_inet_notifier);
}
......
......@@ -38,20 +38,6 @@ MODULE_DESCRIPTION("iptables REJECT target module");
#define DEBUGP(format, args...)
#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)
{
struct iphdr *iph = skb->nh.iph;
......@@ -209,7 +195,7 @@ static void send_reset(struct sk_buff *oldskb, int hook)
if (nskb->len > dst_pmtu(nskb->dst))
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,
ip_finish_output);
......@@ -360,7 +346,7 @@ static void send_unreach(struct sk_buff *skb_in, int code)
icmph->checksum = ip_compute_csum((unsigned char *)icmph,
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,
ip_finish_output);
......
......@@ -3387,6 +3387,29 @@ int unregister_inet6addr_notifier(struct notifier_block *nb)
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);
#ifdef CONFIG_IPV6_PRIVACY
......
......@@ -167,6 +167,7 @@ static inline void
__ipq_reset(void)
{
peer_pid = 0;
net_disable_timestamp();
__ipq_set_mode(IPQ_COPY_NONE, 0);
__ipq_flush(NF_DROP);
}
......@@ -262,7 +263,8 @@ ipq_build_packet_message(struct ipq_queue_entry *entry, int *errp)
}
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;
return skb;
......@@ -366,6 +368,8 @@ ipq_mangle_ipv6(ipq_verdict_msg_t *v, struct ipq_queue_entry *e)
}
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);
e->skb->nfcache |= NFC_ALTERED;
......@@ -517,9 +521,10 @@ ipq_rcv_skb(struct sk_buff *skb)
write_unlock_bh(&queue_lock);
RCV_SKB_FAIL(-EBUSY);
}
}
else
} else {
net_enable_timestamp();
peer_pid = pid;
}
write_unlock_bh(&queue_lock);
......
......@@ -69,7 +69,7 @@ ip6t_eui64_checkentry(const char *tablename,
{
if (hook_mask
& ~((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");
return 0;
}
......
......@@ -51,7 +51,7 @@ ipv6header_match(const struct sk_buff *skb,
temp = 0;
while (ip6t_ext_hdr(nexthdr)) {
struct ipv6_opt_hdr *hdr;
struct ipv6_opt_hdr _hdr, *hp;
int hdrlen;
/* Is there enough space for the next ext header? */
......@@ -68,15 +68,16 @@ ipv6header_match(const struct sk_buff *skb,
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 */
if (nexthdr == NEXTHDR_FRAGMENT) {
hdrlen = 8;
} else if (nexthdr == NEXTHDR_AUTH)
hdrlen = (hdr->hdrlen+2)<<2;
hdrlen = (hp->hdrlen+2)<<2;
else
hdrlen = ipv6_optlen(hdr);
hdrlen = ipv6_optlen(hp);
/* set the flag */
switch (nexthdr){
......@@ -100,7 +101,7 @@ ipv6header_match(const struct sk_buff *skb,
break;
}
nexthdr = hdr->nexthdr;
nexthdr = hp->nexthdr;
len -= hdrlen;
ptr += hdrlen;
if (ptr > skb->len)
......@@ -111,10 +112,14 @@ ipv6header_match(const struct sk_buff *skb,
temp |= MASK_PROTO;
if (info->modeflag)
return (!( (temp & info->matchflags)
^ info->matchflags) ^ info->invflags);
else
return (!( temp ^ info->matchflags) ^ info->invflags);
return !((temp ^ info->matchflags ^ info->invflags)
& info->matchflags);
else {
if (info->invflags)
return temp != info->matchflags;
else
return temp == info->matchflags;
}
}
static int
......@@ -124,11 +129,18 @@ ipv6header_checkentry(const char *tablename,
unsigned int matchsize,
unsigned int hook_mask)
{
const struct ip6t_ipv6header_info *info = matchinfo;
/* Check for obvious errors */
/* This match is valid in all hooks! */
if (matchsize != IP6T_ALIGN(sizeof(struct ip6t_ipv6header_info)))
return 0;
/* invflags is 0 or 0xff in hard mode */
if ((!info->modeflag) && info->invflags != 0x00
&& info->invflags != 0xFF)
return 0;
return 1;
}
......
......@@ -79,7 +79,7 @@ static int xfrm6_tunnel_check_size(struct sk_buff *skb)
int mtu, ret = 0;
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)
mtu = IPV6_MIN_MTU;
......
......@@ -471,9 +471,16 @@ static int netlink_bind(struct socket *sock, struct sockaddr *addr, int addr_len
return err;
}
nlk->groups = nladdr->nl_groups;
if (nladdr->nl_groups)
if (!nladdr->nl_groups && !nlk->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);
nlk->groups = nladdr->nl_groups;
netlink_table_ungrab();
return 0;
}
......
......@@ -78,7 +78,10 @@
#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. */
void sctp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
......@@ -983,7 +986,7 @@ int sctp_v6_init(void)
sctp_register_af(&sctp_ipv6_specific);
/* Register notifier for inet6 address additions/deletions. */
register_inet6addr_notifier(&sctp_inetaddr_notifier);
register_inet6addr_notifier(&sctp_inet6addr_notifier);
rc = 0;
out:
return rc;
......@@ -999,6 +1002,6 @@ void sctp_v6_exit(void)
inet6_del_protocol(&sctpv6_protocol, IPPROTO_SCTP);
inet6_unregister_protosw(&sctpv6_seqpacket_protosw);
inet6_unregister_protosw(&sctpv6_stream_protosw);
unregister_inet6addr_notifier(&sctp_inetaddr_notifier);
unregister_inet6addr_notifier(&sctp_inet6addr_notifier);
sk_free_slab(&sctpv6_prot);
}
......@@ -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.
* 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,
void *ptr)
int sctp_inetaddr_event(struct notifier_block *this, unsigned long ev,
void *ptr)
{
unsigned long flags;
......@@ -824,7 +824,7 @@ static struct sctp_pf sctp_pf_inet = {
};
/* Notifier for inetaddr addition/deletion events. */
struct notifier_block sctp_inetaddr_notifier = {
static struct notifier_block sctp_inetaddr_notifier = {
.notifier_call = sctp_inetaddr_event,
};
......
......@@ -1535,9 +1535,11 @@ static int unix_dgram_recvmsg(struct kiocb *iocb, struct socket *sock,
msg->msg_namelen = 0;
down(&u->readsem);
skb = skb_recv_datagram(sk, flags, noblock, &err);
if (!skb)
goto out;
goto out_unlock;
wake_up_interruptible(&u->peer_wait);
......@@ -1587,6 +1589,8 @@ static int unix_dgram_recvmsg(struct kiocb *iocb, struct socket *sock,
out_free:
skb_free_datagram(sk,skb);
out_unlock:
up(&u->readsem);
out:
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