Thanks for the clarifications :)
As a bonus, when the user would give a host name to -l, it will
resolve to one or several addresses, and memcached will bind to them
all. This is natural, several addresses were connected to one host
name in DNS exactly with the purpose that they all will be used for
this name.
Still following to this point. That's what I figured.
IE; if someone wants to bind to a private-network in IPv4 land, they
presently use -l, but if you're binding by hostname in IPv6, it
makes sense (to me) to continue to allow someone to select a private
address.
There's no way for memcached to automatically distinct between private
and public address. You may relay on the address class, but the truth
is the whole public/private stuff for IPv4 is controlled by your NAT
configuration.
Right, but my point is the relatively unknown behavior of 'bind by
hostname' by the user. They might think 'bind by local hostname' and
it'll _always_ bind all addresses. I'm seeing room for both, especially
given the portability (fears? issues?).
The user will still have a full control if he gives IP address (v4 or
v6) to -l. It would make sense to allow several -l for flexibility
then. Right now I would have to create a DNS record for a set of
addresses I want to use, and then use -l set_name to bind to them all
(that is, if we process all results of getaddrinfo()).
Didn't someone send a patch to allow multiple -l's a while ago? :) Whoops.
Let me stress this again: first returned address is in no way special.
Or rather, it is special as it "has the best chances to succeed", but
this is more relevant to the client side. Actually the return order
may be configured for a site, and the first returned may be any of
loopback, site-local, or globally scoped address. More to that, since
getaddrinfo() can't know how you would use the address, for AI_PASSIVE
the address with "the best chances to succeed" is likely a global
externally visible address ;) (if you use host name, that is,
otherwise it will be INADDR_ANY or IN6ADDR_ANY_INIT). More to that,
there's the line in Drepper's:
Actually, it appears to be special for completely undefined reasons,
which bugs me for reasons only the esteemed Drepper understands. I get
"has the best chances to succeed" but given the constraints you're
establishing you have to iterate over _all_ of them _anyway_, so what's
the purpose in ordering it? Confusing.
Also, unfortunately, partially broken under different OS's?
Even if the system can accept IPv4 connection on IPv6 socket, as Linux
does, you have to bind IPv6 socket to an IPv4-mapped address
(otherwise you won't be able to connect with IPv4 address). As you
guess, there's no guarantee that the first returned address is such.
Nor any of them, I guess.
BTW, that "bug" of OS X 10.5 that was mentioned earlier may not be a
bug at all: if you iterate over all returned addresses, skipping those
you can't bind to, you'll eventually succeed (at least because there's
an IPv4 address down the list). So disabling IPv6 for UDP is an
incorrect workaround. This would also solve the problem with "older
glibc returns garbage".
That goes along with my above point of the whole order thing being
silly. I think disabling UDP isn't necessary tho; brian and I were
discussing it a little earlier.
Brian, if you have any pointers to papers describing the technique you
propose (use only the first address), sharing them would be very
appreciated. However, if that's your own invention, then I suggest
for memcached to stay with the mainstream and be as much secure as the
rest of the world, at least until this technique will be widely
recognized and adopted. Forever I guess... ;)
So actually, the most compelling argument is that memcached's code has
exactly two listener sockets, and no method for natively chaining them? :)
In fact, looking at it shows me it's broken it more subtle ways already.
Presently:
If you set a unix domain socket, tcp and udp are disabled.
tcp is always enabled (unless a unix domain socket is specified)
udp is optional
... and you can only bind one address to each.
So what I propose, right now, in order:
- Whatever minor cleanups are left to make the ipv6 bit work, including
tests that we can throw out.
- Merge it as-is, since you can't multibind without more work anyway.
- Add an option to allow disabling of tcp
- See if we can change the unix domain socket bit to not exclude tcp and
udp (I can see _someone_ wanting to use all three. This whole
discussion's about not restricting it). I'm loathe to change a "default"
tho, so maybe folks have good ideas.
- By "default" the ipv6 code will bind to the first address it finds.
- New option to allow multibinding, for ipv4, ipv6, list of IPs, list of
unix domain sockets, whatever.
Yes? No? I shut up now? :)
-Dormando