1b528cefcSMark Murray /*
2ae771770SStanislav Sedov * Copyright (c) 1997-2007 Kungliga Tekniska Högskolan
3b528cefcSMark Murray * (Royal Institute of Technology, Stockholm, Sweden).
4b528cefcSMark Murray * All rights reserved.
5b528cefcSMark Murray *
6b528cefcSMark Murray * Redistribution and use in source and binary forms, with or without
7b528cefcSMark Murray * modification, are permitted provided that the following conditions
8b528cefcSMark Murray * are met:
9b528cefcSMark Murray *
10b528cefcSMark Murray * 1. Redistributions of source code must retain the above copyright
11b528cefcSMark Murray * notice, this list of conditions and the following disclaimer.
12b528cefcSMark Murray *
13b528cefcSMark Murray * 2. Redistributions in binary form must reproduce the above copyright
14b528cefcSMark Murray * notice, this list of conditions and the following disclaimer in the
15b528cefcSMark Murray * documentation and/or other materials provided with the distribution.
16b528cefcSMark Murray *
17b528cefcSMark Murray * 3. Neither the name of the Institute nor the names of its contributors
18b528cefcSMark Murray * may be used to endorse or promote products derived from this software
19b528cefcSMark Murray * without specific prior written permission.
20b528cefcSMark Murray *
21b528cefcSMark Murray * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
22b528cefcSMark Murray * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23b528cefcSMark Murray * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24b528cefcSMark Murray * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
25b528cefcSMark Murray * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26b528cefcSMark Murray * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27b528cefcSMark Murray * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28b528cefcSMark Murray * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29b528cefcSMark Murray * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30b528cefcSMark Murray * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31b528cefcSMark Murray * SUCH DAMAGE.
32b528cefcSMark Murray */
33b528cefcSMark Murray
34b528cefcSMark Murray #include "krb5_locl.h"
35b528cefcSMark Murray
36b528cefcSMark Murray struct addr_operations {
37b528cefcSMark Murray int af;
38b528cefcSMark Murray krb5_address_type atype;
39b528cefcSMark Murray size_t max_sockaddr_size;
40b528cefcSMark Murray krb5_error_code (*sockaddr2addr)(const struct sockaddr *, krb5_address *);
41b528cefcSMark Murray krb5_error_code (*sockaddr2port)(const struct sockaddr *, int16_t *);
42b528cefcSMark Murray void (*addr2sockaddr)(const krb5_address *, struct sockaddr *,
438373020dSJacques Vidrine krb5_socklen_t *sa_size, int port);
448373020dSJacques Vidrine void (*h_addr2sockaddr)(const char *, struct sockaddr *, krb5_socklen_t *, int);
45b528cefcSMark Murray krb5_error_code (*h_addr2addr)(const char *, krb5_address *);
46b528cefcSMark Murray krb5_boolean (*uninteresting)(const struct sockaddr *);
47ae771770SStanislav Sedov krb5_boolean (*is_loopback)(const struct sockaddr *);
488373020dSJacques Vidrine void (*anyaddr)(struct sockaddr *, krb5_socklen_t *, int);
49b528cefcSMark Murray int (*print_addr)(const krb5_address *, char *, size_t);
504137ff4cSJacques Vidrine int (*parse_addr)(krb5_context, const char*, krb5_address *);
514137ff4cSJacques Vidrine int (*order_addr)(krb5_context, const krb5_address*, const krb5_address*);
524137ff4cSJacques Vidrine int (*free_addr)(krb5_context, krb5_address*);
534137ff4cSJacques Vidrine int (*copy_addr)(krb5_context, const krb5_address*, krb5_address*);
54c19800e8SDoug Rabson int (*mask_boundary)(krb5_context, const krb5_address*, unsigned long,
55c19800e8SDoug Rabson krb5_address*, krb5_address*);
56b528cefcSMark Murray };
57b528cefcSMark Murray
58b528cefcSMark Murray /*
59b528cefcSMark Murray * AF_INET - aka IPv4 implementation
60b528cefcSMark Murray */
61b528cefcSMark Murray
62b528cefcSMark Murray static krb5_error_code
ipv4_sockaddr2addr(const struct sockaddr * sa,krb5_address * a)63b528cefcSMark Murray ipv4_sockaddr2addr (const struct sockaddr *sa, krb5_address *a)
64b528cefcSMark Murray {
65c19800e8SDoug Rabson const struct sockaddr_in *sin4 = (const struct sockaddr_in *)sa;
66b528cefcSMark Murray unsigned char buf[4];
67b528cefcSMark Murray
68b528cefcSMark Murray a->addr_type = KRB5_ADDRESS_INET;
69c19800e8SDoug Rabson memcpy (buf, &sin4->sin_addr, 4);
70b528cefcSMark Murray return krb5_data_copy(&a->address, buf, 4);
71b528cefcSMark Murray }
72b528cefcSMark Murray
73b528cefcSMark Murray static krb5_error_code
ipv4_sockaddr2port(const struct sockaddr * sa,int16_t * port)74b528cefcSMark Murray ipv4_sockaddr2port (const struct sockaddr *sa, int16_t *port)
75b528cefcSMark Murray {
76c19800e8SDoug Rabson const struct sockaddr_in *sin4 = (const struct sockaddr_in *)sa;
77b528cefcSMark Murray
78c19800e8SDoug Rabson *port = sin4->sin_port;
79b528cefcSMark Murray return 0;
80b528cefcSMark Murray }
81b528cefcSMark Murray
82b528cefcSMark Murray static void
ipv4_addr2sockaddr(const krb5_address * a,struct sockaddr * sa,krb5_socklen_t * sa_size,int port)83b528cefcSMark Murray ipv4_addr2sockaddr (const krb5_address *a,
84b528cefcSMark Murray struct sockaddr *sa,
858373020dSJacques Vidrine krb5_socklen_t *sa_size,
86b528cefcSMark Murray int port)
87b528cefcSMark Murray {
888373020dSJacques Vidrine struct sockaddr_in tmp;
89b528cefcSMark Murray
908373020dSJacques Vidrine memset (&tmp, 0, sizeof(tmp));
918373020dSJacques Vidrine tmp.sin_family = AF_INET;
928373020dSJacques Vidrine memcpy (&tmp.sin_addr, a->address.data, 4);
938373020dSJacques Vidrine tmp.sin_port = port;
948373020dSJacques Vidrine memcpy(sa, &tmp, min(sizeof(tmp), *sa_size));
958373020dSJacques Vidrine *sa_size = sizeof(tmp);
96b528cefcSMark Murray }
97b528cefcSMark Murray
98b528cefcSMark Murray static void
ipv4_h_addr2sockaddr(const char * addr,struct sockaddr * sa,krb5_socklen_t * sa_size,int port)99b528cefcSMark Murray ipv4_h_addr2sockaddr(const char *addr,
1008373020dSJacques Vidrine struct sockaddr *sa,
1018373020dSJacques Vidrine krb5_socklen_t *sa_size,
1028373020dSJacques Vidrine int port)
103b528cefcSMark Murray {
1048373020dSJacques Vidrine struct sockaddr_in tmp;
105b528cefcSMark Murray
1068373020dSJacques Vidrine memset (&tmp, 0, sizeof(tmp));
1078373020dSJacques Vidrine tmp.sin_family = AF_INET;
1088373020dSJacques Vidrine tmp.sin_port = port;
1098373020dSJacques Vidrine tmp.sin_addr = *((const struct in_addr *)addr);
1108373020dSJacques Vidrine memcpy(sa, &tmp, min(sizeof(tmp), *sa_size));
1118373020dSJacques Vidrine *sa_size = sizeof(tmp);
112b528cefcSMark Murray }
113b528cefcSMark Murray
114b528cefcSMark Murray static krb5_error_code
ipv4_h_addr2addr(const char * addr,krb5_address * a)115b528cefcSMark Murray ipv4_h_addr2addr (const char *addr,
116b528cefcSMark Murray krb5_address *a)
117b528cefcSMark Murray {
118b528cefcSMark Murray unsigned char buf[4];
119b528cefcSMark Murray
120b528cefcSMark Murray a->addr_type = KRB5_ADDRESS_INET;
121b528cefcSMark Murray memcpy(buf, addr, 4);
122b528cefcSMark Murray return krb5_data_copy(&a->address, buf, 4);
123b528cefcSMark Murray }
124b528cefcSMark Murray
125b528cefcSMark Murray /*
126b528cefcSMark Murray * Are there any addresses that should be considered `uninteresting'?
127b528cefcSMark Murray */
128b528cefcSMark Murray
129b528cefcSMark Murray static krb5_boolean
ipv4_uninteresting(const struct sockaddr * sa)130b528cefcSMark Murray ipv4_uninteresting (const struct sockaddr *sa)
131b528cefcSMark Murray {
132c19800e8SDoug Rabson const struct sockaddr_in *sin4 = (const struct sockaddr_in *)sa;
133b528cefcSMark Murray
134c19800e8SDoug Rabson if (sin4->sin_addr.s_addr == INADDR_ANY)
135b528cefcSMark Murray return TRUE;
136b528cefcSMark Murray
137b528cefcSMark Murray return FALSE;
138b528cefcSMark Murray }
139b528cefcSMark Murray
140ae771770SStanislav Sedov static krb5_boolean
ipv4_is_loopback(const struct sockaddr * sa)141ae771770SStanislav Sedov ipv4_is_loopback (const struct sockaddr *sa)
142ae771770SStanislav Sedov {
143ae771770SStanislav Sedov const struct sockaddr_in *sin4 = (const struct sockaddr_in *)sa;
144ae771770SStanislav Sedov
145ae771770SStanislav Sedov if ((ntohl(sin4->sin_addr.s_addr) >> 24) == IN_LOOPBACKNET)
146ae771770SStanislav Sedov return TRUE;
147ae771770SStanislav Sedov
148ae771770SStanislav Sedov return FALSE;
149ae771770SStanislav Sedov }
150ae771770SStanislav Sedov
151b528cefcSMark Murray static void
ipv4_anyaddr(struct sockaddr * sa,krb5_socklen_t * sa_size,int port)1528373020dSJacques Vidrine ipv4_anyaddr (struct sockaddr *sa, krb5_socklen_t *sa_size, int port)
153b528cefcSMark Murray {
1548373020dSJacques Vidrine struct sockaddr_in tmp;
155b528cefcSMark Murray
1568373020dSJacques Vidrine memset (&tmp, 0, sizeof(tmp));
1578373020dSJacques Vidrine tmp.sin_family = AF_INET;
1588373020dSJacques Vidrine tmp.sin_port = port;
1598373020dSJacques Vidrine tmp.sin_addr.s_addr = INADDR_ANY;
1608373020dSJacques Vidrine memcpy(sa, &tmp, min(sizeof(tmp), *sa_size));
1618373020dSJacques Vidrine *sa_size = sizeof(tmp);
162b528cefcSMark Murray }
163b528cefcSMark Murray
164b528cefcSMark Murray static int
ipv4_print_addr(const krb5_address * addr,char * str,size_t len)165b528cefcSMark Murray ipv4_print_addr (const krb5_address *addr, char *str, size_t len)
166b528cefcSMark Murray {
167b528cefcSMark Murray struct in_addr ia;
168b528cefcSMark Murray
169b528cefcSMark Murray memcpy (&ia, addr->address.data, 4);
170b528cefcSMark Murray
171b528cefcSMark Murray return snprintf (str, len, "IPv4:%s", inet_ntoa(ia));
172b528cefcSMark Murray }
173b528cefcSMark Murray
174b528cefcSMark Murray static int
ipv4_parse_addr(krb5_context context,const char * address,krb5_address * addr)1754137ff4cSJacques Vidrine ipv4_parse_addr (krb5_context context, const char *address, krb5_address *addr)
176b528cefcSMark Murray {
177b528cefcSMark Murray const char *p;
178b528cefcSMark Murray struct in_addr a;
179b528cefcSMark Murray
180b528cefcSMark Murray p = strchr(address, ':');
181b528cefcSMark Murray if(p) {
182b528cefcSMark Murray p++;
183b528cefcSMark Murray if(strncasecmp(address, "ip:", p - address) != 0 &&
184b528cefcSMark Murray strncasecmp(address, "ip4:", p - address) != 0 &&
185b528cefcSMark Murray strncasecmp(address, "ipv4:", p - address) != 0 &&
186b528cefcSMark Murray strncasecmp(address, "inet:", p - address) != 0)
187b528cefcSMark Murray return -1;
188b528cefcSMark Murray } else
189b528cefcSMark Murray p = address;
190b528cefcSMark Murray if(inet_aton(p, &a) == 0)
191b528cefcSMark Murray return -1;
192b528cefcSMark Murray addr->addr_type = KRB5_ADDRESS_INET;
193b528cefcSMark Murray if(krb5_data_alloc(&addr->address, 4) != 0)
194b528cefcSMark Murray return -1;
195b528cefcSMark Murray _krb5_put_int(addr->address.data, ntohl(a.s_addr), addr->address.length);
196b528cefcSMark Murray return 0;
197b528cefcSMark Murray }
198b528cefcSMark Murray
199c19800e8SDoug Rabson static int
ipv4_mask_boundary(krb5_context context,const krb5_address * inaddr,unsigned long len,krb5_address * low,krb5_address * high)200c19800e8SDoug Rabson ipv4_mask_boundary(krb5_context context, const krb5_address *inaddr,
201c19800e8SDoug Rabson unsigned long len, krb5_address *low, krb5_address *high)
202c19800e8SDoug Rabson {
203c19800e8SDoug Rabson unsigned long ia;
204c19800e8SDoug Rabson uint32_t l, h, m = 0xffffffff;
205c19800e8SDoug Rabson
206c19800e8SDoug Rabson if (len > 32) {
207ae771770SStanislav Sedov krb5_set_error_message(context, KRB5_PROG_ATYPE_NOSUPP,
208ae771770SStanislav Sedov N_("IPv4 prefix too large (%ld)", "len"), len);
209c19800e8SDoug Rabson return KRB5_PROG_ATYPE_NOSUPP;
210c19800e8SDoug Rabson }
211c19800e8SDoug Rabson m = m << (32 - len);
212c19800e8SDoug Rabson
213c19800e8SDoug Rabson _krb5_get_int(inaddr->address.data, &ia, inaddr->address.length);
214c19800e8SDoug Rabson
215c19800e8SDoug Rabson l = ia & m;
216c19800e8SDoug Rabson h = l | ~m;
217c19800e8SDoug Rabson
218c19800e8SDoug Rabson low->addr_type = KRB5_ADDRESS_INET;
219c19800e8SDoug Rabson if(krb5_data_alloc(&low->address, 4) != 0)
220c19800e8SDoug Rabson return -1;
221c19800e8SDoug Rabson _krb5_put_int(low->address.data, l, low->address.length);
222c19800e8SDoug Rabson
223c19800e8SDoug Rabson high->addr_type = KRB5_ADDRESS_INET;
224c19800e8SDoug Rabson if(krb5_data_alloc(&high->address, 4) != 0) {
225c19800e8SDoug Rabson krb5_free_address(context, low);
226c19800e8SDoug Rabson return -1;
227c19800e8SDoug Rabson }
228c19800e8SDoug Rabson _krb5_put_int(high->address.data, h, high->address.length);
229c19800e8SDoug Rabson
230c19800e8SDoug Rabson return 0;
231c19800e8SDoug Rabson }
232c19800e8SDoug Rabson
233c19800e8SDoug Rabson
234b528cefcSMark Murray /*
235b528cefcSMark Murray * AF_INET6 - aka IPv6 implementation
236b528cefcSMark Murray */
237b528cefcSMark Murray
238b528cefcSMark Murray #ifdef HAVE_IPV6
239b528cefcSMark Murray
240b528cefcSMark Murray static krb5_error_code
ipv6_sockaddr2addr(const struct sockaddr * sa,krb5_address * a)241b528cefcSMark Murray ipv6_sockaddr2addr (const struct sockaddr *sa, krb5_address *a)
242b528cefcSMark Murray {
243b528cefcSMark Murray const struct sockaddr_in6 *sin6 = (const struct sockaddr_in6 *)sa;
244b528cefcSMark Murray
245b528cefcSMark Murray if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) {
246b528cefcSMark Murray unsigned char buf[4];
247b528cefcSMark Murray
248b528cefcSMark Murray a->addr_type = KRB5_ADDRESS_INET;
249b528cefcSMark Murray #ifndef IN6_ADDR_V6_TO_V4
250b528cefcSMark Murray #ifdef IN6_EXTRACT_V4ADDR
251b528cefcSMark Murray #define IN6_ADDR_V6_TO_V4(x) (&IN6_EXTRACT_V4ADDR(x))
252b528cefcSMark Murray #else
253b528cefcSMark Murray #define IN6_ADDR_V6_TO_V4(x) ((const struct in_addr *)&(x)->s6_addr[12])
254b528cefcSMark Murray #endif
255b528cefcSMark Murray #endif
256b528cefcSMark Murray memcpy (buf, IN6_ADDR_V6_TO_V4(&sin6->sin6_addr), 4);
257b528cefcSMark Murray return krb5_data_copy(&a->address, buf, 4);
258b528cefcSMark Murray } else {
259b528cefcSMark Murray a->addr_type = KRB5_ADDRESS_INET6;
260b528cefcSMark Murray return krb5_data_copy(&a->address,
261b528cefcSMark Murray &sin6->sin6_addr,
262b528cefcSMark Murray sizeof(sin6->sin6_addr));
263b528cefcSMark Murray }
264b528cefcSMark Murray }
265b528cefcSMark Murray
266b528cefcSMark Murray static krb5_error_code
ipv6_sockaddr2port(const struct sockaddr * sa,int16_t * port)267b528cefcSMark Murray ipv6_sockaddr2port (const struct sockaddr *sa, int16_t *port)
268b528cefcSMark Murray {
269b528cefcSMark Murray const struct sockaddr_in6 *sin6 = (const struct sockaddr_in6 *)sa;
270b528cefcSMark Murray
271b528cefcSMark Murray *port = sin6->sin6_port;
272b528cefcSMark Murray return 0;
273b528cefcSMark Murray }
274b528cefcSMark Murray
275b528cefcSMark Murray static void
ipv6_addr2sockaddr(const krb5_address * a,struct sockaddr * sa,krb5_socklen_t * sa_size,int port)276b528cefcSMark Murray ipv6_addr2sockaddr (const krb5_address *a,
277b528cefcSMark Murray struct sockaddr *sa,
2788373020dSJacques Vidrine krb5_socklen_t *sa_size,
279b528cefcSMark Murray int port)
280b528cefcSMark Murray {
2818373020dSJacques Vidrine struct sockaddr_in6 tmp;
282b528cefcSMark Murray
2838373020dSJacques Vidrine memset (&tmp, 0, sizeof(tmp));
2848373020dSJacques Vidrine tmp.sin6_family = AF_INET6;
2858373020dSJacques Vidrine memcpy (&tmp.sin6_addr, a->address.data, sizeof(tmp.sin6_addr));
2868373020dSJacques Vidrine tmp.sin6_port = port;
2878373020dSJacques Vidrine memcpy(sa, &tmp, min(sizeof(tmp), *sa_size));
2888373020dSJacques Vidrine *sa_size = sizeof(tmp);
289b528cefcSMark Murray }
290b528cefcSMark Murray
291b528cefcSMark Murray static void
ipv6_h_addr2sockaddr(const char * addr,struct sockaddr * sa,krb5_socklen_t * sa_size,int port)292b528cefcSMark Murray ipv6_h_addr2sockaddr(const char *addr,
293b528cefcSMark Murray struct sockaddr *sa,
2948373020dSJacques Vidrine krb5_socklen_t *sa_size,
295b528cefcSMark Murray int port)
296b528cefcSMark Murray {
2978373020dSJacques Vidrine struct sockaddr_in6 tmp;
298b528cefcSMark Murray
2998373020dSJacques Vidrine memset (&tmp, 0, sizeof(tmp));
3008373020dSJacques Vidrine tmp.sin6_family = AF_INET6;
3018373020dSJacques Vidrine tmp.sin6_port = port;
3028373020dSJacques Vidrine tmp.sin6_addr = *((const struct in6_addr *)addr);
3038373020dSJacques Vidrine memcpy(sa, &tmp, min(sizeof(tmp), *sa_size));
3048373020dSJacques Vidrine *sa_size = sizeof(tmp);
305b528cefcSMark Murray }
306b528cefcSMark Murray
307b528cefcSMark Murray static krb5_error_code
ipv6_h_addr2addr(const char * addr,krb5_address * a)308b528cefcSMark Murray ipv6_h_addr2addr (const char *addr,
309b528cefcSMark Murray krb5_address *a)
310b528cefcSMark Murray {
311b528cefcSMark Murray a->addr_type = KRB5_ADDRESS_INET6;
312b528cefcSMark Murray return krb5_data_copy(&a->address, addr, sizeof(struct in6_addr));
313b528cefcSMark Murray }
314b528cefcSMark Murray
315b528cefcSMark Murray /*
316b528cefcSMark Murray *
317b528cefcSMark Murray */
318b528cefcSMark Murray
319b528cefcSMark Murray static krb5_boolean
ipv6_uninteresting(const struct sockaddr * sa)320b528cefcSMark Murray ipv6_uninteresting (const struct sockaddr *sa)
321b528cefcSMark Murray {
322b528cefcSMark Murray const struct sockaddr_in6 *sin6 = (const struct sockaddr_in6 *)sa;
323b528cefcSMark Murray const struct in6_addr *in6 = (const struct in6_addr *)&sin6->sin6_addr;
324b528cefcSMark Murray
325ae771770SStanislav Sedov return IN6_IS_ADDR_LINKLOCAL(in6)
326b528cefcSMark Murray || IN6_IS_ADDR_V4COMPAT(in6);
327b528cefcSMark Murray }
328b528cefcSMark Murray
329ae771770SStanislav Sedov static krb5_boolean
ipv6_is_loopback(const struct sockaddr * sa)330ae771770SStanislav Sedov ipv6_is_loopback (const struct sockaddr *sa)
331ae771770SStanislav Sedov {
332ae771770SStanislav Sedov const struct sockaddr_in6 *sin6 = (const struct sockaddr_in6 *)sa;
333ae771770SStanislav Sedov const struct in6_addr *in6 = (const struct in6_addr *)&sin6->sin6_addr;
334ae771770SStanislav Sedov
335ae771770SStanislav Sedov return (IN6_IS_ADDR_LOOPBACK(in6));
336ae771770SStanislav Sedov }
337ae771770SStanislav Sedov
338b528cefcSMark Murray static void
ipv6_anyaddr(struct sockaddr * sa,krb5_socklen_t * sa_size,int port)3398373020dSJacques Vidrine ipv6_anyaddr (struct sockaddr *sa, krb5_socklen_t *sa_size, int port)
340b528cefcSMark Murray {
3418373020dSJacques Vidrine struct sockaddr_in6 tmp;
342b528cefcSMark Murray
3438373020dSJacques Vidrine memset (&tmp, 0, sizeof(tmp));
3448373020dSJacques Vidrine tmp.sin6_family = AF_INET6;
3458373020dSJacques Vidrine tmp.sin6_port = port;
3468373020dSJacques Vidrine tmp.sin6_addr = in6addr_any;
3478373020dSJacques Vidrine *sa_size = sizeof(tmp);
348b528cefcSMark Murray }
349b528cefcSMark Murray
350b528cefcSMark Murray static int
ipv6_print_addr(const krb5_address * addr,char * str,size_t len)351b528cefcSMark Murray ipv6_print_addr (const krb5_address *addr, char *str, size_t len)
352b528cefcSMark Murray {
353b528cefcSMark Murray char buf[128], buf2[3];
354b528cefcSMark Murray if(inet_ntop(AF_INET6, addr->address.data, buf, sizeof(buf)) == NULL)
355b528cefcSMark Murray {
356b528cefcSMark Murray /* XXX this is pretty ugly, but better than abort() */
357ae771770SStanislav Sedov size_t i;
358b528cefcSMark Murray unsigned char *p = addr->address.data;
359b528cefcSMark Murray buf[0] = '\0';
360b528cefcSMark Murray for(i = 0; i < addr->address.length; i++) {
361b528cefcSMark Murray snprintf(buf2, sizeof(buf2), "%02x", p[i]);
362b528cefcSMark Murray if(i > 0 && (i & 1) == 0)
363b528cefcSMark Murray strlcat(buf, ":", sizeof(buf));
364b528cefcSMark Murray strlcat(buf, buf2, sizeof(buf));
365b528cefcSMark Murray }
366b528cefcSMark Murray }
367b528cefcSMark Murray return snprintf(str, len, "IPv6:%s", buf);
368b528cefcSMark Murray }
369b528cefcSMark Murray
370b528cefcSMark Murray static int
ipv6_parse_addr(krb5_context context,const char * address,krb5_address * addr)3714137ff4cSJacques Vidrine ipv6_parse_addr (krb5_context context, const char *address, krb5_address *addr)
372b528cefcSMark Murray {
373b528cefcSMark Murray int ret;
374b528cefcSMark Murray struct in6_addr in6;
3754137ff4cSJacques Vidrine const char *p;
3764137ff4cSJacques Vidrine
3774137ff4cSJacques Vidrine p = strchr(address, ':');
3784137ff4cSJacques Vidrine if(p) {
3794137ff4cSJacques Vidrine p++;
3804137ff4cSJacques Vidrine if(strncasecmp(address, "ip6:", p - address) == 0 ||
3814137ff4cSJacques Vidrine strncasecmp(address, "ipv6:", p - address) == 0 ||
3824137ff4cSJacques Vidrine strncasecmp(address, "inet6:", p - address) == 0)
3834137ff4cSJacques Vidrine address = p;
3844137ff4cSJacques Vidrine }
385b528cefcSMark Murray
386b528cefcSMark Murray ret = inet_pton(AF_INET6, address, &in6.s6_addr);
387b528cefcSMark Murray if(ret == 1) {
388b528cefcSMark Murray addr->addr_type = KRB5_ADDRESS_INET6;
389b528cefcSMark Murray ret = krb5_data_alloc(&addr->address, sizeof(in6.s6_addr));
390b528cefcSMark Murray if (ret)
391b528cefcSMark Murray return -1;
392b528cefcSMark Murray memcpy(addr->address.data, in6.s6_addr, sizeof(in6.s6_addr));
393b528cefcSMark Murray return 0;
394b528cefcSMark Murray }
395b528cefcSMark Murray return -1;
396b528cefcSMark Murray }
397b528cefcSMark Murray
398c19800e8SDoug Rabson static int
ipv6_mask_boundary(krb5_context context,const krb5_address * inaddr,unsigned long len,krb5_address * low,krb5_address * high)399c19800e8SDoug Rabson ipv6_mask_boundary(krb5_context context, const krb5_address *inaddr,
400c19800e8SDoug Rabson unsigned long len, krb5_address *low, krb5_address *high)
401c19800e8SDoug Rabson {
402c19800e8SDoug Rabson struct in6_addr addr, laddr, haddr;
403c19800e8SDoug Rabson uint32_t m;
404c19800e8SDoug Rabson int i, sub_len;
405c19800e8SDoug Rabson
406c19800e8SDoug Rabson if (len > 128) {
407ae771770SStanislav Sedov krb5_set_error_message(context, KRB5_PROG_ATYPE_NOSUPP,
408ae771770SStanislav Sedov N_("IPv6 prefix too large (%ld)", "length"), len);
409c19800e8SDoug Rabson return KRB5_PROG_ATYPE_NOSUPP;
410c19800e8SDoug Rabson }
411c19800e8SDoug Rabson
412c19800e8SDoug Rabson if (inaddr->address.length != sizeof(addr)) {
413ae771770SStanislav Sedov krb5_set_error_message(context, KRB5_PROG_ATYPE_NOSUPP,
414ae771770SStanislav Sedov N_("IPv6 addr bad length", ""));
415c19800e8SDoug Rabson return KRB5_PROG_ATYPE_NOSUPP;
416c19800e8SDoug Rabson }
417c19800e8SDoug Rabson
418c19800e8SDoug Rabson memcpy(&addr, inaddr->address.data, inaddr->address.length);
419c19800e8SDoug Rabson
420c19800e8SDoug Rabson for (i = 0; i < 16; i++) {
421c19800e8SDoug Rabson sub_len = min(8, len);
422c19800e8SDoug Rabson
423c19800e8SDoug Rabson m = 0xff << (8 - sub_len);
424c19800e8SDoug Rabson
425c19800e8SDoug Rabson laddr.s6_addr[i] = addr.s6_addr[i] & m;
426c19800e8SDoug Rabson haddr.s6_addr[i] = (addr.s6_addr[i] & m) | ~m;
427c19800e8SDoug Rabson
428c19800e8SDoug Rabson if (len > 8)
429c19800e8SDoug Rabson len -= 8;
430c19800e8SDoug Rabson else
431c19800e8SDoug Rabson len = 0;
432c19800e8SDoug Rabson }
433c19800e8SDoug Rabson
434c19800e8SDoug Rabson low->addr_type = KRB5_ADDRESS_INET6;
435c19800e8SDoug Rabson if (krb5_data_alloc(&low->address, sizeof(laddr.s6_addr)) != 0)
436c19800e8SDoug Rabson return -1;
437c19800e8SDoug Rabson memcpy(low->address.data, laddr.s6_addr, sizeof(laddr.s6_addr));
438c19800e8SDoug Rabson
439c19800e8SDoug Rabson high->addr_type = KRB5_ADDRESS_INET6;
440c19800e8SDoug Rabson if (krb5_data_alloc(&high->address, sizeof(haddr.s6_addr)) != 0) {
441c19800e8SDoug Rabson krb5_free_address(context, low);
442c19800e8SDoug Rabson return -1;
443c19800e8SDoug Rabson }
444c19800e8SDoug Rabson memcpy(high->address.data, haddr.s6_addr, sizeof(haddr.s6_addr));
445c19800e8SDoug Rabson
446c19800e8SDoug Rabson return 0;
447c19800e8SDoug Rabson }
448c19800e8SDoug Rabson
449b528cefcSMark Murray #endif /* IPv6 */
450b528cefcSMark Murray
451ae771770SStanislav Sedov #ifndef HEIMDAL_SMALLER
452ae771770SStanislav Sedov
453b528cefcSMark Murray /*
454b528cefcSMark Murray * table
455b528cefcSMark Murray */
456b528cefcSMark Murray
4574137ff4cSJacques Vidrine #define KRB5_ADDRESS_ARANGE (-100)
4584137ff4cSJacques Vidrine
4594137ff4cSJacques Vidrine struct arange {
4604137ff4cSJacques Vidrine krb5_address low;
4614137ff4cSJacques Vidrine krb5_address high;
4624137ff4cSJacques Vidrine };
4634137ff4cSJacques Vidrine
4644137ff4cSJacques Vidrine static int
arange_parse_addr(krb5_context context,const char * address,krb5_address * addr)4654137ff4cSJacques Vidrine arange_parse_addr (krb5_context context,
4664137ff4cSJacques Vidrine const char *address, krb5_address *addr)
4674137ff4cSJacques Vidrine {
468c19800e8SDoug Rabson char buf[1024], *p;
469c19800e8SDoug Rabson krb5_address low0, high0;
4704137ff4cSJacques Vidrine struct arange *a;
4714137ff4cSJacques Vidrine krb5_error_code ret;
4724137ff4cSJacques Vidrine
4734137ff4cSJacques Vidrine if(strncasecmp(address, "RANGE:", 6) != 0)
4744137ff4cSJacques Vidrine return -1;
4754137ff4cSJacques Vidrine
4764137ff4cSJacques Vidrine address += 6;
4774137ff4cSJacques Vidrine
478c19800e8SDoug Rabson p = strrchr(address, '/');
479c19800e8SDoug Rabson if (p) {
480c19800e8SDoug Rabson krb5_addresses addrmask;
481c19800e8SDoug Rabson char *q;
482c19800e8SDoug Rabson long num;
483c19800e8SDoug Rabson
484c19800e8SDoug Rabson if (strlcpy(buf, address, sizeof(buf)) > sizeof(buf))
485c19800e8SDoug Rabson return -1;
486c19800e8SDoug Rabson buf[p - address] = '\0';
487c19800e8SDoug Rabson ret = krb5_parse_address(context, buf, &addrmask);
488c19800e8SDoug Rabson if (ret)
489c19800e8SDoug Rabson return ret;
490c19800e8SDoug Rabson if(addrmask.len != 1) {
491c19800e8SDoug Rabson krb5_free_addresses(context, &addrmask);
492c19800e8SDoug Rabson return -1;
493c19800e8SDoug Rabson }
494c19800e8SDoug Rabson
495c19800e8SDoug Rabson address += p - address + 1;
496c19800e8SDoug Rabson
497c19800e8SDoug Rabson num = strtol(address, &q, 10);
498c19800e8SDoug Rabson if (q == address || *q != '\0' || num < 0) {
499c19800e8SDoug Rabson krb5_free_addresses(context, &addrmask);
500c19800e8SDoug Rabson return -1;
501c19800e8SDoug Rabson }
502c19800e8SDoug Rabson
503c19800e8SDoug Rabson ret = krb5_address_prefixlen_boundary(context, &addrmask.val[0], num,
504c19800e8SDoug Rabson &low0, &high0);
505c19800e8SDoug Rabson krb5_free_addresses(context, &addrmask);
506c19800e8SDoug Rabson if (ret)
507c19800e8SDoug Rabson return ret;
508c19800e8SDoug Rabson
509c19800e8SDoug Rabson } else {
510c19800e8SDoug Rabson krb5_addresses low, high;
511c19800e8SDoug Rabson
5124137ff4cSJacques Vidrine strsep_copy(&address, "-", buf, sizeof(buf));
5134137ff4cSJacques Vidrine ret = krb5_parse_address(context, buf, &low);
5144137ff4cSJacques Vidrine if(ret)
5154137ff4cSJacques Vidrine return ret;
5164137ff4cSJacques Vidrine if(low.len != 1) {
5174137ff4cSJacques Vidrine krb5_free_addresses(context, &low);
5184137ff4cSJacques Vidrine return -1;
5194137ff4cSJacques Vidrine }
5204137ff4cSJacques Vidrine
5214137ff4cSJacques Vidrine strsep_copy(&address, "-", buf, sizeof(buf));
5224137ff4cSJacques Vidrine ret = krb5_parse_address(context, buf, &high);
5234137ff4cSJacques Vidrine if(ret) {
5244137ff4cSJacques Vidrine krb5_free_addresses(context, &low);
5254137ff4cSJacques Vidrine return ret;
5264137ff4cSJacques Vidrine }
5274137ff4cSJacques Vidrine
528*ed549cb0SCy Schubert if(high.len != 1 || high.val[0].addr_type != low.val[0].addr_type) {
5294137ff4cSJacques Vidrine krb5_free_addresses(context, &low);
5304137ff4cSJacques Vidrine krb5_free_addresses(context, &high);
5314137ff4cSJacques Vidrine return -1;
5324137ff4cSJacques Vidrine }
5334137ff4cSJacques Vidrine
534c19800e8SDoug Rabson ret = krb5_copy_address(context, &high.val[0], &high0);
535c19800e8SDoug Rabson if (ret == 0) {
536c19800e8SDoug Rabson ret = krb5_copy_address(context, &low.val[0], &low0);
537c19800e8SDoug Rabson if (ret)
538c19800e8SDoug Rabson krb5_free_address(context, &high0);
539c19800e8SDoug Rabson }
540c19800e8SDoug Rabson krb5_free_addresses(context, &low);
541c19800e8SDoug Rabson krb5_free_addresses(context, &high);
542c19800e8SDoug Rabson if (ret)
543c19800e8SDoug Rabson return ret;
544c19800e8SDoug Rabson }
545c19800e8SDoug Rabson
5464137ff4cSJacques Vidrine krb5_data_alloc(&addr->address, sizeof(*a));
5474137ff4cSJacques Vidrine addr->addr_type = KRB5_ADDRESS_ARANGE;
5484137ff4cSJacques Vidrine a = addr->address.data;
5494137ff4cSJacques Vidrine
550c19800e8SDoug Rabson if(krb5_address_order(context, &low0, &high0) < 0) {
551c19800e8SDoug Rabson a->low = low0;
552c19800e8SDoug Rabson a->high = high0;
5534137ff4cSJacques Vidrine } else {
554c19800e8SDoug Rabson a->low = high0;
555c19800e8SDoug Rabson a->high = low0;
5564137ff4cSJacques Vidrine }
5574137ff4cSJacques Vidrine return 0;
5584137ff4cSJacques Vidrine }
5594137ff4cSJacques Vidrine
5604137ff4cSJacques Vidrine static int
arange_free(krb5_context context,krb5_address * addr)5614137ff4cSJacques Vidrine arange_free (krb5_context context, krb5_address *addr)
5624137ff4cSJacques Vidrine {
5634137ff4cSJacques Vidrine struct arange *a;
5644137ff4cSJacques Vidrine a = addr->address.data;
5654137ff4cSJacques Vidrine krb5_free_address(context, &a->low);
5664137ff4cSJacques Vidrine krb5_free_address(context, &a->high);
567c19800e8SDoug Rabson krb5_data_free(&addr->address);
5684137ff4cSJacques Vidrine return 0;
5694137ff4cSJacques Vidrine }
5704137ff4cSJacques Vidrine
5714137ff4cSJacques Vidrine
5724137ff4cSJacques Vidrine static int
arange_copy(krb5_context context,const krb5_address * inaddr,krb5_address * outaddr)5734137ff4cSJacques Vidrine arange_copy (krb5_context context, const krb5_address *inaddr,
5744137ff4cSJacques Vidrine krb5_address *outaddr)
5754137ff4cSJacques Vidrine {
5764137ff4cSJacques Vidrine krb5_error_code ret;
5774137ff4cSJacques Vidrine struct arange *i, *o;
5784137ff4cSJacques Vidrine
5794137ff4cSJacques Vidrine outaddr->addr_type = KRB5_ADDRESS_ARANGE;
5804137ff4cSJacques Vidrine ret = krb5_data_alloc(&outaddr->address, sizeof(*o));
5814137ff4cSJacques Vidrine if(ret)
5824137ff4cSJacques Vidrine return ret;
5834137ff4cSJacques Vidrine i = inaddr->address.data;
5844137ff4cSJacques Vidrine o = outaddr->address.data;
5854137ff4cSJacques Vidrine ret = krb5_copy_address(context, &i->low, &o->low);
5864137ff4cSJacques Vidrine if(ret) {
5874137ff4cSJacques Vidrine krb5_data_free(&outaddr->address);
5884137ff4cSJacques Vidrine return ret;
5894137ff4cSJacques Vidrine }
5904137ff4cSJacques Vidrine ret = krb5_copy_address(context, &i->high, &o->high);
5914137ff4cSJacques Vidrine if(ret) {
5924137ff4cSJacques Vidrine krb5_free_address(context, &o->low);
5934137ff4cSJacques Vidrine krb5_data_free(&outaddr->address);
5944137ff4cSJacques Vidrine return ret;
5954137ff4cSJacques Vidrine }
5964137ff4cSJacques Vidrine return 0;
5974137ff4cSJacques Vidrine }
5984137ff4cSJacques Vidrine
5994137ff4cSJacques Vidrine static int
arange_print_addr(const krb5_address * addr,char * str,size_t len)6004137ff4cSJacques Vidrine arange_print_addr (const krb5_address *addr, char *str, size_t len)
6014137ff4cSJacques Vidrine {
6024137ff4cSJacques Vidrine struct arange *a;
6034137ff4cSJacques Vidrine krb5_error_code ret;
604c19800e8SDoug Rabson size_t l, size, ret_len;
6054137ff4cSJacques Vidrine
6064137ff4cSJacques Vidrine a = addr->address.data;
6074137ff4cSJacques Vidrine
6084137ff4cSJacques Vidrine l = strlcpy(str, "RANGE:", len);
609c19800e8SDoug Rabson ret_len = l;
610c19800e8SDoug Rabson if (l > len)
611c19800e8SDoug Rabson l = len;
612c19800e8SDoug Rabson size = l;
6134137ff4cSJacques Vidrine
614c19800e8SDoug Rabson ret = krb5_print_address (&a->low, str + size, len - size, &l);
615c19800e8SDoug Rabson if (ret)
616c19800e8SDoug Rabson return ret;
6174137ff4cSJacques Vidrine ret_len += l;
618c19800e8SDoug Rabson if (len - size > l)
619c19800e8SDoug Rabson size += l;
620c19800e8SDoug Rabson else
621c19800e8SDoug Rabson size = len;
6224137ff4cSJacques Vidrine
623c19800e8SDoug Rabson l = strlcat(str + size, "-", len - size);
6244137ff4cSJacques Vidrine ret_len += l;
625c19800e8SDoug Rabson if (len - size > l)
626c19800e8SDoug Rabson size += l;
627c19800e8SDoug Rabson else
628c19800e8SDoug Rabson size = len;
6294137ff4cSJacques Vidrine
630c19800e8SDoug Rabson ret = krb5_print_address (&a->high, str + size, len - size, &l);
631c19800e8SDoug Rabson if (ret)
632c19800e8SDoug Rabson return ret;
6334137ff4cSJacques Vidrine ret_len += l;
6344137ff4cSJacques Vidrine
6354137ff4cSJacques Vidrine return ret_len;
6364137ff4cSJacques Vidrine }
6374137ff4cSJacques Vidrine
6384137ff4cSJacques Vidrine static int
arange_order_addr(krb5_context context,const krb5_address * addr1,const krb5_address * addr2)6394137ff4cSJacques Vidrine arange_order_addr(krb5_context context,
6404137ff4cSJacques Vidrine const krb5_address *addr1,
6414137ff4cSJacques Vidrine const krb5_address *addr2)
6424137ff4cSJacques Vidrine {
6434137ff4cSJacques Vidrine int tmp1, tmp2, sign;
6444137ff4cSJacques Vidrine struct arange *a;
6454137ff4cSJacques Vidrine const krb5_address *a2;
6464137ff4cSJacques Vidrine
6474137ff4cSJacques Vidrine if(addr1->addr_type == KRB5_ADDRESS_ARANGE) {
6484137ff4cSJacques Vidrine a = addr1->address.data;
6494137ff4cSJacques Vidrine a2 = addr2;
6504137ff4cSJacques Vidrine sign = 1;
6514137ff4cSJacques Vidrine } else if(addr2->addr_type == KRB5_ADDRESS_ARANGE) {
6524137ff4cSJacques Vidrine a = addr2->address.data;
6534137ff4cSJacques Vidrine a2 = addr1;
6544137ff4cSJacques Vidrine sign = -1;
655ae771770SStanislav Sedov } else {
6564137ff4cSJacques Vidrine abort();
657ae771770SStanislav Sedov UNREACHABLE(return 0);
658ae771770SStanislav Sedov }
6594137ff4cSJacques Vidrine
6604137ff4cSJacques Vidrine if(a2->addr_type == KRB5_ADDRESS_ARANGE) {
6614137ff4cSJacques Vidrine struct arange *b = a2->address.data;
6624137ff4cSJacques Vidrine tmp1 = krb5_address_order(context, &a->low, &b->low);
6634137ff4cSJacques Vidrine if(tmp1 != 0)
6644137ff4cSJacques Vidrine return sign * tmp1;
6654137ff4cSJacques Vidrine return sign * krb5_address_order(context, &a->high, &b->high);
6664137ff4cSJacques Vidrine } else if(a2->addr_type == a->low.addr_type) {
6674137ff4cSJacques Vidrine tmp1 = krb5_address_order(context, &a->low, a2);
6684137ff4cSJacques Vidrine if(tmp1 > 0)
6694137ff4cSJacques Vidrine return sign;
6704137ff4cSJacques Vidrine tmp2 = krb5_address_order(context, &a->high, a2);
6714137ff4cSJacques Vidrine if(tmp2 < 0)
6724137ff4cSJacques Vidrine return -sign;
6734137ff4cSJacques Vidrine return 0;
6744137ff4cSJacques Vidrine } else {
6754137ff4cSJacques Vidrine return sign * (addr1->addr_type - addr2->addr_type);
6764137ff4cSJacques Vidrine }
6774137ff4cSJacques Vidrine }
6784137ff4cSJacques Vidrine
679ae771770SStanislav Sedov #endif /* HEIMDAL_SMALLER */
680ae771770SStanislav Sedov
681bbd80c28SJacques Vidrine static int
addrport_print_addr(const krb5_address * addr,char * str,size_t len)682bbd80c28SJacques Vidrine addrport_print_addr (const krb5_address *addr, char *str, size_t len)
683bbd80c28SJacques Vidrine {
684c19800e8SDoug Rabson krb5_error_code ret;
685bbd80c28SJacques Vidrine krb5_address addr1, addr2;
686bbd80c28SJacques Vidrine uint16_t port = 0;
687c19800e8SDoug Rabson size_t ret_len = 0, l, size = 0;
688c19800e8SDoug Rabson krb5_storage *sp;
689c19800e8SDoug Rabson
690c19800e8SDoug Rabson sp = krb5_storage_from_data((krb5_data*)rk_UNCONST(&addr->address));
691ae771770SStanislav Sedov if (sp == NULL)
692ae771770SStanislav Sedov return ENOMEM;
693ae771770SStanislav Sedov
694bbd80c28SJacques Vidrine /* for totally obscure reasons, these are not in network byteorder */
695bbd80c28SJacques Vidrine krb5_storage_set_byteorder(sp, KRB5_STORAGE_BYTEORDER_LE);
696bbd80c28SJacques Vidrine
697bbd80c28SJacques Vidrine krb5_storage_seek(sp, 2, SEEK_CUR); /* skip first two bytes */
698bbd80c28SJacques Vidrine krb5_ret_address(sp, &addr1);
699bbd80c28SJacques Vidrine
700bbd80c28SJacques Vidrine krb5_storage_seek(sp, 2, SEEK_CUR); /* skip two bytes */
701bbd80c28SJacques Vidrine krb5_ret_address(sp, &addr2);
702bbd80c28SJacques Vidrine krb5_storage_free(sp);
703bbd80c28SJacques Vidrine if(addr2.addr_type == KRB5_ADDRESS_IPPORT && addr2.address.length == 2) {
704bbd80c28SJacques Vidrine unsigned long value;
705bbd80c28SJacques Vidrine _krb5_get_int(addr2.address.data, &value, 2);
706bbd80c28SJacques Vidrine port = value;
707bbd80c28SJacques Vidrine }
708bbd80c28SJacques Vidrine l = strlcpy(str, "ADDRPORT:", len);
709bbd80c28SJacques Vidrine ret_len += l;
710c19800e8SDoug Rabson if (len > l)
711c19800e8SDoug Rabson size += l;
712c19800e8SDoug Rabson else
713c19800e8SDoug Rabson size = len;
714c19800e8SDoug Rabson
715c19800e8SDoug Rabson ret = krb5_print_address(&addr1, str + size, len - size, &l);
716c19800e8SDoug Rabson if (ret)
717c19800e8SDoug Rabson return ret;
718bbd80c28SJacques Vidrine ret_len += l;
719c19800e8SDoug Rabson if (len - size > l)
720c19800e8SDoug Rabson size += l;
721c19800e8SDoug Rabson else
722c19800e8SDoug Rabson size = len;
723c19800e8SDoug Rabson
724c19800e8SDoug Rabson ret = snprintf(str + size, len - size, ",PORT=%u", port);
725c19800e8SDoug Rabson if (ret < 0)
726c19800e8SDoug Rabson return EINVAL;
727c19800e8SDoug Rabson ret_len += ret;
728bbd80c28SJacques Vidrine return ret_len;
729bbd80c28SJacques Vidrine }
730bbd80c28SJacques Vidrine
731b528cefcSMark Murray static struct addr_operations at[] = {
732ae771770SStanislav Sedov {
733ae771770SStanislav Sedov AF_INET, KRB5_ADDRESS_INET, sizeof(struct sockaddr_in),
734b528cefcSMark Murray ipv4_sockaddr2addr,
735b528cefcSMark Murray ipv4_sockaddr2port,
736b528cefcSMark Murray ipv4_addr2sockaddr,
737b528cefcSMark Murray ipv4_h_addr2sockaddr,
738b528cefcSMark Murray ipv4_h_addr2addr,
739ae771770SStanislav Sedov ipv4_uninteresting,
740ae771770SStanislav Sedov ipv4_is_loopback,
741ae771770SStanislav Sedov ipv4_anyaddr,
742ae771770SStanislav Sedov ipv4_print_addr,
743ae771770SStanislav Sedov ipv4_parse_addr,
744ae771770SStanislav Sedov NULL,
745ae771770SStanislav Sedov NULL,
746ae771770SStanislav Sedov NULL,
747ae771770SStanislav Sedov ipv4_mask_boundary
748ae771770SStanislav Sedov },
749b528cefcSMark Murray #ifdef HAVE_IPV6
750ae771770SStanislav Sedov {
751ae771770SStanislav Sedov AF_INET6, KRB5_ADDRESS_INET6, sizeof(struct sockaddr_in6),
752b528cefcSMark Murray ipv6_sockaddr2addr,
753b528cefcSMark Murray ipv6_sockaddr2port,
754b528cefcSMark Murray ipv6_addr2sockaddr,
755b528cefcSMark Murray ipv6_h_addr2sockaddr,
756b528cefcSMark Murray ipv6_h_addr2addr,
757ae771770SStanislav Sedov ipv6_uninteresting,
758ae771770SStanislav Sedov ipv6_is_loopback,
759ae771770SStanislav Sedov ipv6_anyaddr,
760ae771770SStanislav Sedov ipv6_print_addr,
761ae771770SStanislav Sedov ipv6_parse_addr,
762ae771770SStanislav Sedov NULL,
763ae771770SStanislav Sedov NULL,
764ae771770SStanislav Sedov NULL,
765ae771770SStanislav Sedov ipv6_mask_boundary
766ae771770SStanislav Sedov } ,
767b528cefcSMark Murray #endif
768ae771770SStanislav Sedov #ifndef HEIMDAL_SMALLER
7694137ff4cSJacques Vidrine /* fake address type */
770ae771770SStanislav Sedov {
771ae771770SStanislav Sedov KRB5_ADDRESS_ARANGE, KRB5_ADDRESS_ARANGE, sizeof(struct arange),
772ae771770SStanislav Sedov NULL,
773ae771770SStanislav Sedov NULL,
774ae771770SStanislav Sedov NULL,
775ae771770SStanislav Sedov NULL,
776ae771770SStanislav Sedov NULL,
777ae771770SStanislav Sedov NULL,
778ae771770SStanislav Sedov NULL,
779ae771770SStanislav Sedov NULL,
780ae771770SStanislav Sedov arange_print_addr,
781ae771770SStanislav Sedov arange_parse_addr,
782ae771770SStanislav Sedov arange_order_addr,
783ae771770SStanislav Sedov arange_free,
784ae771770SStanislav Sedov arange_copy,
785ae771770SStanislav Sedov NULL
786ae771770SStanislav Sedov },
787ae771770SStanislav Sedov #endif
788ae771770SStanislav Sedov {
789ae771770SStanislav Sedov KRB5_ADDRESS_ADDRPORT, KRB5_ADDRESS_ADDRPORT, 0,
790ae771770SStanislav Sedov NULL,
791ae771770SStanislav Sedov NULL,
792ae771770SStanislav Sedov NULL,
793ae771770SStanislav Sedov NULL,
794ae771770SStanislav Sedov NULL,
795ae771770SStanislav Sedov NULL,
796ae771770SStanislav Sedov NULL,
797ae771770SStanislav Sedov NULL,
798ae771770SStanislav Sedov addrport_print_addr,
799ae771770SStanislav Sedov NULL,
800ae771770SStanislav Sedov NULL,
801ae771770SStanislav Sedov NULL,
802ae771770SStanislav Sedov NULL
803ae771770SStanislav Sedov }
804b528cefcSMark Murray };
805b528cefcSMark Murray
806b528cefcSMark Murray static int num_addrs = sizeof(at) / sizeof(at[0]);
807b528cefcSMark Murray
808b528cefcSMark Murray static size_t max_sockaddr_size = 0;
809b528cefcSMark Murray
810b528cefcSMark Murray /*
811b528cefcSMark Murray * generic functions
812b528cefcSMark Murray */
813b528cefcSMark Murray
814b528cefcSMark Murray static struct addr_operations *
find_af(int af)815b528cefcSMark Murray find_af(int af)
816b528cefcSMark Murray {
817b528cefcSMark Murray struct addr_operations *a;
818b528cefcSMark Murray
819b528cefcSMark Murray for (a = at; a < at + num_addrs; ++a)
820b528cefcSMark Murray if (af == a->af)
821b528cefcSMark Murray return a;
822b528cefcSMark Murray return NULL;
823b528cefcSMark Murray }
824b528cefcSMark Murray
825b528cefcSMark Murray static struct addr_operations *
find_atype(krb5_address_type atype)826ae771770SStanislav Sedov find_atype(krb5_address_type atype)
827b528cefcSMark Murray {
828b528cefcSMark Murray struct addr_operations *a;
829b528cefcSMark Murray
830b528cefcSMark Murray for (a = at; a < at + num_addrs; ++a)
831b528cefcSMark Murray if (atype == a->atype)
832b528cefcSMark Murray return a;
833b528cefcSMark Murray return NULL;
834b528cefcSMark Murray }
835b528cefcSMark Murray
836c19800e8SDoug Rabson /**
837c19800e8SDoug Rabson * krb5_sockaddr2address stores a address a "struct sockaddr" sa in
838c19800e8SDoug Rabson * the krb5_address addr.
839c19800e8SDoug Rabson *
840c19800e8SDoug Rabson * @param context a Keberos context
841c19800e8SDoug Rabson * @param sa a struct sockaddr to extract the address from
842c19800e8SDoug Rabson * @param addr an Kerberos 5 address to store the address in.
843c19800e8SDoug Rabson *
844c19800e8SDoug Rabson * @return Return an error code or 0.
845c19800e8SDoug Rabson *
846c19800e8SDoug Rabson * @ingroup krb5_address
847c19800e8SDoug Rabson */
848c19800e8SDoug Rabson
849ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_sockaddr2address(krb5_context context,const struct sockaddr * sa,krb5_address * addr)850adb0ddaeSAssar Westerlund krb5_sockaddr2address (krb5_context context,
851adb0ddaeSAssar Westerlund const struct sockaddr *sa, krb5_address *addr)
852b528cefcSMark Murray {
853b528cefcSMark Murray struct addr_operations *a = find_af(sa->sa_family);
854adb0ddaeSAssar Westerlund if (a == NULL) {
855ae771770SStanislav Sedov krb5_set_error_message (context, KRB5_PROG_ATYPE_NOSUPP,
856ae771770SStanislav Sedov N_("Address family %d not supported", ""),
857adb0ddaeSAssar Westerlund sa->sa_family);
858b528cefcSMark Murray return KRB5_PROG_ATYPE_NOSUPP;
859adb0ddaeSAssar Westerlund }
860b528cefcSMark Murray return (*a->sockaddr2addr)(sa, addr);
861b528cefcSMark Murray }
862b528cefcSMark Murray
863c19800e8SDoug Rabson /**
864c19800e8SDoug Rabson * krb5_sockaddr2port extracts a port (if possible) from a "struct
865c19800e8SDoug Rabson * sockaddr.
866c19800e8SDoug Rabson *
867c19800e8SDoug Rabson * @param context a Keberos context
868c19800e8SDoug Rabson * @param sa a struct sockaddr to extract the port from
869c19800e8SDoug Rabson * @param port a pointer to an int16_t store the port in.
870c19800e8SDoug Rabson *
871c19800e8SDoug Rabson * @return Return an error code or 0. Will return
872c19800e8SDoug Rabson * KRB5_PROG_ATYPE_NOSUPP in case address type is not supported.
873c19800e8SDoug Rabson *
874c19800e8SDoug Rabson * @ingroup krb5_address
875c19800e8SDoug Rabson */
876c19800e8SDoug Rabson
877ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_sockaddr2port(krb5_context context,const struct sockaddr * sa,int16_t * port)878adb0ddaeSAssar Westerlund krb5_sockaddr2port (krb5_context context,
879adb0ddaeSAssar Westerlund const struct sockaddr *sa, int16_t *port)
880b528cefcSMark Murray {
881b528cefcSMark Murray struct addr_operations *a = find_af(sa->sa_family);
882adb0ddaeSAssar Westerlund if (a == NULL) {
883ae771770SStanislav Sedov krb5_set_error_message (context, KRB5_PROG_ATYPE_NOSUPP,
884ae771770SStanislav Sedov N_("Address family %d not supported", ""),
885adb0ddaeSAssar Westerlund sa->sa_family);
886b528cefcSMark Murray return KRB5_PROG_ATYPE_NOSUPP;
887adb0ddaeSAssar Westerlund }
888b528cefcSMark Murray return (*a->sockaddr2port)(sa, port);
889b528cefcSMark Murray }
890b528cefcSMark Murray
891c19800e8SDoug Rabson /**
892c19800e8SDoug Rabson * krb5_addr2sockaddr sets the "struct sockaddr sockaddr" from addr
893c19800e8SDoug Rabson * and port. The argument sa_size should initially contain the size of
894c19800e8SDoug Rabson * the sa and after the call, it will contain the actual length of the
895c19800e8SDoug Rabson * address. In case of the sa is too small to fit the whole address,
896c19800e8SDoug Rabson * the up to *sa_size will be stored, and then *sa_size will be set to
897c19800e8SDoug Rabson * the required length.
898c19800e8SDoug Rabson *
899c19800e8SDoug Rabson * @param context a Keberos context
900c19800e8SDoug Rabson * @param addr the address to copy the from
901c19800e8SDoug Rabson * @param sa the struct sockaddr that will be filled in
902c19800e8SDoug Rabson * @param sa_size pointer to length of sa, and after the call, it will
903c19800e8SDoug Rabson * contain the actual length of the address.
904c19800e8SDoug Rabson * @param port set port in sa.
905c19800e8SDoug Rabson *
906c19800e8SDoug Rabson * @return Return an error code or 0. Will return
907c19800e8SDoug Rabson * KRB5_PROG_ATYPE_NOSUPP in case address type is not supported.
908c19800e8SDoug Rabson *
909c19800e8SDoug Rabson * @ingroup krb5_address
910c19800e8SDoug Rabson */
911c19800e8SDoug Rabson
912ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_addr2sockaddr(krb5_context context,const krb5_address * addr,struct sockaddr * sa,krb5_socklen_t * sa_size,int port)913adb0ddaeSAssar Westerlund krb5_addr2sockaddr (krb5_context context,
914adb0ddaeSAssar Westerlund const krb5_address *addr,
915b528cefcSMark Murray struct sockaddr *sa,
9168373020dSJacques Vidrine krb5_socklen_t *sa_size,
917b528cefcSMark Murray int port)
918b528cefcSMark Murray {
919b528cefcSMark Murray struct addr_operations *a = find_atype(addr->addr_type);
920b528cefcSMark Murray
921adb0ddaeSAssar Westerlund if (a == NULL) {
922ae771770SStanislav Sedov krb5_set_error_message (context, KRB5_PROG_ATYPE_NOSUPP,
923ae771770SStanislav Sedov N_("Address type %d not supported",
924ae771770SStanislav Sedov "krb5_address type"),
925adb0ddaeSAssar Westerlund addr->addr_type);
926b528cefcSMark Murray return KRB5_PROG_ATYPE_NOSUPP;
927adb0ddaeSAssar Westerlund }
9284137ff4cSJacques Vidrine if (a->addr2sockaddr == NULL) {
929ae771770SStanislav Sedov krb5_set_error_message (context,
930ae771770SStanislav Sedov KRB5_PROG_ATYPE_NOSUPP,
931ae771770SStanislav Sedov N_("Can't convert address type %d to sockaddr", ""),
9324137ff4cSJacques Vidrine addr->addr_type);
9334137ff4cSJacques Vidrine return KRB5_PROG_ATYPE_NOSUPP;
9344137ff4cSJacques Vidrine }
935b528cefcSMark Murray (*a->addr2sockaddr)(addr, sa, sa_size, port);
936b528cefcSMark Murray return 0;
937b528cefcSMark Murray }
938b528cefcSMark Murray
939c19800e8SDoug Rabson /**
940c19800e8SDoug Rabson * krb5_max_sockaddr_size returns the max size of the .Li struct
941c19800e8SDoug Rabson * sockaddr that the Kerberos library will return.
942c19800e8SDoug Rabson *
943c19800e8SDoug Rabson * @return Return an size_t of the maximum struct sockaddr.
944c19800e8SDoug Rabson *
945c19800e8SDoug Rabson * @ingroup krb5_address
946c19800e8SDoug Rabson */
947c19800e8SDoug Rabson
948ae771770SStanislav Sedov KRB5_LIB_FUNCTION size_t KRB5_LIB_CALL
krb5_max_sockaddr_size(void)949b528cefcSMark Murray krb5_max_sockaddr_size (void)
950b528cefcSMark Murray {
951b528cefcSMark Murray if (max_sockaddr_size == 0) {
952b528cefcSMark Murray struct addr_operations *a;
953b528cefcSMark Murray
954b528cefcSMark Murray for(a = at; a < at + num_addrs; ++a)
955b528cefcSMark Murray max_sockaddr_size = max(max_sockaddr_size, a->max_sockaddr_size);
956b528cefcSMark Murray }
957b528cefcSMark Murray return max_sockaddr_size;
958b528cefcSMark Murray }
959b528cefcSMark Murray
960c19800e8SDoug Rabson /**
961c19800e8SDoug Rabson * krb5_sockaddr_uninteresting returns TRUE for all .Fa sa that the
962c19800e8SDoug Rabson * kerberos library thinks are uninteresting. One example are link
963c19800e8SDoug Rabson * local addresses.
964c19800e8SDoug Rabson *
965c19800e8SDoug Rabson * @param sa pointer to struct sockaddr that might be interesting.
966c19800e8SDoug Rabson *
967c19800e8SDoug Rabson * @return Return a non zero for uninteresting addresses.
968c19800e8SDoug Rabson *
969c19800e8SDoug Rabson * @ingroup krb5_address
970c19800e8SDoug Rabson */
971c19800e8SDoug Rabson
972ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_boolean KRB5_LIB_CALL
krb5_sockaddr_uninteresting(const struct sockaddr * sa)973b528cefcSMark Murray krb5_sockaddr_uninteresting(const struct sockaddr *sa)
974b528cefcSMark Murray {
975b528cefcSMark Murray struct addr_operations *a = find_af(sa->sa_family);
9764137ff4cSJacques Vidrine if (a == NULL || a->uninteresting == NULL)
977b528cefcSMark Murray return TRUE;
978b528cefcSMark Murray return (*a->uninteresting)(sa);
979b528cefcSMark Murray }
980b528cefcSMark Murray
981ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_boolean KRB5_LIB_CALL
krb5_sockaddr_is_loopback(const struct sockaddr * sa)982ae771770SStanislav Sedov krb5_sockaddr_is_loopback(const struct sockaddr *sa)
983ae771770SStanislav Sedov {
984ae771770SStanislav Sedov struct addr_operations *a = find_af(sa->sa_family);
985ae771770SStanislav Sedov if (a == NULL || a->is_loopback == NULL)
986ae771770SStanislav Sedov return TRUE;
987ae771770SStanislav Sedov return (*a->is_loopback)(sa);
988ae771770SStanislav Sedov }
989ae771770SStanislav Sedov
990c19800e8SDoug Rabson /**
991c19800e8SDoug Rabson * krb5_h_addr2sockaddr initializes a "struct sockaddr sa" from af and
992c19800e8SDoug Rabson * the "struct hostent" (see gethostbyname(3) ) h_addr_list
993c19800e8SDoug Rabson * component. The argument sa_size should initially contain the size
994c19800e8SDoug Rabson * of the sa, and after the call, it will contain the actual length of
995c19800e8SDoug Rabson * the address.
996c19800e8SDoug Rabson *
997c19800e8SDoug Rabson * @param context a Keberos context
998c19800e8SDoug Rabson * @param af addresses
999c19800e8SDoug Rabson * @param addr address
1000c19800e8SDoug Rabson * @param sa returned struct sockaddr
1001c19800e8SDoug Rabson * @param sa_size size of sa
1002c19800e8SDoug Rabson * @param port port to set in sa.
1003c19800e8SDoug Rabson *
1004c19800e8SDoug Rabson * @return Return an error code or 0.
1005c19800e8SDoug Rabson *
1006c19800e8SDoug Rabson * @ingroup krb5_address
1007c19800e8SDoug Rabson */
1008c19800e8SDoug Rabson
1009ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_h_addr2sockaddr(krb5_context context,int af,const char * addr,struct sockaddr * sa,krb5_socklen_t * sa_size,int port)1010adb0ddaeSAssar Westerlund krb5_h_addr2sockaddr (krb5_context context,
1011adb0ddaeSAssar Westerlund int af,
10128373020dSJacques Vidrine const char *addr, struct sockaddr *sa,
10138373020dSJacques Vidrine krb5_socklen_t *sa_size,
1014b528cefcSMark Murray int port)
1015b528cefcSMark Murray {
1016b528cefcSMark Murray struct addr_operations *a = find_af(af);
1017adb0ddaeSAssar Westerlund if (a == NULL) {
1018ae771770SStanislav Sedov krb5_set_error_message (context, KRB5_PROG_ATYPE_NOSUPP,
1019ae771770SStanislav Sedov "Address family %d not supported", af);
1020b528cefcSMark Murray return KRB5_PROG_ATYPE_NOSUPP;
1021adb0ddaeSAssar Westerlund }
1022b528cefcSMark Murray (*a->h_addr2sockaddr)(addr, sa, sa_size, port);
1023b528cefcSMark Murray return 0;
1024b528cefcSMark Murray }
1025b528cefcSMark Murray
1026c19800e8SDoug Rabson /**
1027c19800e8SDoug Rabson * krb5_h_addr2addr works like krb5_h_addr2sockaddr with the exception
1028c19800e8SDoug Rabson * that it operates on a krb5_address instead of a struct sockaddr.
1029c19800e8SDoug Rabson *
1030c19800e8SDoug Rabson * @param context a Keberos context
1031c19800e8SDoug Rabson * @param af address family
1032c19800e8SDoug Rabson * @param haddr host address from struct hostent.
1033c19800e8SDoug Rabson * @param addr returned krb5_address.
1034c19800e8SDoug Rabson *
1035c19800e8SDoug Rabson * @return Return an error code or 0.
1036c19800e8SDoug Rabson *
1037c19800e8SDoug Rabson * @ingroup krb5_address
1038c19800e8SDoug Rabson */
1039c19800e8SDoug Rabson
1040ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_h_addr2addr(krb5_context context,int af,const char * haddr,krb5_address * addr)1041adb0ddaeSAssar Westerlund krb5_h_addr2addr (krb5_context context,
1042adb0ddaeSAssar Westerlund int af,
1043b528cefcSMark Murray const char *haddr, krb5_address *addr)
1044b528cefcSMark Murray {
1045b528cefcSMark Murray struct addr_operations *a = find_af(af);
1046adb0ddaeSAssar Westerlund if (a == NULL) {
1047ae771770SStanislav Sedov krb5_set_error_message (context, KRB5_PROG_ATYPE_NOSUPP,
1048ae771770SStanislav Sedov N_("Address family %d not supported", ""), af);
1049b528cefcSMark Murray return KRB5_PROG_ATYPE_NOSUPP;
1050adb0ddaeSAssar Westerlund }
1051b528cefcSMark Murray return (*a->h_addr2addr)(haddr, addr);
1052b528cefcSMark Murray }
1053b528cefcSMark Murray
1054c19800e8SDoug Rabson /**
1055c19800e8SDoug Rabson * krb5_anyaddr fills in a "struct sockaddr sa" that can be used to
1056c19800e8SDoug Rabson * bind(2) to. The argument sa_size should initially contain the size
1057c19800e8SDoug Rabson * of the sa, and after the call, it will contain the actual length
1058c19800e8SDoug Rabson * of the address.
1059c19800e8SDoug Rabson *
1060c19800e8SDoug Rabson * @param context a Keberos context
1061c19800e8SDoug Rabson * @param af address family
1062c19800e8SDoug Rabson * @param sa sockaddr
1063c19800e8SDoug Rabson * @param sa_size lenght of sa.
1064c19800e8SDoug Rabson * @param port for to fill into sa.
1065c19800e8SDoug Rabson *
1066c19800e8SDoug Rabson * @return Return an error code or 0.
1067c19800e8SDoug Rabson *
1068c19800e8SDoug Rabson * @ingroup krb5_address
1069c19800e8SDoug Rabson */
1070c19800e8SDoug Rabson
1071ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_anyaddr(krb5_context context,int af,struct sockaddr * sa,krb5_socklen_t * sa_size,int port)1072adb0ddaeSAssar Westerlund krb5_anyaddr (krb5_context context,
1073adb0ddaeSAssar Westerlund int af,
1074b528cefcSMark Murray struct sockaddr *sa,
10758373020dSJacques Vidrine krb5_socklen_t *sa_size,
1076b528cefcSMark Murray int port)
1077b528cefcSMark Murray {
1078b528cefcSMark Murray struct addr_operations *a = find_af (af);
1079b528cefcSMark Murray
1080adb0ddaeSAssar Westerlund if (a == NULL) {
1081ae771770SStanislav Sedov krb5_set_error_message (context, KRB5_PROG_ATYPE_NOSUPP,
1082ae771770SStanislav Sedov N_("Address family %d not supported", ""), af);
1083b528cefcSMark Murray return KRB5_PROG_ATYPE_NOSUPP;
1084adb0ddaeSAssar Westerlund }
1085b528cefcSMark Murray
1086b528cefcSMark Murray (*a->anyaddr)(sa, sa_size, port);
1087b528cefcSMark Murray return 0;
1088b528cefcSMark Murray }
1089b528cefcSMark Murray
1090c19800e8SDoug Rabson /**
1091c19800e8SDoug Rabson * krb5_print_address prints the address in addr to the string string
1092c19800e8SDoug Rabson * that have the length len. If ret_len is not NULL, it will be filled
1093c19800e8SDoug Rabson * with the length of the string if size were unlimited (not including
1094c19800e8SDoug Rabson * the final NUL) .
1095c19800e8SDoug Rabson *
1096c19800e8SDoug Rabson * @param addr address to be printed
1097c19800e8SDoug Rabson * @param str pointer string to print the address into
1098c19800e8SDoug Rabson * @param len length that will fit into area pointed to by "str".
1099c19800e8SDoug Rabson * @param ret_len return length the str.
1100c19800e8SDoug Rabson *
1101c19800e8SDoug Rabson * @return Return an error code or 0.
1102c19800e8SDoug Rabson *
1103c19800e8SDoug Rabson * @ingroup krb5_address
1104c19800e8SDoug Rabson */
1105c19800e8SDoug Rabson
1106ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_print_address(const krb5_address * addr,char * str,size_t len,size_t * ret_len)1107b528cefcSMark Murray krb5_print_address (const krb5_address *addr,
1108b528cefcSMark Murray char *str, size_t len, size_t *ret_len)
1109b528cefcSMark Murray {
1110b528cefcSMark Murray struct addr_operations *a = find_atype(addr->addr_type);
1111c19800e8SDoug Rabson int ret;
1112b528cefcSMark Murray
1113bbd80c28SJacques Vidrine if (a == NULL || a->print_addr == NULL) {
1114b528cefcSMark Murray char *s;
11154137ff4cSJacques Vidrine int l;
1116ae771770SStanislav Sedov size_t i;
11174137ff4cSJacques Vidrine
1118b528cefcSMark Murray s = str;
1119b528cefcSMark Murray l = snprintf(s, len, "TYPE_%d:", addr->addr_type);
1120ae771770SStanislav Sedov if (l < 0 || (size_t)l >= len)
11214137ff4cSJacques Vidrine return EINVAL;
1122b528cefcSMark Murray s += l;
11234137ff4cSJacques Vidrine len -= l;
1124b528cefcSMark Murray for(i = 0; i < addr->address.length; i++) {
1125b528cefcSMark Murray l = snprintf(s, len, "%02x", ((char*)addr->address.data)[i]);
1126ae771770SStanislav Sedov if (l < 0 || (size_t)l >= len)
11274137ff4cSJacques Vidrine return EINVAL;
1128b528cefcSMark Murray len -= l;
1129b528cefcSMark Murray s += l;
1130b528cefcSMark Murray }
11318373020dSJacques Vidrine if(ret_len != NULL)
1132b528cefcSMark Murray *ret_len = s - str;
1133b528cefcSMark Murray return 0;
1134b528cefcSMark Murray }
11358373020dSJacques Vidrine ret = (*a->print_addr)(addr, str, len);
1136c19800e8SDoug Rabson if (ret < 0)
1137c19800e8SDoug Rabson return EINVAL;
11388373020dSJacques Vidrine if(ret_len != NULL)
11398373020dSJacques Vidrine *ret_len = ret;
1140b528cefcSMark Murray return 0;
1141b528cefcSMark Murray }
1142b528cefcSMark Murray
1143c19800e8SDoug Rabson /**
1144c19800e8SDoug Rabson * krb5_parse_address returns the resolved hostname in string to the
1145c19800e8SDoug Rabson * krb5_addresses addresses .
1146c19800e8SDoug Rabson *
1147c19800e8SDoug Rabson * @param context a Keberos context
1148c19800e8SDoug Rabson * @param string
1149c19800e8SDoug Rabson * @param addresses
1150c19800e8SDoug Rabson *
1151c19800e8SDoug Rabson * @return Return an error code or 0.
1152c19800e8SDoug Rabson *
1153c19800e8SDoug Rabson * @ingroup krb5_address
1154c19800e8SDoug Rabson */
1155c19800e8SDoug Rabson
1156ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_parse_address(krb5_context context,const char * string,krb5_addresses * addresses)1157b528cefcSMark Murray krb5_parse_address(krb5_context context,
1158b528cefcSMark Murray const char *string,
1159b528cefcSMark Murray krb5_addresses *addresses)
1160b528cefcSMark Murray {
1161b528cefcSMark Murray int i, n;
1162b528cefcSMark Murray struct addrinfo *ai, *a;
1163b528cefcSMark Murray int error;
1164adb0ddaeSAssar Westerlund int save_errno;
1165b528cefcSMark Murray
1166c19800e8SDoug Rabson addresses->len = 0;
1167c19800e8SDoug Rabson addresses->val = NULL;
1168c19800e8SDoug Rabson
1169b528cefcSMark Murray for(i = 0; i < num_addrs; i++) {
1170b528cefcSMark Murray if(at[i].parse_addr) {
11718373020dSJacques Vidrine krb5_address addr;
11728373020dSJacques Vidrine if((*at[i].parse_addr)(context, string, &addr) == 0) {
1173b528cefcSMark Murray ALLOC_SEQ(addresses, 1);
1174c19800e8SDoug Rabson if (addresses->val == NULL) {
1175ae771770SStanislav Sedov krb5_set_error_message(context, ENOMEM,
1176ae771770SStanislav Sedov N_("malloc: out of memory", ""));
1177c19800e8SDoug Rabson return ENOMEM;
1178c19800e8SDoug Rabson }
11798373020dSJacques Vidrine addresses->val[0] = addr;
1180b528cefcSMark Murray return 0;
1181b528cefcSMark Murray }
1182b528cefcSMark Murray }
1183b528cefcSMark Murray }
1184b528cefcSMark Murray
1185b528cefcSMark Murray error = getaddrinfo (string, NULL, NULL, &ai);
1186adb0ddaeSAssar Westerlund if (error) {
1187ae771770SStanislav Sedov krb5_error_code ret2;
1188adb0ddaeSAssar Westerlund save_errno = errno;
1189ae771770SStanislav Sedov ret2 = krb5_eai_to_heim_errno(error, save_errno);
1190ae771770SStanislav Sedov krb5_set_error_message (context, ret2, "%s: %s",
1191ae771770SStanislav Sedov string, gai_strerror(error));
1192ae771770SStanislav Sedov return ret2;
1193adb0ddaeSAssar Westerlund }
1194b528cefcSMark Murray
1195b528cefcSMark Murray n = 0;
1196b528cefcSMark Murray for (a = ai; a != NULL; a = a->ai_next)
1197b528cefcSMark Murray ++n;
1198b528cefcSMark Murray
1199b528cefcSMark Murray ALLOC_SEQ(addresses, n);
1200c19800e8SDoug Rabson if (addresses->val == NULL) {
1201ae771770SStanislav Sedov krb5_set_error_message(context, ENOMEM,
1202ae771770SStanislav Sedov N_("malloc: out of memory", ""));
1203c19800e8SDoug Rabson freeaddrinfo(ai);
1204c19800e8SDoug Rabson return ENOMEM;
1205c19800e8SDoug Rabson }
1206b528cefcSMark Murray
1207c19800e8SDoug Rabson addresses->len = 0;
12088373020dSJacques Vidrine for (a = ai, i = 0; a != NULL; a = a->ai_next) {
1209c19800e8SDoug Rabson if (krb5_sockaddr2address (context, ai->ai_addr, &addresses->val[i]))
1210c19800e8SDoug Rabson continue;
1211ae771770SStanislav Sedov if(krb5_address_search(context, &addresses->val[i], addresses)) {
1212ae771770SStanislav Sedov krb5_free_address(context, &addresses->val[i]);
1213c19800e8SDoug Rabson continue;
1214ae771770SStanislav Sedov }
12158373020dSJacques Vidrine i++;
1216ae771770SStanislav Sedov addresses->len = i;
1217b528cefcSMark Murray }
1218b528cefcSMark Murray freeaddrinfo (ai);
1219b528cefcSMark Murray return 0;
1220b528cefcSMark Murray }
12214137ff4cSJacques Vidrine
1222c19800e8SDoug Rabson /**
1223c19800e8SDoug Rabson * krb5_address_order compares the addresses addr1 and addr2 so that
1224c19800e8SDoug Rabson * it can be used for sorting addresses. If the addresses are the same
1225c19800e8SDoug Rabson * address krb5_address_order will return 0. Behavies like memcmp(2).
1226c19800e8SDoug Rabson *
1227c19800e8SDoug Rabson * @param context a Keberos context
1228c19800e8SDoug Rabson * @param addr1 krb5_address to compare
1229c19800e8SDoug Rabson * @param addr2 krb5_address to compare
1230c19800e8SDoug Rabson *
1231c19800e8SDoug Rabson * @return < 0 if address addr1 in "less" then addr2. 0 if addr1 and
1232c19800e8SDoug Rabson * addr2 is the same address, > 0 if addr2 is "less" then addr1.
1233c19800e8SDoug Rabson *
1234c19800e8SDoug Rabson * @ingroup krb5_address
1235c19800e8SDoug Rabson */
1236c19800e8SDoug Rabson
1237ae771770SStanislav Sedov KRB5_LIB_FUNCTION int KRB5_LIB_CALL
krb5_address_order(krb5_context context,const krb5_address * addr1,const krb5_address * addr2)12384137ff4cSJacques Vidrine krb5_address_order(krb5_context context,
12394137ff4cSJacques Vidrine const krb5_address *addr1,
12404137ff4cSJacques Vidrine const krb5_address *addr2)
12414137ff4cSJacques Vidrine {
12424137ff4cSJacques Vidrine /* this sucks; what if both addresses have order functions, which
12434137ff4cSJacques Vidrine should we call? this works for now, though */
12444137ff4cSJacques Vidrine struct addr_operations *a;
12454137ff4cSJacques Vidrine a = find_atype(addr1->addr_type);
12464137ff4cSJacques Vidrine if(a == NULL) {
1247ae771770SStanislav Sedov krb5_set_error_message (context, KRB5_PROG_ATYPE_NOSUPP,
1248ae771770SStanislav Sedov N_("Address family %d not supported", ""),
12494137ff4cSJacques Vidrine addr1->addr_type);
12504137ff4cSJacques Vidrine return KRB5_PROG_ATYPE_NOSUPP;
12514137ff4cSJacques Vidrine }
12524137ff4cSJacques Vidrine if(a->order_addr != NULL)
12534137ff4cSJacques Vidrine return (*a->order_addr)(context, addr1, addr2);
12544137ff4cSJacques Vidrine a = find_atype(addr2->addr_type);
12554137ff4cSJacques Vidrine if(a == NULL) {
1256ae771770SStanislav Sedov krb5_set_error_message (context, KRB5_PROG_ATYPE_NOSUPP,
1257ae771770SStanislav Sedov N_("Address family %d not supported", ""),
12584137ff4cSJacques Vidrine addr2->addr_type);
12594137ff4cSJacques Vidrine return KRB5_PROG_ATYPE_NOSUPP;
12604137ff4cSJacques Vidrine }
12614137ff4cSJacques Vidrine if(a->order_addr != NULL)
12624137ff4cSJacques Vidrine return (*a->order_addr)(context, addr1, addr2);
12634137ff4cSJacques Vidrine
12644137ff4cSJacques Vidrine if(addr1->addr_type != addr2->addr_type)
12654137ff4cSJacques Vidrine return addr1->addr_type - addr2->addr_type;
12664137ff4cSJacques Vidrine if(addr1->address.length != addr2->address.length)
12674137ff4cSJacques Vidrine return addr1->address.length - addr2->address.length;
12684137ff4cSJacques Vidrine return memcmp (addr1->address.data,
12694137ff4cSJacques Vidrine addr2->address.data,
12704137ff4cSJacques Vidrine addr1->address.length);
12714137ff4cSJacques Vidrine }
12724137ff4cSJacques Vidrine
1273c19800e8SDoug Rabson /**
1274c19800e8SDoug Rabson * krb5_address_compare compares the addresses addr1 and addr2.
1275c19800e8SDoug Rabson * Returns TRUE if the two addresses are the same.
1276c19800e8SDoug Rabson *
1277c19800e8SDoug Rabson * @param context a Keberos context
1278c19800e8SDoug Rabson * @param addr1 address to compare
1279c19800e8SDoug Rabson * @param addr2 address to compare
1280c19800e8SDoug Rabson *
1281c19800e8SDoug Rabson * @return Return an TRUE is the address are the same FALSE if not
1282c19800e8SDoug Rabson *
1283c19800e8SDoug Rabson * @ingroup krb5_address
1284c19800e8SDoug Rabson */
1285c19800e8SDoug Rabson
1286ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_boolean KRB5_LIB_CALL
krb5_address_compare(krb5_context context,const krb5_address * addr1,const krb5_address * addr2)12874137ff4cSJacques Vidrine krb5_address_compare(krb5_context context,
12884137ff4cSJacques Vidrine const krb5_address *addr1,
12894137ff4cSJacques Vidrine const krb5_address *addr2)
12904137ff4cSJacques Vidrine {
12914137ff4cSJacques Vidrine return krb5_address_order (context, addr1, addr2) == 0;
12924137ff4cSJacques Vidrine }
12934137ff4cSJacques Vidrine
1294c19800e8SDoug Rabson /**
1295c19800e8SDoug Rabson * krb5_address_search checks if the address addr is a member of the
1296c19800e8SDoug Rabson * address set list addrlist .
1297c19800e8SDoug Rabson *
1298c19800e8SDoug Rabson * @param context a Keberos context.
1299c19800e8SDoug Rabson * @param addr address to search for.
1300c19800e8SDoug Rabson * @param addrlist list of addresses to look in for addr.
1301c19800e8SDoug Rabson *
1302c19800e8SDoug Rabson * @return Return an error code or 0.
1303c19800e8SDoug Rabson *
1304c19800e8SDoug Rabson * @ingroup krb5_address
1305c19800e8SDoug Rabson */
1306c19800e8SDoug Rabson
1307ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_boolean KRB5_LIB_CALL
krb5_address_search(krb5_context context,const krb5_address * addr,const krb5_addresses * addrlist)13084137ff4cSJacques Vidrine krb5_address_search(krb5_context context,
13094137ff4cSJacques Vidrine const krb5_address *addr,
13104137ff4cSJacques Vidrine const krb5_addresses *addrlist)
13114137ff4cSJacques Vidrine {
1312ae771770SStanislav Sedov size_t i;
13134137ff4cSJacques Vidrine
13144137ff4cSJacques Vidrine for (i = 0; i < addrlist->len; ++i)
13154137ff4cSJacques Vidrine if (krb5_address_compare (context, addr, &addrlist->val[i]))
13164137ff4cSJacques Vidrine return TRUE;
13174137ff4cSJacques Vidrine return FALSE;
13184137ff4cSJacques Vidrine }
13194137ff4cSJacques Vidrine
1320c19800e8SDoug Rabson /**
1321c19800e8SDoug Rabson * krb5_free_address frees the data stored in the address that is
1322c19800e8SDoug Rabson * alloced with any of the krb5_address functions.
1323c19800e8SDoug Rabson *
1324c19800e8SDoug Rabson * @param context a Keberos context
1325c19800e8SDoug Rabson * @param address addresss to be freed.
1326c19800e8SDoug Rabson *
1327c19800e8SDoug Rabson * @return Return an error code or 0.
1328c19800e8SDoug Rabson *
1329c19800e8SDoug Rabson * @ingroup krb5_address
1330c19800e8SDoug Rabson */
1331c19800e8SDoug Rabson
1332ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_free_address(krb5_context context,krb5_address * address)13334137ff4cSJacques Vidrine krb5_free_address(krb5_context context,
13344137ff4cSJacques Vidrine krb5_address *address)
13354137ff4cSJacques Vidrine {
1336c19800e8SDoug Rabson struct addr_operations *a = find_atype (address->addr_type);
13374137ff4cSJacques Vidrine if(a != NULL && a->free_addr != NULL)
13384137ff4cSJacques Vidrine return (*a->free_addr)(context, address);
13394137ff4cSJacques Vidrine krb5_data_free (&address->address);
1340c19800e8SDoug Rabson memset(address, 0, sizeof(*address));
13414137ff4cSJacques Vidrine return 0;
13424137ff4cSJacques Vidrine }
13434137ff4cSJacques Vidrine
1344c19800e8SDoug Rabson /**
1345c19800e8SDoug Rabson * krb5_free_addresses frees the data stored in the address that is
1346c19800e8SDoug Rabson * alloced with any of the krb5_address functions.
1347c19800e8SDoug Rabson *
1348c19800e8SDoug Rabson * @param context a Keberos context
1349c19800e8SDoug Rabson * @param addresses addressses to be freed.
1350c19800e8SDoug Rabson *
1351c19800e8SDoug Rabson * @return Return an error code or 0.
1352c19800e8SDoug Rabson *
1353c19800e8SDoug Rabson * @ingroup krb5_address
1354c19800e8SDoug Rabson */
1355c19800e8SDoug Rabson
1356ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_free_addresses(krb5_context context,krb5_addresses * addresses)13574137ff4cSJacques Vidrine krb5_free_addresses(krb5_context context,
13584137ff4cSJacques Vidrine krb5_addresses *addresses)
13594137ff4cSJacques Vidrine {
1360ae771770SStanislav Sedov size_t i;
13614137ff4cSJacques Vidrine for(i = 0; i < addresses->len; i++)
13624137ff4cSJacques Vidrine krb5_free_address(context, &addresses->val[i]);
13634137ff4cSJacques Vidrine free(addresses->val);
1364c19800e8SDoug Rabson addresses->len = 0;
1365c19800e8SDoug Rabson addresses->val = NULL;
13664137ff4cSJacques Vidrine return 0;
13674137ff4cSJacques Vidrine }
13684137ff4cSJacques Vidrine
1369c19800e8SDoug Rabson /**
1370c19800e8SDoug Rabson * krb5_copy_address copies the content of address
1371c19800e8SDoug Rabson * inaddr to outaddr.
1372c19800e8SDoug Rabson *
1373c19800e8SDoug Rabson * @param context a Keberos context
1374c19800e8SDoug Rabson * @param inaddr pointer to source address
1375c19800e8SDoug Rabson * @param outaddr pointer to destination address
1376c19800e8SDoug Rabson *
1377c19800e8SDoug Rabson * @return Return an error code or 0.
1378c19800e8SDoug Rabson *
1379c19800e8SDoug Rabson * @ingroup krb5_address
1380c19800e8SDoug Rabson */
1381c19800e8SDoug Rabson
1382ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_copy_address(krb5_context context,const krb5_address * inaddr,krb5_address * outaddr)13834137ff4cSJacques Vidrine krb5_copy_address(krb5_context context,
13844137ff4cSJacques Vidrine const krb5_address *inaddr,
13854137ff4cSJacques Vidrine krb5_address *outaddr)
13864137ff4cSJacques Vidrine {
13874137ff4cSJacques Vidrine struct addr_operations *a = find_af (inaddr->addr_type);
13884137ff4cSJacques Vidrine if(a != NULL && a->copy_addr != NULL)
13894137ff4cSJacques Vidrine return (*a->copy_addr)(context, inaddr, outaddr);
13904137ff4cSJacques Vidrine return copy_HostAddress(inaddr, outaddr);
13914137ff4cSJacques Vidrine }
13924137ff4cSJacques Vidrine
1393c19800e8SDoug Rabson /**
1394c19800e8SDoug Rabson * krb5_copy_addresses copies the content of addresses
1395c19800e8SDoug Rabson * inaddr to outaddr.
1396c19800e8SDoug Rabson *
1397c19800e8SDoug Rabson * @param context a Keberos context
1398c19800e8SDoug Rabson * @param inaddr pointer to source addresses
1399c19800e8SDoug Rabson * @param outaddr pointer to destination addresses
1400c19800e8SDoug Rabson *
1401c19800e8SDoug Rabson * @return Return an error code or 0.
1402c19800e8SDoug Rabson *
1403c19800e8SDoug Rabson * @ingroup krb5_address
1404c19800e8SDoug Rabson */
1405c19800e8SDoug Rabson
1406ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_copy_addresses(krb5_context context,const krb5_addresses * inaddr,krb5_addresses * outaddr)14074137ff4cSJacques Vidrine krb5_copy_addresses(krb5_context context,
14084137ff4cSJacques Vidrine const krb5_addresses *inaddr,
14094137ff4cSJacques Vidrine krb5_addresses *outaddr)
14104137ff4cSJacques Vidrine {
1411ae771770SStanislav Sedov size_t i;
14124137ff4cSJacques Vidrine ALLOC_SEQ(outaddr, inaddr->len);
14134137ff4cSJacques Vidrine if(inaddr->len > 0 && outaddr->val == NULL)
14144137ff4cSJacques Vidrine return ENOMEM;
14154137ff4cSJacques Vidrine for(i = 0; i < inaddr->len; i++)
14164137ff4cSJacques Vidrine krb5_copy_address(context, &inaddr->val[i], &outaddr->val[i]);
14174137ff4cSJacques Vidrine return 0;
14184137ff4cSJacques Vidrine }
14194137ff4cSJacques Vidrine
1420c19800e8SDoug Rabson /**
1421c19800e8SDoug Rabson * krb5_append_addresses adds the set of addresses in source to
1422c19800e8SDoug Rabson * dest. While copying the addresses, duplicates are also sorted out.
1423c19800e8SDoug Rabson *
1424c19800e8SDoug Rabson * @param context a Keberos context
1425c19800e8SDoug Rabson * @param dest destination of copy operation
1426c19800e8SDoug Rabson * @param source adresses that are going to be added to dest
1427c19800e8SDoug Rabson *
1428c19800e8SDoug Rabson * @return Return an error code or 0.
1429c19800e8SDoug Rabson *
1430c19800e8SDoug Rabson * @ingroup krb5_address
1431c19800e8SDoug Rabson */
1432c19800e8SDoug Rabson
1433ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_append_addresses(krb5_context context,krb5_addresses * dest,const krb5_addresses * source)14344137ff4cSJacques Vidrine krb5_append_addresses(krb5_context context,
14354137ff4cSJacques Vidrine krb5_addresses *dest,
14364137ff4cSJacques Vidrine const krb5_addresses *source)
14374137ff4cSJacques Vidrine {
14384137ff4cSJacques Vidrine krb5_address *tmp;
14394137ff4cSJacques Vidrine krb5_error_code ret;
1440ae771770SStanislav Sedov size_t i;
14414137ff4cSJacques Vidrine if(source->len > 0) {
14424137ff4cSJacques Vidrine tmp = realloc(dest->val, (dest->len + source->len) * sizeof(*tmp));
14434137ff4cSJacques Vidrine if(tmp == NULL) {
1444ae771770SStanislav Sedov krb5_set_error_message (context, ENOMEM,
1445ae771770SStanislav Sedov N_("malloc: out of memory", ""));
14464137ff4cSJacques Vidrine return ENOMEM;
14474137ff4cSJacques Vidrine }
14484137ff4cSJacques Vidrine dest->val = tmp;
14494137ff4cSJacques Vidrine for(i = 0; i < source->len; i++) {
14504137ff4cSJacques Vidrine /* skip duplicates */
14514137ff4cSJacques Vidrine if(krb5_address_search(context, &source->val[i], dest))
14524137ff4cSJacques Vidrine continue;
14534137ff4cSJacques Vidrine ret = krb5_copy_address(context,
14544137ff4cSJacques Vidrine &source->val[i],
14554137ff4cSJacques Vidrine &dest->val[dest->len]);
14564137ff4cSJacques Vidrine if(ret)
14574137ff4cSJacques Vidrine return ret;
14584137ff4cSJacques Vidrine dest->len++;
14594137ff4cSJacques Vidrine }
14604137ff4cSJacques Vidrine }
14614137ff4cSJacques Vidrine return 0;
14624137ff4cSJacques Vidrine }
14634137ff4cSJacques Vidrine
1464c19800e8SDoug Rabson /**
14654137ff4cSJacques Vidrine * Create an address of type KRB5_ADDRESS_ADDRPORT from (addr, port)
1466c19800e8SDoug Rabson *
1467c19800e8SDoug Rabson * @param context a Keberos context
1468c19800e8SDoug Rabson * @param res built address from addr/port
1469c19800e8SDoug Rabson * @param addr address to use
1470c19800e8SDoug Rabson * @param port port to use
1471c19800e8SDoug Rabson *
1472c19800e8SDoug Rabson * @return Return an error code or 0.
1473c19800e8SDoug Rabson *
1474c19800e8SDoug Rabson * @ingroup krb5_address
14754137ff4cSJacques Vidrine */
14764137ff4cSJacques Vidrine
1477ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_make_addrport(krb5_context context,krb5_address ** res,const krb5_address * addr,int16_t port)14784137ff4cSJacques Vidrine krb5_make_addrport (krb5_context context,
14794137ff4cSJacques Vidrine krb5_address **res, const krb5_address *addr, int16_t port)
14804137ff4cSJacques Vidrine {
14814137ff4cSJacques Vidrine krb5_error_code ret;
14824137ff4cSJacques Vidrine size_t len = addr->address.length + 2 + 4 * 4;
14834137ff4cSJacques Vidrine u_char *p;
14844137ff4cSJacques Vidrine
14854137ff4cSJacques Vidrine *res = malloc (sizeof(**res));
14864137ff4cSJacques Vidrine if (*res == NULL) {
1487ae771770SStanislav Sedov krb5_set_error_message (context, ENOMEM,
1488ae771770SStanislav Sedov N_("malloc: out of memory", ""));
14894137ff4cSJacques Vidrine return ENOMEM;
14904137ff4cSJacques Vidrine }
14914137ff4cSJacques Vidrine (*res)->addr_type = KRB5_ADDRESS_ADDRPORT;
14924137ff4cSJacques Vidrine ret = krb5_data_alloc (&(*res)->address, len);
14934137ff4cSJacques Vidrine if (ret) {
1494ae771770SStanislav Sedov krb5_set_error_message (context, ret,
1495ae771770SStanislav Sedov N_("malloc: out of memory", ""));
14964137ff4cSJacques Vidrine free (*res);
1497c19800e8SDoug Rabson *res = NULL;
14984137ff4cSJacques Vidrine return ret;
14994137ff4cSJacques Vidrine }
15004137ff4cSJacques Vidrine p = (*res)->address.data;
15014137ff4cSJacques Vidrine *p++ = 0;
15024137ff4cSJacques Vidrine *p++ = 0;
15034137ff4cSJacques Vidrine *p++ = (addr->addr_type ) & 0xFF;
15044137ff4cSJacques Vidrine *p++ = (addr->addr_type >> 8) & 0xFF;
15054137ff4cSJacques Vidrine
15064137ff4cSJacques Vidrine *p++ = (addr->address.length ) & 0xFF;
15074137ff4cSJacques Vidrine *p++ = (addr->address.length >> 8) & 0xFF;
15084137ff4cSJacques Vidrine *p++ = (addr->address.length >> 16) & 0xFF;
15094137ff4cSJacques Vidrine *p++ = (addr->address.length >> 24) & 0xFF;
15104137ff4cSJacques Vidrine
15114137ff4cSJacques Vidrine memcpy (p, addr->address.data, addr->address.length);
15124137ff4cSJacques Vidrine p += addr->address.length;
15134137ff4cSJacques Vidrine
15144137ff4cSJacques Vidrine *p++ = 0;
15154137ff4cSJacques Vidrine *p++ = 0;
15164137ff4cSJacques Vidrine *p++ = (KRB5_ADDRESS_IPPORT ) & 0xFF;
15174137ff4cSJacques Vidrine *p++ = (KRB5_ADDRESS_IPPORT >> 8) & 0xFF;
15184137ff4cSJacques Vidrine
15194137ff4cSJacques Vidrine *p++ = (2 ) & 0xFF;
15204137ff4cSJacques Vidrine *p++ = (2 >> 8) & 0xFF;
15214137ff4cSJacques Vidrine *p++ = (2 >> 16) & 0xFF;
15224137ff4cSJacques Vidrine *p++ = (2 >> 24) & 0xFF;
15234137ff4cSJacques Vidrine
15244137ff4cSJacques Vidrine memcpy (p, &port, 2);
15254137ff4cSJacques Vidrine
15264137ff4cSJacques Vidrine return 0;
15274137ff4cSJacques Vidrine }
1528c19800e8SDoug Rabson
1529c19800e8SDoug Rabson /**
1530c19800e8SDoug Rabson * Calculate the boundary addresses of `inaddr'/`prefixlen' and store
1531c19800e8SDoug Rabson * them in `low' and `high'.
1532c19800e8SDoug Rabson *
1533c19800e8SDoug Rabson * @param context a Keberos context
1534c19800e8SDoug Rabson * @param inaddr address in prefixlen that the bondery searched
1535c19800e8SDoug Rabson * @param prefixlen width of boundery
1536c19800e8SDoug Rabson * @param low lowest address
1537c19800e8SDoug Rabson * @param high highest address
1538c19800e8SDoug Rabson *
1539c19800e8SDoug Rabson * @return Return an error code or 0.
1540c19800e8SDoug Rabson *
1541c19800e8SDoug Rabson * @ingroup krb5_address
1542c19800e8SDoug Rabson */
1543c19800e8SDoug Rabson
1544ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_address_prefixlen_boundary(krb5_context context,const krb5_address * inaddr,unsigned long prefixlen,krb5_address * low,krb5_address * high)1545c19800e8SDoug Rabson krb5_address_prefixlen_boundary(krb5_context context,
1546c19800e8SDoug Rabson const krb5_address *inaddr,
1547c19800e8SDoug Rabson unsigned long prefixlen,
1548c19800e8SDoug Rabson krb5_address *low,
1549c19800e8SDoug Rabson krb5_address *high)
1550c19800e8SDoug Rabson {
1551c19800e8SDoug Rabson struct addr_operations *a = find_atype (inaddr->addr_type);
1552c19800e8SDoug Rabson if(a != NULL && a->mask_boundary != NULL)
1553c19800e8SDoug Rabson return (*a->mask_boundary)(context, inaddr, prefixlen, low, high);
1554ae771770SStanislav Sedov krb5_set_error_message(context, KRB5_PROG_ATYPE_NOSUPP,
1555ae771770SStanislav Sedov N_("Address family %d doesn't support "
1556ae771770SStanislav Sedov "address mask operation", ""),
1557ae771770SStanislav Sedov inaddr->addr_type);
1558c19800e8SDoug Rabson return KRB5_PROG_ATYPE_NOSUPP;
1559c19800e8SDoug Rabson }
1560