Make host name DHCP option configurable. Diff from ha...@sdf.org, tweaks by me.
RFC 2132 says a host name must have a lenght of at least 1, so we can use strlen(h_name) == 0 to not send a host name option at all and h_name == NULL to send the default host name option. OK? diff --git dhcpleased.c dhcpleased.c index 497ca5a0a79..92e96deac00 100644 --- dhcpleased.c +++ dhcpleased.c @@ -732,6 +732,9 @@ main_imsg_send_config(struct dhcpleased_conf *xconf) iface_conf->c_id, iface_conf->c_id_len); main_imsg_compose_engine(IMSG_RECONF_C_ID, -1, iface_conf->c_id, iface_conf->c_id_len); + if (iface_conf->h_name != NULL) + main_imsg_compose_frontend(IMSG_RECONF_H_NAME, -1, + iface_conf->h_name, strlen(iface_conf->h_name) + 1); } /* Config is now complete. */ @@ -1224,6 +1227,7 @@ merge_config(struct dhcpleased_conf *conf, struct dhcpleased_conf *xconf) SIMPLEQ_REMOVE_HEAD(&conf->iface_list, entry); free(iface_conf->vc_id); free(iface_conf->c_id); + free(iface_conf->h_name); free(iface_conf); } diff --git dhcpleased.conf.5 dhcpleased.conf.5 index 31b369bdc52..38026c46eeb 100644 --- dhcpleased.conf.5 +++ dhcpleased.conf.5 @@ -98,6 +98,13 @@ with hardware type 0 would be configured as: .Bd -literal -offset indent send client id "\e0foobar" .Ed +.It Ic send host name Ar host-name +Send the DHCP client host name option with a value of +.Ar host-name . +The default is to send the name of the host. +.It Ic send no host name +Do not send a DHCP host name option. +The default is to send a DHCP host name option with the name of the host. .It Ic send vendor class id Ar vendor-class-id Send the DHCP vendor class identifier option with a value of .Ar vendor-class-id . diff --git dhcpleased.h dhcpleased.h index 02121c19841..5ca6a3a3c2a 100644 --- dhcpleased.h +++ dhcpleased.h @@ -203,6 +203,7 @@ enum imsg_type { IMSG_RECONF_IFACE, IMSG_RECONF_VC_ID, IMSG_RECONF_C_ID, + IMSG_RECONF_H_NAME, IMSG_RECONF_END, #endif /* SMALL */ IMSG_SEND_DISCOVER, @@ -253,6 +254,7 @@ struct iface_conf { int vc_id_len; uint8_t *c_id; int c_id_len; + char *h_name; int ignore; struct in_addr ignore_servers[MAX_SERVERS]; int ignore_servers_len; diff --git engine.c engine.c index 13bea5b89fd..42fec7a4caf 100644 --- engine.c +++ engine.c @@ -480,6 +480,7 @@ engine_dispatch_main(int fd, short event, void *bula) iface_conf->vc_id_len = 0; iface_conf->c_id = NULL; iface_conf->c_id_len = 0; + iface_conf->h_name = NULL; SIMPLEQ_INSERT_TAIL(&nconf->iface_list, iface_conf, entry); break; @@ -511,6 +512,18 @@ engine_dispatch_main(int fd, short event, void *bula) IMSG_DATA_SIZE(imsg)); iface_conf->c_id_len = IMSG_DATA_SIZE(imsg); break; + case IMSG_RECONF_H_NAME: + if (iface_conf == NULL) + fatal("IMSG_RECONF_H_NAME without " + "IMSG_RECONF_IFACE"); + if (((char *)imsg.data)[IMSG_DATA_SIZE(imsg) - 1] != + '\0') + fatalx("Invalid hostname"); + if (IMSG_DATA_SIZE(imsg) > 256) + fatalx("Invalid hostname"); + if ((iface_conf->h_name = strdup(imsg.data)) == NULL) + fatal(NULL); + break; case IMSG_RECONF_END: { struct dhcpleased_iface *iface; int *ifaces; diff --git frontend.c frontend.c index 90b6c20d7bd..cc3815f49ab 100644 --- frontend.c +++ frontend.c @@ -361,6 +361,7 @@ frontend_dispatch_main(int fd, short event, void *bula) iface_conf->vc_id_len = 0; iface_conf->c_id = NULL; iface_conf->c_id_len = 0; + iface_conf->h_name = NULL; SIMPLEQ_INSERT_TAIL(&nconf->iface_list, iface_conf, entry); break; @@ -392,6 +393,18 @@ frontend_dispatch_main(int fd, short event, void *bula) IMSG_DATA_SIZE(imsg)); iface_conf->c_id_len = IMSG_DATA_SIZE(imsg); break; + case IMSG_RECONF_H_NAME: + if (iface_conf == NULL) + fatal("IMSG_RECONF_H_NAME without " + "IMSG_RECONF_IFACE"); + if (((char *)imsg.data)[IMSG_DATA_SIZE(imsg) - 1] != + '\0') + fatalx("Invalid hostname"); + if (IMSG_DATA_SIZE(imsg) > 256) + fatalx("Invalid hostname"); + if ((iface_conf->h_name = strdup(imsg.data)) == NULL) + fatal(NULL); + break; case IMSG_RECONF_END: { int i; int *ifaces; @@ -904,7 +917,7 @@ build_packet(uint8_t message_type, char *if_name, uint32_t xid, static uint8_t dhcp_cookie[] = DHCP_COOKIE; static uint8_t dhcp_message_type[] = {DHO_DHCP_MESSAGE_TYPE, 1, DHCPDISCOVER}; - static uint8_t dhcp_hostname[255] = {DHO_HOST_NAME, 0 /*, ... */}; + static uint8_t dhcp_hostname[255 + 2] = {DHO_HOST_NAME, 0 /*, ... */}; static uint8_t dhcp_client_id[] = {DHO_DHCP_CLIENT_IDENTIFIER, 7, HTYPE_ETHER, 0, 0, 0, 0, 0, 0}; static uint8_t dhcp_req_list[] = {DHO_DHCP_PARAMETER_REQUEST_LIST, @@ -944,12 +957,27 @@ build_packet(uint8_t message_type, char *if_name, uint32_t xid, p += sizeof(dhcp_cookie); memcpy(p, dhcp_message_type, sizeof(dhcp_message_type)); p += sizeof(dhcp_message_type); - if (gethostname(dhcp_hostname + 2, sizeof(dhcp_hostname) - 2) == 0) { - if ((c = strchr(dhcp_hostname + 2, '.')) != NULL) - *c = '\0'; - dhcp_hostname[1] = strlen(dhcp_hostname + 2); - memcpy(p, dhcp_hostname, dhcp_hostname[1] + 2); - p += dhcp_hostname[1] + 2; + +#ifndef SMALL + if (iface_conf != NULL && iface_conf->h_name != NULL) { + if (iface_conf->h_name[0] != '\0') { + dhcp_hostname[1] = strlen(iface_conf->h_name); + memcpy(dhcp_hostname + 2, iface_conf->h_name, + strlen(iface_conf->h_name)); + memcpy(p, dhcp_hostname, dhcp_hostname[1] + 2); + p += dhcp_hostname[1] + 2; + } + } else +#endif /* SMALL */ + { + if (gethostname(dhcp_hostname + 2, + sizeof(dhcp_hostname) - 2) == 0) { + if ((c = strchr(dhcp_hostname + 2, '.')) != NULL) + *c = '\0'; + dhcp_hostname[1] = strlen(dhcp_hostname + 2); + memcpy(p, dhcp_hostname, dhcp_hostname[1] + 2); + p += dhcp_hostname[1] + 2; + } } #ifndef SMALL @@ -1237,6 +1265,10 @@ iface_conf_cmp(struct iface_conf *a, struct iface_conf *b) return 1; if (memcmp(a->c_id, b->c_id, a->c_id_len) != 0) return 1; + if (a->h_name == NULL || b->h_name == NULL) + return 1; + if (strcmp(a->h_name, b->h_name) != 0) + return 1; if (a->ignore != b->ignore) return 1; if (a->ignore_servers_len != b->ignore_servers_len) diff --git parse.y parse.y index 33c2dc7f335..9b9441403a0 100644 --- parse.y +++ parse.y @@ -108,7 +108,8 @@ typedef struct { %} -%token DHCP_IFACE ERROR SEND VENDOR CLASS ID CLIENT IGNORE DNS ROUTES +%token DHCP_IFACE ERROR SEND VENDOR CLASS ID CLIENT IGNORE DNS ROUTES HOST NAME +%token NO %token <v.string> STRING %token <v.number> NUMBER @@ -274,6 +275,30 @@ ifaceoptsl : SEND VENDOR CLASS ID STRING { iface_conf->c_id[0] = DHO_DHCP_CLIENT_IDENTIFIER; iface_conf->c_id[1] = iface_conf->c_id_len - 2; } + | SEND HOST NAME STRING { + if (iface_conf->h_name != NULL) { + free($4); + yyerror("host name already set"); + YYERROR; + } + if (strlen($4) > 255) { + free($4); + yyerror("host name too long"); + YYERROR; + } + iface_conf->h_name = $4; + } + | SEND NO HOST NAME { + if (iface_conf->h_name != NULL) { + yyerror("host name already set"); + YYERROR; + } + + if ((iface_conf->h_name = strdup("")) == NULL) { + yyerror("malloc"); + YYERROR; + } + } | IGNORE ROUTES { iface_conf->ignore |= IGN_ROUTES; } @@ -337,9 +362,12 @@ lookup(char *s) {"class", CLASS}, {"client", CLIENT}, {"dns", DNS}, + {"host", HOST}, {"id", ID}, {"ignore", IGNORE}, {"interface", DHCP_IFACE}, + {"name", NAME}, + {"no", NO}, {"routes", ROUTES}, {"send", SEND}, {"vendor", VENDOR}, diff --git printconf.c printconf.c index 5de78699188..5eced3d19dd 100644 --- printconf.c +++ printconf.c @@ -106,6 +106,14 @@ print_config(struct dhcpleased_conf *conf) SIMPLEQ_FOREACH(iface, &conf->iface_list, entry) { printf("interface %s {\n", iface->name); print_dhcp_options("\t", iface->c_id, iface->c_id_len); + if (iface->h_name != NULL) { + if (iface->h_name[0] == '\0') + printf("\tsend no host name\n"); + else { + printf("\tsend host name \"%s\"\n", + iface->h_name); + } + } print_dhcp_options("\t", iface->vc_id, iface->vc_id_len); if (iface->ignore & IGN_DNS) printf("\tignore dns\n"); -- I'm not entirely sure you are real.