1 /* Copyright (C) 1999 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
3 Contributed by Ulrich Drepper <drepper@cygnus.com>, 1999.
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Library General Public License as
7 published by the Free Software Foundation; either version 2 of the
8 License, or (at your option) any later version.
10 The GNU C Library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Library General Public License for more details.
15 You should have received a copy of the GNU Library General Public
16 License along with the GNU C Library; see the file COPYING.LIB. If not,
17 write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA. */
26 #include <arpa/inet.h>
31 /* We avoid using a too large buffer in case the user is accumulating the
32 results and there is lots of unused space in the allocated buffer. */
36 /* Internal function to test whether IPv4 and/or IPv6 are available. */
37 extern void __protocol_available (int *have_inet
, int *have_inet6
)
41 /* Type of the lookup function we need here. */
42 typedef enum nss_status (*lookup_function
) (const char *, int, int,
43 struct hostent
*, char *,
44 size_t, int *, int *);
46 /* The lookup function for the first entry of this service. */
47 extern int __nss_hosts_lookup (service_user
**nip
, const char *name
,
52 getipnodebyname (const char *name
, int type
, int flags
, int *h_errnop
)
54 static service_user
*startp
;
55 static lookup_function start_fct
;
61 struct hostent
*result
;
66 /* First determine whether we have the appropriate interfaces.
67 XXX I don't think we can cache the result since the system
68 can be reconfigured. */
69 if ((flags
& AI_ADDRCONFIG
) != 0)
70 __protocol_available (&have_inet
, &have_inet6
);
72 /* Handle impossible requests first. */
73 if ((type
== AF_INET
&& have_inet
== 0)
74 || (type
== AF_INET6
&& have_inet6
== 0 && ((flags
& AI_V4MAPPED
) == 0
76 || (type
!= AF_INET
&& type
!= AF_INET6
))
83 buffer
= (char *) malloc (buffer_size
);
89 #define resbuf (*((struct hostent *) buffer))
90 #include "../nss/digits_dots.c"
95 no_more
= __nss_hosts_lookup (&nip
, "getipnodebyname_r", (void **) &fct
);
97 startp
= (service_user
*) -1l;
107 no_more
= (nip
= startp
) == (service_user
*) -1l;
110 /* First do a lookup with the original protocol type. */
111 while (no_more
== 0 && buffer
!= NULL
)
113 enum nss_status status
;
115 status
= DL_CALL_FCT (fct
, (name
, type
,
117 ? flags
: (flags
& ~AI_V4MAPPED
)),
118 (struct hostent
*) buffer
,
119 (char *) ((struct hostent
*) buffer
+ 1),
120 buffer_size
- sizeof (struct hostent
),
123 if (status
== NSS_STATUS_SUCCESS
)
125 result
= (struct hostent
*) buffer
;
129 if (status
== NSS_STATUS_TRYAGAIN
&& *h_errnop
== NETDB_INTERNAL
132 /* Resize the buffer, it's too small. */
133 buffer_size
+= BUFLEN
;
134 buffer
= (char *) realloc (buffer
, buffer_size
);
138 no_more
= __nss_next (&nip
, "getipnodebyname_r",
139 (void **) &fct
, status
, 0);
142 /* If we are looking for an IPv6 address but haven't found any and
143 do not have the AI_ALL but the AI_V4MAPPED flag set, now try
144 looking up an IPv4 address and map it. */
145 if (buffer
!= NULL
&& result
== NULL
146 && type
== AF_INET6
&& (flags
& AI_V4MAPPED
) != 0
147 && (no_more
= (nip
= startp
) == (service_user
*) -1l) == 0)
149 /* We have to use a new buffer if there is already a result. */
154 enum nss_status status
;
156 status
= DL_CALL_FCT (fct
, (name
, type
, flags
,
157 (struct hostent
*) buffer
,
158 (char *) ((struct hostent
*) buffer
+ 1),
159 buffer_size
- sizeof (struct hostent
),
162 if (status
== NSS_STATUS_SUCCESS
)
164 result
= (struct hostent
*) buffer
;
168 if (status
== NSS_STATUS_TRYAGAIN
&& *h_errnop
== NETDB_INTERNAL
171 /* Resize the buffer, it's too small. */
172 buffer_size
+= BUFLEN
;
173 buffer
= (char *) realloc (buffer
, buffer_size
);
177 no_more
= __nss_next (&nip
, "getipnodebyname_r",
178 (void **) &fct
, status
, 0);
180 while (no_more
== 0 && buffer
!= NULL
);
186 /* We are out of memory. */
187 *h_errnop
= TRY_AGAIN
;
188 assert (result
== NULL
);
190 else if (result
== NULL
&& buffer
!= NULL
)