Annotation of embedaddon/mpd/src/ip.c, revision 1.1.1.3

1.1       misho       1: 
                      2: /*
                      3:  * ip.c
                      4:  *
                      5:  * Written by Alexander Motin <mav@FreeBSD.org>
                      6:  */
                      7: 
                      8: #include "ppp.h"
                      9: #include "ip.h"
                     10: #include "util.h"
                     11: 
                     12: /*
                     13:  * IpShowRoutes()
                     14:  *
                     15:  * Show routing tables
                     16:  */
                     17: 
                     18: int
1.1.1.3 ! misho      19: IpShowRoutes(Context ctx, int ac, const char *const av[], const void *arg)
1.1       misho      20: {
                     21:   FILE *fp;
                     22:   char buf[256];
                     23:   char *c;
                     24: 
1.1.1.3 ! misho      25:   (void)ac;
        !            26:   (void)av;
        !            27:   (void)arg;
        !            28: 
1.1       misho      29:   if ((fp = popen(PATH_NETSTAT " -nr -f inet", "r")) == NULL)
                     30:   {
                     31:     Perror("popen");
                     32:     return(CMD_ERR_OTHER);
                     33:   }
                     34:   while (fgets(buf,sizeof(buf)-1,fp)) {
                     35:     if ((c=strrchr(buf,'\n')))
                     36:        *c='\r';
                     37:     Printf("%s\n",buf);
                     38:   }
                     39:   pclose(fp);
                     40:   return(0);
                     41: }
                     42: 
                     43: /*
                     44:  * IpAddrInRange()
                     45:  *
                     46:  * Is the IP address within the range?
                     47:  */
                     48: 
                     49: int
                     50: IpAddrInRange(struct u_range *range, struct u_addr *addr)
                     51: {
                     52:   u_int32_t mask;
                     53:   u_int8_t bmask;
                     54:   int  i;
                     55: 
                     56:   if (u_rangeempty(range))
                     57:     return(1); // For compatibility we think that empty range includes any ip.
                     58: 
                     59:   if (range->addr.family!=addr->family)
                     60:     return(0);
                     61: 
                     62:   switch (range->addr.family) {
                     63:     case AF_INET:
                     64:            mask = range->width ? htonl(~0 << (32 - range->width)) : 0;
                     65:            return((addr->u.ip4.s_addr & mask) == (range->addr.u.ip4.s_addr & mask));
                     66:        break;
                     67:     case AF_INET6:
                     68:            for (i=0; i<((range->width+7)/8); i++) {
                     69:                if ((i*8+7)<range->width) {
                     70:                    if (addr->u.ip6.s6_addr[i]!=range->addr.u.ip6.s6_addr[i])
                     71:                        return 0;
                     72:                } else {
                     73:                    bmask=(range->width==i*8)? 0 : (~0 << (8 - range->width));
                     74:                    if ((addr->u.ip6.s6_addr[i] & bmask) != (range->addr.u.ip6.s6_addr[i] & bmask))
                     75:                        return 0;
                     76:                }
                     77:            }
                     78:            return 1;
                     79:        break;
                     80:   }
                     81:   return 0;
                     82: }
                     83: 
                     84: /*
                     85:  * ParseAddr()
                     86:  *
                     87:  * Parse an IP address & mask of the form X.Y.Z.W/M.
                     88:  * If no slash, then M is assumed to be 32.
                     89:  * Returns TRUE if successful
                     90:  */
                     91: 
                     92: int
                     93: ParseAddr(const char *s, struct u_addr *addr, u_char allow)
                     94: {
                     95:   if (strchr(s, '/'))
                     96:     return (FALSE);
                     97: 
                     98: /* Get IP address part; if that fails, try looking up hostname */
                     99: 
                    100:   if ((allow&ALLOW_IPV4) && inet_pton(AF_INET, s, &addr->u.ip4))
                    101:   {
                    102:     addr->family=AF_INET;
                    103:   } 
                    104:   else if ((allow&ALLOW_IPV6) && inet_pton(AF_INET6, s, &addr->u.ip6))
                    105:   {
                    106:     addr->family=AF_INET6;
                    107:   } 
                    108:   else if ((allow&ALLOW_IPV4) && !GetAnyIpAddress(addr, s)) 
                    109:   {
                    110:     addr->family=AF_INET;
                    111:   }
                    112:   else if (allow&ALLOW_IPV4)
                    113:   {
                    114:        struct hostent  *hptr;
                    115:        int             k;
                    116: 
                    117:        if ((hptr = gethostbyname(s)) == NULL) {
                    118:            return (FALSE);
                    119:        }
                    120:        for (k = 0; hptr->h_addr_list[k]; k++);
                    121:        if (k == 0)
                    122:            k = 1;
                    123:        memcpy(&addr->u.ip4, hptr->h_addr_list[random() % k], sizeof(addr->u.ip4));
                    124:        addr->family=AF_INET;
                    125:   } 
                    126:   else 
                    127:   {
                    128:     return (FALSE);
                    129:   }
                    130: 
                    131:   return(TRUE);
                    132: }
                    133: 
                    134: /*
                    135:  * ParseRange()
                    136:  *
                    137:  * Parse an IP address & mask of the form X.Y.Z.W/M.
                    138:  * If no slash, then M is assumed to be 32.
                    139:  * Returns TRUE if successful
                    140:  */
                    141: 
                    142: int
                    143: ParseRange(const char *s, struct u_range *range, u_char allow)
                    144: {
                    145:   int                  n_bits;
                    146:   char                 *widp, buf[64];
                    147: 
                    148:   strlcpy(buf, s, sizeof(buf));
                    149:   if ((widp = strchr(buf, '/')) != NULL)
                    150:     *widp++ = '\0';
                    151:   else
                    152:     widp = buf + strlen(buf);
                    153: 
                    154: /* Get IP address part; if that fails, try looking up hostname */
                    155: 
                    156:   if (!ParseAddr(buf, &range->addr, allow)) 
                    157:     return(FALSE);
                    158: 
                    159: /* Get mask width */
                    160: 
                    161:   if (*widp)
                    162:   {
                    163:     if ((n_bits = atoi(widp)) < 0 || (range->addr.family==AF_INET && n_bits > 32) || (range->addr.family==AF_INET6 && n_bits > 128))
                    164:     {
                    165:       return(FALSE);
                    166:     }
                    167:   }
                    168:   else if (range->addr.family==AF_INET) {
                    169:     n_bits = 32;
                    170:   } else {
                    171:     n_bits = 128;
                    172:   }
                    173:   range->width = n_bits;
                    174: 
                    175:   return(TRUE);
                    176: }
                    177: 
                    178: /*
                    179:  * ParseAddrPort()
                    180:  *
                    181:  * Parse an IP address & port of the form X.Y.Z.W P.
                    182:  * Returns pointer to sockaddr_in. Not thread safe!
                    183:  */
                    184: 
                    185: struct sockaddr_storage *
1.1.1.3 ! misho     186: ParseAddrPort(int ac, const char *const av[], u_char allow)
1.1       misho     187: {
                    188:   static struct sockaddr_storage ss;
                    189:   struct u_addr addr;
                    190:   int          port = 0;
                    191: 
                    192:   if (ac < 1 || ac > 2)
                    193:     return (NULL);
                    194: 
                    195:   if (!ParseAddr(av[0], &addr, allow))
                    196:     return(NULL);
                    197: 
                    198:   if (ac > 1) {
                    199:     if ((port = atoi(av[1])) < 1 || port > 65535) {
                    200:       Log(LG_ERR, ("Bad port \"%s\"", av[1]));
                    201:       return (NULL);
                    202:     }
                    203:   }
                    204: 
                    205:   memset(&ss, 0, sizeof(ss));
                    206:   ss.ss_family = addr.family;
                    207:   switch (addr.family) {
                    208:     case AF_INET:
                    209:        ss.ss_len = sizeof(struct sockaddr_in);
                    210:        ((struct sockaddr_in*)&ss)->sin_addr = addr.u.ip4;
                    211:        ((struct sockaddr_in*)&ss)->sin_port = htons(port);
                    212:        break;
                    213:     case AF_INET6:
                    214:        ss.ss_len = sizeof(struct sockaddr_in6);
                    215:        ((struct sockaddr_in6*)&ss)->sin6_addr = addr.u.ip6;
                    216:        ((struct sockaddr_in6*)&ss)->sin6_port = htons(port);
                    217:        break;
                    218:     default:
                    219:        ss.ss_len = sizeof(struct sockaddr_storage);
                    220:   }
                    221: 
                    222:   return (&ss);
                    223: }
                    224: 
                    225: sa_family_t    u_addrfamily(struct u_addr *addr)
                    226: {
                    227:     return addr->family;
                    228: }
                    229: 
                    230: sa_family_t    u_rangefamily(struct u_range *range)
                    231: {
                    232:     return range->addr.family;
                    233: }
                    234: 
                    235: char   *u_addrtoa(struct u_addr *addr, char *dst, size_t size)
                    236: {
                    237:     dst[0]=0;
                    238:     
                    239:     if (addr->family==AF_INET) {
                    240:        inet_ntop(addr->family, &addr->u.ip4, dst, size);
                    241:     } 
                    242:     else if (addr->family==AF_INET6) 
                    243:     {
                    244:         inet_ntop(addr->family, &addr->u.ip6, dst, size);
                    245:     }
                    246:     else if (addr->family==AF_UNSPEC) 
                    247:     {
                    248:         snprintf(dst,size,"UNSPEC");
                    249:     }
                    250: 
                    251:     return dst;
                    252: }
                    253: 
                    254: char   *u_rangetoa(struct u_range *range, char *dst, size_t size)
                    255: {
                    256:     if (!u_addrtoa(&range->addr, dst, size))
                    257:        return NULL;
                    258: 
                    259:     if (range->addr.family!=AF_UNSPEC)
                    260:        snprintf(dst+strlen(dst), size-strlen(dst), "/%d", range->width);
                    261: 
                    262:     return dst;
                    263: }
                    264: 
1.1.1.2   misho     265: void u_addrcopy(const struct u_addr *src, struct u_addr *dst)
1.1       misho     266: {
1.1.1.2   misho     267:     memcpy(dst,src,sizeof(struct u_addr));
1.1       misho     268: }
                    269: 
1.1.1.2   misho     270: void  u_rangecopy(const struct u_range *src, struct u_range *dst)
1.1       misho     271: {
1.1.1.2   misho     272:     memcpy(dst,src,sizeof(struct u_range));
1.1       misho     273: }
                    274: 
1.1.1.2   misho     275: void u_addrclear(struct u_addr *addr)
1.1       misho     276: {
                    277:     memset(addr,0,sizeof(struct u_addr));
                    278: }
                    279: 
1.1.1.2   misho     280: void u_rangeclear(struct u_range *range)
1.1       misho     281: {
                    282:     memset(range,0,sizeof(struct u_range));
                    283: }
                    284: 
1.1.1.2   misho     285: void in_addrtou_addr(const struct in_addr *src, struct u_addr *dst)
1.1       misho     286: {
                    287:     u_addrclear(dst);
                    288:     dst->family=AF_INET;
                    289:     dst->u.ip4=*src;
                    290: }
                    291: 
1.1.1.2   misho     292: void in6_addrtou_addr(const struct in6_addr *src, struct u_addr *dst)
1.1       misho     293: {
                    294:     u_addrclear(dst);
                    295:     dst->family=AF_INET6;
                    296:     dst->u.ip6=*src;
                    297: }
                    298: 
1.1.1.2   misho     299: void u_addrtoin_addr(const struct u_addr *src, struct in_addr *dst)
1.1       misho     300: {
                    301:     *dst=src->u.ip4;
                    302: }
                    303: 
1.1.1.2   misho     304: void u_addrtoin6_addr(const struct u_addr *src, struct in6_addr *dst)
1.1       misho     305: {
                    306:     *dst=src->u.ip6;
                    307: }
                    308: 
1.1.1.2   misho     309: void in_addrtou_range(const struct in_addr *src, u_char width, struct u_range *dst)
1.1       misho     310: {
                    311:     u_rangeclear(dst);
                    312:     in_addrtou_addr(src, &dst->addr);
                    313:     dst->width = width;
                    314: }
                    315: 
1.1.1.2   misho     316: void in6_addrtou_range(const struct in6_addr *src, u_char width, struct u_range *dst)
1.1       misho     317: {
                    318:     u_rangeclear(dst);
                    319:     in6_addrtou_addr(src, &dst->addr);
                    320:     dst->width = width;
                    321: }
                    322: 
                    323: int u_addrempty(struct u_addr *addr)
                    324: {
                    325:     int i;
                    326:     switch (addr->family) {
                    327:        case AF_INET:
                    328:                return (addr->u.ip4.s_addr==0); 
                    329:            break;
                    330:        case AF_INET6:
                    331:                for (i=0;i<16;i++) {
                    332:                    if (addr->u.ip6.s6_addr[i]!=0)
                    333:                        return 0;
                    334:                }
                    335:                return 1;
                    336:            break;
                    337:     }
                    338:     return 1;
                    339: }
                    340: 
                    341: int u_rangeempty(struct u_range *range)
                    342: {
                    343:     return u_addrempty(&range->addr);
                    344: }
                    345: 
                    346: int u_rangehost(struct u_range *range)
                    347: {
                    348:     switch (range->addr.family) {
                    349:        case AF_INET:
                    350:                return (range->width==32); 
                    351:            break;
                    352:        case AF_INET6:
                    353:                return (range->width==128); 
                    354:            break;
                    355:     }
                    356:     return 0;
                    357: }
                    358: 
                    359: static struct in6_addr
                    360: bits2mask6(int bits)
                    361: {
                    362:   struct in6_addr result;
                    363:   u_int32_t bit = 0x80;
                    364:   u_char *c = result.s6_addr;
                    365: 
                    366:   memset(&result, '\0', sizeof(result));
                    367: 
                    368:   while (bits) {
                    369:     if (bit == 0) {
                    370:       bit = 0x80;
                    371:       c++;
                    372:     }
                    373:     *c |= bit;
                    374:     bit >>= 1;
                    375:     bits--;
                    376:   }
                    377: 
                    378:   return result;
                    379: }
                    380: 
1.1.1.2   misho     381: void u_rangetosockaddrs(struct u_range *range, struct sockaddr_storage *dst, struct sockaddr_storage *msk)
1.1       misho     382: {
                    383:     memset(dst,0,sizeof(struct sockaddr_storage));
                    384:     memset(msk,0,sizeof(struct sockaddr_storage));
                    385:     dst->ss_family = msk->ss_family = range->addr.family;
                    386:     switch (range->addr.family) {
                    387:        case AF_INET:
                    388:                ((struct sockaddr_in*)dst)->sin_len=sizeof(struct sockaddr_in);
                    389:                ((struct sockaddr_in*)dst)->sin_addr=range->addr.u.ip4;
                    390:                ((struct sockaddr_in*)msk)->sin_len=sizeof(struct sockaddr_in);
                    391:                ((struct sockaddr_in*)msk)->sin_addr.s_addr=htonl(0xFFFFFFFFLL<<(32 - range->width));
                    392:            break;
                    393:        case AF_INET6:
                    394:                ((struct sockaddr_in6*)dst)->sin6_len=sizeof(struct sockaddr_in6);
                    395:                ((struct sockaddr_in6*)dst)->sin6_addr=range->addr.u.ip6;
                    396:                ((struct sockaddr_in6*)msk)->sin6_len=sizeof(struct sockaddr_in6);
                    397:                ((struct sockaddr_in6*)msk)->sin6_addr=bits2mask6(range->width);
                    398:            break;
                    399:        default:
                    400:                dst->ss_len=sizeof(struct sockaddr_storage);
                    401:            break;
                    402:     }
                    403: }
                    404: 
1.1.1.2   misho     405: void u_addrtosockaddr(struct u_addr *addr, in_port_t port, struct sockaddr_storage *dst)
1.1       misho     406: {
                    407:     memset(dst,0,sizeof(struct sockaddr_storage));
                    408:     dst->ss_family=addr->family;
                    409:     switch (addr->family) {
                    410:        case AF_INET:
                    411:                ((struct sockaddr_in*)dst)->sin_len=sizeof(struct sockaddr_in);
                    412:                ((struct sockaddr_in*)dst)->sin_addr=addr->u.ip4;
                    413:                ((struct sockaddr_in*)dst)->sin_port=htons(port);
                    414:            break;
                    415:        case AF_INET6:
                    416:                ((struct sockaddr_in6*)dst)->sin6_len=sizeof(struct sockaddr_in6);
                    417:                ((struct sockaddr_in6*)dst)->sin6_addr=addr->u.ip6;
                    418:                ((struct sockaddr_in6*)dst)->sin6_port=htons(port);
                    419:            break;
                    420:        default:
                    421:                dst->ss_len=sizeof(struct sockaddr_storage);
                    422:            break;
                    423:     }
                    424: }
                    425: 
                    426: void sockaddrtou_addr(struct sockaddr_storage *src, struct u_addr *addr, in_port_t *port)
                    427: {
                    428:     addr->family=src->ss_family;
                    429:     switch (addr->family) {
                    430:        case AF_INET:
                    431:                addr->u.ip4=((struct sockaddr_in*)src)->sin_addr;
                    432:                *port=ntohs(((struct sockaddr_in*)src)->sin_port);
                    433:            break;
                    434:        case AF_INET6:
                    435:                addr->u.ip6=((struct sockaddr_in6*)src)->sin6_addr;
                    436:                *port=ntohs(((struct sockaddr_in6*)src)->sin6_port);
                    437:            break;
                    438:        default:
                    439:            memset(addr,0,sizeof(struct u_addr));
                    440:            *port=0;
                    441:            break;
                    442:     }
                    443: }
                    444: 
                    445: int u_addrcompare(const struct u_addr *addr1, const struct u_addr *addr2)
                    446: {
                    447:   int  i;
                    448: 
                    449:   if (addr1->family<addr2->family)
                    450:     return(-1);
                    451:   else if (addr1->family>addr2->family)
                    452:     return(1);
                    453:   
                    454:   switch (addr1->family) {
                    455:     case AF_INET:
                    456:            if (addr1->u.ip4.s_addr < addr2->u.ip4.s_addr)
                    457:                return (-1);
                    458:            else if (addr1->u.ip4.s_addr == addr2->u.ip4.s_addr)
                    459:                return (0);
                    460:            else 
                    461:                return (1);
                    462:        break;
                    463:     case AF_INET6:
                    464:            for (i=0; i<16; i++) {
                    465:                if (addr1->u.ip6.s6_addr[i] < addr2->u.ip6.s6_addr[i])
                    466:                    return (-1);
                    467:                else if (addr1->u.ip6.s6_addr[i] > addr2->u.ip6.s6_addr[i])
                    468:                    return (1);
                    469:            }
                    470:            return 0;
                    471:        break;
                    472:   }
                    473:   return 0;
                    474: }
                    475: 
                    476: int u_rangecompare(const struct u_range *range1, const struct u_range *range2)
                    477: {
                    478:   if (range1->width<range2->width)
                    479:     return(-1);
                    480:   else if (range1->width>range2->width)
                    481:     return(1);
                    482: 
                    483:   return u_addrcompare(&range1->addr,&range2->addr);
                    484: }
                    485: 
                    486: uint32_t
                    487: u_addrtoid(const struct u_addr *addr)
                    488: {
                    489:     uint32_t id;
                    490: 
                    491:     if (addr->family==AF_INET) {
                    492:        id = ntohl(addr->u.ip4.s_addr);
                    493:     } else if (addr->family==AF_INET6) {
1.1.1.3 ! misho     494:        const uint32_t *a32 = (const uint32_t *)(const void *)(&addr->u.ip6.s6_addr[0]);
1.1       misho     495:         id = a32[0] + a32[1] + a32[2] + a32[3];
                    496:     } else {
                    497:        id = 0;
                    498:     }
                    499: 
                    500:     return (id);
                    501: }
                    502: 
                    503: u_char
                    504: in_addrtowidth(struct in_addr *mask)
                    505: {
                    506:        u_char width = 0;
                    507:        uint32_t m = ntohl(mask->s_addr);
                    508: 
                    509:        while ((m & 0x80000000) != 0) {
                    510:                m <<= 1;
                    511:                width++;
                    512:        }
                    513:        return (width);
                    514: }
                    515: 
                    516: struct in_addr *
                    517: widthtoin_addr(u_char width, struct in_addr *mask)
                    518: {
                    519:        mask->s_addr = htonl(0xFFFFFFFF << (32 - width));
                    520:        return (mask);
                    521: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>