Bug 74348

Summary: dhcpcd fails first attempt to renew lease
Product: [Retired] Red Hat Linux Reporter: lindsay
Component: dhcpcdAssignee: Elliot Lee <sopwith>
Status: CLOSED CURRENTRELEASE QA Contact:
Severity: medium Docs Contact:
Priority: medium    
Version: 7.3   
Target Milestone: ---   
Target Release: ---   
Hardware: i686   
OS: Linux   
Whiteboard:
Fixed In Version: Doc Type: Bug Fix
Doc Text:
Story Points: ---
Clone Of: Environment:
Last Closed: 2003-01-13 18:04:30 UTC Type: ---
Regression: --- Mount Type: ---
Documentation: --- CRM:
Verified Versions: Category: ---
oVirt Team: --- RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: --- Target Upstream Version:
Embargoed:

Description lindsay 2002-09-20 22:47:23 UTC
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 
);

Comment 1 mgriego 2002-11-08 19:30:00 UTC
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.

Comment 2 mgriego 2002-11-08 19:32:02 UTC
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 


Comment 3 Elliot Lee 2003-01-13 18:04:30 UTC
8.0 has dhclient instead - please give that a try.