diff options
Diffstat (limited to 'src/libsystemd-network/sd-ipv4ll.c')
-rw-r--r-- | src/libsystemd-network/sd-ipv4ll.c | 54 |
1 files changed, 43 insertions, 11 deletions
diff --git a/src/libsystemd-network/sd-ipv4ll.c b/src/libsystemd-network/sd-ipv4ll.c index dd427ddd78..0d915e20e7 100644 --- a/src/libsystemd-network/sd-ipv4ll.c +++ b/src/libsystemd-network/sd-ipv4ll.c @@ -18,13 +18,18 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>. ***/ -#include <stdlib.h> +#include <arpa/inet.h> #include <errno.h> -#include <string.h> #include <stdio.h> -#include <arpa/inet.h> +#include <stdlib.h> +#include <string.h> + +#include "sd-ipv4acd.h" +#include "sd-ipv4ll.h" +#include "alloc-util.h" #include "event-util.h" +#include "in-addr-util.h" #include "list.h" #include "random-util.h" #include "refcnt.h" @@ -32,9 +37,6 @@ #include "sparse-endian.h" #include "util.h" -#include "sd-ipv4acd.h" -#include "sd-ipv4ll.h" - #define IPV4LL_NETWORK 0xA9FE0000L #define IPV4LL_NETMASK 0xFFFF0000L @@ -226,12 +228,45 @@ int sd_ipv4ll_set_address_seed(sd_ipv4ll *ll, unsigned seed) { return 0; } -bool sd_ipv4ll_is_running(sd_ipv4ll *ll) { +int sd_ipv4ll_is_running(sd_ipv4ll *ll) { assert_return(ll, false); 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 +282,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; } |