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