LCOV - code coverage report
Current view: top level - libsystemd-network - test-dhcp-client.c (source / functions) Hit Total Coverage
Test: main_coverage.info Lines: 210 238 88.2 %
Date: 2019-08-22 15:41:25 Functions: 13 17 76.5 %

          Line data    Source code
       1             : /* SPDX-License-Identifier: LGPL-2.1+ */
       2             : /***
       3             :   Copyright © 2013 Intel Corporation. All rights reserved.
       4             : ***/
       5             : 
       6             : #include <errno.h>
       7             : #include <stdio.h>
       8             : #include <sys/socket.h>
       9             : #include <unistd.h>
      10             : #include <net/if.h>
      11             : 
      12             : #include "sd-dhcp-client.h"
      13             : #include "sd-event.h"
      14             : 
      15             : #include "alloc-util.h"
      16             : #include "dhcp-identifier.h"
      17             : #include "dhcp-internal.h"
      18             : #include "dhcp-protocol.h"
      19             : #include "fd-util.h"
      20             : #include "random-util.h"
      21             : #include "tests.h"
      22             : #include "util.h"
      23             : 
      24             : static uint8_t mac_addr[] = {'A', 'B', 'C', '1', '2', '3'};
      25             : 
      26             : typedef int (*test_callback_recv_t)(size_t size, DHCPMessage *dhcp);
      27             : 
      28             : static bool verbose = true;
      29             : static int test_fd[2];
      30             : static test_callback_recv_t callback_recv;
      31             : static be32_t xid;
      32             : static sd_event_source *test_hangcheck;
      33             : 
      34           0 : static int test_dhcp_hangcheck(sd_event_source *s, uint64_t usec, void *userdata) {
      35           0 :         assert_not_reached("Test case should have completed in 2 seconds");
      36             : 
      37             :         return 0;
      38             : }
      39             : 
      40           1 : static void test_request_basic(sd_event *e) {
      41             :         int r;
      42             : 
      43             :         sd_dhcp_client *client;
      44             : 
      45           1 :         if (verbose)
      46           1 :                 printf("* %s\n", __FUNCTION__);
      47             : 
      48             :         /* Initialize client without Anonymize settings. */
      49           1 :         r = sd_dhcp_client_new(&client, false);
      50             : 
      51           1 :         assert_se(r >= 0);
      52           1 :         assert_se(client);
      53             : 
      54           1 :         r = sd_dhcp_client_attach_event(client, e, 0);
      55           1 :         assert_se(r >= 0);
      56             : 
      57           1 :         assert_se(sd_dhcp_client_set_request_option(NULL, 0) == -EINVAL);
      58           1 :         assert_se(sd_dhcp_client_set_request_address(NULL, NULL) == -EINVAL);
      59           1 :         assert_se(sd_dhcp_client_set_ifindex(NULL, 0) == -EINVAL);
      60             : 
      61           1 :         assert_se(sd_dhcp_client_set_ifindex(client, 15) == 0);
      62           1 :         assert_se(sd_dhcp_client_set_ifindex(client, -42) == -EINVAL);
      63           1 :         assert_se(sd_dhcp_client_set_ifindex(client, -1) == -EINVAL);
      64           1 :         assert_se(sd_dhcp_client_set_ifindex(client, 0) == -EINVAL);
      65           1 :         assert_se(sd_dhcp_client_set_ifindex(client, 1) == 0);
      66             : 
      67           1 :         assert_se(sd_dhcp_client_set_hostname(client, "host") == 1);
      68           1 :         assert_se(sd_dhcp_client_set_hostname(client, "host.domain") == 1);
      69           1 :         assert_se(sd_dhcp_client_set_hostname(client, NULL) == 1);
      70           1 :         assert_se(sd_dhcp_client_set_hostname(client, "~host") == -EINVAL);
      71           1 :         assert_se(sd_dhcp_client_set_hostname(client, "~host.domain") == -EINVAL);
      72             : 
      73           1 :         assert_se(sd_dhcp_client_set_request_option(client,
      74             :                                         SD_DHCP_OPTION_SUBNET_MASK) == -EEXIST);
      75           1 :         assert_se(sd_dhcp_client_set_request_option(client,
      76             :                                         SD_DHCP_OPTION_ROUTER) == -EEXIST);
      77             :         /* This PRL option is not set when using Anonymize, but in this test
      78             :          * Anonymize settings are not being used. */
      79           1 :         assert_se(sd_dhcp_client_set_request_option(client,
      80             :                                         SD_DHCP_OPTION_HOST_NAME) == -EEXIST);
      81           1 :         assert_se(sd_dhcp_client_set_request_option(client,
      82             :                                         SD_DHCP_OPTION_DOMAIN_NAME) == -EEXIST);
      83           1 :         assert_se(sd_dhcp_client_set_request_option(client,
      84             :                                         SD_DHCP_OPTION_DOMAIN_NAME_SERVER) == -EEXIST);
      85             : 
      86           1 :         assert_se(sd_dhcp_client_set_request_option(client,
      87             :                                         SD_DHCP_OPTION_PAD) == -EINVAL);
      88           1 :         assert_se(sd_dhcp_client_set_request_option(client,
      89             :                                         SD_DHCP_OPTION_END) == -EINVAL);
      90           1 :         assert_se(sd_dhcp_client_set_request_option(client,
      91             :                                         SD_DHCP_OPTION_MESSAGE_TYPE) == -EINVAL);
      92           1 :         assert_se(sd_dhcp_client_set_request_option(client,
      93             :                                         SD_DHCP_OPTION_OVERLOAD) == -EINVAL);
      94           1 :         assert_se(sd_dhcp_client_set_request_option(client,
      95             :                                         SD_DHCP_OPTION_PARAMETER_REQUEST_LIST)
      96             :                         == -EINVAL);
      97             : 
      98             :         /* RFC7844: option 33 (SD_DHCP_OPTION_STATIC_ROUTE) is set in the
      99             :          * default PRL when using Anonymize, so it is changed to other option
     100             :          * that is not set by default, to check that it was set successfully.
     101             :          * Options not set by default (using or not anonymize) are option 17
     102             :          * (SD_DHCP_OPTION_ROOT_PATH) and 42 (SD_DHCP_OPTION_NTP_SERVER) */
     103           1 :         assert_se(sd_dhcp_client_set_request_option(client, 17) == 0);
     104           1 :         assert_se(sd_dhcp_client_set_request_option(client, 17) == -EEXIST);
     105           1 :         assert_se(sd_dhcp_client_set_request_option(client, 42) == 0);
     106           1 :         assert_se(sd_dhcp_client_set_request_option(client, 17) == -EEXIST);
     107             : 
     108           1 :         sd_dhcp_client_unref(client);
     109           1 : }
     110             : 
     111           1 : static void test_request_anonymize(sd_event *e) {
     112             :         int r;
     113             : 
     114             :         sd_dhcp_client *client;
     115             : 
     116           1 :         if (verbose)
     117           1 :                 printf("* %s\n", __FUNCTION__);
     118             : 
     119             :         /* Initialize client with Anonymize settings. */
     120           1 :         r = sd_dhcp_client_new(&client, true);
     121             : 
     122           1 :         assert_se(r >= 0);
     123           1 :         assert_se(client);
     124             : 
     125           1 :         r = sd_dhcp_client_attach_event(client, e, 0);
     126           1 :         assert_se(r >= 0);
     127             : 
     128           1 :         assert_se(sd_dhcp_client_set_request_option(client,
     129             :                                         SD_DHCP_OPTION_NETBIOS_NAMESERVER) == -EEXIST);
     130             :         /* This PRL option is not set when using Anonymize */
     131           1 :         assert_se(sd_dhcp_client_set_request_option(client,
     132             :                                         SD_DHCP_OPTION_HOST_NAME) == 0);
     133           1 :         assert_se(sd_dhcp_client_set_request_option(client,
     134             :                                         SD_DHCP_OPTION_PARAMETER_REQUEST_LIST)
     135             :                         == -EINVAL);
     136             : 
     137             :         /* RFC7844: option 101 (SD_DHCP_OPTION_NEW_TZDB_TIMEZONE) is not set in the
     138             :          * default PRL when using Anonymize, */
     139           1 :         assert_se(sd_dhcp_client_set_request_option(client, 101) == 0);
     140           1 :         assert_se(sd_dhcp_client_set_request_option(client, 101) == -EEXIST);
     141             : 
     142           1 :         sd_dhcp_client_unref(client);
     143           1 : }
     144             : 
     145           1 : static void test_checksum(void) {
     146           1 :         uint8_t buf[20] = {
     147             :                 0x45, 0x00, 0x02, 0x40, 0x00, 0x00, 0x00, 0x00,
     148             :                 0x40, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     149             :                 0xff, 0xff, 0xff, 0xff
     150             :         };
     151             : 
     152           1 :         if (verbose)
     153           1 :                 printf("* %s\n", __FUNCTION__);
     154             : 
     155           1 :         assert_se(dhcp_packet_checksum((uint8_t*)&buf, 20) == be16toh(0x78ae));
     156           1 : }
     157             : 
     158           2 : static void test_dhcp_identifier_set_iaid(void) {
     159             :         uint32_t iaid_legacy;
     160             :         be32_t iaid;
     161             :         int ifindex;
     162             : 
     163           1 :         for (;;) {
     164             :                 char ifname[IFNAMSIZ];
     165             : 
     166             :                 /* try to find an ifindex which does not exist. I causes dhcp_identifier_set_iaid()
     167             :                  * to hash the MAC address. */
     168           2 :                 pseudo_random_bytes(&ifindex, sizeof(ifindex));
     169           2 :                 if (ifindex > 0 && !if_indextoname(ifindex, ifname))
     170           1 :                         break;
     171             :         }
     172             : 
     173           1 :         assert_se(dhcp_identifier_set_iaid(ifindex, mac_addr, sizeof(mac_addr), true, &iaid_legacy) >= 0);
     174           1 :         assert_se(dhcp_identifier_set_iaid(ifindex, mac_addr, sizeof(mac_addr), false, &iaid) >= 0);
     175             : 
     176             :         /* we expect, that the MAC address was hashed. The legacy value is in native
     177             :          * endianness. */
     178           1 :         assert_se(iaid_legacy == 0x8dde4ba8u);
     179           1 :         assert_se(iaid  == htole32(0x8dde4ba8u));
     180             : #if __BYTE_ORDER == __LITTLE_ENDIAN
     181           1 :         assert_se(iaid == iaid_legacy);
     182             : #else
     183             :         assert_se(iaid == __bswap_32(iaid_legacy));
     184             : #endif
     185           1 : }
     186             : 
     187           6 : static int check_options(uint8_t code, uint8_t len, const void *option, void *userdata) {
     188           6 :         switch(code) {
     189           2 :         case SD_DHCP_OPTION_CLIENT_IDENTIFIER:
     190             :         {
     191             :                 uint32_t iaid;
     192             :                 struct duid duid;
     193             :                 size_t duid_len;
     194             : 
     195           2 :                 assert_se(dhcp_identifier_set_duid_en(&duid, &duid_len) >= 0);
     196           2 :                 assert_se(dhcp_identifier_set_iaid(42, mac_addr, ETH_ALEN, true, &iaid) >= 0);
     197             : 
     198           2 :                 assert_se(len == sizeof(uint8_t) + sizeof(uint32_t) + duid_len);
     199           2 :                 assert_se(len == 19);
     200           2 :                 assert_se(((uint8_t*) option)[0] == 0xff);
     201             : 
     202           2 :                 assert_se(memcmp((uint8_t*) option + 1, &iaid, sizeof(iaid)) == 0);
     203           2 :                 assert_se(memcmp((uint8_t*) option + 5, &duid, duid_len) == 0);
     204           2 :                 break;
     205             :         }
     206             : 
     207           4 :         default:
     208           4 :                 break;
     209             :         }
     210             : 
     211           6 :         return 0;
     212             : }
     213             : 
     214           2 : int dhcp_network_send_raw_socket(int s, const union sockaddr_union *link, const void *packet, size_t len) {
     215             :         size_t size;
     216           2 :         _cleanup_free_ DHCPPacket *discover;
     217             :         uint16_t ip_check, udp_check;
     218             : 
     219           2 :         assert_se(s >= 0);
     220           2 :         assert_se(packet);
     221             : 
     222           2 :         size = sizeof(DHCPPacket);
     223           2 :         assert_se(len > size);
     224             : 
     225           2 :         discover = memdup(packet, len);
     226             : 
     227           2 :         assert_se(discover->ip.ttl == IPDEFTTL);
     228           2 :         assert_se(discover->ip.protocol == IPPROTO_UDP);
     229           2 :         assert_se(discover->ip.saddr == INADDR_ANY);
     230           2 :         assert_se(discover->ip.daddr == INADDR_BROADCAST);
     231           2 :         assert_se(discover->udp.source == be16toh(DHCP_PORT_CLIENT));
     232           2 :         assert_se(discover->udp.dest == be16toh(DHCP_PORT_SERVER));
     233             : 
     234           2 :         ip_check = discover->ip.check;
     235             : 
     236           2 :         discover->ip.ttl = 0;
     237           2 :         discover->ip.check = discover->udp.len;
     238             : 
     239           2 :         udp_check = ~dhcp_packet_checksum((uint8_t*)&discover->ip.ttl, len - 8);
     240           2 :         assert_se(udp_check == 0xffff);
     241             : 
     242           2 :         discover->ip.ttl = IPDEFTTL;
     243           2 :         discover->ip.check = ip_check;
     244             : 
     245           2 :         ip_check = ~dhcp_packet_checksum((uint8_t*)&discover->ip, sizeof(discover->ip));
     246           2 :         assert_se(ip_check == 0xffff);
     247             : 
     248           2 :         assert_se(discover->dhcp.xid);
     249           2 :         assert_se(memcmp(discover->dhcp.chaddr, &mac_addr, ETH_ALEN) == 0);
     250             : 
     251           2 :         size = len - sizeof(struct iphdr) - sizeof(struct udphdr);
     252             : 
     253           2 :         assert_se(callback_recv);
     254           2 :         callback_recv(size, &discover->dhcp);
     255             : 
     256           2 :         return 575;
     257             : }
     258             : 
     259           2 : int dhcp_network_bind_raw_socket(
     260             :                 int index,
     261             :                 union sockaddr_union *link,
     262             :                 uint32_t id,
     263             :                 const uint8_t *addr, size_t addr_len,
     264             :                 uint16_t arp_type, uint16_t port) {
     265             : 
     266           2 :         if (socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0, test_fd) < 0)
     267           0 :                 return -errno;
     268             : 
     269           2 :         return test_fd[0];
     270             : }
     271             : 
     272           0 : int dhcp_network_bind_udp_socket(int ifindex, be32_t address, uint16_t port) {
     273             :         int fd;
     274             : 
     275           0 :         fd = socket(AF_INET, SOCK_DGRAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0);
     276           0 :         if (fd < 0)
     277           0 :                 return -errno;
     278             : 
     279           0 :         return fd;
     280             : }
     281             : 
     282           0 : int dhcp_network_send_udp_socket(int s, be32_t address, uint16_t port, const void *packet, size_t len) {
     283           0 :         return 0;
     284             : }
     285             : 
     286           1 : static int test_discover_message_verify(size_t size, struct DHCPMessage *dhcp) {
     287             :         int res;
     288             : 
     289           1 :         res = dhcp_option_parse(dhcp, size, check_options, NULL, NULL);
     290           1 :         assert_se(res == DHCP_DISCOVER);
     291             : 
     292           1 :         if (verbose)
     293           1 :                 printf("  recv DHCP Discover 0x%08x\n", be32toh(dhcp->xid));
     294             : 
     295           1 :         return 0;
     296             : }
     297             : 
     298           1 : static void test_discover_message(sd_event *e) {
     299             :         sd_dhcp_client *client;
     300             :         int res, r;
     301             : 
     302           1 :         if (verbose)
     303           1 :                 printf("* %s\n", __FUNCTION__);
     304             : 
     305           1 :         r = sd_dhcp_client_new(&client, false);
     306           1 :         assert_se(r >= 0);
     307           1 :         assert_se(client);
     308             : 
     309           1 :         r = sd_dhcp_client_attach_event(client, e, 0);
     310           1 :         assert_se(r >= 0);
     311             : 
     312           1 :         assert_se(sd_dhcp_client_set_ifindex(client, 42) >= 0);
     313           1 :         assert_se(sd_dhcp_client_set_mac(client, mac_addr, ETH_ALEN, ARPHRD_ETHER) >= 0);
     314             : 
     315           1 :         assert_se(sd_dhcp_client_set_request_option(client, 248) >= 0);
     316             : 
     317           1 :         callback_recv = test_discover_message_verify;
     318             : 
     319           1 :         res = sd_dhcp_client_start(client);
     320             : 
     321           1 :         assert_se(IN_SET(res, 0, -EINPROGRESS));
     322             : 
     323           1 :         sd_event_run(e, (uint64_t) -1);
     324             : 
     325           1 :         sd_dhcp_client_stop(client);
     326           1 :         sd_dhcp_client_unref(client);
     327             : 
     328           1 :         test_fd[1] = safe_close(test_fd[1]);
     329             : 
     330           1 :         callback_recv = NULL;
     331           1 : }
     332             : 
     333             : static uint8_t test_addr_acq_offer[] = {
     334             :         0x45, 0x10, 0x01, 0x48, 0x00, 0x00, 0x00, 0x00,
     335             :         0x80, 0x11, 0xb3, 0x84, 0xc0, 0xa8, 0x02, 0x01,
     336             :         0xc0, 0xa8, 0x02, 0xbf, 0x00, 0x43, 0x00, 0x44,
     337             :         0x01, 0x34, 0x00, 0x00, 0x02, 0x01, 0x06, 0x00,
     338             :         0x6f, 0x95, 0x2f, 0x30, 0x00, 0x00, 0x00, 0x00,
     339             :         0x00, 0x00, 0x00, 0x00, 0xc0, 0xa8, 0x02, 0xbf,
     340             :         0xc0, 0xa8, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00,
     341             :         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     342             :         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     343             :         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     344             :         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     345             :         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     346             :         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     347             :         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     348             :         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     349             :         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     350             :         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     351             :         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     352             :         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     353             :         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     354             :         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     355             :         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     356             :         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     357             :         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     358             :         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     359             :         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     360             :         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     361             :         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     362             :         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     363             :         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     364             :         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     365             :         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     366             :         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     367             :         0x63, 0x82, 0x53, 0x63, 0x35, 0x01, 0x02, 0x36,
     368             :         0x04, 0xc0, 0xa8, 0x02, 0x01, 0x33, 0x04, 0x00,
     369             :         0x00, 0x02, 0x58, 0x01, 0x04, 0xff, 0xff, 0xff,
     370             :         0x00, 0x2a, 0x04, 0xc0, 0xa8, 0x02, 0x01, 0x0f,
     371             :         0x09, 0x6c, 0x61, 0x62, 0x2e, 0x69, 0x6e, 0x74,
     372             :         0x72, 0x61, 0x03, 0x04, 0xc0, 0xa8, 0x02, 0x01,
     373             :         0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     374             :         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     375             : };
     376             : 
     377             : static uint8_t test_addr_acq_ack[] = {
     378             :         0x45, 0x10, 0x01, 0x48, 0x00, 0x00, 0x00, 0x00,
     379             :         0x80, 0x11, 0xb3, 0x84, 0xc0, 0xa8, 0x02, 0x01,
     380             :         0xc0, 0xa8, 0x02, 0xbf, 0x00, 0x43, 0x00, 0x44,
     381             :         0x01, 0x34, 0x00, 0x00, 0x02, 0x01, 0x06, 0x00,
     382             :         0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
     383             :         0x00, 0x00, 0x00, 0x00, 0xc0, 0xa8, 0x02, 0xbf,
     384             :         0xc0, 0xa8, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00,
     385             :         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     386             :         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     387             :         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     388             :         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     389             :         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     390             :         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     391             :         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     392             :         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     393             :         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     394             :         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     395             :         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     396             :         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     397             :         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     398             :         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     399             :         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     400             :         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     401             :         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     402             :         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     403             :         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     404             :         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     405             :         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     406             :         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     407             :         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     408             :         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     409             :         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     410             :         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     411             :         0x63, 0x82, 0x53, 0x63, 0x35, 0x01, 0x05, 0x36,
     412             :         0x04, 0xc0, 0xa8, 0x02, 0x01, 0x33, 0x04, 0x00,
     413             :         0x00, 0x02, 0x58, 0x01, 0x04, 0xff, 0xff, 0xff,
     414             :         0x00, 0x2a, 0x04, 0xc0, 0xa8, 0x02, 0x01, 0x0f,
     415             :         0x09, 0x6c, 0x61, 0x62, 0x2e, 0x69, 0x6e, 0x74,
     416             :         0x72, 0x61, 0x03, 0x04, 0xc0, 0xa8, 0x02, 0x01,
     417             :         0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     418             :         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     419             : };
     420             : 
     421           1 : static int test_addr_acq_acquired(sd_dhcp_client *client, int event,
     422             :                                    void *userdata) {
     423           1 :         sd_event *e = userdata;
     424             :         sd_dhcp_lease *lease;
     425             :         struct in_addr addr;
     426             :         const struct in_addr *addrs;
     427             : 
     428           1 :         assert_se(client);
     429           1 :         assert_se(IN_SET(event, SD_DHCP_CLIENT_EVENT_IP_ACQUIRE, SD_DHCP_CLIENT_EVENT_SELECTING));
     430             : 
     431           1 :         assert_se(sd_dhcp_client_get_lease(client, &lease) >= 0);
     432           1 :         assert_se(lease);
     433             : 
     434           1 :         assert_se(sd_dhcp_lease_get_address(lease, &addr) >= 0);
     435           1 :         assert_se(memcmp(&addr.s_addr, &test_addr_acq_ack[44],
     436             :                       sizeof(addr.s_addr)) == 0);
     437             : 
     438           1 :         assert_se(sd_dhcp_lease_get_netmask(lease, &addr) >= 0);
     439           1 :         assert_se(memcmp(&addr.s_addr, &test_addr_acq_ack[285],
     440             :                       sizeof(addr.s_addr)) == 0);
     441             : 
     442           1 :         assert_se(sd_dhcp_lease_get_router(lease, &addrs) == 1);
     443           1 :         assert_se(memcmp(&addrs[0].s_addr, &test_addr_acq_ack[308],
     444             :                          sizeof(addrs[0].s_addr)) == 0);
     445             : 
     446           1 :         if (verbose)
     447           1 :                 printf("  DHCP address acquired\n");
     448             : 
     449           1 :         sd_event_exit(e, 0);
     450             : 
     451           1 :         return 0;
     452             : }
     453             : 
     454           0 : static int test_addr_acq_recv_request(size_t size, DHCPMessage *request) {
     455           0 :         uint16_t udp_check = 0;
     456           0 :         uint8_t *msg_bytes = (uint8_t *)request;
     457             :         int res;
     458             : 
     459           0 :         res = dhcp_option_parse(request, size, check_options, NULL, NULL);
     460           0 :         assert_se(res == DHCP_REQUEST);
     461           0 :         assert_se(xid == request->xid);
     462             : 
     463           0 :         assert_se(msg_bytes[size - 1] == SD_DHCP_OPTION_END);
     464             : 
     465           0 :         if (verbose)
     466           0 :                 printf("  recv DHCP Request  0x%08x\n", be32toh(xid));
     467             : 
     468           0 :         memcpy(&test_addr_acq_ack[26], &udp_check, sizeof(udp_check));
     469           0 :         memcpy(&test_addr_acq_ack[32], &xid, sizeof(xid));
     470           0 :         memcpy(&test_addr_acq_ack[56], &mac_addr, ETHER_ADDR_LEN);
     471             : 
     472           0 :         callback_recv = NULL;
     473             : 
     474           0 :         res = write(test_fd[1], test_addr_acq_ack,
     475             :                     sizeof(test_addr_acq_ack));
     476           0 :         assert_se(res == sizeof(test_addr_acq_ack));
     477             : 
     478           0 :         if (verbose)
     479           0 :                 printf("  send DHCP Ack\n");
     480             : 
     481           0 :         return 0;
     482             : };
     483             : 
     484           1 : static int test_addr_acq_recv_discover(size_t size, DHCPMessage *discover) {
     485           1 :         uint16_t udp_check = 0;
     486           1 :         uint8_t *msg_bytes = (uint8_t *)discover;
     487             :         int res;
     488             : 
     489           1 :         res = dhcp_option_parse(discover, size, check_options, NULL, NULL);
     490           1 :         assert_se(res == DHCP_DISCOVER);
     491             : 
     492           1 :         assert_se(msg_bytes[size - 1] == SD_DHCP_OPTION_END);
     493             : 
     494           1 :         xid = discover->xid;
     495             : 
     496           1 :         if (verbose)
     497           1 :                 printf("  recv DHCP Discover 0x%08x\n", be32toh(xid));
     498             : 
     499           1 :         memcpy(&test_addr_acq_offer[26], &udp_check, sizeof(udp_check));
     500           1 :         memcpy(&test_addr_acq_offer[32], &xid, sizeof(xid));
     501           1 :         memcpy(&test_addr_acq_offer[56], &mac_addr, ETHER_ADDR_LEN);
     502             : 
     503           1 :         callback_recv = test_addr_acq_recv_request;
     504             : 
     505           1 :         res = write(test_fd[1], test_addr_acq_offer,
     506             :                     sizeof(test_addr_acq_offer));
     507           1 :         assert_se(res == sizeof(test_addr_acq_offer));
     508             : 
     509           1 :         if (verbose)
     510           1 :                 printf("  sent DHCP Offer\n");
     511             : 
     512           1 :         return 0;
     513             : }
     514             : 
     515           1 : static void test_addr_acq(sd_event *e) {
     516           1 :         usec_t time_now = now(clock_boottime_or_monotonic());
     517             :         sd_dhcp_client *client;
     518             :         int res, r;
     519             : 
     520           1 :         if (verbose)
     521           1 :                 printf("* %s\n", __FUNCTION__);
     522             : 
     523           1 :         r = sd_dhcp_client_new(&client, false);
     524           1 :         assert_se(r >= 0);
     525           1 :         assert_se(client);
     526             : 
     527           1 :         r = sd_dhcp_client_attach_event(client, e, 0);
     528           1 :         assert_se(r >= 0);
     529             : 
     530           1 :         assert_se(sd_dhcp_client_set_ifindex(client, 42) >= 0);
     531           1 :         assert_se(sd_dhcp_client_set_mac(client, mac_addr, ETH_ALEN, ARPHRD_ETHER) >= 0);
     532             : 
     533           1 :         assert_se(sd_dhcp_client_set_callback(client, test_addr_acq_acquired, e) >= 0);
     534             : 
     535           1 :         callback_recv = test_addr_acq_recv_discover;
     536             : 
     537           1 :         assert_se(sd_event_add_time(e, &test_hangcheck,
     538             :                                     clock_boottime_or_monotonic(),
     539             :                                     time_now + 2 * USEC_PER_SEC, 0,
     540             :                                     test_dhcp_hangcheck, NULL) >= 0);
     541             : 
     542           1 :         res = sd_dhcp_client_start(client);
     543           1 :         assert_se(IN_SET(res, 0, -EINPROGRESS));
     544             : 
     545           1 :         assert_se(sd_event_loop(e) >= 0);
     546             : 
     547           1 :         test_hangcheck = sd_event_source_unref(test_hangcheck);
     548             : 
     549           1 :         assert_se(sd_dhcp_client_set_callback(client, NULL, NULL) >= 0);
     550           1 :         assert_se(sd_dhcp_client_stop(client) >= 0);
     551           1 :         sd_dhcp_client_unref(client);
     552             : 
     553           1 :         test_fd[1] = safe_close(test_fd[1]);
     554             : 
     555           1 :         callback_recv = NULL;
     556           1 :         xid = 0;
     557           1 : }
     558             : 
     559           1 : int main(int argc, char *argv[]) {
     560           1 :         _cleanup_(sd_event_unrefp) sd_event *e;
     561             : 
     562           1 :         test_setup_logging(LOG_DEBUG);
     563             : 
     564           1 :         assert_se(sd_event_new(&e) >= 0);
     565             : 
     566           1 :         test_request_basic(e);
     567           1 :         test_request_anonymize(e);
     568           1 :         test_checksum();
     569           1 :         test_dhcp_identifier_set_iaid();
     570             : 
     571           1 :         test_discover_message(e);
     572           1 :         test_addr_acq(e);
     573             : 
     574             : #if VALGRIND
     575             :         /* Make sure the async_close thread has finished.
     576             :          * valgrind would report some of the phread_* structures
     577             :          * as not cleaned up properly. */
     578             :         sleep(1);
     579             : #endif
     580             : 
     581           1 :         return 0;
     582             : }

Generated by: LCOV version 1.14