netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v7 1/2] ipv4: Implement IP_UNICAST_IF socket option.
@ 2012-02-08 19:11 Erich E. Hoover
  2012-02-08 19:28 ` Eric Dumazet
  0 siblings, 1 reply; 4+ messages in thread
From: Erich E. Hoover @ 2012-02-08 19:11 UTC (permalink / raw)
  To: Linux Netdev; +Cc: Erich E. Hoover


The IP_UNICAST_IF feature is needed by the Wine project.  This patch
implements the feature by setting the outgoing interface in a similar
fashion to that of IP_MULTICAST_IF.  A separate option is needed to
handle this feature since the existing options do not provide all of
the characteristics required by IP_UNICAST_IF, a summary is provided
below.

SO_BINDTODEVICE:
* SO_BINDTODEVICE requires administrative privileges, IP_UNICAST_IF
does not.  From reading some old mailing list articles my
understanding is that SO_BINDTODEVICE requires administrative
privileges because it can override the administrator's routing
settings.
* The SO_BINDTODEVICE option restricts both outbound and inbound
traffic, IP_UNICAST_IF only impacts outbound traffic.

IP_PKTINFO:
* Since IP_PKTINFO and IP_UNICAST_IF are independent options,
implementing IP_UNICAST_IF with IP_PKTINFO will likely break some
applications.
* Implementing IP_UNICAST_IF on top of IP_PKTINFO significantly
complicates the Wine codebase and reduces the socket performance
(doing this requires a lot of extra communication between the
"server" and "user" layers).

bind():
* bind() does not work on broadcast packets, IP_UNICAST_IF is
specifically intended to work with broadcast packets.
* Like SO_BINDTODEVICE, bind() restricts both outbound and inbound
traffic.

Signed-off-by: Erich E. Hoover <ehoover@mines.edu>
---
 include/linux/in.h      |    1 +
 include/net/inet_sock.h |    2 ++
 net/ipv4/ip_sockglue.c  |   33 +++++++++++++++++++++++++++++++++
 net/ipv4/ping.c         |    3 ++-
 net/ipv4/raw.c          |    3 ++-
 net/ipv4/udp.c          |    3 ++-
 6 files changed, 42 insertions(+), 3 deletions(-)

diff --git a/include/linux/in.h b/include/linux/in.h
index 01129c0..e0337f1 100644
--- a/include/linux/in.h
+++ b/include/linux/in.h
@@ -111,6 +111,7 @@ struct in_addr {
 #define MCAST_LEAVE_SOURCE_GROUP	47
 #define MCAST_MSFILTER			48
 #define IP_MULTICAST_ALL		49
+#define IP_UNICAST_IF			50
 
 #define MCAST_EXCLUDE	0
 #define MCAST_INCLUDE	1
diff --git a/include/net/inet_sock.h b/include/net/inet_sock.h
index e3e4051..022f772 100644
--- a/include/net/inet_sock.h
+++ b/include/net/inet_sock.h
@@ -132,6 +132,7 @@ struct rtable;
  * @tos - TOS
  * @mc_ttl - Multicasting TTL
  * @is_icsk - is this an inet_connection_sock?
+ * @uc_index - Unicast outgoing device index
  * @mc_index - Multicast device index
  * @mc_list - Group array
  * @cork - info to build ip hdr on each ip frag while socket is corked
@@ -167,6 +168,7 @@ struct inet_sock {
 				transparent:1,
 				mc_all:1,
 				nodefrag:1;
+	int			uc_index;
 	int			mc_index;
 	__be32			mc_addr;
 	struct ip_mc_socklist __rcu	*mc_list;
diff --git a/net/ipv4/ip_sockglue.c b/net/ipv4/ip_sockglue.c
index 8aa87c1..9125529 100644
--- a/net/ipv4/ip_sockglue.c
+++ b/net/ipv4/ip_sockglue.c
@@ -469,6 +469,7 @@ static int do_ip_setsockopt(struct sock *sk, int level,
 			     (1<<IP_ROUTER_ALERT) | (1<<IP_FREEBIND) |
 			     (1<<IP_PASSSEC) | (1<<IP_TRANSPARENT) |
 			     (1<<IP_MINTTL) | (1<<IP_NODEFRAG))) ||
+	    optname == IP_UNICAST_IF ||
 	    optname == IP_MULTICAST_TTL ||
 	    optname == IP_MULTICAST_ALL ||
 	    optname == IP_MULTICAST_LOOP ||
@@ -628,6 +629,35 @@ static int do_ip_setsockopt(struct sock *sk, int level,
 			goto e_inval;
 		inet->mc_loop = !!val;
 		break;
+	case IP_UNICAST_IF:
+	{
+		struct net_device *dev = NULL;
+		int ifindex;
+
+		if (optlen != sizeof(int))
+			goto e_inval;
+
+		ifindex = (__force int)ntohl((__force __be32)val);
+		if (ifindex == 0) {
+			inet->uc_index = 0;
+			err = 0;
+			break;
+		}
+
+		dev = dev_get_by_index(sock_net(sk), ifindex);
+		err = -EADDRNOTAVAIL;
+		if (!dev)
+			break;
+		dev_put(dev);
+
+		err = -EINVAL;
+		if (sk->sk_bound_dev_if)
+			break;
+
+		inet->uc_index = ifindex;
+		err = 0;
+		break;
+	}
 	case IP_MULTICAST_IF:
 	{
 		struct ip_mreqn mreq;
@@ -1178,6 +1208,9 @@ static int do_ip_getsockopt(struct sock *sk, int level, int optname,
 	case IP_MULTICAST_LOOP:
 		val = inet->mc_loop;
 		break;
+	case IP_UNICAST_IF:
+		val = (__force int)htonl((__u32) inet->uc_index);
+		break;
 	case IP_MULTICAST_IF:
 	{
 		struct in_addr addr;
diff --git a/net/ipv4/ping.c b/net/ipv4/ping.c
index aea5a19..cfc82cf 100644
--- a/net/ipv4/ping.c
+++ b/net/ipv4/ping.c
@@ -556,7 +556,8 @@ static int ping_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
 			ipc.oif = inet->mc_index;
 		if (!saddr)
 			saddr = inet->mc_addr;
-	}
+	} else if (!ipc.oif)
+		ipc.oif = inet->uc_index;
 
 	flowi4_init_output(&fl4, ipc.oif, sk->sk_mark, tos,
 			   RT_SCOPE_UNIVERSE, sk->sk_protocol,
diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c
index 3ccda5a..ab46630 100644
--- a/net/ipv4/raw.c
+++ b/net/ipv4/raw.c
@@ -563,7 +563,8 @@ static int raw_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
 			ipc.oif = inet->mc_index;
 		if (!saddr)
 			saddr = inet->mc_addr;
-	}
+	} else if (!ipc.oif)
+		ipc.oif = inet->uc_index;
 
 	flowi4_init_output(&fl4, ipc.oif, sk->sk_mark, tos,
 			   RT_SCOPE_UNIVERSE,
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
index 5d075b5..cd99f1a 100644
--- a/net/ipv4/udp.c
+++ b/net/ipv4/udp.c
@@ -917,7 +917,8 @@ int udp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
 		if (!saddr)
 			saddr = inet->mc_addr;
 		connected = 0;
-	}
+	} else if (!ipc.oif)
+		ipc.oif = inet->uc_index;
 
 	if (connected)
 		rt = (struct rtable *)sk_dst_check(sk, 0);
-- 
1.7.5.4

^ permalink raw reply related	[flat|nested] 4+ messages in thread

* Re: [PATCH v7 1/2] ipv4: Implement IP_UNICAST_IF socket option.
  2012-02-08 19:11 [PATCH v7 1/2] ipv4: Implement IP_UNICAST_IF socket option Erich E. Hoover
@ 2012-02-08 19:28 ` Eric Dumazet
  2012-02-08 20:52   ` David Miller
  0 siblings, 1 reply; 4+ messages in thread
From: Eric Dumazet @ 2012-02-08 19:28 UTC (permalink / raw)
  To: Erich E. Hoover; +Cc: Linux Netdev

Le mercredi 08 février 2012 à 12:11 -0700, Erich E. Hoover a écrit :
> The IP_UNICAST_IF feature is needed by the Wine project.  This patch
> implements the feature by setting the outgoing interface in a similar
> fashion to that of IP_MULTICAST_IF.  A separate option is needed to
> handle this feature since the existing options do not provide all of
> the characteristics required by IP_UNICAST_IF, a summary is provided
> below.
> 
> SO_BINDTODEVICE:
> * SO_BINDTODEVICE requires administrative privileges, IP_UNICAST_IF
> does not.  From reading some old mailing list articles my
> understanding is that SO_BINDTODEVICE requires administrative
> privileges because it can override the administrator's routing
> settings.
> * The SO_BINDTODEVICE option restricts both outbound and inbound
> traffic, IP_UNICAST_IF only impacts outbound traffic.
> 
> IP_PKTINFO:
> * Since IP_PKTINFO and IP_UNICAST_IF are independent options,
> implementing IP_UNICAST_IF with IP_PKTINFO will likely break some
> applications.
> * Implementing IP_UNICAST_IF on top of IP_PKTINFO significantly
> complicates the Wine codebase and reduces the socket performance
> (doing this requires a lot of extra communication between the
> "server" and "user" layers).
> 
> bind():
> * bind() does not work on broadcast packets, IP_UNICAST_IF is
> specifically intended to work with broadcast packets.
> * Like SO_BINDTODEVICE, bind() restricts both outbound and inbound
> traffic.
> 
> Signed-off-by: Erich E. Hoover <ehoover@mines.edu>
> ---

Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH v7 1/2] ipv4: Implement IP_UNICAST_IF socket option.
  2012-02-08 19:28 ` Eric Dumazet
@ 2012-02-08 20:52   ` David Miller
  2012-02-08 22:26     ` Erich E. Hoover
  0 siblings, 1 reply; 4+ messages in thread
From: David Miller @ 2012-02-08 20:52 UTC (permalink / raw)
  To: eric.dumazet; +Cc: ehoover, netdev

From: Eric Dumazet <eric.dumazet@gmail.com>
Date: Wed, 08 Feb 2012 20:28:43 +0100

> Le mercredi 08 février 2012 à 12:11 -0700, Erich E. Hoover a écrit :
>> The IP_UNICAST_IF feature is needed by the Wine project.  This patch
>> implements the feature by setting the outgoing interface in a similar
>> fashion to that of IP_MULTICAST_IF.  A separate option is needed to
>> handle this feature since the existing options do not provide all of
>> the characteristics required by IP_UNICAST_IF, a summary is provided
>> below.
>> 
>> SO_BINDTODEVICE:
>> * SO_BINDTODEVICE requires administrative privileges, IP_UNICAST_IF
>> does not.  From reading some old mailing list articles my
>> understanding is that SO_BINDTODEVICE requires administrative
>> privileges because it can override the administrator's routing
>> settings.
>> * The SO_BINDTODEVICE option restricts both outbound and inbound
>> traffic, IP_UNICAST_IF only impacts outbound traffic.
>> 
>> IP_PKTINFO:
>> * Since IP_PKTINFO and IP_UNICAST_IF are independent options,
>> implementing IP_UNICAST_IF with IP_PKTINFO will likely break some
>> applications.
>> * Implementing IP_UNICAST_IF on top of IP_PKTINFO significantly
>> complicates the Wine codebase and reduces the socket performance
>> (doing this requires a lot of extra communication between the
>> "server" and "user" layers).
>> 
>> bind():
>> * bind() does not work on broadcast packets, IP_UNICAST_IF is
>> specifically intended to work with broadcast packets.
>> * Like SO_BINDTODEVICE, bind() restricts both outbound and inbound
>> traffic.
>> 
>> Signed-off-by: Erich E. Hoover <ehoover@mines.edu>
>> ---
> 
> Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>

Applied.

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH v7 1/2] ipv4: Implement IP_UNICAST_IF socket option.
  2012-02-08 20:52   ` David Miller
@ 2012-02-08 22:26     ` Erich E. Hoover
  0 siblings, 0 replies; 4+ messages in thread
From: Erich E. Hoover @ 2012-02-08 22:26 UTC (permalink / raw)
  To: David Miller; +Cc: eric.dumazet, netdev

On Wed, Feb 8, 2012 at 1:52 PM, David Miller <davem@davemloft.net> wrote:
> ...
> Applied.

Thanks, and many thanks to everyone for all of their help!

Erich Hoover
ehoover@mines.edu

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2012-02-08 22:26 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-02-08 19:11 [PATCH v7 1/2] ipv4: Implement IP_UNICAST_IF socket option Erich E. Hoover
2012-02-08 19:28 ` Eric Dumazet
2012-02-08 20:52   ` David Miller
2012-02-08 22:26     ` Erich E. Hoover

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).