Path: utzoo!attcan!uunet!cs.utexas.edu!tut.cis.ohio-state.edu!husc6!rice!sun-spots-request From: steve@umiacs.umd.edu Newsgroups: comp.sys.sun Subject: ftp problems Keywords: SunOS Message-ID: <8905191218.AA06620@fnord.umiacs.UMD.EDU> Date: 19 May 89 12:18:00 GMT Sender: usenet@rice.edu Organization: Sun-Spots Lines: 90 Approved: Sun-Spots@rice.edu X-Sun-Spots-Digest: Volume 7, Issue 299, message 8 of 13 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@mimsy.umd.edu UUCP: uunet!mimsy!steve Phone: +1-301-454-1808 USPS: UMIACS, Univ. of Maryland, College Park, MD 20742