Annotation of embedaddon/quagga/babeld/util.c, revision 1.1.1.1
1.1 misho 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: *
18: Copyright (c) 2007, 2008 by Juliusz Chroboczek
19: Copyright 2011 by Matthieu Boutier and Juliusz Chroboczek
20:
21: Permission is hereby granted, free of charge, to any person obtaining a copy
22: of this software and associated documentation files (the "Software"), to deal
23: in the Software without restriction, including without limitation the rights
24: to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
25: copies of the Software, and to permit persons to whom the Software is
26: furnished to do so, subject to the following conditions:
27:
28: The above copyright notice and this permission notice shall be included in
29: all copies or substantial portions of the Software.
30:
31: THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
32: IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
33: FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
34: AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
35: LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
36: OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
37: THE 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:
57: unsigned
58: roughly(unsigned value)
59: {
60: return value * 3 / 4 + random() % (value / 2);
61: }
62:
63: /* d = s1 - s2 */
64: void
65: timeval_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:
77: unsigned
78: timeval_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 */
99: void
100: timeval_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:
113: void
114: set_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. */
120: int
121: timeval_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 */
137: void
138: timeval_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] */
149: void
150: timeval_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 */
161: int
162: parse_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:
203: int
204: in_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:
223: unsigned char *
224: mask_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:
240: static const unsigned char v4prefix[16] =
241: {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF, 0, 0, 0, 0 };
242:
243: static const unsigned char llprefix[16] =
244: {0xFE, 0x80};
245:
246: const char *
247: format_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:
259: const char *
260: format_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:
278: const char *
279: format_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:
290: const char *format_bool(const int b) {
291: return b ? "true" : "false";
292: }
293:
294: int
295: parse_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:
319: int
320: parse_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:
346: int
347: wait_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:
366: int
367: martian_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:
379: int
380: linklocal(const unsigned char *address)
381: {
382: return memcmp(address, llprefix, 8) == 0;
383: }
384:
385: int
386: v4mapped(const unsigned char *address)
387: {
388: return memcmp(address, v4prefix, 12) == 0;
389: }
390:
391: void
392: v4tov6(unsigned char *dst, const unsigned char *src)
393: {
394: memcpy(dst, v4prefix, 12);
395: memcpy(dst + 12, src, 4);
396: }
397:
398: void
399: inaddr_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:
406: void
407: uchar_to_inaddr(struct in_addr *dest, const unsigned char *src)
408: {
409: assert(v4mapped(src));
410: memcpy(dest, src + 12, 4);
411: }
412:
413: void
414: in6addr_to_uchar(unsigned char *dest, const struct in6_addr *src)
415: {
416: memcpy(dest, src, 16);
417: }
418:
419: void
420: uchar_to_in6addr(struct in6_addr *dest, const unsigned char *src)
421: {
422: memcpy(dest, src, 16);
423: }
424:
425: int
426: daemonise()
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: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>