[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Re: broken IPv6 code



In article <[🔎] 84n1dcqjnq.fsf@snoopy.apana.org.au> (at 01 Jan 2001 10:02:17 +1100), Brian May <bam@debian.org> says:

> Then again, what is the correct way of doing this on Linux?
:
> [...]
> for (i = 0, a = ai; a != NULL; a = a->ai_next) {
>   fds[i] = socket (a->ai_family, a->ai_socktype, a->ai_protocol);
>   [...]
>   socket_set_reuseaddr (fds[i], 1);
>   [...]
>   bind (fds[i], a->ai_addr, a->ai_addrlen);
>   [...]
>   listen (fds[i], SOMAXCONN);
>   [...]
> }

If it ignores bind failure on ipv4 socket,  it is one of the most common 
way to make server socket(s).


> Is this wrong? If it is, then perhaps the link to the bad web page
> should be removed?

No.


I usually use codes like following ones for "loose" applications:

   memset(&hints, 0, sizeof(hints));
   hints.ai_family = PF_UNSPEC;
   hints.ai_socktype = SOCK_STREAM;
   gai = getaddrinfo(host, port, &hints, &res0);
   if (gai){
      err(1, "getaddrinfo() for host %s serv %s: %s",
             host ? host : "NULL", serv ? serv : "NULL,
	     gai_strerror(gai));
   }
   socklist = NULL; 
   socknum = 0;
   for (res=res0; res; res=res->ai_next){
      int s = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
      if (s < 0){
           warn("socket()");
           continue;
      }
      if (bind(s, res->ai_addr, res->ai_addrlen) < 0){
           warn("bind()");
	   close(s);
	   continue;
      }
      if (listen(s, 5) < 0){
           warn("listen()");
	   close(s);
	   continue;
      }
      newlist = realloc(sizeof(int) * (socknum+1));
      if (!newlist){
	   warn("realloc()");
	   close(s);
	   continue;
      }
      socklist = newlist;
      socklist[socknum++] = s;
  }
  if (!socknum){
      err(1, "cannot bind/listen to any socket");
  }


On systems whose ipv4 port number is separated from ipv6 one,
some "strict" application may want to exit bind failure because 
it indicates "real" failure on binding; other process running
on the same port.  They, such "strict" application, cannot be 
portable and autoconf (or runtime option) is needed; to give them
knowledge of bind(2) behavior.


For strict applications, we must consider 3 things (at least):

 A.bind behavior
    1) bind for ipv6
    2) bind for ipv4
    3) bind for ipv6 -> bind for ipv4
    4) bind for ipv4 -> bind for ipv6
    5) others
 B.traffic delivery for each A.
    1) ipv4 traffic
    2) ipv6 traffic
    3) others
 C.getaddrinfo behvior
    1) ipv6->ipv4
    2) ipv4->ipv6
    3) others


One solution is that; first, do bind ipv6 to wildcard, 
and next, bind ipv4 sockets to each ipv4 address assigned 
to the node.  This is the ISC bind's solution, but nasty... sigh.

-- 
Hideaki YOSHIFUJI @ USAGI Project  <yoshfuji@linux-ipv6.org>
PGP5i FP: F731 6599 5EB2 BBA7 1515  1323 1806 A96F 5700 6B25 



Reply to: