X-Git-Url: https://git.decadent.org.uk/gitweb/?a=blobdiff_plain;f=utils%2Fstatd%2Fsm-notify.c;h=2421f8bb4f043ed73ea0e58f2b37f6030f49eecb;hb=bbd9f5a98c3a401371bc642ac8545b1ccfeeab4d;hp=437e37a6b49de679f72b9663324faad4b346723d;hpb=baa41b2c78e796540c45692ea35214f7090a78cb;p=nfs-utils.git diff --git a/utils/statd/sm-notify.c b/utils/statd/sm-notify.c index 437e37a..2421f8b 100644 --- a/utils/statd/sm-notify.c +++ b/utils/statd/sm-notify.c @@ -34,8 +34,9 @@ #include "nsm.h" #include "nfsrpc.h" -#ifndef HAVE_DECL_AI_ADDRCONFIG -#define AI_ADDRCONFIG 0 +/* glibc before 2.3.4 */ +#ifndef AI_NUMERICSERV +#define AI_NUMERICSERV 0 #endif #define NSM_TIMEOUT 2 @@ -78,7 +79,6 @@ smn_lookup(const char *name) { struct addrinfo *ai = NULL; struct addrinfo hint = { - .ai_flags = AI_ADDRCONFIG, .ai_family = (nsm_family == AF_INET ? AF_INET: AF_UNSPEC), .ai_protocol = (int)IPPROTO_UDP, }; @@ -93,6 +93,101 @@ smn_lookup(const char *name) return ai; } +#ifdef HAVE_GETNAMEINFO +static char * +smn_get_hostname(const struct sockaddr *sap, const socklen_t salen, + const char *name) +{ + char buf[NI_MAXHOST]; + int error; + + error = getnameinfo(sap, salen, buf, sizeof(buf), NULL, 0, NI_NAMEREQD); + if (error != 0) { + xlog(L_ERROR, "my_name '%s' is unusable: %s", + name, gai_strerror(error)); + return NULL; + } + return strdup(buf); +} +#else /* !HAVE_GETNAMEINFO */ +static char * +smn_get_hostname(const struct sockaddr *sap, + __attribute__ ((unused)) const socklen_t salen, + const char *name) +{ + const struct sockaddr_in *sin = (const struct sockaddr_in *)(char *)sap; + const struct in_addr *addr = &sin->sin_addr; + struct hostent *hp; + + if (sap->sa_family != AF_INET) { + xlog(L_ERROR, "my_name '%s' is unusable: Bad address family", + name); + return NULL; + } + + hp = gethostbyaddr(addr, (socklen_t)sizeof(addr), AF_INET); + if (hp == NULL) { + xlog(L_ERROR, "my_name '%s' is unusable: %s", + name, hstrerror(h_errno)); + return NULL; + } + return strdup(hp->h_name); +} +#endif /* !HAVE_GETNAMEINFO */ + +/* + * Presentation addresses are converted to their canonical hostnames. + * If the IP address does not map to a hostname, it is an error: + * we never send a presentation address as the argument of SM_NOTIFY. + * + * If "name" is not a presentation address, it is left alone. This + * allows the administrator some flexibility if DNS isn't configured + * exactly how sm-notify prefers it. + * + * Returns NUL-terminated C string containing the result, or NULL + * if the canonical name doesn't exist or cannot be determined. + * The caller must free the result with free(3). + */ +__attribute_malloc__ +static char * +smn_verify_my_name(const char *name) +{ + struct addrinfo *ai = NULL; + struct addrinfo hint = { +#ifdef IPV6_SUPPORTED + .ai_family = AF_UNSPEC, +#else /* !IPV6_SUPPORTED */ + .ai_family = AF_INET, +#endif /* !IPV6_SUPPORTED */ + .ai_flags = AI_NUMERICHOST, + }; + char *retval; + int error; + + error = getaddrinfo(name, NULL, &hint, &ai); + switch (error) { + case 0: + /* @name was a presentation address */ + retval = smn_get_hostname(ai->ai_addr, ai->ai_addrlen, name); + freeaddrinfo(ai); + if (retval == NULL) + return NULL; + break; + case EAI_NONAME: + /* @name was not a presentation address */ + retval = strdup(name); + break; + default: + xlog(L_ERROR, "my_name '%s' is unusable: %s", + name, gai_strerror(error)); + return NULL; + } + + xlog(D_GENERAL, "Canonical name for my_name '%s': %s", + name, retval); + return retval; +} + __attribute_malloc__ static struct nsm_host * smn_alloc_host(const char *hostname, const char *mon_name, @@ -253,6 +348,7 @@ smn_bind_address(const char *srcaddr, const char *srcport) if (srcaddr == NULL) hint.ai_flags |= AI_PASSIVE; + /* Do not allow "node" and "service" parameters both to be NULL */ if (srcport == NULL) error = getaddrinfo(srcaddr, "", &hint, &ai); else @@ -394,12 +490,14 @@ usage: fprintf(stderr, exit(1); } - xlog_syslog(1); if (opt_debug) { + xlog_syslog(0); xlog_stderr(1); xlog_config(D_ALL, 1); - } else + } else { + xlog_syslog(1); xlog_stderr(0); + } xlog_open(progname); xlog(L_NOTICE, "Version " VERSION " starting"); @@ -413,32 +511,14 @@ usage: fprintf(stderr, } if (opt_srcaddr != NULL) { - struct addrinfo *ai = NULL; - struct addrinfo hint = { - .ai_family = AF_UNSPEC, - .ai_flags = AI_NUMERICHOST, - }; - - if (getaddrinfo(opt_srcaddr, NULL, &hint, &ai)) - /* not a presentation address - use it */ - strncpy(nsm_hostname, opt_srcaddr, sizeof(nsm_hostname)); - else { - /* was a presentation address - look it up in - * /etc/hosts, so it can be used for my_name */ - int error; + char *name; - freeaddrinfo(ai); - hint.ai_flags = AI_CANONNAME; - error = getaddrinfo(opt_srcaddr, NULL, &hint, &ai); - if (error != 0) { - xlog(L_ERROR, "Bind address %s is unusable: %s", - opt_srcaddr, gai_strerror(error)); - exit(1); - } - strncpy(nsm_hostname, ai->ai_canonname, - sizeof(nsm_hostname)); - freeaddrinfo(ai); - } + name = smn_verify_my_name(opt_srcaddr); + if (name == NULL) + exit(1); + + strncpy(nsm_hostname, name, sizeof(nsm_hostname)); + free(name); } (void)nsm_retire_monitored_hosts();