BOOTP Support in BusyBox udhcp Client

Grant Erickson gerickson at nuovations.com
Tue Apr 8 01:17:23 UTC 2008


On 4/3/08 9:10 AM, Grant Erickson wrote:
> Sometime ago, in December 2002 to be exact, there was discussion of a patch
> submitted by Magnus Damm integrating BOOTP support into the udhcp client:
> 
>     http://www.busybox.net/lists/udhcp/2002-December/000002.html
> 
> However, it looks like as of BusyBox-1.9.1, this patch never made it into the
> mainline code base. Do you have any additional insight or background on what
> happened with the patch in the intervening five years?

For those interested, I've adapted the aforementioned patch to
BusyBox-1.9.1:

----

diff -aruN busybox-1.9.1/include/usage.h busybox-1.9.1.N/include/usage.h
--- busybox-1.9.1/include/usage.h    2008-02-12 08:03:10.000000000 -0800
+++ busybox-1.9.1.N/include/usage.h    2008-04-07 10:33:25.000000000 -0700
@@ -3839,13 +3839,14 @@
        "Adjust filesystem options on ext[23] filesystems"
 
 #define udhcpc_trivial_usage \
-       "[-Cfbnqtv] [-c CID] [-V VCLS] [-H HOSTNAME] [-i INTERFACE]\n" \
+       "[-BCfbnqtv] [-c CID] [-V VCLS] [-H HOSTNAME] [-i INTERFACE]\n" \
        "    [-p pidfile] [-r IP] [-s script] [-O dhcp-option]..."
 #define udhcpc_full_usage \
     USE_GETOPT_LONG( \
        "    -V,--vendorclass=CLASSID    Vendor class identifier" \
        "\n    -i,--interface=INTERFACE    Interface to use (default eth0)"
\
        "\n    -H,-h,--hostname=HOSTNAME    Client hostname" \
+       "\n    -B,--bootp        Operate as bootp-only client" \
        "\n    -c,--clientid=CLIENTID    Client identifier" \
        "\n    -C,--clientid-none    Suppress default client identifier" \
        "\n    -p,--pidfile=file    Create pidfile" \
diff -aruN busybox-1.9.1/networking/udhcp/clientpacket.c
busybox-1.9.1.N/networking/udhcp/clientpacket.c
--- busybox-1.9.1/networking/udhcp/clientpacket.c    2008-02-12
08:03:00.000000000 -0800
+++ busybox-1.9.1.N/networking/udhcp/clientpacket.c    2008-04-07
10:33:25.000000000 -0700
@@ -38,11 +38,11 @@
 
 
 /* initialize a packet with the proper defaults */
-static void init_packet(struct dhcpMessage *packet, char type)
+static void init_packet(struct dhcpMessage *packet, char op, char type)
 {
-    udhcp_init_header(packet, type);
+    udhcp_init_header(packet, op, type);
     memcpy(packet->chaddr, client_config.arp, 6);
-    if (client_config.clientid)
+    if (client_config.clientid && type)
         add_option_string(packet->options, client_config.clientid);
     if (client_config.hostname)
         add_option_string(packet->options, client_config.hostname);
@@ -80,7 +80,7 @@
 {
     struct dhcpMessage packet;
 
-    init_packet(&packet, DHCPDECLINE);
+    init_packet(&packet, 0, DHCPDECLINE);
     packet.xid = xid;
     add_requests(&packet);
 
@@ -96,10 +96,19 @@
 {
     struct dhcpMessage packet;
 
-    init_packet(&packet, DHCPDISCOVER);
+    if (client_config.bootp) {
+        init_packet(&packet, BOOTREQUEST, 0);
+        if (requested) {
+            packet.ciaddr = requested; /* already in network order */
+        }
+
+    } else {
+        init_packet(&packet, 0, DHCPDISCOVER);
+        if (requested)
+            add_simple_option(packet.options, DHCP_REQUESTED_IP,
requested);
+
+    }
     packet.xid = xid;
-    if (requested)
-        add_simple_option(packet.options, DHCP_REQUESTED_IP, requested);
 
     /* Explicitly saying that we want RFC-compliant packets helps
      * some buggy DHCP servers to NOT send bigger packets */
@@ -117,7 +126,7 @@
     struct dhcpMessage packet;
     struct in_addr addr;
 
-    init_packet(&packet, DHCPREQUEST);
+    init_packet(&packet, 0, DHCPREQUEST);
     packet.xid = xid;
 
     add_simple_option(packet.options, DHCP_REQUESTED_IP, requested);
@@ -136,7 +145,7 @@
 {
     struct dhcpMessage packet;
 
-    init_packet(&packet, DHCPREQUEST);
+    init_packet(&packet, 0, DHCPREQUEST);
     packet.xid = xid;
     packet.ciaddr = ciaddr;
 
@@ -155,7 +164,7 @@
 {
     struct dhcpMessage packet;
 
-    init_packet(&packet, DHCPRELEASE);
+    init_packet(&packet, 0, DHCPRELEASE);
     packet.xid = random_xid();
     packet.ciaddr = ciaddr;
 
@@ -227,10 +236,6 @@
 
     memcpy(payload, &packet.data, bytes - (sizeof(packet.ip) +
sizeof(packet.udp)));
 
-    if (payload->cookie != htonl(DHCP_MAGIC)) {
-        bb_error_msg("received bogus message (bad magic) - ignoring");
-        return -2;
-    }
     DEBUG("Got valid DHCP packet");
     return bytes - (sizeof(packet.ip) + sizeof(packet.udp));
 }
diff -aruN busybox-1.9.1/networking/udhcp/common.h
busybox-1.9.1.N/networking/udhcp/common.h
--- busybox-1.9.1/networking/udhcp/common.h    2008-02-12 08:03:01.000000000
-0800
+++ busybox-1.9.1.N/networking/udhcp/common.h    2008-04-07
10:33:25.000000000 -0700
@@ -56,7 +56,7 @@
 
 uint16_t udhcp_checksum(void *addr, int count);
 
-void udhcp_init_header(struct dhcpMessage *packet, char type);
+void udhcp_init_header(struct dhcpMessage *packet, char op, char type);
 
 int udhcp_recv_packet(struct dhcpMessage *packet, int fd);
 int udhcp_send_raw_packet(struct dhcpMessage *payload,
diff -aruN busybox-1.9.1/networking/udhcp/dhcpc.c
busybox-1.9.1.N/networking/udhcp/dhcpc.c
--- busybox-1.9.1/networking/udhcp/dhcpc.c    2008-02-12 08:03:01.000000000
-0800
+++ busybox-1.9.1.N/networking/udhcp/dhcpc.c    2008-04-07
11:06:25.000000000 -0700
@@ -181,6 +181,7 @@
         OPT_a = 1 << 20,
         OPT_W = 1 << 21,
 #endif
+        OPT_B = 1 << 22,
     };
 #if ENABLE_GETOPT_LONG
     static const char udhcpc_longopts[] ALIGN1 =
@@ -206,6 +207,7 @@
 #if ENABLE_FEATURE_UDHCPC_ARPING
         "arping\0"         No_argument       "a"
 #endif
+        "bootp\0"           No_argument         "B"
         "request-option\0" Required_argument "O"
         ;
 #endif
@@ -220,7 +222,7 @@
 #endif
     opt = getopt32(argv, "c:CV:fbH:h:F:i:np:qRr:s:T:t:vSA:"
         USE_FEATURE_UDHCPC_ARPING("aW:")
-        "O:"
+        "BO:"
         , &str_c, &str_V, &str_h, &str_h, &str_F
         , &client_config.interface, &client_config.pidfile, &str_r
         , &client_config.script, &str_T, &str_t, &str_A
@@ -276,6 +278,9 @@
         openlog(applet_name, LOG_PID, LOG_LOCAL0);
         logmode |= LOGMODE_SYSLOG;
     }
+    if (opt & OPT_B) {
+        client_config.bootp = 1;
+    }
     while (list_O) {
         int n = index_in_strings(dhcp_option_strings, list_O->data);
         if (n < 0)
@@ -301,6 +306,10 @@
     /* Goes to stdout and possibly syslog */
     bb_info_msg("%s (v"BB_VER") started", applet_name);
 
+    if (client_config.bootp == 1) {
+        DEBUG("Running in bootp-only mode.");
+    }
+
     /* if not set, and not suppressed, setup the default client ID */
     if (!client_config.clientid && !(opt & OPT_C)) {
         client_config.clientid = alloc_dhcp_option(DHCP_CLIENT_ID, "", 7);
@@ -450,9 +459,11 @@
         if (listen_mode != LISTEN_NONE && FD_ISSET(sockfd, &rfds)) {
             /* A packet is ready, read it */
 
-            if (listen_mode == LISTEN_KERNEL)
+            if (listen_mode == LISTEN_KERNEL) {
                 len = udhcp_recv_packet(&packet, sockfd);
-            else len = get_raw_packet(&packet, sockfd);
+            } else {
+                len = get_raw_packet(&packet, sockfd);
+            }
 
             if (len == -1 && errno != EINTR) {
                 DEBUG("error on read, %s, reopening socket",
strerror(errno));
@@ -466,6 +477,22 @@
                 continue;
             }
 
+            if (packet.op != BOOTREPLY) {
+                DEBUG("Ignoring non BOOTREPLY packet");
+                continue;
+            }
+
+            if (client_config.bootp) {
+                udhcp_run_script(&packet, "bound"); /* bound? */
+                change_listen_mode(LISTEN_NONE);
+                goto ret0;
+            }
+            
+            if (packet.cookie != htonl(DHCP_MAGIC)) {
+                bb_error_msg("received bogus message (bad magic) --
ignoring");
+                continue;
+            }
+
             /* Ignore packets that aren't for us */
             if (memcmp(packet.chaddr, client_config.arp, 6)) {
                 DEBUG("Packet does not have our chaddr - ignoring");
diff -aruN busybox-1.9.1/networking/udhcp/dhcpc.h
busybox-1.9.1.N/networking/udhcp/dhcpc.h
--- busybox-1.9.1/networking/udhcp/dhcpc.h    2008-02-12 08:03:01.000000000
-0800
+++ busybox-1.9.1.N/networking/udhcp/dhcpc.h    2008-04-07
10:33:25.000000000 -0700
@@ -30,6 +30,7 @@
     uint8_t *fqdn;                  /* Optional fully qualified domain name
to use */
     int ifindex;                    /* Index number of the interface to use
*/
     uint8_t arp[6];                 /* Our arp address */
+    char bootp;                        /* Act like a BOOTP client. */
     uint8_t opt_mask[256 / 8];      /* Bitmask of options to send (-O
option) */
 };
 
diff -aruN busybox-1.9.1/networking/udhcp/dhcpd.c
busybox-1.9.1.N/networking/udhcp/dhcpd.c
--- busybox-1.9.1/networking/udhcp/dhcpd.c    2008-02-12 08:03:01.000000000
-0800
+++ busybox-1.9.1.N/networking/udhcp/dhcpd.c    2008-04-07
10:33:25.000000000 -0700
@@ -143,6 +143,11 @@
             continue;
         }
 
+        if (packet.cookie != htonl(DHCP_MAGIC)) {
+            bb_error_msg("received bogus message, ignoring");
+            continue;
+        }
+
         state = get_option(&packet, DHCP_MESSAGE_TYPE);
         if (state == NULL) {
             bb_error_msg("cannot get option from packet, ignoring");
diff -aruN busybox-1.9.1/networking/udhcp/packet.c
busybox-1.9.1.N/networking/udhcp/packet.c
--- busybox-1.9.1/networking/udhcp/packet.c    2008-02-12 08:03:01.000000000
-0800
+++ busybox-1.9.1.N/networking/udhcp/packet.c    2008-04-07
10:33:25.000000000 -0700
@@ -15,26 +15,38 @@
 #include "options.h"
 
 
-void udhcp_init_header(struct dhcpMessage *packet, char type)
+void udhcp_init_header(struct dhcpMessage *packet, char op, char type)
 {
     memset(packet, 0, sizeof(struct dhcpMessage));
-    switch (type) {
-    case DHCPDISCOVER:
-    case DHCPREQUEST:
-    case DHCPRELEASE:
-    case DHCPINFORM:
-        packet->op = BOOTREQUEST;
-        break;
-    case DHCPOFFER:
-    case DHCPACK:
-    case DHCPNAK:
-        packet->op = BOOTREPLY;
+
+    /* DHCP-only */
+    if (!op && type) {
+        switch (type) {
+        case DHCPDISCOVER:
+        case DHCPREQUEST:
+        case DHCPRELEASE:
+        case DHCPINFORM:
+            op = BOOTREQUEST;
+            break;
+        case DHCPOFFER:
+        case DHCPACK:
+        case DHCPNAK:
+            op = BOOTREPLY;
+            break;
+        }
     }
+
+    /* Fill in packet with data present in both BOOTP and DHCP */
+    packet->op = op;
     packet->htype = ETH_10MB;
     packet->hlen = ETH_10MB_LEN;
     packet->cookie = htonl(DHCP_MAGIC);
     packet->options[0] = DHCP_END;
-    add_simple_option(packet->options, DHCP_MESSAGE_TYPE, type);
+
+    /* DHCP-only */
+    if (!op && type) {
+        add_simple_option(packet->options, DHCP_MESSAGE_TYPE, type);
+    }
 }
 
 
@@ -57,13 +69,9 @@
         return -1;
     }
 
-    if (packet->cookie != htonl(DHCP_MAGIC)) {
-        bb_error_msg("received bogus message, ignoring");
-        return -2;
-    }
     DEBUG("Received a packet");
 
-    if (packet->op == BOOTREQUEST) {
+    if (packet->cookie == htonl(DHCP_MAGIC) && packet->op == BOOTREQUEST) {
         vendor = get_option(packet, DHCP_VENDOR);
         if (vendor) {
 #if 0
diff -aruN busybox-1.9.1/networking/udhcp/serverpacket.c
busybox-1.9.1.N/networking/udhcp/serverpacket.c
--- busybox-1.9.1/networking/udhcp/serverpacket.c    2008-02-12
08:03:00.000000000 -0800
+++ busybox-1.9.1.N/networking/udhcp/serverpacket.c    2008-04-07
10:33:25.000000000 -0700
@@ -77,7 +77,7 @@
 
 static void init_packet(struct dhcpMessage *packet, struct dhcpMessage
*oldpacket, char type)
 {
-    udhcp_init_header(packet, type);
+    udhcp_init_header(packet, 0, type);
     packet->xid = oldpacket->xid;
     memcpy(packet->chaddr, oldpacket->chaddr, 16);
     packet->flags = oldpacket->flags;





More information about the busybox mailing list