File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / pimdd / inet.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Mon Jun 12 07:58:55 2017 UTC (6 years, 11 months ago) by misho
Branches: pimdd, MAIN
CVS tags: v0_2_1p0, v0_2_1, HEAD
pimdd-dense 0.2.1.0_2

    1: /*
    2:  * The mrouted program is covered by the license in the accompanying file
    3:  * named "LICENSE.mrouted". Use of the mrouted program represents acceptance of
    4:  * the terms and conditions listed in that file.
    5:  *
    6:  * The mrouted program is COPYRIGHT 1989 by The Board of Trustees of
    7:  * Leland Stanford Junior University.
    8:  *
    9:  *
   10:  * inet.c,v 3.8.4.1 1997/01/29 19:49:33 fenner Exp
   11:  */
   12: #define C(x)    ((x) & 0xff)
   13: 
   14: #include "defs.h"
   15: 
   16: 
   17: /*
   18:  * Exported variables.
   19:  */
   20: char s1[19];		/* buffers to hold the string representations  */
   21: char s2[19];		/* of IP addresses, to be passed to inet_fmt() */
   22: char s3[19];
   23: char s4[19];
   24: 
   25: 
   26: /*
   27:  * Verify that a given IP address is credible as a host address.
   28:  * (Without a mask, cannot detect addresses of the form {subnet,0} or
   29:  * {subnet,-1}.)
   30:  */
   31: int
   32: inet_valid_host(naddr)
   33:     u_int32 naddr;
   34: {
   35:     register u_int32 addr;
   36:     
   37:     addr = ntohl(naddr);
   38:     
   39:     return (!(IN_MULTICAST(addr) ||
   40: 	      IN_BADCLASS (addr) ||
   41: 	      (addr & 0xff000000) == 0));
   42: }
   43: 
   44: /*
   45:  * Verify that a given netmask is plausible;
   46:  * make sure that it is a series of 1's followed by
   47:  * a series of 0's with no discontiguous 1's.
   48:  */
   49: int
   50: inet_valid_mask(mask)
   51:     u_int32 mask;
   52: {
   53:     if (~(((mask & -mask) - 1) | mask) != 0) {
   54: 	/* Mask is not contiguous */
   55: 	return (FALSE);
   56:     }
   57: 
   58:     return (TRUE);
   59: }
   60: 
   61: /*
   62:  * Verify that a given subnet number and mask pair are credible.
   63:  *
   64:  * With CIDR, almost any subnet and mask are credible.  mrouted still
   65:  * can't handle aggregated class A's, so we still check that, but
   66:  * otherwise the only requirements are that the subnet address is
   67:  * within the [ABC] range and that the host bits of the subnet
   68:  * are all 0.
   69:  */
   70: int
   71: inet_valid_subnet(nsubnet, nmask)
   72:     u_int32 nsubnet, nmask;
   73: {
   74:     register u_int32 subnet, mask;
   75: 
   76:     subnet = ntohl(nsubnet);
   77:     mask   = ntohl(nmask);
   78: 
   79:     if ((subnet & mask) != subnet)
   80: 	return (FALSE);
   81: 
   82:     if (subnet == 0)
   83: 	return (mask == 0);
   84: 
   85:     if (IN_CLASSA(subnet)) {
   86: 	if (mask < 0xff000000 ||
   87: 	    (subnet & 0xff000000) == 0x7f000000 ||
   88: 	    (subnet & 0xff000000) == 0x00000000) return (FALSE);
   89:     }
   90:     else if (IN_CLASSD(subnet) || IN_BADCLASS(subnet)) {
   91: 	/* Above Class C address space */
   92: 	return (FALSE);
   93:     }
   94:     if (subnet & ~mask) {
   95: 	/* Host bits are set in the subnet */
   96: 	return (FALSE);
   97:     }
   98:     if (!inet_valid_mask(mask)) {
   99: 	/* Netmask is not contiguous */
  100: 	return (FALSE);
  101:     }
  102:     
  103:     return (TRUE);
  104: }
  105: 
  106: 
  107: /*
  108:  * Convert an IP address in u_int32 (network) format into a printable string.
  109:  */
  110: char *
  111: inet_fmt(addr, s)
  112:     u_int32 addr;
  113:     char *s;
  114: {
  115:     register u_char *a;
  116:     
  117:     a = (u_char *)&addr;
  118:     sprintf(s, "%u.%u.%u.%u", a[0], a[1], a[2], a[3]);
  119:     return (s);
  120: }
  121: 
  122: 
  123: /*
  124:  * Convert an IP subnet number in u_int32 (network) format into a printable
  125:  * string including the netmask as a number of bits.
  126:  */
  127: #ifdef NOSUCHDEF	/* replaced by netname() */
  128: char *
  129: inet_fmts(addr, mask, s)
  130:     u_int32 addr, mask;
  131:     char *s;
  132: {
  133:     register u_char *a, *m;
  134:     int bits;
  135: 
  136:     if ((addr == 0) && (mask == 0)) {
  137: 	sprintf(s, "default");
  138: 	return (s);
  139:     }
  140:     a = (u_char *)&addr;
  141:     m = (u_char *)&mask;
  142:     bits = 33 - ffs(ntohl(mask));
  143: 
  144:     if      (m[3] != 0) sprintf(s, "%u.%u.%u.%u/%d", a[0], a[1], a[2], a[3],
  145: 				bits);
  146:     else if (m[2] != 0) sprintf(s, "%u.%u.%u/%d",    a[0], a[1], a[2], bits);
  147:     else if (m[1] != 0) sprintf(s, "%u.%u/%d",       a[0], a[1], bits);
  148:     else                sprintf(s, "%u/%d",          a[0], bits);
  149:     
  150:     return (s);
  151: }
  152: #endif /* NOSUCHDEF */
  153: 
  154: /*
  155:  * Convert the printable string representation of an IP address into the
  156:  * u_int32 (network) format.  Return 0xffffffff on error.  (To detect the
  157:  * legal address with that value, you must explicitly compare the string
  158:  * with "255.255.255.255".)
  159:  * The return value is in network order.
  160:  */
  161: u_int32
  162: inet_parse(s, n)
  163:     char *s;
  164:     int n;
  165: {
  166:     u_int32 a = 0;
  167:     u_int a0 = 0, a1 = 0, a2 = 0, a3 = 0;
  168:     int i;
  169:     char c;
  170: 
  171:     i = sscanf(s, "%u.%u.%u.%u%c", &a0, &a1, &a2, &a3, &c);
  172:     if (i < n || i > 4 || a0 > 255 || a1 > 255 || a2 > 255 || a3 > 255)
  173: 	return (0xffffffff);
  174: 
  175:     ((u_char *)&a)[0] = a0;
  176:     ((u_char *)&a)[1] = a1;
  177:     ((u_char *)&a)[2] = a2;
  178:     ((u_char *)&a)[3] = a3;
  179: 
  180:     return (a);
  181: }
  182: 
  183: 
  184: /*
  185:  * inet_cksum extracted from:
  186:  *			P I N G . C
  187:  *
  188:  * Author -
  189:  *	Mike Muuss
  190:  *	U. S. Army Ballistic Research Laboratory
  191:  *	December, 1983
  192:  * Modified at Uc Berkeley
  193:  *
  194:  * (ping.c) Status -
  195:  *	Public Domain.  Distribution Unlimited.
  196:  *
  197:  *			I N _ C K S U M
  198:  *
  199:  * Checksum routine for Internet Protocol family headers (C Version)
  200:  *
  201:  */
  202: int
  203: inet_cksum(addr, len)
  204: 	u_int16 *addr;
  205: 	u_int len;
  206: {
  207: 	register int nleft = (int)len;
  208: 	register u_int16 *w = addr;
  209: 	u_int16 answer = 0;
  210: 	register int sum = 0;
  211: 
  212: 	/*
  213: 	 *  Our algorithm is simple, using a 32 bit accumulator (sum),
  214: 	 *  we add sequential 16 bit words to it, and at the end, fold
  215: 	 *  back all the carry bits from the top 16 bits into the lower
  216: 	 *  16 bits.
  217: 	 */
  218: 	while (nleft > 1)  {
  219: 		sum += *w++;
  220: 		nleft -= 2;
  221: 	}
  222: 
  223: 	/* mop up an odd byte, if necessary */
  224: 	if (nleft == 1) {
  225: 		*(u_char *) (&answer) = *(u_char *)w ;
  226: 		sum += answer;
  227: 	}
  228: 
  229: 	/*
  230: 	 * add back carry outs from top 16 bits to low 16 bits
  231: 	 */
  232: 	sum = (sum >> 16) + (sum & 0xffff);	/* add hi 16 to low 16 */
  233: 	sum += (sum >> 16);			/* add carry */
  234: 	answer = ~sum;				/* truncate to 16 bits */
  235: 	return (answer);
  236: }
  237: 
  238: /*
  239:  * Called by following netname() to create a mask specified network address.
  240:  */
  241: void
  242: trimdomain(cp)
  243:     char *cp;
  244: {
  245:     static char domain[MAXHOSTNAMELEN + 1];
  246:     static int first = 1;
  247:     char *s;
  248:     
  249:     if (first) {
  250: 	first = 0;
  251: 	if (gethostname(domain, MAXHOSTNAMELEN) == 0 &&
  252: 	    (s = strchr(domain, '.')))
  253: 	    (void) strcpy(domain, s + 1);
  254: 	else
  255: 	    domain[0] = 0;
  256:     }
  257: 
  258:     if (domain[0]) {
  259: 	while ((cp = strchr(cp, '.'))) {
  260: 	    if (!strcasecmp(cp + 1, domain)) {
  261: 		*cp = 0;        /* hit it */
  262: 		break;
  263: 	    } else {
  264: 		cp++;
  265: 	    }
  266: 	}
  267:     }
  268: }
  269: 
  270: static u_long
  271: forgemask(a)
  272:     u_long a;
  273: {
  274:     u_long m;
  275: 
  276:     if (IN_CLASSA(a))
  277: 	m = IN_CLASSA_NET;
  278:     else if (IN_CLASSB(a))
  279: 	m = IN_CLASSB_NET;
  280:     else
  281: 	m = IN_CLASSC_NET;
  282:     return (m);
  283: }
  284: 
  285: static void
  286: domask(dst, addr, mask)
  287:     char *dst;
  288:     u_long addr, mask;
  289: {
  290:     int b, i;
  291: 	
  292:     if (!mask || (forgemask(addr) == mask)) {
  293: 	*dst = '\0';
  294: 	return;         
  295:     }
  296:     i = 0;
  297:     for (b = 0; b < 32; b++)
  298: 	if (mask & (1 << b)) {
  299: 	    int bb;
  300: 	    
  301: 	    i = b;
  302: 	    for (bb = b+1; bb < 32; bb++)
  303: 		if (!(mask & (1 << bb))) {
  304: 		    i = -1; /* noncontig */
  305: 		    break;
  306: 		}
  307: 	    break;
  308: 	}
  309:     if (i == -1) 
  310: 	sprintf(dst, "&0x%lx", mask);
  311:     else
  312: 	sprintf(dst, "/%d", 32 - i);
  313: }
  314: 
  315: /*
  316:  * Return the name of the network whose address is given.
  317:  * The address is assumed to be that of a net or subnet, not a host.
  318:  */
  319: char *
  320: netname(addr, mask)       
  321:     u_int32 addr, mask;
  322: {
  323:     static char line[MAXHOSTNAMELEN + 4];
  324:     u_int32 omask;
  325:     u_int32 i;
  326:     
  327:     i = ntohl(addr);
  328:     omask = mask = ntohl(mask);
  329:     if ((i & 0xffffff) == 0)
  330: 	sprintf(line, "%u", C(i >> 24));
  331:     else if ((i & 0xffff) == 0)
  332: 	sprintf(line, "%u.%u", C(i >> 24) , C(i >> 16));
  333:     else if ((i & 0xff) == 0)
  334: 	sprintf(line, "%u.%u.%u", C(i >> 24), C(i >> 16), C(i >> 8));
  335:     else
  336: 	sprintf(line, "%u.%u.%u.%u", C(i >> 24),
  337: 		C(i >> 16), C(i >> 8), C(i));
  338:     domask(line+strlen(line), i, omask);
  339:     return (line);          
  340: }

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