config: Create statefile dir
[project/odhcpd.git] / src / dhcpv6-ia.c
index e8b6e9f..98fb460 100644 (file)
@@ -1,5 +1,6 @@
 /**
  * Copyright (C) 2013 Steven Barth <steven@midlink.org>
+ * Copyright (C) 2016 Hans Dedecker <dedeckeh@gmail.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License v2 as published by
 #include <arpa/inet.h>
 #include <sys/timerfd.h>
 
-
+static void free_dhcpv6_assignment(struct dhcpv6_assignment *c);
 static void reconf_timer(struct uloop_timeout *event);
 static struct uloop_timeout reconf_event = {.cb = reconf_timer};
 static uint32_t serial = 0;
 static uint8_t statemd5[16];
 
-
 int dhcpv6_ia_init(void)
 {
        uloop_timeout_set(&reconf_event, 2000);
        return 0;
 }
 
-
-void free_dhcpv6_assignment(struct dhcpv6_assignment *c)
-{
-       if (c->managed_sock.fd.registered) {
-               ustream_free(&c->managed_sock.stream);
-               close(c->managed_sock.fd.fd);
-       }
-
-       if (c->head.next)
-               list_del(&c->head);
-
-       free(c->managed);
-       free(c->hostname);
-       free(c);
-}
-
-
 int setup_dhcpv6_ia_interface(struct interface *iface, bool enable)
 {
        if (!enable && iface->ia_assignments.next) {
@@ -114,6 +97,8 @@ int setup_dhcpv6_ia_interface(struct interface *iface, bool enable)
                        odhcpd_urandom(a->key, sizeof(a->key));
                        memcpy(a->clid_data, lease->duid, lease->duid_len);
                        memcpy(a->mac, lease->mac.ether_addr_octet, sizeof(a->mac));
+                       /* Static assignment */
+                       a->flags |= OAF_STATIC;
                        /* Infinite valid */
                        a->valid_until = 0;
 
@@ -134,15 +119,27 @@ int setup_dhcpv6_ia_interface(struct interface *iface, bool enable)
                                        free(a->hostname);
                                        a->hostname = strdup(lease->hostname);
                                }
-                       } else {
-                               free(a->hostname);
-                               free(a);
-                       }
+                       } else
+                               free_dhcpv6_assignment(a);
                }
        }
        return 0;
 }
 
+static void free_dhcpv6_assignment(struct dhcpv6_assignment *c)
+{
+       if (c->managed_sock.fd.registered) {
+               ustream_free(&c->managed_sock.stream);
+               close(c->managed_sock.fd.fd);
+       }
+
+       if (c->head.next)
+               list_del(&c->head);
+
+       free(c->managed);
+       free(c->hostname);
+       free(c);
+}
 
 static int send_reconf(struct interface *iface, struct dhcpv6_assignment *assign)
 {
@@ -207,7 +204,6 @@ static int send_reconf(struct interface *iface, struct dhcpv6_assignment *assign
        return odhcpd_send(iface->dhcpv6_event.uloop.fd, &assign->peer, &iov, 1, iface);
 }
 
-
 void dhcpv6_write_statefile(void)
 {
        md5_ctx_t md5;
@@ -322,7 +318,7 @@ void dhcpv6_write_statefile(void)
                                        struct in_addr addr = {htonl(c->addr)};
                                        inet_ntop(AF_INET, &addr, ipbuf, sizeof(ipbuf) - 1);
 
-                                       if (c->hostname[0]) {
+                                       if (c->hostname) {
                                                fputs(ipbuf, fp);
 
                                                char b[256];
@@ -375,7 +371,6 @@ static void apply_lease(struct interface *iface, struct dhcpv6_assignment *a, bo
        }
 }
 
-
 // More data was received from TCP connection
 static void managed_handle_pd_data(struct ustream *s, _unused int bytes_new)
 {
@@ -457,8 +452,6 @@ static void managed_handle_pd_done(struct ustream *s)
                c->reconf_cnt = 1;
 }
 
-
-
 static bool assign_pd(struct interface *iface, struct dhcpv6_assignment *assign)
 {
        struct dhcpv6_assignment *c;
@@ -532,7 +525,6 @@ static bool assign_pd(struct interface *iface, struct dhcpv6_assignment *assign)
        return false;
 }
 
-
 static bool assign_na(struct interface *iface, struct dhcpv6_assignment *assign)
 {
        // Seed RNG with checksum of DUID
@@ -634,7 +626,6 @@ void dhcpv6_ia_postupdate(struct interface *iface, time_t now)
        dhcpv6_write_statefile();
 }
 
-
 static void reconf_timer(struct uloop_timeout *event)
 {
        time_t now = odhcpd_time();
@@ -662,7 +653,6 @@ static void reconf_timer(struct uloop_timeout *event)
        uloop_timeout_set(event, 2000);
 }
 
-
 static size_t append_reply(uint8_t *buf, size_t buflen, uint16_t status,
                const struct dhcpv6_ia_hdr *ia, struct dhcpv6_assignment *a,
                struct interface *iface, bool request)
@@ -867,7 +857,6 @@ static size_t append_reply(uint8_t *buf, size_t buflen, uint16_t status,
        return datalen;
 }
 
-
 static void dhcpv6_log(uint8_t msgtype, struct interface *iface, time_t now,
                const char *duidbuf, bool is_pd, struct dhcpv6_assignment *a, int code)
 {
@@ -947,8 +936,6 @@ static void dhcpv6_log(uint8_t msgtype, struct interface *iface, time_t now,
                        duidbuf, iface->ifname, status, leasebuf);
 }
 
-
-
 ssize_t dhcpv6_handle_ia(uint8_t *buf, size_t buflen, struct interface *iface,
                const struct sockaddr_in6 *addr, const void *data, const uint8_t *end)
 {
@@ -1130,7 +1117,7 @@ ssize_t dhcpv6_handle_ia(uint8_t *buf, size_t buflen, struct interface *iface,
                        if (assigned && hdr->msg_type == DHCPV6_MSG_SOLICIT) {
                                a->flags &= ~OAF_BOUND;
 
-                               if (!INFINITE_VALID(a->valid_until))
+                               if (!(a->flags & OAF_STATIC))
                                        a->valid_until = now;
                        } else if (assigned && hdr->msg_type == DHCPV6_MSG_REQUEST) {
                                if (hostname_len > 0) {
@@ -1161,7 +1148,7 @@ ssize_t dhcpv6_handle_ia(uint8_t *buf, size_t buflen, struct interface *iface,
                                        apply_lease(iface, a, true);
                                }
                        } else if (hdr->msg_type == DHCPV6_MSG_RELEASE) {
-                               if (!INFINITE_VALID(a->valid_until))
+                               if (!(a->flags & OAF_STATIC))
                                        a->valid_until = now - 1;
 
                                a->flags &= ~OAF_BOUND;
@@ -1169,7 +1156,7 @@ ssize_t dhcpv6_handle_ia(uint8_t *buf, size_t buflen, struct interface *iface,
                        } else if (hdr->msg_type == DHCPV6_MSG_DECLINE && a->length == 128) {
                                a->flags &= ~OAF_BOUND;
 
-                               if (!INFINITE_VALID(a->valid_until)) {
+                               if (!(a->flags & OAF_STATIC)) {
                                        a->clid_len = 0;
                                        a->valid_until = now + 3600; // Block address for 1h
                                }