tizen 2.4 release
[external/systemd.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
357 out:
358         if (r < 0 && ll)
359                 ipv4ll_stop(ll, r);
360 }
361
362 static int ipv4ll_receive_message(sd_event_source *s, int fd,
363                                   uint32_t revents, void *userdata) {
364         int r;
365         struct ether_arp arp;
366         sd_ipv4ll *ll = (sd_ipv4ll*)userdata;
367
368         assert(ll);
369
370         r = read(fd, &arp, sizeof(struct ether_arp));
371         if (r < (int) sizeof(struct ether_arp))
372                 return 0;
373
374         r = arp_packet_verify_headers(&arp);
375         if (r < 0)
376                 return 0;
377
378         ipv4ll_run_state_machine(ll, IPV4LL_TRIGGER_PACKET, &arp);
379
380         return 0;
381 }
382
383 int sd_ipv4ll_set_index(sd_ipv4ll *ll, int interface_index) {
384         assert_return(ll, -EINVAL);
385         assert_return(interface_index > 0, -EINVAL);
386         assert_return(IN_SET(ll->state, IPV4LL_STATE_INIT,
387                              IPV4LL_STATE_STOPPED), -EBUSY);
388
389         ll->index = interface_index;
390
391         return 0;
392 }
393
394 int sd_ipv4ll_set_mac(sd_ipv4ll *ll, const struct ether_addr *addr) {
395         bool need_restart = false;
396
397         assert_return(ll, -EINVAL);
398         assert_return(addr, -EINVAL);
399
400         if (memcmp(&ll->mac_addr, addr, ETH_ALEN) == 0)
401                 return 0;
402
403         if (!IN_SET(ll->state, IPV4LL_STATE_INIT, IPV4LL_STATE_STOPPED)) {
404                 log_ipv4ll(ll, "Changing MAC address on running IPv4LL "
405                            "client, restarting");
406                 ll = ipv4ll_stop(ll, IPV4LL_EVENT_STOP);
407                 need_restart = true;
408         }
409
410         if (!ll)
411                 return 0;
412
413         memcpy(&ll->mac_addr, addr, ETH_ALEN);
414
415         if (need_restart)
416                 sd_ipv4ll_start(ll);
417
418         return 0;
419 }
420
421 int sd_ipv4ll_detach_event(sd_ipv4ll *ll) {
422         assert_return(ll, -EINVAL);
423
424         ll->event = sd_event_unref(ll->event);
425
426         return 0;
427 }
428
429 int sd_ipv4ll_attach_event(sd_ipv4ll *ll, sd_event *event, int priority) {
430         int r;
431
432         assert_return(ll, -EINVAL);
433         assert_return(!ll->event, -EBUSY);
434
435         if (event)
436                 ll->event = sd_event_ref(event);
437         else {
438                 r = sd_event_default(&ll->event);
439                 if (r < 0) {
440                         ipv4ll_stop(ll, IPV4LL_EVENT_STOP);
441                         return r;
442                 }
443         }
444
445         ll->event_priority = priority;
446
447         return 0;
448 }
449
450 int sd_ipv4ll_set_callback(sd_ipv4ll *ll, sd_ipv4ll_cb_t cb, void *userdata) {
451         assert_return(ll, -EINVAL);
452
453         ll->cb = cb;
454         ll->userdata = userdata;
455
456         return 0;
457 }
458
459 int sd_ipv4ll_get_address(sd_ipv4ll *ll, struct in_addr *address){
460         assert_return(ll, -EINVAL);
461         assert_return(address, -EINVAL);
462
463         if (ll->claimed_address == 0) {
464                 return -ENOENT;
465         }
466
467         address->s_addr = ll->claimed_address;
468         return 0;
469 }
470
471 int sd_ipv4ll_set_address_seed (sd_ipv4ll *ll, uint8_t seed[8]) {
472         unsigned int entropy;
473         int r;
474
475         assert_return(ll, -EINVAL);
476         assert_return(seed, -EINVAL);
477
478         entropy = *seed;
479
480         free(ll->random_data);
481         free(ll->random_data_state);
482
483         ll->random_data = new0(struct random_data, 1);
484         ll->random_data_state = new0(char, 128);
485
486         if (!ll->random_data || !ll->random_data_state) {
487                 r = -ENOMEM;
488                 goto error;
489         }
490
491         r = initstate_r((unsigned int)entropy, ll->random_data_state, 128, ll->random_data);
492         if (r < 0)
493                 goto error;
494
495 error:
496         if (r < 0){
497                 free(ll->random_data);
498                 free(ll->random_data_state);
499                 ll->random_data = NULL;
500                 ll->random_data_state = NULL;
501         }
502         return r;
503 }
504
505 bool sd_ipv4ll_is_running(sd_ipv4ll *ll) {
506         assert_return(ll, -EINVAL);
507
508         return !IN_SET(ll->state, IPV4LL_STATE_INIT, IPV4LL_STATE_STOPPED);
509 }
510
511 #define HASH_KEY SD_ID128_MAKE(df,04,22,98,3f,ad,14,52,f9,87,2e,d1,9c,70,e2,f2)
512
513 int sd_ipv4ll_start (sd_ipv4ll *ll) {
514         int r;
515
516         assert_return(ll, -EINVAL);
517         assert_return(ll->event, -EINVAL);
518         assert_return(ll->index > 0, -EINVAL);
519         assert_return(IN_SET(ll->state, IPV4LL_STATE_INIT,
520                              IPV4LL_STATE_STOPPED), -EBUSY);
521
522         ll->state = IPV4LL_STATE_INIT;
523
524         r = arp_network_bind_raw_socket(ll->index, &ll->link);
525
526         if (r < 0)
527                 goto out;
528
529         ll->fd = r;
530         ll->conflict = 0;
531         ll->defend_window = 0;
532         ll->claimed_address = 0;
533
534         if (!ll->random_data) {
535                 uint8_t seed[8];
536
537                 /* Fallback to mac */
538                 siphash24(seed, &ll->mac_addr.ether_addr_octet,
539                           ETH_ALEN, HASH_KEY.bytes);
540
541                 r = sd_ipv4ll_set_address_seed(ll, seed);
542                 if (r < 0)
543                         goto out;
544         }
545
546         if (ll->address == 0) {
547                 r = ipv4ll_pick_address(ll, &ll->address);
548                 if (r < 0)
549                         goto out;
550         }
551
552         ipv4ll_set_state (ll, IPV4LL_STATE_INIT, 1);
553
554         r = sd_event_add_io(ll->event, &ll->receive_message, ll->fd,
555                             EPOLLIN, ipv4ll_receive_message, ll);
556         if (r < 0)
557                 goto out;
558
559         r = sd_event_source_set_priority(ll->receive_message, ll->event_priority);
560         if (r < 0)
561                 goto out;
562
563         r = sd_event_add_time(ll->event,
564                               &ll->timer,
565                               clock_boottime_or_monotonic(),
566                               now(clock_boottime_or_monotonic()), 0,
567                               ipv4ll_timer, ll);
568
569         if (r < 0)
570                 goto out;
571
572         r = sd_event_source_set_priority(ll->timer, ll->event_priority);
573
574 out:
575         if (r < 0)
576                 ipv4ll_stop(ll, IPV4LL_EVENT_STOP);
577
578         return 0;
579 }
580
581 int sd_ipv4ll_stop(sd_ipv4ll *ll) {
582         ipv4ll_stop(ll, IPV4LL_EVENT_STOP);
583         if (ll)
584                 ipv4ll_set_state(ll, IPV4LL_STATE_STOPPED, 1);
585
586         return 0;
587 }
588
589 sd_ipv4ll *sd_ipv4ll_ref(sd_ipv4ll *ll) {
590         if (ll)
591                 assert_se(REFCNT_INC(ll->n_ref) >= 2);
592
593         return ll;
594 }
595
596 sd_ipv4ll *sd_ipv4ll_unref(sd_ipv4ll *ll) {
597         if (ll && REFCNT_DEC(ll->n_ref) <= 0) {
598                 ll->receive_message =
599                         sd_event_source_unref(ll->receive_message);
600                 ll->fd = safe_close(ll->fd);
601
602                 ll->timer = sd_event_source_unref(ll->timer);
603
604                 sd_ipv4ll_detach_event(ll);
605
606                 free(ll->random_data);
607                 free(ll->random_data_state);
608                 free(ll);
609
610                 return NULL;
611         }
612
613         return ll;
614 }
615
616 DEFINE_TRIVIAL_CLEANUP_FUNC(sd_ipv4ll*, sd_ipv4ll_unref);
617 #define _cleanup_ipv4ll_free_ _cleanup_(sd_ipv4ll_unrefp)
618
619 int sd_ipv4ll_new(sd_ipv4ll **ret) {
620         _cleanup_ipv4ll_free_ sd_ipv4ll *ll = NULL;
621
622         assert_return(ret, -EINVAL);
623
624         ll = new0(sd_ipv4ll, 1);
625         if (!ll)
626                 return -ENOMEM;
627
628         ll->n_ref = REFCNT_INIT;
629         ll->state = IPV4LL_STATE_INIT;
630         ll->index = -1;
631         ll->fd = -1;
632
633         *ret = ll;
634         ll = NULL;
635
636         return 0;
637 }