Bug 74348 - dhcpcd fails first attempt to renew lease
Summary: dhcpcd fails first attempt to renew lease
Keywords:
Status: CLOSED CURRENTRELEASE
Alias: None
Product: Red Hat Linux
Classification: Retired
Component: dhcpcd
Version: 7.3
Hardware: i686
OS: Linux
medium
medium
Target Milestone: ---
Assignee: Elliot Lee
QA Contact:
URL:
Whiteboard:
Depends On:
Blocks:
TreeView+ depends on / blocked
 
Reported: 2002-09-20 22:47 UTC by lindsay
Modified: 2008-05-01 15:38 UTC (History)
0 users

Fixed In Version:
Doc Type: Bug Fix
Doc Text:
Clone Of:
Environment:
Last Closed: 2003-01-13 18:04:30 UTC
Embargoed:


Attachments (Terms of Use)

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.


Note You need to log in before you can comment on or make changes to this bug.