]> git.meshlink.io Git - catta/blob - avahi-autoipd/main.c
a few fixes in netlink handling
[catta] / avahi-autoipd / main.c
1 /* $Id$ */
2
3 /***
4   This file is part of avahi.
5  
6   avahi is free software; you can redistribute it and/or modify it
7   under the terms of the GNU Lesser General Public License as
8   published by the Free Software Foundation; either version 2.1 of the
9   License, or (at your option) any later version.
10  
11   avahi is distributed in the hope that it will be useful, but WITHOUT
12   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13   or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General
14   Public License for more details.
15  
16   You should have received a copy of the GNU Lesser General Public
17   License along with avahi; if not, write to the Free Software
18   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
19   USA.
20 ***/
21
22 #ifdef HAVE_CONFIG_H
23 #include <config.h>
24 #endif
25
26 #include <stdlib.h>
27 #include <unistd.h>
28 #include <sys/socket.h>
29 #include <netpacket/packet.h>
30 #include <net/ethernet.h>
31 #include <fcntl.h>
32 #include <time.h>
33 #include <assert.h>
34 #include <errno.h>
35 #include <string.h>
36 #include <inttypes.h>
37 #include <sys/types.h>
38 #include <arpa/inet.h>
39 #include <sys/ioctl.h>
40 #include <poll.h>
41 #include <net/if.h>
42
43 #include <avahi-common/malloc.h>
44 #include <avahi-common/timeval.h>
45
46 #include <avahi-daemon/setproctitle.h>
47
48 #include <libdaemon/dfork.h>
49 #include <libdaemon/dsignal.h>
50 #include <libdaemon/dlog.h>
51 #include <libdaemon/dpid.h>
52 #include <libdaemon/dexec.h>
53
54 #include "main.h"
55 #include "iface.h"
56
57 #ifndef __linux__
58 #error "avahi-autoipd is only available on Linux for now"
59 #endif
60
61 /* An implementation of RFC 3927 */
62
63 /* Constants from the RFC */
64 #define PROBE_WAIT 1
65 #define PROBE_NUM 3
66 #define PROBE_MIN 1
67 #define PROBE_MAX 2
68 #define ANNOUNCE_WAIT 2
69 #define ANNOUNCE_NUM 2
70 #define ANNOUNCE_INTERVAL 2
71 #define MAX_CONFLICTS 10
72 #define RATE_LIMIT_INTERVAL 60
73 #define DEFEND_INTERVAL 10
74
75 #define IPV4LL_NETWORK 0xA9FE0000L
76 #define IPV4LL_NETMASK 0xFFFF0000L
77 #define IPV4LL_HOSTMASK 0x0000FFFFL
78
79 #define ETHER_ADDRLEN 6
80 #define ARP_PACKET_SIZE (8+4+4+2*ETHER_ADDRLEN)
81
82 typedef enum ArpOperation {
83     ARP_REQUEST = 1,
84     ARP_RESPONSE = 2
85 } ArpOperation;
86
87 typedef struct ArpPacketInfo {
88     ArpOperation operation;
89
90     uint32_t sender_ip_address, target_ip_address;
91     uint8_t sender_hw_address[ETHER_ADDRLEN], target_hw_address[ETHER_ADDRLEN];
92 } ArpPacketInfo;
93
94 static State state = STATE_START;
95 static int n_iteration = 0;
96 static int n_conflict = 0;
97
98 #define RANDOM_DEVICE "/dev/urandom"
99
100 static void init_rand_seed(void) {
101     int fd;
102     unsigned seed = 0;
103
104     /* Try to initialize seed from /dev/urandom, to make it a little
105      * less predictable, and to make sure that multiple machines
106      * booted at the same time choose different random seeds.  */
107     if ((fd = open(RANDOM_DEVICE, O_RDONLY)) >= 0) {
108         read(fd, &seed, sizeof(seed));
109         close(fd);
110     }
111
112     /* If the initialization failed by some reason, we add the time to the seed */
113     seed ^= (unsigned) time(NULL);
114
115     srand(seed);
116 }
117
118 static uint32_t pick_addr(uint32_t old_addr) {
119     uint32_t addr;
120
121     do {
122         unsigned r = (unsigned) rand();
123
124         /* Reduce to 16 bits */
125         while (r > 0xFFFF)
126             r = (r >> 16) ^ (r & 0xFFFF);
127         
128         addr = htonl(IPV4LL_NETWORK | (uint32_t) r);
129
130     } while (addr == old_addr);
131
132     return addr;
133 }
134
135 static void* packet_new(const ArpPacketInfo *info, size_t *packet_len) {
136     uint8_t *r;
137
138     assert(info);
139     assert(packet_len);
140     assert(info->operation == ARP_REQUEST || info->operation == ARP_RESPONSE);
141
142     *packet_len = ARP_PACKET_SIZE;
143     r = avahi_new0(uint8_t, *packet_len);
144     
145     r[1] = 1; /* HTYPE */
146     r[2] = 8; /* PTYPE */
147     r[4] = ETHER_ADDRLEN; /* HLEN */
148     r[5] = 4; /* PLEN */
149     r[7] = (uint8_t) info->operation;
150
151     memcpy(r+8, info->sender_hw_address, ETHER_ADDRLEN);
152     memcpy(r+14, &info->sender_ip_address, 4);
153     memcpy(r+18, info->target_hw_address, ETHER_ADDRLEN);
154     memcpy(r+24, &info->target_ip_address, 4);
155
156     return r;
157 }
158
159 static void *packet_new_probe(uint32_t ip_address, const uint8_t*hw_address, size_t *packet_len) {
160     ArpPacketInfo info;
161     
162     memset(&info, 0, sizeof(info));
163     info.operation = ARP_REQUEST;
164     memcpy(info.sender_hw_address, hw_address, ETHER_ADDRLEN);
165     info.target_ip_address = ip_address;
166
167     return packet_new(&info, packet_len);
168 }
169
170 static void *packet_new_announcement(uint32_t ip_address, const uint8_t* hw_address, size_t *packet_len) {
171     ArpPacketInfo info;
172
173     memset(&info, 0, sizeof(info));
174     info.operation = ARP_REQUEST;
175     memcpy(info.sender_hw_address, hw_address, ETHER_ADDRLEN);
176     info.target_ip_address = ip_address;
177     info.sender_ip_address = ip_address;
178
179     return packet_new(&info, packet_len);
180 }
181
182 static int packet_parse(const void *data, size_t packet_len, ArpPacketInfo *info) {
183     const uint8_t *p = data;
184     
185     assert(data);
186
187     if (packet_len < ARP_PACKET_SIZE)
188         return -1;
189
190     /* Check HTYPE and PTYPE */
191     if (p[0] != 0 || p[1] != 1 || p[2] != 8 || p[3] != 0)
192         return -1;
193
194     /* Check HLEN, PLEN, OPERATION */
195     if (p[4] != ETHER_ADDRLEN || p[5] != 4 || p[6] != 0 || (p[7] != 1 && p[7] != 2))
196         return -1;
197     
198     info->operation = p[7];
199     memcpy(info->sender_hw_address, p+8, ETHER_ADDRLEN);
200     memcpy(&info->sender_ip_address, p+14, 4);
201     memcpy(info->target_hw_address, p+18, ETHER_ADDRLEN);
202     memcpy(&info->target_ip_address, p+24, 4);
203
204     return 0;
205 }
206
207 static void set_state(State st, int reset_counter) {
208     const char* const state_table[] = {
209         [STATE_START] = "START",
210         [STATE_WAITING_PROBE] = "WAITING_PROBE",
211         [STATE_PROBING] = "PROBING",
212         [STATE_WAITING_ANNOUNCE] = "WAITING_ANNOUNCE", 
213         [STATE_ANNOUNCING] = "ANNOUNCING",
214         [STATE_RUNNING] = "RUNNING",
215         [STATE_SLEEPING] = "SLEEPING"
216     };
217     
218     assert(st < STATE_MAX);
219
220     if (st == state && !reset_counter) {
221         n_iteration++;
222         daemon_log(LOG_DEBUG, "State iteration %s-%i", state_table[state], n_iteration);
223     } else {
224         daemon_log(LOG_DEBUG, "State transition %s-%i -> %s-0", state_table[state], n_iteration, state_table[st]);
225         state = st;
226         n_iteration = 0;
227     }
228 }
229
230 static int add_address(int iface, uint32_t addr) {
231     char buf[64];
232
233     daemon_log(LOG_INFO, "Configuring address %s", inet_ntop(AF_INET, &addr, buf, sizeof(buf)));
234     return 0;
235 }
236
237 static int remove_address(int iface, uint32_t addr) {
238     char buf[64];
239     
240     daemon_log(LOG_INFO, "Unconfiguring address %s", inet_ntop(AF_INET, &addr, buf, sizeof(buf)));
241     return 0;
242 }
243
244 static int open_socket(int iface, uint8_t *hw_address) {
245     int fd = -1;
246     struct sockaddr_ll sa;
247     socklen_t sa_len;
248     
249     if ((fd = socket(PF_PACKET, SOCK_DGRAM, 0)) < 0) {
250         daemon_log(LOG_ERR, "socket() failed: %s", strerror(errno));
251         goto fail;
252     }
253
254     memset(&sa, 0, sizeof(sa));
255     sa.sll_family = AF_PACKET;
256     sa.sll_protocol = htons(ETH_P_ARP);
257     sa.sll_ifindex = iface;
258
259     if (bind(fd, (struct sockaddr*) &sa, sizeof(sa)) < 0) {
260         daemon_log(LOG_ERR, "bind() failed: %s", strerror(errno));
261         goto fail;
262     }
263
264     sa_len = sizeof(sa);
265     if (getsockname(fd, (struct sockaddr*) &sa, &sa_len) < 0) {
266         daemon_log(LOG_ERR, "getsockname() failed: %s", strerror(errno));
267         goto fail;
268     }
269
270     if (sa.sll_halen != ETHER_ADDRLEN) {
271         daemon_log(LOG_ERR, "getsockname() returned invalid hardware address.");
272         goto fail;
273     }
274
275     memcpy(hw_address, sa.sll_addr, ETHER_ADDRLEN);
276
277     return fd;
278     
279 fail:
280     if (fd >= 0)
281         close(fd);
282
283     return -1;
284 }
285
286 static int send_packet(int fd, int iface, void *packet, size_t packet_len) {
287     struct sockaddr_ll sa;
288     
289     assert(fd >= 0);
290     assert(packet);
291     assert(packet_len > 0);
292
293     memset(&sa, 0, sizeof(sa));
294     sa.sll_family = AF_PACKET;
295     sa.sll_protocol = htons(ETH_P_ARP);
296     sa.sll_ifindex = iface;
297     sa.sll_halen = ETHER_ADDRLEN;
298     memset(sa.sll_addr, 0xFF, ETHER_ADDRLEN);
299
300     if (sendto(fd, packet, packet_len, 0, (struct sockaddr*) &sa, sizeof(sa)) < 0) {
301         daemon_log(LOG_ERR, "sendto() failed: %s", strerror(errno));
302         return -1;
303     }
304
305     return 0;
306 }
307
308 static int recv_packet(int fd, void **packet, size_t *packet_len) {
309     int s;
310     struct sockaddr_ll sa;
311     socklen_t sa_len;
312     
313     assert(fd >= 0);
314     assert(packet);
315     assert(packet_len);
316
317     *packet = NULL;
318
319     if (ioctl(fd, FIONREAD, &s) < 0) {
320         daemon_log(LOG_ERR, "FIONREAD failed: %s", strerror(errno));
321         goto fail;
322     }
323
324     assert(s > 0);
325
326     *packet_len = (size_t) s;
327     *packet = avahi_new(uint8_t, s);
328
329     sa_len = sizeof(sa);
330     if (recvfrom(fd, *packet, s, 0, (struct sockaddr*) &sa, &sa_len) < 0) {
331         daemon_log(LOG_ERR, "recvfrom() failed: %s", strerror(errno));
332         goto fail;
333     }
334     
335     return 0;
336     
337 fail:
338     if (*packet)
339         avahi_free(*packet);
340
341     return -1;
342 }
343  
344 int is_ll_address(uint32_t addr) {
345     return (ntohl(addr) & IPV4LL_NETMASK) == IPV4LL_NETWORK;
346 }
347
348 static struct timeval *elapse_time(struct timeval *tv, unsigned msec, unsigned jitter) {
349     assert(tv);
350
351     gettimeofday(tv, NULL);
352
353     if (msec)
354         avahi_timeval_add(tv, (AvahiUsec) msec*1000);
355
356     if (jitter)
357         avahi_timeval_add(tv, (AvahiUsec) (jitter*1000.0*rand()/(RAND_MAX+1.0)));
358         
359     return tv;
360 }
361
362 static int loop(int iface, uint32_t addr) {
363     enum {
364         FD_ARP,
365         FD_IFACE,
366         FD_MAX
367     };
368
369     int fd = -1, ret = -1;
370     struct timeval next_wakeup;
371     int next_wakeup_valid = 0;
372     char buf[64];
373     void *in_packet = NULL;
374     size_t in_packet_len;
375     void *out_packet = NULL;
376     size_t out_packet_len;
377     uint8_t hw_address[ETHER_ADDRLEN];
378     struct pollfd pollfds[FD_MAX];
379     int iface_fd;
380     Event event = EVENT_NULL;
381
382     if ((fd = open_socket(iface, hw_address)) < 0)
383         goto fail;
384
385     if ((iface_fd = iface_init(iface)) < 0)
386         goto fail;
387
388     if (iface_get_initial_state(&state) < 0)
389         goto fail;
390     
391     if (addr && !is_ll_address(addr)) {
392         daemon_log(LOG_WARNING, "Requested address %s is not from IPv4LL range 169.254/16, ignoring.", inet_ntop(AF_INET, &addr, buf, sizeof(buf)));
393         addr = 0;
394     }
395
396     if (!addr) {
397         int i;
398         uint32_t a = 1;
399
400         for (i = 0; i < ETHER_ADDRLEN; i++)
401             a += hw_address[i]*i;
402
403         addr = htonl(IPV4LL_NETWORK | (uint32_t) a);
404     }
405
406     daemon_log(LOG_INFO, "Starting with address %s", inet_ntop(AF_INET, &addr, buf, sizeof(buf)));
407
408     if (state == STATE_SLEEPING)
409         daemon_log(LOG_INFO, "Routable address already assigned, sleeping.");
410
411     memset(pollfds, 0, sizeof(pollfds));
412     pollfds[FD_ARP].fd = fd;
413     pollfds[FD_ARP].events = POLLIN;
414     pollfds[FD_IFACE].fd = iface_fd;
415     pollfds[FD_IFACE].events = POLLIN;
416     
417     for (;;) {
418         int r, timeout;
419         AvahiUsec usec;
420
421         if (state == STATE_START) {
422
423             /* First, wait a random time */
424             set_state(STATE_WAITING_PROBE, 1);
425
426             elapse_time(&next_wakeup, 0, PROBE_WAIT*1000);
427             next_wakeup_valid = 1;
428
429         } else if ((state == STATE_WAITING_PROBE && event == EVENT_TIMEOUT) ||
430                    (state == STATE_PROBING && event == EVENT_TIMEOUT && n_iteration < PROBE_NUM-2)) {
431
432             /* Send a probe */
433             out_packet = packet_new_probe(addr, hw_address, &out_packet_len);
434             set_state(STATE_PROBING, 0);
435
436             elapse_time(&next_wakeup, PROBE_MIN*1000, (PROBE_MAX-PROBE_MIN)*1000);
437             next_wakeup_valid = 1;
438             
439         } else if (state == STATE_PROBING && event == EVENT_TIMEOUT && n_iteration >= PROBE_NUM-2) {
440
441             /* Send the last probe */
442             out_packet = packet_new_probe(addr, hw_address, &out_packet_len);
443             set_state(STATE_WAITING_ANNOUNCE, 1);
444
445             elapse_time(&next_wakeup, ANNOUNCE_WAIT*1000, 0);
446             next_wakeup_valid = 1;
447             
448         } else if ((state == STATE_WAITING_ANNOUNCE && event == EVENT_TIMEOUT) ||
449                    (state == STATE_ANNOUNCING && event == EVENT_TIMEOUT && n_iteration < ANNOUNCE_NUM-1)) {
450
451             /* Send announcement packet */
452             out_packet = packet_new_announcement(addr, hw_address, &out_packet_len);
453             set_state(STATE_ANNOUNCING, 0);
454
455             elapse_time(&next_wakeup, ANNOUNCE_INTERVAL*1000, 0);
456             next_wakeup_valid = 1;
457             
458             if (n_iteration == 0) {
459                 add_address(iface, addr);
460                 n_conflict = 0;
461             }
462
463         } else if ((state == STATE_ANNOUNCING && event == EVENT_TIMEOUT && n_iteration >= ANNOUNCE_NUM-1)) {
464
465             daemon_log(LOG_INFO, "Successfully claimed IP address %s", inet_ntop(AF_INET, &addr, buf, sizeof(buf)));
466             set_state(STATE_RUNNING, 0);
467
468             next_wakeup_valid = 0;
469             
470         } else if (event == EVENT_PACKET) {
471             ArpPacketInfo info;
472
473             assert(in_packet);
474             
475             if (packet_parse(in_packet, in_packet_len, &info) < 0)
476                 daemon_log(LOG_WARNING, "Failed to parse incoming ARP packet.");
477             else {
478                 int conflict = 0;
479
480                 if (info.sender_ip_address == addr) {
481                     /* Normal conflict */
482                     conflict = 1;
483                     daemon_log(LOG_INFO, "Recieved conflicting normal ARP packet.");
484                 } else if (state == STATE_WAITING_PROBE || state == STATE_PROBING || state == STATE_WAITING_ANNOUNCE) {
485                     /* Probe conflict */
486                     conflict = info.target_ip_address == addr && memcmp(hw_address, info.sender_hw_address, ETHER_ADDRLEN);
487                     daemon_log(LOG_INFO, "Recieved conflicting probe ARP packet.");
488                 }
489
490                 if (conflict) {
491                     
492                     if (state == STATE_RUNNING || state == STATE_ANNOUNCING)
493                         remove_address(iface, addr);
494                     
495                     /* Pick a new address */
496                     addr = pick_addr(addr);
497
498                     daemon_log(LOG_INFO, "Trying address %s", inet_ntop(AF_INET, &addr, buf, sizeof(buf)));
499
500                     n_conflict++;
501
502                     set_state(STATE_WAITING_PROBE, 1);
503                     
504                     if (n_conflict >= MAX_CONFLICTS) {
505                         daemon_log(LOG_WARNING, "Got too many conflicts, rate limiting new probes.");
506                         elapse_time(&next_wakeup, RATE_LIMIT_INTERVAL*1000, PROBE_WAIT*1000);
507                     } else
508                         elapse_time(&next_wakeup, 0, PROBE_WAIT*1000);
509
510                     next_wakeup_valid = 1;
511                 } else
512                     daemon_log(LOG_DEBUG, "Ignoring ARP packet.");
513             }
514             
515         } else if (event == EVENT_ROUTABLE_ADDR_CONFIGURED) {
516
517             daemon_log(LOG_INFO, "A routable address has been configured.");
518
519             if (state == STATE_RUNNING || state == STATE_ANNOUNCING)
520                 remove_address(iface, addr);
521
522             set_state(STATE_SLEEPING, 1);
523             next_wakeup_valid = 0;
524             
525         } else if (event == EVENT_ROUTABLE_ADDR_UNCONFIGURED && state == STATE_SLEEPING) {
526
527             daemon_log(LOG_INFO, "No longer a routable address configured, restarting probe process.");
528
529             set_state(STATE_WAITING_PROBE, 1);
530
531             elapse_time(&next_wakeup, 0, PROBE_WAIT*1000);
532             next_wakeup_valid = 1;
533             
534         }
535         
536         if (out_packet) {
537             daemon_log(LOG_DEBUG, "sending...");
538             
539             if (send_packet(fd, iface, out_packet, out_packet_len) < 0)
540                 goto fail;
541             
542             avahi_free(out_packet);
543             out_packet = NULL;
544         }
545
546         if (in_packet) {
547             avahi_free(in_packet);
548             in_packet = NULL;
549         }
550
551         event = EVENT_NULL;
552         timeout = -1;
553         
554         if (next_wakeup_valid) {
555             usec = avahi_age(&next_wakeup);
556             timeout = usec < 0 ? (int) (-usec/1000) : 0;
557         }
558
559         daemon_log(LOG_DEBUG, "sleeping %ims", timeout);
560                     
561         while ((r = poll(pollfds, FD_MAX, timeout)) < 0 && errno == EINTR)
562             ;
563
564         if (r < 0) {
565             daemon_log(LOG_ERR, "poll() failed: %s", strerror(r));
566             break;
567         } else if (r == 0) {
568             event = EVENT_TIMEOUT;
569             next_wakeup_valid = 0;
570         } else {
571
572             if (pollfds[FD_ARP].revents == POLLIN) {
573                 if (recv_packet(fd, &in_packet, &in_packet_len) < 0)
574                     goto fail;
575                 
576                 if (in_packet)
577                     event = EVENT_PACKET;
578             }
579
580             if (event == EVENT_NULL &&
581                 pollfds[FD_IFACE].revents == POLLIN) {
582                 
583                 if (iface_process(&event) < 0)
584                     goto fail;
585             }
586         }
587     }
588
589     ret = 0;
590     
591 fail:
592
593     avahi_free(out_packet);
594     avahi_free(in_packet);
595     
596     if (fd >= 0)
597         close(fd);
598
599     if (iface_fd >= 0)
600         iface_done();
601     
602     return ret;
603 }
604
605 static int get_ifindex(const char *name) {
606     int fd = -1;
607     struct ifreq ifreq;
608
609     if ((fd = socket(PF_INET, SOCK_DGRAM, 0)) < 0) {
610         daemon_log(LOG_ERR, "socket() failed: %s", strerror(errno));
611         goto fail;
612     }
613
614     memset(&ifreq, 0, sizeof(ifreq));
615     strncpy(ifreq.ifr_name, name, IFNAMSIZ-1);
616     ifreq.ifr_name[IFNAMSIZ-1] = 0;
617
618     if (ioctl(fd, SIOCGIFINDEX, &ifreq) < 0) {
619         daemon_log(LOG_ERR, "SIOCGIFINDEX failed: %s", strerror(errno));
620         goto fail;
621     }
622
623     return ifreq.ifr_ifindex;
624
625 fail:
626
627     if (fd >= 0)
628         close(fd);
629     
630     return -1;
631 }
632
633 int main(int argc, char*argv[]) {
634     int ret = 1;
635     int ifindex;
636     uint32_t addr = 0;
637
638     avahi_init_proc_title(argc, argv);
639     
640     init_rand_seed();
641
642     if ((ifindex = get_ifindex(argc >= 2 ? argv[1] : "eth0")) < 0)
643         goto fail;
644
645     if (argc >= 3)
646         addr = inet_addr(argv[2]);
647     
648     if (loop(ifindex, addr) < 0)
649         goto fail;
650     
651     ret = 0;
652
653     
654 fail:
655     
656     return ret;
657 }
658
659 /* TODO:
660
661 - man page
662 - user script
663 - chroot/drop privs/caps
664 - daemonize
665 - defend
666 - signals
667 - store last used address
668 - cmdline
669 - setproctitle
670
671 */