chiark / gitweb /
Remove src/backlight
[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 <errno.h>
24 #include <unistd.h>
25
26 #include <linux/veth.h>
27 #include <net/if.h>
28
29 #include "util.h"
30 #include "sd-event.h"
31 #include "event-util.h"
32 #include "sd-rtnl.h"
33 #include "sd-pppoe.h"
34
35 static void pppoe_handler(sd_pppoe *ppp, int event, void *userdata) {
36         static int pppoe_state = -1;
37         sd_event *e = userdata;
38
39         assert_se(ppp);
40         assert_se(e);
41
42         switch (event) {
43         case PPPOE_EVENT_RUNNING:
44                 assert_se(pppoe_state == -1);
45                 log_info("running");
46                 break;
47         case PPPOE_EVENT_STOPPED:
48                 assert_se(pppoe_state == PPPOE_EVENT_RUNNING);
49                 log_info("stopped");
50                 assert_se(sd_event_exit(e, 0) >= 0);
51                 break;
52         default:
53                 assert_not_reached("invalid pppoe event");
54         }
55
56         pppoe_state = event;
57 }
58
59 static int client_run(const char *client_name, sd_event *e) {
60         sd_pppoe *pppoe;
61         int client_ifindex;
62
63         client_ifindex = (int) if_nametoindex(client_name);
64         assert_se(client_ifindex > 0);
65
66         assert_se(sd_pppoe_new(&pppoe) >= 0);
67         assert_se(sd_pppoe_attach_event(pppoe, e, 0) >= 0);
68
69         assert_se(sd_pppoe_set_ifname(pppoe, "pppoe-client") >= 0);
70         assert_se(sd_pppoe_set_ifindex(pppoe, client_ifindex) >= 0);
71         assert_se(sd_pppoe_set_callback(pppoe, pppoe_handler, e) >= 0);
72
73         log_info("starting PPPoE client, it will exit when the server times out and sends PADT");
74
75         assert_se(sd_pppoe_start(pppoe) >= 0);
76
77         assert_se(sd_event_loop(e) >= 0);
78
79         assert_se(!sd_pppoe_unref(pppoe));
80
81         return EXIT_SUCCESS;
82 }
83
84 static int test_pppoe_server(sd_event *e) {
85         sd_rtnl *rtnl;
86         sd_rtnl_message *m;
87         pid_t pid;
88         int r, client_ifindex, server_ifindex;
89
90         r = unshare(CLONE_NEWNET);
91         if (r < 0 && errno == EPERM)
92                 return EXIT_TEST_SKIP;
93
94         assert_se(r >= 0);
95
96         assert_se(sd_rtnl_open(&rtnl, 0) >= 0);
97         assert_se(sd_rtnl_attach_event(rtnl, e, 0) >= 0);
98
99         assert_se(sd_rtnl_message_new_link(rtnl, &m, RTM_NEWLINK, 0) >= 0);
100         assert_se(sd_rtnl_message_append_string(m, IFLA_IFNAME, "pppoe-server") >= 0);
101         assert_se(sd_rtnl_message_open_container(m, IFLA_LINKINFO) >= 0);
102         assert_se(sd_rtnl_message_open_container_union(m, IFLA_INFO_DATA, "veth") >= 0);
103         assert_se(sd_rtnl_message_open_container(m, VETH_INFO_PEER) >= 0);
104         assert_se(sd_rtnl_message_append_string(m, IFLA_IFNAME, "pppoe-client") >= 0);
105         assert_se(sd_rtnl_message_close_container(m) >= 0);
106         assert_se(sd_rtnl_message_close_container(m) >= 0);
107         assert_se(sd_rtnl_message_close_container(m) >= 0);
108         assert_se(sd_rtnl_call(rtnl, m, 0, NULL) >= 0);
109
110         client_ifindex = (int) if_nametoindex("pppoe-client");
111         assert_se(client_ifindex > 0);
112         server_ifindex = (int) if_nametoindex("pppoe-server");
113         assert_se(server_ifindex > 0);
114
115         m = sd_rtnl_message_unref(m);
116         assert_se(sd_rtnl_message_new_link(rtnl, &m, RTM_SETLINK, client_ifindex) >= 0);
117         assert_se(sd_rtnl_message_link_set_flags(m, IFF_UP, IFF_UP) >= 0);
118         assert_se(sd_rtnl_call(rtnl, m, 0, NULL) >= 0);
119
120         m = sd_rtnl_message_unref(m);
121         assert_se(sd_rtnl_message_new_link(rtnl, &m, RTM_SETLINK, server_ifindex) >= 0);
122         assert_se(sd_rtnl_message_link_set_flags(m, IFF_UP, IFF_UP) >= 0);
123         assert_se(sd_rtnl_call(rtnl, m, 0, NULL) >= 0);
124
125         pid = fork();
126         assert_se(pid >= 0);
127         if (pid == 0) {
128                 /* let the client send some discover messages before the server is started */
129                 sleep(2);
130
131                 /* TODO: manage pppoe-server-options */
132                 execlp("pppoe-server", "pppoe-server", "-F",
133                        "-I", "pppoe-server",
134                        "-C", "Test-AC",
135                        "-S", "Service-Default",
136                        "-S", "Service-First-Auxiliary",
137                        "-S", "Service-Second-Auxiliary",
138                        NULL);
139                 assert_not_reached("failed to execute pppoe-server. not installed?");
140         }
141
142         client_run("pppoe-client", e);
143
144         assert_se(kill(pid, SIGTERM) >= 0);
145         assert_se(wait_for_terminate(pid, NULL) >= 0);
146
147         assert_se(!sd_rtnl_message_unref(m));
148         assert_se(!sd_rtnl_unref(rtnl));
149
150         return EXIT_SUCCESS;
151 }
152
153 int main(int argc, char *argv[]) {
154         _cleanup_event_unref_ sd_event *e = NULL;
155
156         log_set_max_level(LOG_DEBUG);
157         log_parse_environment();
158         log_open();
159
160         assert_se(sd_event_new(&e) >= 0);
161
162         if (argc == 1) {
163                 log_info("running PPPoE client against local server");
164
165                 return test_pppoe_server(e);
166         } else if (argc == 2) {
167                 log_info("running PPPoE client over '%s'", argv[1]);
168
169                 return client_run(argv[1], e);
170         } else {
171                 log_error("This program takes one or no arguments.\n"
172                           "\t %s [<ifname>]", program_invocation_short_name);
173                 return EXIT_FAILURE;
174         }
175 }