mirror of
https://github.com/systemd/systemd-stable.git
synced 2024-10-28 03:25:27 +03:00
sd-dhcp-server: add basic DISCOVER/OFFER support
This commit is contained in:
parent
969b009d94
commit
4dc3556804
@ -27,6 +27,8 @@
|
||||
#include "dhcp-server-internal.h"
|
||||
#include "dhcp-internal.h"
|
||||
|
||||
#define DHCP_DEFAULT_LEASE_TIME 60
|
||||
|
||||
int sd_dhcp_server_set_address(sd_dhcp_server *server, struct in_addr *address) {
|
||||
assert_return(server, -EINVAL);
|
||||
assert_return(address, -EINVAL);
|
||||
@ -277,6 +279,64 @@ int dhcp_server_send_packet(sd_dhcp_server *server,
|
||||
sizeof(DHCPPacket) + optoffset);
|
||||
}
|
||||
|
||||
static int server_message_init(sd_dhcp_server *server, DHCPPacket **ret,
|
||||
uint8_t type, size_t *_optoffset, DHCPRequest *req) {
|
||||
_cleanup_free_ DHCPPacket *packet = NULL;
|
||||
size_t optoffset;
|
||||
int r;
|
||||
|
||||
assert(server);
|
||||
assert(ret);
|
||||
assert(_optoffset);
|
||||
assert(type == DHCP_OFFER);
|
||||
|
||||
packet = malloc0(sizeof(DHCPPacket) + req->max_optlen);
|
||||
if (!packet)
|
||||
return -ENOMEM;
|
||||
|
||||
r = dhcp_message_init(&packet->dhcp, BOOTREPLY, be32toh(req->message->xid),
|
||||
type, req->max_optlen, &optoffset);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
packet->dhcp.flags = req->message->flags;
|
||||
packet->dhcp.giaddr = req->message->giaddr;
|
||||
memcpy(&packet->dhcp.chaddr, &req->message->chaddr, ETH_ALEN);
|
||||
|
||||
*_optoffset = optoffset;
|
||||
*ret = packet;
|
||||
packet = NULL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int server_send_offer(sd_dhcp_server *server, DHCPRequest *req) {
|
||||
_cleanup_free_ DHCPPacket *packet = NULL;
|
||||
size_t offset;
|
||||
be32_t lease_time;
|
||||
int r;
|
||||
|
||||
r = server_message_init(server, &packet, DHCP_OFFER, &offset, req);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
/* for now offer a random IP */
|
||||
packet->dhcp.yiaddr = random_u32();
|
||||
|
||||
/* for one minute */
|
||||
lease_time = htobe32(DHCP_DEFAULT_LEASE_TIME);
|
||||
r = dhcp_option_append(&packet->dhcp, req->max_optlen, &offset, 0,
|
||||
DHCP_OPTION_IP_ADDRESS_LEASE_TIME, 4, &lease_time);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = dhcp_server_send_packet(server, req, packet, DHCP_OFFER, offset);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int parse_request(uint8_t code, uint8_t len, const uint8_t *option,
|
||||
void *user_data) {
|
||||
DHCPRequest *req = user_data;
|
||||
@ -377,9 +437,27 @@ int dhcp_server_handle_message(sd_dhcp_server *server, DHCPMessage *message,
|
||||
/* this only fails on critical errors */
|
||||
return r;
|
||||
|
||||
log_dhcp_server(server, "received message of type %d", type);
|
||||
switch(type) {
|
||||
case DHCP_DISCOVER:
|
||||
log_dhcp_server(server, "DISCOVER (0x%x)",
|
||||
be32toh(req->message->xid));
|
||||
|
||||
return 1;
|
||||
r = server_send_offer(server, req);
|
||||
if (r < 0) {
|
||||
/* this only fails on critical errors */
|
||||
log_dhcp_server(server, "could not send offer: %s",
|
||||
strerror(-r));
|
||||
return r;
|
||||
} else {
|
||||
log_dhcp_server(server, "OFFER (0x%x)",
|
||||
be32toh(req->message->xid));
|
||||
return DHCP_OFFER;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int server_receive_message(sd_event_source *s, int fd,
|
||||
|
@ -94,13 +94,13 @@ static void test_message_handler(void) {
|
||||
assert_se(sd_dhcp_server_attach_event(server, NULL, 0) >= 0);
|
||||
assert_se(sd_dhcp_server_start(server) >= 0);
|
||||
|
||||
assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == 1);
|
||||
assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == DHCP_OFFER);
|
||||
|
||||
test.end = 0;
|
||||
/* TODO, shouldn't this fail? */
|
||||
assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == 1);
|
||||
assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == DHCP_OFFER);
|
||||
test.end = DHCP_OPTION_END;
|
||||
assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == 1);
|
||||
assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == DHCP_OFFER);
|
||||
|
||||
test.option_type.code = 0;
|
||||
test.option_type.length = 0;
|
||||
@ -109,22 +109,22 @@ static void test_message_handler(void) {
|
||||
test.option_type.code = DHCP_OPTION_MESSAGE_TYPE;
|
||||
test.option_type.length = 1;
|
||||
test.option_type.type = DHCP_DISCOVER;
|
||||
assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == 1);
|
||||
assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == DHCP_OFFER);
|
||||
|
||||
test.message.op = 0;
|
||||
assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == 0);
|
||||
test.message.op = BOOTREQUEST;
|
||||
assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == 1);
|
||||
assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == DHCP_OFFER);
|
||||
|
||||
test.message.htype = 0;
|
||||
assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == 0);
|
||||
test.message.htype = ARPHRD_ETHER;
|
||||
assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == 1);
|
||||
assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == DHCP_OFFER);
|
||||
|
||||
test.message.hlen = 0;
|
||||
assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == 0);
|
||||
test.message.hlen = ETHER_ADDR_LEN;
|
||||
assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == 1);
|
||||
assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == DHCP_OFFER);
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
|
Loading…
Reference in New Issue
Block a user