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