Annotation of embedaddon/pimdd/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[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>