summaryrefslogtreecommitdiff
path: root/src/libsystemd-dhcp
diff options
context:
space:
mode:
authorTom Gundersen <teg@jklm.no>2014-02-27 01:24:05 +0100
committerTom Gundersen <teg@jklm.no>2014-02-28 01:01:13 +0100
commitfe8db0c5ee3365a2fc80ee7ebffa238f9a0a2ae2 (patch)
tree51d408aaec8fa6acd19c51839cd50618c9a00321 /src/libsystemd-dhcp
parentc594cccee264cfd98f183ae6ec289b11e70f2d6c (diff)
sd-network: add new library
This is similar to sd-login, but exposes the state of networkd rather than logind. Include it in libsystemd-dhcp and rename it to libsystemd-network.
Diffstat (limited to 'src/libsystemd-dhcp')
l---------src/libsystemd-dhcp/Makefile1
-rw-r--r--src/libsystemd-dhcp/dhcp-internal.h55
-rw-r--r--src/libsystemd-dhcp/dhcp-lease.c244
-rw-r--r--src/libsystemd-dhcp/dhcp-lease.h57
-rw-r--r--src/libsystemd-dhcp/dhcp-network.c109
-rw-r--r--src/libsystemd-dhcp/dhcp-option.c184
-rw-r--r--src/libsystemd-dhcp/dhcp-packet.c190
-rw-r--r--src/libsystemd-dhcp/dhcp-protocol.h121
-rw-r--r--src/libsystemd-dhcp/sd-dhcp-client.c1051
-rw-r--r--src/libsystemd-dhcp/test-dhcp-client.c496
-rw-r--r--src/libsystemd-dhcp/test-dhcp-option.c378
11 files changed, 0 insertions, 2886 deletions
diff --git a/src/libsystemd-dhcp/Makefile b/src/libsystemd-dhcp/Makefile
deleted file mode 120000
index d0b0e8e008..0000000000
--- a/src/libsystemd-dhcp/Makefile
+++ /dev/null
@@ -1 +0,0 @@
-../Makefile \ No newline at end of file
diff --git a/src/libsystemd-dhcp/dhcp-internal.h b/src/libsystemd-dhcp/dhcp-internal.h
deleted file mode 100644
index ce83b81631..0000000000
--- a/src/libsystemd-dhcp/dhcp-internal.h
+++ /dev/null
@@ -1,55 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-#pragma once
-
-/***
- This file is part of systemd.
-
- Copyright (C) 2013 Intel Corporation. All rights reserved.
- Copyright (C) 2014 Tom Gundersen
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include <stdint.h>
-#include <linux/if_packet.h>
-
-#include "socket-util.h"
-
-#include "dhcp-protocol.h"
-
-int dhcp_network_bind_raw_socket(int index, union sockaddr_union *link);
-int dhcp_network_bind_udp_socket(int index, be32_t address, uint16_t port);
-int dhcp_network_send_raw_socket(int s, const union sockaddr_union *link,
- const void *packet, size_t len);
-int dhcp_network_send_udp_socket(int s, be32_t address, uint16_t port,
- const void *packet, size_t len);
-
-int dhcp_option_append(uint8_t **buf, size_t *buflen, uint8_t code,
- size_t optlen, const void *optval);
-
-typedef int (*dhcp_option_cb_t)(uint8_t code, uint8_t len,
- const uint8_t *option, void *user_data);
-
-int dhcp_option_parse(DHCPMessage *message, size_t len,
- dhcp_option_cb_t cb, void *user_data);
-
-int dhcp_message_init(DHCPMessage *message, uint8_t op, uint32_t xid, uint8_t type,
- uint8_t **opt, size_t *optlen);
-
-void dhcp_packet_append_ip_headers(DHCPPacket *packet, uint16_t len);
-
-int dhcp_packet_verify_headers(DHCPPacket *packet, size_t len, bool checksum);
-
-#define log_dhcp_client(client, fmt, ...) log_meta(LOG_DEBUG, __FILE__, __LINE__, __func__, "DHCP CLIENT: " fmt, ##__VA_ARGS__)
diff --git a/src/libsystemd-dhcp/dhcp-lease.c b/src/libsystemd-dhcp/dhcp-lease.c
deleted file mode 100644
index c1f76aa561..0000000000
--- a/src/libsystemd-dhcp/dhcp-lease.c
+++ /dev/null
@@ -1,244 +0,0 @@
-/***
- This file is part of systemd.
-
- Copyright (C) 2013 Intel Corporation. All rights reserved.
- Copyright (C) 2014 Tom Gundersen
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include <stdlib.h>
-#include <errno.h>
-#include <string.h>
-#include <stdio.h>
-#include <net/ethernet.h>
-#include <sys/param.h>
-
-#include "util.h"
-#include "list.h"
-
-#include "dhcp-protocol.h"
-#include "dhcp-internal.h"
-#include "dhcp-lease.h"
-#include "sd-dhcp-client.h"
-
-int sd_dhcp_lease_get_address(sd_dhcp_lease *lease, struct in_addr *addr) {
- assert_return(lease, -EINVAL);
- assert_return(addr, -EINVAL);
-
- addr->s_addr = lease->address;
-
- return 0;
-}
-
-int sd_dhcp_lease_get_mtu(sd_dhcp_lease *lease, uint16_t *mtu) {
- assert_return(lease, -EINVAL);
- assert_return(mtu, -EINVAL);
-
- if (lease->mtu)
- *mtu = lease->mtu;
- else
- return -ENOENT;
-
- return 0;
-}
-
-int sd_dhcp_lease_get_dns(sd_dhcp_lease *lease, struct in_addr **addr, size_t *addr_size) {
- assert_return(lease, -EINVAL);
- assert_return(addr, -EINVAL);
- assert_return(addr_size, -EINVAL);
-
- if (lease->dns_size) {
- *addr_size = lease->dns_size;
- *addr = lease->dns;
- } else
- return -ENOENT;
-
- return 0;
-}
-
-int sd_dhcp_lease_get_domainname(sd_dhcp_lease *lease, const char **domainname) {
- assert_return(lease, -EINVAL);
- assert_return(domainname, -EINVAL);
-
- if (lease->domainname)
- *domainname = lease->domainname;
- else
- return -ENOENT;
-
- return 0;
-}
-
-int sd_dhcp_lease_get_hostname(sd_dhcp_lease *lease, const char **hostname) {
- assert_return(lease, -EINVAL);
- assert_return(hostname, -EINVAL);
-
- if (lease->hostname)
- *hostname = lease->hostname;
- else
- return -ENOENT;
-
- return 0;
-}
-
-int sd_dhcp_lease_get_router(sd_dhcp_lease *lease, struct in_addr *addr) {
- assert_return(lease, -EINVAL);
- assert_return(addr, -EINVAL);
-
- addr->s_addr = lease->router;
-
- return 0;
-}
-
-int sd_dhcp_lease_get_netmask(sd_dhcp_lease *lease, struct in_addr *addr) {
- assert_return(lease, -EINVAL);
- assert_return(addr, -EINVAL);
-
- addr->s_addr = lease->subnet_mask;
-
- return 0;
-}
-
-sd_dhcp_lease *sd_dhcp_lease_ref(sd_dhcp_lease *lease) {
- if (lease)
- assert_se(REFCNT_INC(lease->n_ref) >= 2);
-
- return lease;
-}
-
-sd_dhcp_lease *sd_dhcp_lease_unref(sd_dhcp_lease *lease) {
- if (lease && REFCNT_DEC(lease->n_ref) <= 0) {
- free(lease->hostname);
- free(lease->domainname);
- free(lease->dns);
- free(lease);
- }
-
- return NULL;
-}
-
-int dhcp_lease_parse_options(uint8_t code, uint8_t len, const uint8_t *option,
- void *user_data) {
- sd_dhcp_lease *lease = user_data;
- be32_t val;
-
- switch(code) {
-
- case DHCP_OPTION_IP_ADDRESS_LEASE_TIME:
- if (len == 4) {
- memcpy(&val, option, 4);
- lease->lifetime = be32toh(val);
- }
-
- break;
-
- case DHCP_OPTION_SERVER_IDENTIFIER:
- if (len >= 4)
- memcpy(&lease->server_address, option, 4);
-
- break;
-
- case DHCP_OPTION_SUBNET_MASK:
- if (len >= 4)
- memcpy(&lease->subnet_mask, option, 4);
-
- break;
-
- case DHCP_OPTION_ROUTER:
- if (len >= 4)
- memcpy(&lease->router, option, 4);
-
- break;
-
- case DHCP_OPTION_DOMAIN_NAME_SERVER:
- if (len && !(len % 4)) {
- unsigned i;
-
- lease->dns_size = len / 4;
-
- free(lease->dns);
- lease->dns = new0(struct in_addr, lease->dns_size);
- if (!lease->dns)
- return -ENOMEM;
-
- for (i = 0; i < lease->dns_size; i++) {
- memcpy(&lease->dns[i].s_addr, option + 4 * i, 4);
- }
- }
-
- break;
-
- case DHCP_OPTION_INTERFACE_MTU:
- if (len >= 2) {
- be16_t mtu;
-
- memcpy(&mtu, option, 2);
- lease->mtu = be16toh(mtu);
-
- if (lease->mtu < 68)
- lease->mtu = 0;
- }
-
- break;
-
- case DHCP_OPTION_DOMAIN_NAME:
- if (len >= 1) {
- free(lease->domainname);
- lease->domainname = strndup((const char *)option, len);
- }
-
- break;
-
- case DHCP_OPTION_HOST_NAME:
- if (len >= 1) {
- free(lease->hostname);
- lease->hostname = strndup((const char *)option, len);
- }
-
- break;
-
- case DHCP_OPTION_RENEWAL_T1_TIME:
- if (len == 4) {
- memcpy(&val, option, 4);
- lease->t1 = be32toh(val);
- }
-
- break;
-
- case DHCP_OPTION_REBINDING_T2_TIME:
- if (len == 4) {
- memcpy(&val, option, 4);
- lease->t2 = be32toh(val);
- }
-
- break;
- }
-
- return 0;
-}
-
-int dhcp_lease_new(sd_dhcp_lease **ret) {
- _cleanup_dhcp_lease_unref_ sd_dhcp_lease *lease = NULL;
-
- lease = new0(sd_dhcp_lease, 1);
- if (!lease)
- return -ENOMEM;
-
- lease->n_ref = REFCNT_INIT;
-
- *ret = lease;
- lease = NULL;
-
- return 0;
-}
diff --git a/src/libsystemd-dhcp/dhcp-lease.h b/src/libsystemd-dhcp/dhcp-lease.h
deleted file mode 100644
index 87323dcb37..0000000000
--- a/src/libsystemd-dhcp/dhcp-lease.h
+++ /dev/null
@@ -1,57 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-#pragma once
-
-/***
- This file is part of systemd.
-
- Copyright (C) 2013 Intel Corporation. All rights reserved.
- Copyright (C) 2014 Tom Gundersen
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include <stdint.h>
-#include <linux/if_packet.h>
-
-#include "socket-util.h"
-#include "refcnt.h"
-
-#include "dhcp-protocol.h"
-
-#include "sd-dhcp-client.h"
-
-struct sd_dhcp_lease {
- RefCount n_ref;
-
- uint32_t t1;
- uint32_t t2;
- uint32_t lifetime;
- be32_t address;
- be32_t server_address;
- be32_t subnet_mask;
- be32_t router;
- struct in_addr *dns;
- size_t dns_size;
- uint16_t mtu;
- char *domainname;
- char *hostname;
-};
-
-int dhcp_lease_new(sd_dhcp_lease **ret);
-int dhcp_lease_parse_options(uint8_t code, uint8_t len, const uint8_t *option,
- void *user_data);
-
-DEFINE_TRIVIAL_CLEANUP_FUNC(sd_dhcp_lease*, sd_dhcp_lease_unref);
-#define _cleanup_dhcp_lease_unref_ _cleanup_(sd_dhcp_lease_unrefp)
diff --git a/src/libsystemd-dhcp/dhcp-network.c b/src/libsystemd-dhcp/dhcp-network.c
deleted file mode 100644
index 934e8bf13e..0000000000
--- a/src/libsystemd-dhcp/dhcp-network.c
+++ /dev/null
@@ -1,109 +0,0 @@
-/***
- This file is part of systemd.
-
- Copyright (C) 2013 Intel Corporation. All rights reserved.
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include <errno.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <string.h>
-#include <linux/if_packet.h>
-#include <net/ethernet.h>
-#include <stdio.h>
-#include <unistd.h>
-
-#include "socket-util.h"
-
-#include "dhcp-internal.h"
-
-int dhcp_network_bind_raw_socket(int index, union sockaddr_union *link)
-{
- int s, one = 1;
-
- assert(index > 0);
- assert(link);
-
- s = socket(AF_PACKET, SOCK_DGRAM | SOCK_CLOEXEC | SOCK_NONBLOCK,
- htons(ETH_P_IP));
- if (s < 0)
- return -errno;
-
- link->ll.sll_family = AF_PACKET;
- link->ll.sll_protocol = htons(ETH_P_IP);
- link->ll.sll_ifindex = index;
- link->ll.sll_halen = ETH_ALEN;
- memset(link->ll.sll_addr, 0xff, ETH_ALEN);
-
- if (setsockopt (s, SOL_PACKET, PACKET_AUXDATA, &one, sizeof(one)) < 0)
- return -errno;
-
- if (bind(s, &link->sa, sizeof(link->ll)) < 0) {
- close_nointr_nofail(s);
- return -errno;
- }
-
- return s;
-}
-
-int dhcp_network_bind_udp_socket(int index, be32_t address, uint16_t port)
-{
- int s;
- union sockaddr_union src = {
- .in.sin_family = AF_INET,
- .in.sin_port = htobe16(port),
- .in.sin_addr.s_addr = address,
- };
-
- s = socket(AF_INET, SOCK_DGRAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0);
- if (s < 0)
- return -errno;
-
- if (bind(s, &src.sa, sizeof(src.in)) < 0) {
- close_nointr_nofail(s);
- return -errno;
- }
-
- return s;
-}
-
-int dhcp_network_send_raw_socket(int s, const union sockaddr_union *link,
- const void *packet, size_t len)
-{
- assert(link);
- assert(packet);
- assert(len);
-
- if (sendto(s, packet, len, 0, &link->sa, sizeof(link->ll)) < 0)
- return -errno;
-
- return 0;
-}
-
-int dhcp_network_send_udp_socket(int s, be32_t address, uint16_t port,
- const void *packet, size_t len)
-{
- union sockaddr_union dest = {
- .in.sin_family = AF_INET,
- .in.sin_port = htobe16(port),
- .in.sin_addr.s_addr = address,
- };
-
- if (sendto(s, packet, len, 0, &dest.sa, sizeof(dest.in)) < 0)
- return -errno;
-
- return 0;
-}
diff --git a/src/libsystemd-dhcp/dhcp-option.c b/src/libsystemd-dhcp/dhcp-option.c
deleted file mode 100644
index 4d45b3b3a4..0000000000
--- a/src/libsystemd-dhcp/dhcp-option.c
+++ /dev/null
@@ -1,184 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
- This file is part of systemd.
-
- Copyright (C) 2013 Intel Corporation. All rights reserved.
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include <stdint.h>
-#include <string.h>
-#include <errno.h>
-#include <stdio.h>
-
-#include "dhcp-internal.h"
-
-int dhcp_option_append(uint8_t **buf, size_t *buflen, uint8_t code,
- size_t optlen, const void *optval)
-{
- if (!buf || !buflen)
- return -EINVAL;
-
- switch (code) {
-
- case DHCP_OPTION_PAD:
- case DHCP_OPTION_END:
- if (*buflen < 1)
- return -ENOBUFS;
-
- (*buf)[0] = code;
- *buf += 1;
- *buflen -= 1;
- break;
-
- default:
- if (*buflen < optlen + 2)
- return -ENOBUFS;
-
- if (!optval)
- return -EINVAL;
-
- (*buf)[0] = code;
- (*buf)[1] = optlen;
- memcpy(&(*buf)[2], optval, optlen);
-
- *buf += optlen + 2;
- *buflen -= (optlen + 2);
-
- break;
- }
-
- return 0;
-}
-
-static int parse_options(const uint8_t *buf, size_t buflen, uint8_t *overload,
- uint8_t *message_type, dhcp_option_cb_t cb,
- void *user_data)
-{
- const uint8_t *code = buf;
- const uint8_t *len;
-
- while (buflen > 0) {
- switch (*code) {
- case DHCP_OPTION_PAD:
- buflen -= 1;
- code++;
- break;
-
- case DHCP_OPTION_END:
- return 0;
-
- case DHCP_OPTION_MESSAGE_TYPE:
- if (buflen < 3)
- return -ENOBUFS;
- buflen -= 3;
-
- len = code + 1;
- if (*len != 1)
- return -EINVAL;
-
- if (message_type)
- *message_type = *(len + 1);
-
- code += 3;
-
- break;
-
- case DHCP_OPTION_OVERLOAD:
- if (buflen < 3)
- return -ENOBUFS;
- buflen -= 3;
-
- len = code + 1;
- if (*len != 1)
- return -EINVAL;
-
- if (overload)
- *overload = *(len + 1);
-
- code += 3;
-
- break;
-
- default:
- if (buflen < 3)
- return -ENOBUFS;
-
- len = code + 1;
-
- if (buflen < (size_t)*len + 2)
- return -EINVAL;
- buflen -= *len + 2;
-
- if (cb)
- cb(*code, *len, len + 1, user_data);
-
- code += *len + 2;
-
- break;
- }
- }
-
- if (buflen)
- return -EINVAL;
-
- return 0;
-}
-
-int dhcp_option_parse(DHCPMessage *message, size_t len,
- dhcp_option_cb_t cb, void *user_data)
-{
- uint8_t overload = 0;
- uint8_t message_type = 0;
- uint8_t *opt = (uint8_t *)(message + 1);
- int res;
-
- if (!message)
- return -EINVAL;
-
- if (len < sizeof(DHCPMessage) + 4)
- return -EINVAL;
-
- len -= sizeof(DHCPMessage) + 4;
-
- if (opt[0] != 0x63 && opt[1] != 0x82 && opt[2] != 0x53 &&
- opt[3] != 0x63)
- return -EINVAL;
-
- res = parse_options(&opt[4], len, &overload, &message_type,
- cb, user_data);
- if (res < 0)
- return res;
-
- if (overload & DHCP_OVERLOAD_FILE) {
- res = parse_options(message->file, sizeof(message->file),
- NULL, &message_type, cb, user_data);
- if (res < 0)
- return res;
- }
-
- if (overload & DHCP_OVERLOAD_SNAME) {
- res = parse_options(message->sname, sizeof(message->sname),
- NULL, &message_type, cb, user_data);
- if (res < 0)
- return res;
- }
-
- if (message_type)
- return message_type;
-
- return -ENOMSG;
-}
diff --git a/src/libsystemd-dhcp/dhcp-packet.c b/src/libsystemd-dhcp/dhcp-packet.c
deleted file mode 100644
index 8388e56222..0000000000
--- a/src/libsystemd-dhcp/dhcp-packet.c
+++ /dev/null
@@ -1,190 +0,0 @@
-/***
- This file is part of systemd.
-
- Copyright (C) 2013 Intel Corporation. All rights reserved.
- Copyright (C) 2014 Tom Gundersen
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include <stdlib.h>
-#include <errno.h>
-#include <string.h>
-#include <stdio.h>
-#include <net/ethernet.h>
-#include <net/if_arp.h>
-#include <sys/param.h>
-
-#include "util.h"
-#include "list.h"
-
-#include "dhcp-protocol.h"
-#include "dhcp-lease.h"
-#include "dhcp-internal.h"
-#include "sd-dhcp-client.h"
-
-#define DHCP_CLIENT_MIN_OPTIONS_SIZE 312
-
-int dhcp_message_init(DHCPMessage *message, uint8_t op, uint32_t xid,
- uint8_t type, uint8_t **opt, size_t *optlen) {
- int err;
-
- assert(op == BOOTREQUEST || op == BOOTREPLY);
-
- *opt = (uint8_t *)(message + 1);
-
- if (*optlen < 4)
- return -ENOBUFS;
- *optlen -= 4;
-
- message->op = op;
- message->htype = ARPHRD_ETHER;
- message->hlen = ETHER_ADDR_LEN;
- message->xid = htobe32(xid);
-
- (*opt)[0] = 0x63;
- (*opt)[1] = 0x82;
- (*opt)[2] = 0x53;
- (*opt)[3] = 0x63;
-
- *opt += 4;
-
- err = dhcp_option_append(opt, optlen, DHCP_OPTION_MESSAGE_TYPE, 1,
- &type);
- if (err < 0)
- return err;
-
- return 0;
-}
-
-static uint16_t dhcp_checksum(void *buf, int len) {
- uint32_t sum;
- uint16_t *check;
- int i;
- uint8_t *odd;
-
- sum = 0;
- check = buf;
-
- for (i = 0; i < len / 2 ; i++)
- sum += check[i];
-
- if (len & 0x01) {
- odd = buf;
- sum += odd[len - 1];
- }
-
- while (sum >> 16)
- sum = (sum & 0xffff) + (sum >> 16);
-
- return ~sum;
-}
-
-void dhcp_packet_append_ip_headers(DHCPPacket *packet, uint16_t len) {
- packet->ip.version = IPVERSION;
- packet->ip.ihl = DHCP_IP_SIZE / 4;
- packet->ip.tot_len = htobe16(len);
-
- packet->ip.protocol = IPPROTO_UDP;
- packet->ip.saddr = INADDR_ANY;
- packet->ip.daddr = INADDR_BROADCAST;
-
- packet->udp.source = htobe16(DHCP_PORT_CLIENT);
- packet->udp.dest = htobe16(DHCP_PORT_SERVER);
-
- packet->udp.len = htobe16(len - DHCP_IP_SIZE);
-
- packet->ip.check = packet->udp.len;
- packet->udp.check = dhcp_checksum(&packet->ip.ttl, len - 8);
-
- packet->ip.ttl = IPDEFTTL;
- packet->ip.check = 0;
- packet->ip.check = dhcp_checksum(&packet->ip, DHCP_IP_SIZE);
-}
-
-int dhcp_packet_verify_headers(DHCPPacket *packet, size_t len, bool checksum) {
- size_t hdrlen;
-
- assert(packet);
-
- /* IP */
-
- if (len < DHCP_IP_SIZE) {
- log_dhcp_client(client, "ignoring packet: packet (%zu bytes) "
- " smaller than IP header (%u bytes)", len,
- DHCP_IP_SIZE);
- return -EINVAL;
- }
-
- if (packet->ip.ihl < 5) {
- log_dhcp_client(client, "ignoring packet: IPv4 IHL (%u words) invalid",
- packet->ip.ihl);
- return -EINVAL;
- }
-
- hdrlen = packet->ip.ihl * 4;
- if (hdrlen < 20) {
- log_dhcp_client(client, "ignoring packet: IPv4 IHL (%zu bytes) "
- "smaller than minimum (20 bytes)", hdrlen);
- return -EINVAL;
- }
-
- if (len < hdrlen) {
- log_dhcp_client(client, "ignoring packet: packet (%zu bytes) "
- "smaller than expected (%zu) by IP header", len,
- hdrlen);
- return -EINVAL;
- }
-
- if (dhcp_checksum(&packet->ip, hdrlen)) {
- log_dhcp_client(client, "ignoring packet: invalid IP checksum");
- return -EINVAL;
- }
-
- /* UDP */
-
- if (len < DHCP_IP_UDP_SIZE) {
- log_dhcp_client(client, "ignoring packet: packet (%zu bytes) "
- " smaller than IP+UDP header (%u bytes)", len,
- DHCP_IP_UDP_SIZE);
- return -EINVAL;
- }
-
- if (len < hdrlen + be16toh(packet->udp.len)) {
- log_dhcp_client(client, "ignoring packet: packet (%zu bytes) "
- "smaller than expected (%zu) by UDP header", len,
- hdrlen + be16toh(packet->udp.len));
- return -EINVAL;
- }
-
- if (checksum && packet->udp.check) {
- packet->ip.check = packet->udp.len;
- packet->ip.ttl = 0;
-
- if (dhcp_checksum(&packet->ip.ttl,
- be16toh(packet->udp.len) + 12)) {
- log_dhcp_client(client, "ignoring packet: invalid UDP checksum");
- return -EINVAL;
- }
- }
-
- if (be16toh(packet->udp.dest) != DHCP_PORT_CLIENT) {
- log_dhcp_client(client, "ignoring packet: to port %u, which "
- "is not the DHCP client port (%u)",
- be16toh(packet->udp.dest), DHCP_PORT_CLIENT);
- return -EINVAL;
- }
-
- return 0;
-}
diff --git a/src/libsystemd-dhcp/dhcp-protocol.h b/src/libsystemd-dhcp/dhcp-protocol.h
deleted file mode 100644
index 81d36cef27..0000000000
--- a/src/libsystemd-dhcp/dhcp-protocol.h
+++ /dev/null
@@ -1,121 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-#pragma once
-
-/***
- This file is part of systemd.
-
- Copyright (C) 2013 Intel Corporation. All rights reserved.
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include <netinet/udp.h>
-#include <netinet/ip.h>
-#include <stdint.h>
-
-#include "macro.h"
-#include "sparse-endian.h"
-
-struct DHCPMessage {
- uint8_t op;
- uint8_t htype;
- uint8_t hlen;
- uint8_t hops;
- be32_t xid;
- be16_t secs;
- be16_t flags;
- be32_t ciaddr;
- be32_t yiaddr;
- be32_t siaddr;
- be32_t giaddr;
- uint8_t chaddr[16];
- uint8_t sname[64];
- uint8_t file[128];
-} _packed_;
-
-typedef struct DHCPMessage DHCPMessage;
-
-struct DHCPPacket {
- struct iphdr ip;
- struct udphdr udp;
- DHCPMessage dhcp;
-} _packed_;
-
-typedef struct DHCPPacket DHCPPacket;
-
-#define DHCP_IP_SIZE (int32_t)(sizeof(struct iphdr))
-#define DHCP_IP_UDP_SIZE (int32_t)(sizeof(struct udphdr) + DHCP_IP_SIZE)
-#define DHCP_MESSAGE_SIZE (int32_t)(sizeof(DHCPMessage))
-#define DHCP_MIN_OPTIONS_SIZE 312
-
-enum {
- DHCP_PORT_SERVER = 67,
- DHCP_PORT_CLIENT = 68,
-};
-
-enum DHCPState {
- DHCP_STATE_INIT = 0,
- DHCP_STATE_SELECTING = 1,
- DHCP_STATE_INIT_REBOOT = 2,
- DHCP_STATE_REBOOTING = 3,
- DHCP_STATE_REQUESTING = 4,
- DHCP_STATE_BOUND = 5,
- DHCP_STATE_RENEWING = 6,
- DHCP_STATE_REBINDING = 7,
-};
-
-typedef enum DHCPState DHCPState;
-
-enum {
- BOOTREQUEST = 1,
- BOOTREPLY = 2,
-};
-
-enum {
- DHCP_DISCOVER = 1,
- DHCP_OFFER = 2,
- DHCP_REQUEST = 3,
- DHCP_DECLINE = 4,
- DHCP_ACK = 5,
- DHCP_NAK = 6,
- DHCP_RELEASE = 7,
-};
-
-enum {
- DHCP_OVERLOAD_FILE = 1,
- DHCP_OVERLOAD_SNAME = 2,
-};
-
-enum {
- DHCP_OPTION_PAD = 0,
- DHCP_OPTION_SUBNET_MASK = 1,
- DHCP_OPTION_ROUTER = 3,
- DHCP_OPTION_DOMAIN_NAME_SERVER = 6,
- DHCP_OPTION_HOST_NAME = 12,
- DHCP_OPTION_DOMAIN_NAME = 15,
- DHCP_OPTION_INTERFACE_MTU = 26,
- DHCP_OPTION_NTP_SERVER = 42,
- DHCP_OPTION_REQUESTED_IP_ADDRESS = 50,
- DHCP_OPTION_IP_ADDRESS_LEASE_TIME = 51,
- DHCP_OPTION_OVERLOAD = 52,
- DHCP_OPTION_MESSAGE_TYPE = 53,
- DHCP_OPTION_SERVER_IDENTIFIER = 54,
- DHCP_OPTION_PARAMETER_REQUEST_LIST = 55,
- DHCP_OPTION_MAXIMUM_MESSAGE_SIZE = 57,
- DHCP_OPTION_RENEWAL_T1_TIME = 58,
- DHCP_OPTION_REBINDING_T2_TIME = 59,
- DHCP_OPTION_CLIENT_IDENTIFIER = 61,
- DHCP_OPTION_END = 255,
-};
diff --git a/src/libsystemd-dhcp/sd-dhcp-client.c b/src/libsystemd-dhcp/sd-dhcp-client.c
deleted file mode 100644
index 0c82260dfd..0000000000
--- a/src/libsystemd-dhcp/sd-dhcp-client.c
+++ /dev/null
@@ -1,1051 +0,0 @@
-/***
- This file is part of systemd.
-
- Copyright (C) 2013 Intel Corporation. All rights reserved.
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include <stdlib.h>
-#include <errno.h>
-#include <string.h>
-#include <stdio.h>
-#include <net/ethernet.h>
-#include <sys/param.h>
-#include <sys/ioctl.h>
-
-#include "util.h"
-#include "list.h"
-
-#include "dhcp-protocol.h"
-#include "dhcp-lease.h"
-#include "dhcp-internal.h"
-#include "sd-dhcp-client.h"
-
-struct sd_dhcp_client {
- DHCPState state;
- sd_event *event;
- int event_priority;
- sd_event_source *timeout_resend;
- int index;
- int fd;
- union sockaddr_union link;
- sd_event_source *receive_message;
- uint8_t *req_opts;
- size_t req_opts_allocated;
- size_t req_opts_size;
- be32_t last_addr;
- struct ether_addr mac_addr;
- uint32_t xid;
- usec_t start_time;
- uint16_t secs;
- unsigned int attempt;
- usec_t request_sent;
- sd_event_source *timeout_t1;
- sd_event_source *timeout_t2;
- sd_event_source *timeout_expire;
- sd_dhcp_client_cb_t cb;
- void *userdata;
- sd_dhcp_lease *lease;
-};
-
-static const uint8_t default_req_opts[] = {
- DHCP_OPTION_SUBNET_MASK,
- DHCP_OPTION_ROUTER,
- DHCP_OPTION_HOST_NAME,
- DHCP_OPTION_DOMAIN_NAME,
- DHCP_OPTION_DOMAIN_NAME_SERVER,
- DHCP_OPTION_NTP_SERVER,
-};
-
-static int client_receive_message_raw(sd_event_source *s, int fd,
- uint32_t revents, void *userdata);
-static int client_receive_message_udp(sd_event_source *s, int fd,
- uint32_t revents, void *userdata);
-
-int sd_dhcp_client_set_callback(sd_dhcp_client *client, sd_dhcp_client_cb_t cb,
- void *userdata) {
- assert_return(client, -EINVAL);
-
- client->cb = cb;
- client->userdata = userdata;
-
- return 0;
-}
-
-int sd_dhcp_client_set_request_option(sd_dhcp_client *client, uint8_t option) {
- size_t i;
-
- assert_return(client, -EINVAL);
- assert_return (client->state == DHCP_STATE_INIT, -EBUSY);
-
- switch(option) {
- case DHCP_OPTION_PAD:
- case DHCP_OPTION_OVERLOAD:
- case DHCP_OPTION_MESSAGE_TYPE:
- case DHCP_OPTION_PARAMETER_REQUEST_LIST:
- case DHCP_OPTION_END:
- return -EINVAL;
-
- default:
- break;
- }
-
- for (i = 0; i < client->req_opts_size; i++)
- if (client->req_opts[i] == option)
- return -EEXIST;
-
- if (!GREEDY_REALLOC(client->req_opts, client->req_opts_allocated,
- client->req_opts_size + 1))
- return -ENOMEM;
-
- client->req_opts[client->req_opts_size++] = option;
-
- return 0;
-}
-
-int sd_dhcp_client_set_request_address(sd_dhcp_client *client,
- const struct in_addr *last_addr) {
- assert_return(client, -EINVAL);
- assert_return(client->state == DHCP_STATE_INIT, -EBUSY);
-
- if (last_addr)
- client->last_addr = last_addr->s_addr;
- else
- client->last_addr = INADDR_ANY;
-
- return 0;
-}
-
-int sd_dhcp_client_set_index(sd_dhcp_client *client, int interface_index) {
- assert_return(client, -EINVAL);
- assert_return(client->state == DHCP_STATE_INIT, -EBUSY);
- assert_return(interface_index >= -1, -EINVAL);
-
- client->index = interface_index;
-
- return 0;
-}
-
-int sd_dhcp_client_set_mac(sd_dhcp_client *client,
- const struct ether_addr *addr) {
- assert_return(client, -EINVAL);
- assert_return(client->state == DHCP_STATE_INIT, -EBUSY);
-
- memcpy(&client->mac_addr, addr, ETH_ALEN);
-
- return 0;
-}
-
-int sd_dhcp_client_get_lease(sd_dhcp_client *client, sd_dhcp_lease **ret) {
- assert_return(client, -EINVAL);
- assert_return(ret, -EINVAL);
-
- if (client->state != DHCP_STATE_BOUND &&
- client->state != DHCP_STATE_RENEWING &&
- client->state != DHCP_STATE_REBINDING)
- return -EADDRNOTAVAIL;
-
- *ret = sd_dhcp_lease_ref(client->lease);
-
- return 0;
-}
-
-static int client_notify(sd_dhcp_client *client, int event) {
- if (client->cb)
- client->cb(client, event, client->userdata);
-
- return 0;
-}
-
-static int client_stop(sd_dhcp_client *client, int error) {
- assert_return(client, -EINVAL);
-
- client->receive_message =
- sd_event_source_unref(client->receive_message);
-
- if (client->fd >= 0)
- close(client->fd);
- client->fd = -1;
-
- client->timeout_resend = sd_event_source_unref(client->timeout_resend);
-
- client->timeout_t1 = sd_event_source_unref(client->timeout_t1);
- client->timeout_t2 = sd_event_source_unref(client->timeout_t2);
- client->timeout_expire = sd_event_source_unref(client->timeout_expire);
-
- client->attempt = 1;
-
- client_notify(client, error);
-
- client->start_time = 0;
- client->secs = 0;
- client->state = DHCP_STATE_INIT;
-
- if (client->lease)
- client->lease = sd_dhcp_lease_unref(client->lease);
-
- log_dhcp_client(client, "STOPPED");
-
- return 0;
-}
-
-static int client_message_init(sd_dhcp_client *client, DHCPMessage *message,
- uint8_t type, uint16_t secs, uint8_t **opt,
- size_t *optlen) {
- int r;
-
- assert(secs);
-
- r = dhcp_message_init(message, BOOTREQUEST, client->xid, type, opt,
- optlen);
- if (r < 0)
- return r;
-
- /* Although 'secs' field is a SHOULD in RFC 2131, certain DHCP servers
- refuse to issue an DHCP lease if 'secs' is set to zero */
- message->secs = htobe16(secs);
-
- memcpy(&message->chaddr, &client->mac_addr, ETH_ALEN);
-
- if (client->state == DHCP_STATE_RENEWING ||
- client->state == DHCP_STATE_REBINDING)
- message->ciaddr = client->lease->address;
-
- /* Some DHCP servers will refuse to issue an DHCP lease if the Client
- Identifier option is not set */
- r = dhcp_option_append(opt, optlen, DHCP_OPTION_CLIENT_IDENTIFIER,
- ETH_ALEN, &client->mac_addr);
- if (r < 0)
- return r;
-
- if (type == DHCP_DISCOVER || type == DHCP_REQUEST) {
- be16_t max_size;
-
- r = dhcp_option_append(opt, optlen,
- DHCP_OPTION_PARAMETER_REQUEST_LIST,
- client->req_opts_size,
- client->req_opts);
- if (r < 0)
- return r;
-
- /* Some DHCP servers will send bigger DHCP packets than the
- defined default size unless the Maximum Messge Size option
- is explicitely set */
- max_size = htobe16(DHCP_IP_UDP_SIZE + DHCP_MESSAGE_SIZE +
- DHCP_MIN_OPTIONS_SIZE);
- r = dhcp_option_append(opt, optlen,
- DHCP_OPTION_MAXIMUM_MESSAGE_SIZE,
- 2, &max_size);
- if (r < 0)
- return r;
- }
-
- return 0;
-}
-
-static int client_send_discover(sd_dhcp_client *client, uint16_t secs) {
- int err = 0;
- _cleanup_free_ DHCPPacket *discover;
- size_t optlen, len;
- uint8_t *opt;
-
- optlen = DHCP_MIN_OPTIONS_SIZE;
- len = sizeof(DHCPPacket) + optlen;
-
- discover = malloc0(len);
-
- if (!discover)
- return -ENOMEM;
-
- err = client_message_init(client, &discover->dhcp, DHCP_DISCOVER,
- secs, &opt, &optlen);
- if (err < 0)
- return err;
-
- if (client->last_addr != INADDR_ANY) {
- err = dhcp_option_append(&opt, &optlen,
- DHCP_OPTION_REQUESTED_IP_ADDRESS,
- 4, &client->last_addr);
- if (err < 0)
- return err;
- }
-
- err = dhcp_option_append(&opt, &optlen, DHCP_OPTION_END, 0, NULL);
- if (err < 0)
- return err;
-
- dhcp_packet_append_ip_headers(discover, len);
-
- err = dhcp_network_send_raw_socket(client->fd, &client->link,
- discover, len);
-
- log_dhcp_client(client, "DISCOVER");
-
- return err;
-}
-
-static int client_send_request(sd_dhcp_client *client, uint16_t secs) {
- _cleanup_free_ DHCPPacket *request;
- size_t optlen, len;
- int err;
- uint8_t *opt;
-
- optlen = DHCP_MIN_OPTIONS_SIZE;
- len = sizeof(DHCPPacket) + optlen;
-
- request = malloc0(len);
- if (!request)
- return -ENOMEM;
-
- err = client_message_init(client, &request->dhcp, DHCP_REQUEST, secs,
- &opt, &optlen);
- if (err < 0)
- return err;
-
- if (client->state == DHCP_STATE_REQUESTING) {
- err = dhcp_option_append(&opt, &optlen,
- DHCP_OPTION_REQUESTED_IP_ADDRESS,
- 4, &client->lease->address);
- if (err < 0)
- return err;
-
- err = dhcp_option_append(&opt, &optlen,
- DHCP_OPTION_SERVER_IDENTIFIER,
- 4, &client->lease->server_address);
- if (err < 0)
- return err;
- }
-
- err = dhcp_option_append(&opt, &optlen, DHCP_OPTION_END, 0, NULL);
- if (err < 0)
- return err;
-
- if (client->state == DHCP_STATE_RENEWING) {
- err = dhcp_network_send_udp_socket(client->fd,
- client->lease->server_address,
- DHCP_PORT_SERVER,
- &request->dhcp,
- len - DHCP_IP_UDP_SIZE);
- } else {
- dhcp_packet_append_ip_headers(request, len);
-
- err = dhcp_network_send_raw_socket(client->fd, &client->link,
- request, len);
- }
-
- log_dhcp_client(client, "REQUEST");
-
- return err;
-}
-
-static uint16_t client_update_secs(sd_dhcp_client *client, usec_t time_now)
-{
- client->secs = ((time_now - client->start_time) / USEC_PER_SEC) ? : 1;
-
- return client->secs;
-}
-
-static int client_timeout_resend(sd_event_source *s, uint64_t usec,
- void *userdata) {
- sd_dhcp_client *client = userdata;
- usec_t next_timeout = 0;
- uint32_t time_left;
- int r = 0;
-
- assert(s);
- assert(client);
- assert(client->event);
-
- switch (client->state) {
- case DHCP_STATE_RENEWING:
-
- time_left = (client->lease->t2 - client->lease->t1) / 2;
- if (time_left < 60)
- time_left = 60;
-
- next_timeout = usec + time_left * USEC_PER_SEC;
-
- break;
-
- case DHCP_STATE_REBINDING:
-
- time_left = (client->lease->lifetime - client->lease->t2) / 2;
- if (time_left < 60)
- time_left = 60;
-
- next_timeout = usec + time_left * USEC_PER_SEC;
- break;
-
- case DHCP_STATE_INIT:
- case DHCP_STATE_INIT_REBOOT:
- case DHCP_STATE_REBOOTING:
- case DHCP_STATE_SELECTING:
- case DHCP_STATE_REQUESTING:
- case DHCP_STATE_BOUND:
-
- if (client->attempt < 64)
- client->attempt *= 2;
-
- next_timeout = usec + (client->attempt - 1) * USEC_PER_SEC;
-
- break;
- }
-
- next_timeout += (random_u32() & 0x1fffff);
-
- client->timeout_resend = sd_event_source_unref(client->timeout_resend);
-
- r = sd_event_add_monotonic(client->event,
- &client->timeout_resend,
- next_timeout,
- 10 * USEC_PER_MSEC,
- client_timeout_resend, client);
- if (r < 0)
- goto error;
-
- r = sd_event_source_set_priority(client->timeout_resend,
- client->event_priority);
- if (r < 0)
- goto error;
-
- switch (client->state) {
- case DHCP_STATE_INIT:
-
- client_update_secs(client, usec);
-
- r = client_send_discover(client, client->secs);
- if (r >= 0) {
- client->state = DHCP_STATE_SELECTING;
- client->attempt = 1;
- } else {
- if (client->attempt >= 64)
- goto error;
- }
-
- break;
-
- case DHCP_STATE_SELECTING:
- client_update_secs(client, usec);
-
- r = client_send_discover(client, client->secs);
- if (r < 0 && client->attempt >= 64)
- goto error;
-
- break;
-
- case DHCP_STATE_REQUESTING:
- case DHCP_STATE_RENEWING:
- case DHCP_STATE_REBINDING:
- r = client_send_request(client, client->secs);
- if (r < 0 && client->attempt >= 64)
- goto error;
-
- client->request_sent = usec;
-
- break;
-
- case DHCP_STATE_INIT_REBOOT:
- case DHCP_STATE_REBOOTING:
- case DHCP_STATE_BOUND:
-
- break;
- }
-
- return 0;
-
-error:
- client_stop(client, r);
-
- /* Errors were dealt with when stopping the client, don't spill
- errors into the event loop handler */
- return 0;
-}
-
-static int client_initialize_events(sd_dhcp_client *client,
- sd_event_io_handler_t io_callback,
- usec_t usec) {
- int r;
-
- assert(client);
- assert(client->event);
-
- r = sd_event_add_io(client->event, &client->receive_message,
- client->fd, EPOLLIN, io_callback,
- client);
- if (r < 0)
- goto error;
-
- r = sd_event_source_set_priority(client->receive_message,
- client->event_priority);
- if (r < 0)
- goto error;
-
- client->timeout_resend = sd_event_source_unref(client->timeout_resend);
-
- r = sd_event_add_monotonic(client->event,
- &client->timeout_resend,
- usec, 0,
- client_timeout_resend, client);
- if (r < 0)
- goto error;
-
- r = sd_event_source_set_priority(client->timeout_resend,
- client->event_priority);
-
-error:
- if (r < 0)
- client_stop(client, r);
-
- return 0;
-
-}
-
-static int client_timeout_expire(sd_event_source *s, uint64_t usec,
- void *userdata) {
- sd_dhcp_client *client = userdata;
-
- log_dhcp_client(client, "EXPIRED");
-
- client_stop(client, DHCP_EVENT_EXPIRED);
-
- return 0;
-}
-
-static int client_timeout_t2(sd_event_source *s, uint64_t usec, void *userdata) {
- sd_dhcp_client *client = userdata;
- int r;
-
- if (client->fd >= 0) {
- client->receive_message =
- sd_event_source_unref(client->receive_message);
- close(client->fd);
- client->fd = -1;
- }
-
- client->state = DHCP_STATE_REBINDING;
- client->attempt = 1;
-
- r = dhcp_network_bind_raw_socket(client->index, &client->link);
- if (r < 0) {
- client_stop(client, r);
- return 0;
- }
-
- client->fd = r;
-
- log_dhcp_client(client, "TIMEOUT T2");
-
- return client_initialize_events(client, client_receive_message_raw,
- usec);
-}
-
-static int client_timeout_t1(sd_event_source *s, uint64_t usec,
- void *userdata) {
- sd_dhcp_client *client = userdata;
- int r;
-
- client->state = DHCP_STATE_RENEWING;
- client->attempt = 1;
-
- r = dhcp_network_bind_udp_socket(client->index,
- client->lease->address,
- DHCP_PORT_CLIENT);
- if (r < 0) {
- client_stop(client, r);
- return 0;
- }
-
- client->fd = r;
-
- log_dhcp_client(client, "TIMEOUT T1");
-
- return client_initialize_events(client, client_receive_message_udp, usec);
-}
-
-static int client_handle_offer(sd_dhcp_client *client, DHCPMessage *offer,
- size_t len) {
- _cleanup_dhcp_lease_unref_ sd_dhcp_lease *lease = NULL;
- int r;
-
- r = dhcp_lease_new(&lease);
- if (r < 0)
- return r;
-
- r = dhcp_option_parse(offer, len, dhcp_lease_parse_options, lease);
- if (r != DHCP_OFFER)
- return -ENOMSG;
-
- lease->address = offer->yiaddr;
-
- if (lease->address == INADDR_ANY ||
- lease->server_address == INADDR_ANY ||
- lease->subnet_mask == INADDR_ANY ||
- lease->lifetime == 0)
- return -ENOMSG;
-
- client->lease = lease;
- lease = NULL;
-
- log_dhcp_client(client, "OFFER");
-
- return 0;
-}
-
-static int client_handle_ack(sd_dhcp_client *client, DHCPMessage *ack,
- size_t len) {
- _cleanup_dhcp_lease_unref_ sd_dhcp_lease *lease = NULL;
- int r;
-
- r = dhcp_lease_new(&lease);
- if (r < 0)
- return r;
-
- r = dhcp_option_parse(ack, len, dhcp_lease_parse_options, lease);
- if (r == DHCP_NAK) {
- log_dhcp_client(client, "NAK");
- return DHCP_EVENT_NO_LEASE;
- }
-
- if (r != DHCP_ACK)
- return -ENOMSG;
-
- lease->address = ack->yiaddr;
-
- if (lease->address == INADDR_ANY ||
- lease->server_address == INADDR_ANY ||
- lease->subnet_mask == INADDR_ANY || lease->lifetime == 0)
- return -ENOMSG;
-
- r = DHCP_EVENT_IP_ACQUIRE;
- if (client->lease) {
- if (client->lease->address != lease->address ||
- client->lease->subnet_mask != lease->subnet_mask ||
- client->lease->router != lease->router) {
- r = DHCP_EVENT_IP_CHANGE;
- }
-
- client->lease = sd_dhcp_lease_unref(client->lease);
- }
-
- client->lease = lease;
- lease = NULL;
-
- log_dhcp_client(client, "ACK");
-
- return r;
-}
-
-static uint64_t client_compute_timeout(uint64_t request_sent,
- uint32_t lifetime) {
- return request_sent + (lifetime - 3) * USEC_PER_SEC +
- + (random_u32() & 0x1fffff);
-}
-
-static int client_set_lease_timeouts(sd_dhcp_client *client, uint64_t usec) {
- uint64_t next_timeout;
- int r;
-
- assert(client);
- assert(client->event);
-
- if (client->lease->lifetime < 10)
- return -EINVAL;
-
- client->timeout_t1 = sd_event_source_unref(client->timeout_t1);
- client->timeout_t2 = sd_event_source_unref(client->timeout_t2);
- client->timeout_expire = sd_event_source_unref(client->timeout_expire);
-
- if (!client->lease->t1)
- client->lease->t1 = client->lease->lifetime / 2;
-
- next_timeout = client_compute_timeout(client->request_sent,
- client->lease->t1);
- if (next_timeout < usec)
- return -EINVAL;
-
- r = sd_event_add_monotonic(client->event,
- &client->timeout_t1,
- next_timeout,
- 10 * USEC_PER_MSEC,
- client_timeout_t1, client);
- if (r < 0)
- return r;
-
- r = sd_event_source_set_priority(client->timeout_t1,
- client->event_priority);
- if (r < 0)
- return r;
-
- if (!client->lease->t2)
- client->lease->t2 = client->lease->lifetime * 7 / 8;
-
- if (client->lease->t2 < client->lease->t1)
- return -EINVAL;
-
- if (client->lease->lifetime < client->lease->t2)
- return -EINVAL;
-
- next_timeout = client_compute_timeout(client->request_sent,
- client->lease->t2);
- if (next_timeout < usec)
- return -EINVAL;
-
- r = sd_event_add_monotonic(client->event,
- &client->timeout_t2,
- next_timeout,
- 10 * USEC_PER_MSEC,
- client_timeout_t2, client);
- if (r < 0)
- return r;
-
- r = sd_event_source_set_priority(client->timeout_t2,
- client->event_priority);
- if (r < 0)
- return r;
-
- next_timeout = client_compute_timeout(client->request_sent,
- client->lease->lifetime);
- if (next_timeout < usec)
- return -EINVAL;
-
- r = sd_event_add_monotonic(client->event,
- &client->timeout_expire, next_timeout,
- 10 * USEC_PER_MSEC,
- client_timeout_expire, client);
- if (r < 0)
- return r;
-
- r = sd_event_source_set_priority(client->timeout_expire,
- client->event_priority);
- if (r < 0)
- return r;
-
- return 0;
-}
-
-static int client_handle_message(sd_dhcp_client *client, DHCPMessage *message,
- int len, usec_t time_now) {
- int r = 0, notify_event = 0;
-
- assert(client);
- assert(client->event);
- assert(message);
-
- if (len < DHCP_MESSAGE_SIZE) {
- log_dhcp_client(client, "message too small (%d bytes): "
- "ignoring", len);
- return 0;
- }
-
- if (message->op != BOOTREPLY) {
- log_dhcp_client(client, "not a BOOTREPLY message: ignoring");
- return 0;
- }
-
- if (be32toh(message->xid) != client->xid) {
- log_dhcp_client(client, "received xid (%u) does not match "
- "expected (%u): ignoring",
- be32toh(message->xid), client->xid);
- return 0;
- }
-
- if (memcmp(&message->chaddr[0], &client->mac_addr.ether_addr_octet,
- ETHER_ADDR_LEN)) {
- log_dhcp_client(client, "received chaddr does not match "
- "expected: ignoring");
- return 0;
- }
-
- switch (client->state) {
- case DHCP_STATE_SELECTING:
-
- r = client_handle_offer(client, message, len);
- if (r >= 0) {
-
- client->timeout_resend =
- sd_event_source_unref(client->timeout_resend);
-
- client->state = DHCP_STATE_REQUESTING;
- client->attempt = 1;
-
- r = sd_event_add_monotonic(client->event,
- &client->timeout_resend,
- time_now, 0,
- client_timeout_resend,
- client);
- if (r < 0)
- goto error;
-
- r = sd_event_source_set_priority(client->timeout_resend,
- client->event_priority);
- if (r < 0)
- goto error;
- }
-
- break;
-
- case DHCP_STATE_REQUESTING:
- case DHCP_STATE_RENEWING:
- case DHCP_STATE_REBINDING:
-
- r = client_handle_ack(client, message, len);
-
- if (r == DHCP_EVENT_NO_LEASE)
- goto error;
-
- if (r >= 0) {
- client->timeout_resend =
- sd_event_source_unref(client->timeout_resend);
-
- if (client->state == DHCP_STATE_REQUESTING)
- notify_event = DHCP_EVENT_IP_ACQUIRE;
- else if (r != DHCP_EVENT_IP_ACQUIRE)
- notify_event = r;
-
- client->state = DHCP_STATE_BOUND;
- client->attempt = 1;
-
- client->last_addr = client->lease->address;
-
- r = client_set_lease_timeouts(client, time_now);
- if (r < 0)
- goto error;
-
- if (notify_event)
- client_notify(client, notify_event);
-
- client->receive_message =
- sd_event_source_unref(client->receive_message);
- close(client->fd);
- client->fd = -1;
- }
-
- r = 0;
-
- break;
-
- case DHCP_STATE_INIT:
- case DHCP_STATE_INIT_REBOOT:
- case DHCP_STATE_REBOOTING:
- case DHCP_STATE_BOUND:
-
- break;
- }
-
-error:
- if (r < 0 || r == DHCP_EVENT_NO_LEASE)
- return client_stop(client, r);
-
- return 0;
-}
-
-static int client_receive_message_udp(sd_event_source *s, int fd,
- uint32_t revents, void *userdata) {
- sd_dhcp_client *client = userdata;
- _cleanup_free_ DHCPMessage *message = NULL;
- int buflen = 0, len, r;
- usec_t time_now;
-
- assert(s);
- assert(client);
- assert(client->event);
-
- r = ioctl(fd, FIONREAD, &buflen);
- if (r < 0 || buflen <= 0)
- buflen = sizeof(DHCPMessage) + DHCP_MIN_OPTIONS_SIZE;
-
- message = malloc0(buflen);
- if (!message)
- return -ENOMEM;
-
- len = read(fd, message, buflen);
- if (len < 0)
- return 0;
-
- r = sd_event_get_now_monotonic(client->event, &time_now);
- if (r < 0)
- return client_stop(client, r);
-
- return client_handle_message(client, message, len,
- time_now);
-}
-
-static int client_receive_message_raw(sd_event_source *s, int fd,
- uint32_t revents, void *userdata) {
- sd_dhcp_client *client = userdata;
- _cleanup_free_ DHCPPacket *packet = NULL;
- usec_t time_now;
- uint8_t cmsgbuf[CMSG_LEN(sizeof(struct tpacket_auxdata))];
- struct iovec iov = {};
- struct msghdr msg = {
- .msg_iov = &iov,
- .msg_iovlen = 1,
- .msg_control = cmsgbuf,
- .msg_controllen = sizeof(cmsgbuf),
- };
- struct cmsghdr *cmsg;
- bool checksum = true;
- int buflen = 0, len, r;
-
- assert(s);
- assert(client);
- assert(client->event);
-
- r = ioctl(fd, FIONREAD, &buflen);
- if (r < 0 || buflen <= 0)
- buflen = sizeof(DHCPPacket) + DHCP_MIN_OPTIONS_SIZE;
-
- packet = malloc0(buflen);
- if (!packet)
- return -ENOMEM;
-
- iov.iov_base = packet;
- iov.iov_len = buflen;
-
- len = recvmsg(fd, &msg, 0);
- if (len < 0) {
- log_dhcp_client(client, "could not receive message from raw "
- "socket: %s", strerror(errno));
- return 0;
- }
-
- for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) {
- if (cmsg->cmsg_level == SOL_PACKET && cmsg->cmsg_type == PACKET_AUXDATA) {
- struct tpacket_auxdata *aux = (void *)CMSG_DATA(cmsg);
-
- checksum = !(aux->tp_status & TP_STATUS_CSUMNOTREADY);
- break;
- }
- }
-
- r = dhcp_packet_verify_headers(packet, len, checksum);
- if (r < 0)
- return 0;
-
- len -= DHCP_IP_UDP_SIZE;
-
- r = sd_event_get_now_monotonic(client->event, &time_now);
- if (r < 0)
- return client_stop(client, r);
-
- return client_handle_message(client, &packet->dhcp, len, time_now);
-}
-
-int sd_dhcp_client_start(sd_dhcp_client *client) {
- int r;
-
- assert_return(client, -EINVAL);
- assert_return(client->event, -EINVAL);
- assert_return(client->index > 0, -EINVAL);
- assert_return(client->state == DHCP_STATE_INIT ||
- client->state == DHCP_STATE_INIT_REBOOT, -EBUSY);
-
- client->xid = random_u32();
-
- r = dhcp_network_bind_raw_socket(client->index, &client->link);
-
- if (r < 0) {
- client_stop(client, r);
- return r;
- }
-
- client->fd = r;
- client->start_time = now(CLOCK_MONOTONIC);
- client->secs = 0;
-
- log_dhcp_client(client, "STARTED");
-
- return client_initialize_events(client, client_receive_message_raw,
- client->start_time);
-}
-
-int sd_dhcp_client_stop(sd_dhcp_client *client) {
- return client_stop(client, DHCP_EVENT_STOP);
-}
-
-int sd_dhcp_client_attach_event(sd_dhcp_client *client, sd_event *event,
- int priority) {
- int r;
-
- assert_return(client, -EINVAL);
- assert_return(!client->event, -EBUSY);
-
- if (event)
- client->event = sd_event_ref(event);
- else {
- r = sd_event_default(&client->event);
- if (r < 0)
- return 0;
- }
-
- client->event_priority = priority;
-
- return 0;
-}
-
-int sd_dhcp_client_detach_event(sd_dhcp_client *client) {
- assert_return(client, -EINVAL);
-
- client->event = sd_event_unref(client->event);
-
- return 0;
-}
-
-sd_event *sd_dhcp_client_get_event(sd_dhcp_client *client) {
- if (!client)
- return NULL;
-
- return client->event;
-}
-
-void sd_dhcp_client_free(sd_dhcp_client *client) {
- if (!client)
- return;
-
- sd_dhcp_client_stop(client);
- sd_dhcp_client_detach_event(client);
-
- free(client->req_opts);
- free(client);
-}
-
-DEFINE_TRIVIAL_CLEANUP_FUNC(sd_dhcp_client*, sd_dhcp_client_free);
-#define _cleanup_dhcp_client_free_ _cleanup_(sd_dhcp_client_freep)
-
-int sd_dhcp_client_new(sd_dhcp_client **ret) {
- _cleanup_dhcp_client_free_ sd_dhcp_client *client = NULL;
-
- assert_return(ret, -EINVAL);
-
- client = new0(sd_dhcp_client, 1);
- if (!client)
- return -ENOMEM;
-
- client->state = DHCP_STATE_INIT;
- client->index = -1;
- client->fd = -1;
- client->attempt = 1;
-
- client->req_opts_size = ELEMENTSOF(default_req_opts);
-
- client->req_opts = memdup(default_req_opts, client->req_opts_size);
- if (!client->req_opts)
- return -ENOMEM;
-
- *ret = client;
- client = NULL;
-
- return 0;
-}
diff --git a/src/libsystemd-dhcp/test-dhcp-client.c b/src/libsystemd-dhcp/test-dhcp-client.c
deleted file mode 100644
index 8061e5fa83..0000000000
--- a/src/libsystemd-dhcp/test-dhcp-client.c
+++ /dev/null
@@ -1,496 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
- This file is part of systemd.
-
- Copyright (C) 2013 Intel Corporation. All rights reserved.
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include <stdlib.h>
-#include <assert.h>
-#include <errno.h>
-#include <stdio.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <unistd.h>
-
-#include "util.h"
-#include "socket-util.h"
-
-#include "dhcp-protocol.h"
-#include "dhcp-internal.h"
-#include "sd-dhcp-client.h"
-
-static struct ether_addr mac_addr = {
- .ether_addr_octet = {'A', 'B', 'C', '1', '2', '3'}
-};
-
-typedef int (*test_callback_recv_t)(size_t size, DHCPMessage *dhcp);
-
-static bool verbose = false;
-static int test_fd[2];
-static test_callback_recv_t callback_recv;
-static be32_t xid;
-
-static void test_request_basic(sd_event *e)
-{
- int r;
-
- sd_dhcp_client *client;
-
- 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_request_option(NULL, 0) == -EINVAL);
- assert_se(sd_dhcp_client_set_request_address(NULL, NULL) == -EINVAL);
- assert_se(sd_dhcp_client_set_index(NULL, 0) == -EINVAL);
-
- assert_se(sd_dhcp_client_set_index(client, 15) == 0);
- assert_se(sd_dhcp_client_set_index(client, -42) == -EINVAL);
- assert_se(sd_dhcp_client_set_index(client, -1) == 0);
-
- assert_se(sd_dhcp_client_set_request_option(client,
- DHCP_OPTION_SUBNET_MASK) == -EEXIST);
- assert_se(sd_dhcp_client_set_request_option(client,
- DHCP_OPTION_ROUTER) == -EEXIST);
- assert_se(sd_dhcp_client_set_request_option(client,
- DHCP_OPTION_HOST_NAME) == -EEXIST);
- assert_se(sd_dhcp_client_set_request_option(client,
- DHCP_OPTION_DOMAIN_NAME) == -EEXIST);
- assert_se(sd_dhcp_client_set_request_option(client,
- DHCP_OPTION_DOMAIN_NAME_SERVER)
- == -EEXIST);
- assert_se(sd_dhcp_client_set_request_option(client,
- DHCP_OPTION_NTP_SERVER) == -EEXIST);
-
- assert_se(sd_dhcp_client_set_request_option(client,
- DHCP_OPTION_PAD) == -EINVAL);
- assert_se(sd_dhcp_client_set_request_option(client,
- DHCP_OPTION_END) == -EINVAL);
- assert_se(sd_dhcp_client_set_request_option(client,
- DHCP_OPTION_MESSAGE_TYPE) == -EINVAL);
- assert_se(sd_dhcp_client_set_request_option(client,
- DHCP_OPTION_OVERLOAD) == -EINVAL);
- assert_se(sd_dhcp_client_set_request_option(client,
- DHCP_OPTION_PARAMETER_REQUEST_LIST)
- == -EINVAL);
-
- assert_se(sd_dhcp_client_set_request_option(client, 33) == 0);
- assert_se(sd_dhcp_client_set_request_option(client, 33) == -EEXIST);
- assert_se(sd_dhcp_client_set_request_option(client, 44) == 0);
- assert_se(sd_dhcp_client_set_request_option(client, 33) == -EEXIST);
-}
-
-static uint16_t client_checksum(void *buf, int len)
-{
- uint32_t sum;
- uint16_t *check;
- int i;
- uint8_t *odd;
-
- sum = 0;
- check = buf;
-
- for (i = 0; i < len / 2 ; i++)
- sum += check[i];
-
- if (len & 0x01) {
- odd = buf;
- sum += odd[len - 1];
- }
-
- while (sum >> 16)
- sum = (sum & 0xffff) + (sum >> 16);
-
- return ~sum;
-}
-
-static void test_checksum(void)
-{
- uint8_t buf[20] = {
- 0x45, 0x00, 0x02, 0x40, 0x00, 0x00, 0x00, 0x00,
- 0x40, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0xff, 0xff, 0xff, 0xff
- };
-
- if (verbose)
- printf("* %s\n", __FUNCTION__);
-
- assert_se(client_checksum(&buf, 20) == be16toh(0x78ae));
-}
-
-static int check_options(uint8_t code, uint8_t len, const uint8_t *option,
- void *user_data)
-{
- return 0;
-}
-
-int dhcp_network_send_raw_socket(int s, const union sockaddr_union *link,
- const void *packet, size_t len)
-{
- size_t size;
- _cleanup_free_ DHCPPacket *discover;
- uint16_t ip_check, udp_check;
-
- assert_se(s >= 0);
- assert_se(packet);
-
- size = sizeof(DHCPPacket) + 4;
- assert_se(len > size);
-
- discover = memdup(packet, len);
-
- assert_se(discover->ip.ttl == IPDEFTTL);
- assert_se(discover->ip.protocol == IPPROTO_UDP);
- assert_se(discover->ip.saddr == INADDR_ANY);
- assert_se(discover->ip.daddr == INADDR_BROADCAST);
- assert_se(discover->udp.source == be16toh(DHCP_PORT_CLIENT));
- assert_se(discover->udp.dest == be16toh(DHCP_PORT_SERVER));
-
- ip_check = discover->ip.check;
-
- discover->ip.ttl = 0;
- discover->ip.check = discover->udp.len;
-
- udp_check = ~client_checksum(&discover->ip.ttl, len - 8);
- assert_se(udp_check == 0xffff);
-
- discover->ip.ttl = IPDEFTTL;
- discover->ip.check = ip_check;
-
- ip_check = ~client_checksum(&discover->ip, sizeof(discover->ip));
- assert_se(ip_check == 0xffff);
-
- 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)
-{
- 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);
-
- close(test_fd[0]);
- 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;
- int res;
-
- res = dhcp_option_parse(request, size, check_options, NULL);
- assert_se(res == DHCP_REQUEST);
- assert_se(xid == request->xid);
-
- 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;
- int res;
-
- res = dhcp_option_parse(discover, size, check_options, NULL);
- assert_se(res == DHCP_DISCOVER);
-
- 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(" send DHCP Offer\n");
-
- return 0;
-}
-
-static void test_addr_acq(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_callback(client, test_addr_acq_acquired, e)
- >= 0);
-
- callback_recv = test_addr_acq_recv_discover;
-
- res = sd_dhcp_client_start(client);
- assert_se(res == 0 || res == -EINPROGRESS);
-
- sd_event_loop(e);
-
- sd_dhcp_client_set_callback(client, NULL, NULL);
- sd_dhcp_client_stop(client);
- sd_dhcp_client_free(client);
-
- close(test_fd[0]);
- 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;
-}
diff --git a/src/libsystemd-dhcp/test-dhcp-option.c b/src/libsystemd-dhcp/test-dhcp-option.c
deleted file mode 100644
index 8659fd5025..0000000000
--- a/src/libsystemd-dhcp/test-dhcp-option.c
+++ /dev/null
@@ -1,378 +0,0 @@
-
-#include <stdio.h>
-#include <stdbool.h>
-#include <errno.h>
-#include <string.h>
-#include <assert.h>
-
-#include "util.h"
-#include "macro.h"
-
-#include "dhcp-protocol.h"
-#include "dhcp-internal.h"
-
-struct option_desc {
- uint8_t sname[64];
- int snamelen;
- uint8_t file[128];
- int filelen;
- uint8_t options[128];
- int len;
- bool success;
- int filepos;
- int snamepos;
- int pos;
-};
-
-static bool verbose = false;
-
-static struct option_desc option_tests[] = {
- { {}, 0, {}, 0, { 42, 5, 65, 66, 67, 68, 69 }, 7, false, },
- { {}, 0, {}, 0, { 42, 5, 65, 66, 67, 68, 69, 0, 0,
- DHCP_OPTION_MESSAGE_TYPE, 1, DHCP_ACK }, 12, true, },
- { {}, 0, {}, 0, { 8, 255, 70, 71, 72 }, 5, false, },
- { {}, 0, {}, 0, { 0x35, 0x01, 0x05, 0x36, 0x04, 0x01, 0x00, 0xa8,
- 0xc0, 0x33, 0x04, 0x00, 0x01, 0x51, 0x80, 0x01,
- 0x04, 0xff, 0xff, 0xff, 0x00, 0x03, 0x04, 0xc0,
- 0xa8, 0x00, 0x01, 0x06, 0x04, 0xc0, 0xa8, 0x00,
- 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, },
- 40, true, },
- { {}, 0, {}, 0, { DHCP_OPTION_MESSAGE_TYPE, 1, DHCP_OFFER,
- 42, 3, 0, 0, 0 }, 8, true, },
- { {}, 0, {}, 0, { 42, 2, 1, 2, 44 }, 5, false, },
-
- { {}, 0,
- { 222, 3, 1, 2, 3, DHCP_OPTION_MESSAGE_TYPE, 1, DHCP_NAK }, 8,
- { DHCP_OPTION_OVERLOAD, 1, DHCP_OVERLOAD_FILE }, 3, true, },
-
- { { 1, 4, 1, 2, 3, 4, DHCP_OPTION_MESSAGE_TYPE, 1, DHCP_ACK }, 9,
- { 222, 3, 1, 2, 3 }, 5,
- { DHCP_OPTION_OVERLOAD, 1,
- DHCP_OVERLOAD_FILE|DHCP_OVERLOAD_SNAME }, 3, true, },
-};
-
-static const char *dhcp_type(int type)
-{
- switch(type) {
- case DHCP_DISCOVER:
- return "DHCPDISCOVER";
- case DHCP_OFFER:
- return "DHCPOFFER";
- case DHCP_REQUEST:
- return "DHCPREQUEST";
- case DHCP_DECLINE:
- return "DHCPDECLINE";
- case DHCP_ACK:
- return "DHCPACK";
- case DHCP_NAK:
- return "DHCPNAK";
- case DHCP_RELEASE:
- return "DHCPRELEASE";
- default:
- return "unknown";
- }
-}
-
-static void test_invalid_buffer_length(void)
-{
- DHCPMessage message;
-
- assert_se(dhcp_option_parse(&message, 0, NULL, NULL) == -EINVAL);
- assert_se(dhcp_option_parse(&message, sizeof(DHCPMessage), NULL, NULL)
- == -EINVAL);
-}
-
-static void test_cookie(void)
-{
- _cleanup_free_ DHCPMessage *message;
- size_t len = sizeof(DHCPMessage) + 4;
- uint8_t *opt;
-
- message = malloc0(len);
-
- opt = (uint8_t *)(message + 1);
- opt[0] = 0xff;
-
- assert_se(dhcp_option_parse(message, len, NULL, NULL) == -EINVAL);
-
- opt[0] = 99;
- opt[1] = 130;
- opt[2] = 83;
- opt[3] = 99;
-
- assert_se(dhcp_option_parse(message, len, NULL, NULL) == -ENOMSG);
-}
-
-static DHCPMessage *create_message(uint8_t *options, uint16_t optlen,
- uint8_t *file, uint8_t filelen,
- uint8_t *sname, uint8_t snamelen)
-{
- DHCPMessage *message;
- size_t len = sizeof(DHCPMessage) + 4 + optlen;
- uint8_t *opt;
-
- message = malloc0(len);
- opt = (uint8_t *)(message + 1);
-
- opt[0] = 99;
- opt[1] = 130;
- opt[2] = 83;
- opt[3] = 99;
-
- if (options && optlen)
- memcpy(&opt[4], options, optlen);
-
- if (file && filelen <= 128)
- memcpy(&message->file, file, filelen);
-
- if (sname && snamelen <= 64)
- memcpy(&message->sname, sname, snamelen);
-
- return message;
-}
-
-static void test_ignore_opts(uint8_t *descoption, int *descpos, int *desclen)
-{
- while (*descpos < *desclen) {
- switch(descoption[*descpos]) {
- case DHCP_OPTION_PAD:
- *descpos += 1;
- break;
-
- case DHCP_OPTION_MESSAGE_TYPE:
- case DHCP_OPTION_OVERLOAD:
- *descpos += 3;
- break;
-
- default:
- return;
- }
- }
-}
-
-static int test_options_cb(uint8_t code, uint8_t len, const uint8_t *option,
- void *user_data)
-{
- struct option_desc *desc = user_data;
- uint8_t *descoption = NULL;
- int *desclen = NULL, *descpos = NULL;
- uint8_t optcode = 0;
- uint8_t optlen = 0;
- uint8_t i;
-
- assert_se((!desc && !code && !len) || desc);
-
- if (!desc)
- return -EINVAL;
-
- assert_se(code != DHCP_OPTION_PAD);
- assert_se(code != DHCP_OPTION_END);
- assert_se(code != DHCP_OPTION_MESSAGE_TYPE);
- assert_se(code != DHCP_OPTION_OVERLOAD);
-
- while (desc->pos >= 0 || desc->filepos >= 0 || desc->snamepos >= 0) {
-
- if (desc->pos >= 0) {
- descoption = &desc->options[0];
- desclen = &desc->len;
- descpos = &desc->pos;
- } else if (desc->filepos >= 0) {
- descoption = &desc->file[0];
- desclen = &desc->filelen;
- descpos = &desc->filepos;
- } else if (desc->snamepos >= 0) {
- descoption = &desc->sname[0];
- desclen = &desc->snamelen;
- descpos = &desc->snamepos;
- }
-
- assert_se(descoption && desclen && descpos);
-
- if (*desclen)
- test_ignore_opts(descoption, descpos, desclen);
-
- if (*descpos < *desclen)
- break;
-
- if (*descpos == *desclen)
- *descpos = -1;
- }
-
- assert_se(descpos);
- assert_se(*descpos != -1);
-
- optcode = descoption[*descpos];
- optlen = descoption[*descpos + 1];
-
- if (verbose)
- printf("DHCP code %2d(%2d) len %2d(%2d) ", code, optcode,
- len, optlen);
-
- assert_se(code == optcode);
- assert_se(len == optlen);
-
- for (i = 0; i < len; i++) {
-
- if (verbose)
- printf("0x%02x(0x%02x) ", option[i],
- descoption[*descpos + 2 + i]);
-
- assert_se(option[i] == descoption[*descpos + 2 + i]);
- }
-
- if (verbose)
- printf("\n");
-
- *descpos += optlen + 2;
-
- test_ignore_opts(descoption, descpos, desclen);
-
- if (desc->pos != -1 && desc->pos == desc->len)
- desc->pos = -1;
-
- if (desc->filepos != -1 && desc->filepos == desc->filelen)
- desc->filepos = -1;
-
- if (desc->snamepos != -1 && desc->snamepos == desc->snamelen)
- desc->snamepos = -1;
-
- return 0;
-}
-
-static void test_options(struct option_desc *desc)
-{
- uint8_t *options = NULL;
- uint8_t *file = NULL;
- uint8_t *sname = NULL;
- int optlen = 0;
- int filelen = 0;
- int snamelen = 0;
- int buflen = 0;
- _cleanup_free_ DHCPMessage *message;
- int res;
-
- if (desc) {
- file = &desc->file[0];
- filelen = desc->filelen;
- if (!filelen)
- desc->filepos = -1;
-
- sname = &desc->sname[0];
- snamelen = desc->snamelen;
- if (!snamelen)
- desc->snamepos = -1;
-
- options = &desc->options[0];
- optlen = desc->len;
- desc->pos = 0;
- }
- message = create_message(options, optlen, file, filelen,
- sname, snamelen);
-
- buflen = sizeof(DHCPMessage) + 4 + optlen;
-
- if (!desc) {
- assert_se((res = dhcp_option_parse(message, buflen,
- test_options_cb,
- NULL)) == -ENOMSG);
- } else if (desc->success) {
- assert_se((res = dhcp_option_parse(message, buflen,
- test_options_cb,
- desc)) >= 0);
- assert_se(desc->pos == -1 && desc->filepos == -1 &&
- desc->snamepos == -1);
- } else
- assert_se((res = dhcp_option_parse(message, buflen,
- test_options_cb,
- desc)) < 0);
-
- if (verbose)
- printf("DHCP type %s\n", dhcp_type(res));
-}
-
-static uint8_t result[64] = {
- 'A', 'B', 'C', 'D',
-};
-
-static uint8_t options[64] = {
- 'A', 'B', 'C', 'D',
- 160, 2, 0x11, 0x12,
- 0,
- 31, 8, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38,
- 0,
- 55, 3, 0x51, 0x52, 0x53,
- 17, 7, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
- 255
-};
-
-static void test_option_set(void)
-{
- size_t len, oldlen;
- int pos, i;
- uint8_t *opt;
-
- assert_se(dhcp_option_append(NULL, NULL, 0, 0, NULL) == -EINVAL);
-
- len = 0;
- opt = &result[0];
- assert_se(dhcp_option_append(&opt, NULL, 0, 0, NULL) == -EINVAL);
- assert_se(opt == &result[0] && len == 0);
-
- assert_se(dhcp_option_append(&opt, &len, DHCP_OPTION_PAD,
- 0, NULL) == -ENOBUFS);
- assert_se(opt == &result[0] && len == 0);
-
- opt = &result[4];
- len = 1;
- assert_se(dhcp_option_append(&opt, &len, DHCP_OPTION_PAD,
- 0, NULL) >= 0);
- assert_se(opt == &result[5] && len == 0);
-
- pos = 4;
- len = 60;
- while (pos < 64 && options[pos] != DHCP_OPTION_END) {
- opt = &result[pos];
- oldlen = len;
-
- assert_se(dhcp_option_append(&opt, &len, options[pos],
- options[pos + 1],
- &options[pos + 2]) >= 0);
-
- if (options[pos] == DHCP_OPTION_PAD) {
- assert_se(opt == &result[pos + 1]);
- assert_se(len == oldlen - 1);
- pos++;
- } else {
- assert_se(opt == &result[pos + 2 + options[pos + 1]]);
- assert_se(len == oldlen - 2 - options[pos + 1]);
- pos += 2 + options[pos + 1];
- }
- }
-
- for (i = 0; i < pos; i++) {
- if (verbose)
- printf("%2d: 0x%02x(0x%02x)\n", i, result[i],
- options[i]);
- assert_se(result[i] == options[i]);
- }
-
- if (verbose)
- printf ("\n");
-}
-
-int main(int argc, char *argv[])
-{
- unsigned int i;
-
- test_invalid_buffer_length();
- test_cookie();
-
- test_options(NULL);
-
- for (i = 0; i < ELEMENTSOF(option_tests); i++)
- test_options(&option_tests[i]);
-
- test_option_set();
-
- return 0;
-}