Annotation of embedaddon/pimd/inet.c, revision 1.1

1.1     ! misho       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>