1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2013 Tom Gundersen <teg@jklm.no>
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.
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.
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/>.
22 #include <linux/rtnetlink.h>
23 #include <netinet/ether.h>
28 #include "socket-util.h"
29 #include "rtnl-util.h"
31 static void test_link_configure(sd_rtnl *rtnl, int ifindex) {
32 _cleanup_sd_rtnl_message_unref_ sd_rtnl_message *message;
34 const char *mac = "98:fe:94:3f:c6:18", *name = "test";
35 unsigned int mtu = 1450;
38 /* we'd really like to test NEWLINK, but let's not mess with the running kernel */
39 assert(sd_rtnl_message_link_new(RTM_GETLINK, ifindex, 0, 0, &message) >= 0);
40 assert(sd_rtnl_message_append(message, IFLA_IFNAME, name) >= 0);
41 assert(sd_rtnl_message_append(message, IFLA_ADDRESS, ether_aton(mac)) >= 0);
42 assert(sd_rtnl_message_append(message, IFLA_MTU, &mtu) >= 0);
44 assert(sd_rtnl_message_read(message, &type, &data) >= 0);
45 assert(type == IFLA_IFNAME);
46 assert(streq(name, (char *) data));
48 assert(sd_rtnl_message_read(message, &type, &data) >= 0);
49 assert(type == IFLA_ADDRESS);
50 assert(streq(mac, ether_ntoa(data)));
52 assert(sd_rtnl_message_read(message, &type, &data) >= 0);
53 assert(type == IFLA_MTU);
54 assert(mtu == *(unsigned int *) data);
56 assert(sd_rtnl_call(rtnl, message, 0, NULL) == 1);
59 static void test_route(void) {
60 _cleanup_sd_rtnl_message_unref_ sd_rtnl_message *req;
61 uint32_t addr = htonl(INADDR_LOOPBACK);
67 r = sd_rtnl_message_route_new(RTM_NEWROUTE, AF_INET, 0, 0, 0,
68 RT_TABLE_MAIN, RT_SCOPE_UNIVERSE, RTPROT_BOOT,
69 RTN_UNICAST, 0, &req);
71 log_error("Could not create RTM_NEWROUTE message: %s", strerror(-r));
75 r = sd_rtnl_message_append(req, RTA_GATEWAY, &addr);
77 log_error("Could not append RTA_GATEWAY attribute: %s", strerror(-r));
81 r = sd_rtnl_message_append(req, RTA_OIF, &index);
83 log_error("Could not append RTA_OIF attribute: %s", strerror(-r));
87 assert(sd_rtnl_message_read(req, &type, &data) > 0);
88 assert(type == RTA_GATEWAY);
89 assert(*(uint32_t *) data == addr);
91 assert(sd_rtnl_message_read(req, &type, &data) > 0);
92 assert(type == RTA_OIF);
93 assert(*(uint32_t *) data == index);
96 static void test_multiple(void) {
97 sd_rtnl *rtnl1, *rtnl2;
99 assert(sd_rtnl_open(0, &rtnl1) >= 0);
100 assert(sd_rtnl_open(0, &rtnl2) >= 0);
102 rtnl1 = sd_rtnl_unref(rtnl1);
103 rtnl2 = sd_rtnl_unref(rtnl2);
106 static int link_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
109 char *ifname = userdata;
114 log_info("got link info about %s", ifname);
117 while (sd_rtnl_message_read(m, &type, &data) > 0) {
120 // assert(*(unsigned int *) data == 65536);
123 // assert(streq((char *) data, "noqueue"));
126 assert(streq((char *) data, "lo"));
134 static int pipe_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
135 int *counter = userdata;
139 log_info("got reply, %d left in pipe", *counter);
141 return sd_rtnl_message_get_errno(m);
144 static void test_async(void) {
145 _cleanup_sd_rtnl_unref_ sd_rtnl *rtnl = NULL;
146 _cleanup_sd_rtnl_message_unref_ sd_rtnl_message *m = NULL, *r = NULL;
151 ifname = strdup("lo");
153 assert(sd_rtnl_open(0, &rtnl) >= 0);
155 if_loopback = (int) if_nametoindex("lo");
156 assert(if_loopback > 0);
158 assert(sd_rtnl_message_link_new(RTM_GETLINK, if_loopback, 0, 0, &m) >= 0);
160 assert(sd_rtnl_call_async(rtnl, m, &link_handler, ifname, 0, &serial) >= 0);
162 assert(sd_rtnl_wait(rtnl, 0) >= 0);
163 assert(sd_rtnl_process(rtnl, &r) >= 0);
166 static void test_pipe(void) {
167 _cleanup_sd_rtnl_unref_ sd_rtnl *rtnl = NULL;
168 _cleanup_sd_rtnl_message_unref_ sd_rtnl_message *m1 = NULL, *m2 = NULL;
172 assert(sd_rtnl_open(0, &rtnl) >= 0);
174 if_loopback = (int) if_nametoindex("lo");
175 assert(if_loopback > 0);
177 assert(sd_rtnl_message_link_new(RTM_GETLINK, if_loopback, 0, 0, &m1) >= 0);
178 assert(sd_rtnl_message_link_new(RTM_GETLINK, if_loopback, 0, 0, &m2) >= 0);
181 assert(sd_rtnl_call_async(rtnl, m1, &pipe_handler, &counter, 0, NULL) >= 0);
184 assert(sd_rtnl_call_async(rtnl, m2, &pipe_handler, &counter, 0, NULL) >= 0);
186 while (counter > 0) {
187 assert(sd_rtnl_wait(rtnl, 0) >= 0);
188 assert(sd_rtnl_process(rtnl, NULL) >= 0);
199 unsigned int mtu = 0;
200 unsigned int *mtu_reply;
210 assert(sd_rtnl_open(0, &rtnl) >= 0);
213 if_loopback = (int) if_nametoindex("lo");
214 assert(if_loopback > 0);
216 test_link_configure(rtnl, if_loopback);
218 assert(sd_rtnl_message_link_new(RTM_GETLINK, if_loopback, 0, 0, &m) >= 0);
221 assert(sd_rtnl_message_get_type(m, &type) >= 0);
222 assert(type == RTM_GETLINK);
224 assert(sd_rtnl_message_read(m, &type, &data) == 0);
226 assert(sd_rtnl_call(rtnl, m, 0, &r) == 1);
227 assert(sd_rtnl_message_get_type(r, &type) >= 0);
228 assert(type == RTM_NEWLINK);
230 assert(sd_rtnl_message_read(m, &type, &data) == 0);
231 assert((r = sd_rtnl_message_unref(r)) == NULL);
233 assert(sd_rtnl_call(rtnl, m, -1, &r) == -EPERM);
234 assert((m = sd_rtnl_message_unref(m)) == NULL);
235 assert((r = sd_rtnl_message_unref(r)) == NULL);
237 assert(sd_rtnl_message_link_new(RTM_GETLINK, if_loopback, 0, 0, &m) >= 0);
240 assert(sd_rtnl_message_append(m, IFLA_MTU, &mtu) >= 0);
241 assert(sd_rtnl_message_read(m, &type, (void **) &mtu_reply) == 1);
243 assert(type == IFLA_MTU);
244 assert(*mtu_reply == 0);
246 assert(sd_rtnl_message_read(m, &type, &data) == 0);
248 assert(sd_rtnl_call(rtnl, m, -1, &r) == 1);
249 while (sd_rtnl_message_read(r, &type, &data) > 0) {
252 // assert(*(unsigned int *) data == 65536);
255 // assert(streq((char *) data, "noqueue"));
258 assert(streq((char *) data, "lo"));
263 assert((m = sd_rtnl_message_unref(m)) == NULL);
264 assert((r = sd_rtnl_message_unref(r)) == NULL);
265 assert((rtnl = sd_rtnl_unref(rtnl)) == NULL);