summaryrefslogtreecommitdiffstats
path: root/src/customdhcpcd/configure.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/customdhcpcd/configure.c')
-rw-r--r--src/customdhcpcd/configure.c1267
1 files changed, 657 insertions, 610 deletions
diff --git a/src/customdhcpcd/configure.c b/src/customdhcpcd/configure.c
index b69ccdc..00d75d0 100644
--- a/src/customdhcpcd/configure.c
+++ b/src/customdhcpcd/configure.c
@@ -1,4 +1,4 @@
-/*
+/*
* dhcpcd - DHCP client daemon
* Copyright 2006-2008 Roy Marples <roy@marples.name>
* All rights reserved
@@ -63,340 +63,360 @@
static int file_in_path (const char *file)
{
- char *p = getenv ("PATH");
- char *path;
- char *token;
- struct stat s;
- char mypath[PATH_MAX];
- int retval = -1;
-
- if (! p) {
- errno = ENOENT;
- return (-1);
- }
-
- path = strdup (p);
- p = path;
- while ((token = strsep (&p, ":"))) {
- snprintf (mypath, PATH_MAX, "%s/%s", token, file);
- if (stat (mypath, &s) == 0) {
- retval = 0;
- break;
- }
- }
- free (path);
- return (retval);
+ char *p = getenv ("PATH");
+ char *path;
+ char *token;
+ struct stat s;
+ char mypath[PATH_MAX];
+ int retval = -1;
+
+ if (! p)
+ {
+ errno = ENOENT;
+ return (-1);
+ }
+
+ path = strdup (p);
+ p = path;
+ while ((token = strsep (&p, ":")))
+ {
+ snprintf (mypath, PATH_MAX, "%s/%s", token, file);
+ if (stat (mypath, &s) == 0)
+ {
+ retval = 0;
+ break;
+ }
+ }
+ free (path);
+ return (retval);
}
/* IMPORTANT: Ensure that the last parameter is NULL when calling */
static int exec_cmd (const char *cmd, const char *args, ...)
{
- va_list va;
- char **argv;
- int n = 1;
- int ret = 0;
- pid_t pid;
- sigset_t full;
- sigset_t old;
-
- va_start (va, args);
- while (va_arg (va, char *) != NULL)
- n++;
- va_end (va);
- argv = xmalloc (sizeof (char *) * (n + 2));
-
- va_start (va, args);
- n = 2;
- argv[0] = (char *) cmd;
- argv[1] = (char *) args;
- while ((argv[n] = va_arg (va, char *)) != NULL)
- n++;
- va_end (va);
-
- /* OK, we need to block signals */
- sigfillset (&full);
- sigprocmask (SIG_SETMASK, &full, &old);
+ va_list va;
+ char **argv;
+ int n = 1;
+ int ret = 0;
+ pid_t pid;
+ sigset_t full;
+ sigset_t old;
+
+ va_start (va, args);
+ while (va_arg (va, char *) != NULL)
+ n++;
+ va_end (va);
+ argv = xmalloc (sizeof (char *) * (n + 2));
+
+ va_start (va, args);
+ n = 2;
+ argv[0] = (char *) cmd;
+ argv[1] = (char *) args;
+ while ((argv[n] = va_arg (va, char *)) != NULL)
+ n++;
+ va_end (va);
+
+ /* OK, we need to block signals */
+ sigfillset (&full);
+ sigprocmask (SIG_SETMASK, &full, &old);
#ifdef THERE_IS_NO_FORK
- signal_reset ();
- pid = vfork ();
+ signal_reset ();
+ pid = vfork ();
#else
- pid = fork();
+ pid = fork();
#endif
- switch (pid) {
- case -1:
- logger (LOG_ERR, "vfork: %s", strerror (errno));
- ret = -1;
- break;
- case 0:
+ switch (pid)
+ {
+ case -1:
+ logger (LOG_ERR, "vfork: %s", strerror (errno));
+ ret = -1;
+ break;
+ case 0:
#ifndef THERE_IS_NO_FORK
- signal_reset ();
+ signal_reset ();
#endif
- sigprocmask (SIG_SETMASK, &old, NULL);
- if (execvp (cmd, argv) && errno != ENOENT)
- logger (LOG_ERR, "error executing \"%s\": %s",
- cmd, strerror (errno));
- _exit (111);
- /* NOTREACHED */
- }
+ sigprocmask (SIG_SETMASK, &old, NULL);
+ if (execvp (cmd, argv) && errno != ENOENT)
+ logger (LOG_ERR, "error executing \"%s\": %s",
+ cmd, strerror (errno));
+ _exit (111);
+ /* NOTREACHED */
+ }
#ifdef THERE_IS_NO_FORK
- signal_setup ();
+ signal_setup ();
#endif
- /* Restore our signals */
- sigprocmask (SIG_SETMASK, &old, NULL);
+ /* Restore our signals */
+ sigprocmask (SIG_SETMASK, &old, NULL);
- free (argv);
- return (ret);
+ free (argv);
+ return (ret);
}
static void exec_script (const char *script, const char *infofile,
- const char *arg)
+ const char *arg)
{
- struct stat buf;
+ struct stat buf;
- if (! script || ! infofile || ! arg)
- return;
+ if (! script || ! infofile || ! arg)
+ return;
- if (stat (script, &buf) == -1) {
- if (strcmp (script, DEFAULT_SCRIPT) != 0)
- logger (LOG_ERR, "`%s': %s", script, strerror (ENOENT));
- return;
- }
+ if (stat (script, &buf) == -1)
+ {
+ if (strcmp (script, DEFAULT_SCRIPT) != 0)
+ logger (LOG_ERR, "`%s': %s", script, strerror (ENOENT));
+ return;
+ }
#ifdef ENABLE_INFO
- logger (LOG_DEBUG, "exec \"%s\" \"%s\" \"%s\"", script, infofile, arg);
- exec_cmd (script, infofile, arg, (char *) NULL);
+ logger (LOG_DEBUG, "exec \"%s\" \"%s\" \"%s\"", script, infofile, arg);
+ exec_cmd (script, infofile, arg, (char *) NULL);
#else
- logger (LOG_DEBUG, "exec \"%s\" \"\" \"%s\"", script, arg);
- exec_cmd (script, "", arg, (char *) NULL);
+ logger (LOG_DEBUG, "exec \"%s\" \"\" \"%s\"", script, arg);
+ exec_cmd (script, "", arg, (char *) NULL);
#endif
}
static int make_resolv (const char *ifname, const dhcp_t *dhcp)
{
- FILE *f = NULL;
- address_t *address;
+ FILE *f = NULL;
+ address_t *address;
#ifdef ENABLE_RESOLVCONF
- char *resolvconf = NULL;
-
- if (file_in_path ("resolvconf") == 0) {
- size_t len = strlen ("resolvconf -a ") + strlen (ifname) + 1;
- resolvconf = xmalloc (sizeof (char) * len);
- snprintf (resolvconf, len, "resolvconf -a %s", ifname);
- if ((f = popen (resolvconf , "w")))
- logger (LOG_DEBUG,
- "sending DNS information to resolvconf");
- else if (errno == EEXIST)
- logger (LOG_ERR, "popen: %s", strerror (errno));
-
- if (ferror (f))
- logger (LOG_ERR, "ferror");
- free (resolvconf);
- }
-#endif
- if (! f) {
- logger (LOG_DEBUG, "writing "RESOLVFILE);
- if (! (f = fopen(RESOLVFILE, "w")))
- logger (LOG_ERR, "fopen `%s': %s", RESOLVFILE, strerror (errno));
- }
-
- if (! f)
- return (-1);
-
- fprintf (f, "# Generated by dhcpcd for interface %s\n", ifname);
- if (dhcp->dnssearch)
- fprintf (f, "search %s\n", dhcp->dnssearch);
- else if (dhcp->dnsdomain) {
- fprintf (f, "search %s\n", dhcp->dnsdomain);
- }
-
- STAILQ_FOREACH (address, dhcp->dnsservers, entries)
- fprintf (f, "nameserver %s\n", inet_ntoa (address->address));
+ char *resolvconf = NULL;
+
+ if (file_in_path ("resolvconf") == 0)
+ {
+ size_t len = strlen ("resolvconf -a ") + strlen (ifname) + 1;
+ resolvconf = xmalloc (sizeof (char) * len);
+ snprintf (resolvconf, len, "resolvconf -a %s", ifname);
+ if ((f = popen (resolvconf , "w")))
+ logger (LOG_DEBUG,
+ "sending DNS information to resolvconf");
+ else if (errno == EEXIST)
+ logger (LOG_ERR, "popen: %s", strerror (errno));
+
+ if (ferror (f))
+ logger (LOG_ERR, "ferror");
+ free (resolvconf);
+ }
+#endif
+ if (! f)
+ {
+ logger (LOG_DEBUG, "writing "RESOLVFILE);
+ if (! (f = fopen(RESOLVFILE, "w")))
+ logger (LOG_ERR, "fopen `%s': %s", RESOLVFILE, strerror (errno));
+ }
+
+ if (! f)
+ return (-1);
+
+ fprintf (f, "# Generated by dhcpcd for interface %s\n", ifname);
+ if (dhcp->dnssearch)
+ fprintf (f, "search %s\n", dhcp->dnssearch);
+ else if (dhcp->dnsdomain)
+ {
+ fprintf (f, "search %s\n", dhcp->dnsdomain);
+ }
+
+ STAILQ_FOREACH (address, dhcp->dnsservers, entries)
+ fprintf (f, "nameserver %s\n", inet_ntoa (address->address));
#ifdef ENABLE_RESOLVCONF
- if (resolvconf)
- pclose (f);
- else
+ if (resolvconf)
+ pclose (f);
+ else
#endif
- fclose (f);
+ fclose (f);
- /* Refresh the local resolver */
- res_init ();
- return (0);
+ /* Refresh the local resolver */
+ res_init ();
+ return (0);
}
static void restore_resolv (const char *ifname)
{
#ifdef ENABLE_RESOLVCONF
- if (file_in_path ("resolvconf") == 0) {
- logger (LOG_DEBUG, "removing information from resolvconf");
- exec_cmd("resolvconf", "-d", ifname, (char *) NULL);
- }
+ if (file_in_path ("resolvconf") == 0)
+ {
+ logger (LOG_DEBUG, "removing information from resolvconf");
+ exec_cmd("resolvconf", "-d", ifname, (char *) NULL);
+ }
#endif
}
static bool in_addresses (const struct address_head *addresses,
- struct in_addr address)
+ struct in_addr address)
{
- const address_t *addr;
+ const address_t *addr;
- STAILQ_FOREACH (addr, addresses, entries)
- if (addr->address.s_addr == address.s_addr)
- return (true);
+ STAILQ_FOREACH (addr, addresses, entries)
+ if (addr->address.s_addr == address.s_addr)
+ return (true);
- return (false);
+ return (false);
}
static bool in_routes (const struct route_head *routes, route_t *route)
{
- const route_t *r;
-
- if (! routes)
- return (false);
-
- STAILQ_FOREACH (r, routes, entries)
- if (r->destination.s_addr == route->destination.s_addr &&
- r->netmask.s_addr == route->netmask.s_addr &&
- r->gateway.s_addr == route->gateway.s_addr)
- return (true);
-
- return (false);
+ const route_t *r;
+
+ if (! routes)
+ return (false);
+
+ STAILQ_FOREACH (r, routes, entries)
+ if (r->destination.s_addr == route->destination.s_addr &&
+ r->netmask.s_addr == route->netmask.s_addr &&
+ r->gateway.s_addr == route->gateway.s_addr)
+ return (true);
+
+ return (false);
}
#ifdef ENABLE_NTP
static int _make_ntp (const char *file, const char *ifname, const dhcp_t *dhcp)
{
- FILE *f;
- address_t *address;
- char *a;
- char *line;
- int tomatch = 0;
- char *token;
- bool ntp = false;
-
- STAILQ_FOREACH (address, dhcp->ntpservers, entries)
- tomatch++;
-
- /* Check that we really need to update the servers.
- * We do this because ntp has to be restarted to
- * work with a changed config. */
- if (! (f = fopen (file, "r"))) {
- if (errno != ENOENT) {
- logger (LOG_ERR, "fopen `%s': %s",
- file, strerror (errno));
- return (-1);
- }
- } else {
- while (tomatch != 0 && (line = get_line (f))) {
- struct in_addr addr;
-
- a = line;
- token = strsep (&a, " ");
- if (! token || strcmp (token, "server") != 0)
- goto next;
-
- if ((token = strsep (&a, " \n")) == NULL)
- goto next;
-
- if (inet_aton (token, &addr) == 1 &&
- in_addresses (dhcp->ntpservers, addr))
- tomatch--;
+ FILE *f;
+ address_t *address;
+ char *a;
+ char *line;
+ int tomatch = 0;
+ char *token;
+ bool ntp = false;
+
+ STAILQ_FOREACH (address, dhcp->ntpservers, entries)
+ tomatch++;
+
+ /* Check that we really need to update the servers.
+ * We do this because ntp has to be restarted to
+ * work with a changed config. */
+ if (! (f = fopen (file, "r")))
+ {
+ if (errno != ENOENT)
+ {
+ logger (LOG_ERR, "fopen `%s': %s",
+ file, strerror (errno));
+ return (-1);
+ }
+ }
+ else
+ {
+ while (tomatch != 0 && (line = get_line (f)))
+ {
+ struct in_addr addr;
+
+ a = line;
+ token = strsep (&a, " ");
+ if (! token || strcmp (token, "server") != 0)
+ goto next;
+
+ if ((token = strsep (&a, " \n")) == NULL)
+ goto next;
+
+ if (inet_aton (token, &addr) == 1 &&
+ in_addresses (dhcp->ntpservers, addr))
+ tomatch--;
next:
- free (line);
- }
- fclose (f);
-
- /* File has the same name servers that we do,
- * so no need to restart ntp */
- if (tomatch == 0) {
- logger (LOG_DEBUG, "%s already configured, skipping",
- file);
- return (0);
- }
- }
-
- logger (LOG_DEBUG, "writing %s", file);
- if (! (f = fopen (file, "w"))) {
- logger (LOG_ERR, "fopen `%s': %s", file, strerror (errno));
- return (-1);
- }
-
- fprintf (f, "# Generated by dhcpcd for interface %s\n", ifname);
+ free (line);
+ }
+ fclose (f);
+
+ /* File has the same name servers that we do,
+ * so no need to restart ntp */
+ if (tomatch == 0)
+ {
+ logger (LOG_DEBUG, "%s already configured, skipping",
+ file);
+ return (0);
+ }
+ }
+
+ logger (LOG_DEBUG, "writing %s", file);
+ if (! (f = fopen (file, "w")))
+ {
+ logger (LOG_ERR, "fopen `%s': %s", file, strerror (errno));
+ return (-1);
+ }
+
+ fprintf (f, "# Generated by dhcpcd for interface %s\n", ifname);
#ifdef NTPFILE
- if (strcmp (file, NTPFILE) == 0) {
- ntp = true;
- fprintf (f, "restrict default noquery notrust nomodify\n");
- fprintf (f, "restrict 127.0.0.1\n");
- }
-#endif
-
- STAILQ_FOREACH (address, dhcp->ntpservers, entries) {
- a = inet_ntoa (address->address);
- if (ntp)
- fprintf (f, "restrict %s nomodify notrap noquery\n", a);
- fprintf (f, "server %s\n", a);
- }
- fclose (f);
-
- return (1);
+ if (strcmp (file, NTPFILE) == 0)
+ {
+ ntp = true;
+ fprintf (f, "restrict default noquery notrust nomodify\n");
+ fprintf (f, "restrict 127.0.0.1\n");
+ }
+#endif
+
+ STAILQ_FOREACH (address, dhcp->ntpservers, entries)
+ {
+ a = inet_ntoa (address->address);
+ if (ntp)
+ fprintf (f, "restrict %s nomodify notrap noquery\n", a);
+ fprintf (f, "server %s\n", a);
+ }
+ fclose (f);
+
+ return (1);
}
static int make_ntp (const char *ifname, const dhcp_t *dhcp)
{
- /* On some systems we have only have one ntp service, but we don't
- * know which configuration file we're using. So we need to write
- * to both and restart accordingly. */
+ /* On some systems we have only have one ntp service, but we don't
+ * know which configuration file we're using. So we need to write
+ * to both and restart accordingly. */
- bool restart_ntp = false;
- bool restart_openntp = false;
- int retval = 0;
+ bool restart_ntp = false;
+ bool restart_openntp = false;
+ int retval = 0;
#ifdef NTPFILE
- if (_make_ntp (NTPFILE, ifname, dhcp) > 0)
- restart_ntp = true;
+ if (_make_ntp (NTPFILE, ifname, dhcp) > 0)
+ restart_ntp = true;
#endif
#ifdef OPENNTPFILE
- if (_make_ntp (OPENNTPFILE, ifname, dhcp) > 0)
- restart_openntp = true;
+ if (_make_ntp (OPENNTPFILE, ifname, dhcp) > 0)
+ restart_openntp = true;
#endif
#ifdef NTPSERVICE
- if (restart_ntp) {
+ if (restart_ntp)
+ {
#ifdef NTPCHECK
- if (system (NTPCHECK) == 0)
+ if (system (NTPCHECK) == 0)
#endif
- retval += exec_cmd (NTPSERVICE, NTPRESTARTARGS,
- (char *) NULL);
- }
+ retval += exec_cmd (NTPSERVICE, NTPRESTARTARGS,
+ (char *) NULL);
+ }
#endif
#if defined (NTPSERVICE) && defined (OPENNTPSERVICE)
- if (restart_openntp &&
- (strcmp (NTPSERVICE, OPENNTPSERVICE) != 0 || ! restart_ntp))
- {
+ if (restart_openntp &&
+ (strcmp (NTPSERVICE, OPENNTPSERVICE) != 0 || ! restart_ntp))
+ {
#ifdef OPENNTPCHECK
- if (system (OPENNTPCHECK) == 0)
+ if (system (OPENNTPCHECK) == 0)
#endif
- retval += exec_cmd (OPENNTPSERVICE,
- OPENNTPRESTARTARGS, (char *) NULL);
- }
+ retval += exec_cmd (OPENNTPSERVICE,
+ OPENNTPRESTARTARGS, (char *) NULL);
+ }
#elif defined (OPENNTPSERVICE) && ! defined (NTPSERVICE)
- if (restart_openntp) {
+ if (restart_openntp)
+ {
#ifdef OPENNTPCHECK
- if (system (OPENNTPCHECK) == 0)
+ if (system (OPENNTPCHECK) == 0)
#endif
- retval += exec_cmd (OPENNTPSERVICE,
- OPENNTPRESTARTARGS, (char *) NULL);
- }
+ retval += exec_cmd (OPENNTPSERVICE,
+ OPENNTPRESTARTARGS, (char *) NULL);
+ }
#endif
- return (retval);
+ return (retval);
}
#endif
@@ -404,411 +424,438 @@ static int make_ntp (const char *ifname, const dhcp_t *dhcp)
#define PREFIXSIZE 256
static int make_nis (const char *ifname, const dhcp_t *dhcp)
{
- FILE *f;
- address_t *address;
- char *prefix;
-
- logger (LOG_DEBUG, "writing "NISFILE);
- if (! (f = fopen(NISFILE, "w"))) {
- logger (LOG_ERR, "fopen `%s': %s", NISFILE, strerror (errno));
- return (-1);
- }
-
- prefix = xmalloc (sizeof (char) * PREFIXSIZE);
- *prefix = '\0';
- fprintf (f, "# Generated by dhcpcd for interface %s\n", ifname);
-
- if (dhcp->nisdomain) {
- setdomainname (dhcp->nisdomain, (int) strlen (dhcp->nisdomain));
-
- if (dhcp->nisservers)
- snprintf (prefix, PREFIXSIZE, "domain %s server",
- dhcp->nisdomain);
- else
- fprintf (f, "domain %s broadcast\n", dhcp->nisdomain);
- }
- else
- snprintf (prefix, PREFIXSIZE, "%s", "ypserver");
-
- NSTAILQ_FOREACH (address, dhcp->nisservers, entries)
- fprintf (f, "%s %s\n", prefix, inet_ntoa (address->address));
-
- free (prefix);
- fclose (f);
+ FILE *f;
+ address_t *address;
+ char *prefix;
+
+ logger (LOG_DEBUG, "writing "NISFILE);
+ if (! (f = fopen(NISFILE, "w")))
+ {
+ logger (LOG_ERR, "fopen `%s': %s", NISFILE, strerror (errno));
+ return (-1);
+ }
+
+ prefix = xmalloc (sizeof (char) * PREFIXSIZE);
+ *prefix = '\0';
+ fprintf (f, "# Generated by dhcpcd for interface %s\n", ifname);
+
+ if (dhcp->nisdomain)
+ {
+ setdomainname (dhcp->nisdomain, (int) strlen (dhcp->nisdomain));
+
+ if (dhcp->nisservers)
+ snprintf (prefix, PREFIXSIZE, "domain %s server",
+ dhcp->nisdomain);
+ else
+ fprintf (f, "domain %s broadcast\n", dhcp->nisdomain);
+ }
+ else
+ snprintf (prefix, PREFIXSIZE, "%s", "ypserver");
+
+ NSTAILQ_FOREACH (address, dhcp->nisservers, entries)
+ fprintf (f, "%s %s\n", prefix, inet_ntoa (address->address));
+
+ free (prefix);
+ fclose (f);
#ifdef NISCHECK
- if (system (NISCHECK) == 0)
+ if (system (NISCHECK) == 0)
#endif
- exec_cmd (NISSERVICE, NISRESTARTARGS, (char *) NULL);
- return (0);
+ exec_cmd (NISSERVICE, NISRESTARTARGS, (char *) NULL);
+ return (0);
}
#endif
static char *lookuphostname (char *hostname, const dhcp_t *dhcp,
- const options_t *options)
+ const options_t *options)
{
- union {
- struct sockaddr sa;
- struct sockaddr_in sin;
- } su;
- socklen_t salen;
- char *addr;
- struct addrinfo hints;
- struct addrinfo *res = NULL;
- int result;
- char *p;
-
- logger (LOG_DEBUG, "Looking up hostname via DNS");
- addr = xmalloc (sizeof (char) * NI_MAXHOST);
- salen = sizeof (su.sa);
- memset (&su.sa, 0, salen);
- su.sin.sin_family = AF_INET;
- memcpy (&su.sin.sin_addr, &dhcp->address, sizeof (su.sin.sin_addr));
-
- if ((result = getnameinfo (&su.sa, salen, addr, NI_MAXHOST,
- NULL, 0, NI_NAMEREQD)) != 0) {
- logger (LOG_ERR,
- "Failed to lookup hostname via DNS: %s",
- gai_strerror (result));
- free (addr);
- return (NULL);
- }
-
- /* Check for a malicious PTR record */
- memset (&hints, 0, sizeof (hints));
- hints.ai_socktype = SOCK_DGRAM;
- hints.ai_flags = AI_NUMERICHOST;
- result = getaddrinfo (addr, "0", &hints, &res);
- if (res)
- freeaddrinfo (res);
- if (result == 0)
- logger (LOG_ERR, "malicious PTR record detected");
- if (result == 0 || ! *addr) {
- free (addr);
- return (NULL);
- }
-
- p = strchr (addr, '.');
- if (p) {
- switch (options->dohostname) {
- case 1: /* -H */
- case 4: /* -HHHH */
- break;
- case 2: /* -HH */
- case 5: /* -HHHHH */
- /* Strip out the domain if it matches */
- p++;
- if (*p && dhcp->dnssearch) {
- char *s = xstrdup (dhcp->dnssearch);
- char *sp = s;
- char *t;
-
- while ((t = strsep (&sp, " ")))
- if (strcmp (t, p) == 0) {
- *--p = '\0';
- break;
- }
- free (s);
- } else if (dhcp->dnsdomain) {
- if (strcmp (dhcp->dnsdomain, p) == 0)
- *--p = '\0';
- }
- break;
- case 3: /* -HHH */
- case 6: /* -HHHHHH */
- /* Just strip the domain */
- *p = '\0';
- break;
- default: /* Too many H! */
- break;
- }
- }
-
- strlcpy (hostname, addr, MAXHOSTNAMELEN);
- free (addr);
- return (hostname);
+ union
+ {
+ struct sockaddr sa;
+ struct sockaddr_in sin;
+ } su;
+ socklen_t salen;
+ char *addr;
+ struct addrinfo hints;
+ struct addrinfo *res = NULL;
+ int result;
+ char *p;
+
+ logger (LOG_DEBUG, "Looking up hostname via DNS");
+ addr = xmalloc (sizeof (char) * NI_MAXHOST);
+ salen = sizeof (su.sa);
+ memset (&su.sa, 0, salen);
+ su.sin.sin_family = AF_INET;
+ memcpy (&su.sin.sin_addr, &dhcp->address, sizeof (su.sin.sin_addr));
+
+ if ((result = getnameinfo (&su.sa, salen, addr, NI_MAXHOST,
+ NULL, 0, NI_NAMEREQD)) != 0)
+ {
+ logger (LOG_ERR,
+ "Failed to lookup hostname via DNS: %s",
+ gai_strerror (result));
+ free (addr);
+ return (NULL);
+ }
+
+ /* Check for a malicious PTR record */
+ memset (&hints, 0, sizeof (hints));
+ hints.ai_socktype = SOCK_DGRAM;
+ hints.ai_flags = AI_NUMERICHOST;
+ result = getaddrinfo (addr, "0", &hints, &res);
+ if (res)
+ freeaddrinfo (res);
+ if (result == 0)
+ logger (LOG_ERR, "malicious PTR record detected");
+ if (result == 0 || ! *addr)
+ {
+ free (addr);
+ return (NULL);
+ }
+
+ p = strchr (addr, '.');
+ if (p)
+ {
+ switch (options->dohostname)
+ {
+ case 1: /* -H */
+ case 4: /* -HHHH */
+ break;
+ case 2: /* -HH */
+ case 5: /* -HHHHH */
+ /* Strip out the domain if it matches */
+ p++;
+ if (*p && dhcp->dnssearch)
+ {
+ char *s = xstrdup (dhcp->dnssearch);
+ char *sp = s;
+ char *t;
+
+ while ((t = strsep (&sp, " ")))
+ if (strcmp (t, p) == 0)
+ {
+ *--p = '\0';
+ break;
+ }
+ free (s);
+ }
+ else if (dhcp->dnsdomain)
+ {
+ if (strcmp (dhcp->dnsdomain, p) == 0)
+ *--p = '\0';
+ }
+ break;
+ case 3: /* -HHH */
+ case 6: /* -HHHHHH */
+ /* Just strip the domain */
+ *p = '\0';
+ break;
+ default: /* Too many H! */
+ break;
+ }
+ }
+
+ strlcpy (hostname, addr, MAXHOSTNAMELEN);
+ free (addr);
+ return (hostname);
}
int configure (const options_t *options, interface_t *iface,
- const dhcp_t *dhcp, bool up)
+ const dhcp_t *dhcp, bool up)
{
- route_t *route = NULL;
- struct route_head *new_routes = NULL;
- route_t *new_route = NULL;
- char *newhostname = NULL;
- char *curhostname = NULL;
- int remember;
+ route_t *route = NULL;
+ struct route_head *new_routes = NULL;
+ route_t *new_route = NULL;
+ char *newhostname = NULL;
+ char *curhostname = NULL;
+ int remember;
#ifdef ENABLE_IPV4LL
- bool haslinklocal = false;
+ bool haslinklocal = false;
#endif
#ifdef THERE_IS_NO_FORK
- int skip = 0;
- size_t skiplen;
- char *skipp;
-#endif
-
- if (! options || ! iface || ! dhcp)
- return (-1);
-
- if (dhcp->address.s_addr == 0)
- up = 0;
-
- logGatewayToFile(iface, dhcp);
-
- /* Remove old routes.
- * Always do this as the interface may have >1 address not added by us
- * so the routes we added may still exist. */
- NSTAILQ_FOREACH (route, iface->previous_routes, entries)
- if ((route->destination.s_addr || options->dogateway) &&
- (! up || ! in_routes (dhcp->routes, route)))
- del_route (iface->name, route->destination,
- route->netmask, route->gateway,
- options->metric);
- /* If we aren't up, then reset the interface as much as we can */
- if (! up) {
- if (iface->previous_routes) {
- free_route (iface->previous_routes);
- iface->previous_routes = NULL;
- }
-
- /* Restore the original MTU value */
- if (iface->mtu && iface->previous_mtu != iface->mtu) {
- set_mtu (iface->name, iface->mtu);
- iface->previous_mtu = iface->mtu;
- }
+ int skip = 0;
+ size_t skiplen;
+ char *skipp;
+#endif
+
+ if (! options || ! iface || ! dhcp)
+ return (-1);
+
+ if (dhcp->address.s_addr == 0)
+ up = 0;
+
+ logGatewayToFile(iface, dhcp);
+
+ /* Remove old routes.
+ * Always do this as the interface may have >1 address not added by us
+ * so the routes we added may still exist. */
+ NSTAILQ_FOREACH (route, iface->previous_routes, entries)
+ if ((route->destination.s_addr || options->dogateway) &&
+ (! up || ! in_routes (dhcp->routes, route)))
+ del_route (iface->name, route->destination,
+ route->netmask, route->gateway,
+ options->metric);
+ /* If we aren't up, then reset the interface as much as we can */
+ if (! up)
+ {
+ if (iface->previous_routes)
+ {
+ free_route (iface->previous_routes);
+ iface->previous_routes = NULL;
+ }
+
+ /* Restore the original MTU value */
+ if (iface->mtu && iface->previous_mtu != iface->mtu)
+ {
+ set_mtu (iface->name, iface->mtu);
+ iface->previous_mtu = iface->mtu;
+ }
#ifdef ENABLE_INFO
- /* If we haven't created an info file, do so now */
- if (! dhcp->frominfo)
- write_info (iface, dhcp, options, false);
-#endif
-
- /* Only reset things if we had set them before */
- if (iface->previous_address.s_addr != 0) {
- if (! options->keep_address) {
- del_address (iface->name,
- iface->previous_address,
- iface->previous_netmask);
- memset (&iface->previous_address,
- 0, sizeof (iface->previous_address));
- memset (&iface->previous_netmask,
- 0, sizeof (iface->previous_netmask));
- }
- }
-
- restore_resolv (iface->name);
- exec_script (options->script, iface->infofile, "down");
-
- return (0);
- }
-
- /* Set the MTU requested.
- * If the DHCP server no longer sends one OR it's invalid then
- * we restore the original MTU */
- if (options->domtu) {
- unsigned short mtu = iface->mtu;
- if (dhcp->mtu)
- mtu = dhcp->mtu;
-
- if (mtu != iface->previous_mtu) {
- if (set_mtu (iface->name, mtu) == 0)
- iface->previous_mtu = mtu;
- }
- }
-
- /* This also changes netmask */
- if (! options->doinform || ! has_address (iface->name, dhcp->address))
- if (add_address (iface->name, dhcp->address, dhcp->netmask,
- dhcp->broadcast) == -1 && errno != EEXIST)
- return (false);
-
- /* Now delete the old address if different */
- if (iface->previous_address.s_addr != dhcp->address.s_addr &&
- iface->previous_address.s_addr != 0 &&
- ! options->keep_address)
- del_address (iface->name,
- iface->previous_address, iface->previous_netmask);
+ /* If we haven't created an info file, do so now */
+ if (! dhcp->frominfo)
+ write_info (iface, dhcp, options, false);
+#endif
+
+ /* Only reset things if we had set them before */
+ if (iface->previous_address.s_addr != 0)
+ {
+ if (! options->keep_address)
+ {
+ del_address (iface->name,
+ iface->previous_address,
+ iface->previous_netmask);
+ memset (&iface->previous_address,
+ 0, sizeof (iface->previous_address));
+ memset (&iface->previous_netmask,
+ 0, sizeof (iface->previous_netmask));
+ }
+ }
+
+ restore_resolv (iface->name);
+ exec_script (options->script, iface->infofile, "down");
+
+ return (0);
+ }
+
+ /* Set the MTU requested.
+ * If the DHCP server no longer sends one OR it's invalid then
+ * we restore the original MTU */
+ if (options->domtu)
+ {
+ unsigned short mtu = iface->mtu;
+ if (dhcp->mtu)
+ mtu = dhcp->mtu;
+
+ if (mtu != iface->previous_mtu)
+ {
+ if (set_mtu (iface->name, mtu) == 0)
+ iface->previous_mtu = mtu;
+ }
+ }
+
+ /* This also changes netmask */
+ if (! options->doinform || ! has_address (iface->name, dhcp->address))
+ if (add_address (iface->name, dhcp->address, dhcp->netmask,
+ dhcp->broadcast) == -1 && errno != EEXIST)
+ return (false);
+
+ /* Now delete the old address if different */
+ if (iface->previous_address.s_addr != dhcp->address.s_addr &&
+ iface->previous_address.s_addr != 0 &&
+ ! options->keep_address)
+ del_address (iface->name,
+ iface->previous_address, iface->previous_netmask);
#ifdef __linux__
- /* On linux, we need to change the subnet route to have our metric. */
- if (iface->previous_address.s_addr != dhcp->address.s_addr &&
- options->metric > 0 &&
- dhcp->netmask.s_addr != INADDR_BROADCAST)
- {
- struct in_addr td;
- struct in_addr tg;
- memset (&td, 0, sizeof (td));
- memset (&tg, 0, sizeof (tg));
- td.s_addr = dhcp->address.s_addr & dhcp->netmask.s_addr;
- add_route (iface->name, td, dhcp->netmask, tg, options->metric);
- del_route (iface->name, td, dhcp->netmask, tg, 0);
- }
+ /* On linux, we need to change the subnet route to have our metric. */
+ if (iface->previous_address.s_addr != dhcp->address.s_addr &&
+ options->metric > 0 &&
+ dhcp->netmask.s_addr != INADDR_BROADCAST)
+ {
+ struct in_addr td;
+ struct in_addr tg;
+ memset (&td, 0, sizeof (td));
+ memset (&tg, 0, sizeof (tg));
+ td.s_addr = dhcp->address.s_addr & dhcp->netmask.s_addr;
+ add_route (iface->name, td, dhcp->netmask, tg, options->metric);
+ del_route (iface->name, td, dhcp->netmask, tg, 0);
+ }
#endif
#ifdef THERE_IS_NO_FORK
- free (dhcpcd_skiproutes);
- /* We can never have more than 255 routes. So we need space
- * for 255 3 digit numbers and commas */
- skiplen = 255 * 4 + 1;
- skipp = dhcpcd_skiproutes = xmalloc (sizeof (char) * skiplen);
- *skipp = '\0';
+ free (dhcpcd_skiproutes);
+ /* We can never have more than 255 routes. So we need space
+ * for 255 3 digit numbers and commas */
+ skiplen = 255 * 4 + 1;
+ skipp = dhcpcd_skiproutes = xmalloc (sizeof (char) * skiplen);
+ *skipp = '\0';
#endif
- /* Remember added routes */
- NSTAILQ_FOREACH (route, dhcp->routes, entries) {
+ /* Remember added routes */
+ NSTAILQ_FOREACH (route, dhcp->routes, entries)
+ {
#ifdef ENABLE_IPV4LL
- /* Check if we have already got a link locale route dished
- * out by the DHCP server */
- if (route->destination.s_addr == htonl (LINKLOCAL_ADDR) &&
- route->netmask.s_addr == htonl (LINKLOCAL_MASK))
- haslinklocal = true;
-#endif
- /* Don't set default routes if not asked to */
- if (route->destination.s_addr == 0 &&
- route->netmask.s_addr == 0 &&
- ! options->dogateway)
- continue;
-
- remember = add_route (iface->name, route->destination,
- route->netmask, route->gateway,
- options->metric);
- /* If we failed to add the route, we may have already added it
- ourselves. If so, remember it again. */
- if (remember < 0 && in_routes (iface->previous_routes, route))
- remember = 1;
-
- if (remember >= 0) {
- if (! new_routes) {
- new_routes = xmalloc (sizeof (*new_routes));
- STAILQ_INIT (new_routes);
- }
- new_route = xmalloc (sizeof (route_t));
- memcpy (new_route, route, sizeof (*new_route));
- STAILQ_INSERT_TAIL (new_routes, new_route, entries);
- }
+ /* Check if we have already got a link locale route dished
+ * out by the DHCP server */
+ if (route->destination.s_addr == htonl (LINKLOCAL_ADDR) &&
+ route->netmask.s_addr == htonl (LINKLOCAL_MASK))
+ haslinklocal = true;
+#endif
+ /* Don't set default routes if not asked to */
+ if (route->destination.s_addr == 0 &&
+ route->netmask.s_addr == 0 &&
+ ! options->dogateway)
+ continue;
+
+ remember = add_route (iface->name, route->destination,
+ route->netmask, route->gateway,
+ options->metric);
+ /* If we failed to add the route, we may have already added it
+ ourselves. If so, remember it again. */
+ if (remember < 0 && in_routes (iface->previous_routes, route))
+ remember = 1;
+
+ if (remember >= 0)
+ {
+ if (! new_routes)
+ {
+ new_routes = xmalloc (sizeof (*new_routes));
+ STAILQ_INIT (new_routes);
+ }
+ new_route = xmalloc (sizeof (route_t));
+ memcpy (new_route, route, sizeof (*new_route));
+ STAILQ_INSERT_TAIL (new_routes, new_route, entries);
+ }
#ifdef THERE_IS_NO_FORK
- /* If we have daemonised yet we need to record which routes
- * we failed to add so we can skip them */
- else if (! options->daemonised) {
- /* We can never have more than 255 / 4 routes,
- * so 3 chars is plently */
- if (*skipp)
- *skipp++ = ',';
- skipp += snprintf (skipp,
- dhcpcd_skiproutes + skiplen - skipp,
- "%d", skip);
- }
- skip++;
-#endif
- }
+ /* If we have daemonised yet we need to record which routes
+ * we failed to add so we can skip them */
+ else if (! options->daemonised)
+ {
+ /* We can never have more than 255 / 4 routes,
+ * so 3 chars is plently */
+ if (*skipp)
+ *skipp++ = ',';
+ skipp += snprintf (skipp,
+ dhcpcd_skiproutes + skiplen - skipp,
+ "%d", skip);
+ }
+ skip++;
+#endif
+ }
#ifdef THERE_IS_NO_FORK
- if (*dhcpcd_skiproutes)
- *skipp = '\0';
- else {
- free (dhcpcd_skiproutes);
- dhcpcd_skiproutes = NULL;
- }
+ if (*dhcpcd_skiproutes)
+ *skipp = '\0';
+ else
+ {
+ free (dhcpcd_skiproutes);
+ dhcpcd_skiproutes = NULL;
+ }
#endif
#ifdef ENABLE_IPV4LL
- /* Ensure we always add the link local route if we got a private
- * address and isn't link local itself */
- if (options->doipv4ll &&
- ! haslinklocal &&
- IN_PRIVATE (ntohl (dhcp->address.s_addr)))
- {
- struct in_addr dest;
- struct in_addr mask;
- struct in_addr gate;
-
- dest.s_addr = htonl (LINKLOCAL_ADDR);
- mask.s_addr = htonl (LINKLOCAL_MASK);
- gate.s_addr = 0;
- remember = add_route (iface->name, dest, mask, gate,
- options->metric);
-
- if (remember >= 0) {
- if (! new_routes) {
- new_routes = xmalloc (sizeof (*new_routes));
- STAILQ_INIT (new_routes);
- }
- new_route = xmalloc (sizeof (*new_route));
- new_route->destination.s_addr = dest.s_addr;
- new_route->netmask.s_addr = mask.s_addr;
- new_route->gateway.s_addr = gate.s_addr;
- STAILQ_INSERT_TAIL (new_routes, new_route, entries);
- }
- }
-#endif
-
- if (iface->previous_routes)
- free_route (iface->previous_routes);
- iface->previous_routes = new_routes;
-
- logToQt(LOG_INFO, DHCPCD_WRITE, "");
- if (options->dodns && dhcp->dnsservers)
- make_resolv(iface->name, dhcp);
- else
- logger (LOG_DEBUG, "no dns information to write");
+ /* Ensure we always add the link local route if we got a private
+ * address and isn't link local itself */
+ if (options->doipv4ll &&
+ ! haslinklocal &&
+ IN_PRIVATE (ntohl (dhcp->address.s_addr)))
+ {
+ struct in_addr dest;
+ struct in_addr mask;
+ struct in_addr gate;
+
+ dest.s_addr = htonl (LINKLOCAL_ADDR);
+ mask.s_addr = htonl (LINKLOCAL_MASK);
+ gate.s_addr = 0;
+ remember = add_route (iface->name, dest, mask, gate,
+ options->metric);
+
+ if (remember >= 0)
+ {
+ if (! new_routes)
+ {
+ new_routes = xmalloc (sizeof (*new_routes));
+ STAILQ_INIT (new_routes);
+ }
+ new_route = xmalloc (sizeof (*new_route));
+ new_route->destination.s_addr = dest.s_addr;
+ new_route->netmask.s_addr = mask.s_addr;
+ new_route->gateway.s_addr = gate.s_addr;
+ STAILQ_INSERT_TAIL (new_routes, new_route, entries);
+ }
+ }
+#endif
+
+ if (iface->previous_routes)
+ free_route (iface->previous_routes);
+ iface->previous_routes = new_routes;
+
+ logToQt(LOG_INFO, DHCPCD_WRITE, "");
+ if (options->dodns && dhcp->dnsservers)
+ make_resolv(iface->name, dhcp);
+ else
+ logger (LOG_DEBUG, "no dns information to write");
#ifdef ENABLE_NTP
- if (options->dontp && dhcp->ntpservers)
- make_ntp(iface->name, dhcp);
+ if (options->dontp && dhcp->ntpservers)
+ make_ntp(iface->name, dhcp);
#endif
#ifdef ENABLE_NIS
- if (options->donis && (dhcp->nisservers || dhcp->nisdomain))
- make_nis(iface->name, dhcp);
+ if (options->donis && (dhcp->nisservers || dhcp->nisdomain))
+ make_nis(iface->name, dhcp);
#endif
- curhostname = xmalloc (sizeof (char) * MAXHOSTNAMELEN);
- *curhostname = '\0';
+ curhostname = xmalloc (sizeof (char) * MAXHOSTNAMELEN);
+ *curhostname = '\0';
- gethostname (curhostname, MAXHOSTNAMELEN);
- if (options->dohostname ||
- strlen (curhostname) == 0 ||
- strcmp (curhostname, "(none)") == 0 ||
- strcmp (curhostname, "localhost") == 0)
- {
- newhostname = xmalloc (sizeof (char) * MAXHOSTNAMELEN);
+ gethostname (curhostname, MAXHOSTNAMELEN);
+ if (options->dohostname ||
+ strlen (curhostname) == 0 ||
+ strcmp (curhostname, "(none)") == 0 ||
+ strcmp (curhostname, "localhost") == 0)
+ {
+ newhostname = xmalloc (sizeof (char) * MAXHOSTNAMELEN);
- if (dhcp->hostname)
- strlcpy (newhostname, dhcp->hostname, MAXHOSTNAMELEN);
- else
- *newhostname = '\0';
+ if (dhcp->hostname)
+ strlcpy (newhostname, dhcp->hostname, MAXHOSTNAMELEN);
+ else
+ *newhostname = '\0';
- /* Now we have made a resolv.conf we can obtain a hostname
- * if we need it */
- if (! *newhostname || options->dohostname > 3)
- lookuphostname (newhostname, dhcp, options);
+ /* Now we have made a resolv.conf we can obtain a hostname
+ * if we need it */
+ if (! *newhostname || options->dohostname > 3)
+ lookuphostname (newhostname, dhcp, options);
- if (*newhostname) {
- logger (LOG_INFO, "setting hostname to `%s'",
- newhostname);
- sethostname (newhostname, (int) strlen (newhostname));
- }
+ if (*newhostname)
+ {
+ logger (LOG_INFO, "setting hostname to `%s'",
+ newhostname);
+ sethostname (newhostname, (int) strlen (newhostname));
+ }
- free (newhostname);
- }
+ free (newhostname);
+ }
- free (curhostname);
+ free (curhostname);
#ifdef ENABLE_INFO
- if (! dhcp->frominfo)
- write_info (iface, dhcp, options, true);
-#endif
-
- if (iface->previous_address.s_addr != dhcp->address.s_addr ||
- iface->previous_netmask.s_addr != dhcp->netmask.s_addr)
- {
- memcpy (&iface->previous_address,
- &dhcp->address, sizeof (iface->previous_address));
- memcpy (&iface->previous_netmask,
- &dhcp->netmask, sizeof (iface->previous_netmask));
- exec_script (options->script, iface->infofile, "new");
- } else
- exec_script (options->script, iface->infofile, "up");
-
- return (0);
+ if (! dhcp->frominfo)
+ write_info (iface, dhcp, options, true);
+#endif
+
+ if (iface->previous_address.s_addr != dhcp->address.s_addr ||
+ iface->previous_netmask.s_addr != dhcp->netmask.s_addr)
+ {
+ memcpy (&iface->previous_address,
+ &dhcp->address, sizeof (iface->previous_address));
+ memcpy (&iface->previous_netmask,
+ &dhcp->netmask, sizeof (iface->previous_netmask));
+ exec_script (options->script, iface->infofile, "new");
+ }
+ else
+ exec_script (options->script, iface->infofile, "up");
+
+ return (0);
}