chiark / gitweb /
sd-lldp: minor header cleanup
[elogind.git] / src / libsystemd-network / sd-ipv4ll.c
1 /***
2   This file is part of systemd.
3
4   Copyright (C) 2014 Axis Communications AB. All rights reserved.
5
6   systemd is free software; you can redistribute it and/or modify it
7   under the terms of the GNU Lesser General Public License as published by
8   the Free Software Foundation; either version 2.1 of the License, or
9   (at your option) any later version.
10
11   systemd is distributed in the hope that it will be useful, but
12   WITHOUT ANY WARRANTY; without even the implied warranty of
13   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14   Lesser General Public License for more details.
15
16   You should have received a copy of the GNU Lesser General Public License
17   along with systemd; If not, see <http://www.gnu.org/licenses/>.
18 ***/
19
20 #include <stdlib.h>
21 #include <errno.h>
22 #include <string.h>
23 #include <stdio.h>
24 #include <arpa/inet.h>
25
26 #include "util.h"
27 #include "siphash24.h"
28 #include "list.h"
29 #include "refcnt.h"
30
31 #include "ipv4ll-internal.h"
32 #include "sd-ipv4ll.h"
33
34 /* Constants from the RFC */
35 #define PROBE_WAIT 1
36 #define PROBE_NUM 3
37 #define PROBE_MIN 1
38 #define PROBE_MAX 2
39 #define ANNOUNCE_WAIT 2
40 #define ANNOUNCE_NUM 2
41 #define ANNOUNCE_INTERVAL 2
42 #define MAX_CONFLICTS 10
43 #define RATE_LIMIT_INTERVAL 60
44 #define DEFEND_INTERVAL 10
45
46 #define IPV4LL_NETWORK 0xA9FE0000L
47 #define IPV4LL_NETMASK 0xFFFF0000L
48
49 typedef enum IPv4LLTrigger{
50         IPV4LL_TRIGGER_NULL,
51         IPV4LL_TRIGGER_PACKET,
52         IPV4LL_TRIGGER_TIMEOUT,
53         _IPV4LL_TRIGGER_MAX,
54         _IPV4LL_TRIGGER_INVALID = -1
55 } IPv4LLTrigger;
56
57 typedef enum IPv4LLState {
58         IPV4LL_STATE_INIT,
59         IPV4LL_STATE_WAITING_PROBE,
60         IPV4LL_STATE_PROBING,
61         IPV4LL_STATE_WAITING_ANNOUNCE,
62         IPV4LL_STATE_ANNOUNCING,
63         IPV4LL_STATE_RUNNING,
64         IPV4LL_STATE_STOPPED,
65         _IPV4LL_STATE_MAX,
66         _IPV4LL_STATE_INVALID = -1
67 } IPv4LLState;
68
69 struct sd_ipv4ll {
70         RefCount n_ref;
71
72         IPv4LLState state;
73         int index;
74         int fd;
75         union sockaddr_union link;
76         int iteration;
77         int conflict;
78         sd_event_source *receive_message;
79         sd_event_source *timer;
80         usec_t next_wakeup;
81         usec_t defend_window;
82         int next_wakeup_valid;
83         be32_t address;
84         struct random_data *random_data;
85         char *random_data_state;
86         /* External */
87         be32_t claimed_address;
88         struct ether_addr mac_addr;
89         sd_event *event;
90         int event_priority;
91         sd_ipv4ll_cb_t cb;
92         void* userdata;
93 };
94
95 static void ipv4ll_run_state_machine(sd_ipv4ll *ll, IPv4LLTrigger trigger, void *trigger_data);
96
97 static void ipv4ll_set_state(sd_ipv4ll *ll, IPv4LLState st, int reset_counter) {
98
99         assert(ll);
100         assert(st < _IPV4LL_STATE_MAX);
101
102         if (st == ll->state && !reset_counter) {
103                 ll->iteration++;
104         } else {
105                 ll->state = st;
106                 ll->iteration = 0;
107         }
108 }
109
110 static sd_ipv4ll *ipv4ll_client_notify(sd_ipv4ll *ll, int event) {
111         assert(ll);
112
113         if (ll->cb) {
114                 ll = sd_ipv4ll_ref(ll);
115                 ll->cb(ll, event, ll->userdata);
116                 ll = sd_ipv4ll_unref(ll);
117         }
118
119         return ll;
120 }
121
122 static sd_ipv4ll *ipv4ll_stop(sd_ipv4ll *ll, int event) {
123         assert(ll);
124
125         ll->receive_message = sd_event_source_unref(ll->receive_message);
126         ll->fd = safe_close(ll->fd);
127
128         ll->timer = sd_event_source_unref(ll->timer);
129
130         log_ipv4ll(ll, "STOPPED");
131
132         ll = ipv4ll_client_notify(ll, event);
133
134         if (ll) {
135                 ll->claimed_address = 0;
136                 ipv4ll_set_state (ll, IPV4LL_STATE_INIT, 1);
137         }
138
139         return ll;
140 }
141
142 static int ipv4ll_pick_address(sd_ipv4ll *ll, be32_t *address) {
143         be32_t addr;
144         int r;
145         int32_t random;
146
147         assert(ll);
148         assert(address);
149         assert(ll->random_data);
150
151         do {
152                 r = random_r(ll->random_data, &random);
153                 if (r < 0)
154                         return r;
155                 addr = htonl((random & 0x0000FFFF) | IPV4LL_NETWORK);
156         } while (addr == ll->address ||
157                 (ntohl(addr) & IPV4LL_NETMASK) != IPV4LL_NETWORK ||
158                 (ntohl(addr) & 0x0000FF00) == 0x0000 ||
159                 (ntohl(addr) & 0x0000FF00) == 0xFF00);
160
161         *address = addr;
162         return 0;
163 }
164
165 static int ipv4ll_timer(sd_event_source *s, uint64_t usec, void *userdata) {
166         sd_ipv4ll *ll = (sd_ipv4ll*)userdata;
167
168         assert(ll);
169
170         ll->next_wakeup_valid = 0;
171         ipv4ll_run_state_machine(ll, IPV4LL_TRIGGER_TIMEOUT, NULL);
172
173         return 0;
174 }
175
176 static void ipv4ll_set_next_wakeup(sd_ipv4ll *ll, int sec, int random_sec) {
177         usec_t next_timeout = 0;
178         usec_t time_now = 0;
179
180         assert(sec >= 0);
181         assert(random_sec >= 0);
182         assert(ll);
183
184         next_timeout = sec * USEC_PER_SEC;
185
186         if (random_sec)
187                 next_timeout += random_u32() % (random_sec * USEC_PER_SEC);
188
189         if (sd_event_now(ll->event, clock_boottime_or_monotonic(), &time_now) < 0)
190                 time_now = now(clock_boottime_or_monotonic());
191
192         ll->next_wakeup = time_now + next_timeout;
193         ll->next_wakeup_valid = 1;
194 }
195
196 static bool ipv4ll_arp_conflict (sd_ipv4ll *ll, struct ether_arp *arp) {
197         assert(ll);
198         assert(arp);
199
200         if (memcmp(arp->arp_spa, &ll->address, sizeof(ll->address)) == 0 &&
201             memcmp(arp->arp_sha, &ll->mac_addr, ETH_ALEN) != 0)
202                 return true;
203
204         return false;
205 }
206
207 static bool ipv4ll_arp_probe_conflict (sd_ipv4ll *ll, struct ether_arp *arp) {
208         assert(ll);
209         assert(arp);
210
211         if (ipv4ll_arp_conflict(ll, arp))
212                 return true;
213
214         if (memcmp(arp->arp_tpa, &ll->address, sizeof(ll->address)) == 0 &&
215             memcmp(arp->arp_sha, &ll->mac_addr, ETH_ALEN))
216                 return true;
217
218         return false;
219 }
220
221 static void ipv4ll_run_state_machine(sd_ipv4ll *ll, IPv4LLTrigger trigger, void *trigger_data) {
222         struct ether_arp out_packet;
223         int out_packet_ready = 0;
224         int r = 0;
225
226         assert(ll);
227         assert(trigger < _IPV4LL_TRIGGER_MAX);
228
229         if (ll->state == IPV4LL_STATE_INIT) {
230
231                 log_ipv4ll(ll, "PROBE");
232                 ipv4ll_set_state(ll, IPV4LL_STATE_WAITING_PROBE, 1);
233                 ipv4ll_set_next_wakeup(ll, 0, PROBE_WAIT);
234
235         } else if ((ll->state == IPV4LL_STATE_WAITING_PROBE && trigger == IPV4LL_TRIGGER_TIMEOUT) ||
236                 (ll->state == IPV4LL_STATE_PROBING && trigger == IPV4LL_TRIGGER_TIMEOUT && ll->iteration < PROBE_NUM-2)) {
237
238                 /* Send a probe */
239                 arp_packet_probe(&out_packet, ll->address, &ll->mac_addr);
240                 out_packet_ready = 1;
241                 ipv4ll_set_state(ll, IPV4LL_STATE_PROBING, 0);
242
243                 ipv4ll_set_next_wakeup(ll, PROBE_MIN, (PROBE_MAX-PROBE_MIN));
244
245         } else if (ll->state == IPV4LL_STATE_PROBING && trigger == IPV4LL_TRIGGER_TIMEOUT && ll->iteration >= PROBE_NUM-2) {
246
247                 /* Send the last probe */
248                 arp_packet_probe(&out_packet, ll->address, &ll->mac_addr);
249                 out_packet_ready = 1;
250                 ipv4ll_set_state(ll, IPV4LL_STATE_WAITING_ANNOUNCE, 1);
251
252                 ipv4ll_set_next_wakeup(ll, ANNOUNCE_WAIT, 0);
253
254         } else if ((ll->state == IPV4LL_STATE_WAITING_ANNOUNCE && trigger == IPV4LL_TRIGGER_TIMEOUT) ||
255                 (ll->state == IPV4LL_STATE_ANNOUNCING && trigger == IPV4LL_TRIGGER_TIMEOUT && ll->iteration < ANNOUNCE_NUM-1)) {
256
257                 /* Send announcement packet */
258                 arp_packet_announcement(&out_packet, ll->address, &ll->mac_addr);
259                 out_packet_ready = 1;
260                 ipv4ll_set_state(ll, IPV4LL_STATE_ANNOUNCING, 0);
261
262                 ipv4ll_set_next_wakeup(ll, ANNOUNCE_INTERVAL, 0);
263
264                 if (ll->iteration == 0) {
265                         log_ipv4ll(ll, "ANNOUNCE");
266                         ll->claimed_address = ll->address;
267                         ll = ipv4ll_client_notify(ll, IPV4LL_EVENT_BIND);
268                         if (!ll || ll->state == IPV4LL_STATE_STOPPED)
269                                 goto out;
270
271                         ll->conflict = 0;
272                 }
273
274         } else if ((ll->state == IPV4LL_STATE_ANNOUNCING && trigger == IPV4LL_TRIGGER_TIMEOUT &&
275                     ll->iteration >= ANNOUNCE_NUM-1)) {
276
277                 ipv4ll_set_state(ll, IPV4LL_STATE_RUNNING, 0);
278                 ll->next_wakeup_valid = 0;
279
280         } else if (trigger == IPV4LL_TRIGGER_PACKET) {
281
282                 int conflicted = 0;
283                 usec_t time_now;
284                 struct ether_arp* in_packet = (struct ether_arp*)trigger_data;
285
286                 assert(in_packet);
287
288                 if (IN_SET(ll->state, IPV4LL_STATE_ANNOUNCING, IPV4LL_STATE_RUNNING)) {
289
290                         if (ipv4ll_arp_conflict(ll, in_packet)) {
291
292                                 r = sd_event_now(ll->event, clock_boottime_or_monotonic(), &time_now);
293                                 if (r < 0)
294                                         goto out;
295
296                                 /* Defend address */
297                                 if (time_now > ll->defend_window) {
298                                         ll->defend_window = time_now + DEFEND_INTERVAL * USEC_PER_SEC;
299                                         arp_packet_announcement(&out_packet, ll->address, &ll->mac_addr);
300                                         out_packet_ready = 1;
301                                 } else
302                                         conflicted = 1;
303                         }
304
305                 } else if (IN_SET(ll->state, IPV4LL_STATE_WAITING_PROBE,
306                                              IPV4LL_STATE_PROBING,
307                                              IPV4LL_STATE_WAITING_ANNOUNCE)) {
308
309                         conflicted = ipv4ll_arp_probe_conflict(ll, in_packet);
310                 }
311
312                 if (conflicted) {
313                         log_ipv4ll(ll, "CONFLICT");
314                         ll = ipv4ll_client_notify(ll, IPV4LL_EVENT_CONFLICT);
315                         if (!ll || ll->state == IPV4LL_STATE_STOPPED)
316                                 goto out;
317
318                         ll->claimed_address = 0;
319
320                         /* Pick a new address */
321                         r = ipv4ll_pick_address(ll, &ll->address);
322                         if (r < 0)
323                                 goto out;
324                         ll->conflict++;
325                         ll->defend_window = 0;
326                         ipv4ll_set_state(ll, IPV4LL_STATE_WAITING_PROBE, 1);
327
328                         if (ll->conflict >= MAX_CONFLICTS) {
329                                 log_ipv4ll(ll, "MAX_CONFLICTS");
330                                 ipv4ll_set_next_wakeup(ll, RATE_LIMIT_INTERVAL, PROBE_WAIT);
331                         } else
332                                 ipv4ll_set_next_wakeup(ll, 0, PROBE_WAIT);
333
334                 }
335         }
336
337         if (out_packet_ready) {
338                 r = arp_network_send_raw_socket(ll->fd, &ll->link, &out_packet);
339                 if (r < 0) {
340                         log_ipv4ll(ll, "failed to send arp packet out");
341                         goto out;
342                 }
343         }
344
345         if (ll->next_wakeup_valid) {
346                 ll->timer = sd_event_source_unref(ll->timer);
347                 r = sd_event_add_time(ll->event, &ll->timer, clock_boottime_or_monotonic(),
348                                       ll->next_wakeup, 0, ipv4ll_timer, ll);
349                 if (r < 0)
350                         goto out;
351
352                 r = sd_event_source_set_priority(ll->timer, ll->event_priority);
353                 if (r < 0)
354                         goto out;
355
356                 r = sd_event_source_set_description(ll->timer, "ipv4ll-timer");
357                 if (r < 0)
358                         goto out;
359         }
360
361 out:
362         if (r < 0 && ll)
363                 ipv4ll_stop(ll, r);
364 }
365
366 static int ipv4ll_receive_message(sd_event_source *s, int fd,
367                                   uint32_t revents, void *userdata) {
368         int r;
369         struct ether_arp arp;
370         sd_ipv4ll *ll = (sd_ipv4ll*)userdata;
371
372         assert(ll);
373
374         r = read(fd, &arp, sizeof(struct ether_arp));
375         if (r < (int) sizeof(struct ether_arp))
376                 return 0;
377
378         r = arp_packet_verify_headers(&arp);
379         if (r < 0)
380                 return 0;
381
382         ipv4ll_run_state_machine(ll, IPV4LL_TRIGGER_PACKET, &arp);
383
384         return 0;
385 }
386
387 int sd_ipv4ll_set_index(sd_ipv4ll *ll, int interface_index) {
388         assert_return(ll, -EINVAL);
389         assert_return(interface_index > 0, -EINVAL);
390         assert_return(IN_SET(ll->state, IPV4LL_STATE_INIT,
391                              IPV4LL_STATE_STOPPED), -EBUSY);
392
393         ll->index = interface_index;
394
395         return 0;
396 }
397
398 int sd_ipv4ll_set_mac(sd_ipv4ll *ll, const struct ether_addr *addr) {
399         bool need_restart = false;
400
401         assert_return(ll, -EINVAL);
402         assert_return(addr, -EINVAL);
403
404         if (memcmp(&ll->mac_addr, addr, ETH_ALEN) == 0)
405                 return 0;
406
407         if (!IN_SET(ll->state, IPV4LL_STATE_INIT, IPV4LL_STATE_STOPPED)) {
408                 log_ipv4ll(ll, "Changing MAC address on running IPv4LL "
409                            "client, restarting");
410                 ll = ipv4ll_stop(ll, IPV4LL_EVENT_STOP);
411                 need_restart = true;
412         }
413
414         if (!ll)
415                 return 0;
416
417         memcpy(&ll->mac_addr, addr, ETH_ALEN);
418
419         if (need_restart)
420                 sd_ipv4ll_start(ll);
421
422         return 0;
423 }
424
425 int sd_ipv4ll_detach_event(sd_ipv4ll *ll) {
426         assert_return(ll, -EINVAL);
427
428         ll->event = sd_event_unref(ll->event);
429
430         return 0;
431 }
432
433 int sd_ipv4ll_attach_event(sd_ipv4ll *ll, sd_event *event, int priority) {
434         int r;
435
436         assert_return(ll, -EINVAL);
437         assert_return(!ll->event, -EBUSY);
438
439         if (event)
440                 ll->event = sd_event_ref(event);
441         else {
442                 r = sd_event_default(&ll->event);
443                 if (r < 0) {
444                         ipv4ll_stop(ll, IPV4LL_EVENT_STOP);
445                         return r;
446                 }
447         }
448
449         ll->event_priority = priority;
450
451         return 0;
452 }
453
454 int sd_ipv4ll_set_callback(sd_ipv4ll *ll, sd_ipv4ll_cb_t cb, void *userdata) {
455         assert_return(ll, -EINVAL);
456
457         ll->cb = cb;
458         ll->userdata = userdata;
459
460         return 0;
461 }
462
463 int sd_ipv4ll_get_address(sd_ipv4ll *ll, struct in_addr *address){
464         assert_return(ll, -EINVAL);
465         assert_return(address, -EINVAL);
466
467         if (ll->claimed_address == 0) {
468                 return -ENOENT;
469         }
470
471         address->s_addr = ll->claimed_address;
472         return 0;
473 }
474
475 int sd_ipv4ll_set_address_seed (sd_ipv4ll *ll, uint8_t seed[8]) {
476         unsigned int entropy;
477         int r;
478
479         assert_return(ll, -EINVAL);
480         assert_return(seed, -EINVAL);
481
482         entropy = *seed;
483
484         free(ll->random_data);
485         free(ll->random_data_state);
486
487         ll->random_data = new0(struct random_data, 1);
488         ll->random_data_state = new0(char, 128);
489
490         if (!ll->random_data || !ll->random_data_state) {
491                 r = -ENOMEM;
492                 goto error;
493         }
494
495         r = initstate_r((unsigned int)entropy, ll->random_data_state, 128, ll->random_data);
496         if (r < 0)
497                 goto error;
498
499 error:
500         if (r < 0){
501                 free(ll->random_data);
502                 free(ll->random_data_state);
503                 ll->random_data = NULL;
504                 ll->random_data_state = NULL;
505         }
506         return r;
507 }
508
509 bool sd_ipv4ll_is_running(sd_ipv4ll *ll) {
510         assert_return(ll, -EINVAL);
511
512         return !IN_SET(ll->state, IPV4LL_STATE_INIT, IPV4LL_STATE_STOPPED);
513 }
514
515 #define HASH_KEY SD_ID128_MAKE(df,04,22,98,3f,ad,14,52,f9,87,2e,d1,9c,70,e2,f2)
516
517 int sd_ipv4ll_start (sd_ipv4ll *ll) {
518         int r;
519
520         assert_return(ll, -EINVAL);
521         assert_return(ll->event, -EINVAL);
522         assert_return(ll->index > 0, -EINVAL);
523         assert_return(IN_SET(ll->state, IPV4LL_STATE_INIT,
524                              IPV4LL_STATE_STOPPED), -EBUSY);
525
526         ll->state = IPV4LL_STATE_INIT;
527
528         r = arp_network_bind_raw_socket(ll->index, &ll->link);
529
530         if (r < 0)
531                 goto out;
532
533         ll->fd = r;
534         ll->conflict = 0;
535         ll->defend_window = 0;
536         ll->claimed_address = 0;
537
538         if (!ll->random_data) {
539                 uint8_t seed[8];
540
541                 /* Fallback to mac */
542                 siphash24(seed, &ll->mac_addr.ether_addr_octet,
543                           ETH_ALEN, HASH_KEY.bytes);
544
545                 r = sd_ipv4ll_set_address_seed(ll, seed);
546                 if (r < 0)
547                         goto out;
548         }
549
550         if (ll->address == 0) {
551                 r = ipv4ll_pick_address(ll, &ll->address);
552                 if (r < 0)
553                         goto out;
554         }
555
556         ipv4ll_set_state (ll, IPV4LL_STATE_INIT, 1);
557
558         r = sd_event_add_io(ll->event, &ll->receive_message, ll->fd,
559                             EPOLLIN, ipv4ll_receive_message, ll);
560         if (r < 0)
561                 goto out;
562
563         r = sd_event_source_set_priority(ll->receive_message, ll->event_priority);
564         if (r < 0)
565                 goto out;
566
567         r = sd_event_source_set_description(ll->receive_message, "ipv4ll-receive-message");
568         if (r < 0)
569                 goto out;
570
571         r = sd_event_add_time(ll->event,
572                               &ll->timer,
573                               clock_boottime_or_monotonic(),
574                               now(clock_boottime_or_monotonic()), 0,
575                               ipv4ll_timer, ll);
576
577         if (r < 0)
578                 goto out;
579
580         r = sd_event_source_set_priority(ll->timer, ll->event_priority);
581         if (r < 0)
582                 goto out;
583
584         r = sd_event_source_set_description(ll->timer, "ipv4ll-timer");
585 out:
586         if (r < 0)
587                 ipv4ll_stop(ll, IPV4LL_EVENT_STOP);
588
589         return 0;
590 }
591
592 int sd_ipv4ll_stop(sd_ipv4ll *ll) {
593         ipv4ll_stop(ll, IPV4LL_EVENT_STOP);
594         if (ll)
595                 ipv4ll_set_state(ll, IPV4LL_STATE_STOPPED, 1);
596
597         return 0;
598 }
599
600 sd_ipv4ll *sd_ipv4ll_ref(sd_ipv4ll *ll) {
601         if (ll)
602                 assert_se(REFCNT_INC(ll->n_ref) >= 2);
603
604         return ll;
605 }
606
607 sd_ipv4ll *sd_ipv4ll_unref(sd_ipv4ll *ll) {
608         if (ll && REFCNT_DEC(ll->n_ref) <= 0) {
609                 ll->receive_message =
610                         sd_event_source_unref(ll->receive_message);
611                 ll->fd = safe_close(ll->fd);
612
613                 ll->timer = sd_event_source_unref(ll->timer);
614
615                 sd_ipv4ll_detach_event(ll);
616
617                 free(ll->random_data);
618                 free(ll->random_data_state);
619                 free(ll);
620
621                 return NULL;
622         }
623
624         return ll;
625 }
626
627 DEFINE_TRIVIAL_CLEANUP_FUNC(sd_ipv4ll*, sd_ipv4ll_unref);
628 #define _cleanup_ipv4ll_free_ _cleanup_(sd_ipv4ll_unrefp)
629
630 int sd_ipv4ll_new(sd_ipv4ll **ret) {
631         _cleanup_ipv4ll_free_ sd_ipv4ll *ll = NULL;
632
633         assert_return(ret, -EINVAL);
634
635         ll = new0(sd_ipv4ll, 1);
636         if (!ll)
637                 return -ENOMEM;
638
639         ll->n_ref = REFCNT_INIT;
640         ll->state = IPV4LL_STATE_INIT;
641         ll->index = -1;
642         ll->fd = -1;
643
644         *ret = ll;
645         ll = NULL;
646
647         return 0;
648 }