aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBalazs Scheidler <bazsi@balabit.hu>2008-11-16 22:32:39 -0500
committerDavid S. Miller <davem@davemloft.net>2008-11-16 22:32:39 -0500
commite8b2dfe9b4501ed0047459b2756ba26e5a940a69 (patch)
tree6f7d497284a8951b8681517f7866851b32a7b02e
parent8164f1b79731ad8ad9c713dc53d587a3b746f82f (diff)
TPROXY: implemented IP_RECVORIGDSTADDR socket option
In case UDP traffic is redirected to a local UDP socket, the originally addressed destination address/port cannot be recovered with the in-kernel tproxy. This patch adds an IP_RECVORIGDSTADDR sockopt that enables a IP_ORIGDSTADDR ancillary message in recvmsg(). This ancillary message contains the original destination address/port of the packet being received. Signed-off-by: Balazs Scheidler <bazsi@balabit.hu> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--include/linux/in.h4
-rw-r--r--net/ipv4/ip_sockglue.c40
2 files changed, 43 insertions, 1 deletions
diff --git a/include/linux/in.h b/include/linux/in.h
index db458beef19d..d60122a3a088 100644
--- a/include/linux/in.h
+++ b/include/linux/in.h
@@ -80,6 +80,10 @@ struct in_addr {
80/* BSD compatibility */ 80/* BSD compatibility */
81#define IP_RECVRETOPTS IP_RETOPTS 81#define IP_RECVRETOPTS IP_RETOPTS
82 82
83/* TProxy original addresses */
84#define IP_ORIGDSTADDR 20
85#define IP_RECVORIGDSTADDR IP_ORIGDSTADDR
86
83/* IP_MTU_DISCOVER values */ 87/* IP_MTU_DISCOVER values */
84#define IP_PMTUDISC_DONT 0 /* Never send DF frames */ 88#define IP_PMTUDISC_DONT 0 /* Never send DF frames */
85#define IP_PMTUDISC_WANT 1 /* Use per route hints */ 89#define IP_PMTUDISC_WANT 1 /* Use per route hints */
diff --git a/net/ipv4/ip_sockglue.c b/net/ipv4/ip_sockglue.c
index e976efeb1456..624b534201e2 100644
--- a/net/ipv4/ip_sockglue.c
+++ b/net/ipv4/ip_sockglue.c
@@ -48,6 +48,7 @@
48#define IP_CMSG_RECVOPTS 8 48#define IP_CMSG_RECVOPTS 8
49#define IP_CMSG_RETOPTS 16 49#define IP_CMSG_RETOPTS 16
50#define IP_CMSG_PASSSEC 32 50#define IP_CMSG_PASSSEC 32
51#define IP_CMSG_ORIGDSTADDR 64
51 52
52/* 53/*
53 * SOL_IP control messages. 54 * SOL_IP control messages.
@@ -126,6 +127,27 @@ static void ip_cmsg_recv_security(struct msghdr *msg, struct sk_buff *skb)
126 security_release_secctx(secdata, seclen); 127 security_release_secctx(secdata, seclen);
127} 128}
128 129
130void ip_cmsg_recv_dstaddr(struct msghdr *msg, struct sk_buff *skb)
131{
132 struct sockaddr_in sin;
133 struct iphdr *iph = ip_hdr(skb);
134 u16 *ports = (u16 *) skb_transport_header(skb);
135
136 if (skb_transport_offset(skb) + 4 > skb->len)
137 return;
138
139 /* All current transport protocols have the port numbers in the
140 * first four bytes of the transport header and this function is
141 * written with this assumption in mind.
142 */
143
144 sin.sin_family = AF_INET;
145 sin.sin_addr.s_addr = iph->daddr;
146 sin.sin_port = ports[1];
147 memset(sin.sin_zero, 0, sizeof(sin.sin_zero));
148
149 put_cmsg(msg, SOL_IP, IP_ORIGDSTADDR, sizeof(sin), &sin);
150}
129 151
130void ip_cmsg_recv(struct msghdr *msg, struct sk_buff *skb) 152void ip_cmsg_recv(struct msghdr *msg, struct sk_buff *skb)
131{ 153{
@@ -160,6 +182,12 @@ void ip_cmsg_recv(struct msghdr *msg, struct sk_buff *skb)
160 182
161 if (flags & 1) 183 if (flags & 1)
162 ip_cmsg_recv_security(msg, skb); 184 ip_cmsg_recv_security(msg, skb);
185
186 if ((flags>>=1) == 0)
187 return;
188 if (flags & 1)
189 ip_cmsg_recv_dstaddr(msg, skb);
190
163} 191}
164 192
165int ip_cmsg_send(struct net *net, struct msghdr *msg, struct ipcm_cookie *ipc) 193int ip_cmsg_send(struct net *net, struct msghdr *msg, struct ipcm_cookie *ipc)
@@ -421,7 +449,8 @@ static int do_ip_setsockopt(struct sock *sk, int level,
421 (1<<IP_ROUTER_ALERT) | (1<<IP_FREEBIND) | 449 (1<<IP_ROUTER_ALERT) | (1<<IP_FREEBIND) |
422 (1<<IP_PASSSEC) | (1<<IP_TRANSPARENT))) || 450 (1<<IP_PASSSEC) | (1<<IP_TRANSPARENT))) ||
423 optname == IP_MULTICAST_TTL || 451 optname == IP_MULTICAST_TTL ||
424 optname == IP_MULTICAST_LOOP) { 452 optname == IP_MULTICAST_LOOP ||
453 optname == IP_RECVORIGDSTADDR) {
425 if (optlen >= sizeof(int)) { 454 if (optlen >= sizeof(int)) {
426 if (get_user(val, (int __user *) optval)) 455 if (get_user(val, (int __user *) optval))
427 return -EFAULT; 456 return -EFAULT;
@@ -509,6 +538,12 @@ static int do_ip_setsockopt(struct sock *sk, int level,
509 else 538 else
510 inet->cmsg_flags &= ~IP_CMSG_PASSSEC; 539 inet->cmsg_flags &= ~IP_CMSG_PASSSEC;
511 break; 540 break;
541 case IP_RECVORIGDSTADDR:
542 if (val)
543 inet->cmsg_flags |= IP_CMSG_ORIGDSTADDR;
544 else
545 inet->cmsg_flags &= ~IP_CMSG_ORIGDSTADDR;
546 break;
512 case IP_TOS: /* This sets both TOS and Precedence */ 547 case IP_TOS: /* This sets both TOS and Precedence */
513 if (sk->sk_type == SOCK_STREAM) { 548 if (sk->sk_type == SOCK_STREAM) {
514 val &= ~3; 549 val &= ~3;
@@ -1022,6 +1057,9 @@ static int do_ip_getsockopt(struct sock *sk, int level, int optname,
1022 case IP_PASSSEC: 1057 case IP_PASSSEC:
1023 val = (inet->cmsg_flags & IP_CMSG_PASSSEC) != 0; 1058 val = (inet->cmsg_flags & IP_CMSG_PASSSEC) != 0;
1024 break; 1059 break;
1060 case IP_RECVORIGDSTADDR:
1061 val = (inet->cmsg_flags & IP_CMSG_ORIGDSTADDR) != 0;
1062 break;
1025 case IP_TOS: 1063 case IP_TOS:
1026 val = inet->tos; 1064 val = inet->tos;
1027 break; 1065 break;