Netdev List
 help / color / mirror / Atom feed
From: William Ahern <william@25thandClement.com>
To: netdev@vger.kernel.org
Subject: connect(2) reassociation regression
Date: Fri, 15 Mar 2013 22:56:32 -0700	[thread overview]
Message-ID: <20130316055632.GA21364@wilbur.25thandClement.com> (raw)

I've stumbled upon what may be a regression in connect(2) behavior.

My DNS library uses connect(2) to reassociate UDP sockets. That way the
kernel can filter my packets, and it makes for cleaner code overall. The
Linux manual page makes it pretty clear that this is okay, and at least one
interpretation of POSIX (certainly the one I had) does as well.

At some point in the 3.x cycle (maybe after 3.2.0) something was changed.
Whereas previously any reassociation worked, regardless of destination
network, now if the _first_ association is to the loopback, any subsequent
association to non-loopback fails with EINVAL. However, if the loopback is
the second or later association then everything continues to work. In other
words, the sequence

	connect(127.0.0.1), connect(8.8.8.8)

fails with EINVAL, but

	connect(8.8.8.8), connect(127.0.0.1), connect(1.2.3.4)

succeeds.

I admit that originally I simply presumed that on each reassociation the
kernel would handle reassociating the source address in addition to the
destination address. The technique worked everywhere I tested, including
Linux, Solaris, NetBSD, OpenBSD, FreeBSD. And I should note that it even
worked when reassociating to different external networks (and still works on
everything but Linux, AFAICT).

I realize now that arguably POSIX only requires that a second connnect call
change the destination address, and not the source address. But what would
be the point of allowing a reassociation if the source address is never
changed? Because any two addresses may route to entirely different networks
or over different devices, the capability to reassociate would be pointless.

OTOH, if you explicitly called bind before connect, most systems these days
will unbind the source address when reassociating. That may be undesirable
behavior, but it is long-standing behavior AFAICT, including on Linux. One
way to bypass the new Linux behavior is to reset the socket with
connect(AF_UNSPEC), but under the pedantic interpretation of POSIX that's
not guaranteed to work.

I first posted this issue on comp.unix.programmer, including example code.
The thread is at

https://groups.google.com/forum/?fromgroups=#!topic/comp.unix.programmer/ya0V-rr8ip0

Although it's hard to follow w/ Google's horrendous interface.

             reply	other threads:[~2013-03-16  6:12 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-03-16  5:56 William Ahern [this message]
2013-03-16 14:51 ` connect(2) reassociation regression Eric Dumazet
2013-03-16 20:39   ` William Ahern

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20130316055632.GA21364@wilbur.25thandClement.com \
    --to=william@25thandclement.com \
    --cc=netdev@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox