1/* Copyright (C) 1996-2024 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
3
4 The GNU C Library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Lesser General Public
6 License as published by the Free Software Foundation; either
7 version 2.1 of the License, or (at your option) any later version.
8
9 The GNU C Library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Lesser General Public License for more details.
13
14 You should have received a copy of the GNU Lesser General Public
15 License along with the GNU C Library; if not, see
16 <https://www.gnu.org/licenses/>. */
17
18#include <assert.h>
19#include <errno.h>
20#include <libc-lock.h>
21#include <stdlib.h>
22#include <resolv.h>
23#include <set-freeres.h>
24
25#include "nsswitch.h"
26
27/*******************************************************************\
28|* Here we assume several symbols to be defined: *|
29|* *|
30|* LOOKUP_TYPE - the return type of the function *|
31|* *|
32|* FUNCTION_NAME - name of the non-reentrant function *|
33|* *|
34|* DATABASE_NAME - name of the database the function accesses *|
35|* (e.g., host, services, ...) *|
36|* *|
37|* ADD_PARAMS - additional parameter, can vary in number *|
38|* *|
39|* ADD_VARIABLES - names of additional parameter *|
40|* *|
41|* BUFLEN - length of buffer allocated for the non *|
42|* reentrant version *|
43|* *|
44|* Optionally the following vars can be defined: *|
45|* *|
46|* NEED_H_ERRNO - an extra parameter will be passed to point to *|
47|* the global `h_errno' variable. *|
48|* *|
49\*******************************************************************/
50
51
52#ifdef HANDLE_DIGITS_DOTS
53# include <resolv/resolv_context.h>
54#endif
55
56/* To make the real sources a bit prettier. */
57#define REENTRANT_NAME APPEND_R (FUNCTION_NAME)
58#define APPEND_R(name) APPEND_R1 (name)
59#define APPEND_R1(name) name##_r
60#define INTERNAL(name) INTERNAL1 (name)
61#define INTERNAL1(name) __##name
62#define APPEND_FREEMEM_NAME1(name) __libc_##name##_freemem_ptr
63#define APPEND_FREEMEM_NAME(name) APPEND_FREEMEM_NAME1(name)
64#define FREEMEM_NAME APPEND_FREEMEM_NAME (FUNCTION_NAME)
65
66/* Sometimes we need to store error codes in the `h_errno' variable. */
67#ifdef NEED_H_ERRNO
68# define H_ERRNO_PARM , int *h_errnop
69# define H_ERRNO_VAR , &h_errno_tmp
70# define H_ERRNO_VAR_P &h_errno_tmp
71#else
72# define H_ERRNO_PARM
73# define H_ERRNO_VAR
74# define H_ERRNO_VAR_P NULL
75#endif
76
77#ifdef HAVE_AF
78# define AF_VAL af
79#else
80# define AF_VAL AF_INET
81#endif
82
83/* Prototype for reentrant version we use here. */
84extern int INTERNAL (REENTRANT_NAME) (ADD_PARAMS, LOOKUP_TYPE *resbuf,
85 char *buffer, size_t buflen,
86 LOOKUP_TYPE **result H_ERRNO_PARM)
87 attribute_hidden;
88
89/* We need to protect the dynamic buffer handling. */
90__libc_lock_define_initialized (static, lock);
91
92/* This points to the static buffer used. */
93static char *buffer;
94
95weak_alias (buffer, FREEMEM_NAME)
96
97LOOKUP_TYPE *
98FUNCTION_NAME (ADD_PARAMS)
99{
100 static size_t buffer_size;
101 static LOOKUP_TYPE resbuf;
102 LOOKUP_TYPE *result;
103#ifdef NEED_H_ERRNO
104 int h_errno_tmp = 0;
105#endif
106
107#ifdef HANDLE_DIGITS_DOTS
108 /* Wrap both __nss_hostname_digits_dots and the actual lookup
109 function call in the same context. */
110 struct resolv_context *res_ctx = __resolv_context_get ();
111 if (res_ctx == NULL)
112 {
113# if NEED_H_ERRNO
114 __set_h_errno (NETDB_INTERNAL);
115# endif
116 return NULL;
117 }
118#endif
119
120 /* Get lock. */
121 __libc_lock_lock (lock);
122
123 if (buffer == NULL)
124 {
125 buffer_size = BUFLEN;
126 buffer = (char *) malloc (size: buffer_size);
127 }
128
129#ifdef HANDLE_DIGITS_DOTS
130 if (buffer != NULL)
131 {
132 if (__nss_hostname_digits_dots_context
133 (res_ctx, name, &resbuf, &buffer, &buffer_size, 0, &result, NULL,
134 AF_VAL, H_ERRNO_VAR_P))
135 goto done;
136 }
137#endif
138
139 while (buffer != NULL
140 && (INTERNAL (REENTRANT_NAME) (ADD_VARIABLES, resbuf: &resbuf, buffer,
141 buflen: buffer_size, result: &result H_ERRNO_VAR)
142 == ERANGE)
143#ifdef NEED_H_ERRNO
144 && h_errno_tmp == NETDB_INTERNAL
145#endif
146 )
147 {
148 char *new_buf;
149 buffer_size *= 2;
150 new_buf = (char *) realloc (ptr: buffer, size: buffer_size);
151 if (new_buf == NULL)
152 {
153 /* We are out of memory. Free the current buffer so that the
154 process gets a chance for a normal termination. */
155 free (ptr: buffer);
156 __set_errno (ENOMEM);
157 }
158 buffer = new_buf;
159 }
160
161 if (buffer == NULL)
162 result = NULL;
163
164#ifdef HANDLE_DIGITS_DOTS
165done:
166#endif
167 /* Release lock. */
168 __libc_lock_unlock (lock);
169
170#ifdef HANDLE_DIGITS_DOTS
171 __resolv_context_put (res_ctx);
172#endif
173
174#ifdef NEED_H_ERRNO
175 if (h_errno_tmp != 0)
176 __set_h_errno (h_errno_tmp);
177#endif
178
179 return result;
180}
181
182nss_interface_function (FUNCTION_NAME)
183

source code of glibc/nss/getXXbyYY.c