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>