File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / mpd / src / ip.c
Revision 1.1.1.2 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Mon Jul 22 08:44:29 2013 UTC (10 years, 11 months ago) by misho
Branches: mpd, MAIN
CVS tags: v5_8p7, v5_8p1_cross, v5_8p1, v5_8, v5_7p0, v5_7, HEAD
5.7

    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: void u_addrcopy(const struct u_addr *src, struct u_addr *dst)
  262: {
  263:     memcpy(dst,src,sizeof(struct u_addr));
  264: }
  265: 
  266: void  u_rangecopy(const struct u_range *src, struct u_range *dst)
  267: {
  268:     memcpy(dst,src,sizeof(struct u_range));
  269: }
  270: 
  271: void u_addrclear(struct u_addr *addr)
  272: {
  273:     memset(addr,0,sizeof(struct u_addr));
  274: }
  275: 
  276: void u_rangeclear(struct u_range *range)
  277: {
  278:     memset(range,0,sizeof(struct u_range));
  279: }
  280: 
  281: void in_addrtou_addr(const struct in_addr *src, struct u_addr *dst)
  282: {
  283:     u_addrclear(dst);
  284:     dst->family=AF_INET;
  285:     dst->u.ip4=*src;
  286: }
  287: 
  288: void in6_addrtou_addr(const struct in6_addr *src, struct u_addr *dst)
  289: {
  290:     u_addrclear(dst);
  291:     dst->family=AF_INET6;
  292:     dst->u.ip6=*src;
  293: }
  294: 
  295: void u_addrtoin_addr(const struct u_addr *src, struct in_addr *dst)
  296: {
  297:     *dst=src->u.ip4;
  298: }
  299: 
  300: void u_addrtoin6_addr(const struct u_addr *src, struct in6_addr *dst)
  301: {
  302:     *dst=src->u.ip6;
  303: }
  304: 
  305: void in_addrtou_range(const struct in_addr *src, u_char width, struct u_range *dst)
  306: {
  307:     u_rangeclear(dst);
  308:     in_addrtou_addr(src, &dst->addr);
  309:     dst->width = width;
  310: }
  311: 
  312: void in6_addrtou_range(const struct in6_addr *src, u_char width, struct u_range *dst)
  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: 
  377: void u_rangetosockaddrs(struct u_range *range, struct sockaddr_storage *dst, struct sockaddr_storage *msk)
  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: 
  401: void u_addrtosockaddr(struct u_addr *addr, in_port_t port, struct sockaddr_storage *dst)
  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>