From 5ee78e28addfaa4f18723bb04dcc58664c59a930 Mon Sep 17 00:00:00 2001 From: Joachim Wiberg Date: Sun, 26 Jan 2025 04:40:15 +0100 Subject: [PATCH] confd: add support for setting fqdn hostnames The hostname leaf in ietf-system.yang defines it as an fqdn. This patch adds support for splitting the host and domain parts to set them in Linux according to hosts(5). Signed-off-by: Joachim Wiberg --- src/confd/src/core.h | 2 +- src/confd/src/ietf-system.c | 54 ++++++++++++++++++++++---------- src/confd/src/infix-containers.c | 2 +- src/confd/yang/infix-system.yang | 2 +- 4 files changed, 41 insertions(+), 19 deletions(-) diff --git a/src/confd/src/core.h b/src/confd/src/core.h index fa3fd170..4dc8c19b 100644 --- a/src/confd/src/core.h +++ b/src/confd/src/core.h @@ -208,7 +208,7 @@ int ietf_syslog_init(struct confd *confd); /* ietf-system.c */ int ietf_system_init (struct confd *confd); -int hostnamefmt (struct confd *confd, const char *fmt, char *buf, size_t len); +int hostnamefmt (struct confd *confd, const char *fmt, char *hostnm, size_t hostlen, char *domain, size_t domlen); /* infix-containers.c */ #ifdef CONTAINERS diff --git a/src/confd/src/ietf-system.c b/src/confd/src/ietf-system.c index 564635cc..62cf9c5d 100644 --- a/src/confd/src/ietf-system.c +++ b/src/confd/src/ietf-system.c @@ -1614,37 +1614,48 @@ static char *get_mac(struct confd *confd, char *mac, size_t len) * NOTE: to be forward compatible, any unknown % combination will be silently consumed. * E.g., "example-%z" will become "example-" */ -int hostnamefmt(struct confd *confd, const char *fmt, char *buf, size_t len) +int hostnamefmt(struct confd *confd, const char *fmt, char *hostnm, size_t hostlen, + char *domain, size_t domlen) { char mac[10]; + char *ptr; size_t i; if (!fmt || !*fmt) return -1; - memset(buf, 0, len); + memset(hostnm, 0, hostlen); + if (domain) + memset(domain, 0, domlen); + + ptr = strchr(fmt, '.'); + if (ptr) { + *ptr++ = 0; + if (domain) + strlcpy(domain, ptr, domlen); + } for (i = 0; i < strlen(fmt); i++) { if (fmt[i] == '%') { switch (fmt[++i]) { case 'i': - strlcat(buf, id, len); + strlcat(hostnm, id, hostlen); break; case 'h': - strlcat(buf, nm, len); + strlcat(hostnm, nm, hostlen); break; case 'm': - strlcat(buf, get_mac(confd, mac, sizeof(mac)), len); + strlcat(hostnm, get_mac(confd, mac, sizeof(mac)), hostlen); break; case '%': - strlcat(buf, "%", len); + strlcat(hostnm, "%", hostlen); break; default: break; /* Unknown, skip */ } } else { char ch[2] = { fmt[i], 0 }; - strlcat(buf, ch, len); + strlcat(hostnm, ch, hostlen); } } @@ -1656,8 +1667,8 @@ static int change_hostname(sr_session_ctx_t *session, uint32_t sub_id, const cha { struct confd *confd = (struct confd *)priv; const char *hostip = "127.0.1.1"; - char hostnm[65], buf[256]; - char *fmt; + char hostnm[65], domain[65]; + char buf[256], *fmt; FILE *nfp, *fp; int err, fd; @@ -1665,11 +1676,13 @@ static int change_hostname(sr_session_ctx_t *session, uint32_t sub_id, const cha return SR_ERR_OK; fmt = srx_get_str(session, "%s", xpath); - if (!fmt) { - fallback: - strlcpy(hostnm, nm, sizeof(hostnm)); - } else if (hostnamefmt(confd, fmt, hostnm, sizeof(hostnm))) - goto fallback; + if (!fmt) + fmt = strdup(nm); + + if (hostnamefmt(confd, fmt, hostnm, sizeof(hostnm), domain, sizeof(domain))) { + err = SR_ERR_SYS; + goto err; + } err = sethostname(hostnm, strlen(hostnm)); if (err) { @@ -1678,6 +1691,11 @@ static int change_hostname(sr_session_ctx_t *session, uint32_t sub_id, const cha goto err; } + if (domain[0] && setdomainname(domain, strlen(domain))) { + ERROR("failed setting domain name"); + /* Not cause for failing this function */ + } + fp = fopen(_PATH_HOSTNAME, "w"); if (!fp) { err = SR_ERR_INTERNAL; @@ -1706,8 +1724,12 @@ static int change_hostname(sr_session_ctx_t *session, uint32_t sub_id, const cha } while (fgets(buf, sizeof(buf), fp)) { - if (!strncmp(buf, hostip, strlen(hostip))) - snprintf(buf, sizeof(buf), "%s\t%s\n", hostip, hostnm); + if (!strncmp(buf, hostip, strlen(hostip))) { + if (domain[0]) + snprintf(buf, sizeof(buf), "%s\t%s.%s %s\n", hostip, hostnm, domain, hostnm); + else + snprintf(buf, sizeof(buf), "%s\t%s\n", hostip, hostnm); + } fputs(buf, nfp); } diff --git a/src/confd/src/infix-containers.c b/src/confd/src/infix-containers.c index 0724690c..9d26bc8a 100644 --- a/src/confd/src/infix-containers.c +++ b/src/confd/src/infix-containers.c @@ -67,7 +67,7 @@ static int add(const char *name, struct lyd_node *cif) if ((string = lydx_get_cattr(cif, "hostname"))) { char buf[65]; - if (hostnamefmt(&confd, string, buf, sizeof(buf))) + if (hostnamefmt(&confd, string, buf, sizeof(buf), NULL, 0)) ERRNO("%s: failed setting custom hostname", name); else fprintf(fp, " --hostname %s", buf); diff --git a/src/confd/yang/infix-system.yang b/src/confd/yang/infix-system.yang index 393f4052..372606a9 100644 --- a/src/confd/yang/infix-system.yang +++ b/src/confd/yang/infix-system.yang @@ -237,7 +237,7 @@ module infix-system { + '|%[him]' + ')' + '([a-zA-Z0-9\-_\.]|%[him])*'; - length "1..64"; + length "1..128"; } description "Linux have the same restrictions as IETF, only shorter. Format specifiers are for, default hostname, ID, and the