]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/network/test-network.c
networkd/dhcp: shorten overlong hostname (#7616)
[thirdparty/systemd.git] / src / network / test-network.c
1 /* SPDX-License-Identifier: LGPL-2.1+ */
2 /***
3 This file is part of systemd.
4
5 Copyright 2013 Tom Gundersen <teg@jklm.no>
6
7 systemd is free software; you can redistribute it and/or modify it
8 under the terms of the GNU Lesser General Public License as published by
9 the Free Software Foundation; either version 2.1 of the License, or
10 (at your option) any later version.
11
12 systemd is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
16
17 You should have received a copy of the GNU Lesser General Public License
18 along with systemd; If not, see <http://www.gnu.org/licenses/>.
19 ***/
20
21 #include <sys/param.h>
22
23 #include "alloc-util.h"
24 #include "dhcp-lease-internal.h"
25 #include "hostname-util.h"
26 #include "network-internal.h"
27 #include "networkd-manager.h"
28 #include "string-util.h"
29 #include "udev-util.h"
30
31 static void test_deserialize_in_addr(void) {
32 _cleanup_free_ struct in_addr *addresses = NULL;
33 _cleanup_free_ struct in6_addr *addresses6 = NULL;
34 struct in_addr a, b, c;
35 struct in6_addr d, e, f;
36 int size;
37 const char *addresses_string = "192.168.0.1 0:0:0:0:0:FFFF:204.152.189.116 192.168.0.2 ::1 192.168.0.3 1:0:0:0:0:0:0:8";
38
39 assert_se(inet_pton(AF_INET, "0:0:0:0:0:FFFF:204.152.189.116", &a) == 0);
40 assert_se(inet_pton(AF_INET6, "192.168.0.1", &d) == 0);
41
42 assert_se(inet_pton(AF_INET, "192.168.0.1", &a) == 1);
43 assert_se(inet_pton(AF_INET, "192.168.0.2", &b) == 1);
44 assert_se(inet_pton(AF_INET, "192.168.0.3", &c) == 1);
45 assert_se(inet_pton(AF_INET6, "0:0:0:0:0:FFFF:204.152.189.116", &d) == 1);
46 assert_se(inet_pton(AF_INET6, "::1", &e) == 1);
47 assert_se(inet_pton(AF_INET6, "1:0:0:0:0:0:0:8", &f) == 1);
48
49 assert_se((size = deserialize_in_addrs(&addresses, addresses_string)) >= 0);
50 assert_se(size == 3);
51 assert_se(!memcmp(&a, &addresses[0], sizeof(struct in_addr)));
52 assert_se(!memcmp(&b, &addresses[1], sizeof(struct in_addr)));
53 assert_se(!memcmp(&c, &addresses[2], sizeof(struct in_addr)));
54
55 assert_se((size = deserialize_in6_addrs(&addresses6, addresses_string)) >= 0);
56 assert_se(size == 3);
57 assert_se(!memcmp(&d, &addresses6[0], sizeof(struct in6_addr)));
58 assert_se(!memcmp(&e, &addresses6[1], sizeof(struct in6_addr)));
59 assert_se(!memcmp(&f, &addresses6[2], sizeof(struct in6_addr)));
60 }
61
62 static void test_deserialize_dhcp_routes(void) {
63 size_t size, allocated;
64
65 {
66 _cleanup_free_ struct sd_dhcp_route *routes = NULL;
67 assert_se(deserialize_dhcp_routes(&routes, &size, &allocated, "") >= 0);
68 assert_se(size == 0);
69 }
70
71 {
72 /* no errors */
73 _cleanup_free_ struct sd_dhcp_route *routes = NULL;
74 const char *routes_string = "192.168.0.0/16,192.168.0.1 10.1.2.0/24,10.1.2.1 0.0.0.0/0,10.0.1.1";
75
76 assert_se(deserialize_dhcp_routes(&routes, &size, &allocated, routes_string) >= 0);
77
78 assert_se(size == 3);
79 assert_se(routes[0].dst_addr.s_addr == inet_addr("192.168.0.0"));
80 assert_se(routes[0].gw_addr.s_addr == inet_addr("192.168.0.1"));
81 assert_se(routes[0].dst_prefixlen == 16);
82
83 assert_se(routes[1].dst_addr.s_addr == inet_addr("10.1.2.0"));
84 assert_se(routes[1].gw_addr.s_addr == inet_addr("10.1.2.1"));
85 assert_se(routes[1].dst_prefixlen == 24);
86
87 assert_se(routes[2].dst_addr.s_addr == inet_addr("0.0.0.0"));
88 assert_se(routes[2].gw_addr.s_addr == inet_addr("10.0.1.1"));
89 assert_se(routes[2].dst_prefixlen == 0);
90 }
91
92 {
93 /* error in second word */
94 _cleanup_free_ struct sd_dhcp_route *routes = NULL;
95 const char *routes_string = "192.168.0.0/16,192.168.0.1 10.1.2.0#24,10.1.2.1 0.0.0.0/0,10.0.1.1";
96
97 assert_se(deserialize_dhcp_routes(&routes, &size, &allocated, routes_string) >= 0);
98
99 assert_se(size == 2);
100 assert_se(routes[0].dst_addr.s_addr == inet_addr("192.168.0.0"));
101 assert_se(routes[0].gw_addr.s_addr == inet_addr("192.168.0.1"));
102 assert_se(routes[0].dst_prefixlen == 16);
103
104 assert_se(routes[1].dst_addr.s_addr == inet_addr("0.0.0.0"));
105 assert_se(routes[1].gw_addr.s_addr == inet_addr("10.0.1.1"));
106 assert_se(routes[1].dst_prefixlen == 0);
107 }
108
109 {
110 /* error in every word */
111 _cleanup_free_ struct sd_dhcp_route *routes = NULL;
112 const char *routes_string = "192.168.0.0/55,192.168.0.1 10.1.2.0#24,10.1.2.1 0.0.0.0/0,10.0.1.X";
113
114 assert_se(deserialize_dhcp_routes(&routes, &size, &allocated, routes_string) >= 0);
115 assert_se(size == 0);
116 }
117 }
118
119 static int test_load_config(Manager *manager) {
120 int r;
121 /* TODO: should_reload, is false if the config dirs do not exist, so
122 * so we can't do this test here, move it to a test for paths_check_timestamps
123 * directly
124 *
125 * assert_se(network_should_reload(manager) == true);
126 */
127
128 r = manager_load_config(manager);
129 if (r == -EPERM)
130 return r;
131 assert_se(r >= 0);
132
133 assert_se(manager_should_reload(manager) == false);
134
135 return 0;
136 }
137
138 static void test_network_get(Manager *manager, struct udev_device *loopback) {
139 Network *network;
140 const struct ether_addr mac = {};
141
142 /* let's assume that the test machine does not have a .network file
143 that applies to the loopback device... */
144 assert_se(network_get(manager, loopback, "lo", &mac, &network) == -ENOENT);
145 assert_se(!network);
146 }
147
148 static void test_address_equality(void) {
149 _cleanup_address_free_ Address *a1 = NULL, *a2 = NULL;
150
151 assert_se(address_new(&a1) >= 0);
152 assert_se(address_new(&a2) >= 0);
153
154 assert_se(address_equal(NULL, NULL));
155 assert_se(!address_equal(a1, NULL));
156 assert_se(!address_equal(NULL, a2));
157 assert_se(address_equal(a1, a2));
158
159 a1->family = AF_INET;
160 assert_se(!address_equal(a1, a2));
161
162 a2->family = AF_INET;
163 assert_se(address_equal(a1, a2));
164
165 assert_se(inet_pton(AF_INET, "192.168.3.9", &a1->in_addr.in));
166 assert_se(!address_equal(a1, a2));
167 assert_se(inet_pton(AF_INET, "192.168.3.9", &a2->in_addr.in));
168 assert_se(address_equal(a1, a2));
169 assert_se(inet_pton(AF_INET, "192.168.3.10", &a1->in_addr_peer.in));
170 assert_se(address_equal(a1, a2));
171 assert_se(inet_pton(AF_INET, "192.168.3.11", &a2->in_addr_peer.in));
172 assert_se(address_equal(a1, a2));
173 a1->prefixlen = 10;
174 assert_se(!address_equal(a1, a2));
175 a2->prefixlen = 10;
176 assert_se(address_equal(a1, a2));
177
178 a1->family = AF_INET6;
179 assert_se(!address_equal(a1, a2));
180
181 a2->family = AF_INET6;
182 assert_se(inet_pton(AF_INET6, "2001:4ca0:4f01::2", &a1->in_addr.in6));
183 assert_se(inet_pton(AF_INET6, "2001:4ca0:4f01::2", &a2->in_addr.in6));
184 assert_se(address_equal(a1, a2));
185
186 a2->prefixlen = 8;
187 assert_se(address_equal(a1, a2));
188
189 assert_se(inet_pton(AF_INET6, "2001:4ca0:4f01::1", &a2->in_addr.in6));
190 assert_se(!address_equal(a1, a2));
191 }
192
193 static void test_dhcp_hostname_shorten_overlong(void) {
194 int r;
195
196 {
197 /* simple hostname, no actions, no errors */
198 _cleanup_free_ char *shortened = NULL;
199 r = shorten_overlong("name1", &shortened);
200 assert_se(r == 0);
201 assert_se(streq("name1", shortened));
202 }
203
204 {
205 /* simple fqdn, no actions, no errors */
206 _cleanup_free_ char *shortened = NULL;
207 r = shorten_overlong("name1.example.com", &shortened);
208 assert_se(r == 0);
209 assert_se(streq("name1.example.com", shortened));
210 }
211
212 {
213 /* overlong fqdn, cut to first dot, no errors */
214 _cleanup_free_ char *shortened = NULL;
215 r = shorten_overlong("name1.test-dhcp-this-one-here-is-a-very-very-long-domain.example.com", &shortened);
216 assert_se(r == 1);
217 assert_se(streq("name1", shortened));
218 }
219
220 {
221 /* overlong hostname, cut to HOST_MAX_LEN, no errors */
222 _cleanup_free_ char *shortened = NULL;
223 r = shorten_overlong("test-dhcp-this-one-here-is-a-very-very-long-hostname-without-domainname", &shortened);
224 assert_se(r == 1);
225 assert_se(streq("test-dhcp-this-one-here-is-a-very-very-long-hostname-without-dom", shortened));
226 }
227
228 {
229 /* overlong fqdn, cut to first dot, empty result error */
230 _cleanup_free_ char *shortened = NULL;
231 r = shorten_overlong(".test-dhcp-this-one-here-is-a-very-very-long-hostname.example.com", &shortened);
232 assert_se(r == -EDOM);
233 assert_se(shortened == NULL);
234 }
235
236 }
237
238 int main(void) {
239 _cleanup_manager_free_ Manager *manager = NULL;
240 _cleanup_(sd_event_unrefp) sd_event *event = NULL;
241 _cleanup_udev_unref_ struct udev *udev = NULL;
242 _cleanup_udev_device_unref_ struct udev_device *loopback = NULL;
243 int r;
244
245 test_deserialize_in_addr();
246 test_deserialize_dhcp_routes();
247 test_address_equality();
248 test_dhcp_hostname_shorten_overlong();
249
250 assert_se(sd_event_default(&event) >= 0);
251
252 assert_se(manager_new(&manager, event) >= 0);
253
254 r = test_load_config(manager);
255 if (r == -EPERM)
256 return EXIT_TEST_SKIP;
257
258 udev = udev_new();
259 assert_se(udev);
260
261 loopback = udev_device_new_from_syspath(udev, "/sys/class/net/lo");
262 assert_se(loopback);
263 assert_se(udev_device_get_ifindex(loopback) == 1);
264
265 test_network_get(manager, loopback);
266
267 assert_se(manager_rtnl_enumerate_links(manager) >= 0);
268 }