summaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorJames Bottomley <jejb@mulgrave.il.steeleye.com>2006-11-22 12:06:44 -0600
committerJames Bottomley <jejb@mulgrave.il.steeleye.com>2006-11-22 12:06:44 -0600
commit0bd2af46839ad6262d25714a6ec0365db9d6b98f (patch)
treedcced72d230d69fd0c5816ac6dd03ab84799a93e /net
parente138a5d2356729b8752e88520cc1525fae9794ac (diff)
parentf26b90440cd74c78fe10c9bd5160809704a9627c (diff)
downloadblackbird-op-linux-0bd2af46839ad6262d25714a6ec0365db9d6b98f.tar.gz
blackbird-op-linux-0bd2af46839ad6262d25714a6ec0365db9d6b98f.zip
Merge ../scsi-rc-fixes-2.6
Diffstat (limited to 'net')
-rw-r--r--net/Kconfig3
-rw-r--r--net/appletalk/ddp.c2
-rw-r--r--net/atm/atm_sysfs.c15
-rw-r--r--net/bluetooth/af_bluetooth.c38
-rw-r--r--net/bluetooth/bnep/core.c4
-rw-r--r--net/bluetooth/bnep/sock.c69
-rw-r--r--net/bluetooth/cmtp/sock.c35
-rw-r--r--net/bluetooth/hci_conn.c6
-rw-r--r--net/bluetooth/hci_event.c34
-rw-r--r--net/bluetooth/hci_sock.c13
-rw-r--r--net/bluetooth/hci_sysfs.c21
-rw-r--r--net/bluetooth/hidp/core.c14
-rw-r--r--net/bluetooth/hidp/sock.c80
-rw-r--r--net/bluetooth/l2cap.c16
-rw-r--r--net/bluetooth/rfcomm/core.c3
-rw-r--r--net/bluetooth/rfcomm/sock.c6
-rw-r--r--net/bluetooth/rfcomm/tty.c7
-rw-r--r--net/bluetooth/sco.c6
-rw-r--r--net/bridge/br_fdb.c7
-rw-r--r--net/bridge/br_if.c4
-rw-r--r--net/bridge/br_private.h2
-rw-r--r--net/bridge/br_stp_if.c2
-rw-r--r--net/bridge/br_sysfs_br.c2
-rw-r--r--net/bridge/netfilter/ebtables.c2
-rw-r--r--net/compat.c3
-rw-r--r--net/core/dev.c2
-rw-r--r--net/core/flow.c42
-rw-r--r--net/core/netpoll.c14
-rw-r--r--net/core/pktgen.c30
-rw-r--r--net/core/rtnetlink.c2
-rw-r--r--net/core/scm.c3
-rw-r--r--net/core/skbuff.c10
-rw-r--r--net/core/sock.c4
-rw-r--r--net/core/utils.c116
-rw-r--r--net/core/wireless.c33
-rw-r--r--net/dccp/Kconfig6
-rw-r--r--net/dccp/ackvec.c12
-rw-r--r--net/dccp/ackvec.h3
-rw-r--r--net/dccp/ccids/Kconfig17
-rw-r--r--net/dccp/ccids/ccid2.c20
-rw-r--r--net/dccp/ccids/ccid3.c3
-rw-r--r--net/dccp/dccp.h2
-rw-r--r--net/dccp/input.c4
-rw-r--r--net/dccp/ipv4.c14
-rw-r--r--net/dccp/ipv6.c22
-rw-r--r--net/dccp/options.c2
-rw-r--r--net/decnet/af_decnet.c29
-rw-r--r--net/decnet/dn_nsp_in.c8
-rw-r--r--net/decnet/dn_nsp_out.c2
-rw-r--r--net/decnet/dn_route.c14
-rw-r--r--net/decnet/dn_rules.c4
-rw-r--r--net/ieee80211/Kconfig2
-rw-r--r--net/ieee80211/ieee80211_rx.c12
-rw-r--r--net/ieee80211/softmac/ieee80211softmac_assoc.c56
-rw-r--r--net/ieee80211/softmac/ieee80211softmac_io.c11
-rw-r--r--net/ieee80211/softmac/ieee80211softmac_module.c1
-rw-r--r--net/ieee80211/softmac/ieee80211softmac_wx.c71
-rw-r--r--net/ipv4/cipso_ipv4.c47
-rw-r--r--net/ipv4/fib_frontend.c5
-rw-r--r--net/ipv4/inetpeer.c29
-rw-r--r--net/ipv4/ip_gre.c4
-rw-r--r--net/ipv4/ip_options.c2
-rw-r--r--net/ipv4/ipconfig.c2
-rw-r--r--net/ipv4/ipvs/ip_vs_ftp.c2
-rw-r--r--net/ipv4/ipvs/ip_vs_proto_tcp.c2
-rw-r--r--net/ipv4/ipvs/ip_vs_proto_udp.c8
-rw-r--r--net/ipv4/netfilter/arp_tables.c27
-rw-r--r--net/ipv4/netfilter/ip_conntrack_netlink.c72
-rw-r--r--net/ipv4/netfilter/ip_queue.c7
-rw-r--r--net/ipv4/netfilter/ip_tables.c70
-rw-r--r--net/ipv4/netfilter/ipt_ECN.c6
-rw-r--r--net/ipv4/netfilter/ipt_TOS.c6
-rw-r--r--net/ipv4/raw.c17
-rw-r--r--net/ipv4/route.c12
-rw-r--r--net/ipv4/sysctl_net_ipv4.c7
-rw-r--r--net/ipv4/tcp.c11
-rw-r--r--net/ipv4/tcp_cong.c8
-rw-r--r--net/ipv4/tcp_cubic.c6
-rw-r--r--net/ipv4/tcp_htcp.c2
-rw-r--r--net/ipv4/tcp_ipv4.c20
-rw-r--r--net/ipv4/tcp_output.c51
-rw-r--r--net/ipv4/xfrm4_policy.c2
-rw-r--r--net/ipv6/Kconfig29
-rw-r--r--net/ipv6/Makefile3
-rw-r--r--net/ipv6/addrconf.c18
-rw-r--r--net/ipv6/af_inet6.c2
-rw-r--r--net/ipv6/fib6_rules.c11
-rw-r--r--net/ipv6/ip6_fib.c9
-rw-r--r--net/ipv6/ip6_flowlabel.c24
-rw-r--r--net/ipv6/ip6_tunnel.c19
-rw-r--r--net/ipv6/ndisc.c3
-rw-r--r--net/ipv6/netfilter/Kconfig2
-rw-r--r--net/ipv6/netfilter/ip6_queue.c7
-rw-r--r--net/ipv6/netfilter/ip6_tables.c47
-rw-r--r--net/ipv6/netfilter/ip6t_ah.c7
-rw-r--r--net/ipv6/netfilter/ip6t_frag.c7
-rw-r--r--net/ipv6/netfilter/ip6t_hbh.c7
-rw-r--r--net/ipv6/netfilter/ip6t_rt.c7
-rw-r--r--net/ipv6/raw.c17
-rw-r--r--net/ipv6/route.c81
-rw-r--r--net/ipv6/sit.c5
-rw-r--r--net/ipv6/tcp_ipv6.c13
-rw-r--r--net/ipv6/udp.c7
-rw-r--r--net/ipv6/xfrm6_policy.c14
-rw-r--r--net/ipv6/xfrm6_tunnel.c4
-rw-r--r--net/ipx/af_ipx.c85
-rw-r--r--net/ipx/ipx_proc.c12
-rw-r--r--net/ipx/ipx_route.c14
-rw-r--r--net/irda/irlmp.c3
-rw-r--r--net/key/af_key.c5
-rw-r--r--net/netfilter/Kconfig4
-rw-r--r--net/netfilter/nf_conntrack_core.c3
-rw-r--r--net/netfilter/nf_conntrack_netlink.c72
-rw-r--r--net/netfilter/nfnetlink_log.c10
-rw-r--r--net/netfilter/nfnetlink_queue.c9
-rw-r--r--net/netfilter/xt_NFQUEUE.c2
-rw-r--r--net/netfilter/xt_connmark.c2
-rw-r--r--net/netlabel/Kconfig2
-rw-r--r--net/netlabel/netlabel_kapi.c2
-rw-r--r--net/netlink/af_netlink.c5
-rw-r--r--net/sched/sch_htb.c11
-rw-r--r--net/sched/sch_netem.c4
-rw-r--r--net/sctp/associola.c15
-rw-r--r--net/sctp/endpointola.c7
-rw-r--r--net/sctp/input.c9
-rw-r--r--net/sctp/ipv6.c10
-rw-r--r--net/sctp/proc.c2
-rw-r--r--net/sctp/protocol.c2
-rw-r--r--net/sctp/socket.c33
-rw-r--r--net/sctp/ulpevent.c25
-rw-r--r--net/sctp/ulpqueue.c2
-rw-r--r--net/sunrpc/pmap_clnt.c14
-rw-r--r--net/sunrpc/svc.c5
-rw-r--r--net/sunrpc/svcauth.c5
-rw-r--r--net/sunrpc/svcsock.c33
-rw-r--r--net/sunrpc/xprtsock.c2
-rw-r--r--net/tipc/bearer.c8
-rw-r--r--net/tipc/config.c5
-rw-r--r--net/tipc/core.c4
-rw-r--r--net/tipc/core.h30
-rw-r--r--net/tipc/dbg.c136
-rw-r--r--net/tipc/dbg.h15
-rw-r--r--net/tipc/discover.c39
-rw-r--r--net/tipc/link.c8
-rw-r--r--net/tipc/name_distr.c2
-rw-r--r--net/tipc/node.c2
-rw-r--r--net/tipc/port.c12
-rw-r--r--net/tipc/socket.c13
-rw-r--r--net/tipc/subscr.c99
-rw-r--r--net/xfrm/xfrm_policy.c101
-rw-r--r--net/xfrm/xfrm_state.c19
-rw-r--r--net/xfrm/xfrm_user.c26
152 files changed, 1604 insertions, 1057 deletions
diff --git a/net/Kconfig b/net/Kconfig
index a81aca43932f..67e39ad8b8b6 100644
--- a/net/Kconfig
+++ b/net/Kconfig
@@ -63,6 +63,7 @@ config INET
if INET
source "net/ipv4/Kconfig"
source "net/ipv6/Kconfig"
+source "net/netlabel/Kconfig"
endif # if INET
@@ -249,8 +250,6 @@ source "net/ieee80211/Kconfig"
config WIRELESS_EXT
bool
-source "net/netlabel/Kconfig"
-
config FIB_RULES
bool
diff --git a/net/appletalk/ddp.c b/net/appletalk/ddp.c
index 708e2e0371af..485e35c3b28b 100644
--- a/net/appletalk/ddp.c
+++ b/net/appletalk/ddp.c
@@ -1584,7 +1584,6 @@ static int atalk_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr
if (usat->sat_addr.s_net || usat->sat_addr.s_node == ATADDR_ANYNODE) {
rt = atrtr_find(&usat->sat_addr);
- dev = rt->dev;
} else {
struct atalk_addr at_hint;
@@ -1592,7 +1591,6 @@ static int atalk_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr
at_hint.s_net = at->src_net;
rt = atrtr_find(&at_hint);
- dev = rt->dev;
}
if (!rt)
return -ENETUNREACH;
diff --git a/net/atm/atm_sysfs.c b/net/atm/atm_sysfs.c
index c0a4ae28fcfa..62f6ed1f2f98 100644
--- a/net/atm/atm_sysfs.c
+++ b/net/atm/atm_sysfs.c
@@ -141,7 +141,7 @@ static struct class atm_class = {
int atm_register_sysfs(struct atm_dev *adev)
{
struct class_device *cdev = &adev->class_dev;
- int i, err;
+ int i, j, err;
cdev->class = &atm_class;
class_set_devdata(cdev, adev);
@@ -151,10 +151,19 @@ int atm_register_sysfs(struct atm_dev *adev)
if (err < 0)
return err;
- for (i = 0; atm_attrs[i]; i++)
- class_device_create_file(cdev, atm_attrs[i]);
+ for (i = 0; atm_attrs[i]; i++) {
+ err = class_device_create_file(cdev, atm_attrs[i]);
+ if (err)
+ goto err_out;
+ }
return 0;
+
+err_out:
+ for (j = 0; j < i; j++)
+ class_device_remove_file(cdev, atm_attrs[j]);
+ class_device_del(cdev);
+ return err;
}
void atm_unregister_sysfs(struct atm_dev *adev)
diff --git a/net/bluetooth/af_bluetooth.c b/net/bluetooth/af_bluetooth.c
index 305a099b7477..67df99e2e5c8 100644
--- a/net/bluetooth/af_bluetooth.c
+++ b/net/bluetooth/af_bluetooth.c
@@ -48,41 +48,56 @@
#define BT_DBG(D...)
#endif
-#define VERSION "2.10"
+#define VERSION "2.11"
/* Bluetooth sockets */
#define BT_MAX_PROTO 8
static struct net_proto_family *bt_proto[BT_MAX_PROTO];
+static DEFINE_RWLOCK(bt_proto_lock);
int bt_sock_register(int proto, struct net_proto_family *ops)
{
+ int err = 0;
+
if (proto < 0 || proto >= BT_MAX_PROTO)
return -EINVAL;
+ write_lock(&bt_proto_lock);
+
if (bt_proto[proto])
- return -EEXIST;
+ err = -EEXIST;
+ else
+ bt_proto[proto] = ops;
- bt_proto[proto] = ops;
- return 0;
+ write_unlock(&bt_proto_lock);
+
+ return err;
}
EXPORT_SYMBOL(bt_sock_register);
int bt_sock_unregister(int proto)
{
+ int err = 0;
+
if (proto < 0 || proto >= BT_MAX_PROTO)
return -EINVAL;
+ write_lock(&bt_proto_lock);
+
if (!bt_proto[proto])
- return -ENOENT;
+ err = -ENOENT;
+ else
+ bt_proto[proto] = NULL;
- bt_proto[proto] = NULL;
- return 0;
+ write_unlock(&bt_proto_lock);
+
+ return err;
}
EXPORT_SYMBOL(bt_sock_unregister);
static int bt_sock_create(struct socket *sock, int proto)
{
- int err = 0;
+ int err;
if (proto < 0 || proto >= BT_MAX_PROTO)
return -EINVAL;
@@ -92,11 +107,18 @@ static int bt_sock_create(struct socket *sock, int proto)
request_module("bt-proto-%d", proto);
}
#endif
+
err = -EPROTONOSUPPORT;
+
+ read_lock(&bt_proto_lock);
+
if (bt_proto[proto] && try_module_get(bt_proto[proto]->owner)) {
err = bt_proto[proto]->create(sock, proto);
module_put(bt_proto[proto]->owner);
}
+
+ read_unlock(&bt_proto_lock);
+
return err;
}
diff --git a/net/bluetooth/bnep/core.c b/net/bluetooth/bnep/core.c
index 2312d050eeed..4d3424c2421c 100644
--- a/net/bluetooth/bnep/core.c
+++ b/net/bluetooth/bnep/core.c
@@ -528,12 +528,10 @@ static struct device *bnep_get_device(struct bnep_session *session)
return NULL;
conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, dst);
- if (!conn)
- return NULL;
hci_dev_put(hdev);
- return &conn->dev;
+ return conn ? &conn->dev : NULL;
}
int bnep_add_connection(struct bnep_connadd_req *req, struct socket *sock)
diff --git a/net/bluetooth/bnep/sock.c b/net/bluetooth/bnep/sock.c
index 28c55835422a..5563db1bf526 100644
--- a/net/bluetooth/bnep/sock.c
+++ b/net/bluetooth/bnep/sock.c
@@ -43,6 +43,7 @@
#include <linux/ioctl.h>
#include <linux/file.h>
#include <linux/init.h>
+#include <linux/compat.h>
#include <net/sock.h>
#include <asm/system.h>
@@ -146,24 +147,56 @@ static int bnep_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned long
return 0;
}
+#ifdef CONFIG_COMPAT
+static int bnep_sock_compat_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
+{
+ if (cmd == BNEPGETCONNLIST) {
+ struct bnep_connlist_req cl;
+ uint32_t uci;
+ int err;
+
+ if (get_user(cl.cnum, (uint32_t __user *) arg) ||
+ get_user(uci, (u32 __user *) (arg + 4)))
+ return -EFAULT;
+
+ cl.ci = compat_ptr(uci);
+
+ if (cl.cnum <= 0)
+ return -EINVAL;
+
+ err = bnep_get_connlist(&cl);
+
+ if (!err && put_user(cl.cnum, (uint32_t __user *) arg))
+ err = -EFAULT;
+
+ return err;
+ }
+
+ return bnep_sock_ioctl(sock, cmd, arg);
+}
+#endif
+
static const struct proto_ops bnep_sock_ops = {
- .family = PF_BLUETOOTH,
- .owner = THIS_MODULE,
- .release = bnep_sock_release,
- .ioctl = bnep_sock_ioctl,
- .bind = sock_no_bind,
- .getname = sock_no_getname,
- .sendmsg = sock_no_sendmsg,
- .recvmsg = sock_no_recvmsg,
- .poll = sock_no_poll,
- .listen = sock_no_listen,
- .shutdown = sock_no_shutdown,
- .setsockopt = sock_no_setsockopt,
- .getsockopt = sock_no_getsockopt,
- .connect = sock_no_connect,
- .socketpair = sock_no_socketpair,
- .accept = sock_no_accept,
- .mmap = sock_no_mmap
+ .family = PF_BLUETOOTH,
+ .owner = THIS_MODULE,
+ .release = bnep_sock_release,
+ .ioctl = bnep_sock_ioctl,
+#ifdef CONFIG_COMPAT
+ .compat_ioctl = bnep_sock_compat_ioctl,
+#endif
+ .bind = sock_no_bind,
+ .getname = sock_no_getname,
+ .sendmsg = sock_no_sendmsg,
+ .recvmsg = sock_no_recvmsg,
+ .poll = sock_no_poll,
+ .listen = sock_no_listen,
+ .shutdown = sock_no_shutdown,
+ .setsockopt = sock_no_setsockopt,
+ .getsockopt = sock_no_getsockopt,
+ .connect = sock_no_connect,
+ .socketpair = sock_no_socketpair,
+ .accept = sock_no_accept,
+ .mmap = sock_no_mmap
};
static struct proto bnep_proto = {
@@ -181,7 +214,7 @@ static int bnep_sock_create(struct socket *sock, int protocol)
if (sock->type != SOCK_RAW)
return -ESOCKTNOSUPPORT;
- sk = sk_alloc(PF_BLUETOOTH, GFP_KERNEL, &bnep_proto, 1);
+ sk = sk_alloc(PF_BLUETOOTH, GFP_ATOMIC, &bnep_proto, 1);
if (!sk)
return -ENOMEM;
diff --git a/net/bluetooth/cmtp/sock.c b/net/bluetooth/cmtp/sock.c
index 10ad7fd91d83..53295d33dc5c 100644
--- a/net/bluetooth/cmtp/sock.c
+++ b/net/bluetooth/cmtp/sock.c
@@ -34,6 +34,7 @@
#include <linux/socket.h>
#include <linux/ioctl.h>
#include <linux/file.h>
+#include <linux/compat.h>
#include <net/sock.h>
#include <linux/isdn/capilli.h>
@@ -137,11 +138,43 @@ static int cmtp_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned long
return -EINVAL;
}
+#ifdef CONFIG_COMPAT
+static int cmtp_sock_compat_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
+{
+ if (cmd == CMTPGETCONNLIST) {
+ struct cmtp_connlist_req cl;
+ uint32_t uci;
+ int err;
+
+ if (get_user(cl.cnum, (uint32_t __user *) arg) ||
+ get_user(uci, (u32 __user *) (arg + 4)))
+ return -EFAULT;
+
+ cl.ci = compat_ptr(uci);
+
+ if (cl.cnum <= 0)
+ return -EINVAL;
+
+ err = cmtp_get_connlist(&cl);
+
+ if (!err && put_user(cl.cnum, (uint32_t __user *) arg))
+ err = -EFAULT;
+
+ return err;
+ }
+
+ return cmtp_sock_ioctl(sock, cmd, arg);
+}
+#endif
+
static const struct proto_ops cmtp_sock_ops = {
.family = PF_BLUETOOTH,
.owner = THIS_MODULE,
.release = cmtp_sock_release,
.ioctl = cmtp_sock_ioctl,
+#ifdef CONFIG_COMPAT
+ .compat_ioctl = cmtp_sock_compat_ioctl,
+#endif
.bind = sock_no_bind,
.getname = sock_no_getname,
.sendmsg = sock_no_sendmsg,
@@ -172,7 +205,7 @@ static int cmtp_sock_create(struct socket *sock, int protocol)
if (sock->type != SOCK_RAW)
return -ESOCKTNOSUPPORT;
- sk = sk_alloc(PF_BLUETOOTH, GFP_KERNEL, &cmtp_proto, 1);
+ sk = sk_alloc(PF_BLUETOOTH, GFP_ATOMIC, &cmtp_proto, 1);
if (!sk)
return -ENOMEM;
diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c
index 90e3a285a17e..6cd5711fa28a 100644
--- a/net/bluetooth/hci_conn.c
+++ b/net/bluetooth/hci_conn.c
@@ -51,7 +51,7 @@
#define BT_DBG(D...)
#endif
-static void hci_acl_connect(struct hci_conn *conn)
+void hci_acl_connect(struct hci_conn *conn)
{
struct hci_dev *hdev = conn->hdev;
struct inquiry_entry *ie;
@@ -63,6 +63,8 @@ static void hci_acl_connect(struct hci_conn *conn)
conn->out = 1;
conn->link_mode = HCI_LM_MASTER;
+ conn->attempt++;
+
memset(&cp, 0, sizeof(cp));
bacpy(&cp.bdaddr, &conn->dst);
cp.pscan_rep_mode = 0x02;
@@ -80,7 +82,7 @@ static void hci_acl_connect(struct hci_conn *conn)
cp.role_switch = 0x01;
else
cp.role_switch = 0x00;
-
+
hci_send_cmd(hdev, OGF_LINK_CTL, OCF_CREATE_CONN, sizeof(cp), &cp);
}
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index d43d0c890975..bb94e6da223c 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -57,6 +57,7 @@
static void hci_cc_link_ctl(struct hci_dev *hdev, __u16 ocf, struct sk_buff *skb)
{
__u8 status;
+ struct hci_conn *pend;
BT_DBG("%s ocf 0x%x", hdev->name, ocf);
@@ -71,6 +72,15 @@ static void hci_cc_link_ctl(struct hci_dev *hdev, __u16 ocf, struct sk_buff *skb
clear_bit(HCI_INQUIRY, &hdev->flags);
hci_req_complete(hdev, status);
}
+
+ hci_dev_lock(hdev);
+
+ pend = hci_conn_hash_lookup_state(hdev, ACL_LINK, BT_CONNECT2);
+ if (pend)
+ hci_acl_connect(pend);
+
+ hci_dev_unlock(hdev);
+
break;
default:
@@ -414,9 +424,12 @@ static inline void hci_cs_create_conn(struct hci_dev *hdev, __u8 status)
if (status) {
if (conn && conn->state == BT_CONNECT) {
- conn->state = BT_CLOSED;
- hci_proto_connect_cfm(conn, status);
- hci_conn_del(conn);
+ if (status != 0x0c || conn->attempt > 2) {
+ conn->state = BT_CLOSED;
+ hci_proto_connect_cfm(conn, status);
+ hci_conn_del(conn);
+ } else
+ conn->state = BT_CONNECT2;
}
} else {
if (!conn) {
@@ -562,11 +575,20 @@ static void hci_cs_info_param(struct hci_dev *hdev, __u16 ocf, __u8 status)
static inline void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
{
__u8 status = *((__u8 *) skb->data);
+ struct hci_conn *pend;
BT_DBG("%s status %d", hdev->name, status);
clear_bit(HCI_INQUIRY, &hdev->flags);
hci_req_complete(hdev, status);
+
+ hci_dev_lock(hdev);
+
+ pend = hci_conn_hash_lookup_state(hdev, ACL_LINK, BT_CONNECT2);
+ if (pend)
+ hci_acl_connect(pend);
+
+ hci_dev_unlock(hdev);
}
/* Inquiry Result */
@@ -728,7 +750,7 @@ static inline void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *sk
static inline void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
{
struct hci_ev_conn_complete *ev = (struct hci_ev_conn_complete *) skb->data;
- struct hci_conn *conn;
+ struct hci_conn *conn, *pend;
BT_DBG("%s", hdev->name);
@@ -801,6 +823,10 @@ static inline void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *s
if (ev->status)
hci_conn_del(conn);
+ pend = hci_conn_hash_lookup_state(hdev, ACL_LINK, BT_CONNECT2);
+ if (pend)
+ hci_acl_connect(pend);
+
hci_dev_unlock(hdev);
}
diff --git a/net/bluetooth/hci_sock.c b/net/bluetooth/hci_sock.c
index 1a35d343e08a..711a085eca5b 100644
--- a/net/bluetooth/hci_sock.c
+++ b/net/bluetooth/hci_sock.c
@@ -120,10 +120,13 @@ void hci_send_to_sock(struct hci_dev *hdev, struct sk_buff *skb)
if (!hci_test_bit(evt, &flt->event_mask))
continue;
- if (flt->opcode && ((evt == HCI_EV_CMD_COMPLETE &&
- flt->opcode != *(__u16 *)(skb->data + 3)) ||
- (evt == HCI_EV_CMD_STATUS &&
- flt->opcode != *(__u16 *)(skb->data + 4))))
+ if (flt->opcode &&
+ ((evt == HCI_EV_CMD_COMPLETE &&
+ flt->opcode !=
+ get_unaligned((__u16 *)(skb->data + 3))) ||
+ (evt == HCI_EV_CMD_STATUS &&
+ flt->opcode !=
+ get_unaligned((__u16 *)(skb->data + 4)))))
continue;
}
@@ -618,7 +621,7 @@ static int hci_sock_create(struct socket *sock, int protocol)
sock->ops = &hci_sock_ops;
- sk = sk_alloc(PF_BLUETOOTH, GFP_KERNEL, &hci_sk_proto, 1);
+ sk = sk_alloc(PF_BLUETOOTH, GFP_ATOMIC, &hci_sk_proto, 1);
if (!sk)
return -ENOMEM;
diff --git a/net/bluetooth/hci_sysfs.c b/net/bluetooth/hci_sysfs.c
index 989b22d9042e..3eeeb7a86e75 100644
--- a/net/bluetooth/hci_sysfs.c
+++ b/net/bluetooth/hci_sysfs.c
@@ -242,10 +242,14 @@ static void add_conn(void *data)
struct hci_conn *conn = data;
int i;
- device_register(&conn->dev);
+ if (device_register(&conn->dev) < 0) {
+ BT_ERR("Failed to register connection device");
+ return;
+ }
for (i = 0; conn_attrs[i]; i++)
- device_create_file(&conn->dev, conn_attrs[i]);
+ if (device_create_file(&conn->dev, conn_attrs[i]) < 0)
+ BT_ERR("Failed to create connection attribute");
}
void hci_conn_add_sysfs(struct hci_conn *conn)
@@ -255,7 +259,9 @@ void hci_conn_add_sysfs(struct hci_conn *conn)
BT_DBG("conn %p", conn);
- conn->dev.parent = &hdev->dev;
+ conn->dev.bus = &bt_bus;
+ conn->dev.parent = &hdev->dev;
+
conn->dev.release = bt_release;
snprintf(conn->dev.bus_id, BUS_ID_SIZE,
@@ -295,11 +301,7 @@ int hci_register_sysfs(struct hci_dev *hdev)
BT_DBG("%p name %s type %d", hdev, hdev->name, hdev->type);
dev->class = bt_class;
-
- if (hdev->parent)
- dev->parent = hdev->parent;
- else
- dev->parent = &bt_platform->dev;
+ dev->parent = hdev->parent;
strlcpy(dev->bus_id, hdev->name, BUS_ID_SIZE);
@@ -312,7 +314,8 @@ int hci_register_sysfs(struct hci_dev *hdev)
return err;
for (i = 0; bt_attrs[i]; i++)
- device_create_file(dev, bt_attrs[i]);
+ if (device_create_file(dev, bt_attrs[i]) < 0)
+ BT_ERR("Failed to create device attribute");
return 0;
}
diff --git a/net/bluetooth/hidp/core.c b/net/bluetooth/hidp/core.c
index 03b5dadb4951..66782010f82c 100644
--- a/net/bluetooth/hidp/core.c
+++ b/net/bluetooth/hidp/core.c
@@ -507,14 +507,12 @@ static int hidp_session(void *arg)
hidp_del_timer(session);
- if (intr_sk->sk_state != BT_CONNECTED)
- wait_event_timeout(*(ctrl_sk->sk_sleep), (ctrl_sk->sk_state == BT_CLOSED), HZ);
-
- fput(session->ctrl_sock->file);
+ fput(session->intr_sock->file);
- wait_event_timeout(*(intr_sk->sk_sleep), (intr_sk->sk_state == BT_CLOSED), HZ);
+ wait_event_timeout(*(ctrl_sk->sk_sleep),
+ (ctrl_sk->sk_state == BT_CLOSED), msecs_to_jiffies(500));
- fput(session->intr_sock->file);
+ fput(session->ctrl_sock->file);
__hidp_unlink_session(session);
@@ -541,12 +539,10 @@ static struct device *hidp_get_device(struct hidp_session *session)
return NULL;
conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, dst);
- if (!conn)
- return NULL;
hci_dev_put(hdev);
- return &conn->dev;
+ return conn ? &conn->dev : NULL;
}
static inline void hidp_setup_input(struct hidp_session *session, struct hidp_connadd_req *req)
diff --git a/net/bluetooth/hidp/sock.c b/net/bluetooth/hidp/sock.c
index 099646e4e2ef..407fba43c1b9 100644
--- a/net/bluetooth/hidp/sock.c
+++ b/net/bluetooth/hidp/sock.c
@@ -35,6 +35,7 @@
#include <linux/ioctl.h>
#include <linux/file.h>
#include <linux/init.h>
+#include <linux/compat.h>
#include <net/sock.h>
#include "hidp.h"
@@ -143,11 +144,88 @@ static int hidp_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned long
return -EINVAL;
}
+#ifdef CONFIG_COMPAT
+struct compat_hidp_connadd_req {
+ int ctrl_sock; // Connected control socket
+ int intr_sock; // Connteted interrupt socket
+ __u16 parser;
+ __u16 rd_size;
+ compat_uptr_t rd_data;
+ __u8 country;
+ __u8 subclass;
+ __u16 vendor;
+ __u16 product;
+ __u16 version;
+ __u32 flags;
+ __u32 idle_to;
+ char name[128];
+};
+
+static int hidp_sock_compat_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
+{
+ if (cmd == HIDPGETCONNLIST) {
+ struct hidp_connlist_req cl;
+ uint32_t uci;
+ int err;
+
+ if (get_user(cl.cnum, (uint32_t __user *) arg) ||
+ get_user(uci, (u32 __user *) (arg + 4)))
+ return -EFAULT;
+
+ cl.ci = compat_ptr(uci);
+
+ if (cl.cnum <= 0)
+ return -EINVAL;
+
+ err = hidp_get_connlist(&cl);
+
+ if (!err && put_user(cl.cnum, (uint32_t __user *) arg))
+ err = -EFAULT;
+
+ return err;
+ } else if (cmd == HIDPCONNADD) {
+ struct compat_hidp_connadd_req ca;
+ struct hidp_connadd_req __user *uca;
+
+ uca = compat_alloc_user_space(sizeof(*uca));
+
+ if (copy_from_user(&ca, (void *) arg, sizeof(ca)))
+ return -EFAULT;
+
+ if (put_user(ca.ctrl_sock, &uca->ctrl_sock) ||
+ put_user(ca.intr_sock, &uca->intr_sock) ||
+ put_user(ca.parser, &uca->parser) ||
+ put_user(ca.rd_size, &uca->parser) ||
+ put_user(compat_ptr(ca.rd_data), &uca->rd_data) ||
+ put_user(ca.country, &uca->country) ||
+ put_user(ca.subclass, &uca->subclass) ||
+ put_user(ca.vendor, &uca->vendor) ||
+ put_user(ca.product, &uca->product) ||
+ put_user(ca.version, &uca->version) ||
+ put_user(ca.flags, &uca->flags) ||
+ put_user(ca.idle_to, &uca->idle_to) ||
+ copy_to_user(&uca->name[0], &ca.name[0], 128))
+ return -EFAULT;
+
+ arg = (unsigned long) uca;
+
+ /* Fall through. We don't actually write back any _changes_
+ to the structure anyway, so there's no need to copy back
+ into the original compat version */
+ }
+
+ return hidp_sock_ioctl(sock, cmd, arg);
+}
+#endif
+
static const struct proto_ops hidp_sock_ops = {
.family = PF_BLUETOOTH,
.owner = THIS_MODULE,
.release = hidp_sock_release,
.ioctl = hidp_sock_ioctl,
+#ifdef CONFIG_COMPAT
+ .compat_ioctl = hidp_sock_compat_ioctl,
+#endif
.bind = sock_no_bind,
.getname = sock_no_getname,
.sendmsg = sock_no_sendmsg,
@@ -178,7 +256,7 @@ static int hidp_sock_create(struct socket *sock, int protocol)
if (sock->type != SOCK_RAW)
return -ESOCKTNOSUPPORT;
- sk = sk_alloc(PF_BLUETOOTH, GFP_KERNEL, &hidp_proto, 1);
+ sk = sk_alloc(PF_BLUETOOTH, GFP_ATOMIC, &hidp_proto, 1);
if (!sk)
return -ENOMEM;
diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c
index d56f60b392ac..bbf78e6a7bc3 100644
--- a/net/bluetooth/l2cap.c
+++ b/net/bluetooth/l2cap.c
@@ -559,7 +559,7 @@ static int l2cap_sock_create(struct socket *sock, int protocol)
sock->ops = &l2cap_sock_ops;
- sk = l2cap_sock_alloc(sock, protocol, GFP_KERNEL);
+ sk = l2cap_sock_alloc(sock, protocol, GFP_ATOMIC);
if (!sk)
return -ENOMEM;
@@ -1353,12 +1353,12 @@ static inline int l2cap_conf_output(struct sock *sk, void **ptr)
/* Configure output options and let the other side know
* which ones we don't like. */
- if (pi->conf_mtu < pi->omtu) {
- l2cap_add_conf_opt(ptr, L2CAP_CONF_MTU, 2, pi->omtu);
+ if (pi->conf_mtu < pi->omtu)
result = L2CAP_CONF_UNACCEPT;
- } else {
+ else
pi->omtu = pi->conf_mtu;
- }
+
+ l2cap_add_conf_opt(ptr, L2CAP_CONF_MTU, 2, pi->omtu);
BT_DBG("sk %p result %d", sk, result);
return result;
@@ -1533,6 +1533,9 @@ static inline int l2cap_config_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr
if (!(sk = l2cap_get_chan_by_scid(&conn->chan_list, dcid)))
return -ENOENT;
+ if (sk->sk_state == BT_DISCONN)
+ goto unlock;
+
l2cap_parse_conf_req(sk, req->data, cmd->len - sizeof(*req));
if (flags & 0x0001) {
@@ -2216,7 +2219,8 @@ static int __init l2cap_init(void)
goto error;
}
- class_create_file(bt_class, &class_attr_l2cap);
+ if (class_create_file(bt_class, &class_attr_l2cap) < 0)
+ BT_ERR("Failed to create L2CAP info file");
BT_INFO("L2CAP ver %s", VERSION);
BT_INFO("L2CAP socket layer initialized");
diff --git a/net/bluetooth/rfcomm/core.c b/net/bluetooth/rfcomm/core.c
index 468df3b953f6..ddc4e9d5963e 100644
--- a/net/bluetooth/rfcomm/core.c
+++ b/net/bluetooth/rfcomm/core.c
@@ -2058,7 +2058,8 @@ static int __init rfcomm_init(void)
kernel_thread(rfcomm_run, NULL, CLONE_KERNEL);
- class_create_file(bt_class, &class_attr_rfcomm_dlc);
+ if (class_create_file(bt_class, &class_attr_rfcomm_dlc) < 0)
+ BT_ERR("Failed to create RFCOMM info file");
rfcomm_init_sockets();
diff --git a/net/bluetooth/rfcomm/sock.c b/net/bluetooth/rfcomm/sock.c
index 220fee04e7f2..544d65b7baa7 100644
--- a/net/bluetooth/rfcomm/sock.c
+++ b/net/bluetooth/rfcomm/sock.c
@@ -336,7 +336,8 @@ static int rfcomm_sock_create(struct socket *sock, int protocol)
sock->ops = &rfcomm_sock_ops;
- if (!(sk = rfcomm_sock_alloc(sock, protocol, GFP_KERNEL)))
+ sk = rfcomm_sock_alloc(sock, protocol, GFP_ATOMIC);
+ if (!sk)
return -ENOMEM;
rfcomm_sock_init(sk, NULL);
@@ -944,7 +945,8 @@ int __init rfcomm_init_sockets(void)
if (err < 0)
goto error;
- class_create_file(bt_class, &class_attr_rfcomm);
+ if (class_create_file(bt_class, &class_attr_rfcomm) < 0)
+ BT_ERR("Failed to create RFCOMM info file");
BT_INFO("RFCOMM socket layer initialized");
diff --git a/net/bluetooth/rfcomm/tty.c b/net/bluetooth/rfcomm/tty.c
index 1958ad1b8541..1fb5d42f37ae 100644
--- a/net/bluetooth/rfcomm/tty.c
+++ b/net/bluetooth/rfcomm/tty.c
@@ -172,12 +172,10 @@ static struct device *rfcomm_get_device(struct rfcomm_dev *dev)
return NULL;
conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &dev->dst);
- if (!conn)
- return NULL;
hci_dev_put(hdev);
- return &conn->dev;
+ return conn ? &conn->dev : NULL;
}
static int rfcomm_dev_add(struct rfcomm_dev_req *req, struct rfcomm_dlc *dlc)
@@ -767,6 +765,9 @@ static void rfcomm_tty_set_termios(struct tty_struct *tty, struct termios *old)
BT_DBG("tty %p termios %p", tty, old);
+ if (!dev || !dev->dlc || !dev->dlc->session)
+ return;
+
/* Handle turning off CRTSCTS */
if ((old->c_cflag & CRTSCTS) && !(new->c_cflag & CRTSCTS))
BT_DBG("Turning off CRTSCTS unsupported");
diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c
index 7714a2ec3854..5d13d4f31753 100644
--- a/net/bluetooth/sco.c
+++ b/net/bluetooth/sco.c
@@ -452,7 +452,8 @@ static int sco_sock_create(struct socket *sock, int protocol)
sock->ops = &sco_sock_ops;
- if (!(sk = sco_sock_alloc(sock, protocol, GFP_KERNEL)))
+ sk = sco_sock_alloc(sock, protocol, GFP_ATOMIC);
+ if (!sk)
return -ENOMEM;
sco_sock_init(sk, NULL);
@@ -967,7 +968,8 @@ static int __init sco_init(void)
goto error;
}
- class_create_file(bt_class, &class_attr_sco);
+ if (class_create_file(bt_class, &class_attr_sco) < 0)
+ BT_ERR("Failed to create SCO info file");
BT_INFO("SCO (Voice Link) ver %s", VERSION);
BT_INFO("SCO socket layer initialized");
diff --git a/net/bridge/br_fdb.c b/net/bridge/br_fdb.c
index 3a73b8c94271..d9f04864d15d 100644
--- a/net/bridge/br_fdb.c
+++ b/net/bridge/br_fdb.c
@@ -128,7 +128,10 @@ void br_fdb_cleanup(unsigned long _data)
mod_timer(&br->gc_timer, jiffies + HZ/10);
}
-void br_fdb_delete_by_port(struct net_bridge *br, struct net_bridge_port *p)
+
+void br_fdb_delete_by_port(struct net_bridge *br,
+ const struct net_bridge_port *p,
+ int do_all)
{
int i;
@@ -142,6 +145,8 @@ void br_fdb_delete_by_port(struct net_bridge *br, struct net_bridge_port *p)
if (f->dst != p)
continue;
+ if (f->is_static && !do_all)
+ continue;
/*
* if multiple ports all have the same device address
* then when one port is deleted, assign
diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c
index b1211d5342f6..f753c40c11d2 100644
--- a/net/bridge/br_if.c
+++ b/net/bridge/br_if.c
@@ -163,7 +163,7 @@ static void del_nbp(struct net_bridge_port *p)
br_stp_disable_port(p);
spin_unlock_bh(&br->lock);
- br_fdb_delete_by_port(br, p);
+ br_fdb_delete_by_port(br, p, 1);
list_del_rcu(&p->list);
@@ -448,7 +448,7 @@ int br_add_if(struct net_bridge *br, struct net_device *dev)
return 0;
err2:
- br_fdb_delete_by_port(br, p);
+ br_fdb_delete_by_port(br, p, 1);
err1:
kobject_del(&p->kobj);
err0:
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h
index c491fb2f280e..74258d86f256 100644
--- a/net/bridge/br_private.h
+++ b/net/bridge/br_private.h
@@ -143,7 +143,7 @@ extern void br_fdb_changeaddr(struct net_bridge_port *p,
const unsigned char *newaddr);
extern void br_fdb_cleanup(unsigned long arg);
extern void br_fdb_delete_by_port(struct net_bridge *br,
- struct net_bridge_port *p);
+ const struct net_bridge_port *p, int do_all);
extern struct net_bridge_fdb_entry *__br_fdb_get(struct net_bridge *br,
const unsigned char *addr);
extern struct net_bridge_fdb_entry *br_fdb_get(struct net_bridge *br,
diff --git a/net/bridge/br_stp_if.c b/net/bridge/br_stp_if.c
index 14cd025079af..d294224592db 100644
--- a/net/bridge/br_stp_if.c
+++ b/net/bridge/br_stp_if.c
@@ -113,6 +113,8 @@ void br_stp_disable_port(struct net_bridge_port *p)
del_timer(&p->forward_delay_timer);
del_timer(&p->hold_timer);
+ br_fdb_delete_by_port(br, p, 0);
+
br_configuration_update(br);
br_port_state_selection(br);
diff --git a/net/bridge/br_sysfs_br.c b/net/bridge/br_sysfs_br.c
index 96bcb2ff59ab..de9d1a9473f2 100644
--- a/net/bridge/br_sysfs_br.c
+++ b/net/bridge/br_sysfs_br.c
@@ -376,7 +376,7 @@ int br_sysfs_addbr(struct net_device *dev)
err = sysfs_create_bin_file(brobj, &bridge_forward);
if (err) {
- pr_info("%s: can't create attribue file %s/%s\n",
+ pr_info("%s: can't create attribute file %s/%s\n",
__FUNCTION__, dev->name, bridge_forward.attr.name);
goto out2;
}
diff --git a/net/bridge/netfilter/ebtables.c b/net/bridge/netfilter/ebtables.c
index 3df55b2bd91d..9f85666f29f7 100644
--- a/net/bridge/netfilter/ebtables.c
+++ b/net/bridge/netfilter/ebtables.c
@@ -86,7 +86,7 @@ static inline int ebt_do_match (struct ebt_entry_match *m,
static inline int ebt_dev_check(char *entry, const struct net_device *device)
{
int i = 0;
- char *devname = device->name;
+ const char *devname = device->name;
if (*entry == '\0')
return 0;
diff --git a/net/compat.c b/net/compat.c
index d5d69fa15d07..52d32f1bc728 100644
--- a/net/compat.c
+++ b/net/compat.c
@@ -285,8 +285,7 @@ void scm_detach_fds_compat(struct msghdr *kmsg, struct scm_cookie *scm)
if (i > 0) {
int cmlen = CMSG_COMPAT_LEN(i * sizeof(int));
- if (!err)
- err = put_user(SOL_SOCKET, &cm->cmsg_level);
+ err = put_user(SOL_SOCKET, &cm->cmsg_level);
if (!err)
err = put_user(SCM_RIGHTS, &cm->cmsg_type);
if (!err)
diff --git a/net/core/dev.c b/net/core/dev.c
index 4d891beab138..81c426adcd1e 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -3502,8 +3502,6 @@ static int __init net_dev_init(void)
BUG_ON(!dev_boot_phase);
- net_random_init();
-
if (dev_proc_init())
goto out;
diff --git a/net/core/flow.c b/net/core/flow.c
index f23e7e386543..b16d31ae5e54 100644
--- a/net/core/flow.c
+++ b/net/core/flow.c
@@ -85,6 +85,14 @@ static void flow_cache_new_hashrnd(unsigned long arg)
add_timer(&flow_hash_rnd_timer);
}
+static void flow_entry_kill(int cpu, struct flow_cache_entry *fle)
+{
+ if (fle->object)
+ atomic_dec(fle->object_ref);
+ kmem_cache_free(flow_cachep, fle);
+ flow_count(cpu)--;
+}
+
static void __flow_cache_shrink(int cpu, int shrink_to)
{
struct flow_cache_entry *fle, **flp;
@@ -100,10 +108,7 @@ static void __flow_cache_shrink(int cpu, int shrink_to)
}
while ((fle = *flp) != NULL) {
*flp = fle->next;
- if (fle->object)
- atomic_dec(fle->object_ref);
- kmem_cache_free(flow_cachep, fle);
- flow_count(cpu)--;
+ flow_entry_kill(cpu, fle);
}
}
}
@@ -220,24 +225,33 @@ void *flow_cache_lookup(struct flowi *key, u16 family, u8 dir,
nocache:
{
+ int err;
void *obj;
atomic_t *obj_ref;
- resolver(key, family, dir, &obj, &obj_ref);
+ err = resolver(key, family, dir, &obj, &obj_ref);
if (fle) {
- fle->genid = atomic_read(&flow_cache_genid);
-
- if (fle->object)
- atomic_dec(fle->object_ref);
-
- fle->object = obj;
- fle->object_ref = obj_ref;
- if (obj)
- atomic_inc(fle->object_ref);
+ if (err) {
+ /* Force security policy check on next lookup */
+ *head = fle->next;
+ flow_entry_kill(cpu, fle);
+ } else {
+ fle->genid = atomic_read(&flow_cache_genid);
+
+ if (fle->object)
+ atomic_dec(fle->object_ref);
+
+ fle->object = obj;
+ fle->object_ref = obj_ref;
+ if (obj)
+ atomic_inc(fle->object_ref);
+ }
}
local_bh_enable();
+ if (err)
+ obj = ERR_PTR(err);
return obj;
}
}
diff --git a/net/core/netpoll.c b/net/core/netpoll.c
index ead5920c26d6..6589adb14cbf 100644
--- a/net/core/netpoll.c
+++ b/net/core/netpoll.c
@@ -335,13 +335,19 @@ void netpoll_send_udp(struct netpoll *np, const char *msg, int len)
memcpy(skb->data, msg, len);
skb->len += len;
- udph = (struct udphdr *) skb_push(skb, sizeof(*udph));
+ skb->h.uh = udph = (struct udphdr *) skb_push(skb, sizeof(*udph));
udph->source = htons(np->local_port);
udph->dest = htons(np->remote_port);
udph->len = htons(udp_len);
udph->check = 0;
+ udph->check = csum_tcpudp_magic(htonl(np->local_ip),
+ htonl(np->remote_ip),
+ udp_len, IPPROTO_UDP,
+ csum_partial((unsigned char *)udph, udp_len, 0));
+ if (udph->check == 0)
+ udph->check = -1;
- iph = (struct iphdr *)skb_push(skb, sizeof(*iph));
+ skb->nh.iph = iph = (struct iphdr *)skb_push(skb, sizeof(*iph));
/* iph->version = 4; iph->ihl = 5; */
put_unaligned(0x45, (unsigned char *)iph);
@@ -357,8 +363,8 @@ void netpoll_send_udp(struct netpoll *np, const char *msg, int len)
iph->check = ip_fast_csum((unsigned char *)iph, iph->ihl);
eth = (struct ethhdr *) skb_push(skb, ETH_HLEN);
-
- eth->h_proto = htons(ETH_P_IP);
+ skb->mac.raw = skb->data;
+ skb->protocol = eth->h_proto = htons(ETH_P_IP);
memcpy(eth->h_source, np->local_mac, 6);
memcpy(eth->h_dest, np->remote_mac, 6);
diff --git a/net/core/pktgen.c b/net/core/pktgen.c
index dd023fd28304..733d86d0a4fb 100644
--- a/net/core/pktgen.c
+++ b/net/core/pktgen.c
@@ -2304,6 +2304,12 @@ static void mpls_push(__be32 *mpls, struct pktgen_dev *pkt_dev)
*mpls |= MPLS_STACK_BOTTOM;
}
+static inline __be16 build_tci(unsigned int id, unsigned int cfi,
+ unsigned int prio)
+{
+ return htons(id | (cfi << 12) | (prio << 13));
+}
+
static struct sk_buff *fill_packet_ipv4(struct net_device *odev,
struct pktgen_dev *pkt_dev)
{
@@ -2353,16 +2359,16 @@ static struct sk_buff *fill_packet_ipv4(struct net_device *odev,
if (pkt_dev->vlan_id != 0xffff) {
if(pkt_dev->svlan_id != 0xffff) {
svlan_tci = (__be16 *)skb_put(skb, sizeof(__be16));
- *svlan_tci = htons(pkt_dev->svlan_id);
- *svlan_tci |= pkt_dev->svlan_p << 5;
- *svlan_tci |= pkt_dev->svlan_cfi << 4;
+ *svlan_tci = build_tci(pkt_dev->svlan_id,
+ pkt_dev->svlan_cfi,
+ pkt_dev->svlan_p);
svlan_encapsulated_proto = (__be16 *)skb_put(skb, sizeof(__be16));
*svlan_encapsulated_proto = __constant_htons(ETH_P_8021Q);
}
vlan_tci = (__be16 *)skb_put(skb, sizeof(__be16));
- *vlan_tci = htons(pkt_dev->vlan_id);
- *vlan_tci |= pkt_dev->vlan_p << 5;
- *vlan_tci |= pkt_dev->vlan_cfi << 4;
+ *vlan_tci = build_tci(pkt_dev->vlan_id,
+ pkt_dev->vlan_cfi,
+ pkt_dev->vlan_p);
vlan_encapsulated_proto = (__be16 *)skb_put(skb, sizeof(__be16));
*vlan_encapsulated_proto = __constant_htons(ETH_P_IP);
}
@@ -2689,16 +2695,16 @@ static struct sk_buff *fill_packet_ipv6(struct net_device *odev,
if (pkt_dev->vlan_id != 0xffff) {
if(pkt_dev->svlan_id != 0xffff) {
svlan_tci = (__be16 *)skb_put(skb, sizeof(__be16));
- *svlan_tci = htons(pkt_dev->svlan_id);
- *svlan_tci |= pkt_dev->svlan_p << 5;
- *svlan_tci |= pkt_dev->svlan_cfi << 4;
+ *svlan_tci = build_tci(pkt_dev->svlan_id,
+ pkt_dev->svlan_cfi,
+ pkt_dev->svlan_p);
svlan_encapsulated_proto = (__be16 *)skb_put(skb, sizeof(__be16));
*svlan_encapsulated_proto = __constant_htons(ETH_P_8021Q);
}
vlan_tci = (__be16 *)skb_put(skb, sizeof(__be16));
- *vlan_tci = htons(pkt_dev->vlan_id);
- *vlan_tci |= pkt_dev->vlan_p << 5;
- *vlan_tci |= pkt_dev->vlan_cfi << 4;
+ *vlan_tci = build_tci(pkt_dev->vlan_id,
+ pkt_dev->vlan_cfi,
+ pkt_dev->vlan_p);
vlan_encapsulated_proto = (__be16 *)skb_put(skb, sizeof(__be16));
*vlan_encapsulated_proto = __constant_htons(ETH_P_IPV6);
}
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
index 221e4038216b..02f3c7947898 100644
--- a/net/core/rtnetlink.c
+++ b/net/core/rtnetlink.c
@@ -602,7 +602,7 @@ static int rtnl_getlink(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
goto errout;
}
- err = rtnl_unicast(skb, NETLINK_CB(skb).pid);
+ err = rtnl_unicast(nskb, NETLINK_CB(skb).pid);
errout:
kfree(iw_buf);
dev_put(dev);
diff --git a/net/core/scm.c b/net/core/scm.c
index 649d01ef35b6..271cf060ef8c 100644
--- a/net/core/scm.c
+++ b/net/core/scm.c
@@ -245,8 +245,7 @@ void scm_detach_fds(struct msghdr *msg, struct scm_cookie *scm)
if (i > 0)
{
int cmlen = CMSG_LEN(i*sizeof(int));
- if (!err)
- err = put_user(SOL_SOCKET, &cm->cmsg_level);
+ err = put_user(SOL_SOCKET, &cm->cmsg_level);
if (!err)
err = put_user(SCM_RIGHTS, &cm->cmsg_type);
if (!err)
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index 3c23760c5827..b8b106358040 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -639,6 +639,7 @@ struct sk_buff *pskb_copy(struct sk_buff *skb, gfp_t gfp_mask)
n->csum = skb->csum;
n->ip_summed = skb->ip_summed;
+ n->truesize += skb->data_len;
n->data_len = skb->data_len;
n->len = skb->len;
@@ -1946,7 +1947,7 @@ struct sk_buff *skb_segment(struct sk_buff *skb, int features)
do {
struct sk_buff *nskb;
skb_frag_t *frag;
- int hsize, nsize;
+ int hsize;
int k;
int size;
@@ -1957,11 +1958,10 @@ struct sk_buff *skb_segment(struct sk_buff *skb, int features)
hsize = skb_headlen(skb) - offset;
if (hsize < 0)
hsize = 0;
- nsize = hsize + doffset;
- if (nsize > len + doffset || !sg)
- nsize = len + doffset;
+ if (hsize > len || !sg)
+ hsize = len;
- nskb = alloc_skb(nsize + headroom, GFP_ATOMIC);
+ nskb = alloc_skb(hsize + doffset + headroom, GFP_ATOMIC);
if (unlikely(!nskb))
goto err;
diff --git a/net/core/sock.c b/net/core/sock.c
index b77e155cbe6c..ee6cd2541d35 100644
--- a/net/core/sock.c
+++ b/net/core/sock.c
@@ -823,7 +823,7 @@ static void inline sock_lock_init(struct sock *sk)
af_family_slock_key_strings[sk->sk_family]);
lockdep_init_map(&sk->sk_lock.dep_map,
af_family_key_strings[sk->sk_family],
- af_family_keys + sk->sk_family);
+ af_family_keys + sk->sk_family, 0);
}
/**
@@ -1160,7 +1160,7 @@ static struct sk_buff *sock_alloc_send_pskb(struct sock *sk,
goto failure;
if (atomic_read(&sk->sk_wmem_alloc) < sk->sk_sndbuf) {
- skb = alloc_skb(header_len, sk->sk_allocation);
+ skb = alloc_skb(header_len, gfp_mask);
if (skb) {
int npages;
int i;
diff --git a/net/core/utils.c b/net/core/utils.c
index 94c5d761c830..d93fe64f6693 100644
--- a/net/core/utils.c
+++ b/net/core/utils.c
@@ -30,119 +30,6 @@
#include <asm/system.h>
#include <asm/uaccess.h>
-/*
- This is a maximally equidistributed combined Tausworthe generator
- based on code from GNU Scientific Library 1.5 (30 Jun 2004)
-
- x_n = (s1_n ^ s2_n ^ s3_n)
-
- s1_{n+1} = (((s1_n & 4294967294) <<12) ^ (((s1_n <<13) ^ s1_n) >>19))
- s2_{n+1} = (((s2_n & 4294967288) << 4) ^ (((s2_n << 2) ^ s2_n) >>25))
- s3_{n+1} = (((s3_n & 4294967280) <<17) ^ (((s3_n << 3) ^ s3_n) >>11))
-
- The period of this generator is about 2^88.
-
- From: P. L'Ecuyer, "Maximally Equidistributed Combined Tausworthe
- Generators", Mathematics of Computation, 65, 213 (1996), 203--213.
-
- This is available on the net from L'Ecuyer's home page,
-
- http://www.iro.umontreal.ca/~lecuyer/myftp/papers/tausme.ps
- ftp://ftp.iro.umontreal.ca/pub/simulation/lecuyer/papers/tausme.ps
-
- There is an erratum in the paper "Tables of Maximally
- Equidistributed Combined LFSR Generators", Mathematics of
- Computation, 68, 225 (1999), 261--269:
- http://www.iro.umontreal.ca/~lecuyer/myftp/papers/tausme2.ps
-
- ... the k_j most significant bits of z_j must be non-
- zero, for each j. (Note: this restriction also applies to the
- computer code given in [4], but was mistakenly not mentioned in
- that paper.)
-
- This affects the seeding procedure by imposing the requirement
- s1 > 1, s2 > 7, s3 > 15.
-
-*/
-struct nrnd_state {
- u32 s1, s2, s3;
-};
-
-static DEFINE_PER_CPU(struct nrnd_state, net_rand_state);
-
-static u32 __net_random(struct nrnd_state *state)
-{
-#define TAUSWORTHE(s,a,b,c,d) ((s&c)<<d) ^ (((s <<a) ^ s)>>b)
-
- state->s1 = TAUSWORTHE(state->s1, 13, 19, 4294967294UL, 12);
- state->s2 = TAUSWORTHE(state->s2, 2, 25, 4294967288UL, 4);
- state->s3 = TAUSWORTHE(state->s3, 3, 11, 4294967280UL, 17);
-
- return (state->s1 ^ state->s2 ^ state->s3);
-}
-
-static void __net_srandom(struct nrnd_state *state, unsigned long s)
-{
- if (s == 0)
- s = 1; /* default seed is 1 */
-
-#define LCG(n) (69069 * n)
- state->s1 = LCG(s);
- state->s2 = LCG(state->s1);
- state->s3 = LCG(state->s2);
-
- /* "warm it up" */
- __net_random(state);
- __net_random(state);
- __net_random(state);
- __net_random(state);
- __net_random(state);
- __net_random(state);
-}
-
-
-unsigned long net_random(void)
-{
- unsigned long r;
- struct nrnd_state *state = &get_cpu_var(net_rand_state);
- r = __net_random(state);
- put_cpu_var(state);
- return r;
-}
-
-
-void net_srandom(unsigned long entropy)
-{
- struct nrnd_state *state = &get_cpu_var(net_rand_state);
- __net_srandom(state, state->s1^entropy);
- put_cpu_var(state);
-}
-
-void __init net_random_init(void)
-{
- int i;
-
- for_each_possible_cpu(i) {
- struct nrnd_state *state = &per_cpu(net_rand_state,i);
- __net_srandom(state, i+jiffies);
- }
-}
-
-static int net_random_reseed(void)
-{
- int i;
- unsigned long seed;
-
- for_each_possible_cpu(i) {
- struct nrnd_state *state = &per_cpu(net_rand_state,i);
-
- get_random_bytes(&seed, sizeof(seed));
- __net_srandom(state, seed);
- }
- return 0;
-}
-late_initcall(net_random_reseed);
-
int net_msg_cost = 5*HZ;
int net_msg_burst = 10;
@@ -153,10 +40,7 @@ int net_ratelimit(void)
{
return __printk_ratelimit(net_msg_cost, net_msg_burst);
}
-
-EXPORT_SYMBOL(net_random);
EXPORT_SYMBOL(net_ratelimit);
-EXPORT_SYMBOL(net_srandom);
/*
* Convert an ASCII string to binary IP.
diff --git a/net/core/wireless.c b/net/core/wireless.c
index ffff0da46c6e..cb1b8728d7ee 100644
--- a/net/core/wireless.c
+++ b/net/core/wireless.c
@@ -748,11 +748,39 @@ static int ioctl_standard_call(struct net_device * dev,
int extra_size;
int user_length = 0;
int err;
+ int essid_compat = 0;
/* Calculate space needed by arguments. Always allocate
* for max space. Easier, and won't last long... */
extra_size = descr->max_tokens * descr->token_size;
+ /* Check need for ESSID compatibility for WE < 21 */
+ switch (cmd) {
+ case SIOCSIWESSID:
+ case SIOCGIWESSID:
+ case SIOCSIWNICKN:
+ case SIOCGIWNICKN:
+ if (iwr->u.data.length == descr->max_tokens + 1)
+ essid_compat = 1;
+ else if (IW_IS_SET(cmd) && (iwr->u.data.length != 0)) {
+ char essid[IW_ESSID_MAX_SIZE + 1];
+
+ err = copy_from_user(essid, iwr->u.data.pointer,
+ iwr->u.data.length *
+ descr->token_size);
+ if (err)
+ return -EFAULT;
+
+ if (essid[iwr->u.data.length - 1] == '\0')
+ essid_compat = 1;
+ }
+ break;
+ default:
+ break;
+ }
+
+ iwr->u.data.length -= essid_compat;
+
/* Check what user space is giving us */
if(IW_IS_SET(cmd)) {
/* Check NULL pointer */
@@ -795,7 +823,8 @@ static int ioctl_standard_call(struct net_device * dev,
#endif /* WE_IOCTL_DEBUG */
/* Create the kernel buffer */
- extra = kmalloc(extra_size, GFP_KERNEL);
+ /* kzalloc ensures NULL-termination for essid_compat */
+ extra = kzalloc(extra_size, GFP_KERNEL);
if (extra == NULL) {
return -ENOMEM;
}
@@ -819,6 +848,8 @@ static int ioctl_standard_call(struct net_device * dev,
/* Call the handler */
ret = handler(dev, &info, &(iwr->u), extra);
+ iwr->u.data.length += essid_compat;
+
/* If we have something to return to the user */
if (!ret && IW_IS_GET(cmd)) {
/* Check if there is enough buffer up there */
diff --git a/net/dccp/Kconfig b/net/dccp/Kconfig
index e2a095d0fd80..ef8919cca74b 100644
--- a/net/dccp/Kconfig
+++ b/net/dccp/Kconfig
@@ -4,15 +4,15 @@ menu "DCCP Configuration (EXPERIMENTAL)"
config IP_DCCP
tristate "The DCCP Protocol (EXPERIMENTAL)"
---help---
- Datagram Congestion Control Protocol
+ Datagram Congestion Control Protocol (RFC 4340)
- From draft-ietf-dccp-spec-11 <http://www.icir.org/kohler/dcp/draft-ietf-dccp-spec-11.txt>.
+ From http://www.ietf.org/rfc/rfc4340.txt:
The Datagram Congestion Control Protocol (DCCP) is a transport
protocol that implements bidirectional, unicast connections of
congestion-controlled, unreliable datagrams. It should be suitable
for use by applications such as streaming media, Internet telephony,
- and on-line games
+ and on-line games.
To compile this protocol support as a module, choose M here: the
module will be called dccp.
diff --git a/net/dccp/ackvec.c b/net/dccp/ackvec.c
index 4d176d33983f..f8208874ac7d 100644
--- a/net/dccp/ackvec.c
+++ b/net/dccp/ackvec.c
@@ -113,7 +113,7 @@ int dccp_insert_option_ackvec(struct sock *sk, struct sk_buff *skb)
memcpy(to, from, len);
/*
- * From draft-ietf-dccp-spec-11.txt:
+ * From RFC 4340, A.2:
*
* For each acknowledgement it sends, the HC-Receiver will add an
* acknowledgement record. ack_seqno will equal the HC-Receiver
@@ -224,7 +224,7 @@ static inline int dccp_ackvec_set_buf_head_state(struct dccp_ackvec *av,
}
/*
- * Implements the draft-ietf-dccp-spec-11.txt Appendix A
+ * Implements the RFC 4340, Appendix A
*/
int dccp_ackvec_add(struct dccp_ackvec *av, const struct sock *sk,
const u64 ackno, const u8 state)
@@ -237,7 +237,7 @@ int dccp_ackvec_add(struct dccp_ackvec *av, const struct sock *sk,
* We may well decide to do buffer compression, etc, but for now lets
* just drop.
*
- * From Appendix A:
+ * From Appendix A.1.1 (`New Packets'):
*
* Of course, the circular buffer may overflow, either when the
* HC-Sender is sending data at a very high rate, when the
@@ -274,9 +274,9 @@ int dccp_ackvec_add(struct dccp_ackvec *av, const struct sock *sk,
/*
* A.1.2. Old Packets
*
- * When a packet with Sequence Number S arrives, and
- * S <= buf_ackno, the HC-Receiver will scan the table
- * for the byte corresponding to S. (Indexing structures
+ * When a packet with Sequence Number S <= buf_ackno
+ * arrives, the HC-Receiver will scan the table for
+ * the byte corresponding to S. (Indexing structures
* could reduce the complexity of this scan.)
*/
u64 delta = dccp_delta_seqno(ackno, av->dccpav_buf_ackno);
diff --git a/net/dccp/ackvec.h b/net/dccp/ackvec.h
index 2424effac7f6..cf8f20ce23a9 100644
--- a/net/dccp/ackvec.h
+++ b/net/dccp/ackvec.h
@@ -28,8 +28,7 @@
/** struct dccp_ackvec - ack vector
*
- * This data structure is the one defined in the DCCP draft
- * Appendix A.
+ * This data structure is the one defined in RFC 4340, Appendix A.
*
* @dccpav_buf_head - circular buffer head
* @dccpav_buf_tail - circular buffer tail
diff --git a/net/dccp/ccids/Kconfig b/net/dccp/ccids/Kconfig
index 32752f750447..8533dabfb9f8 100644
--- a/net/dccp/ccids/Kconfig
+++ b/net/dccp/ccids/Kconfig
@@ -22,11 +22,11 @@ config IP_DCCP_CCID2
for lost packets, would prefer CCID 2 to CCID 3. On-line games may
also prefer CCID 2.
- CCID 2 is further described in:
- http://www.icir.org/kohler/dccp/draft-ietf-dccp-ccid2-10.txt
+ CCID 2 is further described in RFC 4341,
+ http://www.ietf.org/rfc/rfc4341.txt
- This text was extracted from:
- http://www.icir.org/kohler/dccp/draft-ietf-dccp-spec-13.txt
+ This text was extracted from RFC 4340 (sec. 10.1),
+ http://www.ietf.org/rfc/rfc4340.txt
If in doubt, say M.
@@ -53,15 +53,14 @@ config IP_DCCP_CCID3
suitable than CCID 2 for applications such streaming media where a
relatively smooth sending rate is of importance.
- CCID 3 is further described in:
-
- http://www.icir.org/kohler/dccp/draft-ietf-dccp-ccid3-11.txt.
+ CCID 3 is further described in RFC 4342,
+ http://www.ietf.org/rfc/rfc4342.txt
The TFRC congestion control algorithms were initially described in
RFC 3448.
- This text was extracted from:
- http://www.icir.org/kohler/dccp/draft-ietf-dccp-spec-13.txt
+ This text was extracted from RFC 4340 (sec. 10.2),
+ http://www.ietf.org/rfc/rfc4340.txt
If in doubt, say M.
diff --git a/net/dccp/ccids/ccid2.c b/net/dccp/ccids/ccid2.c
index 2efb505aeb35..162032baeac0 100644
--- a/net/dccp/ccids/ccid2.c
+++ b/net/dccp/ccids/ccid2.c
@@ -23,7 +23,7 @@
*/
/*
- * This implementation should follow: draft-ietf-dccp-ccid2-10.txt
+ * This implementation should follow RFC 4341
*
* BUGS:
* - sequence number wrapping
@@ -352,14 +352,14 @@ static void ccid2_hc_tx_packet_sent(struct sock *sk, int more, int len)
#ifdef CONFIG_IP_DCCP_CCID2_DEBUG
ccid2_pr_debug("pipe=%d\n", hctx->ccid2hctx_pipe);
- ccid2_pr_debug("Sent: seq=%llu\n", seq);
+ ccid2_pr_debug("Sent: seq=%llu\n", (unsigned long long)seq);
do {
struct ccid2_seq *seqp = hctx->ccid2hctx_seqt;
while (seqp != hctx->ccid2hctx_seqh) {
ccid2_pr_debug("out seq=%llu acked=%d time=%lu\n",
- seqp->ccid2s_seq, seqp->ccid2s_acked,
- seqp->ccid2s_sent);
+ (unsigned long long)seqp->ccid2s_seq,
+ seqp->ccid2s_acked, seqp->ccid2s_sent);
seqp = seqp->ccid2s_next;
}
} while (0);
@@ -480,7 +480,8 @@ static inline void ccid2_new_ack(struct sock *sk,
/* first measurement */
if (hctx->ccid2hctx_srtt == -1) {
ccid2_pr_debug("R: %lu Time=%lu seq=%llu\n",
- r, jiffies, seqp->ccid2s_seq);
+ r, jiffies,
+ (unsigned long long)seqp->ccid2s_seq);
ccid2_change_srtt(hctx, r);
hctx->ccid2hctx_rttvar = r >> 1;
} else {
@@ -636,8 +637,9 @@ static void ccid2_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb)
u64 ackno_end_rl;
dccp_set_seqno(&ackno_end_rl, ackno - rl);
- ccid2_pr_debug("ackvec start:%llu end:%llu\n", ackno,
- ackno_end_rl);
+ ccid2_pr_debug("ackvec start:%llu end:%llu\n",
+ (unsigned long long)ackno,
+ (unsigned long long)ackno_end_rl);
/* if the seqno we are analyzing is larger than the
* current ackno, then move towards the tail of our
* seqnos.
@@ -672,7 +674,7 @@ static void ccid2_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb)
seqp->ccid2s_acked = 1;
ccid2_pr_debug("Got ack for %llu\n",
- seqp->ccid2s_seq);
+ (unsigned long long)seqp->ccid2s_seq);
ccid2_hc_tx_dec_pipe(sk);
}
if (seqp == hctx->ccid2hctx_seqt) {
@@ -718,7 +720,7 @@ static void ccid2_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb)
while (1) {
if (!seqp->ccid2s_acked) {
ccid2_pr_debug("Packet lost: %llu\n",
- seqp->ccid2s_seq);
+ (unsigned long long)seqp->ccid2s_seq);
/* XXX need to traverse from tail -> head in
* order to detect multiple congestion events in
* one ack vector.
diff --git a/net/dccp/ccids/ccid3.c b/net/dccp/ccids/ccid3.c
index 67d2dc0e7c67..cec23ad286de 100644
--- a/net/dccp/ccids/ccid3.c
+++ b/net/dccp/ccids/ccid3.c
@@ -379,8 +379,7 @@ static void ccid3_hc_tx_packet_sent(struct sock *sk, int more, int len)
packet->dccphtx_seqno = dp->dccps_gss;
/*
* Check if win_count have changed
- * Algorithm in "8.1. Window Counter Valuer" in
- * draft-ietf-dccp-ccid3-11.txt
+ * Algorithm in "8.1. Window Counter Value" in RFC 4342.
*/
quarter_rtt = timeval_delta(&now, &hctx->ccid3hctx_t_last_win_count);
if (likely(hctx->ccid3hctx_rtt > 8))
diff --git a/net/dccp/dccp.h b/net/dccp/dccp.h
index 0a21be437ed3..272e8584564e 100644
--- a/net/dccp/dccp.h
+++ b/net/dccp/dccp.h
@@ -50,7 +50,7 @@ extern void dccp_time_wait(struct sock *sk, int state, int timeo);
#define DCCP_TIMEWAIT_LEN (60 * HZ) /* how long to wait to destroy TIME-WAIT
* state, about 60 seconds */
-/* draft-ietf-dccp-spec-11.txt initial RTO value */
+/* RFC 1122, 4.2.3.1 initial RTO value */
#define DCCP_TIMEOUT_INIT ((unsigned)(3 * HZ))
/* Maximal interval between probes for local resources. */
diff --git a/net/dccp/input.c b/net/dccp/input.c
index 7f9dc6ac58c9..1d24881ac0ab 100644
--- a/net/dccp/input.c
+++ b/net/dccp/input.c
@@ -216,11 +216,11 @@ send_sync:
dccp_send_sync(sk, DCCP_SKB_CB(skb)->dccpd_seq,
DCCP_PKT_SYNCACK);
/*
- * From the draft:
+ * From RFC 4340, sec. 5.7
*
* As with DCCP-Ack packets, DCCP-Sync and DCCP-SyncAck packets
* MAY have non-zero-length application data areas, whose
- * contents * receivers MUST ignore.
+ * contents receivers MUST ignore.
*/
goto discard;
}
diff --git a/net/dccp/ipv4.c b/net/dccp/ipv4.c
index bf692c1c116f..e08e7688a263 100644
--- a/net/dccp/ipv4.c
+++ b/net/dccp/ipv4.c
@@ -183,7 +183,7 @@ static inline void dccp_do_pmtu_discovery(struct sock *sk,
dccp_sync_mss(sk, mtu);
/*
- * From: draft-ietf-dccp-spec-11.txt
+ * From RFC 4340, sec. 14.1:
*
* DCCP-Sync packets are the best choice for upward
* probing, since DCCP-Sync probes do not risk application
@@ -311,7 +311,7 @@ static void dccp_v4_err(struct sk_buff *skb, u32 info)
}
if (sk->sk_state == DCCP_TIME_WAIT) {
- inet_twsk_put((struct inet_timewait_sock *)sk);
+ inet_twsk_put(inet_twsk(sk));
return;
}
@@ -449,6 +449,8 @@ static inline u64 dccp_v4_init_sequence(const struct sock *sk,
dccp_hdr(skb)->dccph_sport);
}
+static struct request_sock_ops dccp_request_sock_ops;
+
int dccp_v4_conn_request(struct sock *sk, struct sk_buff *skb)
{
struct inet_request_sock *ireq;
@@ -489,7 +491,7 @@ int dccp_v4_conn_request(struct sock *sk, struct sk_buff *skb)
if (sk_acceptq_is_full(sk) && inet_csk_reqsk_queue_young(sk) > 1)
goto drop;
- req = reqsk_alloc(sk->sk_prot->rsk_prot);
+ req = reqsk_alloc(&dccp_request_sock_ops);
if (req == NULL)
goto drop;
@@ -614,7 +616,7 @@ static struct sock *dccp_v4_hnd_req(struct sock *sk, struct sk_buff *skb)
bh_lock_sock(nsk);
return nsk;
}
- inet_twsk_put((struct inet_timewait_sock *)nsk);
+ inet_twsk_put(inet_twsk(nsk));
return NULL;
}
@@ -731,7 +733,7 @@ static void dccp_v4_ctl_send_reset(struct sk_buff *rxskb)
dccp_hdr_reset(skb)->dccph_reset_code =
DCCP_SKB_CB(rxskb)->dccpd_reset_code;
- /* See "8.3.1. Abnormal Termination" in draft-ietf-dccp-spec-11 */
+ /* See "8.3.1. Abnormal Termination" in RFC 4340 */
seqno = 0;
if (DCCP_SKB_CB(rxskb)->dccpd_ack_seq != DCCP_PKT_WITHOUT_ACK_SEQ)
dccp_set_seqno(&seqno, DCCP_SKB_CB(rxskb)->dccpd_ack_seq + 1);
@@ -980,7 +982,7 @@ discard_and_relse:
goto discard_it;
do_time_wait:
- inet_twsk_put((struct inet_timewait_sock *)sk);
+ inet_twsk_put(inet_twsk(sk));
goto no_dccp_socket;
}
diff --git a/net/dccp/ipv6.c b/net/dccp/ipv6.c
index 7a47399cf31f..fc4242c0767c 100644
--- a/net/dccp/ipv6.c
+++ b/net/dccp/ipv6.c
@@ -277,7 +277,7 @@ static void dccp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
__u64 seq;
sk = inet6_lookup(&dccp_hashinfo, &hdr->daddr, dh->dccph_dport,
- &hdr->saddr, dh->dccph_sport, skb->dev->ifindex);
+ &hdr->saddr, dh->dccph_sport, inet6_iif(skb));
if (sk == NULL) {
ICMP6_INC_STATS_BH(__in6_dev_get(skb->dev), ICMP6_MIB_INERRORS);
@@ -285,7 +285,7 @@ static void dccp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
}
if (sk->sk_state == DCCP_TIME_WAIT) {
- inet_twsk_put((struct inet_timewait_sock *)sk);
+ inet_twsk_put(inet_twsk(sk));
return;
}
@@ -550,7 +550,7 @@ static void dccp_v6_ctl_send_reset(struct sk_buff *rxskb)
dccp_hdr_reset(skb)->dccph_reset_code =
DCCP_SKB_CB(rxskb)->dccpd_reset_code;
- /* See "8.3.1. Abnormal Termination" in draft-ietf-dccp-spec-11 */
+ /* See "8.3.1. Abnormal Termination" in RFC 4340 */
seqno = 0;
if (DCCP_SKB_CB(rxskb)->dccpd_ack_seq != DCCP_PKT_WITHOUT_ACK_SEQ)
dccp_set_seqno(&seqno, DCCP_SKB_CB(rxskb)->dccpd_ack_seq + 1);
@@ -663,7 +663,7 @@ static struct sock *dccp_v6_hnd_req(struct sock *sk,struct sk_buff *skb)
bh_lock_sock(nsk);
return nsk;
}
- inet_twsk_put((struct inet_timewait_sock *)nsk);
+ inet_twsk_put(inet_twsk(nsk));
return NULL;
}
@@ -672,7 +672,6 @@ static struct sock *dccp_v6_hnd_req(struct sock *sk,struct sk_buff *skb)
static int dccp_v6_conn_request(struct sock *sk, struct sk_buff *skb)
{
- struct inet_request_sock *ireq;
struct dccp_sock dp;
struct request_sock *req;
struct dccp_request_sock *dreq;
@@ -701,7 +700,7 @@ static int dccp_v6_conn_request(struct sock *sk, struct sk_buff *skb)
if (sk_acceptq_is_full(sk) && inet_csk_reqsk_queue_young(sk) > 1)
goto drop;
- req = inet6_reqsk_alloc(sk->sk_prot->rsk_prot);
+ req = inet6_reqsk_alloc(&dccp6_request_sock_ops);
if (req == NULL)
goto drop;
@@ -713,7 +712,6 @@ static int dccp_v6_conn_request(struct sock *sk, struct sk_buff *skb)
goto drop_and_free;
ireq6 = inet6_rsk(req);
- ireq = inet_rsk(req);
ipv6_addr_copy(&ireq6->rmt_addr, &skb->nh.ipv6h->saddr);
ipv6_addr_copy(&ireq6->loc_addr, &skb->nh.ipv6h->daddr);
req->rcv_wnd = dccp_feat_default_sequence_window;
@@ -997,6 +995,10 @@ static int dccp_v6_do_rcv(struct sock *sk, struct sk_buff *skb)
if (sk->sk_state == DCCP_OPEN) { /* Fast path */
if (dccp_rcv_established(sk, skb, dccp_hdr(skb), skb->len))
goto reset;
+ if (opt_skb) {
+ /* This is where we would goto ipv6_pktoptions. */
+ __kfree_skb(opt_skb);
+ }
return 0;
}
@@ -1021,6 +1023,10 @@ static int dccp_v6_do_rcv(struct sock *sk, struct sk_buff *skb)
if (dccp_rcv_state_process(sk, skb, dccp_hdr(skb), skb->len))
goto reset;
+ if (opt_skb) {
+ /* This is where we would goto ipv6_pktoptions. */
+ __kfree_skb(opt_skb);
+ }
return 0;
reset:
@@ -1109,7 +1115,7 @@ discard_and_relse:
goto discard_it;
do_time_wait:
- inet_twsk_put((struct inet_timewait_sock *)sk);
+ inet_twsk_put(inet_twsk(sk));
goto no_dccp_socket;
}
diff --git a/net/dccp/options.c b/net/dccp/options.c
index 07a34696ac97..fb0db1f7cd7b 100644
--- a/net/dccp/options.c
+++ b/net/dccp/options.c
@@ -215,7 +215,7 @@ int dccp_parse_options(struct sock *sk, struct sk_buff *skb)
elapsed_time);
break;
/*
- * From draft-ietf-dccp-spec-11.txt:
+ * From RFC 4340, sec. 10.3:
*
* Option numbers 128 through 191 are for
* options sent from the HC-Sender to the
diff --git a/net/decnet/af_decnet.c b/net/decnet/af_decnet.c
index 70e027375682..21f20f21dd32 100644
--- a/net/decnet/af_decnet.c
+++ b/net/decnet/af_decnet.c
@@ -166,7 +166,7 @@ static struct hlist_head *dn_find_list(struct sock *sk)
if (scp->addr.sdn_flags & SDF_WILD)
return hlist_empty(&dn_wild_sk) ? &dn_wild_sk : NULL;
- return &dn_sk_hash[scp->addrloc & DN_SK_HASH_MASK];
+ return &dn_sk_hash[dn_ntohs(scp->addrloc) & DN_SK_HASH_MASK];
}
/*
@@ -180,7 +180,7 @@ static int check_port(__le16 port)
if (port == 0)
return -1;
- sk_for_each(sk, node, &dn_sk_hash[port & DN_SK_HASH_MASK]) {
+ sk_for_each(sk, node, &dn_sk_hash[dn_ntohs(port) & DN_SK_HASH_MASK]) {
struct dn_scp *scp = DN_SK(sk);
if (scp->addrloc == port)
return -1;
@@ -194,12 +194,12 @@ static unsigned short port_alloc(struct sock *sk)
static unsigned short port = 0x2000;
unsigned short i_port = port;
- while(check_port(++port) != 0) {
+ while(check_port(dn_htons(++port)) != 0) {
if (port == i_port)
return 0;
}
- scp->addrloc = port;
+ scp->addrloc = dn_htons(port);
return 1;
}
@@ -418,7 +418,7 @@ struct sock *dn_find_by_skb(struct sk_buff *skb)
struct dn_scp *scp;
read_lock(&dn_hash_lock);
- sk_for_each(sk, node, &dn_sk_hash[cb->dst_port & DN_SK_HASH_MASK]) {
+ sk_for_each(sk, node, &dn_sk_hash[dn_ntohs(cb->dst_port) & DN_SK_HASH_MASK]) {
scp = DN_SK(sk);
if (cb->src != dn_saddr2dn(&scp->peer))
continue;
@@ -1016,13 +1016,14 @@ static void dn_access_copy(struct sk_buff *skb, struct accessdata_dn *acc)
static void dn_user_copy(struct sk_buff *skb, struct optdata_dn *opt)
{
- unsigned char *ptr = skb->data;
-
- opt->opt_optl = *ptr++;
- opt->opt_status = 0;
- memcpy(opt->opt_data, ptr, opt->opt_optl);
- skb_pull(skb, dn_ntohs(opt->opt_optl) + 1);
-
+ unsigned char *ptr = skb->data;
+ u16 len = *ptr++; /* yes, it's 8bit on the wire */
+
+ BUG_ON(len > 16); /* we've checked the contents earlier */
+ opt->opt_optl = dn_htons(len);
+ opt->opt_status = 0;
+ memcpy(opt->opt_data, ptr, len);
+ skb_pull(skb, len + 1);
}
static struct sk_buff *dn_wait_for_connect(struct sock *sk, long *timeo)
@@ -1178,8 +1179,10 @@ static int dn_getname(struct socket *sock, struct sockaddr *uaddr,int *uaddr_len
if (peer) {
if ((sock->state != SS_CONNECTED &&
sock->state != SS_CONNECTING) &&
- scp->accept_mode == ACC_IMMED)
+ scp->accept_mode == ACC_IMMED) {
+ release_sock(sk);
return -ENOTCONN;
+ }
memcpy(sa, &scp->peer, sizeof(struct sockaddr_dn));
} else {
diff --git a/net/decnet/dn_nsp_in.c b/net/decnet/dn_nsp_in.c
index 72ecc6e62ec4..7683d4f754d2 100644
--- a/net/decnet/dn_nsp_in.c
+++ b/net/decnet/dn_nsp_in.c
@@ -360,9 +360,9 @@ static void dn_nsp_conn_conf(struct sock *sk, struct sk_buff *skb)
scp->max_window = decnet_no_fc_max_cwnd;
if (skb->len > 0) {
- unsigned char dlen = *skb->data;
+ u16 dlen = *skb->data;
if ((dlen <= 16) && (dlen <= skb->len)) {
- scp->conndata_in.opt_optl = dn_htons((__u16)dlen);
+ scp->conndata_in.opt_optl = dn_htons(dlen);
memcpy(scp->conndata_in.opt_data, skb->data + 1, dlen);
}
}
@@ -404,9 +404,9 @@ static void dn_nsp_disc_init(struct sock *sk, struct sk_buff *skb)
memset(scp->discdata_in.opt_data, 0, 16);
if (skb->len > 0) {
- unsigned char dlen = *skb->data;
+ u16 dlen = *skb->data;
if ((dlen <= 16) && (dlen <= skb->len)) {
- scp->discdata_in.opt_optl = dn_htons((__u16)dlen);
+ scp->discdata_in.opt_optl = dn_htons(dlen);
memcpy(scp->discdata_in.opt_data, skb->data + 1, dlen);
}
}
diff --git a/net/decnet/dn_nsp_out.c b/net/decnet/dn_nsp_out.c
index c2e21cd89b3c..b342e4e8f5f8 100644
--- a/net/decnet/dn_nsp_out.c
+++ b/net/decnet/dn_nsp_out.c
@@ -526,7 +526,7 @@ void dn_send_conn_conf(struct sock *sk, gfp_t gfp)
struct nsp_conn_init_msg *msg;
__u8 len = (__u8)dn_ntohs(scp->conndata_out.opt_optl);
- if ((skb = dn_alloc_skb(sk, 50 + dn_ntohs(scp->conndata_out.opt_optl), gfp)) == NULL)
+ if ((skb = dn_alloc_skb(sk, 50 + len, gfp)) == NULL)
return;
msg = (struct nsp_conn_init_msg *)skb_put(skb, sizeof(*msg));
diff --git a/net/decnet/dn_route.c b/net/decnet/dn_route.c
index dd0761e3d280..23489f7232d2 100644
--- a/net/decnet/dn_route.c
+++ b/net/decnet/dn_route.c
@@ -267,9 +267,14 @@ static void dn_dst_link_failure(struct sk_buff *skb)
static inline int compare_keys(struct flowi *fl1, struct flowi *fl2)
{
- return memcmp(&fl1->nl_u.dn_u, &fl2->nl_u.dn_u, sizeof(fl1->nl_u.dn_u)) == 0 &&
- fl1->oif == fl2->oif &&
- fl1->iif == fl2->iif;
+ return ((fl1->nl_u.dn_u.daddr ^ fl2->nl_u.dn_u.daddr) |
+ (fl1->nl_u.dn_u.saddr ^ fl2->nl_u.dn_u.saddr) |
+#ifdef CONFIG_DECNET_ROUTE_FWMARK
+ (fl1->nl_u.dn_u.fwmark ^ fl2->nl_u.dn_u.fwmark) |
+#endif
+ (fl1->nl_u.dn_u.scope ^ fl2->nl_u.dn_u.scope) |
+ (fl1->oif ^ fl2->oif) |
+ (fl1->iif ^ fl2->iif)) == 0;
}
static int dn_insert_route(struct dn_route *rt, unsigned hash, struct dn_route **rp)
@@ -1270,7 +1275,6 @@ static int dn_route_input_slow(struct sk_buff *skb)
goto e_inval;
res.type = RTN_LOCAL;
- flags |= RTCF_DIRECTSRC;
} else {
__le16 src_map = fl.fld_src;
free_res = 1;
@@ -1341,7 +1345,7 @@ static int dn_route_input_slow(struct sk_buff *skb)
goto make_route;
/* Packet was intra-ethernet, so we know its on-link */
- if (cb->rt_flags | DN_RT_F_IE) {
+ if (cb->rt_flags & DN_RT_F_IE) {
gateway = cb->src;
flags |= RTCF_DIRECTSRC;
goto make_route;
diff --git a/net/decnet/dn_rules.c b/net/decnet/dn_rules.c
index 3e0c882c90bf..590e0a72495c 100644
--- a/net/decnet/dn_rules.c
+++ b/net/decnet/dn_rules.c
@@ -124,8 +124,8 @@ static struct nla_policy dn_fib_rule_policy[FRA_MAX+1] __read_mostly = {
static int dn_fib_rule_match(struct fib_rule *rule, struct flowi *fl, int flags)
{
struct dn_fib_rule *r = (struct dn_fib_rule *)rule;
- u16 daddr = fl->fld_dst;
- u16 saddr = fl->fld_src;
+ __le16 daddr = fl->fld_dst;
+ __le16 saddr = fl->fld_src;
if (((saddr ^ r->src) & r->srcmask) ||
((daddr ^ r->dst) & r->dstmask))
diff --git a/net/ieee80211/Kconfig b/net/ieee80211/Kconfig
index f7e84e9d13ad..a64be6cdf078 100644
--- a/net/ieee80211/Kconfig
+++ b/net/ieee80211/Kconfig
@@ -32,6 +32,7 @@ config IEEE80211_CRYPT_WEP
depends on IEEE80211
select CRYPTO
select CRYPTO_ARC4
+ select CRYPTO_ECB
select CRC32
---help---
Include software based cipher suites in support of IEEE
@@ -58,6 +59,7 @@ config IEEE80211_CRYPT_TKIP
depends on IEEE80211 && NET_RADIO
select CRYPTO
select CRYPTO_MICHAEL_MIC
+ select CRYPTO_ECB
select CRC32
---help---
Include software based cipher suites in support of IEEE 802.11i
diff --git a/net/ieee80211/ieee80211_rx.c b/net/ieee80211/ieee80211_rx.c
index 770704183a1b..2759312a4204 100644
--- a/net/ieee80211/ieee80211_rx.c
+++ b/net/ieee80211/ieee80211_rx.c
@@ -1078,12 +1078,12 @@ static int ieee80211_parse_info_param(struct ieee80211_info_element
while (length >= sizeof(*info_element)) {
if (sizeof(*info_element) + info_element->len > length) {
- IEEE80211_ERROR("Info elem: parse failed: "
- "info_element->len + 2 > left : "
- "info_element->len+2=%zd left=%d, id=%d.\n",
- info_element->len +
- sizeof(*info_element),
- length, info_element->id);
+ IEEE80211_DEBUG_MGMT("Info elem: parse failed: "
+ "info_element->len + 2 > left : "
+ "info_element->len+2=%zd left=%d, id=%d.\n",
+ info_element->len +
+ sizeof(*info_element),
+ length, info_element->id);
/* We stop processing but don't return an error here
* because some misbehaviour APs break this rule. ie.
* Orinoco AP1000. */
diff --git a/net/ieee80211/softmac/ieee80211softmac_assoc.c b/net/ieee80211/softmac/ieee80211softmac_assoc.c
index 589f6d2c548a..cf51c87a971d 100644
--- a/net/ieee80211/softmac/ieee80211softmac_assoc.c
+++ b/net/ieee80211/softmac/ieee80211softmac_assoc.c
@@ -48,7 +48,7 @@ ieee80211softmac_assoc(struct ieee80211softmac_device *mac, struct ieee80211soft
dprintk(KERN_INFO PFX "sent association request!\n");
spin_lock_irqsave(&mac->lock, flags);
- mac->associated = 0; /* just to make sure */
+ mac->associnfo.associated = 0; /* just to make sure */
/* Set a timer for timeout */
/* FIXME: make timeout configurable */
@@ -62,24 +62,22 @@ ieee80211softmac_assoc_timeout(void *d)
{
struct ieee80211softmac_device *mac = (struct ieee80211softmac_device *)d;
struct ieee80211softmac_network *n;
- unsigned long flags;
- spin_lock_irqsave(&mac->lock, flags);
+ mutex_lock(&mac->associnfo.mutex);
/* we might race against ieee80211softmac_handle_assoc_response,
* so make sure only one of us does something */
- if (!mac->associnfo.associating) {
- spin_unlock_irqrestore(&mac->lock, flags);
- return;
- }
+ if (!mac->associnfo.associating)
+ goto out;
mac->associnfo.associating = 0;
mac->associnfo.bssvalid = 0;
- mac->associated = 0;
+ mac->associnfo.associated = 0;
n = ieee80211softmac_get_network_by_bssid_locked(mac, mac->associnfo.bssid);
- spin_unlock_irqrestore(&mac->lock, flags);
dprintk(KERN_INFO PFX "assoc request timed out!\n");
ieee80211softmac_call_events(mac, IEEE80211SOFTMAC_EVENT_ASSOCIATE_TIMEOUT, n);
+out:
+ mutex_unlock(&mac->associnfo.mutex);
}
void
@@ -93,7 +91,7 @@ ieee80211softmac_disassoc(struct ieee80211softmac_device *mac)
netif_carrier_off(mac->dev);
- mac->associated = 0;
+ mac->associnfo.associated = 0;
mac->associnfo.bssvalid = 0;
mac->associnfo.associating = 0;
ieee80211softmac_init_bss(mac);
@@ -107,7 +105,7 @@ ieee80211softmac_send_disassoc_req(struct ieee80211softmac_device *mac, u16 reas
{
struct ieee80211softmac_network *found;
- if (mac->associnfo.bssvalid && mac->associated) {
+ if (mac->associnfo.bssvalid && mac->associnfo.associated) {
found = ieee80211softmac_get_network_by_bssid(mac, mac->associnfo.bssid);
if (found)
ieee80211softmac_send_mgt_frame(mac, found, IEEE80211_STYPE_DISASSOC, reason);
@@ -196,17 +194,18 @@ ieee80211softmac_assoc_work(void *d)
int bssvalid;
unsigned long flags;
+ mutex_lock(&mac->associnfo.mutex);
+
+ if (!mac->associnfo.associating)
+ goto out;
+
/* ieee80211_disassoc might clear this */
bssvalid = mac->associnfo.bssvalid;
/* meh */
- if (mac->associated)
+ if (mac->associnfo.associated)
ieee80211softmac_send_disassoc_req(mac, WLAN_REASON_DISASSOC_STA_HAS_LEFT);
- spin_lock_irqsave(&mac->lock, flags);
- mac->associnfo.associating = 1;
- spin_unlock_irqrestore(&mac->lock, flags);
-
/* try to find the requested network in our list, if we found one already */
if (bssvalid || mac->associnfo.bssfixed)
found = ieee80211softmac_get_network_by_bssid(mac, mac->associnfo.bssid);
@@ -260,10 +259,8 @@ ieee80211softmac_assoc_work(void *d)
if (!found) {
if (mac->associnfo.scan_retry > 0) {
- spin_lock_irqsave(&mac->lock, flags);
mac->associnfo.scan_retry--;
- spin_unlock_irqrestore(&mac->lock, flags);
-
+
/* We know of no such network. Let's scan.
* NB: this also happens if we had no memory to copy the network info...
* Maybe we can hope to have more memory after scanning finishes ;)
@@ -272,19 +269,17 @@ ieee80211softmac_assoc_work(void *d)
ieee80211softmac_notify(mac->dev, IEEE80211SOFTMAC_EVENT_SCAN_FINISHED, ieee80211softmac_assoc_notify_scan, NULL);
if (ieee80211softmac_start_scan(mac))
dprintk(KERN_INFO PFX "Associate: failed to initiate scan. Is device up?\n");
- return;
+ goto out;
} else {
- spin_lock_irqsave(&mac->lock, flags);
mac->associnfo.associating = 0;
- mac->associated = 0;
- spin_unlock_irqrestore(&mac->lock, flags);
+ mac->associnfo.associated = 0;
dprintk(KERN_INFO PFX "Unable to find matching network after scan!\n");
/* reset the retry counter for the next user request since we
* break out and don't reschedule ourselves after this point. */
mac->associnfo.scan_retry = IEEE80211SOFTMAC_ASSOC_SCAN_RETRY_LIMIT;
ieee80211softmac_call_events(mac, IEEE80211SOFTMAC_EVENT_ASSOCIATE_NET_NOT_FOUND, NULL);
- return;
+ goto out;
}
}
@@ -297,7 +292,7 @@ ieee80211softmac_assoc_work(void *d)
/* copy the ESSID for displaying it */
mac->associnfo.associate_essid.len = found->essid.len;
memcpy(mac->associnfo.associate_essid.data, found->essid.data, IW_ESSID_MAX_SIZE + 1);
-
+
/* we found a network! authenticate (if necessary) and associate to it. */
if (found->authenticating) {
dprintk(KERN_INFO PFX "Already requested authentication, waiting...\n");
@@ -305,7 +300,7 @@ ieee80211softmac_assoc_work(void *d)
mac->associnfo.assoc_wait = 1;
ieee80211softmac_notify_internal(mac, IEEE80211SOFTMAC_EVENT_ANY, found, ieee80211softmac_assoc_notify_auth, NULL, GFP_KERNEL);
}
- return;
+ goto out;
}
if (!found->authenticated && !found->authenticating) {
/* This relies on the fact that _auth_req only queues the work,
@@ -321,11 +316,14 @@ ieee80211softmac_assoc_work(void *d)
mac->associnfo.assoc_wait = 0;
ieee80211softmac_call_events(mac, IEEE80211SOFTMAC_EVENT_ASSOCIATE_FAILED, found);
}
- return;
+ goto out;
}
/* finally! now we can start associating */
mac->associnfo.assoc_wait = 0;
ieee80211softmac_assoc(mac, found);
+
+out:
+ mutex_unlock(&mac->associnfo.mutex);
}
/* call this to do whatever is necessary when we're associated */
@@ -341,7 +339,7 @@ ieee80211softmac_associated(struct ieee80211softmac_device *mac,
mac->bssinfo.supported_rates = net->supported_rates;
ieee80211softmac_recalc_txrates(mac);
- mac->associated = 1;
+ mac->associnfo.associated = 1;
mac->associnfo.short_preamble_available =
(cap & WLAN_CAPABILITY_SHORT_PREAMBLE) != 0;
@@ -421,7 +419,7 @@ ieee80211softmac_handle_assoc_response(struct net_device * dev,
dprintk(KERN_INFO PFX "associating failed (reason: 0x%x)!\n", status);
mac->associnfo.associating = 0;
mac->associnfo.bssvalid = 0;
- mac->associated = 0;
+ mac->associnfo.associated = 0;
ieee80211softmac_call_events_locked(mac, IEEE80211SOFTMAC_EVENT_ASSOCIATE_FAILED, network);
}
diff --git a/net/ieee80211/softmac/ieee80211softmac_io.c b/net/ieee80211/softmac/ieee80211softmac_io.c
index 82bfddbf33a2..b96931001b43 100644
--- a/net/ieee80211/softmac/ieee80211softmac_io.c
+++ b/net/ieee80211/softmac/ieee80211softmac_io.c
@@ -304,7 +304,7 @@ ieee80211softmac_auth(struct ieee80211_auth **pkt,
2 + /* Auth Transaction Seq */
2 + /* Status Code */
/* Challenge Text IE */
- is_shared_response ? 0 : 1 + 1 + net->challenge_len
+ (is_shared_response ? 1 + 1 + net->challenge_len : 0)
);
if (unlikely((*pkt) == NULL))
return 0;
@@ -475,8 +475,13 @@ int ieee80211softmac_handle_beacon(struct net_device *dev,
{
struct ieee80211softmac_device *mac = ieee80211_priv(dev);
- if (mac->associated && memcmp(network->bssid, mac->associnfo.bssid, ETH_ALEN) == 0)
- ieee80211softmac_process_erp(mac, network->erp_value);
+ /* This might race, but we don't really care and it's not worth
+ * adding heavyweight locking in this fastpath.
+ */
+ if (mac->associnfo.associated) {
+ if (memcmp(network->bssid, mac->associnfo.bssid, ETH_ALEN) == 0)
+ ieee80211softmac_process_erp(mac, network->erp_value);
+ }
return 0;
}
diff --git a/net/ieee80211/softmac/ieee80211softmac_module.c b/net/ieee80211/softmac/ieee80211softmac_module.c
index addea1cf73ae..33aff4f4a471 100644
--- a/net/ieee80211/softmac/ieee80211softmac_module.c
+++ b/net/ieee80211/softmac/ieee80211softmac_module.c
@@ -57,6 +57,7 @@ struct net_device *alloc_ieee80211softmac(int sizeof_priv)
INIT_LIST_HEAD(&softmac->network_list);
INIT_LIST_HEAD(&softmac->events);
+ mutex_init(&softmac->associnfo.mutex);
INIT_WORK(&softmac->associnfo.work, ieee80211softmac_assoc_work, softmac);
INIT_WORK(&softmac->associnfo.timeout, ieee80211softmac_assoc_timeout, softmac);
softmac->start_scan = ieee80211softmac_start_scan_implementation;
diff --git a/net/ieee80211/softmac/ieee80211softmac_wx.c b/net/ieee80211/softmac/ieee80211softmac_wx.c
index 2aa779d18f38..23068a830f7d 100644
--- a/net/ieee80211/softmac/ieee80211softmac_wx.c
+++ b/net/ieee80211/softmac/ieee80211softmac_wx.c
@@ -73,13 +73,14 @@ ieee80211softmac_wx_set_essid(struct net_device *net_dev,
struct ieee80211softmac_network *n;
struct ieee80211softmac_auth_queue_item *authptr;
int length = 0;
- unsigned long flags;
+
+ mutex_lock(&sm->associnfo.mutex);
/* Check if we're already associating to this or another network
* If it's another network, cancel and start over with our new network
* If it's our network, ignore the change, we're already doing it!
*/
- if((sm->associnfo.associating || sm->associated) &&
+ if((sm->associnfo.associating || sm->associnfo.associated) &&
(data->essid.flags && data->essid.length)) {
/* Get the associating network */
n = ieee80211softmac_get_network_by_bssid(sm, sm->associnfo.bssid);
@@ -87,10 +88,9 @@ ieee80211softmac_wx_set_essid(struct net_device *net_dev,
!memcmp(n->essid.data, extra, n->essid.len)) {
dprintk(KERN_INFO PFX "Already associating or associated to "MAC_FMT"\n",
MAC_ARG(sm->associnfo.bssid));
- return 0;
+ goto out;
} else {
dprintk(KERN_INFO PFX "Canceling existing associate request!\n");
- spin_lock_irqsave(&sm->lock,flags);
/* Cancel assoc work */
cancel_delayed_work(&sm->associnfo.work);
/* We don't have to do this, but it's a little cleaner */
@@ -98,14 +98,13 @@ ieee80211softmac_wx_set_essid(struct net_device *net_dev,
cancel_delayed_work(&authptr->work);
sm->associnfo.bssvalid = 0;
sm->associnfo.bssfixed = 0;
- spin_unlock_irqrestore(&sm->lock,flags);
flush_scheduled_work();
+ sm->associnfo.associating = 0;
+ sm->associnfo.associated = 0;
}
}
- spin_lock_irqsave(&sm->lock, flags);
-
sm->associnfo.static_essid = 0;
sm->associnfo.assoc_wait = 0;
@@ -121,10 +120,12 @@ ieee80211softmac_wx_set_essid(struct net_device *net_dev,
* If applicable, we have already copied the data in */
sm->associnfo.req_essid.len = length;
+ sm->associnfo.associating = 1;
/* queue lower level code to do work (if necessary) */
schedule_work(&sm->associnfo.work);
+out:
+ mutex_unlock(&sm->associnfo.mutex);
- spin_unlock_irqrestore(&sm->lock, flags);
return 0;
}
EXPORT_SYMBOL_GPL(ieee80211softmac_wx_set_essid);
@@ -136,10 +137,8 @@ ieee80211softmac_wx_get_essid(struct net_device *net_dev,
char *extra)
{
struct ieee80211softmac_device *sm = ieee80211_priv(net_dev);
- unsigned long flags;
- /* avoid getting inconsistent information */
- spin_lock_irqsave(&sm->lock, flags);
+ mutex_lock(&sm->associnfo.mutex);
/* If all fails, return ANY (empty) */
data->essid.length = 0;
data->essid.flags = 0; /* active */
@@ -152,12 +151,13 @@ ieee80211softmac_wx_get_essid(struct net_device *net_dev,
}
/* If we're associating/associated, return that */
- if (sm->associated || sm->associnfo.associating) {
+ if (sm->associnfo.associated || sm->associnfo.associating) {
data->essid.length = sm->associnfo.associate_essid.len;
data->essid.flags = 1; /* active */
memcpy(extra, sm->associnfo.associate_essid.data, sm->associnfo.associate_essid.len);
}
- spin_unlock_irqrestore(&sm->lock, flags);
+ mutex_unlock(&sm->associnfo.mutex);
+
return 0;
}
EXPORT_SYMBOL_GPL(ieee80211softmac_wx_get_essid);
@@ -322,15 +322,15 @@ ieee80211softmac_wx_get_wap(struct net_device *net_dev,
{
struct ieee80211softmac_device *mac = ieee80211_priv(net_dev);
int err = 0;
- unsigned long flags;
- spin_lock_irqsave(&mac->lock, flags);
+ mutex_lock(&mac->associnfo.mutex);
if (mac->associnfo.bssvalid)
memcpy(data->ap_addr.sa_data, mac->associnfo.bssid, ETH_ALEN);
else
memset(data->ap_addr.sa_data, 0xff, ETH_ALEN);
data->ap_addr.sa_family = ARPHRD_ETHER;
- spin_unlock_irqrestore(&mac->lock, flags);
+ mutex_unlock(&mac->associnfo.mutex);
+
return err;
}
EXPORT_SYMBOL_GPL(ieee80211softmac_wx_get_wap);
@@ -342,28 +342,27 @@ ieee80211softmac_wx_set_wap(struct net_device *net_dev,
char *extra)
{
struct ieee80211softmac_device *mac = ieee80211_priv(net_dev);
- unsigned long flags;
/* sanity check */
if (data->ap_addr.sa_family != ARPHRD_ETHER) {
return -EINVAL;
}
- spin_lock_irqsave(&mac->lock, flags);
+ mutex_lock(&mac->associnfo.mutex);
if (is_broadcast_ether_addr(data->ap_addr.sa_data)) {
/* the bssid we have is not to be fixed any longer,
* and we should reassociate to the best AP. */
mac->associnfo.bssfixed = 0;
/* force reassociation */
mac->associnfo.bssvalid = 0;
- if (mac->associated)
+ if (mac->associnfo.associated)
schedule_work(&mac->associnfo.work);
} else if (is_zero_ether_addr(data->ap_addr.sa_data)) {
/* the bssid we have is no longer fixed */
mac->associnfo.bssfixed = 0;
} else {
if (!memcmp(mac->associnfo.bssid, data->ap_addr.sa_data, ETH_ALEN)) {
- if (mac->associnfo.associating || mac->associated) {
+ if (mac->associnfo.associating || mac->associnfo.associated) {
/* bssid unchanged and associated or associating - just return */
goto out;
}
@@ -378,7 +377,8 @@ ieee80211softmac_wx_set_wap(struct net_device *net_dev,
}
out:
- spin_unlock_irqrestore(&mac->lock, flags);
+ mutex_unlock(&mac->associnfo.mutex);
+
return 0;
}
EXPORT_SYMBOL_GPL(ieee80211softmac_wx_set_wap);
@@ -394,7 +394,8 @@ ieee80211softmac_wx_set_genie(struct net_device *dev,
int err = 0;
char *buf;
int i;
-
+
+ mutex_lock(&mac->associnfo.mutex);
spin_lock_irqsave(&mac->lock, flags);
/* bleh. shouldn't be locked for that kmalloc... */
@@ -432,6 +433,8 @@ ieee80211softmac_wx_set_genie(struct net_device *dev,
out:
spin_unlock_irqrestore(&mac->lock, flags);
+ mutex_unlock(&mac->associnfo.mutex);
+
return err;
}
EXPORT_SYMBOL_GPL(ieee80211softmac_wx_set_genie);
@@ -446,7 +449,8 @@ ieee80211softmac_wx_get_genie(struct net_device *dev,
unsigned long flags;
int err = 0;
int space = wrqu->data.length;
-
+
+ mutex_lock(&mac->associnfo.mutex);
spin_lock_irqsave(&mac->lock, flags);
wrqu->data.length = 0;
@@ -459,6 +463,8 @@ ieee80211softmac_wx_get_genie(struct net_device *dev,
err = -E2BIG;
}
spin_unlock_irqrestore(&mac->lock, flags);
+ mutex_lock(&mac->associnfo.mutex);
+
return err;
}
EXPORT_SYMBOL_GPL(ieee80211softmac_wx_get_genie);
@@ -473,10 +479,13 @@ ieee80211softmac_wx_set_mlme(struct net_device *dev,
struct iw_mlme *mlme = (struct iw_mlme *)extra;
u16 reason = cpu_to_le16(mlme->reason_code);
struct ieee80211softmac_network *net;
+ int err = -EINVAL;
+
+ mutex_lock(&mac->associnfo.mutex);
if (memcmp(mac->associnfo.bssid, mlme->addr.sa_data, ETH_ALEN)) {
printk(KERN_DEBUG PFX "wx_set_mlme: requested operation on net we don't use\n");
- return -EINVAL;
+ goto out;
}
switch (mlme->cmd) {
@@ -484,14 +493,22 @@ ieee80211softmac_wx_set_mlme(struct net_device *dev,
net = ieee80211softmac_get_network_by_bssid_locked(mac, mlme->addr.sa_data);
if (!net) {
printk(KERN_DEBUG PFX "wx_set_mlme: we should know the net here...\n");
- return -EINVAL;
+ goto out;
}
return ieee80211softmac_deauth_req(mac, net, reason);
case IW_MLME_DISASSOC:
ieee80211softmac_send_disassoc_req(mac, reason);
- return 0;
+ mac->associnfo.associated = 0;
+ mac->associnfo.associating = 0;
+ err = 0;
+ goto out;
default:
- return -EOPNOTSUPP;
+ err = -EOPNOTSUPP;
}
+
+out:
+ mutex_unlock(&mac->associnfo.mutex);
+
+ return err;
}
EXPORT_SYMBOL_GPL(ieee80211softmac_wx_set_mlme);
diff --git a/net/ipv4/cipso_ipv4.c b/net/ipv4/cipso_ipv4.c
index a8e2e879a647..6460233407c7 100644
--- a/net/ipv4/cipso_ipv4.c
+++ b/net/ipv4/cipso_ipv4.c
@@ -43,6 +43,7 @@
#include <net/tcp.h>
#include <net/netlabel.h>
#include <net/cipso_ipv4.h>
+#include <asm/atomic.h>
#include <asm/bug.h>
struct cipso_v4_domhsh_entry {
@@ -79,7 +80,7 @@ struct cipso_v4_map_cache_entry {
unsigned char *key;
size_t key_len;
- struct netlbl_lsm_cache lsm_data;
+ struct netlbl_lsm_cache *lsm_data;
u32 activity;
struct list_head list;
@@ -188,13 +189,14 @@ static void cipso_v4_doi_domhsh_free(struct rcu_head *entry)
* @entry: the entry to free
*
* Description:
- * This function frees the memory associated with a cache entry.
+ * This function frees the memory associated with a cache entry including the
+ * LSM cache data if there are no longer any users, i.e. reference count == 0.
*
*/
static void cipso_v4_cache_entry_free(struct cipso_v4_map_cache_entry *entry)
{
- if (entry->lsm_data.free)
- entry->lsm_data.free(entry->lsm_data.data);
+ if (entry->lsm_data)
+ netlbl_secattr_cache_free(entry->lsm_data);
kfree(entry->key);
kfree(entry);
}
@@ -315,8 +317,8 @@ static int cipso_v4_cache_check(const unsigned char *key,
entry->key_len == key_len &&
memcmp(entry->key, key, key_len) == 0) {
entry->activity += 1;
- secattr->cache.free = entry->lsm_data.free;
- secattr->cache.data = entry->lsm_data.data;
+ atomic_inc(&entry->lsm_data->refcount);
+ secattr->cache = entry->lsm_data;
if (prev_entry == NULL) {
spin_unlock_bh(&cipso_v4_cache[bkt].lock);
return 0;
@@ -383,8 +385,8 @@ int cipso_v4_cache_add(const struct sk_buff *skb,
memcpy(entry->key, cipso_ptr, cipso_ptr_len);
entry->key_len = cipso_ptr_len;
entry->hash = cipso_v4_map_cache_hash(cipso_ptr, cipso_ptr_len);
- entry->lsm_data.free = secattr->cache.free;
- entry->lsm_data.data = secattr->cache.data;
+ atomic_inc(&secattr->cache->refcount);
+ entry->lsm_data = secattr->cache;
bkt = entry->hash & (CIPSO_V4_CACHE_BUCKETBITS - 1);
spin_lock_bh(&cipso_v4_cache[bkt].lock);
@@ -771,13 +773,15 @@ static int cipso_v4_map_cat_rbm_valid(const struct cipso_v4_doi *doi_def,
{
int cat = -1;
u32 bitmap_len_bits = bitmap_len * 8;
- u32 cipso_cat_size = doi_def->map.std->cat.cipso_size;
- u32 *cipso_array = doi_def->map.std->cat.cipso;
+ u32 cipso_cat_size;
+ u32 *cipso_array;
switch (doi_def->type) {
case CIPSO_V4_MAP_PASS:
return 0;
case CIPSO_V4_MAP_STD:
+ cipso_cat_size = doi_def->map.std->cat.cipso_size;
+ cipso_array = doi_def->map.std->cat.cipso;
for (;;) {
cat = cipso_v4_bitmap_walk(bitmap,
bitmap_len_bits,
@@ -823,19 +827,21 @@ static int cipso_v4_map_cat_rbm_hton(const struct cipso_v4_doi *doi_def,
u32 net_spot_max = 0;
u32 host_clen_bits = host_cat_len * 8;
u32 net_clen_bits = net_cat_len * 8;
- u32 host_cat_size = doi_def->map.std->cat.local_size;
- u32 *host_cat_array = doi_def->map.std->cat.local;
+ u32 host_cat_size;
+ u32 *host_cat_array;
switch (doi_def->type) {
case CIPSO_V4_MAP_PASS:
- net_spot_max = host_cat_len - 1;
- while (net_spot_max > 0 && host_cat[net_spot_max] == 0)
+ net_spot_max = host_cat_len;
+ while (net_spot_max > 0 && host_cat[net_spot_max - 1] == 0)
net_spot_max--;
if (net_spot_max > net_cat_len)
return -EINVAL;
memcpy(net_cat, host_cat, net_spot_max);
return net_spot_max;
case CIPSO_V4_MAP_STD:
+ host_cat_size = doi_def->map.std->cat.local_size;
+ host_cat_array = doi_def->map.std->cat.local;
for (;;) {
host_spot = cipso_v4_bitmap_walk(host_cat,
host_clen_bits,
@@ -891,8 +897,8 @@ static int cipso_v4_map_cat_rbm_ntoh(const struct cipso_v4_doi *doi_def,
int net_spot = -1;
u32 net_clen_bits = net_cat_len * 8;
u32 host_clen_bits = host_cat_len * 8;
- u32 net_cat_size = doi_def->map.std->cat.cipso_size;
- u32 *net_cat_array = doi_def->map.std->cat.cipso;
+ u32 net_cat_size;
+ u32 *net_cat_array;
switch (doi_def->type) {
case CIPSO_V4_MAP_PASS:
@@ -901,6 +907,8 @@ static int cipso_v4_map_cat_rbm_ntoh(const struct cipso_v4_doi *doi_def,
memcpy(host_cat, net_cat, net_cat_len);
return net_cat_len;
case CIPSO_V4_MAP_STD:
+ net_cat_size = doi_def->map.std->cat.cipso_size;
+ net_cat_array = doi_def->map.std->cat.cipso;
for (;;) {
net_spot = cipso_v4_bitmap_walk(net_cat,
net_clen_bits,
@@ -1299,7 +1307,8 @@ int cipso_v4_socket_setattr(const struct socket *sock,
/* We can't use ip_options_get() directly because it makes a call to
* ip_options_get_alloc() which allocates memory with GFP_KERNEL and
- * we can't block here. */
+ * we won't always have CAP_NET_RAW even though we _always_ want to
+ * set the IPOPT_CIPSO option. */
opt_len = (buf_len + 3) & ~3;
opt = kzalloc(sizeof(*opt) + opt_len, GFP_ATOMIC);
if (opt == NULL) {
@@ -1309,11 +1318,9 @@ int cipso_v4_socket_setattr(const struct socket *sock,
memcpy(opt->__data, buf, buf_len);
opt->optlen = opt_len;
opt->is_data = 1;
+ opt->cipso = sizeof(struct iphdr);
kfree(buf);
buf = NULL;
- ret_val = ip_options_compile(opt, NULL);
- if (ret_val != 0)
- goto socket_setattr_failure;
sk_inet = inet_sk(sk);
if (sk_inet->is_icsk) {
diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c
index 9c399a70dd5d..af0190d8b6c0 100644
--- a/net/ipv4/fib_frontend.c
+++ b/net/ipv4/fib_frontend.c
@@ -482,9 +482,7 @@ static int rtm_to_fib_config(struct sk_buff *skb, struct nlmsghdr *nlh,
memset(cfg, 0, sizeof(*cfg));
rtm = nlmsg_data(nlh);
- cfg->fc_family = rtm->rtm_family;
cfg->fc_dst_len = rtm->rtm_dst_len;
- cfg->fc_src_len = rtm->rtm_src_len;
cfg->fc_tos = rtm->rtm_tos;
cfg->fc_table = rtm->rtm_table;
cfg->fc_protocol = rtm->rtm_protocol;
@@ -501,9 +499,6 @@ static int rtm_to_fib_config(struct sk_buff *skb, struct nlmsghdr *nlh,
case RTA_DST:
cfg->fc_dst = nla_get_be32(attr);
break;
- case RTA_SRC:
- cfg->fc_src = nla_get_be32(attr);
- break;
case RTA_OIF:
cfg->fc_oif = nla_get_u32(attr);
break;
diff --git a/net/ipv4/inetpeer.c b/net/ipv4/inetpeer.c
index 2b1a54b59c48..f072f3875af8 100644
--- a/net/ipv4/inetpeer.c
+++ b/net/ipv4/inetpeer.c
@@ -94,10 +94,8 @@ int inet_peer_minttl = 120 * HZ; /* TTL under high load: 120 sec */
int inet_peer_maxttl = 10 * 60 * HZ; /* usual time to live: 10 min */
static struct inet_peer *inet_peer_unused_head;
-/* Exported for inet_putpeer inline function. */
-struct inet_peer **inet_peer_unused_tailp = &inet_peer_unused_head;
-DEFINE_SPINLOCK(inet_peer_unused_lock);
-#define PEER_MAX_CLEANUP_WORK 30
+static struct inet_peer **inet_peer_unused_tailp = &inet_peer_unused_head;
+static DEFINE_SPINLOCK(inet_peer_unused_lock);
static void peer_check_expire(unsigned long dummy);
static DEFINE_TIMER(peer_periodic_timer, peer_check_expire, 0, 0);
@@ -340,7 +338,8 @@ static int cleanup_once(unsigned long ttl)
spin_lock_bh(&inet_peer_unused_lock);
p = inet_peer_unused_head;
if (p != NULL) {
- if (time_after(p->dtime + ttl, jiffies)) {
+ __u32 delta = (__u32)jiffies - p->dtime;
+ if (delta < ttl) {
/* Do not prune fresh entries. */
spin_unlock_bh(&inet_peer_unused_lock);
return -1;
@@ -432,7 +431,7 @@ out_free:
/* Called with local BH disabled. */
static void peer_check_expire(unsigned long dummy)
{
- int i;
+ unsigned long now = jiffies;
int ttl;
if (peer_total >= inet_peer_threshold)
@@ -441,7 +440,10 @@ static void peer_check_expire(unsigned long dummy)
ttl = inet_peer_maxttl
- (inet_peer_maxttl - inet_peer_minttl) / HZ *
peer_total / inet_peer_threshold * HZ;
- for (i = 0; i < PEER_MAX_CLEANUP_WORK && !cleanup_once(ttl); i++);
+ while (!cleanup_once(ttl)) {
+ if (jiffies != now)
+ break;
+ }
/* Trigger the timer after inet_peer_gc_mintime .. inet_peer_gc_maxtime
* interval depending on the total number of entries (more entries,
@@ -455,3 +457,16 @@ static void peer_check_expire(unsigned long dummy)
peer_total / inet_peer_threshold * HZ;
add_timer(&peer_periodic_timer);
}
+
+void inet_putpeer(struct inet_peer *p)
+{
+ spin_lock_bh(&inet_peer_unused_lock);
+ if (atomic_dec_and_test(&p->refcnt)) {
+ p->unused_prevp = inet_peer_unused_tailp;
+ p->unused_next = NULL;
+ *inet_peer_unused_tailp = p;
+ inet_peer_unused_tailp = &p->unused_next;
+ p->dtime = (__u32)jiffies;
+ }
+ spin_unlock_bh(&inet_peer_unused_lock);
+}
diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c
index f5fba051df3d..d5b5dec075b8 100644
--- a/net/ipv4/ip_gre.c
+++ b/net/ipv4/ip_gre.c
@@ -611,8 +611,8 @@ static int ipgre_rcv(struct sk_buff *skb)
* - When dealing with WCCPv2, Skip extra 4 bytes in GRE header
*/
if (flags == 0 &&
- skb->protocol == __constant_htons(ETH_P_WCCP)) {
- skb->protocol = __constant_htons(ETH_P_IP);
+ skb->protocol == htons(ETH_P_WCCP)) {
+ skb->protocol = htons(ETH_P_IP);
if ((*(h + offset) & 0xF0) != 0x40)
offset += 4;
}
diff --git a/net/ipv4/ip_options.c b/net/ipv4/ip_options.c
index 8dabbfc31267..9f02917d6f45 100644
--- a/net/ipv4/ip_options.c
+++ b/net/ipv4/ip_options.c
@@ -443,7 +443,7 @@ int ip_options_compile(struct ip_options * opt, struct sk_buff * skb)
opt->router_alert = optptr - iph;
break;
case IPOPT_CIPSO:
- if (opt->cipso) {
+ if ((!skb && !capable(CAP_NET_RAW)) || opt->cipso) {
pp_ptr = optptr;
goto error;
}
diff --git a/net/ipv4/ipconfig.c b/net/ipv4/ipconfig.c
index f8ce84759159..955a07abb91d 100644
--- a/net/ipv4/ipconfig.c
+++ b/net/ipv4/ipconfig.c
@@ -420,7 +420,7 @@ ic_rarp_recv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt
{
struct arphdr *rarp;
unsigned char *rarp_ptr;
- unsigned long sip, tip;
+ u32 sip, tip;
unsigned char *sha, *tha; /* s for "source", t for "target" */
struct ic_device *d;
diff --git a/net/ipv4/ipvs/ip_vs_ftp.c b/net/ipv4/ipvs/ip_vs_ftp.c
index 6d398f10aa91..687c1de1146f 100644
--- a/net/ipv4/ipvs/ip_vs_ftp.c
+++ b/net/ipv4/ipvs/ip_vs_ftp.c
@@ -200,7 +200,7 @@ static int ip_vs_ftp_out(struct ip_vs_app *app, struct ip_vs_conn *cp,
from = n_cp->vaddr;
port = n_cp->vport;
sprintf(buf,"%d,%d,%d,%d,%d,%d", NIPQUAD(from),
- ntohs(port)&255, (ntohs(port)>>8)&255);
+ (ntohs(port)>>8)&255, ntohs(port)&255);
buf_len = strlen(buf);
/*
diff --git a/net/ipv4/ipvs/ip_vs_proto_tcp.c b/net/ipv4/ipvs/ip_vs_proto_tcp.c
index bfe779e74590..6ff05c3a32e6 100644
--- a/net/ipv4/ipvs/ip_vs_proto_tcp.c
+++ b/net/ipv4/ipvs/ip_vs_proto_tcp.c
@@ -117,7 +117,7 @@ tcp_fast_csum_update(struct tcphdr *tcph, __be32 oldip, __be32 newip,
{
tcph->check =
ip_vs_check_diff(~oldip, newip,
- ip_vs_check_diff(oldport ^ htonl(0xFFFF),
+ ip_vs_check_diff(oldport ^ htons(0xFFFF),
newport, tcph->check));
}
diff --git a/net/ipv4/ipvs/ip_vs_proto_udp.c b/net/ipv4/ipvs/ip_vs_proto_udp.c
index 54aa7603591f..691c8b637b29 100644
--- a/net/ipv4/ipvs/ip_vs_proto_udp.c
+++ b/net/ipv4/ipvs/ip_vs_proto_udp.c
@@ -122,10 +122,10 @@ udp_fast_csum_update(struct udphdr *uhdr, __be32 oldip, __be32 newip,
{
uhdr->check =
ip_vs_check_diff(~oldip, newip,
- ip_vs_check_diff(oldport ^ htonl(0xFFFF),
+ ip_vs_check_diff(oldport ^ htons(0xFFFF),
newport, uhdr->check));
if (!uhdr->check)
- uhdr->check = htonl(0xFFFF);
+ uhdr->check = -1;
}
static int
@@ -173,7 +173,7 @@ udp_snat_handler(struct sk_buff **pskb,
cp->protocol,
(*pskb)->csum);
if (udph->check == 0)
- udph->check = htonl(0xFFFF);
+ udph->check = -1;
IP_VS_DBG(11, "O-pkt: %s O-csum=%d (+%zd)\n",
pp->name, udph->check,
(char*)&(udph->check) - (char*)udph);
@@ -228,7 +228,7 @@ udp_dnat_handler(struct sk_buff **pskb,
cp->protocol,
(*pskb)->csum);
if (udph->check == 0)
- udph->check = 0xFFFF;
+ udph->check = -1;
(*pskb)->ip_summed = CHECKSUM_UNNECESSARY;
}
return 1;
diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c
index 17e1a687ab45..413c2d0a1f3d 100644
--- a/net/ipv4/netfilter/arp_tables.c
+++ b/net/ipv4/netfilter/arp_tables.c
@@ -466,7 +466,13 @@ static inline int check_entry(struct arpt_entry *e, const char *name, unsigned i
return -EINVAL;
}
+ if (e->target_offset + sizeof(struct arpt_entry_target) > e->next_offset)
+ return -EINVAL;
+
t = arpt_get_target(e);
+ if (e->target_offset + t->u.target_size > e->next_offset)
+ return -EINVAL;
+
target = try_then_request_module(xt_find_target(NF_ARP, t->u.user.name,
t->u.user.revision),
"arpt_%s", t->u.user.name);
@@ -621,20 +627,18 @@ static int translate_table(const char *name,
}
}
- if (!mark_source_chains(newinfo, valid_hooks, entry0)) {
- duprintf("Looping hook\n");
- return -ELOOP;
- }
-
/* Finally, each sanity check must pass */
i = 0;
ret = ARPT_ENTRY_ITERATE(entry0, newinfo->size,
check_entry, name, size, &i);
- if (ret != 0) {
- ARPT_ENTRY_ITERATE(entry0, newinfo->size,
- cleanup_entry, &i);
- return ret;
+ if (ret != 0)
+ goto cleanup;
+
+ ret = -ELOOP;
+ if (!mark_source_chains(newinfo, valid_hooks, entry0)) {
+ duprintf("Looping hook\n");
+ goto cleanup;
}
/* And one copy for every other CPU */
@@ -643,6 +647,9 @@ static int translate_table(const char *name,
memcpy(newinfo->entries[i], entry0, newinfo->size);
}
+ return 0;
+cleanup:
+ ARPT_ENTRY_ITERATE(entry0, newinfo->size, cleanup_entry, &i);
return ret;
}
@@ -1196,6 +1203,8 @@ err1:
static void __exit arp_tables_fini(void)
{
nf_unregister_sockopt(&arpt_sockopts);
+ xt_unregister_target(&arpt_error_target);
+ xt_unregister_target(&arpt_standard_target);
xt_proto_fini(NF_ARP);
}
diff --git a/net/ipv4/netfilter/ip_conntrack_netlink.c b/net/ipv4/netfilter/ip_conntrack_netlink.c
index 53b6dffea6c2..262d0d44ec1b 100644
--- a/net/ipv4/netfilter/ip_conntrack_netlink.c
+++ b/net/ipv4/netfilter/ip_conntrack_netlink.c
@@ -44,13 +44,6 @@ MODULE_LICENSE("GPL");
static char __initdata version[] = "0.90";
-#if 0
-#define DEBUGP printk
-#else
-#define DEBUGP(format, args...)
-#endif
-
-
static inline int
ctnetlink_dump_tuples_proto(struct sk_buff *skb,
const struct ip_conntrack_tuple *tuple,
@@ -398,7 +391,6 @@ nfattr_failure:
static int ctnetlink_done(struct netlink_callback *cb)
{
- DEBUGP("entered %s\n", __FUNCTION__);
if (cb->args[1])
ip_conntrack_put((struct ip_conntrack *)cb->args[1]);
return 0;
@@ -411,9 +403,6 @@ ctnetlink_dump_table(struct sk_buff *skb, struct netlink_callback *cb)
struct ip_conntrack_tuple_hash *h;
struct list_head *i;
- DEBUGP("entered %s, last bucket=%lu id=%u\n", __FUNCTION__,
- cb->args[0], *id);
-
read_lock_bh(&ip_conntrack_lock);
last = (struct ip_conntrack *)cb->args[1];
for (; cb->args[0] < ip_conntrack_htable_size; cb->args[0]++) {
@@ -452,7 +441,6 @@ out:
if (last)
ip_conntrack_put(last);
- DEBUGP("leaving, last bucket=%lu id=%u\n", cb->args[0], *id);
return skb->len;
}
@@ -466,8 +454,6 @@ ctnetlink_parse_tuple_ip(struct nfattr *attr, struct ip_conntrack_tuple *tuple)
{
struct nfattr *tb[CTA_IP_MAX];
- DEBUGP("entered %s\n", __FUNCTION__);
-
nfattr_parse_nested(tb, CTA_IP_MAX, attr);
if (nfattr_bad_size(tb, CTA_IP_MAX, cta_min_ip))
@@ -481,8 +467,6 @@ ctnetlink_parse_tuple_ip(struct nfattr *attr, struct ip_conntrack_tuple *tuple)
return -EINVAL;
tuple->dst.ip = *(__be32 *)NFA_DATA(tb[CTA_IP_V4_DST-1]);
- DEBUGP("leaving\n");
-
return 0;
}
@@ -503,8 +487,6 @@ ctnetlink_parse_tuple_proto(struct nfattr *attr,
struct ip_conntrack_protocol *proto;
int ret = 0;
- DEBUGP("entered %s\n", __FUNCTION__);
-
nfattr_parse_nested(tb, CTA_PROTO_MAX, attr);
if (nfattr_bad_size(tb, CTA_PROTO_MAX, cta_min_proto))
@@ -531,8 +513,6 @@ ctnetlink_parse_tuple(struct nfattr *cda[], struct ip_conntrack_tuple *tuple,
struct nfattr *tb[CTA_TUPLE_MAX];
int err;
- DEBUGP("entered %s\n", __FUNCTION__);
-
memset(tuple, 0, sizeof(*tuple));
nfattr_parse_nested(tb, CTA_TUPLE_MAX, cda[type-1]);
@@ -557,10 +537,6 @@ ctnetlink_parse_tuple(struct nfattr *cda[], struct ip_conntrack_tuple *tuple,
else
tuple->dst.dir = IP_CT_DIR_ORIGINAL;
- DUMP_TUPLE(tuple);
-
- DEBUGP("leaving\n");
-
return 0;
}
@@ -577,8 +553,6 @@ static int ctnetlink_parse_nat_proto(struct nfattr *attr,
struct nfattr *tb[CTA_PROTONAT_MAX];
struct ip_nat_protocol *npt;
- DEBUGP("entered %s\n", __FUNCTION__);
-
nfattr_parse_nested(tb, CTA_PROTONAT_MAX, attr);
if (nfattr_bad_size(tb, CTA_PROTONAT_MAX, cta_min_protonat))
@@ -597,7 +571,6 @@ static int ctnetlink_parse_nat_proto(struct nfattr *attr,
ip_nat_proto_put(npt);
- DEBUGP("leaving\n");
return 0;
}
@@ -613,8 +586,6 @@ ctnetlink_parse_nat(struct nfattr *nat,
struct nfattr *tb[CTA_NAT_MAX];
int err;
- DEBUGP("entered %s\n", __FUNCTION__);
-
memset(range, 0, sizeof(*range));
nfattr_parse_nested(tb, CTA_NAT_MAX, nat);
@@ -640,7 +611,6 @@ ctnetlink_parse_nat(struct nfattr *nat,
if (err < 0)
return err;
- DEBUGP("leaving\n");
return 0;
}
#endif
@@ -650,8 +620,6 @@ ctnetlink_parse_help(struct nfattr *attr, char **helper_name)
{
struct nfattr *tb[CTA_HELP_MAX];
- DEBUGP("entered %s\n", __FUNCTION__);
-
nfattr_parse_nested(tb, CTA_HELP_MAX, attr);
if (!tb[CTA_HELP_NAME-1])
@@ -679,8 +647,6 @@ ctnetlink_del_conntrack(struct sock *ctnl, struct sk_buff *skb,
struct ip_conntrack *ct;
int err = 0;
- DEBUGP("entered %s\n", __FUNCTION__);
-
if (nfattr_bad_size(cda, CTA_MAX, cta_min))
return -EINVAL;
@@ -698,10 +664,8 @@ ctnetlink_del_conntrack(struct sock *ctnl, struct sk_buff *skb,
return err;
h = ip_conntrack_find_get(&tuple, NULL);
- if (!h) {
- DEBUGP("tuple not found in conntrack hash\n");
+ if (!h)
return -ENOENT;
- }
ct = tuplehash_to_ctrack(h);
@@ -716,7 +680,6 @@ ctnetlink_del_conntrack(struct sock *ctnl, struct sk_buff *skb,
ct->timeout.function((unsigned long)ct);
ip_conntrack_put(ct);
- DEBUGP("leaving\n");
return 0;
}
@@ -731,8 +694,6 @@ ctnetlink_get_conntrack(struct sock *ctnl, struct sk_buff *skb,
struct sk_buff *skb2 = NULL;
int err = 0;
- DEBUGP("entered %s\n", __FUNCTION__);
-
if (nlh->nlmsg_flags & NLM_F_DUMP) {
struct nfgenmsg *msg = NLMSG_DATA(nlh);
u32 rlen;
@@ -770,11 +731,9 @@ ctnetlink_get_conntrack(struct sock *ctnl, struct sk_buff *skb,
return err;
h = ip_conntrack_find_get(&tuple, NULL);
- if (!h) {
- DEBUGP("tuple not found in conntrack hash");
+ if (!h)
return -ENOENT;
- }
- DEBUGP("tuple found\n");
+
ct = tuplehash_to_ctrack(h);
err = -ENOMEM;
@@ -795,7 +754,6 @@ ctnetlink_get_conntrack(struct sock *ctnl, struct sk_buff *skb,
if (err < 0)
goto out;
- DEBUGP("leaving\n");
return 0;
free:
@@ -866,8 +824,6 @@ ctnetlink_change_helper(struct ip_conntrack *ct, struct nfattr *cda[])
char *helpname;
int err;
- DEBUGP("entered %s\n", __FUNCTION__);
-
/* don't change helper of sibling connections */
if (ct->master)
return -EINVAL;
@@ -938,8 +894,6 @@ ctnetlink_change_conntrack(struct ip_conntrack *ct, struct nfattr *cda[])
{
int err;
- DEBUGP("entered %s\n", __FUNCTION__);
-
if (cda[CTA_HELP-1]) {
err = ctnetlink_change_helper(ct, cda);
if (err < 0)
@@ -969,7 +923,6 @@ ctnetlink_change_conntrack(struct ip_conntrack *ct, struct nfattr *cda[])
ct->mark = ntohl(*(__be32 *)NFA_DATA(cda[CTA_MARK-1]));
#endif
- DEBUGP("all done\n");
return 0;
}
@@ -981,8 +934,6 @@ ctnetlink_create_conntrack(struct nfattr *cda[],
struct ip_conntrack *ct;
int err = -EINVAL;
- DEBUGP("entered %s\n", __FUNCTION__);
-
ct = ip_conntrack_alloc(otuple, rtuple);
if (ct == NULL || IS_ERR(ct))
return -ENOMEM;
@@ -1017,7 +968,6 @@ ctnetlink_create_conntrack(struct nfattr *cda[],
if (ct->helper)
ip_conntrack_helper_put(ct->helper);
- DEBUGP("conntrack with id %u inserted\n", ct->id);
return 0;
err:
@@ -1033,8 +983,6 @@ ctnetlink_new_conntrack(struct sock *ctnl, struct sk_buff *skb,
struct ip_conntrack_tuple_hash *h = NULL;
int err = 0;
- DEBUGP("entered %s\n", __FUNCTION__);
-
if (nfattr_bad_size(cda, CTA_MAX, cta_min))
return -EINVAL;
@@ -1058,7 +1006,6 @@ ctnetlink_new_conntrack(struct sock *ctnl, struct sk_buff *skb,
if (h == NULL) {
write_unlock_bh(&ip_conntrack_lock);
- DEBUGP("no such conntrack, create new\n");
err = -ENOENT;
if (nlh->nlmsg_flags & NLM_F_CREATE)
err = ctnetlink_create_conntrack(cda, &otuple, &rtuple);
@@ -1074,7 +1021,6 @@ ctnetlink_new_conntrack(struct sock *ctnl, struct sk_buff *skb,
/* We manipulate the conntrack inside the global conntrack table lock,
* so there's no need to increase the refcount */
- DEBUGP("conntrack found\n");
err = -EEXIST;
if (!(nlh->nlmsg_flags & NLM_F_EXCL))
err = ctnetlink_change_conntrack(tuplehash_to_ctrack(h), cda);
@@ -1249,8 +1195,6 @@ ctnetlink_exp_dump_table(struct sk_buff *skb, struct netlink_callback *cb)
struct list_head *i;
u_int32_t *id = (u_int32_t *) &cb->args[0];
- DEBUGP("entered %s, last id=%llu\n", __FUNCTION__, *id);
-
read_lock_bh(&ip_conntrack_lock);
list_for_each_prev(i, &ip_conntrack_expect_list) {
exp = (struct ip_conntrack_expect *) i;
@@ -1266,8 +1210,6 @@ ctnetlink_exp_dump_table(struct sk_buff *skb, struct netlink_callback *cb)
out:
read_unlock_bh(&ip_conntrack_lock);
- DEBUGP("leaving, last id=%llu\n", *id);
-
return skb->len;
}
@@ -1285,8 +1227,6 @@ ctnetlink_get_expect(struct sock *ctnl, struct sk_buff *skb,
struct sk_buff *skb2;
int err = 0;
- DEBUGP("entered %s\n", __FUNCTION__);
-
if (nfattr_bad_size(cda, CTA_EXPECT_MAX, cta_min_exp))
return -EINVAL;
@@ -1437,8 +1377,6 @@ ctnetlink_create_expect(struct nfattr *cda[])
struct ip_conntrack *ct;
int err = 0;
- DEBUGP("entered %s\n", __FUNCTION__);
-
/* caller guarantees that those three CTA_EXPECT_* exist */
err = ctnetlink_parse_tuple(cda, &tuple, CTA_EXPECT_TUPLE);
if (err < 0)
@@ -1490,8 +1428,6 @@ ctnetlink_new_expect(struct sock *ctnl, struct sk_buff *skb,
struct ip_conntrack_expect *exp;
int err = 0;
- DEBUGP("entered %s\n", __FUNCTION__);
-
if (nfattr_bad_size(cda, CTA_EXPECT_MAX, cta_min_exp))
return -EINVAL;
@@ -1520,8 +1456,6 @@ ctnetlink_new_expect(struct sock *ctnl, struct sk_buff *skb,
err = ctnetlink_change_expect(exp, cda);
write_unlock_bh(&ip_conntrack_lock);
- DEBUGP("leaving\n");
-
return err;
}
diff --git a/net/ipv4/netfilter/ip_queue.c b/net/ipv4/netfilter/ip_queue.c
index 7edad790478a..97556cc2e4e0 100644
--- a/net/ipv4/netfilter/ip_queue.c
+++ b/net/ipv4/netfilter/ip_queue.c
@@ -351,9 +351,10 @@ ipq_mangle_ipv4(ipq_verdict_msg_t *v, struct ipq_queue_entry *e)
if (v->data_len < sizeof(*user_iph))
return 0;
diff = v->data_len - e->skb->len;
- if (diff < 0)
- skb_trim(e->skb, v->data_len);
- else if (diff > 0) {
+ if (diff < 0) {
+ if (pskb_trim(e->skb, v->data_len))
+ return -ENOMEM;
+ } else if (diff > 0) {
if (v->data_len > 0xFFFF)
return -EINVAL;
if (diff > skb_tailroom(e->skb)) {
diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c
index 78a44b01c035..8a455439b128 100644
--- a/net/ipv4/netfilter/ip_tables.c
+++ b/net/ipv4/netfilter/ip_tables.c
@@ -547,12 +547,18 @@ check_entry(struct ipt_entry *e, const char *name, unsigned int size,
return -EINVAL;
}
+ if (e->target_offset + sizeof(struct ipt_entry_target) > e->next_offset)
+ return -EINVAL;
+
j = 0;
ret = IPT_MATCH_ITERATE(e, check_match, name, &e->ip, e->comefrom, &j);
if (ret != 0)
goto cleanup_matches;
t = ipt_get_target(e);
+ ret = -EINVAL;
+ if (e->target_offset + t->u.target_size > e->next_offset)
+ goto cleanup_matches;
target = try_then_request_module(xt_find_target(AF_INET,
t->u.user.name,
t->u.user.revision),
@@ -712,19 +718,17 @@ translate_table(const char *name,
}
}
- if (!mark_source_chains(newinfo, valid_hooks, entry0))
- return -ELOOP;
-
/* Finally, each sanity check must pass */
i = 0;
ret = IPT_ENTRY_ITERATE(entry0, newinfo->size,
check_entry, name, size, &i);
- if (ret != 0) {
- IPT_ENTRY_ITERATE(entry0, newinfo->size,
- cleanup_entry, &i);
- return ret;
- }
+ if (ret != 0)
+ goto cleanup;
+
+ ret = -ELOOP;
+ if (!mark_source_chains(newinfo, valid_hooks, entry0))
+ goto cleanup;
/* And one copy for every other CPU */
for_each_possible_cpu(i) {
@@ -732,6 +736,9 @@ translate_table(const char *name,
memcpy(newinfo->entries[i], entry0, newinfo->size);
}
+ return 0;
+cleanup:
+ IPT_ENTRY_ITERATE(entry0, newinfo->size, cleanup_entry, &i);
return ret;
}
@@ -1463,6 +1470,10 @@ check_compat_entry_size_and_hooks(struct ipt_entry *e,
return -EINVAL;
}
+ if (e->target_offset + sizeof(struct compat_xt_entry_target) >
+ e->next_offset)
+ return -EINVAL;
+
off = 0;
entry_offset = (void *)e - (void *)base;
j = 0;
@@ -1472,6 +1483,9 @@ check_compat_entry_size_and_hooks(struct ipt_entry *e,
goto cleanup_matches;
t = ipt_get_target(e);
+ ret = -EINVAL;
+ if (e->target_offset + t->u.target_size > e->next_offset)
+ goto cleanup_matches;
target = try_then_request_module(xt_find_target(AF_INET,
t->u.user.name,
t->u.user.revision),
@@ -1513,7 +1527,7 @@ cleanup_matches:
static inline int compat_copy_match_from_user(struct ipt_entry_match *m,
void **dstptr, compat_uint_t *size, const char *name,
- const struct ipt_ip *ip, unsigned int hookmask, int *i)
+ const struct ipt_ip *ip, unsigned int hookmask)
{
struct ipt_entry_match *dm;
struct ipt_match *match;
@@ -1526,22 +1540,13 @@ static inline int compat_copy_match_from_user(struct ipt_entry_match *m,
ret = xt_check_match(match, AF_INET, dm->u.match_size - sizeof(*dm),
name, hookmask, ip->proto,
ip->invflags & IPT_INV_PROTO);
- if (ret)
- goto err;
-
- if (m->u.kernel.match->checkentry
+ if (!ret && m->u.kernel.match->checkentry
&& !m->u.kernel.match->checkentry(name, ip, match, dm->data,
hookmask)) {
duprintf("ip_tables: check failed for `%s'.\n",
m->u.kernel.match->name);
ret = -EINVAL;
- goto err;
}
- (*i)++;
- return 0;
-
-err:
- module_put(m->u.kernel.match->me);
return ret;
}
@@ -1553,19 +1558,18 @@ static int compat_copy_entry_from_user(struct ipt_entry *e, void **dstptr,
struct ipt_target *target;
struct ipt_entry *de;
unsigned int origsize;
- int ret, h, j;
+ int ret, h;
ret = 0;
origsize = *size;
de = (struct ipt_entry *)*dstptr;
memcpy(de, e, sizeof(struct ipt_entry));
- j = 0;
*dstptr += sizeof(struct compat_ipt_entry);
ret = IPT_MATCH_ITERATE(e, compat_copy_match_from_user, dstptr, size,
- name, &de->ip, de->comefrom, &j);
+ name, &de->ip, de->comefrom);
if (ret)
- goto cleanup_matches;
+ goto err;
de->target_offset = e->target_offset - (origsize - *size);
t = ipt_get_target(e);
target = t->u.kernel.target;
@@ -1599,12 +1603,7 @@ static int compat_copy_entry_from_user(struct ipt_entry *e, void **dstptr,
goto err;
}
ret = 0;
- return ret;
-
err:
- module_put(t->u.kernel.target->me);
-cleanup_matches:
- IPT_MATCH_ITERATE(e, cleanup_match, &j);
return ret;
}
@@ -1618,7 +1617,7 @@ translate_compat_table(const char *name,
unsigned int *hook_entries,
unsigned int *underflows)
{
- unsigned int i;
+ unsigned int i, j;
struct xt_table_info *newinfo, *info;
void *pos, *entry0, *entry1;
unsigned int size;
@@ -1636,21 +1635,21 @@ translate_compat_table(const char *name,
}
duprintf("translate_compat_table: size %u\n", info->size);
- i = 0;
+ j = 0;
xt_compat_lock(AF_INET);
/* Walk through entries, checking offsets. */
ret = IPT_ENTRY_ITERATE(entry0, total_size,
check_compat_entry_size_and_hooks,
info, &size, entry0,
entry0 + total_size,
- hook_entries, underflows, &i, name);
+ hook_entries, underflows, &j, name);
if (ret != 0)
goto out_unlock;
ret = -EINVAL;
- if (i != number) {
+ if (j != number) {
duprintf("translate_compat_table: %u not %u entries\n",
- i, number);
+ j, number);
goto out_unlock;
}
@@ -1709,8 +1708,10 @@ translate_compat_table(const char *name,
free_newinfo:
xt_free_table_info(newinfo);
out:
+ IPT_ENTRY_ITERATE(entry0, total_size, cleanup_entry, &j);
return ret;
out_unlock:
+ compat_flush_offsets();
xt_compat_unlock(AF_INET);
goto out;
}
@@ -1932,6 +1933,9 @@ compat_do_ipt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
{
int ret;
+ if (!capable(CAP_NET_ADMIN))
+ return -EPERM;
+
switch (cmd) {
case IPT_SO_GET_INFO:
ret = get_info(user, len, 1);
diff --git a/net/ipv4/netfilter/ipt_ECN.c b/net/ipv4/netfilter/ipt_ECN.c
index 12a818a2462f..1aa4517fbcdb 100644
--- a/net/ipv4/netfilter/ipt_ECN.c
+++ b/net/ipv4/netfilter/ipt_ECN.c
@@ -28,7 +28,7 @@ static inline int
set_ect_ip(struct sk_buff **pskb, const struct ipt_ECN_info *einfo)
{
struct iphdr *iph = (*pskb)->nh.iph;
- __be16 oldtos;
+ u_int16_t oldtos;
if ((iph->tos & IPT_ECN_IP_MASK) != (einfo->ip_ect & IPT_ECN_IP_MASK)) {
if (!skb_make_writable(pskb, sizeof(struct iphdr)))
@@ -37,8 +37,8 @@ set_ect_ip(struct sk_buff **pskb, const struct ipt_ECN_info *einfo)
oldtos = iph->tos;
iph->tos &= ~IPT_ECN_IP_MASK;
iph->tos |= (einfo->ip_ect & IPT_ECN_IP_MASK);
- iph->check = nf_csum_update(oldtos ^ htons(0xFFFF), iph->tos,
- iph->check);
+ iph->check = nf_csum_update(htons(oldtos) ^ htons(0xFFFF),
+ htons(iph->tos), iph->check);
}
return 1;
}
diff --git a/net/ipv4/netfilter/ipt_TOS.c b/net/ipv4/netfilter/ipt_TOS.c
index 6b8b14ccc3d3..83b80b3a5d2f 100644
--- a/net/ipv4/netfilter/ipt_TOS.c
+++ b/net/ipv4/netfilter/ipt_TOS.c
@@ -30,7 +30,7 @@ target(struct sk_buff **pskb,
{
const struct ipt_tos_target_info *tosinfo = targinfo;
struct iphdr *iph = (*pskb)->nh.iph;
- __be16 oldtos;
+ u_int16_t oldtos;
if ((iph->tos & IPTOS_TOS_MASK) != tosinfo->tos) {
if (!skb_make_writable(pskb, sizeof(struct iphdr)))
@@ -38,8 +38,8 @@ target(struct sk_buff **pskb,
iph = (*pskb)->nh.iph;
oldtos = iph->tos;
iph->tos = (iph->tos & IPTOS_PREC_MASK) | tosinfo->tos;
- iph->check = nf_csum_update(oldtos ^ htons(0xFFFF), iph->tos,
- iph->check);
+ iph->check = nf_csum_update(htons(oldtos) ^ htons(0xFFFF),
+ htons(iph->tos), iph->check);
}
return IPT_CONTINUE;
}
diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c
index b430cf2a4f66..5c31dead2bdc 100644
--- a/net/ipv4/raw.c
+++ b/net/ipv4/raw.c
@@ -329,7 +329,7 @@ error:
return err;
}
-static void raw_probe_proto_opt(struct flowi *fl, struct msghdr *msg)
+static int raw_probe_proto_opt(struct flowi *fl, struct msghdr *msg)
{
struct iovec *iov;
u8 __user *type = NULL;
@@ -338,7 +338,7 @@ static void raw_probe_proto_opt(struct flowi *fl, struct msghdr *msg)
unsigned int i;
if (!msg->msg_iov)
- return;
+ return 0;
for (i = 0; i < msg->msg_iovlen; i++) {
iov = &msg->msg_iov[i];
@@ -360,8 +360,9 @@ static void raw_probe_proto_opt(struct flowi *fl, struct msghdr *msg)
code = iov->iov_base;
if (type && code) {
- get_user(fl->fl_icmp_type, type);
- get_user(fl->fl_icmp_code, code);
+ if (get_user(fl->fl_icmp_type, type) ||
+ get_user(fl->fl_icmp_code, code))
+ return -EFAULT;
probed = 1;
}
break;
@@ -372,6 +373,7 @@ static void raw_probe_proto_opt(struct flowi *fl, struct msghdr *msg)
if (probed)
break;
}
+ return 0;
}
static int raw_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
@@ -480,8 +482,11 @@ static int raw_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
.proto = inet->hdrincl ? IPPROTO_RAW :
sk->sk_protocol,
};
- if (!inet->hdrincl)
- raw_probe_proto_opt(&fl, msg);
+ if (!inet->hdrincl) {
+ err = raw_probe_proto_opt(&fl, msg);
+ if (err)
+ goto done;
+ }
security_sk_classify_flow(sk, &fl);
err = ip_route_output_flow(&rt, &fl, sk, !(msg->msg_flags&MSG_DONTWAIT));
diff --git a/net/ipv4/route.c b/net/ipv4/route.c
index c41ddba02e9d..925ee4dfc32c 100644
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -566,9 +566,15 @@ static inline u32 rt_score(struct rtable *rt)
static inline int compare_keys(struct flowi *fl1, struct flowi *fl2)
{
- return memcmp(&fl1->nl_u.ip4_u, &fl2->nl_u.ip4_u, sizeof(fl1->nl_u.ip4_u)) == 0 &&
- fl1->oif == fl2->oif &&
- fl1->iif == fl2->iif;
+ return ((fl1->nl_u.ip4_u.daddr ^ fl2->nl_u.ip4_u.daddr) |
+ (fl1->nl_u.ip4_u.saddr ^ fl2->nl_u.ip4_u.saddr) |
+#ifdef CONFIG_IP_ROUTE_FWMARK
+ (fl1->nl_u.ip4_u.fwmark ^ fl2->nl_u.ip4_u.fwmark) |
+#endif
+ (*(u16 *)&fl1->nl_u.ip4_u.tos ^
+ *(u16 *)&fl2->nl_u.ip4_u.tos) |
+ (fl1->oif ^ fl2->oif) |
+ (fl1->iif ^ fl2->iif)) == 0;
}
#ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED
diff --git a/net/ipv4/sysctl_net_ipv4.c b/net/ipv4/sysctl_net_ipv4.c
index e82a5be894b5..15061b314411 100644
--- a/net/ipv4/sysctl_net_ipv4.c
+++ b/net/ipv4/sysctl_net_ipv4.c
@@ -129,13 +129,6 @@ static int sysctl_tcp_congestion_control(ctl_table *table, int __user *name,
return ret;
}
-static int __init tcp_congestion_default(void)
-{
- return tcp_set_default_congestion_control(CONFIG_DEFAULT_TCP_CONG);
-}
-
-late_initcall(tcp_congestion_default);
-
ctl_table ipv4_table[] = {
{
.ctl_name = NET_IPV4_TCP_TIMESTAMPS,
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
index 66e9a729f6df..c05e8edaf544 100644
--- a/net/ipv4/tcp.c
+++ b/net/ipv4/tcp.c
@@ -2270,7 +2270,7 @@ void __init tcp_init(void)
thash_entries,
(num_physpages >= 128 * 1024) ?
13 : 15,
- HASH_HIGHMEM,
+ 0,
&tcp_hashinfo.ehash_size,
NULL,
0);
@@ -2286,7 +2286,7 @@ void __init tcp_init(void)
tcp_hashinfo.ehash_size,
(num_physpages >= 128 * 1024) ?
13 : 15,
- HASH_HIGHMEM,
+ 0,
&tcp_hashinfo.bhash_size,
NULL,
64 * 1024);
@@ -2316,9 +2316,10 @@ void __init tcp_init(void)
sysctl_max_syn_backlog = 128;
}
- sysctl_tcp_mem[0] = 768 << order;
- sysctl_tcp_mem[1] = 1024 << order;
- sysctl_tcp_mem[2] = 1536 << order;
+ /* Allow no more than 3/4 kernel memory (usually less) allocated to TCP */
+ sysctl_tcp_mem[0] = (1536 / sizeof (struct inet_bind_hashbucket)) << order;
+ sysctl_tcp_mem[1] = sysctl_tcp_mem[0] * 4 / 3;
+ sysctl_tcp_mem[2] = sysctl_tcp_mem[0] * 2;
limit = ((unsigned long)sysctl_tcp_mem[1]) << (PAGE_SHIFT - 7);
max_share = min(4UL*1024*1024, limit);
diff --git a/net/ipv4/tcp_cong.c b/net/ipv4/tcp_cong.c
index af0aca1e6be6..1e2982f4acd4 100644
--- a/net/ipv4/tcp_cong.c
+++ b/net/ipv4/tcp_cong.c
@@ -131,6 +131,14 @@ int tcp_set_default_congestion_control(const char *name)
return ret;
}
+/* Set default value from kernel configuration at bootup */
+static int __init tcp_congestion_default(void)
+{
+ return tcp_set_default_congestion_control(CONFIG_DEFAULT_TCP_CONG);
+}
+late_initcall(tcp_congestion_default);
+
+
/* Get current default congestion control */
void tcp_get_default_congestion_control(char *name)
{
diff --git a/net/ipv4/tcp_cubic.c b/net/ipv4/tcp_cubic.c
index a60ef38d75c6..6ad184802266 100644
--- a/net/ipv4/tcp_cubic.c
+++ b/net/ipv4/tcp_cubic.c
@@ -190,7 +190,7 @@ static inline void bictcp_update(struct bictcp *ca, u32 cwnd)
*/
/* change the unit from HZ to bictcp_HZ */
- t = ((tcp_time_stamp + ca->delay_min - ca->epoch_start)
+ t = ((tcp_time_stamp + (ca->delay_min>>3) - ca->epoch_start)
<< BICTCP_HZ) / HZ;
if (t < ca->bic_K) /* t - K */
@@ -259,7 +259,7 @@ static inline void measure_delay(struct sock *sk)
(s32)(tcp_time_stamp - ca->epoch_start) < HZ)
return;
- delay = tcp_time_stamp - tp->rx_opt.rcv_tsecr;
+ delay = (tcp_time_stamp - tp->rx_opt.rcv_tsecr)<<3;
if (delay == 0)
delay = 1;
@@ -366,7 +366,7 @@ static int __init cubictcp_register(void)
beta_scale = 8*(BICTCP_BETA_SCALE+beta)/ 3 / (BICTCP_BETA_SCALE - beta);
- cube_rtt_scale = (bic_scale << 3) / 10; /* 1024*c/rtt */
+ cube_rtt_scale = (bic_scale * 10); /* 1024*c/rtt */
/* calculate the "K" for (wmax-cwnd) = c/rtt * K^3
* so K = cubic_root( (wmax-cwnd)*rtt/c )
diff --git a/net/ipv4/tcp_htcp.c b/net/ipv4/tcp_htcp.c
index 682e7d5b6f2f..283be3cb4667 100644
--- a/net/ipv4/tcp_htcp.c
+++ b/net/ipv4/tcp_htcp.c
@@ -23,7 +23,7 @@ module_param(use_bandwidth_switch, int, 0644);
MODULE_PARM_DESC(use_bandwidth_switch, "turn on/off bandwidth switcher");
struct htcp {
- u16 alpha; /* Fixed point arith, << 7 */
+ u32 alpha; /* Fixed point arith, << 7 */
u8 beta; /* Fixed point arith, << 7 */
u8 modeswitch; /* Delay modeswitch until we had at least one congestion event */
u32 last_cong; /* Time since last congestion event end */
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
index c83938b8fcb1..22ef8bd26620 100644
--- a/net/ipv4/tcp_ipv4.c
+++ b/net/ipv4/tcp_ipv4.c
@@ -355,7 +355,7 @@ void tcp_v4_err(struct sk_buff *skb, u32 info)
return;
}
if (sk->sk_state == TCP_TIME_WAIT) {
- inet_twsk_put((struct inet_timewait_sock *)sk);
+ inet_twsk_put(inet_twsk(sk));
return;
}
@@ -373,7 +373,7 @@ void tcp_v4_err(struct sk_buff *skb, u32 info)
seq = ntohl(th->seq);
if (sk->sk_state != TCP_LISTEN &&
!between(seq, tp->snd_una, tp->snd_nxt)) {
- NET_INC_STATS(LINUX_MIB_OUTOFWINDOWICMPS);
+ NET_INC_STATS_BH(LINUX_MIB_OUTOFWINDOWICMPS);
goto out;
}
@@ -578,7 +578,7 @@ static void tcp_v4_send_ack(struct sk_buff *skb, u32 seq, u32 ack,
struct tcphdr *th = skb->h.th;
struct {
struct tcphdr th;
- u32 tsopt[3];
+ u32 tsopt[TCPOLEN_TSTAMP_ALIGNED >> 2];
} rep;
struct ip_reply_arg arg;
@@ -960,7 +960,7 @@ static struct sock *tcp_v4_hnd_req(struct sock *sk, struct sk_buff *skb)
bh_lock_sock(nsk);
return nsk;
}
- inet_twsk_put((struct inet_timewait_sock *)nsk);
+ inet_twsk_put(inet_twsk(nsk));
return NULL;
}
@@ -1154,26 +1154,24 @@ discard_and_relse:
do_time_wait:
if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb)) {
- inet_twsk_put((struct inet_timewait_sock *) sk);
+ inet_twsk_put(inet_twsk(sk));
goto discard_it;
}
if (skb->len < (th->doff << 2) || tcp_checksum_complete(skb)) {
TCP_INC_STATS_BH(TCP_MIB_INERRS);
- inet_twsk_put((struct inet_timewait_sock *) sk);
+ inet_twsk_put(inet_twsk(sk));
goto discard_it;
}
- switch (tcp_timewait_state_process((struct inet_timewait_sock *)sk,
- skb, th)) {
+ switch (tcp_timewait_state_process(inet_twsk(sk), skb, th)) {
case TCP_TW_SYN: {
struct sock *sk2 = inet_lookup_listener(&tcp_hashinfo,
skb->nh.iph->daddr,
th->dest,
inet_iif(skb));
if (sk2) {
- inet_twsk_deschedule((struct inet_timewait_sock *)sk,
- &tcp_death_row);
- inet_twsk_put((struct inet_timewait_sock *)sk);
+ inet_twsk_deschedule(inet_twsk(sk), &tcp_death_row);
+ inet_twsk_put(inet_twsk(sk));
sk = sk2;
goto process;
}
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c
index 9a253faefc81..ca406157724c 100644
--- a/net/ipv4/tcp_output.c
+++ b/net/ipv4/tcp_output.c
@@ -273,10 +273,10 @@ static void tcp_build_and_update_options(__be32 *ptr, struct tcp_sock *tp,
__u32 tstamp)
{
if (tp->rx_opt.tstamp_ok) {
- *ptr++ = __constant_htonl((TCPOPT_NOP << 24) |
- (TCPOPT_NOP << 16) |
- (TCPOPT_TIMESTAMP << 8) |
- TCPOLEN_TIMESTAMP);
+ *ptr++ = htonl((TCPOPT_NOP << 24) |
+ (TCPOPT_NOP << 16) |
+ (TCPOPT_TIMESTAMP << 8) |
+ TCPOLEN_TIMESTAMP);
*ptr++ = htonl(tstamp);
*ptr++ = htonl(tp->rx_opt.ts_recent);
}
@@ -325,18 +325,27 @@ static void tcp_syn_build_options(__be32 *ptr, int mss, int ts, int sack,
*ptr++ = htonl((TCPOPT_MSS << 24) | (TCPOLEN_MSS << 16) | mss);
if (ts) {
if(sack)
- *ptr++ = __constant_htonl((TCPOPT_SACK_PERM << 24) | (TCPOLEN_SACK_PERM << 16) |
- (TCPOPT_TIMESTAMP << 8) | TCPOLEN_TIMESTAMP);
+ *ptr++ = htonl((TCPOPT_SACK_PERM << 24) |
+ (TCPOLEN_SACK_PERM << 16) |
+ (TCPOPT_TIMESTAMP << 8) |
+ TCPOLEN_TIMESTAMP);
else
- *ptr++ = __constant_htonl((TCPOPT_NOP << 24) | (TCPOPT_NOP << 16) |
- (TCPOPT_TIMESTAMP << 8) | TCPOLEN_TIMESTAMP);
+ *ptr++ = htonl((TCPOPT_NOP << 24) |
+ (TCPOPT_NOP << 16) |
+ (TCPOPT_TIMESTAMP << 8) |
+ TCPOLEN_TIMESTAMP);
*ptr++ = htonl(tstamp); /* TSVAL */
*ptr++ = htonl(ts_recent); /* TSECR */
} else if(sack)
- *ptr++ = __constant_htonl((TCPOPT_NOP << 24) | (TCPOPT_NOP << 16) |
- (TCPOPT_SACK_PERM << 8) | TCPOLEN_SACK_PERM);
+ *ptr++ = htonl((TCPOPT_NOP << 24) |
+ (TCPOPT_NOP << 16) |
+ (TCPOPT_SACK_PERM << 8) |
+ TCPOLEN_SACK_PERM);
if (offer_wscale)
- *ptr++ = htonl((TCPOPT_NOP << 24) | (TCPOPT_WINDOW << 16) | (TCPOLEN_WINDOW << 8) | (wscale));
+ *ptr++ = htonl((TCPOPT_NOP << 24) |
+ (TCPOPT_WINDOW << 16) |
+ (TCPOLEN_WINDOW << 8) |
+ (wscale));
}
/* This routine actually transmits TCP packets queued in by
@@ -1087,10 +1096,14 @@ static int tcp_tso_should_defer(struct sock *sk, struct tcp_sock *tp, struct sk_
u32 send_win, cong_win, limit, in_flight;
if (TCP_SKB_CB(skb)->flags & TCPCB_FLAG_FIN)
- return 0;
+ goto send_now;
if (icsk->icsk_ca_state != TCP_CA_Open)
- return 0;
+ goto send_now;
+
+ /* Defer for less than two clock ticks. */
+ if (!tp->tso_deferred && ((jiffies<<1)>>1) - (tp->tso_deferred>>1) > 1)
+ goto send_now;
in_flight = tcp_packets_in_flight(tp);
@@ -1106,7 +1119,7 @@ static int tcp_tso_should_defer(struct sock *sk, struct tcp_sock *tp, struct sk_
/* If a full-sized TSO skb can be sent, do it. */
if (limit >= 65536)
- return 0;
+ goto send_now;
if (sysctl_tcp_tso_win_divisor) {
u32 chunk = min(tp->snd_wnd, tp->snd_cwnd * tp->mss_cache);
@@ -1116,7 +1129,7 @@ static int tcp_tso_should_defer(struct sock *sk, struct tcp_sock *tp, struct sk_
*/
chunk /= sysctl_tcp_tso_win_divisor;
if (limit >= chunk)
- return 0;
+ goto send_now;
} else {
/* Different approach, try not to defer past a single
* ACK. Receiver should ACK every other full sized
@@ -1124,11 +1137,17 @@ static int tcp_tso_should_defer(struct sock *sk, struct tcp_sock *tp, struct sk_
* then send now.
*/
if (limit > tcp_max_burst(tp) * tp->mss_cache)
- return 0;
+ goto send_now;
}
/* Ok, it looks like it is advisable to defer. */
+ tp->tso_deferred = 1 | (jiffies<<1);
+
return 1;
+
+send_now:
+ tp->tso_deferred = 0;
+ return 0;
}
/* Create a new MTU probe if we are ready.
diff --git a/net/ipv4/xfrm4_policy.c b/net/ipv4/xfrm4_policy.c
index 7a7a00147e55..1bed0cdf53e3 100644
--- a/net/ipv4/xfrm4_policy.c
+++ b/net/ipv4/xfrm4_policy.c
@@ -52,7 +52,7 @@ __xfrm4_find_bundle(struct flowi *fl, struct xfrm_policy *policy)
xdst->u.rt.fl.fl4_dst == fl->fl4_dst &&
xdst->u.rt.fl.fl4_src == fl->fl4_src &&
xdst->u.rt.fl.fl4_tos == fl->fl4_tos &&
- xfrm_bundle_ok(xdst, fl, AF_INET, 0)) {
+ xfrm_bundle_ok(policy, xdst, fl, AF_INET, 0)) {
dst_clone(dst);
break;
}
diff --git a/net/ipv6/Kconfig b/net/ipv6/Kconfig
index a460e8132b4d..6e48f52e197c 100644
--- a/net/ipv6/Kconfig
+++ b/net/ipv6/Kconfig
@@ -153,6 +153,19 @@ config INET6_XFRM_MODE_ROUTEOPTIMIZATION
---help---
Support for MIPv6 route optimization mode.
+config IPV6_SIT
+ tristate "IPv6: IPv6-in-IPv4 tunnel (SIT driver)"
+ depends on IPV6
+ default y
+ ---help---
+ Tunneling means encapsulating data of one protocol type within
+ another protocol and sending it over a channel that understands the
+ encapsulating protocol. This driver implements encapsulation of IPv6
+ into IPv4 packets. This is useful if you want to connect two IPv6
+ networks over an IPv4-only path.
+
+ Saying M here will produce a module called sit.ko. If unsure, say Y.
+
config IPV6_TUNNEL
tristate "IPv6: IPv6-in-IPv6 tunnel"
select INET6_TUNNEL
@@ -162,9 +175,16 @@ config IPV6_TUNNEL
If unsure, say N.
+config IPV6_MULTIPLE_TABLES
+ bool "IPv6: Multiple Routing Tables"
+ depends on IPV6 && EXPERIMENTAL
+ select FIB_RULES
+ ---help---
+ Support multiple routing tables.
+
config IPV6_SUBTREES
bool "IPv6: source address based routing"
- depends on IPV6 && EXPERIMENTAL
+ depends on IPV6_MULTIPLE_TABLES
---help---
Enable routing by source address or prefix.
@@ -176,13 +196,6 @@ config IPV6_SUBTREES
If unsure, say N.
-config IPV6_MULTIPLE_TABLES
- bool "IPv6: Multiple Routing Tables"
- depends on IPV6 && EXPERIMENTAL
- select FIB_RULES
- ---help---
- Support multiple routing tables.
-
config IPV6_ROUTE_FWMARK
bool "IPv6: use netfilter MARK value as routing key"
depends on IPV6_MULTIPLE_TABLES && NETFILTER
diff --git a/net/ipv6/Makefile b/net/ipv6/Makefile
index 87274e47fe32..addcc011bc01 100644
--- a/net/ipv6/Makefile
+++ b/net/ipv6/Makefile
@@ -4,7 +4,7 @@
obj-$(CONFIG_IPV6) += ipv6.o
-ipv6-objs := af_inet6.o anycast.o ip6_output.o ip6_input.o addrconf.o sit.o \
+ipv6-objs := af_inet6.o anycast.o ip6_output.o ip6_input.o addrconf.o \
route.o ip6_fib.o ipv6_sockglue.o ndisc.o udp.o raw.o \
protocol.o icmp.o mcast.o reassembly.o tcp_ipv6.o \
exthdrs.o sysctl_net_ipv6.o datagram.o proc.o \
@@ -29,6 +29,7 @@ obj-$(CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION) += xfrm6_mode_ro.o
obj-$(CONFIG_INET6_XFRM_MODE_BEET) += xfrm6_mode_beet.o
obj-$(CONFIG_NETFILTER) += netfilter/
+obj-$(CONFIG_IPV6_SIT) += sit.o
obj-$(CONFIG_IPV6_TUNNEL) += ip6_tunnel.o
obj-y += exthdrs_core.o
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index e03c33b2465b..b312a5f7a759 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -396,8 +396,10 @@ static struct inet6_dev * ipv6_add_dev(struct net_device *dev)
ndev->regen_timer.data = (unsigned long) ndev;
if ((dev->flags&IFF_LOOPBACK) ||
dev->type == ARPHRD_TUNNEL ||
- dev->type == ARPHRD_NONE ||
- dev->type == ARPHRD_SIT) {
+#if defined(CONFIG_IPV6_SIT) || defined(CONFIG_IPV6_SIT_MODULE)
+ dev->type == ARPHRD_SIT ||
+#endif
+ dev->type == ARPHRD_NONE) {
printk(KERN_INFO
"%s: Disabled Privacy Extensions\n",
dev->name);
@@ -1546,8 +1548,10 @@ addrconf_prefix_route(struct in6_addr *pfx, int plen, struct net_device *dev,
This thing is done here expecting that the whole
class of non-broadcast devices need not cloning.
*/
+#if defined(CONFIG_IPV6_SIT) || defined(CONFIG_IPV6_SIT_MODULE)
if (dev->type == ARPHRD_SIT && (dev->flags & IFF_POINTOPOINT))
cfg.fc_flags |= RTF_NONEXTHOP;
+#endif
ip6_route_add(&cfg);
}
@@ -1569,6 +1573,7 @@ static void addrconf_add_mroute(struct net_device *dev)
ip6_route_add(&cfg);
}
+#if defined(CONFIG_IPV6_SIT) || defined(CONFIG_IPV6_SIT_MODULE)
static void sit_route_add(struct net_device *dev)
{
struct fib6_config cfg = {
@@ -1582,6 +1587,7 @@ static void sit_route_add(struct net_device *dev)
/* prefix length - 96 bits "::d.d.d.d" */
ip6_route_add(&cfg);
}
+#endif
static void addrconf_add_lroute(struct net_device *dev)
{
@@ -1852,6 +1858,7 @@ int addrconf_set_dstaddr(void __user *arg)
if (dev == NULL)
goto err_exit;
+#if defined(CONFIG_IPV6_SIT) || defined(CONFIG_IPV6_SIT_MODULE)
if (dev->type == ARPHRD_SIT) {
struct ifreq ifr;
mm_segment_t oldfs;
@@ -1881,6 +1888,7 @@ int addrconf_set_dstaddr(void __user *arg)
err = dev_open(dev);
}
}
+#endif
err_exit:
rtnl_unlock();
@@ -2010,6 +2018,7 @@ int addrconf_del_ifaddr(void __user *arg)
return err;
}
+#if defined(CONFIG_IPV6_SIT) || defined(CONFIG_IPV6_SIT_MODULE)
static void sit_add_v4_addrs(struct inet6_dev *idev)
{
struct inet6_ifaddr * ifp;
@@ -2078,6 +2087,7 @@ static void sit_add_v4_addrs(struct inet6_dev *idev)
}
}
}
+#endif
static void init_loopback(struct net_device *dev)
{
@@ -2141,6 +2151,7 @@ static void addrconf_dev_config(struct net_device *dev)
addrconf_add_linklocal(idev, &addr);
}
+#if defined(CONFIG_IPV6_SIT) || defined(CONFIG_IPV6_SIT_MODULE)
static void addrconf_sit_config(struct net_device *dev)
{
struct inet6_dev *idev;
@@ -2166,6 +2177,7 @@ static void addrconf_sit_config(struct net_device *dev)
} else
sit_route_add(dev);
}
+#endif
static inline int
ipv6_inherit_linklocal(struct inet6_dev *idev, struct net_device *link_dev)
@@ -2260,9 +2272,11 @@ static int addrconf_notify(struct notifier_block *this, unsigned long event,
}
switch(dev->type) {
+#if defined(CONFIG_IPV6_SIT) || defined(CONFIG_IPV6_SIT_MODULE)
case ARPHRD_SIT:
addrconf_sit_config(dev);
break;
+#endif
case ARPHRD_TUNNEL6:
addrconf_ip6_tnl_config(dev);
break;
diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c
index e94eccb99707..858cae29581c 100644
--- a/net/ipv6/af_inet6.c
+++ b/net/ipv6/af_inet6.c
@@ -850,7 +850,6 @@ static int __init inet6_init(void)
err = addrconf_init();
if (err)
goto addrconf_fail;
- sit_init();
/* Init v6 extension headers. */
ipv6_rthdr_init();
@@ -927,7 +926,6 @@ static void __exit inet6_exit(void)
mip6_fini();
#endif
/* Cleanup code parts. */
- sit_cleanup();
ip6_flowlabel_cleanup();
addrconf_cleanup();
ip6_route_cleanup();
diff --git a/net/ipv6/fib6_rules.c b/net/ipv6/fib6_rules.c
index d8c1057e8b00..1896ecb52899 100644
--- a/net/ipv6/fib6_rules.c
+++ b/net/ipv6/fib6_rules.c
@@ -117,12 +117,15 @@ static int fib6_rule_match(struct fib_rule *rule, struct flowi *fl, int flags)
{
struct fib6_rule *r = (struct fib6_rule *) rule;
- if (!ipv6_prefix_equal(&fl->fl6_dst, &r->dst.addr, r->dst.plen))
+ if (r->dst.plen &&
+ !ipv6_prefix_equal(&fl->fl6_dst, &r->dst.addr, r->dst.plen))
return 0;
- if ((flags & RT6_LOOKUP_F_HAS_SADDR) &&
- !ipv6_prefix_equal(&fl->fl6_src, &r->src.addr, r->src.plen))
- return 0;
+ if (r->src.plen) {
+ if (!(flags & RT6_LOOKUP_F_HAS_SADDR) ||
+ !ipv6_prefix_equal(&fl->fl6_src, &r->src.addr, r->src.plen))
+ return 0;
+ }
if (r->tclass && r->tclass != ((ntohl(fl->fl6_flowlabel) >> 20) & 0xff))
return 0;
diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c
index 8fcae7a6510b..f98ca30d7c1f 100644
--- a/net/ipv6/ip6_fib.c
+++ b/net/ipv6/ip6_fib.c
@@ -169,7 +169,6 @@ static __inline__ void rt6_release(struct rt6_info *rt)
static struct fib6_table fib6_main_tbl = {
.tb6_id = RT6_TABLE_MAIN,
- .tb6_lock = RW_LOCK_UNLOCKED,
.tb6_root = {
.leaf = &ip6_null_entry,
.fn_flags = RTN_ROOT | RTN_TL_ROOT | RTN_RTINFO,
@@ -187,6 +186,12 @@ static void fib6_link_table(struct fib6_table *tb)
{
unsigned int h;
+ /*
+ * Initialize table lock at a single place to give lockdep a key,
+ * tables aren't visible prior to being linked to the list.
+ */
+ rwlock_init(&tb->tb6_lock);
+
h = tb->tb6_id & (FIB_TABLE_HASHSZ - 1);
/*
@@ -199,7 +204,6 @@ static void fib6_link_table(struct fib6_table *tb)
#ifdef CONFIG_IPV6_MULTIPLE_TABLES
static struct fib6_table fib6_local_tbl = {
.tb6_id = RT6_TABLE_LOCAL,
- .tb6_lock = RW_LOCK_UNLOCKED,
.tb6_root = {
.leaf = &ip6_null_entry,
.fn_flags = RTN_ROOT | RTN_TL_ROOT | RTN_RTINFO,
@@ -213,7 +217,6 @@ static struct fib6_table *fib6_alloc_table(u32 id)
table = kzalloc(sizeof(*table), GFP_ATOMIC);
if (table != NULL) {
table->tb6_id = id;
- table->tb6_lock = RW_LOCK_UNLOCKED;
table->tb6_root.leaf = &ip6_null_entry;
table->tb6_root.fn_flags = RTN_ROOT | RTN_TL_ROOT | RTN_RTINFO;
}
diff --git a/net/ipv6/ip6_flowlabel.c b/net/ipv6/ip6_flowlabel.c
index 1d672b0547f2..6d4533b58dca 100644
--- a/net/ipv6/ip6_flowlabel.c
+++ b/net/ipv6/ip6_flowlabel.c
@@ -330,8 +330,10 @@ fl_create(struct in6_flowlabel_req *freq, char __user *optval, int optlen, int *
fl->share = freq->flr_share;
addr_type = ipv6_addr_type(&freq->flr_dst);
if ((addr_type&IPV6_ADDR_MAPPED)
- || addr_type == IPV6_ADDR_ANY)
+ || addr_type == IPV6_ADDR_ANY) {
+ err = -EINVAL;
goto done;
+ }
ipv6_addr_copy(&fl->dst, &freq->flr_dst);
atomic_set(&fl->users, 1);
switch (fl->share) {
@@ -587,6 +589,8 @@ static struct ip6_flowlabel *ip6fl_get_next(struct seq_file *seq, struct ip6_flo
while (!fl) {
if (++state->bucket <= FL_HASH_MASK)
fl = fl_ht[state->bucket];
+ else
+ break;
}
return fl;
}
@@ -623,9 +627,13 @@ static void ip6fl_seq_stop(struct seq_file *seq, void *v)
read_unlock_bh(&ip6_fl_lock);
}
-static void ip6fl_fl_seq_show(struct seq_file *seq, struct ip6_flowlabel *fl)
+static int ip6fl_seq_show(struct seq_file *seq, void *v)
{
- while(fl) {
+ if (v == SEQ_START_TOKEN)
+ seq_printf(seq, "%-5s %-1s %-6s %-6s %-6s %-8s %-32s %s\n",
+ "Label", "S", "Owner", "Users", "Linger", "Expires", "Dst", "Opt");
+ else {
+ struct ip6_flowlabel *fl = v;
seq_printf(seq,
"%05X %-1d %-6d %-6d %-6ld %-8ld " NIP6_SEQFMT " %-4d\n",
(unsigned)ntohl(fl->label),
@@ -636,17 +644,7 @@ static void ip6fl_fl_seq_show(struct seq_file *seq, struct ip6_flowlabel *fl)
(long)(fl->expires - jiffies)/HZ,
NIP6(fl->dst),
fl->opt ? fl->opt->opt_nflen : 0);
- fl = fl->next;
}
-}
-
-static int ip6fl_seq_show(struct seq_file *seq, void *v)
-{
- if (v == SEQ_START_TOKEN)
- seq_printf(seq, "%-5s %-1s %-6s %-6s %-6s %-8s %-32s %s\n",
- "Label", "S", "Owner", "Users", "Linger", "Expires", "Dst", "Opt");
- else
- ip6fl_fl_seq_show(seq, v);
return 0;
}
diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c
index 84d7ebdb9d21..b9f40290d12a 100644
--- a/net/ipv6/ip6_tunnel.c
+++ b/net/ipv6/ip6_tunnel.c
@@ -542,6 +542,7 @@ ip6ip6_rcv(struct sk_buff *skb)
skb->dev = t->dev;
dst_release(skb->dst);
skb->dst = NULL;
+ nf_reset(skb);
if (t->parms.flags & IP6_TNL_F_RCV_DSCP_COPY)
ipv6_copy_dscp(ipv6h, skb->nh.ipv6h);
ip6ip6_ecn_decapsulate(ipv6h, skb);
@@ -1149,6 +1150,20 @@ fail:
return err;
}
+static void __exit ip6ip6_destroy_tunnels(void)
+{
+ int h;
+ struct ip6_tnl *t;
+
+ for (h = 0; h < HASH_SIZE; h++) {
+ while ((t = tnls_r_l[h]) != NULL)
+ unregister_netdevice(t->dev);
+ }
+
+ t = tnls_wc[0];
+ unregister_netdevice(t->dev);
+}
+
/**
* ip6_tunnel_cleanup - free resources and unregister protocol
**/
@@ -1158,7 +1173,9 @@ static void __exit ip6_tunnel_cleanup(void)
if (xfrm6_tunnel_deregister(&ip6ip6_handler))
printk(KERN_INFO "ip6ip6 close: can't deregister tunnel\n");
- unregister_netdev(ip6ip6_fb_tnl_dev);
+ rtnl_lock();
+ ip6ip6_destroy_tunnels();
+ rtnl_unlock();
}
module_init(ip6_tunnel_init);
diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c
index 0304b5fe8d6a..73eb8c33e9f0 100644
--- a/net/ipv6/ndisc.c
+++ b/net/ipv6/ndisc.c
@@ -967,8 +967,6 @@ static void ndisc_recv_na(struct sk_buff *skb)
ipv6_devconf.forwarding && ipv6_devconf.proxy_ndp &&
pneigh_lookup(&nd_tbl, &msg->target, dev, 0)) {
/* XXX: idev->cnf.prixy_ndp */
- WARN_ON(skb->dst != NULL &&
- ((struct rt6_info *)skb->dst)->rt6i_idev);
goto out;
}
@@ -1744,6 +1742,7 @@ int __init ndisc_init(struct net_proto_family *ops)
void ndisc_cleanup(void)
{
+ unregister_netdevice_notifier(&ndisc_netdev_notifier);
#ifdef CONFIG_SYSCTL
neigh_sysctl_unregister(&nd_tbl.parms);
#endif
diff --git a/net/ipv6/netfilter/Kconfig b/net/ipv6/netfilter/Kconfig
index 4bc4e5b33794..d7c45a9c15fe 100644
--- a/net/ipv6/netfilter/Kconfig
+++ b/net/ipv6/netfilter/Kconfig
@@ -40,7 +40,7 @@ config IP6_NF_QUEUE
To compile it as a module, choose M here. If unsure, say N.
config IP6_NF_IPTABLES
- tristate "IP6 tables support (required for filtering/masq/NAT)"
+ tristate "IP6 tables support (required for filtering)"
depends on NETFILTER_XTABLES
help
ip6tables is a general, extensible packet identification framework.
diff --git a/net/ipv6/netfilter/ip6_queue.c b/net/ipv6/netfilter/ip6_queue.c
index 9510c24ca8d2..9fec832ee08b 100644
--- a/net/ipv6/netfilter/ip6_queue.c
+++ b/net/ipv6/netfilter/ip6_queue.c
@@ -349,9 +349,10 @@ ipq_mangle_ipv6(ipq_verdict_msg_t *v, struct ipq_queue_entry *e)
if (v->data_len < sizeof(*user_iph))
return 0;
diff = v->data_len - e->skb->len;
- if (diff < 0)
- skb_trim(e->skb, v->data_len);
- else if (diff > 0) {
+ if (diff < 0) {
+ if (pskb_trim(e->skb, v->data_len))
+ return -ENOMEM;
+ } else if (diff > 0) {
if (v->data_len > 0xFFFF)
return -EINVAL;
if (diff > skb_tailroom(e->skb)) {
diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c
index 4ab368fa0b8f..204e02162d49 100644
--- a/net/ipv6/netfilter/ip6_tables.c
+++ b/net/ipv6/netfilter/ip6_tables.c
@@ -111,7 +111,7 @@ ip6_packet_match(const struct sk_buff *skb,
const char *outdev,
const struct ip6t_ip6 *ip6info,
unsigned int *protoff,
- int *fragoff)
+ int *fragoff, int *hotdrop)
{
size_t i;
unsigned long ret;
@@ -169,9 +169,11 @@ ip6_packet_match(const struct sk_buff *skb,
unsigned short _frag_off;
protohdr = ipv6_find_hdr(skb, protoff, -1, &_frag_off);
- if (protohdr < 0)
+ if (protohdr < 0) {
+ if (_frag_off == 0)
+ *hotdrop = 1;
return 0;
-
+ }
*fragoff = _frag_off;
dprintf("Packet protocol %hi ?= %s%hi.\n",
@@ -290,7 +292,7 @@ ip6t_do_table(struct sk_buff **pskb,
IP_NF_ASSERT(e);
IP_NF_ASSERT(back);
if (ip6_packet_match(*pskb, indev, outdev, &e->ipv6,
- &protoff, &offset)) {
+ &protoff, &offset, &hotdrop)) {
struct ip6t_entry_target *t;
if (IP6T_MATCH_ITERATE(e, do_match,
@@ -584,12 +586,19 @@ check_entry(struct ip6t_entry *e, const char *name, unsigned int size,
return -EINVAL;
}
+ if (e->target_offset + sizeof(struct ip6t_entry_target) >
+ e->next_offset)
+ return -EINVAL;
+
j = 0;
ret = IP6T_MATCH_ITERATE(e, check_match, name, &e->ipv6, e->comefrom, &j);
if (ret != 0)
goto cleanup_matches;
t = ip6t_get_target(e);
+ ret = -EINVAL;
+ if (e->target_offset + t->u.target_size > e->next_offset)
+ goto cleanup_matches;
target = try_then_request_module(xt_find_target(AF_INET6,
t->u.user.name,
t->u.user.revision),
@@ -749,19 +758,17 @@ translate_table(const char *name,
}
}
- if (!mark_source_chains(newinfo, valid_hooks, entry0))
- return -ELOOP;
-
/* Finally, each sanity check must pass */
i = 0;
ret = IP6T_ENTRY_ITERATE(entry0, newinfo->size,
check_entry, name, size, &i);
- if (ret != 0) {
- IP6T_ENTRY_ITERATE(entry0, newinfo->size,
- cleanup_entry, &i);
- return ret;
- }
+ if (ret != 0)
+ goto cleanup;
+
+ ret = -ELOOP;
+ if (!mark_source_chains(newinfo, valid_hooks, entry0))
+ goto cleanup;
/* And one copy for every other CPU */
for_each_possible_cpu(i) {
@@ -769,6 +776,9 @@ translate_table(const char *name,
memcpy(newinfo->entries[i], entry0, newinfo->size);
}
+ return 0;
+cleanup:
+ IP6T_ENTRY_ITERATE(entry0, newinfo->size, cleanup_entry, &i);
return ret;
}
@@ -1438,6 +1448,9 @@ static void __exit ip6_tables_fini(void)
* If target header is found, its offset is set in *offset and return protocol
* number. Otherwise, return -1.
*
+ * If the first fragment doesn't contain the final protocol header or
+ * NEXTHDR_NONE it is considered invalid.
+ *
* Note that non-1st fragment is special case that "the protocol number
* of last header" is "next header" field in Fragment header. In this case,
* *offset is meaningless and fragment offset is stored in *fragoff if fragoff
@@ -1461,12 +1474,12 @@ int ipv6_find_hdr(const struct sk_buff *skb, unsigned int *offset,
if ((!ipv6_ext_hdr(nexthdr)) || nexthdr == NEXTHDR_NONE) {
if (target < 0)
break;
- return -1;
+ return -ENOENT;
}
hp = skb_header_pointer(skb, start, sizeof(_hdr), &_hdr);
if (hp == NULL)
- return -1;
+ return -EBADMSG;
if (nexthdr == NEXTHDR_FRAGMENT) {
unsigned short _frag_off, *fp;
fp = skb_header_pointer(skb,
@@ -1475,18 +1488,18 @@ int ipv6_find_hdr(const struct sk_buff *skb, unsigned int *offset,
sizeof(_frag_off),
&_frag_off);
if (fp == NULL)
- return -1;
+ return -EBADMSG;
_frag_off = ntohs(*fp) & ~0x7;
if (_frag_off) {
if (target < 0 &&
((!ipv6_ext_hdr(hp->nexthdr)) ||
- nexthdr == NEXTHDR_NONE)) {
+ hp->nexthdr == NEXTHDR_NONE)) {
if (fragoff)
*fragoff = _frag_off;
return hp->nexthdr;
}
- return -1;
+ return -ENOENT;
}
hdrlen = 8;
} else if (nexthdr == NEXTHDR_AUTH)
diff --git a/net/ipv6/netfilter/ip6t_ah.c b/net/ipv6/netfilter/ip6t_ah.c
index ec1b1608156c..46486645eb75 100644
--- a/net/ipv6/netfilter/ip6t_ah.c
+++ b/net/ipv6/netfilter/ip6t_ah.c
@@ -54,9 +54,14 @@ match(const struct sk_buff *skb,
const struct ip6t_ah *ahinfo = matchinfo;
unsigned int ptr;
unsigned int hdrlen = 0;
+ int err;
- if (ipv6_find_hdr(skb, &ptr, NEXTHDR_AUTH, NULL) < 0)
+ err = ipv6_find_hdr(skb, &ptr, NEXTHDR_AUTH, NULL);
+ if (err < 0) {
+ if (err != -ENOENT)
+ *hotdrop = 1;
return 0;
+ }
ah = skb_header_pointer(skb, ptr, sizeof(_ah), &_ah);
if (ah == NULL) {
diff --git a/net/ipv6/netfilter/ip6t_frag.c b/net/ipv6/netfilter/ip6t_frag.c
index 78d9c8b9e28a..cd22eaaccdca 100644
--- a/net/ipv6/netfilter/ip6t_frag.c
+++ b/net/ipv6/netfilter/ip6t_frag.c
@@ -52,9 +52,14 @@ match(const struct sk_buff *skb,
struct frag_hdr _frag, *fh;
const struct ip6t_frag *fraginfo = matchinfo;
unsigned int ptr;
+ int err;
- if (ipv6_find_hdr(skb, &ptr, NEXTHDR_FRAGMENT, NULL) < 0)
+ err = ipv6_find_hdr(skb, &ptr, NEXTHDR_FRAGMENT, NULL);
+ if (err < 0) {
+ if (err != -ENOENT)
+ *hotdrop = 1;
return 0;
+ }
fh = skb_header_pointer(skb, ptr, sizeof(_frag), &_frag);
if (fh == NULL) {
diff --git a/net/ipv6/netfilter/ip6t_hbh.c b/net/ipv6/netfilter/ip6t_hbh.c
index d32a205e3af2..3f25babe0440 100644
--- a/net/ipv6/netfilter/ip6t_hbh.c
+++ b/net/ipv6/netfilter/ip6t_hbh.c
@@ -65,9 +65,14 @@ match(const struct sk_buff *skb,
u8 _opttype, *tp = NULL;
u8 _optlen, *lp = NULL;
unsigned int optlen;
+ int err;
- if (ipv6_find_hdr(skb, &ptr, match->data, NULL) < 0)
+ err = ipv6_find_hdr(skb, &ptr, match->data, NULL);
+ if (err < 0) {
+ if (err != -ENOENT)
+ *hotdrop = 1;
return 0;
+ }
oh = skb_header_pointer(skb, ptr, sizeof(_optsh), &_optsh);
if (oh == NULL) {
diff --git a/net/ipv6/netfilter/ip6t_rt.c b/net/ipv6/netfilter/ip6t_rt.c
index bcb2e168a5bc..54d7d14134fd 100644
--- a/net/ipv6/netfilter/ip6t_rt.c
+++ b/net/ipv6/netfilter/ip6t_rt.c
@@ -58,9 +58,14 @@ match(const struct sk_buff *skb,
unsigned int hdrlen = 0;
unsigned int ret = 0;
struct in6_addr *ap, _addr;
+ int err;
- if (ipv6_find_hdr(skb, &ptr, NEXTHDR_ROUTING, NULL) < 0)
+ err = ipv6_find_hdr(skb, &ptr, NEXTHDR_ROUTING, NULL);
+ if (err < 0) {
+ if (err != -ENOENT)
+ *hotdrop = 1;
return 0;
+ }
rh = skb_header_pointer(skb, ptr, sizeof(_route), &_route);
if (rh == NULL) {
diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c
index d09329ca3267..d6dedc4aec77 100644
--- a/net/ipv6/raw.c
+++ b/net/ipv6/raw.c
@@ -604,7 +604,7 @@ error:
return err;
}
-static void rawv6_probe_proto_opt(struct flowi *fl, struct msghdr *msg)
+static int rawv6_probe_proto_opt(struct flowi *fl, struct msghdr *msg)
{
struct iovec *iov;
u8 __user *type = NULL;
@@ -616,7 +616,7 @@ static void rawv6_probe_proto_opt(struct flowi *fl, struct msghdr *msg)
int i;
if (!msg->msg_iov)
- return;
+ return 0;
for (i = 0; i < msg->msg_iovlen; i++) {
iov = &msg->msg_iov[i];
@@ -638,8 +638,9 @@ static void rawv6_probe_proto_opt(struct flowi *fl, struct msghdr *msg)
code = iov->iov_base;
if (type && code) {
- get_user(fl->fl_icmp_type, type);
- get_user(fl->fl_icmp_code, code);
+ if (get_user(fl->fl_icmp_type, type) ||
+ get_user(fl->fl_icmp_code, code))
+ return -EFAULT;
probed = 1;
}
break;
@@ -650,7 +651,8 @@ static void rawv6_probe_proto_opt(struct flowi *fl, struct msghdr *msg)
/* check if type field is readable or not. */
if (iov->iov_len > 2 - len) {
u8 __user *p = iov->iov_base;
- get_user(fl->fl_mh_type, &p[2 - len]);
+ if (get_user(fl->fl_mh_type, &p[2 - len]))
+ return -EFAULT;
probed = 1;
} else
len += iov->iov_len;
@@ -664,6 +666,7 @@ static void rawv6_probe_proto_opt(struct flowi *fl, struct msghdr *msg)
if (probed)
break;
}
+ return 0;
}
static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk,
@@ -787,7 +790,9 @@ static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk,
opt = ipv6_fixup_options(&opt_space, opt);
fl.proto = proto;
- rawv6_probe_proto_opt(&fl, msg);
+ err = rawv6_probe_proto_opt(&fl, msg);
+ if (err)
+ goto out;
ipv6_addr_copy(&fl.fl6_dst, daddr);
if (ipv6_addr_any(&fl.fl6_src) && !ipv6_addr_any(&np->saddr))
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index d6b4b4f48d18..b39ae99122d5 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -141,6 +141,10 @@ struct rt6_info ip6_null_entry = {
#ifdef CONFIG_IPV6_MULTIPLE_TABLES
+static int ip6_pkt_prohibit(struct sk_buff *skb);
+static int ip6_pkt_prohibit_out(struct sk_buff *skb);
+static int ip6_pkt_blk_hole(struct sk_buff *skb);
+
struct rt6_info ip6_prohibit_entry = {
.u = {
.dst = {
@@ -150,8 +154,8 @@ struct rt6_info ip6_prohibit_entry = {
.obsolete = -1,
.error = -EACCES,
.metrics = { [RTAX_HOPLIMIT - 1] = 255, },
- .input = ip6_pkt_discard,
- .output = ip6_pkt_discard_out,
+ .input = ip6_pkt_prohibit,
+ .output = ip6_pkt_prohibit_out,
.ops = &ip6_dst_ops,
.path = (struct dst_entry*)&ip6_prohibit_entry,
}
@@ -170,8 +174,8 @@ struct rt6_info ip6_blk_hole_entry = {
.obsolete = -1,
.error = -EINVAL,
.metrics = { [RTAX_HOPLIMIT - 1] = 255, },
- .input = ip6_pkt_discard,
- .output = ip6_pkt_discard_out,
+ .input = ip6_pkt_blk_hole,
+ .output = ip6_pkt_blk_hole,
.ops = &ip6_dst_ops,
.path = (struct dst_entry*)&ip6_blk_hole_entry,
}
@@ -326,6 +330,8 @@ static int inline rt6_check_neigh(struct rt6_info *rt)
read_lock_bh(&neigh->lock);
if (neigh->nud_state & NUD_VALID)
m = 2;
+ else if (!(neigh->nud_state & NUD_FAILED))
+ m = 1;
read_unlock_bh(&neigh->lock);
}
return m;
@@ -343,9 +349,7 @@ static int rt6_score_route(struct rt6_info *rt, int oif,
m |= IPV6_DECODE_PREF(IPV6_EXTRACT_PREF(rt->rt6i_flags)) << 2;
#endif
n = rt6_check_neigh(rt);
- if (n > 1)
- m |= 16;
- else if (!n && strict & RT6_LOOKUP_F_REACHABLE)
+ if (!n && (strict & RT6_LOOKUP_F_REACHABLE))
return -1;
return m;
}
@@ -376,10 +380,11 @@ static struct rt6_info *rt6_select(struct rt6_info **head, int oif,
continue;
if (m > mpri) {
- rt6_probe(match);
+ if (strict & RT6_LOOKUP_F_REACHABLE)
+ rt6_probe(match);
match = rt;
mpri = m;
- } else {
+ } else if (strict & RT6_LOOKUP_F_REACHABLE) {
rt6_probe(rt);
}
}
@@ -484,7 +489,7 @@ int rt6_route_rcv(struct net_device *dev, u8 *opt, int len,
do { \
if (rt == &ip6_null_entry) { \
struct fib6_node *pn; \
- while (fn) { \
+ while (1) { \
if (fn->fn_flags & RTN_TL_ROOT) \
goto out; \
pn = fn->parent; \
@@ -529,13 +534,17 @@ struct rt6_info *rt6_lookup(struct in6_addr *daddr, struct in6_addr *saddr,
.nl_u = {
.ip6_u = {
.daddr = *daddr,
- /* TODO: saddr */
},
},
};
struct dst_entry *dst;
int flags = strict ? RT6_LOOKUP_F_IFACE : 0;
+ if (saddr) {
+ memcpy(&fl.fl6_src, saddr, sizeof(*saddr));
+ flags |= RT6_LOOKUP_F_HAS_SADDR;
+ }
+
dst = fib6_rule_lookup(&fl, flags, ip6_pol_route_lookup);
if (dst->error == 0)
return (struct rt6_info *) dst;
@@ -614,8 +623,6 @@ static struct rt6_info *rt6_alloc_clone(struct rt6_info *ort, struct in6_addr *d
ipv6_addr_copy(&rt->rt6i_dst.addr, daddr);
rt->rt6i_dst.plen = 128;
rt->rt6i_flags |= RTF_CACHE;
- if (rt->rt6i_flags & RTF_REJECT)
- rt->u.dst.error = ort->u.dst.error;
rt->u.dst.flags |= DST_HOST;
rt->rt6i_nexthop = neigh_clone(ort->rt6i_nexthop);
}
@@ -630,7 +637,7 @@ static struct rt6_info *ip6_pol_route_input(struct fib6_table *table,
int strict = 0;
int attempts = 3;
int err;
- int reachable = RT6_LOOKUP_F_REACHABLE;
+ int reachable = ipv6_devconf.forwarding ? 0 : RT6_LOOKUP_F_REACHABLE;
strict |= flags & RT6_LOOKUP_F_IFACE;
@@ -697,6 +704,7 @@ out2:
void ip6_route_input(struct sk_buff *skb)
{
struct ipv6hdr *iph = skb->nh.ipv6h;
+ int flags = RT6_LOOKUP_F_HAS_SADDR;
struct flowi fl = {
.iif = skb->dev->ifindex,
.nl_u = {
@@ -711,7 +719,9 @@ void ip6_route_input(struct sk_buff *skb)
},
.proto = iph->nexthdr,
};
- int flags = rt6_need_strict(&iph->daddr) ? RT6_LOOKUP_F_IFACE : 0;
+
+ if (rt6_need_strict(&iph->daddr))
+ flags |= RT6_LOOKUP_F_IFACE;
skb->dst = fib6_rule_lookup(&fl, flags, ip6_pol_route_input);
}
@@ -724,7 +734,7 @@ static struct rt6_info *ip6_pol_route_output(struct fib6_table *table,
int strict = 0;
int attempts = 3;
int err;
- int reachable = RT6_LOOKUP_F_REACHABLE;
+ int reachable = ipv6_devconf.forwarding ? 0 : RT6_LOOKUP_F_REACHABLE;
strict |= flags & RT6_LOOKUP_F_IFACE;
@@ -794,6 +804,9 @@ struct dst_entry * ip6_route_output(struct sock *sk, struct flowi *fl)
if (rt6_need_strict(&fl->fl6_dst))
flags |= RT6_LOOKUP_F_IFACE;
+ if (!ipv6_addr_any(&fl->fl6_src))
+ flags |= RT6_LOOKUP_F_HAS_SADDR;
+
return fib6_rule_lookup(fl, flags, ip6_pol_route_output);
}
@@ -1345,6 +1358,7 @@ static struct rt6_info *ip6_route_redirect(struct in6_addr *dest,
struct in6_addr *gateway,
struct net_device *dev)
{
+ int flags = RT6_LOOKUP_F_HAS_SADDR;
struct ip6rd_flowi rdfl = {
.fl = {
.oif = dev->ifindex,
@@ -1357,7 +1371,9 @@ static struct rt6_info *ip6_route_redirect(struct in6_addr *dest,
},
.gateway = *gateway,
};
- int flags = rt6_need_strict(dest) ? RT6_LOOKUP_F_IFACE : 0;
+
+ if (rt6_need_strict(dest))
+ flags |= RT6_LOOKUP_F_IFACE;
return (struct rt6_info *)fib6_rule_lookup((struct flowi *)&rdfl, flags, __ip6_route_redirect);
}
@@ -1527,6 +1543,7 @@ static struct rt6_info * ip6_rt_copy(struct rt6_info *ort)
rt->u.dst.output = ort->u.dst.output;
memcpy(rt->u.dst.metrics, ort->u.dst.metrics, RTAX_MAX*sizeof(u32));
+ rt->u.dst.error = ort->u.dst.error;
rt->u.dst.dev = ort->u.dst.dev;
if (rt->u.dst.dev)
dev_hold(rt->u.dst.dev);
@@ -1730,24 +1747,50 @@ int ipv6_route_ioctl(unsigned int cmd, void __user *arg)
* Drop the packet on the floor
*/
-static int ip6_pkt_discard(struct sk_buff *skb)
+static inline int ip6_pkt_drop(struct sk_buff *skb, int code)
{
int type = ipv6_addr_type(&skb->nh.ipv6h->daddr);
if (type == IPV6_ADDR_ANY || type == IPV6_ADDR_RESERVED)
IP6_INC_STATS(IPSTATS_MIB_INADDRERRORS);
IP6_INC_STATS(IPSTATS_MIB_OUTNOROUTES);
- icmpv6_send(skb, ICMPV6_DEST_UNREACH, ICMPV6_NOROUTE, 0, skb->dev);
+ icmpv6_send(skb, ICMPV6_DEST_UNREACH, code, 0, skb->dev);
kfree_skb(skb);
return 0;
}
+static int ip6_pkt_discard(struct sk_buff *skb)
+{
+ return ip6_pkt_drop(skb, ICMPV6_NOROUTE);
+}
+
static int ip6_pkt_discard_out(struct sk_buff *skb)
{
skb->dev = skb->dst->dev;
return ip6_pkt_discard(skb);
}
+#ifdef CONFIG_IPV6_MULTIPLE_TABLES
+
+static int ip6_pkt_prohibit(struct sk_buff *skb)
+{
+ return ip6_pkt_drop(skb, ICMPV6_ADM_PROHIBITED);
+}
+
+static int ip6_pkt_prohibit_out(struct sk_buff *skb)
+{
+ skb->dev = skb->dst->dev;
+ return ip6_pkt_prohibit(skb);
+}
+
+static int ip6_pkt_blk_hole(struct sk_buff *skb)
+{
+ kfree_skb(skb);
+ return 0;
+}
+
+#endif
+
/*
* Allocate a dst for local (unicast / anycast) address.
*/
diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c
index 836eecd7e62b..be699f85b2c7 100644
--- a/net/ipv6/sit.c
+++ b/net/ipv6/sit.c
@@ -850,3 +850,8 @@ int __init sit_init(void)
inet_del_protocol(&sit_protocol, IPPROTO_IPV6);
goto out;
}
+
+module_init(sit_init);
+module_exit(sit_cleanup);
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("sit0");
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
index 3b6575478fcc..4c2a7c0cafef 100644
--- a/net/ipv6/tcp_ipv6.c
+++ b/net/ipv6/tcp_ipv6.c
@@ -329,7 +329,7 @@ static void tcp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
}
if (sk->sk_state == TCP_TIME_WAIT) {
- inet_twsk_put((struct inet_timewait_sock *)sk);
+ inet_twsk_put(inet_twsk(sk));
return;
}
@@ -653,7 +653,7 @@ static void tcp_v6_send_ack(struct sk_buff *skb, u32 seq, u32 ack, u32 win, u32
int tot_len = sizeof(struct tcphdr);
if (ts)
- tot_len += 3*4;
+ tot_len += TCPOLEN_TSTAMP_ALIGNED;
buff = alloc_skb(MAX_HEADER + sizeof(struct ipv6hdr) + tot_len,
GFP_ATOMIC);
@@ -749,7 +749,7 @@ static struct sock *tcp_v6_hnd_req(struct sock *sk,struct sk_buff *skb)
bh_lock_sock(nsk);
return nsk;
}
- inet_twsk_put((struct inet_timewait_sock *)nsk);
+ inet_twsk_put(inet_twsk(nsk));
return NULL;
}
@@ -1283,18 +1283,17 @@ discard_and_relse:
do_time_wait:
if (!xfrm6_policy_check(NULL, XFRM_POLICY_IN, skb)) {
- inet_twsk_put((struct inet_timewait_sock *)sk);
+ inet_twsk_put(inet_twsk(sk));
goto discard_it;
}
if (skb->len < (th->doff<<2) || tcp_checksum_complete(skb)) {
TCP_INC_STATS_BH(TCP_MIB_INERRS);
- inet_twsk_put((struct inet_timewait_sock *)sk);
+ inet_twsk_put(inet_twsk(sk));
goto discard_it;
}
- switch (tcp_timewait_state_process((struct inet_timewait_sock *)sk,
- skb, th)) {
+ switch (tcp_timewait_state_process(inet_twsk(sk), skb, th)) {
case TCP_TW_SYN:
{
struct sock *sk2;
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c
index e0c3934a7e4b..c83f23e51c46 100644
--- a/net/ipv6/udp.c
+++ b/net/ipv6/udp.c
@@ -242,14 +242,13 @@ static void udpv6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
{
struct ipv6_pinfo *np;
struct ipv6hdr *hdr = (struct ipv6hdr*)skb->data;
- struct net_device *dev = skb->dev;
struct in6_addr *saddr = &hdr->saddr;
struct in6_addr *daddr = &hdr->daddr;
struct udphdr *uh = (struct udphdr*)(skb->data+offset);
struct sock *sk;
int err;
- sk = udp_v6_lookup(daddr, uh->dest, saddr, uh->source, dev->ifindex);
+ sk = udp_v6_lookup(daddr, uh->dest, saddr, uh->source, inet6_iif(skb));
if (sk == NULL)
return;
@@ -348,7 +347,7 @@ static void udpv6_mcast_deliver(struct udphdr *uh,
read_lock(&udp_hash_lock);
sk = sk_head(&udp_hash[ntohs(uh->dest) & (UDP_HTABLE_SIZE - 1)]);
- dif = skb->dev->ifindex;
+ dif = inet6_iif(skb);
sk = udp_v6_mcast_next(sk, uh->dest, daddr, uh->source, saddr, dif);
if (!sk) {
kfree_skb(skb);
@@ -429,7 +428,7 @@ static int udpv6_rcv(struct sk_buff **pskb)
* check socket cache ... must talk to Alan about his plans
* for sock caches... i'll skip this for now.
*/
- sk = udp_v6_lookup(saddr, uh->source, daddr, uh->dest, dev->ifindex);
+ sk = udp_v6_lookup(saddr, uh->source, daddr, uh->dest, inet6_iif(skb));
if (sk == NULL) {
if (!xfrm6_policy_check(NULL, XFRM_POLICY_IN, skb))
diff --git a/net/ipv6/xfrm6_policy.c b/net/ipv6/xfrm6_policy.c
index 6a252e2134d1..d400f8fae129 100644
--- a/net/ipv6/xfrm6_policy.c
+++ b/net/ipv6/xfrm6_policy.c
@@ -25,12 +25,14 @@
static struct dst_ops xfrm6_dst_ops;
static struct xfrm_policy_afinfo xfrm6_policy_afinfo;
-static int xfrm6_dst_lookup(struct xfrm_dst **dst, struct flowi *fl)
+static int xfrm6_dst_lookup(struct xfrm_dst **xdst, struct flowi *fl)
{
- int err = 0;
- *dst = (struct xfrm_dst*)ip6_route_output(NULL, fl);
- if (!*dst)
- err = -ENETUNREACH;
+ struct dst_entry *dst = ip6_route_output(NULL, fl);
+ int err = dst->error;
+ if (!err)
+ *xdst = (struct xfrm_dst *) dst;
+ else
+ dst_release(dst);
return err;
}
@@ -73,7 +75,7 @@ __xfrm6_find_bundle(struct flowi *fl, struct xfrm_policy *policy)
xdst->u.rt6.rt6i_src.plen);
if (ipv6_addr_equal(&xdst->u.rt6.rt6i_dst.addr, &fl_dst_prefix) &&
ipv6_addr_equal(&xdst->u.rt6.rt6i_src.addr, &fl_src_prefix) &&
- xfrm_bundle_ok(xdst, fl, AF_INET6,
+ xfrm_bundle_ok(policy, xdst, fl, AF_INET6,
(xdst->u.rt6.rt6i_dst.plen != 128 ||
xdst->u.rt6.rt6i_src.plen != 128))) {
dst_clone(dst);
diff --git a/net/ipv6/xfrm6_tunnel.c b/net/ipv6/xfrm6_tunnel.c
index 7af227bb1551..7931e4f898d4 100644
--- a/net/ipv6/xfrm6_tunnel.c
+++ b/net/ipv6/xfrm6_tunnel.c
@@ -135,7 +135,7 @@ u32 xfrm6_tunnel_spi_lookup(xfrm_address_t *saddr)
x6spi = __xfrm6_tunnel_spi_lookup(saddr);
spi = x6spi ? x6spi->spi : 0;
read_unlock_bh(&xfrm6_tunnel_spi_lock);
- return spi;
+ return htonl(spi);
}
EXPORT_SYMBOL(xfrm6_tunnel_spi_lookup);
@@ -210,7 +210,7 @@ u32 xfrm6_tunnel_alloc_spi(xfrm_address_t *saddr)
spi = __xfrm6_tunnel_alloc_spi(saddr);
write_unlock_bh(&xfrm6_tunnel_spi_lock);
- return spi;
+ return htonl(spi);
}
EXPORT_SYMBOL(xfrm6_tunnel_alloc_spi);
diff --git a/net/ipx/af_ipx.c b/net/ipx/af_ipx.c
index bef3f61569f7..76c661566dfd 100644
--- a/net/ipx/af_ipx.c
+++ b/net/ipx/af_ipx.c
@@ -83,13 +83,13 @@ DEFINE_SPINLOCK(ipx_interfaces_lock);
struct ipx_interface *ipx_primary_net;
struct ipx_interface *ipx_internal_net;
-extern int ipxrtr_add_route(__u32 network, struct ipx_interface *intrfc,
+extern int ipxrtr_add_route(__be32 network, struct ipx_interface *intrfc,
unsigned char *node);
extern void ipxrtr_del_routes(struct ipx_interface *intrfc);
extern int ipxrtr_route_packet(struct sock *sk, struct sockaddr_ipx *usipx,
struct iovec *iov, int len, int noblock);
extern int ipxrtr_route_skb(struct sk_buff *skb);
-extern struct ipx_route *ipxrtr_lookup(__u32 net);
+extern struct ipx_route *ipxrtr_lookup(__be32 net);
extern int ipxrtr_ioctl(unsigned int cmd, void __user *arg);
#undef IPX_REFCNT_DEBUG
@@ -177,7 +177,7 @@ static void ipxitf_clear_primary_net(void)
}
static struct ipx_interface *__ipxitf_find_using_phys(struct net_device *dev,
- unsigned short datalink)
+ __be16 datalink)
{
struct ipx_interface *i;
@@ -190,7 +190,7 @@ out:
}
static struct ipx_interface *ipxitf_find_using_phys(struct net_device *dev,
- unsigned short datalink)
+ __be16 datalink)
{
struct ipx_interface *i;
@@ -202,7 +202,7 @@ static struct ipx_interface *ipxitf_find_using_phys(struct net_device *dev,
return i;
}
-struct ipx_interface *ipxitf_find_using_net(__u32 net)
+struct ipx_interface *ipxitf_find_using_net(__be32 net)
{
struct ipx_interface *i;
@@ -237,7 +237,7 @@ static void ipxitf_insert_socket(struct ipx_interface *intrfc, struct sock *sk)
/* caller must hold intrfc->if_sklist_lock */
static struct sock *__ipxitf_find_socket(struct ipx_interface *intrfc,
- unsigned short port)
+ __be16 port)
{
struct sock *s;
struct hlist_node *node;
@@ -252,7 +252,7 @@ found:
/* caller must hold a reference to intrfc */
static struct sock *ipxitf_find_socket(struct ipx_interface *intrfc,
- unsigned short port)
+ __be16 port)
{
struct sock *s;
@@ -268,7 +268,7 @@ static struct sock *ipxitf_find_socket(struct ipx_interface *intrfc,
#ifdef CONFIG_IPX_INTERN
static struct sock *ipxitf_find_internal_socket(struct ipx_interface *intrfc,
unsigned char *ipx_node,
- unsigned short port)
+ __be16 port)
{
struct sock *s;
struct hlist_node *node;
@@ -600,10 +600,10 @@ int ipxitf_send(struct ipx_interface *intrfc, struct sk_buff *skb, char *node)
/* see if we need to include the netnum in the route list */
if (IPX_SKB_CB(skb)->last_hop.index >= 0) {
- u32 *last_hop = (u32 *)(((u8 *) skb->data) +
+ __be32 *last_hop = (__be32 *)(((u8 *) skb->data) +
sizeof(struct ipxhdr) +
IPX_SKB_CB(skb)->last_hop.index *
- sizeof(u32));
+ sizeof(__be32));
*last_hop = IPX_SKB_CB(skb)->last_hop.netnum;
IPX_SKB_CB(skb)->last_hop.index = -1;
}
@@ -772,7 +772,7 @@ static void ipxitf_discover_netnum(struct ipx_interface *intrfc,
} else {
printk(KERN_WARNING "IPX: Network number collision "
"%lx\n %s %s and %s %s\n",
- (unsigned long) htonl(cb->ipx_source_net),
+ (unsigned long) ntohl(cb->ipx_source_net),
ipx_device_name(i),
ipx_frame_name(i->if_dlink_type),
ipx_device_name(intrfc),
@@ -812,7 +812,7 @@ static int ipxitf_pprop(struct ipx_interface *intrfc, struct sk_buff *skb)
int i, rc = -EINVAL;
struct ipx_interface *ifcs;
char *c;
- u32 *l;
+ __be32 *l;
/* Illegal packet - too many hops or too short */
/* We decide to throw it away: no broadcasting, no local processing.
@@ -833,7 +833,7 @@ static int ipxitf_pprop(struct ipx_interface *intrfc, struct sk_buff *skb)
goto out;
c = ((u8 *) ipx) + sizeof(struct ipxhdr);
- l = (u32 *) c;
+ l = (__be32 *) c;
/* Don't broadcast packet if already seen this net */
for (i = 0; i < IPX_SKB_CB(skb)->ipx_tctrl; i++)
@@ -855,7 +855,7 @@ static int ipxitf_pprop(struct ipx_interface *intrfc, struct sk_buff *skb)
/* That aren't in the list */
if (ifcs == intrfc)
continue;
- l = (__u32 *) c;
+ l = (__be32 *) c;
/* don't consider the last entry in the packet list,
* it is our netnum, and it is not there yet */
for (i = 0; i < IPX_SKB_CB(skb)->ipx_tctrl; i++)
@@ -885,8 +885,8 @@ static void ipxitf_insert(struct ipx_interface *intrfc)
ipx_primary_net = intrfc;
}
-static struct ipx_interface *ipxitf_alloc(struct net_device *dev, __u32 netnum,
- unsigned short dlink_type,
+static struct ipx_interface *ipxitf_alloc(struct net_device *dev, __be32 netnum,
+ __be16 dlink_type,
struct datalink_proto *dlink,
unsigned char internal,
int ipx_offset)
@@ -960,7 +960,7 @@ static __be16 ipx_map_frame_type(unsigned char type)
static int ipxitf_create(struct ipx_interface_definition *idef)
{
struct net_device *dev;
- unsigned short dlink_type = 0;
+ __be16 dlink_type = 0;
struct datalink_proto *datalink = NULL;
struct ipx_interface *intrfc;
int rc;
@@ -1073,7 +1073,7 @@ out:
static int ipxitf_delete(struct ipx_interface_definition *idef)
{
struct net_device *dev = NULL;
- unsigned short dlink_type = 0;
+ __be16 dlink_type = 0;
struct ipx_interface *intrfc;
int rc = 0;
@@ -1110,7 +1110,7 @@ out:
}
static struct ipx_interface *ipxitf_auto_create(struct net_device *dev,
- unsigned short dlink_type)
+ __be16 dlink_type)
{
struct ipx_interface *intrfc = NULL;
struct datalink_proto *datalink;
@@ -1122,7 +1122,7 @@ static struct ipx_interface *ipxitf_auto_create(struct net_device *dev,
if (dev->addr_len > IPX_NODE_LEN)
goto out;
- switch (htons(dlink_type)) {
+ switch (ntohs(dlink_type)) {
case ETH_P_IPX: datalink = pEII_datalink; break;
case ETH_P_802_2: datalink = p8022_datalink; break;
case ETH_P_SNAP: datalink = pSNAP_datalink; break;
@@ -1234,27 +1234,27 @@ static int ipxitf_ioctl(unsigned int cmd, void __user *arg)
/* Note: We assume ipx_tctrl==0 and htons(length)==ipx_pktsize */
/* This functions should *not* mess with packet contents */
-__u16 ipx_cksum(struct ipxhdr *packet, int length)
+__be16 ipx_cksum(struct ipxhdr *packet, int length)
{
/*
* NOTE: sum is a net byte order quantity, which optimizes the
* loop. This only works on big and little endian machines. (I
* don't know of a machine that isn't.)
*/
- /* start at ipx_dest - We skip the checksum field and start with
- * ipx_type before the loop, not considering ipx_tctrl in the calc */
- __u16 *p = (__u16 *)&packet->ipx_dest;
- __u32 i = (length >> 1) - 1; /* Number of complete words */
- __u32 sum = packet->ipx_type << sizeof(packet->ipx_tctrl);
-
- /* Loop through all complete words except the checksum field,
- * ipx_type (accounted above) and ipx_tctrl (not used in the cksum) */
- while (--i)
+ /* handle the first 3 words separately; checksum should be skipped
+ * and ipx_tctrl masked out */
+ __u16 *p = (__u16 *)packet;
+ __u32 sum = p[1] + (p[2] & (__force u16)htons(0x00ff));
+ __u32 i = (length >> 1) - 3; /* Number of remaining complete words */
+
+ /* Loop through them */
+ p += 3;
+ while (i--)
sum += *p++;
/* Add on the last part word if it exists */
if (packet->ipx_pktsize & htons(1))
- sum += ntohs(0xff00) & *p;
+ sum += (__force u16)htons(0xff00) & *p;
/* Do final fixup */
sum = (sum & 0xffff) + (sum >> 16);
@@ -1263,10 +1263,17 @@ __u16 ipx_cksum(struct ipxhdr *packet, int length)
if (sum >= 0x10000)
sum++;
- return ~sum;
+ /*
+ * Leave 0 alone; we don't want 0xffff here. Note that we can't get
+ * here with 0x10000, so this check is the same as ((__u16)sum)
+ */
+ if (sum)
+ sum = ~sum;
+
+ return (__force __be16)sum;
}
-const char *ipx_frame_name(unsigned short frame)
+const char *ipx_frame_name(__be16 frame)
{
char* rc = "None";
@@ -1401,7 +1408,7 @@ out:
/* caller must hold a reference to intrfc */
-static unsigned short ipx_first_free_socketnum(struct ipx_interface *intrfc)
+static __be16 ipx_first_free_socketnum(struct ipx_interface *intrfc)
{
unsigned short socketNum = intrfc->if_sknum;
@@ -1410,7 +1417,7 @@ static unsigned short ipx_first_free_socketnum(struct ipx_interface *intrfc)
if (socketNum < IPX_MIN_EPHEMERAL_SOCKET)
socketNum = IPX_MIN_EPHEMERAL_SOCKET;
- while (__ipxitf_find_socket(intrfc, ntohs(socketNum)))
+ while (__ipxitf_find_socket(intrfc, htons(socketNum)))
if (socketNum > IPX_MAX_EPHEMERAL_SOCKET)
socketNum = IPX_MIN_EPHEMERAL_SOCKET;
else
@@ -1419,7 +1426,7 @@ static unsigned short ipx_first_free_socketnum(struct ipx_interface *intrfc)
spin_unlock_bh(&intrfc->if_sklist_lock);
intrfc->if_sknum = socketNum;
- return ntohs(socketNum);
+ return htons(socketNum);
}
static int ipx_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
@@ -1473,7 +1480,7 @@ static int ipx_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
ipxs->port)) {
SOCK_DEBUG(sk,
"IPX: bind failed because port %X in use.\n",
- ntohs((int)addr->sipx_port));
+ ntohs(addr->sipx_port));
goto out_put;
}
} else {
@@ -1488,7 +1495,7 @@ static int ipx_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
if (ipxitf_find_socket(intrfc, addr->sipx_port)) {
SOCK_DEBUG(sk,
"IPX: bind failed because port %X in use.\n",
- ntohs((int)addr->sipx_port));
+ ntohs(addr->sipx_port));
goto out_put;
}
}
@@ -1665,7 +1672,7 @@ static int ipx_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_ty
intrfc = ipxitf_find_using_phys(dev, pt->type);
if (!intrfc) {
if (ipxcfg_auto_create_interfaces &&
- ntohl(IPX_SKB_CB(skb)->ipx_dest_net)) {
+ IPX_SKB_CB(skb)->ipx_dest_net) {
intrfc = ipxitf_auto_create(dev, pt->type);
if (intrfc)
ipxitf_hold(intrfc);
diff --git a/net/ipx/ipx_proc.c b/net/ipx/ipx_proc.c
index 4c0c71206e54..b7463dfca63e 100644
--- a/net/ipx/ipx_proc.c
+++ b/net/ipx/ipx_proc.c
@@ -260,22 +260,22 @@ static int ipx_seq_socket_show(struct seq_file *seq, void *v)
ipxs = ipx_sk(s);
#ifdef CONFIG_IPX_INTERN
seq_printf(seq, "%08lX:%02X%02X%02X%02X%02X%02X:%04X ",
- (unsigned long)htonl(ipxs->intrfc->if_netnum),
+ (unsigned long)ntohl(ipxs->intrfc->if_netnum),
ipxs->node[0], ipxs->node[1], ipxs->node[2], ipxs->node[3],
- ipxs->node[4], ipxs->node[5], htons(ipxs->port));
+ ipxs->node[4], ipxs->node[5], ntohs(ipxs->port));
#else
- seq_printf(seq, "%08lX:%04X ", (unsigned long) htonl(ipxs->intrfc->if_netnum),
- htons(ipxs->port));
+ seq_printf(seq, "%08lX:%04X ", (unsigned long) ntohl(ipxs->intrfc->if_netnum),
+ ntohs(ipxs->port));
#endif /* CONFIG_IPX_INTERN */
if (s->sk_state != TCP_ESTABLISHED)
seq_printf(seq, "%-28s", "Not_Connected");
else {
seq_printf(seq, "%08lX:%02X%02X%02X%02X%02X%02X:%04X ",
- (unsigned long)htonl(ipxs->dest_addr.net),
+ (unsigned long)ntohl(ipxs->dest_addr.net),
ipxs->dest_addr.node[0], ipxs->dest_addr.node[1],
ipxs->dest_addr.node[2], ipxs->dest_addr.node[3],
ipxs->dest_addr.node[4], ipxs->dest_addr.node[5],
- htons(ipxs->dest_addr.sock));
+ ntohs(ipxs->dest_addr.sock));
}
seq_printf(seq, "%08X %08X %02X %03d\n",
diff --git a/net/ipx/ipx_route.c b/net/ipx/ipx_route.c
index a30dbb1e08fb..68560ee0d797 100644
--- a/net/ipx/ipx_route.c
+++ b/net/ipx/ipx_route.c
@@ -19,17 +19,17 @@ DEFINE_RWLOCK(ipx_routes_lock);
extern struct ipx_interface *ipx_internal_net;
-extern __u16 ipx_cksum(struct ipxhdr *packet, int length);
-extern struct ipx_interface *ipxitf_find_using_net(__u32 net);
+extern __be16 ipx_cksum(struct ipxhdr *packet, int length);
+extern struct ipx_interface *ipxitf_find_using_net(__be32 net);
extern int ipxitf_demux_socket(struct ipx_interface *intrfc,
struct sk_buff *skb, int copy);
extern int ipxitf_demux_socket(struct ipx_interface *intrfc,
struct sk_buff *skb, int copy);
extern int ipxitf_send(struct ipx_interface *intrfc, struct sk_buff *skb,
char *node);
-extern struct ipx_interface *ipxitf_find_using_net(__u32 net);
+extern struct ipx_interface *ipxitf_find_using_net(__be32 net);
-struct ipx_route *ipxrtr_lookup(__u32 net)
+struct ipx_route *ipxrtr_lookup(__be32 net)
{
struct ipx_route *r;
@@ -48,7 +48,7 @@ unlock:
/*
* Caller must hold a reference to intrfc
*/
-int ipxrtr_add_route(__u32 network, struct ipx_interface *intrfc,
+int ipxrtr_add_route(__be32 network, struct ipx_interface *intrfc,
unsigned char *node)
{
struct ipx_route *rt;
@@ -118,7 +118,7 @@ out:
return rc;
}
-static int ipxrtr_delete(__u32 net)
+static int ipxrtr_delete(__be32 net)
{
struct ipx_route *r, *tmp;
int rc;
@@ -238,7 +238,7 @@ int ipxrtr_route_packet(struct sock *sk, struct sockaddr_ipx *usipx,
/* Apply checksum. Not allowed on 802.3 links. */
if (sk->sk_no_check || intrfc->if_dlink_type == htons(IPX_FRAME_8023))
- ipx->ipx_checksum = 0xFFFF;
+ ipx->ipx_checksum = htons(0xFFFF);
else
ipx->ipx_checksum = ipx_cksum(ipx, len + sizeof(struct ipxhdr));
diff --git a/net/irda/irlmp.c b/net/irda/irlmp.c
index 5073261b9d0c..fede83763095 100644
--- a/net/irda/irlmp.c
+++ b/net/irda/irlmp.c
@@ -1678,7 +1678,8 @@ static int irlmp_slsap_inuse(__u8 slsap_sel)
* every IrLAP connection and check every LSAP associated with each
* the connection.
*/
- spin_lock_irqsave(&irlmp->links->hb_spinlock, flags);
+ spin_lock_irqsave_nested(&irlmp->links->hb_spinlock, flags,
+ SINGLE_DEPTH_NESTING);
lap = (struct lap_cb *) hashbin_get_first(irlmp->links);
while (lap != NULL) {
IRDA_ASSERT(lap->magic == LMP_LAP_MAGIC, goto errlap;);
diff --git a/net/key/af_key.c b/net/key/af_key.c
index ff98e70b0931..20ff7cca1d07 100644
--- a/net/key/af_key.c
+++ b/net/key/af_key.c
@@ -2928,11 +2928,6 @@ static struct xfrm_policy *pfkey_compile_policy(struct sock *sk, int opt,
if (*dir)
goto out;
}
- else {
- *dir = security_xfrm_sock_policy_alloc(xp, sk);
- if (*dir)
- goto out;
- }
*dir = pol->sadb_x_policy_dir-1;
return xp;
diff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig
index ce94732b8e23..f619c6527266 100644
--- a/net/netfilter/Kconfig
+++ b/net/netfilter/Kconfig
@@ -209,7 +209,9 @@ config NETFILTER_XT_TARGET_SECMARK
config NETFILTER_XT_TARGET_CONNSECMARK
tristate '"CONNSECMARK" target support'
- depends on NETFILTER_XTABLES && (NF_CONNTRACK_SECMARK || IP_NF_CONNTRACK_SECMARK)
+ depends on NETFILTER_XTABLES && \
+ ((NF_CONNTRACK && NF_CONNTRACK_SECMARK) || \
+ (IP_NF_CONNTRACK && IP_NF_CONNTRACK_SECMARK))
help
The CONNSECMARK target copies security markings from packets
to connections, and restores security markings from connections
diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c
index 093b3ddc513c..836541e509fe 100644
--- a/net/netfilter/nf_conntrack_core.c
+++ b/net/netfilter/nf_conntrack_core.c
@@ -1520,9 +1520,10 @@ get_next_corpse(int (*iter)(struct nf_conn *i, void *data),
if (iter(ct, data))
goto found;
}
+ write_unlock_bh(&nf_conntrack_lock);
return NULL;
found:
- atomic_inc(&nf_ct_tuplehash_to_ctrack(h)->ct_general.use);
+ atomic_inc(&ct->ct_general.use);
write_unlock_bh(&nf_conntrack_lock);
return ct;
}
diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c
index 1721f7c78c77..bd0156a28ecd 100644
--- a/net/netfilter/nf_conntrack_netlink.c
+++ b/net/netfilter/nf_conntrack_netlink.c
@@ -47,13 +47,6 @@ MODULE_LICENSE("GPL");
static char __initdata version[] = "0.93";
-#if 0
-#define DEBUGP printk
-#else
-#define DEBUGP(format, args...)
-#endif
-
-
static inline int
ctnetlink_dump_tuples_proto(struct sk_buff *skb,
const struct nf_conntrack_tuple *tuple,
@@ -410,7 +403,6 @@ static int ctnetlink_done(struct netlink_callback *cb)
{
if (cb->args[1])
nf_ct_put((struct nf_conn *)cb->args[1]);
- DEBUGP("entered %s\n", __FUNCTION__);
return 0;
}
@@ -425,9 +417,6 @@ ctnetlink_dump_table(struct sk_buff *skb, struct netlink_callback *cb)
struct nfgenmsg *nfmsg = NLMSG_DATA(cb->nlh);
u_int8_t l3proto = nfmsg->nfgen_family;
- DEBUGP("entered %s, last bucket=%lu id=%u\n", __FUNCTION__,
- cb->args[0], *id);
-
read_lock_bh(&nf_conntrack_lock);
last = (struct nf_conn *)cb->args[1];
for (; cb->args[0] < nf_conntrack_htable_size; cb->args[0]++) {
@@ -471,7 +460,6 @@ out:
if (last)
nf_ct_put(last);
- DEBUGP("leaving, last bucket=%lu id=%u\n", cb->args[0], *id);
return skb->len;
}
@@ -482,8 +470,6 @@ ctnetlink_parse_tuple_ip(struct nfattr *attr, struct nf_conntrack_tuple *tuple)
struct nf_conntrack_l3proto *l3proto;
int ret = 0;
- DEBUGP("entered %s\n", __FUNCTION__);
-
nfattr_parse_nested(tb, CTA_IP_MAX, attr);
l3proto = nf_ct_l3proto_find_get(tuple->src.l3num);
@@ -493,8 +479,6 @@ ctnetlink_parse_tuple_ip(struct nfattr *attr, struct nf_conntrack_tuple *tuple)
nf_ct_l3proto_put(l3proto);
- DEBUGP("leaving\n");
-
return ret;
}
@@ -510,8 +494,6 @@ ctnetlink_parse_tuple_proto(struct nfattr *attr,
struct nf_conntrack_protocol *proto;
int ret = 0;
- DEBUGP("entered %s\n", __FUNCTION__);
-
nfattr_parse_nested(tb, CTA_PROTO_MAX, attr);
if (nfattr_bad_size(tb, CTA_PROTO_MAX, cta_min_proto))
@@ -538,8 +520,6 @@ ctnetlink_parse_tuple(struct nfattr *cda[], struct nf_conntrack_tuple *tuple,
struct nfattr *tb[CTA_TUPLE_MAX];
int err;
- DEBUGP("entered %s\n", __FUNCTION__);
-
memset(tuple, 0, sizeof(*tuple));
nfattr_parse_nested(tb, CTA_TUPLE_MAX, cda[type-1]);
@@ -566,10 +546,6 @@ ctnetlink_parse_tuple(struct nfattr *cda[], struct nf_conntrack_tuple *tuple,
else
tuple->dst.dir = IP_CT_DIR_ORIGINAL;
- NF_CT_DUMP_TUPLE(tuple);
-
- DEBUGP("leaving\n");
-
return 0;
}
@@ -586,8 +562,6 @@ static int ctnetlink_parse_nat_proto(struct nfattr *attr,
struct nfattr *tb[CTA_PROTONAT_MAX];
struct ip_nat_protocol *npt;
- DEBUGP("entered %s\n", __FUNCTION__);
-
nfattr_parse_nested(tb, CTA_PROTONAT_MAX, attr);
if (nfattr_bad_size(tb, CTA_PROTONAT_MAX, cta_min_protonat))
@@ -606,7 +580,6 @@ static int ctnetlink_parse_nat_proto(struct nfattr *attr,
ip_nat_proto_put(npt);
- DEBUGP("leaving\n");
return 0;
}
@@ -622,8 +595,6 @@ ctnetlink_parse_nat(struct nfattr *nat,
struct nfattr *tb[CTA_NAT_MAX];
int err;
- DEBUGP("entered %s\n", __FUNCTION__);
-
memset(range, 0, sizeof(*range));
nfattr_parse_nested(tb, CTA_NAT_MAX, nat);
@@ -649,7 +620,6 @@ ctnetlink_parse_nat(struct nfattr *nat,
if (err < 0)
return err;
- DEBUGP("leaving\n");
return 0;
}
#endif
@@ -659,8 +629,6 @@ ctnetlink_parse_help(struct nfattr *attr, char **helper_name)
{
struct nfattr *tb[CTA_HELP_MAX];
- DEBUGP("entered %s\n", __FUNCTION__);
-
nfattr_parse_nested(tb, CTA_HELP_MAX, attr);
if (!tb[CTA_HELP_NAME-1])
@@ -690,8 +658,6 @@ ctnetlink_del_conntrack(struct sock *ctnl, struct sk_buff *skb,
u_int8_t u3 = nfmsg->nfgen_family;
int err = 0;
- DEBUGP("entered %s\n", __FUNCTION__);
-
if (nfattr_bad_size(cda, CTA_MAX, cta_min))
return -EINVAL;
@@ -709,10 +675,8 @@ ctnetlink_del_conntrack(struct sock *ctnl, struct sk_buff *skb,
return err;
h = nf_conntrack_find_get(&tuple, NULL);
- if (!h) {
- DEBUGP("tuple not found in conntrack hash\n");
+ if (!h)
return -ENOENT;
- }
ct = nf_ct_tuplehash_to_ctrack(h);
@@ -727,7 +691,6 @@ ctnetlink_del_conntrack(struct sock *ctnl, struct sk_buff *skb,
ct->timeout.function((unsigned long)ct);
nf_ct_put(ct);
- DEBUGP("leaving\n");
return 0;
}
@@ -744,8 +707,6 @@ ctnetlink_get_conntrack(struct sock *ctnl, struct sk_buff *skb,
u_int8_t u3 = nfmsg->nfgen_family;
int err = 0;
- DEBUGP("entered %s\n", __FUNCTION__);
-
if (nlh->nlmsg_flags & NLM_F_DUMP) {
u32 rlen;
@@ -779,11 +740,9 @@ ctnetlink_get_conntrack(struct sock *ctnl, struct sk_buff *skb,
return err;
h = nf_conntrack_find_get(&tuple, NULL);
- if (!h) {
- DEBUGP("tuple not found in conntrack hash");
+ if (!h)
return -ENOENT;
- }
- DEBUGP("tuple found\n");
+
ct = nf_ct_tuplehash_to_ctrack(h);
err = -ENOMEM;
@@ -804,7 +763,6 @@ ctnetlink_get_conntrack(struct sock *ctnl, struct sk_buff *skb,
if (err < 0)
goto out;
- DEBUGP("leaving\n");
return 0;
free:
@@ -876,8 +834,6 @@ ctnetlink_change_helper(struct nf_conn *ct, struct nfattr *cda[])
char *helpname;
int err;
- DEBUGP("entered %s\n", __FUNCTION__);
-
if (!help) {
/* FIXME: we need to reallocate and rehash */
return -EBUSY;
@@ -954,8 +910,6 @@ ctnetlink_change_conntrack(struct nf_conn *ct, struct nfattr *cda[])
{
int err;
- DEBUGP("entered %s\n", __FUNCTION__);
-
if (cda[CTA_HELP-1]) {
err = ctnetlink_change_helper(ct, cda);
if (err < 0)
@@ -985,7 +939,6 @@ ctnetlink_change_conntrack(struct nf_conn *ct, struct nfattr *cda[])
ct->mark = ntohl(*(u_int32_t *)NFA_DATA(cda[CTA_MARK-1]));
#endif
- DEBUGP("all done\n");
return 0;
}
@@ -997,8 +950,6 @@ ctnetlink_create_conntrack(struct nfattr *cda[],
struct nf_conn *ct;
int err = -EINVAL;
- DEBUGP("entered %s\n", __FUNCTION__);
-
ct = nf_conntrack_alloc(otuple, rtuple);
if (ct == NULL || IS_ERR(ct))
return -ENOMEM;
@@ -1028,7 +979,6 @@ ctnetlink_create_conntrack(struct nfattr *cda[],
add_timer(&ct->timeout);
nf_conntrack_hash_insert(ct);
- DEBUGP("conntrack with id %u inserted\n", ct->id);
return 0;
err:
@@ -1046,8 +996,6 @@ ctnetlink_new_conntrack(struct sock *ctnl, struct sk_buff *skb,
u_int8_t u3 = nfmsg->nfgen_family;
int err = 0;
- DEBUGP("entered %s\n", __FUNCTION__);
-
if (nfattr_bad_size(cda, CTA_MAX, cta_min))
return -EINVAL;
@@ -1071,7 +1019,6 @@ ctnetlink_new_conntrack(struct sock *ctnl, struct sk_buff *skb,
if (h == NULL) {
write_unlock_bh(&nf_conntrack_lock);
- DEBUGP("no such conntrack, create new\n");
err = -ENOENT;
if (nlh->nlmsg_flags & NLM_F_CREATE)
err = ctnetlink_create_conntrack(cda, &otuple, &rtuple);
@@ -1087,7 +1034,6 @@ ctnetlink_new_conntrack(struct sock *ctnl, struct sk_buff *skb,
/* We manipulate the conntrack inside the global conntrack table lock,
* so there's no need to increase the refcount */
- DEBUGP("conntrack found\n");
err = -EEXIST;
if (!(nlh->nlmsg_flags & NLM_F_EXCL))
err = ctnetlink_change_conntrack(nf_ct_tuplehash_to_ctrack(h), cda);
@@ -1268,8 +1214,6 @@ ctnetlink_exp_dump_table(struct sk_buff *skb, struct netlink_callback *cb)
struct nfgenmsg *nfmsg = NLMSG_DATA(cb->nlh);
u_int8_t l3proto = nfmsg->nfgen_family;
- DEBUGP("entered %s, last id=%llu\n", __FUNCTION__, *id);
-
read_lock_bh(&nf_conntrack_lock);
list_for_each_prev(i, &nf_conntrack_expect_list) {
exp = (struct nf_conntrack_expect *) i;
@@ -1287,8 +1231,6 @@ ctnetlink_exp_dump_table(struct sk_buff *skb, struct netlink_callback *cb)
out:
read_unlock_bh(&nf_conntrack_lock);
- DEBUGP("leaving, last id=%llu\n", *id);
-
return skb->len;
}
@@ -1308,8 +1250,6 @@ ctnetlink_get_expect(struct sock *ctnl, struct sk_buff *skb,
u_int8_t u3 = nfmsg->nfgen_family;
int err = 0;
- DEBUGP("entered %s\n", __FUNCTION__);
-
if (nfattr_bad_size(cda, CTA_EXPECT_MAX, cta_min_exp))
return -EINVAL;
@@ -1460,8 +1400,6 @@ ctnetlink_create_expect(struct nfattr *cda[], u_int8_t u3)
struct nf_conn_help *help;
int err = 0;
- DEBUGP("entered %s\n", __FUNCTION__);
-
/* caller guarantees that those three CTA_EXPECT_* exist */
err = ctnetlink_parse_tuple(cda, &tuple, CTA_EXPECT_TUPLE, u3);
if (err < 0)
@@ -1516,8 +1454,6 @@ ctnetlink_new_expect(struct sock *ctnl, struct sk_buff *skb,
u_int8_t u3 = nfmsg->nfgen_family;
int err = 0;
- DEBUGP("entered %s\n", __FUNCTION__);
-
if (nfattr_bad_size(cda, CTA_EXPECT_MAX, cta_min_exp))
return -EINVAL;
@@ -1546,8 +1482,6 @@ ctnetlink_new_expect(struct sock *ctnl, struct sk_buff *skb,
err = ctnetlink_change_expect(exp, cda);
write_unlock_bh(&nf_conntrack_lock);
- DEBUGP("leaving\n");
-
return err;
}
diff --git a/net/netfilter/nfnetlink_log.c b/net/netfilter/nfnetlink_log.c
index b59d3b2bde21..1e5207b80fe5 100644
--- a/net/netfilter/nfnetlink_log.c
+++ b/net/netfilter/nfnetlink_log.c
@@ -427,7 +427,7 @@ __build_packet_message(struct nfulnl_instance *inst,
nfmsg->version = NFNETLINK_V0;
nfmsg->res_id = htons(inst->group_num);
- pmsg.hw_protocol = htons(skb->protocol);
+ pmsg.hw_protocol = skb->protocol;
pmsg.hook = hooknum;
NFA_PUT(inst->skb, NFULA_PACKET_HDR, sizeof(pmsg), &pmsg);
@@ -544,7 +544,7 @@ __build_packet_message(struct nfulnl_instance *inst,
}
/* global sequence number */
if (inst->flags & NFULNL_CFG_F_SEQ_GLOBAL) {
- tmp_uint = atomic_inc_return(&global_seq);
+ tmp_uint = htonl(atomic_inc_return(&global_seq));
NFA_PUT(inst->skb, NFULA_SEQ_GLOBAL, sizeof(tmp_uint), &tmp_uint);
}
@@ -878,7 +878,7 @@ nfulnl_recv_config(struct sock *ctnl, struct sk_buff *skb,
params = NFA_DATA(nfula[NFULA_CFG_MODE-1]);
nfulnl_set_mode(inst, params->copy_mode,
- ntohs(params->copy_range));
+ ntohl(params->copy_range));
}
if (nfula[NFULA_CFG_TIMEOUT-1]) {
@@ -896,8 +896,8 @@ nfulnl_recv_config(struct sock *ctnl, struct sk_buff *skb,
}
if (nfula[NFULA_CFG_QTHRESH-1]) {
- u_int32_t qthresh =
- *(u_int16_t *)NFA_DATA(nfula[NFULA_CFG_QTHRESH-1]);
+ __be32 qthresh =
+ *(__be32 *)NFA_DATA(nfula[NFULA_CFG_QTHRESH-1]);
nfulnl_set_qthresh(inst, ntohl(qthresh));
}
diff --git a/net/netfilter/nfnetlink_queue.c b/net/netfilter/nfnetlink_queue.c
index 8eb2473d83e1..e815a9aa6e95 100644
--- a/net/netfilter/nfnetlink_queue.c
+++ b/net/netfilter/nfnetlink_queue.c
@@ -414,7 +414,7 @@ nfqnl_build_packet_message(struct nfqnl_instance *queue,
nfmsg->res_id = htons(queue->queue_num);
pmsg.packet_id = htonl(entry->id);
- pmsg.hw_protocol = htons(entskb->protocol);
+ pmsg.hw_protocol = entskb->protocol;
pmsg.hook = entinf->hook;
NFA_PUT(skb, NFQA_PACKET_HDR, sizeof(pmsg), &pmsg);
@@ -622,9 +622,10 @@ nfqnl_mangle(void *data, int data_len, struct nfqnl_queue_entry *e)
int diff;
diff = data_len - e->skb->len;
- if (diff < 0)
- skb_trim(e->skb, data_len);
- else if (diff > 0) {
+ if (diff < 0) {
+ if (pskb_trim(e->skb, data_len))
+ return -ENOMEM;
+ } else if (diff > 0) {
if (data_len > 0xFFFF)
return -EINVAL;
if (diff > skb_tailroom(e->skb)) {
diff --git a/net/netfilter/xt_NFQUEUE.c b/net/netfilter/xt_NFQUEUE.c
index db9b896e57c8..39e117502bd7 100644
--- a/net/netfilter/xt_NFQUEUE.c
+++ b/net/netfilter/xt_NFQUEUE.c
@@ -68,7 +68,7 @@ static int __init xt_nfqueue_init(void)
static void __exit xt_nfqueue_fini(void)
{
- xt_register_targets(xt_nfqueue_target, ARRAY_SIZE(xt_nfqueue_target));
+ xt_unregister_targets(xt_nfqueue_target, ARRAY_SIZE(xt_nfqueue_target));
}
module_init(xt_nfqueue_init);
diff --git a/net/netfilter/xt_connmark.c b/net/netfilter/xt_connmark.c
index 92a5726ef237..a8f03057dbde 100644
--- a/net/netfilter/xt_connmark.c
+++ b/net/netfilter/xt_connmark.c
@@ -147,7 +147,7 @@ static int __init xt_connmark_init(void)
static void __exit xt_connmark_fini(void)
{
- xt_register_matches(xt_connmark_match, ARRAY_SIZE(xt_connmark_match));
+ xt_unregister_matches(xt_connmark_match, ARRAY_SIZE(xt_connmark_match));
}
module_init(xt_connmark_init);
diff --git a/net/netlabel/Kconfig b/net/netlabel/Kconfig
index 9f7121ae13e9..56958c85f2b4 100644
--- a/net/netlabel/Kconfig
+++ b/net/netlabel/Kconfig
@@ -4,7 +4,7 @@
config NETLABEL
bool "NetLabel subsystem support"
- depends on NET && SECURITY
+ depends on SECURITY
default n
---help---
NetLabel provides support for explicit network packet labeling
diff --git a/net/netlabel/netlabel_kapi.c b/net/netlabel/netlabel_kapi.c
index 54fb7de3c2b1..ff971103fd0c 100644
--- a/net/netlabel/netlabel_kapi.c
+++ b/net/netlabel/netlabel_kapi.c
@@ -200,7 +200,7 @@ void netlbl_cache_invalidate(void)
int netlbl_cache_add(const struct sk_buff *skb,
const struct netlbl_lsm_secattr *secattr)
{
- if (secattr->cache.data == NULL)
+ if (secattr->cache == NULL)
return -ENOMSG;
if (CIPSO_V4_OPTEXIST(skb))
diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c
index d56e0d21f919..d527c8977b1f 100644
--- a/net/netlink/af_netlink.c
+++ b/net/netlink/af_netlink.c
@@ -1075,8 +1075,9 @@ static int netlink_getsockopt(struct socket *sock, int level, int optname,
return -EINVAL;
len = sizeof(int);
val = nlk->flags & NETLINK_RECV_PKTINFO ? 1 : 0;
- put_user(len, optlen);
- put_user(val, optval);
+ if (put_user(len, optlen) ||
+ put_user(val, optval))
+ return -EFAULT;
err = 0;
break;
default:
diff --git a/net/sched/sch_htb.c b/net/sched/sch_htb.c
index bb3ddd4784b1..4b52fa78935a 100644
--- a/net/sched/sch_htb.c
+++ b/net/sched/sch_htb.c
@@ -786,11 +786,10 @@ static long htb_do_events(struct htb_sched *q, int level)
for (i = 0; i < 500; i++) {
struct htb_class *cl;
long diff;
- struct rb_node *p = q->wait_pq[level].rb_node;
+ struct rb_node *p = rb_first(&q->wait_pq[level]);
+
if (!p)
return 0;
- while (p->rb_left)
- p = p->rb_left;
cl = rb_entry(p, struct htb_class, pq_node);
if (time_after(cl->pq_key, q->jiffies)) {
@@ -1285,8 +1284,7 @@ static void htb_destroy_class(struct Qdisc *sch, struct htb_class *cl)
struct htb_class, sibling));
/* note: this delete may happen twice (see htb_delete) */
- if (!hlist_unhashed(&cl->hlist))
- hlist_del(&cl->hlist);
+ hlist_del_init(&cl->hlist);
list_del(&cl->sibling);
if (cl->prio_activity)
@@ -1334,8 +1332,7 @@ static int htb_delete(struct Qdisc *sch, unsigned long arg)
sch_tree_lock(sch);
/* delete from hash and active; remainder in destroy_class */
- if (!hlist_unhashed(&cl->hlist))
- hlist_del(&cl->hlist);
+ hlist_del_init(&cl->hlist);
if (cl->prio_activity)
htb_deactivate(q, cl);
diff --git a/net/sched/sch_netem.c b/net/sched/sch_netem.c
index 45939bafbdf8..0441876aa1e7 100644
--- a/net/sched/sch_netem.c
+++ b/net/sched/sch_netem.c
@@ -4,7 +4,7 @@
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version
- * 2 of the License, or (at your option) any later version.
+ * 2 of the License.
*
* Many of the algorithms and ideas for this came from
* NIST Net which is not copyrighted.
@@ -170,6 +170,8 @@ static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch)
return NET_XMIT_BYPASS;
}
+ skb_orphan(skb);
+
/*
* If we need to duplicate packet, then re-insert at top of the
* qdisc tree, since parent queuer expects that only one
diff --git a/net/sctp/associola.c b/net/sctp/associola.c
index 27329ce9c311..ed0445fe85e7 100644
--- a/net/sctp/associola.c
+++ b/net/sctp/associola.c
@@ -346,11 +346,18 @@ void sctp_association_free(struct sctp_association *asoc)
struct list_head *pos, *temp;
int i;
- list_del(&asoc->asocs);
+ /* Only real associations count against the endpoint, so
+ * don't bother for if this is a temporary association.
+ */
+ if (!asoc->temp) {
+ list_del(&asoc->asocs);
- /* Decrement the backlog value for a TCP-style listening socket. */
- if (sctp_style(sk, TCP) && sctp_sstate(sk, LISTENING))
- sk->sk_ack_backlog--;
+ /* Decrement the backlog value for a TCP-style listening
+ * socket.
+ */
+ if (sctp_style(sk, TCP) && sctp_sstate(sk, LISTENING))
+ sk->sk_ack_backlog--;
+ }
/* Mark as dead, so other users can know this structure is
* going away.
diff --git a/net/sctp/endpointola.c b/net/sctp/endpointola.c
index 35c49ff2d062..9b6b394b66f6 100644
--- a/net/sctp/endpointola.c
+++ b/net/sctp/endpointola.c
@@ -144,6 +144,13 @@ void sctp_endpoint_add_asoc(struct sctp_endpoint *ep,
{
struct sock *sk = ep->base.sk;
+ /* If this is a temporary association, don't bother
+ * since we'll be removing it shortly and don't
+ * want anyone to find it anyway.
+ */
+ if (asoc->temp)
+ return;
+
/* Now just add it to our list of asocs */
list_add_tail(&asoc->asocs, &ep->asocs);
diff --git a/net/sctp/input.c b/net/sctp/input.c
index 64f630102532..6d82f400d13c 100644
--- a/net/sctp/input.c
+++ b/net/sctp/input.c
@@ -135,6 +135,9 @@ int sctp_rcv(struct sk_buff *skb)
SCTP_INC_STATS_BH(SCTP_MIB_INSCTPPACKS);
+ if (skb_linearize(skb))
+ goto discard_it;
+
sh = (struct sctphdr *) skb->h.raw;
/* Pull up the IP and SCTP headers. */
@@ -768,6 +771,9 @@ static void __sctp_hash_established(struct sctp_association *asoc)
/* Add an association to the hash. Local BH-safe. */
void sctp_hash_established(struct sctp_association *asoc)
{
+ if (asoc->temp)
+ return;
+
sctp_local_bh_disable();
__sctp_hash_established(asoc);
sctp_local_bh_enable();
@@ -801,6 +807,9 @@ static void __sctp_unhash_established(struct sctp_association *asoc)
/* Remove association from the hash table. Local BH-safe. */
void sctp_unhash_established(struct sctp_association *asoc)
{
+ if (asoc->temp)
+ return;
+
sctp_local_bh_disable();
__sctp_unhash_established(asoc);
sctp_local_bh_enable();
diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c
index 249e5033c1a8..78071c6e6cf1 100644
--- a/net/sctp/ipv6.c
+++ b/net/sctp/ipv6.c
@@ -215,17 +215,17 @@ static struct dst_entry *sctp_v6_get_dst(struct sctp_association *asoc,
}
dst = ip6_route_output(NULL, &fl);
- if (dst) {
+ if (!dst->error) {
struct rt6_info *rt;
rt = (struct rt6_info *)dst;
SCTP_DEBUG_PRINTK(
"rt6_dst:" NIP6_FMT " rt6_src:" NIP6_FMT "\n",
NIP6(rt->rt6i_dst.addr), NIP6(rt->rt6i_src.addr));
- } else {
- SCTP_DEBUG_PRINTK("NO ROUTE\n");
+ return dst;
}
-
- return dst;
+ SCTP_DEBUG_PRINTK("NO ROUTE\n");
+ dst_release(dst);
+ return NULL;
}
/* Returns the number of consecutive initial bits that match in the 2 ipv6
diff --git a/net/sctp/proc.c b/net/sctp/proc.c
index a356d8d310a9..7f49e769080e 100644
--- a/net/sctp/proc.c
+++ b/net/sctp/proc.c
@@ -344,7 +344,7 @@ static int sctp_assocs_seq_show(struct seq_file *seq, void *v)
assoc, sk, sctp_sk(sk)->type, sk->sk_state,
assoc->state, hash, assoc->assoc_id,
assoc->sndbuf_used,
- (sk->sk_rcvbuf - assoc->rwnd),
+ atomic_read(&assoc->rmem_alloc),
sock_i_uid(sk), sock_i_ino(sk),
epb->bind_addr.port,
assoc->peer.port);
diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c
index fac7674438a4..5b4f82fd98f8 100644
--- a/net/sctp/protocol.c
+++ b/net/sctp/protocol.c
@@ -591,7 +591,7 @@ static struct sock *sctp_v4_create_accept_sk(struct sock *sk,
newinet->dport = htons(asoc->peer.port);
newinet->daddr = asoc->peer.primary_addr.v4.sin_addr.s_addr;
newinet->pmtudisc = inet->pmtudisc;
- newinet->id = 0;
+ newinet->id = asoc->next_tsn ^ jiffies;
newinet->uc_ttl = -1;
newinet->mc_loop = 1;
diff --git a/net/sctp/socket.c b/net/sctp/socket.c
index 3fe906d65069..935bc9187fd8 100644
--- a/net/sctp/socket.c
+++ b/net/sctp/socket.c
@@ -821,7 +821,7 @@ out:
* addrs is a pointer to an array of one or more socket addresses. Each
* address is contained in its appropriate structure (i.e. struct
* sockaddr_in or struct sockaddr_in6) the family of the address type
- * must be used to distengish the address length (note that this
+ * must be used to distinguish the address length (note that this
* representation is termed a "packed array" of addresses). The caller
* specifies the number of addresses in the array with addrcnt.
*
@@ -3372,6 +3372,7 @@ SCTP_STATIC int sctp_do_peeloff(struct sctp_association *asoc,
{
struct sock *sk = asoc->base.sk;
struct socket *sock;
+ struct inet_sock *inetsk;
int err = 0;
/* An association cannot be branched off from an already peeled-off
@@ -3389,6 +3390,14 @@ SCTP_STATIC int sctp_do_peeloff(struct sctp_association *asoc,
* asoc to the newsk.
*/
sctp_sock_migrate(sk, sock->sk, asoc, SCTP_SOCKET_UDP_HIGH_BANDWIDTH);
+
+ /* Make peeled-off sockets more like 1-1 accepted sockets.
+ * Set the daddr and initialize id to something more random
+ */
+ inetsk = inet_sk(sock->sk);
+ inetsk->daddr = asoc->peer.primary_addr.v4.sin_addr.s_addr;
+ inetsk->id = asoc->next_tsn ^ jiffies;
+
*sockp = sock;
return err;
@@ -5362,6 +5371,20 @@ static void sctp_wfree(struct sk_buff *skb)
sctp_association_put(asoc);
}
+/* Do accounting for the receive space on the socket.
+ * Accounting for the association is done in ulpevent.c
+ * We set this as a destructor for the cloned data skbs so that
+ * accounting is done at the correct time.
+ */
+void sctp_sock_rfree(struct sk_buff *skb)
+{
+ struct sock *sk = skb->sk;
+ struct sctp_ulpevent *event = sctp_skb2event(skb);
+
+ atomic_sub(event->rmem_len, &sk->sk_rmem_alloc);
+}
+
+
/* Helper function to wait for space in the sndbuf. */
static int sctp_wait_for_sndbuf(struct sctp_association *asoc, long *timeo_p,
size_t msg_len)
@@ -5634,10 +5657,10 @@ static void sctp_sock_migrate(struct sock *oldsk, struct sock *newsk,
sctp_skb_for_each(skb, &oldsk->sk_receive_queue, tmp) {
event = sctp_skb2event(skb);
if (event->asoc == assoc) {
- sock_rfree(skb);
+ sctp_sock_rfree(skb);
__skb_unlink(skb, &oldsk->sk_receive_queue);
__skb_queue_tail(&newsk->sk_receive_queue, skb);
- skb_set_owner_r(skb, newsk);
+ sctp_skb_set_owner_r(skb, newsk);
}
}
@@ -5665,10 +5688,10 @@ static void sctp_sock_migrate(struct sock *oldsk, struct sock *newsk,
sctp_skb_for_each(skb, &oldsp->pd_lobby, tmp) {
event = sctp_skb2event(skb);
if (event->asoc == assoc) {
- sock_rfree(skb);
+ sctp_sock_rfree(skb);
__skb_unlink(skb, &oldsp->pd_lobby);
__skb_queue_tail(queue, skb);
- skb_set_owner_r(skb, newsk);
+ sctp_skb_set_owner_r(skb, newsk);
}
}
diff --git a/net/sctp/ulpevent.c b/net/sctp/ulpevent.c
index ee236784a6bb..a015283a9087 100644
--- a/net/sctp/ulpevent.c
+++ b/net/sctp/ulpevent.c
@@ -55,10 +55,13 @@ static void sctp_ulpevent_release_frag_data(struct sctp_ulpevent *event);
/* Initialize an ULP event from an given skb. */
-SCTP_STATIC void sctp_ulpevent_init(struct sctp_ulpevent *event, int msg_flags)
+SCTP_STATIC void sctp_ulpevent_init(struct sctp_ulpevent *event,
+ int msg_flags,
+ unsigned int len)
{
memset(event, 0, sizeof(struct sctp_ulpevent));
event->msg_flags = msg_flags;
+ event->rmem_len = len;
}
/* Create a new sctp_ulpevent. */
@@ -73,7 +76,7 @@ SCTP_STATIC struct sctp_ulpevent *sctp_ulpevent_new(int size, int msg_flags,
goto fail;
event = sctp_skb2event(skb);
- sctp_ulpevent_init(event, msg_flags);
+ sctp_ulpevent_init(event, msg_flags, skb->truesize);
return event;
@@ -101,17 +104,16 @@ static inline void sctp_ulpevent_set_owner(struct sctp_ulpevent *event,
sctp_association_hold((struct sctp_association *)asoc);
skb = sctp_event2skb(event);
event->asoc = (struct sctp_association *)asoc;
- atomic_add(skb->truesize, &event->asoc->rmem_alloc);
- skb_set_owner_r(skb, asoc->base.sk);
+ atomic_add(event->rmem_len, &event->asoc->rmem_alloc);
+ sctp_skb_set_owner_r(skb, asoc->base.sk);
}
/* A simple destructor to give up the reference to the association. */
static inline void sctp_ulpevent_release_owner(struct sctp_ulpevent *event)
{
struct sctp_association *asoc = event->asoc;
- struct sk_buff *skb = sctp_event2skb(event);
- atomic_sub(skb->truesize, &asoc->rmem_alloc);
+ atomic_sub(event->rmem_len, &asoc->rmem_alloc);
sctp_association_put(asoc);
}
@@ -372,7 +374,7 @@ struct sctp_ulpevent *sctp_ulpevent_make_remote_error(
/* Embed the event fields inside the cloned skb. */
event = sctp_skb2event(skb);
- sctp_ulpevent_init(event, MSG_NOTIFICATION);
+ sctp_ulpevent_init(event, MSG_NOTIFICATION, skb->truesize);
sre = (struct sctp_remote_error *)
skb_push(skb, sizeof(struct sctp_remote_error));
@@ -464,7 +466,7 @@ struct sctp_ulpevent *sctp_ulpevent_make_send_failed(
/* Embed the event fields inside the cloned skb. */
event = sctp_skb2event(skb);
- sctp_ulpevent_init(event, MSG_NOTIFICATION);
+ sctp_ulpevent_init(event, MSG_NOTIFICATION, skb->truesize);
ssf = (struct sctp_send_failed *)
skb_push(skb, sizeof(struct sctp_send_failed));
@@ -682,8 +684,11 @@ struct sctp_ulpevent *sctp_ulpevent_make_rcvmsg(struct sctp_association *asoc,
/* Embed the event fields inside the cloned skb. */
event = sctp_skb2event(skb);
- /* Initialize event with flags 0. */
- sctp_ulpevent_init(event, 0);
+ /* Initialize event with flags 0 and correct length
+ * Since this is a clone of the original skb, only account for
+ * the data of this chunk as other chunks will be accounted separately.
+ */
+ sctp_ulpevent_init(event, 0, skb->len + sizeof(struct sk_buff));
sctp_ulpevent_receive_data(event, asoc);
diff --git a/net/sctp/ulpqueue.c b/net/sctp/ulpqueue.c
index 575e556aeb3e..e1d144275f97 100644
--- a/net/sctp/ulpqueue.c
+++ b/net/sctp/ulpqueue.c
@@ -309,7 +309,7 @@ static struct sctp_ulpevent *sctp_make_reassembled_event(struct sk_buff_head *qu
if (!new)
return NULL; /* try again later */
- new->sk = f_frag->sk;
+ sctp_skb_set_owner_r(new, f_frag->sk);
skb_shinfo(new)->frag_list = pos;
} else
diff --git a/net/sunrpc/pmap_clnt.c b/net/sunrpc/pmap_clnt.c
index 919d5ba7ca0a..e52afab413de 100644
--- a/net/sunrpc/pmap_clnt.c
+++ b/net/sunrpc/pmap_clnt.c
@@ -101,11 +101,13 @@ void rpc_getport(struct rpc_task *task)
/* Autobind on cloned rpc clients is discouraged */
BUG_ON(clnt->cl_parent != clnt);
- if (xprt_test_and_set_binding(xprt)) {
- task->tk_status = -EACCES; /* tell caller to check again */
- rpc_sleep_on(&xprt->binding, task, NULL, NULL);
- return;
- }
+ /* Put self on queue before sending rpcbind request, in case
+ * pmap_getport_done completes before we return from rpc_run_task */
+ rpc_sleep_on(&xprt->binding, task, NULL, NULL);
+
+ status = -EACCES; /* tell caller to check again */
+ if (xprt_test_and_set_binding(xprt))
+ goto bailout_nofree;
/* Someone else may have bound if we slept */
status = 0;
@@ -134,8 +136,6 @@ void rpc_getport(struct rpc_task *task)
goto bailout;
rpc_release_task(child);
- rpc_sleep_on(&xprt->binding, task, NULL, NULL);
-
task->tk_xprt->stat.bind_count++;
return;
diff --git a/net/sunrpc/svc.c b/net/sunrpc/svc.c
index 2807fa0eab40..eb44ec929ca1 100644
--- a/net/sunrpc/svc.c
+++ b/net/sunrpc/svc.c
@@ -828,6 +828,11 @@ svc_process(struct svc_rqst *rqstp)
*statp = procp->pc_func(rqstp, rqstp->rq_argp, rqstp->rq_resp);
/* Encode reply */
+ if (*statp == rpc_drop_reply) {
+ if (procp->pc_release)
+ procp->pc_release(rqstp, NULL, rqstp->rq_resp);
+ goto dropit;
+ }
if (*statp == rpc_success && (xdr = procp->pc_encode)
&& !xdr(rqstp, resv->iov_base+resv->iov_len, rqstp->rq_resp)) {
dprintk("svc: failed to encode reply\n");
diff --git a/net/sunrpc/svcauth.c b/net/sunrpc/svcauth.c
index 8f2320aded5c..ee9bb1522d5e 100644
--- a/net/sunrpc/svcauth.c
+++ b/net/sunrpc/svcauth.c
@@ -126,6 +126,7 @@ void auth_domain_put(struct auth_domain *dom)
if (atomic_dec_and_lock(&dom->ref.refcount, &auth_domain_lock)) {
hlist_del(&dom->hash);
dom->flavour->domain_release(dom);
+ spin_unlock(&auth_domain_lock);
}
}
@@ -147,10 +148,8 @@ auth_domain_lookup(char *name, struct auth_domain *new)
return hp;
}
}
- if (new) {
+ if (new)
hlist_add_head(&new->hash, head);
- kref_get(&new->ref);
- }
spin_unlock(&auth_domain_lock);
return new;
}
diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c
index 61e307cca13d..64ca1f61dd94 100644
--- a/net/sunrpc/svcsock.c
+++ b/net/sunrpc/svcsock.c
@@ -299,9 +299,15 @@ void svc_reserve(struct svc_rqst *rqstp, int space)
static inline void
svc_sock_put(struct svc_sock *svsk)
{
- if (atomic_dec_and_test(&svsk->sk_inuse) && test_bit(SK_DEAD, &svsk->sk_flags)) {
+ if (atomic_dec_and_test(&svsk->sk_inuse) &&
+ test_bit(SK_DEAD, &svsk->sk_flags)) {
dprintk("svc: releasing dead socket\n");
- sock_release(svsk->sk_sock);
+ if (svsk->sk_sock->file)
+ sockfd_put(svsk->sk_sock);
+ else
+ sock_release(svsk->sk_sock);
+ if (svsk->sk_info_authunix != NULL)
+ svcauth_unix_info_release(svsk->sk_info_authunix);
kfree(svsk);
}
}
@@ -973,7 +979,7 @@ svc_tcp_recvfrom(struct svc_rqst *rqstp)
return 0;
}
- if (test_bit(SK_CONN, &svsk->sk_flags)) {
+ if (svsk->sk_sk->sk_state == TCP_LISTEN) {
svc_tcp_accept(svsk);
svc_sock_received(svsk);
return 0;
@@ -1604,20 +1610,13 @@ svc_delete_socket(struct svc_sock *svsk)
if (test_bit(SK_TEMP, &svsk->sk_flags))
serv->sv_tmpcnt--;
- if (!atomic_read(&svsk->sk_inuse)) {
- spin_unlock_bh(&serv->sv_lock);
- if (svsk->sk_sock->file)
- sockfd_put(svsk->sk_sock);
- else
- sock_release(svsk->sk_sock);
- if (svsk->sk_info_authunix != NULL)
- svcauth_unix_info_release(svsk->sk_info_authunix);
- kfree(svsk);
- } else {
- spin_unlock_bh(&serv->sv_lock);
- dprintk(KERN_NOTICE "svc: server socket destroy delayed\n");
- /* svsk->sk_server = NULL; */
- }
+ /* This atomic_inc should be needed - svc_delete_socket
+ * should have the semantic of dropping a reference.
+ * But it doesn't yet....
+ */
+ atomic_inc(&svsk->sk_inuse);
+ spin_unlock_bh(&serv->sv_lock);
+ svc_sock_put(svsk);
}
/*
diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c
index 28100e019225..757fc91ef25d 100644
--- a/net/sunrpc/xprtsock.c
+++ b/net/sunrpc/xprtsock.c
@@ -1366,7 +1366,7 @@ int xs_setup_udp(struct rpc_xprt *xprt, struct rpc_timeout *to)
if (xprt->slot == NULL)
return -ENOMEM;
- if (ntohs(addr->sin_port != 0))
+ if (ntohs(addr->sin_port) != 0)
xprt_set_bound(xprt);
xprt->port = xs_get_random_port();
diff --git a/net/tipc/bearer.c b/net/tipc/bearer.c
index 75a5968c2139..39744a33bd36 100644
--- a/net/tipc/bearer.c
+++ b/net/tipc/bearer.c
@@ -2,7 +2,7 @@
* net/tipc/bearer.c: TIPC bearer code
*
* Copyright (c) 1996-2006, Ericsson AB
- * Copyright (c) 2004-2005, Wind River Systems
+ * Copyright (c) 2004-2006, Wind River Systems
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -191,14 +191,14 @@ void tipc_media_addr_printf(struct print_buf *pb, struct tipc_media_addr *a)
if ((i < media_count) && (m_ptr->addr2str != NULL)) {
char addr_str[MAX_ADDR_STR];
- tipc_printf(pb, "%s(%s) ", m_ptr->name,
+ tipc_printf(pb, "%s(%s)", m_ptr->name,
m_ptr->addr2str(a, addr_str, sizeof(addr_str)));
} else {
unchar *addr = (unchar *)&a->dev_addr;
- tipc_printf(pb, "UNKNOWN(%u):", media_type);
+ tipc_printf(pb, "UNKNOWN(%u)", media_type);
for (i = 0; i < (sizeof(*a) - sizeof(a->type)); i++) {
- tipc_printf(pb, "%02x ", addr[i]);
+ tipc_printf(pb, "-%02x", addr[i]);
}
}
}
diff --git a/net/tipc/config.c b/net/tipc/config.c
index 285e1bc2d880..ed1351ed05e1 100644
--- a/net/tipc/config.c
+++ b/net/tipc/config.c
@@ -2,7 +2,7 @@
* net/tipc/config.c: TIPC configuration management code
*
* Copyright (c) 2002-2006, Ericsson AB
- * Copyright (c) 2004-2005, Wind River Systems
+ * Copyright (c) 2004-2006, Wind River Systems
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -613,7 +613,8 @@ struct sk_buff *tipc_cfg_do_cmd(u32 orig_node, u16 cmd, const void *request_area
rep_tlv_buf = tipc_cfg_reply_unsigned(tipc_net_id);
break;
default:
- rep_tlv_buf = NULL;
+ rep_tlv_buf = tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED
+ " (unknown command)");
break;
}
diff --git a/net/tipc/core.c b/net/tipc/core.c
index 0539a8362858..6f5b7ee31180 100644
--- a/net/tipc/core.c
+++ b/net/tipc/core.c
@@ -57,7 +57,7 @@ void tipc_socket_stop(void);
int tipc_netlink_start(void);
void tipc_netlink_stop(void);
-#define TIPC_MOD_VER "1.6.1"
+#define TIPC_MOD_VER "1.6.2"
#ifndef CONFIG_TIPC_ZONES
#define CONFIG_TIPC_ZONES 3
@@ -90,7 +90,7 @@ int tipc_random;
atomic_t tipc_user_count = ATOMIC_INIT(0);
const char tipc_alphabet[] =
- "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_";
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_.";
/* configurable TIPC parameters */
diff --git a/net/tipc/core.h b/net/tipc/core.h
index 762aac2572be..4638947c2326 100644
--- a/net/tipc/core.h
+++ b/net/tipc/core.h
@@ -65,7 +65,7 @@
#define assert(i) BUG_ON(!(i))
struct tipc_msg;
-extern struct print_buf *TIPC_CONS, *TIPC_LOG;
+extern struct print_buf *TIPC_NULL, *TIPC_CONS, *TIPC_LOG;
extern struct print_buf *TIPC_TEE(struct print_buf *, struct print_buf *);
void tipc_msg_print(struct print_buf*,struct tipc_msg *,const char*);
void tipc_printf(struct print_buf *, const char *fmt, ...);
@@ -83,9 +83,9 @@ void tipc_dump(struct print_buf*,const char *fmt, ...);
#define warn(fmt, arg...) tipc_printf(TIPC_OUTPUT, KERN_WARNING "TIPC: " fmt, ## arg)
#define info(fmt, arg...) tipc_printf(TIPC_OUTPUT, KERN_NOTICE "TIPC: " fmt, ## arg)
-#define dbg(fmt, arg...) do {if (DBG_OUTPUT) tipc_printf(DBG_OUTPUT, fmt, ## arg);} while(0)
-#define msg_dbg(msg, txt) do {if (DBG_OUTPUT) tipc_msg_print(DBG_OUTPUT, msg, txt);} while(0)
-#define dump(fmt, arg...) do {if (DBG_OUTPUT) tipc_dump(DBG_OUTPUT, fmt, ##arg);} while(0)
+#define dbg(fmt, arg...) do {if (DBG_OUTPUT != TIPC_NULL) tipc_printf(DBG_OUTPUT, fmt, ## arg);} while(0)
+#define msg_dbg(msg, txt) do {if (DBG_OUTPUT != TIPC_NULL) tipc_msg_print(DBG_OUTPUT, msg, txt);} while(0)
+#define dump(fmt, arg...) do {if (DBG_OUTPUT != TIPC_NULL) tipc_dump(DBG_OUTPUT, fmt, ##arg);} while(0)
/*
@@ -94,11 +94,11 @@ void tipc_dump(struct print_buf*,const char *fmt, ...);
* here, or on a per .c file basis, by redefining these symbols. The following
* print buffer options are available:
*
- * NULL : Output to null print buffer (i.e. print nowhere)
- * TIPC_CONS : Output to system console
- * TIPC_LOG : Output to TIPC log buffer
- * &buf : Output to user-defined buffer (struct print_buf *)
- * TIPC_TEE(&buf_a,&buf_b) : Output to two print buffers (eg. TIPC_TEE(TIPC_CONS,TIPC_LOG) )
+ * TIPC_NULL : null buffer (i.e. print nowhere)
+ * TIPC_CONS : system console
+ * TIPC_LOG : TIPC log buffer
+ * &buf : user-defined buffer (struct print_buf *)
+ * TIPC_TEE(&buf_a,&buf_b) : list of buffers (eg. TIPC_TEE(TIPC_CONS,TIPC_LOG))
*/
#ifndef TIPC_OUTPUT
@@ -106,7 +106,7 @@ void tipc_dump(struct print_buf*,const char *fmt, ...);
#endif
#ifndef DBG_OUTPUT
-#define DBG_OUTPUT NULL
+#define DBG_OUTPUT TIPC_NULL
#endif
#else
@@ -136,7 +136,7 @@ void tipc_dump(struct print_buf*,const char *fmt, ...);
#define TIPC_OUTPUT TIPC_CONS
#undef DBG_OUTPUT
-#define DBG_OUTPUT NULL
+#define DBG_OUTPUT TIPC_NULL
#endif
@@ -275,11 +275,15 @@ static inline void k_term_timer(struct timer_list *timer)
/*
* TIPC message buffer code
*
- * TIPC message buffer headroom leaves room for 14 byte Ethernet header,
+ * TIPC message buffer headroom reserves space for a link-level header
+ * (in case the message is sent off-node),
* while ensuring TIPC header is word aligned for quicker access
+ *
+ * The largest header currently supported is 18 bytes, which is used when
+ * the standard 14 byte Ethernet header has 4 added bytes for VLAN info
*/
-#define BUF_HEADROOM 16u
+#define BUF_HEADROOM 20u
struct tipc_skb_cb {
void *handle;
diff --git a/net/tipc/dbg.c b/net/tipc/dbg.c
index 55130655e1ed..d8af4c28695d 100644
--- a/net/tipc/dbg.c
+++ b/net/tipc/dbg.c
@@ -1,8 +1,8 @@
/*
- * net/tipc/dbg.c: TIPC print buffer routines for debuggign
+ * net/tipc/dbg.c: TIPC print buffer routines for debugging
*
* Copyright (c) 1996-2006, Ericsson AB
- * Copyright (c) 2005, Wind River Systems
+ * Copyright (c) 2005-2006, Wind River Systems
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -38,11 +38,12 @@
#include "config.h"
#include "dbg.h"
-#define MAX_STRING 512
-
-static char print_string[MAX_STRING];
+static char print_string[TIPC_PB_MAX_STR];
static DEFINE_SPINLOCK(print_lock);
+static struct print_buf null_buf = { NULL, 0, NULL, NULL };
+struct print_buf *TIPC_NULL = &null_buf;
+
static struct print_buf cons_buf = { NULL, 0, NULL, NULL };
struct print_buf *TIPC_CONS = &cons_buf;
@@ -62,68 +63,83 @@ struct print_buf *TIPC_LOG = &log_buf;
/*
* Locking policy when using print buffers.
*
- * 1) Routines of the form printbuf_XXX() rely on the caller to prevent
- * simultaneous use of the print buffer(s) being manipulated.
- * 2) tipc_printf() uses 'print_lock' to prevent simultaneous use of
- * 'print_string' and to protect its print buffer(s).
- * 3) TIPC_TEE() uses 'print_lock' to protect its print buffer(s).
- * 4) Routines of the form log_XXX() uses 'print_lock' to protect TIPC_LOG.
+ * The following routines use 'print_lock' for protection:
+ * 1) tipc_printf() - to protect its print buffer(s) and 'print_string'
+ * 2) TIPC_TEE() - to protect its print buffer(s)
+ * 3) tipc_dump() - to protect its print buffer(s) and 'print_string'
+ * 4) tipc_log_XXX() - to protect TIPC_LOG
+ *
+ * All routines of the form tipc_printbuf_XXX() rely on the caller to prevent
+ * simultaneous use of the print buffer(s) being manipulated.
*/
/**
* tipc_printbuf_init - initialize print buffer to empty
+ * @pb: pointer to print buffer structure
+ * @raw: pointer to character array used by print buffer
+ * @size: size of character array
+ *
+ * Makes the print buffer a null device that discards anything written to it
+ * if the character array is too small (or absent).
*/
-void tipc_printbuf_init(struct print_buf *pb, char *raw, u32 sz)
+void tipc_printbuf_init(struct print_buf *pb, char *raw, u32 size)
{
- if (!pb || !raw || (sz < (MAX_STRING + 1)))
- return;
-
- pb->crs = pb->buf = raw;
- pb->size = sz;
+ pb->buf = raw;
+ pb->crs = raw;
+ pb->size = size;
pb->next = NULL;
- pb->buf[0] = 0;
- pb->buf[sz-1] = ~0;
+
+ if (size < TIPC_PB_MIN_SIZE) {
+ pb->buf = NULL;
+ } else if (raw) {
+ pb->buf[0] = 0;
+ pb->buf[size-1] = ~0;
+ }
}
/**
* tipc_printbuf_reset - reinitialize print buffer to empty state
+ * @pb: pointer to print buffer structure
*/
void tipc_printbuf_reset(struct print_buf *pb)
{
- if (pb && pb->buf)
- tipc_printbuf_init(pb, pb->buf, pb->size);
+ tipc_printbuf_init(pb, pb->buf, pb->size);
}
/**
* tipc_printbuf_empty - test if print buffer is in empty state
+ * @pb: pointer to print buffer structure
+ *
+ * Returns non-zero if print buffer is empty.
*/
int tipc_printbuf_empty(struct print_buf *pb)
{
- return (!pb || !pb->buf || (pb->crs == pb->buf));
+ return (!pb->buf || (pb->crs == pb->buf));
}
/**
* tipc_printbuf_validate - check for print buffer overflow
+ * @pb: pointer to print buffer structure
*
* Verifies that a print buffer has captured all data written to it.
* If data has been lost, linearize buffer and prepend an error message
*
- * Returns length of print buffer data string (including trailing NULL)
+ * Returns length of print buffer data string (including trailing NUL)
*/
int tipc_printbuf_validate(struct print_buf *pb)
{
- char *err = " *** PRINT BUFFER WRAPPED AROUND ***\n";
+ char *err = "\n\n*** PRINT BUFFER OVERFLOW ***\n\n";
char *cp_buf;
struct print_buf cb;
- if (!pb || !pb->buf)
+ if (!pb->buf)
return 0;
- if (pb->buf[pb->size - 1] == '\0') {
+ if (pb->buf[pb->size - 1] == 0) {
cp_buf = kmalloc(pb->size, GFP_ATOMIC);
if (cp_buf != NULL){
tipc_printbuf_init(&cb, cp_buf, pb->size);
@@ -141,6 +157,8 @@ int tipc_printbuf_validate(struct print_buf *pb)
/**
* tipc_printbuf_move - move print buffer contents to another print buffer
+ * @pb_to: pointer to destination print buffer structure
+ * @pb_from: pointer to source print buffer structure
*
* Current contents of destination print buffer (if any) are discarded.
* Source print buffer becomes empty if a successful move occurs.
@@ -152,21 +170,22 @@ void tipc_printbuf_move(struct print_buf *pb_to, struct print_buf *pb_from)
/* Handle the cases where contents can't be moved */
- if (!pb_to || !pb_to->buf)
+ if (!pb_to->buf)
return;
- if (!pb_from || !pb_from->buf) {
+ if (!pb_from->buf) {
tipc_printbuf_reset(pb_to);
return;
}
if (pb_to->size < pb_from->size) {
tipc_printbuf_reset(pb_to);
- tipc_printf(pb_to, "*** PRINT BUFFER OVERFLOW ***");
+ tipc_printf(pb_to, "*** PRINT BUFFER MOVE ERROR ***");
return;
}
/* Copy data from char after cursor to end (if used) */
+
len = pb_from->buf + pb_from->size - pb_from->crs - 2;
if ((pb_from->buf[pb_from->size-1] == 0) && (len > 0)) {
strcpy(pb_to->buf, pb_from->crs + 1);
@@ -175,6 +194,7 @@ void tipc_printbuf_move(struct print_buf *pb_to, struct print_buf *pb_from)
pb_to->crs = pb_to->buf;
/* Copy data from start to cursor (always) */
+
len = pb_from->crs - pb_from->buf;
strcpy(pb_to->crs, pb_from->buf);
pb_to->crs += len;
@@ -184,6 +204,8 @@ void tipc_printbuf_move(struct print_buf *pb_to, struct print_buf *pb_from)
/**
* tipc_printf - append formatted output to print buffer chain
+ * @pb: pointer to chain of print buffers (may be NULL)
+ * @fmt: formatted info to be printed
*/
void tipc_printf(struct print_buf *pb, const char *fmt, ...)
@@ -195,8 +217,8 @@ void tipc_printf(struct print_buf *pb, const char *fmt, ...)
spin_lock_bh(&print_lock);
FORMAT(print_string, chars_to_add, fmt);
- if (chars_to_add >= MAX_STRING)
- strcpy(print_string, "*** STRING TOO LONG ***");
+ if (chars_to_add >= TIPC_PB_MAX_STR)
+ strcpy(print_string, "*** PRINT BUFFER STRING TOO LONG ***");
while (pb) {
if (pb == TIPC_CONS)
@@ -206,6 +228,10 @@ void tipc_printf(struct print_buf *pb, const char *fmt, ...)
if (chars_to_add <= chars_left) {
strcpy(pb->crs, print_string);
pb->crs += chars_to_add;
+ } else if (chars_to_add >= (pb->size - 1)) {
+ strcpy(pb->buf, print_string + chars_to_add + 1
+ - pb->size);
+ pb->crs = pb->buf + pb->size - 1;
} else {
strcpy(pb->buf, print_string + chars_left);
save_char = print_string[chars_left];
@@ -224,6 +250,10 @@ void tipc_printf(struct print_buf *pb, const char *fmt, ...)
/**
* TIPC_TEE - perform next output operation on both print buffers
+ * @b0: pointer to chain of print buffers (may be NULL)
+ * @b1: pointer to print buffer to add to chain
+ *
+ * Returns pointer to print buffer chain.
*/
struct print_buf *TIPC_TEE(struct print_buf *b0, struct print_buf *b1)
@@ -232,8 +262,6 @@ struct print_buf *TIPC_TEE(struct print_buf *b0, struct print_buf *b1)
if (!b0 || (b0 == b1))
return b1;
- if (!b1)
- return b0;
spin_lock_bh(&print_lock);
while (pb->next) {
@@ -256,7 +284,7 @@ static void print_to_console(char *crs, int len)
int rest = len;
while (rest > 0) {
- int sz = rest < MAX_STRING ? rest : MAX_STRING;
+ int sz = rest < TIPC_PB_MAX_STR ? rest : TIPC_PB_MAX_STR;
char c = crs[sz];
crs[sz] = 0;
@@ -275,36 +303,48 @@ static void printbuf_dump(struct print_buf *pb)
{
int len;
+ if (!pb->buf) {
+ printk("*** PRINT BUFFER NOT ALLOCATED ***");
+ return;
+ }
+
/* Dump print buffer from char after cursor to end (if used) */
+
len = pb->buf + pb->size - pb->crs - 2;
if ((pb->buf[pb->size - 1] == 0) && (len > 0))
print_to_console(pb->crs + 1, len);
/* Dump print buffer from start to cursor (always) */
+
len = pb->crs - pb->buf;
print_to_console(pb->buf, len);
}
/**
* tipc_dump - dump non-console print buffer(s) to console
+ * @pb: pointer to chain of print buffers
*/
void tipc_dump(struct print_buf *pb, const char *fmt, ...)
{
+ struct print_buf *pb_next;
int len;
spin_lock_bh(&print_lock);
- FORMAT(TIPC_CONS->buf, len, fmt);
- printk(TIPC_CONS->buf);
+ FORMAT(print_string, len, fmt);
+ printk(print_string);
for (; pb; pb = pb->next) {
- if (pb == TIPC_CONS)
- continue;
- printk("\n---- Start of dump,%s log ----\n\n",
- (pb == TIPC_LOG) ? "global" : "local");
- printbuf_dump(pb);
- tipc_printbuf_reset(pb);
- printk("\n-------- End of dump --------\n");
+ if (pb != TIPC_CONS) {
+ printk("\n---- Start of %s log dump ----\n\n",
+ (pb == TIPC_LOG) ? "global" : "local");
+ printbuf_dump(pb);
+ tipc_printbuf_reset(pb);
+ printk("\n---- End of dump ----\n");
+ }
+ pb_next = pb->next;
+ pb->next = NULL;
+ pb = pb_next;
}
spin_unlock_bh(&print_lock);
}
@@ -324,7 +364,8 @@ void tipc_log_stop(void)
}
/**
- * tipc_log_reinit - set TIPC log print buffer to specified size
+ * tipc_log_reinit - (re)initialize TIPC log print buffer
+ * @log_size: print buffer size to use
*/
void tipc_log_reinit(int log_size)
@@ -332,10 +373,11 @@ void tipc_log_reinit(int log_size)
tipc_log_stop();
if (log_size) {
- if (log_size <= MAX_STRING)
- log_size = MAX_STRING + 1;
+ if (log_size < TIPC_PB_MIN_SIZE)
+ log_size = TIPC_PB_MIN_SIZE;
spin_lock_bh(&print_lock);
- tipc_printbuf_init(TIPC_LOG, kmalloc(log_size, GFP_ATOMIC), log_size);
+ tipc_printbuf_init(TIPC_LOG, kmalloc(log_size, GFP_ATOMIC),
+ log_size);
spin_unlock_bh(&print_lock);
}
}
diff --git a/net/tipc/dbg.h b/net/tipc/dbg.h
index 227f050d2a52..467c0bc78a79 100644
--- a/net/tipc/dbg.h
+++ b/net/tipc/dbg.h
@@ -2,7 +2,7 @@
* net/tipc/dbg.h: Include file for TIPC print buffer routines
*
* Copyright (c) 1997-2006, Ericsson AB
- * Copyright (c) 2005, Wind River Systems
+ * Copyright (c) 2005-2006, Wind River Systems
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -37,6 +37,14 @@
#ifndef _TIPC_DBG_H
#define _TIPC_DBG_H
+/**
+ * struct print_buf - TIPC print buffer structure
+ * @buf: pointer to character array containing print buffer contents
+ * @size: size of character array
+ * @crs: pointer to first unused space in character array (i.e. final NUL)
+ * @next: used to link print buffers when printing to more than one at a time
+ */
+
struct print_buf {
char *buf;
u32 size;
@@ -44,7 +52,10 @@ struct print_buf {
struct print_buf *next;
};
-void tipc_printbuf_init(struct print_buf *pb, char *buf, u32 sz);
+#define TIPC_PB_MIN_SIZE 64 /* minimum size for a print buffer's array */
+#define TIPC_PB_MAX_STR 512 /* max printable string (with trailing NUL) */
+
+void tipc_printbuf_init(struct print_buf *pb, char *buf, u32 size);
void tipc_printbuf_reset(struct print_buf *pb);
int tipc_printbuf_empty(struct print_buf *pb);
int tipc_printbuf_validate(struct print_buf *pb);
diff --git a/net/tipc/discover.c b/net/tipc/discover.c
index ee94de92ae99..3b0cd12f37da 100644
--- a/net/tipc/discover.c
+++ b/net/tipc/discover.c
@@ -132,6 +132,28 @@ static struct sk_buff *tipc_disc_init_msg(u32 type,
}
/**
+ * disc_dupl_alert - issue node address duplication alert
+ * @b_ptr: pointer to bearer detecting duplication
+ * @node_addr: duplicated node address
+ * @media_addr: media address advertised by duplicated node
+ */
+
+static void disc_dupl_alert(struct bearer *b_ptr, u32 node_addr,
+ struct tipc_media_addr *media_addr)
+{
+ char node_addr_str[16];
+ char media_addr_str[64];
+ struct print_buf pb;
+
+ addr_string_fill(node_addr_str, node_addr);
+ tipc_printbuf_init(&pb, media_addr_str, sizeof(media_addr_str));
+ tipc_media_addr_printf(&pb, media_addr);
+ tipc_printbuf_validate(&pb);
+ warn("Duplicate %s using %s seen on <%s>\n",
+ node_addr_str, media_addr_str, b_ptr->publ.name);
+}
+
+/**
* tipc_disc_recv_msg - handle incoming link setup message (request or response)
* @buf: buffer containing message
*/
@@ -157,8 +179,11 @@ void tipc_disc_recv_msg(struct sk_buff *buf)
return;
if (!tipc_addr_node_valid(orig))
return;
- if (orig == tipc_own_addr)
+ if (orig == tipc_own_addr) {
+ if (memcmp(&media_addr, &b_ptr->publ.addr, sizeof(media_addr)))
+ disc_dupl_alert(b_ptr, tipc_own_addr, &media_addr);
return;
+ }
if (!in_scope(dest, tipc_own_addr))
return;
if (is_slave(tipc_own_addr) && is_slave(orig))
@@ -170,7 +195,8 @@ void tipc_disc_recv_msg(struct sk_buff *buf)
struct sk_buff *rbuf;
struct tipc_media_addr *addr;
struct node *n_ptr = tipc_node_find(orig);
- int link_up;
+ int link_fully_up;
+
dbg(" in own cluster\n");
if (n_ptr == NULL) {
n_ptr = tipc_node_create(orig);
@@ -190,14 +216,19 @@ void tipc_disc_recv_msg(struct sk_buff *buf)
}
addr = &link->media_addr;
if (memcmp(addr, &media_addr, sizeof(*addr))) {
+ if (tipc_link_is_up(link) || (!link->started)) {
+ disc_dupl_alert(b_ptr, orig, &media_addr);
+ spin_unlock_bh(&n_ptr->lock);
+ return;
+ }
warn("Resetting link <%s>, peer interface address changed\n",
link->name);
memcpy(addr, &media_addr, sizeof(*addr));
tipc_link_reset(link);
}
- link_up = tipc_link_is_up(link);
+ link_fully_up = (link->state == WORKING_WORKING);
spin_unlock_bh(&n_ptr->lock);
- if ((type == DSC_RESP_MSG) || link_up)
+ if ((type == DSC_RESP_MSG) || link_fully_up)
return;
rbuf = tipc_disc_init_msg(DSC_RESP_MSG, 1, orig, b_ptr);
if (rbuf != NULL) {
diff --git a/net/tipc/link.c b/net/tipc/link.c
index 53bc8cb5adbc..1bb983c8130b 100644
--- a/net/tipc/link.c
+++ b/net/tipc/link.c
@@ -132,7 +132,7 @@ static void link_print(struct link *l_ptr, struct print_buf *buf,
* allow the output from multiple links to be intermixed. For this reason
* routines of the form "dbg_link_XXX()" have been created that will capture
* debug info into a link's personal print buffer, which can then be dumped
- * into the TIPC system log (LOG) upon request.
+ * into the TIPC system log (TIPC_LOG) upon request.
*
* To enable per-link debugging, use LINK_LOG_BUF_SIZE to specify the size
* of the print buffer used by each link. If LINK_LOG_BUF_SIZE is set to 0,
@@ -141,7 +141,7 @@ static void link_print(struct link *l_ptr, struct print_buf *buf,
* when there is only a single link in the system being debugged.
*
* Notes:
- * - When enabled, LINK_LOG_BUF_SIZE should be set to at least 1000 (bytes)
+ * - When enabled, LINK_LOG_BUF_SIZE should be set to at least TIPC_PB_MIN_SIZE
* - "l_ptr" must be valid when using dbg_link_XXX() macros
*/
@@ -159,13 +159,13 @@ static void link_print(struct link *l_ptr, struct print_buf *buf,
static void dbg_print_link(struct link *l_ptr, const char *str)
{
- if (DBG_OUTPUT)
+ if (DBG_OUTPUT != TIPC_NULL)
link_print(l_ptr, DBG_OUTPUT, str);
}
static void dbg_print_buf_chain(struct sk_buff *root_buf)
{
- if (DBG_OUTPUT) {
+ if (DBG_OUTPUT != TIPC_NULL) {
struct sk_buff *buf = root_buf;
while (buf) {
diff --git a/net/tipc/name_distr.c b/net/tipc/name_distr.c
index f0b063bcc2a9..03bd659c43ca 100644
--- a/net/tipc/name_distr.c
+++ b/net/tipc/name_distr.c
@@ -122,7 +122,7 @@ void tipc_named_publish(struct publication *publ)
struct sk_buff *buf;
struct distr_item *item;
- list_add(&publ->local_list, &publ_root);
+ list_add_tail(&publ->local_list, &publ_root);
publ_cnt++;
buf = named_prepare_buf(PUBLICATION, ITEM_SIZE, 0);
diff --git a/net/tipc/node.c b/net/tipc/node.c
index fc6d09630ccd..886bda5e88db 100644
--- a/net/tipc/node.c
+++ b/net/tipc/node.c
@@ -648,7 +648,7 @@ struct sk_buff *tipc_node_get_links(const void *req_tlv_area, int req_tlv_space)
return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE
" (network address)");
- if (!tipc_nodes)
+ if (tipc_mode != TIPC_NET_MODE)
return tipc_cfg_reply_none();
/* Get space for all unicast links + multicast link */
diff --git a/net/tipc/port.c b/net/tipc/port.c
index b9c8c6b9e94f..b7f3199523ca 100644
--- a/net/tipc/port.c
+++ b/net/tipc/port.c
@@ -505,8 +505,13 @@ static void port_timeout(unsigned long ref)
struct port *p_ptr = tipc_port_lock(ref);
struct sk_buff *buf = NULL;
- if (!p_ptr || !p_ptr->publ.connected)
+ if (!p_ptr)
+ return;
+
+ if (!p_ptr->publ.connected) {
+ tipc_port_unlock(p_ptr);
return;
+ }
/* Last probe answered ? */
if (p_ptr->probing_state == PROBING) {
@@ -1131,11 +1136,12 @@ int tipc_publish(u32 ref, unsigned int scope, struct tipc_name_seq const *seq)
int res = -EINVAL;
p_ptr = tipc_port_lock(ref);
+ if (!p_ptr)
+ return -EINVAL;
+
dbg("tipc_publ %u, p_ptr = %x, conn = %x, scope = %x, "
"lower = %u, upper = %u\n",
ref, p_ptr, p_ptr->publ.connected, scope, seq->lower, seq->upper);
- if (!p_ptr)
- return -EINVAL;
if (p_ptr->publ.connected)
goto exit;
if (seq->lower > seq->upper)
diff --git a/net/tipc/socket.c b/net/tipc/socket.c
index acfb852e7c98..2a6a5a6b4c12 100644
--- a/net/tipc/socket.c
+++ b/net/tipc/socket.c
@@ -2,7 +2,7 @@
* net/tipc/socket.c: TIPC socket API
*
* Copyright (c) 2001-2006, Ericsson AB
- * Copyright (c) 2004-2005, Wind River Systems
+ * Copyright (c) 2004-2006, Wind River Systems
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -629,6 +629,9 @@ static int send_stream(struct kiocb *iocb, struct socket *sock,
return -ENOTCONN;
}
+ if (unlikely(m->msg_name))
+ return -EISCONN;
+
/*
* Send each iovec entry using one or more messages
*
@@ -641,6 +644,8 @@ static int send_stream(struct kiocb *iocb, struct socket *sock,
curr_iovlen = m->msg_iovlen;
my_msg.msg_iov = &my_iov;
my_msg.msg_iovlen = 1;
+ my_msg.msg_flags = m->msg_flags;
+ my_msg.msg_name = NULL;
bytes_sent = 0;
while (curr_iovlen--) {
@@ -1203,7 +1208,8 @@ static u32 dispatch(struct tipc_port *tport, struct sk_buff *buf)
atomic_inc(&tipc_queue_size);
skb_queue_tail(&sock->sk->sk_receive_queue, buf);
- wake_up_interruptible(sock->sk->sk_sleep);
+ if (waitqueue_active(sock->sk->sk_sleep))
+ wake_up_interruptible(sock->sk->sk_sleep);
return TIPC_OK;
}
@@ -1218,7 +1224,8 @@ static void wakeupdispatch(struct tipc_port *tport)
{
struct tipc_sock *tsock = (struct tipc_sock *)tport->usr_handle;
- wake_up_interruptible(tsock->sk.sk_sleep);
+ if (waitqueue_active(tsock->sk.sk_sleep))
+ wake_up_interruptible(tsock->sk.sk_sleep);
}
/**
diff --git a/net/tipc/subscr.c b/net/tipc/subscr.c
index c51600ba5f4a..7a918f12a5df 100644
--- a/net/tipc/subscr.c
+++ b/net/tipc/subscr.c
@@ -155,7 +155,7 @@ void tipc_subscr_report_overlap(struct subscription *sub,
sub->seq.upper, found_lower, found_upper);
if (!tipc_subscr_overlap(sub, found_lower, found_upper))
return;
- if (!must && (sub->filter != TIPC_SUB_PORTS))
+ if (!must && !(sub->filter & TIPC_SUB_PORTS))
return;
subscr_send_event(sub, found_lower, found_upper, event, port_ref, node);
}
@@ -176,6 +176,13 @@ static void subscr_timeout(struct subscription *sub)
if (subscriber == NULL)
return;
+ /* Validate timeout (in case subscription is being cancelled) */
+
+ if (sub->timeout == TIPC_WAIT_FOREVER) {
+ tipc_ref_unlock(subscriber_ref);
+ return;
+ }
+
/* Unlink subscription from name table */
tipc_nametbl_unsubscribe(sub);
@@ -199,6 +206,20 @@ static void subscr_timeout(struct subscription *sub)
}
/**
+ * subscr_del - delete a subscription within a subscription list
+ *
+ * Called with subscriber locked.
+ */
+
+static void subscr_del(struct subscription *sub)
+{
+ tipc_nametbl_unsubscribe(sub);
+ list_del(&sub->subscription_list);
+ kfree(sub);
+ atomic_dec(&topsrv.subscription_count);
+}
+
+/**
* subscr_terminate - terminate communication with a subscriber
*
* Called with subscriber locked. Routine must temporarily release this lock
@@ -227,12 +248,9 @@ static void subscr_terminate(struct subscriber *subscriber)
k_cancel_timer(&sub->timer);
k_term_timer(&sub->timer);
}
- tipc_nametbl_unsubscribe(sub);
- list_del(&sub->subscription_list);
- dbg("Term: Removed sub %u,%u,%u from subscriber %x list\n",
+ dbg("Term: Removing sub %u,%u,%u from subscriber %x list\n",
sub->seq.type, sub->seq.lower, sub->seq.upper, subscriber);
- kfree(sub);
- atomic_dec(&topsrv.subscription_count);
+ subscr_del(sub);
}
/* Sever connection to subscriber */
@@ -253,6 +271,49 @@ static void subscr_terminate(struct subscriber *subscriber)
}
/**
+ * subscr_cancel - handle subscription cancellation request
+ *
+ * Called with subscriber locked. Routine must temporarily release this lock
+ * to enable the subscription timeout routine to finish without deadlocking;
+ * the lock is then reclaimed to allow caller to release it upon return.
+ *
+ * Note that fields of 's' use subscriber's endianness!
+ */
+
+static void subscr_cancel(struct tipc_subscr *s,
+ struct subscriber *subscriber)
+{
+ struct subscription *sub;
+ struct subscription *sub_temp;
+ int found = 0;
+
+ /* Find first matching subscription, exit if not found */
+
+ list_for_each_entry_safe(sub, sub_temp, &subscriber->subscription_list,
+ subscription_list) {
+ if (!memcmp(s, &sub->evt.s, sizeof(struct tipc_subscr))) {
+ found = 1;
+ break;
+ }
+ }
+ if (!found)
+ return;
+
+ /* Cancel subscription timer (if used), then delete subscription */
+
+ if (sub->timeout != TIPC_WAIT_FOREVER) {
+ sub->timeout = TIPC_WAIT_FOREVER;
+ spin_unlock_bh(subscriber->lock);
+ k_cancel_timer(&sub->timer);
+ k_term_timer(&sub->timer);
+ spin_lock_bh(subscriber->lock);
+ }
+ dbg("Cancel: removing sub %u,%u,%u from subscriber %x list\n",
+ sub->seq.type, sub->seq.lower, sub->seq.upper, subscriber);
+ subscr_del(sub);
+}
+
+/**
* subscr_subscribe - create subscription for subscriber
*
* Called with subscriber locked
@@ -263,6 +324,21 @@ static void subscr_subscribe(struct tipc_subscr *s,
{
struct subscription *sub;
+ /* Determine/update subscriber's endianness */
+
+ if (s->filter & (TIPC_SUB_PORTS | TIPC_SUB_SERVICE))
+ subscriber->swap = 0;
+ else
+ subscriber->swap = 1;
+
+ /* Detect & process a subscription cancellation request */
+
+ if (s->filter & htohl(TIPC_SUB_CANCEL, subscriber->swap)) {
+ s->filter &= ~htohl(TIPC_SUB_CANCEL, subscriber->swap);
+ subscr_cancel(s, subscriber);
+ return;
+ }
+
/* Refuse subscription if global limit exceeded */
if (atomic_read(&topsrv.subscription_count) >= tipc_max_subscriptions) {
@@ -281,13 +357,6 @@ static void subscr_subscribe(struct tipc_subscr *s,
return;
}
- /* Determine/update subscriber's endianness */
-
- if ((s->filter == TIPC_SUB_PORTS) || (s->filter == TIPC_SUB_SERVICE))
- subscriber->swap = 0;
- else
- subscriber->swap = 1;
-
/* Initialize subscription object */
memset(sub, 0, sizeof(*sub));
@@ -296,8 +365,8 @@ static void subscr_subscribe(struct tipc_subscr *s,
sub->seq.upper = htohl(s->seq.upper, subscriber->swap);
sub->timeout = htohl(s->timeout, subscriber->swap);
sub->filter = htohl(s->filter, subscriber->swap);
- if ((((sub->filter != TIPC_SUB_PORTS)
- && (sub->filter != TIPC_SUB_SERVICE)))
+ if ((!(sub->filter & TIPC_SUB_PORTS)
+ == !(sub->filter & TIPC_SUB_SERVICE))
|| (sub->seq.lower > sub->seq.upper)) {
warn("Subscription rejected, illegal request\n");
kfree(sub);
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
index 2a7861661f14..7736b23c3f03 100644
--- a/net/xfrm/xfrm_policy.c
+++ b/net/xfrm/xfrm_policy.c
@@ -883,30 +883,32 @@ out:
}
EXPORT_SYMBOL(xfrm_policy_walk);
-/* Find policy to apply to this flow. */
-
+/*
+ * Find policy to apply to this flow.
+ *
+ * Returns 0 if policy found, else an -errno.
+ */
static int xfrm_policy_match(struct xfrm_policy *pol, struct flowi *fl,
u8 type, u16 family, int dir)
{
struct xfrm_selector *sel = &pol->selector;
- int match;
+ int match, ret = -ESRCH;
if (pol->family != family ||
pol->type != type)
- return 0;
+ return ret;
match = xfrm_selector_match(sel, fl, family);
- if (match) {
- if (!security_xfrm_policy_lookup(pol, fl->secid, dir))
- return 1;
- }
+ if (match)
+ ret = security_xfrm_policy_lookup(pol, fl->secid, dir);
- return 0;
+ return ret;
}
static struct xfrm_policy *xfrm_policy_lookup_bytype(u8 type, struct flowi *fl,
u16 family, u8 dir)
{
+ int err;
struct xfrm_policy *pol, *ret;
xfrm_address_t *daddr, *saddr;
struct hlist_node *entry;
@@ -922,7 +924,15 @@ static struct xfrm_policy *xfrm_policy_lookup_bytype(u8 type, struct flowi *fl,
chain = policy_hash_direct(daddr, saddr, family, dir);
ret = NULL;
hlist_for_each_entry(pol, entry, chain, bydst) {
- if (xfrm_policy_match(pol, fl, type, family, dir)) {
+ err = xfrm_policy_match(pol, fl, type, family, dir);
+ if (err) {
+ if (err == -ESRCH)
+ continue;
+ else {
+ ret = ERR_PTR(err);
+ goto fail;
+ }
+ } else {
ret = pol;
priority = ret->priority;
break;
@@ -930,36 +940,53 @@ static struct xfrm_policy *xfrm_policy_lookup_bytype(u8 type, struct flowi *fl,
}
chain = &xfrm_policy_inexact[dir];
hlist_for_each_entry(pol, entry, chain, bydst) {
- if (xfrm_policy_match(pol, fl, type, family, dir) &&
- pol->priority < priority) {
+ err = xfrm_policy_match(pol, fl, type, family, dir);
+ if (err) {
+ if (err == -ESRCH)
+ continue;
+ else {
+ ret = ERR_PTR(err);
+ goto fail;
+ }
+ } else if (pol->priority < priority) {
ret = pol;
break;
}
}
if (ret)
xfrm_pol_hold(ret);
+fail:
read_unlock_bh(&xfrm_policy_lock);
return ret;
}
-static void xfrm_policy_lookup(struct flowi *fl, u16 family, u8 dir,
+static int xfrm_policy_lookup(struct flowi *fl, u16 family, u8 dir,
void **objp, atomic_t **obj_refp)
{
struct xfrm_policy *pol;
+ int err = 0;
#ifdef CONFIG_XFRM_SUB_POLICY
pol = xfrm_policy_lookup_bytype(XFRM_POLICY_TYPE_SUB, fl, family, dir);
- if (pol)
+ if (IS_ERR(pol)) {
+ err = PTR_ERR(pol);
+ pol = NULL;
+ }
+ if (pol || err)
goto end;
#endif
pol = xfrm_policy_lookup_bytype(XFRM_POLICY_TYPE_MAIN, fl, family, dir);
-
+ if (IS_ERR(pol)) {
+ err = PTR_ERR(pol);
+ pol = NULL;
+ }
#ifdef CONFIG_XFRM_SUB_POLICY
end:
#endif
if ((*objp = (void *) pol) != NULL)
*obj_refp = &pol->refcnt;
+ return err;
}
static inline int policy_to_flow_dir(int dir)
@@ -989,12 +1016,16 @@ static struct xfrm_policy *xfrm_sk_policy_lookup(struct sock *sk, int dir, struc
sk->sk_family);
int err = 0;
- if (match)
- err = security_xfrm_policy_lookup(pol, fl->secid, policy_to_flow_dir(dir));
-
- if (match && !err)
- xfrm_pol_hold(pol);
- else
+ if (match) {
+ err = security_xfrm_policy_lookup(pol, fl->secid,
+ policy_to_flow_dir(dir));
+ if (!err)
+ xfrm_pol_hold(pol);
+ else if (err == -ESRCH)
+ pol = NULL;
+ else
+ pol = ERR_PTR(err);
+ } else
pol = NULL;
}
read_unlock_bh(&xfrm_policy_lock);
@@ -1286,8 +1317,11 @@ restart:
pol_dead = 0;
xfrm_nr = 0;
- if (sk && sk->sk_policy[1])
+ if (sk && sk->sk_policy[1]) {
policy = xfrm_sk_policy_lookup(sk, XFRM_POLICY_OUT, fl);
+ if (IS_ERR(policy))
+ return PTR_ERR(policy);
+ }
if (!policy) {
/* To accelerate a bit... */
@@ -1297,6 +1331,8 @@ restart:
policy = flow_cache_lookup(fl, dst_orig->ops->family,
dir, xfrm_policy_lookup);
+ if (IS_ERR(policy))
+ return PTR_ERR(policy);
}
if (!policy)
@@ -1343,6 +1379,10 @@ restart:
fl, family,
XFRM_POLICY_OUT);
if (pols[1]) {
+ if (IS_ERR(pols[1])) {
+ err = PTR_ERR(pols[1]);
+ goto error;
+ }
if (pols[1]->action == XFRM_POLICY_BLOCK) {
err = -EPERM;
goto error;
@@ -1574,13 +1614,19 @@ int __xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb,
}
pol = NULL;
- if (sk && sk->sk_policy[dir])
+ if (sk && sk->sk_policy[dir]) {
pol = xfrm_sk_policy_lookup(sk, dir, &fl);
+ if (IS_ERR(pol))
+ return 0;
+ }
if (!pol)
pol = flow_cache_lookup(&fl, family, fl_dir,
xfrm_policy_lookup);
+ if (IS_ERR(pol))
+ return 0;
+
if (!pol) {
if (skb->sp && secpath_has_nontransport(skb->sp, 0, &xerr_idx)) {
xfrm_secpath_reject(xerr_idx, skb, &fl);
@@ -1599,6 +1645,8 @@ int __xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb,
&fl, family,
XFRM_POLICY_IN);
if (pols[1]) {
+ if (IS_ERR(pols[1]))
+ return 0;
pols[1]->curlft.use_time = (unsigned long)xtime.tv_sec;
npols ++;
}
@@ -1706,7 +1754,7 @@ static struct dst_entry *xfrm_dst_check(struct dst_entry *dst, u32 cookie)
static int stale_bundle(struct dst_entry *dst)
{
- return !xfrm_bundle_ok((struct xfrm_dst *)dst, NULL, AF_UNSPEC, 0);
+ return !xfrm_bundle_ok(NULL, (struct xfrm_dst *)dst, NULL, AF_UNSPEC, 0);
}
void xfrm_dst_ifdown(struct dst_entry *dst, struct net_device *dev)
@@ -1828,7 +1876,8 @@ EXPORT_SYMBOL(xfrm_init_pmtu);
* still valid.
*/
-int xfrm_bundle_ok(struct xfrm_dst *first, struct flowi *fl, int family, int strict)
+int xfrm_bundle_ok(struct xfrm_policy *pol, struct xfrm_dst *first,
+ struct flowi *fl, int family, int strict)
{
struct dst_entry *dst = &first->u.dst;
struct xfrm_dst *last;
@@ -1845,7 +1894,7 @@ int xfrm_bundle_ok(struct xfrm_dst *first, struct flowi *fl, int family, int str
if (fl && !xfrm_selector_match(&dst->xfrm->sel, fl, family))
return 0;
- if (fl && !security_xfrm_flow_state_match(fl, dst->xfrm))
+ if (fl && !security_xfrm_flow_state_match(fl, dst->xfrm, pol))
return 0;
if (dst->xfrm->km.state != XFRM_STATE_VALID)
return 0;
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c
index 39b8bf3a9ded..899de9ed22a6 100644
--- a/net/xfrm/xfrm_state.c
+++ b/net/xfrm/xfrm_state.c
@@ -505,6 +505,14 @@ __xfrm_state_locate(struct xfrm_state *x, int use_spi, int family)
x->id.proto, family);
}
+static void xfrm_hash_grow_check(int have_hash_collision)
+{
+ if (have_hash_collision &&
+ (xfrm_state_hmask + 1) < xfrm_state_hashmax &&
+ xfrm_state_num > xfrm_state_hmask)
+ schedule_work(&xfrm_hash_work);
+}
+
struct xfrm_state *
xfrm_state_find(xfrm_address_t *daddr, xfrm_address_t *saddr,
struct flowi *fl, struct xfrm_tmpl *tmpl,
@@ -598,6 +606,8 @@ xfrm_state_find(xfrm_address_t *daddr, xfrm_address_t *saddr,
x->lft.hard_add_expires_seconds = XFRM_ACQ_EXPIRES;
x->timer.expires = jiffies + XFRM_ACQ_EXPIRES*HZ;
add_timer(&x->timer);
+ xfrm_state_num++;
+ xfrm_hash_grow_check(x->bydst.next != NULL);
} else {
x->km.state = XFRM_STATE_DEAD;
xfrm_state_put(x);
@@ -642,10 +652,7 @@ static void __xfrm_state_insert(struct xfrm_state *x)
xfrm_state_num++;
- if (x->bydst.next != NULL &&
- (xfrm_state_hmask + 1) < xfrm_state_hashmax &&
- xfrm_state_num > xfrm_state_hmask)
- schedule_work(&xfrm_hash_work);
+ xfrm_hash_grow_check(x->bydst.next != NULL);
}
/* xfrm_state_lock is held */
@@ -753,6 +760,10 @@ static struct xfrm_state *__find_acq_core(unsigned short family, u8 mode, u32 re
h = xfrm_src_hash(daddr, saddr, family);
hlist_add_head(&x->bysrc, xfrm_state_bysrc+h);
wake_up(&km_waitq);
+
+ xfrm_state_num++;
+
+ xfrm_hash_grow_check(x->bydst.next != NULL);
}
return x;
diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c
index d54b3a70d5df..c4cde57d9216 100644
--- a/net/xfrm/xfrm_user.c
+++ b/net/xfrm/xfrm_user.c
@@ -323,7 +323,7 @@ static void copy_from_user_state(struct xfrm_state *x, struct xfrm_usersa_info *
x->props.replay_window = p->replay_window;
x->props.reqid = p->reqid;
x->props.family = p->family;
- x->props.saddr = p->saddr;
+ memcpy(&x->props.saddr, &p->saddr, sizeof(x->props.saddr));
x->props.flags = p->flags;
}
@@ -545,7 +545,7 @@ static void copy_to_user_state(struct xfrm_state *x, struct xfrm_usersa_info *p)
memcpy(&p->lft, &x->lft, sizeof(p->lft));
memcpy(&p->curlft, &x->curlft, sizeof(p->curlft));
memcpy(&p->stats, &x->stats, sizeof(p->stats));
- p->saddr = x->props.saddr;
+ memcpy(&p->saddr, &x->props.saddr, sizeof(p->saddr));
p->mode = x->props.mode;
p->replay_window = x->props.replay_window;
p->reqid = x->props.reqid;
@@ -1927,6 +1927,9 @@ static int xfrm_send_acquire(struct xfrm_state *x, struct xfrm_tmpl *xt,
len = RTA_SPACE(sizeof(struct xfrm_user_tmpl) * xp->xfrm_nr);
len += NLMSG_SPACE(sizeof(struct xfrm_user_acquire));
len += RTA_SPACE(xfrm_user_sec_ctx_size(xp));
+#ifdef CONFIG_XFRM_SUB_POLICY
+ len += RTA_SPACE(sizeof(struct xfrm_userpolicy_type));
+#endif
skb = alloc_skb(len, GFP_ATOMIC);
if (skb == NULL)
return -ENOMEM;
@@ -1992,15 +1995,6 @@ static struct xfrm_policy *xfrm_compile_policy(struct sock *sk, int opt,
xp->type = XFRM_POLICY_TYPE_MAIN;
copy_templates(xp, ut, nr);
- if (!xp->security) {
- int err = security_xfrm_sock_policy_alloc(xp, sk);
- if (err) {
- kfree(xp);
- *dir = err;
- return NULL;
- }
- }
-
*dir = p->dir;
return xp;
@@ -2043,6 +2037,9 @@ static int xfrm_exp_policy_notify(struct xfrm_policy *xp, int dir, struct km_eve
len = RTA_SPACE(sizeof(struct xfrm_user_tmpl) * xp->xfrm_nr);
len += NLMSG_SPACE(sizeof(struct xfrm_user_polexpire));
len += RTA_SPACE(xfrm_user_sec_ctx_size(xp));
+#ifdef CONFIG_XFRM_SUB_POLICY
+ len += RTA_SPACE(sizeof(struct xfrm_userpolicy_type));
+#endif
skb = alloc_skb(len, GFP_ATOMIC);
if (skb == NULL)
return -ENOMEM;
@@ -2069,6 +2066,9 @@ static int xfrm_notify_policy(struct xfrm_policy *xp, int dir, struct km_event *
len += RTA_SPACE(headlen);
headlen = sizeof(*id);
}
+#ifdef CONFIG_XFRM_SUB_POLICY
+ len += RTA_SPACE(sizeof(struct xfrm_userpolicy_type));
+#endif
len += NLMSG_SPACE(headlen);
skb = alloc_skb(len, GFP_ATOMIC);
@@ -2115,10 +2115,12 @@ static int xfrm_notify_policy_flush(struct km_event *c)
struct nlmsghdr *nlh;
struct sk_buff *skb;
unsigned char *b;
+ int len = 0;
#ifdef CONFIG_XFRM_SUB_POLICY
struct xfrm_userpolicy_type upt;
+ len += RTA_SPACE(sizeof(struct xfrm_userpolicy_type));
#endif
- int len = NLMSG_LENGTH(0);
+ len += NLMSG_LENGTH(0);
skb = alloc_skb(len, GFP_ATOMIC);
if (skb == NULL)
OpenPOWER on IntegriCloud