diff options
| author | Roy Marples <roy@marples.name> | 2009-05-13 19:17:21 +0000 |
|---|---|---|
| committer | Roy Marples <roy@marples.name> | 2009-05-13 19:17:21 +0000 |
| commit | 3c12970b61e18cc31c7c710cf257213b2b409c14 (patch) | |
| tree | c2b9a69cb8d3aa3dbc5c1e70b0351757bbbd38ad | |
| parent | f2dab1db9d623f5c8455e6dd0441f6c0bc79fec8 (diff) | |
| download | dhcpcd-3c12970b61e18cc31c7c710cf257213b2b409c14.tar.xz | |
Although RFC2131 requires a ServerID we can actually work without one.
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.
| -rw-r--r-- | dhcpcd.c | 70 | ||||
| -rw-r--r-- | dhcpcd.conf | 18 |
2 files changed, 52 insertions, 36 deletions
@@ -365,19 +365,6 @@ send_rebind(void *arg) } 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) { struct interface *iface = 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) { diff --git a/dhcpcd.conf b/dhcpcd.conf index 98705f24..9c273af4 100644 --- a/dhcpcd.conf +++ b/dhcpcd.conf @@ -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 |
