[systemd-devel] [PATCH 01/24] sd-dhcp6-client: Add initial DHCPv6 client files

Patrik Flykt patrik.flykt at linux.intel.com
Fri Jun 13 06:44:51 PDT 2014


Add initial structure definition and functions for setting index, MAC
address, callback and event loop. Define protocol values and states.
---
 src/libsystemd-network/dhcp6-protocol.h  | 104 ++++++++++++++++
 src/libsystemd-network/sd-dhcp6-client.c | 203 +++++++++++++++++++++++++++++++
 src/systemd/sd-dhcp6-client.h            |  54 ++++++++
 3 files changed, 361 insertions(+)
 create mode 100644 src/libsystemd-network/dhcp6-protocol.h
 create mode 100644 src/libsystemd-network/sd-dhcp6-client.c
 create mode 100644 src/systemd/sd-dhcp6-client.h

diff --git a/src/libsystemd-network/dhcp6-protocol.h b/src/libsystemd-network/dhcp6-protocol.h
new file mode 100644
index 0000000..afe1413
--- /dev/null
+++ b/src/libsystemd-network/dhcp6-protocol.h
@@ -0,0 +1,104 @@
+/*-*- 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 "macro.h"
+#include "sparse-endian.h"
+
+struct DHCP6Message {
+        union {
+                struct {
+                        uint8_t type;
+                        uint8_t _pad[3];
+                } _packed_;
+                be32_t transaction_id;
+        };
+} _packed_;
+
+typedef struct DHCP6Message DHCP6Message;
+
+enum {
+        DHCP6_PORT_SERVER                       = 547,
+        DHCP6_PORT_CLIENT                       = 546,
+};
+
+enum {
+        DHCP6_DUID_LLT                          = 1,
+        DHCP6_DUID_EN                           = 2,
+        DHCP6_DUID_LL                           = 3,
+        DHCP6_DUID_UUID                         = 4,
+};
+
+enum DHCP6State {
+        DHCP6_STATE_STOPPED                     = 0,
+        DHCP6_STATE_RS                          = 1,
+};
+
+enum {
+        DHCP6_SOLICIT                           = 1,
+        DHCP6_ADVERTISE                         = 2,
+        DHCP6_REQUEST                           = 3,
+        DHCP6_CONFIRM                           = 4,
+        DHCP6_RENEW                             = 5,
+        DHCP6_REBIND                            = 6,
+        DHCP6_REPLY                             = 7,
+        DHCP6_RELEASE                           = 8,
+        DHCP6_DECLINE                           = 9,
+        DHCP6_RECONFIGURE                       = 10,
+        DHCP6_INFORMATION_REQUEST               = 11,
+        DHCP6_RELAY_FORW                        = 12,
+        DHCP6_RELAY_REPL                        = 13,
+        _DHCP6_MESSAGE_MAX                      = 14,
+};
+
+enum {
+        DHCP6_OPTION_CLIENTID                   = 1,
+        DHCP6_OPTION_SERVERID                   = 2,
+        DHCP6_OPTION_IA_NA                      = 3,
+        DHCP6_OPTION_IA_TA                      = 4,
+        DHCP6_OPTION_IAADDR                     = 5,
+        DHCP6_OPTION_ORO                        = 6,
+        DHCP6_OPTION_PREFERENCE                 = 7,
+        DHCP6_OPTION_ELAPSED_TIME               = 8,
+        DHCP6_OPTION_RELAY_MSG                  = 9,
+        /* option code 10 is unassigned */
+        DHCP6_OPTION_AUTH                       = 11,
+        DHCP6_OPTION_UNICAST                    = 12,
+        DHCP6_OPTION_STATUS_CODE                = 13,
+        DHCP6_OPTION_RAPID_COMMIT               = 14,
+        DHCP6_OPTION_USER_CLASS                 = 15,
+        DHCP6_OPTION_VENDOR_CLASS               = 16,
+        DHCP6_OPTION_VENDOR_OPTS                = 17,
+        DHCP6_OPTION_INTERFACE_ID               = 18,
+        DHCP6_OPTION_RECONF_MSG                 = 19,
+        DHCP6_OPTION_RECONF_ACCEPT              = 20,
+};
+
+enum {
+        DHCP6_STATUS_SUCCESS                    = 0,
+        DHCP6_STATUS_UNSPEC_FAIL                = 1,
+        DHCP6_STATUS_NO_ADDRS_AVAIL             = 2,
+        DHCP6_STATUS_NO_BINDING                 = 3,
+        DHCP6_STATUS_NOT_ON_LINK                = 4,
+        DHCP6_STATUS_USE_MULTICAST              = 5,
+        _DHCP6_STATUS_MAX                       = 6,
+};
diff --git a/src/libsystemd-network/sd-dhcp6-client.c b/src/libsystemd-network/sd-dhcp6-client.c
new file mode 100644
index 0000000..5063d4a
--- /dev/null
+++ b/src/libsystemd-network/sd-dhcp6-client.c
@@ -0,0 +1,203 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+/***
+  This file is part of systemd.
+
+  Copyright (C) 2014 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 <string.h>
+
+#include "util.h"
+#include "refcnt.h"
+
+#include "sd-dhcp6-client.h"
+#include "dhcp6-protocol.h"
+
+struct sd_dhcp6_client {
+        RefCount n_ref;
+
+        enum DHCP6State state;
+        sd_event *event;
+        int event_priority;
+        int index;
+        struct ether_addr mac_addr;
+        sd_dhcp6_client_cb_t cb;
+        void *userdata;
+};
+
+int sd_dhcp6_client_set_callback(sd_dhcp6_client *client,
+                                 sd_dhcp6_client_cb_t cb, void *userdata)
+{
+        assert_return(client, -EINVAL);
+
+        client->cb = cb;
+        client->userdata = userdata;
+
+        return 0;
+}
+
+int sd_dhcp6_client_set_index(sd_dhcp6_client *client, int interface_index)
+{
+        assert_return(client, -EINVAL);
+        assert_return(interface_index >= -1, -EINVAL);
+
+        client->index = interface_index;
+
+        return 0;
+}
+
+int sd_dhcp6_client_set_mac(sd_dhcp6_client *client,
+                            const struct ether_addr *mac_addr)
+{
+        assert_return(client, -EINVAL);
+
+        if (mac_addr)
+                memcpy(&client->mac_addr, mac_addr, sizeof(client->mac_addr));
+        else
+                memset(&client->mac_addr, 0x00, sizeof(client->mac_addr));
+
+        return 0;
+}
+
+static sd_dhcp6_client *client_notify(sd_dhcp6_client *client, int event) {
+        if (client->cb) {
+                client = sd_dhcp6_client_ref(client);
+                client->cb(client, event, client->userdata);
+                client = sd_dhcp6_client_unref(client);
+        }
+
+        return client;
+}
+
+static int client_initialize(sd_dhcp6_client *client)
+{
+        assert_return(client, -EINVAL);
+
+        client->state = DHCP6_STATE_STOPPED;
+
+        return 0;
+}
+
+static sd_dhcp6_client *client_stop(sd_dhcp6_client *client, int error) {
+        assert_return(client, NULL);
+
+        client = client_notify(client, error);
+        if (client)
+                client_initialize(client);
+
+        return client;
+}
+
+int sd_dhcp6_client_stop(sd_dhcp6_client *client)
+{
+        client_stop(client, DHCP6_EVENT_STOP);
+
+        return 0;
+}
+
+int sd_dhcp6_client_start(sd_dhcp6_client *client)
+{
+        int r = 0;
+
+        assert_return(client, -EINVAL);
+        assert_return(client->event, -EINVAL);
+        assert_return(client->index > 0, -EINVAL);
+
+        return r;
+}
+
+int sd_dhcp6_client_attach_event(sd_dhcp6_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_dhcp6_client_detach_event(sd_dhcp6_client *client) {
+        assert_return(client, -EINVAL);
+
+        client->event = sd_event_unref(client->event);
+
+        return 0;
+}
+
+sd_event *sd_dhcp6_client_get_event(sd_dhcp6_client *client) {
+        if (!client)
+                return NULL;
+
+        return client->event;
+}
+
+sd_dhcp6_client *sd_dhcp6_client_ref(sd_dhcp6_client *client) {
+        if (client)
+                assert_se(REFCNT_INC(client->n_ref) >= 2);
+
+        return client;
+}
+
+sd_dhcp6_client *sd_dhcp6_client_unref(sd_dhcp6_client *client) {
+        if (client && REFCNT_DEC(client->n_ref) <= 0) {
+
+                client_initialize(client);
+
+                sd_dhcp6_client_detach_event(client);
+
+                free(client);
+
+                return NULL;
+        }
+
+        return client;
+}
+
+DEFINE_TRIVIAL_CLEANUP_FUNC(sd_dhcp6_client*, sd_dhcp6_client_unref);
+#define _cleanup_dhcp6_client_free_ _cleanup_(sd_dhcp6_client_unrefp)
+
+int sd_dhcp6_client_new(sd_dhcp6_client **ret)
+{
+        _cleanup_dhcp6_client_free_ sd_dhcp6_client *client = NULL;
+
+        assert_return(ret, -EINVAL);
+
+        client = new0(sd_dhcp6_client, 1);
+        if (!client)
+                return -ENOMEM;
+
+        client->n_ref = REFCNT_INIT;
+
+        client->index = -1;
+
+        *ret = client;
+        client = NULL;
+
+        return 0;
+}
diff --git a/src/systemd/sd-dhcp6-client.h b/src/systemd/sd-dhcp6-client.h
new file mode 100644
index 0000000..4965011
--- /dev/null
+++ b/src/systemd/sd-dhcp6-client.h
@@ -0,0 +1,54 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+#ifndef foosddhcp6clienthfoo
+#define foosddhcp6clienthfoo
+
+/***
+  This file is part of systemd.
+
+  Copyright (C) 2014 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 <net/ethernet.h>
+
+#include "sd-event.h"
+
+enum {
+        DHCP6_EVENT_STOP                        = 0,
+};
+
+typedef struct sd_dhcp6_client sd_dhcp6_client;
+
+typedef void (*sd_dhcp6_client_cb_t)(sd_dhcp6_client *client, int event,
+                                     void *userdata);
+int sd_dhcp6_client_set_callback(sd_dhcp6_client *client,
+                                 sd_dhcp6_client_cb_t cb, void *userdata);
+
+int sd_dhcp6_client_set_index(sd_dhcp6_client *client, int interface_index);
+int sd_dhcp6_client_set_mac(sd_dhcp6_client *client,
+                            const struct ether_addr *mac_addr);
+
+int sd_dhcp6_client_stop(sd_dhcp6_client *client);
+int sd_dhcp6_client_start(sd_dhcp6_client *client);
+int sd_dhcp6_client_attach_event(sd_dhcp6_client *client, sd_event *event,
+                                 int priority);
+int sd_dhcp6_client_detach_event(sd_dhcp6_client *client);
+sd_event *sd_dhcp6_client_get_event(sd_dhcp6_client *client);
+sd_dhcp6_client *sd_dhcp6_client_ref(sd_dhcp6_client *client);
+sd_dhcp6_client *sd_dhcp6_client_unref(sd_dhcp6_client *client);
+int sd_dhcp6_client_new(sd_dhcp6_client **ret);
+
+#endif
-- 
1.9.1



More information about the systemd-devel mailing list