Annotation of embedaddon/pimdd/inet.c, revision 1.1.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>