home *** CD-ROM | disk | FTP | other *** search
/ NetNews Usenet Archive 1992 #26 / NN_1992_26.iso / spool / comp / unix / internal / 1935 next >
Encoding:
Internet Message Format  |  1992-11-04  |  3.5 KB

  1. Path: sparky!uunet!charon.amdahl.com!pacbell.com!decwrl!sun-barr!ames!agate!dog.ee.lbl.gov!horse.ee.lbl.gov!torek
  2. From: torek@horse.ee.lbl.gov (Chris Torek)
  3. Newsgroups: comp.unix.internals
  4. Subject: Re: A problem in bind() system call.Help!
  5. Date: 5 Nov 1992 06:04:15 GMT
  6. Organization: Lawrence Berkeley Laboratory, Berkeley
  7. Lines: 82
  8. Message-ID: <27240@dog.ee.lbl.gov>
  9. References: <mahesh.720064067@depot.cis.ksu.edu.cis.ksu.edu> <1992Nov4.192429.10342@wuecl.wustl.edu>
  10. Reply-To: torek@horse.ee.lbl.gov (Chris Torek)
  11. NNTP-Posting-Host: 128.3.112.15
  12.  
  13. In article <1992Nov4.192429.10342@wuecl.wustl.edu> pete@arl.wustl.edu writes:
  14. >... I tried to use SO_REUSEADDR as well, but I believe it doesn't work in
  15. >all cases.
  16.  
  17. Oddly enough, I just looked into something similar today.
  18.  
  19. SO_REUSEADDR is rather broken.  It does work for special cases.
  20.  
  21. The current 4BSD kernel---recent SunOS releases are similar---has this
  22. code in in_pcbbind():
  23.  
  24.     if ((so->so_options & SO_REUSEADDR) == 0 &&
  25.         ((so->so_proto->pr_flags & PR_CONNREQUIRED) == 0 ||
  26.          (so->so_options & SO_ACCEPTCONN) == 0))
  27.         wild = INPLOOKUP_WILDCARD;
  28.     if (in_pcblookup(..., sin->sin_addr, lport, wild))
  29.         return (EADDRINUSE);
  30.  
  31. The `wild' flag tells in_pcblookup to include all TCP or UDP sockets,
  32. rather than only those `listening'.  This is often desirable since a
  33. unique <laddr,lport> pair automatically guarantees that the 4-tuple
  34. <laddr,lport,faddr,fport> will be unique.  (TCP and UDP require the
  35. latter.)  At the time of the bind() call, the <faddr,fport> portion are
  36. unknown.
  37.  
  38. (This suggests---rather appropriately, actually---that the system
  39. really should have a combined bind and connect call, in which one of
  40. the two addresses is optional.  Then the kernel would usually have all
  41. the information it needs to pass judgement on the four-tuple, rather
  42. than having to second-guess two elements, or apply too-inclusive tests
  43. to the <laddr,lport> portion, as it does now.  But never mind that.)
  44.  
  45. The tests in in_pcbbind() use a `wildcard' lookup if:
  46.  
  47.     a) you did not set SO_REUSEADDR, and:
  48.         b1) this is a UDP socket (not PR_CONNREQUIRED), or:
  49.         b2) you have not yet done a listen() call.
  50.  
  51. Point b2) is most peculiar, because the `standard' method of writing a
  52. tcp server is:
  53.  
  54.     s = socket(...);
  55.     if (s < 0) ERROR
  56.     if (bind(s, ...)) ERROR
  57.     if (listen(s, 5)) ERROR
  58.     for (;;) {
  59.         s2 = accept(s, ...);
  60.         if (s2 < 0) ERROR
  61.         ...
  62.     }
  63.  
  64. If you put a listen() call before the bind(), it does its own internal
  65. bind(), and the system assigns you a port number.  This is only OK if
  66. you use a `service number service' a la Sun's portmap.  Even then,
  67. SO_ACCEPTCONN will not be set in in_pcbbind(), because listen() sets it
  68. *after* the internal bind.  Hence, this is effectively the same as:
  69.  
  70.     if (!SO_REUSEADDR && (is_udp || 1))
  71.         wild = INPLOOKUP_WILDCARD;
  72.  
  73. or just
  74.  
  75.     if (!SO_REUSEADDR)
  76.  
  77. Thus, all SO_REUSEADDR does is prevent setting INPLOOKUP_WILDCARD, and
  78. we can concentrate on the logic (or lack thereof?) in in_pcblookup.  It
  79. is long and twisty, but it boils down to one thing in the case of TCP
  80. servers:
  81.  
  82.  *** If you specify a local address (other than 0) in your bind()
  83.  *** call, SO_REUSEADDR will have no effect.
  84.  
  85. The code really ought to say
  86.  
  87.     if ((so->so_state & SO_REUSEADDR) == 0 && in_pcblookup(...))
  88.         return (EADDRINUSE);
  89.  
  90. and programmers who use SO_REUSEADDR should expect to get EADDRINUSE
  91. errors from connect() whenever they do not get a unique 4-tuple.
  92. -- 
  93. In-Real-Life: Chris Torek, Lawrence Berkeley Lab CSE/EE (+1 510 486 5427)
  94. Berkeley, CA        Domain:    torek@ee.lbl.gov
  95.