summaryrefslogtreecommitdiffstats
path: root/configure.c
diff options
context:
space:
mode:
authorRoy Marples <roy@marples.name>2008-04-11 16:14:55 +0000
committerRoy Marples <roy@marples.name>2008-04-11 16:14:55 +0000
commit1a60d14fa2f91876b9ec14d6e6c88d97dacf6c4c (patch)
tree9e992f64d969ddef2e7d3836afa0d4065f69706a /configure.c
parent211da073490c5decd1deb46034385437a54ca977 (diff)
downloaddhcpcd-1a60d14fa2f91876b9ec14d6e6c88d97dacf6c4c.tar.xz
Normally I hate massive code drops, but heh.
The code has been drastically re-arranged. Instead of populating a custom structure while parsing dhcp messages, we now pluck what we need right out of the message itself. We have custom functions and a lookup table to make this really easy. This makes us more like dhclient and udhcpc, and will enable us to easily add (and remove!) more dhcp options without having to actually change the code (much). We now store the real dhcp message we got in /var/db/dhcpcd-$iface.lease, the mtime of the file being used as when we got the lease. This file is read in when re-using an old lease instead of parsing the .info file. The benefit of all of this means that we're actually ~15k smaller when compiled with the same features. This has been tested for quite some time, and I'm pretty sure most bugs with the 3.2 branch have been fixed whilst making this. Right now, we are 99% command line compatible with the 3.2 branch.
Diffstat (limited to 'configure.c')
-rw-r--r--configure.c1260
1 files changed, 669 insertions, 591 deletions
diff --git a/configure.c b/configure.c
index 47273744..542a123b 100644
--- a/configure.c
+++ b/configure.c
@@ -25,19 +25,12 @@
* SUCH DAMAGE.
*/
-#include <sys/types.h>
-#include <sys/ioctl.h>
-#include <sys/param.h>
-#include <sys/socket.h>
#include <sys/stat.h>
+#include <netinet/in.h>
#include <arpa/inet.h>
-#include <netinet/in.h>
-#ifdef __linux__
-# include <netinet/ether.h>
-#endif
-#include <string.h>
+#include <ctype.h>
#include <errno.h>
#include <netdb.h>
#include <resolv.h>
@@ -50,147 +43,13 @@
#include "common.h"
#include "configure.h"
#include "dhcp.h"
-#ifdef ENABLE_INFO
-# include "info.h"
-#endif
-#include "if.h"
#include "dhcpcd.h"
#include "logger.h"
+#include "net.h"
#include "signal.h"
#include "socket.h"
-static void
-log_route(const struct in_addr *destination,
- const struct in_addr *netmask,
- const struct in_addr *gateway, _unused int metric, int del)
-{
- char *dstd = xstrdup(inet_ntoa(*destination));
-
-#ifdef __linux__
-#define METRIC " metric %d"
-#else
-#define METRIC ""
-#endif
-
- if (gateway->s_addr == destination->s_addr ||
- gateway->s_addr == INADDR_ANY)
- logger(LOG_INFO, "%s route to %s/%d" METRIC,
- del ? "removing" : "adding",
- dstd, inet_ntocidr(*netmask)
-#ifdef __linux__
- , metric
-#endif
- );
- else if (destination->s_addr == INADDR_ANY)
- logger(LOG_INFO, "%s default route via %s" METRIC,
- del ? "removing" : "adding",
- inet_ntoa(*gateway)
-
-#ifdef __linux__
- , metric
-#endif
- );
- else
- logger(LOG_INFO, "%s route to %s/%d via %s" METRIC,
- del ? "removing" : "adding",
- dstd, inet_ntocidr(*netmask), inet_ntoa(*gateway)
-#ifdef __linux__
- , metric
-#endif
- );
-
- free(dstd);
-}
-
-static int
-a_address(const char *ifname, const struct in_addr *address,
- const struct in_addr *netmask, const struct in_addr *broadcast)
-{
- int retval;
-
- logger(LOG_INFO, "adding IP address %s/%d",
- inet_ntoa(*address), inet_ntocidr(*netmask));
- retval = add_address(ifname, address, netmask, broadcast);
- if (retval == -1)
- logger(LOG_ERR, "if_address: %s", strerror(errno));
- return retval;
-}
-
-static int
-d_address(const char *ifname,
- const struct in_addr *address, const struct in_addr *netmask)
-{
- int retval;
-
- logger(LOG_INFO, "removing IP address %s/%d",
- inet_ntoa(*address), inet_ntocidr(*netmask));
- retval = del_address(ifname, address, netmask);
- if (retval == -1)
- logger(LOG_ERR, "del_address: %s", strerror(errno));
- return retval;
-}
-
-
-static int
-a_route(const char *ifname, const struct in_addr *destination,
- const struct in_addr *netmask, const struct in_addr *gateway,
- int metric)
-{
- int retval;
-
- log_route(destination, netmask, gateway, metric, 0);
- retval = add_route(ifname, destination, netmask, gateway, metric);
- if (retval == -1)
- logger(LOG_ERR, "add_route: %s", strerror(errno));
- return retval;
-}
-
-static int
-d_route(const char *ifname, const struct in_addr *destination,
- const struct in_addr *netmask, const struct in_addr *gateway,
- int metric)
-{
- int retval;
-
- log_route(destination, netmask, gateway, metric, 1);
- retval = del_route(ifname, destination, netmask, gateway, metric);
- if (retval == -1)
- logger(LOG_ERR, "del_route: %s", strerror(errno));
- return retval;
-}
-
-#ifdef ENABLE_RESOLVCONF
-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);
-}
-#endif
-
-/* IMPORTANT: Ensure that the last parameter is NULL when calling */
-static int
+int
exec_cmd(const char *cmd, const char *args, ...)
{
va_list va;
@@ -254,6 +113,7 @@ exec_cmd(const char *cmd, const char *args, ...)
return ret;
}
+/* IMPORTANT: Ensure that the last parameter is NULL when calling */
static void
exec_script(const char *script, _unused const char *infofile, const char *arg)
{
@@ -274,138 +134,194 @@ exec_script(const char *script, _unused const char *infofile, const char *arg)
#endif
}
-static int
-make_resolv(const char *ifname, const struct dhcp *dhcp)
+static char *
+lookuphostname(in_addr_t addr)
{
- FILE *f = NULL;
- struct address *address;
+ union {
+ struct sockaddr sa;
+ struct sockaddr_in sin;
+ } su;
+ socklen_t salen;
+ char *name;
+ struct addrinfo hints;
+ struct addrinfo *res = NULL;
+ int r;
-#ifdef ENABLE_RESOLVCONF
- char *resolvconf = NULL;
- size_t len;
+ name = xmalloc(sizeof(char) * NI_MAXHOST);
+ salen = sizeof(su.sa);
+ memset(&su.sa, 0, salen);
+ su.sin.sin_family = AF_INET;
+ su.sin.sin_addr.s_addr = addr;
- if (file_in_path("resolvconf") == 0) {
- 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);
- }
+ r = getnameinfo(&su.sa, salen, name, NI_MAXHOST, NULL, 0, NI_NAMEREQD);
+ if (r != 0) {
+ free(name);
+ switch (r) {
+#ifdef EAI_NODATA
+ case EAI_NODATA: /* FALLTHROUGH */
#endif
- if (!f) {
- logger(LOG_DEBUG, "writing "RESOLVFILE);
- if (!(f = fopen(RESOLVFILE, "w")))
- logger(LOG_ERR, "fopen `%s': %s",
- RESOLVFILE, strerror(errno));
+ case EAI_NONAME:
+ errno = ENOENT;
+ break;
+ case EAI_SYSTEM:
+ break;
+ default:
+ errno = EIO;
+ break;
+ }
+ return NULL;
+ }
+
+ /* Check for a malicious PTR record */
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_socktype = SOCK_DGRAM;
+ hints.ai_flags = AI_NUMERICHOST;
+ r = getaddrinfo(name, "0", &hints, &res);
+ if (res)
+ freeaddrinfo(res);
+ if (r == 0 || !*name) {
+ free(name);
+ errno = ENOENT;
+ return NULL;
}
- if (!f)
- return -1;
+ return name;
+}
- 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);
- }
+static int
+configure_hostname(const struct dhcp_message *dhcp, in_addr_t addr, int h)
+{
+ char *newhostname;
+ char *curhostname;
- STAILQ_FOREACH(address, dhcp->dnsservers, entries)
- fprintf(f, "nameserver %s\n", inet_ntoa(address->address));
+ curhostname = xmalloc(sizeof(char) * MAXHOSTNAMELEN);
+ *curhostname = '\0';
-#ifdef ENABLE_RESOLVCONF
- if (resolvconf)
- pclose(f);
- else
-#endif
- fclose(f);
+ gethostname(curhostname, MAXHOSTNAMELEN);
+ if (h ||
+ strlen(curhostname) == 0 ||
+ strcmp(curhostname, "(none)") == 0 ||
+ strcmp(curhostname, "localhost") == 0)
+ {
+ newhostname = get_option_string(dhcp, DHCP_HOSTNAME);
+ if (!newhostname || h)
+ newhostname = lookuphostname(addr);
- /* Refresh the local resolver */
- res_init();
+ if (newhostname) {
+ logger(LOG_INFO, "setting hostname to `%s'", newhostname);
+ sethostname(newhostname, (int)strlen(newhostname));
+ free(newhostname);
+ }
+ }
+
+ free(curhostname);
return 0;
}
-#ifdef ENABLE_RESOLVCONF
-static void
-restore_resolv(const char *ifname)
+#ifdef ENABLE_NIS
+#define PREFIXSIZE 300
+static int
+configure_nis(const char *ifname, const struct dhcp_message *dhcp)
{
- if (file_in_path("resolvconf") == 0) {
- logger(LOG_DEBUG, "removing information from resolvconf");
- exec_cmd("resolvconf", "-d", ifname, (char *)NULL);
+ const uint8_t *servers;
+ char *domain;
+ FILE *f;
+ char *prefix;
+ const uint8_t *e;
+ uint8_t l;
+ struct in_addr addr;
+
+ servers = get_option(dhcp, DHCP_NISSERVER);
+ domain = get_option_string(dhcp, DHCP_NISDOMAIN);
+
+ if (!servers && !domain) {
+ if (errno == ENOENT)
+ return 0;
+ return -1;
}
-}
-#endif
-static bool
-in_routes(const struct route_head *routes, struct rt *route)
-{
- const struct rt *r;
+ if (!(f = fopen(NISFILE, "w")))
+ return -1;
- 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;
+ prefix = xmalloc(sizeof(char) * PREFIXSIZE);
+ *prefix = '\0';
+ fprintf(f, "# Generated by dhcpcd for interface %s\n", ifname);
+
+ if (domain) {
+ setdomainname(domain, (int)strlen(domain));
+ if (servers)
+ snprintf(prefix, PREFIXSIZE, "domain %s server",
+ domain);
+ else
+ fprintf(f, "domain %s broadcast\n", domain);
+ free(domain);
+ }
+ else
+ strlcpy(prefix, "ypserver", PREFIXSIZE);
+
+ if (servers) {
+ l = *servers++;
+ e = servers + l;
+ for(; servers < e; servers += sizeof(uint32_t)) {
+ memcpy(&addr.s_addr, servers, sizeof(uint32_t));
+ fprintf(f, "%s %s\n", prefix, inet_ntoa(addr));
+ }
+ }
+
+ free(prefix);
+ fclose(f);
- return false;
+ return exec_cmd(NISSERVICE, NISRESTARTARGS, (char *)NULL);
}
+#endif
#ifdef ENABLE_NTP
-static bool
-in_addresses(const struct address_head *addresses, struct in_addr address)
+static int
+in_addresses(const uint8_t *addresses, uint32_t addr)
{
- const struct address *addr;
+ uint8_t l = *addresses++;
+ const uint8_t *e = addresses + l;
+ uint32_t a;
- STAILQ_FOREACH (addr, addresses, entries)
- if (addr->address.s_addr == address.s_addr)
- return true;
-
- return false;
+ for (; addresses < e; addresses += sizeof(a)) {
+ memcpy(&a, addresses, sizeof(a));
+ if (a == addr)
+ return 0;
+ }
+ return -1;
}
static int
-_make_ntp(const char *file, const char *ifname, const struct dhcp *dhcp)
+_make_ntp(const char *file, const char *ifname, const uint8_t *ntp)
{
FILE *f;
- struct address *address;
char *a;
char *line = NULL;
size_t len = 0;
- int tomatch = 0;
char *token;
- bool ntp = false;
struct in_addr addr;
-
- STAILQ_FOREACH(address, dhcp->ntpservers, entries)
- tomatch++;
+ uint8_t tomatch = *ntp;
+ const uint8_t *e;
+#ifdef NTPFILE
+ int ntpfile;
+#endif
/* 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));
+ if (errno != ENOENT)
return -1;
- }
} else {
while (tomatch != 0 && (get_line(&line, &len, f))) {
a = line;
token = strsep(&a, " ");
- if (! token || strcmp(token, "server") != 0)
+ if (!token || strcmp(token, "server") != 0)
continue;
if ((token = strsep(&a, " \n")) == NULL)
continue;
if (inet_aton(token, &addr) == 1 &&
- in_addresses(dhcp->ntpservers, addr))
+ in_addresses(ntp, addr.s_addr) == 0)
tomatch--;
}
fclose(f);
@@ -413,389 +329,378 @@ _make_ntp(const char *file, const char *ifname, const struct dhcp *dhcp)
/* 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);
+ if (tomatch == 0)
return 0;
- }
}
- logger(LOG_DEBUG, "writing %s", file);
- if (!(f = fopen(file, "w"))) {
- logger(LOG_ERR, "fopen `%s': %s", file, strerror(errno));
+ if (!(f = fopen(file, "w")))
return -1;
- }
fprintf(f, "# Generated by dhcpcd for interface %s\n", ifname);
#ifdef NTPFILE
- if (strcmp(file, NTPFILE) == 0) {
- ntp = true;
+ if ((ntpfile = strcmp(file, NTPFILE)) == 0) {
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)
+ tomatch = *ntp++;
+ e = ntp + tomatch;
+ for (; ntp < e; ntp += sizeof(uint32_t)) {
+ memcpy(&addr.s_addr, ntp, sizeof(uint32_t));
+ a = inet_ntoa(addr);
+#ifdef NTPFILE
+ if (ntpfile == 0)
fprintf(f, "restrict %s nomodify notrap noquery\n", a);
+#endif
fprintf(f, "server %s\n", a);
}
fclose(f);
return 1;
}
+#endif
static int
-make_ntp(const char *ifname, const struct dhcp *dhcp)
+configure_ntp(const char *ifname, const struct dhcp_message *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. */
+ const uint8_t *ntp = get_option(dhcp, DHCP_NTPSERVER);
+ int restart = 0;
+ int r;
- bool restart_ntp = false;
- bool restart_openntp = false;
- int retval = 0;
+ if (!ntp) {
+ if (errno == ENOENT)
+ return 0;
+ return -1;
+ }
#ifdef NTPFILE
- if (_make_ntp(NTPFILE, ifname, dhcp) > 0)
- restart_ntp = true;
+ r = _make_ntp(NTPFILE, ifname, ntp);
+ if (r == -1)
+ return -1;
+ if (r > 0)
+ restart |= 1;
#endif
#ifdef OPENNTPFILE
- if (_make_ntp(OPENNTPFILE, ifname, dhcp) > 0)
- restart_openntp = true;
+ r = _make_ntp(OPENNTPFILE, ifname, ntp);
+ if (r == -1)
+ return -1;
+ if (r > 0)
+ restart |= 2;
#endif
-#ifdef NTPSERVICE
- if (restart_ntp) {
-#ifdef NTPCHECK
- if (system(NTPCHECK) == 0)
-#endif
- retval += exec_cmd(NTPSERVICE, NTPRESTARTARGS,
- (char *)NULL);
- }
-#endif
+ if (restart)
+ return exec_cmd(NTPSERVICE, NTPRESTARTARGS, (char *)NULL);
+ return 0;
+}
-#if defined (NTPSERVICE) && defined (OPENNTPSERVICE)
- if (restart_openntp &&
- (strcmp(NTPSERVICE, OPENNTPSERVICE) != 0 || !restart_ntp))
- {
-#ifdef OPENNTPCHECK
- if (system(OPENNTPCHECK) == 0)
-#endif
- retval += exec_cmd (OPENNTPSERVICE,
- OPENNTPRESTARTARGS, (char *)NULL);
- }
-#elif defined (OPENNTPSERVICE) && ! defined (NTPSERVICE)
- if (restart_openntp) {
-#ifdef OPENNTPCHECK
- if (system(OPENNTPCHECK) == 0)
-#endif
- retval += exec_cmd(OPENNTPSERVICE,
- OPENNTPRESTARTARGS, (char *) NULL);
+#ifdef ENABLE_RESOLVCONF
+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;
}
-#endif
- return retval;
+ 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);
}
#endif
-#ifdef ENABLE_NIS
-#define PREFIXSIZE 256
static int
-make_nis(const char *ifname, const struct dhcp *dhcp)
+configure_resolv(const char *ifname, const struct dhcp_message *dhcp)
{
- FILE *f;
- struct address *address;
- char *prefix;
+ FILE *f = NULL;
+ const uint8_t *servers;
+ const uint8_t *e;
+ uint8_t l;
+ struct in_addr addr;
+ char *p;
+
+#ifdef ENABLE_RESOLVCONF
+ char *resolvconf = NULL;
+ size_t len;
+#endif
- logger(LOG_DEBUG, "writing "NISFILE);
- if (!(f = fopen(NISFILE, "w"))) {
- logger(LOG_ERR, "fopen `%s': %s", NISFILE, strerror(errno));
+ servers = get_option(dhcp, DHCP_DNSSERVER);
+ if (!servers) {
+ if (errno == ENOENT)
+ return 0;
return -1;
}
- prefix = xmalloc(sizeof(char) * PREFIXSIZE);
- *prefix = '\0';
- fprintf(f, "# Generated by dhcpcd for interface %s\n", ifname);
+#ifdef ENABLE_RESOLVCONF
+ if (file_in_path("resolvconf") == 0) {
+ len = strlen("resolvconf -a ") + strlen(ifname) + 1;
+ resolvconf = xmalloc(sizeof(char) * len);
+ snprintf(resolvconf, len, "resolvconf -a %s", ifname);
+ f = popen(resolvconf , "w");
+ free(resolvconf);
+ }
+#endif
+ if (!f && !(f = fopen(RESOLVFILE, "w")))
+ return -1;
- if (dhcp->nisdomain) {
- setdomainname(dhcp->nisdomain, (int)strlen(dhcp->nisdomain));
+ fprintf(f, "# Generated by dhcpcd for interface %s\n", ifname);
+ p = get_option_string(dhcp, DHCP_DNSSEARCH);
+ if (!p)
+ p = get_option_string(dhcp, DHCP_DNSDOMAIN);
+ if (p) {
+ fprintf(f, "search %s\n", p);
+ free(p);
+ }
- if (dhcp->nisservers)
- snprintf(prefix, PREFIXSIZE, "domain %s server",
- dhcp->nisdomain);
- else
- fprintf(f, "domain %s broadcast\n", dhcp->nisdomain);
+ l = *servers++;
+ e = servers + l;
+ for (; servers < e; servers += sizeof(uint32_t)) {
+ memcpy(&addr.s_addr, servers, sizeof(uint32_t));
+ fprintf(f, "nameserver %s\n", inet_ntoa(addr));
}
+
+#ifdef ENABLE_RESOLVCONF
+ if (resolvconf)
+ pclose(f);
else
- snprintf(prefix, PREFIXSIZE, "%s", "ypserver");
+#endif
+ fclose(f);
- NSTAILQ_FOREACH(address, dhcp->nisservers, entries)
- fprintf(f, "%s %s\n", prefix, inet_ntoa(address->address));
+ /* Refresh the local resolver */
+ res_init();
+ return 0;
+}
- free(prefix);
- fclose(f);
+#ifdef ENABLE_RESOLVCONF
+static int
+restore_resolv(const char *ifname)
+{
+ if (file_in_path("resolvconf") != 0)
+ return 0;
-#ifdef NISCHECK
- if (system(NISCHECK) == 0)
-#endif
- exec_cmd(NISSERVICE, NISRESTARTARGS, (char *)NULL);
- return 0;
+ return exec_cmd("resolvconf", "-d", ifname, (char *)NULL);
}
#endif
-static char *
-lookuphostname(char *hostname, const struct dhcp *dhcp,
- const struct options *options)
+
+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)
{
- 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, *s, *sp, *t;
+ int retval;
- 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));
+ addr = xstrdup(inet_ntoa(rt->dest));
+ logger(LOG_DEBUG, "removing 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)
+ logger(LOG_ERR," del_route: %s", strerror(errno));
+ return retval;
- 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) {
- s = sp = xstrdup(dhcp->dnssearch);
- 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;
- }
+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;
- strlcpy(hostname, addr, MAXHOSTNAMELEN);
- free(addr);
- return hostname;
+ return retval;
}
-int
-configure(const struct options *options, struct interface *iface,
- const struct dhcp *dhcp, bool up)
+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 *route = NULL;
- struct route_head *new_routes = NULL;
- struct rt *new_route = NULL;
- char *newhostname = NULL;
- char *curhostname = NULL;
+ struct rt *rt, *ort;
+ struct rt *rtn = NULL, *nr = NULL;
int remember;
- unsigned short mtu;
-#if defined(ENABLE_IPV4LL) || defined(__linux__)
- struct in_addr dest;
- struct in_addr mask;
- struct in_addr gate;
-#endif
+ int retval = 0;
+ char *addr;
-#ifdef ENABLE_IPV4LL
- bool haslinklocal = false;
-#endif
#ifdef THERE_IS_NO_FORK
- int skip = 0;
- size_t skiplen;
char *skipp;
+ size_t skiplen;
+ int skip = 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
- if (dhcp->address.s_addr == 0)
- up = 0;
+ ort = get_option_routes(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->options & DHCPCD_GATEWAY) &&
- (!up || !in_routes(dhcp->routes, route)))
- d_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;
+#ifdef ENABLE_IPV4LL
+ 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;
}
- /* Restore the original MTU value */
- if (iface->mtu && iface->previous_mtu != iface->mtu) {
- set_mtu(iface->name, iface->mtu);
- iface->previous_mtu = iface->mtu;
+ 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;
}
-
-#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->options & DHCPCD_KEEPADDRESS)) {
- d_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));
+#ifdef THERE_IS_NO_FORK
+ if (dhcpcd_skiproutes) {
+ int i = -1;
+ char *sk, *skp, *token;
+ free_routes(iface->routes);
+ for (rt = ort; rt; rt = rt->next) {
+ i++;
+ /* Check that we did add this route or not */
+ sk = skp = xstrdup(dhcpcd_skiproutes);
+ while ((token = strsep(&skp, ","))) {
+ if (isdigit(*token) && atoi(token) == i)
+ break;
}
+ free(sk);
+ if (token)
+ continue;
+ 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;
}
+ iface->routes = nr;
+ nr = NULL;
-#ifdef ENABLE_RESOLVCONF
- restore_resolv(iface->name);
-#endif
- 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->options & DHCPCD_MTU) {
- 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->options & DHCPCD_INFORM) ||
- !has_address (iface->name, dhcp->address))
- if (a_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->options & DHCPCD_KEEPADDRESS))
- d_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)
- {
- dest.s_addr = dhcp->address.s_addr & dhcp->netmask.s_addr;
- gate.s_addr = 0;
- a_route(iface->name, &dest, &dhcp->netmask, &gate, options->metric);
- d_route(iface->name, &dest, &dhcp->netmask, &gate, 0);
+ /* We no longer need this */
+ free(dhcpcd_skiproutes);
+ dhcpcd_skiproutes = NULL;
}
#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';
-#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);
- /* 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
+ for (rt = ort; rt; rt = rt->next) {
/* Don't set default routes if not asked to */
- if (route->destination.s_addr == 0 &&
- route->netmask.s_addr == 0 &&
+ if (rt->dest.s_addr == 0 &&
+ rt->net.s_addr == 0 &&
!(options->options & DHCPCD_GATEWAY))
continue;
- remember = a_route(iface->name, &route->destination,
- &route->netmask, &route->gateway,
- options->metric);
+ 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 && in_routes(iface->previous_routes, route))
- remember = 1;
+ 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 (!new_routes) {
- new_routes = xmalloc(sizeof(*new_routes));
- STAILQ_INIT(new_routes);
+ if (nr) {
+ rtn->next = xmalloc(sizeof(*rtn));
+ rtn = rtn->next;
+ } else {
+ nr = rtn = xmalloc(sizeof(*rtn));
}
- new_route = xmalloc(sizeof(*new_route));
- memcpy(new_route, route, sizeof(*new_route));
- STAILQ_INSERT_TAIL(new_routes, new_route, entries);
+ 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;
}
#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->options & DAEMONISED)) {
+ else if (!(options->options & DHCPCD_DAEMONISED)) {
/* We can never have more than 255 / 4 routes,
* so 3 chars is plently */
if (*skipp)
@@ -807,6 +712,9 @@ configure(const struct options *options, struct interface *iface,
skip++;
#endif
}
+ free_routes(ort);
+ free_routes(iface->routes);
+ iface->routes = nr;
#ifdef THERE_IS_NO_FORK
if (*dhcpcd_skiproutes)
@@ -817,100 +725,270 @@ configure(const struct options *options, struct interface *iface,
}
#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->options & DHCPCD_IPV4LL &&
- !haslinklocal &&
- IN_PRIVATE(ntohl(dhcp->address.s_addr)))
- {
- dest.s_addr = htonl(LINKLOCAL_ADDR);
- mask.s_addr = htonl(LINKLOCAL_MASK);
- gate.s_addr = 0;
- remember = a_route(iface->name, &dest, &mask, &gate,
- options->metric);
- if (remember >= 0) {
- if (!new_routes) {
- new_routes = xmalloc(sizeof(*new_routes));
- STAILQ_INIT(new_routes);
+ return retval;
+}
+
+#ifdef ENABLE_INFO
+static void
+print_clean(FILE *f, const char *name, const char *value)
+{
+ char *clean;
+
+ if (! value)
+ return;
+
+ clean = clean_metas(value);
+ fprintf(f, "%s='%s'\n", name, clean);
+ free(clean);
+}
+
+int
+write_info(const struct interface *iface, const struct dhcp_message *dhcp,
+ const struct dhcp_lease *lease, const struct options *options,
+ int overwrite)
+{
+ FILE *f;
+ struct rt *rt, *ort;
+ struct stat sb;
+ struct in_addr addr;
+ int doneone;
+
+ if (options->options & DHCPCD_TEST)
+ f = stdout;
+ else {
+ if (!overwrite && stat(iface->infofile, &sb) == 0)
+ return 0;
+
+ if ((f = fopen(iface->infofile, "w")) == NULL)
+ return -1;
+ }
+
+ if (dhcp->yiaddr) {
+ fprintf(f, "IPADDR=%s\n", inet_ntoa(iface->addr));
+ fprintf(f, "NETMASK=%s\n", inet_ntoa(iface->net));
+ addr.s_addr = dhcp->yiaddr & iface->net.s_addr;
+ fprintf(f, "NETWORK=%s\n", inet_ntoa(addr));
+ if (get_option_addr(&addr.s_addr, dhcp, DHCP_BROADCAST) == -1)
+ addr.s_addr = dhcp->yiaddr | ~iface->net.s_addr;
+ fprintf(f, "BROADCAST=%s\n", inet_ntoa(addr));
+
+ ort = get_option_routes(dhcp);
+ doneone = 0;
+ fprintf(f, "ROUTES=");
+ for (rt = ort; rt; rt = rt->next) {
+ if (rt->dest.s_addr == 0)
+ continue;
+ if (doneone)
+ fputc(' ', f);
+ else {
+ fputc('\'', f);
+ doneone = 1;
+ }
+ fprintf(f, "%s", inet_ntoa(rt->dest));
+ fprintf(f, ",%s", inet_ntoa(rt->net));
+ fprintf(f, ",%s", inet_ntoa(rt->gate));
+ }
+ if (doneone)
+ fputc('\'', f);
+ fputc('\n', f);
+
+ doneone = 0;
+ fprintf(f, "GATEWAYS=");
+ for (rt = ort; rt; rt = rt->next) {
+ if (rt->dest.s_addr != 0)
+ continue;
+ if (doneone)
+ fputc(' ', f);
+ else {
+ fputc('\'', f);
+ doneone = 1;
}
- 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);
+ fprintf(f, "%s", inet_ntoa(rt->gate));
}
+ if (doneone)
+ fputc('\'', f);
+ fputc('\n', f);
+ free_routes(ort);
}
-#endif
- if (iface->previous_routes)
- free_route(iface->previous_routes);
- iface->previous_routes = new_routes;
+ write_options(f, dhcp);
- if (options->options & DHCPCD_DNS && dhcp->dnsservers)
- make_resolv(iface->name, dhcp);
- else
- logger(LOG_DEBUG, "no dns information to write");
+/* FIXME
+ if (dhcp->fqdn) {
+ fprintf(f, "FQDNFLAGS='%u'\n", dhcp->fqdn->flags);
+ fprintf(f, "FQDNRCODE1='%u'\n", dhcp->fqdn->r1);
+ fprintf(f, "FQDNRCODE2='%u'\n", dhcp->fqdn->r2);
+ print_clean(f, "FQDNHOSTNAME", dhcp->fqdn->name);
+ }
+*/
+ if (dhcp->siaddr) {
+ addr.s_addr = dhcp->siaddr;
+ fprintf(f, "DHCPSID='%s'\n", inet_ntoa(addr));
+ }
+ if (dhcp->servername[0])
+ print_clean(f, "DHCPSNAME", (const char *)dhcp->servername);
+
+ if (!(options->options & DHCPCD_INFORM) && dhcp->yiaddr) {
+ if (!(options->options & DHCPCD_TEST))
+ fprintf(f, "LEASEDFROM=%u\n", lease->leasedfrom);
+ fprintf(f, "LEASETIME=%u\n", lease->leasetime);
+ fprintf(f, "RENEWALTIME=%u\n", lease->renewaltime);
+ fprintf(f, "REBINDTIME=%u\n", lease->rebindtime);
+ }
+ print_clean(f, "INTERFACE", iface->name);
+ print_clean(f, "CLASSID", options->classid);
+ if (iface->clientid_len > 0) {
+ fprintf(f, "CLIENTID=%s\n",
+ hwaddr_ntoa(iface->clientid, iface->clientid_len));
+ }
+ fprintf(f, "DHCPCHADDR=%s\n",
+ hwaddr_ntoa(iface->hwaddr, iface->hwlen));
-#ifdef ENABLE_NTP
- if (options->options & DHCPCD_NTP && dhcp->ntpservers)
- make_ntp(iface->name, dhcp);
+ if (!(options->options & DHCPCD_TEST))
+ fclose(f);
+ return 0;
+}
#endif
-#ifdef ENABLE_NIS
- if (options->options & DHCPCD_NIS &&
- (dhcp->nisservers || dhcp->nisdomain))
- make_nis(iface->name, dhcp);
+int
+configure(struct interface *iface, const struct dhcp_message *dhcp,
+ const struct dhcp_lease *lease, const struct options *options,
+ int up)
+{
+ unsigned short mtu;
+ struct in_addr addr;
+ struct in_addr net;
+ struct in_addr brd;
+#ifdef __linux__
+ struct in_addr dest;
+ struct in_addr gate;
#endif
- curhostname = xmalloc(sizeof(char) * MAXHOSTNAMELEN);
- *curhostname = '\0';
+ /* Grab our IP config */
+ if (dhcp == NULL || dhcp->yiaddr == 0)
+ up = 0;
+ else {
+ addr.s_addr = dhcp->yiaddr;
+ /* Ensure we have all the needed values */
+ if (get_option_addr(&net.s_addr, dhcp, DHCP_NETMASK) == -1)
+ net.s_addr = get_netmask(addr.s_addr);
+ if (get_option_addr(&brd.s_addr, dhcp, DHCP_BROADCAST) == -1)
+ brd.s_addr = addr.s_addr | ~net.s_addr;
+ }
- gethostname(curhostname, MAXHOSTNAMELEN);
- if (options->dohostname ||
- strlen(curhostname) == 0 ||
- strcmp(curhostname, "(none)") == 0 ||
- strcmp(curhostname, "localhost") == 0)
- {
- newhostname = xmalloc(sizeof(char) * MAXHOSTNAMELEN);
+ /* If we aren't up, then reset the interface as much as we can */
+ if (!up) {
+ /* Restore the original MTU value */
+ if (iface->initial_mtu != iface->mtu) {
+ set_mtu(iface->name, iface->initial_mtu);
+ iface->mtu = iface->initial_mtu;
+ }
- if (dhcp->hostname)
- strlcpy(newhostname, dhcp->hostname, MAXHOSTNAMELEN);
- else
- *newhostname = '\0';
+#ifdef ENABLE_INFO
+ /* If we haven't created an info file, do so now */
+ if (!lease->frominfo) {
+ if (write_info(iface, dhcp, lease, options, 0) == -1)
+ logger(LOG_ERR, "write_info: %s",
+ strerror(errno));
+ }
+#endif
+
+ /* Only reset things if we had set them before */
+ if (iface->addr.s_addr != 0) {
+ if (!(options->options & DHCPCD_KEEPADDRESS)) {
+ delete_routes(iface, options->metric);
+ logger(LOG_DEBUG, "deleting IP address %s/%d",
+ inet_ntoa(iface->addr),
+ inet_ntocidr(iface->net));
+ if (del_address(iface->name, &iface->addr,
+ &iface->net) == -1 &&
+ errno != ENOENT)
+ logger(LOG_ERR, "del_address: %s",
+ strerror(errno));
+ iface->addr.s_addr = 0;
+ iface->net.s_addr = 0;
+ }
+#ifdef ENABLE_RESOLVCONF
+ if (options->options & DHCPCD_DNS)
+ restore_resolv(iface->name);
+#endif
+ }
- /* 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);
+ exec_script(options->script, iface->infofile, "down");
- if (*newhostname) {
- logger(LOG_INFO, "setting hostname to `%s'",
- newhostname);
- sethostname(newhostname, (int)strlen(newhostname));
+ return 0;
+ }
+
+ if (options->options & DHCPCD_MTU)
+ if (get_option_uint16(&mtu, dhcp, DHCP_MTU) == 0)
+ if (mtu != iface->mtu && mtu >= MTU_MIN) {
+ if (set_mtu(iface->name, mtu) == 0)
+ iface->mtu = mtu;
+ else
+ logger(LOG_ERR, "set_mtu: %s",
+ strerror(errno));
+ }
+
+ /* 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 &&
+ !(options->options & DHCPCD_KEEPADDRESS))
+ del_address(iface->name, &iface->addr, &iface->net);
- free(newhostname);
+#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
- free(curhostname);
+ configure_routes(iface, dhcp, options);
+ if (options->options & DHCPCD_DNS)
+ configure_resolv(iface->name, dhcp);
+#ifdef ENABLE_NTP
+ if (options->options & DHCPCD_NTP)
+ configure_ntp(iface->name, dhcp);
+#endif
+#ifdef ENABLE_NIS
+ if (options->options & DHCPCD_NIS)
+ configure_nis(iface->name, dhcp);
+#endif
+ configure_hostname(dhcp, addr.s_addr,
+ options->options & DHCPCD_HOSTNAME);
+
+ 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;
#ifdef ENABLE_INFO
- if (!dhcp->frominfo)
- write_info(iface, dhcp, options, true);
+ //if (!lease->frominfo)
+ write_info(iface, dhcp, lease, options, 1);
+ if (write_lease(iface, dhcp) == -1)
+ logger(LOG_ERR, "write_lease: %s", strerror(errno));
#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");
+
+ exec_script(options->script, iface->infofile, up ? "new" : "up");
return 0;
}