LCOV - code coverage report
Current view: top level - libsystemd-network - sd-dhcp6-lease.c (source / functions) Hit Total Coverage
Test: systemd_full.info Lines: 119 214 55.6 %
Date: 2019-08-23 13:36:53 Functions: 17 26 65.4 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 83 239 34.7 %

           Branch data     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                 :         60 : DHCP6IA *dhcp6_lease_free_ia(DHCP6IA *ia) {
      37                 :            :         DHCP6Address *address;
      38                 :            : 
      39         [ -  + ]:         60 :         if (!ia)
      40                 :          0 :                 return NULL;
      41                 :            : 
      42         [ +  + ]:         92 :         while (ia->addresses) {
      43                 :         32 :                 address = ia->addresses;
      44                 :            : 
      45   [ -  +  +  +  :         32 :                 LIST_REMOVE(addresses, ia->addresses, address);
             -  +  -  + ]
      46                 :            : 
      47                 :         32 :                 free(address);
      48                 :            :         }
      49                 :            : 
      50                 :         60 :         return NULL;
      51                 :            : }
      52                 :            : 
      53                 :         16 : int dhcp6_lease_set_serverid(sd_dhcp6_lease *lease, const uint8_t *id,
      54                 :            :                              size_t len) {
      55                 :            :         uint8_t *serverid;
      56                 :            : 
      57   [ -  +  -  + ]:         16 :         assert_return(lease, -EINVAL);
      58   [ -  +  -  + ]:         16 :         assert_return(id, -EINVAL);
      59                 :            : 
      60                 :         16 :         serverid = memdup(id, len);
      61         [ -  + ]:         16 :         if (!serverid)
      62                 :          0 :                 return -ENOMEM;
      63                 :            : 
      64                 :         16 :         free_and_replace(lease->serverid, serverid);
      65                 :         16 :         lease->serverid_len = len;
      66                 :            : 
      67                 :         16 :         return 0;
      68                 :            : }
      69                 :            : 
      70                 :         24 : int dhcp6_lease_get_serverid(sd_dhcp6_lease *lease, uint8_t **id, size_t *len) {
      71   [ -  +  -  + ]:         24 :         assert_return(lease, -EINVAL);
      72                 :            : 
      73         [ +  + ]:         24 :         if (!lease->serverid)
      74                 :         12 :                 return -ENOMSG;
      75                 :            : 
      76         [ +  + ]:         12 :         if (id)
      77                 :          4 :                 *id = lease->serverid;
      78         [ +  + ]:         12 :         if (len)
      79                 :          4 :                 *len = lease->serverid_len;
      80                 :            : 
      81                 :         12 :         return 0;
      82                 :            : }
      83                 :            : 
      84                 :          8 : int dhcp6_lease_set_preference(sd_dhcp6_lease *lease, uint8_t preference) {
      85   [ -  +  -  + ]:          8 :         assert_return(lease, -EINVAL);
      86                 :            : 
      87                 :          8 :         lease->preference = preference;
      88                 :            : 
      89                 :          8 :         return 0;
      90                 :            : }
      91                 :            : 
      92                 :         12 : int dhcp6_lease_get_preference(sd_dhcp6_lease *lease, uint8_t *preference) {
      93   [ -  +  -  + ]:         12 :         assert_return(preference, -EINVAL);
      94                 :            : 
      95         [ +  + ]:         12 :         if (!lease)
      96                 :          4 :                 return -EINVAL;
      97                 :            : 
      98                 :          8 :         *preference = lease->preference;
      99                 :            : 
     100                 :          8 :         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                 :          8 : int dhcp6_lease_get_iaid(sd_dhcp6_lease *lease, be32_t *iaid) {
     121   [ -  +  -  + ]:          8 :         assert_return(lease, -EINVAL);
     122   [ -  +  -  + ]:          8 :         assert_return(iaid, -EINVAL);
     123                 :            : 
     124                 :          8 :         *iaid = lease->ia.ia_na.id;
     125                 :            : 
     126                 :          8 :         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                 :         36 : 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   [ -  +  -  + ]:         36 :         assert_return(lease, -EINVAL);
     142   [ -  +  -  + ]:         36 :         assert_return(addr, -EINVAL);
     143   [ -  +  -  + ]:         36 :         assert_return(lifetime_preferred, -EINVAL);
     144   [ -  +  -  + ]:         36 :         assert_return(lifetime_valid, -EINVAL);
     145                 :            : 
     146         [ +  + ]:         36 :         if (!lease->addr_iter)
     147                 :         20 :                 return -ENOMSG;
     148                 :            : 
     149                 :         16 :         memcpy(addr, &lease->addr_iter->iaaddr.address,
     150                 :            :                 sizeof(struct in6_addr));
     151                 :         16 :         *lifetime_preferred =
     152                 :         16 :                 be32toh(lease->addr_iter->iaaddr.lifetime_preferred);
     153                 :         16 :         *lifetime_valid = be32toh(lease->addr_iter->iaaddr.lifetime_valid);
     154                 :            : 
     155                 :         16 :         lease->addr_iter = lease->addr_iter->addresses_next;
     156                 :            : 
     157                 :         16 :         return 0;
     158                 :            : }
     159                 :            : 
     160                 :         20 : void sd_dhcp6_lease_reset_address_iter(sd_dhcp6_lease *lease) {
     161         [ +  - ]:         20 :         if (lease)
     162                 :         20 :                 lease->addr_iter = lease->ia.addresses;
     163                 :         20 : }
     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                 :         16 : int dhcp6_lease_set_dns(sd_dhcp6_lease *lease, uint8_t *optval, size_t optlen) {
     197                 :            :         int r;
     198                 :            : 
     199   [ -  +  -  + ]:         16 :         assert_return(lease, -EINVAL);
     200   [ -  +  -  + ]:         16 :         assert_return(optval, -EINVAL);
     201                 :            : 
     202         [ -  + ]:         16 :         if (!optlen)
     203                 :          0 :                 return 0;
     204                 :            : 
     205                 :         16 :         r = dhcp6_option_parse_ip6addrs(optval, optlen, &lease->dns,
     206                 :            :                                         lease->dns_count,
     207                 :            :                                         &lease->dns_allocated);
     208         [ -  + ]:         16 :         if (r < 0)
     209                 :          0 :                 return log_dhcp6_client_errno(client, r, "Invalid DNS server option: %m");
     210                 :            : 
     211                 :         16 :         lease->dns_count = r;
     212                 :            : 
     213                 :         16 :         return 0;
     214                 :            : }
     215                 :            : 
     216                 :         12 : int sd_dhcp6_lease_get_dns(sd_dhcp6_lease *lease, struct in6_addr **addrs) {
     217   [ -  +  -  + ]:         12 :         assert_return(lease, -EINVAL);
     218   [ -  +  -  + ]:         12 :         assert_return(addrs, -EINVAL);
     219                 :            : 
     220         [ +  - ]:         12 :         if (lease->dns_count) {
     221                 :         12 :                 *addrs = lease->dns;
     222                 :         12 :                 return lease->dns_count;
     223                 :            :         }
     224                 :            : 
     225                 :          0 :         return -ENOENT;
     226                 :            : }
     227                 :            : 
     228                 :         16 : int dhcp6_lease_set_domains(sd_dhcp6_lease *lease, uint8_t *optval,
     229                 :            :                             size_t optlen) {
     230                 :            :         int r;
     231                 :            :         char **domains;
     232                 :            : 
     233   [ -  +  -  + ]:         16 :         assert_return(lease, -EINVAL);
     234   [ -  +  -  + ]:         16 :         assert_return(optval, -EINVAL);
     235                 :            : 
     236         [ -  + ]:         16 :         if (!optlen)
     237                 :          0 :                 return 0;
     238                 :            : 
     239                 :         16 :         r = dhcp6_option_parse_domainname(optval, optlen, &domains);
     240         [ -  + ]:         16 :         if (r < 0)
     241                 :          0 :                 return 0;
     242                 :            : 
     243                 :         16 :         strv_free_and_replace(lease->domains, domains);
     244                 :         16 :         lease->domains_count = r;
     245                 :            : 
     246                 :         16 :         return r;
     247                 :            : }
     248                 :            : 
     249                 :         12 : int sd_dhcp6_lease_get_domains(sd_dhcp6_lease *lease, char ***domains) {
     250   [ -  +  -  + ]:         12 :         assert_return(lease, -EINVAL);
     251   [ -  +  -  + ]:         12 :         assert_return(domains, -EINVAL);
     252                 :            : 
     253         [ +  - ]:         12 :         if (lease->domains_count) {
     254                 :         12 :                 *domains = lease->domains;
     255                 :         12 :                 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                 :         16 : int dhcp6_lease_set_sntp(sd_dhcp6_lease *lease, uint8_t *optval, size_t optlen) {
     316                 :            :         int r;
     317                 :            : 
     318   [ -  +  -  + ]:         16 :         assert_return(lease, -EINVAL);
     319   [ -  +  -  + ]:         16 :         assert_return(optval, -EINVAL);
     320                 :            : 
     321         [ -  + ]:         16 :         if (!optlen)
     322                 :          0 :                 return 0;
     323                 :            : 
     324   [ +  -  -  + ]:         16 :         if (lease->ntp || lease->ntp_fqdn) {
     325                 :          0 :                 log_dhcp6_client(client, "NTP information already provided");
     326                 :            : 
     327                 :          0 :                 return 0;
     328                 :            :         }
     329                 :            : 
     330                 :         16 :         log_dhcp6_client(client, "Using deprecated SNTP information");
     331                 :            : 
     332                 :         16 :         r = dhcp6_option_parse_ip6addrs(optval, optlen, &lease->ntp,
     333                 :            :                                         lease->ntp_count,
     334                 :            :                                         &lease->ntp_allocated);
     335         [ -  + ]:         16 :         if (r < 0)
     336                 :          0 :                 return log_dhcp6_client_errno(client, r, "Invalid SNTP server option: %m");
     337                 :            : 
     338                 :         16 :         lease->ntp_count = r;
     339                 :            : 
     340                 :         16 :         return 0;
     341                 :            : }
     342                 :            : 
     343                 :         12 : int sd_dhcp6_lease_get_ntp_addrs(sd_dhcp6_lease *lease,
     344                 :            :                                  struct in6_addr **addrs) {
     345   [ -  +  -  + ]:         12 :         assert_return(lease, -EINVAL);
     346   [ -  +  -  + ]:         12 :         assert_return(addrs, -EINVAL);
     347                 :            : 
     348         [ +  - ]:         12 :         if (lease->ntp_count) {
     349                 :         12 :                 *addrs = lease->ntp;
     350                 :         12 :                 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                 :         24 : static sd_dhcp6_lease *dhcp6_lease_free(sd_dhcp6_lease *lease) {
     369         [ -  + ]:         24 :         assert(lease);
     370                 :            : 
     371                 :         24 :         free(lease->serverid);
     372                 :         24 :         dhcp6_lease_free_ia(&lease->ia);
     373                 :         24 :         dhcp6_lease_free_ia(&lease->pd);
     374                 :            : 
     375                 :         24 :         free(lease->dns);
     376                 :            : 
     377                 :         24 :         lease->domains = strv_free(lease->domains);
     378                 :            : 
     379                 :         24 :         free(lease->ntp);
     380                 :            : 
     381                 :         24 :         lease->ntp_fqdn = strv_free(lease->ntp_fqdn);
     382                 :         24 :         return mfree(lease);
     383                 :            : }
     384                 :            : 
     385   [ +  +  -  +  :         44 : DEFINE_TRIVIAL_REF_UNREF_FUNC(sd_dhcp6_lease, sd_dhcp6_lease, dhcp6_lease_free);
                   -  + ]
     386                 :            : 
     387                 :         24 : int dhcp6_lease_new(sd_dhcp6_lease **ret) {
     388                 :            :         sd_dhcp6_lease *lease;
     389                 :            : 
     390                 :         24 :         lease = new0(sd_dhcp6_lease, 1);
     391         [ -  + ]:         24 :         if (!lease)
     392                 :          0 :                 return -ENOMEM;
     393                 :            : 
     394                 :         24 :         lease->n_ref = 1;
     395                 :            : 
     396                 :         24 :         LIST_HEAD_INIT(lease->ia.addresses);
     397                 :            : 
     398                 :         24 :         *ret = lease;
     399                 :         24 :         return 0;
     400                 :            : }

Generated by: LCOV version 1.14