test-ipv4ll-manual.c revision 7b713b81c27277f37420c121f2c9eeb10646ff5a
7b713b81c27277f37420c121f2c9eeb10646ff5aTom Gundersen/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
7b713b81c27277f37420c121f2c9eeb10646ff5aTom Gundersen
7b713b81c27277f37420c121f2c9eeb10646ff5aTom Gundersen/***
7b713b81c27277f37420c121f2c9eeb10646ff5aTom Gundersen This file is part of systemd.
7b713b81c27277f37420c121f2c9eeb10646ff5aTom Gundersen
7b713b81c27277f37420c121f2c9eeb10646ff5aTom Gundersen Copyright (C) 2014 Tom Gundersen <teg@jklm.no>
7b713b81c27277f37420c121f2c9eeb10646ff5aTom Gundersen
7b713b81c27277f37420c121f2c9eeb10646ff5aTom Gundersen systemd is free software; you can redistribute it and/or modify it
7b713b81c27277f37420c121f2c9eeb10646ff5aTom Gundersen under the terms of the GNU Lesser General Public License as published by
7b713b81c27277f37420c121f2c9eeb10646ff5aTom Gundersen the Free Software Foundation; either version 2.1 of the License, or
7b713b81c27277f37420c121f2c9eeb10646ff5aTom Gundersen (at your option) any later version.
7b713b81c27277f37420c121f2c9eeb10646ff5aTom Gundersen
7b713b81c27277f37420c121f2c9eeb10646ff5aTom Gundersen systemd is distributed in the hope that it will be useful, but
7b713b81c27277f37420c121f2c9eeb10646ff5aTom Gundersen WITHOUT ANY WARRANTY; without even the implied warranty of
7b713b81c27277f37420c121f2c9eeb10646ff5aTom Gundersen MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
7b713b81c27277f37420c121f2c9eeb10646ff5aTom Gundersen Lesser General Public License for more details.
7b713b81c27277f37420c121f2c9eeb10646ff5aTom Gundersen
7b713b81c27277f37420c121f2c9eeb10646ff5aTom Gundersen You should have received a copy of the GNU Lesser General Public License
7b713b81c27277f37420c121f2c9eeb10646ff5aTom Gundersen along with systemd; If not, see <http://www.gnu.org/licenses/>.
7b713b81c27277f37420c121f2c9eeb10646ff5aTom Gundersen***/
7b713b81c27277f37420c121f2c9eeb10646ff5aTom Gundersen
7b713b81c27277f37420c121f2c9eeb10646ff5aTom Gundersen#include <stdlib.h>
7b713b81c27277f37420c121f2c9eeb10646ff5aTom Gundersen#include <errno.h>
7b713b81c27277f37420c121f2c9eeb10646ff5aTom Gundersen#include <unistd.h>
7b713b81c27277f37420c121f2c9eeb10646ff5aTom Gundersen
7b713b81c27277f37420c121f2c9eeb10646ff5aTom Gundersen#include <linux/veth.h>
7b713b81c27277f37420c121f2c9eeb10646ff5aTom Gundersen#include <net/if.h>
7b713b81c27277f37420c121f2c9eeb10646ff5aTom Gundersen
7b713b81c27277f37420c121f2c9eeb10646ff5aTom Gundersen#include "sd-event.h"
7b713b81c27277f37420c121f2c9eeb10646ff5aTom Gundersen#include "sd-netlink.h"
7b713b81c27277f37420c121f2c9eeb10646ff5aTom Gundersen#include "sd-ipv4ll.h"
7b713b81c27277f37420c121f2c9eeb10646ff5aTom Gundersen
7b713b81c27277f37420c121f2c9eeb10646ff5aTom Gundersen#include "util.h"
7b713b81c27277f37420c121f2c9eeb10646ff5aTom Gundersen#include "event-util.h"
7b713b81c27277f37420c121f2c9eeb10646ff5aTom Gundersen#include "netlink-util.h"
7b713b81c27277f37420c121f2c9eeb10646ff5aTom Gundersen#include "in-addr-util.h"
7b713b81c27277f37420c121f2c9eeb10646ff5aTom Gundersen
7b713b81c27277f37420c121f2c9eeb10646ff5aTom Gundersenstatic void ll_handler(sd_ipv4ll *ll, int event, void *userdata) {
7b713b81c27277f37420c121f2c9eeb10646ff5aTom Gundersen _cleanup_free_ char *address = NULL;
7b713b81c27277f37420c121f2c9eeb10646ff5aTom Gundersen struct in_addr addr = {};
7b713b81c27277f37420c121f2c9eeb10646ff5aTom Gundersen
7b713b81c27277f37420c121f2c9eeb10646ff5aTom Gundersen assert_se(ll);
7b713b81c27277f37420c121f2c9eeb10646ff5aTom Gundersen
7b713b81c27277f37420c121f2c9eeb10646ff5aTom Gundersen if (sd_ipv4ll_get_address(ll, &addr) >= 0)
7b713b81c27277f37420c121f2c9eeb10646ff5aTom Gundersen assert_se(in_addr_to_string(AF_INET, (const union in_addr_union*) &addr, &address) >= 0);
7b713b81c27277f37420c121f2c9eeb10646ff5aTom Gundersen
7b713b81c27277f37420c121f2c9eeb10646ff5aTom Gundersen switch (event) {
7b713b81c27277f37420c121f2c9eeb10646ff5aTom Gundersen case IPV4LL_EVENT_BIND:
7b713b81c27277f37420c121f2c9eeb10646ff5aTom Gundersen log_info("bound %s", strna(address));
7b713b81c27277f37420c121f2c9eeb10646ff5aTom Gundersen break;
7b713b81c27277f37420c121f2c9eeb10646ff5aTom Gundersen case IPV4LL_EVENT_CONFLICT:
7b713b81c27277f37420c121f2c9eeb10646ff5aTom Gundersen log_info("conflict on %s", strna(address));
7b713b81c27277f37420c121f2c9eeb10646ff5aTom Gundersen break;
7b713b81c27277f37420c121f2c9eeb10646ff5aTom Gundersen case IPV4LL_EVENT_STOP:
7b713b81c27277f37420c121f2c9eeb10646ff5aTom Gundersen log_error("the client was stopped with address %s", strna(address));
7b713b81c27277f37420c121f2c9eeb10646ff5aTom Gundersen break;
7b713b81c27277f37420c121f2c9eeb10646ff5aTom Gundersen default:
7b713b81c27277f37420c121f2c9eeb10646ff5aTom Gundersen assert_not_reached("invalid LL event");
7b713b81c27277f37420c121f2c9eeb10646ff5aTom Gundersen }
7b713b81c27277f37420c121f2c9eeb10646ff5aTom Gundersen}
7b713b81c27277f37420c121f2c9eeb10646ff5aTom Gundersen
7b713b81c27277f37420c121f2c9eeb10646ff5aTom Gundersenstatic int client_run(int ifindex, const char *seed_str, const struct ether_addr *ha, sd_event *e) {
7b713b81c27277f37420c121f2c9eeb10646ff5aTom Gundersen sd_ipv4ll *ll;
7b713b81c27277f37420c121f2c9eeb10646ff5aTom Gundersen
7b713b81c27277f37420c121f2c9eeb10646ff5aTom Gundersen assert_se(sd_ipv4ll_new(&ll) >= 0);
7b713b81c27277f37420c121f2c9eeb10646ff5aTom Gundersen assert_se(sd_ipv4ll_attach_event(ll, e, 0) >= 0);
7b713b81c27277f37420c121f2c9eeb10646ff5aTom Gundersen
7b713b81c27277f37420c121f2c9eeb10646ff5aTom Gundersen assert_se(sd_ipv4ll_set_index(ll, ifindex) >= 0);
7b713b81c27277f37420c121f2c9eeb10646ff5aTom Gundersen assert_se(sd_ipv4ll_set_mac(ll, ha) >= 0);
7b713b81c27277f37420c121f2c9eeb10646ff5aTom Gundersen assert_se(sd_ipv4ll_set_callback(ll, ll_handler, NULL) >= 0);
7b713b81c27277f37420c121f2c9eeb10646ff5aTom Gundersen
7b713b81c27277f37420c121f2c9eeb10646ff5aTom Gundersen if (seed_str) {
7b713b81c27277f37420c121f2c9eeb10646ff5aTom Gundersen unsigned seed;
7b713b81c27277f37420c121f2c9eeb10646ff5aTom Gundersen
7b713b81c27277f37420c121f2c9eeb10646ff5aTom Gundersen assert_se(safe_atou(seed_str, &seed) >= 0);
7b713b81c27277f37420c121f2c9eeb10646ff5aTom Gundersen
7b713b81c27277f37420c121f2c9eeb10646ff5aTom Gundersen assert_se(sd_ipv4ll_set_address_seed(ll, seed) >= 0);
7b713b81c27277f37420c121f2c9eeb10646ff5aTom Gundersen }
7b713b81c27277f37420c121f2c9eeb10646ff5aTom Gundersen
7b713b81c27277f37420c121f2c9eeb10646ff5aTom Gundersen log_info("starting IPv4LL client");
7b713b81c27277f37420c121f2c9eeb10646ff5aTom Gundersen
7b713b81c27277f37420c121f2c9eeb10646ff5aTom Gundersen assert_se(sd_ipv4ll_start(ll) >= 0);
7b713b81c27277f37420c121f2c9eeb10646ff5aTom Gundersen
7b713b81c27277f37420c121f2c9eeb10646ff5aTom Gundersen assert_se(sd_event_loop(e) >= 0);
7b713b81c27277f37420c121f2c9eeb10646ff5aTom Gundersen
7b713b81c27277f37420c121f2c9eeb10646ff5aTom Gundersen assert_se(!sd_ipv4ll_unref(ll));
7b713b81c27277f37420c121f2c9eeb10646ff5aTom Gundersen
7b713b81c27277f37420c121f2c9eeb10646ff5aTom Gundersen return EXIT_SUCCESS;
7b713b81c27277f37420c121f2c9eeb10646ff5aTom Gundersen}
7b713b81c27277f37420c121f2c9eeb10646ff5aTom Gundersen
7b713b81c27277f37420c121f2c9eeb10646ff5aTom Gundersenstatic int test_ll(const char *ifname, const char *seed) {
7b713b81c27277f37420c121f2c9eeb10646ff5aTom Gundersen _cleanup_event_unref_ sd_event *e = NULL;
7b713b81c27277f37420c121f2c9eeb10646ff5aTom Gundersen _cleanup_netlink_unref_ sd_netlink *rtnl = NULL;
7b713b81c27277f37420c121f2c9eeb10646ff5aTom Gundersen _cleanup_netlink_message_unref_ sd_netlink_message *m = NULL, *reply = NULL;
7b713b81c27277f37420c121f2c9eeb10646ff5aTom Gundersen struct ether_addr ha;
7b713b81c27277f37420c121f2c9eeb10646ff5aTom Gundersen int ifindex;
7b713b81c27277f37420c121f2c9eeb10646ff5aTom Gundersen
7b713b81c27277f37420c121f2c9eeb10646ff5aTom Gundersen assert_se(sd_event_new(&e) >= 0);
7b713b81c27277f37420c121f2c9eeb10646ff5aTom Gundersen
7b713b81c27277f37420c121f2c9eeb10646ff5aTom Gundersen assert_se(sd_netlink_open(&rtnl) >= 0);
7b713b81c27277f37420c121f2c9eeb10646ff5aTom Gundersen assert_se(sd_netlink_attach_event(rtnl, e, 0) >= 0);
7b713b81c27277f37420c121f2c9eeb10646ff5aTom Gundersen
7b713b81c27277f37420c121f2c9eeb10646ff5aTom Gundersen assert_se(sd_rtnl_message_new_link(rtnl, &m, RTM_GETLINK, 0) >= 0);
7b713b81c27277f37420c121f2c9eeb10646ff5aTom Gundersen assert_se(sd_netlink_message_append_string(m, IFLA_IFNAME, ifname) >= 0);
7b713b81c27277f37420c121f2c9eeb10646ff5aTom Gundersen assert_se(sd_netlink_call(rtnl, m, 0, &reply) >= 0);
7b713b81c27277f37420c121f2c9eeb10646ff5aTom Gundersen
7b713b81c27277f37420c121f2c9eeb10646ff5aTom Gundersen assert_se(sd_rtnl_message_link_get_ifindex(reply, &ifindex) >= 0);
7b713b81c27277f37420c121f2c9eeb10646ff5aTom Gundersen assert_se(sd_netlink_message_read_ether_addr(reply, IFLA_ADDRESS, &ha) >= 0);
7b713b81c27277f37420c121f2c9eeb10646ff5aTom Gundersen
7b713b81c27277f37420c121f2c9eeb10646ff5aTom Gundersen client_run(ifindex, seed, &ha, e);
7b713b81c27277f37420c121f2c9eeb10646ff5aTom Gundersen
7b713b81c27277f37420c121f2c9eeb10646ff5aTom Gundersen return EXIT_SUCCESS;
7b713b81c27277f37420c121f2c9eeb10646ff5aTom Gundersen}
7b713b81c27277f37420c121f2c9eeb10646ff5aTom Gundersen
7b713b81c27277f37420c121f2c9eeb10646ff5aTom Gundersenint main(int argc, char *argv[]) {
7b713b81c27277f37420c121f2c9eeb10646ff5aTom Gundersen log_set_max_level(LOG_DEBUG);
7b713b81c27277f37420c121f2c9eeb10646ff5aTom Gundersen log_parse_environment();
7b713b81c27277f37420c121f2c9eeb10646ff5aTom Gundersen log_open();
7b713b81c27277f37420c121f2c9eeb10646ff5aTom Gundersen
7b713b81c27277f37420c121f2c9eeb10646ff5aTom Gundersen if (argc == 2)
7b713b81c27277f37420c121f2c9eeb10646ff5aTom Gundersen return test_ll(argv[1], NULL);
7b713b81c27277f37420c121f2c9eeb10646ff5aTom Gundersen else if (argc == 3)
7b713b81c27277f37420c121f2c9eeb10646ff5aTom Gundersen return test_ll(argv[1], argv[2]);
7b713b81c27277f37420c121f2c9eeb10646ff5aTom Gundersen else {
7b713b81c27277f37420c121f2c9eeb10646ff5aTom Gundersen log_error("This program takes one or two arguments.\n"
7b713b81c27277f37420c121f2c9eeb10646ff5aTom Gundersen "\t %s <ifname> [<seed>]", program_invocation_short_name);
7b713b81c27277f37420c121f2c9eeb10646ff5aTom Gundersen return EXIT_FAILURE;
7b713b81c27277f37420c121f2c9eeb10646ff5aTom Gundersen }
7b713b81c27277f37420c121f2c9eeb10646ff5aTom Gundersen}