]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/network/networkd-ipv4ll.c
networkd: route - rename fields in struct
[thirdparty/systemd.git] / src / network / networkd-ipv4ll.c
CommitLineData
b22d8a00
TG
1/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3/***
4 This file is part of systemd.
5
6 Copyright 2013-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 <netinet/ether.h>
23#include <linux/if.h>
24
25#include "networkd-link.h"
26#include "network-internal.h"
27
28static int ipv4ll_address_lost(Link *link) {
29 _cleanup_address_free_ Address *address = NULL;
30 _cleanup_route_free_ Route *route = NULL;
31 struct in_addr addr;
32 int r;
33
34 assert(link);
35
36 link->ipv4ll_route = false;
920b52e4 37 link->ipv4ll_address = false;
b22d8a00
TG
38
39 r = sd_ipv4ll_get_address(link->ipv4ll, &addr);
40 if (r < 0)
41 return 0;
42
79008bdd 43 log_link_debug(link, "IPv4 link-local release %u.%u.%u.%u", ADDRESS_FMT_VAL(addr));
b22d8a00 44
f0213e37 45 r = address_new(&address);
b22d8a00 46 if (r < 0) {
e53fc357 47 log_link_error_errno(link, r, "Could not allocate address: %m");
b22d8a00
TG
48 return r;
49 }
50
51 address->family = AF_INET;
52 address->in_addr.in = addr;
53 address->prefixlen = 16;
54 address->scope = RT_SCOPE_LINK;
55
91b5f997 56 address_remove(address, link, &link_address_remove_handler);
b22d8a00 57
ed9e361a 58 r = route_new(&route);
b22d8a00 59 if (r < 0) {
e53fc357 60 log_link_error_errno(link, r, "Could not allocate route: %m");
b22d8a00
TG
61 return r;
62 }
63
64 route->family = AF_INET;
65 route->scope = RT_SCOPE_LINK;
66 route->metrics = IPV4LL_ROUTE_METRIC;
67
91b5f997 68 route_remove(route, link, &link_route_remove_handler);
b22d8a00 69
8012cd39 70 link_check_ready(link);
b22d8a00
TG
71
72 return 0;
73}
74
1c4baffc 75static int ipv4ll_route_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) {
b22d8a00
TG
76 _cleanup_link_unref_ Link *link = userdata;
77 int r;
78
79 assert(link);
80 assert(!link->ipv4ll_route);
81
1c4baffc 82 r = sd_netlink_message_get_errno(m);
b22d8a00 83 if (r < 0 && r != -EEXIST) {
e53fc357 84 log_link_error_errno(link, r, "could not set ipv4ll route: %m");
b22d8a00
TG
85 link_enter_failed(link);
86 }
87
88 link->ipv4ll_route = true;
89
90 if (link->ipv4ll_address == true)
8012cd39 91 link_check_ready(link);
b22d8a00
TG
92
93 return 1;
94}
95
1c4baffc 96static int ipv4ll_address_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) {
b22d8a00
TG
97 _cleanup_link_unref_ Link *link = userdata;
98 int r;
99
100 assert(link);
101 assert(!link->ipv4ll_address);
102
1c4baffc 103 r = sd_netlink_message_get_errno(m);
b22d8a00 104 if (r < 0 && r != -EEXIST) {
e53fc357 105 log_link_error_errno(link, r, "could not set ipv4ll address: %m");
b22d8a00 106 link_enter_failed(link);
45af44d4 107 } else if (r >= 0)
200a0868 108 manager_rtnl_process_address(rtnl, m, link->manager);
b22d8a00
TG
109
110 link->ipv4ll_address = true;
111
112 if (link->ipv4ll_route == true)
8012cd39 113 link_check_ready(link);
b22d8a00
TG
114
115 return 1;
116}
117
118static int ipv4ll_address_claimed(sd_ipv4ll *ll, Link *link) {
119 _cleanup_address_free_ Address *ll_addr = NULL;
120 _cleanup_route_free_ Route *route = NULL;
121 struct in_addr address;
122 int r;
123
124 assert(ll);
125 assert(link);
126
127 r = sd_ipv4ll_get_address(ll, &address);
128 if (r == -ENOENT)
129 return 0;
130 else if (r < 0)
131 return r;
132
79008bdd 133 log_link_debug(link, "IPv4 link-local claim %u.%u.%u.%u",
b22d8a00
TG
134 ADDRESS_FMT_VAL(address));
135
f0213e37 136 r = address_new(&ll_addr);
b22d8a00
TG
137 if (r < 0)
138 return r;
139
140 ll_addr->family = AF_INET;
141 ll_addr->in_addr.in = address;
142 ll_addr->prefixlen = 16;
143 ll_addr->broadcast.s_addr = ll_addr->in_addr.in.s_addr | htonl(0xfffffffflu >> ll_addr->prefixlen);
144 ll_addr->scope = RT_SCOPE_LINK;
145
66669078 146 r = address_configure(ll_addr, link, ipv4ll_address_handler, false);
b22d8a00
TG
147 if (r < 0)
148 return r;
149
150 link->ipv4ll_address = false;
151
ed9e361a 152 r = route_new(&route);
b22d8a00
TG
153 if (r < 0)
154 return r;
155
156 route->family = AF_INET;
157 route->scope = RT_SCOPE_LINK;
ed9e361a 158 route->protocol = RTPROT_STATIC;
b22d8a00
TG
159 route->metrics = IPV4LL_ROUTE_METRIC;
160
161 r = route_configure(route, link, ipv4ll_route_handler);
162 if (r < 0)
163 return r;
164
165 link->ipv4ll_route = false;
166
167 return 0;
168}
169
170static void ipv4ll_handler(sd_ipv4ll *ll, int event, void *userdata){
171 Link *link = userdata;
172 int r;
173
174 assert(link);
175 assert(link->network);
176 assert(link->manager);
177
178 if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
179 return;
180
181 switch(event) {
be19c5b5
DH
182 case SD_IPV4LL_EVENT_STOP:
183 case SD_IPV4LL_EVENT_CONFLICT:
b22d8a00
TG
184 r = ipv4ll_address_lost(link);
185 if (r < 0) {
186 link_enter_failed(link);
187 return;
188 }
189 break;
be19c5b5 190 case SD_IPV4LL_EVENT_BIND:
b22d8a00
TG
191 r = ipv4ll_address_claimed(ll, link);
192 if (r < 0) {
193 link_enter_failed(link);
194 return;
195 }
196 break;
197 default:
b45e4eb6 198 log_link_warning(link, "IPv4 link-local unknown event: %d", event);
b22d8a00
TG
199 break;
200 }
201}
202
203int ipv4ll_configure(Link *link) {
204 uint8_t seed[8];
205 int r;
206
207 assert(link);
208 assert(link->network);
e0ee46f2 209 assert(link->network->link_local & ADDRESS_FAMILY_IPV4);
b22d8a00
TG
210
211 r = sd_ipv4ll_new(&link->ipv4ll);
212 if (r < 0)
213 return r;
214
215 if (link->udev_device) {
216 r = net_get_unique_predictable_data(link->udev_device, seed);
217 if (r >= 0) {
e3dca008
TG
218 assert_cc(sizeof(unsigned) <= 8);
219
220 r = sd_ipv4ll_set_address_seed(link->ipv4ll, *(unsigned *)seed);
b22d8a00
TG
221 if (r < 0)
222 return r;
223 }
224 }
225
226 r = sd_ipv4ll_attach_event(link->ipv4ll, NULL, 0);
227 if (r < 0)
228 return r;
229
230 r = sd_ipv4ll_set_mac(link->ipv4ll, &link->mac);
231 if (r < 0)
232 return r;
233
234 r = sd_ipv4ll_set_index(link->ipv4ll, link->ifindex);
235 if (r < 0)
236 return r;
237
238 r = sd_ipv4ll_set_callback(link->ipv4ll, ipv4ll_handler, link);
239 if (r < 0)
240 return r;
241
242 return 0;
243}