File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / pimd / inet.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Mon Jun 12 07:59:37 2017 UTC (7 years ago) by misho
Branches: pimd, MAIN
CVS tags: v2_3_2, HEAD
pimd 2.3.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[MAX_INET_BUF_LEN];		/* buffers to hold the string representations  */
   21: char s2[MAX_INET_BUF_LEN];		/* of IP addresses, to be passed to inet_fmt() */
   22: char s3[MAX_INET_BUF_LEN];
   23: char s4[MAX_INET_BUF_LEN];
   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 inet_valid_host(uint32_t naddr)
   32: {
   33:     uint32_t addr;
   34: 
   35:     addr = ntohl(naddr);
   36: 
   37:     return !(IN_MULTICAST(addr) ||
   38: 	     IN_BADCLASS (addr) ||
   39: 	     (addr & 0xff000000) == 0);
   40: }
   41: 
   42: /*
   43:  * Verify that a given netmask is plausible;
   44:  * make sure that it is a series of 1's followed by
   45:  * a series of 0's with no discontiguous 1's.
   46:  */
   47: int inet_valid_mask(uint32_t mask)
   48: {
   49:     if (~(((mask & -mask) - 1) | mask) != 0) {
   50:         /* Mask is not contiguous */
   51:         return FALSE;
   52:     }
   53: 
   54:     return TRUE;
   55: }
   56: 
   57: /*
   58:  * Verify that a given subnet number and mask pair are credible.
   59:  *
   60:  * With CIDR, almost any subnet and mask are credible.  mrouted still
   61:  * can't handle aggregated class A's, so we still check that, but
   62:  * otherwise the only requirements are that the subnet address is
   63:  * within the [ABC] range and that the host bits of the subnet
   64:  * are all 0.
   65:  */
   66: int inet_valid_subnet(uint32_t nsubnet, uint32_t nmask)
   67: {
   68:     uint32_t subnet, mask;
   69: 
   70:     subnet = ntohl(nsubnet);
   71:     mask   = ntohl(nmask);
   72: 
   73:     if ((subnet & mask) != subnet)
   74:         return FALSE;
   75: 
   76:     if (subnet == 0)
   77:         return mask == 0;
   78: 
   79:     if (IN_CLASSA(subnet)) {
   80:         if (mask < 0xff000000 ||
   81:             (subnet & 0xff000000) == 0x7f000000 ||
   82:             (subnet & 0xff000000) == 0x00000000)
   83: 	    return FALSE;
   84:     }
   85:     else if (IN_CLASSD(subnet) || IN_BADCLASS(subnet)) {
   86:         /* Above Class C address space */
   87:         return FALSE;
   88:     }
   89:     if (subnet & ~mask) {
   90:         /* Host bits are set in the subnet */
   91:         return FALSE;
   92:     }
   93:     if (!inet_valid_mask(mask)) {
   94:         /* Netmask is not contiguous */
   95:         return FALSE;
   96:     }
   97: 
   98:     return TRUE;
   99: }
  100: 
  101: 
  102: /*
  103:  * Convert an IP address in uint32_t (network) format into a printable string.
  104:  */
  105: char *inet_fmt(uint32_t addr, char *s, size_t len)
  106: {
  107:     uint8_t *a;
  108: 
  109:     a = (uint8_t *)&addr;
  110:     snprintf(s, len, "%u.%u.%u.%u", a[0], a[1], a[2], a[3]);
  111: 
  112:     return s;
  113: }
  114: 
  115: /*
  116:  * Convert the printable string representation of an IP address into the
  117:  * uint32_t (network) format.  Return 0xffffffff on error.  (To detect the
  118:  * legal address with that value, you must explicitly compare the string
  119:  * with "255.255.255.255".)
  120:  * The return value is in network order.
  121:  */
  122: uint32_t inet_parse(char *s, int n)
  123: {
  124:     uint32_t a = 0;
  125:     u_int a0 = 0, a1 = 0, a2 = 0, a3 = 0;
  126:     int i;
  127:     char c;
  128: 
  129:     i = sscanf(s, "%u.%u.%u.%u%c", &a0, &a1, &a2, &a3, &c);
  130:     if (i < n || i > 4 || a0 > 255 || a1 > 255 || a2 > 255 || a3 > 255)
  131:         return 0xffffffff;
  132: 
  133:     ((uint8_t *)&a)[0] = a0;
  134:     ((uint8_t *)&a)[1] = a1;
  135:     ((uint8_t *)&a)[2] = a2;
  136:     ((uint8_t *)&a)[3] = a3;
  137: 
  138:     return a;
  139: }
  140: 
  141: 
  142: /*
  143:  * inet_cksum extracted from:
  144:  *			P I N G . C
  145:  *
  146:  * Author -
  147:  *	Mike Muuss
  148:  *	U. S. Army Ballistic Research Laboratory
  149:  *	December, 1983
  150:  * Modified at Uc Berkeley
  151:  *
  152:  * (ping.c) Status -
  153:  *	Public Domain.  Distribution Unlimited.
  154:  *
  155:  *			I N _ C K S U M
  156:  *
  157:  * Checksum routine for Internet Protocol family headers (C Version)
  158:  *
  159:  */
  160: int inet_cksum(uint16_t *addr, u_int len)
  161: {
  162:         int sum = 0;
  163:         int nleft = (int)len;
  164:         uint16_t *w = addr;
  165:         uint16_t answer = 0;
  166: 
  167:         /*
  168:          *  Our algorithm is simple, using a 32 bit accumulator (sum),
  169:          *  we add sequential 16 bit words to it, and at the end, fold
  170:          *  back all the carry bits from the top 16 bits into the lower
  171:          *  16 bits.
  172:          */
  173:         while (nleft > 1)  {
  174:                 sum += *w++;
  175:                 nleft -= 2;
  176:         }
  177: 
  178:         /* mop up an odd byte, if necessary */
  179:         if (nleft == 1) {
  180:                 *(uint8_t *) (&answer) = *(uint8_t *)w ;
  181:                 sum += answer;
  182:         }
  183: 
  184:         /*
  185:          * add back carry outs from top 16 bits to low 16 bits
  186:          */
  187:         sum = (sum >> 16) + (sum & 0xffff);	/* add hi 16 to low 16 */
  188:         sum += (sum >> 16);			/* add carry */
  189:         answer = ~sum;				/* truncate to 16 bits */
  190: 
  191:         return answer;
  192: }
  193: 
  194: /*
  195:  * Called by following netname() to create a mask specified network address.
  196:  */
  197: void trimdomain(char *cp)
  198: {
  199:     static char domain[MAXHOSTNAMELEN + 1];
  200:     static int first = 1;
  201:     char *s;
  202: 
  203:     if (first) {
  204:         first = 0;
  205:         if (gethostname(domain, MAXHOSTNAMELEN) == 0 &&
  206:             (s = strchr(domain, '.')))
  207:            (void) strlcpy(domain, s + 1, sizeof(domain));
  208:         else
  209:             domain[0] = 0;
  210:     }
  211: 
  212:     if (domain[0]) {
  213:         while ((cp = strchr(cp, '.'))) {
  214:             if (!strcasecmp(cp + 1, domain)) {
  215:                 *cp = 0;
  216:                 break;
  217:             }
  218: 	    cp++;
  219:         }
  220:     }
  221: }
  222: 
  223: static uint32_t forgemask(uint32_t a)
  224: {
  225:     uint32_t m;
  226: 
  227:     if (IN_CLASSA(a))
  228:         m = IN_CLASSA_NET;
  229:     else if (IN_CLASSB(a))
  230:         m = IN_CLASSB_NET;
  231:     else
  232:         m = IN_CLASSC_NET;
  233: 
  234:     return (m);
  235: }
  236: 
  237: static void domask(char *dst, size_t len, uint32_t addr, uint32_t mask)
  238: {
  239:     int b, i;
  240: 
  241:     if (!mask || (forgemask(addr) == mask)) {
  242:         *dst = '\0';
  243:         return;
  244:     }
  245: 
  246:     i = 0;
  247:     for (b = 0; b < 32; b++) {
  248:         if (mask & (1 << b)) {
  249:             int bb;
  250: 
  251:             i = b;
  252:             for (bb = b+1; bb < 32; bb++) {
  253:                 if (!(mask & (1 << bb))) {
  254:                     i = -1; /* noncontig */
  255:                     break;
  256:                 }
  257: 	    }
  258:             break;
  259:         }
  260:     }
  261: 
  262:     if (i == -1)
  263:         snprintf(dst, len, "&0x%x", mask);
  264:     else
  265:         snprintf(dst, len, "/%d", 32 - i);
  266: }
  267: 
  268: /*
  269:  * Return the name of the network whose address is given.
  270:  * The address is assumed to be that of a net or subnet, not a host.
  271:  */
  272: char *netname(uint32_t addr, uint32_t mask)
  273: {
  274:     static char line[MAXHOSTNAMELEN + 4];
  275:     uint32_t omask;
  276:     uint32_t i;
  277: 
  278:     i = ntohl(addr);
  279:     omask = mask = ntohl(mask);
  280:     if ((i & 0xffffff) == 0)
  281:         snprintf(line, sizeof(line), "%u", C(i >> 24));
  282:     else if ((i & 0xffff) == 0)
  283:         snprintf(line, sizeof(line), "%u.%u", C(i >> 24) , C(i >> 16));
  284:     else if ((i & 0xff) == 0)
  285:         snprintf(line, sizeof(line), "%u.%u.%u", C(i >> 24), C(i >> 16), C(i >> 8));
  286:     else
  287:         snprintf(line, sizeof(line), "%u.%u.%u.%u", C(i >> 24),
  288:                 C(i >> 16), C(i >> 8), C(i));
  289:     domask(line + strlen(line), sizeof(line) - strlen(line), i, omask);
  290: 
  291:     return line;
  292: }
  293: 
  294: /**
  295:  * Local Variables:
  296:  *  version-control: t
  297:  *  indent-tabs-mode: t
  298:  *  c-file-style: "ellemtel"
  299:  *  c-basic-offset: 4
  300:  * End:
  301:  */

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