Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 18 Jan 2004 13:19:58 -0800
From:      Saint Aardvark the Carpeted <aardvark@saintaardvarkthecarpeted.com>
To:        freebsd-questions@freebsd.org
Subject:   ypset(8) attempts to bind to Weird IP (and possible solution)
Message-ID:  <20040118211958.GP11291@hardesty.saintaardvarkthecarpeted.com>

next in thread | raw e-mail | index | archive | help
A while back I came across some strange behaviour with ypset(8).  I was
having trouble at work making a host bind to our NIS server, so I thought
I'd try using ypset.  When running these commands:

	domainname [domain]
	ypbind
	ypset -h localhost -d [domain] 192.168.0.254

and watching network traffic with tcpdump, I found UDP packets going
off to port 111 on an IP address I'd never seen before:  164.110.15.40.
As far as I could tell, it was trying to bind to the Weird IP (tm)
instead of our NIS server.

The domainname didn't seem to matter or change things; I tried both
the domain we use at work, and "foo" without any change in behaviour.
The same goes for the IP address I had specified, which was that of the
local NIS server.  The Weird IP was was completely unrelated to the local
network (192.168.0.0/24), and turns out to belong to the Washington
State Department of Transportation (!).  I tried this again at home,
and exactly the same behaviour was seen.

A couple days ago I decided to track this down, and found nearly the
same behaviour;  the difference is that this time, the Weird IP was
132.110.15.40, which turns out to belong to the US Army National Guard
Bureau (!!).  Again, that IP address is *completely* different from
anything on my local network or my public IP address.

This is all using 4.8-RELEASE; however, the relevant code for ypset
appears to be the same in 4.9-RELEASE.  Each test was done on a box
that had one interface, IP address 10.0.0.1, going to a gateway box
(10.0.0.254) with an external IP (192.168.0.100 at work, 192.168.23.254
at home).  I varied the IP addresses at home, but saw the same behaviour
each time.

To make a long story short, I compiled a debug version of ypset and stepped
through it with gdb.  I narrowed it down to this range of code:

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                  }

This chunk goes over the arguments to ypset; pretty much immediately
afterward, it calls bind_tohost() with sin as one of its arguments.

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.

ObDisclaimer:  I Am Not A Programmer, and my knowledge of C is pretty
slim.  But:  if I change lines 142/143 to:

	bcopy(&hent->h_addr_list[0][0], &sin.sin_addr, sizeof sin.sin_addr);

then the Weird IP doesn't show up in sin, and ypset only tries to bind
to the IP address listed in its arguments.

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.

*But*, as I mentioned, I'm no programmer.  I find it hard to believe
that I could pick up a mistake that simple, especially when I'm not
at all familiar with using sockets, or that this simple-seeming fix
wouldn't introduce more problems.

So -- what's going on?  Is this a real bug, or have I misunderstood
something?

Please let me know if I've left anything out, or if there's a better
place to ask this question.

Thanks for your time, everyone!

-- 
Saint Aardvark the Carpeted
aardvark@saintaardvarkthecarpeted.com
Because the plural of Anecdote is Myth.



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20040118211958.GP11291>