chiark / gitweb /
bus-proxyd: explicitly address messages to unique and well-known name
[elogind.git] / src / libsystemd-network / test-pppoe.c
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3 /***
4   This file is part of systemd.
5
6   Copyright (C) 2014 Tom Gundersen <teg@jklm.no>
7
8   systemd is free software; you can redistribute it and/or modify it
9   under the terms of the GNU Lesser General Public License as published by
10   the Free Software Foundation; either version 2.1 of the License, or
11   (at your option) any later version.
12
13   systemd is distributed in the hope that it will be useful, but
14   WITHOUT ANY WARRANTY; without even the implied warranty of
15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16   Lesser General Public License for more details.
17
18   You should have received a copy of the GNU Lesser General Public License
19   along with systemd; If not, see <http://www.gnu.org/licenses/>.
20 ***/
21
22 #include <stdlib.h>
23 #include <assert.h>
24 #include <errno.h>
25 #include <stdio.h>
26 #include <sys/types.h>
27 #include <sys/socket.h>
28 #include <unistd.h>
29
30 #include <linux/veth.h>
31 #include <net/if.h>
32
33 #include "util.h"
34 #include "socket-util.h"
35 #include "sd-event.h"
36 #include "event-util.h"
37 #include "sd-rtnl.h"
38 #include "rtnl-util.h"
39 #include "sd-pppoe.h"
40
41 static void pppoe_handler(sd_pppoe *ppp, int event, void *userdata) {
42         static int pppoe_state = -1;
43         sd_event *e = userdata;
44
45         assert_se(ppp);
46         assert_se(e);
47
48         switch (event) {
49         case PPPOE_EVENT_RUNNING:
50                 assert_se(pppoe_state == -1);
51                 log_info("running");
52                 break;
53         case PPPOE_EVENT_STOPPED:
54                 assert_se(pppoe_state == PPPOE_EVENT_RUNNING);
55                 log_info("stopped");
56                 assert_se(sd_event_exit(e, 0) >= 0);
57                 break;
58         default:
59                 assert_not_reached("invalid pppoe event");
60         }
61
62         pppoe_state = event;
63 }
64
65 static int client_run(const char *client_name, sd_event *e) {
66         sd_pppoe *pppoe;
67         int client_ifindex;
68
69         client_ifindex = (int) if_nametoindex(client_name);
70         assert_se(client_ifindex > 0);
71
72         assert_se(sd_pppoe_new(&pppoe) >= 0);
73         assert_se(sd_pppoe_attach_event(pppoe, e, 0) >= 0);
74
75         assert_se(sd_pppoe_set_ifname(pppoe, "pppoe-client") >= 0);
76         assert_se(sd_pppoe_set_ifindex(pppoe, client_ifindex) >= 0);
77         assert_se(sd_pppoe_set_callback(pppoe, pppoe_handler, e) >= 0);
78
79         log_info("starting PPPoE client, it will exit when the server times out and sends PADT");
80
81         assert_se(sd_pppoe_start(pppoe) >= 0);
82
83         assert_se(sd_event_loop(e) >= 0);
84
85         assert_se(!sd_pppoe_unref(pppoe));
86
87         return EXIT_SUCCESS;
88 }
89
90 static int test_pppoe_server(sd_event *e) {
91         sd_rtnl *rtnl;
92         sd_rtnl_message *m;
93         pid_t pid;
94         int r, client_ifindex, server_ifindex;
95
96         r = unshare(CLONE_NEWNET);
97         if (r < 0 && errno == EPERM)
98                 return EXIT_TEST_SKIP;
99
100         assert_se(r >= 0);
101
102         assert_se(sd_rtnl_open(&rtnl, 0) >= 0);
103         assert_se(sd_rtnl_attach_event(rtnl, e, 0) >= 0);
104
105         assert_se(sd_rtnl_message_new_link(rtnl, &m, RTM_NEWLINK, 0) >= 0);
106         assert_se(sd_rtnl_message_append_string(m, IFLA_IFNAME, "pppoe-server") >= 0);
107         assert_se(sd_rtnl_message_open_container(m, IFLA_LINKINFO) >= 0);
108         assert_se(sd_rtnl_message_open_container_union(m, IFLA_INFO_DATA, "veth") >= 0);
109         assert_se(sd_rtnl_message_open_container(m, VETH_INFO_PEER) >= 0);
110         assert_se(sd_rtnl_message_append_string(m, IFLA_IFNAME, "pppoe-client") >= 0);
111         assert_se(sd_rtnl_message_close_container(m) >= 0);
112         assert_se(sd_rtnl_message_close_container(m) >= 0);
113         assert_se(sd_rtnl_message_close_container(m) >= 0);
114         assert_se(sd_rtnl_call(rtnl, m, 0, NULL) >= 0);
115
116         client_ifindex = (int) if_nametoindex("pppoe-client");
117         assert_se(client_ifindex > 0);
118         server_ifindex = (int) if_nametoindex("pppoe-server");
119         assert_se(server_ifindex > 0);
120
121         m = sd_rtnl_message_unref(m);
122         assert_se(sd_rtnl_message_new_link(rtnl, &m, RTM_SETLINK, client_ifindex) >= 0);
123         assert_se(sd_rtnl_message_link_set_flags(m, IFF_UP, IFF_UP) >= 0);
124         assert_se(sd_rtnl_call(rtnl, m, 0, NULL) >= 0);
125
126         m = sd_rtnl_message_unref(m);
127         assert_se(sd_rtnl_message_new_link(rtnl, &m, RTM_SETLINK, server_ifindex) >= 0);
128         assert_se(sd_rtnl_message_link_set_flags(m, IFF_UP, IFF_UP) >= 0);
129         assert_se(sd_rtnl_call(rtnl, m, 0, NULL) >= 0);
130
131         pid = fork();
132         assert_se(pid >= 0);
133         if (pid == 0) {
134                 /* let the client send some discover messages before the server is started */
135                 sleep(2);
136
137                 /* TODO: manage pppoe-server-options */
138                 execlp("pppoe-server", "pppoe-server", "-F",
139                        "-I", "pppoe-server",
140                        "-C", "Test-AC",
141                        "-S", "Service-Default",
142                        "-S", "Service-First-Auxillary",
143                        "-S", "Service-Second-Auxillary",
144                        NULL);
145                 assert_not_reached("failed to execute pppoe-server. not installed?");
146         }
147
148         client_run("pppoe-client", e);
149
150         assert_se(kill(pid, SIGTERM) >= 0);
151         assert_se(wait_for_terminate(pid, NULL) >= 0);
152
153         assert_se(!sd_rtnl_message_unref(m));
154         assert_se(!sd_rtnl_unref(rtnl));
155
156         return EXIT_SUCCESS;
157 }
158
159 int main(int argc, char *argv[]) {
160         _cleanup_event_unref_ sd_event *e = NULL;
161
162         log_set_max_level(LOG_DEBUG);
163         log_parse_environment();
164         log_open();
165
166         assert_se(sd_event_new(&e) >= 0);
167
168         if (argc == 1) {
169                 log_info("running PPPoE client against local server");
170
171                 return test_pppoe_server(e);
172         } else if (argc == 2) {
173                 log_info("running PPPoE client over '%s'", argv[1]);
174
175                 return client_run(argv[1], e);
176         } else {
177                 log_error("This program takes one or no arguments.\n"
178                           "\t %s [<ifname>]", program_invocation_short_name);
179                 return EXIT_FAILURE;
180         }
181 }