Commit 39771b12 authored by Willem de Bruijn's avatar Willem de Bruijn Committed by David S. Miller

sock: break up sock_cmsg_snd into __sock_cmsg_snd and loop

To process cmsg's of the SOL_SOCKET level in addition to
cmsgs of another level, protocols can call sock_cmsg_send().
This causes a double walk on the cmsghdr list, one for SOL_SOCKET
and one for the other level.

Extract the inner demultiplex logic from the loop that walks the list,
to allow having this called directly from a walker in the protocol
specific code.
Signed-off-by: default avatarWillem de Bruijn <willemb@google.com>
Signed-off-by: default avatarSoheil Hassas Yeganeh <soheil@google.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 833716e0
...@@ -1420,6 +1420,8 @@ struct sockcm_cookie { ...@@ -1420,6 +1420,8 @@ struct sockcm_cookie {
u32 mark; u32 mark;
}; };
int __sock_cmsg_send(struct sock *sk, struct msghdr *msg, struct cmsghdr *cmsg,
struct sockcm_cookie *sockc);
int sock_cmsg_send(struct sock *sk, struct msghdr *msg, int sock_cmsg_send(struct sock *sk, struct msghdr *msg,
struct sockcm_cookie *sockc); struct sockcm_cookie *sockc);
......
...@@ -1866,27 +1866,38 @@ struct sk_buff *sock_alloc_send_skb(struct sock *sk, unsigned long size, ...@@ -1866,27 +1866,38 @@ struct sk_buff *sock_alloc_send_skb(struct sock *sk, unsigned long size,
} }
EXPORT_SYMBOL(sock_alloc_send_skb); EXPORT_SYMBOL(sock_alloc_send_skb);
int __sock_cmsg_send(struct sock *sk, struct msghdr *msg, struct cmsghdr *cmsg,
struct sockcm_cookie *sockc)
{
switch (cmsg->cmsg_type) {
case SO_MARK:
if (!ns_capable(sock_net(sk)->user_ns, CAP_NET_ADMIN))
return -EPERM;
if (cmsg->cmsg_len != CMSG_LEN(sizeof(u32)))
return -EINVAL;
sockc->mark = *(u32 *)CMSG_DATA(cmsg);
break;
default:
return -EINVAL;
}
return 0;
}
EXPORT_SYMBOL(__sock_cmsg_send);
int sock_cmsg_send(struct sock *sk, struct msghdr *msg, int sock_cmsg_send(struct sock *sk, struct msghdr *msg,
struct sockcm_cookie *sockc) struct sockcm_cookie *sockc)
{ {
struct cmsghdr *cmsg; struct cmsghdr *cmsg;
int ret;
for_each_cmsghdr(cmsg, msg) { for_each_cmsghdr(cmsg, msg) {
if (!CMSG_OK(msg, cmsg)) if (!CMSG_OK(msg, cmsg))
return -EINVAL; return -EINVAL;
if (cmsg->cmsg_level != SOL_SOCKET) if (cmsg->cmsg_level != SOL_SOCKET)
continue; continue;
switch (cmsg->cmsg_type) { ret = __sock_cmsg_send(sk, msg, cmsg, sockc);
case SO_MARK: if (ret)
if (!ns_capable(sock_net(sk)->user_ns, CAP_NET_ADMIN)) return ret;
return -EPERM;
if (cmsg->cmsg_len != CMSG_LEN(sizeof(u32)))
return -EINVAL;
sockc->mark = *(u32 *)CMSG_DATA(cmsg);
break;
default:
return -EINVAL;
}
} }
return 0; return 0;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment