1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright (C) 2014 Intel Corporation. All rights reserved.
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
25 #include "siphash24.h"
29 #include "sd-dhcp6-client.h"
30 #include "dhcp6-protocol.h"
32 #define SYSTEMD_PEN 43793
33 #define HASH_KEY SD_ID128_MAKE(80,11,8c,c2,fe,4a,03,ee,3e,d6,0c,6f,36,39,14,09)
35 struct sd_dhcp6_client {
38 enum DHCP6State state;
42 struct ether_addr mac_addr;
43 sd_dhcp6_client_cb_t cb;
47 uint16_t type; /* DHCP6_DUID_EN */
53 int sd_dhcp6_client_set_callback(sd_dhcp6_client *client,
54 sd_dhcp6_client_cb_t cb, void *userdata)
56 assert_return(client, -EINVAL);
59 client->userdata = userdata;
64 int sd_dhcp6_client_set_index(sd_dhcp6_client *client, int interface_index)
66 assert_return(client, -EINVAL);
67 assert_return(interface_index >= -1, -EINVAL);
69 client->index = interface_index;
74 int sd_dhcp6_client_set_mac(sd_dhcp6_client *client,
75 const struct ether_addr *mac_addr)
77 assert_return(client, -EINVAL);
80 memcpy(&client->mac_addr, mac_addr, sizeof(client->mac_addr));
82 memset(&client->mac_addr, 0x00, sizeof(client->mac_addr));
87 static sd_dhcp6_client *client_notify(sd_dhcp6_client *client, int event) {
89 client = sd_dhcp6_client_ref(client);
90 client->cb(client, event, client->userdata);
91 client = sd_dhcp6_client_unref(client);
97 static int client_initialize(sd_dhcp6_client *client)
99 assert_return(client, -EINVAL);
101 client->state = DHCP6_STATE_STOPPED;
106 static sd_dhcp6_client *client_stop(sd_dhcp6_client *client, int error) {
107 assert_return(client, NULL);
109 client = client_notify(client, error);
111 client_initialize(client);
116 int sd_dhcp6_client_stop(sd_dhcp6_client *client)
118 client_stop(client, DHCP6_EVENT_STOP);
123 int sd_dhcp6_client_start(sd_dhcp6_client *client)
127 assert_return(client, -EINVAL);
128 assert_return(client->event, -EINVAL);
129 assert_return(client->index > 0, -EINVAL);
134 int sd_dhcp6_client_attach_event(sd_dhcp6_client *client, sd_event *event,
139 assert_return(client, -EINVAL);
140 assert_return(!client->event, -EBUSY);
143 client->event = sd_event_ref(event);
145 r = sd_event_default(&client->event);
150 client->event_priority = priority;
155 int sd_dhcp6_client_detach_event(sd_dhcp6_client *client) {
156 assert_return(client, -EINVAL);
158 client->event = sd_event_unref(client->event);
163 sd_event *sd_dhcp6_client_get_event(sd_dhcp6_client *client) {
167 return client->event;
170 sd_dhcp6_client *sd_dhcp6_client_ref(sd_dhcp6_client *client) {
172 assert_se(REFCNT_INC(client->n_ref) >= 2);
177 sd_dhcp6_client *sd_dhcp6_client_unref(sd_dhcp6_client *client) {
178 if (client && REFCNT_DEC(client->n_ref) <= 0) {
180 client_initialize(client);
182 sd_dhcp6_client_detach_event(client);
192 DEFINE_TRIVIAL_CLEANUP_FUNC(sd_dhcp6_client*, sd_dhcp6_client_unref);
193 #define _cleanup_dhcp6_client_free_ _cleanup_(sd_dhcp6_client_unrefp)
195 int sd_dhcp6_client_new(sd_dhcp6_client **ret)
197 _cleanup_dhcp6_client_free_ sd_dhcp6_client *client = NULL;
198 sd_id128_t machine_id;
201 assert_return(ret, -EINVAL);
203 client = new0(sd_dhcp6_client, 1);
207 client->n_ref = REFCNT_INIT;
211 /* initialize DUID */
212 client->duid.type = htobe16(DHCP6_DUID_EN);
213 client->duid.pen = htobe32(SYSTEMD_PEN);
215 r = sd_id128_get_machine(&machine_id);
219 /* a bit of snake-oil perhaps, but no need to expose the machine-id
221 siphash24(client->duid.id, &machine_id, sizeof(machine_id),