aboutsummaryrefslogtreecommitdiffstats
path: root/net/xfrm/xfrm_user.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/xfrm/xfrm_user.c')
-rw-r--r--net/xfrm/xfrm_user.c61
1 files changed, 5 insertions, 56 deletions
diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c
index 6996b7e85665..0cdd9a07e043 100644
--- a/net/xfrm/xfrm_user.c
+++ b/net/xfrm/xfrm_user.c
@@ -18,7 +18,6 @@
18#include <linux/string.h> 18#include <linux/string.h>
19#include <linux/net.h> 19#include <linux/net.h>
20#include <linux/skbuff.h> 20#include <linux/skbuff.h>
21#include <linux/netlink.h>
22#include <linux/rtnetlink.h> 21#include <linux/rtnetlink.h>
23#include <linux/pfkeyv2.h> 22#include <linux/pfkeyv2.h>
24#include <linux/ipsec.h> 23#include <linux/ipsec.h>
@@ -26,6 +25,7 @@
26#include <linux/security.h> 25#include <linux/security.h>
27#include <net/sock.h> 26#include <net/sock.h>
28#include <net/xfrm.h> 27#include <net/xfrm.h>
28#include <net/netlink.h>
29#include <asm/uaccess.h> 29#include <asm/uaccess.h>
30 30
31static struct sock *xfrm_nl; 31static struct sock *xfrm_nl;
@@ -979,8 +979,6 @@ static int xfrm_user_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, int *err
979 if ((type == (XFRM_MSG_GETSA - XFRM_MSG_BASE) || 979 if ((type == (XFRM_MSG_GETSA - XFRM_MSG_BASE) ||
980 type == (XFRM_MSG_GETPOLICY - XFRM_MSG_BASE)) && 980 type == (XFRM_MSG_GETPOLICY - XFRM_MSG_BASE)) &&
981 (nlh->nlmsg_flags & NLM_F_DUMP)) { 981 (nlh->nlmsg_flags & NLM_F_DUMP)) {
982 u32 rlen;
983
984 if (link->dump == NULL) 982 if (link->dump == NULL)
985 goto err_einval; 983 goto err_einval;
986 984
@@ -988,10 +986,8 @@ static int xfrm_user_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, int *err
988 link->dump, NULL)) != 0) { 986 link->dump, NULL)) != 0) {
989 return -1; 987 return -1;
990 } 988 }
991 rlen = NLMSG_ALIGN(nlh->nlmsg_len); 989
992 if (rlen > skb->len) 990 netlink_queue_skip(nlh, skb);
993 rlen = skb->len;
994 skb_pull(skb, rlen);
995 return -1; 991 return -1;
996 } 992 }
997 993
@@ -1026,60 +1022,13 @@ err_einval:
1026 return -1; 1022 return -1;
1027} 1023}
1028 1024
1029static int xfrm_user_rcv_skb(struct sk_buff *skb)
1030{
1031 int err;
1032 struct nlmsghdr *nlh;
1033
1034 while (skb->len >= NLMSG_SPACE(0)) {
1035 u32 rlen;
1036
1037 nlh = (struct nlmsghdr *) skb->data;
1038 if (nlh->nlmsg_len < sizeof(*nlh) ||
1039 skb->len < nlh->nlmsg_len)
1040 return 0;
1041 rlen = NLMSG_ALIGN(nlh->nlmsg_len);
1042 if (rlen > skb->len)
1043 rlen = skb->len;
1044 if (xfrm_user_rcv_msg(skb, nlh, &err) < 0) {
1045 if (err == 0)
1046 return -1;
1047 netlink_ack(skb, nlh, err);
1048 } else if (nlh->nlmsg_flags & NLM_F_ACK)
1049 netlink_ack(skb, nlh, 0);
1050 skb_pull(skb, rlen);
1051 }
1052
1053 return 0;
1054}
1055
1056static void xfrm_netlink_rcv(struct sock *sk, int len) 1025static void xfrm_netlink_rcv(struct sock *sk, int len)
1057{ 1026{
1058 unsigned int qlen = skb_queue_len(&sk->sk_receive_queue); 1027 unsigned int qlen = 0;
1059 1028
1060 do { 1029 do {
1061 struct sk_buff *skb;
1062
1063 down(&xfrm_cfg_sem); 1030 down(&xfrm_cfg_sem);
1064 1031 netlink_run_queue(sk, &qlen, &xfrm_user_rcv_msg);
1065 if (qlen > skb_queue_len(&sk->sk_receive_queue))
1066 qlen = skb_queue_len(&sk->sk_receive_queue);
1067
1068 for (; qlen; qlen--) {
1069 skb = skb_dequeue(&sk->sk_receive_queue);
1070 if (xfrm_user_rcv_skb(skb)) {
1071 if (skb->len)
1072 skb_queue_head(&sk->sk_receive_queue,
1073 skb);
1074 else {
1075 kfree_skb(skb);
1076 qlen--;
1077 }
1078 break;
1079 }
1080 kfree_skb(skb);
1081 }
1082
1083 up(&xfrm_cfg_sem); 1032 up(&xfrm_cfg_sem);
1084 1033
1085 } while (qlen); 1034 } while (qlen);