4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright (c) 1999 by Sun Microsystems, Inc.
24 * All rights reserved.
27 #pragma ident "%Z%%M% %I% %E% SMI"
32 #include <sys/types.h>
33 #include <sys/socket.h>
34 #include <sys/sockio.h>
35 #include <arpa/inet.h>
39 #include <nss_dbdefs.h>
40 #include <slp-internal.h>
41 #include <slp_net_utils.h>
43 typedef struct slp_ifinfo
{
44 struct sockaddr_in addr
;
45 struct sockaddr_in netmask
;
46 struct sockaddr_in bc_addr
;
50 typedef struct slp_handle_ifinfo
{
51 slp_ifinfo_t
*all_ifs
;
53 } slp_handle_ifinfo_t
;
56 static SLPError
get_all_interfaces(slp_handle_ifinfo_t
*info
);
59 * Obtains the broadcast addresses for all local interfaces given in
62 * hp IN / OUT holds cached-per-handle if info
63 * given_ifs IN an array of local interfaces
64 * num_givenifs IN number of addresses in given_ifs
65 * bc_addrs OUT an array of broadcast addresses for local interfaces
66 * num_addrs OUT number of addrs returned in bc_addrs
68 * Returns SLP_OK if at least one broadcast address was found; if none
69 * were found, returns err != SLP_OK and *bc_addrs = NULL;
70 * Caller must free *bc_addrs when done.
72 SLPError
slp_broadcast_addrs(slp_handle_impl_t
*hp
, struct in_addr
*given_ifs
,
74 struct sockaddr_in
*bc_addrs
[],
79 slp_ifinfo_t
*all_ifs
;
80 slp_handle_ifinfo_t
*ifinfo
;
84 if (!(ifinfo
= malloc(sizeof (*ifinfo
)))) {
85 slp_err(LOG_CRIT
, 0, "slp_broadcast_addrs",
87 return (SLP_MEMORY_ALLOC_FAILED
);
89 if ((err
= get_all_interfaces(ifinfo
)) != SLP_OK
) {
95 all_ifs
= ((slp_handle_ifinfo_t
*)hp
->ifinfo
)->all_ifs
;
96 numifs
= ((slp_handle_ifinfo_t
*)hp
->ifinfo
)->numifs
;
98 /* allocate memory for reply */
99 if (!(*bc_addrs
= calloc(num_givenifs
, sizeof (**bc_addrs
)))) {
100 slp_err(LOG_CRIT
, 0, "slp_broadcast_addrs", "out of memory");
101 return (SLP_MEMORY_ALLOC_FAILED
);
104 /* copy bc addrs for all desired interfaces which are bc-enabled */
106 for (j
= 0; j
< num_givenifs
; j
++) {
107 for (i
= 0; i
< numifs
; i
++) {
109 if (!(all_ifs
[i
].flags
& IFF_BROADCAST
)) {
113 if (memcmp(&(all_ifs
[i
].addr
.sin_addr
.s_addr
),
114 &(given_ifs
[j
].s_addr
),
115 sizeof (given_ifs
[j
].s_addr
)) == 0 &&
116 all_ifs
[i
].bc_addr
.sin_addr
.s_addr
!= 0) {
118 /* got it, so copy it to bc_addrs */
120 *bc_addrs
+ *num_addrs
,
121 &(all_ifs
[i
].bc_addr
),
122 sizeof (all_ifs
[i
].bc_addr
));
130 if (*num_addrs
== 0) {
134 return (SLP_INTERNAL_SYSTEM_ERROR
);
140 * Returns true if addr is on a subnet local to the local host.
142 SLPBoolean
slp_on_subnet(slp_handle_impl_t
*hp
, struct in_addr addr
) {
144 struct in_addr netmask
, net_addr
, masked_addr
;
145 slp_ifinfo_t
*all_ifs
;
146 slp_handle_ifinfo_t
*ifinfo
;
150 if (!(ifinfo
= malloc(sizeof (*ifinfo
)))) {
151 slp_err(LOG_CRIT
, 0, "slp_broadcast_addrs",
155 if (get_all_interfaces(ifinfo
) != SLP_OK
) {
161 all_ifs
= ((slp_handle_ifinfo_t
*)hp
->ifinfo
)->all_ifs
;
162 numifs
= ((slp_handle_ifinfo_t
*)hp
->ifinfo
)->numifs
;
164 for (i
= 0; i
< numifs
; i
++) {
166 netmask
.s_addr
= all_ifs
[i
].netmask
.sin_addr
.s_addr
;
167 /* get network address */
169 all_ifs
[i
].addr
.sin_addr
.s_addr
& netmask
.s_addr
;
170 /* apply netmask to input addr */
171 masked_addr
.s_addr
= addr
.s_addr
& netmask
.s_addr
;
173 if (memcmp(&(masked_addr
.s_addr
), &(net_addr
.s_addr
),
174 sizeof (net_addr
.s_addr
)) == 0) {
183 * Returns true if any local interface if configured with addr.
185 SLPBoolean
slp_on_localhost(slp_handle_impl_t
*hp
, struct in_addr addr
) {
187 slp_ifinfo_t
*all_ifs
;
188 slp_handle_ifinfo_t
*ifinfo
;
192 if (!(ifinfo
= malloc(sizeof (*ifinfo
)))) {
193 slp_err(LOG_CRIT
, 0, "slp_broadcast_addrs",
197 if (get_all_interfaces(ifinfo
) != SLP_OK
) {
203 all_ifs
= ((slp_handle_ifinfo_t
*)hp
->ifinfo
)->all_ifs
;
204 numifs
= ((slp_handle_ifinfo_t
*)hp
->ifinfo
)->numifs
;
206 for (i
= 0; i
< numifs
; i
++) {
207 if (memcmp(&(addr
.s_addr
), &(all_ifs
[i
].addr
.sin_addr
.s_addr
),
208 sizeof (addr
)) == 0) {
217 void slp_free_ifinfo(void *hi
) {
218 free(((slp_handle_ifinfo_t
*)hi
)->all_ifs
);
224 static SLPError
get_all_interfaces(slp_handle_ifinfo_t
*info
) {
230 struct ifreq
*ifrp
, ifr
;
231 slp_ifinfo_t
*all_ifs
= NULL
;
232 SLPError err
= SLP_OK
;
234 /* create a socket with which to get interface info */
235 if ((s
= socket(AF_INET
, SOCK_DGRAM
, 0)) < 0) {
239 /* how many interfaces are configured? */
240 if (ioctl(s
, SIOCGIFNUM
, (char *)&numifs
) < 0) {
244 /* allocate memory for ifinfo_t array */
245 if (!(all_ifs
= calloc(numifs
, sizeof (*all_ifs
)))) {
246 slp_err(LOG_CRIT
, 0, "get_all_interfaces", "out of memory");
247 err
= SLP_MEMORY_ALLOC_FAILED
;
251 /* allocate memory for interface info */
252 bufsize
= numifs
* sizeof (struct ifreq
);
253 if (!(buf
= malloc(bufsize
))) {
254 slp_err(LOG_CRIT
, 0, "get_all_interfaces", "out of memory");
255 err
= SLP_MEMORY_ALLOC_FAILED
;
260 ifc
.ifc_len
= bufsize
;
262 if (ioctl(s
, SIOCGIFCONF
, (char *)&ifc
) < 0) {
268 for (n
= ifc
.ifc_len
/ sizeof (struct ifreq
); n
> 0; n
--, ifrp
++) {
270 /* ignore if interface is not up */
271 (void) memset((char *)&ifr
, 0, sizeof (ifr
));
272 (void) strncpy(ifr
.ifr_name
, ifrp
->ifr_name
, sizeof (ifr
.ifr_name
));
273 if (ioctl(s
, SIOCGIFFLAGS
, (caddr_t
)&ifr
) < 0) {
276 if (!(ifr
.ifr_flags
& IFF_UP
)) {
280 all_ifs
[i
].flags
= ifr
.ifr_flags
;
282 /* get the interface's address */
283 if (ioctl(s
, SIOCGIFADDR
, (caddr_t
)&ifr
) < 0) {
287 (void) memcpy(&(all_ifs
[i
].addr
), &ifr
.ifr_addr
,
288 sizeof (all_ifs
[i
].addr
));
290 /* get the interface's broadcast address */
291 if (ioctl(s
, SIOCGIFBRDADDR
, (caddr_t
)&ifr
) < 0) {
292 (void) memset(&(all_ifs
[i
].bc_addr
), 0,
293 sizeof (all_ifs
[i
].bc_addr
));
295 (void) memcpy(&(all_ifs
[i
].bc_addr
), &ifr
.ifr_addr
,
296 sizeof (all_ifs
[i
].bc_addr
));
299 /* get the interface's subnet mask */
300 if (ioctl(s
, SIOCGIFNETMASK
, (caddr_t
)&ifr
) < 0) {
301 (void) memset(&(all_ifs
[i
].netmask
), 0,
302 sizeof (all_ifs
[i
].netmask
));
304 (void) memcpy(&(all_ifs
[i
].netmask
), &ifr
.ifr_addr
,
305 sizeof (all_ifs
[i
].netmask
));
311 /* i contains the number we actually got info on */
313 info
->all_ifs
= all_ifs
;
316 err
= SLP_INTERNAL_SYSTEM_ERROR
;
318 info
->all_ifs
= NULL
;
322 if (s
) (void) close(s
);
329 * Converts a SLPSrvURL to a network address. 'sa' must have been
330 * allocated by the caller.
331 * Assumes that addresses are given as specified in the protocol spec,
332 * i.e. as IP addresses and not host names.
334 SLPError
slp_surl2sin(SLPSrvURL
*surl
, struct sockaddr_in
*sa
) {
335 struct sockaddr_in
*sin
= (struct sockaddr_in
*)sa
;
337 if (slp_pton(surl
->s_pcHost
, &(sin
->sin_addr
)) < 1)
338 return (SLP_PARAMETER_BAD
);
339 sin
->sin_family
= AF_INET
;
341 sin
->sin_port
= htons(
342 (surl
->s_iPort
== 0 ? SLP_PORT
: surl
->s_iPort
));
348 * A wrapper around gethostbyaddr_r. This checks the useGetXXXbyYYY
349 * property first to determine whether a name service lookup should
350 * be used. If not, it converts the address in 'addr' to a string
351 * and just returns that.
353 * The core functionality herein will be replaced with getaddrinfo
354 * when it becomes available.
357 char *slp_gethostbyaddr(const char *addr
, int size
) {
358 char storebuf
[SLP_NETDB_BUFSZ
], addrbuf
[INET6_ADDRSTRLEN
], *cname
;
359 const char *use_xbyy
;
360 struct hostent namestruct
[1], *name
;
363 /* default: copy in the IP address */
364 cname
= slp_ntop(addrbuf
, INET6_ADDRSTRLEN
, (const void *) addr
);
365 if (cname
&& !(cname
= strdup(cname
))) {
366 slp_err(LOG_CRIT
, 0, "slp_gethostbyaddr", "out of memory");
370 if ((use_xbyy
= SLPGetProperty(SLP_CONFIG_USEGETXXXBYYYY
)) != NULL
&&
371 strcasecmp(use_xbyy
, "false") == 0) {
375 while (!(name
= gethostbyaddr_r(addr
, size
,
388 return (cname
); /* IP address */
393 if (!(cname
= strdup(name
->h_name
))) {
394 slp_err(LOG_CRIT
, 0, "slp_gethostbyaddr", "out of memory");
401 /* @@@ currently getting these from libresolv2 -> change? */
404 * Converts the address pointed to by 'addr' to a string. Currently
405 * just calls inet_ntoa, but is structured to be a wrapper to
406 * inet_ntop. Returns NULL on failure.
408 * This wrapper allows callers to be protocol agnostic. Right now it
412 char *slp_ntop(char *buf
, int buflen
, const void *addr
) {
413 return (inet_ntoa(*(struct in_addr
*)addr
));
417 * convert from presentation format (which usually means ASCII printable)
418 * to network format (which is usually some kind of binary format).
420 * 1 if the address was valid for the specified address family
421 * 0 if the address wasn't valid (`dst' is untouched in this case)
422 * -1 if some other error occurred (`dst' is untouched in this case, too)
424 * This wrapper allows callers to be protocol agnostic. Right now it
427 int slp_pton(const char *addrstr
, void *addr
) {
428 return (inet_pton(AF_INET
, addrstr
, addr
));