ftp problems

steve at umiacs.umd.edu steve at umiacs.umd.edu
Fri May 19 22:18:00 AEST 1989


If you haven't already, I *strongly* suggest that you look at the results
of the ifconfigs in /etc/rc.boot.  Even if everything seems to be set up
correctly, I suspect that the ifconfigs are all failing.

[ Those of you who have seen me prattle on about this before can stop
paying attention now.  Long-winded explanation follows.  Fine details may
vary, but the gist of what I say below is correct. ]

The time when I had this problem, I traced it down to the following
sequence of events:

	1) Diskless client boots, and kernel initializes the network
	interface data structures using RARP.  The network address
	in a 'struct ifnet' is a sockaddr, but RARP treats it as a
	sockaddr_in.  When the address is assigned to the interface by
	the RARP code, the last eight bytes of the sockaddr (the sin_zero
	part of a sockaddr_in) aren't zeroed.  So now we have as the
	interface address:

		sa_family: AF_INET
		sa_data[0,1]: zero (port doesn't matter)
		sa_data[2-5]: client's IP address
		sa_data[6-13]: garbage

	2) Diskless client tries (in rc.boot) to ifconfig the interface.
	Normally, the ifconfig succeeds, and the code path taken by
	the SIOCCSIFADDR ioctl makes good and damm sure that the sin_zero
	stuff is actually zero.  In this case, we'll assume that this is
	what's failing.

	3) Ftp does a getsockaddr() call on some socket at some point to
	get the address it's using.  This is stored in the myctladdr variable.
	Myctladdr looks like:

		sin_family: AF_INET
		sin_port: (doesn't matter here)
		sin_addr: client's IP address
		sin_zero: zeroed

	4) Ftp tries to bind the local data port.  It copies myctladdr into
	another variable (data_addr), sets the port to something or another,
	and then tries to bind this address.

	5) The kernel tries to find an interface matching this address.
	It puts the port number in a temporary, then sets the port number
	to zero.  It then does something like:


		for (each of our interfaces) {
			compare (with bcmp) the sockaddr we want to
				bind with the address on this interface
			if we find a match, use that interface
		}
		return(EADDRNOTAVAIL);

	   Note that this is in the network-independent part of the kernel, so
	the comparisons *have* to be done on a full sockaddr basis; the
	alternative is for the network-independent code to know something
	about each possible set of protocols built into the kernel.

	   Also note that we're comparing AF_INET to AF_INET, zero (port)
	to zero (port), the client's IP address to itself... and zeros to
	garbage.  The one interface that we *should* find in the loop
	above fails to match for this reason.

   The fix is (for SunOS 3.2, sigh):

	RCS file: RCS/if_ether.c,v
	retrieving revision 1.2
	retrieving revision 1.3
	diff -c -r1.2 -r1.3
	*** /tmp/,RCSt1a03203   Fri May 19 07:54:30 1989
	--- /tmp/,RCSt2a03203   Fri May 19 07:54:31 1989
	***************
	*** 501,506 ****
	--- 501,507 ----
	         * We need to give the interface a temporary address just
	         * so it gets initialized. Hopefully, the address won't get used.
	         */
	+       bzero((caddr_t)&temp, sizeof(temp));
	        sin->sin_family = AF_INET;
	        sin->sin_port = 0;

   Alternatively, making absolutely sure that the ifconfig works will solve
this problem.

	-Steve

Spoken: Steve Miller    Domain: steve at mimsy.umd.edu    UUCP: uunet!mimsy!steve
Phone: +1-301-454-1808  USPS: UMIACS, Univ. of Maryland, College Park, MD 20742



More information about the Comp.sys.sun mailing list