BIND 10 #353: Move function 'check_port()' and 'check_addr()' to one library
BIND 10 Development
do-not-reply at isc.org
Sun Oct 17 06:47:29 UTC 2010
#353: Move function 'check_port()' and 'check_addr()' to one library
-------------------------------+--------------------------------------------
Reporter: zhanglikun | Owner: vorner
Type: enhancement | Status: reviewing
Priority: major | Milestone:
Component: Unclassified | Resolution:
Keywords: | Sensitive: 0
Estimatedhours: 0.0 | Hours: 0
Billable: 1 | Totalhours: 0
Internal: 0 |
-------------------------------+--------------------------------------------
Changes (by jinmei):
* owner: jinmei => vorner
Comment:
Replying to [comment:6 vorner]:
> I modified the function to guess first by a regular expression which
version of address it is. This saves one call to inet_ntop() that fails in
case of IPv6 address and should workaround about this problem as a
sideeffect. Could you run the tests once more and see if it really does? I
don't have MacOS.
>
The offending test now passes on MacOS X.
Understanding it may be controversial, however, I always wonder why some
people tend to write in-house versions of this type of parser (e.g., by
using a regular expression) while the standard getaddrinfo() library is
provided exactly for this purpose.
Regular expressions are often difficult to understand for many people,
which is in itself against one major goal of BIND 10: better code
understandability. And, in general, in-house code tends to more errors
than carefully written and widely deployed standard libraries (which is
why I believe the "NIH syndrome" is considered a bad practice). In fact,
the regular expression "isv6" has a minor bug: it cannot recognize the
third form of IPv6 textual representation as defined in Section 2.2 of
RFC4291: It incorrectly rejects forms like "::ffff:192.0.2.1" or
"2001:4f8:3:bb::0.0.0.5" (yes, the latter form is a valid representation
even though it's quite unlikely to see the latter form in practice).
Admittedly, standard libraries are not always correct (just like we saw it
in OS X's inet_pton()), but if we use it as an excuse to introduce an in-
house partial parser, we should end up even replacing inet_pton() with an
in-house complete parser.
So, my suggestion is:
- ignore the buggy behavior of MacOS. it should be a minor and rare
error anyway, so IMO it's not worth making our implementation more
complicated and less understandable. If we want to ensure this type of
bogus string be rejected in other platforms, I'd rather move the
complexity to the test code, e.g.:
{{{
try:
# XXX: MacOS X's inet_pton() doesn't reject this form, so we
# check the behavior of the underlying library implementation
# before the actual test
socket.inet_pton(socket.AF_INET, "0000.0.0.0")
except socket.error:
self.assertRaises(ValueError, addr_parse, "0000.0.0.0")
}}}
- then, independently from how to address the buggy inet_pton() behavior,
if we want to save the unnecessary call to inet_pton() for IPv6, use
socket.getaddrinfo(), e.g.:
{{{
try:
addrinfo = socket.getaddrinfo(addr, None)[0]
self.family = addrinfo[0]
# (we could avoid the call to inet_pton() if it's okay to just
# hold the string address or address tuple)
self.addr = socket.inet_pton(self.family, addrinfo[4][0])
except socket.error as e:
raise InvalidAddress(str(e))
}}}
> > I also have following minor comments. I'd leave it to you whether and
how to address these points.
> > - port_check()/addr_check() may not be a good name (and in that sense
check.py, too) because xxx_check() sounds like performing a check only and
it's not intuitive for it to return something
>
> I changed it to _parse, which can be expected to complain if it is
invalid. Does it seem better?
>
Yes, I think so.
> > - it's not clear that IPAddr() raises socket.error against an invalid
input (unless you read the source code, and has knowledge that inet_pton()
raises that exception on failure). Please at least describe it in the
function description, and it's probably better to use a user-defined
specific exception.
>
> Added and documented.
>
Confirmed.
> > - in check_test.py, you assume specific output of inet_ntop(), but as
far as I know it's implementation dependent (although we may expect a
"canonical form" with future implementation due to RFC5952).
>
> I left it there. For one, I do not see any simple way to check it works.
For another, even if it is implementation dependent, the canonical form
(which I hope I put there) seems the only reasonable thing it could return
and I guess there's no system that would return something else. If there
is, the only thing that happens would be a false positive of the test (it
would fail even when it shouldn't), which is better than the other way
around. Would you mind if it is left there until we actually find a system
that returns something else?
>
That's fine for me, but I'd suggest commenting on it in the test code.
--
Ticket URL: <https://bind10.isc.org/ticket/353#comment:7>
BIND 10 Development <http://bind10.isc.org>
BIND 10 Development
More information about the bind10-tickets
mailing list