[systemd-devel] [PATCH 02/28] dhcp: Add DHCP client initialization
Zbigniew Jędrzejewski-Szmek
zbyszek at in.waw.pl
Wed Nov 13 15:43:59 PST 2013
On Wed, Nov 13, 2013 at 11:22:30PM +0200, Patrik Flykt wrote:
> Provide functionality for initializing a DHCP client struct, setting
> interface index, last used address and additional options to request.
> On initialization the most useful options are added by default.
> ---
> src/dhcp/client.c | 137 +++++++++++++++++++++++++++++++++++++++++++++++++++++
> src/dhcp/client.h | 34 +++++++++++++
> 2 files changed, 171 insertions(+)
> create mode 100644 src/dhcp/client.c
> create mode 100644 src/dhcp/client.h
>
> diff --git a/src/dhcp/client.c b/src/dhcp/client.c
> new file mode 100644
> index 0000000..172ddd9
> --- /dev/null
> +++ b/src/dhcp/client.c
> @@ -0,0 +1,137 @@
> +/***
> + 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 "protocol.h"
> +#include "client.h"
> +
> +struct DHCPClient {
> + DHCPState state;
> + int index;
> + uint8_t *req_opts;
> + int req_opts_size;
> + struct in_addr *last_addr;
> +};
> +
> +static 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 dhcp_client_set_request_option(DHCPClient *client, uint8_t option)
> +{
> + int i;
> +
> + if (!client)
> + return -EINVAL;
> +
> + if (client->state != DHCP_STATE_INIT)
> + return -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;
> +
> + client->req_opts_size++;
> + client->req_opts = realloc(client->req_opts, client->req_opts_size);
> + if (!client->req_opts) {
> + client->req_opts_size = 0;
> + return -ENOBUFS;
> + }
Hm, you have memory leak here. And repeated realloc is slow.
Try something like this:
if (!GREEDY_REALLOC(client->req_opts,
client->req_opts_size,
client->req_opts_size + 1))
return -ENOMEM;
In general we use -ENOMEM, so for consistency it should be used here too.
> + client->req_opts[client->req_opts_size - 1] = option;
> +
> + return 0;
> +}
> +
> +int dhcp_client_set_request_address(DHCPClient *client,
> + struct in_addr *last_addr)
> +{
> + if (!client)
> + return -EINVAL;
> +
> + if (client->state != DHCP_STATE_INIT)
> + return -EBUSY;
> +
> + client->last_addr = malloc(sizeof(struct in_addr));
> + if (!client->last_addr)
> + return -ENOBUFS;
> +
> + memcpy(&client->last_addr, last_addr, sizeof(struct in_addr));
client->last_addr = memdup(last_addr, sizeof(struct in_addr));
> +
> + return 0;
> +}
> +
> +int dhcp_client_set_index(DHCPClient *client, int interface_index)
> +{
> + if (!client || interface_index < -1)
> + return -EINVAL;
> +
> + if (client->state != DHCP_STATE_INIT)
> + return -EBUSY;
> +
> + client->index = interface_index;
> +
> + return 0;
> +}
> +
> +DHCPClient *dhcp_client_new(void)
> +{
> + DHCPClient *client;
> + int i;
> +
> + client = new0(DHCPClient, 1);
> + if (!client)
> + return NULL;
> +
> + client->state = DHCP_STATE_INIT;
> + client->index = -1;
> +
> + client->req_opts_size = sizeof(default_req_opts)
> + / sizeof(default_req_opts[0]);
ELEMENTSOF(default_req_opts)
> + client->req_opts = malloc(client->req_opts_size);
> + for (i = 0; i < client->req_opts_size; i++)
> + client->req_opts[i] = default_req_opts[i];
client->req_opts = memdup_multiply(client->req_opts_size, sizeof(default_req_opts),
client->req_opts_size);
> +
> + return client;
> +}
> diff --git a/src/dhcp/client.h b/src/dhcp/client.h
> new file mode 100644
> index 0000000..447c03b
> --- /dev/null
> +++ b/src/dhcp/client.h
> @@ -0,0 +1,34 @@
> +/*-*- 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/in.h>
> +
> +struct DHCPClient;
> +typedef struct DHCPClient DHCPClient;
> +
> +int dhcp_client_set_request_option(DHCPClient *client, uint8_t option);
> +int dhcp_client_set_request_address(DHCPClient *client,
> + struct in_addr *last_address);
> +int dhcp_client_set_index(DHCPClient *client, int interface_index);
> +
> +DHCPClient *dhcp_client_new(void);
Zbyszek
More information about the systemd-devel
mailing list