LCOV - code coverage report
Current view: top level - libsystemd-network - test-dhcp-server.c (source / functions) Hit Total Coverage
Test: main_coverage.info Lines: 39 143 27.3 %
Date: 2019-08-22 15:41:25 Functions: 3 6 50.0 %

          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             : 
       8             : #include "sd-dhcp-server.h"
       9             : #include "sd-event.h"
      10             : 
      11             : #include "dhcp-server-internal.h"
      12             : #include "tests.h"
      13             : 
      14           2 : static void test_pool(struct in_addr *address, unsigned size, int ret) {
      15           2 :         _cleanup_(sd_dhcp_server_unrefp) sd_dhcp_server *server = NULL;
      16             : 
      17           2 :         assert_se(sd_dhcp_server_new(&server, 1) >= 0);
      18             : 
      19           2 :         assert_se(sd_dhcp_server_configure_pool(server, address, 8, 0, size) == ret);
      20           2 : }
      21             : 
      22           1 : static int test_basic(sd_event *event) {
      23           1 :         _cleanup_(sd_dhcp_server_unrefp) sd_dhcp_server *server = NULL;
      24           1 :         struct in_addr address_lo = {
      25           1 :                 .s_addr = htonl(INADDR_LOOPBACK),
      26             :         };
      27           1 :         struct in_addr address_any = {
      28           1 :                 .s_addr = htonl(INADDR_ANY),
      29             :         };
      30             :         int r;
      31             : 
      32             :         /* attach to loopback interface */
      33           1 :         assert_se(sd_dhcp_server_new(&server, 1) >= 0);
      34           1 :         assert_se(server);
      35             : 
      36           1 :         assert_se(sd_dhcp_server_attach_event(server, event, 0) >= 0);
      37           1 :         assert_se(sd_dhcp_server_attach_event(server, event, 0) == -EBUSY);
      38           1 :         assert_se(sd_dhcp_server_get_event(server) == event);
      39           1 :         assert_se(sd_dhcp_server_detach_event(server) >= 0);
      40           1 :         assert_se(!sd_dhcp_server_get_event(server));
      41           1 :         assert_se(sd_dhcp_server_attach_event(server, NULL, 0) >= 0);
      42           1 :         assert_se(sd_dhcp_server_attach_event(server, NULL, 0) == -EBUSY);
      43             : 
      44           1 :         assert_se(sd_dhcp_server_ref(server) == server);
      45           1 :         assert_se(!sd_dhcp_server_unref(server));
      46             : 
      47           1 :         assert_se(sd_dhcp_server_start(server) == -EUNATCH);
      48             : 
      49           1 :         assert_se(sd_dhcp_server_configure_pool(server, &address_any, 28, 0, 0) == -EINVAL);
      50           1 :         assert_se(sd_dhcp_server_configure_pool(server, &address_lo, 38, 0, 0) == -ERANGE);
      51           1 :         assert_se(sd_dhcp_server_configure_pool(server, &address_lo, 8, 0, 0) >= 0);
      52           1 :         assert_se(sd_dhcp_server_configure_pool(server, &address_lo, 8, 0, 0) >= 0);
      53             : 
      54           1 :         test_pool(&address_any, 1, -EINVAL);
      55           1 :         test_pool(&address_lo, 1, 0);
      56             : 
      57           1 :         r = sd_dhcp_server_start(server);
      58           1 :         if (r == -EPERM)
      59           1 :                 return log_info_errno(r, "sd_dhcp_server_start failed: %m");
      60           0 :         assert_se(r >= 0);
      61             : 
      62           0 :         assert_se(sd_dhcp_server_start(server) == -EBUSY);
      63           0 :         assert_se(sd_dhcp_server_stop(server) >= 0);
      64           0 :         assert_se(sd_dhcp_server_stop(server) >= 0);
      65           0 :         assert_se(sd_dhcp_server_start(server) >= 0);
      66             : 
      67           0 :         return 0;
      68             : }
      69             : 
      70           0 : static void test_message_handler(void) {
      71           0 :         _cleanup_(sd_dhcp_server_unrefp) sd_dhcp_server *server = NULL;
      72             :         struct {
      73             :                 DHCPMessage message;
      74             :                 struct {
      75             :                         uint8_t code;
      76             :                         uint8_t length;
      77             :                         uint8_t type;
      78             :                 } _packed_ option_type;
      79             :                 struct {
      80             :                         uint8_t code;
      81             :                         uint8_t length;
      82             :                         be32_t address;
      83             :                 } _packed_ option_requested_ip;
      84             :                 struct {
      85             :                         uint8_t code;
      86             :                         uint8_t length;
      87             :                         be32_t address;
      88             :                 } _packed_ option_server_id;
      89             :                 struct {
      90             :                         uint8_t code;
      91             :                         uint8_t length;
      92             :                         uint8_t id[7];
      93             :                 } _packed_ option_client_id;
      94             :                 uint8_t end;
      95           0 :         } _packed_ test = {
      96             :                 .message.op = BOOTREQUEST,
      97             :                 .message.htype = ARPHRD_ETHER,
      98             :                 .message.hlen = ETHER_ADDR_LEN,
      99           0 :                 .message.xid = htobe32(0x12345678),
     100             :                 .message.chaddr = { 'A', 'B', 'C', 'D', 'E', 'F' },
     101             :                 .option_type.code = SD_DHCP_OPTION_MESSAGE_TYPE,
     102             :                 .option_type.length = 1,
     103             :                 .option_type.type = DHCP_DISCOVER,
     104             :                 .end = SD_DHCP_OPTION_END,
     105             :         };
     106           0 :         struct in_addr address_lo = {
     107           0 :                 .s_addr = htonl(INADDR_LOOPBACK),
     108             :         };
     109             : 
     110           0 :         assert_se(sd_dhcp_server_new(&server, 1) >= 0);
     111           0 :         assert_se(sd_dhcp_server_configure_pool(server, &address_lo, 8, 0, 0) >= 0);
     112           0 :         assert_se(sd_dhcp_server_attach_event(server, NULL, 0) >= 0);
     113           0 :         assert_se(sd_dhcp_server_start(server) >= 0);
     114             : 
     115           0 :         assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == DHCP_OFFER);
     116             : 
     117           0 :         test.end = 0;
     118             :         /* TODO, shouldn't this fail? */
     119           0 :         assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == DHCP_OFFER);
     120           0 :         test.end = SD_DHCP_OPTION_END;
     121           0 :         assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == DHCP_OFFER);
     122             : 
     123           0 :         test.option_type.code = 0;
     124           0 :         test.option_type.length = 0;
     125           0 :         test.option_type.type = 0;
     126           0 :         assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == 0);
     127           0 :         test.option_type.code = SD_DHCP_OPTION_MESSAGE_TYPE;
     128           0 :         test.option_type.length = 1;
     129           0 :         test.option_type.type = DHCP_DISCOVER;
     130           0 :         assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == DHCP_OFFER);
     131             : 
     132           0 :         test.message.op = 0;
     133           0 :         assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == 0);
     134           0 :         test.message.op = BOOTREQUEST;
     135           0 :         assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == DHCP_OFFER);
     136             : 
     137           0 :         test.message.htype = 0;
     138           0 :         assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == 0);
     139           0 :         test.message.htype = ARPHRD_ETHER;
     140           0 :         assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == DHCP_OFFER);
     141             : 
     142           0 :         test.message.hlen = 0;
     143           0 :         assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == 0);
     144           0 :         test.message.hlen = ETHER_ADDR_LEN;
     145           0 :         assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == DHCP_OFFER);
     146             : 
     147           0 :         test.option_type.type = DHCP_REQUEST;
     148           0 :         assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == 0);
     149           0 :         test.option_requested_ip.code = SD_DHCP_OPTION_REQUESTED_IP_ADDRESS;
     150           0 :         test.option_requested_ip.length = 4;
     151           0 :         test.option_requested_ip.address = htobe32(0x12345678);
     152           0 :         assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == DHCP_NAK);
     153           0 :         test.option_server_id.code = SD_DHCP_OPTION_SERVER_IDENTIFIER;
     154           0 :         test.option_server_id.length = 4;
     155           0 :         test.option_server_id.address = htobe32(INADDR_LOOPBACK);
     156           0 :         test.option_requested_ip.address = htobe32(INADDR_LOOPBACK + 3);
     157           0 :         assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == DHCP_ACK);
     158             : 
     159           0 :         test.option_server_id.address = htobe32(0x12345678);
     160           0 :         test.option_requested_ip.address = htobe32(INADDR_LOOPBACK + 3);
     161           0 :         assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == 0);
     162           0 :         test.option_server_id.address = htobe32(INADDR_LOOPBACK);
     163           0 :         test.option_requested_ip.address = htobe32(INADDR_LOOPBACK + 4);
     164           0 :         assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == 0);
     165           0 :         test.option_requested_ip.address = htobe32(INADDR_LOOPBACK + 3);
     166           0 :         assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == DHCP_ACK);
     167             : 
     168           0 :         test.option_client_id.code = SD_DHCP_OPTION_CLIENT_IDENTIFIER;
     169           0 :         test.option_client_id.length = 7;
     170           0 :         test.option_client_id.id[0] = 0x01;
     171           0 :         test.option_client_id.id[1] = 'A';
     172           0 :         test.option_client_id.id[2] = 'B';
     173           0 :         test.option_client_id.id[3] = 'C';
     174           0 :         test.option_client_id.id[4] = 'D';
     175           0 :         test.option_client_id.id[5] = 'E';
     176           0 :         test.option_client_id.id[6] = 'F';
     177           0 :         assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == DHCP_ACK);
     178             : 
     179           0 :         test.option_requested_ip.address = htobe32(INADDR_LOOPBACK + 30);
     180           0 :         assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == 0);
     181           0 : }
     182             : 
     183           0 : static uint64_t client_id_hash_helper(DHCPClientId *id, uint8_t key[HASH_KEY_SIZE]) {
     184             :         struct siphash state;
     185             : 
     186           0 :         siphash24_init(&state, key);
     187           0 :         client_id_hash_func(id, &state);
     188             : 
     189           0 :         return htole64(siphash24_finalize(&state));
     190             : }
     191             : 
     192           0 : static void test_client_id_hash(void) {
     193           0 :         DHCPClientId a = {
     194             :                 .length = 4,
     195           0 :         }, b = {
     196             :                 .length = 4,
     197             :         };
     198           0 :         uint8_t hash_key[HASH_KEY_SIZE] = {
     199             :                 '0', '1', '2', '3', '4', '5', '6', '7',
     200             :                 '8', '9', 'A', 'B', 'C', 'D', 'E', 'F',
     201             :         };
     202             : 
     203           0 :         a.data = (uint8_t*)strdup("abcd");
     204           0 :         b.data = (uint8_t*)strdup("abcd");
     205             : 
     206           0 :         assert_se(client_id_compare_func(&a, &b) == 0);
     207           0 :         assert_se(client_id_hash_helper(&a, hash_key) == client_id_hash_helper(&b, hash_key));
     208           0 :         a.length = 3;
     209           0 :         assert_se(client_id_compare_func(&a, &b) != 0);
     210           0 :         a.length = 4;
     211           0 :         assert_se(client_id_compare_func(&a, &b) == 0);
     212           0 :         assert_se(client_id_hash_helper(&a, hash_key) == client_id_hash_helper(&b, hash_key));
     213             : 
     214           0 :         b.length = 3;
     215           0 :         assert_se(client_id_compare_func(&a, &b) != 0);
     216           0 :         b.length = 4;
     217           0 :         assert_se(client_id_compare_func(&a, &b) == 0);
     218           0 :         assert_se(client_id_hash_helper(&a, hash_key) == client_id_hash_helper(&b, hash_key));
     219             : 
     220           0 :         free(b.data);
     221           0 :         b.data = (uint8_t*)strdup("abce");
     222           0 :         assert_se(client_id_compare_func(&a, &b) != 0);
     223             : 
     224           0 :         free(a.data);
     225           0 :         free(b.data);
     226           0 : }
     227             : 
     228           1 : int main(int argc, char *argv[]) {
     229           1 :         _cleanup_(sd_event_unrefp) sd_event *e;
     230             :         int r;
     231             : 
     232           1 :         test_setup_logging(LOG_DEBUG);
     233             : 
     234           1 :         assert_se(sd_event_new(&e) >= 0);
     235             : 
     236           1 :         r = test_basic(e);
     237           1 :         if (r != 0)
     238           1 :                 return log_tests_skipped("cannot start dhcp server");
     239             : 
     240           0 :         test_message_handler();
     241           0 :         test_client_id_hash();
     242             : 
     243           0 :         return 0;
     244             : }

Generated by: LCOV version 1.14