1*df930be7Sderaadt /* $NetBSD: inet.c,v 1.3 1995/10/09 03:51:42 thorpej Exp $ */ 2*df930be7Sderaadt 3*df930be7Sderaadt /* 4*df930be7Sderaadt * The mrouted program is covered by the license in the accompanying file 5*df930be7Sderaadt * named "LICENSE". Use of the mrouted program represents acceptance of 6*df930be7Sderaadt * the terms and conditions listed in that file. 7*df930be7Sderaadt * 8*df930be7Sderaadt * The mrouted program is COPYRIGHT 1989 by The Board of Trustees of 9*df930be7Sderaadt * Leland Stanford Junior University. 10*df930be7Sderaadt */ 11*df930be7Sderaadt 12*df930be7Sderaadt 13*df930be7Sderaadt #include "defs.h" 14*df930be7Sderaadt 15*df930be7Sderaadt 16*df930be7Sderaadt /* 17*df930be7Sderaadt * Exported variables. 18*df930be7Sderaadt */ 19*df930be7Sderaadt char s1[19]; /* buffers to hold the string representations */ 20*df930be7Sderaadt char s2[19]; /* of IP addresses, to be passed to inet_fmt() */ 21*df930be7Sderaadt char s3[19]; /* or inet_fmts(). */ 22*df930be7Sderaadt char s4[19]; 23*df930be7Sderaadt 24*df930be7Sderaadt 25*df930be7Sderaadt /* 26*df930be7Sderaadt * Verify that a given IP address is credible as a host address. 27*df930be7Sderaadt * (Without a mask, cannot detect addresses of the form {subnet,0} or 28*df930be7Sderaadt * {subnet,-1}.) 29*df930be7Sderaadt */ 30*df930be7Sderaadt int inet_valid_host(naddr) 31*df930be7Sderaadt u_int32_t naddr; 32*df930be7Sderaadt { 33*df930be7Sderaadt register u_int32_t addr; 34*df930be7Sderaadt 35*df930be7Sderaadt addr = ntohl(naddr); 36*df930be7Sderaadt 37*df930be7Sderaadt return (!(IN_MULTICAST(addr) || 38*df930be7Sderaadt IN_BADCLASS (addr) || 39*df930be7Sderaadt (addr & 0xff000000) == 0)); 40*df930be7Sderaadt } 41*df930be7Sderaadt 42*df930be7Sderaadt 43*df930be7Sderaadt /* 44*df930be7Sderaadt * Verify that a given subnet number and mask pair are credible. 45*df930be7Sderaadt * 46*df930be7Sderaadt * With CIDR, almost any subnet and mask are credible. mrouted still 47*df930be7Sderaadt * can't handle aggregated class A's, so we still check that, but 48*df930be7Sderaadt * otherwise the only requirements are that the subnet address is 49*df930be7Sderaadt * within the [ABC] range and that the host bits of the subnet 50*df930be7Sderaadt * are all 0. 51*df930be7Sderaadt */ 52*df930be7Sderaadt int inet_valid_subnet(nsubnet, nmask) 53*df930be7Sderaadt u_int32_t nsubnet, nmask; 54*df930be7Sderaadt { 55*df930be7Sderaadt register u_int32_t subnet, mask; 56*df930be7Sderaadt 57*df930be7Sderaadt subnet = ntohl(nsubnet); 58*df930be7Sderaadt mask = ntohl(nmask); 59*df930be7Sderaadt 60*df930be7Sderaadt if ((subnet & mask) != subnet) return (FALSE); 61*df930be7Sderaadt 62*df930be7Sderaadt if (subnet == 0 && mask == 0) 63*df930be7Sderaadt return (TRUE); 64*df930be7Sderaadt 65*df930be7Sderaadt if (IN_CLASSA(subnet)) { 66*df930be7Sderaadt if (mask < 0xff000000 || 67*df930be7Sderaadt (subnet & 0xff000000) == 0x7f000000) return (FALSE); 68*df930be7Sderaadt } 69*df930be7Sderaadt else if (IN_CLASSD(subnet) || IN_BADCLASS(subnet)) { 70*df930be7Sderaadt /* Above Class C address space */ 71*df930be7Sderaadt return (FALSE); 72*df930be7Sderaadt } 73*df930be7Sderaadt else if (subnet & ~mask) { 74*df930be7Sderaadt /* Host bits are set in the subnet */ 75*df930be7Sderaadt return (FALSE); 76*df930be7Sderaadt } 77*df930be7Sderaadt 78*df930be7Sderaadt return (TRUE); 79*df930be7Sderaadt } 80*df930be7Sderaadt 81*df930be7Sderaadt 82*df930be7Sderaadt /* 83*df930be7Sderaadt * Convert an IP address in u_long (network) format into a printable string. 84*df930be7Sderaadt */ 85*df930be7Sderaadt char *inet_fmt(addr, s) 86*df930be7Sderaadt u_int32_t addr; 87*df930be7Sderaadt char *s; 88*df930be7Sderaadt { 89*df930be7Sderaadt register u_char *a; 90*df930be7Sderaadt 91*df930be7Sderaadt a = (u_char *)&addr; 92*df930be7Sderaadt sprintf(s, "%u.%u.%u.%u", a[0], a[1], a[2], a[3]); 93*df930be7Sderaadt return (s); 94*df930be7Sderaadt } 95*df930be7Sderaadt 96*df930be7Sderaadt 97*df930be7Sderaadt /* 98*df930be7Sderaadt * Convert an IP subnet number in u_long (network) format into a printable 99*df930be7Sderaadt * string including the netmask as a number of bits. 100*df930be7Sderaadt */ 101*df930be7Sderaadt char *inet_fmts(addr, mask, s) 102*df930be7Sderaadt u_int32_t addr, mask; 103*df930be7Sderaadt char *s; 104*df930be7Sderaadt { 105*df930be7Sderaadt register u_char *a, *m; 106*df930be7Sderaadt int bits; 107*df930be7Sderaadt 108*df930be7Sderaadt if ((addr == 0) && (mask == 0)) { 109*df930be7Sderaadt sprintf(s, "default"); 110*df930be7Sderaadt return (s); 111*df930be7Sderaadt } 112*df930be7Sderaadt a = (u_char *)&addr; 113*df930be7Sderaadt m = (u_char *)&mask; 114*df930be7Sderaadt bits = 33 - ffs(ntohl(mask)); 115*df930be7Sderaadt 116*df930be7Sderaadt if (m[3] != 0) sprintf(s, "%u.%u.%u.%u/%d", a[0], a[1], a[2], a[3], 117*df930be7Sderaadt bits); 118*df930be7Sderaadt else if (m[2] != 0) sprintf(s, "%u.%u.%u/%d", a[0], a[1], a[2], bits); 119*df930be7Sderaadt else if (m[1] != 0) sprintf(s, "%u.%u/%d", a[0], a[1], bits); 120*df930be7Sderaadt else sprintf(s, "%u/%d", a[0], bits); 121*df930be7Sderaadt 122*df930be7Sderaadt return (s); 123*df930be7Sderaadt } 124*df930be7Sderaadt 125*df930be7Sderaadt /* 126*df930be7Sderaadt * Convert the printable string representation of an IP address into the 127*df930be7Sderaadt * u_long (network) format. Return 0xffffffff on error. (To detect the 128*df930be7Sderaadt * legal address with that value, you must explicitly compare the string 129*df930be7Sderaadt * with "255.255.255.255".) 130*df930be7Sderaadt */ 131*df930be7Sderaadt u_int32_t inet_parse(s) 132*df930be7Sderaadt char *s; 133*df930be7Sderaadt { 134*df930be7Sderaadt u_int32_t a = 0; 135*df930be7Sderaadt u_int a0, a1, a2, a3; 136*df930be7Sderaadt char c; 137*df930be7Sderaadt 138*df930be7Sderaadt if (sscanf(s, "%u.%u.%u.%u%c", &a0, &a1, &a2, &a3, &c) != 4 || 139*df930be7Sderaadt a0 > 255 || a1 > 255 || a2 > 255 || a3 > 255) 140*df930be7Sderaadt return (0xffffffff); 141*df930be7Sderaadt 142*df930be7Sderaadt ((u_char *)&a)[0] = a0; 143*df930be7Sderaadt ((u_char *)&a)[1] = a1; 144*df930be7Sderaadt ((u_char *)&a)[2] = a2; 145*df930be7Sderaadt ((u_char *)&a)[3] = a3; 146*df930be7Sderaadt 147*df930be7Sderaadt return (a); 148*df930be7Sderaadt } 149*df930be7Sderaadt 150*df930be7Sderaadt 151*df930be7Sderaadt /* 152*df930be7Sderaadt * inet_cksum extracted from: 153*df930be7Sderaadt * P I N G . C 154*df930be7Sderaadt * 155*df930be7Sderaadt * Author - 156*df930be7Sderaadt * Mike Muuss 157*df930be7Sderaadt * U. S. Army Ballistic Research Laboratory 158*df930be7Sderaadt * December, 1983 159*df930be7Sderaadt * Modified at Uc Berkeley 160*df930be7Sderaadt * 161*df930be7Sderaadt * (ping.c) Status - 162*df930be7Sderaadt * Public Domain. Distribution Unlimited. 163*df930be7Sderaadt * 164*df930be7Sderaadt * I N _ C K S U M 165*df930be7Sderaadt * 166*df930be7Sderaadt * Checksum routine for Internet Protocol family headers (C Version) 167*df930be7Sderaadt * 168*df930be7Sderaadt */ 169*df930be7Sderaadt int inet_cksum(addr, len) 170*df930be7Sderaadt u_short *addr; 171*df930be7Sderaadt u_int len; 172*df930be7Sderaadt { 173*df930be7Sderaadt register int nleft = (int)len; 174*df930be7Sderaadt register u_short *w = addr; 175*df930be7Sderaadt u_short answer = 0; 176*df930be7Sderaadt register int sum = 0; 177*df930be7Sderaadt 178*df930be7Sderaadt /* 179*df930be7Sderaadt * Our algorithm is simple, using a 32 bit accumulator (sum), 180*df930be7Sderaadt * we add sequential 16 bit words to it, and at the end, fold 181*df930be7Sderaadt * back all the carry bits from the top 16 bits into the lower 182*df930be7Sderaadt * 16 bits. 183*df930be7Sderaadt */ 184*df930be7Sderaadt while( nleft > 1 ) { 185*df930be7Sderaadt sum += *w++; 186*df930be7Sderaadt nleft -= 2; 187*df930be7Sderaadt } 188*df930be7Sderaadt 189*df930be7Sderaadt /* mop up an odd byte, if necessary */ 190*df930be7Sderaadt if( nleft == 1 ) { 191*df930be7Sderaadt *(u_char *) (&answer) = *(u_char *)w ; 192*df930be7Sderaadt sum += answer; 193*df930be7Sderaadt } 194*df930be7Sderaadt 195*df930be7Sderaadt /* 196*df930be7Sderaadt * add back carry outs from top 16 bits to low 16 bits 197*df930be7Sderaadt */ 198*df930be7Sderaadt sum = (sum >> 16) + (sum & 0xffff); /* add hi 16 to low 16 */ 199*df930be7Sderaadt sum += (sum >> 16); /* add carry */ 200*df930be7Sderaadt answer = ~sum; /* truncate to 16 bits */ 201*df930be7Sderaadt return (answer); 202*df930be7Sderaadt } 203