/*** 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 "util.h" #include "list.h" #include "dhcp-protocol.h" #include "sd-dhcp-client.h" struct sd_dhcp_client { DHCPState state; int index; uint8_t *req_opts; size_t req_opts_size; uint32_t last_addr; }; 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, }; 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_size, client->req_opts_size + 1)) return -ENOMEM; client->req_opts[client->req_opts_size - 1] = 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; } sd_dhcp_client *sd_dhcp_client_new(void) { sd_dhcp_client *client; client = new0(sd_dhcp_client, 1); if (!client) return NULL; client->state = DHCP_STATE_INIT; client->index = -1; client->req_opts_size = ELEMENTSOF(default_req_opts); client->req_opts = memdup(default_req_opts, client->req_opts_size); if (!client->req_opts) { free(client); return NULL; } return client; }