LCOV - code coverage report
Current view: top level - libsystemd-network - sd-dhcp6-lease.c (source / functions) Hit Total Coverage
Test: main_coverage.info Lines: 119 214 55.6 %
Date: 2019-08-22 15:41:25 Functions: 17 26 65.4 %

          Line data    Source code
       1             : /* SPDX-License-Identifier: LGPL-2.1+ */
       2             : /***
       3             :   Copyright © 2014-2015 Intel Corporation. All rights reserved.
       4             : ***/
       5             : 
       6             : #include <errno.h>
       7             : 
       8             : #include "alloc-util.h"
       9             : #include "dhcp6-lease-internal.h"
      10             : #include "dhcp6-protocol.h"
      11             : #include "strv.h"
      12             : #include "util.h"
      13             : 
      14           0 : int dhcp6_lease_ia_rebind_expire(const DHCP6IA *ia, uint32_t *expire) {
      15             :         DHCP6Address *addr;
      16           0 :         uint32_t valid = 0, t;
      17             : 
      18           0 :         assert_return(ia, -EINVAL);
      19           0 :         assert_return(expire, -EINVAL);
      20             : 
      21           0 :         LIST_FOREACH(addresses, addr, ia->addresses) {
      22           0 :                 t = be32toh(addr->iaaddr.lifetime_valid);
      23           0 :                 if (valid < t)
      24           0 :                         valid = t;
      25             :         }
      26             : 
      27           0 :         t = be32toh(ia->ia_na.lifetime_t2);
      28           0 :         if (t > valid)
      29           0 :                 return -EINVAL;
      30             : 
      31           0 :         *expire = valid - t;
      32             : 
      33           0 :         return 0;
      34             : }
      35             : 
      36          15 : DHCP6IA *dhcp6_lease_free_ia(DHCP6IA *ia) {
      37             :         DHCP6Address *address;
      38             : 
      39          15 :         if (!ia)
      40           0 :                 return NULL;
      41             : 
      42          23 :         while (ia->addresses) {
      43           8 :                 address = ia->addresses;
      44             : 
      45           8 :                 LIST_REMOVE(addresses, ia->addresses, address);
      46             : 
      47           8 :                 free(address);
      48             :         }
      49             : 
      50          15 :         return NULL;
      51             : }
      52             : 
      53           4 : int dhcp6_lease_set_serverid(sd_dhcp6_lease *lease, const uint8_t *id,
      54             :                              size_t len) {
      55             :         uint8_t *serverid;
      56             : 
      57           4 :         assert_return(lease, -EINVAL);
      58           4 :         assert_return(id, -EINVAL);
      59             : 
      60           4 :         serverid = memdup(id, len);
      61           4 :         if (!serverid)
      62           0 :                 return -ENOMEM;
      63             : 
      64           4 :         free_and_replace(lease->serverid, serverid);
      65           4 :         lease->serverid_len = len;
      66             : 
      67           4 :         return 0;
      68             : }
      69             : 
      70           6 : int dhcp6_lease_get_serverid(sd_dhcp6_lease *lease, uint8_t **id, size_t *len) {
      71           6 :         assert_return(lease, -EINVAL);
      72             : 
      73           6 :         if (!lease->serverid)
      74           3 :                 return -ENOMSG;
      75             : 
      76           3 :         if (id)
      77           1 :                 *id = lease->serverid;
      78           3 :         if (len)
      79           1 :                 *len = lease->serverid_len;
      80             : 
      81           3 :         return 0;
      82             : }
      83             : 
      84           2 : int dhcp6_lease_set_preference(sd_dhcp6_lease *lease, uint8_t preference) {
      85           2 :         assert_return(lease, -EINVAL);
      86             : 
      87           2 :         lease->preference = preference;
      88             : 
      89           2 :         return 0;
      90             : }
      91             : 
      92           3 : int dhcp6_lease_get_preference(sd_dhcp6_lease *lease, uint8_t *preference) {
      93           3 :         assert_return(preference, -EINVAL);
      94             : 
      95           3 :         if (!lease)
      96           1 :                 return -EINVAL;
      97             : 
      98           2 :         *preference = lease->preference;
      99             : 
     100           2 :         return 0;
     101             : }
     102             : 
     103           0 : int dhcp6_lease_set_rapid_commit(sd_dhcp6_lease *lease) {
     104           0 :         assert_return(lease, -EINVAL);
     105             : 
     106           0 :         lease->rapid_commit = true;
     107             : 
     108           0 :         return 0;
     109             : }
     110             : 
     111           0 : int dhcp6_lease_get_rapid_commit(sd_dhcp6_lease *lease, bool *rapid_commit) {
     112           0 :         assert_return(lease, -EINVAL);
     113           0 :         assert_return(rapid_commit, -EINVAL);
     114             : 
     115           0 :         *rapid_commit = lease->rapid_commit;
     116             : 
     117           0 :         return 0;
     118             : }
     119             : 
     120           2 : int dhcp6_lease_get_iaid(sd_dhcp6_lease *lease, be32_t *iaid) {
     121           2 :         assert_return(lease, -EINVAL);
     122           2 :         assert_return(iaid, -EINVAL);
     123             : 
     124           2 :         *iaid = lease->ia.ia_na.id;
     125             : 
     126           2 :         return 0;
     127             : }
     128             : 
     129           0 : int dhcp6_lease_get_pd_iaid(sd_dhcp6_lease *lease, be32_t *iaid) {
     130           0 :         assert_return(lease, -EINVAL);
     131           0 :         assert_return(iaid, -EINVAL);
     132             : 
     133           0 :         *iaid = lease->pd.ia_pd.id;
     134             : 
     135           0 :         return 0;
     136             : }
     137             : 
     138           9 : int sd_dhcp6_lease_get_address(sd_dhcp6_lease *lease, struct in6_addr *addr,
     139             :                                uint32_t *lifetime_preferred,
     140             :                                uint32_t *lifetime_valid) {
     141           9 :         assert_return(lease, -EINVAL);
     142           9 :         assert_return(addr, -EINVAL);
     143           9 :         assert_return(lifetime_preferred, -EINVAL);
     144           9 :         assert_return(lifetime_valid, -EINVAL);
     145             : 
     146           9 :         if (!lease->addr_iter)
     147           5 :                 return -ENOMSG;
     148             : 
     149           4 :         memcpy(addr, &lease->addr_iter->iaaddr.address,
     150             :                 sizeof(struct in6_addr));
     151           4 :         *lifetime_preferred =
     152           4 :                 be32toh(lease->addr_iter->iaaddr.lifetime_preferred);
     153           4 :         *lifetime_valid = be32toh(lease->addr_iter->iaaddr.lifetime_valid);
     154             : 
     155           4 :         lease->addr_iter = lease->addr_iter->addresses_next;
     156             : 
     157           4 :         return 0;
     158             : }
     159             : 
     160           5 : void sd_dhcp6_lease_reset_address_iter(sd_dhcp6_lease *lease) {
     161           5 :         if (lease)
     162           5 :                 lease->addr_iter = lease->ia.addresses;
     163           5 : }
     164             : 
     165           0 : int sd_dhcp6_lease_get_pd(sd_dhcp6_lease *lease, struct in6_addr *prefix,
     166             :                           uint8_t *prefix_len,
     167             :                           uint32_t *lifetime_preferred,
     168             :                           uint32_t *lifetime_valid) {
     169           0 :         assert_return(lease, -EINVAL);
     170           0 :         assert_return(prefix, -EINVAL);
     171           0 :         assert_return(prefix_len, -EINVAL);
     172           0 :         assert_return(lifetime_preferred, -EINVAL);
     173           0 :         assert_return(lifetime_valid, -EINVAL);
     174             : 
     175           0 :         if (!lease->prefix_iter)
     176           0 :                 return -ENOMSG;
     177             : 
     178           0 :         memcpy(prefix, &lease->prefix_iter->iapdprefix.address,
     179             :                sizeof(struct in6_addr));
     180           0 :         *prefix_len = lease->prefix_iter->iapdprefix.prefixlen;
     181           0 :         *lifetime_preferred =
     182           0 :                 be32toh(lease->prefix_iter->iapdprefix.lifetime_preferred);
     183           0 :         *lifetime_valid =
     184           0 :                 be32toh(lease->prefix_iter->iapdprefix.lifetime_valid);
     185             : 
     186           0 :         lease->prefix_iter = lease->prefix_iter->addresses_next;
     187             : 
     188           0 :         return 0;
     189             : }
     190             : 
     191           0 : void sd_dhcp6_lease_reset_pd_prefix_iter(sd_dhcp6_lease *lease) {
     192           0 :         if (lease)
     193           0 :                 lease->prefix_iter = lease->pd.addresses;
     194           0 : }
     195             : 
     196           4 : int dhcp6_lease_set_dns(sd_dhcp6_lease *lease, uint8_t *optval, size_t optlen) {
     197             :         int r;
     198             : 
     199           4 :         assert_return(lease, -EINVAL);
     200           4 :         assert_return(optval, -EINVAL);
     201             : 
     202           4 :         if (!optlen)
     203           0 :                 return 0;
     204             : 
     205           4 :         r = dhcp6_option_parse_ip6addrs(optval, optlen, &lease->dns,
     206             :                                         lease->dns_count,
     207             :                                         &lease->dns_allocated);
     208           4 :         if (r < 0)
     209           0 :                 return log_dhcp6_client_errno(client, r, "Invalid DNS server option: %m");
     210             : 
     211           4 :         lease->dns_count = r;
     212             : 
     213           4 :         return 0;
     214             : }
     215             : 
     216           3 : int sd_dhcp6_lease_get_dns(sd_dhcp6_lease *lease, struct in6_addr **addrs) {
     217           3 :         assert_return(lease, -EINVAL);
     218           3 :         assert_return(addrs, -EINVAL);
     219             : 
     220           3 :         if (lease->dns_count) {
     221           3 :                 *addrs = lease->dns;
     222           3 :                 return lease->dns_count;
     223             :         }
     224             : 
     225           0 :         return -ENOENT;
     226             : }
     227             : 
     228           4 : int dhcp6_lease_set_domains(sd_dhcp6_lease *lease, uint8_t *optval,
     229             :                             size_t optlen) {
     230             :         int r;
     231             :         char **domains;
     232             : 
     233           4 :         assert_return(lease, -EINVAL);
     234           4 :         assert_return(optval, -EINVAL);
     235             : 
     236           4 :         if (!optlen)
     237           0 :                 return 0;
     238             : 
     239           4 :         r = dhcp6_option_parse_domainname(optval, optlen, &domains);
     240           4 :         if (r < 0)
     241           0 :                 return 0;
     242             : 
     243           4 :         strv_free_and_replace(lease->domains, domains);
     244           4 :         lease->domains_count = r;
     245             : 
     246           4 :         return r;
     247             : }
     248             : 
     249           3 : int sd_dhcp6_lease_get_domains(sd_dhcp6_lease *lease, char ***domains) {
     250           3 :         assert_return(lease, -EINVAL);
     251           3 :         assert_return(domains, -EINVAL);
     252             : 
     253           3 :         if (lease->domains_count) {
     254           3 :                 *domains = lease->domains;
     255           3 :                 return lease->domains_count;
     256             :         }
     257             : 
     258           0 :         return -ENOENT;
     259             : }
     260             : 
     261           0 : int dhcp6_lease_set_ntp(sd_dhcp6_lease *lease, uint8_t *optval, size_t optlen) {
     262             :         int r;
     263             :         uint16_t subopt;
     264             :         size_t sublen;
     265             :         uint8_t *subval;
     266             : 
     267           0 :         assert_return(lease, -EINVAL);
     268           0 :         assert_return(optval, -EINVAL);
     269             : 
     270           0 :         lease->ntp = mfree(lease->ntp);
     271           0 :         lease->ntp_count = 0;
     272           0 :         lease->ntp_allocated = 0;
     273             : 
     274           0 :         while ((r = dhcp6_option_parse(&optval, &optlen, &subopt, &sublen,
     275             :                                        &subval)) >= 0) {
     276             :                 int s;
     277             :                 char **servers;
     278             : 
     279           0 :                 switch(subopt) {
     280           0 :                 case DHCP6_NTP_SUBOPTION_SRV_ADDR:
     281             :                 case DHCP6_NTP_SUBOPTION_MC_ADDR:
     282           0 :                         if (sublen != 16)
     283           0 :                                 return 0;
     284             : 
     285           0 :                         s = dhcp6_option_parse_ip6addrs(subval, sublen,
     286             :                                                         &lease->ntp,
     287             :                                                         lease->ntp_count,
     288             :                                                         &lease->ntp_allocated);
     289           0 :                         if (s < 0)
     290           0 :                                 return s;
     291             : 
     292           0 :                         lease->ntp_count = s;
     293             : 
     294           0 :                         break;
     295             : 
     296           0 :                 case DHCP6_NTP_SUBOPTION_SRV_FQDN:
     297           0 :                         r = dhcp6_option_parse_domainname(subval, sublen,
     298             :                                                           &servers);
     299           0 :                         if (r < 0)
     300           0 :                                 return 0;
     301             : 
     302           0 :                         strv_free_and_replace(lease->ntp_fqdn, servers);
     303           0 :                         lease->ntp_fqdn_count = r;
     304             : 
     305           0 :                         break;
     306             :                 }
     307           0 :         }
     308             : 
     309           0 :         if (r != -ENOMSG)
     310           0 :                 return r;
     311             : 
     312           0 :         return 0;
     313             : }
     314             : 
     315           4 : int dhcp6_lease_set_sntp(sd_dhcp6_lease *lease, uint8_t *optval, size_t optlen) {
     316             :         int r;
     317             : 
     318           4 :         assert_return(lease, -EINVAL);
     319           4 :         assert_return(optval, -EINVAL);
     320             : 
     321           4 :         if (!optlen)
     322           0 :                 return 0;
     323             : 
     324           4 :         if (lease->ntp || lease->ntp_fqdn) {
     325           0 :                 log_dhcp6_client(client, "NTP information already provided");
     326             : 
     327           0 :                 return 0;
     328             :         }
     329             : 
     330           4 :         log_dhcp6_client(client, "Using deprecated SNTP information");
     331             : 
     332           4 :         r = dhcp6_option_parse_ip6addrs(optval, optlen, &lease->ntp,
     333             :                                         lease->ntp_count,
     334             :                                         &lease->ntp_allocated);
     335           4 :         if (r < 0)
     336           0 :                 return log_dhcp6_client_errno(client, r, "Invalid SNTP server option: %m");
     337             : 
     338           4 :         lease->ntp_count = r;
     339             : 
     340           4 :         return 0;
     341             : }
     342             : 
     343           3 : int sd_dhcp6_lease_get_ntp_addrs(sd_dhcp6_lease *lease,
     344             :                                  struct in6_addr **addrs) {
     345           3 :         assert_return(lease, -EINVAL);
     346           3 :         assert_return(addrs, -EINVAL);
     347             : 
     348           3 :         if (lease->ntp_count) {
     349           3 :                 *addrs = lease->ntp;
     350           3 :                 return lease->ntp_count;
     351             :         }
     352             : 
     353           0 :         return -ENOENT;
     354             : }
     355             : 
     356           0 : int sd_dhcp6_lease_get_ntp_fqdn(sd_dhcp6_lease *lease, char ***ntp_fqdn) {
     357           0 :         assert_return(lease, -EINVAL);
     358           0 :         assert_return(ntp_fqdn, -EINVAL);
     359             : 
     360           0 :         if (lease->ntp_fqdn_count) {
     361           0 :                 *ntp_fqdn = lease->ntp_fqdn;
     362           0 :                 return lease->ntp_fqdn_count;
     363             :         }
     364             : 
     365           0 :         return -ENOENT;
     366             : }
     367             : 
     368           6 : static sd_dhcp6_lease *dhcp6_lease_free(sd_dhcp6_lease *lease) {
     369           6 :         assert(lease);
     370             : 
     371           6 :         free(lease->serverid);
     372           6 :         dhcp6_lease_free_ia(&lease->ia);
     373           6 :         dhcp6_lease_free_ia(&lease->pd);
     374             : 
     375           6 :         free(lease->dns);
     376             : 
     377           6 :         lease->domains = strv_free(lease->domains);
     378             : 
     379           6 :         free(lease->ntp);
     380             : 
     381           6 :         lease->ntp_fqdn = strv_free(lease->ntp_fqdn);
     382           6 :         return mfree(lease);
     383             : }
     384             : 
     385          11 : DEFINE_TRIVIAL_REF_UNREF_FUNC(sd_dhcp6_lease, sd_dhcp6_lease, dhcp6_lease_free);
     386             : 
     387           6 : int dhcp6_lease_new(sd_dhcp6_lease **ret) {
     388             :         sd_dhcp6_lease *lease;
     389             : 
     390           6 :         lease = new0(sd_dhcp6_lease, 1);
     391           6 :         if (!lease)
     392           0 :                 return -ENOMEM;
     393             : 
     394           6 :         lease->n_ref = 1;
     395             : 
     396           6 :         LIST_HEAD_INIT(lease->ia.addresses);
     397             : 
     398           6 :         *ret = lease;
     399           6 :         return 0;
     400             : }

Generated by: LCOV version 1.14