]> git.ipfire.org Git - thirdparty/systemd.git/blobdiff - src/libsystemd-network/sd-dhcp6-lease.c
tree-wide: use mfree more
[thirdparty/systemd.git] / src / libsystemd-network / sd-dhcp6-lease.c
index 78e15892864fa953afdad9e9a2e56d68e1e9ad99..ab59977a3f914cb14e6c1f82ba2f831930e5b300 100644 (file)
@@ -2,7 +2,7 @@
   This file is part of systemd.
 
   Copyright (C) 2014 Tom Gundersen
-  Copyright (C) 2014 Intel Corporation. All rights reserved.
+  Copyright (C) 2014-2015 Intel Corporation. All rights reserved.
 
   systemd is free software; you can redistribute it and/or modify it
   under the terms of the GNU Lesser General Public License as published by
 
 #include <errno.h>
 
-#include "util.h"
-
+#include "alloc-util.h"
 #include "dhcp6-lease-internal.h"
+#include "dhcp6-protocol.h"
+#include "strv.h"
+#include "util.h"
 
 int dhcp6_lease_clear_timers(DHCP6IA *ia) {
         assert_return(ia, -EINVAL);
@@ -146,10 +148,9 @@ int dhcp6_lease_get_iaid(sd_dhcp6_lease *lease, be32_t *iaid) {
         return 0;
 }
 
-int sd_dhcp6_lease_get_next_address(sd_dhcp6_lease *lease,
-                                    struct in6_addr *addr,
-                                    uint32_t *lifetime_preferred,
-                                    uint32_t *lifetime_valid) {
+int sd_dhcp6_lease_get_address(sd_dhcp6_lease *lease, struct in6_addr *addr,
+                               uint32_t *lifetime_preferred,
+                               uint32_t *lifetime_valid) {
         assert_return(lease, -EINVAL);
         assert_return(addr, -EINVAL);
         assert_return(lifetime_preferred, -EINVAL);
@@ -169,40 +170,226 @@ int sd_dhcp6_lease_get_next_address(sd_dhcp6_lease *lease,
         return 0;
 }
 
-int sd_dhcp6_lease_get_first_address(sd_dhcp6_lease *lease,
-                                     struct in6_addr *addr,
-                                     uint32_t *lifetime_preferred,
-                                     uint32_t *lifetime_valid) {
+void sd_dhcp6_lease_reset_address_iter(sd_dhcp6_lease *lease) {
+        if (lease)
+                lease->addr_iter = lease->ia.addresses;
+}
+
+int dhcp6_lease_set_dns(sd_dhcp6_lease *lease, uint8_t *optval, size_t optlen) {
+        int r;
+
         assert_return(lease, -EINVAL);
-        assert_return(addr, -EINVAL);
-        assert_return(lifetime_preferred, -EINVAL);
-        assert_return(lifetime_valid, -EINVAL);
+        assert_return(optval, -EINVAL);
 
-        if (!lease->ia.addresses)
-                return -ENOMSG;
+        if (!optlen)
+                return 0;
+
+        r = dhcp6_option_parse_ip6addrs(optval, optlen, &lease->dns,
+                                        lease->dns_count,
+                                        &lease->dns_allocated);
+        if (r < 0) {
+                log_dhcp6_client(client, "Invalid DNS server option: %s",
+                                 strerror(-r));
+
+                return r;
+        }
+
+        lease->dns_count = r;
+
+        return 0;
+}
+
+int sd_dhcp6_lease_get_dns(sd_dhcp6_lease *lease, struct in6_addr **addrs) {
+        assert_return(lease, -EINVAL);
+        assert_return(addrs, -EINVAL);
+
+        if (lease->dns_count) {
+                *addrs = lease->dns;
+                return lease->dns_count;
+        }
 
-        lease->addr_iter = lease->ia.addresses;
+        return -ENOENT;
+}
+
+int dhcp6_lease_set_domains(sd_dhcp6_lease *lease, uint8_t *optval,
+                            size_t optlen) {
+        int r;
+        char **domains;
+
+        assert_return(lease, -EINVAL);
+        assert_return(optval, -EINVAL);
+
+        if (!optlen)
+                return 0;
+
+        r = dhcp6_option_parse_domainname(optval, optlen, &domains);
+        if (r < 0)
+                return 0;
+
+        free(lease->domains);
+        lease->domains = domains;
+        lease->domains_count = r;
+
+        return r;
+}
+
+int sd_dhcp6_lease_get_domains(sd_dhcp6_lease *lease, char ***domains) {
+        assert_return(lease, -EINVAL);
+        assert_return(domains, -EINVAL);
 
-        return sd_dhcp6_lease_get_next_address(lease, addr, lifetime_preferred,
-                                               lifetime_valid);
+        if (lease->domains_count) {
+                *domains = lease->domains;
+                return lease->domains_count;
+        }
+
+        return -ENOENT;
+}
+
+int dhcp6_lease_set_ntp(sd_dhcp6_lease *lease, uint8_t *optval, size_t optlen) {
+        int r;
+        uint16_t subopt;
+        size_t sublen;
+        uint8_t *subval;
+
+        assert_return(lease, -EINVAL);
+        assert_return(optval, -EINVAL);
+
+        lease->ntp = mfree(lease->ntp);
+        lease->ntp_count = 0;
+        lease->ntp_allocated = 0;
+
+        while ((r = dhcp6_option_parse(&optval, &optlen, &subopt, &sublen,
+                                       &subval)) >= 0) {
+                int s;
+                char **servers;
+
+                switch(subopt) {
+                case DHCP6_NTP_SUBOPTION_SRV_ADDR:
+                case DHCP6_NTP_SUBOPTION_MC_ADDR:
+                        if (sublen != 16)
+                                return 0;
+
+                        s = dhcp6_option_parse_ip6addrs(subval, sublen,
+                                                        &lease->ntp,
+                                                        lease->ntp_count,
+                                                        &lease->ntp_allocated);
+                        if (s < 0)
+                                return s;
+
+                        lease->ntp_count = s;
+
+                        break;
+
+                case DHCP6_NTP_SUBOPTION_SRV_FQDN:
+                        r = dhcp6_option_parse_domainname(subval, sublen,
+                                                          &servers);
+                        if (r < 0)
+                                return 0;
+
+                        lease->ntp_fqdn = strv_free(lease->ntp_fqdn);
+                        lease->ntp_fqdn = servers;
+                        lease->ntp_fqdn_count = r;
+
+                        break;
+                }
+        }
+
+        if (r != -ENOMSG)
+                return r;
+
+        return 0;
+}
+
+int dhcp6_lease_set_sntp(sd_dhcp6_lease *lease, uint8_t *optval, size_t optlen) {
+        int r;
+
+        assert_return(lease, -EINVAL);
+        assert_return(optval, -EINVAL);
+
+        if (!optlen)
+                return 0;
+
+        if (lease->ntp || lease->ntp_fqdn) {
+                log_dhcp6_client(client, "NTP information already provided");
+
+                return 0;
+        }
+
+        log_dhcp6_client(client, "Using deprecated SNTP information");
+
+        r = dhcp6_option_parse_ip6addrs(optval, optlen, &lease->ntp,
+                                        lease->ntp_count,
+                                        &lease->ntp_allocated);
+        if (r < 0) {
+                log_dhcp6_client(client, "Invalid SNTP server option: %s",
+                                 strerror(-r));
+
+                return r;
+        }
+
+        lease->ntp_count = r;
+
+        return 0;
+}
+
+int sd_dhcp6_lease_get_ntp_addrs(sd_dhcp6_lease *lease,
+                                 struct in6_addr **addrs) {
+        assert_return(lease, -EINVAL);
+        assert_return(addrs, -EINVAL);
+
+        if (lease->ntp_count) {
+                *addrs = lease->ntp;
+                return lease->ntp_count;
+        }
+
+        return -ENOENT;
+}
+
+int sd_dhcp6_lease_get_ntp_fqdn(sd_dhcp6_lease *lease, char ***ntp_fqdn) {
+        assert_return(lease, -EINVAL);
+        assert_return(ntp_fqdn, -EINVAL);
+
+        if (lease->ntp_fqdn_count) {
+                *ntp_fqdn = lease->ntp_fqdn;
+                return lease->ntp_fqdn_count;
+        }
+
+        return -ENOENT;
 }
 
 sd_dhcp6_lease *sd_dhcp6_lease_ref(sd_dhcp6_lease *lease) {
-        if (lease)
-                assert_se(REFCNT_INC(lease->n_ref) >= 2);
+
+        if (!lease)
+                return NULL;
+
+        assert(lease->n_ref >= 1);
+        lease->n_ref++;
 
         return lease;
 }
 
 sd_dhcp6_lease *sd_dhcp6_lease_unref(sd_dhcp6_lease *lease) {
-        if (lease && REFCNT_DEC(lease->n_ref) == 0) {
-                free(lease->serverid);
-                dhcp6_lease_free_ia(&lease->ia);
 
-                free(lease);
-        }
+        if (!lease)
+                return NULL;
 
-        return NULL;
+        assert(lease->n_ref >= 1);
+        lease->n_ref--;
+
+        if (lease->n_ref > 0)
+                return NULL;
+
+        free(lease->serverid);
+        dhcp6_lease_free_ia(&lease->ia);
+
+        free(lease->dns);
+
+        lease->domains = strv_free(lease->domains);
+
+        free(lease->ntp);
+
+        lease->ntp_fqdn = strv_free(lease->ntp_fqdn);
+        return mfree(lease);
 }
 
 int dhcp6_lease_new(sd_dhcp6_lease **ret) {
@@ -212,7 +399,7 @@ int dhcp6_lease_new(sd_dhcp6_lease **ret) {
         if (!lease)
                 return -ENOMEM;
 
-        lease->n_ref = REFCNT_INIT;
+        lease->n_ref = 1;
 
         LIST_HEAD_INIT(lease->ia.addresses);