lib tdb: memcmp ubsan warning
[Samba.git] / nsswitch / wins.c
blob371ab78d2f877712e923b91302f7c55653c78f82
1 /*
2 Unix SMB/CIFS implementation.
3 a WINS nsswitch module
4 Copyright (C) Andrew Tridgell 1999
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program. If not, see <http://www.gnu.org/licenses/>.
21 #include "includes.h"
22 #include "nsswitch/winbind_client.h"
23 #include "nsswitch/libwbclient/wbclient.h"
25 #ifdef HAVE_NS_API_H
27 #include <ns_daemon.h>
28 #endif
30 #ifdef HAVE_PTHREAD_H
31 #include <pthread.h>
32 #endif
34 #ifdef HAVE_PTHREAD
35 static pthread_mutex_t wins_nss_mutex = PTHREAD_MUTEX_INITIALIZER;
36 #endif
38 #ifndef INADDRSZ
39 #define INADDRSZ 4
40 #endif
42 NSS_STATUS _nss_wins_gethostbyname_r(const char *hostname,
43 struct hostent *he,
44 char *buffer,
45 size_t buflen,
46 int *errnop,
47 int *h_errnop);
48 NSS_STATUS _nss_wins_gethostbyname2_r(const char *name,
49 int af,
50 struct hostent *he,
51 char *buffer,
52 size_t buflen,
53 int *errnop,
54 int *h_errnop);
56 static char *lookup_byname_backend(const char *name)
58 const char *p;
59 char *ip, *ipp;
60 size_t nbt_len;
61 wbcErr result;
63 nbt_len = strlen(name);
64 if (nbt_len > MAX_NETBIOSNAME_LEN - 1) {
65 return NULL;
67 p = strchr(name, '.');
68 if (p != NULL) {
69 return NULL;
72 wbcSetClientProcessName("nss_wins");
73 result = wbcResolveWinsByName(name, &ip);
74 if (result != WBC_ERR_SUCCESS) {
75 return NULL;
78 ipp = strchr(ip, '\t');
79 if (ipp != NULL) {
80 *ipp = '\0';
83 return ip;
86 #ifdef HAVE_NS_API_H
88 static char *lookup_byaddr_backend(const char *ip)
90 wbcErr result;
91 char *name = NULL;
93 wbcSetClientProcessName("nss_wins");
94 result = wbcResolveWinsByIP(ip, &name);
95 if (result != WBC_ERR_SUCCESS) {
96 return NULL;
99 return name;
102 /* IRIX version */
104 int init(void)
106 bool ok;
108 nsd_logprintf(NSD_LOG_MIN, "entering init (wins)\n");
110 ok = nss_wins_init();
111 if (!ok) {
112 return NSD_ERROR;
115 return NSD_OK;
118 int lookup(nsd_file_t *rq)
120 char *map;
121 char *key;
122 char *addr;
123 int i, count, len, size;
124 char response[1024];
125 bool found = False;
127 nsd_logprintf(NSD_LOG_MIN, "entering lookup (wins)\n");
128 if (! rq)
129 return NSD_ERROR;
131 map = nsd_attr_fetch_string(rq->f_attrs, "table", (char*)0);
132 if (! map) {
133 rq->f_status = NS_FATAL;
134 return NSD_ERROR;
137 key = nsd_attr_fetch_string(rq->f_attrs, "key", (char*)0);
138 if (! key || ! *key) {
139 rq->f_status = NS_FATAL;
140 return NSD_ERROR;
143 response[0] = '\0';
144 len = sizeof(response) - 2;
147 * response needs to be a string of the following format
148 * ip_address[ ip_address]*\tname[ alias]*
150 if (strcasecmp_m(map,"hosts.byaddr") == 0) {
151 char *name;
153 name = lookup_byaddr_backend(key);
154 if (name != NULL) {
155 size = strlen(key) + 1;
156 if (size > len) {
157 return NSD_ERROR;
159 len -= size;
160 strncat(response,key,size);
161 strncat(response,"\t",1);
163 size = strlen(name) + 1;
164 if (size > len) {
165 return NSD_ERROR;
167 len -= size;
168 strncat(response, name, size);
169 strncat(response, " ", 1);
170 found = True;
172 response[strlen(response)-1] = '\n';
173 } else if (strcasecmp_m(map,"hosts.byname") == 0) {
174 char *ip;
176 ip = lookup_byname_backend(key);
177 if (ip != NULL) {
178 size = strlen(ip) + 1;
179 if (size > len) {
180 wbcFreeMemory(ip);
181 return NSD_ERROR;
183 len -= size;
184 strncat(response,ip,size);
185 strncat(response,"\t",1);
186 size = strlen(key) + 1;
187 wbcFreeMemory(ip);
188 if (size > len) {
189 return NSD_ERROR;
191 strncat(response,key,size);
192 strncat(response,"\n",1);
194 found = True;
198 if (found) {
199 nsd_logprintf(NSD_LOG_LOW, "lookup (wins %s) %s\n",map,response);
200 nsd_set_result(rq,NS_SUCCESS,response,strlen(response),VOLATILE);
201 return NSD_OK;
203 nsd_logprintf(NSD_LOG_LOW, "lookup (wins) not found\n");
204 rq->f_status = NS_NOTFOUND;
205 return NSD_NEXT;
208 #else
210 /* Allocate some space from the nss static buffer. The buffer and buflen
211 are the pointers passed in by the C library to the _nss_*_*
212 functions. */
214 static char *get_static(char **buffer, size_t *buflen, size_t len)
216 char *result;
218 /* Error check. We return false if things aren't set up right, or
219 there isn't enough buffer space left. */
221 if ((buffer == NULL) || (buflen == NULL) || (*buflen < len)) {
222 return NULL;
225 /* Return an index into the static buffer */
227 result = *buffer;
228 *buffer += len;
229 *buflen -= len;
231 return result;
234 /****************************************************************************
235 gethostbyname() - we ignore any domain portion of the name and only
236 handle names that are at most 15 characters long
237 **************************************************************************/
238 NSS_STATUS
239 _nss_wins_gethostbyname_r(const char *hostname,
240 struct hostent *he,
241 char *buffer,
242 size_t buflen,
243 int *errnop,
244 int *h_errnop)
246 NSS_STATUS nss_status = NSS_STATUS_SUCCESS;
247 char *ip;
248 struct in_addr in;
249 int i;
250 fstring name;
251 size_t namelen;
252 int rc;
254 #ifdef HAVE_PTHREAD
255 pthread_mutex_lock(&wins_nss_mutex);
256 #endif
258 memset(he, '\0', sizeof(*he));
259 fstrcpy(name, hostname);
261 /* Do lookup */
263 ip = lookup_byname_backend(name);
264 if (ip == NULL) {
265 *h_errnop = HOST_NOT_FOUND;
266 nss_status = NSS_STATUS_NOTFOUND;
267 goto out;
270 rc = inet_pton(AF_INET, ip, &in);
271 wbcFreeMemory(ip);
272 if (rc == 0) {
273 *errnop = errno;
274 *h_errnop = NETDB_INTERNAL;
275 nss_status = NSS_STATUS_TRYAGAIN;
276 goto out;
279 /* Copy h_name */
281 namelen = strlen(name) + 1;
283 if ((he->h_name = get_static(&buffer, &buflen, namelen)) == NULL) {
284 *errnop = EAGAIN;
285 *h_errnop = NETDB_INTERNAL;
286 nss_status = NSS_STATUS_TRYAGAIN;
287 goto out;
290 memcpy(he->h_name, name, namelen);
292 /* Copy h_addr_list, align to pointer boundary first */
294 if ((i = (unsigned long)(buffer) % sizeof(char*)) != 0)
295 i = sizeof(char*) - i;
297 if (get_static(&buffer, &buflen, i) == NULL) {
298 *errnop = EAGAIN;
299 *h_errnop = NETDB_INTERNAL;
300 nss_status = NSS_STATUS_TRYAGAIN;
301 goto out;
304 if ((he->h_addr_list = (char **)get_static(
305 &buffer, &buflen, 2 * sizeof(char *))) == NULL) {
306 *errnop = EAGAIN;
307 *h_errnop = NETDB_INTERNAL;
308 nss_status = NSS_STATUS_TRYAGAIN;
309 goto out;
312 if ((he->h_addr_list[0] = get_static(&buffer, &buflen,
313 INADDRSZ)) == NULL) {
314 *errnop = EAGAIN;
315 *h_errnop = NETDB_INTERNAL;
316 nss_status = NSS_STATUS_TRYAGAIN;
317 goto out;
320 memcpy(he->h_addr_list[0], &in, INADDRSZ);
322 he->h_addr_list[1] = NULL;
324 /* Set h_addr_type and h_length */
326 he->h_addrtype = AF_INET;
327 he->h_length = INADDRSZ;
329 /* Set h_aliases */
331 if ((i = (unsigned long)(buffer) % sizeof(char*)) != 0)
332 i = sizeof(char*) - i;
334 if (get_static(&buffer, &buflen, i) == NULL) {
335 *errnop = EAGAIN;
336 *h_errnop = NETDB_INTERNAL;
337 nss_status = NSS_STATUS_TRYAGAIN;
338 goto out;
341 if ((he->h_aliases = (char **)get_static(
342 &buffer, &buflen, sizeof(char *))) == NULL) {
343 *errnop = EAGAIN;
344 *h_errnop = NETDB_INTERNAL;
345 nss_status = NSS_STATUS_TRYAGAIN;
346 goto out;
349 he->h_aliases[0] = NULL;
351 *h_errnop = NETDB_SUCCESS;
352 nss_status = NSS_STATUS_SUCCESS;
354 out:
356 #ifdef HAVE_PTHREAD
357 pthread_mutex_unlock(&wins_nss_mutex);
358 #endif
359 return nss_status;
363 NSS_STATUS
364 _nss_wins_gethostbyname2_r(const char *name,
365 int af,
366 struct hostent *he,
367 char *buffer,
368 size_t buflen,
369 int *errnop,
370 int *h_errnop)
372 NSS_STATUS nss_status;
374 if(af!=AF_INET) {
375 *errnop = EAFNOSUPPORT;
376 *h_errnop = NO_DATA;
377 nss_status = NSS_STATUS_UNAVAIL;
378 } else {
379 nss_status = _nss_wins_gethostbyname_r(name,
381 buffer,
382 buflen,
383 errnop,
384 h_errnop);
386 return nss_status;
388 #endif