1/*
2 *  This file is free software: you may copy, redistribute and/or modify it
3 *  under the terms of the GNU General Public License as published by the
4 *  Free Software Foundation, either version 2 of the License, or (at your
5 *  option) any later version.
6 *
7 *  This file is distributed in the hope that it will be useful, but
8 *  WITHOUT ANY WARRANTY; without even the implied warranty of
9 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
10 *  General Public License for more details.
11 *
12 *  You should have received a copy of the GNU General Public License
13 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
14 *
15 * This file incorporates work covered by the following copyright and
16 * permission notice:
17 *
18Copyright (c) 2007, 2008 by Juliusz Chroboczek
19Copyright 2011 by Matthieu Boutier and Juliusz Chroboczek
20
21Permission is hereby granted, free of charge, to any person obtaining a copy
22of this software and associated documentation files (the "Software"), to deal
23in the Software without restriction, including without limitation the rights
24to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
25copies of the Software, and to permit persons to whom the Software is
26furnished to do so, subject to the following conditions:
27
28The above copyright notice and this permission notice shall be included in
29all copies or substantial portions of the Software.
30
31THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
32IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
33FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
34AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
35LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
36OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
37THE SOFTWARE.
38*/
39
40#include <stdlib.h>
41#include <stdarg.h>
42#include <string.h>
43#include <sys/time.h>
44#include <time.h>
45#include <stdio.h>
46#include <unistd.h>
47
48#include <sys/types.h>
49#include <sys/socket.h>
50#include <netinet/in.h>
51#include <arpa/inet.h>
52
53#include "babel_main.h"
54#include "babeld.h"
55#include "util.h"
56
57unsigned
58roughly(unsigned value)
59{
60    return value * 3 / 4 + random() % (value / 2);
61}
62
63/* d = s1 - s2 */
64void
65timeval_minus(struct timeval *d,
66              const struct timeval *s1, const struct timeval *s2)
67{
68    if(s1->tv_usec >= s2->tv_usec) {
69        d->tv_usec = s1->tv_usec - s2->tv_usec;
70        d->tv_sec = s1->tv_sec - s2->tv_sec;
71    } else {
72        d->tv_usec = s1->tv_usec + 1000000 - s2->tv_usec;
73        d->tv_sec = s1->tv_sec - s2->tv_sec - 1;
74    }
75}
76
77unsigned
78timeval_minus_msec(const struct timeval *s1, const struct timeval *s2)
79{
80    if(s1->tv_sec < s2->tv_sec)
81        return 0;
82
83    /* Avoid overflow. */
84    if(s1->tv_sec - s2->tv_sec > 2000000)
85        return 2000000000;
86
87    if(s1->tv_sec > s2->tv_sec)
88        return
89            (unsigned)((unsigned)(s1->tv_sec - s2->tv_sec) * 1000 +
90                       ((int)s1->tv_usec - s2->tv_usec) / 1000);
91
92    if(s1->tv_usec <= s2->tv_usec)
93        return 0;
94
95    return (unsigned)(s1->tv_usec - s2->tv_usec) / 1000u;
96}
97
98/* d = s + msecs */
99void
100timeval_add_msec(struct timeval *d, const struct timeval *s, const int msecs)
101{
102    int usecs;
103    d->tv_sec = s->tv_sec + msecs / 1000;
104    usecs = s->tv_usec + (msecs % 1000) * 1000;
105    if(usecs < 1000000) {
106        d->tv_usec = usecs;
107    } else {
108        d->tv_usec = usecs - 1000000;
109        d->tv_sec++;
110    }
111}
112
113void
114set_timeout(struct timeval *timeout, int msecs)
115{
116    timeval_add_msec(timeout, &babel_now, roughly(msecs));
117}
118
119/* returns <0 if "s1" < "s2", etc. */
120int
121timeval_compare(const struct timeval *s1, const struct timeval *s2)
122{
123    if(s1->tv_sec < s2->tv_sec)
124        return -1;
125    else if(s1->tv_sec > s2->tv_sec)
126        return 1;
127    else if(s1->tv_usec < s2->tv_usec)
128        return -1;
129    else if(s1->tv_usec > s2->tv_usec)
130        return 1;
131    else
132        return 0;
133}
134
135/* set d at min(d, s) */
136/* {0, 0} represents infinity */
137void
138timeval_min(struct timeval *d, const struct timeval *s)
139{
140    if(s->tv_sec == 0)
141        return;
142
143    if(d->tv_sec == 0 || timeval_compare(d, s) > 0) {
144        *d = *s;
145    }
146}
147
148/* set d to min(d, x) with x in [secs, secs+1] */
149void
150timeval_min_sec(struct timeval *d, time_t secs)
151{
152    if(d->tv_sec == 0 || d->tv_sec > secs) {
153        d->tv_sec = secs;
154        d->tv_usec = random() % 1000000;
155    }
156}
157
158/* parse a float value in second and return the corresponding mili-seconds.
159 For example:
160 parse_msec("12.342345") returns 12342 */
161int
162parse_msec(const char *string)
163{
164    unsigned int in, fl;
165    int i, j;
166
167    in = fl = 0;
168    i = 0;
169    while(string[i] == ' ' || string[i] == '\t')
170        i++;
171    while(string[i] >= '0' && string[i] <= '9') {
172        in = in * 10 + string[i] - '0';
173        i++;
174    }
175    if(string[i] == '.') {
176        i++;
177        j = 0;
178        while(string[i] >= '0' && string[i] <= '9') {
179            fl = fl * 10 + string[i] - '0';
180            i++;
181            j++;
182        }
183
184        while(j > 3) {
185            fl /= 10;
186            j--;
187        }
188        while(j < 3) {
189            fl *= 10;
190            j++;
191        }
192    }
193
194    while(string[i] == ' ' || string[i] == '\t')
195        i++;
196
197    if(string[i] == '\0')
198        return in * 1000 + fl;
199
200    return -1;
201}
202
203int
204in_prefix(const unsigned char *restrict address,
205          const unsigned char *restrict prefix, unsigned char plen)
206{
207    unsigned char m;
208
209    if(plen > 128)
210        plen = 128;
211
212    if(memcmp(address, prefix, plen / 8) != 0)
213        return 0;
214
215    if(plen % 8 == 0)
216        return 1;
217
218    m = 0xFF << (8 - (plen % 8));
219
220    return ((address[plen / 8] & m) == (prefix[plen / 8] & m));
221}
222
223unsigned char *
224mask_prefix(unsigned char *restrict ret,
225            const unsigned char *restrict prefix, unsigned char plen)
226{
227    if(plen >= 128) {
228        memcpy(ret, prefix, 16);
229        return ret;
230    }
231
232    memset(ret, 0, 16);
233    memcpy(ret, prefix, plen / 8);
234    if(plen % 8 != 0)
235        ret[plen / 8] =
236            (prefix[plen / 8] & ((0xFF << (8 - (plen % 8))) & 0xFF));
237    return ret;
238}
239
240static const unsigned char v4prefix[16] =
241    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF, 0, 0, 0, 0 };
242
243static const unsigned char llprefix[16] =
244    {0xFE, 0x80};
245
246const char *
247format_address(const unsigned char *address)
248{
249    static char buf[4][INET6_ADDRSTRLEN];
250    static int i = 0;
251    i = (i + 1) % 4;
252    if(v4mapped(address))
253       inet_ntop(AF_INET, address + 12, buf[i], INET6_ADDRSTRLEN);
254    else
255       inet_ntop(AF_INET6, address, buf[i], INET6_ADDRSTRLEN);
256    return buf[i];
257}
258
259const char *
260format_prefix(const unsigned char *prefix, unsigned char plen)
261{
262    static char buf[4][INET6_ADDRSTRLEN + 4];
263    static int i = 0;
264    int n;
265    i = (i + 1) % 4;
266    if(plen >= 96 && v4mapped(prefix)) {
267        inet_ntop(AF_INET, prefix + 12, buf[i], INET6_ADDRSTRLEN);
268        n = strlen(buf[i]);
269        snprintf(buf[i] + n, INET6_ADDRSTRLEN + 4 - n, "/%d", plen - 96);
270    } else {
271        inet_ntop(AF_INET6, prefix, buf[i], INET6_ADDRSTRLEN);
272        n = strlen(buf[i]);
273        snprintf(buf[i] + n, INET6_ADDRSTRLEN + 4 - n, "/%d", plen);
274    }
275    return buf[i];
276}
277
278const char *
279format_eui64(const unsigned char *eui)
280{
281    static char buf[4][28];
282    static int i = 0;
283    i = (i + 1) % 4;
284    snprintf(buf[i], 28, "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x",
285             eui[0], eui[1], eui[2], eui[3],
286             eui[4], eui[5], eui[6], eui[7]);
287    return buf[i];
288}
289
290const char *format_bool(const int b) {
291    return b ? "true" : "false";
292}
293
294int
295parse_address(const char *address, unsigned char *addr_r, int *af_r)
296{
297    struct in_addr ina;
298    struct in6_addr ina6;
299    int rc;
300
301    rc = inet_pton(AF_INET, address, &ina);
302    if(rc > 0) {
303        memcpy(addr_r, v4prefix, 12);
304        memcpy(addr_r + 12, &ina, 4);
305        if(af_r) *af_r = AF_INET;
306        return 0;
307    }
308
309    rc = inet_pton(AF_INET6, address, &ina6);
310    if(rc > 0) {
311        memcpy(addr_r, &ina6, 16);
312        if(af_r) *af_r = AF_INET6;
313        return 0;
314    }
315
316    return -1;
317}
318
319int
320parse_eui64(const char *eui, unsigned char *eui_r)
321{
322    int n;
323    n = sscanf(eui, "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
324               &eui_r[0], &eui_r[1], &eui_r[2], &eui_r[3],
325               &eui_r[4], &eui_r[5], &eui_r[6], &eui_r[7]);
326    if(n == 8)
327        return 0;
328
329    n = sscanf(eui, "%02hhx-%02hhx-%02hhx-%02hhx-%02hhx-%02hhx-%02hhx-%02hhx",
330               &eui_r[0], &eui_r[1], &eui_r[2], &eui_r[3],
331               &eui_r[4], &eui_r[5], &eui_r[6], &eui_r[7]);
332    if(n == 8)
333        return 0;
334
335    n = sscanf(eui, "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
336               &eui_r[0], &eui_r[1], &eui_r[2],
337               &eui_r[5], &eui_r[6], &eui_r[7]);
338    if(n == 6) {
339        eui_r[3] = 0xFF;
340        eui_r[4] = 0xFE;
341        return 0;
342    }
343    return -1;
344}
345
346int
347wait_for_fd(int direction, int fd, int msecs)
348{
349    fd_set fds;
350    int rc;
351    struct timeval tv;
352
353    tv.tv_sec = msecs / 1000;
354    tv.tv_usec = (msecs % 1000) * 1000;
355
356    FD_ZERO(&fds);
357    FD_SET(fd, &fds);
358    if(direction)
359        rc = select(fd + 1, NULL, &fds, NULL, &tv);
360    else
361        rc = select(fd + 1, &fds, NULL, NULL, &tv);
362
363    return rc;
364}
365
366int
367martian_prefix(const unsigned char *prefix, int plen)
368{
369    return
370        (plen >= 8 && prefix[0] == 0xFF) ||
371        (plen >= 10 && prefix[0] == 0xFE && (prefix[1] & 0xC0) == 0x80) ||
372        (plen >= 128 && memcmp(prefix, zeroes, 15) == 0 &&
373         (prefix[15] == 0 || prefix[15] == 1)) ||
374        (plen >= 96 && v4mapped(prefix) &&
375         ((plen >= 104 && (prefix[12] == 127 || prefix[12] == 0)) ||
376          (plen >= 100 && (prefix[12] & 0xE0) == 0xE0)));
377}
378
379int
380linklocal(const unsigned char *address)
381{
382    return memcmp(address, llprefix, 8) == 0;
383}
384
385int
386v4mapped(const unsigned char *address)
387{
388    return memcmp(address, v4prefix, 12) == 0;
389}
390
391void
392v4tov6(unsigned char *dst, const unsigned char *src)
393{
394    memcpy(dst, v4prefix, 12);
395    memcpy(dst + 12, src, 4);
396}
397
398void
399inaddr_to_uchar(unsigned char *dest, const struct in_addr *src)
400{
401    memcpy(dest, v4prefix, 12);
402    memcpy(dest + 12, src, 4);
403    assert(v4mapped(dest));
404}
405
406void
407uchar_to_inaddr(struct in_addr *dest, const unsigned char *src)
408{
409    assert(v4mapped(src));
410    memcpy(dest, src + 12, 4);
411}
412
413void
414in6addr_to_uchar(unsigned char *dest, const struct in6_addr *src)
415{
416    memcpy(dest, src, 16);
417}
418
419void
420uchar_to_in6addr(struct in6_addr *dest, const unsigned char *src)
421{
422    memcpy(dest, src, 16);
423}
424
425int
426daemonise()
427{
428    int rc;
429
430    fflush(stdout);
431    fflush(stderr);
432
433    rc = fork();
434    if(rc < 0)
435        return -1;
436
437    if(rc > 0)
438        exit(0);
439
440    rc = setsid();
441    if(rc < 0)
442        return -1;
443
444    return 1;
445}
446