aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
Diffstat (limited to 'net')
-rw-r--r--net/8021q/vlan_dev.c4
-rw-r--r--net/9p/trans_fd.c4
-rw-r--r--net/atm/clip.c19
-rw-r--r--net/atm/lec.c4
-rw-r--r--net/ax25/TODO4
-rw-r--r--net/bluetooth/bnep/bnep.h2
-rw-r--r--net/bluetooth/bnep/sock.c4
-rw-r--r--net/bluetooth/hci_core.c4
-rw-r--r--net/bluetooth/hci_sock.c4
-rw-r--r--net/bridge/br_fdb.c2
-rw-r--r--net/core/dev.c4
-rw-r--r--net/core/neighbour.c23
-rw-r--r--net/core/netpoll.c6
-rw-r--r--net/core/sock.c4
-rw-r--r--net/ipv4/af_inet.c2
-rw-r--r--net/ipv4/esp4.c2
-rw-r--r--net/ipv4/fib_trie.c7
-rw-r--r--net/ipv4/icmp.c6
-rw-r--r--net/ipv4/ip_fragment.c2
-rw-r--r--net/ipv4/ip_sockglue.c2
-rw-r--r--net/ipv4/ipconfig.c9
-rw-r--r--net/ipv4/netfilter/ipt_recent.c2
-rw-r--r--net/ipv4/tcp.c4
-rw-r--r--net/ipv4/tcp_output.c14
-rw-r--r--net/ipv4/xfrm4_mode_beet.c11
-rw-r--r--net/ipv4/xfrm4_mode_tunnel.c2
-rw-r--r--net/ipv4/xfrm4_output.c2
-rw-r--r--net/ipv4/xfrm4_state.c2
-rw-r--r--net/ipv6/Kconfig5
-rw-r--r--net/ipv6/ndisc.c24
-rw-r--r--net/ipv6/xfrm6_mode_beet.c1
-rw-r--r--net/ipv6/xfrm6_mode_tunnel.c2
-rw-r--r--net/ipv6/xfrm6_output.c2
-rw-r--r--net/ipv6/xfrm6_state.c2
-rw-r--r--net/irda/irnet/irnet.h2
-rw-r--r--net/key/af_key.c2
-rw-r--r--net/netfilter/nf_conntrack_expect.c2
-rw-r--r--net/netfilter/nf_conntrack_extend.c19
-rw-r--r--net/netfilter/nf_conntrack_h323_main.c2
-rw-r--r--net/netfilter/nf_queue.c2
-rw-r--r--net/netfilter/nfnetlink_log.c32
-rw-r--r--net/netfilter/nfnetlink_queue.c17
-rw-r--r--net/netfilter/xt_time.c7
-rw-r--r--net/rxrpc/ar-internal.h2
-rw-r--r--net/rxrpc/ar-recvmsg.c3
-rw-r--r--net/rxrpc/rxkad.c27
-rw-r--r--net/sched/cls_u32.c8
-rw-r--r--net/sched/em_u32.c2
-rw-r--r--net/sched/sch_htb.c13
-rw-r--r--net/sctp/bind_addr.c4
-rw-r--r--net/sctp/input.c2
-rw-r--r--net/sctp/ipv6.c36
-rw-r--r--net/sctp/protocol.c143
-rw-r--r--net/sctp/sm_make_chunk.c8
-rw-r--r--net/sctp/socket.c73
-rw-r--r--net/socket.c7
-rw-r--r--net/sunrpc/auth_gss/gss_mech_switch.c2
-rw-r--r--net/sunrpc/svc_xprt.c2
-rw-r--r--net/sunrpc/xprtrdma/svc_rdma_recvfrom.c23
-rw-r--r--net/sunrpc/xprtrdma/svc_rdma_sendto.c2
-rw-r--r--net/sunrpc/xprtrdma/svc_rdma_transport.c96
-rw-r--r--net/xfrm/xfrm_input.c22
-rw-r--r--net/xfrm/xfrm_output.c18
-rw-r--r--net/xfrm/xfrm_state.c54
-rw-r--r--net/xfrm/xfrm_user.c7
65 files changed, 539 insertions, 291 deletions
diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c
index 77f04e49a1a0..480ea90e7dcd 100644
--- a/net/8021q/vlan_dev.c
+++ b/net/8021q/vlan_dev.c
@@ -382,7 +382,7 @@ static int vlan_dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
vlan_dev_info(dev)->cnt_encap_on_xmit++;
pr_debug("%s: proto to encap: 0x%hx\n",
- __FUNCTION__, htons(veth->h_vlan_proto));
+ __FUNCTION__, ntohs(veth->h_vlan_proto));
/* Construct the second two bytes. This field looks something
* like:
* usr_priority: 3 bits (high bits)
@@ -660,7 +660,7 @@ static int vlan_dev_init(struct net_device *dev)
int subclass = 0;
/* IFF_BROADCAST|IFF_MULTICAST; ??? */
- dev->flags = real_dev->flags & ~IFF_UP;
+ dev->flags = real_dev->flags & ~(IFF_UP | IFF_PROMISC | IFF_ALLMULTI);
dev->iflink = real_dev->ifindex;
dev->state = (real_dev->state & ((1<<__LINK_STATE_NOCARRIER) |
(1<<__LINK_STATE_DORMANT))) |
diff --git a/net/9p/trans_fd.c b/net/9p/trans_fd.c
index 1aa9d5175398..f624dff76852 100644
--- a/net/9p/trans_fd.c
+++ b/net/9p/trans_fd.c
@@ -861,7 +861,6 @@ static void p9_mux_free_request(struct p9_conn *m, struct p9_req *req)
static void p9_mux_flush_cb(struct p9_req *freq, void *a)
{
- p9_conn_req_callback cb;
int tag;
struct p9_conn *m;
struct p9_req *req, *rreq, *rptr;
@@ -872,7 +871,6 @@ static void p9_mux_flush_cb(struct p9_req *freq, void *a)
freq->tcall->params.tflush.oldtag);
spin_lock(&m->lock);
- cb = NULL;
tag = freq->tcall->params.tflush.oldtag;
req = NULL;
list_for_each_entry_safe(rreq, rptr, &m->req_list, req_list) {
@@ -1522,7 +1520,7 @@ static int __init p9_trans_fd_init(void)
v9fs_register_trans(&p9_unix_trans);
v9fs_register_trans(&p9_fd_trans);
- return 1;
+ return 0;
}
module_init(p9_trans_fd_init);
diff --git a/net/atm/clip.c b/net/atm/clip.c
index d30167c0b48e..2ab1e36098fd 100644
--- a/net/atm/clip.c
+++ b/net/atm/clip.c
@@ -947,6 +947,8 @@ static const struct file_operations arp_seq_fops = {
};
#endif
+static void atm_clip_exit_noproc(void);
+
static int __init atm_clip_init(void)
{
neigh_table_init_no_netlink(&clip_tbl);
@@ -963,18 +965,22 @@ static int __init atm_clip_init(void)
struct proc_dir_entry *p;
p = proc_create("arp", S_IRUGO, atm_proc_root, &arp_seq_fops);
+ if (!p) {
+ printk(KERN_ERR "Unable to initialize "
+ "/proc/net/atm/arp\n");
+ atm_clip_exit_noproc();
+ return -ENOMEM;
+ }
}
#endif
return 0;
}
-static void __exit atm_clip_exit(void)
+static void atm_clip_exit_noproc(void)
{
struct net_device *dev, *next;
- remove_proc_entry("arp", atm_proc_root);
-
unregister_inetaddr_notifier(&clip_inet_notifier);
unregister_netdevice_notifier(&clip_dev_notifier);
@@ -1005,6 +1011,13 @@ static void __exit atm_clip_exit(void)
clip_tbl_hook = NULL;
}
+static void __exit atm_clip_exit(void)
+{
+ remove_proc_entry("arp", atm_proc_root);
+
+ atm_clip_exit_noproc();
+}
+
module_init(atm_clip_init);
module_exit(atm_clip_exit);
MODULE_AUTHOR("Werner Almesberger");
diff --git a/net/atm/lec.c b/net/atm/lec.c
index 0e450d12f035..a2efa7ff41f1 100644
--- a/net/atm/lec.c
+++ b/net/atm/lec.c
@@ -1250,6 +1250,10 @@ static int __init lane_module_init(void)
struct proc_dir_entry *p;
p = proc_create("lec", S_IRUGO, atm_proc_root, &lec_seq_fops);
+ if (!p) {
+ printk(KERN_ERR "Unable to initialize /proc/net/atm/lec\n");
+ return -ENOMEM;
+ }
#endif
register_atm_ioctl(&lane_ioctl_ops);
diff --git a/net/ax25/TODO b/net/ax25/TODO
index 4089c49e45cc..69fb4e368d92 100644
--- a/net/ax25/TODO
+++ b/net/ax25/TODO
@@ -9,10 +9,6 @@ being used.
Routes to a device being taken down might be deleted by ax25_rt_device_down
but added by somebody else before the device has been deleted fully.
-Massive amounts of lock_kernel / unlock_kernel are just a temporary solution to
-get around the removal of SOCKOPS_WRAP. A serious locking strategy has to be
-implemented.
-
The ax25_rt_find_route synopsys is pervert but I somehow had to deal with
the race caused by the static variable in it's previous implementation.
diff --git a/net/bluetooth/bnep/bnep.h b/net/bluetooth/bnep/bnep.h
index a2992280c3d1..e69244dd8de8 100644
--- a/net/bluetooth/bnep/bnep.h
+++ b/net/bluetooth/bnep/bnep.h
@@ -174,7 +174,7 @@ struct bnep_session {
void bnep_net_setup(struct net_device *dev);
int bnep_sock_init(void);
-int bnep_sock_cleanup(void);
+void bnep_sock_cleanup(void);
static inline int bnep_mc_hash(__u8 *addr)
{
diff --git a/net/bluetooth/bnep/sock.c b/net/bluetooth/bnep/sock.c
index 81065e548a1f..201e5b1ce473 100644
--- a/net/bluetooth/bnep/sock.c
+++ b/net/bluetooth/bnep/sock.c
@@ -257,12 +257,10 @@ error:
return err;
}
-int __exit bnep_sock_cleanup(void)
+void __exit bnep_sock_cleanup(void)
{
if (bt_sock_unregister(BTPROTO_BNEP) < 0)
BT_ERR("Can't unregister BNEP socket");
proto_unregister(&bnep_proto);
-
- return 0;
}
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index 930b58e7149a..aec6929f5c16 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -902,8 +902,6 @@ int hci_unregister_dev(struct hci_dev *hdev)
BT_DBG("%p name %s type %d", hdev, hdev->name, hdev->type);
- hci_unregister_sysfs(hdev);
-
write_lock_bh(&hci_dev_list_lock);
list_del(&hdev->list);
write_unlock_bh(&hci_dev_list_lock);
@@ -915,6 +913,8 @@ int hci_unregister_dev(struct hci_dev *hdev)
hci_notify(hdev, HCI_DEV_UNREG);
+ hci_unregister_sysfs(hdev);
+
__hci_dev_put(hdev);
return 0;
diff --git a/net/bluetooth/hci_sock.c b/net/bluetooth/hci_sock.c
index 14991323c273..b5d4019d3572 100644
--- a/net/bluetooth/hci_sock.c
+++ b/net/bluetooth/hci_sock.c
@@ -734,7 +734,7 @@ error:
return err;
}
-int __exit hci_sock_cleanup(void)
+void __exit hci_sock_cleanup(void)
{
if (bt_sock_unregister(BTPROTO_HCI) < 0)
BT_ERR("HCI socket unregistration failed");
@@ -742,6 +742,4 @@ int __exit hci_sock_cleanup(void)
hci_unregister_notifier(&hci_sock_nblock);
proto_unregister(&hci_sk_proto);
-
- return 0;
}
diff --git a/net/bridge/br_fdb.c b/net/bridge/br_fdb.c
index bc40377136a2..9326c377822e 100644
--- a/net/bridge/br_fdb.c
+++ b/net/bridge/br_fdb.c
@@ -136,7 +136,7 @@ void br_fdb_cleanup(unsigned long _data)
this_timer = f->ageing_timer + delay;
if (time_before_eq(this_timer, jiffies))
fdb_delete(f);
- else if (this_timer < next_timer)
+ else if (time_before(this_timer, next_timer))
next_timer = this_timer;
}
}
diff --git a/net/core/dev.c b/net/core/dev.c
index fcdf03cf3b3f..460e7f99ce3e 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -3329,7 +3329,7 @@ static int dev_ifsioc(struct net *net, struct ifreq *ifr, unsigned int cmd)
return -EOPNOTSUPP;
case SIOCADDMULTI:
- if (!dev->set_multicast_list ||
+ if ((!dev->set_multicast_list && !dev->set_rx_mode) ||
ifr->ifr_hwaddr.sa_family != AF_UNSPEC)
return -EINVAL;
if (!netif_device_present(dev))
@@ -3338,7 +3338,7 @@ static int dev_ifsioc(struct net *net, struct ifreq *ifr, unsigned int cmd)
dev->addr_len, 1);
case SIOCDELMULTI:
- if (!dev->set_multicast_list ||
+ if ((!dev->set_multicast_list && !dev->set_rx_mode) ||
ifr->ifr_hwaddr.sa_family != AF_UNSPEC)
return -EINVAL;
if (!netif_device_present(dev))
diff --git a/net/core/neighbour.c b/net/core/neighbour.c
index d9a02b2cc289..19b8e003f150 100644
--- a/net/core/neighbour.c
+++ b/net/core/neighbour.c
@@ -466,6 +466,28 @@ out_neigh_release:
goto out;
}
+struct pneigh_entry *__pneigh_lookup(struct neigh_table *tbl,
+ struct net *net, const void *pkey, struct net_device *dev)
+{
+ struct pneigh_entry *n;
+ int key_len = tbl->key_len;
+ u32 hash_val = *(u32 *)(pkey + key_len - 4);
+
+ hash_val ^= (hash_val >> 16);
+ hash_val ^= hash_val >> 8;
+ hash_val ^= hash_val >> 4;
+ hash_val &= PNEIGH_HASHMASK;
+
+ for (n = tbl->phash_buckets[hash_val]; n; n = n->next) {
+ if (!memcmp(n->key, pkey, key_len) &&
+ (n->net == net) &&
+ (n->dev == dev || !n->dev))
+ break;
+ }
+
+ return n;
+}
+
struct pneigh_entry * pneigh_lookup(struct neigh_table *tbl,
struct net *net, const void *pkey,
struct net_device *dev, int creat)
@@ -2803,6 +2825,7 @@ EXPORT_SYMBOL(neigh_table_init_no_netlink);
EXPORT_SYMBOL(neigh_update);
EXPORT_SYMBOL(pneigh_enqueue);
EXPORT_SYMBOL(pneigh_lookup);
+EXPORT_SYMBOL_GPL(__pneigh_lookup);
#ifdef CONFIG_ARPD
EXPORT_SYMBOL(neigh_app_ns);
diff --git a/net/core/netpoll.c b/net/core/netpoll.c
index 4b7e756181c9..c635de52526c 100644
--- a/net/core/netpoll.c
+++ b/net/core/netpoll.c
@@ -215,10 +215,12 @@ static void zap_completion_queue(void)
while (clist != NULL) {
struct sk_buff *skb = clist;
clist = clist->next;
- if (skb->destructor)
+ if (skb->destructor) {
+ atomic_inc(&skb->users);
dev_kfree_skb_any(skb); /* put this one back */
- else
+ } else {
__kfree_skb(skb);
+ }
}
}
diff --git a/net/core/sock.c b/net/core/sock.c
index 09cb3a74de7f..2654c147c004 100644
--- a/net/core/sock.c
+++ b/net/core/sock.c
@@ -1621,7 +1621,7 @@ static void sock_def_readable(struct sock *sk, int len)
{
read_lock(&sk->sk_callback_lock);
if (sk->sk_sleep && waitqueue_active(sk->sk_sleep))
- wake_up_interruptible(sk->sk_sleep);
+ wake_up_interruptible_sync(sk->sk_sleep);
sk_wake_async(sk, SOCK_WAKE_WAITD, POLL_IN);
read_unlock(&sk->sk_callback_lock);
}
@@ -1635,7 +1635,7 @@ static void sock_def_write_space(struct sock *sk)
*/
if ((atomic_read(&sk->sk_wmem_alloc) << 1) <= sk->sk_sndbuf) {
if (sk->sk_sleep && waitqueue_active(sk->sk_sleep))
- wake_up_interruptible(sk->sk_sleep);
+ wake_up_interruptible_sync(sk->sk_sleep);
/* Should agree with poll, otherwise some programs break */
if (sock_writeable(sk))
diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c
index 09ca5293d08f..0d109504ed86 100644
--- a/net/ipv4/af_inet.c
+++ b/net/ipv4/af_inet.c
@@ -458,7 +458,7 @@ int inet_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
err = -EADDRNOTAVAIL;
if (!sysctl_ip_nonlocal_bind &&
!inet->freebind &&
- addr->sin_addr.s_addr != INADDR_ANY &&
+ addr->sin_addr.s_addr != htonl(INADDR_ANY) &&
chk_addr_ret != RTN_LOCAL &&
chk_addr_ret != RTN_MULTICAST &&
chk_addr_ret != RTN_BROADCAST)
diff --git a/net/ipv4/esp4.c b/net/ipv4/esp4.c
index 091e6709f831..f3ceca31aa45 100644
--- a/net/ipv4/esp4.c
+++ b/net/ipv4/esp4.c
@@ -168,7 +168,7 @@ static int esp_output(struct xfrm_state *x, struct sk_buff *skb)
struct xfrm_encap_tmpl *encap = x->encap;
struct udphdr *uh;
__be32 *udpdata32;
- unsigned int sport, dport;
+ __be16 sport, dport;
int encap_type;
spin_lock_bh(&x->lock);
diff --git a/net/ipv4/fib_trie.c b/net/ipv4/fib_trie.c
index 1ff446d0fa8b..f6cdc012eec5 100644
--- a/net/ipv4/fib_trie.c
+++ b/net/ipv4/fib_trie.c
@@ -177,10 +177,13 @@ static inline struct tnode *node_parent_rcu(struct node *node)
return rcu_dereference(ret);
}
+/* Same as rcu_assign_pointer
+ * but that macro() assumes that value is a pointer.
+ */
static inline void node_set_parent(struct node *node, struct tnode *ptr)
{
- rcu_assign_pointer(node->parent,
- (unsigned long)ptr | NODE_TYPE(node));
+ smp_wmb();
+ node->parent = (unsigned long)ptr | NODE_TYPE(node);
}
static inline struct node *tnode_get_child(struct tnode *tn, unsigned int i)
diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c
index a13c074dac09..a944e8053e28 100644
--- a/net/ipv4/icmp.c
+++ b/net/ipv4/icmp.c
@@ -591,7 +591,7 @@ void icmp_send(struct sk_buff *skb_in, int type, int code, __be32 info)
}
if (xfrm_decode_session_reverse(skb_in, &fl, AF_INET))
- goto out_unlock;
+ goto ende;
if (inet_addr_type(net, fl.fl4_src) == RTN_LOCAL)
err = __ip_route_output_key(net, &rt2, &fl);
@@ -601,7 +601,7 @@ void icmp_send(struct sk_buff *skb_in, int type, int code, __be32 info)
fl2.fl4_dst = fl.fl4_src;
if (ip_route_output_key(net, &rt2, &fl2))
- goto out_unlock;
+ goto ende;
/* Ugh! */
odst = skb_in->dst;
@@ -614,7 +614,7 @@ void icmp_send(struct sk_buff *skb_in, int type, int code, __be32 info)
}
if (err)
- goto out_unlock;
+ goto ende;
err = xfrm_lookup((struct dst_entry **)&rt2, &fl, NULL,
XFRM_LOOKUP_ICMP);
diff --git a/net/ipv4/ip_fragment.c b/net/ipv4/ip_fragment.c
index a2e92f9709db..3b2e5adca838 100644
--- a/net/ipv4/ip_fragment.c
+++ b/net/ipv4/ip_fragment.c
@@ -568,7 +568,7 @@ int ip_defrag(struct sk_buff *skb, u32 user)
IP_INC_STATS_BH(IPSTATS_MIB_REASMREQDS);
- net = skb->dev->nd_net;
+ net = skb->dev ? skb->dev->nd_net : skb->dst->dev->nd_net;
/* Start by cleaning up the memory. */
if (atomic_read(&net->ipv4.frags.mem) > net->ipv4.frags.high_thresh)
ip_evictor(net);
diff --git a/net/ipv4/ip_sockglue.c b/net/ipv4/ip_sockglue.c
index de0572c88859..f72457b4b0a7 100644
--- a/net/ipv4/ip_sockglue.c
+++ b/net/ipv4/ip_sockglue.c
@@ -583,7 +583,7 @@ static int do_ip_setsockopt(struct sock *sk, int level,
}
if (!mreq.imr_ifindex) {
- if (mreq.imr_address.s_addr == INADDR_ANY) {
+ if (mreq.imr_address.s_addr == htonl(INADDR_ANY)) {
inet->mc_index = 0;
inet->mc_addr = 0;
err = 0;
diff --git a/net/ipv4/ipconfig.c b/net/ipv4/ipconfig.c
index 5dd938579eeb..7c992fbbc2c3 100644
--- a/net/ipv4/ipconfig.c
+++ b/net/ipv4/ipconfig.c
@@ -103,6 +103,7 @@
- '3' from resolv.h */
#define NONE __constant_htonl(INADDR_NONE)
+#define ANY __constant_htonl(INADDR_ANY)
/*
* Public IP configuration
@@ -1479,19 +1480,19 @@ static int __init ip_auto_config_setup(char *addrs)
DBG(("IP-Config: Parameter #%d: `%s'\n", num, ip));
switch (num) {
case 0:
- if ((ic_myaddr = in_aton(ip)) == INADDR_ANY)
+ if ((ic_myaddr = in_aton(ip)) == ANY)
ic_myaddr = NONE;
break;
case 1:
- if ((ic_servaddr = in_aton(ip)) == INADDR_ANY)
+ if ((ic_servaddr = in_aton(ip)) == ANY)
ic_servaddr = NONE;
break;
case 2:
- if ((ic_gateway = in_aton(ip)) == INADDR_ANY)
+ if ((ic_gateway = in_aton(ip)) == ANY)
ic_gateway = NONE;
break;
case 3:
- if ((ic_netmask = in_aton(ip)) == INADDR_ANY)
+ if ((ic_netmask = in_aton(ip)) == ANY)
ic_netmask = NONE;
break;
case 4:
diff --git a/net/ipv4/netfilter/ipt_recent.c b/net/ipv4/netfilter/ipt_recent.c
index 68cbe3ca01ce..8e8f0425a8ed 100644
--- a/net/ipv4/netfilter/ipt_recent.c
+++ b/net/ipv4/netfilter/ipt_recent.c
@@ -252,6 +252,8 @@ recent_mt_check(const char *tablename, const void *ip,
if ((info->check_set & (IPT_RECENT_SET | IPT_RECENT_REMOVE)) &&
(info->seconds || info->hit_count))
return false;
+ if (info->hit_count > ip_pkt_list_tot)
+ return false;
if (info->name[0] == '\0' ||
strnlen(info->name, IPT_RECENT_NAME_LEN) == IPT_RECENT_NAME_LEN)
return false;
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
index 071e83a894ad..39b629ac2404 100644
--- a/net/ipv4/tcp.c
+++ b/net/ipv4/tcp.c
@@ -735,7 +735,7 @@ new_segment:
if (!(psize -= copy))
goto out;
- if (skb->len < mss_now || (flags & MSG_OOB))
+ if (skb->len < size_goal || (flags & MSG_OOB))
continue;
if (forced_push(tp)) {
@@ -981,7 +981,7 @@ new_segment:
if ((seglen -= copy) == 0 && iovlen == 0)
goto out;
- if (skb->len < mss_now || (flags & MSG_OOB))
+ if (skb->len < size_goal || (flags & MSG_OOB))
continue;
if (forced_push(tp)) {
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c
index ed750f9ceb07..72b9350006fe 100644
--- a/net/ipv4/tcp_output.c
+++ b/net/ipv4/tcp_output.c
@@ -255,7 +255,7 @@ static u16 tcp_select_window(struct sock *sk)
*
* Relax Will Robinson.
*/
- new_win = cur_win;
+ new_win = ALIGN(cur_win, 1 << tp->rx_opt.rcv_wscale);
}
tp->rcv_wnd = new_win;
tp->rcv_wup = tp->rcv_nxt;
@@ -1035,6 +1035,13 @@ static void tcp_cwnd_validate(struct sock *sk)
* introducing MSS oddities to segment boundaries. In rare cases where
* mss_now != mss_cache, we will request caller to create a small skb
* per input skb which could be mostly avoided here (if desired).
+ *
+ * We explicitly want to create a request for splitting write queue tail
+ * to a small skb for Nagle purposes while avoiding unnecessary modulos,
+ * thus all the complexity (cwnd_len is always MSS multiple which we
+ * return whenever allowed by the other factors). Basically we need the
+ * modulo only when the receiver window alone is the limiting factor or
+ * when we would be allowed to send the split-due-to-Nagle skb fully.
*/
static unsigned int tcp_mss_split_point(struct sock *sk, struct sk_buff *skb,
unsigned int mss_now, unsigned int cwnd)
@@ -1048,10 +1055,11 @@ static unsigned int tcp_mss_split_point(struct sock *sk, struct sk_buff *skb,
if (likely(cwnd_len <= window && skb != tcp_write_queue_tail(sk)))
return cwnd_len;
- if (skb == tcp_write_queue_tail(sk) && cwnd_len <= skb->len)
+ needed = min(skb->len, window);
+
+ if (skb == tcp_write_queue_tail(sk) && cwnd_len <= needed)
return cwnd_len;
- needed = min(skb->len, window);
return needed - needed % mss_now;
}
diff --git a/net/ipv4/xfrm4_mode_beet.c b/net/ipv4/xfrm4_mode_beet.c
index b47030ba162b..9c798abce736 100644
--- a/net/ipv4/xfrm4_mode_beet.c
+++ b/net/ipv4/xfrm4_mode_beet.c
@@ -39,13 +39,11 @@ static void xfrm4_beet_make_header(struct sk_buff *skb)
static int xfrm4_beet_output(struct xfrm_state *x, struct sk_buff *skb)
{
struct ip_beet_phdr *ph;
- struct iphdr *iph, *top_iph;
+ struct iphdr *top_iph;
int hdrlen, optlen;
- iph = ip_hdr(skb);
-
hdrlen = 0;
- optlen = iph->ihl * 4 - sizeof(*iph);
+ optlen = XFRM_MODE_SKB_CB(skb)->optlen;
if (unlikely(optlen))
hdrlen += IPV4_BEET_PHMAXLEN - (optlen & 4);
@@ -53,11 +51,12 @@ static int xfrm4_beet_output(struct xfrm_state *x, struct sk_buff *skb)
hdrlen);
skb->mac_header = skb->network_header +
offsetof(struct iphdr, protocol);
- skb->transport_header = skb->network_header + sizeof(*iph);
+ skb->transport_header = skb->network_header + sizeof(*top_iph);
xfrm4_beet_make_header(skb);
- ph = (struct ip_beet_phdr *)__skb_pull(skb, sizeof(*iph) - hdrlen);
+ ph = (struct ip_beet_phdr *)
+ __skb_pull(skb, XFRM_MODE_SKB_CB(skb)->ihl - hdrlen);
top_iph = ip_hdr(skb);
diff --git a/net/ipv4/xfrm4_mode_tunnel.c b/net/ipv4/xfrm4_mode_tunnel.c
index 8dee617ee900..584e6d74e3a9 100644
--- a/net/ipv4/xfrm4_mode_tunnel.c
+++ b/net/ipv4/xfrm4_mode_tunnel.c
@@ -41,7 +41,7 @@ static int xfrm4_mode_tunnel_output(struct xfrm_state *x, struct sk_buff *skb)
top_iph->ihl = 5;
top_iph->version = 4;
- top_iph->protocol = x->inner_mode->afinfo->proto;
+ top_iph->protocol = xfrm_af2proto(skb->dst->ops->family);
/* DS disclosed */
top_iph->tos = INET_ECN_encapsulate(XFRM_MODE_SKB_CB(skb)->tos,
diff --git a/net/ipv4/xfrm4_output.c b/net/ipv4/xfrm4_output.c
index d5a58a818021..8c3180adddbf 100644
--- a/net/ipv4/xfrm4_output.c
+++ b/net/ipv4/xfrm4_output.c
@@ -56,7 +56,7 @@ int xfrm4_prepare_output(struct xfrm_state *x, struct sk_buff *skb)
{
int err;
- err = x->inner_mode->afinfo->extract_output(x, skb);
+ err = xfrm_inner_extract_output(x, skb);
if (err)
return err;
diff --git a/net/ipv4/xfrm4_state.c b/net/ipv4/xfrm4_state.c
index fdeebe68a379..07735ed280d7 100644
--- a/net/ipv4/xfrm4_state.c
+++ b/net/ipv4/xfrm4_state.c
@@ -52,10 +52,12 @@ int xfrm4_extract_header(struct sk_buff *skb)
{
struct iphdr *iph = ip_hdr(skb);
+ XFRM_MODE_SKB_CB(skb)->ihl = sizeof(*iph);
XFRM_MODE_SKB_CB(skb)->id = iph->id;
XFRM_MODE_SKB_CB(skb)->frag_off = iph->frag_off;
XFRM_MODE_SKB_CB(skb)->tos = iph->tos;
XFRM_MODE_SKB_CB(skb)->ttl = iph->ttl;
+ XFRM_MODE_SKB_CB(skb)->optlen = iph->ihl * 4 - sizeof(*iph);
memset(XFRM_MODE_SKB_CB(skb)->flow_lbl, 0,
sizeof(XFRM_MODE_SKB_CB(skb)->flow_lbl));
diff --git a/net/ipv6/Kconfig b/net/ipv6/Kconfig
index 58219dfffef8..47263e45bacb 100644
--- a/net/ipv6/Kconfig
+++ b/net/ipv6/Kconfig
@@ -179,11 +179,12 @@ config IPV6_SIT
Saying M here will produce a module called sit.ko. If unsure, say Y.
config IPV6_TUNNEL
- tristate "IPv6: IPv6-in-IPv6 tunnel"
+ tristate "IPv6: IP-in-IPv6 tunnel (RFC2473)"
select INET6_TUNNEL
depends on IPV6
---help---
- Support for IPv6-in-IPv6 tunnels described in RFC 2473.
+ Support for IPv6-in-IPv6 and IPv4-in-IPv6 tunnels described in
+ RFC 2473.
If unsure, say N.
diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c
index 0d33a7d32125..452a2ac4eec8 100644
--- a/net/ipv6/ndisc.c
+++ b/net/ipv6/ndisc.c
@@ -676,6 +676,20 @@ static void ndisc_solicit(struct neighbour *neigh, struct sk_buff *skb)
}
}
+static struct pneigh_entry *pndisc_check_router(struct net_device *dev,
+ struct in6_addr *addr, int *is_router)
+{
+ struct pneigh_entry *n;
+
+ read_lock_bh(&nd_tbl.lock);
+ n = __pneigh_lookup(&nd_tbl, &init_net, addr, dev);
+ if (n != NULL)
+ *is_router = (n->flags & NTF_ROUTER);
+ read_unlock_bh(&nd_tbl.lock);
+
+ return n;
+}
+
static void ndisc_recv_ns(struct sk_buff *skb)
{
struct nd_msg *msg = (struct nd_msg *)skb_transport_header(skb);
@@ -692,7 +706,7 @@ static void ndisc_recv_ns(struct sk_buff *skb)
struct pneigh_entry *pneigh = NULL;
int dad = ipv6_addr_any(saddr);
int inc;
- int is_router;
+ int is_router = 0;
if (ipv6_addr_is_multicast(&msg->target)) {
ND_PRINTK2(KERN_WARNING
@@ -790,8 +804,8 @@ static void ndisc_recv_ns(struct sk_buff *skb)
if (ipv6_chk_acast_addr(dev, &msg->target) ||
(idev->cnf.forwarding &&
(ipv6_devconf.proxy_ndp || idev->cnf.proxy_ndp) &&
- (pneigh = pneigh_lookup(&nd_tbl, &init_net,
- &msg->target, dev, 0)) != NULL)) {
+ (pneigh = pndisc_check_router(dev, &msg->target,
+ &is_router)) != NULL)) {
if (!(NEIGH_CB(skb)->flags & LOCALLY_ENQUEUED) &&
skb->pkt_type != PACKET_HOST &&
inc != 0 &&
@@ -812,7 +826,7 @@ static void ndisc_recv_ns(struct sk_buff *skb)
goto out;
}
- is_router = !!(pneigh ? pneigh->flags & NTF_ROUTER : idev->cnf.forwarding);
+ is_router = !!(pneigh ? is_router : idev->cnf.forwarding);
if (dad) {
struct in6_addr maddr;
@@ -1420,7 +1434,6 @@ void ndisc_send_redirect(struct sk_buff *skb, struct neighbour *neigh,
u8 *opt;
int rd_len;
int err;
- int hlen;
u8 ha_buf[MAX_ADDR_LEN], *ha = NULL;
dev = skb->dev;
@@ -1491,7 +1504,6 @@ void ndisc_send_redirect(struct sk_buff *skb, struct neighbour *neigh,
return;
}
- hlen = 0;
skb_reserve(buff, LL_RESERVED_SPACE(dev));
ip6_nd_hdr(sk, buff, dev, &saddr_buf, &ipv6_hdr(skb)->saddr,
diff --git a/net/ipv6/xfrm6_mode_beet.c b/net/ipv6/xfrm6_mode_beet.c
index 0527d11c1ae3..d6ce400f585f 100644
--- a/net/ipv6/xfrm6_mode_beet.c
+++ b/net/ipv6/xfrm6_mode_beet.c
@@ -45,6 +45,7 @@ static int xfrm6_beet_output(struct xfrm_state *x, struct sk_buff *skb)
skb->mac_header = skb->network_header +
offsetof(struct ipv6hdr, nexthdr);
skb->transport_header = skb->network_header + sizeof(*top_iph);
+ __skb_pull(skb, XFRM_MODE_SKB_CB(skb)->ihl);
xfrm6_beet_make_header(skb);
diff --git a/net/ipv6/xfrm6_mode_tunnel.c b/net/ipv6/xfrm6_mode_tunnel.c
index 0c742faaa30b..e20529b4c825 100644
--- a/net/ipv6/xfrm6_mode_tunnel.c
+++ b/net/ipv6/xfrm6_mode_tunnel.c
@@ -45,7 +45,7 @@ static int xfrm6_mode_tunnel_output(struct xfrm_state *x, struct sk_buff *skb)
memcpy(top_iph->flow_lbl, XFRM_MODE_SKB_CB(skb)->flow_lbl,
sizeof(top_iph->flow_lbl));
- top_iph->nexthdr = x->inner_mode->afinfo->proto;
+ top_iph->nexthdr = xfrm_af2proto(skb->dst->ops->family);
dsfield = XFRM_MODE_SKB_CB(skb)->tos;
dsfield = INET_ECN_encapsulate(dsfield, dsfield);
diff --git a/net/ipv6/xfrm6_output.c b/net/ipv6/xfrm6_output.c
index 79ccfb080733..0af823cf7f1f 100644
--- a/net/ipv6/xfrm6_output.c
+++ b/net/ipv6/xfrm6_output.c
@@ -62,7 +62,7 @@ int xfrm6_prepare_output(struct xfrm_state *x, struct sk_buff *skb)
{
int err;
- err = x->inner_mode->afinfo->extract_output(x, skb);
+ err = xfrm_inner_extract_output(x, skb);
if (err)
return err;
diff --git a/net/ipv6/xfrm6_state.c b/net/ipv6/xfrm6_state.c
index dc817e035e23..ff1e1db8e236 100644
--- a/net/ipv6/xfrm6_state.c
+++ b/net/ipv6/xfrm6_state.c
@@ -174,10 +174,12 @@ int xfrm6_extract_header(struct sk_buff *skb)
{
struct ipv6hdr *iph = ipv6_hdr(skb);
+ XFRM_MODE_SKB_CB(skb)->ihl = sizeof(*iph);
XFRM_MODE_SKB_CB(skb)->id = 0;
XFRM_MODE_SKB_CB(skb)->frag_off = htons(IP_DF);
XFRM_MODE_SKB_CB(skb)->tos = ipv6_get_dsfield(iph);
XFRM_MODE_SKB_CB(skb)->ttl = iph->hop_limit;
+ XFRM_MODE_SKB_CB(skb)->optlen = 0;
memcpy(XFRM_MODE_SKB_CB(skb)->flow_lbl, iph->flow_lbl,
sizeof(XFRM_MODE_SKB_CB(skb)->flow_lbl));
diff --git a/net/irda/irnet/irnet.h b/net/irda/irnet/irnet.h
index bc2e15ce7004..7873c392ab4c 100644
--- a/net/irda/irnet/irnet.h
+++ b/net/irda/irnet/irnet.h
@@ -405,7 +405,7 @@ typedef struct irnet_socket
/* "pppd" interact directly with us on a /dev/ file */
struct file * file; /* File descriptor of this instance */
/* TTY stuff - to keep "pppd" happy */
- struct termios termios; /* Various tty flags */
+ struct ktermios termios; /* Various tty flags */
/* Stuff for the control channel */
int event_index; /* Last read in the event log */
diff --git a/net/key/af_key.c b/net/key/af_key.c
index 8b5f486ac80f..e9ef9af4a53b 100644
--- a/net/key/af_key.c
+++ b/net/key/af_key.c
@@ -1219,7 +1219,7 @@ static struct xfrm_state * pfkey_msg2xfrm_state(struct sadb_msg *hdr,
x->sel.prefixlen_s = addr->sadb_address_prefixlen;
}
- if (!x->sel.family)
+ if (x->props.mode == XFRM_MODE_TRANSPORT)
x->sel.family = x->props.family;
if (ext_hdrs[SADB_X_EXT_NAT_T_TYPE-1]) {
diff --git a/net/netfilter/nf_conntrack_expect.c b/net/netfilter/nf_conntrack_expect.c
index e06bf0028bb1..684ec9c1ad38 100644
--- a/net/netfilter/nf_conntrack_expect.c
+++ b/net/netfilter/nf_conntrack_expect.c
@@ -381,7 +381,7 @@ int nf_ct_expect_related(struct nf_conntrack_expect *expect)
if (nf_ct_expect_count >= nf_ct_expect_max) {
if (net_ratelimit())
printk(KERN_WARNING
- "nf_conntrack: expectation table full");
+ "nf_conntrack: expectation table full\n");
ret = -EMFILE;
goto out;
}
diff --git a/net/netfilter/nf_conntrack_extend.c b/net/netfilter/nf_conntrack_extend.c
index 8b9be1e978cd..2bd9963b5b3e 100644
--- a/net/netfilter/nf_conntrack_extend.c
+++ b/net/netfilter/nf_conntrack_extend.c
@@ -19,14 +19,6 @@
static struct nf_ct_ext_type *nf_ct_ext_types[NF_CT_EXT_NUM];
static DEFINE_MUTEX(nf_ct_ext_type_mutex);
-/* Horrible trick to figure out smallest amount worth kmallocing. */
-#define CACHE(x) (x) + 0 *
-enum {
- NF_CT_EXT_MIN_SIZE =
-#include <linux/kmalloc_sizes.h>
- 1 };
-#undef CACHE
-
void __nf_ct_ext_destroy(struct nf_conn *ct)
{
unsigned int i;
@@ -53,7 +45,7 @@ EXPORT_SYMBOL(__nf_ct_ext_destroy);
static void *
nf_ct_ext_create(struct nf_ct_ext **ext, enum nf_ct_ext_id id, gfp_t gfp)
{
- unsigned int off, len, real_len;
+ unsigned int off, len;
struct nf_ct_ext_type *t;
rcu_read_lock();
@@ -61,16 +53,14 @@ nf_ct_ext_create(struct nf_ct_ext **ext, enum nf_ct_ext_id id, gfp_t gfp)
BUG_ON(t == NULL);
off = ALIGN(sizeof(struct nf_ct_ext), t->align);
len = off + t->len;
- real_len = t->alloc_size;
rcu_read_unlock();
- *ext = kzalloc(real_len, gfp);
+ *ext = kzalloc(t->alloc_size, gfp);
if (!*ext)
return NULL;
(*ext)->offset[id] = off;
(*ext)->len = len;
- (*ext)->real_len = real_len;
return (void *)(*ext) + off;
}
@@ -95,7 +85,7 @@ void *__nf_ct_ext_add(struct nf_conn *ct, enum nf_ct_ext_id id, gfp_t gfp)
newlen = newoff + t->len;
rcu_read_unlock();
- if (newlen >= ct->ext->real_len) {
+ if (newlen >= ksize(ct->ext)) {
new = kmalloc(newlen, gfp);
if (!new)
return NULL;
@@ -114,7 +104,6 @@ void *__nf_ct_ext_add(struct nf_conn *ct, enum nf_ct_ext_id id, gfp_t gfp)
rcu_read_unlock();
}
kfree(ct->ext);
- new->real_len = newlen;
ct->ext = new;
}
@@ -156,8 +145,6 @@ static void update_alloc_size(struct nf_ct_ext_type *type)
t1->alloc_size = ALIGN(t1->alloc_size, t2->align)
+ t2->len;
}
- if (t1->alloc_size < NF_CT_EXT_MIN_SIZE)
- t1->alloc_size = NF_CT_EXT_MIN_SIZE;
}
}
diff --git a/net/netfilter/nf_conntrack_h323_main.c b/net/netfilter/nf_conntrack_h323_main.c
index 62137879e6aa..898f1922b5b8 100644
--- a/net/netfilter/nf_conntrack_h323_main.c
+++ b/net/netfilter/nf_conntrack_h323_main.c
@@ -842,7 +842,7 @@ static int process_setup(struct sk_buff *skb, struct nf_conn *ct,
set_h225_addr = rcu_dereference(set_h225_addr_hook);
if ((setup->options & eSetup_UUIE_destCallSignalAddress) &&
- (set_h225_addr) && ct->status && IPS_NAT_MASK &&
+ (set_h225_addr) && ct->status & IPS_NAT_MASK &&
get_h225_addr(ct, *data, &setup->destCallSignalAddress,
&addr, &port) &&
memcmp(&addr, &ct->tuplehash[!dir].tuple.src.u3, sizeof(addr))) {
diff --git a/net/netfilter/nf_queue.c b/net/netfilter/nf_queue.c
index bfc2928c1912..ddc80ea114cd 100644
--- a/net/netfilter/nf_queue.c
+++ b/net/netfilter/nf_queue.c
@@ -51,7 +51,7 @@ int nf_unregister_queue_handler(int pf, const struct nf_queue_handler *qh)
return -EINVAL;
mutex_lock(&queue_handler_mutex);
- if (queue_handler[pf] != qh) {
+ if (queue_handler[pf] && queue_handler[pf] != qh) {
mutex_unlock(&queue_handler_mutex);
return -EINVAL;
}
diff --git a/net/netfilter/nfnetlink_log.c b/net/netfilter/nfnetlink_log.c
index 7efa40d47393..bf3f19b21fe4 100644
--- a/net/netfilter/nfnetlink_log.c
+++ b/net/netfilter/nfnetlink_log.c
@@ -556,7 +556,7 @@ nfulnl_log_packet(unsigned int pf,
/* FIXME: do we want to make the size calculation conditional based on
* what is actually present? way more branches and checks, but more
* memory efficient... */
- size = NLMSG_ALIGN(sizeof(struct nfgenmsg))
+ size = NLMSG_SPACE(sizeof(struct nfgenmsg))
+ nla_total_size(sizeof(struct nfulnl_msg_packet_hdr))
+ nla_total_size(sizeof(u_int32_t)) /* ifindex */
+ nla_total_size(sizeof(u_int32_t)) /* ifindex */
@@ -702,20 +702,30 @@ nfulnl_recv_config(struct sock *ctnl, struct sk_buff *skb,
struct nfgenmsg *nfmsg = NLMSG_DATA(nlh);
u_int16_t group_num = ntohs(nfmsg->res_id);
struct nfulnl_instance *inst;
+ struct nfulnl_msg_config_cmd *cmd = NULL;
int ret = 0;
+ if (nfula[NFULA_CFG_CMD]) {
+ u_int8_t pf = nfmsg->nfgen_family;
+ cmd = nla_data(nfula[NFULA_CFG_CMD]);
+
+ /* Commands without queue context */
+ switch (cmd->command) {
+ case NFULNL_CFG_CMD_PF_BIND:
+ return nf_log_register(pf, &nfulnl_logger);
+ case NFULNL_CFG_CMD_PF_UNBIND:
+ nf_log_unregister_pf(pf);
+ return 0;
+ }
+ }
+
inst = instance_lookup_get(group_num);
if (inst && inst->peer_pid != NETLINK_CB(skb).pid) {
ret = -EPERM;
goto out_put;
}
- if (nfula[NFULA_CFG_CMD]) {
- u_int8_t pf = nfmsg->nfgen_family;
- struct nfulnl_msg_config_cmd *cmd;
-
- cmd = nla_data(nfula[NFULA_CFG_CMD]);
-
+ if (cmd != NULL) {
switch (cmd->command) {
case NFULNL_CFG_CMD_BIND:
if (inst) {
@@ -738,14 +748,6 @@ nfulnl_recv_config(struct sock *ctnl, struct sk_buff *skb,
instance_destroy(inst);
goto out;
- case NFULNL_CFG_CMD_PF_BIND:
- ret = nf_log_register(pf, &nfulnl_logger);
- break;
- case NFULNL_CFG_CMD_PF_UNBIND:
- /* This is a bug and a feature. We cannot unregister
- * other handlers, like nfnetlink_inst can */
- nf_log_unregister_pf(pf);
- break;
default:
ret = -ENOTSUPP;
break;
diff --git a/net/netfilter/nfnetlink_queue.c b/net/netfilter/nfnetlink_queue.c
index 0043d3a9f87e..012cb6910820 100644
--- a/net/netfilter/nfnetlink_queue.c
+++ b/net/netfilter/nfnetlink_queue.c
@@ -224,7 +224,7 @@ nfqnl_build_packet_message(struct nfqnl_instance *queue,
struct net_device *indev;
struct net_device *outdev;
- size = NLMSG_ALIGN(sizeof(struct nfgenmsg))
+ size = NLMSG_SPACE(sizeof(struct nfgenmsg))
+ nla_total_size(sizeof(struct nfqnl_msg_packet_hdr))
+ nla_total_size(sizeof(u_int32_t)) /* ifindex */
+ nla_total_size(sizeof(u_int32_t)) /* ifindex */
@@ -703,19 +703,12 @@ nfqnl_recv_config(struct sock *ctnl, struct sk_buff *skb,
/* Commands without queue context - might sleep */
switch (cmd->command) {
case NFQNL_CFG_CMD_PF_BIND:
- ret = nf_register_queue_handler(ntohs(cmd->pf),
- &nfqh);
- break;
+ return nf_register_queue_handler(ntohs(cmd->pf),
+ &nfqh);
case NFQNL_CFG_CMD_PF_UNBIND:
- ret = nf_unregister_queue_handler(ntohs(cmd->pf),
- &nfqh);
- break;
- default:
- break;
+ return nf_unregister_queue_handler(ntohs(cmd->pf),
+ &nfqh);
}
-
- if (ret < 0)
- return ret;
}
rcu_read_lock();
diff --git a/net/netfilter/xt_time.c b/net/netfilter/xt_time.c
index e9a8794bc3ab..9fa2e0824708 100644
--- a/net/netfilter/xt_time.c
+++ b/net/netfilter/xt_time.c
@@ -95,8 +95,11 @@ static inline void localtime_2(struct xtm *r, time_t time)
*/
r->dse = time / 86400;
- /* 1970-01-01 (w=0) was a Thursday (4). */
- r->weekday = (4 + r->dse) % 7;
+ /*
+ * 1970-01-01 (w=0) was a Thursday (4).
+ * -1 and +1 map Sunday properly onto 7.
+ */
+ r->weekday = (4 + r->dse - 1) % 7 + 1;
}
static void localtime_3(struct xtm *r, time_t time)
diff --git a/net/rxrpc/ar-internal.h b/net/rxrpc/ar-internal.h
index 1aaa2e804b0d..126ca777b410 100644
--- a/net/rxrpc/ar-internal.h
+++ b/net/rxrpc/ar-internal.h
@@ -23,7 +23,7 @@
struct rxrpc_crypt {
union {
u8 x[FCRYPT_BSIZE];
- u32 n[2];
+ __be32 n[2];
};
} __attribute__((aligned(8)));
diff --git a/net/rxrpc/ar-recvmsg.c b/net/rxrpc/ar-recvmsg.c
index f19121d4795b..a39bf97f8830 100644
--- a/net/rxrpc/ar-recvmsg.c
+++ b/net/rxrpc/ar-recvmsg.c
@@ -143,7 +143,8 @@ int rxrpc_recvmsg(struct kiocb *iocb, struct socket *sock,
/* copy the peer address and timestamp */
if (!continue_call) {
if (msg->msg_name && msg->msg_namelen > 0)
- memcpy(&msg->msg_name, &call->conn->trans->peer->srx,
+ memcpy(msg->msg_name,
+ &call->conn->trans->peer->srx,
sizeof(call->conn->trans->peer->srx));
sock_recv_timestamp(msg, &rx->sk, skb);
}
diff --git a/net/rxrpc/rxkad.c b/net/rxrpc/rxkad.c
index f48434adb7c2..d1c296f2d617 100644
--- a/net/rxrpc/rxkad.c
+++ b/net/rxrpc/rxkad.c
@@ -261,6 +261,7 @@ static int rxkad_secure_packet(const struct rxrpc_call *call,
__be32 x[2];
} tmpbuf __attribute__((aligned(8))); /* must all be in same page */
__be32 x;
+ u32 y;
int ret;
sp = rxrpc_skb(skb);
@@ -292,11 +293,11 @@ static int rxkad_secure_packet(const struct rxrpc_call *call,
sg_init_one(&sg[1], &tmpbuf, sizeof(tmpbuf));
crypto_blkcipher_encrypt_iv(&desc, &sg[0], &sg[1], sizeof(tmpbuf));
- x = ntohl(tmpbuf.x[1]);
- x = (x >> 16) & 0xffff;
- if (x == 0)
- x = 1; /* zero checksums are not permitted */
- sp->hdr.cksum = htons(x);
+ y = ntohl(tmpbuf.x[1]);
+ y = (y >> 16) & 0xffff;
+ if (y == 0)
+ y = 1; /* zero checksums are not permitted */
+ sp->hdr.cksum = htons(y);
switch (call->conn->security_level) {
case RXRPC_SECURITY_PLAIN:
@@ -314,7 +315,7 @@ static int rxkad_secure_packet(const struct rxrpc_call *call,
break;
}
- _leave(" = %d [set %hx]", ret, x);
+ _leave(" = %d [set %hx]", ret, y);
return ret;
}
@@ -492,6 +493,7 @@ static int rxkad_verify_packet(const struct rxrpc_call *call,
__be32 x[2];
} tmpbuf __attribute__((aligned(8))); /* must all be in same page */
__be32 x;
+ u16 y;
__be16 cksum;
int ret;
@@ -526,12 +528,12 @@ static int rxkad_verify_packet(const struct rxrpc_call *call,
sg_init_one(&sg[1], &tmpbuf, sizeof(tmpbuf));
crypto_blkcipher_encrypt_iv(&desc, &sg[0], &sg[1], sizeof(tmpbuf));
- x = ntohl(tmpbuf.x[1]);
- x = (x >> 16) & 0xffff;
- if (x == 0)
- x = 1; /* zero checksums are not permitted */
+ y = ntohl(tmpbuf.x[1]);
+ y = (y >> 16) & 0xffff;
+ if (y == 0)
+ y = 1; /* zero checksums are not permitted */
- cksum = htons(x);
+ cksum = htons(y);
if (sp->hdr.cksum != cksum) {
*_abort_code = RXKADSEALEDINCON;
_leave(" = -EPROTO [csum failed]");
@@ -1001,7 +1003,8 @@ static int rxkad_verify_response(struct rxrpc_connection *conn,
struct rxrpc_crypt session_key;
time_t expiry;
void *ticket;
- u32 abort_code, version, kvno, ticket_len, csum, level;
+ u32 abort_code, version, kvno, ticket_len, level;
+ __be32 csum;
int ret;
_enter("{%d,%x}", conn->debug_id, key_serial(conn->server_key));
diff --git a/net/sched/cls_u32.c b/net/sched/cls_u32.c
index b18fa95ef248..c5c16b4b6e98 100644
--- a/net/sched/cls_u32.c
+++ b/net/sched/cls_u32.c
@@ -89,7 +89,7 @@ static const struct tcf_ext_map u32_ext_map = {
static struct tc_u_common *u32_list;
-static __inline__ unsigned u32_hash_fold(u32 key, struct tc_u32_sel *sel, u8 fshift)
+static __inline__ unsigned u32_hash_fold(__be32 key, struct tc_u32_sel *sel, u8 fshift)
{
unsigned h = ntohl(key & sel->hmask)>>fshift;
@@ -137,7 +137,7 @@ next_knode:
for (i = n->sel.nkeys; i>0; i--, key++) {
- if ((*(u32*)(ptr+key->off+(off2&key->offmask))^key->val)&key->mask) {
+ if ((*(__be32*)(ptr+key->off+(off2&key->offmask))^key->val)&key->mask) {
n = n->next;
goto next_knode;
}
@@ -182,7 +182,7 @@ check_terminal:
ht = n->ht_down;
sel = 0;
if (ht->divisor)
- sel = ht->divisor&u32_hash_fold(*(u32*)(ptr+n->sel.hoff), &n->sel,n->fshift);
+ sel = ht->divisor&u32_hash_fold(*(__be32*)(ptr+n->sel.hoff), &n->sel,n->fshift);
if (!(n->sel.flags&(TC_U32_VAROFFSET|TC_U32_OFFSET|TC_U32_EAT)))
goto next_ht;
@@ -190,7 +190,7 @@ check_terminal:
if (n->sel.flags&(TC_U32_OFFSET|TC_U32_VAROFFSET)) {
off2 = n->sel.off + 3;
if (n->sel.flags&TC_U32_VAROFFSET)
- off2 += ntohs(n->sel.offmask & *(u16*)(ptr+n->sel.offoff)) >>n->sel.offshift;
+ off2 += ntohs(n->sel.offmask & *(__be16*)(ptr+n->sel.offoff)) >>n->sel.offshift;
off2 &= ~3;
}
if (n->sel.flags&TC_U32_EAT) {
diff --git a/net/sched/em_u32.c b/net/sched/em_u32.c
index 112796e4a7c4..953f1479f7da 100644
--- a/net/sched/em_u32.c
+++ b/net/sched/em_u32.c
@@ -35,7 +35,7 @@ static int em_u32_match(struct sk_buff *skb, struct tcf_ematch *em,
if (!tcf_valid_offset(skb, ptr, sizeof(u32)))
return 0;
- return !(((*(u32*) ptr) ^ key->val) & key->mask);
+ return !(((*(__be32*) ptr) ^ key->val) & key->mask);
}
static struct tcf_ematch_ops em_u32_ops = {
diff --git a/net/sched/sch_htb.c b/net/sched/sch_htb.c
index 795c761ad99f..66148cc4759e 100644
--- a/net/sched/sch_htb.c
+++ b/net/sched/sch_htb.c
@@ -711,9 +711,11 @@ static void htb_charge_class(struct htb_sched *q, struct htb_class *cl,
*/
static psched_time_t htb_do_events(struct htb_sched *q, int level)
{
- int i;
-
- for (i = 0; i < 500; i++) {
+ /* don't run for longer than 2 jiffies; 2 is used instead of
+ 1 to simplify things when jiffy is going to be incremented
+ too soon */
+ unsigned long stop_at = jiffies + 2;
+ while (time_before(jiffies, stop_at)) {
struct htb_class *cl;
long diff;
struct rb_node *p = rb_first(&q->wait_pq[level]);
@@ -731,9 +733,8 @@ static psched_time_t htb_do_events(struct htb_sched *q, int level)
if (cl->cmode != HTB_CAN_SEND)
htb_add_to_wait_tree(q, cl, diff);
}
- if (net_ratelimit())
- printk(KERN_WARNING "htb: too many events !\n");
- return q->now + PSCHED_TICKS_PER_SEC / 10;
+ /* too much load - let's continue on next jiffie */
+ return q->now + PSCHED_TICKS_PER_SEC / HZ;
}
/* Returns class->node+prio from id-tree where classe's id is >= id. NULL
diff --git a/net/sctp/bind_addr.c b/net/sctp/bind_addr.c
index a27511ebc4cb..ceefda025e2d 100644
--- a/net/sctp/bind_addr.c
+++ b/net/sctp/bind_addr.c
@@ -209,6 +209,7 @@ int sctp_add_bind_addr(struct sctp_bind_addr *bp, union sctp_addr *new,
int sctp_del_bind_addr(struct sctp_bind_addr *bp, union sctp_addr *del_addr)
{
struct sctp_sockaddr_entry *addr, *temp;
+ int found = 0;
/* We hold the socket lock when calling this function,
* and that acts as a writer synchronizing lock.
@@ -216,13 +217,14 @@ int sctp_del_bind_addr(struct sctp_bind_addr *bp, union sctp_addr *del_addr)
list_for_each_entry_safe(addr, temp, &bp->address_list, list) {
if (sctp_cmp_addr_exact(&addr->a, del_addr)) {
/* Found the exact match. */
+ found = 1;
addr->valid = 0;
list_del_rcu(&addr->list);
break;
}
}
- if (addr && !addr->valid) {
+ if (found) {
call_rcu(&addr->rcu, sctp_local_addr_free);
SCTP_DBG_OBJCNT_DEC(addr);
return 0;
diff --git a/net/sctp/input.c b/net/sctp/input.c
index 57fe2f81eca8..812ff1756c3e 100644
--- a/net/sctp/input.c
+++ b/net/sctp/input.c
@@ -944,7 +944,7 @@ static struct sctp_association *__sctp_rcv_init_lookup(struct sk_buff *skb,
static struct sctp_association *__sctp_rcv_asconf_lookup(
sctp_chunkhdr_t *ch,
const union sctp_addr *laddr,
- __be32 peer_port,
+ __be16 peer_port,
struct sctp_transport **transportp)
{
sctp_addip_chunk_t *asconf = (struct sctp_addip_chunk *)ch;
diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c
index 87f940587d5f..b1e05d719f9b 100644
--- a/net/sctp/ipv6.c
+++ b/net/sctp/ipv6.c
@@ -89,6 +89,7 @@ static int sctp_inet6addr_event(struct notifier_block *this, unsigned long ev,
struct inet6_ifaddr *ifa = (struct inet6_ifaddr *)ptr;
struct sctp_sockaddr_entry *addr = NULL;
struct sctp_sockaddr_entry *temp;
+ int found = 0;
switch (ev) {
case NETDEV_UP:
@@ -111,13 +112,14 @@ static int sctp_inet6addr_event(struct notifier_block *this, unsigned long ev,
&sctp_local_addr_list, list) {
if (ipv6_addr_equal(&addr->a.v6.sin6_addr,
&ifa->addr)) {
+ found = 1;
addr->valid = 0;
list_del_rcu(&addr->list);
break;
}
}
spin_unlock_bh(&sctp_local_addr_lock);
- if (addr && !addr->valid)
+ if (found)
call_rcu(&addr->rcu, sctp_local_addr_free);
break;
}
@@ -1012,15 +1014,24 @@ static struct sctp_pf sctp_pf_inet6 = {
};
/* Initialize IPv6 support and register with socket layer. */
-int sctp_v6_init(void)
+void sctp_v6_pf_init(void)
{
- int rc;
-
/* Register the SCTP specific PF_INET6 functions. */
sctp_register_pf(&sctp_pf_inet6, PF_INET6);
/* Register the SCTP specific AF_INET6 functions. */
sctp_register_af(&sctp_af_inet6);
+}
+
+void sctp_v6_pf_exit(void)
+{
+ list_del(&sctp_af_inet6.list);
+}
+
+/* Initialize IPv6 support and register with socket layer. */
+int sctp_v6_protosw_init(void)
+{
+ int rc;
rc = proto_register(&sctpv6_prot, 1);
if (rc)
@@ -1033,6 +1044,14 @@ int sctp_v6_init(void)
return 0;
}
+void sctp_v6_protosw_exit(void)
+{
+ inet6_unregister_protosw(&sctpv6_seqpacket_protosw);
+ inet6_unregister_protosw(&sctpv6_stream_protosw);
+ proto_unregister(&sctpv6_prot);
+}
+
+
/* Register with inet6 layer. */
int sctp_v6_add_protocol(void)
{
@@ -1045,15 +1064,6 @@ int sctp_v6_add_protocol(void)
return 0;
}
-/* IPv6 specific exit support. */
-void sctp_v6_exit(void)
-{
- inet6_unregister_protosw(&sctpv6_seqpacket_protosw);
- inet6_unregister_protosw(&sctpv6_stream_protosw);
- proto_unregister(&sctpv6_prot);
- list_del(&sctp_af_inet6.list);
-}
-
/* Unregister with inet6 layer. */
void sctp_v6_del_protocol(void)
{
diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c
index 688546dccd82..f90091a1b9ce 100644
--- a/net/sctp/protocol.c
+++ b/net/sctp/protocol.c
@@ -337,14 +337,14 @@ static int sctp_v4_cmp_addr(const union sctp_addr *addr1,
static void sctp_v4_inaddr_any(union sctp_addr *addr, __be16 port)
{
addr->v4.sin_family = AF_INET;
- addr->v4.sin_addr.s_addr = INADDR_ANY;
+ addr->v4.sin_addr.s_addr = htonl(INADDR_ANY);
addr->v4.sin_port = port;
}
/* Is this a wildcard address? */
static int sctp_v4_is_any(const union sctp_addr *addr)
{
- return INADDR_ANY == addr->v4.sin_addr.s_addr;
+ return htonl(INADDR_ANY) == addr->v4.sin_addr.s_addr;
}
/* This function checks if the address is a valid address to be used for
@@ -375,7 +375,7 @@ static int sctp_v4_available(union sctp_addr *addr, struct sctp_sock *sp)
int ret = inet_addr_type(&init_net, addr->v4.sin_addr.s_addr);
- if (addr->v4.sin_addr.s_addr != INADDR_ANY &&
+ if (addr->v4.sin_addr.s_addr != htonl(INADDR_ANY) &&
ret != RTN_LOCAL &&
!sp->inet.freebind &&
!sysctl_ip_nonlocal_bind)
@@ -628,6 +628,7 @@ static int sctp_inetaddr_event(struct notifier_block *this, unsigned long ev,
struct in_ifaddr *ifa = (struct in_ifaddr *)ptr;
struct sctp_sockaddr_entry *addr = NULL;
struct sctp_sockaddr_entry *temp;
+ int found = 0;
switch (ev) {
case NETDEV_UP:
@@ -647,13 +648,14 @@ static int sctp_inetaddr_event(struct notifier_block *this, unsigned long ev,
list_for_each_entry_safe(addr, temp,
&sctp_local_addr_list, list) {
if (addr->a.v4.sin_addr.s_addr == ifa->ifa_local) {
+ found = 1;
addr->valid = 0;
list_del_rcu(&addr->list);
break;
}
}
spin_unlock_bh(&sctp_local_addr_lock);
- if (addr && !addr->valid)
+ if (found)
call_rcu(&addr->rcu, sctp_local_addr_free);
break;
}
@@ -783,8 +785,8 @@ static int sctp_inet_cmp_addr(const union sctp_addr *addr1,
/* PF_INET only supports AF_INET addresses. */
if (addr1->sa.sa_family != addr2->sa.sa_family)
return 0;
- if (INADDR_ANY == addr1->v4.sin_addr.s_addr ||
- INADDR_ANY == addr2->v4.sin_addr.s_addr)
+ if (htonl(INADDR_ANY) == addr1->v4.sin_addr.s_addr ||
+ htonl(INADDR_ANY) == addr2->v4.sin_addr.s_addr)
return 1;
if (addr1->v4.sin_addr.s_addr == addr2->v4.sin_addr.s_addr)
return 1;
@@ -990,6 +992,58 @@ static void cleanup_sctp_mibs(void)
free_percpu(sctp_statistics[1]);
}
+static void sctp_v4_pf_init(void)
+{
+ /* Initialize the SCTP specific PF functions. */
+ sctp_register_pf(&sctp_pf_inet, PF_INET);
+ sctp_register_af(&sctp_af_inet);
+}
+
+static void sctp_v4_pf_exit(void)
+{
+ list_del(&sctp_af_inet.list);
+}
+
+static int sctp_v4_protosw_init(void)
+{
+ int rc;
+
+ rc = proto_register(&sctp_prot, 1);
+ if (rc)
+ return rc;
+
+ /* Register SCTP(UDP and TCP style) with socket layer. */
+ inet_register_protosw(&sctp_seqpacket_protosw);
+ inet_register_protosw(&sctp_stream_protosw);
+
+ return 0;
+}
+
+static void sctp_v4_protosw_exit(void)
+{
+ inet_unregister_protosw(&sctp_stream_protosw);
+ inet_unregister_protosw(&sctp_seqpacket_protosw);
+ proto_unregister(&sctp_prot);
+}
+
+static int sctp_v4_add_protocol(void)
+{
+ /* Register notifier for inet address additions/deletions. */
+ register_inetaddr_notifier(&sctp_inetaddr_notifier);
+
+ /* Register SCTP with inet layer. */
+ if (inet_add_protocol(&sctp_protocol, IPPROTO_SCTP) < 0)
+ return -EAGAIN;
+
+ return 0;
+}
+
+static void sctp_v4_del_protocol(void)
+{
+ inet_del_protocol(&sctp_protocol, IPPROTO_SCTP);
+ unregister_inetaddr_notifier(&sctp_inetaddr_notifier);
+}
+
/* Initialize the universe into something sensible. */
SCTP_STATIC __init int sctp_init(void)
{
@@ -1033,8 +1087,6 @@ SCTP_STATIC __init int sctp_init(void)
/* Initialize object count debugging. */
sctp_dbg_objcnt_init();
- /* Initialize the SCTP specific PF functions. */
- sctp_register_pf(&sctp_pf_inet, PF_INET);
/*
* 14. Suggested SCTP Protocol Parameter Values
*/
@@ -1192,19 +1244,22 @@ SCTP_STATIC __init int sctp_init(void)
sctp_sysctl_register();
INIT_LIST_HEAD(&sctp_address_families);
- sctp_register_af(&sctp_af_inet);
+ sctp_v4_pf_init();
+ sctp_v6_pf_init();
- status = proto_register(&sctp_prot, 1);
- if (status)
- goto err_proto_register;
+ /* Initialize the local address list. */
+ INIT_LIST_HEAD(&sctp_local_addr_list);
+ spin_lock_init(&sctp_local_addr_lock);
+ sctp_get_local_addr_list();
- /* Register SCTP(UDP and TCP style) with socket layer. */
- inet_register_protosw(&sctp_seqpacket_protosw);
- inet_register_protosw(&sctp_stream_protosw);
+ status = sctp_v4_protosw_init();
- status = sctp_v6_init();
if (status)
- goto err_v6_init;
+ goto err_protosw_init;
+
+ status = sctp_v6_protosw_init();
+ if (status)
+ goto err_v6_protosw_init;
/* Initialize the control inode/socket for handling OOTB packets. */
if ((status = sctp_ctl_sock_init())) {
@@ -1213,19 +1268,9 @@ SCTP_STATIC __init int sctp_init(void)
goto err_ctl_sock_init;
}
- /* Initialize the local address list. */
- INIT_LIST_HEAD(&sctp_local_addr_list);
- spin_lock_init(&sctp_local_addr_lock);
- sctp_get_local_addr_list();
-
- /* Register notifier for inet address additions/deletions. */
- register_inetaddr_notifier(&sctp_inetaddr_notifier);
-
- /* Register SCTP with inet layer. */
- if (inet_add_protocol(&sctp_protocol, IPPROTO_SCTP) < 0) {
- status = -EAGAIN;
+ status = sctp_v4_add_protocol();
+ if (status)
goto err_add_protocol;
- }
/* Register SCTP with inet6 layer. */
status = sctp_v6_add_protocol();
@@ -1236,18 +1281,18 @@ SCTP_STATIC __init int sctp_init(void)
out:
return status;
err_v6_add_protocol:
- inet_del_protocol(&sctp_protocol, IPPROTO_SCTP);
- unregister_inetaddr_notifier(&sctp_inetaddr_notifier);
+ sctp_v6_del_protocol();
err_add_protocol:
- sctp_free_local_addr_list();
+ sctp_v4_del_protocol();
sock_release(sctp_ctl_socket);
err_ctl_sock_init:
- sctp_v6_exit();
-err_v6_init:
- inet_unregister_protosw(&sctp_stream_protosw);
- inet_unregister_protosw(&sctp_seqpacket_protosw);
- proto_unregister(&sctp_prot);
-err_proto_register:
+ sctp_v6_protosw_exit();
+err_v6_protosw_init:
+ sctp_v4_protosw_exit();
+err_protosw_init:
+ sctp_free_local_addr_list();
+ sctp_v4_pf_exit();
+ sctp_v6_pf_exit();
sctp_sysctl_unregister();
list_del(&sctp_af_inet.list);
free_pages((unsigned long)sctp_port_hashtable,
@@ -1280,23 +1325,21 @@ SCTP_STATIC __exit void sctp_exit(void)
/* Unregister with inet6/inet layers. */
sctp_v6_del_protocol();
- inet_del_protocol(&sctp_protocol, IPPROTO_SCTP);
-
- /* Unregister notifier for inet address additions/deletions. */
- unregister_inetaddr_notifier(&sctp_inetaddr_notifier);
-
- /* Free the local address list. */
- sctp_free_local_addr_list();
+ sctp_v4_del_protocol();
/* Free the control endpoint. */
sock_release(sctp_ctl_socket);
- /* Cleanup v6 initializations. */
- sctp_v6_exit();
+ /* Free protosw registrations */
+ sctp_v6_protosw_exit();
+ sctp_v4_protosw_exit();
+
+ /* Free the local address list. */
+ sctp_free_local_addr_list();
/* Unregister with socket layer. */
- inet_unregister_protosw(&sctp_stream_protosw);
- inet_unregister_protosw(&sctp_seqpacket_protosw);
+ sctp_v6_pf_exit();
+ sctp_v4_pf_exit();
sctp_sysctl_unregister();
list_del(&sctp_af_inet.list);
@@ -1315,8 +1358,6 @@ SCTP_STATIC __exit void sctp_exit(void)
kmem_cache_destroy(sctp_chunk_cachep);
kmem_cache_destroy(sctp_bucket_cachep);
-
- proto_unregister(&sctp_prot);
}
module_init(sctp_init);
diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c
index e45be4e3f80d..578630e8e00d 100644
--- a/net/sctp/sm_make_chunk.c
+++ b/net/sctp/sm_make_chunk.c
@@ -2375,6 +2375,14 @@ static int sctp_process_param(struct sctp_association *asoc,
asoc->peer.ipv4_address = 0;
asoc->peer.ipv6_address = 0;
+ /* Assume that peer supports the address family
+ * by which it sends a packet.
+ */
+ if (peer_addr->sa.sa_family == AF_INET6)
+ asoc->peer.ipv6_address = 1;
+ else if (peer_addr->sa.sa_family == AF_INET)
+ asoc->peer.ipv4_address = 1;
+
/* Cycle through address types; avoid divide by 0. */
sat = ntohs(param.p->length) - sizeof(sctp_paramhdr_t);
if (sat)
diff --git a/net/sctp/socket.c b/net/sctp/socket.c
index 939892691a26..d994d822900d 100644
--- a/net/sctp/socket.c
+++ b/net/sctp/socket.c
@@ -2933,17 +2933,39 @@ static int sctp_setsockopt_maxburst(struct sock *sk,
char __user *optval,
int optlen)
{
+ struct sctp_assoc_value params;
+ struct sctp_sock *sp;
+ struct sctp_association *asoc;
int val;
+ int assoc_id = 0;
- if (optlen != sizeof(int))
+ if (optlen < sizeof(int))
return -EINVAL;
- if (get_user(val, (int __user *)optval))
- return -EFAULT;
- if (val < 0)
+ if (optlen == sizeof(int)) {
+ printk(KERN_WARNING
+ "SCTP: Use of int in max_burst socket option deprecated\n");
+ printk(KERN_WARNING
+ "SCTP: Use struct sctp_assoc_value instead\n");
+ if (copy_from_user(&val, optval, optlen))
+ return -EFAULT;
+ } else if (optlen == sizeof(struct sctp_assoc_value)) {
+ if (copy_from_user(&params, optval, optlen))
+ return -EFAULT;
+ val = params.assoc_value;
+ assoc_id = params.assoc_id;
+ } else
return -EINVAL;
- sctp_sk(sk)->max_burst = val;
+ sp = sctp_sk(sk);
+
+ if (assoc_id != 0) {
+ asoc = sctp_id2assoc(sk, assoc_id);
+ if (!asoc)
+ return -EINVAL;
+ asoc->max_burst = val;
+ } else
+ sp->max_burst = val;
return 0;
}
@@ -5005,20 +5027,45 @@ static int sctp_getsockopt_maxburst(struct sock *sk, int len,
char __user *optval,
int __user *optlen)
{
- int val;
+ struct sctp_assoc_value params;
+ struct sctp_sock *sp;
+ struct sctp_association *asoc;
if (len < sizeof(int))
return -EINVAL;
- len = sizeof(int);
+ if (len == sizeof(int)) {
+ printk(KERN_WARNING
+ "SCTP: Use of int in max_burst socket option deprecated\n");
+ printk(KERN_WARNING
+ "SCTP: Use struct sctp_assoc_value instead\n");
+ params.assoc_id = 0;
+ } else if (len == sizeof (struct sctp_assoc_value)) {
+ if (copy_from_user(&params, optval, len))
+ return -EFAULT;
+ } else
+ return -EINVAL;
- val = sctp_sk(sk)->max_burst;
- if (put_user(len, optlen))
- return -EFAULT;
- if (copy_to_user(optval, &val, len))
- return -EFAULT;
+ sp = sctp_sk(sk);
+
+ if (params.assoc_id != 0) {
+ asoc = sctp_id2assoc(sk, params.assoc_id);
+ if (!asoc)
+ return -EINVAL;
+ params.assoc_value = asoc->max_burst;
+ } else
+ params.assoc_value = sp->max_burst;
+
+ if (len == sizeof(int)) {
+ if (copy_to_user(optval, &params.assoc_value, len))
+ return -EFAULT;
+ } else {
+ if (copy_to_user(optval, &params, len))
+ return -EFAULT;
+ }
+
+ return 0;
- return -ENOTSUPP;
}
static int sctp_getsockopt_hmac_ident(struct sock *sk, int len,
diff --git a/net/socket.c b/net/socket.c
index b6d35cd72a50..9d3fbfbc8535 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -909,11 +909,10 @@ static long sock_ioctl(struct file *file, unsigned cmd, unsigned long arg)
if (!dlci_ioctl_hook)
request_module("dlci");
- if (dlci_ioctl_hook) {
- mutex_lock(&dlci_ioctl_mutex);
+ mutex_lock(&dlci_ioctl_mutex);
+ if (dlci_ioctl_hook)
err = dlci_ioctl_hook(cmd, argp);
- mutex_unlock(&dlci_ioctl_mutex);
- }
+ mutex_unlock(&dlci_ioctl_mutex);
break;
default:
err = sock->ops->ioctl(sock, cmd, arg);
diff --git a/net/sunrpc/auth_gss/gss_mech_switch.c b/net/sunrpc/auth_gss/gss_mech_switch.c
index 61801a069ff0..bce9d527af08 100644
--- a/net/sunrpc/auth_gss/gss_mech_switch.c
+++ b/net/sunrpc/auth_gss/gss_mech_switch.c
@@ -317,7 +317,7 @@ gss_delete_sec_context(struct gss_ctx **context_handle)
if (!*context_handle)
return(GSS_S_NO_CONTEXT);
- if ((*context_handle)->internal_ctx_id != 0)
+ if ((*context_handle)->internal_ctx_id)
(*context_handle)->mech_type->gm_ops
->gss_delete_sec_context((*context_handle)
->internal_ctx_id);
diff --git a/net/sunrpc/svc_xprt.c b/net/sunrpc/svc_xprt.c
index ea377e06afae..332eb47539e1 100644
--- a/net/sunrpc/svc_xprt.c
+++ b/net/sunrpc/svc_xprt.c
@@ -185,7 +185,7 @@ int svc_create_xprt(struct svc_serv *serv, char *xprt_name, unsigned short port,
struct svc_xprt_class *xcl;
struct sockaddr_in sin = {
.sin_family = AF_INET,
- .sin_addr.s_addr = INADDR_ANY,
+ .sin_addr.s_addr = htonl(INADDR_ANY),
.sin_port = htons(port),
};
dprintk("svc: creating transport %s[%d]\n", xprt_name, port);
diff --git a/net/sunrpc/xprtrdma/svc_rdma_recvfrom.c b/net/sunrpc/xprtrdma/svc_rdma_recvfrom.c
index ab54a736486e..c22d6b6f2db4 100644
--- a/net/sunrpc/xprtrdma/svc_rdma_recvfrom.c
+++ b/net/sunrpc/xprtrdma/svc_rdma_recvfrom.c
@@ -237,14 +237,12 @@ static void rdma_set_ctxt_sge(struct svc_rdma_op_ctxt *ctxt,
static int rdma_read_max_sge(struct svcxprt_rdma *xprt, int sge_count)
{
-#ifdef RDMA_TRANSPORT_IWARP
if ((RDMA_TRANSPORT_IWARP ==
rdma_node_get_transport(xprt->sc_cm_id->
device->node_type))
&& sge_count > 1)
return 1;
else
-#endif
return min_t(int, sge_count, xprt->sc_max_sge);
}
@@ -324,15 +322,6 @@ next_sge:
ctxt->direction = DMA_FROM_DEVICE;
clear_bit(RDMACTXT_F_READ_DONE, &ctxt->flags);
clear_bit(RDMACTXT_F_LAST_CTXT, &ctxt->flags);
- if ((ch+1)->rc_discrim == 0) {
- /*
- * Checked in sq_cq_reap to see if we need to
- * be enqueued
- */
- set_bit(RDMACTXT_F_LAST_CTXT, &ctxt->flags);
- ctxt->next = hdr_ctxt;
- hdr_ctxt->next = head;
- }
/* Prepare READ WR */
memset(&read_wr, 0, sizeof read_wr);
@@ -350,7 +339,17 @@ next_sge:
rdma_set_ctxt_sge(ctxt, &sge[ch_sge_ary[ch_no].start],
&sgl_offset,
read_wr.num_sge);
-
+ if (((ch+1)->rc_discrim == 0) &&
+ (read_wr.num_sge == ch_sge_ary[ch_no].count)) {
+ /*
+ * Mark the last RDMA_READ with a bit to
+ * indicate all RPC data has been fetched from
+ * the client and the RPC needs to be enqueued.
+ */
+ set_bit(RDMACTXT_F_LAST_CTXT, &ctxt->flags);
+ ctxt->next = hdr_ctxt;
+ hdr_ctxt->next = head;
+ }
/* Post the read */
err = svc_rdma_send(xprt, &read_wr);
if (err) {
diff --git a/net/sunrpc/xprtrdma/svc_rdma_sendto.c b/net/sunrpc/xprtrdma/svc_rdma_sendto.c
index 0598b229c11d..981f190c1b39 100644
--- a/net/sunrpc/xprtrdma/svc_rdma_sendto.c
+++ b/net/sunrpc/xprtrdma/svc_rdma_sendto.c
@@ -156,7 +156,7 @@ static int send_write(struct svcxprt_rdma *xprt, struct svc_rqst *rqstp,
struct svc_rdma_op_ctxt *ctxt;
int ret = 0;
- BUG_ON(sge_count >= 32);
+ BUG_ON(sge_count > RPCSVC_MAXPAGES);
dprintk("svcrdma: RDMA_WRITE rmr=%x, to=%llx, xdr_off=%d, "
"write_len=%d, xdr_sge=%p, sge_count=%d\n",
rmr, (unsigned long long)to, xdr_off,
diff --git a/net/sunrpc/xprtrdma/svc_rdma_transport.c b/net/sunrpc/xprtrdma/svc_rdma_transport.c
index f09444c451bc..16fd3f6718ff 100644
--- a/net/sunrpc/xprtrdma/svc_rdma_transport.c
+++ b/net/sunrpc/xprtrdma/svc_rdma_transport.c
@@ -54,7 +54,6 @@ static struct svc_xprt *svc_rdma_create(struct svc_serv *serv,
int flags);
static struct svc_xprt *svc_rdma_accept(struct svc_xprt *xprt);
static void svc_rdma_release_rqst(struct svc_rqst *);
-static void rdma_destroy_xprt(struct svcxprt_rdma *xprt);
static void dto_tasklet_func(unsigned long data);
static void svc_rdma_detach(struct svc_xprt *xprt);
static void svc_rdma_free(struct svc_xprt *xprt);
@@ -247,6 +246,7 @@ static void dto_tasklet_func(unsigned long data)
sq_cq_reap(xprt);
}
+ svc_xprt_put(&xprt->sc_xprt);
spin_lock_irqsave(&dto_lock, flags);
}
spin_unlock_irqrestore(&dto_lock, flags);
@@ -275,8 +275,10 @@ static void rq_comp_handler(struct ib_cq *cq, void *cq_context)
* add it
*/
spin_lock_irqsave(&dto_lock, flags);
- if (list_empty(&xprt->sc_dto_q))
+ if (list_empty(&xprt->sc_dto_q)) {
+ svc_xprt_get(&xprt->sc_xprt);
list_add_tail(&xprt->sc_dto_q, &dto_xprt_q);
+ }
spin_unlock_irqrestore(&dto_lock, flags);
/* Tasklet does all the work to avoid irqsave locks. */
@@ -386,8 +388,10 @@ static void sq_comp_handler(struct ib_cq *cq, void *cq_context)
* add it
*/
spin_lock_irqsave(&dto_lock, flags);
- if (list_empty(&xprt->sc_dto_q))
+ if (list_empty(&xprt->sc_dto_q)) {
+ svc_xprt_get(&xprt->sc_xprt);
list_add_tail(&xprt->sc_dto_q, &dto_xprt_q);
+ }
spin_unlock_irqrestore(&dto_lock, flags);
/* Tasklet does all the work to avoid irqsave locks. */
@@ -611,6 +615,7 @@ static int rdma_cma_handler(struct rdma_cm_id *cma_id,
switch (event->event) {
case RDMA_CM_EVENT_ESTABLISHED:
/* Accept complete */
+ svc_xprt_get(xprt);
dprintk("svcrdma: Connection completed on DTO xprt=%p, "
"cm_id=%p\n", xprt, cma_id);
clear_bit(RDMAXPRT_CONN_PENDING, &rdma->sc_flags);
@@ -661,15 +666,15 @@ static struct svc_xprt *svc_rdma_create(struct svc_serv *serv,
listen_id = rdma_create_id(rdma_listen_handler, cma_xprt, RDMA_PS_TCP);
if (IS_ERR(listen_id)) {
- rdma_destroy_xprt(cma_xprt);
+ svc_xprt_put(&cma_xprt->sc_xprt);
dprintk("svcrdma: rdma_create_id failed = %ld\n",
PTR_ERR(listen_id));
return (void *)listen_id;
}
ret = rdma_bind_addr(listen_id, sa);
if (ret) {
- rdma_destroy_xprt(cma_xprt);
rdma_destroy_id(listen_id);
+ svc_xprt_put(&cma_xprt->sc_xprt);
dprintk("svcrdma: rdma_bind_addr failed = %d\n", ret);
return ERR_PTR(ret);
}
@@ -678,8 +683,9 @@ static struct svc_xprt *svc_rdma_create(struct svc_serv *serv,
ret = rdma_listen(listen_id, RPCRDMA_LISTEN_BACKLOG);
if (ret) {
rdma_destroy_id(listen_id);
- rdma_destroy_xprt(cma_xprt);
+ svc_xprt_put(&cma_xprt->sc_xprt);
dprintk("svcrdma: rdma_listen failed = %d\n", ret);
+ return ERR_PTR(ret);
}
/*
@@ -820,6 +826,7 @@ static struct svc_xprt *svc_rdma_accept(struct svc_xprt *xprt)
newxprt->sc_sq_depth = qp_attr.cap.max_send_wr;
newxprt->sc_max_requests = qp_attr.cap.max_recv_wr;
}
+ svc_xprt_get(&newxprt->sc_xprt);
newxprt->sc_qp = newxprt->sc_cm_id->qp;
/* Register all of physical memory */
@@ -891,8 +898,15 @@ static struct svc_xprt *svc_rdma_accept(struct svc_xprt *xprt)
errout:
dprintk("svcrdma: failure accepting new connection rc=%d.\n", ret);
+ /* Take a reference in case the DTO handler runs */
+ svc_xprt_get(&newxprt->sc_xprt);
+ if (newxprt->sc_qp && !IS_ERR(newxprt->sc_qp)) {
+ ib_destroy_qp(newxprt->sc_qp);
+ svc_xprt_put(&newxprt->sc_xprt);
+ }
rdma_destroy_id(newxprt->sc_cm_id);
- rdma_destroy_xprt(newxprt);
+ /* This call to put will destroy the transport */
+ svc_xprt_put(&newxprt->sc_xprt);
return NULL;
}
@@ -919,54 +933,60 @@ static void svc_rdma_release_rqst(struct svc_rqst *rqstp)
rqstp->rq_xprt_ctxt = NULL;
}
-/* Disable data ready events for this connection */
+/*
+ * When connected, an svc_xprt has at least three references:
+ *
+ * - A reference held by the QP. We still hold that here because this
+ * code deletes the QP and puts the reference.
+ *
+ * - A reference held by the cm_id between the ESTABLISHED and
+ * DISCONNECTED events. If the remote peer disconnected first, this
+ * reference could be gone.
+ *
+ * - A reference held by the svc_recv code that called this function
+ * as part of close processing.
+ *
+ * At a minimum two references should still be held.
+ */
static void svc_rdma_detach(struct svc_xprt *xprt)
{
struct svcxprt_rdma *rdma =
container_of(xprt, struct svcxprt_rdma, sc_xprt);
- unsigned long flags;
-
dprintk("svc: svc_rdma_detach(%p)\n", xprt);
- /*
- * Shutdown the connection. This will ensure we don't get any
- * more events from the provider.
- */
+
+ /* Disconnect and flush posted WQE */
rdma_disconnect(rdma->sc_cm_id);
- rdma_destroy_id(rdma->sc_cm_id);
- /* We may already be on the DTO list */
- spin_lock_irqsave(&dto_lock, flags);
- if (!list_empty(&rdma->sc_dto_q))
- list_del_init(&rdma->sc_dto_q);
- spin_unlock_irqrestore(&dto_lock, flags);
+ /* Destroy the QP if present (not a listener) */
+ if (rdma->sc_qp && !IS_ERR(rdma->sc_qp)) {
+ ib_destroy_qp(rdma->sc_qp);
+ svc_xprt_put(xprt);
+ }
+
+ /* Destroy the CM ID */
+ rdma_destroy_id(rdma->sc_cm_id);
}
static void svc_rdma_free(struct svc_xprt *xprt)
{
struct svcxprt_rdma *rdma = (struct svcxprt_rdma *)xprt;
dprintk("svcrdma: svc_rdma_free(%p)\n", rdma);
- rdma_destroy_xprt(rdma);
- kfree(rdma);
-}
-
-static void rdma_destroy_xprt(struct svcxprt_rdma *xprt)
-{
- if (xprt->sc_qp && !IS_ERR(xprt->sc_qp))
- ib_destroy_qp(xprt->sc_qp);
-
- if (xprt->sc_sq_cq && !IS_ERR(xprt->sc_sq_cq))
- ib_destroy_cq(xprt->sc_sq_cq);
+ /* We should only be called from kref_put */
+ BUG_ON(atomic_read(&xprt->xpt_ref.refcount) != 0);
+ if (rdma->sc_sq_cq && !IS_ERR(rdma->sc_sq_cq))
+ ib_destroy_cq(rdma->sc_sq_cq);
- if (xprt->sc_rq_cq && !IS_ERR(xprt->sc_rq_cq))
- ib_destroy_cq(xprt->sc_rq_cq);
+ if (rdma->sc_rq_cq && !IS_ERR(rdma->sc_rq_cq))
+ ib_destroy_cq(rdma->sc_rq_cq);
- if (xprt->sc_phys_mr && !IS_ERR(xprt->sc_phys_mr))
- ib_dereg_mr(xprt->sc_phys_mr);
+ if (rdma->sc_phys_mr && !IS_ERR(rdma->sc_phys_mr))
+ ib_dereg_mr(rdma->sc_phys_mr);
- if (xprt->sc_pd && !IS_ERR(xprt->sc_pd))
- ib_dealloc_pd(xprt->sc_pd);
+ if (rdma->sc_pd && !IS_ERR(rdma->sc_pd))
+ ib_dealloc_pd(rdma->sc_pd);
- destroy_context_cache(xprt->sc_ctxt_head);
+ destroy_context_cache(rdma->sc_ctxt_head);
+ kfree(rdma);
}
static int svc_rdma_has_wspace(struct svc_xprt *xprt)
diff --git a/net/xfrm/xfrm_input.c b/net/xfrm/xfrm_input.c
index 62188c6a06dd..75279402ccf4 100644
--- a/net/xfrm/xfrm_input.c
+++ b/net/xfrm/xfrm_input.c
@@ -84,14 +84,21 @@ int xfrm_parse_spi(struct sk_buff *skb, u8 nexthdr, __be32 *spi, __be32 *seq)
int xfrm_prepare_input(struct xfrm_state *x, struct sk_buff *skb)
{
+ struct xfrm_mode *inner_mode = x->inner_mode;
int err;
err = x->outer_mode->afinfo->extract_input(x, skb);
if (err)
return err;
- skb->protocol = x->inner_mode->afinfo->eth_proto;
- return x->inner_mode->input2(x, skb);
+ if (x->sel.family == AF_UNSPEC) {
+ inner_mode = xfrm_ip2inner_mode(x, XFRM_MODE_SKB_CB(skb)->protocol);
+ if (inner_mode == NULL)
+ return -EAFNOSUPPORT;
+ }
+
+ skb->protocol = inner_mode->afinfo->eth_proto;
+ return inner_mode->input2(x, skb);
}
EXPORT_SYMBOL(xfrm_prepare_input);
@@ -101,6 +108,7 @@ int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type)
__be32 seq;
struct xfrm_state *x;
xfrm_address_t *daddr;
+ struct xfrm_mode *inner_mode;
unsigned int family;
int decaps = 0;
int async = 0;
@@ -207,7 +215,15 @@ resume:
XFRM_MODE_SKB_CB(skb)->protocol = nexthdr;
- if (x->inner_mode->input(x, skb)) {
+ inner_mode = x->inner_mode;
+
+ if (x->sel.family == AF_UNSPEC) {
+ inner_mode = xfrm_ip2inner_mode(x, XFRM_MODE_SKB_CB(skb)->protocol);
+ if (inner_mode == NULL)
+ goto drop;
+ }
+
+ if (inner_mode->input(x, skb)) {
XFRM_INC_STATS(LINUX_MIB_XFRMINSTATEMODEERROR);
goto drop;
}
diff --git a/net/xfrm/xfrm_output.c b/net/xfrm/xfrm_output.c
index 569d377932c4..2519129c6d21 100644
--- a/net/xfrm/xfrm_output.c
+++ b/net/xfrm/xfrm_output.c
@@ -124,7 +124,7 @@ int xfrm_output_resume(struct sk_buff *skb, int err)
if (!x)
return dst_output(skb);
- err = nf_hook(x->inner_mode->afinfo->family,
+ err = nf_hook(skb->dst->ops->family,
NF_INET_POST_ROUTING, skb,
NULL, skb->dst->dev, xfrm_output2);
if (unlikely(err != 1))
@@ -193,4 +193,20 @@ int xfrm_output(struct sk_buff *skb)
return xfrm_output2(skb);
}
+
+int xfrm_inner_extract_output(struct xfrm_state *x, struct sk_buff *skb)
+{
+ struct xfrm_mode *inner_mode;
+ if (x->sel.family == AF_UNSPEC)
+ inner_mode = xfrm_ip2inner_mode(x,
+ xfrm_af2proto(skb->dst->ops->family));
+ else
+ inner_mode = x->inner_mode;
+
+ if (inner_mode == NULL)
+ return -EAFNOSUPPORT;
+ return inner_mode->afinfo->extract_output(x, skb);
+}
+
EXPORT_SYMBOL_GPL(xfrm_output);
+EXPORT_SYMBOL_GPL(xfrm_inner_extract_output);
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c
index 7ba65e82941c..58f1f9347b54 100644
--- a/net/xfrm/xfrm_state.c
+++ b/net/xfrm/xfrm_state.c
@@ -388,6 +388,8 @@ static void xfrm_state_gc_destroy(struct xfrm_state *x)
kfree(x->coaddr);
if (x->inner_mode)
xfrm_put_mode(x->inner_mode);
+ if (x->inner_mode_iaf)
+ xfrm_put_mode(x->inner_mode_iaf);
if (x->outer_mode)
xfrm_put_mode(x->outer_mode);
if (x->type) {
@@ -523,6 +525,8 @@ struct xfrm_state *xfrm_state_alloc(void)
x->lft.hard_packet_limit = XFRM_INF;
x->replay_maxage = 0;
x->replay_maxdiff = 0;
+ x->inner_mode = NULL;
+ x->inner_mode_iaf = NULL;
spin_lock_init(&x->lock);
}
return x;
@@ -796,7 +800,7 @@ xfrm_state_find(xfrm_address_t *daddr, xfrm_address_t *saddr,
selector.
*/
if (x->km.state == XFRM_STATE_VALID) {
- if (!xfrm_selector_match(&x->sel, fl, x->sel.family) ||
+ if ((x->sel.family && !xfrm_selector_match(&x->sel, fl, x->sel.family)) ||
!security_xfrm_state_pol_flow_match(x, pol, fl))
continue;
if (!best ||
@@ -1944,6 +1948,7 @@ int xfrm_state_mtu(struct xfrm_state *x, int mtu)
int xfrm_init_state(struct xfrm_state *x)
{
struct xfrm_state_afinfo *afinfo;
+ struct xfrm_mode *inner_mode;
int family = x->props.family;
int err;
@@ -1962,13 +1967,48 @@ int xfrm_init_state(struct xfrm_state *x)
goto error;
err = -EPROTONOSUPPORT;
- x->inner_mode = xfrm_get_mode(x->props.mode, x->sel.family);
- if (x->inner_mode == NULL)
- goto error;
- if (!(x->inner_mode->flags & XFRM_MODE_FLAG_TUNNEL) &&
- family != x->sel.family)
- goto error;
+ if (x->sel.family != AF_UNSPEC) {
+ inner_mode = xfrm_get_mode(x->props.mode, x->sel.family);
+ if (inner_mode == NULL)
+ goto error;
+
+ if (!(inner_mode->flags & XFRM_MODE_FLAG_TUNNEL) &&
+ family != x->sel.family) {
+ xfrm_put_mode(inner_mode);
+ goto error;
+ }
+
+ x->inner_mode = inner_mode;
+ } else {
+ struct xfrm_mode *inner_mode_iaf;
+
+ inner_mode = xfrm_get_mode(x->props.mode, AF_INET);
+ if (inner_mode == NULL)
+ goto error;
+
+ if (!(inner_mode->flags & XFRM_MODE_FLAG_TUNNEL)) {
+ xfrm_put_mode(inner_mode);
+ goto error;
+ }
+
+ inner_mode_iaf = xfrm_get_mode(x->props.mode, AF_INET6);
+ if (inner_mode_iaf == NULL)
+ goto error;
+
+ if (!(inner_mode_iaf->flags & XFRM_MODE_FLAG_TUNNEL)) {
+ xfrm_put_mode(inner_mode_iaf);
+ goto error;
+ }
+
+ if (x->props.family == AF_INET) {
+ x->inner_mode = inner_mode;
+ x->inner_mode_iaf = inner_mode_iaf;
+ } else {
+ x->inner_mode = inner_mode_iaf;
+ x->inner_mode_iaf = inner_mode;
+ }
+ }
x->type = xfrm_get_type(x->id.proto, family);
if (x->type == NULL)
diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c
index f971ca5645f8..5d96f2728dc6 100644
--- a/net/xfrm/xfrm_user.c
+++ b/net/xfrm/xfrm_user.c
@@ -288,12 +288,9 @@ static void copy_from_user_state(struct xfrm_state *x, struct xfrm_usersa_info *
memcpy(&x->props.saddr, &p->saddr, sizeof(x->props.saddr));
x->props.flags = p->flags;
- /*
- * Set inner address family if the KM left it as zero.
- * See comment in validate_tmpl.
- */
- if (!x->sel.family)
+ if (x->props.mode == XFRM_MODE_TRANSPORT)
x->sel.family = p->family;
+
}
/*