freeipa/util/ipa_hostname.c
Christian Heimes 727a2ffb93 Easier to use ipa_gethostfqdn()
ipa_gethostfqdn() now returns a pointer to a statically allocated buffer
or NULL in case of an error. The caller no longer has to supply a
correctly allocated buffer.

Rename IPA_HOST_HOST to_LEN IPA_HOST_FQDN_LEN and use IPA_HOST_FQDN_LEN
wherever code copies a hostname supplied from ipa_gethostfqdn().

Clarify that MAXHOSTNAMELEN and MAXHOSTFQDNLEN are different things.

Signed-off-by: Christian Heimes <cheimes@redhat.com>
Reviewed-By: Fraser Tweedale <ftweedal@redhat.com>
2020-10-26 17:11:19 +11:00

99 lines
2.3 KiB
C

/*
* Copyright (C) 2020 FreeIPA Contributors see COPYING for license
*/
#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif
#include <errno.h>
#include <netdb.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include "ipa_hostname.h"
static int
_get_fqdn(char *fqdn)
{
char hostname[IPA_HOST_FQDN_LEN];
char *canonname = NULL;
struct addrinfo hints;
struct addrinfo *ai = NULL;
int r;
r = gethostname(hostname, IPA_HOST_FQDN_LEN - 1);
if (r != 0) {
goto error;
}
memset(&hints, 0, sizeof(struct addrinfo));
/* use IPv4 or IPv6 */
hints.ai_family = AF_UNSPEC;
/* optimize, RAW and STREAM return same kind of information */
hints.ai_socktype = SOCK_DGRAM;
/* any protocol */
hints.ai_protocol = 0;
/* get canonical name
* only use IPv4/6 when at least one interface for proto is configured */
hints.ai_flags = AI_CANONNAME | AI_ADDRCONFIG;
r = getaddrinfo(hostname, NULL, &hints, &ai);
if (r != 0) {
/* getaddrinfo() for gethostname() should never fail. The
* nss-myhostname provider should always add a positive match. */
errno = ENOENT;
goto error;
}
/* only the first addrinfo struct holds a canonical name value */
canonname = ai->ai_canonname;
/* check that canon name is filled and not too long */
if (!canonname) {
errno = ENOENT;
goto error;
}
if (strlen(canonname) > (IPA_HOST_FQDN_LEN - 1)) {
errno = ENAMETOOLONG;
goto error;
}
#if 0
/* refuse non-qualified short names and localhost */
if ((strchr(canonname, '.') == NULL) ||
(strcasecmp(canonname, "localhost.localdomain") == 0)) {
errno = EINVAL;
goto error;
}
#endif
strncpy(fqdn, canonname, IPA_HOST_FQDN_LEN);
/* Make double sure it is terminated */
fqdn[IPA_HOST_FQDN_LEN - 1] = '\0';
freeaddrinfo(ai);
return 0;
error:
if (ai != NULL) {
freeaddrinfo(ai);
}
return -1;
}
const char* ipa_gethostfqdn()
{
static char cached_fqdn[IPA_HOST_FQDN_LEN] = {0};
if (*cached_fqdn == '\0') {
int res = _get_fqdn(cached_fqdn);
if (res != 0) {
return NULL;
}
}
return (const char*)cached_fqdn;
}