Improve hostname support in general, so we are aware of hostname changes.
When setting the hostname, prefer the FQDN name or append a domain.
# define _PATH_DEVNULL "/dev/null"
#endif
+static char hostname_buffer[HOSTNAME_MAX_LEN];
int clock_monotonic;
static char *lbuf;
static size_t lbuf_len;
return 0;
}
+const char *
+get_hostname(void)
+{
+
+ gethostname(hostname_buffer, sizeof(hostname_buffer));
+ if (strcmp(hostname_buffer, "(none)") == 0 ||
+ strcmp(hostname_buffer, "localhost") == 0 ||
+ strncmp(hostname_buffer, "localhost.", strlen("localhost.")) == 0 ||
+ hostname_buffer[0] == '.')
+ return NULL;
+ return hostname_buffer;
+}
+
/* Handy function to get the time.
* We only care about time advancements, not the actual time itself
* Which is why we use CLOCK_MONOTONIC, but it is not available on all
#include "config.h"
#include "defs.h"
+#ifndef HOSTNAME_MAX_LEN
+#define HOSTNAME_MAX_LEN 250 /* 255 - 3 (FQDN) - 2 (DNS enc) */
+#endif
+
#define UNCONST(a) ((void *)(unsigned long)(const void *)(a))
#define timeval_to_double(tv) ((tv)->tv_sec * 1.0 + (tv)->tv_usec * 1.0e-6)
int set_cloexec(int);
int set_nonblock(int);
char *get_line(FILE * __restrict);
+const char *get_hostname(void);
extern int clock_monotonic;
int get_monotonic(struct timeval *);
ssize_t setvar(char ***, const char *, const char *, const char *);
return 0;
}
+size_t
+encode_rfc1035(const char *src, uint8_t *dst)
+{
+ uint8_t *p;
+ uint8_t *lp;
+ size_t len;
+ uint8_t has_dot;
+
+ if (src == NULL || *src == '\0')
+ return 0;
+ if (dst) {
+ p = dst;
+ lp = p++;
+ }
+ len = 1;
+ has_dot = 0;
+ for (; *src; src++) {
+ if (*src == '\0')
+ break;
+ if (*src == '.') {
+ /* Skip the trailing . */
+ if (src[1] == '\0')
+ break;
+ has_dot = 1;
+ if (dst) {
+ *lp = p - lp - 1;
+ if (*lp == '\0')
+ return len;
+ lp = p++;
+ }
+ } else if (dst)
+ *p++ = (uint8_t)*src;
+ len++;
+ }
+ if (dst) {
+ *lp = p - lp - 1;
+ if (has_dot)
+ *p++ = '\0';
+ }
+ if (has_dot)
+ len++;
+ return len;
+}
+
/* Decode an RFC3397 DNS search order option into a space
* separated string. Returns length of string (including
* terminating zero) or zero on error. out may be NULL
#define del_option_mask(var, val) (var[val >> 3] &= ~(1 << (val & 7)))
#define has_option_mask(var, val) (var[val >> 3] & (1 << (val & 7)))
int make_option_mask(const struct dhcp_opt *,uint8_t *, const char *, int);
+size_t encode_rfc1035(const char *src, uint8_t *dst);
ssize_t decode_rfc3397(char *, ssize_t, int, const uint8_t *);
ssize_t print_string(char *, ssize_t, int, const uint8_t *);
ssize_t print_option(char *, ssize_t, int, int, const uint8_t *, const char *);
return routes;
}
-static size_t
-encode_rfc1035(const char *src, uint8_t *dst)
-{
- uint8_t *p = dst;
- uint8_t *lp = p++;
-
- if (*src == '\0')
- return 0;
- for (; *src; src++) {
- if (*src == '\0')
- break;
- if (*src == '.') {
- /* Skip the trailing . */
- if (src[1] == '\0')
- break;
- *lp = p - lp - 1;
- if (*lp == '\0')
- return p - dst;
- lp = p++;
- } else
- *p++ = (uint8_t)*src;
- }
- *lp = p - lp - 1;
- *p++ = '\0';
- return p - dst;
-}
-
#define PUTADDR(_type, _val) \
{ \
*p++ = _type; \
const struct dhcp_state *state = D_CSTATE(iface);
const struct dhcp_lease *lease = &state->lease;
time_t up = uptime() - state->start_uptime;
+ const char *hostname;
dhcp = calloc(1, sizeof (*dhcp));
if (dhcp == NULL)
* upto the first dot (the short hostname) as otherwise
* confuses some DHCP servers when updating DNS.
* The FQDN option should be used if a FQDN is required. */
- if (ifo->options & DHCPCD_HOSTNAME && ifo->hostname[0]) {
+ if (ifo->hostname[0] == '\0')
+ hostname = get_hostname();
+ else
+ hostname = ifo->hostname;
+ if (ifo->options & DHCPCD_HOSTNAME && hostname) {
*p++ = DHO_HOSTNAME;
- hp = strchr(ifo->hostname, '.');
+ hp = strchr(hostname, '.');
if (hp)
- len = hp - ifo->hostname;
+ len = hp - hostname;
else
- len = strlen(ifo->hostname);
+ len = strlen(hostname);
*p++ = len;
- memcpy(p, ifo->hostname, len);
+ memcpy(p, hostname, len);
p += len;
}
- if (ifo->fqdn != FQDN_DISABLE && ifo->hostname[0]) {
+ if (ifo->fqdn != FQDN_DISABLE) {
/* IETF DHC-FQDN option (81), RFC4702 */
*p++ = DHO_FQDN;
lp = p;
* N: 1 => Client requests Server to not
* update DNS
*/
- *p++ = (ifo->fqdn & 0x09) | 0x04;
+ if (hostname)
+ *p++ = (ifo->fqdn & 0x09) | 0x04;
+ else
+ *p++ = (FQDN_NONE & 0x09) | 0x04;
*p++ = 0; /* from server for PTR RR */
*p++ = 0; /* from server for A RR if S=1 */
- ul = encode_rfc1035(ifo->hostname, p);
- *lp += ul;
- p += ul;
+ if (hostname) {
+ ul = encode_rfc1035(hostname, p);
+ *lp += ul;
+ p += ul;
+ }
}
/* vendor is already encoded correctly, so just add it */
{ D6_OPTION_BCMS_SERVER_A, IPV6A, "bcms_server_a" },
{ D6_OPTION_POSIX_TIMEZONE, STRING, "posix_timezone" },
{ D6_OPTION_TZDB_TIMEZONE, STRING, "tzdb_timezone" },
+ { D6_OPTION_FQDN, RFC3397, "fqdn" },
{ 0, 0, NULL }
};
uint8_t IA, *p;
uint32_t u32;
const struct ipv6_addr *ap;
+ const char *hostname;
state = D6_STATE(ifp);
if (state->send) {
len += sizeof(*u16);
}
if (len == 0)
- len = sizeof(*u16) * 3;
+ len = sizeof(*u16) * 4;
len += sizeof(*o);
+
+ if (ifo->fqdn != FQDN_DISABLE) {
+ if (ifo->hostname[0] == '\0')
+ hostname = get_hostname();
+ else
+ hostname = ifo->hostname;
+ len += sizeof(*o) + 1 + encode_rfc1035(hostname, NULL);
+ }
}
len += sizeof(*state->send);
}
if (state->send->type != DHCP6_RELEASE) {
+ if (ifo->fqdn != FQDN_DISABLE) {
+ o = D6_NEXT_OPTION(o);
+ o->code = htons(D6_OPTION_FQDN);
+ p = D6_OPTION_DATA(o);
+ switch (ifo->fqdn) {
+ case FQDN_BOTH:
+ *p = 0x01;
+ break;
+ case FQDN_PTR:
+ *p = 0x00;
+ break;
+ default:
+ *p = 0x04;
+ break;
+ }
+ o->len = encode_rfc1035(hostname, p + 1);
+ if (o->len == 0)
+ *p = 0x04;
+ o->len = htons(++o->len);
+ }
o = D6_NEXT_OPTION(o);
o->code = htons(D6_OPTION_ORO);
o->len = 0;
}
}
if (o->len == 0) {
+ *u16++ = htons(D6_OPTION_UNICAST);
*u16++ = htons(D6_OPTION_DNS_SERVERS);
*u16++ = htons(D6_OPTION_DOMAIN_LIST);
- *u16++ = htons(D6_OPTION_UNICAST);
- o->len = sizeof(*u16) * 3;
+ *u16++ = htons(D6_OPTION_FQDN);
+ o->len = sizeof(*u16) * 4;
}
o->len = htons(o->len);
}
#define D6_OPTION_INFO_REFRESH_TIME 32
#define D6_OPTION_BCMS_SERVER_D 33
#define D6_OPTION_BCMS_SERVER_A 34
+#define D6_OPTION_FQDN 39
#define D6_OPTION_POSIX_TIMEZONE 41
#define D6_OPTION_TZDB_TIMEZONE 42
set_hostname()
{
- if need_hostname; then
- if [ -n "$new_host_name" ]; then
+
+ need_hostname || return
+
+ if [ -n "$new_fqdn_name" ]; then
+ try_hostname "$new_fqdn_name"
+ elif [ -n "$new_host_name" ]; then
+ if [ -n "$new_domain_name" ]; then
+ try_hostname "$new_host_name.$new_domain_name"
+ else
try_hostname "$new_host_name"
- elif [ -n "$new_fqdn_name" ]; then
- try_hostname "$new_fqdn_name"
fi
fi
}
+# For ease of use, map DHCP6 names onto our DHCP4 names
+case "$reason" in
+BOUND6|RENEW6|REBIND6|REBOOT6|INFORM6)
+ new_fqdn_name="$new_dhcp6_fqdn"
+ ;;
+esac
+
if $if_up; then
set_hostname
fi
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.Dd May 3, 2013
+.Dd June 5, 2013
.Dt DHCPCD 8
.Os
.Sh NAME
.Xr resolvconf 8
.Sh STANDARDS
RFC 951, RFC 1534, RFC 2131, RFC 2132, RFC 2855, RFC 3004, RFC 3315,RFC 3361,
-RFC 3633, RFC 3396, RFC 3397, RFC 3442, RFC 3927, RFC 4361, RFC 4390, RFC 4702,
-RFC 4861, RFC 4833, RFC 5227, RFC 5969, RFC 6106.
+RFC 3633, RFC 3396, RFC 3397, RFC 3442, RFC 3927, RFC 4361, RFC 4390, RFC 4702,
+RFC 4704, RFC 4861, RFC 4833, RFC 5227, RFC 5969, RFC 6106.
.Sh AUTHORS
.An Roy Marples Aq roy@marples.name
.Sh BUGS
Only configure IPv4.
.It Ic ipv6only
Only confgiure IPv6.
-.It Ic fqdn Op none | ptr | both
-none disables FQDN encoding, ptr just asks the DHCP server to update the PTR
+.It Ic fqdn Op disable | ptr | both
+ptr just asks the DHCP server to update the PTR
record of the host in DNS whereas both also updates the A record.
+disable will disable the FQDN option.
+The default is both.
.Nm dhcpcd
itself never does any DNS updates.
.Nm dhcpcd
add_environ(ifo, arg, 1);
break;
case 'h':
- if (arg) {
- s = parse_string(ifo->hostname,
- HOSTNAME_MAX_LEN, arg);
- if (s == -1) {
- syslog(LOG_ERR, "hostname: %m");
- return -1;
- }
- if (s != 0 && ifo->hostname[0] == '.') {
- syslog(LOG_ERR,
- "hostname cannot begin with .");
- return -1;
- }
- ifo->hostname[s] = '\0';
+ if (!arg) {
+ ifo->options |= DHCPCD_HOSTNAME;
+ break;
+ }
+ s = parse_string(ifo->hostname, HOSTNAME_MAX_LEN, arg);
+ if (s == -1) {
+ syslog(LOG_ERR, "hostname: %m");
+ return -1;
+ }
+ if (s != 0 && ifo->hostname[0] == '.') {
+ syslog(LOG_ERR, "hostname cannot begin with .");
+ return -1;
}
+ ifo->hostname[s] = '\0';
if (ifo->hostname[0] == '\0')
ifo->options &= ~DHCPCD_HOSTNAME;
else
ifo->reboot = DEFAULT_REBOOT;
ifo->metric = -1;
strlcpy(ifo->script, SCRIPT, sizeof(ifo->script));
- gethostname(ifo->hostname, HOSTNAME_MAX_LEN);
- /* Ensure that the hostname is NULL terminated */
- ifo->hostname[HOSTNAME_MAX_LEN] = '\0';
- if (strcmp(ifo->hostname, "(none)") == 0 ||
- strcmp(ifo->hostname, "localhost") == 0)
- ifo->hostname[0] = '\0';
ifo->vendorclassid[0] = strlen(vendor);
memcpy(ifo->vendorclassid + 1, vendor, ifo->vendorclassid[0]);
#define DEFAULT_TIMEOUT 30
#define DEFAULT_REBOOT 5
+#ifndef HOSTNAME_MAX_LEN
#define HOSTNAME_MAX_LEN 250 /* 255 - 3 (FQDN) - 2 (DNS enc) */
+#endif
#define VENDORCLASSID_MAX_LEN 255
#define CLIENTID_MAX_LEN 48
#define USERCLASS_MAX_LEN 255