1 1.1 elric /* $NetBSD: addr_families.c,v 1.3 2023/06/19 21:41:44 christos Exp $ */ 2 1.1 elric 3 1.1 elric /* 4 1.1 elric * Copyright (c) 1997-2007 Kungliga Tekniska Hgskolan 5 1.1 elric * (Royal Institute of Technology, Stockholm, Sweden). 6 1.1 elric * All rights reserved. 7 1.1 elric * 8 1.1 elric * Redistribution and use in source and binary forms, with or without 9 1.1 elric * modification, are permitted provided that the following conditions 10 1.1 elric * are met: 11 1.1 elric * 12 1.1 elric * 1. Redistributions of source code must retain the above copyright 13 1.1 elric * notice, this list of conditions and the following disclaimer. 14 1.1 elric * 15 1.1 elric * 2. Redistributions in binary form must reproduce the above copyright 16 1.1 elric * notice, this list of conditions and the following disclaimer in the 17 1.1 elric * documentation and/or other materials provided with the distribution. 18 1.1 elric * 19 1.1 elric * 3. Neither the name of the Institute nor the names of its contributors 20 1.1 elric * may be used to endorse or promote products derived from this software 21 1.1 elric * without specific prior written permission. 22 1.1 elric * 23 1.1 elric * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 24 1.1 elric * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25 1.1 elric * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26 1.1 elric * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 27 1.1 elric * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28 1.1 elric * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29 1.1 elric * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30 1.1 elric * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31 1.1 elric * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32 1.1 elric * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33 1.1 elric * SUCH DAMAGE. 34 1.1 elric */ 35 1.1 elric 36 1.1 elric #include "krb5_locl.h" 37 1.1 elric 38 1.1 elric struct addr_operations { 39 1.1 elric int af; 40 1.1 elric krb5_address_type atype; 41 1.1 elric size_t max_sockaddr_size; 42 1.1 elric krb5_error_code (*sockaddr2addr)(const struct sockaddr *, krb5_address *); 43 1.1 elric krb5_error_code (*sockaddr2port)(const struct sockaddr *, int16_t *); 44 1.1 elric void (*addr2sockaddr)(const krb5_address *, struct sockaddr *, 45 1.1 elric krb5_socklen_t *sa_size, int port); 46 1.1 elric void (*h_addr2sockaddr)(const char *, struct sockaddr *, krb5_socklen_t *, int); 47 1.1 elric krb5_error_code (*h_addr2addr)(const char *, krb5_address *); 48 1.1 elric krb5_boolean (*uninteresting)(const struct sockaddr *); 49 1.1 elric krb5_boolean (*is_loopback)(const struct sockaddr *); 50 1.1 elric void (*anyaddr)(struct sockaddr *, krb5_socklen_t *, int); 51 1.1 elric int (*print_addr)(const krb5_address *, char *, size_t); 52 1.1 elric int (*parse_addr)(krb5_context, const char*, krb5_address *); 53 1.1 elric int (*order_addr)(krb5_context, const krb5_address*, const krb5_address*); 54 1.1 elric int (*free_addr)(krb5_context, krb5_address*); 55 1.1 elric int (*copy_addr)(krb5_context, const krb5_address*, krb5_address*); 56 1.1 elric int (*mask_boundary)(krb5_context, const krb5_address*, unsigned long, 57 1.1 elric krb5_address*, krb5_address*); 58 1.1 elric }; 59 1.1 elric 60 1.1 elric /* 61 1.1 elric * AF_INET - aka IPv4 implementation 62 1.1 elric */ 63 1.1 elric 64 1.1 elric static krb5_error_code 65 1.1 elric ipv4_sockaddr2addr (const struct sockaddr *sa, krb5_address *a) 66 1.1 elric { 67 1.1 elric const struct sockaddr_in *sin4 = (const struct sockaddr_in *)sa; 68 1.1 elric unsigned char buf[4]; 69 1.1 elric 70 1.1 elric a->addr_type = KRB5_ADDRESS_INET; 71 1.1 elric memcpy (buf, &sin4->sin_addr, 4); 72 1.1 elric return krb5_data_copy(&a->address, buf, 4); 73 1.1 elric } 74 1.1 elric 75 1.1 elric static krb5_error_code 76 1.1 elric ipv4_sockaddr2port (const struct sockaddr *sa, int16_t *port) 77 1.1 elric { 78 1.1 elric const struct sockaddr_in *sin4 = (const struct sockaddr_in *)sa; 79 1.1 elric 80 1.1 elric *port = sin4->sin_port; 81 1.1 elric return 0; 82 1.1 elric } 83 1.1 elric 84 1.1 elric static void 85 1.1 elric ipv4_addr2sockaddr (const krb5_address *a, 86 1.1 elric struct sockaddr *sa, 87 1.1 elric krb5_socklen_t *sa_size, 88 1.1 elric int port) 89 1.1 elric { 90 1.1 elric struct sockaddr_in tmp; 91 1.1 elric 92 1.1 elric memset (&tmp, 0, sizeof(tmp)); 93 1.1 elric tmp.sin_family = AF_INET; 94 1.1 elric memcpy (&tmp.sin_addr, a->address.data, 4); 95 1.1 elric tmp.sin_port = port; 96 1.1 elric memcpy(sa, &tmp, min(sizeof(tmp), *sa_size)); 97 1.1 elric *sa_size = sizeof(tmp); 98 1.1 elric } 99 1.1 elric 100 1.1 elric static void 101 1.1 elric ipv4_h_addr2sockaddr(const char *addr, 102 1.1 elric struct sockaddr *sa, 103 1.1 elric krb5_socklen_t *sa_size, 104 1.1 elric int port) 105 1.1 elric { 106 1.1 elric struct sockaddr_in tmp; 107 1.1 elric 108 1.1 elric memset (&tmp, 0, sizeof(tmp)); 109 1.1 elric tmp.sin_family = AF_INET; 110 1.1 elric tmp.sin_port = port; 111 1.1 elric tmp.sin_addr = *((const struct in_addr *)addr); 112 1.1 elric memcpy(sa, &tmp, min(sizeof(tmp), *sa_size)); 113 1.1 elric *sa_size = sizeof(tmp); 114 1.1 elric } 115 1.1 elric 116 1.1 elric static krb5_error_code 117 1.1 elric ipv4_h_addr2addr (const char *addr, 118 1.1 elric krb5_address *a) 119 1.1 elric { 120 1.1 elric unsigned char buf[4]; 121 1.1 elric 122 1.1 elric a->addr_type = KRB5_ADDRESS_INET; 123 1.1 elric memcpy(buf, addr, 4); 124 1.1 elric return krb5_data_copy(&a->address, buf, 4); 125 1.1 elric } 126 1.1 elric 127 1.1 elric /* 128 1.1 elric * Are there any addresses that should be considered `uninteresting'? 129 1.1 elric */ 130 1.1 elric 131 1.1 elric static krb5_boolean 132 1.1 elric ipv4_uninteresting (const struct sockaddr *sa) 133 1.1 elric { 134 1.1 elric const struct sockaddr_in *sin4 = (const struct sockaddr_in *)sa; 135 1.1 elric 136 1.1 elric if (sin4->sin_addr.s_addr == INADDR_ANY) 137 1.1 elric return TRUE; 138 1.1 elric 139 1.1 elric return FALSE; 140 1.1 elric } 141 1.1 elric 142 1.1 elric static krb5_boolean 143 1.1 elric ipv4_is_loopback (const struct sockaddr *sa) 144 1.1 elric { 145 1.1 elric const struct sockaddr_in *sin4 = (const struct sockaddr_in *)sa; 146 1.1 elric 147 1.1 elric if ((ntohl(sin4->sin_addr.s_addr) >> 24) == IN_LOOPBACKNET) 148 1.1 elric return TRUE; 149 1.1 elric 150 1.1 elric return FALSE; 151 1.1 elric } 152 1.1 elric 153 1.1 elric static void 154 1.1 elric ipv4_anyaddr (struct sockaddr *sa, krb5_socklen_t *sa_size, int port) 155 1.1 elric { 156 1.1 elric struct sockaddr_in tmp; 157 1.1 elric 158 1.1 elric memset (&tmp, 0, sizeof(tmp)); 159 1.1 elric tmp.sin_family = AF_INET; 160 1.1 elric tmp.sin_port = port; 161 1.1 elric tmp.sin_addr.s_addr = INADDR_ANY; 162 1.1 elric memcpy(sa, &tmp, min(sizeof(tmp), *sa_size)); 163 1.1 elric *sa_size = sizeof(tmp); 164 1.1 elric } 165 1.1 elric 166 1.1 elric static int 167 1.1 elric ipv4_print_addr (const krb5_address *addr, char *str, size_t len) 168 1.1 elric { 169 1.1 elric struct in_addr ia; 170 1.1 elric 171 1.1 elric memcpy (&ia, addr->address.data, 4); 172 1.1 elric 173 1.1 elric return snprintf (str, len, "IPv4:%s", inet_ntoa(ia)); 174 1.1 elric } 175 1.1 elric 176 1.1 elric static int 177 1.1 elric ipv4_parse_addr (krb5_context context, const char *address, krb5_address *addr) 178 1.1 elric { 179 1.1 elric const char *p; 180 1.1 elric struct in_addr a; 181 1.1 elric 182 1.1 elric p = strchr(address, ':'); 183 1.1 elric if(p) { 184 1.1 elric p++; 185 1.1 elric if(strncasecmp(address, "ip:", p - address) != 0 && 186 1.1 elric strncasecmp(address, "ip4:", p - address) != 0 && 187 1.1 elric strncasecmp(address, "ipv4:", p - address) != 0 && 188 1.1 elric strncasecmp(address, "inet:", p - address) != 0) 189 1.1 elric return -1; 190 1.1 elric } else 191 1.1 elric p = address; 192 1.1 elric if(inet_aton(p, &a) == 0) 193 1.1 elric return -1; 194 1.1 elric addr->addr_type = KRB5_ADDRESS_INET; 195 1.1 elric if(krb5_data_alloc(&addr->address, 4) != 0) 196 1.1 elric return -1; 197 1.1 elric _krb5_put_int(addr->address.data, ntohl(a.s_addr), addr->address.length); 198 1.1 elric return 0; 199 1.1 elric } 200 1.1 elric 201 1.1 elric static int 202 1.1 elric ipv4_mask_boundary(krb5_context context, const krb5_address *inaddr, 203 1.1 elric unsigned long len, krb5_address *low, krb5_address *high) 204 1.1 elric { 205 1.1 elric unsigned long ia; 206 1.1 elric uint32_t l, h, m = 0xffffffff; 207 1.1 elric 208 1.1 elric if (len > 32) { 209 1.1 elric krb5_set_error_message(context, KRB5_PROG_ATYPE_NOSUPP, 210 1.1 elric N_("IPv4 prefix too large (%ld)", "len"), len); 211 1.1 elric return KRB5_PROG_ATYPE_NOSUPP; 212 1.1 elric } 213 1.1 elric m = m << (32 - len); 214 1.1 elric 215 1.1 elric _krb5_get_int(inaddr->address.data, &ia, inaddr->address.length); 216 1.1 elric 217 1.1 elric l = ia & m; 218 1.1 elric h = l | ~m; 219 1.1 elric 220 1.1 elric low->addr_type = KRB5_ADDRESS_INET; 221 1.1 elric if(krb5_data_alloc(&low->address, 4) != 0) 222 1.1 elric return -1; 223 1.1 elric _krb5_put_int(low->address.data, l, low->address.length); 224 1.1 elric 225 1.1 elric high->addr_type = KRB5_ADDRESS_INET; 226 1.1 elric if(krb5_data_alloc(&high->address, 4) != 0) { 227 1.1 elric krb5_free_address(context, low); 228 1.1 elric return -1; 229 1.1 elric } 230 1.1 elric _krb5_put_int(high->address.data, h, high->address.length); 231 1.1 elric 232 1.1 elric return 0; 233 1.1 elric } 234 1.1 elric 235 1.1 elric 236 1.1 elric /* 237 1.1 elric * AF_INET6 - aka IPv6 implementation 238 1.1 elric */ 239 1.1 elric 240 1.1 elric #ifdef HAVE_IPV6 241 1.1 elric 242 1.1 elric static krb5_error_code 243 1.1 elric ipv6_sockaddr2addr (const struct sockaddr *sa, krb5_address *a) 244 1.1 elric { 245 1.1 elric const struct sockaddr_in6 *sin6 = (const struct sockaddr_in6 *)sa; 246 1.1 elric 247 1.1 elric if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) { 248 1.1 elric unsigned char buf[4]; 249 1.1 elric 250 1.1 elric a->addr_type = KRB5_ADDRESS_INET; 251 1.1 elric #ifndef IN6_ADDR_V6_TO_V4 252 1.1 elric #ifdef IN6_EXTRACT_V4ADDR 253 1.1 elric #define IN6_ADDR_V6_TO_V4(x) (&IN6_EXTRACT_V4ADDR(x)) 254 1.1 elric #else 255 1.1 elric #define IN6_ADDR_V6_TO_V4(x) ((const struct in_addr *)&(x)->s6_addr[12]) 256 1.1 elric #endif 257 1.1 elric #endif 258 1.1 elric memcpy (buf, IN6_ADDR_V6_TO_V4(&sin6->sin6_addr), 4); 259 1.1 elric return krb5_data_copy(&a->address, buf, 4); 260 1.1 elric } else { 261 1.1 elric a->addr_type = KRB5_ADDRESS_INET6; 262 1.1 elric return krb5_data_copy(&a->address, 263 1.1 elric &sin6->sin6_addr, 264 1.1 elric sizeof(sin6->sin6_addr)); 265 1.1 elric } 266 1.1 elric } 267 1.1 elric 268 1.1 elric static krb5_error_code 269 1.1 elric ipv6_sockaddr2port (const struct sockaddr *sa, int16_t *port) 270 1.1 elric { 271 1.1 elric const struct sockaddr_in6 *sin6 = (const struct sockaddr_in6 *)sa; 272 1.1 elric 273 1.1 elric *port = sin6->sin6_port; 274 1.1 elric return 0; 275 1.1 elric } 276 1.1 elric 277 1.1 elric static void 278 1.1 elric ipv6_addr2sockaddr (const krb5_address *a, 279 1.1 elric struct sockaddr *sa, 280 1.1 elric krb5_socklen_t *sa_size, 281 1.1 elric int port) 282 1.1 elric { 283 1.1 elric struct sockaddr_in6 tmp; 284 1.1 elric 285 1.1 elric memset (&tmp, 0, sizeof(tmp)); 286 1.1 elric tmp.sin6_family = AF_INET6; 287 1.1 elric memcpy (&tmp.sin6_addr, a->address.data, sizeof(tmp.sin6_addr)); 288 1.1 elric tmp.sin6_port = port; 289 1.1 elric memcpy(sa, &tmp, min(sizeof(tmp), *sa_size)); 290 1.1 elric *sa_size = sizeof(tmp); 291 1.1 elric } 292 1.1 elric 293 1.1 elric static void 294 1.1 elric ipv6_h_addr2sockaddr(const char *addr, 295 1.1 elric struct sockaddr *sa, 296 1.1 elric krb5_socklen_t *sa_size, 297 1.1 elric int port) 298 1.1 elric { 299 1.1 elric struct sockaddr_in6 tmp; 300 1.1 elric 301 1.1 elric memset (&tmp, 0, sizeof(tmp)); 302 1.1 elric tmp.sin6_family = AF_INET6; 303 1.1 elric tmp.sin6_port = port; 304 1.1 elric tmp.sin6_addr = *((const struct in6_addr *)addr); 305 1.1 elric memcpy(sa, &tmp, min(sizeof(tmp), *sa_size)); 306 1.1 elric *sa_size = sizeof(tmp); 307 1.1 elric } 308 1.1 elric 309 1.1 elric static krb5_error_code 310 1.1 elric ipv6_h_addr2addr (const char *addr, 311 1.1 elric krb5_address *a) 312 1.1 elric { 313 1.1 elric a->addr_type = KRB5_ADDRESS_INET6; 314 1.1 elric return krb5_data_copy(&a->address, addr, sizeof(struct in6_addr)); 315 1.1 elric } 316 1.1 elric 317 1.1 elric /* 318 1.1 elric * 319 1.1 elric */ 320 1.1 elric 321 1.1 elric static krb5_boolean 322 1.1 elric ipv6_uninteresting (const struct sockaddr *sa) 323 1.1 elric { 324 1.1 elric const struct sockaddr_in6 *sin6 = (const struct sockaddr_in6 *)sa; 325 1.1 elric const struct in6_addr *in6 = (const struct in6_addr *)&sin6->sin6_addr; 326 1.1 elric 327 1.1 elric return IN6_IS_ADDR_LINKLOCAL(in6) 328 1.1 elric || IN6_IS_ADDR_V4COMPAT(in6); 329 1.1 elric } 330 1.1 elric 331 1.1 elric static krb5_boolean 332 1.1 elric ipv6_is_loopback (const struct sockaddr *sa) 333 1.1 elric { 334 1.1 elric const struct sockaddr_in6 *sin6 = (const struct sockaddr_in6 *)sa; 335 1.1 elric const struct in6_addr *in6 = (const struct in6_addr *)&sin6->sin6_addr; 336 1.1 elric 337 1.1 elric return (IN6_IS_ADDR_LOOPBACK(in6)); 338 1.1 elric } 339 1.1 elric 340 1.1 elric static void 341 1.1 elric ipv6_anyaddr (struct sockaddr *sa, krb5_socklen_t *sa_size, int port) 342 1.1 elric { 343 1.1 elric struct sockaddr_in6 tmp; 344 1.1 elric 345 1.1 elric memset (&tmp, 0, sizeof(tmp)); 346 1.1 elric tmp.sin6_family = AF_INET6; 347 1.1 elric tmp.sin6_port = port; 348 1.1 elric tmp.sin6_addr = in6addr_any; 349 1.1 elric *sa_size = sizeof(tmp); 350 1.1 elric } 351 1.1 elric 352 1.1 elric static int 353 1.1 elric ipv6_print_addr (const krb5_address *addr, char *str, size_t len) 354 1.1 elric { 355 1.1 elric char buf[128], buf2[3]; 356 1.1 elric if(inet_ntop(AF_INET6, addr->address.data, buf, sizeof(buf)) == NULL) 357 1.1 elric { 358 1.1 elric /* XXX this is pretty ugly, but better than abort() */ 359 1.2 christos size_t i; 360 1.1 elric unsigned char *p = addr->address.data; 361 1.1 elric buf[0] = '\0'; 362 1.1 elric for(i = 0; i < addr->address.length; i++) { 363 1.1 elric snprintf(buf2, sizeof(buf2), "%02x", p[i]); 364 1.1 elric if(i > 0 && (i & 1) == 0) 365 1.1 elric strlcat(buf, ":", sizeof(buf)); 366 1.1 elric strlcat(buf, buf2, sizeof(buf)); 367 1.1 elric } 368 1.1 elric } 369 1.1 elric return snprintf(str, len, "IPv6:%s", buf); 370 1.1 elric } 371 1.1 elric 372 1.1 elric static int 373 1.1 elric ipv6_parse_addr (krb5_context context, const char *address, krb5_address *addr) 374 1.1 elric { 375 1.1 elric int ret; 376 1.1 elric struct in6_addr in6; 377 1.1 elric const char *p; 378 1.1 elric 379 1.1 elric p = strchr(address, ':'); 380 1.1 elric if(p) { 381 1.1 elric p++; 382 1.1 elric if(strncasecmp(address, "ip6:", p - address) == 0 || 383 1.1 elric strncasecmp(address, "ipv6:", p - address) == 0 || 384 1.1 elric strncasecmp(address, "inet6:", p - address) == 0) 385 1.1 elric address = p; 386 1.1 elric } 387 1.1 elric 388 1.1 elric ret = inet_pton(AF_INET6, address, &in6.s6_addr); 389 1.1 elric if(ret == 1) { 390 1.1 elric addr->addr_type = KRB5_ADDRESS_INET6; 391 1.1 elric ret = krb5_data_alloc(&addr->address, sizeof(in6.s6_addr)); 392 1.1 elric if (ret) 393 1.1 elric return -1; 394 1.1 elric memcpy(addr->address.data, in6.s6_addr, sizeof(in6.s6_addr)); 395 1.1 elric return 0; 396 1.1 elric } 397 1.1 elric return -1; 398 1.1 elric } 399 1.1 elric 400 1.1 elric static int 401 1.1 elric ipv6_mask_boundary(krb5_context context, const krb5_address *inaddr, 402 1.1 elric unsigned long len, krb5_address *low, krb5_address *high) 403 1.1 elric { 404 1.1 elric struct in6_addr addr, laddr, haddr; 405 1.1 elric uint32_t m; 406 1.1 elric int i, sub_len; 407 1.1 elric 408 1.1 elric if (len > 128) { 409 1.1 elric krb5_set_error_message(context, KRB5_PROG_ATYPE_NOSUPP, 410 1.1 elric N_("IPv6 prefix too large (%ld)", "length"), len); 411 1.1 elric return KRB5_PROG_ATYPE_NOSUPP; 412 1.1 elric } 413 1.1 elric 414 1.1 elric if (inaddr->address.length != sizeof(addr)) { 415 1.1 elric krb5_set_error_message(context, KRB5_PROG_ATYPE_NOSUPP, 416 1.1 elric N_("IPv6 addr bad length", "")); 417 1.1 elric return KRB5_PROG_ATYPE_NOSUPP; 418 1.1 elric } 419 1.1 elric 420 1.1 elric memcpy(&addr, inaddr->address.data, inaddr->address.length); 421 1.1 elric 422 1.1 elric for (i = 0; i < 16; i++) { 423 1.1 elric sub_len = min(8, len); 424 1.1 elric 425 1.1 elric m = 0xff << (8 - sub_len); 426 1.2 christos 427 1.1 elric laddr.s6_addr[i] = addr.s6_addr[i] & m; 428 1.1 elric haddr.s6_addr[i] = (addr.s6_addr[i] & m) | ~m; 429 1.1 elric 430 1.1 elric if (len > 8) 431 1.1 elric len -= 8; 432 1.1 elric else 433 1.1 elric len = 0; 434 1.1 elric } 435 1.1 elric 436 1.1 elric low->addr_type = KRB5_ADDRESS_INET6; 437 1.1 elric if (krb5_data_alloc(&low->address, sizeof(laddr.s6_addr)) != 0) 438 1.1 elric return -1; 439 1.1 elric memcpy(low->address.data, laddr.s6_addr, sizeof(laddr.s6_addr)); 440 1.1 elric 441 1.1 elric high->addr_type = KRB5_ADDRESS_INET6; 442 1.1 elric if (krb5_data_alloc(&high->address, sizeof(haddr.s6_addr)) != 0) { 443 1.1 elric krb5_free_address(context, low); 444 1.1 elric return -1; 445 1.1 elric } 446 1.1 elric memcpy(high->address.data, haddr.s6_addr, sizeof(haddr.s6_addr)); 447 1.1 elric 448 1.1 elric return 0; 449 1.1 elric } 450 1.1 elric 451 1.1 elric #endif /* IPv6 */ 452 1.1 elric 453 1.1 elric #ifndef HEIMDAL_SMALLER 454 1.1 elric 455 1.1 elric /* 456 1.1 elric * table 457 1.1 elric */ 458 1.1 elric 459 1.1 elric #define KRB5_ADDRESS_ARANGE (-100) 460 1.1 elric 461 1.1 elric struct arange { 462 1.1 elric krb5_address low; 463 1.1 elric krb5_address high; 464 1.1 elric }; 465 1.1 elric 466 1.1 elric static int 467 1.1 elric arange_parse_addr (krb5_context context, 468 1.1 elric const char *address, krb5_address *addr) 469 1.1 elric { 470 1.1 elric char buf[1024], *p; 471 1.1 elric krb5_address low0, high0; 472 1.1 elric struct arange *a; 473 1.1 elric krb5_error_code ret; 474 1.1 elric 475 1.1 elric if(strncasecmp(address, "RANGE:", 6) != 0) 476 1.1 elric return -1; 477 1.1 elric 478 1.1 elric address += 6; 479 1.1 elric 480 1.1 elric p = strrchr(address, '/'); 481 1.1 elric if (p) { 482 1.1 elric krb5_addresses addrmask; 483 1.1 elric char *q; 484 1.1 elric long num; 485 1.1 elric 486 1.1 elric if (strlcpy(buf, address, sizeof(buf)) > sizeof(buf)) 487 1.1 elric return -1; 488 1.1 elric buf[p - address] = '\0'; 489 1.1 elric ret = krb5_parse_address(context, buf, &addrmask); 490 1.1 elric if (ret) 491 1.1 elric return ret; 492 1.1 elric if(addrmask.len != 1) { 493 1.1 elric krb5_free_addresses(context, &addrmask); 494 1.1 elric return -1; 495 1.1 elric } 496 1.2 christos 497 1.1 elric address += p - address + 1; 498 1.1 elric 499 1.1 elric num = strtol(address, &q, 10); 500 1.1 elric if (q == address || *q != '\0' || num < 0) { 501 1.1 elric krb5_free_addresses(context, &addrmask); 502 1.1 elric return -1; 503 1.1 elric } 504 1.1 elric 505 1.1 elric ret = krb5_address_prefixlen_boundary(context, &addrmask.val[0], num, 506 1.1 elric &low0, &high0); 507 1.1 elric krb5_free_addresses(context, &addrmask); 508 1.1 elric if (ret) 509 1.1 elric return ret; 510 1.1 elric 511 1.1 elric } else { 512 1.1 elric krb5_addresses low, high; 513 1.2 christos 514 1.1 elric strsep_copy(&address, "-", buf, sizeof(buf)); 515 1.1 elric ret = krb5_parse_address(context, buf, &low); 516 1.1 elric if(ret) 517 1.1 elric return ret; 518 1.1 elric if(low.len != 1) { 519 1.1 elric krb5_free_addresses(context, &low); 520 1.1 elric return -1; 521 1.1 elric } 522 1.2 christos 523 1.1 elric strsep_copy(&address, "-", buf, sizeof(buf)); 524 1.1 elric ret = krb5_parse_address(context, buf, &high); 525 1.1 elric if(ret) { 526 1.1 elric krb5_free_addresses(context, &low); 527 1.1 elric return ret; 528 1.1 elric } 529 1.2 christos 530 1.3 christos if(high.len != 1 || high.val[0].addr_type != low.val[0].addr_type) { 531 1.1 elric krb5_free_addresses(context, &low); 532 1.1 elric krb5_free_addresses(context, &high); 533 1.1 elric return -1; 534 1.1 elric } 535 1.1 elric 536 1.1 elric ret = krb5_copy_address(context, &high.val[0], &high0); 537 1.1 elric if (ret == 0) { 538 1.1 elric ret = krb5_copy_address(context, &low.val[0], &low0); 539 1.1 elric if (ret) 540 1.1 elric krb5_free_address(context, &high0); 541 1.1 elric } 542 1.1 elric krb5_free_addresses(context, &low); 543 1.1 elric krb5_free_addresses(context, &high); 544 1.1 elric if (ret) 545 1.1 elric return ret; 546 1.1 elric } 547 1.1 elric 548 1.1 elric krb5_data_alloc(&addr->address, sizeof(*a)); 549 1.1 elric addr->addr_type = KRB5_ADDRESS_ARANGE; 550 1.1 elric a = addr->address.data; 551 1.1 elric 552 1.1 elric if(krb5_address_order(context, &low0, &high0) < 0) { 553 1.1 elric a->low = low0; 554 1.1 elric a->high = high0; 555 1.1 elric } else { 556 1.1 elric a->low = high0; 557 1.1 elric a->high = low0; 558 1.1 elric } 559 1.1 elric return 0; 560 1.1 elric } 561 1.1 elric 562 1.1 elric static int 563 1.1 elric arange_free (krb5_context context, krb5_address *addr) 564 1.1 elric { 565 1.1 elric struct arange *a; 566 1.1 elric a = addr->address.data; 567 1.1 elric krb5_free_address(context, &a->low); 568 1.1 elric krb5_free_address(context, &a->high); 569 1.1 elric krb5_data_free(&addr->address); 570 1.1 elric return 0; 571 1.1 elric } 572 1.1 elric 573 1.1 elric 574 1.1 elric static int 575 1.1 elric arange_copy (krb5_context context, const krb5_address *inaddr, 576 1.1 elric krb5_address *outaddr) 577 1.1 elric { 578 1.1 elric krb5_error_code ret; 579 1.1 elric struct arange *i, *o; 580 1.1 elric 581 1.1 elric outaddr->addr_type = KRB5_ADDRESS_ARANGE; 582 1.1 elric ret = krb5_data_alloc(&outaddr->address, sizeof(*o)); 583 1.1 elric if(ret) 584 1.1 elric return ret; 585 1.1 elric i = inaddr->address.data; 586 1.1 elric o = outaddr->address.data; 587 1.1 elric ret = krb5_copy_address(context, &i->low, &o->low); 588 1.1 elric if(ret) { 589 1.1 elric krb5_data_free(&outaddr->address); 590 1.1 elric return ret; 591 1.1 elric } 592 1.1 elric ret = krb5_copy_address(context, &i->high, &o->high); 593 1.1 elric if(ret) { 594 1.1 elric krb5_free_address(context, &o->low); 595 1.1 elric krb5_data_free(&outaddr->address); 596 1.1 elric return ret; 597 1.1 elric } 598 1.1 elric return 0; 599 1.1 elric } 600 1.1 elric 601 1.1 elric static int 602 1.1 elric arange_print_addr (const krb5_address *addr, char *str, size_t len) 603 1.1 elric { 604 1.1 elric struct arange *a; 605 1.1 elric krb5_error_code ret; 606 1.1 elric size_t l, size, ret_len; 607 1.1 elric 608 1.1 elric a = addr->address.data; 609 1.1 elric 610 1.1 elric l = strlcpy(str, "RANGE:", len); 611 1.1 elric ret_len = l; 612 1.1 elric if (l > len) 613 1.1 elric l = len; 614 1.1 elric size = l; 615 1.2 christos 616 1.1 elric ret = krb5_print_address (&a->low, str + size, len - size, &l); 617 1.1 elric if (ret) 618 1.1 elric return ret; 619 1.1 elric ret_len += l; 620 1.1 elric if (len - size > l) 621 1.1 elric size += l; 622 1.1 elric else 623 1.1 elric size = len; 624 1.1 elric 625 1.1 elric l = strlcat(str + size, "-", len - size); 626 1.1 elric ret_len += l; 627 1.1 elric if (len - size > l) 628 1.1 elric size += l; 629 1.1 elric else 630 1.1 elric size = len; 631 1.1 elric 632 1.1 elric ret = krb5_print_address (&a->high, str + size, len - size, &l); 633 1.1 elric if (ret) 634 1.1 elric return ret; 635 1.1 elric ret_len += l; 636 1.1 elric 637 1.1 elric return ret_len; 638 1.1 elric } 639 1.1 elric 640 1.1 elric static int 641 1.1 elric arange_order_addr(krb5_context context, 642 1.1 elric const krb5_address *addr1, 643 1.1 elric const krb5_address *addr2) 644 1.1 elric { 645 1.1 elric int tmp1, tmp2, sign; 646 1.1 elric struct arange *a; 647 1.1 elric const krb5_address *a2; 648 1.1 elric 649 1.1 elric if(addr1->addr_type == KRB5_ADDRESS_ARANGE) { 650 1.1 elric a = addr1->address.data; 651 1.1 elric a2 = addr2; 652 1.1 elric sign = 1; 653 1.1 elric } else if(addr2->addr_type == KRB5_ADDRESS_ARANGE) { 654 1.1 elric a = addr2->address.data; 655 1.1 elric a2 = addr1; 656 1.1 elric sign = -1; 657 1.2 christos } else { 658 1.1 elric abort(); 659 1.2 christos UNREACHABLE(return 0); 660 1.2 christos } 661 1.2 christos 662 1.1 elric if(a2->addr_type == KRB5_ADDRESS_ARANGE) { 663 1.1 elric struct arange *b = a2->address.data; 664 1.1 elric tmp1 = krb5_address_order(context, &a->low, &b->low); 665 1.1 elric if(tmp1 != 0) 666 1.1 elric return sign * tmp1; 667 1.1 elric return sign * krb5_address_order(context, &a->high, &b->high); 668 1.1 elric } else if(a2->addr_type == a->low.addr_type) { 669 1.1 elric tmp1 = krb5_address_order(context, &a->low, a2); 670 1.1 elric if(tmp1 > 0) 671 1.1 elric return sign; 672 1.1 elric tmp2 = krb5_address_order(context, &a->high, a2); 673 1.1 elric if(tmp2 < 0) 674 1.1 elric return -sign; 675 1.1 elric return 0; 676 1.1 elric } else { 677 1.1 elric return sign * (addr1->addr_type - addr2->addr_type); 678 1.1 elric } 679 1.1 elric } 680 1.1 elric 681 1.1 elric #endif /* HEIMDAL_SMALLER */ 682 1.1 elric 683 1.1 elric static int 684 1.1 elric addrport_print_addr (const krb5_address *addr, char *str, size_t len) 685 1.1 elric { 686 1.1 elric krb5_error_code ret; 687 1.1 elric krb5_address addr1, addr2; 688 1.1 elric uint16_t port = 0; 689 1.1 elric size_t ret_len = 0, l, size = 0; 690 1.1 elric krb5_storage *sp; 691 1.1 elric 692 1.1 elric sp = krb5_storage_from_data((krb5_data*)rk_UNCONST(&addr->address)); 693 1.1 elric if (sp == NULL) 694 1.1 elric return ENOMEM; 695 1.1 elric 696 1.1 elric /* for totally obscure reasons, these are not in network byteorder */ 697 1.1 elric krb5_storage_set_byteorder(sp, KRB5_STORAGE_BYTEORDER_LE); 698 1.1 elric 699 1.1 elric krb5_storage_seek(sp, 2, SEEK_CUR); /* skip first two bytes */ 700 1.1 elric krb5_ret_address(sp, &addr1); 701 1.1 elric 702 1.1 elric krb5_storage_seek(sp, 2, SEEK_CUR); /* skip two bytes */ 703 1.1 elric krb5_ret_address(sp, &addr2); 704 1.1 elric krb5_storage_free(sp); 705 1.1 elric if(addr2.addr_type == KRB5_ADDRESS_IPPORT && addr2.address.length == 2) { 706 1.1 elric unsigned long value; 707 1.1 elric _krb5_get_int(addr2.address.data, &value, 2); 708 1.1 elric port = value; 709 1.1 elric } 710 1.1 elric l = strlcpy(str, "ADDRPORT:", len); 711 1.1 elric ret_len += l; 712 1.1 elric if (len > l) 713 1.1 elric size += l; 714 1.1 elric else 715 1.1 elric size = len; 716 1.1 elric 717 1.1 elric ret = krb5_print_address(&addr1, str + size, len - size, &l); 718 1.1 elric if (ret) 719 1.1 elric return ret; 720 1.1 elric ret_len += l; 721 1.1 elric if (len - size > l) 722 1.1 elric size += l; 723 1.1 elric else 724 1.1 elric size = len; 725 1.1 elric 726 1.1 elric ret = snprintf(str + size, len - size, ",PORT=%u", port); 727 1.1 elric if (ret < 0) 728 1.1 elric return EINVAL; 729 1.1 elric ret_len += ret; 730 1.1 elric return ret_len; 731 1.1 elric } 732 1.1 elric 733 1.1 elric static struct addr_operations at[] = { 734 1.2 christos { 735 1.2 christos AF_INET, KRB5_ADDRESS_INET, sizeof(struct sockaddr_in), 736 1.2 christos ipv4_sockaddr2addr, 737 1.2 christos ipv4_sockaddr2port, 738 1.2 christos ipv4_addr2sockaddr, 739 1.2 christos ipv4_h_addr2sockaddr, 740 1.2 christos ipv4_h_addr2addr, 741 1.2 christos ipv4_uninteresting, 742 1.2 christos ipv4_is_loopback, 743 1.2 christos ipv4_anyaddr, 744 1.2 christos ipv4_print_addr, 745 1.2 christos ipv4_parse_addr, 746 1.2 christos NULL, 747 1.2 christos NULL, 748 1.2 christos NULL, 749 1.2 christos ipv4_mask_boundary 750 1.2 christos }, 751 1.1 elric #ifdef HAVE_IPV6 752 1.2 christos { 753 1.2 christos AF_INET6, KRB5_ADDRESS_INET6, sizeof(struct sockaddr_in6), 754 1.2 christos ipv6_sockaddr2addr, 755 1.2 christos ipv6_sockaddr2port, 756 1.2 christos ipv6_addr2sockaddr, 757 1.2 christos ipv6_h_addr2sockaddr, 758 1.2 christos ipv6_h_addr2addr, 759 1.2 christos ipv6_uninteresting, 760 1.2 christos ipv6_is_loopback, 761 1.2 christos ipv6_anyaddr, 762 1.2 christos ipv6_print_addr, 763 1.2 christos ipv6_parse_addr, 764 1.2 christos NULL, 765 1.2 christos NULL, 766 1.2 christos NULL, 767 1.2 christos ipv6_mask_boundary 768 1.2 christos } , 769 1.1 elric #endif 770 1.1 elric #ifndef HEIMDAL_SMALLER 771 1.1 elric /* fake address type */ 772 1.2 christos { 773 1.2 christos KRB5_ADDRESS_ARANGE, KRB5_ADDRESS_ARANGE, sizeof(struct arange), 774 1.2 christos NULL, 775 1.2 christos NULL, 776 1.2 christos NULL, 777 1.2 christos NULL, 778 1.2 christos NULL, 779 1.2 christos NULL, 780 1.2 christos NULL, 781 1.2 christos NULL, 782 1.2 christos arange_print_addr, 783 1.2 christos arange_parse_addr, 784 1.2 christos arange_order_addr, 785 1.2 christos arange_free, 786 1.2 christos arange_copy, 787 1.2 christos NULL 788 1.2 christos }, 789 1.1 elric #endif 790 1.2 christos { 791 1.2 christos KRB5_ADDRESS_ADDRPORT, KRB5_ADDRESS_ADDRPORT, 0, 792 1.2 christos NULL, 793 1.2 christos NULL, 794 1.2 christos NULL, 795 1.2 christos NULL, 796 1.2 christos NULL, 797 1.2 christos NULL, 798 1.2 christos NULL, 799 1.2 christos NULL, 800 1.2 christos addrport_print_addr, 801 1.2 christos NULL, 802 1.2 christos NULL, 803 1.2 christos NULL, 804 1.2 christos NULL, 805 1.2 christos NULL 806 1.2 christos } 807 1.1 elric }; 808 1.1 elric 809 1.1 elric static int num_addrs = sizeof(at) / sizeof(at[0]); 810 1.1 elric 811 1.1 elric static size_t max_sockaddr_size = 0; 812 1.1 elric 813 1.1 elric /* 814 1.1 elric * generic functions 815 1.1 elric */ 816 1.1 elric 817 1.1 elric static struct addr_operations * 818 1.1 elric find_af(int af) 819 1.1 elric { 820 1.1 elric struct addr_operations *a; 821 1.1 elric 822 1.1 elric for (a = at; a < at + num_addrs; ++a) 823 1.1 elric if (af == a->af) 824 1.1 elric return a; 825 1.1 elric return NULL; 826 1.1 elric } 827 1.1 elric 828 1.1 elric static struct addr_operations * 829 1.2 christos find_atype(krb5_address_type atype) 830 1.1 elric { 831 1.1 elric struct addr_operations *a; 832 1.1 elric 833 1.1 elric for (a = at; a < at + num_addrs; ++a) 834 1.1 elric if (atype == a->atype) 835 1.1 elric return a; 836 1.1 elric return NULL; 837 1.1 elric } 838 1.1 elric 839 1.1 elric /** 840 1.1 elric * krb5_sockaddr2address stores a address a "struct sockaddr" sa in 841 1.1 elric * the krb5_address addr. 842 1.1 elric * 843 1.1 elric * @param context a Keberos context 844 1.1 elric * @param sa a struct sockaddr to extract the address from 845 1.1 elric * @param addr an Kerberos 5 address to store the address in. 846 1.1 elric * 847 1.1 elric * @return Return an error code or 0. 848 1.1 elric * 849 1.1 elric * @ingroup krb5_address 850 1.1 elric */ 851 1.1 elric 852 1.1 elric KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 853 1.1 elric krb5_sockaddr2address (krb5_context context, 854 1.1 elric const struct sockaddr *sa, krb5_address *addr) 855 1.1 elric { 856 1.1 elric struct addr_operations *a = find_af(sa->sa_family); 857 1.1 elric if (a == NULL) { 858 1.1 elric krb5_set_error_message (context, KRB5_PROG_ATYPE_NOSUPP, 859 1.1 elric N_("Address family %d not supported", ""), 860 1.1 elric sa->sa_family); 861 1.1 elric return KRB5_PROG_ATYPE_NOSUPP; 862 1.1 elric } 863 1.1 elric return (*a->sockaddr2addr)(sa, addr); 864 1.1 elric } 865 1.1 elric 866 1.1 elric /** 867 1.1 elric * krb5_sockaddr2port extracts a port (if possible) from a "struct 868 1.1 elric * sockaddr. 869 1.1 elric * 870 1.1 elric * @param context a Keberos context 871 1.1 elric * @param sa a struct sockaddr to extract the port from 872 1.1 elric * @param port a pointer to an int16_t store the port in. 873 1.1 elric * 874 1.1 elric * @return Return an error code or 0. Will return 875 1.1 elric * KRB5_PROG_ATYPE_NOSUPP in case address type is not supported. 876 1.1 elric * 877 1.1 elric * @ingroup krb5_address 878 1.1 elric */ 879 1.1 elric 880 1.1 elric KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 881 1.1 elric krb5_sockaddr2port (krb5_context context, 882 1.1 elric const struct sockaddr *sa, int16_t *port) 883 1.1 elric { 884 1.1 elric struct addr_operations *a = find_af(sa->sa_family); 885 1.1 elric if (a == NULL) { 886 1.1 elric krb5_set_error_message (context, KRB5_PROG_ATYPE_NOSUPP, 887 1.1 elric N_("Address family %d not supported", ""), 888 1.1 elric sa->sa_family); 889 1.1 elric return KRB5_PROG_ATYPE_NOSUPP; 890 1.1 elric } 891 1.1 elric return (*a->sockaddr2port)(sa, port); 892 1.1 elric } 893 1.1 elric 894 1.1 elric /** 895 1.1 elric * krb5_addr2sockaddr sets the "struct sockaddr sockaddr" from addr 896 1.1 elric * and port. The argument sa_size should initially contain the size of 897 1.1 elric * the sa and after the call, it will contain the actual length of the 898 1.1 elric * address. In case of the sa is too small to fit the whole address, 899 1.1 elric * the up to *sa_size will be stored, and then *sa_size will be set to 900 1.1 elric * the required length. 901 1.1 elric * 902 1.1 elric * @param context a Keberos context 903 1.1 elric * @param addr the address to copy the from 904 1.1 elric * @param sa the struct sockaddr that will be filled in 905 1.1 elric * @param sa_size pointer to length of sa, and after the call, it will 906 1.1 elric * contain the actual length of the address. 907 1.1 elric * @param port set port in sa. 908 1.1 elric * 909 1.1 elric * @return Return an error code or 0. Will return 910 1.1 elric * KRB5_PROG_ATYPE_NOSUPP in case address type is not supported. 911 1.1 elric * 912 1.1 elric * @ingroup krb5_address 913 1.1 elric */ 914 1.1 elric 915 1.1 elric KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 916 1.1 elric krb5_addr2sockaddr (krb5_context context, 917 1.1 elric const krb5_address *addr, 918 1.1 elric struct sockaddr *sa, 919 1.1 elric krb5_socklen_t *sa_size, 920 1.1 elric int port) 921 1.1 elric { 922 1.1 elric struct addr_operations *a = find_atype(addr->addr_type); 923 1.1 elric 924 1.1 elric if (a == NULL) { 925 1.1 elric krb5_set_error_message (context, KRB5_PROG_ATYPE_NOSUPP, 926 1.1 elric N_("Address type %d not supported", 927 1.1 elric "krb5_address type"), 928 1.1 elric addr->addr_type); 929 1.1 elric return KRB5_PROG_ATYPE_NOSUPP; 930 1.1 elric } 931 1.1 elric if (a->addr2sockaddr == NULL) { 932 1.1 elric krb5_set_error_message (context, 933 1.1 elric KRB5_PROG_ATYPE_NOSUPP, 934 1.1 elric N_("Can't convert address type %d to sockaddr", ""), 935 1.1 elric addr->addr_type); 936 1.1 elric return KRB5_PROG_ATYPE_NOSUPP; 937 1.1 elric } 938 1.1 elric (*a->addr2sockaddr)(addr, sa, sa_size, port); 939 1.1 elric return 0; 940 1.1 elric } 941 1.1 elric 942 1.1 elric /** 943 1.1 elric * krb5_max_sockaddr_size returns the max size of the .Li struct 944 1.1 elric * sockaddr that the Kerberos library will return. 945 1.1 elric * 946 1.1 elric * @return Return an size_t of the maximum struct sockaddr. 947 1.1 elric * 948 1.1 elric * @ingroup krb5_address 949 1.1 elric */ 950 1.1 elric 951 1.1 elric KRB5_LIB_FUNCTION size_t KRB5_LIB_CALL 952 1.1 elric krb5_max_sockaddr_size (void) 953 1.1 elric { 954 1.1 elric if (max_sockaddr_size == 0) { 955 1.1 elric struct addr_operations *a; 956 1.1 elric 957 1.1 elric for(a = at; a < at + num_addrs; ++a) 958 1.1 elric max_sockaddr_size = max(max_sockaddr_size, a->max_sockaddr_size); 959 1.1 elric } 960 1.1 elric return max_sockaddr_size; 961 1.1 elric } 962 1.1 elric 963 1.1 elric /** 964 1.1 elric * krb5_sockaddr_uninteresting returns TRUE for all .Fa sa that the 965 1.1 elric * kerberos library thinks are uninteresting. One example are link 966 1.1 elric * local addresses. 967 1.1 elric * 968 1.1 elric * @param sa pointer to struct sockaddr that might be interesting. 969 1.1 elric * 970 1.1 elric * @return Return a non zero for uninteresting addresses. 971 1.1 elric * 972 1.1 elric * @ingroup krb5_address 973 1.1 elric */ 974 1.1 elric 975 1.1 elric KRB5_LIB_FUNCTION krb5_boolean KRB5_LIB_CALL 976 1.1 elric krb5_sockaddr_uninteresting(const struct sockaddr *sa) 977 1.1 elric { 978 1.1 elric struct addr_operations *a = find_af(sa->sa_family); 979 1.1 elric if (a == NULL || a->uninteresting == NULL) 980 1.1 elric return TRUE; 981 1.1 elric return (*a->uninteresting)(sa); 982 1.1 elric } 983 1.1 elric 984 1.1 elric KRB5_LIB_FUNCTION krb5_boolean KRB5_LIB_CALL 985 1.1 elric krb5_sockaddr_is_loopback(const struct sockaddr *sa) 986 1.1 elric { 987 1.1 elric struct addr_operations *a = find_af(sa->sa_family); 988 1.1 elric if (a == NULL || a->is_loopback == NULL) 989 1.1 elric return TRUE; 990 1.1 elric return (*a->is_loopback)(sa); 991 1.1 elric } 992 1.1 elric 993 1.1 elric /** 994 1.1 elric * krb5_h_addr2sockaddr initializes a "struct sockaddr sa" from af and 995 1.1 elric * the "struct hostent" (see gethostbyname(3) ) h_addr_list 996 1.1 elric * component. The argument sa_size should initially contain the size 997 1.1 elric * of the sa, and after the call, it will contain the actual length of 998 1.1 elric * the address. 999 1.1 elric * 1000 1.1 elric * @param context a Keberos context 1001 1.1 elric * @param af addresses 1002 1.1 elric * @param addr address 1003 1.1 elric * @param sa returned struct sockaddr 1004 1.1 elric * @param sa_size size of sa 1005 1.1 elric * @param port port to set in sa. 1006 1.1 elric * 1007 1.1 elric * @return Return an error code or 0. 1008 1.1 elric * 1009 1.1 elric * @ingroup krb5_address 1010 1.1 elric */ 1011 1.1 elric 1012 1.1 elric KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 1013 1.1 elric krb5_h_addr2sockaddr (krb5_context context, 1014 1.1 elric int af, 1015 1.1 elric const char *addr, struct sockaddr *sa, 1016 1.1 elric krb5_socklen_t *sa_size, 1017 1.1 elric int port) 1018 1.1 elric { 1019 1.1 elric struct addr_operations *a = find_af(af); 1020 1.1 elric if (a == NULL) { 1021 1.1 elric krb5_set_error_message (context, KRB5_PROG_ATYPE_NOSUPP, 1022 1.1 elric "Address family %d not supported", af); 1023 1.1 elric return KRB5_PROG_ATYPE_NOSUPP; 1024 1.1 elric } 1025 1.1 elric (*a->h_addr2sockaddr)(addr, sa, sa_size, port); 1026 1.1 elric return 0; 1027 1.1 elric } 1028 1.1 elric 1029 1.1 elric /** 1030 1.1 elric * krb5_h_addr2addr works like krb5_h_addr2sockaddr with the exception 1031 1.1 elric * that it operates on a krb5_address instead of a struct sockaddr. 1032 1.1 elric * 1033 1.1 elric * @param context a Keberos context 1034 1.1 elric * @param af address family 1035 1.1 elric * @param haddr host address from struct hostent. 1036 1.1 elric * @param addr returned krb5_address. 1037 1.1 elric * 1038 1.1 elric * @return Return an error code or 0. 1039 1.1 elric * 1040 1.1 elric * @ingroup krb5_address 1041 1.1 elric */ 1042 1.1 elric 1043 1.1 elric KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 1044 1.1 elric krb5_h_addr2addr (krb5_context context, 1045 1.1 elric int af, 1046 1.1 elric const char *haddr, krb5_address *addr) 1047 1.1 elric { 1048 1.1 elric struct addr_operations *a = find_af(af); 1049 1.1 elric if (a == NULL) { 1050 1.1 elric krb5_set_error_message (context, KRB5_PROG_ATYPE_NOSUPP, 1051 1.1 elric N_("Address family %d not supported", ""), af); 1052 1.1 elric return KRB5_PROG_ATYPE_NOSUPP; 1053 1.1 elric } 1054 1.1 elric return (*a->h_addr2addr)(haddr, addr); 1055 1.1 elric } 1056 1.1 elric 1057 1.1 elric /** 1058 1.1 elric * krb5_anyaddr fills in a "struct sockaddr sa" that can be used to 1059 1.1 elric * bind(2) to. The argument sa_size should initially contain the size 1060 1.1 elric * of the sa, and after the call, it will contain the actual length 1061 1.1 elric * of the address. 1062 1.1 elric * 1063 1.1 elric * @param context a Keberos context 1064 1.1 elric * @param af address family 1065 1.1 elric * @param sa sockaddr 1066 1.1 elric * @param sa_size lenght of sa. 1067 1.1 elric * @param port for to fill into sa. 1068 1.1 elric * 1069 1.1 elric * @return Return an error code or 0. 1070 1.1 elric * 1071 1.1 elric * @ingroup krb5_address 1072 1.1 elric */ 1073 1.1 elric 1074 1.1 elric KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 1075 1.1 elric krb5_anyaddr (krb5_context context, 1076 1.1 elric int af, 1077 1.1 elric struct sockaddr *sa, 1078 1.1 elric krb5_socklen_t *sa_size, 1079 1.1 elric int port) 1080 1.1 elric { 1081 1.1 elric struct addr_operations *a = find_af (af); 1082 1.1 elric 1083 1.1 elric if (a == NULL) { 1084 1.1 elric krb5_set_error_message (context, KRB5_PROG_ATYPE_NOSUPP, 1085 1.1 elric N_("Address family %d not supported", ""), af); 1086 1.1 elric return KRB5_PROG_ATYPE_NOSUPP; 1087 1.1 elric } 1088 1.1 elric 1089 1.1 elric (*a->anyaddr)(sa, sa_size, port); 1090 1.1 elric return 0; 1091 1.1 elric } 1092 1.1 elric 1093 1.1 elric /** 1094 1.1 elric * krb5_print_address prints the address in addr to the string string 1095 1.1 elric * that have the length len. If ret_len is not NULL, it will be filled 1096 1.1 elric * with the length of the string if size were unlimited (not including 1097 1.1 elric * the final NUL) . 1098 1.1 elric * 1099 1.1 elric * @param addr address to be printed 1100 1.1 elric * @param str pointer string to print the address into 1101 1.1 elric * @param len length that will fit into area pointed to by "str". 1102 1.1 elric * @param ret_len return length the str. 1103 1.1 elric * 1104 1.1 elric * @return Return an error code or 0. 1105 1.1 elric * 1106 1.1 elric * @ingroup krb5_address 1107 1.1 elric */ 1108 1.1 elric 1109 1.1 elric KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 1110 1.1 elric krb5_print_address (const krb5_address *addr, 1111 1.1 elric char *str, size_t len, size_t *ret_len) 1112 1.1 elric { 1113 1.1 elric struct addr_operations *a = find_atype(addr->addr_type); 1114 1.1 elric int ret; 1115 1.1 elric 1116 1.1 elric if (a == NULL || a->print_addr == NULL) { 1117 1.1 elric char *s; 1118 1.1 elric int l; 1119 1.2 christos size_t i; 1120 1.1 elric 1121 1.1 elric s = str; 1122 1.1 elric l = snprintf(s, len, "TYPE_%d:", addr->addr_type); 1123 1.2 christos if (l < 0 || (size_t)l >= len) 1124 1.1 elric return EINVAL; 1125 1.1 elric s += l; 1126 1.1 elric len -= l; 1127 1.1 elric for(i = 0; i < addr->address.length; i++) { 1128 1.1 elric l = snprintf(s, len, "%02x", ((char*)addr->address.data)[i]); 1129 1.2 christos if (l < 0 || (size_t)l >= len) 1130 1.1 elric return EINVAL; 1131 1.1 elric len -= l; 1132 1.1 elric s += l; 1133 1.1 elric } 1134 1.1 elric if(ret_len != NULL) 1135 1.1 elric *ret_len = s - str; 1136 1.1 elric return 0; 1137 1.1 elric } 1138 1.1 elric ret = (*a->print_addr)(addr, str, len); 1139 1.1 elric if (ret < 0) 1140 1.1 elric return EINVAL; 1141 1.1 elric if(ret_len != NULL) 1142 1.1 elric *ret_len = ret; 1143 1.1 elric return 0; 1144 1.1 elric } 1145 1.1 elric 1146 1.1 elric /** 1147 1.1 elric * krb5_parse_address returns the resolved hostname in string to the 1148 1.1 elric * krb5_addresses addresses . 1149 1.1 elric * 1150 1.1 elric * @param context a Keberos context 1151 1.1 elric * @param string 1152 1.1 elric * @param addresses 1153 1.1 elric * 1154 1.1 elric * @return Return an error code or 0. 1155 1.1 elric * 1156 1.1 elric * @ingroup krb5_address 1157 1.1 elric */ 1158 1.1 elric 1159 1.1 elric KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 1160 1.1 elric krb5_parse_address(krb5_context context, 1161 1.1 elric const char *string, 1162 1.1 elric krb5_addresses *addresses) 1163 1.1 elric { 1164 1.1 elric int i, n; 1165 1.1 elric struct addrinfo *ai, *a; 1166 1.2 christos struct addrinfo hint; 1167 1.1 elric int error; 1168 1.1 elric int save_errno; 1169 1.1 elric 1170 1.1 elric addresses->len = 0; 1171 1.1 elric addresses->val = NULL; 1172 1.1 elric 1173 1.1 elric for(i = 0; i < num_addrs; i++) { 1174 1.1 elric if(at[i].parse_addr) { 1175 1.1 elric krb5_address addr; 1176 1.1 elric if((*at[i].parse_addr)(context, string, &addr) == 0) { 1177 1.1 elric ALLOC_SEQ(addresses, 1); 1178 1.2 christos if (addresses->val == NULL) 1179 1.2 christos return krb5_enomem(context); 1180 1.1 elric addresses->val[0] = addr; 1181 1.1 elric return 0; 1182 1.1 elric } 1183 1.1 elric } 1184 1.1 elric } 1185 1.1 elric 1186 1.2 christos /* if not parsed as numeric address, do a name lookup */ 1187 1.2 christos memset(&hint, 0, sizeof(hint)); 1188 1.2 christos hint.ai_family = AF_UNSPEC; 1189 1.2 christos error = getaddrinfo (string, NULL, &hint, &ai); 1190 1.1 elric if (error) { 1191 1.1 elric krb5_error_code ret2; 1192 1.1 elric save_errno = errno; 1193 1.1 elric ret2 = krb5_eai_to_heim_errno(error, save_errno); 1194 1.1 elric krb5_set_error_message (context, ret2, "%s: %s", 1195 1.1 elric string, gai_strerror(error)); 1196 1.1 elric return ret2; 1197 1.1 elric } 1198 1.1 elric 1199 1.1 elric n = 0; 1200 1.1 elric for (a = ai; a != NULL; a = a->ai_next) 1201 1.1 elric ++n; 1202 1.1 elric 1203 1.1 elric ALLOC_SEQ(addresses, n); 1204 1.1 elric if (addresses->val == NULL) { 1205 1.1 elric freeaddrinfo(ai); 1206 1.2 christos return krb5_enomem(context); 1207 1.1 elric } 1208 1.1 elric 1209 1.1 elric addresses->len = 0; 1210 1.1 elric for (a = ai, i = 0; a != NULL; a = a->ai_next) { 1211 1.2 christos if (krb5_sockaddr2address (context, a->ai_addr, &addresses->val[i])) 1212 1.1 elric continue; 1213 1.1 elric if(krb5_address_search(context, &addresses->val[i], addresses)) { 1214 1.1 elric krb5_free_address(context, &addresses->val[i]); 1215 1.1 elric continue; 1216 1.1 elric } 1217 1.1 elric i++; 1218 1.1 elric addresses->len = i; 1219 1.1 elric } 1220 1.1 elric freeaddrinfo (ai); 1221 1.1 elric return 0; 1222 1.1 elric } 1223 1.1 elric 1224 1.1 elric /** 1225 1.1 elric * krb5_address_order compares the addresses addr1 and addr2 so that 1226 1.1 elric * it can be used for sorting addresses. If the addresses are the same 1227 1.1 elric * address krb5_address_order will return 0. Behavies like memcmp(2). 1228 1.1 elric * 1229 1.1 elric * @param context a Keberos context 1230 1.1 elric * @param addr1 krb5_address to compare 1231 1.1 elric * @param addr2 krb5_address to compare 1232 1.1 elric * 1233 1.1 elric * @return < 0 if address addr1 in "less" then addr2. 0 if addr1 and 1234 1.1 elric * addr2 is the same address, > 0 if addr2 is "less" then addr1. 1235 1.1 elric * 1236 1.1 elric * @ingroup krb5_address 1237 1.1 elric */ 1238 1.1 elric 1239 1.1 elric KRB5_LIB_FUNCTION int KRB5_LIB_CALL 1240 1.1 elric krb5_address_order(krb5_context context, 1241 1.1 elric const krb5_address *addr1, 1242 1.1 elric const krb5_address *addr2) 1243 1.1 elric { 1244 1.1 elric /* this sucks; what if both addresses have order functions, which 1245 1.1 elric should we call? this works for now, though */ 1246 1.1 elric struct addr_operations *a; 1247 1.1 elric a = find_atype(addr1->addr_type); 1248 1.1 elric if(a == NULL) { 1249 1.1 elric krb5_set_error_message (context, KRB5_PROG_ATYPE_NOSUPP, 1250 1.1 elric N_("Address family %d not supported", ""), 1251 1.1 elric addr1->addr_type); 1252 1.1 elric return KRB5_PROG_ATYPE_NOSUPP; 1253 1.1 elric } 1254 1.1 elric if(a->order_addr != NULL) 1255 1.1 elric return (*a->order_addr)(context, addr1, addr2); 1256 1.1 elric a = find_atype(addr2->addr_type); 1257 1.1 elric if(a == NULL) { 1258 1.1 elric krb5_set_error_message (context, KRB5_PROG_ATYPE_NOSUPP, 1259 1.1 elric N_("Address family %d not supported", ""), 1260 1.1 elric addr2->addr_type); 1261 1.1 elric return KRB5_PROG_ATYPE_NOSUPP; 1262 1.1 elric } 1263 1.1 elric if(a->order_addr != NULL) 1264 1.1 elric return (*a->order_addr)(context, addr1, addr2); 1265 1.1 elric 1266 1.1 elric if(addr1->addr_type != addr2->addr_type) 1267 1.1 elric return addr1->addr_type - addr2->addr_type; 1268 1.1 elric if(addr1->address.length != addr2->address.length) 1269 1.1 elric return addr1->address.length - addr2->address.length; 1270 1.1 elric return memcmp (addr1->address.data, 1271 1.1 elric addr2->address.data, 1272 1.1 elric addr1->address.length); 1273 1.1 elric } 1274 1.1 elric 1275 1.1 elric /** 1276 1.1 elric * krb5_address_compare compares the addresses addr1 and addr2. 1277 1.1 elric * Returns TRUE if the two addresses are the same. 1278 1.1 elric * 1279 1.1 elric * @param context a Keberos context 1280 1.1 elric * @param addr1 address to compare 1281 1.1 elric * @param addr2 address to compare 1282 1.1 elric * 1283 1.1 elric * @return Return an TRUE is the address are the same FALSE if not 1284 1.1 elric * 1285 1.1 elric * @ingroup krb5_address 1286 1.1 elric */ 1287 1.1 elric 1288 1.1 elric KRB5_LIB_FUNCTION krb5_boolean KRB5_LIB_CALL 1289 1.1 elric krb5_address_compare(krb5_context context, 1290 1.1 elric const krb5_address *addr1, 1291 1.1 elric const krb5_address *addr2) 1292 1.1 elric { 1293 1.1 elric return krb5_address_order (context, addr1, addr2) == 0; 1294 1.1 elric } 1295 1.1 elric 1296 1.1 elric /** 1297 1.1 elric * krb5_address_search checks if the address addr is a member of the 1298 1.1 elric * address set list addrlist . 1299 1.1 elric * 1300 1.1 elric * @param context a Keberos context. 1301 1.1 elric * @param addr address to search for. 1302 1.1 elric * @param addrlist list of addresses to look in for addr. 1303 1.1 elric * 1304 1.1 elric * @return Return an error code or 0. 1305 1.1 elric * 1306 1.1 elric * @ingroup krb5_address 1307 1.1 elric */ 1308 1.1 elric 1309 1.1 elric KRB5_LIB_FUNCTION krb5_boolean KRB5_LIB_CALL 1310 1.1 elric krb5_address_search(krb5_context context, 1311 1.1 elric const krb5_address *addr, 1312 1.1 elric const krb5_addresses *addrlist) 1313 1.1 elric { 1314 1.2 christos size_t i; 1315 1.1 elric 1316 1.1 elric for (i = 0; i < addrlist->len; ++i) 1317 1.1 elric if (krb5_address_compare (context, addr, &addrlist->val[i])) 1318 1.1 elric return TRUE; 1319 1.1 elric return FALSE; 1320 1.1 elric } 1321 1.1 elric 1322 1.1 elric /** 1323 1.1 elric * krb5_free_address frees the data stored in the address that is 1324 1.1 elric * alloced with any of the krb5_address functions. 1325 1.1 elric * 1326 1.1 elric * @param context a Keberos context 1327 1.1 elric * @param address addresss to be freed. 1328 1.1 elric * 1329 1.1 elric * @return Return an error code or 0. 1330 1.1 elric * 1331 1.1 elric * @ingroup krb5_address 1332 1.1 elric */ 1333 1.1 elric 1334 1.1 elric KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 1335 1.1 elric krb5_free_address(krb5_context context, 1336 1.1 elric krb5_address *address) 1337 1.1 elric { 1338 1.1 elric struct addr_operations *a = find_atype (address->addr_type); 1339 1.1 elric if(a != NULL && a->free_addr != NULL) 1340 1.1 elric return (*a->free_addr)(context, address); 1341 1.1 elric krb5_data_free (&address->address); 1342 1.1 elric memset(address, 0, sizeof(*address)); 1343 1.1 elric return 0; 1344 1.1 elric } 1345 1.1 elric 1346 1.1 elric /** 1347 1.1 elric * krb5_free_addresses frees the data stored in the address that is 1348 1.1 elric * alloced with any of the krb5_address functions. 1349 1.1 elric * 1350 1.1 elric * @param context a Keberos context 1351 1.1 elric * @param addresses addressses to be freed. 1352 1.1 elric * 1353 1.1 elric * @return Return an error code or 0. 1354 1.1 elric * 1355 1.1 elric * @ingroup krb5_address 1356 1.1 elric */ 1357 1.1 elric 1358 1.1 elric KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 1359 1.1 elric krb5_free_addresses(krb5_context context, 1360 1.1 elric krb5_addresses *addresses) 1361 1.1 elric { 1362 1.2 christos size_t i; 1363 1.1 elric for(i = 0; i < addresses->len; i++) 1364 1.1 elric krb5_free_address(context, &addresses->val[i]); 1365 1.1 elric free(addresses->val); 1366 1.1 elric addresses->len = 0; 1367 1.1 elric addresses->val = NULL; 1368 1.1 elric return 0; 1369 1.1 elric } 1370 1.1 elric 1371 1.1 elric /** 1372 1.1 elric * krb5_copy_address copies the content of address 1373 1.1 elric * inaddr to outaddr. 1374 1.1 elric * 1375 1.1 elric * @param context a Keberos context 1376 1.1 elric * @param inaddr pointer to source address 1377 1.1 elric * @param outaddr pointer to destination address 1378 1.1 elric * 1379 1.1 elric * @return Return an error code or 0. 1380 1.1 elric * 1381 1.1 elric * @ingroup krb5_address 1382 1.1 elric */ 1383 1.1 elric 1384 1.1 elric KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 1385 1.1 elric krb5_copy_address(krb5_context context, 1386 1.1 elric const krb5_address *inaddr, 1387 1.1 elric krb5_address *outaddr) 1388 1.1 elric { 1389 1.1 elric struct addr_operations *a = find_af (inaddr->addr_type); 1390 1.1 elric if(a != NULL && a->copy_addr != NULL) 1391 1.1 elric return (*a->copy_addr)(context, inaddr, outaddr); 1392 1.1 elric return copy_HostAddress(inaddr, outaddr); 1393 1.1 elric } 1394 1.1 elric 1395 1.1 elric /** 1396 1.1 elric * krb5_copy_addresses copies the content of addresses 1397 1.1 elric * inaddr to outaddr. 1398 1.1 elric * 1399 1.1 elric * @param context a Keberos context 1400 1.1 elric * @param inaddr pointer to source addresses 1401 1.1 elric * @param outaddr pointer to destination addresses 1402 1.1 elric * 1403 1.1 elric * @return Return an error code or 0. 1404 1.1 elric * 1405 1.1 elric * @ingroup krb5_address 1406 1.1 elric */ 1407 1.1 elric 1408 1.1 elric KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 1409 1.1 elric krb5_copy_addresses(krb5_context context, 1410 1.1 elric const krb5_addresses *inaddr, 1411 1.1 elric krb5_addresses *outaddr) 1412 1.1 elric { 1413 1.2 christos size_t i; 1414 1.1 elric ALLOC_SEQ(outaddr, inaddr->len); 1415 1.1 elric if(inaddr->len > 0 && outaddr->val == NULL) 1416 1.2 christos return krb5_enomem(context); 1417 1.1 elric for(i = 0; i < inaddr->len; i++) 1418 1.1 elric krb5_copy_address(context, &inaddr->val[i], &outaddr->val[i]); 1419 1.1 elric return 0; 1420 1.1 elric } 1421 1.1 elric 1422 1.1 elric /** 1423 1.1 elric * krb5_append_addresses adds the set of addresses in source to 1424 1.1 elric * dest. While copying the addresses, duplicates are also sorted out. 1425 1.1 elric * 1426 1.1 elric * @param context a Keberos context 1427 1.1 elric * @param dest destination of copy operation 1428 1.1 elric * @param source adresses that are going to be added to dest 1429 1.1 elric * 1430 1.1 elric * @return Return an error code or 0. 1431 1.1 elric * 1432 1.1 elric * @ingroup krb5_address 1433 1.1 elric */ 1434 1.1 elric 1435 1.1 elric KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 1436 1.1 elric krb5_append_addresses(krb5_context context, 1437 1.1 elric krb5_addresses *dest, 1438 1.1 elric const krb5_addresses *source) 1439 1.1 elric { 1440 1.1 elric krb5_address *tmp; 1441 1.1 elric krb5_error_code ret; 1442 1.2 christos size_t i; 1443 1.1 elric if(source->len > 0) { 1444 1.1 elric tmp = realloc(dest->val, (dest->len + source->len) * sizeof(*tmp)); 1445 1.2 christos if (tmp == NULL) 1446 1.2 christos return krb5_enomem(context); 1447 1.1 elric dest->val = tmp; 1448 1.1 elric for(i = 0; i < source->len; i++) { 1449 1.1 elric /* skip duplicates */ 1450 1.1 elric if(krb5_address_search(context, &source->val[i], dest)) 1451 1.1 elric continue; 1452 1.1 elric ret = krb5_copy_address(context, 1453 1.1 elric &source->val[i], 1454 1.1 elric &dest->val[dest->len]); 1455 1.1 elric if(ret) 1456 1.1 elric return ret; 1457 1.1 elric dest->len++; 1458 1.1 elric } 1459 1.1 elric } 1460 1.1 elric return 0; 1461 1.1 elric } 1462 1.1 elric 1463 1.1 elric /** 1464 1.1 elric * Create an address of type KRB5_ADDRESS_ADDRPORT from (addr, port) 1465 1.1 elric * 1466 1.1 elric * @param context a Keberos context 1467 1.1 elric * @param res built address from addr/port 1468 1.1 elric * @param addr address to use 1469 1.1 elric * @param port port to use 1470 1.1 elric * 1471 1.1 elric * @return Return an error code or 0. 1472 1.1 elric * 1473 1.1 elric * @ingroup krb5_address 1474 1.1 elric */ 1475 1.1 elric 1476 1.1 elric KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 1477 1.1 elric krb5_make_addrport (krb5_context context, 1478 1.1 elric krb5_address **res, const krb5_address *addr, int16_t port) 1479 1.1 elric { 1480 1.1 elric krb5_error_code ret; 1481 1.1 elric size_t len = addr->address.length + 2 + 4 * 4; 1482 1.1 elric u_char *p; 1483 1.1 elric 1484 1.1 elric *res = malloc (sizeof(**res)); 1485 1.2 christos if (*res == NULL) 1486 1.2 christos return krb5_enomem(context); 1487 1.1 elric (*res)->addr_type = KRB5_ADDRESS_ADDRPORT; 1488 1.1 elric ret = krb5_data_alloc (&(*res)->address, len); 1489 1.1 elric if (ret) { 1490 1.1 elric free (*res); 1491 1.1 elric *res = NULL; 1492 1.2 christos return krb5_enomem(context); 1493 1.1 elric } 1494 1.1 elric p = (*res)->address.data; 1495 1.1 elric *p++ = 0; 1496 1.1 elric *p++ = 0; 1497 1.1 elric *p++ = (addr->addr_type ) & 0xFF; 1498 1.1 elric *p++ = (addr->addr_type >> 8) & 0xFF; 1499 1.1 elric 1500 1.1 elric *p++ = (addr->address.length ) & 0xFF; 1501 1.1 elric *p++ = (addr->address.length >> 8) & 0xFF; 1502 1.1 elric *p++ = (addr->address.length >> 16) & 0xFF; 1503 1.1 elric *p++ = (addr->address.length >> 24) & 0xFF; 1504 1.1 elric 1505 1.1 elric memcpy (p, addr->address.data, addr->address.length); 1506 1.1 elric p += addr->address.length; 1507 1.1 elric 1508 1.1 elric *p++ = 0; 1509 1.1 elric *p++ = 0; 1510 1.1 elric *p++ = (KRB5_ADDRESS_IPPORT ) & 0xFF; 1511 1.1 elric *p++ = (KRB5_ADDRESS_IPPORT >> 8) & 0xFF; 1512 1.1 elric 1513 1.1 elric *p++ = (2 ) & 0xFF; 1514 1.1 elric *p++ = (2 >> 8) & 0xFF; 1515 1.1 elric *p++ = (2 >> 16) & 0xFF; 1516 1.1 elric *p++ = (2 >> 24) & 0xFF; 1517 1.1 elric 1518 1.1 elric memcpy (p, &port, 2); 1519 1.1 elric 1520 1.1 elric return 0; 1521 1.1 elric } 1522 1.1 elric 1523 1.1 elric /** 1524 1.1 elric * Calculate the boundary addresses of `inaddr'/`prefixlen' and store 1525 1.1 elric * them in `low' and `high'. 1526 1.1 elric * 1527 1.1 elric * @param context a Keberos context 1528 1.1 elric * @param inaddr address in prefixlen that the bondery searched 1529 1.1 elric * @param prefixlen width of boundery 1530 1.1 elric * @param low lowest address 1531 1.1 elric * @param high highest address 1532 1.1 elric * 1533 1.1 elric * @return Return an error code or 0. 1534 1.1 elric * 1535 1.1 elric * @ingroup krb5_address 1536 1.1 elric */ 1537 1.1 elric 1538 1.1 elric KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 1539 1.1 elric krb5_address_prefixlen_boundary(krb5_context context, 1540 1.1 elric const krb5_address *inaddr, 1541 1.1 elric unsigned long prefixlen, 1542 1.1 elric krb5_address *low, 1543 1.1 elric krb5_address *high) 1544 1.1 elric { 1545 1.1 elric struct addr_operations *a = find_atype (inaddr->addr_type); 1546 1.1 elric if(a != NULL && a->mask_boundary != NULL) 1547 1.1 elric return (*a->mask_boundary)(context, inaddr, prefixlen, low, high); 1548 1.1 elric krb5_set_error_message(context, KRB5_PROG_ATYPE_NOSUPP, 1549 1.1 elric N_("Address family %d doesn't support " 1550 1.1 elric "address mask operation", ""), 1551 1.1 elric inaddr->addr_type); 1552 1.1 elric return KRB5_PROG_ATYPE_NOSUPP; 1553 1.1 elric } 1554