aboutsummaryrefslogtreecommitdiffstats
path: root/configure.c
diff options
context:
space:
mode:
authorThe Android Open Source Project <initial-contribution@android.com>2009-03-03 18:28:20 -0800
committerThe Android Open Source Project <initial-contribution@android.com>2009-03-03 18:28:20 -0800
commitd97c47cad830d00c9da685cc4ea157d6185f6c97 (patch)
tree4b825dc642cb6eb9a060e54bf8d69288fbee4904 /configure.c
parent4c5a5fb53bccceff331bae70f748bf9b4609fe0a (diff)
downloadexternal_dhcpcd-d97c47cad830d00c9da685cc4ea157d6185f6c97.zip
external_dhcpcd-d97c47cad830d00c9da685cc4ea157d6185f6c97.tar.gz
external_dhcpcd-d97c47cad830d00c9da685cc4ea157d6185f6c97.tar.bz2
auto import from //depot/cupcake/@135843
Diffstat (limited to 'configure.c')
-rw-r--r--configure.c420
1 files changed, 0 insertions, 420 deletions
diff --git a/configure.c b/configure.c
deleted file mode 100644
index dad3bce..0000000
--- a/configure.c
+++ /dev/null
@@ -1,420 +0,0 @@
-/*
- * dhcpcd - DHCP client daemon
- * Copyright 2006-2008 Roy Marples <roy@marples.name>
- * All rights reserved
-
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <sys/stat.h>
-#include <sys/wait.h>
-
-#include <netinet/in.h>
-#include <arpa/inet.h>
-
-#include <ctype.h>
-#include <errno.h>
-#include <signal.h>
-#include <stdlib.h>
-#include <unistd.h>
-
-#include "config.h"
-#include "common.h"
-#include "configure.h"
-#include "dhcp.h"
-#include "dhcpcd.h"
-#include "logger.h"
-#include "net.h"
-#include "signals.h"
-
-#define DEFAULT_PATH "PATH=/usr/bin:/usr/sbin:/bin:/sbin"
-
-
-static int
-exec_script(char *const *argv, char *const *env)
-{
- pid_t pid;
- sigset_t full;
- sigset_t old;
-
- /* OK, we need to block signals */
- sigfillset(&full);
- sigprocmask(SIG_SETMASK, &full, &old);
- signal_reset();
-
- switch (pid = vfork()) {
- case -1:
- logger(LOG_ERR, "vfork: %s", strerror(errno));
- break;
- case 0:
- sigprocmask(SIG_SETMASK, &old, NULL);
- execve(argv[0], argv, env);
- logger(LOG_ERR, "%s: %s", argv[0], strerror(errno));
- _exit(127);
- /* NOTREACHED */
- }
-
- /* Restore our signals */
- signal_setup();
- sigprocmask(SIG_SETMASK, &old, NULL);
- return pid;
-}
-
-int
-run_script(const struct options *options, const char *iface,
- const char *reason,
- const struct dhcp_message *dhcpn, const struct dhcp_message *dhcpo)
-{
- char *const argv[2] = { UNCONST(options->script), NULL };
- char **env = NULL, **ep;
- char *path;
- ssize_t e, elen;
- pid_t pid;
- int status = 0;
-
- logger(LOG_DEBUG, "executing `%s', reason %s", options->script, reason);
-
- /* Make our env */
- elen = 5;
- env = xmalloc(sizeof(char *) * (elen + 1));
- path = getenv("PATH");
- if (path) {
- e = strlen("PATH") + strlen(path) + 2;
- env[0] = xmalloc(e);
- snprintf(env[0], e, "PATH=%s", path);
- } else
- env[0] = xstrdup(DEFAULT_PATH);
- e = strlen("interface") + strlen(iface) + 2;
- env[1] = xmalloc(e);
- snprintf(env[1], e, "interface=%s", iface);
- e = strlen("reason") + strlen(reason) + 2;
- env[2] = xmalloc(e);
- snprintf(env[2], e, "reason=%s", reason);
- e = 20;
- env[3] = xmalloc(e);
- snprintf(env[3], e, "pid=%d", getpid());
- env[4] = xmalloc(e);
- snprintf(env[4], e, "metric=%d", options->metric);
- if (dhcpo) {
- e = configure_env(NULL, NULL, dhcpo, options);
- if (e > 0) {
- env = xrealloc(env, sizeof(char *) * (elen + e + 1));
- elen += configure_env(env + elen, "old", dhcpo, options);
- }
- }
- if (dhcpn) {
- e = configure_env(NULL, NULL, dhcpn, options);
- if (e > 0) {
- env = xrealloc(env, sizeof(char *) * (elen + e + 1));
- elen += configure_env(env + elen, "new", dhcpn, options);
- }
- }
- /* Add our base environment */
- if (options->environ) {
- e = 0;
- while (options->environ[e++])
- ;
- env = xrealloc(env, sizeof(char *) * (elen + e + 1));
- e = 0;
- while (options->environ[e]) {
- env[elen + e] = xstrdup(options->environ[e]);
- e++;
- }
- elen += e;
- }
- env[elen] = '\0';
-
- pid = exec_script(argv, env);
- if (pid == -1)
- status = -1;
- else if (pid != 0) {
- /* Wait for the script to finish */
- while (waitpid(pid, &status, 0) == -1) {
- if (errno != EINTR) {
- logger(LOG_ERR, "waitpid: %s", strerror(errno));
- status = -1;
- break;
- }
- }
- }
-
- /* Cleanup */
- ep = env;
- while (*ep)
- free(*ep++);
- free(env);
- return status;
-}
-
-static struct rt *
-reverse_routes(struct rt *routes)
-{
- struct rt *rt;
- struct rt *rtn = NULL;
-
- while (routes) {
- rt = routes->next;
- routes->next = rtn;
- rtn = routes;
- routes = rt;
- }
- return rtn;
-}
-
-static int
-delete_route(const char *iface, struct rt *rt, int metric)
-{
- char *addr;
- int retval;
-
- addr = xstrdup(inet_ntoa(rt->dest));
- logger(LOG_DEBUG, "deleting route %s/%d via %s",
- addr, inet_ntocidr(rt->net), inet_ntoa(rt->gate));
- free(addr);
- retval = del_route(iface, &rt->dest, &rt->net, &rt->gate, metric);
- if (retval != 0 && errno != ENOENT && errno != ESRCH)
- logger(LOG_ERR," del_route: %s", strerror(errno));
- return retval;
-}
-
-static int
-delete_routes(struct interface *iface, int metric)
-{
- struct rt *rt;
- struct rt *rtn;
- int retval = 0;
-
- rt = reverse_routes(iface->routes);
- while (rt) {
- rtn = rt->next;
- retval += delete_route(iface->name, rt, metric);
- free(rt);
- rt = rtn;
- }
- iface->routes = NULL;
-
- return retval;
-}
-
-static int
-in_routes(const struct rt *routes, const struct rt *rt)
-{
- while (routes) {
- if (routes->dest.s_addr == rt->dest.s_addr &&
- routes->net.s_addr == rt->net.s_addr &&
- routes->gate.s_addr == rt->gate.s_addr)
- return 0;
- routes = routes->next;
- }
- return -1;
-}
-
-static int
-configure_routes(struct interface *iface, const struct dhcp_message *dhcp,
- const struct options *options)
-{
- struct rt *rt, *ort;
- struct rt *rtn = NULL, *nr = NULL;
- int remember;
- int retval = 0;
- char *addr;
-
- ort = get_option_routes(dhcp);
-
-#ifdef IPV4LL_ALWAYSROUTE
- if (options->options & DHCPCD_IPV4LL &&
- IN_PRIVATE(ntohl(dhcp->yiaddr)))
- {
- for (rt = ort; rt; rt = rt->next) {
- /* Check if we have already got a link locale route
- * dished out by the DHCP server */
- if (rt->dest.s_addr == htonl(LINKLOCAL_ADDR) &&
- rt->net.s_addr == htonl(LINKLOCAL_MASK))
- break;
- rtn = rt;
- }
-
- if (!rt) {
- rt = xmalloc(sizeof(*rt));
- rt->dest.s_addr = htonl(LINKLOCAL_ADDR);
- rt->net.s_addr = htonl(LINKLOCAL_MASK);
- rt->gate.s_addr = 0;
- rt->next = NULL;
- if (rtn)
- rtn->next = rt;
- else
- ort = rt;
- }
- }
-#endif
-
- /* Now remove old routes we no longer use.
- * We should do this in reverse order. */
- iface->routes = reverse_routes(iface->routes);
- for (rt = iface->routes; rt; rt = rt->next)
- if (in_routes(ort, rt) != 0)
- delete_route(iface->name, rt, options->metric);
-
- for (rt = ort; rt; rt = rt->next) {
- /* Don't set default routes if not asked to */
- if (rt->dest.s_addr == 0 &&
- rt->net.s_addr == 0 &&
- !(options->options & DHCPCD_GATEWAY))
- continue;
-
- addr = xstrdup(inet_ntoa(rt->dest));
- logger(LOG_DEBUG, "adding route to %s/%d via %s",
- addr, inet_ntocidr(rt->net), inet_ntoa(rt->gate));
- free(addr);
- remember = add_route(iface->name, &rt->dest,
- &rt->net, &rt->gate,
- options->metric);
- retval += remember;
-
- /* If we failed to add the route, we may have already added it
- ourselves. If so, remember it again. */
- if (remember < 0) {
- if (errno != EEXIST)
- logger(LOG_ERR, "add_route: %s",
- strerror(errno));
- if (in_routes(iface->routes, rt) == 0)
- remember = 1;
- }
-
- /* This login is split from above due to the #ifdef below */
- if (remember >= 0) {
- if (nr) {
- rtn->next = xmalloc(sizeof(*rtn));
- rtn = rtn->next;
- } else {
- nr = rtn = xmalloc(sizeof(*rtn));
- }
- rtn->dest.s_addr = rt->dest.s_addr;
- rtn->net.s_addr = rt->net.s_addr;
- rtn->gate.s_addr = rt->gate.s_addr;
- rtn->next = NULL;
- }
- }
- free_routes(ort);
- free_routes(iface->routes);
- iface->routes = nr;
- return retval;
-}
-
-static int
-delete_address(struct interface *iface)
-{
- int retval;
- logger(LOG_DEBUG, "deleting IP address %s/%d",
- inet_ntoa(iface->addr),
- inet_ntocidr(iface->net));
- retval = del_address(iface->name, &iface->addr, &iface->net);
- if (retval == -1 && errno != EADDRNOTAVAIL)
- logger(LOG_ERR, "del_address: %s", strerror(errno));
- iface->addr.s_addr = 0;
- iface->net.s_addr = 0;
- return retval;
-}
-
-int
-configure(struct interface *iface, const char *reason,
- const struct dhcp_message *dhcp, const struct dhcp_message *old,
- const struct dhcp_lease *lease, const struct options *options,
- int up)
-{
- struct in_addr addr;
- struct in_addr net;
- struct in_addr brd;
-#ifdef __linux__
- struct in_addr dest;
- struct in_addr gate;
-#endif
-
- /* Grab our IP config */
- if (dhcp == NULL)
- up = 0;
- else {
- addr.s_addr = dhcp->yiaddr;
- if (addr.s_addr == 0)
- addr.s_addr = lease->addr.s_addr;
- /* Ensure we have all the needed values */
- if (get_option_addr(&net.s_addr, dhcp, DHO_SUBNETMASK) == -1)
- net.s_addr = get_netmask(addr.s_addr);
- if (get_option_addr(&brd.s_addr, dhcp, DHO_BROADCAST) == -1)
- brd.s_addr = addr.s_addr | ~net.s_addr;
- }
-
- /* If we aren't up, then reset the interface as much as we can */
- if (!up) {
- /* Only reset things if we had set them before */
- if (iface->addr.s_addr != 0) {
- delete_routes(iface, options->metric);
- delete_address(iface);
- }
-
- run_script(options, iface->name, reason, NULL, old);
- return 0;
- }
-
- /* This also changes netmask */
- if (!(options->options & DHCPCD_INFORM) ||
- !has_address(iface->name, &addr, &net)) {
- logger(LOG_DEBUG, "adding IP address %s/%d",
- inet_ntoa(addr), inet_ntocidr(net));
- if (add_address(iface->name, &addr, &net, &brd) == -1 &&
- errno != EEXIST)
- {
- logger(LOG_ERR, "add_address: %s", strerror(errno));
- return -1;
- }
- }
-
- /* Now delete the old address if different */
- if (iface->addr.s_addr != addr.s_addr &&
- iface->addr.s_addr != 0)
- delete_address(iface);
-
-#ifdef __linux__
- /* On linux, we need to change the subnet route to have our metric. */
- if (iface->addr.s_addr != lease->addr.s_addr &&
- options->metric > 0 && net.s_addr != INADDR_BROADCAST)
- {
- dest.s_addr = addr.s_addr & net.s_addr;
- gate.s_addr = 0;
- add_route(iface->name, &dest, &net, &gate, options->metric);
- del_route(iface->name, &dest, &net, &gate, 0);
- }
-#endif
-
- configure_routes(iface, dhcp, options);
- up = (iface->addr.s_addr != addr.s_addr ||
- iface->net.s_addr != net.s_addr);
- iface->addr.s_addr = addr.s_addr;
- iface->net.s_addr = net.s_addr;
-
- if (!lease->frominfo)
- if (write_lease(iface, dhcp) == -1)
- logger(LOG_ERR, "write_lease: %s", strerror(errno));
-
- run_script(options, iface->name, reason, dhcp, old);
- return 0;
-}