sd-ipv4ll: allow initial address to be set explicitly
This is useful in case the daemon is restarted and the state of the IPv4LL client should be serialized/deserialized.
This commit is contained in:
parent
a2fae7bbb2
commit
129dc1b489
|
@ -25,6 +25,7 @@
|
|||
#include <arpa/inet.h>
|
||||
|
||||
#include "event-util.h"
|
||||
#include "in-addr-util.h"
|
||||
#include "list.h"
|
||||
#include "random-util.h"
|
||||
#include "refcnt.h"
|
||||
|
@ -232,6 +233,39 @@ bool sd_ipv4ll_is_running(sd_ipv4ll *ll) {
|
|||
return sd_ipv4acd_is_running(ll->acd);
|
||||
}
|
||||
|
||||
static bool ipv4ll_address_is_valid(const struct in_addr *address) {
|
||||
uint32_t addr;
|
||||
|
||||
assert(address);
|
||||
|
||||
if (!in_addr_is_link_local(AF_INET, (const union in_addr_union *) address))
|
||||
return false;
|
||||
|
||||
addr = be32toh(address->s_addr);
|
||||
|
||||
if ((addr & 0x0000FF00) == 0x0000 ||
|
||||
(addr & 0x0000FF00) == 0xFF00)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int sd_ipv4ll_set_address(sd_ipv4ll *ll, const struct in_addr *address) {
|
||||
int r;
|
||||
|
||||
assert_return(ll, -EINVAL);
|
||||
assert_return(address, -EINVAL);
|
||||
assert_return(ipv4ll_address_is_valid(address), -EINVAL);
|
||||
|
||||
r = sd_ipv4acd_set_address(ll->acd, address);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
ll->address = address->s_addr;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ipv4ll_pick_address(sd_ipv4ll *ll) {
|
||||
struct in_addr in_addr;
|
||||
be32_t addr;
|
||||
|
@ -247,18 +281,15 @@ static int ipv4ll_pick_address(sd_ipv4ll *ll) {
|
|||
return r;
|
||||
addr = htonl((random & 0x0000FFFF) | IPV4LL_NETWORK);
|
||||
} while (addr == ll->address ||
|
||||
(ntohl(addr) & IPV4LL_NETMASK) != IPV4LL_NETWORK ||
|
||||
(ntohl(addr) & 0x0000FF00) == 0x0000 ||
|
||||
(ntohl(addr) & 0x0000FF00) == 0xFF00);
|
||||
|
||||
in_addr.s_addr = addr;
|
||||
|
||||
r = sd_ipv4acd_set_address(ll->acd, &in_addr);
|
||||
r = sd_ipv4ll_set_address(ll, &in_addr);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
ll->address = addr;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -100,6 +100,7 @@ int arp_network_bind_raw_socket(int index, be32_t address, const struct ether_ad
|
|||
}
|
||||
|
||||
static void test_public_api_setters(sd_event *e) {
|
||||
struct in_addr address = {};
|
||||
unsigned seed = 0;
|
||||
sd_ipv4ll *ll;
|
||||
struct ether_addr mac_addr = {
|
||||
|
@ -118,6 +119,16 @@ static void test_public_api_setters(sd_event *e) {
|
|||
assert_se(sd_ipv4ll_set_callback(NULL, NULL, NULL) == -EINVAL);
|
||||
assert_se(sd_ipv4ll_set_callback(ll, NULL, NULL) == 0);
|
||||
|
||||
assert_se(sd_ipv4ll_set_address(ll, &address) == -EINVAL);
|
||||
address.s_addr |= htobe32(169U << 24 | 254U << 16);
|
||||
assert_se(sd_ipv4ll_set_address(ll, &address) == -EINVAL);
|
||||
address.s_addr |= htobe32(0x00FF);
|
||||
assert_se(sd_ipv4ll_set_address(ll, &address) == -EINVAL);
|
||||
address.s_addr |= htobe32(0xF000);
|
||||
assert_se(sd_ipv4ll_set_address(ll, &address) == 0);
|
||||
address.s_addr |= htobe32(0x0F00);
|
||||
assert_se(sd_ipv4ll_set_address(ll, &address) == -EINVAL);
|
||||
|
||||
assert_se(sd_ipv4ll_set_address_seed(NULL, seed) == -EINVAL);
|
||||
assert_se(sd_ipv4ll_set_address_seed(ll, seed) == 0);
|
||||
|
||||
|
|
|
@ -43,6 +43,7 @@ int sd_ipv4ll_get_address(sd_ipv4ll *ll, struct in_addr *address);
|
|||
int sd_ipv4ll_set_callback(sd_ipv4ll *ll, sd_ipv4ll_cb_t cb, void *userdata);
|
||||
int sd_ipv4ll_set_mac(sd_ipv4ll *ll, const struct ether_addr *addr);
|
||||
int sd_ipv4ll_set_index(sd_ipv4ll *ll, int interface_index);
|
||||
int sd_ipv4ll_set_address(sd_ipv4ll *ll, const struct in_addr *address);
|
||||
int sd_ipv4ll_set_address_seed(sd_ipv4ll *ll, unsigned seed);
|
||||
bool sd_ipv4ll_is_running(sd_ipv4ll *ll);
|
||||
int sd_ipv4ll_start(sd_ipv4ll *ll);
|
||||
|
|
Loading…
Reference in a new issue