| line | stmt | bran | cond | sub | pod | time | code | 
| 1 |  |  |  |  |  |  | /* | 
| 2 |  |  |  |  |  |  | functions.c - Core functions for Net::IP::XS. | 
| 3 |  |  |  |  |  |  |  | 
| 4 |  |  |  |  |  |  | Copyright (C) 2010-2018 Tom Harrison | 
| 5 |  |  |  |  |  |  | Original inet_pton4, inet_pton6 are Copyright (C) 2006 Free Software | 
| 6 |  |  |  |  |  |  | Foundation. | 
| 7 |  |  |  |  |  |  | Original interface, and the auth and ip_auth functions, are Copyright | 
| 8 |  |  |  |  |  |  | (C) 1999-2002 RIPE NCC. | 
| 9 |  |  |  |  |  |  |  | 
| 10 |  |  |  |  |  |  | This program is free software; you can redistribute it and/or modify | 
| 11 |  |  |  |  |  |  | it under the terms of the GNU General Public License as published by | 
| 12 |  |  |  |  |  |  | the Free Software Foundation; either version 2 of the License, or | 
| 13 |  |  |  |  |  |  | (at your option) any later version. | 
| 14 |  |  |  |  |  |  |  | 
| 15 |  |  |  |  |  |  | This program is distributed in the hope that it will be useful, | 
| 16 |  |  |  |  |  |  | but WITHOUT ANY WARRANTY; without even the implied warranty of | 
| 17 |  |  |  |  |  |  | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
| 18 |  |  |  |  |  |  | GNU General Public License for more details. | 
| 19 |  |  |  |  |  |  |  | 
| 20 |  |  |  |  |  |  | You should have received a copy of the GNU General Public License along | 
| 21 |  |  |  |  |  |  | with this program; if not, write to the Free Software Foundation, Inc., | 
| 22 |  |  |  |  |  |  | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | 
| 23 |  |  |  |  |  |  | */ | 
| 24 |  |  |  |  |  |  |  | 
| 25 |  |  |  |  |  |  | #include "EXTERN.h" | 
| 26 |  |  |  |  |  |  | #include "perl.h" | 
| 27 |  |  |  |  |  |  | #include "XSUB.h" | 
| 28 |  |  |  |  |  |  |  | 
| 29 |  |  |  |  |  |  | #include "functions.h" | 
| 30 |  |  |  |  |  |  | #include "inet_pton.h" | 
| 31 |  |  |  |  |  |  |  | 
| 32 |  |  |  |  |  |  | #ifdef __cplusplus | 
| 33 |  |  |  |  |  |  | extern "C" { | 
| 34 |  |  |  |  |  |  | #endif | 
| 35 |  |  |  |  |  |  |  | 
| 36 |  |  |  |  |  |  | /* Global error string and error number (tied to $Net::IP::XS::ERROR | 
| 37 |  |  |  |  |  |  | * and $Net::IP::XS::ERRNO). */ | 
| 38 |  |  |  |  |  |  | static char netip_Error[512]; | 
| 39 |  |  |  |  |  |  | static int  netip_Errno; | 
| 40 |  |  |  |  |  |  |  | 
| 41 |  |  |  |  |  |  | /** | 
| 42 |  |  |  |  |  |  | * NI_hv_get_pv(): get string value from hashref. | 
| 43 |  |  |  |  |  |  | * @object: reference to a hashref. | 
| 44 |  |  |  |  |  |  | * @key: hashref key as a string. | 
| 45 |  |  |  |  |  |  | * @keylen: the length of the hashref key. | 
| 46 |  |  |  |  |  |  | * | 
| 47 |  |  |  |  |  |  | * Returns a pointer to the beginning of the string to which @key is | 
| 48 |  |  |  |  |  |  | * mapped in the hashref. If @key does not exist in the hashref, | 
| 49 |  |  |  |  |  |  | * returns 0. | 
| 50 |  |  |  |  |  |  | */ | 
| 51 |  |  |  |  |  |  | const char* | 
| 52 | 2814 |  |  |  |  |  | NI_hv_get_pv(SV *object, const char *key, int keylen) | 
| 53 |  |  |  |  |  |  | { | 
| 54 |  |  |  |  |  |  | SV **ref; | 
| 55 |  |  |  |  |  |  |  | 
| 56 | 2814 |  |  |  |  |  | ref = hv_fetch((HV*) SvRV(object), key, keylen, 0); | 
| 57 | 2814 | 100 |  |  |  |  | if (!ref) { | 
| 58 | 87 |  |  |  |  |  | return NULL; | 
| 59 |  |  |  |  |  |  | } | 
| 60 | 2727 | 50 |  |  |  |  | return SvPV(*ref, PL_na); | 
| 61 |  |  |  |  |  |  | } | 
| 62 |  |  |  |  |  |  |  | 
| 63 |  |  |  |  |  |  | /** | 
| 64 |  |  |  |  |  |  | * NI_hv_get_iv(): get integer value from hashref. | 
| 65 |  |  |  |  |  |  | * @object: reference to a hashref. | 
| 66 |  |  |  |  |  |  | * @key: hashref key as a string. | 
| 67 |  |  |  |  |  |  | * @keylen: the length of the hashref key. | 
| 68 |  |  |  |  |  |  | * | 
| 69 |  |  |  |  |  |  | * Returns the integer to which @key is mapped in the hashref.  If | 
| 70 |  |  |  |  |  |  | * @key does not exist in the hashref, returns 0. | 
| 71 |  |  |  |  |  |  | */ | 
| 72 |  |  |  |  |  |  | int | 
| 73 | 1916 |  |  |  |  |  | NI_hv_get_iv(SV *object, const char *key, int keylen) | 
| 74 |  |  |  |  |  |  | { | 
| 75 |  |  |  |  |  |  | SV **ref; | 
| 76 |  |  |  |  |  |  |  | 
| 77 | 1916 |  |  |  |  |  | ref = hv_fetch((HV*) SvRV(object), key, keylen, 0); | 
| 78 | 1916 | 100 |  |  |  |  | if (!ref) { | 
| 79 | 20 |  |  |  |  |  | return -1; | 
| 80 |  |  |  |  |  |  | } | 
| 81 | 1896 | 100 |  |  |  |  | return SvIV(*ref); | 
| 82 |  |  |  |  |  |  | } | 
| 83 |  |  |  |  |  |  |  | 
| 84 |  |  |  |  |  |  | /** | 
| 85 |  |  |  |  |  |  | * NI_hv_get_uv(): get unsigned integer value from hashref. | 
| 86 |  |  |  |  |  |  | * @object: reference to a hashref. | 
| 87 |  |  |  |  |  |  | * @key: hashref key as a string. | 
| 88 |  |  |  |  |  |  | * @keylen: the length of the hashref key. | 
| 89 |  |  |  |  |  |  | * | 
| 90 |  |  |  |  |  |  | * Returns the unsigned integer to which @key is mapped in the | 
| 91 |  |  |  |  |  |  | * hashref. If @key does not exist in the hashref, returns 0. | 
| 92 |  |  |  |  |  |  | */ | 
| 93 |  |  |  |  |  |  | unsigned int | 
| 94 | 928 |  |  |  |  |  | NI_hv_get_uv(SV *object, const char *key, int keylen) | 
| 95 |  |  |  |  |  |  | { | 
| 96 |  |  |  |  |  |  | SV **ref; | 
| 97 |  |  |  |  |  |  |  | 
| 98 | 928 |  |  |  |  |  | ref = hv_fetch((HV*) SvRV(object), key, keylen, 0); | 
| 99 | 928 | 100 |  |  |  |  | if (!ref) { | 
| 100 | 2 |  |  |  |  |  | return -1; | 
| 101 |  |  |  |  |  |  | } | 
| 102 | 926 | 50 |  |  |  |  | return SvUV(*ref); | 
| 103 |  |  |  |  |  |  | } | 
| 104 |  |  |  |  |  |  |  | 
| 105 |  |  |  |  |  |  | /** | 
| 106 |  |  |  |  |  |  | * NI_set_Errno() - set the global error number. | 
| 107 |  |  |  |  |  |  | * @Errno: the new error number. | 
| 108 |  |  |  |  |  |  | */ | 
| 109 |  |  |  |  |  |  | void | 
| 110 | 3 |  |  |  |  |  | NI_set_Errno(int Errno) | 
| 111 |  |  |  |  |  |  | { | 
| 112 | 3 |  |  |  |  |  | netip_Errno = Errno; | 
| 113 | 3 |  |  |  |  |  | } | 
| 114 |  |  |  |  |  |  |  | 
| 115 |  |  |  |  |  |  | /** | 
| 116 |  |  |  |  |  |  | * NI_get_Errno() - get the global error number. | 
| 117 |  |  |  |  |  |  | */ | 
| 118 |  |  |  |  |  |  | int | 
| 119 | 76 |  |  |  |  |  | NI_get_Errno(void) | 
| 120 |  |  |  |  |  |  | { | 
| 121 | 76 |  |  |  |  |  | return netip_Errno; | 
| 122 |  |  |  |  |  |  | } | 
| 123 |  |  |  |  |  |  |  | 
| 124 |  |  |  |  |  |  | /** | 
| 125 |  |  |  |  |  |  | * NI_set_Error() - set the global error string. | 
| 126 |  |  |  |  |  |  | * @Error: the new error string. | 
| 127 |  |  |  |  |  |  | * | 
| 128 |  |  |  |  |  |  | * If the error string is more than 512 characters in length | 
| 129 |  |  |  |  |  |  | * (including the ending null), only the first 511 characters will be | 
| 130 |  |  |  |  |  |  | * used (with a null as the 512th character). | 
| 131 |  |  |  |  |  |  | */ | 
| 132 |  |  |  |  |  |  | void | 
| 133 | 3 |  |  |  |  |  | NI_set_Error(const char *Error) | 
| 134 |  |  |  |  |  |  | { | 
| 135 |  |  |  |  |  |  | int len; | 
| 136 |  |  |  |  |  |  |  | 
| 137 | 3 |  |  |  |  |  | len = strlen(Error); | 
| 138 | 3 | 100 |  |  |  |  | if (len > 511) { | 
| 139 | 1 |  |  |  |  |  | len = 511; | 
| 140 |  |  |  |  |  |  | } | 
| 141 | 3 |  |  |  |  |  | memcpy(netip_Error, Error, len); | 
| 142 | 3 |  |  |  |  |  | netip_Error[len] = '\0'; | 
| 143 | 3 |  |  |  |  |  | } | 
| 144 |  |  |  |  |  |  |  | 
| 145 |  |  |  |  |  |  | /** | 
| 146 |  |  |  |  |  |  | * NI_get_Error() - get the global error string. | 
| 147 |  |  |  |  |  |  | */ | 
| 148 |  |  |  |  |  |  | const char* | 
| 149 | 73 |  |  |  |  |  | NI_get_Error(void) | 
| 150 |  |  |  |  |  |  | { | 
| 151 | 73 |  |  |  |  |  | return (const char *) netip_Error; | 
| 152 |  |  |  |  |  |  | } | 
| 153 |  |  |  |  |  |  |  | 
| 154 |  |  |  |  |  |  | /** | 
| 155 |  |  |  |  |  |  | * NI_set_Error_Errno() - set the global error number and string. | 
| 156 |  |  |  |  |  |  | * @Errno: the new error number. | 
| 157 |  |  |  |  |  |  | * @Error: the new error string (can include printf modifiers). | 
| 158 |  |  |  |  |  |  | * @...: format arguments to substitute into @Error. | 
| 159 |  |  |  |  |  |  | */ | 
| 160 |  |  |  |  |  |  | void | 
| 161 | 442 |  |  |  |  |  | NI_set_Error_Errno(int Errno, const char *Error, ...) | 
| 162 |  |  |  |  |  |  | { | 
| 163 |  |  |  |  |  |  | va_list args; | 
| 164 |  |  |  |  |  |  |  | 
| 165 | 442 |  |  |  |  |  | va_start(args, Error); | 
| 166 | 442 |  |  |  |  |  | vsnprintf(netip_Error, 512, Error, args); | 
| 167 | 442 |  |  |  |  |  | netip_Error[511] = '\0'; | 
| 168 | 442 |  |  |  |  |  | netip_Errno = Errno; | 
| 169 | 442 |  |  |  |  |  | va_end(args); | 
| 170 | 442 |  |  |  |  |  | } | 
| 171 |  |  |  |  |  |  |  | 
| 172 |  |  |  |  |  |  | /** | 
| 173 |  |  |  |  |  |  | * NI_ip_uchars_to_n128(): make N128 integer from array of chars. | 
| 174 |  |  |  |  |  |  | * @uchars: array of at least 16 unsigned chars. | 
| 175 |  |  |  |  |  |  | * @buf: N128 integer buffer. | 
| 176 |  |  |  |  |  |  | */ | 
| 177 |  |  |  |  |  |  | void | 
| 178 | 52 |  |  |  |  |  | NI_ip_uchars_to_n128(unsigned char uchars[16], n128_t *num) | 
| 179 |  |  |  |  |  |  | { | 
| 180 |  |  |  |  |  |  | int i; | 
| 181 |  |  |  |  |  |  | int j; | 
| 182 |  |  |  |  |  |  | unsigned long k; | 
| 183 |  |  |  |  |  |  |  | 
| 184 | 260 | 100 |  |  |  |  | for (i = 0; i < 4; i++) { | 
| 185 | 208 |  |  |  |  |  | j = i * 4; | 
| 186 | 416 |  |  |  |  |  | k = (  (uchars[j + 3]) | 
| 187 | 208 |  |  |  |  |  | | (uchars[j + 2] << 8) | 
| 188 | 208 |  |  |  |  |  | | (uchars[j + 1] << 16) | 
| 189 | 208 |  |  |  |  |  | | (uchars[j]     << 24)); | 
| 190 | 208 |  |  |  |  |  | num->nums[i] = k; | 
| 191 |  |  |  |  |  |  | } | 
| 192 | 52 |  |  |  |  |  | } | 
| 193 |  |  |  |  |  |  |  | 
| 194 |  |  |  |  |  |  | /** | 
| 195 |  |  |  |  |  |  | * NI_ip_uchars_to_ulong(): get whole integer from array of chars. | 
| 196 |  |  |  |  |  |  | * @uchars: array of at least 4 unsigned chars. | 
| 197 |  |  |  |  |  |  | */ | 
| 198 |  |  |  |  |  |  | unsigned long | 
| 199 | 1043 |  |  |  |  |  | NI_ip_uchars_to_ulong(unsigned char uchars[4]) | 
| 200 |  |  |  |  |  |  | { | 
| 201 |  |  |  |  |  |  | return | 
| 202 | 1043 |  |  |  |  |  | (uchars[3] | 
| 203 | 1043 |  |  |  |  |  | | (uchars[2] << 8) | 
| 204 | 1043 |  |  |  |  |  | | (uchars[1] << 16) | 
| 205 | 1043 |  |  |  |  |  | | (uchars[0] << 24)); | 
| 206 |  |  |  |  |  |  | } | 
| 207 |  |  |  |  |  |  |  | 
| 208 |  |  |  |  |  |  | /** | 
| 209 |  |  |  |  |  |  | * NI_hdtoi(): convert hexadecimal character to integer. | 
| 210 |  |  |  |  |  |  | * @c: hexadecimal character. | 
| 211 |  |  |  |  |  |  | * | 
| 212 |  |  |  |  |  |  | * Returns -1 when the character is not a valid hexadecimal character. | 
| 213 |  |  |  |  |  |  | */ | 
| 214 |  |  |  |  |  |  | int | 
| 215 | 27606 |  |  |  |  |  | NI_hdtoi(char c) | 
| 216 |  |  |  |  |  |  | { | 
| 217 | 27606 |  |  |  |  |  | c = tolower(c); | 
| 218 |  |  |  |  |  |  |  | 
| 219 |  |  |  |  |  |  | return | 
| 220 | 55212 |  |  |  |  |  | (isdigit(c))               ? c - '0' | 
| 221 | 58487 | 100 |  |  |  |  | : ((c >= 'a') && (c <= 'f')) ? 10 + (c - 'a') | 
|  |  | 50 |  |  |  |  |  | 
| 222 | 30881 | 100 |  |  |  |  | : -1; | 
| 223 |  |  |  |  |  |  | } | 
| 224 |  |  |  |  |  |  |  | 
| 225 |  |  |  |  |  |  | /** | 
| 226 |  |  |  |  |  |  | * NI_trailing_zeroes(): get trailing zeroes from number treated as binary. | 
| 227 |  |  |  |  |  |  | * @n: the number. | 
| 228 |  |  |  |  |  |  | */ | 
| 229 |  |  |  |  |  |  | int | 
| 230 | 5561 |  |  |  |  |  | NI_trailing_zeroes(unsigned long n) | 
| 231 |  |  |  |  |  |  | { | 
| 232 |  |  |  |  |  |  | int c; | 
| 233 |  |  |  |  |  |  |  | 
| 234 | 5561 | 100 |  |  |  |  | if (!n) { | 
| 235 | 53 |  |  |  |  |  | return CHAR_BIT * sizeof(n); | 
| 236 |  |  |  |  |  |  | } | 
| 237 |  |  |  |  |  |  |  | 
| 238 | 5508 |  |  |  |  |  | n = (n ^ (n - 1)) >> 1; | 
| 239 | 109846 | 100 |  |  |  |  | for (c = 0; n; c++) { | 
| 240 | 104338 |  |  |  |  |  | n >>= 1; | 
| 241 |  |  |  |  |  |  | } | 
| 242 |  |  |  |  |  |  |  | 
| 243 | 5508 |  |  |  |  |  | return c; | 
| 244 |  |  |  |  |  |  | } | 
| 245 |  |  |  |  |  |  |  | 
| 246 |  |  |  |  |  |  | /** | 
| 247 |  |  |  |  |  |  | * NI_bintoint(): convert bitstring to integer. | 
| 248 |  |  |  |  |  |  | * @bitstr: the bitstring. | 
| 249 |  |  |  |  |  |  | * @len: the number of characters to use from the bitstring. | 
| 250 |  |  |  |  |  |  | */ | 
| 251 |  |  |  |  |  |  | unsigned long | 
| 252 | 66129 |  |  |  |  |  | NI_bintoint(const char *bitstr, int len) | 
| 253 |  |  |  |  |  |  | { | 
| 254 |  |  |  |  |  |  | unsigned long res; | 
| 255 |  |  |  |  |  |  | int i; | 
| 256 |  |  |  |  |  |  | int help; | 
| 257 |  |  |  |  |  |  |  | 
| 258 | 66129 |  |  |  |  |  | res  = 0; | 
| 259 | 66129 |  |  |  |  |  | help = len - 1; | 
| 260 |  |  |  |  |  |  |  | 
| 261 | 2182099 | 100 |  |  |  |  | for (i = 0; i < len; i++) { | 
| 262 | 2115970 |  |  |  |  |  | res += (((unsigned long) (bitstr[i] == '1')) << (help - i)); | 
| 263 |  |  |  |  |  |  | } | 
| 264 |  |  |  |  |  |  |  | 
| 265 | 66129 |  |  |  |  |  | return res; | 
| 266 |  |  |  |  |  |  | } | 
| 267 |  |  |  |  |  |  |  | 
| 268 |  |  |  |  |  |  | /** | 
| 269 |  |  |  |  |  |  | * NI_bintoint_nonzero(): convert bitstring to integer. | 
| 270 |  |  |  |  |  |  | * @bitstr: the bitstring. | 
| 271 |  |  |  |  |  |  | * @len: the number of characters to use from the bitstring. | 
| 272 |  |  |  |  |  |  | * | 
| 273 |  |  |  |  |  |  | * This function treats all non-zero characters in the bitstring as | 
| 274 |  |  |  |  |  |  | * if they were '1', whereas NI_bintoint() treats all non-one | 
| 275 |  |  |  |  |  |  | * characters as if they were '0'. | 
| 276 |  |  |  |  |  |  | */ | 
| 277 |  |  |  |  |  |  | unsigned long | 
| 278 | 7 |  |  |  |  |  | NI_bintoint_nonzero(const char *bitstr, int len) | 
| 279 |  |  |  |  |  |  | { | 
| 280 |  |  |  |  |  |  | unsigned long res; | 
| 281 |  |  |  |  |  |  | int i; | 
| 282 |  |  |  |  |  |  | int help; | 
| 283 |  |  |  |  |  |  |  | 
| 284 | 7 |  |  |  |  |  | res  = 0; | 
| 285 | 7 |  |  |  |  |  | help = len - 1; | 
| 286 |  |  |  |  |  |  |  | 
| 287 | 88 | 100 |  |  |  |  | for (i = 0; i < len; i++) { | 
| 288 | 81 |  |  |  |  |  | res += (((unsigned long) (bitstr[i] != '0')) << (help - i)); | 
| 289 |  |  |  |  |  |  | } | 
| 290 |  |  |  |  |  |  |  | 
| 291 | 7 |  |  |  |  |  | return res; | 
| 292 |  |  |  |  |  |  | } | 
| 293 |  |  |  |  |  |  |  | 
| 294 |  |  |  |  |  |  | /** | 
| 295 |  |  |  |  |  |  | * NI_iplengths() - return length in bits of the version of IP address. | 
| 296 |  |  |  |  |  |  | * @version: IP version as integer (either 4 or 6). | 
| 297 |  |  |  |  |  |  | * | 
| 298 |  |  |  |  |  |  | * Returns 0 if @version is an invalid value. | 
| 299 |  |  |  |  |  |  | */ | 
| 300 |  |  |  |  |  |  | int | 
| 301 | 19329 |  |  |  |  |  | NI_iplengths(int version) | 
| 302 |  |  |  |  |  |  | { | 
| 303 | 19329 |  |  |  |  |  | switch (version) { | 
| 304 | 1881 |  |  |  |  |  | case 4:  return 32; | 
| 305 | 17439 |  |  |  |  |  | case 6:  return 128; | 
| 306 | 9 |  |  |  |  |  | default: return 0; | 
| 307 |  |  |  |  |  |  | }; | 
| 308 |  |  |  |  |  |  | } | 
| 309 |  |  |  |  |  |  |  | 
| 310 |  |  |  |  |  |  | /** | 
| 311 |  |  |  |  |  |  | * NI_ip_n128tobin(): make bitstring from N128 integer. | 
| 312 |  |  |  |  |  |  | * @num: N128 integer. | 
| 313 |  |  |  |  |  |  | * @len: the number of bits to write to the buffer. | 
| 314 |  |  |  |  |  |  | * @buf: the bitstring buffer. | 
| 315 |  |  |  |  |  |  | * | 
| 316 |  |  |  |  |  |  | * This does not null-terminate the buffer. | 
| 317 |  |  |  |  |  |  | */ | 
| 318 |  |  |  |  |  |  | void | 
| 319 | 16008 |  |  |  |  |  | NI_ip_n128tobin(n128_t *num, int len, char *buf) | 
| 320 |  |  |  |  |  |  | { | 
| 321 |  |  |  |  |  |  | int i; | 
| 322 |  |  |  |  |  |  |  | 
| 323 | 16008 | 100 |  |  |  |  | if (len == 0) { | 
| 324 | 3 |  |  |  |  |  | return; | 
| 325 |  |  |  |  |  |  | } | 
| 326 |  |  |  |  |  |  |  | 
| 327 | 2063800 | 100 |  |  |  |  | for (i = 0; i < len; i++) { | 
| 328 | 2047795 | 100 |  |  |  |  | buf[len - 1 - i] = (n128_tstbit(num, i) ? '1' : '0'); | 
| 329 |  |  |  |  |  |  | } | 
| 330 |  |  |  |  |  |  | } | 
| 331 |  |  |  |  |  |  |  | 
| 332 |  |  |  |  |  |  | /** | 
| 333 |  |  |  |  |  |  | * NI_ip_inttobin_str() - make bitstring from IP address integer. | 
| 334 |  |  |  |  |  |  | * @ip_int_str: the IP address integer as a string. | 
| 335 |  |  |  |  |  |  | * @version: the IP address version. | 
| 336 |  |  |  |  |  |  | * @buf: the bitstring buffer. | 
| 337 |  |  |  |  |  |  | * | 
| 338 |  |  |  |  |  |  | * Returns 1 if the buffer is able to be populated properly. Returns 0 | 
| 339 |  |  |  |  |  |  | * if the IP version is invalid. This function null-terminates the | 
| 340 |  |  |  |  |  |  | * buffer. The buffer must have at least 129 characters' capacity. | 
| 341 |  |  |  |  |  |  | */ | 
| 342 |  |  |  |  |  |  | int | 
| 343 | 13 |  |  |  |  |  | NI_ip_inttobin_str(const char *ip_int_str, int version, char *buf) | 
| 344 |  |  |  |  |  |  | { | 
| 345 |  |  |  |  |  |  | n128_t num; | 
| 346 |  |  |  |  |  |  | int i; | 
| 347 |  |  |  |  |  |  | int len; | 
| 348 |  |  |  |  |  |  | int res; | 
| 349 |  |  |  |  |  |  |  | 
| 350 | 13 | 100 |  |  |  |  | if (!version) { | 
| 351 | 1 |  |  |  |  |  | NI_set_Error_Errno(101, "Cannot determine IP " | 
| 352 |  |  |  |  |  |  | "version for %s", ip_int_str); | 
| 353 | 1 |  |  |  |  |  | return 0; | 
| 354 |  |  |  |  |  |  | } | 
| 355 |  |  |  |  |  |  |  | 
| 356 | 12 |  |  |  |  |  | len = strlen(ip_int_str); | 
| 357 | 165 | 100 |  |  |  |  | for (i = 0; i < len; i++) { | 
| 358 | 155 | 100 |  |  |  |  | if (!isdigit(ip_int_str[i])) { | 
| 359 | 2 | 100 |  |  |  |  | memset(buf, '0', (version == 4) ? 32 : 128); | 
| 360 | 2 | 100 |  |  |  |  | buf[(version == 4) ? 32 : 128] = '\0'; | 
| 361 | 2 |  |  |  |  |  | return 1; | 
| 362 |  |  |  |  |  |  | } | 
| 363 |  |  |  |  |  |  | } | 
| 364 |  |  |  |  |  |  |  | 
| 365 | 10 |  |  |  |  |  | n128_set_ui(&num, 0); | 
| 366 | 10 |  |  |  |  |  | res = n128_set_str_decimal(&num, ip_int_str, strlen(ip_int_str)); | 
| 367 | 10 | 100 |  |  |  |  | if (!res) { | 
| 368 | 1 |  |  |  |  |  | return 0; | 
| 369 |  |  |  |  |  |  | } | 
| 370 |  |  |  |  |  |  |  | 
| 371 | 9 |  |  |  |  |  | n128_print_bin(&num, buf, (version == 4)); | 
| 372 |  |  |  |  |  |  |  | 
| 373 | 13 |  |  |  |  |  | return 1; | 
| 374 |  |  |  |  |  |  | } | 
| 375 |  |  |  |  |  |  |  | 
| 376 |  |  |  |  |  |  | /** | 
| 377 |  |  |  |  |  |  | * NI_ip_bintoint_str(): convert bitstring to integer string. | 
| 378 |  |  |  |  |  |  | * @bitstr: the bitstring. | 
| 379 |  |  |  |  |  |  | * @buf: the integer string buffer. | 
| 380 |  |  |  |  |  |  | */ | 
| 381 |  |  |  |  |  |  | int | 
| 382 | 10 |  |  |  |  |  | NI_ip_bintoint_str(const char *bitstr, char *buf) | 
| 383 |  |  |  |  |  |  | { | 
| 384 |  |  |  |  |  |  | unsigned long num_ulong; | 
| 385 |  |  |  |  |  |  | n128_t num_n128; | 
| 386 |  |  |  |  |  |  | int len; | 
| 387 |  |  |  |  |  |  |  | 
| 388 | 10 |  |  |  |  |  | len = strlen(bitstr); | 
| 389 |  |  |  |  |  |  |  | 
| 390 | 10 | 100 |  |  |  |  | if (len <= 32) { | 
| 391 | 7 |  |  |  |  |  | num_ulong = NI_bintoint_nonzero(bitstr, len); | 
| 392 | 7 |  |  |  |  |  | sprintf(buf, "%lu", num_ulong); | 
| 393 | 7 |  |  |  |  |  | return 1; | 
| 394 |  |  |  |  |  |  | } | 
| 395 |  |  |  |  |  |  |  | 
| 396 | 3 |  |  |  |  |  | n128_set_ui(&num_n128, 0); | 
| 397 |  |  |  |  |  |  |  | 
| 398 | 3 |  |  |  |  |  | n128_set_str_binary(&num_n128, bitstr, len); | 
| 399 | 3 |  |  |  |  |  | n128_print_dec(&num_n128, buf); | 
| 400 |  |  |  |  |  |  |  | 
| 401 | 10 |  |  |  |  |  | return 1; | 
| 402 |  |  |  |  |  |  | } | 
| 403 |  |  |  |  |  |  |  | 
| 404 |  |  |  |  |  |  | /** | 
| 405 |  |  |  |  |  |  | * NI_ip_is_ipv4(): check whether string is an IPv4 address. | 
| 406 |  |  |  |  |  |  | * @str: IP address string (null-terminated). | 
| 407 |  |  |  |  |  |  | */ | 
| 408 |  |  |  |  |  |  | int | 
| 409 | 949 |  |  |  |  |  | NI_ip_is_ipv4(const char *str) | 
| 410 |  |  |  |  |  |  | { | 
| 411 |  |  |  |  |  |  | int i; | 
| 412 |  |  |  |  |  |  | int len; | 
| 413 | 949 |  |  |  |  |  | int quads = 0; | 
| 414 |  |  |  |  |  |  | int quadspots[3]; | 
| 415 |  |  |  |  |  |  | long current_quad; | 
| 416 |  |  |  |  |  |  | int cq_index; | 
| 417 |  |  |  |  |  |  | char *endptr; | 
| 418 |  |  |  |  |  |  |  | 
| 419 | 949 |  |  |  |  |  | len = strlen(str); | 
| 420 | 949 | 100 |  |  |  |  | if (!len) { | 
| 421 | 2 |  |  |  |  |  | NI_set_Error_Errno(107, "Invalid chars in IP "); | 
| 422 | 2 |  |  |  |  |  | return 0; | 
| 423 |  |  |  |  |  |  | } | 
| 424 |  |  |  |  |  |  |  | 
| 425 |  |  |  |  |  |  | /* Contains invalid characters. */ | 
| 426 |  |  |  |  |  |  |  | 
| 427 | 11120 | 100 |  |  |  |  | for (i = 0; i < len; i++) { | 
| 428 | 10530 | 100 |  |  |  |  | if (!isdigit(str[i]) && str[i] != '.') { | 
|  |  | 100 |  |  |  |  |  | 
| 429 | 357 |  |  |  |  |  | NI_set_Error_Errno(107, "Invalid chars in IP %s", str); | 
| 430 | 357 |  |  |  |  |  | return 0; | 
| 431 |  |  |  |  |  |  | } | 
| 432 |  |  |  |  |  |  | } | 
| 433 |  |  |  |  |  |  |  | 
| 434 |  |  |  |  |  |  | /* Starts or ends with '.'. */ | 
| 435 |  |  |  |  |  |  |  | 
| 436 | 590 | 100 |  |  |  |  | if (str[0] == '.') { | 
| 437 | 1 |  |  |  |  |  | NI_set_Error_Errno(103, "Invalid IP %s - starts with a dot", str); | 
| 438 | 1 |  |  |  |  |  | return 0; | 
| 439 |  |  |  |  |  |  | } | 
| 440 |  |  |  |  |  |  |  | 
| 441 | 589 | 100 |  |  |  |  | if (str[len - 1] == '.') { | 
| 442 | 1 |  |  |  |  |  | NI_set_Error_Errno(104, "Invalid IP %s - ends with a dot", str); | 
| 443 | 1 |  |  |  |  |  | return 0; | 
| 444 |  |  |  |  |  |  | } | 
| 445 |  |  |  |  |  |  |  | 
| 446 |  |  |  |  |  |  | /* Contains more than four quads (octets). */ | 
| 447 |  |  |  |  |  |  |  | 
| 448 | 10740 | 100 |  |  |  |  | for (i = 0; i < len; i++) { | 
| 449 | 10153 | 100 |  |  |  |  | if (str[i] == '.') { | 
| 450 | 1656 | 100 |  |  |  |  | if (quads == 3) { | 
| 451 | 1 |  |  |  |  |  | NI_set_Error_Errno(105, "Invalid IP address %s", str); | 
| 452 | 1 |  |  |  |  |  | return 0; | 
| 453 |  |  |  |  |  |  | } | 
| 454 | 1655 |  |  |  |  |  | quadspots[quads] = i + 1; | 
| 455 | 1655 |  |  |  |  |  | quads++; | 
| 456 |  |  |  |  |  |  | } | 
| 457 |  |  |  |  |  |  | } | 
| 458 |  |  |  |  |  |  |  | 
| 459 |  |  |  |  |  |  | /* Contains an empty quad. */ | 
| 460 |  |  |  |  |  |  |  | 
| 461 | 10140 | 100 |  |  |  |  | for (i = 0; i < (len - 1); i++) { | 
| 462 | 9554 | 100 |  |  |  |  | if ((str[i] == '.') && (str[i + 1] == '.')) { | 
|  |  | 100 |  |  |  |  |  | 
| 463 | 1 |  |  |  |  |  | NI_set_Error_Errno(106, "Empty quad in IP address %s", str); | 
| 464 | 1 |  |  |  |  |  | return 0; | 
| 465 |  |  |  |  |  |  | } | 
| 466 |  |  |  |  |  |  | } | 
| 467 |  |  |  |  |  |  |  | 
| 468 |  |  |  |  |  |  | /* Contains an invalid quad value. */ | 
| 469 |  |  |  |  |  |  |  | 
| 470 | 2812 | 100 |  |  |  |  | for (cq_index = 0; cq_index <= quads; cq_index++) { | 
| 471 | 2235 | 100 |  |  |  |  | i = (cq_index > 0) ? (quadspots[cq_index - 1]) : 0; | 
| 472 |  |  |  |  |  |  |  | 
| 473 | 2235 |  |  |  |  |  | endptr = NULL; | 
| 474 |  |  |  |  |  |  |  | 
| 475 | 2235 |  |  |  |  |  | current_quad = strtol(str + i, &endptr, 10); | 
| 476 | 2235 | 100 |  |  |  |  | if (STRTOL_FAILED(current_quad, str + i, endptr) | 
|  |  | 50 |  |  |  |  |  | 
|  |  | 50 |  |  |  |  |  | 
|  |  | 100 |  |  |  |  |  | 
|  |  | 50 |  |  |  |  |  | 
| 477 | 2232 | 50 |  |  |  |  | || (!(current_quad >= 0 && current_quad < 256))) { | 
|  |  | 100 |  |  |  |  |  | 
| 478 | 9 |  |  |  |  |  | NI_set_Error_Errno(107, "Invalid quad in IP address " | 
| 479 |  |  |  |  |  |  | "%s - %d", str, current_quad); | 
| 480 | 9 |  |  |  |  |  | return 0; | 
| 481 |  |  |  |  |  |  | } | 
| 482 |  |  |  |  |  |  | } | 
| 483 |  |  |  |  |  |  |  | 
| 484 | 949 |  |  |  |  |  | return 1; | 
| 485 |  |  |  |  |  |  | } | 
| 486 |  |  |  |  |  |  |  | 
| 487 |  |  |  |  |  |  | /** | 
| 488 |  |  |  |  |  |  | * NI_ip_is_ipv6(): check whether string is an IPv6 address. | 
| 489 |  |  |  |  |  |  | * @str: the IP address string. | 
| 490 |  |  |  |  |  |  | */ | 
| 491 |  |  |  |  |  |  | int | 
| 492 | 447 |  |  |  |  |  | NI_ip_is_ipv6(const char *str) | 
| 493 |  |  |  |  |  |  | { | 
| 494 |  |  |  |  |  |  | int i; | 
| 495 |  |  |  |  |  |  | int len; | 
| 496 | 447 |  |  |  |  |  | int octs = 0; | 
| 497 |  |  |  |  |  |  | int octspots[8]; | 
| 498 |  |  |  |  |  |  | int oct_index; | 
| 499 |  |  |  |  |  |  | const char *double_colon; | 
| 500 |  |  |  |  |  |  | const char *next_oct; | 
| 501 |  |  |  |  |  |  | const char *cc; | 
| 502 |  |  |  |  |  |  | int count; | 
| 503 |  |  |  |  |  |  | int is_hd; | 
| 504 |  |  |  |  |  |  | int max_colons; | 
| 505 |  |  |  |  |  |  |  | 
| 506 | 447 |  |  |  |  |  | len = strlen(str); | 
| 507 |  |  |  |  |  |  |  | 
| 508 | 447 |  |  |  |  |  | double_colon = strstr(str, "::"); | 
| 509 | 447 | 100 |  |  |  |  | max_colons = (double_colon == NULL) ? 7 : 8; | 
| 510 |  |  |  |  |  |  |  | 
| 511 |  |  |  |  |  |  | /* Store a pointer to the next character after each ':' in | 
| 512 |  |  |  |  |  |  | * octspots. */ | 
| 513 |  |  |  |  |  |  |  | 
| 514 | 17099 | 100 |  |  |  |  | for (i = 0; i < len; i++) { | 
| 515 | 16654 | 100 |  |  |  |  | if (str[i] == ':') { | 
| 516 | 2646 | 100 |  |  |  |  | if (octs == max_colons) { | 
| 517 | 2 |  |  |  |  |  | return 0; | 
| 518 |  |  |  |  |  |  | } | 
| 519 | 2644 |  |  |  |  |  | octspots[octs++] = i + 1; | 
| 520 |  |  |  |  |  |  | } | 
| 521 |  |  |  |  |  |  | } | 
| 522 |  |  |  |  |  |  |  | 
| 523 | 445 | 100 |  |  |  |  | if (!octs) { | 
| 524 | 12 |  |  |  |  |  | return 0; | 
| 525 |  |  |  |  |  |  | } | 
| 526 |  |  |  |  |  |  |  | 
| 527 | 3490 | 100 |  |  |  |  | for (oct_index = 0; oct_index <= octs; oct_index++) { | 
| 528 | 3060 | 100 |  |  |  |  | i = (oct_index > 0) ? (octspots[oct_index - 1]) : 0; | 
| 529 |  |  |  |  |  |  |  | 
| 530 |  |  |  |  |  |  | /* Empty octet. */ | 
| 531 |  |  |  |  |  |  |  | 
| 532 | 3060 | 100 |  |  |  |  | if (str[i] == ':') { | 
| 533 | 119 |  |  |  |  |  | continue; | 
| 534 |  |  |  |  |  |  | } | 
| 535 | 2941 | 100 |  |  |  |  | if (strlen(str + i) == 0) { | 
| 536 | 68 |  |  |  |  |  | continue; | 
| 537 |  |  |  |  |  |  | } | 
| 538 |  |  |  |  |  |  |  | 
| 539 |  |  |  |  |  |  | /* Last octet can be an IPv4 address. */ | 
| 540 |  |  |  |  |  |  |  | 
| 541 | 2873 |  |  |  |  |  | cc = str + i; | 
| 542 | 2873 | 100 |  |  |  |  | if ((oct_index == octs) && NI_ip_is_ipv4(cc)) { | 
|  |  | 100 |  |  |  |  |  | 
| 543 | 16 |  |  |  |  |  | continue; | 
| 544 |  |  |  |  |  |  | } | 
| 545 |  |  |  |  |  |  |  | 
| 546 |  |  |  |  |  |  | /* 1-4 hex digits. */ | 
| 547 |  |  |  |  |  |  |  | 
| 548 | 2857 |  |  |  |  |  | next_oct = strchr(str + i, ':'); | 
| 549 | 2857 | 100 |  |  |  |  | if (next_oct == NULL) { | 
| 550 | 347 |  |  |  |  |  | next_oct = (str + len); | 
| 551 |  |  |  |  |  |  | } | 
| 552 |  |  |  |  |  |  |  | 
| 553 | 2857 |  |  |  |  |  | count = next_oct - cc; | 
| 554 | 2857 |  |  |  |  |  | is_hd = 1; | 
| 555 |  |  |  |  |  |  |  | 
| 556 | 14193 | 100 |  |  |  |  | while (cc != next_oct) { | 
| 557 | 11338 | 100 |  |  |  |  | if (!isxdigit(*cc)) { | 
| 558 | 2 |  |  |  |  |  | is_hd = 0; | 
| 559 | 2 |  |  |  |  |  | break; | 
| 560 |  |  |  |  |  |  | } | 
| 561 | 11336 |  |  |  |  |  | cc++; | 
| 562 |  |  |  |  |  |  | } | 
| 563 |  |  |  |  |  |  |  | 
| 564 | 2857 | 100 |  |  |  |  | if (is_hd && (count <= 4)) { | 
|  |  | 100 |  |  |  |  |  | 
| 565 | 2854 |  |  |  |  |  | continue; | 
| 566 |  |  |  |  |  |  | } | 
| 567 |  |  |  |  |  |  |  | 
| 568 | 3 |  |  |  |  |  | NI_set_Error_Errno(108, "Invalid IP address %s", str); | 
| 569 | 3 |  |  |  |  |  | return 0; | 
| 570 |  |  |  |  |  |  | } | 
| 571 |  |  |  |  |  |  |  | 
| 572 |  |  |  |  |  |  | /* Starts or ends with ':'. */ | 
| 573 |  |  |  |  |  |  |  | 
| 574 | 430 | 100 |  |  |  |  | if ((str[0] == ':') && (str[1] != ':')) { | 
|  |  | 100 |  |  |  |  |  | 
| 575 | 1 |  |  |  |  |  | NI_set_Error_Errno(109, "Invalid address %s " | 
| 576 |  |  |  |  |  |  | "(starts with :)", str); | 
| 577 | 1 |  |  |  |  |  | return 0; | 
| 578 |  |  |  |  |  |  | } | 
| 579 |  |  |  |  |  |  |  | 
| 580 | 429 | 100 |  |  |  |  | if ((str[len - 1] == ':') && (str[len - 2] != ':')) { | 
|  |  | 100 |  |  |  |  |  | 
| 581 | 1 |  |  |  |  |  | NI_set_Error_Errno(110, "Invalid address %s " | 
| 582 |  |  |  |  |  |  | "(ends with :)", str); | 
| 583 | 1 |  |  |  |  |  | return 0; | 
| 584 |  |  |  |  |  |  | } | 
| 585 |  |  |  |  |  |  |  | 
| 586 |  |  |  |  |  |  | /* Contains more than one '::'. */ | 
| 587 |  |  |  |  |  |  |  | 
| 588 | 428 | 100 |  |  |  |  | if ((double_colon != NULL) && (strstr(double_colon + 1, "::"))) { | 
|  |  | 100 |  |  |  |  |  | 
| 589 | 1 |  |  |  |  |  | NI_set_Error_Errno(111, "Invalid address %s " | 
| 590 |  |  |  |  |  |  | "(More than one :: pattern)", str); | 
| 591 | 1 |  |  |  |  |  | return 0; | 
| 592 |  |  |  |  |  |  | } | 
| 593 |  |  |  |  |  |  |  | 
| 594 |  |  |  |  |  |  | /* Doesn't contain '::', though it has fewer than eight segments. */ | 
| 595 |  |  |  |  |  |  |  | 
| 596 | 427 | 100 |  |  |  |  | if ((octs != 7) && (double_colon == NULL)) { | 
|  |  | 100 |  |  |  |  |  | 
| 597 | 1 |  |  |  |  |  | NI_set_Error_Errno(112, "Invalid number of octets %s",  str); | 
| 598 | 1 |  |  |  |  |  | return 0; | 
| 599 |  |  |  |  |  |  | } | 
| 600 |  |  |  |  |  |  |  | 
| 601 | 447 |  |  |  |  |  | return 1; | 
| 602 |  |  |  |  |  |  | } | 
| 603 |  |  |  |  |  |  |  | 
| 604 |  |  |  |  |  |  | /** | 
| 605 |  |  |  |  |  |  | * NI_ip_get_version(): return the version of the IP address string. | 
| 606 |  |  |  |  |  |  | * @str: the IP address string. | 
| 607 |  |  |  |  |  |  | * | 
| 608 |  |  |  |  |  |  | * Returns 0 if the string is neither an IPv4 nor an IPv6 address | 
| 609 |  |  |  |  |  |  | * string. | 
| 610 |  |  |  |  |  |  | */ | 
| 611 |  |  |  |  |  |  | int | 
| 612 | 983 |  |  |  |  |  | NI_ip_get_version(const char *str) | 
| 613 |  |  |  |  |  |  | { | 
| 614 | 983 | 100 |  |  |  |  | if ((!strchr(str, ':')) && NI_ip_is_ipv4(str)) { | 
|  |  | 100 |  |  |  |  |  | 
| 615 | 549 |  |  |  |  |  | return 4; | 
| 616 | 434 | 100 |  |  |  |  | } else if (NI_ip_is_ipv6(str)) { | 
| 617 | 421 |  |  |  |  |  | return 6; | 
| 618 |  |  |  |  |  |  | } else { | 
| 619 | 13 |  |  |  |  |  | return 0; | 
| 620 |  |  |  |  |  |  | } | 
| 621 |  |  |  |  |  |  | } | 
| 622 |  |  |  |  |  |  |  | 
| 623 |  |  |  |  |  |  | /** | 
| 624 |  |  |  |  |  |  | * NI_ip_get_mask(): make bitstring network mask. | 
| 625 |  |  |  |  |  |  | * @len: the mask's prefix length. | 
| 626 |  |  |  |  |  |  | * @version: the mask's IP address version. | 
| 627 |  |  |  |  |  |  | * @buf: the bitstring mask buffer. | 
| 628 |  |  |  |  |  |  | * | 
| 629 |  |  |  |  |  |  | * If @len is larger than the number of bits for an IP address of the | 
| 630 |  |  |  |  |  |  | * specified version, then @len is set to equal that number of bits. | 
| 631 |  |  |  |  |  |  | * So if 48 were specified for @len for an IPv4 address, it would be | 
| 632 |  |  |  |  |  |  | * set to 32. This function does not null-terminate the buffer. The | 
| 633 |  |  |  |  |  |  | * buffer must have 32 or 128 characters' capacity for IPv4 and IPv6 | 
| 634 |  |  |  |  |  |  | * respectively. | 
| 635 |  |  |  |  |  |  | */ | 
| 636 |  |  |  |  |  |  | int | 
| 637 | 144 |  |  |  |  |  | NI_ip_get_mask(int len, int version, char *buf) | 
| 638 |  |  |  |  |  |  | { | 
| 639 |  |  |  |  |  |  | int size; | 
| 640 |  |  |  |  |  |  |  | 
| 641 | 144 | 100 |  |  |  |  | if (!version) { | 
| 642 | 1 |  |  |  |  |  | NI_set_Error_Errno(101, "Cannot determine IP version"); | 
| 643 | 1 |  |  |  |  |  | return 0; | 
| 644 |  |  |  |  |  |  | } | 
| 645 |  |  |  |  |  |  |  | 
| 646 | 143 |  |  |  |  |  | size = NI_iplengths(version); | 
| 647 |  |  |  |  |  |  |  | 
| 648 | 143 | 100 |  |  |  |  | if (len < 0) { | 
| 649 | 1 |  |  |  |  |  | len = 0; | 
| 650 | 142 | 100 |  |  |  |  | } else if (len > size) { | 
| 651 | 2 |  |  |  |  |  | len = size; | 
| 652 |  |  |  |  |  |  | } | 
| 653 |  |  |  |  |  |  |  | 
| 654 | 143 |  |  |  |  |  | memset(buf, '1', len); | 
| 655 | 143 |  |  |  |  |  | memset(buf + len, '0', (size - len)); | 
| 656 |  |  |  |  |  |  |  | 
| 657 | 143 |  |  |  |  |  | return 1; | 
| 658 |  |  |  |  |  |  | } | 
| 659 |  |  |  |  |  |  |  | 
| 660 |  |  |  |  |  |  | /** | 
| 661 |  |  |  |  |  |  | * NI_ip_last_address_ipv6(): get last address of prefix. | 
| 662 |  |  |  |  |  |  | * @ip: the beginning IP address. | 
| 663 |  |  |  |  |  |  | * @len: the prefix length. | 
| 664 |  |  |  |  |  |  | * @buf: N128 integer buffer for the last address. | 
| 665 |  |  |  |  |  |  | */ | 
| 666 |  |  |  |  |  |  | int | 
| 667 | 47 |  |  |  |  |  | NI_ip_last_address_ipv6(n128_t *ip, int len, n128_t *buf) | 
| 668 |  |  |  |  |  |  | { | 
| 669 |  |  |  |  |  |  | int i; | 
| 670 |  |  |  |  |  |  |  | 
| 671 | 47 |  |  |  |  |  | memcpy(buf, ip, sizeof(*ip)); | 
| 672 |  |  |  |  |  |  |  | 
| 673 | 47 | 100 |  |  |  |  | len = (len == 0) ? 128 : (128 - len); | 
| 674 |  |  |  |  |  |  |  | 
| 675 | 4529 | 100 |  |  |  |  | for (i = 0; i < len; i++) { | 
| 676 | 4482 |  |  |  |  |  | n128_setbit(buf, i); | 
| 677 |  |  |  |  |  |  | } | 
| 678 |  |  |  |  |  |  |  | 
| 679 | 47 |  |  |  |  |  | return 1; | 
| 680 |  |  |  |  |  |  | } | 
| 681 |  |  |  |  |  |  |  | 
| 682 |  |  |  |  |  |  | /** | 
| 683 |  |  |  |  |  |  | * NI_ip_last_address_ipv4(): get last address of prefix. | 
| 684 |  |  |  |  |  |  | * @ip: the beginning IP address. | 
| 685 |  |  |  |  |  |  | * @len: the prefix length. | 
| 686 |  |  |  |  |  |  | */ | 
| 687 |  |  |  |  |  |  | unsigned long | 
| 688 | 61 |  |  |  |  |  | NI_ip_last_address_ipv4(unsigned long ip, int len) | 
| 689 |  |  |  |  |  |  | { | 
| 690 |  |  |  |  |  |  | unsigned long mask; | 
| 691 |  |  |  |  |  |  |  | 
| 692 | 61 | 100 |  |  |  |  | mask = (len == 0) ? 0xFFFFFFFF : ((1 << (32 - len)) - 1); | 
| 693 | 61 |  |  |  |  |  | return ip | mask; | 
| 694 |  |  |  |  |  |  | } | 
| 695 |  |  |  |  |  |  |  | 
| 696 |  |  |  |  |  |  | /** | 
| 697 |  |  |  |  |  |  | * NI_ip_last_address_bin(): make last address of prefix as a bitstring. | 
| 698 |  |  |  |  |  |  | * @bitstr: the beginning IP address as a bitstring. | 
| 699 |  |  |  |  |  |  | * @len: the prefix length. | 
| 700 |  |  |  |  |  |  | * @version: the IP address version. | 
| 701 |  |  |  |  |  |  | * @buf: the last address bitstring buffer. | 
| 702 |  |  |  |  |  |  | * | 
| 703 |  |  |  |  |  |  | * This function does not null-terminate the buffer. The buffer must | 
| 704 |  |  |  |  |  |  | * have 32 or 128 characters' capacity for IPv4 and IPv6 respectively. | 
| 705 |  |  |  |  |  |  | */ | 
| 706 |  |  |  |  |  |  | int | 
| 707 | 28 |  |  |  |  |  | NI_ip_last_address_bin(const char *bitstr, int len, int version, char *buf) | 
| 708 |  |  |  |  |  |  | { | 
| 709 |  |  |  |  |  |  | int size; | 
| 710 |  |  |  |  |  |  |  | 
| 711 | 28 | 100 |  |  |  |  | if (!version) { | 
| 712 | 1 |  |  |  |  |  | NI_set_Error_Errno(101, "Cannot determine IP version"); | 
| 713 | 1 |  |  |  |  |  | return 0; | 
| 714 |  |  |  |  |  |  | } | 
| 715 |  |  |  |  |  |  |  | 
| 716 | 27 |  |  |  |  |  | size = NI_iplengths(version); | 
| 717 |  |  |  |  |  |  |  | 
| 718 | 27 | 100 |  |  |  |  | if ((len < 0) || (len > size)) { | 
|  |  | 100 |  |  |  |  |  | 
| 719 | 3 |  |  |  |  |  | len = size; | 
| 720 |  |  |  |  |  |  | } | 
| 721 |  |  |  |  |  |  |  | 
| 722 | 27 |  |  |  |  |  | strncpy(buf, bitstr, len); | 
| 723 | 27 |  |  |  |  |  | memset(buf + len, '1', (size - len)); | 
| 724 |  |  |  |  |  |  |  | 
| 725 | 27 |  |  |  |  |  | return 1; | 
| 726 |  |  |  |  |  |  | } | 
| 727 |  |  |  |  |  |  |  | 
| 728 |  |  |  |  |  |  | /** | 
| 729 |  |  |  |  |  |  | * NI_ip_bincomp(): compare two bitstrings. | 
| 730 |  |  |  |  |  |  | * @bitstr_1: first bitstring. | 
| 731 |  |  |  |  |  |  | * @op_str: the comparator as a string. | 
| 732 |  |  |  |  |  |  | * @bitstr_2: second bitstring. | 
| 733 |  |  |  |  |  |  | * @result: a pointer to an integer. | 
| 734 |  |  |  |  |  |  | * | 
| 735 |  |  |  |  |  |  | * The bitstrings and the comparator must be null-terminated. The | 
| 736 |  |  |  |  |  |  | * comparator must be one of 'gt', 'ge', 'lt', and 'le'. 'gt' means | 
| 737 |  |  |  |  |  |  | * 'greater than', 'ge' means 'greater than or equal to', 'lt' means | 
| 738 |  |  |  |  |  |  | * 'less than', 'le' means 'less than or equal to'. Returns 1 or 0 | 
| 739 |  |  |  |  |  |  | * depending on whether the strings were able to be compared | 
| 740 |  |  |  |  |  |  | * successfully. If the comparison was able to be made, the result of | 
| 741 |  |  |  |  |  |  | * the comparison is stored in @result. This function will not compare | 
| 742 |  |  |  |  |  |  | * two bitstrings of different lengths. | 
| 743 |  |  |  |  |  |  | */ | 
| 744 |  |  |  |  |  |  | int | 
| 745 | 954 |  |  |  |  |  | NI_ip_bincomp(const char *bitstr_1, const char *op_str, | 
| 746 |  |  |  |  |  |  | const char *bitstr_2, int *result) | 
| 747 |  |  |  |  |  |  | { | 
| 748 |  |  |  |  |  |  | const char *b; | 
| 749 |  |  |  |  |  |  | const char *e; | 
| 750 |  |  |  |  |  |  | int op; | 
| 751 |  |  |  |  |  |  | int res; | 
| 752 |  |  |  |  |  |  |  | 
| 753 | 1908 |  |  |  |  |  | op = (!strcmp(op_str, "gt")) ? GT | 
| 754 | 1903 | 100 |  |  |  |  | : (!strcmp(op_str, "lt")) ? LT | 
| 755 | 1888 | 100 |  |  |  |  | : (!strcmp(op_str, "le")) ? LE | 
| 756 | 948 | 100 |  |  |  |  | : (!strcmp(op_str, "ge")) ? GE | 
| 757 | 9 | 100 |  |  |  |  | : 0; | 
| 758 |  |  |  |  |  |  |  | 
| 759 | 954 | 100 |  |  |  |  | if (!op) { | 
| 760 | 2 |  |  |  |  |  | NI_set_Error_Errno(131, "Invalid Operator %s", op_str); | 
| 761 | 2 |  |  |  |  |  | return 0; | 
| 762 |  |  |  |  |  |  | } | 
| 763 |  |  |  |  |  |  |  | 
| 764 | 952 | 100 |  |  |  |  | if ((op == GT) || (op == GE)) { | 
|  |  | 100 |  |  |  |  |  | 
| 765 | 12 |  |  |  |  |  | b = bitstr_1; | 
| 766 | 12 |  |  |  |  |  | e = bitstr_2; | 
| 767 |  |  |  |  |  |  | } else { | 
| 768 | 940 |  |  |  |  |  | b = bitstr_2; | 
| 769 | 940 |  |  |  |  |  | e = bitstr_1; | 
| 770 |  |  |  |  |  |  | } | 
| 771 |  |  |  |  |  |  |  | 
| 772 | 952 | 100 |  |  |  |  | if (strlen(b) != (strlen(e))) { | 
| 773 | 2 |  |  |  |  |  | NI_set_Error_Errno(130, "IP addresses of different length"); | 
| 774 | 2 |  |  |  |  |  | return 0; | 
| 775 |  |  |  |  |  |  | } | 
| 776 |  |  |  |  |  |  |  | 
| 777 | 950 |  |  |  |  |  | res = strcmp(b, e); | 
| 778 |  |  |  |  |  |  |  | 
| 779 | 950 |  |  |  |  |  | *result = | 
| 780 | 20 | 100 |  |  |  |  | (!res && ((op == GE) || (op == LE))) | 
|  |  | 100 |  |  |  |  |  | 
| 781 |  |  |  |  |  |  | ? 1 | 
| 782 | 970 | 100 |  |  |  |  | : (res > 0); | 
|  |  | 100 |  |  |  |  |  | 
| 783 |  |  |  |  |  |  |  | 
| 784 | 950 |  |  |  |  |  | return 1; | 
| 785 |  |  |  |  |  |  | } | 
| 786 |  |  |  |  |  |  |  | 
| 787 |  |  |  |  |  |  | /** | 
| 788 |  |  |  |  |  |  | * NI_ip_is_overlap_ipv6(): get overlap status of two ranges. | 
| 789 |  |  |  |  |  |  | * @begin_1: beginning address of first range. | 
| 790 |  |  |  |  |  |  | * @end_1: ending address of first range. | 
| 791 |  |  |  |  |  |  | * @begin_2: beginning address of second range. | 
| 792 |  |  |  |  |  |  | * @end_2: ending address of second range. | 
| 793 |  |  |  |  |  |  | * @result: a pointer to an integer. | 
| 794 |  |  |  |  |  |  | */ | 
| 795 |  |  |  |  |  |  | void | 
| 796 | 15 |  |  |  |  |  | NI_ip_is_overlap_ipv6(n128_t *begin_1, n128_t *end_1, | 
| 797 |  |  |  |  |  |  | n128_t *begin_2, n128_t *end_2, int *result) | 
| 798 |  |  |  |  |  |  | { | 
| 799 |  |  |  |  |  |  | int res; | 
| 800 |  |  |  |  |  |  |  | 
| 801 | 15 | 100 |  |  |  |  | if (!n128_cmp(begin_1, begin_2)) { | 
| 802 | 5 | 100 |  |  |  |  | if (!n128_cmp(end_1, end_2)) { | 
| 803 | 2 |  |  |  |  |  | *result = IP_IDENTICAL; | 
| 804 | 2 |  |  |  |  |  | return; | 
| 805 |  |  |  |  |  |  | } | 
| 806 | 3 |  |  |  |  |  | res = n128_cmp(end_1, end_2); | 
| 807 | 3 |  |  |  |  |  | *result = (res < 0) ? IP_A_IN_B_OVERLAP | 
| 808 | 3 | 100 |  |  |  |  | : IP_B_IN_A_OVERLAP; | 
| 809 | 3 |  |  |  |  |  | return; | 
| 810 |  |  |  |  |  |  | } | 
| 811 |  |  |  |  |  |  |  | 
| 812 | 10 | 100 |  |  |  |  | if (!n128_cmp(end_1, end_2)) { | 
| 813 | 2 |  |  |  |  |  | res = n128_cmp(begin_1, begin_2); | 
| 814 | 2 |  |  |  |  |  | *result = (res < 0) ? IP_B_IN_A_OVERLAP | 
| 815 | 2 | 100 |  |  |  |  | : IP_A_IN_B_OVERLAP; | 
| 816 | 2 |  |  |  |  |  | return; | 
| 817 |  |  |  |  |  |  | } | 
| 818 |  |  |  |  |  |  |  | 
| 819 | 8 |  |  |  |  |  | res = n128_cmp(begin_1, begin_2); | 
| 820 | 8 | 100 |  |  |  |  | if (res < 0) { | 
| 821 | 5 |  |  |  |  |  | res = n128_cmp(end_1, begin_2); | 
| 822 | 5 | 100 |  |  |  |  | if (res < 0) { | 
| 823 | 2 |  |  |  |  |  | *result = IP_NO_OVERLAP; | 
| 824 | 2 |  |  |  |  |  | return; | 
| 825 |  |  |  |  |  |  | } | 
| 826 | 3 |  |  |  |  |  | res = n128_cmp(end_1, end_2); | 
| 827 | 3 |  |  |  |  |  | *result = (res < 0) ? IP_PARTIAL_OVERLAP | 
| 828 | 3 | 100 |  |  |  |  | : IP_B_IN_A_OVERLAP; | 
| 829 | 3 |  |  |  |  |  | return; | 
| 830 |  |  |  |  |  |  | } | 
| 831 |  |  |  |  |  |  |  | 
| 832 | 3 |  |  |  |  |  | res = n128_cmp(end_2, begin_1); | 
| 833 | 3 | 100 |  |  |  |  | if (res < 0) { | 
| 834 | 1 |  |  |  |  |  | *result = IP_NO_OVERLAP; | 
| 835 | 1 |  |  |  |  |  | return; | 
| 836 |  |  |  |  |  |  | } | 
| 837 |  |  |  |  |  |  |  | 
| 838 | 2 |  |  |  |  |  | res = n128_cmp(end_2, end_1); | 
| 839 | 2 |  |  |  |  |  | *result = (res < 0) ? IP_PARTIAL_OVERLAP | 
| 840 | 2 | 100 |  |  |  |  | : IP_A_IN_B_OVERLAP; | 
| 841 |  |  |  |  |  |  |  | 
| 842 | 2 |  |  |  |  |  | return; | 
| 843 |  |  |  |  |  |  | } | 
| 844 |  |  |  |  |  |  |  | 
| 845 |  |  |  |  |  |  | /** | 
| 846 |  |  |  |  |  |  | * NI_ip_is_overlap_ipv4(): get overlap status of two ranges. | 
| 847 |  |  |  |  |  |  | * @begin_1: beginning address of first range. | 
| 848 |  |  |  |  |  |  | * @end_1: ending address of first range. | 
| 849 |  |  |  |  |  |  | * @begin_2: beginning address of second range. | 
| 850 |  |  |  |  |  |  | * @end_2: ending address of second range. | 
| 851 |  |  |  |  |  |  | * @result: a pointer to an integer. | 
| 852 |  |  |  |  |  |  | */ | 
| 853 |  |  |  |  |  |  | void | 
| 854 | 13 |  |  |  |  |  | NI_ip_is_overlap_ipv4(unsigned long begin_1, unsigned long end_1, | 
| 855 |  |  |  |  |  |  | unsigned long begin_2, unsigned long end_2, | 
| 856 |  |  |  |  |  |  | int *result) | 
| 857 |  |  |  |  |  |  | { | 
| 858 | 13 | 100 |  |  |  |  | if (begin_1 == begin_2) { | 
| 859 | 4 | 100 |  |  |  |  | if (end_1 == end_2) { | 
| 860 | 2 |  |  |  |  |  | *result = IP_IDENTICAL; | 
| 861 | 2 |  |  |  |  |  | return; | 
| 862 |  |  |  |  |  |  | } | 
| 863 | 2 |  |  |  |  |  | *result = | 
| 864 |  |  |  |  |  |  | (end_1 < end_2) | 
| 865 |  |  |  |  |  |  | ? IP_A_IN_B_OVERLAP | 
| 866 | 2 | 100 |  |  |  |  | : IP_B_IN_A_OVERLAP; | 
| 867 | 2 |  |  |  |  |  | return; | 
| 868 |  |  |  |  |  |  | } | 
| 869 |  |  |  |  |  |  |  | 
| 870 | 9 | 100 |  |  |  |  | if (end_1 == end_2) { | 
| 871 | 2 |  |  |  |  |  | *result = | 
| 872 |  |  |  |  |  |  | (begin_1 < begin_2) | 
| 873 |  |  |  |  |  |  | ? IP_B_IN_A_OVERLAP | 
| 874 | 2 | 100 |  |  |  |  | : IP_A_IN_B_OVERLAP; | 
| 875 | 2 |  |  |  |  |  | return; | 
| 876 |  |  |  |  |  |  | } | 
| 877 |  |  |  |  |  |  |  | 
| 878 | 7 | 100 |  |  |  |  | if (begin_1 < begin_2) { | 
| 879 | 4 | 100 |  |  |  |  | if (end_1 < begin_2) { | 
| 880 | 2 |  |  |  |  |  | *result = IP_NO_OVERLAP; | 
| 881 | 2 |  |  |  |  |  | return; | 
| 882 |  |  |  |  |  |  | } | 
| 883 | 2 |  |  |  |  |  | *result = | 
| 884 |  |  |  |  |  |  | (end_1 < end_2) | 
| 885 |  |  |  |  |  |  | ? IP_PARTIAL_OVERLAP | 
| 886 | 2 | 100 |  |  |  |  | : IP_B_IN_A_OVERLAP; | 
| 887 | 2 |  |  |  |  |  | return; | 
| 888 |  |  |  |  |  |  | } | 
| 889 |  |  |  |  |  |  |  | 
| 890 | 3 | 100 |  |  |  |  | if (end_2 < begin_1) { | 
| 891 | 1 |  |  |  |  |  | *result = IP_NO_OVERLAP; | 
| 892 | 1 |  |  |  |  |  | return; | 
| 893 |  |  |  |  |  |  | } | 
| 894 |  |  |  |  |  |  |  | 
| 895 | 2 |  |  |  |  |  | *result = | 
| 896 |  |  |  |  |  |  | (end_2 < end_1) | 
| 897 |  |  |  |  |  |  | ? IP_PARTIAL_OVERLAP | 
| 898 | 2 | 100 |  |  |  |  | : IP_A_IN_B_OVERLAP; | 
| 899 |  |  |  |  |  |  |  | 
| 900 | 2 |  |  |  |  |  | return; | 
| 901 |  |  |  |  |  |  | } | 
| 902 |  |  |  |  |  |  |  | 
| 903 |  |  |  |  |  |  | /** | 
| 904 |  |  |  |  |  |  | * NI_ip_is_overlap(): get overlap status of two ranges. | 
| 905 |  |  |  |  |  |  | * @begin_1: beginning bitstring IP address for first range. | 
| 906 |  |  |  |  |  |  | * @end_1: ending bitstring IP address for first range. | 
| 907 |  |  |  |  |  |  | * @begin_2: beginning bitstring IP address for second range. | 
| 908 |  |  |  |  |  |  | * @end_2: ending bitstring IP address for second range. | 
| 909 |  |  |  |  |  |  | * @result: a pointer to an integer. | 
| 910 |  |  |  |  |  |  | * | 
| 911 |  |  |  |  |  |  | * Each bitstring must be null-terminated.  Returns 1 or 0 depending | 
| 912 |  |  |  |  |  |  | * on whether the ranges are able to be compared successfully. If the | 
| 913 |  |  |  |  |  |  | * overlap status is able to be determined, stores that status in | 
| 914 |  |  |  |  |  |  | * @result. Returns 0 if the bitstrings are not all of equal length. | 
| 915 |  |  |  |  |  |  | * The possible overlap statuses are NO_OVERLAP, IP_PARTIAL_OVERLAP, | 
| 916 |  |  |  |  |  |  | * IP_A_IN_B_OVERLAP (first range completely contained within second | 
| 917 |  |  |  |  |  |  | * range), IP_B_IN_A_OVERLAP (second range completely contained within | 
| 918 |  |  |  |  |  |  | * first range) and IP_IDENTICAL. | 
| 919 |  |  |  |  |  |  | */ | 
| 920 |  |  |  |  |  |  | int | 
| 921 | 23 |  |  |  |  |  | NI_ip_is_overlap(const char *begin_1, const char *end_1, | 
| 922 |  |  |  |  |  |  | const char *begin_2, const char *end_2, int *result) | 
| 923 |  |  |  |  |  |  | { | 
| 924 |  |  |  |  |  |  | int b1_len; | 
| 925 |  |  |  |  |  |  | int b2_len; | 
| 926 | 23 |  |  |  |  |  | int res = 0; | 
| 927 |  |  |  |  |  |  | n128_t begin_1_n128; | 
| 928 |  |  |  |  |  |  | n128_t end_1_n128; | 
| 929 |  |  |  |  |  |  | n128_t begin_2_n128; | 
| 930 |  |  |  |  |  |  | n128_t end_2_n128; | 
| 931 |  |  |  |  |  |  | unsigned long begin_1_ulong; | 
| 932 |  |  |  |  |  |  | unsigned long begin_2_ulong; | 
| 933 |  |  |  |  |  |  | unsigned long end_1_ulong; | 
| 934 |  |  |  |  |  |  | unsigned long end_2_ulong; | 
| 935 |  |  |  |  |  |  |  | 
| 936 | 23 |  |  |  |  |  | b1_len = strlen(begin_1); | 
| 937 | 23 |  |  |  |  |  | b2_len = strlen(begin_2); | 
| 938 |  |  |  |  |  |  |  | 
| 939 | 44 | 100 |  |  |  |  | if (!(     (b1_len == (int) strlen(end_1)) | 
|  |  | 100 |  |  |  |  |  | 
| 940 | 22 | 100 |  |  |  |  | && (b2_len == (int) strlen(end_2)) | 
| 941 |  |  |  |  |  |  | && (b1_len == b2_len))) { | 
| 942 | 3 |  |  |  |  |  | NI_set_Error_Errno(130, "IP addresses of different length"); | 
| 943 | 3 |  |  |  |  |  | return 0; | 
| 944 |  |  |  |  |  |  | } | 
| 945 |  |  |  |  |  |  |  | 
| 946 | 20 |  |  |  |  |  | NI_ip_bincomp(begin_1, "le", end_1, &res); | 
| 947 | 20 | 100 |  |  |  |  | if (!res) { | 
| 948 | 1 |  |  |  |  |  | NI_set_Error_Errno(140, "Invalid range %s - %s", begin_1, end_1); | 
| 949 | 1 |  |  |  |  |  | return 0; | 
| 950 |  |  |  |  |  |  | } | 
| 951 |  |  |  |  |  |  |  | 
| 952 | 19 |  |  |  |  |  | NI_ip_bincomp(begin_2, "le", end_2, &res); | 
| 953 | 19 | 100 |  |  |  |  | if (!res) { | 
| 954 | 1 |  |  |  |  |  | NI_set_Error_Errno(140, "Invalid range %s - %s", begin_2, end_2); | 
| 955 | 1 |  |  |  |  |  | return 0; | 
| 956 |  |  |  |  |  |  | } | 
| 957 |  |  |  |  |  |  |  | 
| 958 |  |  |  |  |  |  | /* IPv4-specific version (avoids using N128). */ | 
| 959 |  |  |  |  |  |  |  | 
| 960 | 18 | 100 |  |  |  |  | if (b1_len <= 32) { | 
| 961 | 8 |  |  |  |  |  | begin_1_ulong = NI_bintoint(begin_1, b1_len); | 
| 962 | 8 |  |  |  |  |  | begin_2_ulong = NI_bintoint(begin_2, b1_len); | 
| 963 | 8 |  |  |  |  |  | end_1_ulong   = NI_bintoint(end_1,   b1_len); | 
| 964 | 8 |  |  |  |  |  | end_2_ulong   = NI_bintoint(end_2,   b1_len); | 
| 965 | 8 |  |  |  |  |  | NI_ip_is_overlap_ipv4(begin_1_ulong, end_1_ulong, | 
| 966 |  |  |  |  |  |  | begin_2_ulong, end_2_ulong, result); | 
| 967 | 8 |  |  |  |  |  | return 1; | 
| 968 |  |  |  |  |  |  | } | 
| 969 |  |  |  |  |  |  |  | 
| 970 |  |  |  |  |  |  | /* IPv6 version (using N128). */ | 
| 971 |  |  |  |  |  |  |  | 
| 972 | 10 |  |  |  |  |  | n128_set_str_binary(&begin_1_n128, begin_1, b1_len); | 
| 973 | 10 |  |  |  |  |  | n128_set_str_binary(&begin_2_n128, begin_2, b1_len); | 
| 974 | 10 |  |  |  |  |  | n128_set_str_binary(&end_1_n128,   end_1,   b1_len); | 
| 975 | 10 |  |  |  |  |  | n128_set_str_binary(&end_2_n128,   end_2,   b1_len); | 
| 976 |  |  |  |  |  |  |  | 
| 977 | 10 |  |  |  |  |  | NI_ip_is_overlap_ipv6(&begin_1_n128, &end_1_n128, | 
| 978 |  |  |  |  |  |  | &begin_2_n128, &end_2_n128, result); | 
| 979 |  |  |  |  |  |  |  | 
| 980 | 23 |  |  |  |  |  | return 1; | 
| 981 |  |  |  |  |  |  | } | 
| 982 |  |  |  |  |  |  |  | 
| 983 |  |  |  |  |  |  | /** | 
| 984 |  |  |  |  |  |  | * NI_ip_check_prefix_ipv6(): check whether prefix length is valid. | 
| 985 |  |  |  |  |  |  | * @ip: IP address. | 
| 986 |  |  |  |  |  |  | * @len: the prefix length. | 
| 987 |  |  |  |  |  |  | */ | 
| 988 |  |  |  |  |  |  | int | 
| 989 | 50 |  |  |  |  |  | NI_ip_check_prefix_ipv6(n128_t *ip, int len) | 
| 990 |  |  |  |  |  |  | { | 
| 991 |  |  |  |  |  |  | n128_t mask; | 
| 992 |  |  |  |  |  |  | char buf[IPV6_BITSTR_LEN]; | 
| 993 |  |  |  |  |  |  | int i; | 
| 994 |  |  |  |  |  |  |  | 
| 995 | 50 | 100 |  |  |  |  | if ((len < 0) || (len > 128)) { | 
|  |  | 100 |  |  |  |  |  | 
| 996 | 2 |  |  |  |  |  | NI_set_Error_Errno(172, "Invalid prefix length /%d", len); | 
| 997 | 2 |  |  |  |  |  | return 0; | 
| 998 |  |  |  |  |  |  | } | 
| 999 |  |  |  |  |  |  |  | 
| 1000 | 48 |  |  |  |  |  | n128_set_ui(&mask, 0); | 
| 1001 | 4657 | 100 |  |  |  |  | for (i = 0; i < (128 - len); i++) { | 
| 1002 | 4609 |  |  |  |  |  | n128_setbit(&mask, i); | 
| 1003 |  |  |  |  |  |  | } | 
| 1004 | 48 |  |  |  |  |  | n128_and(&mask, ip); | 
| 1005 |  |  |  |  |  |  |  | 
| 1006 | 48 | 100 |  |  |  |  | if (n128_cmp_ui(&mask, 0)) { | 
| 1007 | 1 |  |  |  |  |  | NI_ip_n128tobin(ip, len, buf); | 
| 1008 | 1 |  |  |  |  |  | buf[len] = '\0'; | 
| 1009 | 1 |  |  |  |  |  | NI_set_Error_Errno(171, "Invalid prefix %s/%d", buf, len); | 
| 1010 | 1 |  |  |  |  |  | return 0; | 
| 1011 |  |  |  |  |  |  | } | 
| 1012 |  |  |  |  |  |  |  | 
| 1013 | 50 |  |  |  |  |  | return 1; | 
| 1014 |  |  |  |  |  |  | } | 
| 1015 |  |  |  |  |  |  |  | 
| 1016 |  |  |  |  |  |  | /** | 
| 1017 |  |  |  |  |  |  | * NI_ip_check_prefix_ipv4(): check whether prefix length is valid. | 
| 1018 |  |  |  |  |  |  | * @ip: IP address. | 
| 1019 |  |  |  |  |  |  | * @len: the prefix length. | 
| 1020 |  |  |  |  |  |  | */ | 
| 1021 |  |  |  |  |  |  | int | 
| 1022 | 64 |  |  |  |  |  | NI_ip_check_prefix_ipv4(unsigned long ip, int len) | 
| 1023 |  |  |  |  |  |  | { | 
| 1024 |  |  |  |  |  |  | unsigned long mask; | 
| 1025 |  |  |  |  |  |  |  | 
| 1026 | 64 | 100 |  |  |  |  | if ((len < 0) || (len > 32)) { | 
|  |  | 100 |  |  |  |  |  | 
| 1027 | 2 |  |  |  |  |  | NI_set_Error_Errno(172, "Invalid prefix length /%d", len); | 
| 1028 | 2 |  |  |  |  |  | return 0; | 
| 1029 |  |  |  |  |  |  | } | 
| 1030 |  |  |  |  |  |  |  | 
| 1031 | 62 | 100 |  |  |  |  | mask = (len == 0) ? 0xFFFFFFFF : ((1 << (32 - len)) - 1); | 
| 1032 |  |  |  |  |  |  |  | 
| 1033 | 62 | 100 |  |  |  |  | if ((ip & mask) != 0) { | 
| 1034 | 1 |  |  |  |  |  | NI_set_Error_Errno(171, "Invalid prefix %u/%d", ip, len); | 
| 1035 | 1 |  |  |  |  |  | return 0; | 
| 1036 |  |  |  |  |  |  | } | 
| 1037 |  |  |  |  |  |  |  | 
| 1038 | 61 |  |  |  |  |  | return 1; | 
| 1039 |  |  |  |  |  |  | } | 
| 1040 |  |  |  |  |  |  |  | 
| 1041 |  |  |  |  |  |  | /** | 
| 1042 |  |  |  |  |  |  | * NI_ip_check_prefix(): check whether prefix length is valid for address. | 
| 1043 |  |  |  |  |  |  | * @bitstr: the bitstring IP address. | 
| 1044 |  |  |  |  |  |  | * @len: the prefix length. | 
| 1045 |  |  |  |  |  |  | * @version: the IP address version. | 
| 1046 |  |  |  |  |  |  | * | 
| 1047 |  |  |  |  |  |  | * The bitstring must be null-terminated. | 
| 1048 |  |  |  |  |  |  | */ | 
| 1049 |  |  |  |  |  |  | int | 
| 1050 | 160 |  |  |  |  |  | NI_ip_check_prefix(const char *bitstr, int len, int version) | 
| 1051 |  |  |  |  |  |  | { | 
| 1052 |  |  |  |  |  |  | int iplen; | 
| 1053 |  |  |  |  |  |  | const char *c; | 
| 1054 |  |  |  |  |  |  |  | 
| 1055 | 160 | 100 |  |  |  |  | if (len < 0) { | 
| 1056 | 1 |  |  |  |  |  | NI_set_Error_Errno(172, "Invalid prefix length /%d", len); | 
| 1057 | 1 |  |  |  |  |  | return 0; | 
| 1058 |  |  |  |  |  |  | } | 
| 1059 |  |  |  |  |  |  |  | 
| 1060 | 159 |  |  |  |  |  | iplen = strlen(bitstr); | 
| 1061 |  |  |  |  |  |  |  | 
| 1062 | 159 | 100 |  |  |  |  | if (len > iplen) { | 
| 1063 | 1 |  |  |  |  |  | NI_set_Error_Errno(170, "Prefix length %d is longer than " | 
| 1064 |  |  |  |  |  |  | "IP address (%d)", len, iplen); | 
| 1065 | 1 |  |  |  |  |  | return 0; | 
| 1066 |  |  |  |  |  |  | } | 
| 1067 |  |  |  |  |  |  |  | 
| 1068 | 158 |  |  |  |  |  | c = bitstr + len; | 
| 1069 |  |  |  |  |  |  |  | 
| 1070 | 6218 | 100 |  |  |  |  | while (*c != '\0') { | 
| 1071 | 6062 | 100 |  |  |  |  | if (*c != '0') { | 
| 1072 | 2 |  |  |  |  |  | NI_set_Error_Errno(171, "Invalid prefix %s/%d", bitstr, len); | 
| 1073 | 2 |  |  |  |  |  | return 0; | 
| 1074 |  |  |  |  |  |  | } | 
| 1075 | 6060 |  |  |  |  |  | c++; | 
| 1076 |  |  |  |  |  |  | } | 
| 1077 |  |  |  |  |  |  |  | 
| 1078 | 156 | 100 |  |  |  |  | if (iplen != NI_iplengths(version)) { | 
| 1079 | 1 |  |  |  |  |  | NI_set_Error_Errno(172, "Invalid prefix length /%d", len); | 
| 1080 | 1 |  |  |  |  |  | return 0; | 
| 1081 |  |  |  |  |  |  | } | 
| 1082 |  |  |  |  |  |  |  | 
| 1083 | 155 |  |  |  |  |  | return 1; | 
| 1084 |  |  |  |  |  |  | } | 
| 1085 |  |  |  |  |  |  |  | 
| 1086 |  |  |  |  |  |  | /** | 
| 1087 |  |  |  |  |  |  | * NI_ip_get_prefix_length_ipv4(): get prefix length for a given range. | 
| 1088 |  |  |  |  |  |  | * @begin: first IP address. | 
| 1089 |  |  |  |  |  |  | * @end: second IP address. | 
| 1090 |  |  |  |  |  |  | * @bits: number of bits to check. | 
| 1091 |  |  |  |  |  |  | * @len: a pointer to an integer. | 
| 1092 |  |  |  |  |  |  | */ | 
| 1093 |  |  |  |  |  |  | void | 
| 1094 | 5561 |  |  |  |  |  | NI_ip_get_prefix_length_ipv4(unsigned long begin, unsigned long end, | 
| 1095 |  |  |  |  |  |  | int bits, int *len) | 
| 1096 |  |  |  |  |  |  | { | 
| 1097 |  |  |  |  |  |  | int i; | 
| 1098 | 5561 |  |  |  |  |  | int res = 0; | 
| 1099 |  |  |  |  |  |  |  | 
| 1100 | 110742 | 100 |  |  |  |  | for (i = 0; i < bits; i++) { | 
| 1101 | 110732 | 100 |  |  |  |  | if ((begin & 1) == (end & 1)) { | 
| 1102 | 5551 |  |  |  |  |  | res = bits - i; | 
| 1103 | 5551 |  |  |  |  |  | break; | 
| 1104 |  |  |  |  |  |  | } | 
| 1105 | 105181 |  |  |  |  |  | begin >>= 1; | 
| 1106 | 105181 |  |  |  |  |  | end   >>= 1; | 
| 1107 |  |  |  |  |  |  | } | 
| 1108 |  |  |  |  |  |  |  | 
| 1109 | 5561 |  |  |  |  |  | *len = res; | 
| 1110 | 5561 |  |  |  |  |  | } | 
| 1111 |  |  |  |  |  |  |  | 
| 1112 |  |  |  |  |  |  | /** | 
| 1113 |  |  |  |  |  |  | * NI_ip_get_prefix_length_ipv6(): get prefix length for a given range. | 
| 1114 |  |  |  |  |  |  | * @num1: first IP address as an N128 integer. | 
| 1115 |  |  |  |  |  |  | * @num2: second IP address as an N128 integer. | 
| 1116 |  |  |  |  |  |  | * @bits: number of bits to check | 
| 1117 |  |  |  |  |  |  | * @len: a pointer to an integer. | 
| 1118 |  |  |  |  |  |  | * | 
| 1119 |  |  |  |  |  |  | * Returns 1 or 0 depending on whether the prefix length could be | 
| 1120 |  |  |  |  |  |  | * calculated. Stores the prefix length in @len if it is able to be | 
| 1121 |  |  |  |  |  |  | * calculated. | 
| 1122 |  |  |  |  |  |  | */ | 
| 1123 |  |  |  |  |  |  | void | 
| 1124 | 15995 |  |  |  |  |  | NI_ip_get_prefix_length_ipv6(n128_t *num1, n128_t *num2, int bits, int *len) | 
| 1125 |  |  |  |  |  |  | { | 
| 1126 |  |  |  |  |  |  | int i; | 
| 1127 | 15995 |  |  |  |  |  | int res = 0; | 
| 1128 |  |  |  |  |  |  |  | 
| 1129 | 1316809 | 100 |  |  |  |  | for (i = 0; i < bits; i++) { | 
| 1130 | 1316777 | 100 |  |  |  |  | if (n128_tstbit(num1, i) == n128_tstbit(num2, i)) { | 
| 1131 | 15963 |  |  |  |  |  | res = bits - i; | 
| 1132 | 15963 |  |  |  |  |  | break; | 
| 1133 |  |  |  |  |  |  | } | 
| 1134 |  |  |  |  |  |  | } | 
| 1135 |  |  |  |  |  |  |  | 
| 1136 | 15995 |  |  |  |  |  | *len = res; | 
| 1137 | 15995 |  |  |  |  |  | } | 
| 1138 |  |  |  |  |  |  |  | 
| 1139 |  |  |  |  |  |  | /** | 
| 1140 |  |  |  |  |  |  | * NI_ip_get_prefix_length(): get prefix length for a given range. | 
| 1141 |  |  |  |  |  |  | * @bitstr_1: first IP address as a bitstring. | 
| 1142 |  |  |  |  |  |  | * @bitstr_2: second IP address as a bitstring. | 
| 1143 |  |  |  |  |  |  | * @len: a pointer to an integer. | 
| 1144 |  |  |  |  |  |  | * | 
| 1145 |  |  |  |  |  |  | * Returns 1 or 0 depending on whether the prefix length could be | 
| 1146 |  |  |  |  |  |  | * calculated. Stores the prefix length in @len if it is able to be | 
| 1147 |  |  |  |  |  |  | * calculated. | 
| 1148 |  |  |  |  |  |  | */ | 
| 1149 |  |  |  |  |  |  | int | 
| 1150 | 15 |  |  |  |  |  | NI_ip_get_prefix_length(const char *bitstr_1, const char *bitstr_2, int *len) | 
| 1151 |  |  |  |  |  |  | { | 
| 1152 |  |  |  |  |  |  | int bin1_len; | 
| 1153 |  |  |  |  |  |  | int bin2_len; | 
| 1154 |  |  |  |  |  |  | int i; | 
| 1155 |  |  |  |  |  |  | int res; | 
| 1156 |  |  |  |  |  |  |  | 
| 1157 | 15 |  |  |  |  |  | bin1_len = strlen(bitstr_1); | 
| 1158 | 15 |  |  |  |  |  | bin2_len = strlen(bitstr_2); | 
| 1159 |  |  |  |  |  |  |  | 
| 1160 | 15 | 100 |  |  |  |  | if (bin1_len != bin2_len) { | 
| 1161 | 1 |  |  |  |  |  | NI_set_Error_Errno(130, "IP addresses of different length"); | 
| 1162 | 1 |  |  |  |  |  | return 0; | 
| 1163 |  |  |  |  |  |  | } | 
| 1164 |  |  |  |  |  |  |  | 
| 1165 | 14 |  |  |  |  |  | res = bin1_len; | 
| 1166 |  |  |  |  |  |  |  | 
| 1167 | 245 | 100 |  |  |  |  | for (i = (bin1_len - 1); i >= 0; i--) { | 
| 1168 | 243 | 100 |  |  |  |  | if (bitstr_1[i] == bitstr_2[i]) { | 
| 1169 | 12 |  |  |  |  |  | res = (bin1_len - 1 - i); | 
| 1170 | 12 |  |  |  |  |  | break; | 
| 1171 |  |  |  |  |  |  | } | 
| 1172 |  |  |  |  |  |  | } | 
| 1173 |  |  |  |  |  |  |  | 
| 1174 | 14 |  |  |  |  |  | *len = res; | 
| 1175 | 14 |  |  |  |  |  | return 1; | 
| 1176 |  |  |  |  |  |  | } | 
| 1177 |  |  |  |  |  |  |  | 
| 1178 |  |  |  |  |  |  | /** | 
| 1179 |  |  |  |  |  |  | * NI_ip_inttoip_ipv4(): make IPv4 address from integer. | 
| 1180 |  |  |  |  |  |  | * @n: the IP address as a number. | 
| 1181 |  |  |  |  |  |  | * @buf: the IP address buffer. | 
| 1182 |  |  |  |  |  |  | */ | 
| 1183 |  |  |  |  |  |  | void | 
| 1184 | 7544 |  |  |  |  |  | NI_ip_inttoip_ipv4(unsigned long n, char *buf) | 
| 1185 |  |  |  |  |  |  | { | 
| 1186 | 22632 |  |  |  |  |  | sprintf(buf, "%lu.%lu.%lu.%lu", (n >> 24) & 0xFF, | 
| 1187 | 7544 |  |  |  |  |  | (n >> 16) & 0xFF, | 
| 1188 | 7544 |  |  |  |  |  | (n >> 8)  & 0xFF, | 
| 1189 |  |  |  |  |  |  | (n >> 0)  & 0xFF); | 
| 1190 | 7544 |  |  |  |  |  | } | 
| 1191 |  |  |  |  |  |  |  | 
| 1192 |  |  |  |  |  |  | /** | 
| 1193 |  |  |  |  |  |  | * NI_ip_inttoip_ipv6(): make IPv6 address from integers. | 
| 1194 |  |  |  |  |  |  | * @n1: the most significant 32 bits of the address. | 
| 1195 |  |  |  |  |  |  | * @n2: the next-most significant 32 bits of the address. | 
| 1196 |  |  |  |  |  |  | * @n3: the next-most significant 32 bits of the address. | 
| 1197 |  |  |  |  |  |  | * @n4: the least significant 32 bits of the address. | 
| 1198 |  |  |  |  |  |  | * @buf: the IP address buffer. | 
| 1199 |  |  |  |  |  |  | */ | 
| 1200 |  |  |  |  |  |  | void | 
| 1201 | 17525 |  |  |  |  |  | NI_ip_inttoip_ipv6(unsigned long n1, unsigned long n2, | 
| 1202 |  |  |  |  |  |  | unsigned long n3, unsigned long n4, char *buf) | 
| 1203 |  |  |  |  |  |  | { | 
| 1204 | 140200 |  |  |  |  |  | sprintf(buf, "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x", | 
| 1205 | 17525 |  |  |  |  |  | (unsigned int) (n1 >> 16) & 0xFFFF, | 
| 1206 | 17525 |  |  |  |  |  | (unsigned int) (n1      ) & 0xFFFF, | 
| 1207 | 17525 |  |  |  |  |  | (unsigned int) (n2 >> 16) & 0xFFFF, | 
| 1208 | 17525 |  |  |  |  |  | (unsigned int) (n2      ) & 0xFFFF, | 
| 1209 | 17525 |  |  |  |  |  | (unsigned int) (n3 >> 16) & 0xFFFF, | 
| 1210 | 17525 |  |  |  |  |  | (unsigned int) (n3      ) & 0xFFFF, | 
| 1211 | 17525 |  |  |  |  |  | (unsigned int) (n4 >> 16) & 0xFFFF, | 
| 1212 | 17525 |  |  |  |  |  | (unsigned int) (n4      ) & 0xFFFF); | 
| 1213 | 17525 |  |  |  |  |  | } | 
| 1214 |  |  |  |  |  |  |  | 
| 1215 |  |  |  |  |  |  | /** | 
| 1216 |  |  |  |  |  |  | * NI_ip_inttoip_n128(): make IPv6 address from N128 integer. | 
| 1217 |  |  |  |  |  |  | * @ip: IP address. | 
| 1218 |  |  |  |  |  |  | * @buf: the IP address buffer. | 
| 1219 |  |  |  |  |  |  | */ | 
| 1220 |  |  |  |  |  |  | void | 
| 1221 | 774 |  |  |  |  |  | NI_ip_inttoip_n128(n128_t *ip, char *buf) | 
| 1222 |  |  |  |  |  |  | { | 
| 1223 | 774 |  |  |  |  |  | NI_ip_inttoip_ipv6(ip->nums[0], ip->nums[1], | 
| 1224 | 1548 |  |  |  |  |  | ip->nums[2], ip->nums[3], buf); | 
| 1225 | 774 |  |  |  |  |  | } | 
| 1226 |  |  |  |  |  |  |  | 
| 1227 |  |  |  |  |  |  | /** | 
| 1228 |  |  |  |  |  |  | * NI_ip_bintoip(): make IP address from bitstring. | 
| 1229 |  |  |  |  |  |  | * @bitstr: the IP address as a bitstring. | 
| 1230 |  |  |  |  |  |  | * @version: IP address version as integer. | 
| 1231 |  |  |  |  |  |  | * @buf: the IP address buffer. | 
| 1232 |  |  |  |  |  |  | * | 
| 1233 |  |  |  |  |  |  | * The bitstring must be null-terminated. This function null-terminates the | 
| 1234 |  |  |  |  |  |  | * buffer, so it has to have between eight and sixteen characters' capacity | 
| 1235 |  |  |  |  |  |  | * (inclusive) for IPv4 addresses, depending on the value of the address, and | 
| 1236 |  |  |  |  |  |  | * 40 characters' capacity for IPv6 addresses. Bitstrings that have fewer | 
| 1237 |  |  |  |  |  |  | * characters than there are bits in the relevant version of IP address will be | 
| 1238 |  |  |  |  |  |  | * treated as if they were left-padded with '0' characters until that number of | 
| 1239 |  |  |  |  |  |  | * bits is met: e.g., passing "1" and 4 as the first two arguments to this | 
| 1240 |  |  |  |  |  |  | * function will yield "0.0.0.1" in @buf. | 
| 1241 |  |  |  |  |  |  | */ | 
| 1242 |  |  |  |  |  |  | int | 
| 1243 | 16037 |  |  |  |  |  | NI_ip_bintoip(const char *bitstr, int version, char *buf) | 
| 1244 |  |  |  |  |  |  | { | 
| 1245 |  |  |  |  |  |  | int size; | 
| 1246 |  |  |  |  |  |  | int iplen; | 
| 1247 |  |  |  |  |  |  | int longs; | 
| 1248 |  |  |  |  |  |  | int i; | 
| 1249 |  |  |  |  |  |  | int j; | 
| 1250 |  |  |  |  |  |  | int excess; | 
| 1251 |  |  |  |  |  |  | int bits; | 
| 1252 |  |  |  |  |  |  | unsigned long nums[4]; | 
| 1253 |  |  |  |  |  |  |  | 
| 1254 | 16037 |  |  |  |  |  | iplen = NI_iplengths(version); | 
| 1255 | 16037 |  |  |  |  |  | size  = strlen(bitstr); | 
| 1256 | 16037 | 100 |  |  |  |  | if (size > iplen) { | 
| 1257 | 4 |  |  |  |  |  | NI_set_Error_Errno(189, "Invalid IP length for " | 
| 1258 |  |  |  |  |  |  | "binary IP %s", bitstr); | 
| 1259 | 4 |  |  |  |  |  | return 0; | 
| 1260 |  |  |  |  |  |  | } | 
| 1261 |  |  |  |  |  |  |  | 
| 1262 | 16033 | 100 |  |  |  |  | if (version == 4) { | 
| 1263 | 24 |  |  |  |  |  | nums[0] = NI_bintoint(bitstr, size); | 
| 1264 | 24 |  |  |  |  |  | NI_ip_inttoip_ipv4(nums[0], buf); | 
| 1265 | 24 |  |  |  |  |  | return 1; | 
| 1266 |  |  |  |  |  |  | } | 
| 1267 |  |  |  |  |  |  |  | 
| 1268 | 80045 | 100 |  |  |  |  | for (i = 0; i < 4; i++) { | 
| 1269 | 64036 |  |  |  |  |  | nums[i] = 0; | 
| 1270 |  |  |  |  |  |  | } | 
| 1271 |  |  |  |  |  |  |  | 
| 1272 | 16009 |  |  |  |  |  | excess = size % 32; | 
| 1273 | 16009 |  |  |  |  |  | longs  = (size / 32) + (!excess ? 0 : 1); | 
| 1274 |  |  |  |  |  |  |  | 
| 1275 | 80020 | 100 |  |  |  |  | for (i = (4 - longs), j = 0; i < 4; i++, j++) { | 
| 1276 | 64011 |  |  |  |  |  | bits = | 
| 1277 | 16005 | 100 |  |  |  |  | (i == (4 - longs) && excess) | 
| 1278 |  |  |  |  |  |  | ? excess | 
| 1279 | 80016 | 100 |  |  |  |  | : 32; | 
| 1280 | 64011 |  |  |  |  |  | nums[i] = NI_bintoint(bitstr + (j * 32), bits); | 
| 1281 |  |  |  |  |  |  | } | 
| 1282 |  |  |  |  |  |  |  | 
| 1283 | 16009 |  |  |  |  |  | NI_ip_inttoip_ipv6(nums[0], nums[1], nums[2], nums[3], buf); | 
| 1284 | 16037 |  |  |  |  |  | return 1; | 
| 1285 |  |  |  |  |  |  | } | 
| 1286 |  |  |  |  |  |  |  | 
| 1287 |  |  |  |  |  |  | /** | 
| 1288 |  |  |  |  |  |  | * NI_ip_binadd(): add two bitstring IP addresses. | 
| 1289 |  |  |  |  |  |  | * @ip1: first bitstring IP address. | 
| 1290 |  |  |  |  |  |  | * @ip2: second bitstring IP address. | 
| 1291 |  |  |  |  |  |  | * @buf: result buffer. | 
| 1292 |  |  |  |  |  |  | * @maxlen: maximum capacity of buffer. | 
| 1293 |  |  |  |  |  |  | * | 
| 1294 |  |  |  |  |  |  | * Both bitstrings must be null-terminated and of the same length as | 
| 1295 |  |  |  |  |  |  | * each other. The result is stored as a bitstring and | 
| 1296 |  |  |  |  |  |  | * null-terminated. The result will be of the length of the | 
| 1297 |  |  |  |  |  |  | * bitstrings, regardless of the result of the addition. | 
| 1298 |  |  |  |  |  |  | */ | 
| 1299 |  |  |  |  |  |  | int | 
| 1300 | 17 |  |  |  |  |  | NI_ip_binadd(const char *ip1, const char *ip2, char *buf, int maxlen) | 
| 1301 |  |  |  |  |  |  | { | 
| 1302 |  |  |  |  |  |  | n128_t num1; | 
| 1303 |  |  |  |  |  |  | n128_t num2; | 
| 1304 |  |  |  |  |  |  | int len1; | 
| 1305 |  |  |  |  |  |  | int len2; | 
| 1306 |  |  |  |  |  |  |  | 
| 1307 | 17 |  |  |  |  |  | len1 = strlen(ip1); | 
| 1308 | 17 |  |  |  |  |  | len2 = strlen(ip2); | 
| 1309 |  |  |  |  |  |  |  | 
| 1310 | 17 | 100 |  |  |  |  | if (len1 != len2) { | 
| 1311 | 3 |  |  |  |  |  | NI_set_Error_Errno(130, "IP addresses of different length"); | 
| 1312 | 3 |  |  |  |  |  | return 0; | 
| 1313 |  |  |  |  |  |  | } | 
| 1314 | 14 | 100 |  |  |  |  | if (len1 > (maxlen - 1)) { | 
| 1315 | 2 |  |  |  |  |  | return 0; | 
| 1316 |  |  |  |  |  |  | } | 
| 1317 |  |  |  |  |  |  |  | 
| 1318 | 12 |  |  |  |  |  | n128_set_str_binary(&num1, ip1, len1); | 
| 1319 | 12 |  |  |  |  |  | n128_set_str_binary(&num2, ip2, len2); | 
| 1320 | 12 |  |  |  |  |  | n128_add(&num1, &num2); | 
| 1321 | 12 |  |  |  |  |  | NI_ip_n128tobin(&num1, len1, buf); | 
| 1322 |  |  |  |  |  |  |  | 
| 1323 | 12 |  |  |  |  |  | buf[len2] = '\0'; | 
| 1324 | 17 |  |  |  |  |  | return 1; | 
| 1325 |  |  |  |  |  |  | } | 
| 1326 |  |  |  |  |  |  |  | 
| 1327 |  |  |  |  |  |  | /** | 
| 1328 |  |  |  |  |  |  | * NI_ip_range_to_prefix_ipv4(): get prefixes contained within range. | 
| 1329 |  |  |  |  |  |  | * @begin: beginning address. | 
| 1330 |  |  |  |  |  |  | * @end: ending address. | 
| 1331 |  |  |  |  |  |  | * @version: IP address version. | 
| 1332 |  |  |  |  |  |  | * @prefixes: prefix strings buffer. | 
| 1333 |  |  |  |  |  |  | * @pcount: prefix count buffer. | 
| 1334 |  |  |  |  |  |  | * | 
| 1335 |  |  |  |  |  |  | * Will write at most 32 prefix strings to @prefixes. | 
| 1336 |  |  |  |  |  |  | */ | 
| 1337 |  |  |  |  |  |  | int | 
| 1338 | 519 |  |  |  |  |  | NI_ip_range_to_prefix_ipv4(unsigned long begin, unsigned long end, | 
| 1339 |  |  |  |  |  |  | int version, char **prefixes, int *pcount) | 
| 1340 |  |  |  |  |  |  | { | 
| 1341 |  |  |  |  |  |  | unsigned long current; | 
| 1342 |  |  |  |  |  |  | unsigned long mask; | 
| 1343 |  |  |  |  |  |  |  | 
| 1344 |  |  |  |  |  |  | unsigned long zeroes; | 
| 1345 |  |  |  |  |  |  | int iplen; | 
| 1346 |  |  |  |  |  |  | int res; | 
| 1347 |  |  |  |  |  |  | int i; | 
| 1348 |  |  |  |  |  |  | int prefix_length; | 
| 1349 |  |  |  |  |  |  | char *new_prefix; | 
| 1350 |  |  |  |  |  |  | char range[4]; | 
| 1351 |  |  |  |  |  |  |  | 
| 1352 | 519 |  |  |  |  |  | current = 0; | 
| 1353 | 519 |  |  |  |  |  | mask = 0; | 
| 1354 |  |  |  |  |  |  |  | 
| 1355 | 519 |  |  |  |  |  | iplen = NI_iplengths(version); | 
| 1356 |  |  |  |  |  |  |  | 
| 1357 | 519 |  |  |  |  |  | *pcount = 0; | 
| 1358 |  |  |  |  |  |  |  | 
| 1359 | 5638 | 100 |  |  |  |  | while (begin <= end) { | 
| 1360 |  |  |  |  |  |  | /* Calculate the number of zeroes that exist on the right of | 
| 1361 |  |  |  |  |  |  | * 'begin', and create a mask for that number of bits. */ | 
| 1362 | 5561 |  |  |  |  |  | zeroes = NI_trailing_zeroes(begin); | 
| 1363 | 5561 |  |  |  |  |  | mask = 0; | 
| 1364 |  |  |  |  |  |  |  | 
| 1365 | 113291 | 100 |  |  |  |  | for (i = 0; i < (int) zeroes; i++) { | 
| 1366 | 107730 |  |  |  |  |  | mask |= (1 << i); | 
| 1367 |  |  |  |  |  |  | } | 
| 1368 |  |  |  |  |  |  |  | 
| 1369 |  |  |  |  |  |  | /* Find the largest range (from 'begin' to 'current') that | 
| 1370 |  |  |  |  |  |  | * does not exceed 'end'. */ | 
| 1371 |  |  |  |  |  |  |  | 
| 1372 |  |  |  |  |  |  | do { | 
| 1373 | 8110 |  |  |  |  |  | current = begin; | 
| 1374 | 8110 |  |  |  |  |  | current |= mask; | 
| 1375 | 8110 |  |  |  |  |  | mask >>= 1; | 
| 1376 | 8110 | 100 |  |  |  |  | } while (current > end); | 
| 1377 |  |  |  |  |  |  |  | 
| 1378 |  |  |  |  |  |  | /* Get the prefix length for the range and add the stringified | 
| 1379 |  |  |  |  |  |  | * range to @prefixes. */ | 
| 1380 |  |  |  |  |  |  |  | 
| 1381 | 5561 |  |  |  |  |  | NI_ip_get_prefix_length_ipv4(begin, current, | 
| 1382 |  |  |  |  |  |  | iplen, &prefix_length); | 
| 1383 |  |  |  |  |  |  |  | 
| 1384 | 5561 |  |  |  |  |  | new_prefix = (char *) malloc(MAX_IPV4_RANGE_STR_LEN); | 
| 1385 | 5561 | 50 |  |  |  |  | if (!new_prefix) { | 
| 1386 | 0 |  |  |  |  |  | printf("NI_ip_range_to_prefix: malloc failed!\n"); | 
| 1387 | 0 |  |  |  |  |  | return 0; | 
| 1388 |  |  |  |  |  |  | } | 
| 1389 |  |  |  |  |  |  |  | 
| 1390 | 5561 |  |  |  |  |  | prefixes[(*pcount)++] = new_prefix; | 
| 1391 | 5561 |  |  |  |  |  | NI_ip_inttoip_ipv4(begin, new_prefix); | 
| 1392 | 5561 |  |  |  |  |  | strcat(new_prefix, "/"); | 
| 1393 | 5561 |  |  |  |  |  | res = snprintf(range, 4, "%d", prefix_length); | 
| 1394 | 5561 |  |  |  |  |  | strncat(new_prefix, range, res); | 
| 1395 |  |  |  |  |  |  |  | 
| 1396 | 5561 |  |  |  |  |  | begin = current + 1; | 
| 1397 |  |  |  |  |  |  |  | 
| 1398 |  |  |  |  |  |  | /* Do not continue getting prefixes if 'current' completely | 
| 1399 |  |  |  |  |  |  | * comprises set bits. */ | 
| 1400 |  |  |  |  |  |  |  | 
| 1401 | 5561 | 100 |  |  |  |  | if (current == 0xFFFFFFFF) { | 
| 1402 | 442 |  |  |  |  |  | break; | 
| 1403 |  |  |  |  |  |  | } | 
| 1404 |  |  |  |  |  |  | } | 
| 1405 |  |  |  |  |  |  |  | 
| 1406 | 519 |  |  |  |  |  | return 1; | 
| 1407 |  |  |  |  |  |  | } | 
| 1408 |  |  |  |  |  |  |  | 
| 1409 |  |  |  |  |  |  | /** | 
| 1410 |  |  |  |  |  |  | * NI_ip_range_to_prefix_ipv6(): get prefixes contained within range. | 
| 1411 |  |  |  |  |  |  | * @begin: beginning address. | 
| 1412 |  |  |  |  |  |  | * @end: ending address. | 
| 1413 |  |  |  |  |  |  | * @version: IP address version. | 
| 1414 |  |  |  |  |  |  | * @prefixes: prefix strings buffer. | 
| 1415 |  |  |  |  |  |  | * @pcount: prefix count buffer. | 
| 1416 |  |  |  |  |  |  | * | 
| 1417 |  |  |  |  |  |  | * Will write at most 128 prefix strings to @prefixes. | 
| 1418 |  |  |  |  |  |  | */ | 
| 1419 |  |  |  |  |  |  | int | 
| 1420 | 411 |  |  |  |  |  | NI_ip_range_to_prefix_ipv6(n128_t *begin, n128_t *end, | 
| 1421 |  |  |  |  |  |  | int version, char **prefixes, int *pcount) | 
| 1422 |  |  |  |  |  |  | { | 
| 1423 |  |  |  |  |  |  | n128_t current; | 
| 1424 |  |  |  |  |  |  | n128_t mask; | 
| 1425 |  |  |  |  |  |  | unsigned long zeroes; | 
| 1426 |  |  |  |  |  |  | int iplen; | 
| 1427 |  |  |  |  |  |  | unsigned long res; | 
| 1428 |  |  |  |  |  |  | int i; | 
| 1429 |  |  |  |  |  |  | int prefix_length; | 
| 1430 |  |  |  |  |  |  | char *new_prefix; | 
| 1431 |  |  |  |  |  |  | char tempip[IPV6_BITSTR_LEN]; | 
| 1432 |  |  |  |  |  |  | char range[4]; | 
| 1433 |  |  |  |  |  |  |  | 
| 1434 | 411 |  |  |  |  |  | iplen = NI_iplengths(version); | 
| 1435 |  |  |  |  |  |  |  | 
| 1436 | 411 |  |  |  |  |  | tempip[iplen] = '\0'; | 
| 1437 | 411 |  |  |  |  |  | *pcount = 0; | 
| 1438 |  |  |  |  |  |  |  | 
| 1439 | 16030 | 100 |  |  |  |  | while (n128_cmp(begin, end) <= 0) { | 
| 1440 | 15995 | 50 |  |  |  |  | if (*pcount == 128) { | 
| 1441 | 0 |  |  |  |  |  | return 0; | 
| 1442 |  |  |  |  |  |  | } | 
| 1443 |  |  |  |  |  |  |  | 
| 1444 |  |  |  |  |  |  | /* Calculate the number of zeroes that exist on the right of | 
| 1445 |  |  |  |  |  |  | * 'begin', and create a mask for that number of bits. */ | 
| 1446 |  |  |  |  |  |  |  | 
| 1447 | 15995 |  |  |  |  |  | zeroes = n128_scan1(begin); | 
| 1448 | 15995 | 100 |  |  |  |  | zeroes = ((zeroes == INT_MAX) ? (unsigned) iplen : zeroes) - 1; | 
| 1449 |  |  |  |  |  |  |  | 
| 1450 | 15995 |  |  |  |  |  | n128_set_ui(&mask, 0); | 
| 1451 | 1319844 | 100 |  |  |  |  | for (i = 0; i < ((int) zeroes + 1); i++) { | 
| 1452 | 1303849 |  |  |  |  |  | n128_setbit(&mask, i); | 
| 1453 |  |  |  |  |  |  | } | 
| 1454 |  |  |  |  |  |  |  | 
| 1455 |  |  |  |  |  |  | /* Find the largest range (from 'begin' to 'current') that | 
| 1456 |  |  |  |  |  |  | * does not exceed 'end'. */ | 
| 1457 |  |  |  |  |  |  |  | 
| 1458 |  |  |  |  |  |  | do { | 
| 1459 | 19030 |  |  |  |  |  | n128_set(¤t, begin); | 
| 1460 | 19030 |  |  |  |  |  | n128_ior(¤t, &mask); | 
| 1461 | 19030 |  |  |  |  |  | n128_clrbit(&mask, zeroes); | 
| 1462 | 19030 |  |  |  |  |  | zeroes--; | 
| 1463 | 19030 | 100 |  |  |  |  | } while (n128_cmp(¤t, end) > 0); | 
| 1464 |  |  |  |  |  |  |  | 
| 1465 |  |  |  |  |  |  | /* Get the prefix length for the range and add the stringified | 
| 1466 |  |  |  |  |  |  | * range to @prefixes. */ | 
| 1467 |  |  |  |  |  |  |  | 
| 1468 | 15995 |  |  |  |  |  | NI_ip_get_prefix_length_ipv6(begin, ¤t, | 
| 1469 |  |  |  |  |  |  | iplen, &prefix_length); | 
| 1470 |  |  |  |  |  |  |  | 
| 1471 | 15995 |  |  |  |  |  | new_prefix = (char *) malloc(MAX_IPV6_RANGE_STR_LEN); | 
| 1472 | 15995 | 50 |  |  |  |  | if (!new_prefix) { | 
| 1473 | 0 |  |  |  |  |  | printf("NI_ip_range_to_prefix: malloc failed!\n"); | 
| 1474 | 0 |  |  |  |  |  | return 0; | 
| 1475 |  |  |  |  |  |  | } | 
| 1476 |  |  |  |  |  |  |  | 
| 1477 | 15995 |  |  |  |  |  | prefixes[(*pcount)++] = new_prefix; | 
| 1478 | 15995 |  |  |  |  |  | NI_ip_n128tobin(begin, iplen, tempip); | 
| 1479 | 15995 |  |  |  |  |  | NI_ip_bintoip(tempip, version, new_prefix); | 
| 1480 | 15995 |  |  |  |  |  | strcat(new_prefix, "/"); | 
| 1481 | 15995 |  |  |  |  |  | res = snprintf(range, 4, "%d", prefix_length); | 
| 1482 | 15995 |  |  |  |  |  | strncat(new_prefix, range, res); | 
| 1483 |  |  |  |  |  |  |  | 
| 1484 | 15995 |  |  |  |  |  | n128_set(begin, ¤t); | 
| 1485 | 15995 |  |  |  |  |  | n128_add_ui(begin, 1); | 
| 1486 |  |  |  |  |  |  |  | 
| 1487 |  |  |  |  |  |  | /* Do not continue getting prefixes if 'current' completely | 
| 1488 |  |  |  |  |  |  | * comprises set bits. */ | 
| 1489 |  |  |  |  |  |  |  | 
| 1490 | 15995 |  |  |  |  |  | res = n128_scan0(¤t); | 
| 1491 | 15995 | 100 |  |  |  |  | if (res == INT_MAX) { | 
| 1492 | 376 |  |  |  |  |  | break; | 
| 1493 |  |  |  |  |  |  | } | 
| 1494 |  |  |  |  |  |  | } | 
| 1495 |  |  |  |  |  |  |  | 
| 1496 | 411 |  |  |  |  |  | return 1; | 
| 1497 |  |  |  |  |  |  | } | 
| 1498 |  |  |  |  |  |  |  | 
| 1499 |  |  |  |  |  |  | /** | 
| 1500 |  |  |  |  |  |  | * NI_ip_range_to_prefix(): get prefixes contained within range. | 
| 1501 |  |  |  |  |  |  | * @begin: first IP address as a bitstring. | 
| 1502 |  |  |  |  |  |  | * @end: second IP address as a bitstring. | 
| 1503 |  |  |  |  |  |  | * @version: IP address version. | 
| 1504 |  |  |  |  |  |  | * @prefixes: prefix strings buffer. | 
| 1505 |  |  |  |  |  |  | * @pcount: prefix count buffer. | 
| 1506 |  |  |  |  |  |  | * | 
| 1507 |  |  |  |  |  |  | * Both bitstrings must be null-terminated. If unsure of the number of | 
| 1508 |  |  |  |  |  |  | * prefixes that will be created, @prefixes must contain space for 128 | 
| 1509 |  |  |  |  |  |  | * character pointers. Returns 1/0 depending on whether it completed | 
| 1510 |  |  |  |  |  |  | * successfully. | 
| 1511 |  |  |  |  |  |  | */ | 
| 1512 |  |  |  |  |  |  | int | 
| 1513 | 923 |  |  |  |  |  | NI_ip_range_to_prefix(const char *begin, const char *end, | 
| 1514 |  |  |  |  |  |  | int version, char **prefixes, int *pcount) | 
| 1515 |  |  |  |  |  |  | { | 
| 1516 |  |  |  |  |  |  | n128_t begin_n128; | 
| 1517 |  |  |  |  |  |  | n128_t end_n128; | 
| 1518 |  |  |  |  |  |  | unsigned long begin_ulong; | 
| 1519 |  |  |  |  |  |  | unsigned long end_ulong; | 
| 1520 |  |  |  |  |  |  | int iplen; | 
| 1521 |  |  |  |  |  |  | int res; | 
| 1522 |  |  |  |  |  |  |  | 
| 1523 | 923 | 100 |  |  |  |  | if (!version) { | 
| 1524 | 2 |  |  |  |  |  | NI_set_Error_Errno(101, "Cannot determine IP version"); | 
| 1525 | 2 |  |  |  |  |  | return 0; | 
| 1526 |  |  |  |  |  |  | } | 
| 1527 |  |  |  |  |  |  |  | 
| 1528 | 921 | 100 |  |  |  |  | if (strlen(begin) != strlen(end)) { | 
| 1529 | 1 |  |  |  |  |  | NI_set_Error_Errno(130, "IP addresses of different length"); | 
| 1530 | 1 |  |  |  |  |  | return 0; | 
| 1531 |  |  |  |  |  |  | } | 
| 1532 |  |  |  |  |  |  |  | 
| 1533 | 920 |  |  |  |  |  | iplen = NI_iplengths(version); | 
| 1534 | 920 | 100 |  |  |  |  | if (!iplen) { | 
| 1535 | 1 |  |  |  |  |  | return 0; | 
| 1536 |  |  |  |  |  |  | } | 
| 1537 |  |  |  |  |  |  |  | 
| 1538 | 919 | 100 |  |  |  |  | if (version == 4) { | 
| 1539 | 513 |  |  |  |  |  | begin_ulong = NI_bintoint(begin, 32); | 
| 1540 | 513 |  |  |  |  |  | end_ulong   = NI_bintoint(end,   32); | 
| 1541 | 513 |  |  |  |  |  | return NI_ip_range_to_prefix_ipv4(begin_ulong, end_ulong, | 
| 1542 |  |  |  |  |  |  | version, prefixes, pcount); | 
| 1543 |  |  |  |  |  |  | } | 
| 1544 |  |  |  |  |  |  |  | 
| 1545 | 406 |  |  |  |  |  | n128_set_str_binary(&begin_n128, begin, strlen(begin)); | 
| 1546 | 406 |  |  |  |  |  | n128_set_str_binary(&end_n128,   end,   strlen(end)); | 
| 1547 |  |  |  |  |  |  |  | 
| 1548 | 406 |  |  |  |  |  | res = NI_ip_range_to_prefix_ipv6(&begin_n128, &end_n128, | 
| 1549 |  |  |  |  |  |  | version, prefixes, pcount); | 
| 1550 |  |  |  |  |  |  |  | 
| 1551 | 923 |  |  |  |  |  | return res; | 
| 1552 |  |  |  |  |  |  | } | 
| 1553 |  |  |  |  |  |  |  | 
| 1554 |  |  |  |  |  |  | /** | 
| 1555 |  |  |  |  |  |  | * NI_ip_aggregate_tail(): post-processing after version-specific aggregation. | 
| 1556 |  |  |  |  |  |  | * @res: the result of the relevant ip_range_to_prefix function. | 
| 1557 |  |  |  |  |  |  | * @prefixes: prefix strings buffer. | 
| 1558 |  |  |  |  |  |  | * @pcount: prefix count. | 
| 1559 |  |  |  |  |  |  | * @version: IP address version. | 
| 1560 |  |  |  |  |  |  | * @buf: the buffer for the new range. | 
| 1561 |  |  |  |  |  |  | * | 
| 1562 |  |  |  |  |  |  | * If @res is false, then frees the prefixes and returns zero. If no | 
| 1563 |  |  |  |  |  |  | * prefixes were returned, returns zero. If more than one prefix was | 
| 1564 |  |  |  |  |  |  |  | 
| 1565 |  |  |  |  |  |  | * returned, frees the prefixes and returns 161. Otherwise, populates | 
| 1566 |  |  |  |  |  |  | * the buffer (null-terminated) with the first range from @prefixes | 
| 1567 |  |  |  |  |  |  | * and returns 1. | 
| 1568 |  |  |  |  |  |  | */ | 
| 1569 |  |  |  |  |  |  | int | 
| 1570 | 11 |  |  |  |  |  | NI_ip_aggregate_tail(int res, char **prefixes, int pcount, | 
| 1571 |  |  |  |  |  |  | int version, char *buf) | 
| 1572 |  |  |  |  |  |  | { | 
| 1573 |  |  |  |  |  |  | int i; | 
| 1574 |  |  |  |  |  |  | int len; | 
| 1575 |  |  |  |  |  |  | int max; | 
| 1576 |  |  |  |  |  |  |  | 
| 1577 | 11 | 50 |  |  |  |  | if (!res) { | 
| 1578 | 0 | 0 |  |  |  |  | for (i = 0; i < pcount; i++) { | 
| 1579 | 0 |  |  |  |  |  | free(prefixes[i]); | 
| 1580 |  |  |  |  |  |  | } | 
| 1581 | 0 |  |  |  |  |  | return 0; | 
| 1582 |  |  |  |  |  |  | } | 
| 1583 |  |  |  |  |  |  |  | 
| 1584 | 11 | 100 |  |  |  |  | if (pcount == 0) { | 
| 1585 | 1 |  |  |  |  |  | return 0; | 
| 1586 |  |  |  |  |  |  | } | 
| 1587 |  |  |  |  |  |  |  | 
| 1588 | 10 | 100 |  |  |  |  | if (pcount > 1) { | 
| 1589 | 33 | 100 |  |  |  |  | for (i = 0; i < pcount; i++) { | 
| 1590 | 32 |  |  |  |  |  | free(prefixes[i]); | 
| 1591 |  |  |  |  |  |  | } | 
| 1592 | 1 |  |  |  |  |  | return 161; | 
| 1593 |  |  |  |  |  |  | } | 
| 1594 |  |  |  |  |  |  |  | 
| 1595 | 9 |  |  |  |  |  | len = strlen(*prefixes); | 
| 1596 | 9 |  |  |  |  |  | max = (version == 4) ? MAX_IPV4_RANGE_STR_LEN - 1 | 
| 1597 | 9 | 100 |  |  |  |  | : MAX_IPV6_RANGE_STR_LEN - 1; | 
| 1598 | 9 | 50 |  |  |  |  | if (len > max) { | 
| 1599 | 0 |  |  |  |  |  | len = max; | 
| 1600 |  |  |  |  |  |  | } | 
| 1601 |  |  |  |  |  |  |  | 
| 1602 | 9 |  |  |  |  |  | strncpy(buf, *prefixes, len); | 
| 1603 | 9 |  |  |  |  |  | buf[len] = 0; | 
| 1604 |  |  |  |  |  |  |  | 
| 1605 | 9 |  |  |  |  |  | return 1; | 
| 1606 |  |  |  |  |  |  | } | 
| 1607 |  |  |  |  |  |  |  | 
| 1608 |  |  |  |  |  |  | /** | 
| 1609 |  |  |  |  |  |  | * NI_ip_aggregate_ipv6(): get the aggregate range of two ranges as a string. | 
| 1610 |  |  |  |  |  |  | * @begin_1: beginning N128 integer IP address for first range. | 
| 1611 |  |  |  |  |  |  | * @end_1: ending N128 integer IP address for first range. | 
| 1612 |  |  |  |  |  |  | * @begin_2: beginning N128 integer IP address for second range. | 
| 1613 |  |  |  |  |  |  | * @end_2: ending N128 integer IP address for second range. | 
| 1614 |  |  |  |  |  |  | * @version: IP address version. | 
| 1615 |  |  |  |  |  |  | * @buf: the buffer for the new range. | 
| 1616 |  |  |  |  |  |  | * | 
| 1617 |  |  |  |  |  |  | * See NI_ip_aggregate(). | 
| 1618 |  |  |  |  |  |  | */ | 
| 1619 |  |  |  |  |  |  | int | 
| 1620 | 7 |  |  |  |  |  | NI_ip_aggregate_ipv6(n128_t *b1, n128_t *e1, n128_t *b2, n128_t *e2, | 
| 1621 |  |  |  |  |  |  | int version, char *buf) | 
| 1622 |  |  |  |  |  |  | { | 
| 1623 |  |  |  |  |  |  | char *prefixes[128]; | 
| 1624 |  |  |  |  |  |  | int pcount; | 
| 1625 |  |  |  |  |  |  | int res; | 
| 1626 |  |  |  |  |  |  |  | 
| 1627 | 7 |  |  |  |  |  | n128_add_ui(e1, 1); | 
| 1628 | 7 | 100 |  |  |  |  | if (n128_cmp(e1, b2)) { | 
| 1629 | 2 |  |  |  |  |  | return 160; | 
| 1630 |  |  |  |  |  |  | } | 
| 1631 |  |  |  |  |  |  |  | 
| 1632 | 5 |  |  |  |  |  | pcount = 0; | 
| 1633 | 5 |  |  |  |  |  | res = NI_ip_range_to_prefix_ipv6(b1, e2, version, prefixes, &pcount); | 
| 1634 | 7 |  |  |  |  |  | return NI_ip_aggregate_tail(res, prefixes, pcount, version, buf); | 
| 1635 |  |  |  |  |  |  | } | 
| 1636 |  |  |  |  |  |  |  | 
| 1637 |  |  |  |  |  |  | /** | 
| 1638 |  |  |  |  |  |  | * NI_ip_aggregate_ipv4(): get the aggregate range of two ranges as a string. | 
| 1639 |  |  |  |  |  |  | * @begin_1: beginning integer IP address for first range. | 
| 1640 |  |  |  |  |  |  | * @end_1: ending integer IP address for first range. | 
| 1641 |  |  |  |  |  |  | * @begin_2: beginning integer IP address for second range. | 
| 1642 |  |  |  |  |  |  | * @end_2: ending integer IP address for second range. | 
| 1643 |  |  |  |  |  |  | * @version: IP address version. | 
| 1644 |  |  |  |  |  |  | * @buf: the buffer for the new range. | 
| 1645 |  |  |  |  |  |  | * | 
| 1646 |  |  |  |  |  |  | * See NI_ip_aggregate(). | 
| 1647 |  |  |  |  |  |  | */ | 
| 1648 |  |  |  |  |  |  | int | 
| 1649 | 7 |  |  |  |  |  | NI_ip_aggregate_ipv4(unsigned long b1, unsigned long e1, | 
| 1650 |  |  |  |  |  |  | unsigned long b2, unsigned long e2, | 
| 1651 |  |  |  |  |  |  | int version, char *buf) | 
| 1652 |  |  |  |  |  |  | { | 
| 1653 |  |  |  |  |  |  | char *prefixes[128]; | 
| 1654 |  |  |  |  |  |  | int pcount; | 
| 1655 |  |  |  |  |  |  | int res; | 
| 1656 |  |  |  |  |  |  |  | 
| 1657 | 7 | 100 |  |  |  |  | if (e1 + 1 != b2) { | 
| 1658 | 1 |  |  |  |  |  | return 160; | 
| 1659 |  |  |  |  |  |  | } | 
| 1660 |  |  |  |  |  |  |  | 
| 1661 | 6 |  |  |  |  |  | pcount = 0; | 
| 1662 | 6 |  |  |  |  |  | res = NI_ip_range_to_prefix_ipv4(b1, e2, version, prefixes, &pcount); | 
| 1663 | 7 |  |  |  |  |  | return NI_ip_aggregate_tail(res, prefixes, pcount, version, buf); | 
| 1664 |  |  |  |  |  |  | } | 
| 1665 |  |  |  |  |  |  |  | 
| 1666 |  |  |  |  |  |  | /** | 
| 1667 |  |  |  |  |  |  | * NI_ip_aggregate(): get the aggregate range of two ranges as a string. | 
| 1668 |  |  |  |  |  |  | * @begin_1: beginning bitstring IP address for first range. | 
| 1669 |  |  |  |  |  |  | * @end_1: ending bitstring IP address for first range. | 
| 1670 |  |  |  |  |  |  | * @begin_2: beginning bitstring IP address for second range. | 
| 1671 |  |  |  |  |  |  | * @end_2: ending bitstring IP address for second range. | 
| 1672 |  |  |  |  |  |  | * @version: IP address version. | 
| 1673 |  |  |  |  |  |  | * @buf: the buffer for the new range. | 
| 1674 |  |  |  |  |  |  | * | 
| 1675 |  |  |  |  |  |  | * Returns zero and sets error messages if the ranges are not | 
| 1676 |  |  |  |  |  |  | * contiguous or the aggregate of the ranges cannot be represented as | 
| 1677 |  |  |  |  |  |  | * a single prefix. Otherwise, populates the buffer with the aggregate | 
| 1678 |  |  |  |  |  |  | * of the two ranges as a prefix range string (e.g. '1.0.0.0/8'). | 
| 1679 |  |  |  |  |  |  | */ | 
| 1680 |  |  |  |  |  |  | int | 
| 1681 | 14 |  |  |  |  |  | NI_ip_aggregate(const char *b1, const char *e1, | 
| 1682 |  |  |  |  |  |  | const char *b2, const char *e2, | 
| 1683 |  |  |  |  |  |  | int version, char *buf) | 
| 1684 |  |  |  |  |  |  | { | 
| 1685 |  |  |  |  |  |  | int res; | 
| 1686 |  |  |  |  |  |  | int i; | 
| 1687 |  |  |  |  |  |  | n128_t b1_n128; | 
| 1688 |  |  |  |  |  |  | n128_t e1_n128; | 
| 1689 |  |  |  |  |  |  | n128_t b2_n128; | 
| 1690 |  |  |  |  |  |  | n128_t e2_n128; | 
| 1691 |  |  |  |  |  |  | unsigned long b1_ulong; | 
| 1692 |  |  |  |  |  |  | unsigned long e1_ulong; | 
| 1693 |  |  |  |  |  |  | unsigned long b2_ulong; | 
| 1694 |  |  |  |  |  |  | unsigned long e2_ulong; | 
| 1695 |  |  |  |  |  |  | const char *addr_args[4]; | 
| 1696 | 14 |  |  |  |  |  | addr_args[0] = b1; | 
| 1697 | 14 |  |  |  |  |  | addr_args[1] = b2; | 
| 1698 | 14 |  |  |  |  |  | addr_args[2] = e1; | 
| 1699 | 14 |  |  |  |  |  | addr_args[3] = e2; | 
| 1700 |  |  |  |  |  |  |  | 
| 1701 | 14 | 100 |  |  |  |  | if (!version) { | 
| 1702 | 1 |  |  |  |  |  | NI_set_Error_Errno(101, "Cannot determine IP version for %s", | 
| 1703 |  |  |  |  |  |  | b1); | 
| 1704 | 1 |  |  |  |  |  | return 0; | 
| 1705 | 13 | 100 |  |  |  |  | } else if (version == 4) { | 
| 1706 | 31 | 100 |  |  |  |  | for (i = 0; i < 4; i++) { | 
| 1707 | 25 | 100 |  |  |  |  | if (strlen(addr_args[i]) != 32) { | 
| 1708 | 1 |  |  |  |  |  | NI_set_Error_Errno(107, "Invalid IP address %s", | 
| 1709 |  |  |  |  |  |  | addr_args[i]); | 
| 1710 | 1 |  |  |  |  |  | return 0; | 
| 1711 |  |  |  |  |  |  | } | 
| 1712 |  |  |  |  |  |  | } | 
| 1713 | 6 |  |  |  |  |  | b1_ulong = NI_bintoint(b1, 32); | 
| 1714 | 6 |  |  |  |  |  | e1_ulong = NI_bintoint(e1, 32); | 
| 1715 | 6 |  |  |  |  |  | b2_ulong = NI_bintoint(b2, 32); | 
| 1716 | 6 |  |  |  |  |  | e2_ulong = NI_bintoint(e2, 32); | 
| 1717 | 6 |  |  |  |  |  | res = NI_ip_aggregate_ipv4(b1_ulong, e1_ulong, | 
| 1718 |  |  |  |  |  |  | b2_ulong, e2_ulong, version, buf); | 
| 1719 |  |  |  |  |  |  | } else { | 
| 1720 | 26 | 100 |  |  |  |  | for (i = 0; i < 4; i++) { | 
| 1721 | 21 | 100 |  |  |  |  | if (strlen(addr_args[i]) != 128) { | 
| 1722 | 1 |  |  |  |  |  | NI_set_Error_Errno(108, "Invalid IP address %s", | 
| 1723 |  |  |  |  |  |  | addr_args[i]); | 
| 1724 | 1 |  |  |  |  |  | return 0; | 
| 1725 |  |  |  |  |  |  | } | 
| 1726 |  |  |  |  |  |  | } | 
| 1727 | 5 |  |  |  |  |  | n128_set_str_binary(&b1_n128, b1, strlen(b1)); | 
| 1728 | 5 |  |  |  |  |  | n128_set_str_binary(&e1_n128, e1, strlen(e1)); | 
| 1729 | 5 |  |  |  |  |  | n128_set_str_binary(&b2_n128, b2, strlen(b2)); | 
| 1730 | 5 |  |  |  |  |  | n128_set_str_binary(&e2_n128, e2, strlen(e2)); | 
| 1731 | 5 |  |  |  |  |  | res = NI_ip_aggregate_ipv6(&b1_n128, &e1_n128, | 
| 1732 |  |  |  |  |  |  | &b2_n128, &e2_n128, version, buf); | 
| 1733 |  |  |  |  |  |  | } | 
| 1734 |  |  |  |  |  |  |  | 
| 1735 | 11 | 100 |  |  |  |  | if (res == 0) { | 
| 1736 | 1 |  |  |  |  |  | return 0; | 
| 1737 |  |  |  |  |  |  | } | 
| 1738 | 10 | 100 |  |  |  |  | if (res == 160) { | 
| 1739 | 2 |  |  |  |  |  | NI_set_Error_Errno(160, "Ranges not contiguous - %s - %s", e1, b2); | 
| 1740 | 2 |  |  |  |  |  | return 0; | 
| 1741 |  |  |  |  |  |  | } | 
| 1742 | 8 | 100 |  |  |  |  | if (res == 161) { | 
| 1743 | 1 |  |  |  |  |  | NI_set_Error_Errno(161, "%s - %s is not a single prefix", b1, e2); | 
| 1744 | 1 |  |  |  |  |  | return 0; | 
| 1745 |  |  |  |  |  |  | } | 
| 1746 | 14 |  |  |  |  |  | return 1; | 
| 1747 |  |  |  |  |  |  | } | 
| 1748 |  |  |  |  |  |  |  | 
| 1749 |  |  |  |  |  |  | /** | 
| 1750 |  |  |  |  |  |  | * NI_ip_iptobin(): get bitstring from IP address. | 
| 1751 |  |  |  |  |  |  | * @ip: single IP address as a string. | 
| 1752 |  |  |  |  |  |  | * @version: IP address version. | 
| 1753 |  |  |  |  |  |  | * @buf: bitstring buffer. | 
| 1754 |  |  |  |  |  |  | * | 
| 1755 |  |  |  |  |  |  | * Returns zero (and may also set Error/Errno) if the IP address is | 
| 1756 |  |  |  |  |  |  | * invalid. If an IPv6 address is provided, it must be fully expanded | 
| 1757 |  |  |  |  |  |  | * - IPv6 addresses like '0::0' or '0:0:0:0:0:0:0:0' will not be | 
| 1758 |  |  |  |  |  |  | *   handled correctly. | 
| 1759 |  |  |  |  |  |  | */ | 
| 1760 |  |  |  |  |  |  |  | 
| 1761 |  |  |  |  |  |  | int | 
| 1762 | 2000 |  |  |  |  |  | NI_ip_iptobin(const char *ip, int ipversion, char *buf) | 
| 1763 |  |  |  |  |  |  | { | 
| 1764 |  |  |  |  |  |  | int res; | 
| 1765 |  |  |  |  |  |  | int j; | 
| 1766 |  |  |  |  |  |  | int k; | 
| 1767 |  |  |  |  |  |  | int y; | 
| 1768 |  |  |  |  |  |  | int i; | 
| 1769 |  |  |  |  |  |  | char c; | 
| 1770 |  |  |  |  |  |  | int ncount; | 
| 1771 |  |  |  |  |  |  | unsigned char ipv4[4]; | 
| 1772 |  |  |  |  |  |  |  | 
| 1773 | 2000 | 100 |  |  |  |  | if (ipversion == 4) { | 
| 1774 | 1131 |  |  |  |  |  | res = inet_pton4(ip, ipv4); | 
| 1775 | 1131 | 100 |  |  |  |  | if (res == 0) { | 
| 1776 | 4 |  |  |  |  |  | return 0; | 
| 1777 |  |  |  |  |  |  | } | 
| 1778 |  |  |  |  |  |  |  | 
| 1779 | 5635 | 100 |  |  |  |  | for (j = 0; j < 4; j++) { | 
| 1780 | 40572 | 100 |  |  |  |  | for (i = 0; i < 8; i++) { | 
| 1781 | 36064 | 100 |  |  |  |  | buf[(j * 8) + i] = | 
| 1782 | 36064 |  |  |  |  |  | ((ipv4[j] & (1 << (8 - i - 1)))) ? '1' : '0'; | 
| 1783 |  |  |  |  |  |  | } | 
| 1784 |  |  |  |  |  |  | } | 
| 1785 | 1127 |  |  |  |  |  | return 1; | 
| 1786 |  |  |  |  |  |  | } else { | 
| 1787 | 869 |  |  |  |  |  | j = 0; | 
| 1788 | 869 |  |  |  |  |  | ncount = 0; | 
| 1789 | 34618 | 100 |  |  |  |  | while ((c = ip[j])) { | 
| 1790 | 33749 | 100 |  |  |  |  | if (c != ':') { | 
| 1791 | 27701 |  |  |  |  |  | ncount++; | 
| 1792 |  |  |  |  |  |  | } | 
| 1793 | 33749 |  |  |  |  |  | j++; | 
| 1794 |  |  |  |  |  |  | } | 
| 1795 | 869 | 100 |  |  |  |  | if (ncount != 32) { | 
| 1796 | 4 |  |  |  |  |  | NI_set_Error_Errno(102, "Bad IP address %s", ip); | 
| 1797 | 4 |  |  |  |  |  | return 0; | 
| 1798 |  |  |  |  |  |  | } | 
| 1799 |  |  |  |  |  |  |  | 
| 1800 | 865 |  |  |  |  |  | i = -1; | 
| 1801 | 34499 | 100 |  |  |  |  | for (j = 0; ip[j] != '\0'; j++) { | 
| 1802 | 33637 | 100 |  |  |  |  | if (ip[j] == ':') { | 
| 1803 | 6031 |  |  |  |  |  | continue; | 
| 1804 |  |  |  |  |  |  | } else { | 
| 1805 | 27606 |  |  |  |  |  | i++; | 
| 1806 |  |  |  |  |  |  | } | 
| 1807 |  |  |  |  |  |  |  | 
| 1808 | 27606 |  |  |  |  |  | y = NI_hdtoi(ip[j]); | 
| 1809 | 27606 | 100 |  |  |  |  | if (y == -1) { | 
| 1810 | 3 |  |  |  |  |  | return 0; | 
| 1811 |  |  |  |  |  |  | } | 
| 1812 |  |  |  |  |  |  |  | 
| 1813 | 138015 | 100 |  |  |  |  | for (k = 0; k < 4; k++) { | 
| 1814 | 110412 | 100 |  |  |  |  | buf[ (i * 4) + k ] = | 
| 1815 | 110412 |  |  |  |  |  | ((y >> (3 - k)) & 1) ? '1' : '0'; | 
| 1816 |  |  |  |  |  |  | } | 
| 1817 |  |  |  |  |  |  | } | 
| 1818 | 2000 |  |  |  |  |  | return 1; | 
| 1819 |  |  |  |  |  |  | } | 
| 1820 |  |  |  |  |  |  | } | 
| 1821 |  |  |  |  |  |  |  | 
| 1822 |  |  |  |  |  |  | /** | 
| 1823 |  |  |  |  |  |  | * NI_ip_expand_address_ipv4(): expand an IPv4 address. | 
| 1824 |  |  |  |  |  |  | * @ip: the IPv4 address as a string. | 
| 1825 |  |  |  |  |  |  | * @buf: the IP address buffer. | 
| 1826 |  |  |  |  |  |  | * | 
| 1827 |  |  |  |  |  |  | * The IPv4 address string must be null-terminated. The buffer will be | 
| 1828 |  |  |  |  |  |  | * null-terminated on success. | 
| 1829 |  |  |  |  |  |  | */ | 
| 1830 |  |  |  |  |  |  | int | 
| 1831 | 969 |  |  |  |  |  | NI_ip_expand_address_ipv4(const char *ip, char *buf) | 
| 1832 |  |  |  |  |  |  | { | 
| 1833 |  |  |  |  |  |  | int res; | 
| 1834 |  |  |  |  |  |  | unsigned char ipv4[4]; | 
| 1835 |  |  |  |  |  |  |  | 
| 1836 | 969 |  |  |  |  |  | res = inet_pton4(ip, ipv4); | 
| 1837 | 969 | 100 |  |  |  |  | if (!res) { | 
| 1838 | 4 |  |  |  |  |  | return 0; | 
| 1839 |  |  |  |  |  |  | } | 
| 1840 |  |  |  |  |  |  |  | 
| 1841 | 965 |  |  |  |  |  | NI_ip_inttoip_ipv4(NI_ip_uchars_to_ulong(ipv4), buf); | 
| 1842 |  |  |  |  |  |  |  | 
| 1843 | 969 |  |  |  |  |  | return 1; | 
| 1844 |  |  |  |  |  |  | } | 
| 1845 |  |  |  |  |  |  |  | 
| 1846 |  |  |  |  |  |  | /** | 
| 1847 |  |  |  |  |  |  | * NI_ip_expand_address_ipv6(): expand an IPv6 address. | 
| 1848 |  |  |  |  |  |  | * @ip: the IPv6 address as a string. | 
| 1849 |  |  |  |  |  |  | * @buf: the IP address buffer. | 
| 1850 |  |  |  |  |  |  | * | 
| 1851 |  |  |  |  |  |  | * The IPv6 address string must be null-terminated. The buffer will be | 
| 1852 |  |  |  |  |  |  | * null-terminated on success. | 
| 1853 |  |  |  |  |  |  | */ | 
| 1854 |  |  |  |  |  |  | int | 
| 1855 | 753 |  |  |  |  |  | NI_ip_expand_address_ipv6(const char *ip, char *retbuf) | 
| 1856 |  |  |  |  |  |  | { | 
| 1857 |  |  |  |  |  |  | int res; | 
| 1858 |  |  |  |  |  |  | int i; | 
| 1859 |  |  |  |  |  |  | unsigned char ipv6[16]; | 
| 1860 |  |  |  |  |  |  | unsigned long n[4]; | 
| 1861 |  |  |  |  |  |  |  | 
| 1862 | 753 |  |  |  |  |  | res = inet_pton6(ip, ipv6); | 
| 1863 | 753 | 100 |  |  |  |  | if (!res) { | 
| 1864 | 11 |  |  |  |  |  | return 0; | 
| 1865 |  |  |  |  |  |  | } | 
| 1866 |  |  |  |  |  |  |  | 
| 1867 | 3710 | 100 |  |  |  |  | for (i = 0; i < 4; i++) { | 
| 1868 | 5936 |  |  |  |  |  | n[i] = (ipv6[(i * 4) + 0] << 24) | 
| 1869 | 2968 |  |  |  |  |  | | (ipv6[(i * 4) + 1] << 16) | 
| 1870 | 2968 |  |  |  |  |  | | (ipv6[(i * 4) + 2] << 8) | 
| 1871 | 2968 |  |  |  |  |  | | (ipv6[(i * 4) + 3]); | 
| 1872 |  |  |  |  |  |  | } | 
| 1873 |  |  |  |  |  |  |  | 
| 1874 | 742 |  |  |  |  |  | NI_ip_inttoip_ipv6(n[0], n[1], n[2], n[3], retbuf); | 
| 1875 |  |  |  |  |  |  |  | 
| 1876 | 753 |  |  |  |  |  | return 1; | 
| 1877 |  |  |  |  |  |  | } | 
| 1878 |  |  |  |  |  |  |  | 
| 1879 |  |  |  |  |  |  | /** | 
| 1880 |  |  |  |  |  |  | * NI_ip_expand_address(): expand an IP address. | 
| 1881 |  |  |  |  |  |  | * @ip: the IP address as a string. | 
| 1882 |  |  |  |  |  |  | * @version: the IP address version. | 
| 1883 |  |  |  |  |  |  | * @buf: the IP address buffer. | 
| 1884 |  |  |  |  |  |  | * | 
| 1885 |  |  |  |  |  |  | * See NI_ip_expand_address_ipv4() and NI_ip_expand_address_ipv6(). This | 
| 1886 |  |  |  |  |  |  | * function dispatches to one of those functions depending on the | 
| 1887 |  |  |  |  |  |  | * value of the @version argument. | 
| 1888 |  |  |  |  |  |  | */ | 
| 1889 |  |  |  |  |  |  | int | 
| 1890 | 1722 |  |  |  |  |  | NI_ip_expand_address(const char *ip, int version, char *buf) | 
| 1891 |  |  |  |  |  |  | { | 
| 1892 |  |  |  |  |  |  | return | 
| 1893 | 1722 |  |  |  |  |  | (version == 4) | 
| 1894 |  |  |  |  |  |  | ? NI_ip_expand_address_ipv4(ip, buf) | 
| 1895 | 1722 | 100 |  |  |  |  | : NI_ip_expand_address_ipv6(ip, buf); | 
| 1896 |  |  |  |  |  |  | } | 
| 1897 |  |  |  |  |  |  |  | 
| 1898 |  |  |  |  |  |  | /** | 
| 1899 |  |  |  |  |  |  | * NI_ip_reverse_ipv4(): get reverse domain for an IPv4 address. | 
| 1900 |  |  |  |  |  |  | * @ip: the IP address as a string. | 
| 1901 |  |  |  |  |  |  | * @len: the prefix length of the reverse domain. | 
| 1902 |  |  |  |  |  |  | * @buf: the reverse domain buffer. | 
| 1903 |  |  |  |  |  |  | * | 
| 1904 |  |  |  |  |  |  | * If the length is not evenly divisible by eight, then it will be | 
| 1905 |  |  |  |  |  |  | * treated as though it were the next number lower than it that is | 
| 1906 |  |  |  |  |  |  | * evenly divisible by eight when determining how many octets to | 
| 1907 |  |  |  |  |  |  | * print. So e.g. if the length is 31, three octets from the address | 
| 1908 |  |  |  |  |  |  | * will be included in the domain. The buffer is null-terminated. The | 
| 1909 |  |  |  |  |  |  | * longest possible IPv4 reverse domain name contains 25 characters | 
| 1910 |  |  |  |  |  |  | * (including the null terminator). | 
| 1911 |  |  |  |  |  |  | */ | 
| 1912 |  |  |  |  |  |  | int | 
| 1913 | 14 |  |  |  |  |  | NI_ip_reverse_ipv4(const char *ip, int len, char *buf) | 
| 1914 |  |  |  |  |  |  | { | 
| 1915 |  |  |  |  |  |  | int res; | 
| 1916 |  |  |  |  |  |  | int quads; | 
| 1917 |  |  |  |  |  |  | int i; | 
| 1918 |  |  |  |  |  |  | char numbuf[5]; | 
| 1919 |  |  |  |  |  |  | unsigned char ipv4[4]; | 
| 1920 |  |  |  |  |  |  |  | 
| 1921 | 14 | 100 |  |  |  |  | if ((len < 0) || (len > 32)) { | 
|  |  | 100 |  |  |  |  |  | 
| 1922 | 2 |  |  |  |  |  | return 0; | 
| 1923 |  |  |  |  |  |  | } | 
| 1924 | 12 |  |  |  |  |  | quads = len / 8; | 
| 1925 |  |  |  |  |  |  |  | 
| 1926 | 12 |  |  |  |  |  | res = inet_pton4(ip, ipv4); | 
| 1927 | 12 | 100 |  |  |  |  | if (!res) { | 
| 1928 | 1 |  |  |  |  |  | return 0; | 
| 1929 |  |  |  |  |  |  | } | 
| 1930 |  |  |  |  |  |  |  | 
| 1931 | 39 | 100 |  |  |  |  | for (i = (quads - 1); i >= 0; i--) { | 
| 1932 | 28 |  |  |  |  |  | sprintf(numbuf, "%u.", ipv4[i]); | 
| 1933 | 28 |  |  |  |  |  | strcat(buf, numbuf); | 
| 1934 |  |  |  |  |  |  | } | 
| 1935 |  |  |  |  |  |  |  | 
| 1936 | 11 |  |  |  |  |  | strcat(buf, "in-addr.arpa."); | 
| 1937 | 14 |  |  |  |  |  | return 1; | 
| 1938 |  |  |  |  |  |  | } | 
| 1939 |  |  |  |  |  |  |  | 
| 1940 |  |  |  |  |  |  | /** | 
| 1941 |  |  |  |  |  |  | * NI_ip_reverse_ipv6(): get reverse domain for an IPv4 address. | 
| 1942 |  |  |  |  |  |  | * @ip: the IP address as a string. | 
| 1943 |  |  |  |  |  |  | * @len: the prefix length of the reverse domain. | 
| 1944 |  |  |  |  |  |  | * @buf: the reverse domain buffer. | 
| 1945 |  |  |  |  |  |  | * | 
| 1946 |  |  |  |  |  |  | * If the length is not evenly divisible by four, then it will be | 
| 1947 |  |  |  |  |  |  | * treated as though it were the next number lower than it that is | 
| 1948 |  |  |  |  |  |  | * evenly divisible by four when determining how many nibbles to | 
| 1949 |  |  |  |  |  |  | * print. So e.g. if the length is 10, two nibbles from the address | 
| 1950 |  |  |  |  |  |  | * will be included in the domain. The buffer is null-terminated. The | 
| 1951 |  |  |  |  |  |  | * longest possible IPv6 reverse domain name contains 74 characters | 
| 1952 |  |  |  |  |  |  | * (including the null terminator). | 
| 1953 |  |  |  |  |  |  | */ | 
| 1954 |  |  |  |  |  |  | int | 
| 1955 | 19 |  |  |  |  |  | NI_ip_reverse_ipv6(const char *ip, int len, char *buf) | 
| 1956 |  |  |  |  |  |  | { | 
| 1957 |  |  |  |  |  |  | int res; | 
| 1958 |  |  |  |  |  |  | int i; | 
| 1959 |  |  |  |  |  |  | int index; | 
| 1960 |  |  |  |  |  |  | int shift; | 
| 1961 |  |  |  |  |  |  | unsigned char ipv6[16]; | 
| 1962 |  |  |  |  |  |  |  | 
| 1963 | 19 | 100 |  |  |  |  | if ((len < 0) || (len > 128)) { | 
|  |  | 100 |  |  |  |  |  | 
| 1964 | 2 |  |  |  |  |  | return 0; | 
| 1965 |  |  |  |  |  |  | } | 
| 1966 | 17 |  |  |  |  |  | len = (len / 4); | 
| 1967 |  |  |  |  |  |  |  | 
| 1968 | 17 |  |  |  |  |  | res = inet_pton6(ip, ipv6); | 
| 1969 | 17 | 100 |  |  |  |  | if (!res) { | 
| 1970 | 1 |  |  |  |  |  | return 0; | 
| 1971 |  |  |  |  |  |  | } | 
| 1972 |  |  |  |  |  |  |  | 
| 1973 | 126 | 100 |  |  |  |  | for (i = (len - 1); i >= 0; i--) { | 
| 1974 | 110 |  |  |  |  |  | index = i / 2; | 
| 1975 | 110 | 100 |  |  |  |  | shift = !(i % 2) * 4; | 
| 1976 | 110 |  |  |  |  |  | sprintf(buf, "%x.", ((ipv6[index] >> shift) & 0xF)); | 
| 1977 | 110 |  |  |  |  |  | buf += 2; | 
| 1978 |  |  |  |  |  |  | } | 
| 1979 | 16 |  |  |  |  |  | strcat(buf, "ip6.arpa."); | 
| 1980 | 19 |  |  |  |  |  | return 1; | 
| 1981 |  |  |  |  |  |  | } | 
| 1982 |  |  |  |  |  |  |  | 
| 1983 |  |  |  |  |  |  | /** | 
| 1984 |  |  |  |  |  |  | * NI_ip_reverse(): get reverse domain for an IP address. | 
| 1985 |  |  |  |  |  |  | * @ip: the IP address as a string. | 
| 1986 |  |  |  |  |  |  | * @len: the prefix length of the reverse domain. | 
| 1987 |  |  |  |  |  |  | * @buf: the reverse domain buffer. | 
| 1988 |  |  |  |  |  |  | * | 
| 1989 |  |  |  |  |  |  | * See NI_ip_reverse_ipv4() and NI_ip_reverse_ipv6(). | 
| 1990 |  |  |  |  |  |  | */ | 
| 1991 |  |  |  |  |  |  | int | 
| 1992 | 35 |  |  |  |  |  | NI_ip_reverse(const char *ip, int len, int ipversion, char *buf) | 
| 1993 |  |  |  |  |  |  | { | 
| 1994 | 35 | 100 |  |  |  |  | if (!ipversion) { | 
| 1995 | 1 |  |  |  |  |  | ipversion = NI_ip_get_version(ip); | 
| 1996 |  |  |  |  |  |  | } | 
| 1997 | 35 | 100 |  |  |  |  | if (!ipversion) { | 
| 1998 | 1 |  |  |  |  |  | NI_set_Error_Errno(101, "Cannot determine IP " | 
| 1999 |  |  |  |  |  |  | "version for %s", ip); | 
| 2000 | 1 |  |  |  |  |  | return 0; | 
| 2001 |  |  |  |  |  |  | } | 
| 2002 |  |  |  |  |  |  |  | 
| 2003 | 34 | 100 |  |  |  |  | if (ipversion == 4) { | 
| 2004 | 14 |  |  |  |  |  | return NI_ip_reverse_ipv4(ip, len, buf); | 
| 2005 | 20 | 100 |  |  |  |  | } else if (ipversion == 6) { | 
| 2006 | 19 |  |  |  |  |  | return NI_ip_reverse_ipv6(ip, len, buf); | 
| 2007 |  |  |  |  |  |  | } | 
| 2008 |  |  |  |  |  |  |  | 
| 2009 | 1 |  |  |  |  |  | return 0; | 
| 2010 |  |  |  |  |  |  | } | 
| 2011 |  |  |  |  |  |  |  | 
| 2012 |  |  |  |  |  |  | /** | 
| 2013 |  |  |  |  |  |  | * NI_ip_normalize_prefix_ipv4(): get first and last address from prefix range. | 
| 2014 |  |  |  |  |  |  | * @ip: IP address. | 
| 2015 |  |  |  |  |  |  | * @slash: pointer to first '/' in original string. | 
| 2016 |  |  |  |  |  |  | * @ip1buf: first IP address buffer. | 
| 2017 |  |  |  |  |  |  | * @ip2buf: second IP address buffer. | 
| 2018 |  |  |  |  |  |  | * | 
| 2019 |  |  |  |  |  |  | * Both buffers are null-terminated on success. | 
| 2020 |  |  |  |  |  |  | */ | 
| 2021 |  |  |  |  |  |  | int | 
| 2022 | 63 |  |  |  |  |  | NI_ip_normalize_prefix_ipv4(unsigned long ip, char *slash, | 
| 2023 |  |  |  |  |  |  | char *ip1buf, char *ip2buf) | 
| 2024 |  |  |  |  |  |  | { | 
| 2025 |  |  |  |  |  |  | unsigned long current; | 
| 2026 | 63 |  |  |  |  |  | char *endptr = NULL; | 
| 2027 |  |  |  |  |  |  | int res; | 
| 2028 | 63 |  |  |  |  |  | long clen  = 0; | 
| 2029 | 63 |  |  |  |  |  | int addcst = 0; | 
| 2030 |  |  |  |  |  |  | char c; | 
| 2031 |  |  |  |  |  |  |  | 
| 2032 | 63 |  |  |  |  |  | current = ip; | 
| 2033 |  |  |  |  |  |  |  | 
| 2034 |  |  |  |  |  |  | for (;;) { | 
| 2035 | 124 |  |  |  |  |  | c = *slash++; | 
| 2036 | 124 | 100 |  |  |  |  | if (c != '/') { | 
| 2037 | 54 |  |  |  |  |  | break; | 
| 2038 |  |  |  |  |  |  | } | 
| 2039 |  |  |  |  |  |  |  | 
| 2040 | 70 |  |  |  |  |  | endptr = NULL; | 
| 2041 |  |  |  |  |  |  |  | 
| 2042 | 70 |  |  |  |  |  | clen = strtol(slash, &endptr, 10); | 
| 2043 | 70 | 50 |  |  |  |  | if (STRTOL_FAILED(clen, slash, endptr)) { | 
|  |  | 50 |  |  |  |  |  | 
|  |  | 0 |  |  |  |  |  | 
|  |  | 100 |  |  |  |  |  | 
|  |  | 100 |  |  |  |  |  | 
| 2044 | 3 |  |  |  |  |  | return 0; | 
| 2045 |  |  |  |  |  |  | } | 
| 2046 | 67 | 100 |  |  |  |  | if (*endptr == ',') { | 
| 2047 | 8 |  |  |  |  |  | addcst = 1; | 
| 2048 | 59 | 100 |  |  |  |  | } else if (endptr != (slash + strlen(slash))) { | 
| 2049 | 3 |  |  |  |  |  | NI_set_Error_Errno(172, "Invalid prefix length /%s", slash); | 
| 2050 | 3 |  |  |  |  |  | return 0; | 
| 2051 |  |  |  |  |  |  | } else { | 
| 2052 | 56 |  |  |  |  |  | addcst = 0; | 
| 2053 |  |  |  |  |  |  | } | 
| 2054 |  |  |  |  |  |  |  | 
| 2055 | 64 |  |  |  |  |  | res = NI_ip_check_prefix_ipv4(current, clen); | 
| 2056 | 64 | 100 |  |  |  |  | if (!res) { | 
| 2057 | 3 |  |  |  |  |  | return 0; | 
| 2058 |  |  |  |  |  |  | } | 
| 2059 |  |  |  |  |  |  |  | 
| 2060 | 61 |  |  |  |  |  | current = NI_ip_last_address_ipv4(current, clen); | 
| 2061 |  |  |  |  |  |  |  | 
| 2062 | 61 | 100 |  |  |  |  | if (addcst) { | 
| 2063 | 8 |  |  |  |  |  | current += 1; | 
| 2064 | 8 |  |  |  |  |  | slash = endptr + 1; | 
| 2065 |  |  |  |  |  |  | } | 
| 2066 | 61 |  |  |  |  |  | } | 
| 2067 |  |  |  |  |  |  |  | 
| 2068 | 54 |  |  |  |  |  | NI_ip_inttoip_ipv4(ip,      ip1buf); | 
| 2069 | 54 |  |  |  |  |  | NI_ip_inttoip_ipv4(current, ip2buf); | 
| 2070 |  |  |  |  |  |  |  | 
| 2071 | 63 |  |  |  |  |  | return 2; | 
| 2072 |  |  |  |  |  |  | } | 
| 2073 |  |  |  |  |  |  |  | 
| 2074 |  |  |  |  |  |  | /** | 
| 2075 |  |  |  |  |  |  | * NI_ip_normalize_prefix_ipv6(): get first and last address from prefix range. | 
| 2076 |  |  |  |  |  |  | * @ip: IP address (N128 integer). | 
| 2077 |  |  |  |  |  |  | * @slash: pointer to first '/' in original string. | 
| 2078 |  |  |  |  |  |  | * @ip1buf: first IP address buffer. | 
| 2079 |  |  |  |  |  |  | * @ip2buf: second IP address buffer. | 
| 2080 |  |  |  |  |  |  | * | 
| 2081 |  |  |  |  |  |  | * Both buffers are null-terminated on success. | 
| 2082 |  |  |  |  |  |  | */ | 
| 2083 |  |  |  |  |  |  | int | 
| 2084 | 48 |  |  |  |  |  | NI_ip_normalize_prefix_ipv6(n128_t *ip, char *slash, | 
| 2085 |  |  |  |  |  |  | char *ip1buf, char *ip2buf) | 
| 2086 |  |  |  |  |  |  | { | 
| 2087 |  |  |  |  |  |  | n128_t current; | 
| 2088 | 48 |  |  |  |  |  | char *endptr = NULL; | 
| 2089 |  |  |  |  |  |  | int res; | 
| 2090 | 48 |  |  |  |  |  | long clen  = 0; | 
| 2091 | 48 |  |  |  |  |  | int addcst = 0; | 
| 2092 |  |  |  |  |  |  | char c; | 
| 2093 |  |  |  |  |  |  |  | 
| 2094 | 48 |  |  |  |  |  | n128_set(¤t, ip); | 
| 2095 |  |  |  |  |  |  |  | 
| 2096 |  |  |  |  |  |  | for (;;) { | 
| 2097 | 95 |  |  |  |  |  | c = *slash++; | 
| 2098 | 95 | 100 |  |  |  |  | if (c != '/') { | 
| 2099 | 42 |  |  |  |  |  | break; | 
| 2100 |  |  |  |  |  |  | } | 
| 2101 |  |  |  |  |  |  |  | 
| 2102 | 53 |  |  |  |  |  | endptr = NULL; | 
| 2103 |  |  |  |  |  |  |  | 
| 2104 | 53 |  |  |  |  |  | clen = strtol(slash, &endptr, 10); | 
| 2105 | 53 | 50 |  |  |  |  | if (STRTOL_FAILED(clen, slash, endptr)) { | 
|  |  | 50 |  |  |  |  |  | 
|  |  | 0 |  |  |  |  |  | 
|  |  | 100 |  |  |  |  |  | 
|  |  | 100 |  |  |  |  |  | 
| 2106 | 1 |  |  |  |  |  | return 0; | 
| 2107 |  |  |  |  |  |  | } | 
| 2108 | 52 | 100 |  |  |  |  | if (*endptr == ',') { | 
| 2109 | 5 |  |  |  |  |  | addcst = 1; | 
| 2110 | 47 | 100 |  |  |  |  | } else if (endptr != (slash + strlen(slash))) { | 
| 2111 | 2 |  |  |  |  |  | NI_set_Error_Errno(172, "Invalid prefix length /%s", slash); | 
| 2112 | 2 |  |  |  |  |  | return 0; | 
| 2113 |  |  |  |  |  |  | } else { | 
| 2114 | 45 |  |  |  |  |  | addcst = 0; | 
| 2115 |  |  |  |  |  |  | } | 
| 2116 |  |  |  |  |  |  |  | 
| 2117 | 50 |  |  |  |  |  | res = NI_ip_check_prefix_ipv6(¤t, clen); | 
| 2118 | 50 | 100 |  |  |  |  | if (!res) { | 
| 2119 | 3 |  |  |  |  |  | return 0; | 
| 2120 |  |  |  |  |  |  | } | 
| 2121 |  |  |  |  |  |  |  | 
| 2122 | 47 |  |  |  |  |  | NI_ip_last_address_ipv6(¤t, clen, ¤t); | 
| 2123 |  |  |  |  |  |  |  | 
| 2124 | 47 | 100 |  |  |  |  | if (addcst) { | 
| 2125 | 5 |  |  |  |  |  | n128_add_ui(¤t, 1); | 
| 2126 | 5 |  |  |  |  |  | slash = endptr + 1; | 
| 2127 |  |  |  |  |  |  | } | 
| 2128 | 47 |  |  |  |  |  | } | 
| 2129 |  |  |  |  |  |  |  | 
| 2130 | 42 |  |  |  |  |  | NI_ip_inttoip_n128(ip,       ip1buf); | 
| 2131 | 42 |  |  |  |  |  | NI_ip_inttoip_n128(¤t, ip2buf); | 
| 2132 |  |  |  |  |  |  |  | 
| 2133 | 48 |  |  |  |  |  | return 2; | 
| 2134 |  |  |  |  |  |  | } | 
| 2135 |  |  |  |  |  |  |  | 
| 2136 |  |  |  |  |  |  | /** | 
| 2137 |  |  |  |  |  |  | * NI_ip_normalize_prefix(): get first and last address from prefix range. | 
| 2138 |  |  |  |  |  |  | * @ip: IP address prefix range as a string. | 
| 2139 |  |  |  |  |  |  | * @ip1buf: first IP address buffer. | 
| 2140 |  |  |  |  |  |  | * @ip2buf: second IP address buffer. | 
| 2141 |  |  |  |  |  |  | * | 
| 2142 |  |  |  |  |  |  | * The range can include commas and additional prefixes, e.g. | 
| 2143 |  |  |  |  |  |  | * '0.0.0.0/32,/32,/32' will yield '0.0.0.0' and '0.0.0.2'. | 
| 2144 |  |  |  |  |  |  | */ | 
| 2145 |  |  |  |  |  |  | int | 
| 2146 | 978 |  |  |  |  |  | NI_ip_normalize_prefix(char *ip, char *ip1buf, char *ip2buf) | 
| 2147 |  |  |  |  |  |  | { | 
| 2148 |  |  |  |  |  |  | char c; | 
| 2149 |  |  |  |  |  |  | int res; | 
| 2150 |  |  |  |  |  |  | int i; | 
| 2151 |  |  |  |  |  |  | char *slash; | 
| 2152 |  |  |  |  |  |  | int islash; | 
| 2153 |  |  |  |  |  |  | char *start; | 
| 2154 |  |  |  |  |  |  | unsigned char ipnum[16]; | 
| 2155 |  |  |  |  |  |  | unsigned long ipv4; | 
| 2156 |  |  |  |  |  |  | n128_t ipv6; | 
| 2157 |  |  |  |  |  |  | int ipversion; | 
| 2158 |  |  |  |  |  |  |  | 
| 2159 | 978 |  |  |  |  |  | i      = 0; | 
| 2160 | 978 |  |  |  |  |  | slash  = NULL; | 
| 2161 | 978 |  |  |  |  |  | islash = -1; | 
| 2162 | 978 |  |  |  |  |  | start  = ip; | 
| 2163 |  |  |  |  |  |  |  | 
| 2164 | 24087 | 100 |  |  |  |  | while ((c = *ip)) { | 
| 2165 | 23930 | 100 |  |  |  |  | if (isspace(c)) { | 
| 2166 | 821 |  |  |  |  |  | return -1; | 
| 2167 |  |  |  |  |  |  | } | 
| 2168 | 23109 | 100 |  |  |  |  | if (i && (c == '/') && (!slash)) { | 
|  |  | 100 |  |  |  |  |  | 
|  |  | 100 |  |  |  |  |  | 
| 2169 | 112 |  |  |  |  |  | slash  = ip; | 
| 2170 | 112 |  |  |  |  |  | islash = i; | 
| 2171 |  |  |  |  |  |  | } | 
| 2172 | 23109 |  |  |  |  |  | i++; | 
| 2173 | 23109 |  |  |  |  |  | ip++; | 
| 2174 |  |  |  |  |  |  | } | 
| 2175 |  |  |  |  |  |  |  | 
| 2176 | 157 | 100 |  |  |  |  | if (islash < 1) { | 
| 2177 | 45 |  |  |  |  |  | return -1; | 
| 2178 |  |  |  |  |  |  | } | 
| 2179 |  |  |  |  |  |  |  | 
| 2180 | 112 |  |  |  |  |  | *slash = '\0'; | 
| 2181 | 112 |  |  |  |  |  | ipversion = NI_ip_get_version(start); | 
| 2182 |  |  |  |  |  |  |  | 
| 2183 | 112 | 100 |  |  |  |  | if (ipversion == 4) { | 
| 2184 | 63 |  |  |  |  |  | res = inet_pton4(start, ipnum); | 
| 2185 | 63 | 50 |  |  |  |  | if (!res) { | 
| 2186 | 0 |  |  |  |  |  | return 0; | 
| 2187 |  |  |  |  |  |  | } | 
| 2188 | 63 |  |  |  |  |  | *slash = '/'; | 
| 2189 | 63 |  |  |  |  |  | ipv4 = NI_ip_uchars_to_ulong(ipnum); | 
| 2190 | 63 |  |  |  |  |  | return NI_ip_normalize_prefix_ipv4(ipv4, | 
| 2191 |  |  |  |  |  |  | slash, | 
| 2192 |  |  |  |  |  |  | ip1buf, | 
| 2193 |  |  |  |  |  |  | ip2buf); | 
| 2194 | 49 | 100 |  |  |  |  | } else if (ipversion == 6) { | 
| 2195 | 48 |  |  |  |  |  | res = inet_pton6(start, ipnum); | 
| 2196 | 48 | 50 |  |  |  |  | if (!res) { | 
| 2197 | 0 |  |  |  |  |  | return 0; | 
| 2198 |  |  |  |  |  |  | } | 
| 2199 | 48 |  |  |  |  |  | *slash = '/'; | 
| 2200 | 48 |  |  |  |  |  | NI_ip_uchars_to_n128(ipnum, &ipv6); | 
| 2201 | 48 |  |  |  |  |  | res = NI_ip_normalize_prefix_ipv6(&ipv6, | 
| 2202 |  |  |  |  |  |  | slash, | 
| 2203 |  |  |  |  |  |  | ip1buf, | 
| 2204 |  |  |  |  |  |  | ip2buf); | 
| 2205 | 48 |  |  |  |  |  | return res; | 
| 2206 |  |  |  |  |  |  | } else { | 
| 2207 | 978 |  |  |  |  |  | return 0; | 
| 2208 |  |  |  |  |  |  | } | 
| 2209 |  |  |  |  |  |  | } | 
| 2210 |  |  |  |  |  |  |  | 
| 2211 |  |  |  |  |  |  | /** | 
| 2212 |  |  |  |  |  |  | * NI_ip_tokenize_on_char(): get parts of string before and after char. | 
| 2213 |  |  |  |  |  |  | * @str: the string to tokenize. | 
| 2214 |  |  |  |  |  |  | * @separator: the char that separates the two parts of the string. | 
| 2215 |  |  |  |  |  |  | * @end_first: buffer for the end of the first string. | 
| 2216 |  |  |  |  |  |  | * @second: buffer for the start of the second string. | 
| 2217 |  |  |  |  |  |  | * | 
| 2218 |  |  |  |  |  |  | * Tokenizes the string based on the @separator character. Ignores | 
| 2219 |  |  |  |  |  |  | * whitespace occurring before and after @separator. For example, if | 
| 2220 |  |  |  |  |  |  | * the string provided is '127.0.0.1 - 127.0.0.255', @end_first will | 
| 2221 |  |  |  |  |  |  | * point to the space immediately after the first IP address, and | 
| 2222 |  |  |  |  |  |  | * @second will point to the second IP address. | 
| 2223 |  |  |  |  |  |  | */ | 
| 2224 |  |  |  |  |  |  | int | 
| 2225 | 920 |  |  |  |  |  | NI_ip_tokenize_on_char(char *str, char separator, | 
| 2226 |  |  |  |  |  |  | char **end_first, char **second) | 
| 2227 |  |  |  |  |  |  | { | 
| 2228 |  |  |  |  |  |  | char c; | 
| 2229 |  |  |  |  |  |  | char *break_char; | 
| 2230 |  |  |  |  |  |  | int i; | 
| 2231 |  |  |  |  |  |  | int hit_separator; | 
| 2232 |  |  |  |  |  |  |  | 
| 2233 | 920 |  |  |  |  |  | break_char = NULL; | 
| 2234 | 920 |  |  |  |  |  | i = 0; | 
| 2235 | 920 |  |  |  |  |  | hit_separator = 0; | 
| 2236 |  |  |  |  |  |  |  | 
| 2237 | 26936 | 100 |  |  |  |  | while ((c = *str)) { | 
| 2238 | 26852 | 100 |  |  |  |  | if (c == separator) { | 
| 2239 | 836 |  |  |  |  |  | hit_separator = 1; | 
| 2240 | 836 | 100 |  |  |  |  | if (!break_char) { | 
| 2241 | 17 | 100 |  |  |  |  | if (!i) { | 
| 2242 | 3 |  |  |  |  |  | return 0; | 
| 2243 |  |  |  |  |  |  | } else { | 
| 2244 | 14 |  |  |  |  |  | break_char = str; | 
| 2245 |  |  |  |  |  |  | } | 
| 2246 |  |  |  |  |  |  | } | 
| 2247 | 833 |  |  |  |  |  | break; | 
| 2248 | 26016 | 100 |  |  |  |  | } else if (isspace(c)) { | 
| 2249 | 856 | 100 |  |  |  |  | if (!break_char) { | 
| 2250 | 856 |  |  |  |  |  | break_char = str; | 
| 2251 |  |  |  |  |  |  | } | 
| 2252 |  |  |  |  |  |  | } else { | 
| 2253 | 25160 |  |  |  |  |  | break_char = NULL; | 
| 2254 |  |  |  |  |  |  | } | 
| 2255 | 26016 |  |  |  |  |  | str++; | 
| 2256 | 26016 |  |  |  |  |  | i++; | 
| 2257 |  |  |  |  |  |  | } | 
| 2258 |  |  |  |  |  |  |  | 
| 2259 | 917 | 100 |  |  |  |  | if (!hit_separator) { | 
| 2260 | 84 |  |  |  |  |  | return 0; | 
| 2261 |  |  |  |  |  |  | } | 
| 2262 |  |  |  |  |  |  |  | 
| 2263 | 833 |  |  |  |  |  | str++; | 
| 2264 | 833 |  |  |  |  |  | c = *str; | 
| 2265 | 833 | 100 |  |  |  |  | if (c == '\0') { | 
| 2266 | 1 |  |  |  |  |  | return 0; | 
| 2267 |  |  |  |  |  |  | } | 
| 2268 |  |  |  |  |  |  |  | 
| 2269 | 1657 | 100 |  |  |  |  | while ((c = *str) && (isspace(c))) { | 
|  |  | 100 |  |  |  |  |  | 
| 2270 | 825 |  |  |  |  |  | str++; | 
| 2271 |  |  |  |  |  |  | } | 
| 2272 |  |  |  |  |  |  |  | 
| 2273 | 832 | 100 |  |  |  |  | if (c == '\0') { | 
| 2274 | 1 |  |  |  |  |  | return 0; | 
| 2275 |  |  |  |  |  |  | } | 
| 2276 |  |  |  |  |  |  |  | 
| 2277 | 831 |  |  |  |  |  | *end_first = break_char; | 
| 2278 | 831 |  |  |  |  |  | *second    = str; | 
| 2279 |  |  |  |  |  |  |  | 
| 2280 | 831 |  |  |  |  |  | return 1; | 
| 2281 |  |  |  |  |  |  | } | 
| 2282 |  |  |  |  |  |  |  | 
| 2283 |  |  |  |  |  |  | /** | 
| 2284 |  |  |  |  |  |  | * NI_ip_normalize_range(): get first and last address from a range. | 
| 2285 |  |  |  |  |  |  | * @ip: the IP address range to normalize. | 
| 2286 |  |  |  |  |  |  | * @ipbuf1: first IP address buffer. | 
| 2287 |  |  |  |  |  |  | * @ipbuf2: second IP address buffer. | 
| 2288 |  |  |  |  |  |  | * | 
| 2289 |  |  |  |  |  |  | * @ip must be a range containing a hyphen, e.g. '127.0.0.0 - | 
| 2290 |  |  |  |  |  |  | * 127.0.0.255'. Whitespace before and after the hyphen is ignored. | 
| 2291 |  |  |  |  |  |  | * The IP address buffers will be null-terminated on success. | 
| 2292 |  |  |  |  |  |  | */ | 
| 2293 |  |  |  |  |  |  | int | 
| 2294 | 866 |  |  |  |  |  | NI_ip_normalize_range(char *ip, char *ipbuf1, char *ipbuf2) | 
| 2295 |  |  |  |  |  |  | { | 
| 2296 |  |  |  |  |  |  | char *break_char; | 
| 2297 |  |  |  |  |  |  | char *start; | 
| 2298 |  |  |  |  |  |  | int ipversion; | 
| 2299 |  |  |  |  |  |  | int res; | 
| 2300 |  |  |  |  |  |  | char old_char; | 
| 2301 |  |  |  |  |  |  |  | 
| 2302 | 866 |  |  |  |  |  | res = NI_ip_tokenize_on_char(ip, '-', &break_char, &start); | 
| 2303 | 866 | 100 |  |  |  |  | if (!res) { | 
| 2304 | 54 |  |  |  |  |  | return -1; | 
| 2305 |  |  |  |  |  |  | } | 
| 2306 |  |  |  |  |  |  |  | 
| 2307 | 812 |  |  |  |  |  | old_char = *break_char; | 
| 2308 | 812 |  |  |  |  |  | *break_char = '\0'; | 
| 2309 |  |  |  |  |  |  |  | 
| 2310 | 812 |  |  |  |  |  | ipversion = NI_ip_get_version(start); | 
| 2311 | 812 | 100 |  |  |  |  | if (!ipversion) { | 
| 2312 | 1 |  |  |  |  |  | *break_char = old_char; | 
| 2313 | 1 |  |  |  |  |  | return 0; | 
| 2314 |  |  |  |  |  |  | } | 
| 2315 |  |  |  |  |  |  |  | 
| 2316 | 811 |  |  |  |  |  | res = NI_ip_expand_address(ip, ipversion, ipbuf1); | 
| 2317 | 811 |  |  |  |  |  | *break_char = old_char; | 
| 2318 |  |  |  |  |  |  |  | 
| 2319 | 811 | 100 |  |  |  |  | if (!res) { | 
| 2320 | 1 |  |  |  |  |  | return 0; | 
| 2321 |  |  |  |  |  |  | } | 
| 2322 |  |  |  |  |  |  |  | 
| 2323 | 810 |  |  |  |  |  | res = NI_ip_expand_address(start, ipversion, ipbuf2); | 
| 2324 | 810 | 50 |  |  |  |  | if (!res) { | 
| 2325 | 0 |  |  |  |  |  | return 0; | 
| 2326 |  |  |  |  |  |  | } | 
| 2327 |  |  |  |  |  |  |  | 
| 2328 | 866 |  |  |  |  |  | return 2; | 
| 2329 |  |  |  |  |  |  | } | 
| 2330 |  |  |  |  |  |  |  | 
| 2331 |  |  |  |  |  |  | /** | 
| 2332 |  |  |  |  |  |  | * NI_ip_normalize_plus_ipv4(): get first and last address from addition. | 
| 2333 |  |  |  |  |  |  | * @ip: the IP address string. | 
| 2334 |  |  |  |  |  |  | * @num: the number of addresses to add as a string. | 
| 2335 |  |  |  |  |  |  | * @ipbuf1: first IP address buffer. | 
| 2336 |  |  |  |  |  |  | * @ipbuf2: second IP address buffer. | 
| 2337 |  |  |  |  |  |  | * | 
| 2338 |  |  |  |  |  |  | * The IP address buffers will be null-terminated on success. | 
| 2339 |  |  |  |  |  |  | */ | 
| 2340 |  |  |  |  |  |  | int | 
| 2341 | 15 |  |  |  |  |  | NI_ip_normalize_plus_ipv4(char *ip, char *num, | 
| 2342 |  |  |  |  |  |  | char *ipbuf1, char *ipbuf2) | 
| 2343 |  |  |  |  |  |  | { | 
| 2344 |  |  |  |  |  |  | int res; | 
| 2345 |  |  |  |  |  |  | char *endptr; | 
| 2346 |  |  |  |  |  |  | unsigned char ipnum[4]; | 
| 2347 |  |  |  |  |  |  | unsigned long ipv4; | 
| 2348 |  |  |  |  |  |  | unsigned long addnum; | 
| 2349 |  |  |  |  |  |  |  | 
| 2350 | 15 |  |  |  |  |  | res = inet_pton4(ip, ipnum); | 
| 2351 | 15 | 50 |  |  |  |  | if (!res) { | 
| 2352 | 0 |  |  |  |  |  | return 0; | 
| 2353 |  |  |  |  |  |  | } | 
| 2354 |  |  |  |  |  |  |  | 
| 2355 | 15 |  |  |  |  |  | ipv4 = NI_ip_uchars_to_ulong(ipnum); | 
| 2356 |  |  |  |  |  |  |  | 
| 2357 | 15 |  |  |  |  |  | endptr = NULL; | 
| 2358 |  |  |  |  |  |  |  | 
| 2359 | 15 |  |  |  |  |  | addnum = strtoul(num, &endptr, 10); | 
| 2360 | 15 | 100 |  |  |  |  | if (STRTOUL_FAILED(addnum, num, endptr)) { | 
|  |  | 100 |  |  |  |  |  | 
|  |  | 50 |  |  |  |  |  | 
|  |  | 50 |  |  |  |  |  | 
|  |  | 0 |  |  |  |  |  | 
| 2361 | 2 |  |  |  |  |  | return 0; | 
| 2362 |  |  |  |  |  |  | } | 
| 2363 | 13 | 100 |  |  |  |  | if (addnum > 0xFFFFFFFF) { | 
| 2364 | 1 |  |  |  |  |  | return 0; | 
| 2365 |  |  |  |  |  |  | } | 
| 2366 |  |  |  |  |  |  |  | 
| 2367 | 12 |  |  |  |  |  | NI_ip_inttoip_ipv4(ipv4, ipbuf1); | 
| 2368 | 12 |  |  |  |  |  | ipv4 += addnum; | 
| 2369 | 12 |  |  |  |  |  | NI_ip_inttoip_ipv4(ipv4, ipbuf2); | 
| 2370 |  |  |  |  |  |  |  | 
| 2371 | 15 |  |  |  |  |  | return 2; | 
| 2372 |  |  |  |  |  |  | } | 
| 2373 |  |  |  |  |  |  |  | 
| 2374 |  |  |  |  |  |  | /** | 
| 2375 |  |  |  |  |  |  | * NI_ip_normalize_plus_ipv6(): get first and last address from addition. | 
| 2376 |  |  |  |  |  |  | * @ip: the IP address string. | 
| 2377 |  |  |  |  |  |  | * @num: the number of addresses to add as a string. | 
| 2378 |  |  |  |  |  |  | * @ipbuf1: first IP address buffer. | 
| 2379 |  |  |  |  |  |  | * @ipbuf2: second IP address buffer. | 
| 2380 |  |  |  |  |  |  | * | 
| 2381 |  |  |  |  |  |  | * The IP address buffers will be null-terminated on success. | 
| 2382 |  |  |  |  |  |  | */ | 
| 2383 |  |  |  |  |  |  | int | 
| 2384 | 4 |  |  |  |  |  | NI_ip_normalize_plus_ipv6(char *ip, char *num, | 
| 2385 |  |  |  |  |  |  | char *ipbuf1, char *ipbuf2) | 
| 2386 |  |  |  |  |  |  | { | 
| 2387 |  |  |  |  |  |  | unsigned char ipnum[16]; | 
| 2388 |  |  |  |  |  |  | n128_t ipv6; | 
| 2389 |  |  |  |  |  |  | n128_t addnum; | 
| 2390 |  |  |  |  |  |  | int res; | 
| 2391 |  |  |  |  |  |  |  | 
| 2392 | 4 |  |  |  |  |  | res = inet_pton6(ip, ipnum); | 
| 2393 | 4 | 50 |  |  |  |  | if (!res) { | 
| 2394 | 0 |  |  |  |  |  | return 0; | 
| 2395 |  |  |  |  |  |  | } | 
| 2396 |  |  |  |  |  |  |  | 
| 2397 | 4 |  |  |  |  |  | NI_ip_uchars_to_n128(ipnum, &ipv6); | 
| 2398 |  |  |  |  |  |  |  | 
| 2399 | 4 |  |  |  |  |  | res = n128_set_str_decimal(&addnum, num, strlen(num)); | 
| 2400 | 4 | 100 |  |  |  |  | if (!res) { | 
| 2401 | 2 |  |  |  |  |  | return 0; | 
| 2402 |  |  |  |  |  |  | } | 
| 2403 |  |  |  |  |  |  |  | 
| 2404 | 2 |  |  |  |  |  | NI_ip_inttoip_n128(&ipv6, ipbuf1); | 
| 2405 | 2 |  |  |  |  |  | n128_add(&ipv6, &addnum); | 
| 2406 | 2 |  |  |  |  |  | NI_ip_inttoip_n128(&ipv6, ipbuf2); | 
| 2407 |  |  |  |  |  |  |  | 
| 2408 | 4 |  |  |  |  |  | return 2; | 
| 2409 |  |  |  |  |  |  | } | 
| 2410 |  |  |  |  |  |  |  | 
| 2411 |  |  |  |  |  |  | /** | 
| 2412 |  |  |  |  |  |  | * NI_ip_normalize_plus(): get first and last address from addition. | 
| 2413 |  |  |  |  |  |  | * @ip: the IP address string. | 
| 2414 |  |  |  |  |  |  | * @ipbuf1: first IP address buffer. | 
| 2415 |  |  |  |  |  |  | * @ipbuf2: second IP address buffer. | 
| 2416 |  |  |  |  |  |  | * | 
| 2417 |  |  |  |  |  |  | * @ip must begin with an IP address, then contain a '+' and an | 
| 2418 |  |  |  |  |  |  | * integer, e.g. '127.0.0.0 + 16777216', '2000::+1234849245892845'. | 
| 2419 |  |  |  |  |  |  | * The IP address buffers will be null-terminated on success. | 
| 2420 |  |  |  |  |  |  | */ | 
| 2421 |  |  |  |  |  |  | int | 
| 2422 | 54 |  |  |  |  |  | NI_ip_normalize_plus(char *ip1, char *ipbuf1, char *ipbuf2) | 
| 2423 |  |  |  |  |  |  | { | 
| 2424 |  |  |  |  |  |  | char *break_char; | 
| 2425 |  |  |  |  |  |  | char *start; | 
| 2426 |  |  |  |  |  |  | int ipversion; | 
| 2427 |  |  |  |  |  |  | int res; | 
| 2428 |  |  |  |  |  |  | char old_char; | 
| 2429 |  |  |  |  |  |  |  | 
| 2430 | 54 |  |  |  |  |  | res = NI_ip_tokenize_on_char(ip1, '+', &break_char, &start); | 
| 2431 | 54 | 100 |  |  |  |  | if (!res) { | 
| 2432 | 35 |  |  |  |  |  | return -1; | 
| 2433 |  |  |  |  |  |  | } | 
| 2434 |  |  |  |  |  |  |  | 
| 2435 | 19 |  |  |  |  |  | old_char = *break_char; | 
| 2436 | 19 |  |  |  |  |  | *break_char = '\0'; | 
| 2437 |  |  |  |  |  |  |  | 
| 2438 | 19 |  |  |  |  |  | ipversion = NI_ip_get_version(ip1); | 
| 2439 |  |  |  |  |  |  |  | 
| 2440 | 19 |  |  |  |  |  | switch (ipversion) { | 
| 2441 | 15 |  |  |  |  |  | case 4:  res = NI_ip_normalize_plus_ipv4(ip1, start, ipbuf1, ipbuf2); | 
| 2442 | 15 |  |  |  |  |  | break; | 
| 2443 | 4 |  |  |  |  |  | case 6:  res = NI_ip_normalize_plus_ipv6(ip1, start, ipbuf1, ipbuf2); | 
| 2444 | 4 |  |  |  |  |  | break; | 
| 2445 | 0 |  |  |  |  |  | default: res = 0; | 
| 2446 |  |  |  |  |  |  | } | 
| 2447 |  |  |  |  |  |  |  | 
| 2448 | 19 |  |  |  |  |  | *break_char = old_char; | 
| 2449 | 54 |  |  |  |  |  | return res; | 
| 2450 |  |  |  |  |  |  | } | 
| 2451 |  |  |  |  |  |  |  | 
| 2452 |  |  |  |  |  |  | /** | 
| 2453 |  |  |  |  |  |  | * NI_ip_normalize_bare(): normalize a single IP address. | 
| 2454 |  |  |  |  |  |  | * @ip: the IP address string. | 
| 2455 |  |  |  |  |  |  | * @ipbuf1: the IP address buffer. | 
| 2456 |  |  |  |  |  |  | * | 
| 2457 |  |  |  |  |  |  | * Checks the version of the IP address and then expands it. For a | 
| 2458 |  |  |  |  |  |  | * valid IP address, this function has the same effect as calling | 
| 2459 |  |  |  |  |  |  | * NI_ip_expand_address(). The IP address buffer will be | 
| 2460 |  |  |  |  |  |  | * null-terminated on success. | 
| 2461 |  |  |  |  |  |  | */ | 
| 2462 |  |  |  |  |  |  | int | 
| 2463 | 35 |  |  |  |  |  | NI_ip_normalize_bare(char *ip, char *ipbuf1) | 
| 2464 |  |  |  |  |  |  | { | 
| 2465 |  |  |  |  |  |  | int ipversion; | 
| 2466 |  |  |  |  |  |  | int res; | 
| 2467 |  |  |  |  |  |  |  | 
| 2468 | 35 |  |  |  |  |  | ipversion = NI_ip_get_version(ip); | 
| 2469 | 35 | 100 |  |  |  |  | if (!ipversion) { | 
| 2470 | 9 |  |  |  |  |  | return 0; | 
| 2471 |  |  |  |  |  |  | } | 
| 2472 |  |  |  |  |  |  |  | 
| 2473 | 26 |  |  |  |  |  | res = NI_ip_expand_address(ip, ipversion, ipbuf1); | 
| 2474 | 26 | 50 |  |  |  |  | if (!res) { | 
| 2475 | 0 |  |  |  |  |  | return 0; | 
| 2476 |  |  |  |  |  |  | } | 
| 2477 |  |  |  |  |  |  |  | 
| 2478 | 26 |  |  |  |  |  | return 1; | 
| 2479 |  |  |  |  |  |  | } | 
| 2480 |  |  |  |  |  |  |  | 
| 2481 |  |  |  |  |  |  | /** | 
| 2482 |  |  |  |  |  |  | * NI_ip_normalize(): normalize an IP address string. | 
| 2483 |  |  |  |  |  |  | * @ip: the IP address string. | 
| 2484 |  |  |  |  |  |  | * @ipbuf1: the first IP address buffer. | 
| 2485 |  |  |  |  |  |  | * @ipbuf2: the second IP address buffer. | 
| 2486 |  |  |  |  |  |  | * | 
| 2487 |  |  |  |  |  |  | * The various formats that @ip can take are described in | 
| 2488 |  |  |  |  |  |  | * NI_ip_normalize_prefix(), NI_ip_normalize_range(), | 
| 2489 |  |  |  |  |  |  | * NI_ip_normalize_plus() and NI_ip_normalize_bare(). Returns zero on | 
| 2490 |  |  |  |  |  |  | * failure, otherwise returns the number of IP address buffers that | 
| 2491 |  |  |  |  |  |  | * were populated. Those buffers will be null-terminated on success. | 
| 2492 |  |  |  |  |  |  | */ | 
| 2493 |  |  |  |  |  |  | int | 
| 2494 | 978 |  |  |  |  |  | NI_ip_normalize(char *ip, char *ipbuf1, char *ipbuf2) | 
| 2495 |  |  |  |  |  |  | { | 
| 2496 |  |  |  |  |  |  | int res; | 
| 2497 |  |  |  |  |  |  |  | 
| 2498 | 978 |  |  |  |  |  | res = NI_ip_normalize_prefix(ip, ipbuf1, ipbuf2); | 
| 2499 | 978 | 100 |  |  |  |  | if (res >= 0) { | 
| 2500 | 112 |  |  |  |  |  | return res; | 
| 2501 |  |  |  |  |  |  | } | 
| 2502 |  |  |  |  |  |  |  | 
| 2503 | 866 |  |  |  |  |  | res = NI_ip_normalize_range(ip, ipbuf1, ipbuf2); | 
| 2504 | 866 | 100 |  |  |  |  | if (res >= 0) { | 
| 2505 | 812 |  |  |  |  |  | return res; | 
| 2506 |  |  |  |  |  |  | } | 
| 2507 |  |  |  |  |  |  |  | 
| 2508 | 54 |  |  |  |  |  | res = NI_ip_normalize_plus(ip, ipbuf1, ipbuf2); | 
| 2509 | 54 | 100 |  |  |  |  | if (res >= 0) { | 
| 2510 | 19 |  |  |  |  |  | return res; | 
| 2511 |  |  |  |  |  |  | } | 
| 2512 |  |  |  |  |  |  |  | 
| 2513 | 35 |  |  |  |  |  | res = NI_ip_normalize_bare(ip, ipbuf1); | 
| 2514 | 35 | 50 |  |  |  |  | if (res >= 0) { | 
| 2515 | 35 |  |  |  |  |  | return res; | 
| 2516 |  |  |  |  |  |  | } | 
| 2517 |  |  |  |  |  |  |  | 
| 2518 | 0 |  |  |  |  |  | return 0; | 
| 2519 |  |  |  |  |  |  | } | 
| 2520 |  |  |  |  |  |  |  | 
| 2521 |  |  |  |  |  |  | /** | 
| 2522 |  |  |  |  |  |  | * NI_ip_normal_range(): normalize an IP address string into a range. | 
| 2523 |  |  |  |  |  |  | * @ip: the IP address string. | 
| 2524 |  |  |  |  |  |  | * @buf: the IP address range buffer. | 
| 2525 |  |  |  |  |  |  | * | 
| 2526 |  |  |  |  |  |  | * Uses NI_ip_normalize() to get the first and last (if applicable) | 
| 2527 |  |  |  |  |  |  | * addresses from the string. Sets the buffer so that it is always in | 
| 2528 |  |  |  |  |  |  | * range format (i.e. first address, hyphen, second address), even | 
| 2529 |  |  |  |  |  |  | * where the IP address string contains only one address, in which | 
| 2530 |  |  |  |  |  |  | * case both of the addresses will be the same. @buf is | 
| 2531 |  |  |  |  |  |  | * null-terminated on success. | 
| 2532 |  |  |  |  |  |  | */ | 
| 2533 |  |  |  |  |  |  | int | 
| 2534 | 9 |  |  |  |  |  | NI_ip_normal_range(char *ip, char *buf) | 
| 2535 |  |  |  |  |  |  | { | 
| 2536 |  |  |  |  |  |  | char ip1buf[MAX_IPV6_STR_LEN]; | 
| 2537 |  |  |  |  |  |  | char ip2buf[MAX_IPV6_STR_LEN]; | 
| 2538 |  |  |  |  |  |  | int res; | 
| 2539 |  |  |  |  |  |  |  | 
| 2540 | 9 |  |  |  |  |  | res = NI_ip_normalize(ip, ip1buf, ip2buf); | 
| 2541 | 9 | 100 |  |  |  |  | if (!res) { | 
| 2542 | 3 |  |  |  |  |  | return 0; | 
| 2543 |  |  |  |  |  |  | } | 
| 2544 |  |  |  |  |  |  |  | 
| 2545 | 6 | 100 |  |  |  |  | sprintf(buf, "%s - %s", ip1buf, | 
| 2546 |  |  |  |  |  |  | (res == 1) ? ip1buf : ip2buf); | 
| 2547 |  |  |  |  |  |  |  | 
| 2548 | 9 |  |  |  |  |  | return 1; | 
| 2549 |  |  |  |  |  |  | } | 
| 2550 |  |  |  |  |  |  |  | 
| 2551 |  |  |  |  |  |  | /** | 
| 2552 |  |  |  |  |  |  | * NI_ip_compress_v4_prefix(): get smallest representation of IPv4 prefix range. | 
| 2553 |  |  |  |  |  |  | * @ip: the IP address. | 
| 2554 |  |  |  |  |  |  | * @len: the prefix length of the range. | 
| 2555 |  |  |  |  |  |  | * @buf: buffer for the compressed representation. | 
| 2556 |  |  |  |  |  |  | * @maxlen: maximum capacity of buffer. | 
| 2557 |  |  |  |  |  |  | */ | 
| 2558 |  |  |  |  |  |  | int | 
| 2559 | 52 |  |  |  |  |  | NI_ip_compress_v4_prefix(const char *ip, int len, char *buf, int maxlen) | 
| 2560 |  |  |  |  |  |  | { | 
| 2561 |  |  |  |  |  |  | int dotcount; | 
| 2562 |  |  |  |  |  |  | const char *c; | 
| 2563 |  |  |  |  |  |  | int buflen; | 
| 2564 |  |  |  |  |  |  |  | 
| 2565 | 52 | 100 |  |  |  |  | if ((len < 0) || (len > 32)) { | 
|  |  | 100 |  |  |  |  |  | 
| 2566 | 3 |  |  |  |  |  | return 0; | 
| 2567 |  |  |  |  |  |  | } | 
| 2568 | 49 | 100 |  |  |  |  | if (strlen(ip) > (MAX_IPV4_RANGE_STR_LEN - 1)) { | 
| 2569 | 2 |  |  |  |  |  | return 0; | 
| 2570 |  |  |  |  |  |  | } | 
| 2571 |  |  |  |  |  |  |  | 
| 2572 | 47 |  |  |  |  |  | c = ip; | 
| 2573 | 47 | 100 |  |  |  |  | dotcount = (len == 0) ? 1 : ((len / 8) + (!(len % 8) ? 0 : 1)); | 
| 2574 | 141 | 100 |  |  |  |  | while (dotcount--) { | 
| 2575 | 108 |  |  |  |  |  | c = strchr(c, '.'); | 
| 2576 | 108 | 100 |  |  |  |  | if (c == NULL) { | 
| 2577 | 14 |  |  |  |  |  | c = ip + (strlen(ip) + 1); | 
| 2578 | 14 |  |  |  |  |  | break; | 
| 2579 |  |  |  |  |  |  | } | 
| 2580 | 94 | 50 |  |  |  |  | if (*(c + 1) != '\0') { | 
| 2581 | 94 |  |  |  |  |  | c++; | 
| 2582 |  |  |  |  |  |  | } | 
| 2583 |  |  |  |  |  |  | } | 
| 2584 |  |  |  |  |  |  |  | 
| 2585 | 47 |  |  |  |  |  | buflen = c - ip - 1; | 
| 2586 | 47 | 50 |  |  |  |  | if (buflen > maxlen) { | 
| 2587 | 0 |  |  |  |  |  | buflen = maxlen; | 
| 2588 |  |  |  |  |  |  | } | 
| 2589 |  |  |  |  |  |  |  | 
| 2590 | 47 |  |  |  |  |  | strncpy(buf, ip, buflen); | 
| 2591 | 47 |  |  |  |  |  | buf[buflen] = '\0'; | 
| 2592 |  |  |  |  |  |  |  | 
| 2593 | 47 |  |  |  |  |  | return 1; | 
| 2594 |  |  |  |  |  |  | } | 
| 2595 |  |  |  |  |  |  |  | 
| 2596 |  |  |  |  |  |  | /** | 
| 2597 |  |  |  |  |  |  | * NI_ip_compress_address(): get smallest representation of IPv6 prefix range. | 
| 2598 |  |  |  |  |  |  | * @ip: the IP address. | 
| 2599 |  |  |  |  |  |  | * @version: the IP address version. | 
| 2600 |  |  |  |  |  |  | * @buf: buffer for the compressed representation. | 
| 2601 |  |  |  |  |  |  | * | 
| 2602 |  |  |  |  |  |  | * If @ip is an IPv4 address, it will simply be copied to @buf. | 
| 2603 |  |  |  |  |  |  | */ | 
| 2604 |  |  |  |  |  |  | int | 
| 2605 | 19 |  |  |  |  |  | NI_ip_compress_address(const char *ip, int version, char *buf) | 
| 2606 |  |  |  |  |  |  | { | 
| 2607 |  |  |  |  |  |  | unsigned char ipv6[16]; | 
| 2608 |  |  |  |  |  |  | int i; | 
| 2609 |  |  |  |  |  |  | char mybuf[5]; | 
| 2610 |  |  |  |  |  |  | int res; | 
| 2611 | 19 |  |  |  |  |  | int in_ws = 0; | 
| 2612 | 19 |  |  |  |  |  | int ws_index = -1; | 
| 2613 |  |  |  |  |  |  | int ws_start[4]; | 
| 2614 |  |  |  |  |  |  | int ws_count[4]; | 
| 2615 |  |  |  |  |  |  | int largest_index; | 
| 2616 |  |  |  |  |  |  | int largest; | 
| 2617 |  |  |  |  |  |  |  | 
| 2618 | 19 |  |  |  |  |  | memset(ws_start, 0, 4 * sizeof(int)); | 
| 2619 | 19 |  |  |  |  |  | memset(ws_count, 0, 4 * sizeof(int)); | 
| 2620 |  |  |  |  |  |  |  | 
| 2621 | 19 | 100 |  |  |  |  | if (!version) { | 
| 2622 | 1 |  |  |  |  |  | NI_set_Error_Errno(101, "Cannot determine IP version for %s", | 
| 2623 |  |  |  |  |  |  | ip); | 
| 2624 | 1 |  |  |  |  |  | return 0; | 
| 2625 |  |  |  |  |  |  | } | 
| 2626 |  |  |  |  |  |  |  | 
| 2627 | 18 | 100 |  |  |  |  | if (version == 4) { | 
| 2628 | 1 |  |  |  |  |  | strcpy(buf, ip); | 
| 2629 | 1 |  |  |  |  |  | return 1; | 
| 2630 |  |  |  |  |  |  | } | 
| 2631 |  |  |  |  |  |  |  | 
| 2632 | 17 |  |  |  |  |  | res = inet_pton6(ip, ipv6); | 
| 2633 | 17 | 100 |  |  |  |  | if (!res) { | 
| 2634 | 1 |  |  |  |  |  | return 0; | 
| 2635 |  |  |  |  |  |  | } | 
| 2636 |  |  |  |  |  |  |  | 
| 2637 | 144 | 100 |  |  |  |  | for (i = 0; i < 16; i += 2) { | 
| 2638 | 128 | 100 |  |  |  |  | if ((ipv6[i] == 0) && (ipv6[i + 1] == 0)) { | 
|  |  | 100 |  |  |  |  |  | 
| 2639 | 72 | 100 |  |  |  |  | if (!in_ws) { | 
| 2640 | 26 |  |  |  |  |  | in_ws = 1; | 
| 2641 | 26 |  |  |  |  |  | ws_start[++ws_index] = i; | 
| 2642 |  |  |  |  |  |  | } | 
| 2643 | 72 |  |  |  |  |  | ws_count[ws_index] += 1; | 
| 2644 |  |  |  |  |  |  | } else { | 
| 2645 | 56 |  |  |  |  |  | in_ws = 0; | 
| 2646 |  |  |  |  |  |  | } | 
| 2647 |  |  |  |  |  |  | } | 
| 2648 |  |  |  |  |  |  |  | 
| 2649 | 16 |  |  |  |  |  | largest       = 0; | 
| 2650 | 16 |  |  |  |  |  | largest_index = -1; | 
| 2651 |  |  |  |  |  |  |  | 
| 2652 | 80 | 100 |  |  |  |  | for (i = 0; i < 4; i++) { | 
| 2653 |  |  |  |  |  |  | /* "The symbol '::' MUST NOT be used to shorten just one 16-bit 0 | 
| 2654 |  |  |  |  |  |  | field. For example, the representation 2001:db8:0:1:1:1:1:1 is | 
| 2655 |  |  |  |  |  |  | correct, but 2001:db8::1:1:1:1:1 is not correct" | 
| 2656 |  |  |  |  |  |  | (RFC 5952, [4.2.2]). So make sure that ws_count is greater | 
| 2657 |  |  |  |  |  |  | than 1. */ | 
| 2658 | 64 | 100 |  |  |  |  | if (ws_count[i] > largest && ws_count[i] > 1) { | 
|  |  | 100 |  |  |  |  |  | 
| 2659 | 14 |  |  |  |  |  | largest       = ws_count[i]; | 
| 2660 | 14 |  |  |  |  |  | largest_index = i; | 
| 2661 |  |  |  |  |  |  | } | 
| 2662 |  |  |  |  |  |  | } | 
| 2663 |  |  |  |  |  |  |  | 
| 2664 | 101 | 100 |  |  |  |  | for (i = 0; i < 16; i += 2) { | 
| 2665 | 85 | 100 |  |  |  |  | if ((largest_index != -1) && (i == ws_start[largest_index])) { | 
|  |  | 100 |  |  |  |  |  | 
| 2666 | 12 | 100 |  |  |  |  | if (i == 0) { | 
| 2667 | 2 |  |  |  |  |  | strcat(buf, ":"); | 
| 2668 |  |  |  |  |  |  | } | 
| 2669 | 12 |  |  |  |  |  | i += ((largest * 2) - 2); | 
| 2670 | 12 |  |  |  |  |  | strcat(buf, ":"); | 
| 2671 |  |  |  |  |  |  | } else { | 
| 2672 | 73 |  |  |  |  |  | sprintf(mybuf, "%x", | 
| 2673 | 73 |  |  |  |  |  | (ipv6[i] << 8) + ipv6[i + 1]); | 
| 2674 | 73 |  |  |  |  |  | strcat(buf, mybuf); | 
| 2675 | 73 | 100 |  |  |  |  | if (i < 14) { | 
| 2676 | 59 |  |  |  |  |  | strcat(buf, ":"); | 
| 2677 |  |  |  |  |  |  | } | 
| 2678 |  |  |  |  |  |  | } | 
| 2679 |  |  |  |  |  |  | } | 
| 2680 |  |  |  |  |  |  |  | 
| 2681 | 19 |  |  |  |  |  | return 1; | 
| 2682 |  |  |  |  |  |  | } | 
| 2683 |  |  |  |  |  |  |  | 
| 2684 |  |  |  |  |  |  | /** | 
| 2685 |  |  |  |  |  |  | * NI_ip_splitprefix(): split range into IP address and prefix length. | 
| 2686 |  |  |  |  |  |  | * @prefix: the IP address prefix range. | 
| 2687 |  |  |  |  |  |  | * @ipbuf: the IP address buffer. | 
| 2688 |  |  |  |  |  |  | * @lenbuf: the prefix length buffer. | 
| 2689 |  |  |  |  |  |  | */ | 
| 2690 |  |  |  |  |  |  | int | 
| 2691 | 147 |  |  |  |  |  | NI_ip_splitprefix(const char *prefix, char *ipbuf, int *lenbuf) | 
| 2692 |  |  |  |  |  |  | { | 
| 2693 |  |  |  |  |  |  | const char *c; | 
| 2694 |  |  |  |  |  |  | const char *slash; | 
| 2695 |  |  |  |  |  |  | char *endptr; | 
| 2696 |  |  |  |  |  |  | long num; | 
| 2697 |  |  |  |  |  |  | int len; | 
| 2698 |  |  |  |  |  |  |  | 
| 2699 | 147 |  |  |  |  |  | c = slash = strchr(prefix, '/'); | 
| 2700 | 147 | 100 |  |  |  |  | if (!slash) { | 
| 2701 | 2 |  |  |  |  |  | return 0; | 
| 2702 |  |  |  |  |  |  | } | 
| 2703 |  |  |  |  |  |  |  | 
| 2704 | 145 |  |  |  |  |  | len = slash - prefix; | 
| 2705 | 145 | 100 |  |  |  |  | if ((len == 0) || (len > (MAX_IPV6_STR_LEN - 1))) { | 
|  |  | 100 |  |  |  |  |  | 
| 2706 | 3 |  |  |  |  |  | return 0; | 
| 2707 |  |  |  |  |  |  | } | 
| 2708 |  |  |  |  |  |  |  | 
| 2709 | 142 |  |  |  |  |  | c++; | 
| 2710 | 142 | 100 |  |  |  |  | if (*c == '\0') { | 
| 2711 | 1 |  |  |  |  |  | return 0; | 
| 2712 |  |  |  |  |  |  | } | 
| 2713 |  |  |  |  |  |  |  | 
| 2714 | 141 |  |  |  |  |  | endptr = NULL; | 
| 2715 |  |  |  |  |  |  |  | 
| 2716 | 141 |  |  |  |  |  | num = strtol(c, &endptr, 10); | 
| 2717 | 141 | 50 |  |  |  |  | if (STRTOL_FAILED(num, c, endptr)) { | 
|  |  | 100 |  |  |  |  |  | 
|  |  | 50 |  |  |  |  |  | 
|  |  | 100 |  |  |  |  |  | 
|  |  | 100 |  |  |  |  |  | 
| 2718 | 2 |  |  |  |  |  | return 0; | 
| 2719 |  |  |  |  |  |  | } | 
| 2720 | 139 | 100 |  |  |  |  | if (num < 0) { | 
| 2721 | 1 |  |  |  |  |  | return 0; | 
| 2722 |  |  |  |  |  |  | } | 
| 2723 |  |  |  |  |  |  |  | 
| 2724 | 138 |  |  |  |  |  | memcpy(ipbuf, prefix, len); | 
| 2725 | 138 |  |  |  |  |  | ipbuf[len] = '\0'; | 
| 2726 | 138 |  |  |  |  |  | *lenbuf = num; | 
| 2727 |  |  |  |  |  |  |  | 
| 2728 | 147 |  |  |  |  |  | return 1; | 
| 2729 |  |  |  |  |  |  | } | 
| 2730 |  |  |  |  |  |  |  | 
| 2731 |  |  |  |  |  |  | /** | 
| 2732 |  |  |  |  |  |  | * NI_ip_iptype(): get type of IP address as a string. | 
| 2733 |  |  |  |  |  |  | * @ip: the IP address. | 
| 2734 |  |  |  |  |  |  | * @version: the IP address version. | 
| 2735 |  |  |  |  |  |  | * @buf: the type buffer. | 
| 2736 |  |  |  |  |  |  | * | 
| 2737 |  |  |  |  |  |  | * The type buffer will be null-terminated on success. Relies on | 
| 2738 |  |  |  |  |  |  | * IPv4ranges and IPv6ranges for determining types. | 
| 2739 |  |  |  |  |  |  | */ | 
| 2740 |  |  |  |  |  |  | int | 
| 2741 | 16 |  |  |  |  |  | NI_ip_iptype(const char *ip, int version, char *buf) | 
| 2742 |  |  |  |  |  |  | { | 
| 2743 |  |  |  |  |  |  | HV *hash; | 
| 2744 |  |  |  |  |  |  | HE *entry; | 
| 2745 |  |  |  |  |  |  | char *key; | 
| 2746 |  |  |  |  |  |  | I32 keylen; | 
| 2747 |  |  |  |  |  |  | SV *value; | 
| 2748 |  |  |  |  |  |  | STRLEN len; | 
| 2749 |  |  |  |  |  |  | int current_keylen; | 
| 2750 |  |  |  |  |  |  | char *typestr; | 
| 2751 |  |  |  |  |  |  |  | 
| 2752 | 16 | 100 |  |  |  |  | hash = get_hv( | 
| 2753 |  |  |  |  |  |  | (version == 4 ? "Net::IP::XS::IPv4ranges" | 
| 2754 |  |  |  |  |  |  | : "Net::IP::XS::IPv6ranges"), 0); | 
| 2755 |  |  |  |  |  |  |  | 
| 2756 | 16 | 50 |  |  |  |  | if (!hash) { | 
| 2757 | 0 |  |  |  |  |  | return 0; | 
| 2758 |  |  |  |  |  |  | } | 
| 2759 |  |  |  |  |  |  |  | 
| 2760 | 16 |  |  |  |  |  | hv_iterinit(hash); | 
| 2761 | 16 |  |  |  |  |  | current_keylen = 0; | 
| 2762 |  |  |  |  |  |  |  | 
| 2763 | 284 | 100 |  |  |  |  | while ((entry = hv_iternext(hash))) { | 
| 2764 | 268 |  |  |  |  |  | key = hv_iterkey(entry, &keylen); | 
| 2765 | 268 | 100 |  |  |  |  | if (keylen > current_keylen) { | 
| 2766 | 205 | 100 |  |  |  |  | if (!strncmp(key, ip, keylen)) { | 
| 2767 | 13 |  |  |  |  |  | current_keylen = keylen; | 
| 2768 | 13 |  |  |  |  |  | value = hv_iterval(hash, entry); | 
| 2769 | 13 | 50 |  |  |  |  | typestr = SvPV(value, len); | 
| 2770 | 13 | 100 |  |  |  |  | if (len > (MAX_TYPE_STR_LEN - 1)) { | 
| 2771 | 1 |  |  |  |  |  | len = (MAX_TYPE_STR_LEN - 1); | 
| 2772 |  |  |  |  |  |  | } | 
| 2773 | 13 |  |  |  |  |  | memcpy(buf, typestr, len); | 
| 2774 | 13 |  |  |  |  |  | buf[len] = '\0'; | 
| 2775 |  |  |  |  |  |  | } | 
| 2776 |  |  |  |  |  |  | } | 
| 2777 |  |  |  |  |  |  | } | 
| 2778 |  |  |  |  |  |  |  | 
| 2779 | 16 | 100 |  |  |  |  | if (current_keylen) { | 
| 2780 | 10 |  |  |  |  |  | return 1; | 
| 2781 |  |  |  |  |  |  | } | 
| 2782 |  |  |  |  |  |  |  | 
| 2783 | 6 | 100 |  |  |  |  | if (version == 4) { | 
| 2784 | 3 |  |  |  |  |  | memcpy(buf, "PUBLIC", 6); | 
| 2785 | 3 |  |  |  |  |  | buf[6] = '\0'; | 
| 2786 | 3 |  |  |  |  |  | return 1; | 
| 2787 |  |  |  |  |  |  | } | 
| 2788 |  |  |  |  |  |  |  | 
| 2789 | 3 |  |  |  |  |  | NI_set_Error_Errno(180, "Cannot determine type for %s", ip); | 
| 2790 |  |  |  |  |  |  |  | 
| 2791 | 16 |  |  |  |  |  | return 0; | 
| 2792 |  |  |  |  |  |  | } | 
| 2793 |  |  |  |  |  |  |  | 
| 2794 |  |  |  |  |  |  | /** | 
| 2795 |  |  |  |  |  |  | * NI_ip_is_valid_mask(): determine the validity of a bitstring mask. | 
| 2796 |  |  |  |  |  |  | * @mask: bitstring mask. | 
| 2797 |  |  |  |  |  |  | * @version: mask's IP address version. | 
| 2798 |  |  |  |  |  |  | */ | 
| 2799 |  |  |  |  |  |  | int | 
| 2800 | 9 |  |  |  |  |  | NI_ip_is_valid_mask(const char *mask, int version) | 
| 2801 |  |  |  |  |  |  | { | 
| 2802 |  |  |  |  |  |  | const char *c; | 
| 2803 |  |  |  |  |  |  | int iplen; | 
| 2804 |  |  |  |  |  |  | int mask_len; | 
| 2805 |  |  |  |  |  |  | int state; | 
| 2806 |  |  |  |  |  |  |  | 
| 2807 | 9 | 100 |  |  |  |  | if (!version) { | 
| 2808 | 1 |  |  |  |  |  | NI_set_Error_Errno(101, "Cannot determine IP version for %s", | 
| 2809 |  |  |  |  |  |  | mask); | 
| 2810 | 1 |  |  |  |  |  | return 0; | 
| 2811 |  |  |  |  |  |  | } | 
| 2812 |  |  |  |  |  |  |  | 
| 2813 | 8 |  |  |  |  |  | iplen    = NI_iplengths(version); | 
| 2814 | 8 |  |  |  |  |  | mask_len = strlen(mask); | 
| 2815 |  |  |  |  |  |  |  | 
| 2816 | 8 | 100 |  |  |  |  | if (mask_len != iplen) { | 
| 2817 | 2 |  |  |  |  |  | NI_set_Error_Errno(150, "Invalid mask length for %s", mask); | 
| 2818 | 2 |  |  |  |  |  | return 0; | 
| 2819 |  |  |  |  |  |  | } | 
| 2820 |  |  |  |  |  |  |  | 
| 2821 | 6 |  |  |  |  |  | state = 0; | 
| 2822 | 6 |  |  |  |  |  | c     = mask; | 
| 2823 |  |  |  |  |  |  |  | 
| 2824 | 103 | 100 |  |  |  |  | while (*c != '\0') { | 
| 2825 | 99 | 100 |  |  |  |  | if ((*c == '1') && (state == 0)) { | 
|  |  | 100 |  |  |  |  |  | 
| 2826 | 33 |  |  |  |  |  | c++; | 
| 2827 | 33 |  |  |  |  |  | continue; | 
| 2828 |  |  |  |  |  |  | } | 
| 2829 | 66 | 100 |  |  |  |  | if (*c == '0') { | 
| 2830 | 64 | 100 |  |  |  |  | if (state == 0) { | 
| 2831 | 3 |  |  |  |  |  | state = 1; | 
| 2832 |  |  |  |  |  |  | } | 
| 2833 | 64 |  |  |  |  |  | c++; | 
| 2834 | 64 |  |  |  |  |  | continue; | 
| 2835 |  |  |  |  |  |  | } | 
| 2836 | 2 |  |  |  |  |  | NI_set_Error_Errno(151, "Invalid mask %s", mask); | 
| 2837 | 2 |  |  |  |  |  | return 0; | 
| 2838 |  |  |  |  |  |  | } | 
| 2839 |  |  |  |  |  |  |  | 
| 2840 | 4 |  |  |  |  |  | return 1; | 
| 2841 |  |  |  |  |  |  | } | 
| 2842 |  |  |  |  |  |  |  | 
| 2843 |  |  |  |  |  |  | /** | 
| 2844 |  |  |  |  |  |  | * NI_ip_prefix_to_range(): get begin/end addresses from address and length. | 
| 2845 |  |  |  |  |  |  | * @ip: IP address. | 
| 2846 |  |  |  |  |  |  | * @len: prefix length of range. | 
| 2847 |  |  |  |  |  |  | * @version: IP address version. | 
| 2848 |  |  |  |  |  |  | * @buf: last IP address buffer. | 
| 2849 |  |  |  |  |  |  | */ | 
| 2850 |  |  |  |  |  |  | int | 
| 2851 | 22 |  |  |  |  |  | NI_ip_prefix_to_range(const char *ip, int len, int version, char *buf) | 
| 2852 |  |  |  |  |  |  | { | 
| 2853 |  |  |  |  |  |  | char bitstr1[IPV6_BITSTR_LEN]; | 
| 2854 |  |  |  |  |  |  | char bitstr2[IPV6_BITSTR_LEN]; | 
| 2855 |  |  |  |  |  |  |  | 
| 2856 | 22 | 100 |  |  |  |  | if (!version) { | 
| 2857 | 1 |  |  |  |  |  | NI_set_Error_Errno(101, "Cannot determine IP version"); | 
| 2858 | 1 |  |  |  |  |  | return 0; | 
| 2859 |  |  |  |  |  |  | } | 
| 2860 |  |  |  |  |  |  |  | 
| 2861 | 21 | 100 |  |  |  |  | if (!NI_ip_expand_address(ip, version, buf)) { | 
| 2862 | 1 |  |  |  |  |  | return 0; | 
| 2863 |  |  |  |  |  |  | } | 
| 2864 |  |  |  |  |  |  |  | 
| 2865 | 20 | 50 |  |  |  |  | if (!NI_ip_iptobin(ip, version, bitstr1)) { | 
| 2866 | 0 |  |  |  |  |  | return 0; | 
| 2867 |  |  |  |  |  |  | } | 
| 2868 |  |  |  |  |  |  |  | 
| 2869 | 20 | 100 |  |  |  |  | bitstr1[(version == 4) ? 32 : 128] = '\0'; | 
| 2870 |  |  |  |  |  |  |  | 
| 2871 | 20 | 100 |  |  |  |  | if (!NI_ip_check_prefix(bitstr1, len, version)) { | 
| 2872 | 1 |  |  |  |  |  | return 0; | 
| 2873 |  |  |  |  |  |  | } | 
| 2874 |  |  |  |  |  |  |  | 
| 2875 | 19 |  |  |  |  |  | NI_ip_last_address_bin(bitstr1, len, version, bitstr2); | 
| 2876 |  |  |  |  |  |  |  | 
| 2877 | 19 | 100 |  |  |  |  | bitstr2[(version == 4) ? 32 : 128] = '\0'; | 
| 2878 |  |  |  |  |  |  |  | 
| 2879 | 19 | 50 |  |  |  |  | if (!NI_ip_bintoip(bitstr2, version, buf)) { | 
| 2880 | 0 |  |  |  |  |  | return 0; | 
| 2881 |  |  |  |  |  |  | } | 
| 2882 |  |  |  |  |  |  |  | 
| 2883 | 22 |  |  |  |  |  | return 1; | 
| 2884 |  |  |  |  |  |  | } | 
| 2885 |  |  |  |  |  |  |  | 
| 2886 |  |  |  |  |  |  | /** | 
| 2887 |  |  |  |  |  |  | * NI_ip_get_embedded_ipv4(): get IPv4 address contained within IPv6 address. | 
| 2888 |  |  |  |  |  |  | * @ipv6: IPv6 address as a string. | 
| 2889 |  |  |  |  |  |  | * @buf: IPv4 address buffer. | 
| 2890 |  |  |  |  |  |  | */ | 
| 2891 |  |  |  |  |  |  | int | 
| 2892 | 8 |  |  |  |  |  | NI_ip_get_embedded_ipv4(const char *ipv6, char *buf) | 
| 2893 |  |  |  |  |  |  | { | 
| 2894 |  |  |  |  |  |  | const char *c; | 
| 2895 |  |  |  |  |  |  | int len; | 
| 2896 |  |  |  |  |  |  |  | 
| 2897 | 8 |  |  |  |  |  | c = strrchr(ipv6, ':'); | 
| 2898 | 8 | 100 |  |  |  |  | if (c == NULL) { | 
| 2899 | 3 |  |  |  |  |  | c = ipv6; | 
| 2900 |  |  |  |  |  |  | } else { | 
| 2901 | 5 |  |  |  |  |  | c++; | 
| 2902 |  |  |  |  |  |  | } | 
| 2903 |  |  |  |  |  |  |  | 
| 2904 | 8 |  |  |  |  |  | len = strlen(c); | 
| 2905 | 8 | 100 |  |  |  |  | if (len > (MAX_IPV4_STR_LEN - 1)) { | 
| 2906 | 1 |  |  |  |  |  | len = (MAX_IPV4_STR_LEN - 1); | 
| 2907 |  |  |  |  |  |  | } | 
| 2908 | 8 | 100 |  |  |  |  | if ((len > 0) && NI_ip_is_ipv4(c)) { | 
|  |  | 100 |  |  |  |  |  | 
| 2909 | 4 |  |  |  |  |  | strncpy(buf, c, len); | 
| 2910 | 4 |  |  |  |  |  | buf[len] = '\0'; | 
| 2911 | 4 |  |  |  |  |  | return 1; | 
| 2912 |  |  |  |  |  |  | } else { | 
| 2913 | 4 |  |  |  |  |  | return 0; | 
| 2914 |  |  |  |  |  |  | } | 
| 2915 |  |  |  |  |  |  | } | 
| 2916 |  |  |  |  |  |  |  | 
| 2917 |  |  |  |  |  |  | #ifdef __cplusplus | 
| 2918 |  |  |  |  |  |  | } | 
| 2919 |  |  |  |  |  |  | #endif |