|
@@ -50,6 +50,7 @@
|
|
#define IP_CMSG_TOS 4
|
|
#define IP_CMSG_TOS 4
|
|
#define IP_CMSG_RECVOPTS 8
|
|
#define IP_CMSG_RECVOPTS 8
|
|
#define IP_CMSG_RETOPTS 16
|
|
#define IP_CMSG_RETOPTS 16
|
|
|
|
+#define IP_CMSG_PASSSEC 32
|
|
|
|
|
|
/*
|
|
/*
|
|
* SOL_IP control messages.
|
|
* SOL_IP control messages.
|
|
@@ -109,6 +110,19 @@ static void ip_cmsg_recv_retopts(struct msghdr *msg, struct sk_buff *skb)
|
|
put_cmsg(msg, SOL_IP, IP_RETOPTS, opt->optlen, opt->__data);
|
|
put_cmsg(msg, SOL_IP, IP_RETOPTS, opt->optlen, opt->__data);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+static void ip_cmsg_recv_security(struct msghdr *msg, struct sk_buff *skb)
|
|
|
|
+{
|
|
|
|
+ char *secdata;
|
|
|
|
+ u32 seclen;
|
|
|
|
+ int err;
|
|
|
|
+
|
|
|
|
+ err = security_socket_getpeersec_dgram(skb, &secdata, &seclen);
|
|
|
|
+ if (err)
|
|
|
|
+ return;
|
|
|
|
+
|
|
|
|
+ put_cmsg(msg, SOL_IP, SCM_SECURITY, seclen, secdata);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
|
|
void ip_cmsg_recv(struct msghdr *msg, struct sk_buff *skb)
|
|
void ip_cmsg_recv(struct msghdr *msg, struct sk_buff *skb)
|
|
{
|
|
{
|
|
@@ -138,6 +152,11 @@ void ip_cmsg_recv(struct msghdr *msg, struct sk_buff *skb)
|
|
|
|
|
|
if (flags & 1)
|
|
if (flags & 1)
|
|
ip_cmsg_recv_retopts(msg, skb);
|
|
ip_cmsg_recv_retopts(msg, skb);
|
|
|
|
+ if ((flags>>=1) == 0)
|
|
|
|
+ return;
|
|
|
|
+
|
|
|
|
+ if (flags & 1)
|
|
|
|
+ ip_cmsg_recv_security(msg, skb);
|
|
}
|
|
}
|
|
|
|
|
|
int ip_cmsg_send(struct msghdr *msg, struct ipcm_cookie *ipc)
|
|
int ip_cmsg_send(struct msghdr *msg, struct ipcm_cookie *ipc)
|
|
@@ -393,7 +412,8 @@ int ip_setsockopt(struct sock *sk, int level, int optname, char __user *optval,
|
|
(1<<IP_RETOPTS) | (1<<IP_TOS) |
|
|
(1<<IP_RETOPTS) | (1<<IP_TOS) |
|
|
(1<<IP_TTL) | (1<<IP_HDRINCL) |
|
|
(1<<IP_TTL) | (1<<IP_HDRINCL) |
|
|
(1<<IP_MTU_DISCOVER) | (1<<IP_RECVERR) |
|
|
(1<<IP_MTU_DISCOVER) | (1<<IP_RECVERR) |
|
|
- (1<<IP_ROUTER_ALERT) | (1<<IP_FREEBIND))) ||
|
|
|
|
|
|
+ (1<<IP_ROUTER_ALERT) | (1<<IP_FREEBIND) |
|
|
|
|
+ (1<<IP_PASSSEC))) ||
|
|
optname == IP_MULTICAST_TTL ||
|
|
optname == IP_MULTICAST_TTL ||
|
|
optname == IP_MULTICAST_LOOP) {
|
|
optname == IP_MULTICAST_LOOP) {
|
|
if (optlen >= sizeof(int)) {
|
|
if (optlen >= sizeof(int)) {
|
|
@@ -478,6 +498,12 @@ int ip_setsockopt(struct sock *sk, int level, int optname, char __user *optval,
|
|
else
|
|
else
|
|
inet->cmsg_flags &= ~IP_CMSG_RETOPTS;
|
|
inet->cmsg_flags &= ~IP_CMSG_RETOPTS;
|
|
break;
|
|
break;
|
|
|
|
+ case IP_PASSSEC:
|
|
|
|
+ if (val)
|
|
|
|
+ inet->cmsg_flags |= IP_CMSG_PASSSEC;
|
|
|
|
+ else
|
|
|
|
+ inet->cmsg_flags &= ~IP_CMSG_PASSSEC;
|
|
|
|
+ break;
|
|
case IP_TOS: /* This sets both TOS and Precedence */
|
|
case IP_TOS: /* This sets both TOS and Precedence */
|
|
if (sk->sk_type == SOCK_STREAM) {
|
|
if (sk->sk_type == SOCK_STREAM) {
|
|
val &= ~3;
|
|
val &= ~3;
|
|
@@ -932,6 +958,9 @@ int ip_getsockopt(struct sock *sk, int level, int optname, char __user *optval,
|
|
case IP_RETOPTS:
|
|
case IP_RETOPTS:
|
|
val = (inet->cmsg_flags & IP_CMSG_RETOPTS) != 0;
|
|
val = (inet->cmsg_flags & IP_CMSG_RETOPTS) != 0;
|
|
break;
|
|
break;
|
|
|
|
+ case IP_PASSSEC:
|
|
|
|
+ val = (inet->cmsg_flags & IP_CMSG_PASSSEC) != 0;
|
|
|
|
+ break;
|
|
case IP_TOS:
|
|
case IP_TOS:
|
|
val = inet->tos;
|
|
val = inet->tos;
|
|
break;
|
|
break;
|