test-acd.c revision 4afd3348c7506dd1d36305b7bcb9feb8952b9d6b
9661674ed58ba62a40e43d1a4b38d5e77c3c6545Knut Anders Hatlen/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
9661674ed58ba62a40e43d1a4b38d5e77c3c6545Knut Anders Hatlen
9661674ed58ba62a40e43d1a4b38d5e77c3c6545Knut Anders Hatlen/***
551b849ce88d596dc52dda2f78229a932b339c78Lubos Kosco This file is part of systemd.
551b849ce88d596dc52dda2f78229a932b339c78Lubos Kosco
9661674ed58ba62a40e43d1a4b38d5e77c3c6545Knut Anders Hatlen Copyright (C) 2014 Tom Gundersen <teg@jklm.no>
a1318a82916028f363b3c5b52e7fd7256b632497Trond Norbye
a1318a82916028f363b3c5b52e7fd7256b632497Trond Norbye systemd is free software; you can redistribute it and/or modify it
a1318a82916028f363b3c5b52e7fd7256b632497Trond Norbye under the terms of the GNU Lesser General Public License as published by
a1318a82916028f363b3c5b52e7fd7256b632497Trond Norbye the Free Software Foundation; either version 2.1 of the License, or
a1318a82916028f363b3c5b52e7fd7256b632497Trond Norbye (at your option) any later version.
a1318a82916028f363b3c5b52e7fd7256b632497Trond Norbye
bcae302a5f4b516d2f3c05f657df054e1a0efde7Knut Anders Hatlen systemd is distributed in the hope that it will be useful, but
a1318a82916028f363b3c5b52e7fd7256b632497Trond Norbye WITHOUT ANY WARRANTY; without even the implied warranty of
a1318a82916028f363b3c5b52e7fd7256b632497Trond Norbye MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
a1318a82916028f363b3c5b52e7fd7256b632497Trond Norbye Lesser General Public License for more details.
a1318a82916028f363b3c5b52e7fd7256b632497Trond Norbye
a1318a82916028f363b3c5b52e7fd7256b632497Trond Norbye You should have received a copy of the GNU Lesser General Public License
afb218f076cae538126a5f931299a82a114a075aKnut Anders Hatlen along with systemd; If not, see <http://www.gnu.org/licenses/>.
a1318a82916028f363b3c5b52e7fd7256b632497Trond Norbye***/
a1318a82916028f363b3c5b52e7fd7256b632497Trond Norbye
a1318a82916028f363b3c5b52e7fd7256b632497Trond Norbye#include <errno.h>
a1318a82916028f363b3c5b52e7fd7256b632497Trond Norbye#include <stdlib.h>
a1318a82916028f363b3c5b52e7fd7256b632497Trond Norbye#include <unistd.h>
a1318a82916028f363b3c5b52e7fd7256b632497Trond Norbye
a1318a82916028f363b3c5b52e7fd7256b632497Trond Norbye#include <linux/veth.h>
c0550b01024b910b8c1468811c0ea663b10b1372Trond Norbye#include <net/if.h>
a1318a82916028f363b3c5b52e7fd7256b632497Trond Norbye
a1318a82916028f363b3c5b52e7fd7256b632497Trond Norbye#include "sd-event.h"
9661674ed58ba62a40e43d1a4b38d5e77c3c6545Knut Anders Hatlen#include "sd-ipv4acd.h"
a1318a82916028f363b3c5b52e7fd7256b632497Trond Norbye#include "sd-netlink.h"
a1318a82916028f363b3c5b52e7fd7256b632497Trond Norbye
2ee41fb5c7467f453a1282e3afdfacdd4aa4e6b8Trond Norbye#include "in-addr-util.h"
2ee41fb5c7467f453a1282e3afdfacdd4aa4e6b8Trond Norbye#include "netlink-util.h"
a1318a82916028f363b3c5b52e7fd7256b632497Trond Norbye#include "util.h"
a1318a82916028f363b3c5b52e7fd7256b632497Trond Norbye
a1318a82916028f363b3c5b52e7fd7256b632497Trond Norbyestatic void acd_handler(sd_ipv4acd *acd, int event, void *userdata) {
a1318a82916028f363b3c5b52e7fd7256b632497Trond Norbye assert_se(acd);
ca37bb3c4127b35d333203398bd983ee730d9da5Jan S Berg
ca37bb3c4127b35d333203398bd983ee730d9da5Jan S Berg switch (event) {
a1318a82916028f363b3c5b52e7fd7256b632497Trond Norbye case SD_IPV4ACD_EVENT_BIND:
a1318a82916028f363b3c5b52e7fd7256b632497Trond Norbye log_info("bound");
a1318a82916028f363b3c5b52e7fd7256b632497Trond Norbye break;
9661674ed58ba62a40e43d1a4b38d5e77c3c6545Knut Anders Hatlen case SD_IPV4ACD_EVENT_CONFLICT:
a1318a82916028f363b3c5b52e7fd7256b632497Trond Norbye log_info("conflict");
a1318a82916028f363b3c5b52e7fd7256b632497Trond Norbye break;
2ee41fb5c7467f453a1282e3afdfacdd4aa4e6b8Trond Norbye case SD_IPV4ACD_EVENT_STOP:
2ee41fb5c7467f453a1282e3afdfacdd4aa4e6b8Trond Norbye log_error("the client was stopped");
a1318a82916028f363b3c5b52e7fd7256b632497Trond Norbye break;
a1318a82916028f363b3c5b52e7fd7256b632497Trond Norbye default:
a1318a82916028f363b3c5b52e7fd7256b632497Trond Norbye assert_not_reached("invalid ACD event");
ca37bb3c4127b35d333203398bd983ee730d9da5Jan S Berg }
ca37bb3c4127b35d333203398bd983ee730d9da5Jan S Berg}
ca37bb3c4127b35d333203398bd983ee730d9da5Jan S Berg
ca37bb3c4127b35d333203398bd983ee730d9da5Jan S Bergstatic int client_run(int ifindex, const struct in_addr *pa, const struct ether_addr *ha, sd_event *e) {
a1318a82916028f363b3c5b52e7fd7256b632497Trond Norbye sd_ipv4acd *acd;
a1318a82916028f363b3c5b52e7fd7256b632497Trond Norbye
a1318a82916028f363b3c5b52e7fd7256b632497Trond Norbye assert_se(sd_ipv4acd_new(&acd) >= 0);
a1318a82916028f363b3c5b52e7fd7256b632497Trond Norbye assert_se(sd_ipv4acd_attach_event(acd, e, 0) >= 0);
a1318a82916028f363b3c5b52e7fd7256b632497Trond Norbye
a1318a82916028f363b3c5b52e7fd7256b632497Trond Norbye assert_se(sd_ipv4acd_set_index(acd, ifindex) >= 0);
a1318a82916028f363b3c5b52e7fd7256b632497Trond Norbye assert_se(sd_ipv4acd_set_mac(acd, ha) >= 0);
a1318a82916028f363b3c5b52e7fd7256b632497Trond Norbye assert_se(sd_ipv4acd_set_address(acd, pa) >= 0);
4bb936310d8f131aa850821e9254ac14242c7f95Knut Anders Hatlen assert_se(sd_ipv4acd_set_callback(acd, acd_handler, NULL) >= 0);
4bb936310d8f131aa850821e9254ac14242c7f95Knut Anders Hatlen
a1318a82916028f363b3c5b52e7fd7256b632497Trond Norbye log_info("starting IPv4ACD client");
a1318a82916028f363b3c5b52e7fd7256b632497Trond Norbye
a1318a82916028f363b3c5b52e7fd7256b632497Trond Norbye assert_se(sd_ipv4acd_start(acd) >= 0);
a1318a82916028f363b3c5b52e7fd7256b632497Trond Norbye
a1318a82916028f363b3c5b52e7fd7256b632497Trond Norbye assert_se(sd_event_loop(e) >= 0);
a1318a82916028f363b3c5b52e7fd7256b632497Trond Norbye
a1318a82916028f363b3c5b52e7fd7256b632497Trond Norbye assert_se(!sd_ipv4acd_unref(acd));
a1318a82916028f363b3c5b52e7fd7256b632497Trond Norbye
a1318a82916028f363b3c5b52e7fd7256b632497Trond Norbye return EXIT_SUCCESS;
a1318a82916028f363b3c5b52e7fd7256b632497Trond Norbye}
a1318a82916028f363b3c5b52e7fd7256b632497Trond Norbye
a1318a82916028f363b3c5b52e7fd7256b632497Trond Norbyestatic int test_acd(const char *ifname, const char *address) {
a1318a82916028f363b3c5b52e7fd7256b632497Trond Norbye _cleanup_(sd_event_unrefp) sd_event *e = NULL;
a1318a82916028f363b3c5b52e7fd7256b632497Trond Norbye _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL;
a1318a82916028f363b3c5b52e7fd7256b632497Trond Norbye _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL, *reply = NULL;
a1318a82916028f363b3c5b52e7fd7256b632497Trond Norbye union in_addr_union pa;
a1318a82916028f363b3c5b52e7fd7256b632497Trond Norbye struct ether_addr ha;
a1318a82916028f363b3c5b52e7fd7256b632497Trond Norbye int ifindex;
a1318a82916028f363b3c5b52e7fd7256b632497Trond Norbye
a1318a82916028f363b3c5b52e7fd7256b632497Trond Norbye assert_se(in_addr_from_string(AF_INET, address, &pa) >= 0);
a1318a82916028f363b3c5b52e7fd7256b632497Trond Norbye
a1318a82916028f363b3c5b52e7fd7256b632497Trond Norbye assert_se(sd_event_new(&e) >= 0);
a1318a82916028f363b3c5b52e7fd7256b632497Trond Norbye
a1318a82916028f363b3c5b52e7fd7256b632497Trond Norbye assert_se(sd_netlink_open(&rtnl) >= 0);
a1318a82916028f363b3c5b52e7fd7256b632497Trond Norbye assert_se(sd_netlink_attach_event(rtnl, e, 0) >= 0);
a1318a82916028f363b3c5b52e7fd7256b632497Trond Norbye
8d5c49b3d8edaa0069e4f802cf8bd70af9994c35Knut Anders Hatlen assert_se(sd_rtnl_message_new_link(rtnl, &m, RTM_GETLINK, 0) >= 0);
a1318a82916028f363b3c5b52e7fd7256b632497Trond Norbye assert_se(sd_netlink_message_append_string(m, IFLA_IFNAME, ifname) >= 0);
a1318a82916028f363b3c5b52e7fd7256b632497Trond Norbye assert_se(sd_netlink_call(rtnl, m, 0, &reply) >= 0);
a1318a82916028f363b3c5b52e7fd7256b632497Trond Norbye
a1318a82916028f363b3c5b52e7fd7256b632497Trond Norbye assert_se(sd_rtnl_message_link_get_ifindex(reply, &ifindex) >= 0);
a1318a82916028f363b3c5b52e7fd7256b632497Trond Norbye assert_se(sd_netlink_message_read_ether_addr(reply, IFLA_ADDRESS, &ha) >= 0);
a1318a82916028f363b3c5b52e7fd7256b632497Trond Norbye
a1318a82916028f363b3c5b52e7fd7256b632497Trond Norbye client_run(ifindex, &pa.in, &ha, e);
return EXIT_SUCCESS;
}
int main(int argc, char *argv[]) {
log_set_max_level(LOG_DEBUG);
log_parse_environment();
log_open();
if (argc == 3)
return test_acd(argv[1], argv[2]);
else {
log_error("This program takes two arguments.\n"
"\t %s <ifname> <IPv4 address>", program_invocation_short_name);
return EXIT_FAILURE;
}
}