Subject: comment on v4mapped-api-harmful

From: Pekka Savola <[email-masked]>
Date: Sun, 17 Nov 2002 23:46:48 +0200 (EET)

Hello,

Even though I'm sympathic to the cause, I, too, have started to believe 
it's too late now -- changing this would only add confusion.  We don't 
want even another different behaviour when binding addresses.

However, I believe the long-term goal should be separate INET6 and INET.  
The question is how to get there, and how quickly.

In particular,

o Do not intentionally use RFC2553 section 3.7 (IPv4 traffic on AF_INET6
  socket).  Implement server applications by using separate AF_INET and
  AF_INET6 listening sockets.  Explicitly set the IPV6_V6ONLY socket
  option to on, whenever the socket option is available on the system.

==> please provide some overview on the migration path (kernel/library, 
apps) from the current state to this.

Reversing the default value would appear to be totally unacceptable, 
because it'd break _all_ current apps.

Perhaps detecting the behaviour might be doable by some test macro..

-- 
Pekka Savola                 "Tell me of difficulties surmounted,
Netcore Oy                   not those you stumble over and fall"
Systems. Networks. Security.  -- Robert Jordan: A Crown of Swords

---

From: [email-masked]
Date: Mon, 18 Nov 2002 07:25:46 +0900

to be clear, i have been pointing this problem out since 2553bis
	discussions group (apifolks).

>because it'd break _all_ current apps.

	it'd breaks apps that assume IPv4 mapped address support, such as:
	- server program that listens to AF_INET6 socket only to receive both
	  IPv4 and IPv6 inbound traffic.
		can be worked around by running two instance of the app,
		one for AF_INET and one for AF_INET6
	- client program that uses getaddrinfo(3) with AI_MAPPED and AF_INET6
	  socket to connect to IPv4 and IPv6 destination
		should be rewritten to socket(2) after getaddrinfo(3)

	the change in default behavior shouldn't break applications if
	appliations are correctly written to handle IPv4 traffic on AF_INET
	socket, and IPv6 traffic on AF_INET6 socket.

	the following code fragment (server side) should avoid vulnerability
	on systems with/without IPv4 mapped address behavior, assuming:
	- bind(2) to the same port on AF_INET and AF_INET6 does not conflict
	  (yes, some systems they do conflict and you can open only one of them)
	- 2553bis IPV6_V6ONLY is implemented
	- getaddrinfo(3) returns both AF_INET and AF_INET6 wildcard address
	  on AI_PASSIVE
	i dunno, on how many systems, the above assumption holds.  due to the
	lack of specification bind(2) behavior varies very much by
	implementation.

>Perhaps detecting the behaviour might be doable by some test macro..

	getsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, &v, sizeof(v))?

itojun

int socks[NSOCK];
int nsocks;

foo(port)
	char *port;
{
	struct addrinfo hints, *res, *res0;
	int s;
	const int on = 1;

	memset(&hints, 0, sizeof(hints));
	hints.ai_socktype = SOCK_STREAM;	/* of DGRAM if you want to */
	hints.ai_flags = AI_PASSIVE;
	getaddrinfo(NULL, port, &hints, &res0);
	nsocks = 0;
	for (res = res0; res; res = res->ai_next) {
		s = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
		if (s < 0)
			continue;
#ifdef IPV6_V6ONLY
		if (res->ai_family == AF_INET6 && setsockopt(s, IPPROTO_IPV6,
		    IPV6_V6ONLY, &on, sizeof(on)) < 0) {
			close(s);
			continue;
		}
#endif
		if (bind(s, res->ai_addr, res->ai_addrlen) < 0) {
			close(s);
			continue;
		}
		if (listen(s, 5) < 0) {
			close(s);
			continue;
		}
		socks[nsocks++] = s;
	}
	if (nsocks == 0)
		exit(1);

	/* handle socks[0] to socks[nsocks - 1] by select(2) or poll(2 )*/
}

---

From: Pekka Savola <[email-masked]>
Date: Mon, 18 Nov 2002 14:28:22 +0200 (EET)

> 	discussions group (apifolks).

Yep..
 
> 		one for AF_INET and one for AF_INET6

Sure, but the point was how to get there?

Hypothetically assume that the model you proposed is adopted.  Some
vendors have it right now.  Some have it in 1 year, some in 2.  Some may
never implement it.

How should you code your app so that it detects whether AF_INET6 is enough 
or whether it needs also AF_INET? 

In particular, in some systems:

1) bind to AF_INET6 with IPV6_V6ONLY gives only AF_INET6
 a) on some, setsockopt IPV6_V6ONLY will fail
2) bind to AF_INET6 without IPV6_ONLY gives
  a) only AF_INET6
  b) both AF_INET and AF_INET6
3) bind to AF_INET6 with some new "IPV6_ALSOV4" gives both sockets

Porting apps wrt. AF_INET6 quirks is complicated enough already (but 
somehow getting to the state you propose would simplify it in the long 
term).

I guess you could use something like "#ifdef IPV6_ALSOV4" to check whether
the system would support your model -- checking with IPV6_V6ONLY will not
be enough -- but in reality, the check should be done at runtime.

> 	socket, and IPv6 traffic on AF_INET6 socket.

The problem is that the definition of "correctly written" is currently 
satisfied by doing AF_INET6 + mapped addrs.
 
> 	lack of specification bind(2) behavior varies very much by

I think you're also assuming:
 - when the system headers/libs support IPV6_V6ONLY, the kernel also 
supports it
 - the same binary cannot be used on systems with different IPV6_V6ONLY 
etc. implementation (see above)
 
> 		if (bind(s, res->ai_addr, res->ai_addrlen) < 0) {

if your lib supports IPV6_V6ONLY (or, rather, the version where the
program compiled with) but kernel doesn't, I believe this will end up
listening to AF_INET only.

Seems like a pretty nasty change of behaviour (== DoS) to me.

---

From: [email-masked]
Date: Mon, 18 Nov 2002 22:11:31 +0900

> - when the system headers/libs support IPV6_V6ONLY, the kernel also 

	i consider such system totally broken.  header has to have items
	that is supported by kernel, period.

>Seems like a pretty nasty change of behaviour (== DoS) to me.

	we could ignore setsockopt() error and continue on, but if we do so,
	on certain stacks AF_INET/INET6 port number conflict happens on
	some of the platforms.

itojun

---

From: Pekka Savola <[email-masked]>
Date: Mon, 18 Nov 2002 15:31:39 +0200 (EET)

> 	that is supported by kernel, period.

This is is an easy consideration, but it just doesn't hold, e.g. in two 
cases:
 1) incremental OS upgrades ("to upgrade X, you must also upgrade Y 
immediately and reboot or else hell breaks loose"), or
 2) libc and kernel managed by different people (eg. linux, possibly 
others)

YMMV.

> 	on certain stacks AF_INET/INET6 port number conflict happens on

Exactly.. which is why some form of more reliable indicator of the system 
support would be nice.

---

From: Francis Dupont <[email-masked]>
Date: Mon, 18 Nov 2002 16:05:09 +0100

In your previous mail you wrote:

=> yes, it'd breaks apps that assume implementations are compliant!
We already had this discussion, I support Jim: don't reopen it
because your side didn't win.

Regards

[email-masked]