Annotation of embedaddon/quagga/babeld/util.c, revision 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>