test-dhcp-client.c revision c4acff1275e8d3a1c29c9b417b93f6cf6f10e258
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen/***
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen This file is part of systemd.
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen Copyright (C) 2013 Intel Corporation. All rights reserved.
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen systemd is free software; you can redistribute it and/or modify it
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen under the terms of the GNU Lesser General Public License as published by
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen the Free Software Foundation; either version 2.1 of the License, or
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen (at your option) any later version.
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen systemd is distributed in the hope that it will be useful, but
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen WITHOUT ANY WARRANTY; without even the implied warranty of
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen Lesser General Public License for more details.
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen You should have received a copy of the GNU Lesser General Public License
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen along with systemd; If not, see <http://www.gnu.org/licenses/>.
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen***/
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen#include <stdlib.h>
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersen#include <assert.h>
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersen#include <errno.h>
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen#include <stdio.h>
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen#include <sys/types.h>
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersen#include <sys/socket.h>
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen#include <unistd.h>
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen#include "util.h"
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen#include "socket-util.h"
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen#include "dhcp-protocol.h"
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen#include "dhcp-internal.h"
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen#include "sd-dhcp-client.h"
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersenstatic struct ether_addr mac_addr = {
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen .ether_addr_octet = {'A', 'B', 'C', '1', '2', '3'}
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen};
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersen
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersentypedef int (*test_callback_recv_t)(size_t size, DHCPMessage *dhcp);
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersenstatic bool verbose = false;
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersenstatic int test_fd[2];
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersenstatic test_callback_recv_t callback_recv;
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersenstatic be32_t xid;
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersenstatic sd_event_source *test_hangcheck;
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersenstatic int test_dhcp_hangcheck(sd_event_source *s, uint64_t usec,
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen void *userdata)
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen{
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen assert_not_reached("Test case should have completed in 2 seconds");
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen return 0;
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen}
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersenstatic void test_request_basic(sd_event *e)
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen{
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersen int r;
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen sd_dhcp_client *client;
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen if (verbose)
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen printf("* %s\n", __FUNCTION__);
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen r = sd_dhcp_client_new(&client);
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen assert_se(r >= 0);
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen assert_se(client);
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen r = sd_dhcp_client_attach_event(client, e, 0);
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen assert_se(r >= 0);
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen assert_se(sd_dhcp_client_set_request_option(NULL, 0) == -EINVAL);
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen assert_se(sd_dhcp_client_set_request_address(NULL, NULL) == -EINVAL);
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen assert_se(sd_dhcp_client_set_index(NULL, 0) == -EINVAL);
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen assert_se(sd_dhcp_client_set_index(client, 15) == 0);
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen assert_se(sd_dhcp_client_set_index(client, -42) == -EINVAL);
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen assert_se(sd_dhcp_client_set_index(client, -1) == 0);
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen assert_se(sd_dhcp_client_set_request_option(client,
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen DHCP_OPTION_SUBNET_MASK) == -EEXIST);
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen assert_se(sd_dhcp_client_set_request_option(client,
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen DHCP_OPTION_ROUTER) == -EEXIST);
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen assert_se(sd_dhcp_client_set_request_option(client,
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen DHCP_OPTION_HOST_NAME) == -EEXIST);
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen assert_se(sd_dhcp_client_set_request_option(client,
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen DHCP_OPTION_DOMAIN_NAME) == -EEXIST);
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen assert_se(sd_dhcp_client_set_request_option(client,
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen DHCP_OPTION_DOMAIN_NAME_SERVER)
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen == -EEXIST);
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen assert_se(sd_dhcp_client_set_request_option(client,
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen DHCP_OPTION_NTP_SERVER) == -EEXIST);
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen assert_se(sd_dhcp_client_set_request_option(client,
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen DHCP_OPTION_PAD) == -EINVAL);
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen assert_se(sd_dhcp_client_set_request_option(client,
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersen DHCP_OPTION_END) == -EINVAL);
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersen assert_se(sd_dhcp_client_set_request_option(client,
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersen DHCP_OPTION_MESSAGE_TYPE) == -EINVAL);
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersen assert_se(sd_dhcp_client_set_request_option(client,
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersen DHCP_OPTION_OVERLOAD) == -EINVAL);
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersen assert_se(sd_dhcp_client_set_request_option(client,
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersen DHCP_OPTION_PARAMETER_REQUEST_LIST)
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersen == -EINVAL);
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersen
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersen assert_se(sd_dhcp_client_set_request_option(client, 33) == 0);
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersen assert_se(sd_dhcp_client_set_request_option(client, 33) == -EEXIST);
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersen assert_se(sd_dhcp_client_set_request_option(client, 44) == 0);
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersen assert_se(sd_dhcp_client_set_request_option(client, 33) == -EEXIST);
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersen}
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersen
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersenstatic void test_checksum(void)
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersen{
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersen uint8_t buf[20] = {
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersen 0x45, 0x00, 0x02, 0x40, 0x00, 0x00, 0x00, 0x00,
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersen 0x40, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersen 0xff, 0xff, 0xff, 0xff
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersen };
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersen
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersen if (verbose)
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersen printf("* %s\n", __FUNCTION__);
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersen
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersen assert_se(dhcp_packet_checksum(&buf, 20) == be16toh(0x78ae));
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersen}
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersen
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersenstatic int check_options(uint8_t code, uint8_t len, const uint8_t *option,
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersen void *user_data)
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersen{
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersen switch(code) {
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersen case DHCP_OPTION_CLIENT_IDENTIFIER:
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersen assert_se(len == 7);
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersen assert_se(option[0] == 0x01);
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersen assert_se(memcmp(&option[1], &mac_addr, ETH_ALEN) == 0);
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersen break;
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersen
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersen default:
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersen break;
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersen }
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersen
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersen return 0;
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersen}
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersen
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersenint dhcp_network_send_raw_socket(int s, const union sockaddr_union *link,
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersen const void *packet, size_t len)
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersen{
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersen size_t size;
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersen _cleanup_free_ DHCPPacket *discover;
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersen uint16_t ip_check, udp_check;
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersen
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersen assert_se(s >= 0);
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersen assert_se(packet);
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersen
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersen size = sizeof(DHCPPacket) + 4;
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersen assert_se(len > size);
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersen
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersen discover = memdup(packet, len);
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersen
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersen assert_se(discover->ip.ttl == IPDEFTTL);
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersen assert_se(discover->ip.protocol == IPPROTO_UDP);
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersen assert_se(discover->ip.saddr == INADDR_ANY);
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersen assert_se(discover->ip.daddr == INADDR_BROADCAST);
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersen assert_se(discover->udp.source == be16toh(DHCP_PORT_CLIENT));
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersen assert_se(discover->udp.dest == be16toh(DHCP_PORT_SERVER));
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersen
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersen ip_check = discover->ip.check;
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersen
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersen discover->ip.ttl = 0;
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersen discover->ip.check = discover->udp.len;
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersen
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersen udp_check = ~dhcp_packet_checksum(&discover->ip.ttl, len - 8);
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersen assert_se(udp_check == 0xffff);
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersen
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersen discover->ip.ttl = IPDEFTTL;
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersen discover->ip.check = ip_check;
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersen
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersen ip_check = ~dhcp_packet_checksum(&discover->ip, sizeof(discover->ip));
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersen assert_se(ip_check == 0xffff);
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersen
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersen assert_se(discover->dhcp.xid);
assert_se(memcmp(discover->dhcp.chaddr,
&mac_addr.ether_addr_octet, 6) == 0);
size = len - sizeof(struct iphdr) - sizeof(struct udphdr);
assert_se(callback_recv);
callback_recv(size, &discover->dhcp);
return 575;
}
int dhcp_network_bind_raw_socket(int index, union sockaddr_union *link, uint32_t id)
{
if (socketpair(AF_UNIX, SOCK_STREAM, 0, test_fd) < 0)
return -errno;
return test_fd[0];
}
int dhcp_network_bind_udp_socket(int index, be32_t address, uint16_t port)
{
return 0;
}
int dhcp_network_send_udp_socket(int s, be32_t address, uint16_t port,
const void *packet, size_t len)
{
return 0;
}
static int test_discover_message_verify(size_t size, struct DHCPMessage *dhcp)
{
int res;
res = dhcp_option_parse(dhcp, size, check_options, NULL);
assert_se(res == DHCP_DISCOVER);
if (verbose)
printf(" recv DHCP Discover 0x%08x\n", be32toh(dhcp->xid));
return 0;
}
static void test_discover_message(sd_event *e)
{
sd_dhcp_client *client;
int res, r;
if (verbose)
printf("* %s\n", __FUNCTION__);
r = sd_dhcp_client_new(&client);
assert_se(r >= 0);
assert_se(client);
r = sd_dhcp_client_attach_event(client, e, 0);
assert_se(r >= 0);
assert_se(sd_dhcp_client_set_index(client, 42) >= 0);
assert_se(sd_dhcp_client_set_mac(client, &mac_addr) >= 0);
assert_se(sd_dhcp_client_set_request_option(client, 248) >= 0);
callback_recv = test_discover_message_verify;
res = sd_dhcp_client_start(client);
assert_se(res == 0 || res == -EINPROGRESS);
sd_event_run(e, (uint64_t) -1);
sd_dhcp_client_stop(client);
sd_dhcp_client_free(client);
test_fd[1] = safe_close(test_fd[1]);
callback_recv = NULL;
}
static uint8_t test_addr_acq_offer[] = {
0x45, 0x10, 0x01, 0x48, 0x00, 0x00, 0x00, 0x00,
0x80, 0x11, 0xb3, 0x84, 0xc0, 0xa8, 0x02, 0x01,
0xc0, 0xa8, 0x02, 0xbf, 0x00, 0x43, 0x00, 0x44,
0x01, 0x34, 0x00, 0x00, 0x02, 0x01, 0x06, 0x00,
0x6f, 0x95, 0x2f, 0x30, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0xc0, 0xa8, 0x02, 0xbf,
0xc0, 0xa8, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x63, 0x82, 0x53, 0x63, 0x35, 0x01, 0x02, 0x36,
0x04, 0xc0, 0xa8, 0x02, 0x01, 0x33, 0x04, 0x00,
0x00, 0x02, 0x58, 0x01, 0x04, 0xff, 0xff, 0xff,
0x00, 0x2a, 0x04, 0xc0, 0xa8, 0x02, 0x01, 0x0f,
0x09, 0x6c, 0x61, 0x62, 0x2e, 0x69, 0x6e, 0x74,
0x72, 0x61, 0x03, 0x04, 0xc0, 0xa8, 0x02, 0x01,
0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
};
static uint8_t test_addr_acq_ack[] = {
0x45, 0x10, 0x01, 0x48, 0x00, 0x00, 0x00, 0x00,
0x80, 0x11, 0xb3, 0x84, 0xc0, 0xa8, 0x02, 0x01,
0xc0, 0xa8, 0x02, 0xbf, 0x00, 0x43, 0x00, 0x44,
0x01, 0x34, 0x00, 0x00, 0x02, 0x01, 0x06, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0xc0, 0xa8, 0x02, 0xbf,
0xc0, 0xa8, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x63, 0x82, 0x53, 0x63, 0x35, 0x01, 0x05, 0x36,
0x04, 0xc0, 0xa8, 0x02, 0x01, 0x33, 0x04, 0x00,
0x00, 0x02, 0x58, 0x01, 0x04, 0xff, 0xff, 0xff,
0x00, 0x2a, 0x04, 0xc0, 0xa8, 0x02, 0x01, 0x0f,
0x09, 0x6c, 0x61, 0x62, 0x2e, 0x69, 0x6e, 0x74,
0x72, 0x61, 0x03, 0x04, 0xc0, 0xa8, 0x02, 0x01,
0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
};
static void test_addr_acq_acquired(sd_dhcp_client *client, int event,
void *userdata) {
sd_event *e = userdata;
sd_dhcp_lease *lease;
struct in_addr addr;
assert_se(client);
assert_se(event == DHCP_EVENT_IP_ACQUIRE);
assert_se(sd_dhcp_client_get_lease(client, &lease) >= 0);
assert_se(lease);
assert_se(sd_dhcp_lease_get_address(lease, &addr) >= 0);
assert_se(memcmp(&addr.s_addr, &test_addr_acq_ack[44],
sizeof(addr.s_addr)) == 0);
assert_se(sd_dhcp_lease_get_netmask(lease, &addr) >= 0);
assert_se(memcmp(&addr.s_addr, &test_addr_acq_ack[285],
sizeof(addr.s_addr)) == 0);
assert_se(sd_dhcp_lease_get_router(lease, &addr) >= 0);
assert_se(memcmp(&addr.s_addr, &test_addr_acq_ack[308],
sizeof(addr.s_addr)) == 0);
if (verbose)
printf(" DHCP address acquired\n");
sd_event_exit(e, 0);
}
static int test_addr_acq_recv_request(size_t size, DHCPMessage *request) {
uint16_t udp_check = 0;
uint8_t *msg_bytes = (uint8_t *)request;
int res;
res = dhcp_option_parse(request, size, check_options, NULL);
assert_se(res == DHCP_REQUEST);
assert_se(xid == request->xid);
assert_se(msg_bytes[size - 1] == DHCP_OPTION_END);
if (verbose)
printf(" recv DHCP Request 0x%08x\n", be32toh(xid));
memcpy(&test_addr_acq_ack[26], &udp_check, sizeof(udp_check));
memcpy(&test_addr_acq_ack[32], &xid, sizeof(xid));
memcpy(&test_addr_acq_ack[56], &mac_addr.ether_addr_octet,
ETHER_ADDR_LEN);
callback_recv = NULL;
res = write(test_fd[1], test_addr_acq_ack,
sizeof(test_addr_acq_ack));
assert_se(res == sizeof(test_addr_acq_ack));
if (verbose)
printf(" send DHCP Ack\n");
return 0;
};
static int test_addr_acq_recv_discover(size_t size, DHCPMessage *discover) {
uint16_t udp_check = 0;
uint8_t *msg_bytes = (uint8_t *)discover;
int res;
res = dhcp_option_parse(discover, size, check_options, NULL);
assert_se(res == DHCP_DISCOVER);
assert_se(msg_bytes[size - 1] == DHCP_OPTION_END);
xid = discover->xid;
if (verbose)
printf(" recv DHCP Discover 0x%08x\n", be32toh(xid));
memcpy(&test_addr_acq_offer[26], &udp_check, sizeof(udp_check));
memcpy(&test_addr_acq_offer[32], &xid, sizeof(xid));
memcpy(&test_addr_acq_offer[56], &mac_addr.ether_addr_octet,
ETHER_ADDR_LEN);
callback_recv = test_addr_acq_recv_request;
res = write(test_fd[1], test_addr_acq_offer,
sizeof(test_addr_acq_offer));
assert_se(res == sizeof(test_addr_acq_offer));
if (verbose)
printf(" sent DHCP Offer\n");
return 0;
}
static void test_addr_acq(sd_event *e) {
usec_t time_now = now(CLOCK_MONOTONIC);
sd_dhcp_client *client;
int res, r;
if (verbose)
printf("* %s\n", __FUNCTION__);
r = sd_dhcp_client_new(&client);
assert_se(r >= 0);
assert_se(client);
r = sd_dhcp_client_attach_event(client, e, 0);
assert_se(r >= 0);
assert_se(sd_dhcp_client_set_index(client, 42) >= 0);
assert_se(sd_dhcp_client_set_mac(client, &mac_addr) >= 0);
assert_se(sd_dhcp_client_set_callback(client, test_addr_acq_acquired, e)
>= 0);
callback_recv = test_addr_acq_recv_discover;
assert_se(sd_event_add_time(e, &test_hangcheck,
CLOCK_MONOTONIC,
time_now + 2 * USEC_PER_SEC, 0,
test_dhcp_hangcheck, NULL) >= 0);
res = sd_dhcp_client_start(client);
assert_se(res == 0 || res == -EINPROGRESS);
sd_event_loop(e);
test_hangcheck = sd_event_source_unref(test_hangcheck);
sd_dhcp_client_set_callback(client, NULL, NULL);
sd_dhcp_client_stop(client);
sd_dhcp_client_free(client);
test_fd[1] = safe_close(test_fd[1]);
callback_recv = NULL;
xid = 0;
}
int main(int argc, char *argv[]) {
sd_event *e;
assert_se(sd_event_new(&e) >= 0);
test_request_basic(e);
test_checksum();
test_discover_message(e);
test_addr_acq(e);
return 0;
}