Annotation of embedaddon/mpd/src/ip.c, revision 1.1
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:
! 261: struct u_addr *u_addrcopy(const struct u_addr *src, struct u_addr *dst)
! 262: {
! 263: return memcpy(dst,src,sizeof(struct u_addr));
! 264: }
! 265:
! 266: struct u_addr *u_rangecopy(const struct u_range *src, struct u_range *dst)
! 267: {
! 268: return memcpy(dst,src,sizeof(struct u_range));
! 269: }
! 270:
! 271: struct u_addr *u_addrclear(struct u_addr *addr)
! 272: {
! 273: memset(addr,0,sizeof(struct u_addr));
! 274: return addr;
! 275: }
! 276:
! 277: struct u_range *u_rangeclear(struct u_range *range)
! 278: {
! 279: memset(range,0,sizeof(struct u_range));
! 280: return range;
! 281: }
! 282:
! 283: struct u_addr *in_addrtou_addr(const struct in_addr *src, struct u_addr *dst)
! 284: {
! 285: u_addrclear(dst);
! 286: dst->family=AF_INET;
! 287: dst->u.ip4=*src;
! 288: return dst;
! 289: }
! 290:
! 291: struct u_addr *in6_addrtou_addr(const struct in6_addr *src, struct u_addr *dst)
! 292: {
! 293: u_addrclear(dst);
! 294: dst->family=AF_INET6;
! 295: dst->u.ip6=*src;
! 296: return dst;
! 297: }
! 298:
! 299: struct in_addr *u_addrtoin_addr(const struct u_addr *src, struct in_addr *dst)
! 300: {
! 301: *dst=src->u.ip4;
! 302: return dst;
! 303: }
! 304:
! 305: struct in6_addr *u_addrtoin6_addr(const struct u_addr *src, struct in6_addr *dst)
! 306: {
! 307: *dst=src->u.ip6;
! 308: return dst;
! 309: }
! 310:
! 311: struct u_range *in_addrtou_range(const struct in_addr *src, u_char width, struct u_range *dst)
! 312: {
! 313: u_rangeclear(dst);
! 314: in_addrtou_addr(src, &dst->addr);
! 315: dst->width = width;
! 316: return dst;
! 317: }
! 318:
! 319: struct u_range *in6_addrtou_range(const struct in6_addr *src, u_char width, struct u_range *dst)
! 320: {
! 321: u_rangeclear(dst);
! 322: in6_addrtou_addr(src, &dst->addr);
! 323: dst->width = width;
! 324: return dst;
! 325: }
! 326:
! 327: int u_addrempty(struct u_addr *addr)
! 328: {
! 329: int i;
! 330: switch (addr->family) {
! 331: case AF_INET:
! 332: return (addr->u.ip4.s_addr==0);
! 333: break;
! 334: case AF_INET6:
! 335: for (i=0;i<16;i++) {
! 336: if (addr->u.ip6.s6_addr[i]!=0)
! 337: return 0;
! 338: }
! 339: return 1;
! 340: break;
! 341: }
! 342: return 1;
! 343: }
! 344:
! 345: int u_rangeempty(struct u_range *range)
! 346: {
! 347: return u_addrempty(&range->addr);
! 348: }
! 349:
! 350: int u_rangehost(struct u_range *range)
! 351: {
! 352: switch (range->addr.family) {
! 353: case AF_INET:
! 354: return (range->width==32);
! 355: break;
! 356: case AF_INET6:
! 357: return (range->width==128);
! 358: break;
! 359: }
! 360: return 0;
! 361: }
! 362:
! 363: static struct in6_addr
! 364: bits2mask6(int bits)
! 365: {
! 366: struct in6_addr result;
! 367: u_int32_t bit = 0x80;
! 368: u_char *c = result.s6_addr;
! 369:
! 370: memset(&result, '\0', sizeof(result));
! 371:
! 372: while (bits) {
! 373: if (bit == 0) {
! 374: bit = 0x80;
! 375: c++;
! 376: }
! 377: *c |= bit;
! 378: bit >>= 1;
! 379: bits--;
! 380: }
! 381:
! 382: return result;
! 383: }
! 384:
! 385: struct sockaddr_storage *u_rangetosockaddrs(struct u_range *range, struct sockaddr_storage *dst, struct sockaddr_storage *msk)
! 386: {
! 387: memset(dst,0,sizeof(struct sockaddr_storage));
! 388: memset(msk,0,sizeof(struct sockaddr_storage));
! 389: dst->ss_family = msk->ss_family = range->addr.family;
! 390: switch (range->addr.family) {
! 391: case AF_INET:
! 392: ((struct sockaddr_in*)dst)->sin_len=sizeof(struct sockaddr_in);
! 393: ((struct sockaddr_in*)dst)->sin_addr=range->addr.u.ip4;
! 394: ((struct sockaddr_in*)msk)->sin_len=sizeof(struct sockaddr_in);
! 395: ((struct sockaddr_in*)msk)->sin_addr.s_addr=htonl(0xFFFFFFFFLL<<(32 - range->width));
! 396: break;
! 397: case AF_INET6:
! 398: ((struct sockaddr_in6*)dst)->sin6_len=sizeof(struct sockaddr_in6);
! 399: ((struct sockaddr_in6*)dst)->sin6_addr=range->addr.u.ip6;
! 400: ((struct sockaddr_in6*)msk)->sin6_len=sizeof(struct sockaddr_in6);
! 401: ((struct sockaddr_in6*)msk)->sin6_addr=bits2mask6(range->width);
! 402: break;
! 403: default:
! 404: dst->ss_len=sizeof(struct sockaddr_storage);
! 405: break;
! 406: }
! 407: return dst;
! 408: }
! 409:
! 410: struct sockaddr_storage *u_addrtosockaddr(struct u_addr *addr, in_port_t port, struct sockaddr_storage *dst)
! 411: {
! 412: memset(dst,0,sizeof(struct sockaddr_storage));
! 413: dst->ss_family=addr->family;
! 414: switch (addr->family) {
! 415: case AF_INET:
! 416: ((struct sockaddr_in*)dst)->sin_len=sizeof(struct sockaddr_in);
! 417: ((struct sockaddr_in*)dst)->sin_addr=addr->u.ip4;
! 418: ((struct sockaddr_in*)dst)->sin_port=htons(port);
! 419: break;
! 420: case AF_INET6:
! 421: ((struct sockaddr_in6*)dst)->sin6_len=sizeof(struct sockaddr_in6);
! 422: ((struct sockaddr_in6*)dst)->sin6_addr=addr->u.ip6;
! 423: ((struct sockaddr_in6*)dst)->sin6_port=htons(port);
! 424: break;
! 425: default:
! 426: dst->ss_len=sizeof(struct sockaddr_storage);
! 427: break;
! 428: }
! 429: return dst;
! 430: }
! 431:
! 432: void sockaddrtou_addr(struct sockaddr_storage *src, struct u_addr *addr, in_port_t *port)
! 433: {
! 434: addr->family=src->ss_family;
! 435: switch (addr->family) {
! 436: case AF_INET:
! 437: addr->u.ip4=((struct sockaddr_in*)src)->sin_addr;
! 438: *port=ntohs(((struct sockaddr_in*)src)->sin_port);
! 439: break;
! 440: case AF_INET6:
! 441: addr->u.ip6=((struct sockaddr_in6*)src)->sin6_addr;
! 442: *port=ntohs(((struct sockaddr_in6*)src)->sin6_port);
! 443: break;
! 444: default:
! 445: memset(addr,0,sizeof(struct u_addr));
! 446: *port=0;
! 447: break;
! 448: }
! 449: }
! 450:
! 451: int u_addrcompare(const struct u_addr *addr1, const struct u_addr *addr2)
! 452: {
! 453: int i;
! 454:
! 455: if (addr1->family<addr2->family)
! 456: return(-1);
! 457: else if (addr1->family>addr2->family)
! 458: return(1);
! 459:
! 460: switch (addr1->family) {
! 461: case AF_INET:
! 462: if (addr1->u.ip4.s_addr < addr2->u.ip4.s_addr)
! 463: return (-1);
! 464: else if (addr1->u.ip4.s_addr == addr2->u.ip4.s_addr)
! 465: return (0);
! 466: else
! 467: return (1);
! 468: break;
! 469: case AF_INET6:
! 470: for (i=0; i<16; i++) {
! 471: if (addr1->u.ip6.s6_addr[i] < addr2->u.ip6.s6_addr[i])
! 472: return (-1);
! 473: else if (addr1->u.ip6.s6_addr[i] > addr2->u.ip6.s6_addr[i])
! 474: return (1);
! 475: }
! 476: return 0;
! 477: break;
! 478: }
! 479: return 0;
! 480: }
! 481:
! 482: int u_rangecompare(const struct u_range *range1, const struct u_range *range2)
! 483: {
! 484: if (range1->width<range2->width)
! 485: return(-1);
! 486: else if (range1->width>range2->width)
! 487: return(1);
! 488:
! 489: return u_addrcompare(&range1->addr,&range2->addr);
! 490: }
! 491:
! 492: uint32_t
! 493: u_addrtoid(const struct u_addr *addr)
! 494: {
! 495: uint32_t id;
! 496:
! 497: if (addr->family==AF_INET) {
! 498: id = ntohl(addr->u.ip4.s_addr);
! 499: } else if (addr->family==AF_INET6) {
! 500: uint32_t *a32 = (uint32_t *)(&addr->u.ip6.s6_addr[0]);
! 501: id = a32[0] + a32[1] + a32[2] + a32[3];
! 502: } else {
! 503: id = 0;
! 504: }
! 505:
! 506: return (id);
! 507: }
! 508:
! 509: u_char
! 510: in_addrtowidth(struct in_addr *mask)
! 511: {
! 512: u_char width = 0;
! 513: uint32_t m = ntohl(mask->s_addr);
! 514:
! 515: while ((m & 0x80000000) != 0) {
! 516: m <<= 1;
! 517: width++;
! 518: }
! 519: return (width);
! 520: }
! 521:
! 522: struct in_addr *
! 523: widthtoin_addr(u_char width, struct in_addr *mask)
! 524: {
! 525: mask->s_addr = htonl(0xFFFFFFFF << (32 - width));
! 526: return (mask);
! 527: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>