home *** CD-ROM | disk | FTP | other *** search
- Path: sparky!uunet!charon.amdahl.com!pacbell.com!decwrl!sun-barr!ames!agate!dog.ee.lbl.gov!horse.ee.lbl.gov!torek
- From: torek@horse.ee.lbl.gov (Chris Torek)
- Newsgroups: comp.unix.internals
- Subject: Re: A problem in bind() system call.Help!
- Date: 5 Nov 1992 06:04:15 GMT
- Organization: Lawrence Berkeley Laboratory, Berkeley
- Lines: 82
- Message-ID: <27240@dog.ee.lbl.gov>
- References: <mahesh.720064067@depot.cis.ksu.edu.cis.ksu.edu> <1992Nov4.192429.10342@wuecl.wustl.edu>
- Reply-To: torek@horse.ee.lbl.gov (Chris Torek)
- NNTP-Posting-Host: 128.3.112.15
-
- In article <1992Nov4.192429.10342@wuecl.wustl.edu> pete@arl.wustl.edu writes:
- >... I tried to use SO_REUSEADDR as well, but I believe it doesn't work in
- >all cases.
-
- Oddly enough, I just looked into something similar today.
-
- SO_REUSEADDR is rather broken. It does work for special cases.
-
- The current 4BSD kernel---recent SunOS releases are similar---has this
- code in in_pcbbind():
-
- if ((so->so_options & SO_REUSEADDR) == 0 &&
- ((so->so_proto->pr_flags & PR_CONNREQUIRED) == 0 ||
- (so->so_options & SO_ACCEPTCONN) == 0))
- wild = INPLOOKUP_WILDCARD;
- if (in_pcblookup(..., sin->sin_addr, lport, wild))
- return (EADDRINUSE);
-
- The `wild' flag tells in_pcblookup to include all TCP or UDP sockets,
- rather than only those `listening'. This is often desirable since a
- unique <laddr,lport> pair automatically guarantees that the 4-tuple
- <laddr,lport,faddr,fport> will be unique. (TCP and UDP require the
- latter.) At the time of the bind() call, the <faddr,fport> portion are
- unknown.
-
- (This suggests---rather appropriately, actually---that the system
- really should have a combined bind and connect call, in which one of
- the two addresses is optional. Then the kernel would usually have all
- the information it needs to pass judgement on the four-tuple, rather
- than having to second-guess two elements, or apply too-inclusive tests
- to the <laddr,lport> portion, as it does now. But never mind that.)
-
- The tests in in_pcbbind() use a `wildcard' lookup if:
-
- a) you did not set SO_REUSEADDR, and:
- b1) this is a UDP socket (not PR_CONNREQUIRED), or:
- b2) you have not yet done a listen() call.
-
- Point b2) is most peculiar, because the `standard' method of writing a
- tcp server is:
-
- s = socket(...);
- if (s < 0) ERROR
- if (bind(s, ...)) ERROR
- if (listen(s, 5)) ERROR
- for (;;) {
- s2 = accept(s, ...);
- if (s2 < 0) ERROR
- ...
- }
-
- If you put a listen() call before the bind(), it does its own internal
- bind(), and the system assigns you a port number. This is only OK if
- you use a `service number service' a la Sun's portmap. Even then,
- SO_ACCEPTCONN will not be set in in_pcbbind(), because listen() sets it
- *after* the internal bind. Hence, this is effectively the same as:
-
- if (!SO_REUSEADDR && (is_udp || 1))
- wild = INPLOOKUP_WILDCARD;
-
- or just
-
- if (!SO_REUSEADDR)
-
- Thus, all SO_REUSEADDR does is prevent setting INPLOOKUP_WILDCARD, and
- we can concentrate on the logic (or lack thereof?) in in_pcblookup. It
- is long and twisty, but it boils down to one thing in the case of TCP
- servers:
-
- *** If you specify a local address (other than 0) in your bind()
- *** call, SO_REUSEADDR will have no effect.
-
- The code really ought to say
-
- if ((so->so_state & SO_REUSEADDR) == 0 && in_pcblookup(...))
- return (EADDRINUSE);
-
- and programmers who use SO_REUSEADDR should expect to get EADDRINUSE
- errors from connect() whenever they do not get a unique 4-tuple.
- --
- In-Real-Life: Chris Torek, Lawrence Berkeley Lab CSE/EE (+1 510 486 5427)
- Berkeley, CA Domain: torek@ee.lbl.gov
-