This is the mail archive of the ecos-discuss@sources.redhat.com mailing list for the eCos project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Re: dhcp XID generation



Robin Farine <acnrf@dial.eunet.ch> writes:

> Hi Hugo,
> 
> If the method to generate the XID seems suitable then here follows trial
> number 3 (hopefully correct this time :-/):

Nice one, thanks Robin; here's what I actually committed.  Your patch plus
a hack to arc4random().

	- Huge

Index: net/tcpip/current//ChangeLog
===================================================================
RCS file: /home/cvs/ecc/ecc/net/tcpip/current/ChangeLog,v
retrieving revision 1.122
diff -u -5 -p -r1.122 ChangeLog
--- net/tcpip/current//ChangeLog	2001/05/09 16:35:12	1.122
+++ net/tcpip/current//ChangeLog	2001/05/09 17:15:03
@@ -1,8 +1,21 @@
 2001-05-09  Robin Farine <acnrf@dial.eunet.ch>
 2001-05-09  Hugo Tyson  <hmt@redhat.com>
 
+	* src/lib/dhcp_prot.c (do_dhcp): In DHCPSTATE_INIT case, create a
+	new xid.  Servers apparantly can use *only* this to distinguish
+	machines, even with different MAC addresses!  Therefore we use
+	both the most sensitive randomizer available (arc4random()) which
+	in reality uses a finegrain clock, and salt the value further with
+	the MAC address itself.  Thanks again Robin.
+
+	* src/ecos/support.c (arc4random): Make arc4random not always be a
+	multiple of 256; stir the clock into the low bits also.
+
+2001-05-09  Robin Farine <acnrf@dial.eunet.ch>
+2001-05-09  Hugo Tyson  <hmt@redhat.com>
+
 	* src/sys/net/if_bridge.c: Patch from Robin; the route aging
 	process took twice as long to timeout because an entry requires
 	*two* executions of bridge_rtage() to actually get removed.
 	Record the timeout over 2 to fix that and also define
 	BRIDGE_RTABLE_TIMEOUT as 300s that the standard specifies as
Index: net/tcpip/current//src/ecos/support.c
===================================================================
RCS file: /home/cvs/ecc/ecc/net/tcpip/current/src/ecos/support.c,v
retrieving revision 1.24
diff -u -5 -p -r1.24 support.c
--- net/tcpip/current//src/ecos/support.c	2001/01/08 02:41:04	1.24
+++ net/tcpip/current//src/ecos/support.c	2001/05/09 17:15:03
@@ -341,11 +341,11 @@ int cyg_net_get_mem_stats( int which, cy
             cyg_mempool_fix_get_info( net_clusters, p );
             break;
         default:
             return 0;
         }
-    return p;
+    return (int)p;
 }
 
 int
 cyg_mtocl(u_long x)
 {
@@ -382,14 +382,14 @@ net_memset(void *s, int v, int n)
 int
 arc4random(void)
 {
     cyg_uint32 res;
     static unsigned long seed = 0xDEADB00B;
-    HAL_CLOCK_READ(&res);  // Not so bad...
-    seed = ((seed & 0x07F00FF) << 7) ^
-        (seed & 0xF80FF00) ^ 
-        (res << 13);
+    HAL_CLOCK_READ(&res);  // Not so bad... (but often 0..N where N is small)
+    seed = ((seed & 0x007F00FF) << 7) ^
+        ((seed & 0x0F80FF00) >> 8) ^ // be sure to stir those low bits
+        (res << 13) ^ (res >> 9);    // using the clock too!
     return (int)seed;
 }
 
 void 
 get_random_bytes(void *buf, size_t len)
Index: net/tcpip/current//src/lib/dhcp_prot.c
===================================================================
RCS file: /home/cvs/ecc/ecc/net/tcpip/current/src/lib/dhcp_prot.c,v
retrieving revision 1.6
diff -u -5 -p -r1.6 dhcp_prot.c
--- net/tcpip/current//src/lib/dhcp_prot.c	2001/01/03 18:45:17	1.6
+++ net/tcpip/current//src/lib/dhcp_prot.c	2001/05/09 17:15:04
@@ -391,15 +391,13 @@ do_dhcp(const char *intf, struct bootp *
          || DHCPSTATE_FAILED == oldstate
          || 0                == oldstate ) {
         // either explicit init state or the beginning of time or retry
         if ( ! bring_half_up( intf, &ifr ) )
             return false;
+
         *pstate = DHCPSTATE_INIT;
-        xid = (cyg_uint32)res + (cyg_uint32)(0xffffffff & cyg_current_time());
     }
-    else
-        xid = res->bp_xid; // use what's there already
 
     s = socket(AF_INET, SOCK_DGRAM, 0);
     if (s < 0) {
         perror("socket");
         return false;
@@ -442,10 +440,12 @@ do_dhcp(const char *intf, struct bootp *
     // be the neatest way to do it; it returns from within the switch arms
     // when all is well, or utterly failed.
 
     reset_timeout( &tv, &timeout_scratch );
 
+    xid = res->bp_xid; // default to what's there already;
+
     while ( 1 ) {
 
         // If we are active rather than in the process of shutting down,
         // check for any lease expiry every time round, so that alarms
         // *can* change the course of events even when already renewing,
@@ -483,10 +483,19 @@ do_dhcp(const char *intf, struct bootp *
             // Send the DHCPDISCOVER packet
 
             if (ioctl(s, SIOCGIFHWADDR, &ifr) < 0) { /* get MAC address */
                 perror("SIOCGIFHWADDR 2");
                 return false;
+            }
+
+            // generates a new XID
+            {
+                unsigned char* xp = (unsigned char*)&xid;
+
+                *xp++ = ifr.ifr_hwaddr.sa_data[5];
+                *xp++ = ifr.ifr_hwaddr.sa_data[4];
+                *((cyg_uint16*)xp) = (cyg_uint16)(arc4random() & 0xffff);
             }
 
             // Fill in the BOOTP request - DHCPDISCOVER packet
             bzero(xmit, sizeof(*xmit));
             xmit->bp_op = BOOTREQUEST;


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]