diff options
Diffstat (limited to 'net/xfrm/xfrm_user.c')
| -rw-r--r-- | net/xfrm/xfrm_user.c | 69 | 
1 files changed, 6 insertions, 63 deletions
| diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c index c35336a0f71b..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 | ||
| 31 | static struct sock *xfrm_nl; | 31 | static struct sock *xfrm_nl; | 
| @@ -948,11 +948,6 @@ static struct xfrm_link { | |||
| 948 | [XFRM_MSG_FLUSHPOLICY - XFRM_MSG_BASE] = { .doit = xfrm_flush_policy }, | 948 | [XFRM_MSG_FLUSHPOLICY - XFRM_MSG_BASE] = { .doit = xfrm_flush_policy }, | 
| 949 | }; | 949 | }; | 
| 950 | 950 | ||
| 951 | static int xfrm_done(struct netlink_callback *cb) | ||
| 952 | { | ||
| 953 | return 0; | ||
| 954 | } | ||
| 955 | |||
| 956 | static int xfrm_user_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, int *errp) | 951 | static int xfrm_user_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, int *errp) | 
| 957 | { | 952 | { | 
| 958 | struct rtattr *xfrma[XFRMA_MAX]; | 953 | struct rtattr *xfrma[XFRMA_MAX]; | 
| @@ -984,20 +979,15 @@ static int xfrm_user_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, int *err | |||
| 984 | if ((type == (XFRM_MSG_GETSA - XFRM_MSG_BASE) || | 979 | if ((type == (XFRM_MSG_GETSA - XFRM_MSG_BASE) || | 
| 985 | type == (XFRM_MSG_GETPOLICY - XFRM_MSG_BASE)) && | 980 | type == (XFRM_MSG_GETPOLICY - XFRM_MSG_BASE)) && | 
| 986 | (nlh->nlmsg_flags & NLM_F_DUMP)) { | 981 | (nlh->nlmsg_flags & NLM_F_DUMP)) { | 
| 987 | u32 rlen; | ||
| 988 | |||
| 989 | if (link->dump == NULL) | 982 | if (link->dump == NULL) | 
| 990 | goto err_einval; | 983 | goto err_einval; | 
| 991 | 984 | ||
| 992 | if ((*errp = netlink_dump_start(xfrm_nl, skb, nlh, | 985 | if ((*errp = netlink_dump_start(xfrm_nl, skb, nlh, | 
| 993 | link->dump, | 986 | link->dump, NULL)) != 0) { | 
| 994 | xfrm_done)) != 0) { | ||
| 995 | return -1; | 987 | return -1; | 
| 996 | } | 988 | } | 
| 997 | rlen = NLMSG_ALIGN(nlh->nlmsg_len); | 989 | |
| 998 | if (rlen > skb->len) | 990 | netlink_queue_skip(nlh, skb); | 
| 999 | rlen = skb->len; | ||
| 1000 | skb_pull(skb, rlen); | ||
| 1001 | return -1; | 991 | return -1; | 
| 1002 | } | 992 | } | 
| 1003 | 993 | ||
| @@ -1032,60 +1022,13 @@ err_einval: | |||
| 1032 | return -1; | 1022 | return -1; | 
| 1033 | } | 1023 | } | 
| 1034 | 1024 | ||
| 1035 | static int xfrm_user_rcv_skb(struct sk_buff *skb) | ||
| 1036 | { | ||
| 1037 | int err; | ||
| 1038 | struct nlmsghdr *nlh; | ||
| 1039 | |||
| 1040 | while (skb->len >= NLMSG_SPACE(0)) { | ||
| 1041 | u32 rlen; | ||
| 1042 | |||
| 1043 | nlh = (struct nlmsghdr *) skb->data; | ||
| 1044 | if (nlh->nlmsg_len < sizeof(*nlh) || | ||
| 1045 | skb->len < nlh->nlmsg_len) | ||
| 1046 | return 0; | ||
| 1047 | rlen = NLMSG_ALIGN(nlh->nlmsg_len); | ||
| 1048 | if (rlen > skb->len) | ||
| 1049 | rlen = skb->len; | ||
| 1050 | if (xfrm_user_rcv_msg(skb, nlh, &err) < 0) { | ||
| 1051 | if (err == 0) | ||
| 1052 | return -1; | ||
| 1053 | netlink_ack(skb, nlh, err); | ||
| 1054 | } else if (nlh->nlmsg_flags & NLM_F_ACK) | ||
| 1055 | netlink_ack(skb, nlh, 0); | ||
| 1056 | skb_pull(skb, rlen); | ||
| 1057 | } | ||
| 1058 | |||
| 1059 | return 0; | ||
| 1060 | } | ||
| 1061 | |||
| 1062 | static void xfrm_netlink_rcv(struct sock *sk, int len) | 1025 | static void xfrm_netlink_rcv(struct sock *sk, int len) | 
| 1063 | { | 1026 | { | 
| 1064 | unsigned int qlen = skb_queue_len(&sk->sk_receive_queue); | 1027 | unsigned int qlen = 0; | 
| 1065 | 1028 | ||
| 1066 | do { | 1029 | do { | 
| 1067 | struct sk_buff *skb; | ||
| 1068 | |||
| 1069 | down(&xfrm_cfg_sem); | 1030 | down(&xfrm_cfg_sem); | 
| 1070 | 1031 | netlink_run_queue(sk, &qlen, &xfrm_user_rcv_msg); | |
| 1071 | if (qlen > skb_queue_len(&sk->sk_receive_queue)) | ||
| 1072 | qlen = skb_queue_len(&sk->sk_receive_queue); | ||
| 1073 | |||
| 1074 | for (; qlen; qlen--) { | ||
| 1075 | skb = skb_dequeue(&sk->sk_receive_queue); | ||
| 1076 | if (xfrm_user_rcv_skb(skb)) { | ||
| 1077 | if (skb->len) | ||
| 1078 | skb_queue_head(&sk->sk_receive_queue, | ||
| 1079 | skb); | ||
| 1080 | else { | ||
| 1081 | kfree_skb(skb); | ||
| 1082 | qlen--; | ||
| 1083 | } | ||
| 1084 | break; | ||
| 1085 | } | ||
| 1086 | kfree_skb(skb); | ||
| 1087 | } | ||
| 1088 | |||
| 1089 | up(&xfrm_cfg_sem); | 1032 | up(&xfrm_cfg_sem); | 
| 1090 | 1033 | ||
| 1091 | } while (qlen); | 1034 | } while (qlen); | 
