]> git.ipfire.org Git - thirdparty/dhcpcd.git/commitdiff
Move if_state into interface->if_data as dhcp_state.
authorRoy Marples <roy@marples.name>
Sun, 3 Feb 2013 22:55:45 +0000 (22:55 +0000)
committerRoy Marples <roy@marples.name>
Sun, 3 Feb 2013 22:55:45 +0000 (22:55 +0000)
This should reduce memory usage for non IPv4 interfaces.

13 files changed:
arp.c
dhcp.c
dhcp.h
dhcpcd.c
dhcpcd.h
if-linux.c
if-pref.c
ipv4.c
ipv4ll.c
lpf.c
net.c
script.c
script.h

diff --git a/arp.c b/arp.c
index 190a5183e493b22280fc140d676b682a8d92d310..9bf1a59786fb7593735a88f25053376e4fb454bc 100644 (file)
--- a/arp.c
+++ b/arp.c
@@ -79,24 +79,25 @@ arp_send(const struct interface *ifp, int op, in_addr_t sip, in_addr_t tip)
 static void
 arp_failure(struct interface *ifp)
 {
+       const struct dhcp_state *state = D_CSTATE(ifp);
 
        /* If we failed without a magic cookie then we need to try
         * and defend our IPv4LL address. */
-       if ((ifp->state->offer != NULL &&
-               ifp->state->offer->cookie != htonl(MAGIC_COOKIE)) ||
-           (ifp->state->new != NULL &&
-               ifp->state->new->cookie != htonl(MAGIC_COOKIE)))
+       if ((state->offer != NULL &&
+               state->offer->cookie != htonl(MAGIC_COOKIE)) ||
+           (state->new != NULL &&
+               state->new->cookie != htonl(MAGIC_COOKIE)))
        {
                ipv4ll_handle_failure(ifp);
                return;
        }
 
-       unlink(ifp->state->leasefile);
-       if (!ifp->state->lease.frominfo)
+       unlink(state->leasefile);
+       if (!state->lease.frominfo)
                dhcp_decline(ifp);
        dhcp_close(ifp);
        eloop_timeout_delete(NULL, ifp);
-       if (ifp->state->lease.frominfo)
+       if (state->lease.frominfo)
                start_interface(ifp);
        else
                eloop_timeout_add_sec(DHCP_ARP_FAIL, start_interface, ifp);
@@ -112,11 +113,12 @@ arp_packet(void *arg)
        uint32_t reply_t;
        uint8_t *hw_s, *hw_t;
        ssize_t bytes;
-       struct if_state *state = ifp->state;
+       struct dhcp_state *state;
        struct if_options *opts = ifp->options;
        const char *hwaddr;
        struct in_addr ina;
 
+       state = D_STATE(ifp);
        state->fail.s_addr = 0;
        for(;;) {
                bytes = get_raw_packet(ifp, ETHERTYPE_ARP,
@@ -202,7 +204,7 @@ void
 arp_announce(void *arg)
 {
        struct interface *ifp = arg;
-       struct if_state *state = ifp->state;
+       struct dhcp_state *state = D_STATE(ifp);
        struct timeval tv;
 
        if (state->new == NULL)
@@ -249,7 +251,7 @@ void
 arp_probe(void *arg)
 {
        struct interface *ifp = arg;
-       struct if_state *state = ifp->state;
+       struct dhcp_state *state = D_STATE(ifp);
        struct in_addr addr;
        struct timeval tv;
        int arping = 0;
@@ -305,8 +307,9 @@ arp_probe(void *arg)
 void
 arp_start(struct interface *ifp)
 {
+       struct dhcp_state *state = D_STATE(ifp);
 
-       ifp->state->probes = 0;
-       ifp->state->arping_index = 0;
+       state->probes = 0;
+       state->arping_index = 0;
        arp_probe(ifp);
 }
diff --git a/dhcp.c b/dhcp.c
index 3e87c57b6b6507c4102d230426b48f92b23aa509..f217073d9069f72fb7593e3d7ff89908288bbb74 100644 (file)
--- a/dhcp.c
+++ b/dhcp.c
@@ -46,7 +46,9 @@
 #include "config.h"
 #include "common.h"
 #include "dhcp.h"
+#include "dhcpcd.h"
 #include "dhcp-common.h"
+#include "duid.h"
 #include "eloop.h"
 #include "ipv4.h"
 #include "ipv4ll.h"
@@ -261,6 +263,7 @@ static void
 free_option_buffer(void)
 {
 
+       free(packet);
        free(opt_buffer);
 }
 #endif
@@ -825,9 +828,9 @@ make_message(struct dhcp_message **message,
        const char *hp;
        const struct dhcp_opt *opt;
        const struct if_options *ifo = iface->options;
-       const struct if_state *ifs = iface->state;
-       const struct dhcp_lease *lease = &ifs->lease;
-       time_t up = uptime() - ifs->start_uptime;
+       const struct dhcp_state *state = D_CSTATE(iface);
+       const struct dhcp_lease *lease = &state->lease;
+       time_t up = uptime() - state->start_uptime;
 
        dhcp = xzalloc(sizeof (*dhcp));
        m = (uint8_t *)dhcp;
@@ -835,13 +838,13 @@ make_message(struct dhcp_message **message,
 
        if ((type == DHCP_INFORM || type == DHCP_RELEASE ||
                (type == DHCP_REQUEST &&
-                   ifs->net.s_addr == lease->net.s_addr &&
-                   (ifs->new == NULL ||
-                       ifs->new->cookie == htonl(MAGIC_COOKIE)))))
+                   state->net.s_addr == lease->net.s_addr &&
+                   (state->new == NULL ||
+                       state->new->cookie == htonl(MAGIC_COOKIE)))))
        {
-               dhcp->ciaddr = ifs->addr.s_addr;
+               dhcp->ciaddr = state->addr.s_addr;
                /* In-case we haven't actually configured the address yet */
-               if (type == DHCP_INFORM && ifs->addr.s_addr == 0)
+               if (type == DHCP_INFORM && state->addr.s_addr == 0)
                        dhcp->ciaddr = lease->addr.s_addr;
        }
 
@@ -867,23 +870,23 @@ make_message(struct dhcp_message **message,
                else
                        dhcp->secs = htons(up);
        }
-       dhcp->xid = htonl(ifs->xid);
+       dhcp->xid = htonl(state->xid);
        dhcp->cookie = htonl(MAGIC_COOKIE);
 
        *p++ = DHO_MESSAGETYPE; 
        *p++ = 1;
        *p++ = type;
 
-       if (ifs->clientid) {
+       if (state->clientid) {
                *p++ = DHO_CLIENTID;
-               memcpy(p, ifs->clientid, ifs->clientid[0] + 1);
-               p += ifs->clientid[0] + 1;
+               memcpy(p, state->clientid, state->clientid[0] + 1);
+               p += state->clientid[0] + 1;
        }
 
        if (lease->addr.s_addr && lease->cookie == htonl(MAGIC_COOKIE)) {
                if (type == DHCP_DECLINE ||
                    (type == DHCP_REQUEST &&
-                       lease->addr.s_addr != ifs->addr.s_addr))
+                       lease->addr.s_addr != state->addr.s_addr))
                {
                        PUTADDR(DHO_IPADDRESS, lease->addr);
                        if (lease->server.s_addr)
@@ -1026,7 +1029,7 @@ make_message(struct dhcp_message **message,
 }
 
 ssize_t
-write_lease(const struct interface *iface, const struct dhcp_message *dhcp)
+write_lease(const struct interface *ifp, const struct dhcp_message *dhcp)
 {
        int fd;
        ssize_t bytes = sizeof(*dhcp);
@@ -1034,17 +1037,18 @@ write_lease(const struct interface *iface, const struct dhcp_message *dhcp)
        const uint8_t *e = p + sizeof(dhcp->options);
        uint8_t l;
        uint8_t o = 0;
+       const struct dhcp_state *state = D_CSTATE(ifp);
 
        /* We don't write BOOTP leases */
        if (is_bootp(dhcp)) {
-               unlink(iface->state->leasefile);
+               unlink(state->leasefile);
                return 0;
        }
 
        syslog(LOG_DEBUG, "%s: writing lease `%s'",
-           iface->name, iface->state->leasefile);
+           ifp->name, state->leasefile);
 
-       fd = open(iface->state->leasefile, O_WRONLY | O_CREAT | O_TRUNC, 0444);
+       fd = open(state->leasefile, O_WRONLY | O_CREAT | O_TRUNC, 0444);
        if (fd == -1)
                return -1;
 
@@ -1067,21 +1071,22 @@ write_lease(const struct interface *iface, const struct dhcp_message *dhcp)
 }
 
 struct dhcp_message *
-read_lease(const struct interface *iface)
+read_lease(const struct interface *ifp)
 {
        int fd;
        struct dhcp_message *dhcp;
+       const struct dhcp_state *state = D_CSTATE(ifp);
        ssize_t bytes;
 
-       fd = open(iface->state->leasefile, O_RDONLY);
+       fd = open(state->leasefile, O_RDONLY);
        if (fd == -1) {
                if (errno != ENOENT)
                        syslog(LOG_ERR, "%s: open `%s': %m",
-                           iface->name, iface->state->leasefile);
+                           ifp->name, state->leasefile);
                return NULL;
        }
        syslog(LOG_DEBUG, "%s: reading lease `%s'",
-           iface->name, iface->state->leasefile);
+           ifp->name, state->leasefile);
        dhcp = xmalloc(sizeof(*dhcp));
        memset(dhcp, 0, sizeof(*dhcp));
        bytes = read(fd, dhcp, sizeof(*dhcp));
@@ -1253,30 +1258,35 @@ dhcp_xid(const struct interface *ifp)
 void
 dhcp_close(struct interface *ifp)
 {
-       struct if_state *ifs = ifp->state;
+       struct dhcp_state *state = D_STATE(ifp);
+
+       if (state == NULL)
+               return;
 
-       if (ifs->arp_fd != -1) {
-               eloop_event_delete(ifs->arp_fd);
-               close(ifs->arp_fd);
-               ifs->arp_fd = -1;
+       if (state->arp_fd != -1) {
+               eloop_event_delete(state->arp_fd);
+               close(state->arp_fd);
+               state->arp_fd = -1;
        }
-       if (ifs->raw_fd != -1) {
-               eloop_event_delete(ifs->raw_fd);
-               close(ifs->raw_fd);
-               ifs->raw_fd = -1;
+       if (state->raw_fd != -1) {
+               eloop_event_delete(state->raw_fd);
+               close(state->raw_fd);
+               state->raw_fd = -1;
        }
-       if (ifs->udp_fd != -1) {
+       if (state->udp_fd != -1) {
                /* we don't listen to events on the udp */
-               close(ifs->udp_fd);
-               ifs->udp_fd = -1;
+               close(state->udp_fd);
+               state->udp_fd = -1;
        }
+
+       state->interval = 0;
 }
 
 static void
 send_message(struct interface *iface, int type,
     void (*callback)(void *))
 {
-       struct if_state *state = iface->state;
+       struct dhcp_state *state = D_STATE(iface);
        struct if_options *ifo = iface->options;
        struct dhcp_message *dhcp;
        uint8_t *udp;
@@ -1401,29 +1411,28 @@ void
 dhcp_discover(void *arg)
 {
        struct interface *iface = arg;
+       struct dhcp_state *state = D_STATE(iface);
        struct if_options *ifo = iface->options;
        int timeout = ifo->timeout;
 
        /* If we're rebooting and we're not daemonised then we need
         * to shorten the normal timeout to ensure we try correctly
         * for a fallback or IPv4LL address. */
-       if (iface->state->state == DHS_REBOOT &&
-           !(options & DHCPCD_DAEMONISED))
-       {
+       if (state->state == DHS_REBOOT && !(options & DHCPCD_DAEMONISED)) {
                timeout -= ifo->reboot;
                if (timeout <= 0)
                        timeout = 2;
        }
 
-       iface->state->state = DHS_DISCOVER;
-       iface->state->xid = dhcp_xid(iface);
+       state->state = DHS_DISCOVER;
+       state->xid = dhcp_xid(iface);
        eloop_timeout_delete(NULL, iface);
        if (ifo->fallback)
                eloop_timeout_add_sec(timeout, dhcp_fallback, iface);
        else if (ifo->options & DHCPCD_IPV4LL &&
-           !IN_LINKLOCAL(htonl(iface->state->addr.s_addr)))
+           !IN_LINKLOCAL(htonl(state->addr.s_addr)))
        {
-               if (IN_LINKLOCAL(htonl(iface->state->fail.s_addr)))
+               if (IN_LINKLOCAL(htonl(state->fail.s_addr)))
                        eloop_timeout_add_sec(RATE_LIMIT_INTERVAL,
                            ipv4ll_start, iface);
                else
@@ -1440,52 +1449,53 @@ dhcp_discover(void *arg)
 static void
 dhcp_request(void *arg)
 {
-       struct interface *iface = arg;
+       struct interface *ifp = arg;
+       struct dhcp_state *state = D_STATE(ifp);
 
-       iface->state->state = DHS_REQUEST;
-       send_request(iface);
+       state->state = DHS_REQUEST;
+       send_request(ifp);
 }
 
 static void
 dhcp_expire(void *arg)
 {
-       struct interface *iface = arg;
+       struct interface *ifp = arg;
+       struct dhcp_state *state = D_STATE(ifp);
 
-       iface->state->interval = 0;
-       if (iface->state->addr.s_addr == 0) {
+       state->interval = 0;
+       if (state->addr.s_addr == 0) {
                /* We failed to reboot, so enter discovery. */
-               iface->state->lease.addr.s_addr = 0;
-               dhcp_discover(iface);
+               state->lease.addr.s_addr = 0;
+               dhcp_discover(ifp);
                return;
        }
 
-       syslog(LOG_ERR, "%s: lease expired", iface->name);
-       eloop_timeout_delete(NULL, iface);
-       dhcp_drop(iface, "EXPIRE");
-       unlink(iface->state->leasefile);
-       if (iface->carrier != LINK_DOWN)
-               start_interface(iface);
+       syslog(LOG_ERR, "%s: lease expired", ifp->name);
+       eloop_timeout_delete(NULL, ifp);
+       dhcp_drop(ifp, "EXPIRE");
+       unlink(state->leasefile);
+       if (ifp->carrier != LINK_DOWN)
+               start_interface(ifp);
 }
 
 void
-dhcp_release(struct interface *iface)
+dhcp_release(struct interface *ifp)
 {
+       struct dhcp_state *state = D_STATE(ifp);
        struct timespec ts;
 
-       if (iface->state->new != NULL &&
-           iface->state->new->cookie == htonl(MAGIC_COOKIE))
-       {
+       if (state->new != NULL && state->new->cookie == htonl(MAGIC_COOKIE)) {
                syslog(LOG_INFO, "%s: releasing lease of %s",
-                   iface->name, inet_ntoa(iface->state->lease.addr));
-               iface->state->xid = dhcp_xid(iface);
-               send_message(iface, DHCP_RELEASE, NULL);
+                   ifp->name, inet_ntoa(state->lease.addr));
+               state->xid = dhcp_xid(ifp);
+               send_message(ifp, DHCP_RELEASE, NULL);
                /* Give the packet a chance to go before dropping the ip */
                ts.tv_sec = RELEASE_DELAY_S;
                ts.tv_nsec = RELEASE_DELAY_NS;
                nanosleep(&ts, NULL);
-               dhcp_drop(iface, "RELEASE");
+               dhcp_drop(ifp, "RELEASE");
        }
-       unlink(iface->state->leasefile);
+       unlink(state->leasefile);
 }
 
 void
@@ -1498,40 +1508,42 @@ dhcp_decline(struct interface *ifp)
 static void
 dhcp_renew(void *arg)
 {
-       struct interface *iface = arg;
-       struct dhcp_lease *lease = &iface->state->lease;
+       struct interface *ifp = arg;
+       struct dhcp_state *state = D_STATE(ifp);
+       struct dhcp_lease *lease = &state->lease;
 
        syslog(LOG_INFO, "%s: renewing lease of %s",
-           iface->name, inet_ntoa(lease->addr));
+           ifp->name, inet_ntoa(lease->addr));
        syslog(LOG_DEBUG, "%s: rebind in %u seconds, expire in %u seconds",
-           iface->name, lease->rebindtime - lease->renewaltime,
+           ifp->name, lease->rebindtime - lease->renewaltime,
            lease->leasetime - lease->renewaltime);
-       iface->state->state = DHS_RENEW;
-       iface->state->xid = dhcp_xid(iface);
-       send_renew(iface);
+       state->state = DHS_RENEW;
+       state->xid = dhcp_xid(ifp);
+       send_renew(ifp);
 }
 
 static void
 dhcp_rebind(void *arg)
 {
-       struct interface *iface = arg;
-       struct dhcp_lease *lease = &iface->state->lease;
+       struct interface *ifp = arg;
+       struct dhcp_state *state = D_STATE(ifp);
+       struct dhcp_lease *lease = &state->lease;
 
        syslog(LOG_ERR, "%s: failed to renew, attempting to rebind",
-           iface->name);
+           ifp->name);
        syslog(LOG_DEBUG, "%s: expire in %u seconds",
-           iface->name, lease->leasetime - lease->rebindtime);
-       iface->state->state = DHS_REBIND;
-       eloop_timeout_delete(send_renew, iface);
-       iface->state->lease.server.s_addr = 0;
-       send_rebind(iface);
+           ifp->name, lease->leasetime - lease->rebindtime);
+       state->state = DHS_REBIND;
+       eloop_timeout_delete(send_renew, ifp);
+       state->lease.server.s_addr = 0;
+       send_rebind(ifp);
 }
 
 void
 dhcp_bind(void *arg)
 {
        struct interface *iface = arg;
-       struct if_state *state = iface->state;
+       struct dhcp_state *state = D_STATE(iface);
        struct if_options *ifo = iface->options;
        struct dhcp_lease *lease = &state->lease;
        struct timeval tv;
@@ -1610,7 +1622,7 @@ dhcp_bind(void *arg)
        }
        if (options & DHCPCD_TEST) {
                state->reason = "TEST";
-               script_run(iface);
+               script_runreason(iface, state->reason);
                exit(EXIT_SUCCESS);
        }
        if (state->reason == NULL) {
@@ -1649,11 +1661,12 @@ dhcp_bind(void *arg)
 static void
 dhcp_timeout(void *arg)
 {
-       struct interface *iface = arg;
+       struct interface *ifp = arg;
+       struct dhcp_state *state = D_STATE(ifp);
 
-       dhcp_bind(iface);
-       iface->state->interval = 0;
-       dhcp_discover(iface);
+       dhcp_bind(ifp);
+       state->interval = 0;
+       dhcp_discover(ifp);
 }
 
 struct dhcp_message *
@@ -1676,125 +1689,146 @@ dhcp_message_new(struct in_addr *addr, struct in_addr *mask)
 }
 
 static int
-handle_3rdparty(struct interface *iface)
+handle_3rdparty(struct interface *ifp)
 {
        struct if_options *ifo;
+       struct dhcp_state *state;
        struct in_addr addr, net, dst;
        
-       ifo = iface->options;
+       ifo = ifp->options;
        if (ifo->req_addr.s_addr != INADDR_ANY)
                return 0;
 
-       if (get_address(iface->name, &addr, &net, &dst) == 1)
-               ipv4_handleifa(RTM_NEWADDR, iface->name, &addr, &net, &dst);
+       if (get_address(ifp->name, &addr, &net, &dst) == 1)
+               ipv4_handleifa(RTM_NEWADDR, ifp->name, &addr, &net, &dst);
        else {
                syslog(LOG_INFO,
                    "%s: waiting for 3rd party to configure IP address",
-                   iface->name);
-               iface->state->reason = "3RDPARTY";
-               script_run(iface);
+                   ifp->name);
+               state = D_STATE(ifp);
+               state->reason = "3RDPARTY";
+               script_runreason(ifp, state->reason);
        }
        return 1;
 }
 
 static void
-dhcp_static(struct interface *iface)
+dhcp_static(struct interface *ifp)
 {
        struct if_options *ifo;
+       struct dhcp_state *state;
 
-       if (handle_3rdparty(iface))
+       if (handle_3rdparty(ifp))
                return;
-       ifo = iface->options;
-       iface->state->offer =
-           dhcp_message_new(&ifo->req_addr, &ifo->req_mask);
-       eloop_timeout_delete(NULL, iface);
-       dhcp_bind(iface);
+       ifo = ifp->options;
+       state = D_STATE(ifp);
+       state->offer = dhcp_message_new(&ifo->req_addr, &ifo->req_mask);
+       eloop_timeout_delete(NULL, ifp);
+       dhcp_bind(ifp);
 }
 
 void
-dhcp_inform(struct interface *iface)
+dhcp_inform(struct interface *ifp)
 {
+       struct dhcp_state *state;
 
-       if (handle_3rdparty(iface))
+       if (handle_3rdparty(ifp))
                return;
 
+       state = D_STATE(ifp);
        if (options & DHCPCD_TEST) {
-               iface->state->addr.s_addr = iface->options->req_addr.s_addr;
-               iface->state->net.s_addr = iface->options->req_mask.s_addr;
+               state->addr.s_addr = ifp->options->req_addr.s_addr;
+               state->net.s_addr = ifp->options->req_mask.s_addr;
        } else {
-               iface->options->options |= DHCPCD_STATIC;
-               dhcp_static(iface);
+               ifp->options->options |= DHCPCD_STATIC;
+               dhcp_static(ifp);
        }
 
-       iface->state->state = DHS_INFORM;
-       iface->state->xid = dhcp_xid(iface);
-       send_inform(iface);
+       state->state = DHS_INFORM;
+       state->xid = dhcp_xid(ifp);
+       send_inform(ifp);
 }
 
-static void
-dhcp_reboot(struct interface *iface)
+void
+dhcp_reboot(struct interface *ifp, int oldopts)
 {
-       struct if_options *ifo = iface->options;
+       struct if_options *ifo = ifp->options;
+       struct dhcp_state *state = D_STATE(ifp);
+
+       ifo = ifp->options;
+       state->interval = 0;
+       if ((ifo->options & (DHCPCD_INFORM | DHCPCD_STATIC) &&
+               state->addr.s_addr != ifo->req_addr.s_addr) ||
+           (oldopts & (DHCPCD_INFORM | DHCPCD_STATIC) &&
+               !(ifo->options & (DHCPCD_INFORM | DHCPCD_STATIC))))
+       {
+               dhcp_drop(ifp, "EXPIRE");
+       } else {
+               free(state->offer);
+               state->offer = NULL;
+       }
 
-       if (ifo->options & DHCPCD_LINK && iface->carrier == LINK_DOWN) {
-               syslog(LOG_INFO, "%s: waiting for carrier", iface->name);
+       if (ifo->options & DHCPCD_LINK && ifp->carrier == LINK_DOWN) {
+               syslog(LOG_INFO, "%s: waiting for carrier", ifp->name);
                return;
        }
        if (ifo->options & DHCPCD_STATIC) {
-               dhcp_static(iface);
+               dhcp_static(ifp);
                return;
        }
-       if (ifo->reboot == 0 || iface->state->offer == NULL) {
-               dhcp_discover(iface);
+       if (ifo->reboot == 0 || state->offer == NULL) {
+               dhcp_discover(ifp);
                return;
        }
        if (ifo->options & DHCPCD_INFORM) {
                syslog(LOG_INFO, "%s: informing address of %s",
-                   iface->name, inet_ntoa(iface->state->lease.addr));
-       } else if (iface->state->offer->cookie == 0) {
+                   ifp->name, inet_ntoa(state->lease.addr));
+       } else if (state->offer->cookie == 0) {
                if (ifo->options & DHCPCD_IPV4LL) {
-                       iface->state->claims = 0;
-                       arp_announce(iface);
+                       state->claims = 0;
+                       arp_announce(ifp);
                } else
-                       dhcp_discover(iface);
+                       dhcp_discover(ifp);
                return;
        } else {
                syslog(LOG_INFO, "%s: rebinding lease of %s",
-                   iface->name, inet_ntoa(iface->state->lease.addr));
+                   ifp->name, inet_ntoa(state->lease.addr));
        }
-       iface->state->state = DHS_REBOOT;
-       iface->state->xid = dhcp_xid(iface);
-       iface->state->lease.server.s_addr = 0;
-       eloop_timeout_delete(NULL, iface);
+       state->state = DHS_REBOOT;
+       state->xid = dhcp_xid(ifp);
+       state->lease.server.s_addr = 0;
+       eloop_timeout_delete(NULL, ifp);
        if (ifo->fallback)
-               eloop_timeout_add_sec(ifo->reboot, dhcp_fallback, iface);
-       else if (ifo->options & DHCPCD_LASTLEASE &&
-           iface->state->lease.frominfo)
-               eloop_timeout_add_sec(ifo->reboot, dhcp_timeout, iface);
+               eloop_timeout_add_sec(ifo->reboot, dhcp_fallback, ifp);
+       else if (ifo->options & DHCPCD_LASTLEASE && state->lease.frominfo)
+               eloop_timeout_add_sec(ifo->reboot, dhcp_timeout, ifp);
        else if (!(ifo->options & DHCPCD_INFORM &&
            options & (DHCPCD_MASTER | DHCPCD_DAEMONISED)))
-               eloop_timeout_add_sec(ifo->reboot, dhcp_expire, iface);
+               eloop_timeout_add_sec(ifo->reboot, dhcp_expire, ifp);
        /* Don't bother ARP checking as the server could NAK us first. */
        if (ifo->options & DHCPCD_INFORM)
-               dhcp_inform(iface);
+               dhcp_inform(ifp);
        else
-               dhcp_request(iface);
+               dhcp_request(ifp);
 }
 
 
 void
 dhcp_drop(struct interface *iface, const char *reason)
 {
+       struct dhcp_state *state = D_STATE(iface);
 
+       if (state == NULL)
+               return;
        eloop_timeouts_delete(iface, dhcp_expire, NULL);
-       free(iface->state->old);
-       iface->state->old = iface->state->new;
-       iface->state->new = NULL;
-       iface->state->reason = reason;
+       free(state->old);
+       state->old = state->new;
+       state->new = NULL;
+       state->reason = reason;
        ipv4_applyaddr(iface);
-       free(iface->state->old);
-       iface->state->old = NULL;
-       iface->state->lease.addr.s_addr = 0;
+       free(state->old);
+       state->old = NULL;
+       state->lease.addr.s_addr = 0;
 }
 
 static void
@@ -1863,7 +1897,7 @@ static void
 dhcp_handle(struct interface *iface, struct dhcp_message **dhcpp,
     const struct in_addr *from)
 {
-       struct if_state *state = iface->state;
+       struct dhcp_state *state = D_STATE(iface);
        struct if_options *ifo = iface->options;
        struct dhcp_message *dhcp = *dhcpp;
        struct dhcp_lease *lease = &state->lease;
@@ -1890,7 +1924,7 @@ dhcp_handle(struct interface *iface, struct dhcp_message **dhcpp,
                log_dhcp(LOG_WARNING, "NAK:", iface, dhcp, from);
                if (!(options & DHCPCD_TEST)) {
                        dhcp_drop(iface, "NAK");
-                       unlink(iface->state->leasefile);
+                       unlink(state->leasefile);
                }
                dhcp_close(iface);
                /* If we constantly get NAKS then we should slowly back off */
@@ -1951,7 +1985,7 @@ dhcp_handle(struct interface *iface, struct dhcp_message **dhcpp,
                        state->new = state->offer;
                        state->offer = NULL;
                        state->reason = "TEST";
-                       script_run(iface);
+                       script_runreason(iface, state->reason);
                        exit(EXIT_SUCCESS);
                }
                eloop_timeout_delete(send_discover, iface);
@@ -2030,6 +2064,7 @@ dhcp_handlepacket(void *arg)
        ssize_t bytes;
        struct in_addr from;
        int i, partialcsum = 0;
+       const struct dhcp_state *state = D_CSTATE(iface);
 
        /* We loop through until our buffer is empty.
         * The benefit is that if we get >1 DHCP packet in our buffer and
@@ -2061,7 +2096,7 @@ dhcp_handlepacket(void *arg)
                        continue;
                }
                if (iface->flags & IFF_POINTOPOINT &&
-                   iface->state->dst.s_addr != from.s_addr)
+                   state->dst.s_addr != from.s_addr)
                {
                        syslog(LOG_WARNING,
                            "%s: server %s is not destination",
@@ -2083,10 +2118,10 @@ dhcp_handlepacket(void *arg)
                        continue;
                }
                /* Ensure it's the right transaction */
-               if (iface->state->xid != ntohl(dhcp->xid)) {
+               if (state->xid != ntohl(dhcp->xid)) {
                        syslog(LOG_DEBUG,
                            "%s: wrong xid 0x%x (expecting 0x%x) from %s",
-                           iface->name, ntohl(dhcp->xid), iface->state->xid,
+                           iface->name, ntohl(dhcp->xid), state->xid,
                            inet_ntoa(from));
                        continue;
                }
@@ -2100,7 +2135,7 @@ dhcp_handlepacket(void *arg)
                        continue;
                }
                dhcp_handle(iface, &dhcp, &from);
-               if (iface->state->raw_fd == -1)
+               if (state->raw_fd == -1)
                        break;
        }
        free(packet);
@@ -2112,19 +2147,19 @@ static int
 dhcp_open(struct interface *ifp)
 {
        int r = 0;
-       struct if_state *ifs;
+       struct dhcp_state *state;
 
-       ifs = ifp->state;
-       if (ifs->raw_fd == -1) {
+       state = D_STATE(ifp);
+       if (state->raw_fd == -1) {
                if ((r = open_socket(ifp, ETHERTYPE_IP)) == -1)
                        syslog(LOG_ERR, "%s: %s: %m", __func__, ifp->name);
                else
-                       eloop_event_add(ifs->raw_fd, dhcp_handlepacket, ifp);
+                       eloop_event_add(state->raw_fd, dhcp_handlepacket, ifp);
        }
-       if (ifs->udp_fd == -1 &&
-           ifs->addr.s_addr != 0 &&
-           ifs->new != NULL &&
-           (ifs->new->cookie == htonl(MAGIC_COOKIE) ||
+       if (state->udp_fd == -1 &&
+           state->addr.s_addr != 0 &&
+           state->new != NULL &&
+           (state->new->cookie == htonl(MAGIC_COOKIE) ||
            ifp->options->options & DHCPCD_INFORM))
        {
                if (open_udp_socket(ifp) == -1 && errno != EADDRINUSE) {
@@ -2135,10 +2170,134 @@ dhcp_open(struct interface *ifp)
        return r;
 }
 
+int
+dhcp_dump(const char *ifname)
+{
+       struct interface *ifp;
+       struct dhcp_state *state;
+
+       ifaces = ifp = xzalloc(sizeof(*ifp));
+       ifp->if_data[IF_DATA_DHCP] = state = xzalloc(sizeof(*state));
+       ifp->options = xzalloc(sizeof(*ifp->options));
+       strlcpy(ifp->name, ifname, sizeof(ifp->name));
+       snprintf(state->leasefile, sizeof(state->leasefile),
+           LEASEFILE, ifp->name);
+       strlcpy(ifp->options->script, if_options->script,
+           sizeof(ifp->options->script));
+       state->new = read_lease(ifp);
+       if (state->new == NULL && errno == ENOENT) {
+               strlcpy(state->leasefile, ifname, sizeof(state->leasefile));
+               state->new = read_lease(ifp);
+       }
+       if (state->new == NULL) {
+               if (errno == ENOENT)
+                       syslog(LOG_ERR, "%s: no lease to dump", ifname);
+               return -1;
+       }
+       state->reason = "DUMP";
+       return script_runreason(ifp, state->reason);
+}
+
+void
+dhcp_free(struct interface *ifp)
+{
+       struct dhcp_state *state = D_STATE(ifp);
+
+       if (state) {
+               free(state->old);
+               free(state->new);
+               free(state->offer);
+               free(state->buffer);
+               free(state->clientid);
+               free(state);
+               ifp->if_data[IF_DATA_DHCP] = NULL;
+       }
+}
+
+static int
+dhcp_init(struct interface *ifp)
+{
+       struct dhcp_state *state;
+       const struct if_options *ifo;
+       unsigned char *duid;
+       size_t len, ifl;
+
+       state = D_STATE(ifp);
+       if (state == NULL) {
+               ifp->if_data[IF_DATA_DHCP] = calloc(1, sizeof(*state));
+               state = D_STATE(ifp);
+       }
+       if (state == NULL)
+               return -1;
+
+       state->state = DHS_INIT;
+       state->reason = "PREINIT";
+       state->nakoff = 0;
+       snprintf(state->leasefile, sizeof(state->leasefile),
+           LEASEFILE, ifp->name);
+       /* 0 is a valid fd, so init to -1 */
+       state->raw_fd = state->udp_fd = state->arp_fd = -1;
+
+       ifo = ifp->options;
+       /* We need to drop the leasefile so that start_interface
+        * doesn't load it. */  
+       if (ifo->options & DHCPCD_REQUEST)
+               unlink(state->leasefile);
+
+       free(state->clientid);
+       state->clientid = NULL;
+
+       if (*ifo->clientid) {
+               state->clientid = xmalloc(ifo->clientid[0] + 1);
+               memcpy(state->clientid, ifo->clientid, ifo->clientid[0] + 1);
+       } else if (ifo->options & DHCPCD_CLIENTID) {
+               len = 0;
+               if (ifo->options & DHCPCD_DUID) {
+                       duid = xmalloc(DUID_LEN);
+                       if ((len = get_duid(duid, ifp)) == 0)
+                               syslog(LOG_ERR, "get_duid: %m");
+               } else
+                       duid = NULL;
+               if (len > 0) {
+                       state->clientid = xmalloc(len + 6);
+                       state->clientid[0] = len + 5;
+                       state->clientid[1] = 255; /* RFC 4361 */
+                       ifl = strlen(ifp->name);
+                       if (ifl < 5) {
+                               memcpy(state->clientid + 2, ifp->name, ifl);
+                               if (ifl < 4)
+                                       memset(state->clientid + 2 + ifl,
+                                           0, 4 - ifl);
+                       } else {
+                               ifl = htonl(ifp->index);
+                               memcpy(state->clientid + 2, &ifl, 4);
+                       }
+                       memcpy(state->clientid + 6, duid, len);
+               } else if (len == 0) {
+                       len = ifp->hwlen + 1;
+                       state->clientid = xmalloc(len + 1);
+                       state->clientid[0] = len;
+                       state->clientid[1] = ifp->family;
+                       memcpy(state->clientid + 2, ifp->hwaddr,
+                           ifp->hwlen);
+               }
+               free(duid);
+       }
+       if (ifo->options & DHCPCD_CLIENTID)
+               syslog(LOG_DEBUG, "%s: using ClientID %s", ifp->name,
+                   hwaddr_ntoa(state->clientid + 1, state->clientid[0]));
+       else if (ifp->hwlen)
+               syslog(LOG_DEBUG, "%s: using hwaddr %s", ifp->name,
+                   hwaddr_ntoa(ifp->hwaddr, ifp->hwlen));
+
+       return 0;
+}
+
 void
 dhcp_start(struct interface *ifp)
 {
        struct if_options *ifo = ifp->options;
+       struct dhcp_state *state;
        struct stat st;
        struct timeval now;
        uint32_t l;
@@ -2147,6 +2306,21 @@ dhcp_start(struct interface *ifp)
        if (!(ifo->options & DHCPCD_IPV4))
                return;
 
+       if (dhcp_init(ifp) == -1) {
+               syslog(LOG_ERR, "%s: dhcp_init: %m", ifp->name);
+               return;
+       }
+
+       state = D_STATE(ifp);
+       state->start_uptime = uptime();
+       free(state->offer);
+       state->offer = NULL;
+
+       if (state->arping_index < ifo->arping_len) {
+               arp_start(ifp);
+               return;
+       }
+
        if (ifo->options & DHCPCD_STATIC) {
                dhcp_static(ifp);
                return;
@@ -2168,47 +2342,45 @@ dhcp_start(struct interface *ifp)
                return;
        }
        /* We don't want to read the old lease if we NAK an old test */
-       nolease = ifp->state->offer && options & DHCPCD_TEST;
+       nolease = state->offer && options & DHCPCD_TEST;
        if (!nolease)
-               ifp->state->offer = read_lease(ifp);
-       if (ifp->state->offer) {
-               get_lease(&ifp->state->lease, ifp->state->offer);
-               ifp->state->lease.frominfo = 1;
-               if (ifp->state->offer->cookie == 0) {
-                       if (ifp->state->offer->yiaddr ==
-                           ifp->state->addr.s_addr)
-                       {
-                               free(ifp->state->offer);
-                               ifp->state->offer = NULL;
+               state->offer = read_lease(ifp);
+       if (state->offer) {
+               get_lease(&state->lease, state->offer);
+               state->lease.frominfo = 1;
+               if (state->offer->cookie == 0) {
+                       if (state->offer->yiaddr == state->addr.s_addr) {
+                               free(state->offer);
+                               state->offer = NULL;
                        }
-               } else if (ifp->state->lease.leasetime != ~0U &&
-                   stat(ifp->state->leasefile, &st) == 0)
+               } else if (state->lease.leasetime != ~0U &&
+                   stat(state->leasefile, &st) == 0)
                {
                        /* Offset lease times and check expiry */
                        gettimeofday(&now, NULL);
-                       if ((time_t)ifp->state->lease.leasetime <
+                       if ((time_t)state->lease.leasetime <
                            now.tv_sec - st.st_mtime)
                        {
                                syslog(LOG_DEBUG,
                                    "%s: discarding expired lease",
                                    ifp->name);
-                               free(ifp->state->offer);
-                               ifp->state->offer = NULL;
-                               ifp->state->lease.addr.s_addr = 0;
+                               free(state->offer);
+                               state->offer = NULL;
+                               state->lease.addr.s_addr = 0;
                        } else {
                                l = now.tv_sec - st.st_mtime;
-                               ifp->state->lease.leasetime -= l;
-                               ifp->state->lease.renewaltime -= l;
-                               ifp->state->lease.rebindtime -= l;
+                               state->lease.leasetime -= l;
+                               state->lease.renewaltime -= l;
+                               state->lease.rebindtime -= l;
                        }
                }
        }
-       if (ifp->state->offer == NULL)
+       if (state->offer == NULL)
                dhcp_discover(ifp);
-       else if (ifp->state->offer->cookie == 0 &&
+       else if (state->offer->cookie == 0 &&
            ifp->options->options & DHCPCD_IPV4LL)
                ipv4ll_start(ifp);
        else
-               dhcp_reboot(ifp);
+               dhcp_reboot(ifp, ifp->options->options);
 }
 
diff --git a/dhcp.h b/dhcp.h
index f83722bb2c768869bce8c1f6ceac79a6b5e83898..d5bab1cd68820830716dcc8b4fed73dea3721e39 100644 (file)
--- a/dhcp.h
+++ b/dhcp.h
@@ -31,6 +31,7 @@
 #include <arpa/inet.h>
 #include <netinet/in.h>
 
+#include <limits.h>
 #include <stdint.h>
 
 #include "common.h"
@@ -166,6 +167,60 @@ struct dhcp_lease {
        uint32_t cookie;
 };
 
+enum DHS {
+       DHS_INIT,
+       DHS_DISCOVER,
+       DHS_REQUEST,
+       DHS_BOUND,
+       DHS_RENEW,
+       DHS_REBIND,
+       DHS_REBOOT,
+       DHS_INFORM,
+       DHS_RENEW_REQUESTED,
+       DHS_INIT_IPV4LL,
+       DHS_PROBE
+};
+
+struct dhcp_state {
+       enum DHS state;
+       struct dhcp_message *sent;
+       struct dhcp_message *offer;
+       struct dhcp_message *new;
+       struct dhcp_message *old;
+       struct dhcp_lease lease;
+       const char *reason;
+       time_t interval;
+       time_t nakoff;
+       uint32_t xid;
+       int socket;
+       int probes;
+       int claims;
+       int conflicts;
+       time_t defend;
+       struct in_addr fail;
+       size_t arping_index;
+
+       int raw_fd;
+       int udp_fd;
+       int arp_fd;
+       size_t buffer_size, buffer_len, buffer_pos;
+       unsigned char *buffer;
+
+       struct in_addr addr;
+       struct in_addr net;
+       struct in_addr dst;
+
+       char leasefile[PATH_MAX];
+       time_t start_uptime;
+
+       unsigned char *clientid;
+};
+
+#define D_STATE(ifp)                                                          \
+       ((struct dhcp_state *)(ifp)->if_data[IF_DATA_DHCP])
+#define D_CSTATE(ifp)                                                         \
+       ((const struct dhcp_state *)(ifp)->if_data[IF_DATA_DHCP])
+
 #include "dhcpcd.h"
 #include "if-options.h"
 #include "net.h"
@@ -209,6 +264,9 @@ void dhcp_discover(void *);
 void dhcp_inform(struct interface *);
 void dhcp_release(struct interface *);
 void dhcp_bind(void *);
+void dhcp_reboot(struct interface *, int);
 void dhcp_close(struct interface *);
+void dhcp_free(struct interface *);
+int dhcp_dump(const char *);
 
 #endif
index 4f3ca3fb6866f7adc9664e94e219b241cdbc4983..9f8779e91912b1dd20b94cc182d1a202f34e676f 100644 (file)
--- a/dhcpcd.c
+++ b/dhcpcd.c
@@ -54,12 +54,10 @@ const char copyright[] = "Copyright (c) 2006-2013 Roy Marples";
 #include "control.h"
 #include "dhcpcd.h"
 #include "dhcp6.h"
-#include "duid.h"
 #include "eloop.h"
 #include "if-options.h"
 #include "if-pref.h"
 #include "ipv4.h"
-#include "ipv4ll.h"
 #include "ipv6.h"
 #include "ipv6ns.h"
 #include "ipv6rs.h"
@@ -68,9 +66,6 @@ const char copyright[] = "Copyright (c) 2006-2013 Roy Marples";
 #include "script.h"
 #include "signals.h"
 
-/* We should define a maximum for the NAK exponential backoff */ 
-#define NAKOFF_MAX              60
-
 /* Wait N nanoseconds between sending a RELEASE and dropping the address.
  * This gives the kernel enough time to actually send it. */
 #define RELEASE_DELAY_S                0
@@ -79,6 +74,7 @@ const char copyright[] = "Copyright (c) 2006-2013 Roy Marples";
 char vendor[VENDORCLASSID_MAX_LEN];
 int pidfd = -1;
 struct interface *ifaces = NULL;
+struct if_options *if_options = NULL;
 int ifac = 0;
 char **ifav = NULL;
 int ifdc = 0;
@@ -87,7 +83,6 @@ char **ifdv = NULL;
 sigset_t dhcpcd_sigset;
 
 static char *cffile;
-static struct if_options *if_options;
 static char *pidfile;
 static int linkfd = -1, ipv6rsfd = -1, ipv6nsfd = -1;
 static char **ifv;
@@ -155,7 +150,6 @@ cleanup(void)
        for (i = 0; i < ifdc; i++)
                free(ifdv[i]);
        free(ifdv);
-       free(packet);
 #endif
 
        if (linkfd != -1)
@@ -299,10 +293,7 @@ stop_interface(struct interface *iface)
 static void
 configure_interface1(struct interface *ifp)
 {
-       struct if_state *ifs = ifp->state;
        struct if_options *ifo = ifp->options;
-       uint8_t *duid;
-       size_t len, ifl;
 
        /* Do any platform specific configuration */
        if_conf(ifp);
@@ -340,54 +331,6 @@ configure_interface1(struct interface *ifp)
                ifo->options |= DHCPCD_CLIENTID | DHCPCD_BROADCAST;
                break;
        }
-
-       free(ifs->clientid);
-       ifs->clientid = NULL;
-       if (!(ifo->options & DHCPCD_IPV4))
-               return;
-
-       if (*ifo->clientid) {
-               ifs->clientid = xmalloc(ifo->clientid[0] + 1);
-               memcpy(ifs->clientid, ifo->clientid, ifo->clientid[0] + 1);
-       } else if (ifo->options & DHCPCD_CLIENTID) {
-               len = 0;
-               if (ifo->options & DHCPCD_DUID) {
-                       duid = xmalloc(DUID_LEN);
-                       if ((len = get_duid(duid, ifp)) == 0)
-                               syslog(LOG_ERR, "get_duid: %m");
-               } else
-                       duid = NULL;
-               if (len > 0) {
-                       ifs->clientid = xmalloc(len + 6);
-                       ifs->clientid[0] = len + 5;
-                       ifs->clientid[1] = 255; /* RFC 4361 */
-                       ifl = strlen(ifp->name);
-                       if (ifl < 5) {
-                               memcpy(ifs->clientid + 2, ifp->name, ifl);
-                               if (ifl < 4)
-                                       memset(ifs->clientid + 2 + ifl,
-                                           0, 4 - ifl);
-                       } else {
-                               ifl = htonl(ifp->index);
-                               memcpy(ifs->clientid + 2, &ifl, 4);
-                       }
-                       memcpy(ifs->clientid + 6, duid, len);
-               } else if (len == 0) {
-                       len = ifp->hwlen + 1;
-                       ifs->clientid = xmalloc(len + 1);
-                       ifs->clientid[0] = len;
-                       ifs->clientid[1] = ifp->family;
-                       memcpy(ifs->clientid + 2, ifp->hwaddr,
-                           ifp->hwlen);
-               }
-               free(duid);
-       }
-       if (ifo->options & DHCPCD_CLIENTID)
-               syslog(LOG_DEBUG, "%s: using ClientID %s", ifp->name,
-                   hwaddr_ntoa(ifs->clientid + 1, ifs->clientid[0]));
-       else if (ifp->hwlen)
-               syslog(LOG_DEBUG, "%s: using hwaddr %s", ifp->name,
-                   hwaddr_ntoa(ifp->hwaddr, ifp->hwlen));
 }
 
 int
@@ -404,12 +347,11 @@ select_profile(struct interface *ifp, const char *profile)
                goto exit;
        }
        if (profile != NULL) {
-               strlcpy(ifp->state->profile, profile,
-                   sizeof(ifp->state->profile));
+               strlcpy(ifp->profile, profile, sizeof(ifp->profile));
                syslog(LOG_INFO, "%s: selected profile %s",
                    ifp->name, profile);
        } else
-               *ifp->state->profile = '\0';
+               *ifp->profile = '\0';
        free_options(ifp->options);
        ifp->options = ifo;
 
@@ -471,9 +413,7 @@ handle_carrier(int action, int flags, const char *ifname)
                        if (ifp->wireless)
                                getifssid(ifp->name, ifp->ssid);
                        configure_interface(ifp, margc, margv);
-                       ifp->state->interval = 0;
-                       ifp->state->reason = "CARRIER";
-                       script_run(ifp);
+                       script_runreason(ifp, "CARRIER");
                        start_interface(ifp);
                }
        }
@@ -492,19 +432,10 @@ start_interface(void *arg)
                return;
        }
 
-       ifp->state->start_uptime = uptime();
-       free(ifp->state->offer);
-       ifp->state->offer = NULL;
-
        if (options & DHCPCD_IPV6RS && ifo->options & DHCPCD_IPV6RS &&
            !(ifo->options & DHCPCD_INFORM))
                ipv6rs_start(ifp);
 
-       if (ifp->state->arping_index < ifo->arping_len) {
-               arp_start(ifp);
-               return;
-       }
-
        if (ifo->options & DHCPCD_IPV6) {
                if (ifo->options & DHCPCD_INFORM)
                        nolease = dhcp6_start(ifp, 0);
@@ -523,46 +454,28 @@ start_interface(void *arg)
 static void
 init_state(struct interface *ifp, int argc, char **argv)
 {
-       struct if_state *ifs;
-
-       if (ifp->state)
-               ifs = ifp->state;
-       else
-               ifs = ifp->state = xzalloc(sizeof(*ifs));
-
-       ifs->state = DHS_INIT;
-       ifs->reason = "PREINIT";
-       ifs->nakoff = 0;
-       snprintf(ifs->leasefile, sizeof(ifs->leasefile),
-           LEASEFILE, ifp->name);
-       /* 0 is a valid fd, so init to -1 */
-       ifs->raw_fd = ifs->udp_fd = ifs->arp_fd = -1;
+       const char *reason = NULL;
 
        configure_interface(ifp, argc, argv);
        if (!(options & DHCPCD_TEST))
-               script_run(ifp);
-
-       /* We need to drop the leasefile so that start_interface
-        * doesn't load it. */  
-       if (ifp->options->options & DHCPCD_REQUEST)
-               unlink(ifs->leasefile);
+               script_runreason(ifp, "PREINIT");
 
        if (ifp->options->options & DHCPCD_LINK) {
                switch (carrier_status(ifp)) {
                case 0:
                        ifp->carrier = LINK_DOWN;
-                       ifs->reason = "NOCARRIER";
+                       reason = "NOCARRIER";
                        break;
                case 1:
                        ifp->carrier = LINK_UP;
-                       ifs->reason = "CARRIER";
+                       reason = "CARRIER";
                        break;
                default:
                        ifp->carrier = LINK_UNKNOWN;
                        return;
                }
-               if (!(options & DHCPCD_TEST))
-                       script_run(ifp);
+               if (reason && !(options & DHCPCD_TEST))
+                       script_runreason(ifp, reason);
        } else
                ifp->carrier = LINK_UNKNOWN;
 }
@@ -666,24 +579,11 @@ handle_link(_unused void *arg)
 static void
 if_reboot(struct interface *ifp, int argc, char **argv)
 {
-       const struct if_options *ifo;
-       int opt;
-       
-       ifo = ifp->options;
-       opt = ifo->options;
+       int oldopts;
+
+       oldopts = ifp->options->options;
        configure_interface(ifp, argc, argv);
-       ifo = ifp->options;
-       ifp->state->interval = 0;
-       if ((ifo->options & (DHCPCD_INFORM | DHCPCD_STATIC) &&
-               ifp->state->addr.s_addr != ifo->req_addr.s_addr) ||
-           (opt & (DHCPCD_INFORM | DHCPCD_STATIC) &&
-               !(ifo->options & (DHCPCD_INFORM | DHCPCD_STATIC))))
-       {
-               dhcp_drop(ifp, "EXPIRE");
-       } else {
-               free(ifp->state->offer);
-               ifp->state->offer = NULL;
-       }
+       dhcp_reboot(ifp, oldopts);
        start_interface(ifp);
 }
 
@@ -706,7 +606,7 @@ reconf_reboot(int action, int argc, char **argv, int oi)
                if (ifn) {
                        if (action)
                                if_reboot(ifn, argc, argv);
-                       else if (ifn->state->new)
+                       else
                                ipv4_applyaddr(ifn);
                        free_interface(ifp);
                } else {
@@ -768,8 +668,7 @@ handle_signal(int sig)
        case SIGUSR1:
                syslog(LOG_INFO, "received SIGUSR, reconfiguring");
                for (ifp = ifaces; ifp; ifp = ifp->next)
-                       if (ifp->state->new)
-                               ipv4_applyaddr(ifp);
+                       ipv4_applyaddr(ifp);
                return;
        case SIGPIPE:
                syslog(LOG_WARNING, "received SIGPIPE");
@@ -946,7 +845,6 @@ int
 main(int argc, char **argv)
 {
        struct interface *iface;
-       struct if_state *ifs;
        uint16_t family = 0;
        int opt, oi = 0, sig = 0, i, control_fd;
        size_t len;
@@ -1079,28 +977,8 @@ main(int argc, char **argv)
                        syslog(LOG_ERR, "dumplease requires an interface");
                        exit(EXIT_FAILURE);
                }
-               ifaces = iface = xzalloc(sizeof(*iface));
-               iface->state = ifs = xzalloc(sizeof(*iface->state));
-               iface->options = xzalloc(sizeof(*iface->options));
-               strlcpy(iface->name, argv[optind], sizeof(iface->name));
-               snprintf(ifs->leasefile, sizeof(ifs->leasefile),
-                   LEASEFILE, iface->name);
-               strlcpy(iface->options->script, if_options->script,
-                   sizeof(iface->options->script));
-               iface->state->new = read_lease(iface);
-               if (iface->state->new == NULL && errno == ENOENT) {
-                       strlcpy(ifs->leasefile, argv[optind],
-                           sizeof(ifs->leasefile));
-                       iface->state->new = read_lease(iface);
-               }
-               if (iface->state->new == NULL) {
-                       if (errno == ENOENT)
-                               syslog(LOG_ERR, "%s: no lease to dump",
-                                   iface->name);
+               if (dhcp_dump(argv[optind]) == -1)
                        exit(EXIT_FAILURE);
-               }
-               iface->state->reason = "DUMP";
-               script_run(iface);
                exit(EXIT_SUCCESS);
        }
 
index 41bb73515851cee1d0f66d595a97ffdae0a7dcb7..c734360c2d05f51dabebac65a9b75dab620bd825 100644 (file)
--- a/dhcpcd.h
+++ b/dhcpcd.h
 #define IF_SSIDSIZE 33
 #define PROFILE_LEN 64
 
-enum DHS {
-       DHS_INIT,
-       DHS_DISCOVER,
-       DHS_REQUEST,
-       DHS_BOUND,
-       DHS_RENEW,
-       DHS_REBIND,
-       DHS_REBOOT,
-       DHS_INFORM,
-       DHS_RENEW_REQUESTED,
-       DHS_INIT_IPV4LL,
-       DHS_PROBE
-};
-
 #define LINK_UP        1
 #define LINK_UNKNOWN   0
 #define LINK_DOWN      -1
@@ -64,47 +50,8 @@ enum DHS {
 #define IF_DATA_DHCP6  2
 #define IF_DATA_MAX    3
 
-struct if_state {
-       enum DHS state;
-       char profile[PROFILE_LEN];
-       struct dhcp_message *sent;
-       struct dhcp_message *offer;
-       struct dhcp_message *new;
-       struct dhcp_message *old;
-       struct dhcp_lease lease;
-       const char *reason;
-       time_t interval;
-       time_t nakoff;
-       uint32_t xid;
-       int socket;
-       int probes;
-       int claims;
-       int conflicts;
-       time_t defend;
-       struct in_addr fail;
-       size_t arping_index;
-
-       int raw_fd;
-       int udp_fd;
-       int arp_fd;
-       size_t buffer_size, buffer_len, buffer_pos;
-       unsigned char *buffer;
-
-       struct in_addr addr;
-       struct in_addr net;
-       struct in_addr dst;
-
-       char leasefile[PATH_MAX];
-       time_t start_uptime;
-
-       unsigned char *clientid;
-};
-
 struct interface {
        char name[IF_NAMESIZE];
-       struct if_state *state;
-       void *if_data[IF_DATA_MAX];
-
        unsigned int index;
        int flags;
        sa_family_t family;
@@ -115,8 +62,9 @@ struct interface {
        int wireless;
        char ssid[IF_SSIDSIZE];
 
+       char profile[PROFILE_LEN];
        struct if_options *options;
-
+       void *if_data[IF_DATA_MAX];
        struct interface *next;
 };
 
@@ -127,6 +75,7 @@ extern int ifac;
 extern char **ifav;
 extern int ifdc;
 extern char **ifdv;
+extern struct if_options *if_options;
 extern struct interface *ifaces;
 
 pid_t daemonise(void);
index 41be95f1121a915ea76ac8ba0776579db2181c3a..34248d0c8b86c1aff92dd92c79f63a5e9b42274d 100644 (file)
@@ -542,7 +542,7 @@ if_route(const struct rt *rt, int action)
 {
        struct nlmr *nlm;
        int retval = 0;
-       struct if_state *ifs;
+       struct dhcp_state *state;
 
        nlm = xzalloc(sizeof(*nlm));
        nlm->hdr.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg));
@@ -557,14 +557,15 @@ if_route(const struct rt *rt, int action)
        nlm->rt.rtm_family = AF_INET;
        nlm->rt.rtm_table = RT_TABLE_MAIN;
 
-       ifs = rt->iface->state;
+       state = D_STATE(rt->iface);
        if (action == -1 || action == -2)
                nlm->rt.rtm_scope = RT_SCOPE_NOWHERE;
        else {
                nlm->hdr.nlmsg_flags |= NLM_F_CREATE | NLM_F_EXCL;
                /* We only change route metrics for kernel routes */
-               if (rt->dest.s_addr == (ifs->addr.s_addr & ifs->net.s_addr) &&
-                   rt->net.s_addr == ifs->net.s_addr)
+               if (rt->dest.s_addr ==
+                   (state->addr.s_addr & state->net.s_addr) &&
+                   rt->net.s_addr == state->net.s_addr)
                        nlm->rt.rtm_protocol = RTPROT_KERNEL;
                else
                        nlm->rt.rtm_protocol = RTPROT_BOOT;
@@ -582,7 +583,7 @@ if_route(const struct rt *rt, int action)
            &rt->dest.s_addr, sizeof(rt->dest.s_addr));
        if (nlm->rt.rtm_protocol == RTPROT_KERNEL) {
                add_attr_l(&nlm->hdr, sizeof(*nlm), RTA_PREFSRC,
-                   &ifs->addr.s_addr, sizeof(ifs->addr.s_addr));
+                   &state->addr.s_addr, sizeof(state->addr.s_addr));
        }
        /* If destination == gateway then don't add the gateway */
        if (rt->dest.s_addr != rt->gate.s_addr ||
index 6169dbe968c00a9016c8bb59056ea9977ea61bf2..9e95fba58bfd07bb814d07d9c46348993ea7d5cd 100644 (file)
--- a/if-pref.c
+++ b/if-pref.c
 #include <sys/types.h>
 
 #include "config.h"
-#include "dhcpcd.h"
+#include "dhcp.h"
 #include "if-pref.h"
 #include "net.h"
 
 /* Interface comparer for working out ordering. */
 static int
-ifcmp(struct interface *si, struct interface *ti)
+ifcmp(const struct interface *si, const struct interface *ti)
 {
        int sill, till;
+       const struct dhcp_state *sis, *tis;
 
-       if (si->state && !ti->state)
+       sis = D_CSTATE(si);
+       tis = D_CSTATE(ti);
+       if (sis && !tis)
                return -1;
-       if (!si->state && ti->state)
+       if (!sis && tis)
                return 1;
-       if (!si->state && !ti->state)
+       if (!sis && !tis)
                return 0;
        /* If one has a lease and the other not, it takes precedence. */
-       if (si->state->new && !ti->state->new)
+       if (sis->new && !tis->new)
                return -1;
-       if (!si->state->new && ti->state->new)
+       if (!sis->new && tis->new)
                return 1;
        /* If we are either, they neither have a lease, or they both have.
         * We need to check for IPv4LL and make it non-preferred. */
-       if (si->state->new && ti->state->new) {
-               sill = (si->state->new->cookie == htonl(MAGIC_COOKIE));
-               till = (ti->state->new->cookie == htonl(MAGIC_COOKIE));
+       if (sis->new && tis->new) {
+               sill = (sis->new->cookie == htonl(MAGIC_COOKIE));
+               till = (tis->new->cookie == htonl(MAGIC_COOKIE));
                if (!sill && till)
                        return 1;
                if (sill && !till)
diff --git a/ipv4.c b/ipv4.c
index a5475e518e837bfe09aeb35e18f94189e0cc0553..e2170acfa71d13b92f1fbf58aefbf95cfe87fdcf 100644 (file)
--- a/ipv4.c
+++ b/ipv4.c
@@ -118,7 +118,7 @@ ipv4_routedeleted(const struct rt *rt)
 static int
 n_route(struct rt *rt)
 {
-       struct if_state *s;
+       const struct dhcp_state *s;
 
        /* Don't set default routes if not asked to */
        if (rt->dest.s_addr == 0 &&
@@ -130,7 +130,7 @@ n_route(struct rt *rt)
        if (!add_route(rt))
                return 0;
        if (errno == EEXIST) {
-               s = rt->iface->state;
+               s = D_CSTATE(rt->iface);
                /* Pretend we added the subnet route */
                if (rt->dest.s_addr == (s->addr.s_addr & s->net.s_addr) &&
                    rt->net.s_addr == s->net.s_addr &&
@@ -201,9 +201,9 @@ static struct rt *
 add_subnet_route(struct rt *rt, const struct interface *iface)
 {
        struct rt *r;
-       struct if_state *s;
+       const struct dhcp_state *s;
 
-       s = iface->state;
+       s = D_CSTATE(iface);
        if (s->net.s_addr == INADDR_BROADCAST ||
            s->net.s_addr == INADDR_ANY ||
            (iface->options->options &
@@ -243,7 +243,7 @@ get_routes(struct interface *ifp)
                return nrt;
        }
 
-       return get_option_routes(ifp, ifp->state->new);
+       return get_option_routes(ifp, D_STATE(ifp)->new);
 }
 
 /* Some DHCP servers add set host routes by setting the gateway
@@ -255,7 +255,7 @@ massage_host_routes(struct rt *rt, const struct interface *ifp)
        struct rt *r;
 
        for (r = rt; r; r = r->next) {
-               if (r->gate.s_addr == ifp->state->addr.s_addr &&
+               if (r->gate.s_addr == D_CSTATE(ifp)->addr.s_addr &&
                    r->net.s_addr == INADDR_BROADCAST)
                        r->gate.s_addr = r->dest.s_addr;
        }
@@ -273,7 +273,7 @@ add_destination_route(struct rt *rt, const struct interface *iface)
        r = xmalloc(sizeof(*r));
        r->dest.s_addr = INADDR_ANY;
        r->net.s_addr = INADDR_ANY;
-       r->gate.s_addr = iface->state->dst.s_addr;
+       r->gate.s_addr = D_CSTATE(iface)->dst.s_addr;
        r->next = rt;
        return r;
 }
@@ -335,9 +335,11 @@ ipv4_buildroutes(void)
 {
        struct rt *nrs = NULL, *dnr, *or, *rt, *rtn, *rtl, *lrt = NULL;
        struct interface *ifp;
+       const struct dhcp_state *state;
 
        for (ifp = ifaces; ifp; ifp = ifp->next) {
-               if (ifp->state->new == NULL)
+               state = D_CSTATE(ifp);
+               if (state == NULL || state->new == NULL)
                        continue;
                dnr = get_routes(ifp);
                dnr = massage_host_routes(dnr, ifp);
@@ -352,11 +354,11 @@ ipv4_buildroutes(void)
                        /* Is this route already in our table? */
                        if ((find_route(nrs, rt, NULL, NULL)) != NULL)
                                continue;
-                       rt->src.s_addr = ifp->state->addr.s_addr;
+                       rt->src.s_addr = state->addr.s_addr;
                        /* Do we already manage it? */
                        if ((or = find_route(routes, rt, &rtl, NULL))) {
                                if (or->iface != ifp ||
-                                   or->src.s_addr != ifp->state->addr.s_addr ||
+                                   or->src.s_addr != state->addr.s_addr ||
                                    rt->gate.s_addr != or->gate.s_addr ||
                                    rt->metric != or->metric)
                                {
@@ -398,54 +400,60 @@ delete_address(struct interface *iface)
 {
        int retval;
        struct if_options *ifo;
+       struct dhcp_state *state;
 
+       state = D_STATE(iface);
        ifo = iface->options;
        if (ifo->options & DHCPCD_INFORM ||
            (ifo->options & DHCPCD_STATIC && ifo->req_addr.s_addr == 0))
                return 0;
        syslog(LOG_DEBUG, "%s: deleting IP address %s/%d",
-           iface->name,
-           inet_ntoa(iface->state->addr),
-           inet_ntocidr(iface->state->net));
-       retval = del_address(iface, &iface->state->addr, &iface->state->net);
+           iface->name, inet_ntoa(state->addr), inet_ntocidr(state->net));
+       retval = del_address(iface, &state->addr, &state->net);
        if (retval == -1 && errno != EADDRNOTAVAIL) 
                syslog(LOG_ERR, "del_address: %m");
-       iface->state->addr.s_addr = 0;
-       iface->state->net.s_addr = 0;
+       state->addr.s_addr = 0;
+       state->net.s_addr = 0;
        return retval;
 }
 
 void
 ipv4_applyaddr(void *arg)
 {
-       struct interface *iface = arg;
-       struct dhcp_message *dhcp = iface->state->new;
-       struct dhcp_lease *lease = &iface->state->lease;
-       struct if_options *ifo = iface->options;
+       struct interface *ifp = arg;
+       struct dhcp_state *state = D_STATE(ifp);
+       struct dhcp_message *dhcp;
+       struct dhcp_lease *lease;
+       struct if_options *ifo = ifp->options;
        struct rt *rt;
 
        /* As we are now adjusting an interface, we need to ensure
         * we have them in the right order for routing and configuration. */
        sort_interfaces();
 
+       if (state == NULL)
+               return;
+       dhcp = state->new;
+       lease = &state->lease;
+
        if (dhcp == NULL) {
                if (!(ifo->options & DHCPCD_PERSISTENT)) {
                        ipv4_buildroutes();
-                       if (iface->state->addr.s_addr != 0)
-                               delete_address(iface);
-                       script_run(iface);
+                       if (state->addr.s_addr != 0)
+                               delete_address(ifp);
+                       script_runreason(ifp, state->reason);
                }
                return;
        }
 
        /* This also changes netmask */
        if (!(ifo->options & DHCPCD_INFORM) ||
-           !has_address(iface->name, &lease->addr, &lease->net))
+           !has_address(ifp->name, &lease->addr, &lease->net))
        {
                syslog(LOG_DEBUG, "%s: adding IP address %s/%d",
-                   iface->name, inet_ntoa(lease->addr),
+                   ifp->name, inet_ntoa(lease->addr),
                    inet_ntocidr(lease->net));
-               if (add_address(iface,
+               if (add_address(ifp,
                        &lease->addr, &lease->net, &lease->brd) == -1 &&
                    errno != EEXIST)
                {
@@ -455,18 +463,18 @@ ipv4_applyaddr(void *arg)
        }
 
        /* Now delete the old address if different */
-       if (iface->state->addr.s_addr != lease->addr.s_addr &&
-           iface->state->addr.s_addr != 0)
-               delete_address(iface);
+       if (state->addr.s_addr != lease->addr.s_addr &&
+           state->addr.s_addr != 0)
+               delete_address(ifp);
 
-       iface->state->addr.s_addr = lease->addr.s_addr;
-       iface->state->net.s_addr = lease->net.s_addr;
+       state->addr.s_addr = lease->addr.s_addr;
+       state->net.s_addr = lease->net.s_addr;
 
        /* We need to delete the subnet route to have our metric or
         * prefer the interface. */
        rt = get_subnet_route(dhcp);
        if (rt != NULL) {
-               rt->iface = iface;
+               rt->iface = ifp;
                rt->metric = 0;
                if (!find_route(routes, rt, NULL, NULL))
                        del_route(rt);
@@ -474,11 +482,11 @@ ipv4_applyaddr(void *arg)
        }
 
        ipv4_buildroutes();
-       if (!iface->state->lease.frominfo &&
+       if (!state->lease.frominfo &&
            !(ifo->options & (DHCPCD_INFORM | DHCPCD_STATIC)))
-               if (write_lease(iface, dhcp) == -1)
+               if (write_lease(ifp, dhcp) == -1)
                        syslog(LOG_ERR, "%s: write_lease: %m", __func__);
-       script_run(iface);
+       script_runreason(ifp, state->reason);
 }
 
 void
@@ -487,6 +495,7 @@ ipv4_handleifa(int type, const char *ifname,
 {
        struct interface *ifp;
        struct if_options *ifo;
+       struct dhcp_state *state;
        int i;
 
        if (addr->s_addr == INADDR_ANY)
@@ -497,12 +506,13 @@ ipv4_handleifa(int type, const char *ifname,
        if (ifp == NULL)
                return;
 
+       state = D_STATE(ifp);
        if (type == RTM_DELADDR) {
-               if (ifp->state->new &&
-                   ifp->state->new->yiaddr == addr->s_addr)
+               if (state->new &&
+                   state->new->yiaddr == addr->s_addr)
                        syslog(LOG_INFO, "%s: removing IP address %s/%d",
-                           ifp->name, inet_ntoa(ifp->state->lease.addr),
-                           inet_ntocidr(ifp->state->lease.net));
+                           ifp->name, inet_ntoa(state->lease.addr),
+                           inet_ntocidr(state->lease.net));
                return;
        }
 
@@ -514,25 +524,24 @@ ipv4_handleifa(int type, const char *ifname,
            ifo->req_addr.s_addr != INADDR_ANY)
                return;
 
-       free(ifp->state->old);
-       ifp->state->old = ifp->state->new;
-       ifp->state->new = dhcp_message_new(addr, net);
-       ifp->state->dst.s_addr = dst ? dst->s_addr : INADDR_ANY;
+       free(state->old);
+       state->old = state->new;
+       state->new = dhcp_message_new(addr, net);
+       state->dst.s_addr = dst ? dst->s_addr : INADDR_ANY;
        if (dst) {
                for (i = 1; i < 255; i++)
                        if (i != DHO_ROUTER && has_option_mask(ifo->dstmask,i))
-                               dhcp_message_add_addr(ifp->state->new, i, *dst);
+                               dhcp_message_add_addr(state->new, i, *dst);
        }
-       ifp->state->reason = "STATIC";
+       state->reason = "STATIC";
        ipv4_buildroutes();
-       script_run(ifp);
+       script_runreason(ifp, state->reason);
        if (ifo->options & DHCPCD_INFORM) {
-               ifp->state->state = DHS_INFORM;
-               ifp->state->xid = dhcp_xid(ifp);
-               ifp->state->lease.server.s_addr =
-                   dst ? dst->s_addr : INADDR_ANY;
-               ifp->state->addr = *addr;
-               ifp->state->net = *net;
+               state->state = DHS_INFORM;
+               state->xid = dhcp_xid(ifp);
+               state->lease.server.s_addr = dst ? dst->s_addr : INADDR_ANY;
+               state->addr = *addr;
+               state->net = *net;
                dhcp_inform(ifp);
        }
 }
index a12147564a568fa3b3c4b95c92a3ecf6d550172f..970293f225df0e9a3d768f2a3cd8de328707eeb1 100644 (file)
--- a/ipv4ll.c
+++ b/ipv4ll.c
@@ -34,7 +34,7 @@
 
 #include "arp.h"
 #include "common.h"
-#include "dhcpcd.h"
+#include "dhcp.h"
 #include "eloop.h"
 #include "if-options.h"
 #include "ipv4ll.h"
@@ -86,24 +86,25 @@ void
 ipv4ll_start(void *arg)
 {
        struct interface *ifp = arg;
+       struct dhcp_state *state = D_STATE(ifp);
        uint32_t addr;
 
        eloop_timeout_delete(NULL, ifp);
-       ifp->state->probes = 0;
-       ifp->state->claims = 0;
-       if (ifp->state->addr.s_addr) {
-               ifp->state->conflicts = 0;
-               if (IN_LINKLOCAL(htonl(ifp->state->addr.s_addr))) {
+       state->probes = 0;
+       state->claims = 0;
+       if (state->addr.s_addr) {
+               state->conflicts = 0;
+               if (IN_LINKLOCAL(htonl(state->addr.s_addr))) {
                        arp_announce(ifp);
                        return;
                }
        }
 
-       if (ifp->state->offer == NULL)
+       if (state->offer == NULL)
                addr = 0;
        else {
-               addr = ifp->state->offer->yiaddr;
-               free(ifp->state->offer);
+               addr = state->offer->yiaddr;
+               free(state->offer);
        }
        /* We maybe rebooting an IPv4LL address. */
        if (!IN_LINKLOCAL(htonl(addr))) {
@@ -112,10 +113,10 @@ ipv4ll_start(void *arg)
                addr = 0;
        }
        if (addr == 0)
-               ifp->state->offer = ipv4ll_find_lease(addr);
+               state->offer = ipv4ll_find_lease(addr);
        else
-               ifp->state->offer = ipv4ll_make_lease(addr);
-       ifp->state->lease.frominfo = 0;
+               state->offer = ipv4ll_make_lease(addr);
+       state->lease.frominfo = 0;
        arp_probe(ifp);
 }
 
@@ -123,32 +124,33 @@ void
 ipv4ll_handle_failure(void *arg)
 {
        struct interface *ifp = arg;
+       struct dhcp_state *state = D_STATE(ifp);
        time_t up;
 
-       if (ifp->state->fail.s_addr == ifp->state->addr.s_addr) {
+       if (state->fail.s_addr == state->addr.s_addr) {
                up = uptime();
-               if (ifp->state->defend + DEFEND_INTERVAL > up) {
+               if (state->defend + DEFEND_INTERVAL > up) {
                        syslog(LOG_DEBUG,
                            "%s: IPv4LL %d second defence failed",
                            ifp->name, DEFEND_INTERVAL);
                        dhcp_drop(ifp, "EXPIRE");
-                       ifp->state->conflicts = -1;
+                       state->conflicts = -1;
                } else {
                        syslog(LOG_DEBUG, "%s: defended IPv4LL address",
                            ifp->name);
-                       ifp->state->defend = up;
+                       state->defend = up;
                        return;
                }
        }
 
        dhcp_close(ifp);
-       free(ifp->state->offer);
-       ifp->state->offer = NULL;
+       free(state->offer);
+       state->offer = NULL;
        eloop_timeout_delete(NULL, ifp);
-       if (++ifp->state->conflicts > MAX_CONFLICTS) {
+       if (++state->conflicts > MAX_CONFLICTS) {
                syslog(LOG_ERR, "%s: failed to acquire an IPv4LL address",
                    ifp->name);
-               ifp->state->interval = RATE_LIMIT_INTERVAL / 2;
+               state->interval = RATE_LIMIT_INTERVAL / 2;
                dhcp_discover(ifp);
        } else {
                eloop_timeout_add_sec(PROBE_WAIT, ipv4ll_start, ifp);
diff --git a/lpf.c b/lpf.c
index e313cf37bf5ef3b16e0edbe3e217428a8fc5e8d2..4c98ade9d71e20073a06155d81e5866f853d4dd5 100644 (file)
--- a/lpf.c
+++ b/lpf.c
@@ -65,7 +65,7 @@ static const uint8_t ipv4_bcast_addr[] = {
 };
 
 int
-open_socket(struct interface *iface, int protocol)
+open_socket(struct interface *ifp, int protocol)
 {
        int s;
        union sockunion {
@@ -76,6 +76,7 @@ open_socket(struct interface *iface, int protocol)
        } su;
        struct sock_fprog pf;
        int *fd;
+       struct dhcp_state *state;
 #ifdef PACKET_AUXDATA
        int n;
 #endif
@@ -86,7 +87,7 @@ open_socket(struct interface *iface, int protocol)
        memset(&su, 0, sizeof(su));
        su.sll.sll_family = PF_PACKET;
        su.sll.sll_protocol = htons(protocol);
-       su.sll.sll_ifindex = iface->index;
+       su.sll.sll_ifindex = ifp->index;
        /* Install the DHCP filter */
        memset(&pf, 0, sizeof(pf));
        if (protocol == ETHERTYPE_ARP) {
@@ -111,10 +112,11 @@ open_socket(struct interface *iface, int protocol)
                goto eexit;
        if (bind(s, &su.sa, sizeof(su)) == -1)
                goto eexit;
+       state = D_STATE(ifp);
        if (protocol == ETHERTYPE_ARP)
-               fd = &iface->state->arp_fd;
+               fd = &state->arp_fd;
        else
-               fd = &iface->state->raw_fd;
+               fd = &state->raw_fd;
        if (*fd != -1)
                close(*fd);
        *fd = s;
@@ -126,9 +128,10 @@ eexit:
 }
 
 ssize_t
-send_raw_packet(const struct interface *iface, int protocol,
+send_raw_packet(const struct interface *ifp, int protocol,
     const void *data, ssize_t len)
 {
+       const struct dhcp_state *state;
        union sockunion {
                struct sockaddr sa;
                struct sockaddr_ll sll;
@@ -139,24 +142,25 @@ send_raw_packet(const struct interface *iface, int protocol,
        memset(&su, 0, sizeof(su));
        su.sll.sll_family = AF_PACKET;
        su.sll.sll_protocol = htons(protocol);
-       su.sll.sll_ifindex = iface->index;
-       su.sll.sll_hatype = htons(iface->family);
-       su.sll.sll_halen = iface->hwlen;
-       if (iface->family == ARPHRD_INFINIBAND)
+       su.sll.sll_ifindex = ifp->index;
+       su.sll.sll_hatype = htons(ifp->family);
+       su.sll.sll_halen = ifp->hwlen;
+       if (ifp->family == ARPHRD_INFINIBAND)
                memcpy(&su.sll.sll_addr,
                    &ipv4_bcast_addr, sizeof(ipv4_bcast_addr));
        else
-               memset(&su.sll.sll_addr, 0xff, iface->hwlen);
+               memset(&su.sll.sll_addr, 0xff, ifp->hwlen);
+       state = D_CSTATE(ifp);
        if (protocol == ETHERTYPE_ARP)
-               fd = iface->state->arp_fd;
+               fd = state->arp_fd;
        else
-               fd = iface->state->raw_fd;
+               fd = state->raw_fd;
 
        return sendto(fd, data, len, 0, &su.sa, sizeof(su));
 }
 
 ssize_t
-get_raw_packet(struct interface *iface, int protocol,
+get_raw_packet(struct interface *ifp, int protocol,
     void *data, ssize_t len, int *partialcsum)
 {
        struct iovec iov = {
@@ -167,6 +171,7 @@ get_raw_packet(struct interface *iface, int protocol,
                .msg_iov = &iov,
                .msg_iovlen = 1,
        };
+       struct dhcp_state *state;
 #ifdef PACKET_AUXDATA
        unsigned char cmsgbuf[CMSG_LEN(sizeof(struct tpacket_auxdata))];
        struct cmsghdr *cmsg;
@@ -181,10 +186,11 @@ get_raw_packet(struct interface *iface, int protocol,
        msg.msg_controllen = sizeof(cmsgbuf);
 #endif
 
+       state = D_STATE(ifp);
        if (protocol == ETHERTYPE_ARP)
-               fd = iface->state->arp_fd;
+               fd = state->arp_fd;
        else
-               fd = iface->state->raw_fd;
+               fd = state->raw_fd;
        bytes = recvmsg(fd, &msg, 0);
        if (bytes == -1)
                return errno == EAGAIN ? 0 : -1;
diff --git a/net.c b/net.c
index 7379ea2386710b0cb943a0aa759f463580e6842d..11662a2b94f71f07625692fb19b4f35d19ef4e68 100644 (file)
--- a/net.c
+++ b/net.c
@@ -189,17 +189,10 @@ free_interface(struct interface *ifp)
 
        if (ifp == NULL)
                return;
+       dhcp_free(ifp);
        dhcp6_free(ifp);
        ipv6rs_free(ifp);
        free_options(ifp->options);
-       if (ifp->state) {
-               free(ifp->state->old);
-               free(ifp->state->new);
-               free(ifp->state->offer);
-               free(ifp->state->buffer);
-               free(ifp->state->clientid);
-               free(ifp->state);
-       }
        free(ifp);
 }
 
@@ -572,6 +565,7 @@ open_udp_socket(struct interface *iface)
        int s;
        struct sockaddr_in sin;
        int n;
+       struct dhcp_state *state;
 #ifdef SO_BINDTODEVICE
        struct ifreq ifr;
        char *p;
@@ -599,14 +593,15 @@ open_udp_socket(struct interface *iface)
        n = 1;
        if (setsockopt(s, SOL_SOCKET, SO_RCVBUF, &n, sizeof(n)) == -1)
                goto eexit;
+       state = D_STATE(iface);
        memset(&sin, 0, sizeof(sin));
        sin.sin_family = AF_INET;
        sin.sin_port = htons(DHCP_CLIENT_PORT);
-       sin.sin_addr.s_addr = iface->state->addr.s_addr;
+       sin.sin_addr.s_addr = state->addr.s_addr;
        if (bind(s, (struct sockaddr *)&sin, sizeof(sin)) == -1)
                goto eexit;
 
-       iface->state->udp_fd = s;
+       state->udp_fd = s;
        set_cloexec(s);
        return 0;
 
@@ -625,7 +620,7 @@ send_packet(const struct interface *iface, struct in_addr to,
        sin.sin_family = AF_INET;
        sin.sin_addr.s_addr = to.s_addr;
        sin.sin_port = htons(DHCP_SERVER_PORT);
-       return sendto(iface->state->udp_fd, data, len, 0,
+       return sendto(D_CSTATE(iface)->udp_fd, data, len, 0,
            (struct sockaddr *)&sin, sizeof(sin));
 }
 
index cf286e1d847c65e2bbb00d85af9662b1e9d85445..895c19640fd1e64ef18690323f19c2412721bb36 100644 (file)
--- a/script.c
+++ b/script.c
@@ -182,10 +182,12 @@ make_env(const struct interface *ifp, const char *reason, char ***argv)
        const struct if_options *ifo = ifp->options;
        const struct interface *ifp2;
        int dhcp, dhcp6, ra;
+       const struct dhcp_state *state;
        const struct dhcp6_state *d6_state;
 
        dhcp = dhcp6 = ra = 0;
-       d6_state = D6_STATE(ifp);
+       state = D_STATE(ifp);
+       d6_state = D6_CSTATE(ifp);
        if (strcmp(reason, "TEST") == 0) {
                if (d6_state && d6_state->new)
                        dhcp6 = 1;
@@ -247,8 +249,8 @@ make_env(const struct interface *ifp, const char *reason, char ***argv)
        if (strcmp(reason, "TEST") == 0) {
                env[8] = strdup("if_up=false");
                env[9] = strdup("if_down=false");
-       } else if ((dhcp && ifp->state->new) ||
-           (dhcp6 && d6_state->new) ||
+       } else if ((dhcp && state && state->new) ||
+           (dhcp6 && d6_state && d6_state->new) ||
            (ra && ipv6rs_has_ra(ifp)))
        {
                env[8] = strdup("if_up=true");
@@ -257,39 +259,35 @@ make_env(const struct interface *ifp, const char *reason, char ***argv)
                env[8] = strdup("if_up=false");
                env[9] = strdup("if_down=true");
        }
-       if (*ifp->state->profile) {
-               e = strlen("profile=") + strlen(ifp->state->profile) + 2;
+       if (*ifp->profile) {
+               e = strlen("profile=") + strlen(ifp->profile) + 2;
                env[elen] = xmalloc(e);
-               snprintf(env[elen++], e, "profile=%s", ifp->state->profile);
+               snprintf(env[elen++], e, "profile=%s", ifp->profile);
        }
        if (ifp->wireless) {
                e = strlen("new_ssid=") + strlen(ifp->ssid) + 2;
-               if (ifp->state->new != NULL ||
-                   strcmp(ifp->state->reason, "CARRIER") == 0)
-               {
+               if (strcmp(reason, "CARRIER") == 0) {
                        env = xrealloc(env, sizeof(char *) * (elen + 2));
                        env[elen] = xmalloc(e);
                        snprintf(env[elen++], e, "new_ssid=%s", ifp->ssid);
                }
-               if (ifp->state->old != NULL ||
-                   strcmp(ifp->state->reason, "NOCARRIER") == 0)
-               {
+               else if (strcmp(reason, "NOCARRIER") == 0) {
                        env = xrealloc(env, sizeof(char *) * (elen + 2));
                        env[elen] = xmalloc(e);
                        snprintf(env[elen++], e, "old_ssid=%s", ifp->ssid);
                }
        }
-       if (dhcp && ifp->state->old) {
-               e = configure_env(NULL, NULL, ifp->state->old, ifp);
+       if (dhcp && state && state->old) {
+               e = configure_env(NULL, NULL, state->old, ifp);
                if (e > 0) {
                        env = xrealloc(env, sizeof(char *) * (elen + e + 1));
                        elen += configure_env(env + elen, "old",
-                           ifp->state->old, ifp);
+                           state->old, ifp);
                }
                append_config(&env, &elen, "old",
                    (const char *const *)ifo->config);
        }
-       if (dhcp6 && d6_state->old) {
+       if (dhcp6 && d6_state && d6_state->old) {
                e = dhcp6_env(NULL, NULL, ifp,
                    d6_state->old, d6_state->old_len);
                if (e > 0) {
@@ -300,17 +298,17 @@ make_env(const struct interface *ifp, const char *reason, char ***argv)
        }
 
 dumplease:
-       if (dhcp && ifp->state->new) {
-               e = configure_env(NULL, NULL, ifp->state->new, ifp);
+       if (dhcp && state && state->new) {
+               e = configure_env(NULL, NULL, state->new, ifp);
                if (e > 0) {
                        env = xrealloc(env, sizeof(char *) * (elen + e + 1));
                        elen += configure_env(env + elen, "new",
-                           ifp->state->new, ifp);
+                           state->new, ifp);
                }
                append_config(&env, &elen, "new",
                    (const char *const *)ifo->config);
        }
-       if (dhcp6 && d6_state->new) {
+       if (dhcp6 && d6_state && d6_state->new) {
                e = dhcp6_env(NULL, NULL, ifp,
                    d6_state->new, d6_state->new_len);
                if (e > 0) {
@@ -373,7 +371,9 @@ int
 send_interface(int fd, const struct interface *iface)
 {
        int retval = 0;
-       if (send_interface1(fd, iface, iface->state->reason) == -1)
+       const struct dhcp_state *state = D_CSTATE(iface);
+
+       if (state && send_interface1(fd, iface, state->reason) == -1)
                retval = -1;
        if (ipv6rs_has_ra(iface)) {
                if (send_interface1(fd, iface, "ROUTERADVERT") == -1)
@@ -403,8 +403,11 @@ script_runreason(const struct interface *ifp, const char *reason)
            strcmp(ifp->options->script, "/dev/null") == 0)
                return 0;
 
-       if (reason == NULL)
-               reason = ifp->state->reason;
+       if (reason == NULL) {
+               const struct dhcp_state *state = D_CSTATE(ifp);
+               if (state)
+                       reason = state->reason;
+       }
        syslog(LOG_DEBUG, "%s: executing `%s', reason %s",
            ifp->name, argv[0], reason);
 
index 50e142cc7a96ebefba2f5acc6ddd2c500cada4e7..5979355c3549f76a38d2a4ba737ee1fb9e1e28a0 100644 (file)
--- a/script.h
+++ b/script.h
@@ -34,5 +34,4 @@ void if_printoptions(void);
 int send_interface(int, const struct interface *);
 int script_runreason(const struct interface *, const char *);
 
-#define script_run(ifp) script_runreason(ifp, (ifp)->state->reason);
 #endif