summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDerek Martin <code@pizzashack.org>2016-03-08 13:12:02 -0800
committerDerek Martin <code@pizzashack.org>2016-03-08 13:12:02 -0800
commit5c5c34f2e7eb0694d79bcbabdbd0520014d0f713 (patch)
tree237dea15fe8b0b83dc84f16b09b8cac9978026d8
parent7929646388906b43da8530da6439610ffd4979d9 (diff)
Improve method of determining FQDN. (closes #3298)
Rather than reading /etc/resolv.conf, use gethostname() and getaddrinfo() to get the canonical domain. Thanks to Vincent Lefèvre for the memory leak fix.
-rw-r--r--getdomain.c103
-rw-r--r--init.c54
2 files changed, 91 insertions, 66 deletions
diff --git a/getdomain.c b/getdomain.c
index 71636279..209848b7 100644
--- a/getdomain.c
+++ b/getdomain.c
@@ -1,68 +1,69 @@
+/*
+ * Copyright (C) 2009,2013 Derek Martin <code@pizzashack.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
#if HAVE_CONFIG_H
# include "config.h"
#endif
-#include <stdio.h>
-#include <ctype.h>
#include <string.h>
+#include <unistd.h>
+#include <netdb.h>
+#include <sys/types.h>
+#include <sys/socket.h>
#include "mutt.h"
-#ifndef STDC_HEADERS
-int fclose ();
-#endif
-/* poor man's version of getdomainname() for systems where it does not return
- * return the DNS domain, but the NIS domain.
- */
-
-static void strip_trailing_dot (char *q)
+int getdnsdomainname (char *d, size_t len)
{
- char *p = q;
-
- for (; *q; q++)
- p = q;
-
- if (*p == '.')
- *p = '\0';
-}
+ /* A DNS name can actually be only 253 octets, string is 256 */
+ char *node;
+ long node_len;
+ struct addrinfo hints;
+ struct addrinfo *h;
+ char *p;
+ int ret;
-int getdnsdomainname (char *s, size_t l)
-{
- FILE *f;
- char tmp[1024];
- char *p = NULL;
- char *q;
+ *d = '\0';
+ memset(&hints, 0, sizeof (struct addrinfo));
+ hints.ai_flags = AI_CANONNAME;
+ hints.ai_family = AF_UNSPEC;
- if ((f = fopen ("/etc/resolv.conf", "r")) == NULL) return (-1);
-
- tmp[sizeof (tmp) - 1] = 0;
-
- l--; /* save room for the terminal \0 */
-
- while (fgets (tmp, sizeof (tmp) - 1, f) != NULL)
+ if ((node_len = sysconf(_SC_HOST_NAME_MAX)) == -1)
+ node_len = STRING;
+ node = safe_malloc(node_len + 1);
+ if (gethostname(node, node_len))
+ ret = -1;
+ else if (getaddrinfo(node, NULL, &hints, &h))
+ ret = -1;
+ else
{
- p = tmp;
- while (ISSPACE (*p)) p++;
- if (mutt_strncmp ("domain", p, 6) == 0 || mutt_strncmp ("search", p, 6) == 0)
+ if (!(p = strchr(h->ai_canonname, '.')))
+ ret = -1;
+ else
{
- p += 6;
-
- for (q = strtok (p, " \t\n"); q; q = strtok (NULL, " \t\n"))
- if (strcmp (q, "."))
- break;
-
- if (q)
- {
- strip_trailing_dot (q);
- strfcpy (s, q, l);
- safe_fclose (&f);
- return 0;
- }
-
+ strfcpy(d, ++p, len);
+ ret = 0;
+ dprint(1, (debugfile, "getdnsdomainname(): %s\n", d));
}
+ freeaddrinfo(h);
}
-
- safe_fclose (&f);
- return (-1);
+ FREE (&node);
+ return ret;
}
+
diff --git a/init.c b/init.c
index 959fd1c1..27e34968 100644
--- a/init.c
+++ b/init.c
@@ -2889,6 +2889,7 @@ void mutt_init (int skip_sys_rc, LIST *commands)
struct passwd *pw;
struct utsname utsname;
char *p, buffer[STRING];
+ char *domain = NULL;
int i, default_rc = 0, need_pause = 0;
BUFFER err;
@@ -2953,30 +2954,53 @@ void mutt_init (int skip_sys_rc, LIST *commands)
#endif
/* And about the host... */
- uname (&utsname);
+
+#ifdef DOMAIN
+ domain = safe_strdup (DOMAIN);
+#endif /* DOMAIN */
+
+ /*
+ * The call to uname() shouldn't fail, but if it does, the system is horribly
+ * broken, and the system's networking configuration is in an unreliable
+ * state. We should bail.
+ */
+ if ((uname (&utsname)) == -1)
+ {
+ mutt_endwin (NULL);
+ perror (_("unable to determine nodename via uname()"));
+ exit (1);
+ }
+
/* some systems report the FQDN instead of just the hostname */
if ((p = strchr (utsname.nodename, '.')))
- {
Hostname = mutt_substrdup (utsname.nodename, p);
- p++;
- strfcpy (buffer, p, sizeof (buffer)); /* save the domain for below */
- }
else
Hostname = safe_strdup (utsname.nodename);
-#ifndef DOMAIN
-#define DOMAIN buffer
- if (!p && getdnsdomainname (buffer, sizeof (buffer)) == -1)
- Fqdn = safe_strdup ("@");
- else
-#endif /* DOMAIN */
- if (*DOMAIN != '@')
+ /* now get FQDN. Use configured domain first, DNS next, then uname */
+ if (domain)
{
- Fqdn = safe_malloc (mutt_strlen (DOMAIN) + mutt_strlen (Hostname) + 2);
- sprintf (Fqdn, "%s.%s", NONULL(Hostname), DOMAIN); /* __SPRINTF_CHECKED__ */
+ /* we have a compile-time domain name, use that for Fqdn */
+ Fqdn = safe_malloc (mutt_strlen (domain) + mutt_strlen (Hostname) + 2);
+ sprintf (Fqdn, "%s.%s", NONULL(Hostname), domain); /* __SPRINTF_CHECKED__ */
+ }
+ else if (!(getdnsdomainname (buffer, sizeof buffer)))
+ {
+ Fqdn = safe_malloc (mutt_strlen (buffer) + mutt_strlen (Hostname) + 2);
+ sprintf (Fqdn, "%s.%s", NONULL(Hostname), buffer); /* __SPRINTF_CHECKED__ */
}
else
- Fqdn = safe_strdup(NONULL(Hostname));
+ /*
+ * DNS failed, use the nodename. Whether or not the nodename had a '.' in
+ * it, we can use the nodename as the FQDN. On hosts where DNS is not
+ * being used, e.g. small network that relies on hosts files, a short host
+ * name is all that is required for SMTP to work correctly. It could be
+ * wrong, but we've done the best we can, at this point the onus is on the
+ * user to provide the correct hostname if the nodename won't work in their
+ * network.
+ */
+ Fqdn = safe_strdup(utsname.nodename);
+
if ((p = getenv ("MAIL")))
Spoolfile = safe_strdup (p);