test-ipv4ll.c revision 996d16975b4d802335188a3be2bbc3635c1287f3
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering/***
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering This file is part of systemd.
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering Copyright (C) 2014 Axis Communications AB. All rights reserved.
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering systemd is free software; you can redistribute it and/or modify it
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering under the terms of the GNU Lesser General Public License as published by
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering the Free Software Foundation; either version 2.1 of the License, or
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering (at your option) any later version.
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering systemd is distributed in the hope that it will be useful, but
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering WITHOUT ANY WARRANTY; without even the implied warranty of
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering Lesser General Public License for more details.
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering You should have received a copy of the GNU Lesser General Public License
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering along with systemd; If not, see <http://www.gnu.org/licenses/>.
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering***/
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include <stdlib.h>
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include <assert.h>
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include <errno.h>
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include <stdio.h>
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include <sys/types.h>
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include <sys/socket.h>
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include <unistd.h>
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen#include "util.h"
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen#include "socket-util.h"
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include "event-util.h"
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include "sd-ipv4ll.h"
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include "arp-util.h"
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersenstatic bool verbose = false;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringstatic bool extended = false;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringstatic int test_fd[2];
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringstatic int basic_request_handler_bind = 0;
9d12709626bccc0cae677a7035f62efe6aabb4abLennart Poetteringstatic int basic_request_handler_stop = 0;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringstatic void* basic_request_handler_userdata = (void*)0xCABCAB;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringstatic void basic_request_handler(sd_ipv4ll *ll, int event, void *userdata) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering assert_se(userdata == basic_request_handler_userdata);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering switch(event) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering case IPV4LL_EVENT_STOP:
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering basic_request_handler_stop = 1;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering break;
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering case IPV4LL_EVENT_BIND:
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering basic_request_handler_bind = 1;
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering break;
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering default:
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering assert_se(0);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering break;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering }
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering}
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringstatic int arp_network_send_raw_socket(int fd, int ifindex,
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering const struct ether_arp *arp) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering assert_se(arp);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering assert_se(ifindex > 0);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering assert_se(fd >= 0);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (send(fd, arp, sizeof(struct ether_arp), 0) < 0)
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen return -errno;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen return 0;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen}
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringint arp_send_probe(int fd, int ifindex,
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering be32_t pa, const struct ether_addr *ha) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering struct ether_arp ea = {};
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen assert(fd >= 0);
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen assert(ifindex > 0);
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen assert(pa != 0);
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen assert(ha);
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen return arp_network_send_raw_socket(fd, ifindex, &ea);
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen}
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersenint arp_send_announcement(int fd, int ifindex,
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen be32_t pa, const struct ether_addr *ha) {
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen struct ether_arp ea = {};
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering assert(fd >= 0);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering assert(ifindex > 0);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering assert(pa != 0);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering assert(ha);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen return arp_network_send_raw_socket(fd, ifindex, &ea);
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen}
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringint arp_network_bind_raw_socket(int index, be32_t address, const struct ether_addr *eth_mac) {
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen if (socketpair(AF_UNIX, SOCK_DGRAM | SOCK_NONBLOCK, 0, test_fd) < 0)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return -errno;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return test_fd[0];
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering}
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersenstatic void test_public_api_setters(sd_event *e) {
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen uint8_t seed[8];
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen sd_ipv4ll *ll;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen struct ether_addr mac_addr = {
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen .ether_addr_octet = {'A', 'B', 'C', '1', '2', '3'}};
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (verbose)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering printf("* %s\n", __FUNCTION__);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering assert_se(sd_ipv4ll_new(&ll) == 0);
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen assert_se(ll);
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen assert_se(sd_ipv4ll_attach_event(NULL, NULL, 0) == -EINVAL);
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering assert_se(sd_ipv4ll_attach_event(ll, e, 0) == 0);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering assert_se(sd_ipv4ll_attach_event(ll, e, 0) == -EBUSY);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen assert_se(sd_ipv4ll_set_callback(NULL, NULL, NULL) == -EINVAL);
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen assert_se(sd_ipv4ll_set_callback(ll, NULL, NULL) == 0);
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering assert_se(sd_ipv4ll_set_address_seed(NULL, NULL) == -EINVAL);
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering assert_se(sd_ipv4ll_set_address_seed(ll, NULL) == -EINVAL);
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering assert_se(sd_ipv4ll_set_address_seed(ll, seed) == 0);
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering assert_se(sd_ipv4ll_set_mac(NULL, NULL) == -EINVAL);
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering assert_se(sd_ipv4ll_set_mac(ll, NULL) == -EINVAL);
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering assert_se(sd_ipv4ll_set_mac(ll, &mac_addr) == 0);
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering assert_se(sd_ipv4ll_set_index(NULL, -1) == -EINVAL);
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering assert_se(sd_ipv4ll_set_index(ll, -1) == -EINVAL);
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering assert_se(sd_ipv4ll_set_index(ll, -99) == -EINVAL);
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering assert_se(sd_ipv4ll_set_index(ll, 1) == 0);
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering assert_se(sd_ipv4ll_set_index(ll, 99) == 0);
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering assert_se(sd_ipv4ll_ref(ll) == ll);
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering assert_se(sd_ipv4ll_unref(ll) == ll);
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering /* Cleanup */
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering assert_se(sd_ipv4ll_unref(ll) == NULL);
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering}
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poetteringstatic void test_basic_request(sd_event *e) {
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering sd_ipv4ll *ll;
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering struct ether_arp arp;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen struct ether_addr mac_addr = {
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering .ether_addr_octet = {'A', 'B', 'C', '1', '2', '3'}};
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering if (verbose)
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering printf("* %s\n", __FUNCTION__);
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen assert_se(sd_ipv4ll_new(&ll) == 0);
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen assert_se(sd_ipv4ll_start(ll) == -EINVAL);
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering assert_se(sd_ipv4ll_attach_event(ll, e, 0) == 0);
9d12709626bccc0cae677a7035f62efe6aabb4abLennart Poettering assert_se(sd_ipv4ll_start(ll) == -EINVAL);
9d12709626bccc0cae677a7035f62efe6aabb4abLennart Poettering
9d12709626bccc0cae677a7035f62efe6aabb4abLennart Poettering assert_se(sd_ipv4ll_set_mac(ll, &mac_addr) == 0);
9d12709626bccc0cae677a7035f62efe6aabb4abLennart Poettering assert_se(sd_ipv4ll_start(ll) == -EINVAL);
9d12709626bccc0cae677a7035f62efe6aabb4abLennart Poettering
9d12709626bccc0cae677a7035f62efe6aabb4abLennart Poettering assert_se(sd_ipv4ll_set_callback(ll, basic_request_handler,
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering basic_request_handler_userdata) == 0);
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering assert_se(sd_ipv4ll_start(ll) == -EINVAL);
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering assert_se(sd_ipv4ll_set_index(ll, 1) == 0);
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering assert_se(sd_ipv4ll_start(ll) == 0);
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering sd_event_run(e, (uint64_t) -1);
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering assert_se(sd_ipv4ll_start(ll) == -EBUSY);
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering /* PROBE */
9d12709626bccc0cae677a7035f62efe6aabb4abLennart Poettering sd_event_run(e, (uint64_t) -1);
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering assert_se(read(test_fd[1], &arp, sizeof(struct ether_arp)) == sizeof(struct ether_arp));
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering if (extended) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering /* PROBE */
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering sd_event_run(e, (uint64_t) -1);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering assert_se(read(test_fd[1], &arp, sizeof(struct ether_arp)) == sizeof(struct ether_arp));
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering /* PROBE */
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering sd_event_run(e, (uint64_t) -1);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering assert_se(read(test_fd[1], &arp, sizeof(struct ether_arp)) == sizeof(struct ether_arp));
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering sd_event_run(e, (uint64_t) -1);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering assert_se(basic_request_handler_bind == 1);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering }
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering sd_ipv4ll_stop(ll);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering assert_se(basic_request_handler_stop == 1);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering /* Cleanup */
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering assert_se(sd_ipv4ll_unref(ll) == NULL);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering safe_close(test_fd[1]);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering}
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringint main(int argc, char *argv[]) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering _cleanup_event_unref_ sd_event *e = NULL;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering assert_se(sd_event_new(&e) >= 0);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering test_public_api_setters(e);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering test_basic_request(e);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return 0;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering}
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering