]> git.ipfire.org Git - thirdparty/dhcpcd.git/commitdiff
Although RFC2131 requires a ServerID we can actually work without one.
authorRoy Marples <roy@marples.name>
Wed, 13 May 2009 19:17:21 +0000 (19:17 +0000)
committerRoy Marples <roy@marples.name>
Wed, 13 May 2009 19:17:21 +0000 (19:17 +0000)
Some broken servers don't send a ServerID, so make the requirement optional.
We default to requiring ServerID in dhcpcd.conf though as some other broken
servers NAK incorrectly without a ServerID.

dhcpcd.c
dhcpcd.conf

index 358df647c544ee0e19244f093867fac0926ee19e..96eb83e474a16711eab9604bfdb86e2733917885 100644 (file)
--- a/dhcpcd.c
+++ b/dhcpcd.c
@@ -364,19 +364,6 @@ send_rebind(void *arg)
        send_message((struct interface *)arg, DHCP_REQUEST, send_rebind);
 }
 
-void
-start_rebind(void *arg)
-{
-       struct interface *iface = arg;
-
-       syslog(LOG_ERR, "%s: failed to renew, attmepting to rebind",
-           iface->name);
-       iface->state->state = DHS_REBIND;
-       delete_timeout(send_renew, iface);
-       iface->state->lease.server.s_addr = 0;
-       send_rebind(iface);
-}
-
 void
 start_expire(void *arg)
 {
@@ -413,10 +400,11 @@ log_dhcp(int lvl, const char *msg,
 
        if (strcmp(msg, "NAK:") == 0)
                a = get_option_string(dhcp, DHO_MESSAGE);
-       else {
+       else if (dhcp->yiaddr != 0) {
                addr.s_addr = dhcp->yiaddr;
                a = xstrdup(inet_ntoa(addr));
-       }
+       } else
+               a = NULL;
        r = get_option_addr(&addr.s_addr, dhcp, DHO_SERVERID);
        if (dhcp->servername[0] && r == 0)
                syslog(lvl, "%s: %s %s from %s `%s'", iface->name, msg, a,
@@ -424,8 +412,10 @@ log_dhcp(int lvl, const char *msg,
        else if (r == 0)
                syslog(lvl, "%s: %s %s from %s",
                    iface->name, msg, a, inet_ntoa(addr));
-       else
+       else if (a != NULL)
                syslog(lvl, "%s: %s %s", iface->name, msg, a);
+       else
+               syslog(lvl, "%s: %s", iface->name, msg);
        free(a);
 }
 
@@ -457,15 +447,16 @@ handle_dhcp(struct interface *iface, struct dhcp_message **dhcpp)
        /* We may have found a BOOTP server */
        if (get_option_uint8(&type, dhcp, DHO_MESSAGETYPE) == -1) 
                type = 0;
-       else if (get_option_addr(&addr.s_addr, dhcp, DHO_SERVERID) == -1) {
-               /* We should ignore invalid NAK messages without a ServerID */
-               syslog(LOG_WARNING, "%s: ignoring DHCP message; no Server ID",
-                   iface->name);
-               return;
-       }
 
-       /* We should restart on a NAK */
        if (type == DHCP_NAK) {
+               /* For NAK, only check if we require the ServerID */
+               if (has_option_mask(ifo->requiremask, DHO_SERVERID) &&
+                   get_option_addr(&addr.s_addr, dhcp, DHO_SERVERID) == -1)
+               {
+                       log_dhcp(LOG_WARNING, "reject NAK", iface, dhcp);
+                       return;
+               }
+               /* We should restart on a NAK */
                log_dhcp(LOG_WARNING, "NAK:", iface, dhcp);
                drop_config(iface, "NAK");
                unlink(iface->leasefile);
@@ -482,27 +473,31 @@ handle_dhcp(struct interface *iface, struct dhcp_message **dhcpp)
                return;
        }
 
-       /* No NAK, so reset the backoff */
-       state->nakoff = 1;
-
        /* Ensure that all required options are present */
        for (i = 1; i < 255; i++) {
                if (has_option_mask(ifo->requiremask, i) &&
                    get_option_uint8(&tmp, dhcp, i) != 0)
                {
-                       log_dhcp(LOG_WARNING, "reject", iface, dhcp);
+                       /* If we are bootp, then ignore the need for serverid.
+                        * To ignore bootp, require dhcp_message_type instead. */
+                       if (type == 0 && i == DHO_SERVERID)
+                               continue;
+                       log_dhcp(LOG_WARNING, "reject DHCP", iface, dhcp);
                        return;
                }
-       }
+       }               
+
+       /* No NAK, so reset the backoff */
+       state->nakoff = 1;
 
        if ((type == 0 || type == DHCP_OFFER) &&
            state->state == DHS_DISCOVER)
        {
                lease->frominfo = 0;
                lease->addr.s_addr = dhcp->yiaddr;
-               lease->server.s_addr = 0;
+               lease->server.s_addr = INADDR_ANY;
                if (type != 0)
-                       lease->server.s_addr = addr.s_addr;
+                       get_option_addr(&lease->server.s_addr, dhcp, DHO_SERVERID);
                log_dhcp(LOG_INFO, "offered", iface, dhcp);
                free(state->offer);
                state->offer = dhcp;
@@ -871,6 +866,21 @@ start_renew(void *arg)
        send_renew(iface);
 }
 
+void
+start_rebind(void *arg)
+{
+       struct interface *iface = arg;
+
+       syslog(LOG_ERR, "%s: failed to renew, attmepting to rebind",
+           iface->name);
+       iface->state->state = DHS_REBIND;
+       delete_timeout(send_renew, iface);
+       iface->state->lease.server.s_addr = 0;
+       if (iface->raw_fd == -1)
+               open_sockets(iface);
+       send_rebind(iface);
+}
+
 static void
 start_timeout(void *arg)
 {
index 98705f24e39e39218ad163a7df8b0eb999a08d97..9c273af4c7af1039245d60aa7863998d6c7e6090 100644 (file)
@@ -1,19 +1,25 @@
 # A sample configuration for dhcpcd.
 # See dhcpcd.conf(5) for details.
 
-# We normally want to inform the DHCP server of our hostname for DDNS.
+# Inform the DHCP server of our hostname for DDNS.
 hostname
 
-# A list of options we should request from the DHCP server.
+# A list of options to request from the DHCP server.
 option domain_name_servers, domain_name, domain_search, host_name
-# Most distros have ntp support.
+# Most distributions have NTP support.
 option ntp_servers
 
-# We should behave nicely on networks and respect their MTU.
+# Behave nicely on networks and respect their MTU.
 # However, a lot of buggy DHCP servers set invalid MTUs so this is not
 # enabled by default.
 #option interface_mtu
 
-# We provide a hook script to lookup the hostname if not set by the DHCP
-# server, but we should not run it by default.
+# A ServerID is required by RFC2131.
+# Some broken DHCP servers do not send one and dhcpcd can work without it.
+# Some broken DHCP servers NAK incorrectly and do not include a ServerID either so
+# the default is to require a ServerID.
+require dhcp_server_identifier
+
+# A hook script is provided to lookup the hostname if not set by the DHCP
+# server, but it should not be run by default.
 nohook lookup-hostname