summaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@woody.linux-foundation.org>2008-02-15 07:33:07 -0800
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2008-02-15 07:33:07 -0800
commitf6866fecd6fd8e44a6715da09844a4fd1b8484da (patch)
treea166c399ddb37a48035589ffda29ef05d236c4b4 /net
parent4ee29f6a52158cea526b16a44ae38643946103ec (diff)
parent997b37da1515c1620692521786a74af271664eb7 (diff)
downloadlinux-f6866fecd6fd8e44a6715da09844a4fd1b8484da.tar.gz
linux-f6866fecd6fd8e44a6715da09844a4fd1b8484da.tar.bz2
linux-f6866fecd6fd8e44a6715da09844a4fd1b8484da.zip
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6: (82 commits) [NET]: Make sure sockets implement splice_read netconsole: avoid null pointer dereference at show_local_mac() [IPV6]: Fix reversed local_df test in ip6_fragment [XFRM]: Avoid bogus BUG() when throwing new policy away. [AF_KEY]: Fix bug in spdadd [NETFILTER] nf_conntrack_proto_tcp.c: Mistyped state corrected. net: xfrm statistics depend on INET [NETFILTER]: make secmark_tg_destroy() static [INET]: Unexport inet_listen_wlock [INET]: Unexport __inet_hash_connect [NET]: Improve cache line coherency of ingress qdisc [NET]: Fix race in dev_close(). (Bug 9750) [IPSEC]: Fix bogus usage of u64 on input sequence number [RTNETLINK]: Send a single notification on device state changes. [NETLABLE]: Hide netlbl_unlabel_audit_addr6 under ifdef CONFIG_IPV6. [NETLABEL]: Don't produce unused variables when IPv6 is off. [NETLABEL]: Compilation for CONFIG_AUDIT=n case. [GENETLINK]: Relax dances with genl_lock. [NETLABEL]: Fix lookup logic of netlbl_domhsh_search_def. [IPV6]: remove unused method declaration (net/ndisc.h). ...
Diffstat (limited to 'net')
-rw-r--r--net/ax25/af_ax25.c12
-rw-r--r--net/ax25/ax25_dev.c2
-rw-r--r--net/ax25/ax25_ds_timer.c12
-rw-r--r--net/ax25/ax25_route.c28
-rw-r--r--net/ax25/ax25_timer.c60
-rw-r--r--net/core/dev.c4
-rw-r--r--net/core/neighbour.c12
-rw-r--r--net/core/rtnetlink.c36
-rw-r--r--net/core/skbuff.c3
-rw-r--r--net/ipv4/ah4.c2
-rw-r--r--net/ipv4/arp.c3
-rw-r--r--net/ipv4/esp4.c5
-rw-r--r--net/ipv4/fib_trie.c99
-rw-r--r--net/ipv4/inet_hashtables.c3
-rw-r--r--net/ipv4/ip_sockglue.c5
-rw-r--r--net/ipv6/ah6.c2
-rw-r--r--net/ipv6/esp6.c5
-rw-r--r--net/ipv6/ip6_output.c6
-rw-r--r--net/ipv6/xfrm6_output.c2
-rw-r--r--net/key/af_key.c1
-rw-r--r--net/netfilter/nf_conntrack_proto_tcp.c2
-rw-r--r--net/netfilter/xt_SECMARK.c2
-rw-r--r--net/netlabel/netlabel_domainhash.c6
-rw-r--r--net/netlabel/netlabel_unlabeled.c30
-rw-r--r--net/netlabel/netlabel_user.c3
-rw-r--r--net/netlink/genetlink.c6
-rw-r--r--net/socket.c3
-rw-r--r--net/xfrm/Kconfig2
-rw-r--r--net/xfrm/xfrm_input.c4
-rw-r--r--net/xfrm/xfrm_output.c2
-rw-r--r--net/xfrm/xfrm_user.c1
31 files changed, 210 insertions, 153 deletions
diff --git a/net/ax25/af_ax25.c b/net/ax25/af_ax25.c
index 8fc64e3150a2..48bfcc741f25 100644
--- a/net/ax25/af_ax25.c
+++ b/net/ax25/af_ax25.c
@@ -510,11 +510,7 @@ ax25_cb *ax25_create_cb(void)
skb_queue_head_init(&ax25->ack_queue);
skb_queue_head_init(&ax25->reseq_queue);
- init_timer(&ax25->timer);
- init_timer(&ax25->t1timer);
- init_timer(&ax25->t2timer);
- init_timer(&ax25->t3timer);
- init_timer(&ax25->idletimer);
+ ax25_setup_timers(ax25);
ax25_fillin_cb(ax25, NULL);
@@ -1928,12 +1924,10 @@ static int ax25_info_show(struct seq_file *seq, void *v)
ax25->paclen);
if (ax25->sk != NULL) {
- bh_lock_sock(ax25->sk);
- seq_printf(seq," %d %d %ld\n",
+ seq_printf(seq, " %d %d %lu\n",
atomic_read(&ax25->sk->sk_wmem_alloc),
atomic_read(&ax25->sk->sk_rmem_alloc),
- ax25->sk->sk_socket != NULL ? SOCK_INODE(ax25->sk->sk_socket)->i_ino : 0L);
- bh_unlock_sock(ax25->sk);
+ sock_i_ino(ax25->sk));
} else {
seq_puts(seq, " * * *\n");
}
diff --git a/net/ax25/ax25_dev.c b/net/ax25/ax25_dev.c
index 528c874d9828..a7a0e0c9698b 100644
--- a/net/ax25/ax25_dev.c
+++ b/net/ax25/ax25_dev.c
@@ -82,7 +82,7 @@ void ax25_dev_device_up(struct net_device *dev)
ax25_dev->values[AX25_VALUES_DS_TIMEOUT]= AX25_DEF_DS_TIMEOUT;
#if defined(CONFIG_AX25_DAMA_SLAVE) || defined(CONFIG_AX25_DAMA_MASTER)
- init_timer(&ax25_dev->dama.slave_timer);
+ ax25_ds_setup_timer(ax25_dev);
#endif
spin_lock_bh(&ax25_dev_lock);
diff --git a/net/ax25/ax25_ds_timer.c b/net/ax25/ax25_ds_timer.c
index c4e3b025d21c..2ce79df00680 100644
--- a/net/ax25/ax25_ds_timer.c
+++ b/net/ax25/ax25_ds_timer.c
@@ -40,13 +40,10 @@ static void ax25_ds_timeout(unsigned long);
* 1/10th of a second.
*/
-static void ax25_ds_add_timer(ax25_dev *ax25_dev)
+void ax25_ds_setup_timer(ax25_dev *ax25_dev)
{
- struct timer_list *t = &ax25_dev->dama.slave_timer;
- t->data = (unsigned long) ax25_dev;
- t->function = &ax25_ds_timeout;
- t->expires = jiffies + HZ;
- add_timer(t);
+ setup_timer(&ax25_dev->dama.slave_timer, ax25_ds_timeout,
+ (unsigned long)ax25_dev);
}
void ax25_ds_del_timer(ax25_dev *ax25_dev)
@@ -60,10 +57,9 @@ void ax25_ds_set_timer(ax25_dev *ax25_dev)
if (ax25_dev == NULL) /* paranoia */
return;
- del_timer(&ax25_dev->dama.slave_timer);
ax25_dev->dama.slave_timeout =
msecs_to_jiffies(ax25_dev->values[AX25_VALUES_DS_TIMEOUT]) / 10;
- ax25_ds_add_timer(ax25_dev);
+ mod_timer(&ax25_dev->dama.slave_timer, jiffies + HZ);
}
/*
diff --git a/net/ax25/ax25_route.c b/net/ax25/ax25_route.c
index 38c7f3087ec3..8672cd84fdf9 100644
--- a/net/ax25/ax25_route.c
+++ b/net/ax25/ax25_route.c
@@ -45,7 +45,7 @@ void ax25_rt_device_down(struct net_device *dev)
{
ax25_route *s, *t, *ax25_rt;
- write_lock(&ax25_route_lock);
+ write_lock_bh(&ax25_route_lock);
ax25_rt = ax25_route_list;
while (ax25_rt != NULL) {
s = ax25_rt;
@@ -68,7 +68,7 @@ void ax25_rt_device_down(struct net_device *dev)
}
}
}
- write_unlock(&ax25_route_lock);
+ write_unlock_bh(&ax25_route_lock);
}
static int __must_check ax25_rt_add(struct ax25_routes_struct *route)
@@ -82,7 +82,7 @@ static int __must_check ax25_rt_add(struct ax25_routes_struct *route)
if (route->digi_count > AX25_MAX_DIGIS)
return -EINVAL;
- write_lock(&ax25_route_lock);
+ write_lock_bh(&ax25_route_lock);
ax25_rt = ax25_route_list;
while (ax25_rt != NULL) {
@@ -92,7 +92,7 @@ static int __must_check ax25_rt_add(struct ax25_routes_struct *route)
ax25_rt->digipeat = NULL;
if (route->digi_count != 0) {
if ((ax25_rt->digipeat = kmalloc(sizeof(ax25_digi), GFP_ATOMIC)) == NULL) {
- write_unlock(&ax25_route_lock);
+ write_unlock_bh(&ax25_route_lock);
return -ENOMEM;
}
ax25_rt->digipeat->lastrepeat = -1;
@@ -102,14 +102,14 @@ static int __must_check ax25_rt_add(struct ax25_routes_struct *route)
ax25_rt->digipeat->calls[i] = route->digi_addr[i];
}
}
- write_unlock(&ax25_route_lock);
+ write_unlock_bh(&ax25_route_lock);
return 0;
}
ax25_rt = ax25_rt->next;
}
if ((ax25_rt = kmalloc(sizeof(ax25_route), GFP_ATOMIC)) == NULL) {
- write_unlock(&ax25_route_lock);
+ write_unlock_bh(&ax25_route_lock);
return -ENOMEM;
}
@@ -120,7 +120,7 @@ static int __must_check ax25_rt_add(struct ax25_routes_struct *route)
ax25_rt->ip_mode = ' ';
if (route->digi_count != 0) {
if ((ax25_rt->digipeat = kmalloc(sizeof(ax25_digi), GFP_ATOMIC)) == NULL) {
- write_unlock(&ax25_route_lock);
+ write_unlock_bh(&ax25_route_lock);
kfree(ax25_rt);
return -ENOMEM;
}
@@ -133,7 +133,7 @@ static int __must_check ax25_rt_add(struct ax25_routes_struct *route)
}
ax25_rt->next = ax25_route_list;
ax25_route_list = ax25_rt;
- write_unlock(&ax25_route_lock);
+ write_unlock_bh(&ax25_route_lock);
return 0;
}
@@ -152,7 +152,7 @@ static int ax25_rt_del(struct ax25_routes_struct *route)
if ((ax25_dev = ax25_addr_ax25dev(&route->port_addr)) == NULL)
return -EINVAL;
- write_lock(&ax25_route_lock);
+ write_lock_bh(&ax25_route_lock);
ax25_rt = ax25_route_list;
while (ax25_rt != NULL) {
@@ -174,7 +174,7 @@ static int ax25_rt_del(struct ax25_routes_struct *route)
}
}
}
- write_unlock(&ax25_route_lock);
+ write_unlock_bh(&ax25_route_lock);
return 0;
}
@@ -188,7 +188,7 @@ static int ax25_rt_opt(struct ax25_route_opt_struct *rt_option)
if ((ax25_dev = ax25_addr_ax25dev(&rt_option->port_addr)) == NULL)
return -EINVAL;
- write_lock(&ax25_route_lock);
+ write_lock_bh(&ax25_route_lock);
ax25_rt = ax25_route_list;
while (ax25_rt != NULL) {
@@ -216,7 +216,7 @@ static int ax25_rt_opt(struct ax25_route_opt_struct *rt_option)
}
out:
- write_unlock(&ax25_route_lock);
+ write_unlock_bh(&ax25_route_lock);
return err;
}
@@ -492,7 +492,7 @@ void __exit ax25_rt_free(void)
{
ax25_route *s, *ax25_rt = ax25_route_list;
- write_lock(&ax25_route_lock);
+ write_lock_bh(&ax25_route_lock);
while (ax25_rt != NULL) {
s = ax25_rt;
ax25_rt = ax25_rt->next;
@@ -500,5 +500,5 @@ void __exit ax25_rt_free(void)
kfree(s->digipeat);
kfree(s);
}
- write_unlock(&ax25_route_lock);
+ write_unlock_bh(&ax25_route_lock);
}
diff --git a/net/ax25/ax25_timer.c b/net/ax25/ax25_timer.c
index 72594867fab6..db29ea71e80a 100644
--- a/net/ax25/ax25_timer.c
+++ b/net/ax25/ax25_timer.c
@@ -40,63 +40,45 @@ static void ax25_t2timer_expiry(unsigned long);
static void ax25_t3timer_expiry(unsigned long);
static void ax25_idletimer_expiry(unsigned long);
-void ax25_start_heartbeat(ax25_cb *ax25)
+void ax25_setup_timers(ax25_cb *ax25)
{
- del_timer(&ax25->timer);
-
- ax25->timer.data = (unsigned long)ax25;
- ax25->timer.function = &ax25_heartbeat_expiry;
- ax25->timer.expires = jiffies + 5 * HZ;
+ setup_timer(&ax25->timer, ax25_heartbeat_expiry, (unsigned long)ax25);
+ setup_timer(&ax25->t1timer, ax25_t1timer_expiry, (unsigned long)ax25);
+ setup_timer(&ax25->t2timer, ax25_t2timer_expiry, (unsigned long)ax25);
+ setup_timer(&ax25->t3timer, ax25_t3timer_expiry, (unsigned long)ax25);
+ setup_timer(&ax25->idletimer, ax25_idletimer_expiry,
+ (unsigned long)ax25);
+}
- add_timer(&ax25->timer);
+void ax25_start_heartbeat(ax25_cb *ax25)
+{
+ mod_timer(&ax25->timer, jiffies + 5 * HZ);
}
void ax25_start_t1timer(ax25_cb *ax25)
{
- del_timer(&ax25->t1timer);
-
- ax25->t1timer.data = (unsigned long)ax25;
- ax25->t1timer.function = &ax25_t1timer_expiry;
- ax25->t1timer.expires = jiffies + ax25->t1;
-
- add_timer(&ax25->t1timer);
+ mod_timer(&ax25->t1timer, jiffies + ax25->t1);
}
void ax25_start_t2timer(ax25_cb *ax25)
{
- del_timer(&ax25->t2timer);
-
- ax25->t2timer.data = (unsigned long)ax25;
- ax25->t2timer.function = &ax25_t2timer_expiry;
- ax25->t2timer.expires = jiffies + ax25->t2;
-
- add_timer(&ax25->t2timer);
+ mod_timer(&ax25->t2timer, jiffies + ax25->t2);
}
void ax25_start_t3timer(ax25_cb *ax25)
{
- del_timer(&ax25->t3timer);
-
- if (ax25->t3 > 0) {
- ax25->t3timer.data = (unsigned long)ax25;
- ax25->t3timer.function = &ax25_t3timer_expiry;
- ax25->t3timer.expires = jiffies + ax25->t3;
-
- add_timer(&ax25->t3timer);
- }
+ if (ax25->t3 > 0)
+ mod_timer(&ax25->t3timer, jiffies + ax25->t3);
+ else
+ del_timer(&ax25->t3timer);
}
void ax25_start_idletimer(ax25_cb *ax25)
{
- del_timer(&ax25->idletimer);
-
- if (ax25->idle > 0) {
- ax25->idletimer.data = (unsigned long)ax25;
- ax25->idletimer.function = &ax25_idletimer_expiry;
- ax25->idletimer.expires = jiffies + ax25->idle;
-
- add_timer(&ax25->idletimer);
- }
+ if (ax25->idle > 0)
+ mod_timer(&ax25->idletimer, jiffies + ax25->idle);
+ else
+ del_timer(&ax25->idletimer);
}
void ax25_stop_heartbeat(ax25_cb *ax25)
diff --git a/net/core/dev.c b/net/core/dev.c
index b3e19ae57f95..908f07c3bd7d 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -1071,8 +1071,6 @@ int dev_close(struct net_device *dev)
*/
call_netdevice_notifiers(NETDEV_GOING_DOWN, dev);
- dev_deactivate(dev);
-
clear_bit(__LINK_STATE_START, &dev->state);
/* Synchronize to scheduled poll. We cannot touch poll list,
@@ -1083,6 +1081,8 @@ int dev_close(struct net_device *dev)
*/
smp_mb__after_clear_bit(); /* Commit netif_running(). */
+ dev_deactivate(dev);
+
/*
* Call the device specific close. This cannot fail.
* Only if device is UP
diff --git a/net/core/neighbour.c b/net/core/neighbour.c
index a16cf1ec5e5e..7bb6a9a1256d 100644
--- a/net/core/neighbour.c
+++ b/net/core/neighbour.c
@@ -834,18 +834,12 @@ static void neigh_timer_handler(unsigned long arg)
}
if (neigh->nud_state & (NUD_INCOMPLETE | NUD_PROBE)) {
struct sk_buff *skb = skb_peek(&neigh->arp_queue);
- /* keep skb alive even if arp_queue overflows */
- if (skb)
- skb_get(skb);
- write_unlock(&neigh->lock);
+
neigh->ops->solicit(neigh, skb);
atomic_inc(&neigh->probes);
- if (skb)
- kfree_skb(skb);
- } else {
-out:
- write_unlock(&neigh->lock);
}
+out:
+ write_unlock(&neigh->lock);
if (notify)
neigh_update_notify(neigh);
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
index 61ac8d06292c..ecb02afd52dc 100644
--- a/net/core/rtnetlink.c
+++ b/net/core/rtnetlink.c
@@ -504,7 +504,7 @@ int rtnl_put_cacheinfo(struct sk_buff *skb, struct dst_entry *dst, u32 id,
EXPORT_SYMBOL_GPL(rtnl_put_cacheinfo);
-static void set_operstate(struct net_device *dev, unsigned char transition)
+static int set_operstate(struct net_device *dev, unsigned char transition, bool send_notification)
{
unsigned char operstate = dev->operstate;
@@ -527,8 +527,12 @@ static void set_operstate(struct net_device *dev, unsigned char transition)
write_lock_bh(&dev_base_lock);
dev->operstate = operstate;
write_unlock_bh(&dev_base_lock);
- netdev_state_change(dev);
- }
+
+ if (send_notification)
+ netdev_state_change(dev);
+ return 1;
+ } else
+ return 0;
}
static void copy_rtnl_link_stats(struct rtnl_link_stats *a,
@@ -822,6 +826,7 @@ static int do_setlink(struct net_device *dev, struct ifinfomsg *ifm,
if (tb[IFLA_BROADCAST]) {
nla_memcpy(dev->broadcast, tb[IFLA_BROADCAST], dev->addr_len);
send_addr_notify = 1;
+ modified = 1;
}
if (ifm->ifi_flags || ifm->ifi_change) {
@@ -834,16 +839,23 @@ static int do_setlink(struct net_device *dev, struct ifinfomsg *ifm,
dev_change_flags(dev, flags);
}
- if (tb[IFLA_TXQLEN])
- dev->tx_queue_len = nla_get_u32(tb[IFLA_TXQLEN]);
+ if (tb[IFLA_TXQLEN]) {
+ if (dev->tx_queue_len != nla_get_u32(tb[IFLA_TXQLEN])) {
+ dev->tx_queue_len = nla_get_u32(tb[IFLA_TXQLEN]);
+ modified = 1;
+ }
+ }
if (tb[IFLA_OPERSTATE])
- set_operstate(dev, nla_get_u8(tb[IFLA_OPERSTATE]));
+ modified |= set_operstate(dev, nla_get_u8(tb[IFLA_OPERSTATE]), false);
if (tb[IFLA_LINKMODE]) {
- write_lock_bh(&dev_base_lock);
- dev->link_mode = nla_get_u8(tb[IFLA_LINKMODE]);
- write_unlock_bh(&dev_base_lock);
+ if (dev->link_mode != nla_get_u8(tb[IFLA_LINKMODE])) {
+ write_lock_bh(&dev_base_lock);
+ dev->link_mode = nla_get_u8(tb[IFLA_LINKMODE]);
+ write_lock_bh(&dev_base_lock);
+ modified = 1;
+ }
}
err = 0;
@@ -857,6 +869,10 @@ errout:
if (send_addr_notify)
call_netdevice_notifiers(NETDEV_CHANGEADDR, dev);
+
+ if (modified)
+ netdev_state_change(dev);
+
return err;
}
@@ -974,7 +990,7 @@ struct net_device *rtnl_create_link(struct net *net, char *ifname,
if (tb[IFLA_TXQLEN])
dev->tx_queue_len = nla_get_u32(tb[IFLA_TXQLEN]);
if (tb[IFLA_OPERSTATE])
- set_operstate(dev, nla_get_u8(tb[IFLA_OPERSTATE]));
+ set_operstate(dev, nla_get_u8(tb[IFLA_OPERSTATE]), true);
if (tb[IFLA_LINKMODE])
dev->link_mode = nla_get_u8(tb[IFLA_LINKMODE]);
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index cfc07dac636c..0d0fd28a9041 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -2106,11 +2106,10 @@ int skb_append_datato_frags(struct sock *sk, struct sk_buff *skb,
/**
* skb_pull_rcsum - pull skb and update receive checksum
* @skb: buffer to update
- * @start: start of data before pull
* @len: length of data pulled
*
* This function performs an skb_pull on the packet and updates
- * update the CHECKSUM_COMPLETE checksum. It should be used on
+ * the CHECKSUM_COMPLETE checksum. It should be used on
* receive path processing instead of skb_pull unless you know
* that the checksum difference is zero (e.g., a valid IP header)
* or you are setting ip_summed to CHECKSUM_NONE.
diff --git a/net/ipv4/ah4.c b/net/ipv4/ah4.c
index 9d4555ec0b59..8219b7e0968d 100644
--- a/net/ipv4/ah4.c
+++ b/net/ipv4/ah4.c
@@ -96,7 +96,7 @@ static int ah_output(struct xfrm_state *x, struct sk_buff *skb)
ah->reserved = 0;
ah->spi = x->id.spi;
- ah->seq_no = htonl(XFRM_SKB_CB(skb)->seq);
+ ah->seq_no = htonl(XFRM_SKB_CB(skb)->seq.output);
spin_lock_bh(&x->lock);
err = ah_mac_digest(ahp, skb, ah->auth_data);
diff --git a/net/ipv4/arp.c b/net/ipv4/arp.c
index 8e17f65f4002..c663fa5339ee 100644
--- a/net/ipv4/arp.c
+++ b/net/ipv4/arp.c
@@ -368,7 +368,6 @@ static void arp_solicit(struct neighbour *neigh, struct sk_buff *skb)
if (!(neigh->nud_state&NUD_VALID))
printk(KERN_DEBUG "trying to ucast probe in NUD_INVALID\n");
dst_ha = neigh->ha;
- read_lock_bh(&neigh->lock);
} else if ((probes -= neigh->parms->app_probes) < 0) {
#ifdef CONFIG_ARPD
neigh_app_ns(neigh);
@@ -378,8 +377,6 @@ static void arp_solicit(struct neighbour *neigh, struct sk_buff *skb)
arp_send(ARPOP_REQUEST, ETH_P_ARP, target, dev, saddr,
dst_ha, dev->dev_addr, NULL);
- if (dst_ha)
- read_unlock_bh(&neigh->lock);
}
static int arp_ignore(struct in_device *in_dev, __be32 sip, __be32 tip)
diff --git a/net/ipv4/esp4.c b/net/ipv4/esp4.c
index 258d17631b4b..091e6709f831 100644
--- a/net/ipv4/esp4.c
+++ b/net/ipv4/esp4.c
@@ -199,7 +199,7 @@ static int esp_output(struct xfrm_state *x, struct sk_buff *skb)
}
esph->spi = x->id.spi;
- esph->seq_no = htonl(XFRM_SKB_CB(skb)->seq);
+ esph->seq_no = htonl(XFRM_SKB_CB(skb)->seq.output);
sg_init_table(sg, nfrags);
skb_to_sgvec(skb, sg,
@@ -210,7 +210,8 @@ static int esp_output(struct xfrm_state *x, struct sk_buff *skb)
aead_givcrypt_set_callback(req, 0, esp_output_done, skb);
aead_givcrypt_set_crypt(req, sg, sg, clen, iv);
aead_givcrypt_set_assoc(req, asg, sizeof(*esph));
- aead_givcrypt_set_giv(req, esph->enc_data, XFRM_SKB_CB(skb)->seq);
+ aead_givcrypt_set_giv(req, esph->enc_data,
+ XFRM_SKB_CB(skb)->seq.output);
ESP_SKB_CB(skb)->tmp = tmp;
err = crypto_aead_givencrypt(req);
diff --git a/net/ipv4/fib_trie.c b/net/ipv4/fib_trie.c
index f5fba3f71c06..1ff446d0fa8b 100644
--- a/net/ipv4/fib_trie.c
+++ b/net/ipv4/fib_trie.c
@@ -1762,11 +1762,9 @@ static struct leaf *trie_leafindex(struct trie *t, int index)
{
struct leaf *l = trie_firstleaf(t);
- while (index-- > 0) {
+ while (l && index-- > 0)
l = trie_nextleaf(l);
- if (!l)
- break;
- }
+
return l;
}
@@ -2461,6 +2459,84 @@ static const struct file_operations fib_trie_fops = {
.release = seq_release_net,
};
+struct fib_route_iter {
+ struct seq_net_private p;
+ struct trie *main_trie;
+ loff_t pos;
+ t_key key;
+};
+
+static struct leaf *fib_route_get_idx(struct fib_route_iter *iter, loff_t pos)
+{
+ struct leaf *l = NULL;
+ struct trie *t = iter->main_trie;
+
+ /* use cache location of last found key */
+ if (iter->pos > 0 && pos >= iter->pos && (l = fib_find_node(t, iter->key)))
+ pos -= iter->pos;
+ else {
+ iter->pos = 0;
+ l = trie_firstleaf(t);
+ }
+
+ while (l && pos-- > 0) {
+ iter->pos++;
+ l = trie_nextleaf(l);
+ }
+
+ if (l)
+ iter->key = pos; /* remember it */
+ else
+ iter->pos = 0; /* forget it */
+
+ return l;
+}
+
+static void *fib_route_seq_start(struct seq_file *seq, loff_t *pos)
+ __acquires(RCU)
+{
+ struct fib_route_iter *iter = seq->private;
+ struct fib_table *tb;
+
+ rcu_read_lock();
+ tb = fib_get_table(iter->p.net, RT_TABLE_MAIN);
+ if (!tb)
+ return NULL;
+
+ iter->main_trie = (struct trie *) tb->tb_data;
+ if (*pos == 0)
+ return SEQ_START_TOKEN;
+ else
+ return fib_route_get_idx(iter, *pos - 1);
+}
+
+static void *fib_route_seq_next(struct seq_file *seq, void *v, loff_t *pos)
+{
+ struct fib_route_iter *iter = seq->private;
+ struct leaf *l = v;
+
+ ++*pos;
+ if (v == SEQ_START_TOKEN) {
+ iter->pos = 0;
+ l = trie_firstleaf(iter->main_trie);
+ } else {
+ iter->pos++;
+ l = trie_nextleaf(l);
+ }
+
+ if (l)
+ iter->key = l->key;
+ else
+ iter->pos = 0;
+ return l;
+}
+
+static void fib_route_seq_stop(struct seq_file *seq, void *v)
+ __releases(RCU)
+{
+ rcu_read_unlock();
+}
+
static unsigned fib_flag_trans(int type, __be32 mask, const struct fib_info *fi)
{
static unsigned type2flags[RTN_MAX + 1] = {
@@ -2484,7 +2560,6 @@ static unsigned fib_flag_trans(int type, __be32 mask, const struct fib_info *fi)
*/
static int fib_route_seq_show(struct seq_file *seq, void *v)
{
- const struct fib_trie_iter *iter = seq->private;
struct leaf *l = v;
struct leaf_info *li;
struct hlist_node *node;
@@ -2496,12 +2571,6 @@ static int fib_route_seq_show(struct seq_file *seq, void *v)
return 0;
}
- if (iter->trie == iter->trie_local)
- return 0;
-
- if (IS_TNODE(l))
- return 0;
-
hlist_for_each_entry_rcu(li, node, &l->list, hlist) {
struct fib_alias *fa;
__be32 mask, prefix;
@@ -2544,16 +2613,16 @@ static int fib_route_seq_show(struct seq_file *seq, void *v)
}
static const struct seq_operations fib_route_seq_ops = {
- .start = fib_trie_seq_start,
- .next = fib_trie_seq_next,
- .stop = fib_trie_seq_stop,
+ .start = fib_route_seq_start,
+ .next = fib_route_seq_next,
+ .stop = fib_route_seq_stop,
.show = fib_route_seq_show,
};
static int fib_route_seq_open(struct inode *inode, struct file *file)
{
return seq_open_net(inode, file, &fib_route_seq_ops,
- sizeof(struct fib_trie_iter));
+ sizeof(struct fib_route_iter));
}
static const struct file_operations fib_route_fops = {
diff --git a/net/ipv4/inet_hashtables.c b/net/ipv4/inet_hashtables.c
index 9cac6c034abd..1aba606f6bbb 100644
--- a/net/ipv4/inet_hashtables.c
+++ b/net/ipv4/inet_hashtables.c
@@ -120,8 +120,6 @@ void inet_listen_wlock(struct inet_hashinfo *hashinfo)
}
}
-EXPORT_SYMBOL(inet_listen_wlock);
-
/*
* Don't inline this cruft. Here are some nice properties to exploit here. The
* BSD API does not allow a listening sock to specify the remote port nor the
@@ -494,7 +492,6 @@ out:
return ret;
}
}
-EXPORT_SYMBOL_GPL(__inet_hash_connect);
/*
* Bind a port for a connect operation and hash it.
diff --git a/net/ipv4/ip_sockglue.c b/net/ipv4/ip_sockglue.c
index 754b0a5bbfe9..de0572c88859 100644
--- a/net/ipv4/ip_sockglue.c
+++ b/net/ipv4/ip_sockglue.c
@@ -514,11 +514,6 @@ static int do_ip_setsockopt(struct sock *sk, int level,
val &= ~3;
val |= inet->tos & 3;
}
- if (IPTOS_PREC(val) >= IPTOS_PREC_CRITIC_ECP &&
- !capable(CAP_NET_ADMIN)) {
- err = -EPERM;
- break;
- }
if (inet->tos != val) {
inet->tos = val;
sk->sk_priority = rt_tos2priority(val);
diff --git a/net/ipv6/ah6.c b/net/ipv6/ah6.c
index 379c8e04c36c..2ff0c8233e47 100644
--- a/net/ipv6/ah6.c
+++ b/net/ipv6/ah6.c
@@ -283,7 +283,7 @@ static int ah6_output(struct xfrm_state *x, struct sk_buff *skb)
ah->reserved = 0;
ah->spi = x->id.spi;
- ah->seq_no = htonl(XFRM_SKB_CB(skb)->seq);
+ ah->seq_no = htonl(XFRM_SKB_CB(skb)->seq.output);
spin_lock_bh(&x->lock);
err = ah_mac_digest(ahp, skb, ah->auth_data);
diff --git a/net/ipv6/esp6.c b/net/ipv6/esp6.c
index 8e0f1428c716..0ec1402320ea 100644
--- a/net/ipv6/esp6.c
+++ b/net/ipv6/esp6.c
@@ -188,7 +188,7 @@ static int esp6_output(struct xfrm_state *x, struct sk_buff *skb)
*skb_mac_header(skb) = IPPROTO_ESP;
esph->spi = x->id.spi;
- esph->seq_no = htonl(XFRM_SKB_CB(skb)->seq);
+ esph->seq_no = htonl(XFRM_SKB_CB(skb)->seq.output);
sg_init_table(sg, nfrags);
skb_to_sgvec(skb, sg,
@@ -199,7 +199,8 @@ static int esp6_output(struct xfrm_state *x, struct sk_buff *skb)
aead_givcrypt_set_callback(req, 0, esp_output_done, skb);
aead_givcrypt_set_crypt(req, sg, sg, clen, iv);
aead_givcrypt_set_assoc(req, asg, sizeof(*esph));
- aead_givcrypt_set_giv(req, esph->enc_data, XFRM_SKB_CB(skb)->seq);
+ aead_givcrypt_set_giv(req, esph->enc_data,
+ XFRM_SKB_CB(skb)->seq.output);
ESP_SKB_CB(skb)->tmp = tmp;
err = crypto_aead_givencrypt(req);
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
index 9ac6ca2521c3..8b67ca07467d 100644
--- a/net/ipv6/ip6_output.c
+++ b/net/ipv6/ip6_output.c
@@ -621,7 +621,7 @@ static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *))
* or if the skb it not generated by a local socket. (This last
* check should be redundant, but it's free.)
*/
- if (!np || np->pmtudisc >= IPV6_PMTUDISC_DO) {
+ if (!skb->local_df) {
skb->dev = skb->dst->dev;
icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu, skb->dev);
IP6_INC_STATS(ip6_dst_idev(skb->dst), IPSTATS_MIB_FRAGFAILS);
@@ -1420,6 +1420,10 @@ int ip6_push_pending_frames(struct sock *sk)
tmp_skb->sk = NULL;
}
+ /* Allow local fragmentation. */
+ if (np->pmtudisc < IPV6_PMTUDISC_DO)
+ skb->local_df = 1;
+
ipv6_addr_copy(final_dst, &fl->fl6_dst);
__skb_pull(skb, skb_network_header_len(skb));
if (opt && opt->opt_flen)
diff --git a/net/ipv6/xfrm6_output.c b/net/ipv6/xfrm6_output.c
index b34c58c65656..79ccfb080733 100644
--- a/net/ipv6/xfrm6_output.c
+++ b/net/ipv6/xfrm6_output.c
@@ -36,7 +36,7 @@ static int xfrm6_tunnel_check_size(struct sk_buff *skb)
if (mtu < IPV6_MIN_MTU)
mtu = IPV6_MIN_MTU;
- if (skb->len > mtu) {
+ if (!skb->local_df && skb->len > mtu) {
skb->dev = dst->dev;
icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu, skb->dev);
ret = -EMSGSIZE;
diff --git a/net/key/af_key.c b/net/key/af_key.c
index b3ac85e808ac..1c853927810a 100644
--- a/net/key/af_key.c
+++ b/net/key/af_key.c
@@ -2291,6 +2291,7 @@ static int pfkey_spdadd(struct sock *sk, struct sk_buff *skb, struct sadb_msg *h
return 0;
out:
+ xp->dead = 1;
xfrm_policy_destroy(xp);
return err;
}
diff --git a/net/netfilter/nf_conntrack_proto_tcp.c b/net/netfilter/nf_conntrack_proto_tcp.c
index 202d7fa09483..62567959b66e 100644
--- a/net/netfilter/nf_conntrack_proto_tcp.c
+++ b/net/netfilter/nf_conntrack_proto_tcp.c
@@ -945,7 +945,7 @@ static int tcp_packet(struct nf_conn *ct,
ct->proto.tcp.state = new_state;
if (old_state != new_state
- && new_state == TCP_CONNTRACK_CLOSE)
+ && new_state == TCP_CONNTRACK_FIN_WAIT)
ct->proto.tcp.seen[dir].flags |= IP_CT_TCP_FLAG_CLOSE_INIT;
timeout = ct->proto.tcp.retrans >= nf_ct_tcp_max_retrans
&& tcp_timeouts[new_state] > nf_ct_tcp_timeout_max_retrans
diff --git a/net/netfilter/xt_SECMARK.c b/net/netfilter/xt_SECMARK.c
index 7708e2084ce2..c0284856ccd4 100644
--- a/net/netfilter/xt_SECMARK.c
+++ b/net/netfilter/xt_SECMARK.c
@@ -111,7 +111,7 @@ secmark_tg_check(const char *tablename, const void *entry,
return true;
}
-void secmark_tg_destroy(const struct xt_target *target, void *targinfo)
+static void secmark_tg_destroy(const struct xt_target *target, void *targinfo)
{
switch (mode) {
case SECMARK_MODE_SEL:
diff --git a/net/netlabel/netlabel_domainhash.c b/net/netlabel/netlabel_domainhash.c
index 9a8ea0195c4f..fd462313471c 100644
--- a/net/netlabel/netlabel_domainhash.c
+++ b/net/netlabel/netlabel_domainhash.c
@@ -150,11 +150,11 @@ static struct netlbl_dom_map *netlbl_domhsh_search_def(const char *domain)
entry = netlbl_domhsh_search(domain);
if (entry == NULL) {
entry = rcu_dereference(netlbl_domhsh_def);
- if (entry != NULL && entry->valid)
- return entry;
+ if (entry != NULL && !entry->valid)
+ entry = NULL;
}
- return NULL;
+ return entry;
}
/*
diff --git a/net/netlabel/netlabel_unlabeled.c b/net/netlabel/netlabel_unlabeled.c
index 42e81fd8cc49..3e745b72fded 100644
--- a/net/netlabel/netlabel_unlabeled.c
+++ b/net/netlabel/netlabel_unlabeled.c
@@ -180,6 +180,7 @@ static void netlbl_unlabel_audit_addr4(struct audit_buffer *audit_buf,
}
}
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
/**
* netlbl_unlabel_audit_addr6 - Audit an IPv6 address
* @audit_buf: audit buffer
@@ -213,6 +214,7 @@ static void netlbl_unlabel_audit_addr6(struct audit_buffer *audit_buf,
audit_log_format(audit_buf, " src_prefixlen=%d", mask_len);
}
}
+#endif /* IPv6 */
/*
* Unlabeled Connection Hash Table Functions
@@ -617,8 +619,6 @@ static int netlbl_unlhsh_add(struct net *net,
int ifindex;
struct net_device *dev;
struct netlbl_unlhsh_iface *iface;
- struct in_addr *addr4, *mask4;
- struct in6_addr *addr6, *mask6;
struct audit_buffer *audit_buf = NULL;
char *secctx = NULL;
u32 secctx_len;
@@ -651,7 +651,9 @@ static int netlbl_unlhsh_add(struct net *net,
audit_buf = netlbl_audit_start_common(AUDIT_MAC_UNLBL_STCADD,
audit_info);
switch (addr_len) {
- case sizeof(struct in_addr):
+ case sizeof(struct in_addr): {
+ struct in_addr *addr4, *mask4;
+
addr4 = (struct in_addr *)addr;
mask4 = (struct in_addr *)mask;
ret_val = netlbl_unlhsh_add_addr4(iface, addr4, mask4, secid);
@@ -661,8 +663,11 @@ static int netlbl_unlhsh_add(struct net *net,
addr4->s_addr,
mask4->s_addr);
break;
+ }
#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
- case sizeof(struct in6_addr):
+ case sizeof(struct in6_addr): {
+ struct in6_addr *addr6, *mask6;
+
addr6 = (struct in6_addr *)addr;
mask6 = (struct in6_addr *)mask;
ret_val = netlbl_unlhsh_add_addr6(iface, addr6, mask6, secid);
@@ -671,6 +676,7 @@ static int netlbl_unlhsh_add(struct net *net,
dev_name,
addr6, mask6);
break;
+ }
#endif /* IPv6 */
default:
ret_val = -EINVAL;
@@ -1741,10 +1747,6 @@ int netlbl_unlabel_getattr(const struct sk_buff *skb,
u16 family,
struct netlbl_lsm_secattr *secattr)
{
- struct iphdr *hdr4;
- struct ipv6hdr *hdr6;
- struct netlbl_unlhsh_addr4 *addr4;
- struct netlbl_unlhsh_addr6 *addr6;
struct netlbl_unlhsh_iface *iface;
rcu_read_lock();
@@ -1752,21 +1754,29 @@ int netlbl_unlabel_getattr(const struct sk_buff *skb,
if (iface == NULL)
goto unlabel_getattr_nolabel;
switch (family) {
- case PF_INET:
+ case PF_INET: {
+ struct iphdr *hdr4;
+ struct netlbl_unlhsh_addr4 *addr4;
+
hdr4 = ip_hdr(skb);
addr4 = netlbl_unlhsh_search_addr4(hdr4->saddr, iface);
if (addr4 == NULL)
goto unlabel_getattr_nolabel;
secattr->attr.secid = addr4->secid;
break;
+ }
#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
- case PF_INET6:
+ case PF_INET6: {
+ struct ipv6hdr *hdr6;
+ struct netlbl_unlhsh_addr6 *addr6;
+
hdr6 = ipv6_hdr(skb);
addr6 = netlbl_unlhsh_search_addr6(&hdr6->saddr, iface);
if (addr6 == NULL)
goto unlabel_getattr_nolabel;
secattr->attr.secid = addr6->secid;
break;
+ }
#endif /* IPv6 */
default:
goto unlabel_getattr_nolabel;
diff --git a/net/netlabel/netlabel_user.c b/net/netlabel/netlabel_user.c
index 85a96a3fddaa..023fc8fe840d 100644
--- a/net/netlabel/netlabel_user.c
+++ b/net/netlabel/netlabel_user.c
@@ -96,7 +96,6 @@ int netlbl_netlink_init(void)
struct audit_buffer *netlbl_audit_start_common(int type,
struct netlbl_audit *audit_info)
{
- struct audit_context *audit_ctx = current->audit_context;
struct audit_buffer *audit_buf;
char *secctx;
u32 secctx_len;
@@ -104,7 +103,7 @@ struct audit_buffer *netlbl_audit_start_common(int type,
if (audit_enabled == 0)
return NULL;
- audit_buf = audit_log_start(audit_ctx, GFP_ATOMIC, type);
+ audit_buf = audit_log_start(current->audit_context, GFP_ATOMIC, type);
if (audit_buf == NULL)
return NULL;
diff --git a/net/netlink/genetlink.c b/net/netlink/genetlink.c
index 150579a21469..d16929c9b4bc 100644
--- a/net/netlink/genetlink.c
+++ b/net/netlink/genetlink.c
@@ -230,10 +230,8 @@ static void genl_unregister_mc_groups(struct genl_family *family)
{
struct genl_multicast_group *grp, *tmp;
- genl_lock();
list_for_each_entry_safe(grp, tmp, &family->mcast_groups, list)
__genl_unregister_mc_group(family, grp);
- genl_unlock();
}
/**
@@ -396,10 +394,10 @@ int genl_unregister_family(struct genl_family *family)
{
struct genl_family *rc;
- genl_unregister_mc_groups(family);
-
genl_lock();
+ genl_unregister_mc_groups(family);
+
list_for_each_entry(rc, genl_family_chain(family->id), family_list) {
if (family->id != rc->id || strcmp(rc->name, family->name))
continue;
diff --git a/net/socket.c b/net/socket.c
index 7651de008502..b6d35cd72a50 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -701,6 +701,9 @@ static ssize_t sock_splice_read(struct file *file, loff_t *ppos,
{
struct socket *sock = file->private_data;
+ if (unlikely(!sock->ops->splice_read))
+ return -EINVAL;
+
return sock->ops->splice_read(sock, ppos, pipe, len, flags);
}
diff --git a/net/xfrm/Kconfig b/net/xfrm/Kconfig
index 8f9dbec319be..9201ef8ad90e 100644
--- a/net/xfrm/Kconfig
+++ b/net/xfrm/Kconfig
@@ -38,7 +38,7 @@ config XFRM_MIGRATE
config XFRM_STATISTICS
bool "Transformation statistics (EXPERIMENTAL)"
- depends on XFRM && PROC_FS && EXPERIMENTAL
+ depends on INET && XFRM && PROC_FS && EXPERIMENTAL
---help---
This statistics is not a SNMP/MIB specification but shows
statistics about transformation error (or almost error) factor
diff --git a/net/xfrm/xfrm_input.c b/net/xfrm/xfrm_input.c
index 4d6ebc633a94..62188c6a06dd 100644
--- a/net/xfrm/xfrm_input.c
+++ b/net/xfrm/xfrm_input.c
@@ -109,7 +109,7 @@ int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type)
if (encap_type < 0) {
async = 1;
x = xfrm_input_state(skb);
- seq = XFRM_SKB_CB(skb)->seq;
+ seq = XFRM_SKB_CB(skb)->seq.input;
goto resume;
}
@@ -175,7 +175,7 @@ int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type)
spin_unlock(&x->lock);
- XFRM_SKB_CB(skb)->seq = seq;
+ XFRM_SKB_CB(skb)->seq.input = seq;
nexthdr = x->type->input(x, skb);
diff --git a/net/xfrm/xfrm_output.c b/net/xfrm/xfrm_output.c
index fc690368325f..569d377932c4 100644
--- a/net/xfrm/xfrm_output.c
+++ b/net/xfrm/xfrm_output.c
@@ -62,7 +62,7 @@ static int xfrm_output_one(struct sk_buff *skb, int err)
}
if (x->type->flags & XFRM_TYPE_REPLAY_PROT) {
- XFRM_SKB_CB(skb)->seq = ++x->replay.oseq;
+ XFRM_SKB_CB(skb)->seq.output = ++x->replay.oseq;
if (unlikely(x->replay.oseq == 0)) {
XFRM_INC_STATS(LINUX_MIB_XFRMOUTSTATESEQERROR);
x->replay.oseq--;
diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c
index 78338079b7f5..f971ca5645f8 100644
--- a/net/xfrm/xfrm_user.c
+++ b/net/xfrm/xfrm_user.c
@@ -1105,6 +1105,7 @@ static struct xfrm_policy *xfrm_policy_construct(struct xfrm_userpolicy_info *p,
return xp;
error:
*errp = err;
+ xp->dead = 1;
xfrm_policy_destroy(xp);
return NULL;
}