2 * Copyright (c) 1997-2003 Kungliga Tekniska Högskolan
3 * (Royal Institute of Technology, Stockholm, Sweden).
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
17 * 3. Neither the name of the Institute nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 #include "krb5_locl.h"
36 RCSID("$Id: addr_families.c,v 1.38 2003/03/25 12:37:02 joda Exp $");
38 struct addr_operations
{
40 krb5_address_type atype
;
41 size_t max_sockaddr_size
;
42 krb5_error_code (*sockaddr2addr
)(const struct sockaddr
*, krb5_address
*);
43 krb5_error_code (*sockaddr2port
)(const struct sockaddr
*, int16_t *);
44 void (*addr2sockaddr
)(const krb5_address
*, struct sockaddr
*,
45 krb5_socklen_t
*sa_size
, int port
);
46 void (*h_addr2sockaddr
)(const char *, struct sockaddr
*, krb5_socklen_t
*, int);
47 krb5_error_code (*h_addr2addr
)(const char *, krb5_address
*);
48 krb5_boolean (*uninteresting
)(const struct sockaddr
*);
49 void (*anyaddr
)(struct sockaddr
*, krb5_socklen_t
*, int);
50 int (*print_addr
)(const krb5_address
*, char *, size_t);
51 int (*parse_addr
)(krb5_context
, const char*, krb5_address
*);
52 int (*order_addr
)(krb5_context
, const krb5_address
*, const krb5_address
*);
53 int (*free_addr
)(krb5_context
, krb5_address
*);
54 int (*copy_addr
)(krb5_context
, const krb5_address
*, krb5_address
*);
58 * AF_INET - aka IPv4 implementation
61 static krb5_error_code
62 ipv4_sockaddr2addr (const struct sockaddr
*sa
, krb5_address
*a
)
64 const struct sockaddr_in
*sin
= (const struct sockaddr_in
*)sa
;
67 a
->addr_type
= KRB5_ADDRESS_INET
;
68 memcpy (buf
, &sin
->sin_addr
, 4);
69 return krb5_data_copy(&a
->address
, buf
, 4);
72 static krb5_error_code
73 ipv4_sockaddr2port (const struct sockaddr
*sa
, int16_t *port
)
75 const struct sockaddr_in
*sin
= (const struct sockaddr_in
*)sa
;
77 *port
= sin
->sin_port
;
82 ipv4_addr2sockaddr (const krb5_address
*a
,
84 krb5_socklen_t
*sa_size
,
87 struct sockaddr_in tmp
;
89 memset (&tmp
, 0, sizeof(tmp
));
90 tmp
.sin_family
= AF_INET
;
91 memcpy (&tmp
.sin_addr
, a
->address
.data
, 4);
93 memcpy(sa
, &tmp
, min(sizeof(tmp
), *sa_size
));
94 *sa_size
= sizeof(tmp
);
98 ipv4_h_addr2sockaddr(const char *addr
,
100 krb5_socklen_t
*sa_size
,
103 struct sockaddr_in tmp
;
105 memset (&tmp
, 0, sizeof(tmp
));
106 tmp
.sin_family
= AF_INET
;
108 tmp
.sin_addr
= *((const struct in_addr
*)addr
);
109 memcpy(sa
, &tmp
, min(sizeof(tmp
), *sa_size
));
110 *sa_size
= sizeof(tmp
);
113 static krb5_error_code
114 ipv4_h_addr2addr (const char *addr
,
117 unsigned char buf
[4];
119 a
->addr_type
= KRB5_ADDRESS_INET
;
120 memcpy(buf
, addr
, 4);
121 return krb5_data_copy(&a
->address
, buf
, 4);
125 * Are there any addresses that should be considered `uninteresting'?
129 ipv4_uninteresting (const struct sockaddr
*sa
)
131 const struct sockaddr_in
*sin
= (const struct sockaddr_in
*)sa
;
133 if (sin
->sin_addr
.s_addr
== INADDR_ANY
)
140 ipv4_anyaddr (struct sockaddr
*sa
, krb5_socklen_t
*sa_size
, int port
)
142 struct sockaddr_in tmp
;
144 memset (&tmp
, 0, sizeof(tmp
));
145 tmp
.sin_family
= AF_INET
;
147 tmp
.sin_addr
.s_addr
= INADDR_ANY
;
148 memcpy(sa
, &tmp
, min(sizeof(tmp
), *sa_size
));
149 *sa_size
= sizeof(tmp
);
153 ipv4_print_addr (const krb5_address
*addr
, char *str
, size_t len
)
157 memcpy (&ia
, addr
->address
.data
, 4);
159 return snprintf (str
, len
, "IPv4:%s", inet_ntoa(ia
));
163 ipv4_parse_addr (krb5_context context
, const char *address
, krb5_address
*addr
)
168 p
= strchr(address
, ':');
171 if(strncasecmp(address
, "ip:", p
- address
) != 0 &&
172 strncasecmp(address
, "ip4:", p
- address
) != 0 &&
173 strncasecmp(address
, "ipv4:", p
- address
) != 0 &&
174 strncasecmp(address
, "inet:", p
- address
) != 0)
178 #ifdef HAVE_INET_ATON
179 if(inet_aton(p
, &a
) == 0)
181 #elif defined(HAVE_INET_ADDR)
182 a
.s_addr
= inet_addr(p
);
183 if(a
.s_addr
== INADDR_NONE
)
188 addr
->addr_type
= KRB5_ADDRESS_INET
;
189 if(krb5_data_alloc(&addr
->address
, 4) != 0)
191 _krb5_put_int(addr
->address
.data
, ntohl(a
.s_addr
), addr
->address
.length
);
196 * AF_INET6 - aka IPv6 implementation
201 static krb5_error_code
202 ipv6_sockaddr2addr (const struct sockaddr
*sa
, krb5_address
*a
)
204 const struct sockaddr_in6
*sin6
= (const struct sockaddr_in6
*)sa
;
206 if (IN6_IS_ADDR_V4MAPPED(&sin6
->sin6_addr
)) {
207 unsigned char buf
[4];
209 a
->addr_type
= KRB5_ADDRESS_INET
;
210 #ifndef IN6_ADDR_V6_TO_V4
211 #ifdef IN6_EXTRACT_V4ADDR
212 #define IN6_ADDR_V6_TO_V4(x) (&IN6_EXTRACT_V4ADDR(x))
214 #define IN6_ADDR_V6_TO_V4(x) ((const struct in_addr *)&(x)->s6_addr[12])
217 memcpy (buf
, IN6_ADDR_V6_TO_V4(&sin6
->sin6_addr
), 4);
218 return krb5_data_copy(&a
->address
, buf
, 4);
220 a
->addr_type
= KRB5_ADDRESS_INET6
;
221 return krb5_data_copy(&a
->address
,
223 sizeof(sin6
->sin6_addr
));
227 static krb5_error_code
228 ipv6_sockaddr2port (const struct sockaddr
*sa
, int16_t *port
)
230 const struct sockaddr_in6
*sin6
= (const struct sockaddr_in6
*)sa
;
232 *port
= sin6
->sin6_port
;
237 ipv6_addr2sockaddr (const krb5_address
*a
,
239 krb5_socklen_t
*sa_size
,
242 struct sockaddr_in6 tmp
;
244 memset (&tmp
, 0, sizeof(tmp
));
245 tmp
.sin6_family
= AF_INET6
;
246 memcpy (&tmp
.sin6_addr
, a
->address
.data
, sizeof(tmp
.sin6_addr
));
247 tmp
.sin6_port
= port
;
248 memcpy(sa
, &tmp
, min(sizeof(tmp
), *sa_size
));
249 *sa_size
= sizeof(tmp
);
253 ipv6_h_addr2sockaddr(const char *addr
,
255 krb5_socklen_t
*sa_size
,
258 struct sockaddr_in6 tmp
;
260 memset (&tmp
, 0, sizeof(tmp
));
261 tmp
.sin6_family
= AF_INET6
;
262 tmp
.sin6_port
= port
;
263 tmp
.sin6_addr
= *((const struct in6_addr
*)addr
);
264 memcpy(sa
, &tmp
, min(sizeof(tmp
), *sa_size
));
265 *sa_size
= sizeof(tmp
);
268 static krb5_error_code
269 ipv6_h_addr2addr (const char *addr
,
272 a
->addr_type
= KRB5_ADDRESS_INET6
;
273 return krb5_data_copy(&a
->address
, addr
, sizeof(struct in6_addr
));
281 ipv6_uninteresting (const struct sockaddr
*sa
)
283 const struct sockaddr_in6
*sin6
= (const struct sockaddr_in6
*)sa
;
284 const struct in6_addr
*in6
= (const struct in6_addr
*)&sin6
->sin6_addr
;
287 IN6_IS_ADDR_LINKLOCAL(in6
)
288 || IN6_IS_ADDR_V4COMPAT(in6
);
292 ipv6_anyaddr (struct sockaddr
*sa
, krb5_socklen_t
*sa_size
, int port
)
294 struct sockaddr_in6 tmp
;
296 memset (&tmp
, 0, sizeof(tmp
));
297 tmp
.sin6_family
= AF_INET6
;
298 tmp
.sin6_port
= port
;
299 tmp
.sin6_addr
= in6addr_any
;
300 *sa_size
= sizeof(tmp
);
304 ipv6_print_addr (const krb5_address
*addr
, char *str
, size_t len
)
306 char buf
[128], buf2
[3];
307 #ifdef HAVE_INET_NTOP
308 if(inet_ntop(AF_INET6
, addr
->address
.data
, buf
, sizeof(buf
)) == NULL
)
311 /* XXX this is pretty ugly, but better than abort() */
313 unsigned char *p
= addr
->address
.data
;
315 for(i
= 0; i
< addr
->address
.length
; i
++) {
316 snprintf(buf2
, sizeof(buf2
), "%02x", p
[i
]);
317 if(i
> 0 && (i
& 1) == 0)
318 strlcat(buf
, ":", sizeof(buf
));
319 strlcat(buf
, buf2
, sizeof(buf
));
322 return snprintf(str
, len
, "IPv6:%s", buf
);
326 ipv6_parse_addr (krb5_context context
, const char *address
, krb5_address
*addr
)
332 p
= strchr(address
, ':');
335 if(strncasecmp(address
, "ip6:", p
- address
) == 0 ||
336 strncasecmp(address
, "ipv6:", p
- address
) == 0 ||
337 strncasecmp(address
, "inet6:", p
- address
) == 0)
341 ret
= inet_pton(AF_INET6
, address
, &in6
.s6_addr
);
343 addr
->addr_type
= KRB5_ADDRESS_INET6
;
344 ret
= krb5_data_alloc(&addr
->address
, sizeof(in6
.s6_addr
));
347 memcpy(addr
->address
.data
, in6
.s6_addr
, sizeof(in6
.s6_addr
));
359 #define KRB5_ADDRESS_ARANGE (-100)
367 arange_parse_addr (krb5_context context
,
368 const char *address
, krb5_address
*addr
)
371 krb5_addresses low
, high
;
375 if(strncasecmp(address
, "RANGE:", 6) != 0)
380 /* should handle netmasks */
381 strsep_copy(&address
, "-", buf
, sizeof(buf
));
382 ret
= krb5_parse_address(context
, buf
, &low
);
386 krb5_free_addresses(context
, &low
);
390 strsep_copy(&address
, "-", buf
, sizeof(buf
));
391 ret
= krb5_parse_address(context
, buf
, &high
);
393 krb5_free_addresses(context
, &low
);
397 if(high
.len
!= 1 || high
.val
[0].addr_type
!= low
.val
[0].addr_type
) {
398 krb5_free_addresses(context
, &low
);
399 krb5_free_addresses(context
, &high
);
403 krb5_data_alloc(&addr
->address
, sizeof(*a
));
404 addr
->addr_type
= KRB5_ADDRESS_ARANGE
;
405 a
= addr
->address
.data
;
407 if(krb5_address_order(context
, &low
.val
[0], &high
.val
[0]) < 0) {
409 a
->high
= high
.val
[0];
411 a
->low
= high
.val
[0];
412 a
->high
= low
.val
[0];
418 arange_free (krb5_context context
, krb5_address
*addr
)
421 a
= addr
->address
.data
;
422 krb5_free_address(context
, &a
->low
);
423 krb5_free_address(context
, &a
->high
);
429 arange_copy (krb5_context context
, const krb5_address
*inaddr
,
430 krb5_address
*outaddr
)
433 struct arange
*i
, *o
;
435 outaddr
->addr_type
= KRB5_ADDRESS_ARANGE
;
436 ret
= krb5_data_alloc(&outaddr
->address
, sizeof(*o
));
439 i
= inaddr
->address
.data
;
440 o
= outaddr
->address
.data
;
441 ret
= krb5_copy_address(context
, &i
->low
, &o
->low
);
443 krb5_data_free(&outaddr
->address
);
446 ret
= krb5_copy_address(context
, &i
->high
, &o
->high
);
448 krb5_free_address(context
, &o
->low
);
449 krb5_data_free(&outaddr
->address
);
456 arange_print_addr (const krb5_address
*addr
, char *str
, size_t len
)
460 size_t l
, ret_len
= 0;
462 a
= addr
->address
.data
;
464 l
= strlcpy(str
, "RANGE:", len
);
467 ret
= krb5_print_address (&a
->low
, str
+ ret_len
, len
- ret_len
, &l
);
470 l
= strlcat(str
, "-", len
);
473 ret
= krb5_print_address (&a
->high
, str
+ ret_len
, len
- ret_len
, &l
);
480 arange_order_addr(krb5_context context
,
481 const krb5_address
*addr1
,
482 const krb5_address
*addr2
)
484 int tmp1
, tmp2
, sign
;
486 const krb5_address
*a2
;
488 if(addr1
->addr_type
== KRB5_ADDRESS_ARANGE
) {
489 a
= addr1
->address
.data
;
492 } else if(addr2
->addr_type
== KRB5_ADDRESS_ARANGE
) {
493 a
= addr2
->address
.data
;
499 if(a2
->addr_type
== KRB5_ADDRESS_ARANGE
) {
500 struct arange
*b
= a2
->address
.data
;
501 tmp1
= krb5_address_order(context
, &a
->low
, &b
->low
);
504 return sign
* krb5_address_order(context
, &a
->high
, &b
->high
);
505 } else if(a2
->addr_type
== a
->low
.addr_type
) {
506 tmp1
= krb5_address_order(context
, &a
->low
, a2
);
509 tmp2
= krb5_address_order(context
, &a
->high
, a2
);
514 return sign
* (addr1
->addr_type
- addr2
->addr_type
);
519 addrport_print_addr (const krb5_address
*addr
, char *str
, size_t len
)
521 krb5_address addr1
, addr2
;
523 size_t ret_len
= 0, l
;
524 krb5_storage
*sp
= krb5_storage_from_data((krb5_data
*)&addr
->address
);
525 /* for totally obscure reasons, these are not in network byteorder */
526 krb5_storage_set_byteorder(sp
, KRB5_STORAGE_BYTEORDER_LE
);
528 krb5_storage_seek(sp
, 2, SEEK_CUR
); /* skip first two bytes */
529 krb5_ret_address(sp
, &addr1
);
531 krb5_storage_seek(sp
, 2, SEEK_CUR
); /* skip two bytes */
532 krb5_ret_address(sp
, &addr2
);
533 krb5_storage_free(sp
);
534 if(addr2
.addr_type
== KRB5_ADDRESS_IPPORT
&& addr2
.address
.length
== 2) {
536 _krb5_get_int(addr2
.address
.data
, &value
, 2);
539 l
= strlcpy(str
, "ADDRPORT:", len
);
541 krb5_print_address(&addr1
, str
+ ret_len
, len
- ret_len
, &l
);
543 l
= snprintf(str
+ ret_len
, len
- ret_len
, ",PORT=%u", port
);
548 static struct addr_operations at
[] = {
549 {AF_INET
, KRB5_ADDRESS_INET
, sizeof(struct sockaddr_in
),
553 ipv4_h_addr2sockaddr
,
555 ipv4_uninteresting
, ipv4_anyaddr
, ipv4_print_addr
, ipv4_parse_addr
},
557 {AF_INET6
, KRB5_ADDRESS_INET6
, sizeof(struct sockaddr_in6
),
561 ipv6_h_addr2sockaddr
,
563 ipv6_uninteresting
, ipv6_anyaddr
, ipv6_print_addr
, ipv6_parse_addr
} ,
565 {KRB5_ADDRESS_ADDRPORT
, KRB5_ADDRESS_ADDRPORT
, 0,
566 NULL
, NULL
, NULL
, NULL
, NULL
,
567 NULL
, NULL
, addrport_print_addr
, NULL
, NULL
, NULL
, NULL
},
568 /* fake address type */
569 {KRB5_ADDRESS_ARANGE
, KRB5_ADDRESS_ARANGE
, sizeof(struct arange
),
570 NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
,
571 arange_print_addr
, arange_parse_addr
,
572 arange_order_addr
, arange_free
, arange_copy
}
575 static int num_addrs
= sizeof(at
) / sizeof(at
[0]);
577 static size_t max_sockaddr_size
= 0;
583 static struct addr_operations
*
586 struct addr_operations
*a
;
588 for (a
= at
; a
< at
+ num_addrs
; ++a
)
594 static struct addr_operations
*
595 find_atype(int atype
)
597 struct addr_operations
*a
;
599 for (a
= at
; a
< at
+ num_addrs
; ++a
)
600 if (atype
== a
->atype
)
606 krb5_sockaddr2address (krb5_context context
,
607 const struct sockaddr
*sa
, krb5_address
*addr
)
609 struct addr_operations
*a
= find_af(sa
->sa_family
);
611 krb5_set_error_string (context
, "Address family %d not supported",
613 return KRB5_PROG_ATYPE_NOSUPP
;
615 return (*a
->sockaddr2addr
)(sa
, addr
);
619 krb5_sockaddr2port (krb5_context context
,
620 const struct sockaddr
*sa
, int16_t *port
)
622 struct addr_operations
*a
= find_af(sa
->sa_family
);
624 krb5_set_error_string (context
, "Address family %d not supported",
626 return KRB5_PROG_ATYPE_NOSUPP
;
628 return (*a
->sockaddr2port
)(sa
, port
);
632 krb5_addr2sockaddr (krb5_context context
,
633 const krb5_address
*addr
,
635 krb5_socklen_t
*sa_size
,
638 struct addr_operations
*a
= find_atype(addr
->addr_type
);
641 krb5_set_error_string (context
, "Address type %d not supported",
643 return KRB5_PROG_ATYPE_NOSUPP
;
645 if (a
->addr2sockaddr
== NULL
) {
646 krb5_set_error_string (context
, "Can't convert address type %d to sockaddr",
648 return KRB5_PROG_ATYPE_NOSUPP
;
650 (*a
->addr2sockaddr
)(addr
, sa
, sa_size
, port
);
655 krb5_max_sockaddr_size (void)
657 if (max_sockaddr_size
== 0) {
658 struct addr_operations
*a
;
660 for(a
= at
; a
< at
+ num_addrs
; ++a
)
661 max_sockaddr_size
= max(max_sockaddr_size
, a
->max_sockaddr_size
);
663 return max_sockaddr_size
;
667 krb5_sockaddr_uninteresting(const struct sockaddr
*sa
)
669 struct addr_operations
*a
= find_af(sa
->sa_family
);
670 if (a
== NULL
|| a
->uninteresting
== NULL
)
672 return (*a
->uninteresting
)(sa
);
676 krb5_h_addr2sockaddr (krb5_context context
,
678 const char *addr
, struct sockaddr
*sa
,
679 krb5_socklen_t
*sa_size
,
682 struct addr_operations
*a
= find_af(af
);
684 krb5_set_error_string (context
, "Address family %d not supported", af
);
685 return KRB5_PROG_ATYPE_NOSUPP
;
687 (*a
->h_addr2sockaddr
)(addr
, sa
, sa_size
, port
);
692 krb5_h_addr2addr (krb5_context context
,
694 const char *haddr
, krb5_address
*addr
)
696 struct addr_operations
*a
= find_af(af
);
698 krb5_set_error_string (context
, "Address family %d not supported", af
);
699 return KRB5_PROG_ATYPE_NOSUPP
;
701 return (*a
->h_addr2addr
)(haddr
, addr
);
705 krb5_anyaddr (krb5_context context
,
708 krb5_socklen_t
*sa_size
,
711 struct addr_operations
*a
= find_af (af
);
714 krb5_set_error_string (context
, "Address family %d not supported", af
);
715 return KRB5_PROG_ATYPE_NOSUPP
;
718 (*a
->anyaddr
)(sa
, sa_size
, port
);
723 krb5_print_address (const krb5_address
*addr
,
724 char *str
, size_t len
, size_t *ret_len
)
727 struct addr_operations
*a
= find_atype(addr
->addr_type
);
729 if (a
== NULL
|| a
->print_addr
== NULL
) {
735 l
= snprintf(s
, len
, "TYPE_%d:", addr
->addr_type
);
740 for(i
= 0; i
< addr
->address
.length
; i
++) {
741 l
= snprintf(s
, len
, "%02x", ((char*)addr
->address
.data
)[i
]);
751 ret
= (*a
->print_addr
)(addr
, str
, len
);
758 krb5_parse_address(krb5_context context
,
760 krb5_addresses
*addresses
)
763 struct addrinfo
*ai
, *a
;
767 for(i
= 0; i
< num_addrs
; i
++) {
768 if(at
[i
].parse_addr
) {
770 if((*at
[i
].parse_addr
)(context
, string
, &addr
) == 0) {
771 ALLOC_SEQ(addresses
, 1);
772 addresses
->val
[0] = addr
;
778 error
= getaddrinfo (string
, NULL
, NULL
, &ai
);
781 krb5_set_error_string (context
, "%s: %s", string
, gai_strerror(error
));
782 return krb5_eai_to_heim_errno(error
, save_errno
);
786 for (a
= ai
; a
!= NULL
; a
= a
->ai_next
)
789 ALLOC_SEQ(addresses
, n
);
791 for (a
= ai
, i
= 0; a
!= NULL
; a
= a
->ai_next
) {
792 if(krb5_sockaddr2address (context
, ai
->ai_addr
,
793 &addresses
->val
[i
]) == 0)
801 krb5_address_order(krb5_context context
,
802 const krb5_address
*addr1
,
803 const krb5_address
*addr2
)
805 /* this sucks; what if both addresses have order functions, which
806 should we call? this works for now, though */
807 struct addr_operations
*a
;
808 a
= find_atype(addr1
->addr_type
);
810 krb5_set_error_string (context
, "Address family %d not supported",
812 return KRB5_PROG_ATYPE_NOSUPP
;
814 if(a
->order_addr
!= NULL
)
815 return (*a
->order_addr
)(context
, addr1
, addr2
);
816 a
= find_atype(addr2
->addr_type
);
818 krb5_set_error_string (context
, "Address family %d not supported",
820 return KRB5_PROG_ATYPE_NOSUPP
;
822 if(a
->order_addr
!= NULL
)
823 return (*a
->order_addr
)(context
, addr1
, addr2
);
825 if(addr1
->addr_type
!= addr2
->addr_type
)
826 return addr1
->addr_type
- addr2
->addr_type
;
827 if(addr1
->address
.length
!= addr2
->address
.length
)
828 return addr1
->address
.length
- addr2
->address
.length
;
829 return memcmp (addr1
->address
.data
,
831 addr1
->address
.length
);
835 krb5_address_compare(krb5_context context
,
836 const krb5_address
*addr1
,
837 const krb5_address
*addr2
)
839 return krb5_address_order (context
, addr1
, addr2
) == 0;
843 krb5_address_search(krb5_context context
,
844 const krb5_address
*addr
,
845 const krb5_addresses
*addrlist
)
849 for (i
= 0; i
< addrlist
->len
; ++i
)
850 if (krb5_address_compare (context
, addr
, &addrlist
->val
[i
]))
856 krb5_free_address(krb5_context context
,
857 krb5_address
*address
)
859 struct addr_operations
*a
= find_af (address
->addr_type
);
860 if(a
!= NULL
&& a
->free_addr
!= NULL
)
861 return (*a
->free_addr
)(context
, address
);
862 krb5_data_free (&address
->address
);
867 krb5_free_addresses(krb5_context context
,
868 krb5_addresses
*addresses
)
871 for(i
= 0; i
< addresses
->len
; i
++)
872 krb5_free_address(context
, &addresses
->val
[i
]);
873 free(addresses
->val
);
878 krb5_copy_address(krb5_context context
,
879 const krb5_address
*inaddr
,
880 krb5_address
*outaddr
)
882 struct addr_operations
*a
= find_af (inaddr
->addr_type
);
883 if(a
!= NULL
&& a
->copy_addr
!= NULL
)
884 return (*a
->copy_addr
)(context
, inaddr
, outaddr
);
885 return copy_HostAddress(inaddr
, outaddr
);
889 krb5_copy_addresses(krb5_context context
,
890 const krb5_addresses
*inaddr
,
891 krb5_addresses
*outaddr
)
894 ALLOC_SEQ(outaddr
, inaddr
->len
);
895 if(inaddr
->len
> 0 && outaddr
->val
== NULL
)
897 for(i
= 0; i
< inaddr
->len
; i
++)
898 krb5_copy_address(context
, &inaddr
->val
[i
], &outaddr
->val
[i
]);
903 krb5_append_addresses(krb5_context context
,
904 krb5_addresses
*dest
,
905 const krb5_addresses
*source
)
910 if(source
->len
> 0) {
911 tmp
= realloc(dest
->val
, (dest
->len
+ source
->len
) * sizeof(*tmp
));
913 krb5_set_error_string(context
, "realloc: out of memory");
917 for(i
= 0; i
< source
->len
; i
++) {
918 /* skip duplicates */
919 if(krb5_address_search(context
, &source
->val
[i
], dest
))
921 ret
= krb5_copy_address(context
,
923 &dest
->val
[dest
->len
]);
933 * Create an address of type KRB5_ADDRESS_ADDRPORT from (addr, port)
937 krb5_make_addrport (krb5_context context
,
938 krb5_address
**res
, const krb5_address
*addr
, int16_t port
)
941 size_t len
= addr
->address
.length
+ 2 + 4 * 4;
944 *res
= malloc (sizeof(**res
));
946 krb5_set_error_string(context
, "malloc: out of memory");
949 (*res
)->addr_type
= KRB5_ADDRESS_ADDRPORT
;
950 ret
= krb5_data_alloc (&(*res
)->address
, len
);
952 krb5_set_error_string(context
, "malloc: out of memory");
956 p
= (*res
)->address
.data
;
959 *p
++ = (addr
->addr_type
) & 0xFF;
960 *p
++ = (addr
->addr_type
>> 8) & 0xFF;
962 *p
++ = (addr
->address
.length
) & 0xFF;
963 *p
++ = (addr
->address
.length
>> 8) & 0xFF;
964 *p
++ = (addr
->address
.length
>> 16) & 0xFF;
965 *p
++ = (addr
->address
.length
>> 24) & 0xFF;
967 memcpy (p
, addr
->address
.data
, addr
->address
.length
);
968 p
+= addr
->address
.length
;
972 *p
++ = (KRB5_ADDRESS_IPPORT
) & 0xFF;
973 *p
++ = (KRB5_ADDRESS_IPPORT
>> 8) & 0xFF;
976 *p
++ = (2 >> 8) & 0xFF;
977 *p
++ = (2 >> 16) & 0xFF;
978 *p
++ = (2 >> 24) & 0xFF;
980 memcpy (p
, &port
, 2);