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

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

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