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 <troglobit@gmail.com>
This commit is contained in:
Joachim Wiberg
2025-01-31 13:55:35 +01:00
parent bcfd3d4a5b
commit 5ee78e28ad
4 changed files with 41 additions and 19 deletions
+1 -1
View File
@@ -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
+38 -16
View File
@@ -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);
}
+1 -1
View File
@@ -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);
+1 -1
View File
@@ -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