From Bugzilla Helper: User-Agent: Mozilla/5.0 (compatible; Konqueror/3.0.0-10; Linux) Description of problem: dhcpcd fails when sending first DHCPREQUEST *after* initial contact with server because it has closed the socket. It recovers by creating a new socket and sending a DHCPDISCOVER request, which (with ISC DHCP v3 server) will result in getting a new IP address because the old address is still valid, and the ping sent by the server is returned. The client accepts the new address and is fine. But any IPSEC tunnels are dead. A patch is included below. Version-Release number of selected component (if applicable): 1.3.22pl1 How reproducible: Always Steps to Reproduce: 1.Set DHCP server lease time to (say) 60 secs 2.Reboot client machine 3.Watch server logs for DHCPREQUEST then DHCPDISCOVER messages Actual Results: The client gets a new IP address Expected Results: The original lease should be renewed. Additional info: The problem is the client erroneously closes the socket to the server after it fork()s in dhcpcd.c - the presumption is that fd's 0 - 2 are open, which they are not, unless dhcpcd is being run manually. The following patch solves the problem by only closing the fd's if they were open at start up. I'm not an experienced patch user; I may have the original/fixed code the wrong way around ================================================== diff -r --context dhcpcd-1.3.22-pl1/dhcpcd.c my-dhcpcd-2.3.22-pl1/dhcpcd.c *** dhcpcd-1.3.22-pl1/dhcpcd.c Sun Jan 20 14:49:02 2002 --- my-dhcpcd-2.3.22-pl1/dhcpcd.c Fri Sep 20 15:18:35 2002 *************** *** 91,96 **** --- 91,109 ---- int s = 1; int k = 1; int i = 1; + + int openFd = 0; + int ii; + + /* Discover open fd's for brain dead close-all-standard-fd after fork()! */ + for( ii = 0; ii < 3; ++ii ) + { + struct stat sb; + + if( fstat( ii, &sb ) == 0 ) + openFd |= (1 << ii); + } + if ( getuid() ) { *************** *** 344,356 **** exit(0); /* got into bound state. */ } setsid(); ! if ( (i=open("/dev/null",O_RDWR,0)) >= 0 ) ! { ! (void)dup2(i,STDIN_FILENO); ! (void)dup2(i,STDOUT_FILENO); ! (void)dup2(i,STDERR_FILENO); ! if ( i > 2 ) (void)close(i); ! } #endif chdir("/"); do currState=(void *(*)())currState(); while ( currState ); --- 357,382 ---- exit(0); /* got into bound state. */ } setsid(); ! if( openFd ) ! { ! /* Only close standard fd's if they were open at the beginning. ! * Otherwise, we end up closing the socket to the server, and thus ! * the first lease renewal fails (bad socket!) and then we issue ! * a DHCPDISCOVER message, which causes the DHCP server to ping ! * us, and we respond, so the server thinks OUR current IP address ! * is in use, and so it issues a new IP address, which gets IPSEC really ! * confused. - lindsay. Sep 2002 ! */ ! if ( (i=open("/dev/null",O_RDWR,0)) >= 0 ) ! { ! for( ii = 0; ii < 2; ++ii ) ! { ! if( openFd & (1 <<ii) ) ! dup2(i, ii ); ! } ! if ( i > 2 ) (void)close(i); ! } ! } #endif chdir("/"); do currState=(void *(*)())currState(); while ( currState );
I just experienced this same problem. According to RFC2131, the server is well within its rights to do an ICMP ping to the IP address it's about to offer to the client before offering it and abandon it if it gets a response. So, given this, sending a DHCPDISCOVER message after a valid lease has been obtained can be catastrophic to any established network connections.
Sorry for not putting this in the last comment. You can see the DHCP client process failing to send data to the socket by the following messages in the syslog: Nov 8 11:03:49 feather dhcpcd[983]: sendto: Socket operation on non-socket Nov 8 11:03:49 feather dhcpcd[983]: sendto: Socket operation on non-socket Nov 8 11:03:49 feather dhcpcd[983]: dhcpStop: ioctl SIOCSIFADDR: Inappropriate ioctl for device Nov 8 11:03:49 feather dhcpcd[983]: dhcpStop: ioctl SIOCSIFFLAGS: Inappropriate ioctl for device
8.0 has dhclient instead - please give that a try.