bin/62550: [patch] bug in ypset(8) causes attempt to bind to weird
IP addresses
Saint Aardvark the Carpeted
aardvark at saintaardvarkthecarpeted.com
Sun Feb 8 13:30:16 PST 2004
>Number: 62550
>Category: bin
>Synopsis: [patch] bug in ypset(8) causes attempt to bind to weird IP addresses
>Confidential: no
>Severity: non-critical
>Priority: low
>Responsible: freebsd-bugs
>State: open
>Quarter:
>Keywords:
>Date-Required:
>Class: sw-bug
>Submitter-Id: current-users
>Arrival-Date: Sun Feb 08 13:30:15 PST 2004
>Closed-Date:
>Last-Modified:
>Originator: Saint Aardvark the Carpeted
>Release: FreeBSD 4.9-RELEASE i386
>Organization:
>Environment:
System: FreeBSD 4.9-RELEASE FreeBSD 4.9-RELEASE #0: Mon Oct 27 17:51:09 GMT 2003 root at freebsd-stable.sentex.ca:/usr/obj/usr/src/sys/GENERIC i386
I've seen this in two separate environments:
Internal box: Pentium 4 running 4.8-PRERELEASE on a private
network (10.0.0.0/24) within another private network
(192.168.0.0/24); default gateway has two interfaces, and
forwards traffic from 10.0.0.0/24 to its gateway (192.168.0.1),
which in turn does NAT and is connected to the Internet
Pentium 2 ("Dagny") running either 4.8-RELEASE or 4.9-RELEASE
on private network (10.0.1.0/24) connected to NAT/firewall
box ("Francisco") with three interfaces (ep1 -- 10.0.1.254
attached to Dagny via crossover cable; vr0 -- 192.168.23.254
going to the rest of my home network; xl0 -- external
interface attached to cable Internet connection)
The first setup is at my job, and is where I first noticed this
behaviour. I don't have access to it to duplicate it -- I'm just
mentioning it to show that it's not solely my home network. The
second is my home network, and I'm able to do what I like with it.
>Description:
ypset(8) attempts to bind to strange IP addresses when told to try
binding to NIS server on private IP address (192.168.0.2 in first
example, 192.168.23.254 in second example). I've seen three different
IP addresses:
164.110.15.40, which belongs to the Washington State
Department of Transportation
132.110.15.40, which belongs to the US Army National Guard
Bureau
164.113.15.40, which belongs to the Kansas Research and
Education Network
(Information from "whois -a <ip address>").
>How-To-Repeat:
Francisco: ifconfig ep1 10.0.1.254 netmask 255.255.255.0
domainname foo
ypserv
(natd already running)
Dagny: ifconfig ep1 10.0.1.1 netmask 255.255.255.0
route add default 10.0.1.254
ypset -h localhost -d foo 192.168.23.254
Francisco: "tcpdump -n -i ep1 port not 22" shows:
14:14:15.779438 10.0.1.1.1003 > 192.168.23.254.111: udp 56
14:14:15.782620 10.0.1.254.111 > 10.0.1.1.1003: udp 28
14:14:15.783349 10.0.1.1.1002 > 164.113.15.40.111: udp 56
14:14:15.884530 164.113.221.114 > 10.0.1.1: icmp: host 164.113.15.40 unreachable
Packets continue to go to 164.113.15.40 for about a minute; after
this, ypset on Dagny exits with this error message:
ypset: can't yp_bind, reason: Can't communicate with ypbind
This example is with Dagny running 4.9-RELEASE; the same behaviour
is seen with 4.8-RELEASE except that the strange IP is 132.110.15.40,
and there was no "icmp unreachable" response. When I first saw
this at work (4.8-PRERELEASE), the strange IP was 164.110.15.40.
None of these numbers are remotely close to any of the private
networks in use, nor to the public IP addresses of the machines
that were connected to the Internet.
I compiled a debug version of ypset and stepped through it with
gdb. I narrowed it down to this range of code in /usr/src/usr.sbin/ypset/ypset.c:
120 struct hostent *hent;
[snip]
130 sin.sin_addr.s_addr = htonl(0x7f000001);
131
132 while ((c = getopt(argc, argv, "h:d:")) != -1)
133 switch (c) {
134 case 'd':
135 domainname = optarg;
136 break;
137 case 'h':
138 if ((sin.sin_addr.s_addr = inet_addr(optarg)) == -1) {
139 hent = gethostbyname(optarg);
140 if (hent == NULL)
141 errx(1, "host %s unknown", optarg);
142 bcopy(&hent->h_addr_list[0], &sin.sin_addr,
143 sizeof sin.sin_addr);
144 }
145 break;
146 default:
147 usage();
148 }
The CVS tag for ypset.c was:
#ifndef lint
static const char rcsid[] =
"$FreeBSD: src/usr.sbin/ypset/ypset.c,v 1.5.2.2 2002/02/15 00:47:00 des Exp $";
#endif /* not lint */
This chunk goes over the arguments to ypset; pretty much immediately
afterward, it calls bind_tohost() with sin as one of its arguments.
To print hent->h_addr_list[0], I ran this in gdb:
p (unsigned char)hp->h_addr_list[0][n]
I changed n from 0 to 3; this printed out the numbers in the IP address,
dotted-quad form without the dots. For example, if h_addr_list had
127.0.0.1, I would see 127, then 0, then 0, then 1. To print out
sin.sin_addr.s_addr, I ran:
p (unsigned char)((char *)&(sin.sin_addr.s_addr))[n]
in gdb. Again, n went from 0 to 3.
The problem seems to come in at lines 142/143: before this,
sin.sin_addr.s_addr is localhost (as set at line 130), as is
hent->h_addr_list[0][0]. *After* this, it's set with the Weird IP,
bind_tohost() is called, and packets go off to the Weird IP.
Looking through man pages and header files, it looks like
hostent->h_addr_list is an array of pointers to chars (is that the
right term?):
char **h_addr_list
and so gethostbyname is returning the IP address as the *first entry*
in that list. It makes sense to me, then, that bcopy should have
h_addr_list[0][0] as its first argument.
>Fix:
If I apply this patch:
--- /usr/src/usr.sbin/ypset/ypset.c Sun Feb 8 14:10:38 2004
+++ /tmp/ypset.c Sun Feb 8 14:10:30 2004
@@ -139,7 +139,7 @@
hent = gethostbyname(optarg);
if (hent == NULL)
errx(1, "host %s unknown", optarg);
- bcopy(&hent->h_addr_list[0], &sin.sin_addr,
+ bcopy(hent->h_addr_list[0], &sin.sin_addr,
sizeof sin.sin_addr);
}
break;
then the Weird IP doesn't show up in sin, and ypset only tries to bind
to the IP address listed in its arguments.
This is against ypset.c with the CVS tag described above, which is
part of 4.9-RELEASE; however, it looks like this line is the same
in 1.13, which is the version in HEAD.
Please let me know if I've missed anything or can provide any more
information.
--- pr ends here ---
>Release-Note:
>Audit-Trail:
>Unformatted:
More information about the freebsd-bugs
mailing list