chiark
/
gitweb
/
~ianmdlvl
/
elogind.git
/ blobdiff
commit
grep
author
committer
pickaxe
?
search:
re
summary
|
shortlog
|
log
|
commit
|
commitdiff
|
tree
raw
|
inline
| side by side
update TODO
[elogind.git]
/
src
/
libsystemd-network
/
sd-ipv4ll.c
diff --git
a/src/libsystemd-network/sd-ipv4ll.c
b/src/libsystemd-network/sd-ipv4ll.c
index 7431af729e6cbcc999f3d52f62121197d0e01a25..02f2f9e0a91cf3216e9f9df360ee206243957975 100644
(file)
--- a/
src/libsystemd-network/sd-ipv4ll.c
+++ b/
src/libsystemd-network/sd-ipv4ll.c
@@
-26,6
+26,7
@@
#include "util.h"
#include "siphash24.h"
#include "list.h"
#include "util.h"
#include "siphash24.h"
#include "list.h"
+#include "refcnt.h"
#include "ipv4ll-internal.h"
#include "sd-ipv4ll.h"
#include "ipv4ll-internal.h"
#include "sd-ipv4ll.h"
@@
-60,11
+61,14
@@
typedef enum IPv4LLState {
IPV4LL_STATE_WAITING_ANNOUNCE,
IPV4LL_STATE_ANNOUNCING,
IPV4LL_STATE_RUNNING,
IPV4LL_STATE_WAITING_ANNOUNCE,
IPV4LL_STATE_ANNOUNCING,
IPV4LL_STATE_RUNNING,
+ IPV4LL_STATE_STOPPED,
_IPV4LL_STATE_MAX,
_IPV4LL_STATE_INVALID = -1
} IPv4LLState;
struct sd_ipv4ll {
_IPV4LL_STATE_MAX,
_IPV4LL_STATE_INVALID = -1
} IPv4LLState;
struct sd_ipv4ll {
+ RefCount n_ref;
+
IPv4LLState state;
int index;
int fd;
IPv4LLState state;
int index;
int fd;
@@
-103,16
+107,19
@@
static void ipv4ll_set_state(sd_ipv4ll *ll, IPv4LLState st, int reset_counter) {
}
}
}
}
-static
int
ipv4ll_client_notify(sd_ipv4ll *ll, int event) {
+static
sd_ipv4ll *
ipv4ll_client_notify(sd_ipv4ll *ll, int event) {
assert(ll);
assert(ll);
- if (ll->cb)
+ if (ll->cb) {
+ ll = sd_ipv4ll_ref(ll);
ll->cb(ll, event, ll->userdata);
ll->cb(ll, event, ll->userdata);
+ ll = sd_ipv4ll_unref(ll);
+ }
- return
0
;
+ return
ll
;
}
}
-static
int
ipv4ll_stop(sd_ipv4ll *ll, int event) {
+static
sd_ipv4ll *
ipv4ll_stop(sd_ipv4ll *ll, int event) {
assert(ll);
ll->receive_message = sd_event_source_unref(ll->receive_message);
assert(ll);
ll->receive_message = sd_event_source_unref(ll->receive_message);
@@
-120,15
+127,16
@@
static int ipv4ll_stop(sd_ipv4ll *ll, int event) {
ll->timer = sd_event_source_unref(ll->timer);
ll->timer = sd_event_source_unref(ll->timer);
- ipv4ll_client_notify(ll, event);
-
- ll->claimed_address = 0;
+ log_ipv4ll(ll, "STOPPED");
-
ipv4ll_set_state (ll, IPV4LL_STATE_INIT, 1
);
+
ll = ipv4ll_client_notify(ll, event
);
- log_ipv4ll(ll, "STOPPED");
+ if (ll) {
+ ll->claimed_address = 0;
+ ipv4ll_set_state (ll, IPV4LL_STATE_INIT, 1);
+ }
- return
0
;
+ return
ll
;
}
static int ipv4ll_pick_address(sd_ipv4ll *ll, be32_t *address) {
}
static int ipv4ll_pick_address(sd_ipv4ll *ll, be32_t *address) {
@@
-165,7
+173,7
@@
static int ipv4ll_timer(sd_event_source *s, uint64_t usec, void *userdata) {
return 0;
}
return 0;
}
-static void ipv4ll_set_next_wakeup
(sd_ipv4ll *ll, int sec, int random_sec) {
+static void ipv4ll_set_next_wakeup(sd_ipv4ll *ll, int sec, int random_sec) {
usec_t next_timeout = 0;
usec_t time_now = 0;
usec_t next_timeout = 0;
usec_t time_now = 0;
@@
-178,8
+186,8
@@
static void ipv4ll_set_next_wakeup (sd_ipv4ll *ll, int sec, int random_sec) {
if (random_sec)
next_timeout += random_u32() % (random_sec * USEC_PER_SEC);
if (random_sec)
next_timeout += random_u32() % (random_sec * USEC_PER_SEC);
- if (sd_event_
get_now_monotonic(ll->event
, &time_now) < 0)
- time_now = now(
CLOCK_MONOTONIC
);
+ if (sd_event_
now(ll->event, clock_boottime_or_monotonic()
, &time_now) < 0)
+ time_now = now(
clock_boottime_or_monotonic()
);
ll->next_wakeup = time_now + next_timeout;
ll->next_wakeup_valid = 1;
ll->next_wakeup = time_now + next_timeout;
ll->next_wakeup_valid = 1;
@@
-256,7
+264,10
@@
static void ipv4ll_run_state_machine(sd_ipv4ll *ll, IPv4LLTrigger trigger, void
if (ll->iteration == 0) {
log_ipv4ll(ll, "ANNOUNCE");
ll->claimed_address = ll->address;
if (ll->iteration == 0) {
log_ipv4ll(ll, "ANNOUNCE");
ll->claimed_address = ll->address;
- r = ipv4ll_client_notify(ll, IPV4LL_EVENT_BIND);
+ ll = ipv4ll_client_notify(ll, IPV4LL_EVENT_BIND);
+ if (!ll || ll->state == IPV4LL_STATE_STOPPED)
+ goto out;
+
ll->conflict = 0;
}
ll->conflict = 0;
}
@@
-278,7
+289,7
@@
static void ipv4ll_run_state_machine(sd_ipv4ll *ll, IPv4LLTrigger trigger, void
if (ipv4ll_arp_conflict(ll, in_packet)) {
if (ipv4ll_arp_conflict(ll, in_packet)) {
- r = sd_event_
get_now_monotonic(ll->event
, &time_now);
+ r = sd_event_
now(ll->event, clock_boottime_or_monotonic()
, &time_now);
if (r < 0)
goto out;
if (r < 0)
goto out;
@@
-300,7
+311,10
@@
static void ipv4ll_run_state_machine(sd_ipv4ll *ll, IPv4LLTrigger trigger, void
if (conflicted) {
log_ipv4ll(ll, "CONFLICT");
if (conflicted) {
log_ipv4ll(ll, "CONFLICT");
- r = ipv4ll_client_notify(ll, IPV4LL_EVENT_CONFLICT);
+ ll = ipv4ll_client_notify(ll, IPV4LL_EVENT_CONFLICT);
+ if (!ll || ll->state == IPV4LL_STATE_STOPPED)
+ goto out;
+
ll->claimed_address = 0;
/* Pick a new address */
ll->claimed_address = 0;
/* Pick a new address */
@@
-330,18
+344,22
@@
static void ipv4ll_run_state_machine(sd_ipv4ll *ll, IPv4LLTrigger trigger, void
if (ll->next_wakeup_valid) {
ll->timer = sd_event_source_unref(ll->timer);
if (ll->next_wakeup_valid) {
ll->timer = sd_event_source_unref(ll->timer);
- r = sd_event_add_
monotonic(ll->event, &ll->timer
,
- ll->next_wakeup, 0, ipv4ll_timer, ll);
+ r = sd_event_add_
time(ll->event, &ll->timer, clock_boottime_or_monotonic()
,
+
ll->next_wakeup, 0, ipv4ll_timer, ll);
if (r < 0)
goto out;
r = sd_event_source_set_priority(ll->timer, ll->event_priority);
if (r < 0)
goto out;
if (r < 0)
goto out;
r = sd_event_source_set_priority(ll->timer, ll->event_priority);
if (r < 0)
goto out;
+
+ r = sd_event_source_set_description(ll->timer, "ipv4ll-timer");
+ if (r < 0)
+ goto out;
}
out:
}
out:
- if (r < 0)
+ if (r < 0
&& ll
)
ipv4ll_stop(ll, r);
}
ipv4ll_stop(ll, r);
}
@@
-368,8
+386,9
@@
static int ipv4ll_receive_message(sd_event_source *s, int fd,
int sd_ipv4ll_set_index(sd_ipv4ll *ll, int interface_index) {
assert_return(ll, -EINVAL);
int sd_ipv4ll_set_index(sd_ipv4ll *ll, int interface_index) {
assert_return(ll, -EINVAL);
- assert_return(interface_index >= -1, -EINVAL);
- assert_return(ll->state == IPV4LL_STATE_INIT, -EBUSY);
+ assert_return(interface_index > 0, -EINVAL);
+ assert_return(IN_SET(ll->state, IPV4LL_STATE_INIT,
+ IPV4LL_STATE_STOPPED), -EBUSY);
ll->index = interface_index;
ll->index = interface_index;
@@
-385,13
+404,16
@@
int sd_ipv4ll_set_mac(sd_ipv4ll *ll, const struct ether_addr *addr) {
if (memcmp(&ll->mac_addr, addr, ETH_ALEN) == 0)
return 0;
if (memcmp(&ll->mac_addr, addr, ETH_ALEN) == 0)
return 0;
- if (
ll->state != IPV4LL_STATE_INIT
) {
+ if (
!IN_SET(ll->state, IPV4LL_STATE_INIT, IPV4LL_STATE_STOPPED)
) {
log_ipv4ll(ll, "Changing MAC address on running IPv4LL "
"client, restarting");
log_ipv4ll(ll, "Changing MAC address on running IPv4LL "
"client, restarting");
-
sd_ipv4ll_stop(ll
);
+
ll = ipv4ll_stop(ll, IPV4LL_EVENT_STOP
);
need_restart = true;
}
need_restart = true;
}
+ if (!ll)
+ return 0;
+
memcpy(&ll->mac_addr, addr, ETH_ALEN);
if (need_restart)
memcpy(&ll->mac_addr, addr, ETH_ALEN);
if (need_restart)
@@
-451,10
+473,13
@@
int sd_ipv4ll_get_address(sd_ipv4ll *ll, struct in_addr *address){
}
int sd_ipv4ll_set_address_seed (sd_ipv4ll *ll, uint8_t seed[8]) {
}
int sd_ipv4ll_set_address_seed (sd_ipv4ll *ll, uint8_t seed[8]) {
- unsigned int entropy
= *seed
;
+ unsigned int entropy;
int r;
assert_return(ll, -EINVAL);
int r;
assert_return(ll, -EINVAL);
+ assert_return(seed, -EINVAL);
+
+ entropy = *seed;
free(ll->random_data);
free(ll->random_data_state);
free(ll->random_data);
free(ll->random_data_state);
@@
-481,6
+506,12
@@
error:
return r;
}
return r;
}
+bool sd_ipv4ll_is_running(sd_ipv4ll *ll) {
+ assert_return(ll, -EINVAL);
+
+ return !IN_SET(ll->state, IPV4LL_STATE_INIT, IPV4LL_STATE_STOPPED);
+}
+
#define HASH_KEY SD_ID128_MAKE(df,04,22,98,3f,ad,14,52,f9,87,2e,d1,9c,70,e2,f2)
int sd_ipv4ll_start (sd_ipv4ll *ll) {
#define HASH_KEY SD_ID128_MAKE(df,04,22,98,3f,ad,14,52,f9,87,2e,d1,9c,70,e2,f2)
int sd_ipv4ll_start (sd_ipv4ll *ll) {
@@
-489,7
+520,10
@@
int sd_ipv4ll_start (sd_ipv4ll *ll) {
assert_return(ll, -EINVAL);
assert_return(ll->event, -EINVAL);
assert_return(ll->index > 0, -EINVAL);
assert_return(ll, -EINVAL);
assert_return(ll->event, -EINVAL);
assert_return(ll->index > 0, -EINVAL);
- assert_return(ll->state == IPV4LL_STATE_INIT, -EBUSY);
+ assert_return(IN_SET(ll->state, IPV4LL_STATE_INIT,
+ IPV4LL_STATE_STOPPED), -EBUSY);
+
+ ll->state = IPV4LL_STATE_INIT;
r = arp_network_bind_raw_socket(ll->index, &ll->link);
r = arp_network_bind_raw_socket(ll->index, &ll->link);
@@
-530,14
+564,24
@@
int sd_ipv4ll_start (sd_ipv4ll *ll) {
if (r < 0)
goto out;
if (r < 0)
goto out;
- r = sd_event_add_monotonic(ll->event, &ll->timer, now(CLOCK_MONOTONIC), 0,
- ipv4ll_timer, ll);
+ r = sd_event_source_set_description(ll->receive_message, "ipv4ll-receive-message");
+ if (r < 0)
+ goto out;
+
+ r = sd_event_add_time(ll->event,
+ &ll->timer,
+ clock_boottime_or_monotonic(),
+ now(clock_boottime_or_monotonic()), 0,
+ ipv4ll_timer, ll);
if (r < 0)
goto out;
r = sd_event_source_set_priority(ll->timer, ll->event_priority);
if (r < 0)
goto out;
r = sd_event_source_set_priority(ll->timer, ll->event_priority);
+ if (r < 0)
+ goto out;
+ r = sd_event_source_set_description(ll->timer, "ipv4ll-timer");
out:
if (r < 0)
ipv4ll_stop(ll, IPV4LL_EVENT_STOP);
out:
if (r < 0)
ipv4ll_stop(ll, IPV4LL_EVENT_STOP);
@@
-546,23
+590,42
@@
out:
}
int sd_ipv4ll_stop(sd_ipv4ll *ll) {
}
int sd_ipv4ll_stop(sd_ipv4ll *ll) {
- return ipv4ll_stop(ll, IPV4LL_EVENT_STOP);
+ ipv4ll_stop(ll, IPV4LL_EVENT_STOP);
+ if (ll)
+ ipv4ll_set_state(ll, IPV4LL_STATE_STOPPED, 1);
+
+ return 0;
}
}
-
void sd_ipv4ll_free
(sd_ipv4ll *ll) {
- if (
!
ll)
-
return
;
+
sd_ipv4ll *sd_ipv4ll_ref
(sd_ipv4ll *ll) {
+ if (ll)
+
assert_se(REFCNT_INC(ll->n_ref) >= 2)
;
-
sd_ipv4ll_stop(ll)
;
- sd_ipv4ll_detach_event(ll);
+
return ll
;
+}
- free(ll->random_data);
- free(ll->random_data_state);
- free(ll);
+sd_ipv4ll *sd_ipv4ll_unref(sd_ipv4ll *ll) {
+ if (ll && REFCNT_DEC(ll->n_ref) == 0) {
+ ll->receive_message =
+ sd_event_source_unref(ll->receive_message);
+ ll->fd = safe_close(ll->fd);
+
+ ll->timer = sd_event_source_unref(ll->timer);
+
+ sd_ipv4ll_detach_event(ll);
+
+ free(ll->random_data);
+ free(ll->random_data_state);
+ free(ll);
+
+ return NULL;
+ }
+
+ return ll;
}
}
-DEFINE_TRIVIAL_CLEANUP_FUNC(sd_ipv4ll*, sd_ipv4ll_
free
);
-#define _cleanup_ipv4ll_free_ _cleanup_(sd_ipv4ll_
free
p)
+DEFINE_TRIVIAL_CLEANUP_FUNC(sd_ipv4ll*, sd_ipv4ll_
unref
);
+#define _cleanup_ipv4ll_free_ _cleanup_(sd_ipv4ll_
unref
p)
int sd_ipv4ll_new(sd_ipv4ll **ret) {
_cleanup_ipv4ll_free_ sd_ipv4ll *ll = NULL;
int sd_ipv4ll_new(sd_ipv4ll **ret) {
_cleanup_ipv4ll_free_ sd_ipv4ll *ll = NULL;
@@
-573,6
+636,7
@@
int sd_ipv4ll_new(sd_ipv4ll **ret) {
if (!ll)
return -ENOMEM;
if (!ll)
return -ENOMEM;
+ ll->n_ref = REFCNT_INIT;
ll->state = IPV4LL_STATE_INIT;
ll->index = -1;
ll->fd = -1;
ll->state = IPV4LL_STATE_INIT;
ll->index = -1;
ll->fd = -1;