diff options
Diffstat (limited to 'src/customdhcpcd/configure.c')
-rw-r--r-- | src/customdhcpcd/configure.c | 1267 |
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); } |