1 /*
2 Solaris NSS wrapper for winbind
3 - Shirish Kalele 2000
4
5 Based on Luke Howard's ldap_nss module for Solaris
6 */
7
8 /*
9 Copyright (C) 1997-2003 Luke Howard.
10 This file is part of the nss_ldap library.
11
12 The nss_ldap library is free software; you can redistribute it and/or
13 modify it under the terms of the GNU Lesser General Public License as
14 published by the Free Software Foundation; either version 3 of the
15 License, or (at your option) any later version.
16
17 The nss_ldap library is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 Library General Public License for more details.
21
22 You should have received a copy of the GNU Lesser General Public
23 License along with the nss_ldap library; see the file COPYING.LIB. If not,
24 see <http://www.gnu.org/licenses/>.
25 */
26
27 #undef DEVELOPER
28
29
30 #include "winbind_client.h"
31 #include <stdlib.h>
32 #include <sys/types.h>
33 #include <sys/param.h>
34 #include <string.h>
35 #include <pwd.h>
36 #include <syslog.h>
37
38 #if !defined(HPUX)
39 #include <sys/syslog.h>
40 #endif /*hpux*/
41
42 #if defined(HAVE_NSS_COMMON_H) || defined(HPUX)
43
44 #undef NSS_DEBUG
45
46 #ifdef NSS_DEBUG
47 #define NSS_DEBUG(str) syslog(LOG_DEBUG, "nss_winbind: %s", str);
48 #else
49 #define NSS_DEBUG(str) ;
50 #endif
51
52 #if !defined(SMB_MALLOC_P)
53 #define SMB_MALLOC_P(type) (type *)malloc(sizeof(type))
54 #endif
55
56 #define NSS_ARGS(args) ((nss_XbyY_args_t *)args)
57
58 #ifdef HPUX
59
60 /*
61 * HP-UX 11 has no definiton of the nss_groupsbymem structure. This
62 * definition is taken from the nss_ldap project at:
63 * http://www.padl.com/OSS/nss_ldap.html
64 */
65
66 struct nss_groupsbymem {
67 const char *username;
68 gid_t *gid_array;
69 int maxgids;
70 int force_slow_way;
71 int (*str2ent)(const char *instr, int instr_len, void *ent,
72 char *buffer, int buflen);
73 nss_status_t (*process_cstr)(const char *instr, int instr_len,
74 struct nss_groupsbymem *);
75 int numgids;
76 };
77
78 #endif /* HPUX */
79
_nss_winbind_setpwent_solwrap(nss_backend_t * be,void * args)80 static NSS_STATUS _nss_winbind_setpwent_solwrap (nss_backend_t* be, void* args)
81 {
82 NSS_DEBUG("_nss_winbind_setpwent_solwrap");
83 return _nss_winbind_setpwent();
84 }
85
86 static NSS_STATUS
_nss_winbind_endpwent_solwrap(nss_backend_t * be,void * args)87 _nss_winbind_endpwent_solwrap (nss_backend_t * be, void *args)
88 {
89 NSS_DEBUG("_nss_winbind_endpwent_solwrap");
90 return _nss_winbind_endpwent();
91 }
92
93 static NSS_STATUS
_nss_winbind_getpwent_solwrap(nss_backend_t * be,void * args)94 _nss_winbind_getpwent_solwrap (nss_backend_t* be, void *args)
95 {
96 NSS_STATUS ret;
97 char* buffer = NSS_ARGS(args)->buf.buffer;
98 int buflen = NSS_ARGS(args)->buf.buflen;
99 struct passwd* result = (struct passwd*) NSS_ARGS(args)->buf.result;
100 int* errnop = &NSS_ARGS(args)->erange;
101 char logmsg[80];
102
103 ret = _nss_winbind_getpwent_r(result, buffer,
104 buflen, errnop);
105
106 if(ret == NSS_STATUS_SUCCESS)
107 {
108 snprintf(logmsg, 79, "_nss_winbind_getpwent_solwrap: Returning user: %s\n",
109 result->pw_name);
110 NSS_DEBUG(logmsg);
111 NSS_ARGS(args)->returnval = (void*) result;
112 } else {
113 snprintf(logmsg, 79, "_nss_winbind_getpwent_solwrap: Returning error: %d.\n",ret);
114 NSS_DEBUG(logmsg);
115 }
116
117 return ret;
118 }
119
120 static NSS_STATUS
_nss_winbind_getpwnam_solwrap(nss_backend_t * be,void * args)121 _nss_winbind_getpwnam_solwrap (nss_backend_t* be, void* args)
122 {
123 NSS_STATUS ret;
124 struct passwd* result = (struct passwd*) NSS_ARGS(args)->buf.result;
125
126 NSS_DEBUG("_nss_winbind_getpwnam_solwrap");
127
128 ret = _nss_winbind_getpwnam_r (NSS_ARGS(args)->key.name,
129 result,
130 NSS_ARGS(args)->buf.buffer,
131 NSS_ARGS(args)->buf.buflen,
132 &NSS_ARGS(args)->erange);
133 if(ret == NSS_STATUS_SUCCESS)
134 NSS_ARGS(args)->returnval = (void*) result;
135
136 return ret;
137 }
138
139 static NSS_STATUS
_nss_winbind_getpwuid_solwrap(nss_backend_t * be,void * args)140 _nss_winbind_getpwuid_solwrap(nss_backend_t* be, void* args)
141 {
142 NSS_STATUS ret;
143 struct passwd* result = (struct passwd*) NSS_ARGS(args)->buf.result;
144
145 NSS_DEBUG("_nss_winbind_getpwuid_solwrap");
146 ret = _nss_winbind_getpwuid_r (NSS_ARGS(args)->key.uid,
147 result,
148 NSS_ARGS(args)->buf.buffer,
149 NSS_ARGS(args)->buf.buflen,
150 &NSS_ARGS(args)->erange);
151 if(ret == NSS_STATUS_SUCCESS)
152 NSS_ARGS(args)->returnval = (void*) result;
153
154 return ret;
155 }
156
_nss_winbind_passwd_destr(nss_backend_t * be,void * args)157 static NSS_STATUS _nss_winbind_passwd_destr (nss_backend_t * be, void *args)
158 {
159 SAFE_FREE(be);
160 NSS_DEBUG("_nss_winbind_passwd_destr");
161 return NSS_STATUS_SUCCESS;
162 }
163
164 static nss_backend_op_t passwd_ops[] =
165 {
166 _nss_winbind_passwd_destr,
167 _nss_winbind_endpwent_solwrap, /* NSS_DBOP_ENDENT */
168 _nss_winbind_setpwent_solwrap, /* NSS_DBOP_SETENT */
169 _nss_winbind_getpwent_solwrap, /* NSS_DBOP_GETENT */
170 _nss_winbind_getpwnam_solwrap, /* NSS_DBOP_PASSWD_BYNAME */
171 _nss_winbind_getpwuid_solwrap /* NSS_DBOP_PASSWD_BYUID */
172 };
173
174 nss_backend_t*
_nss_winbind_passwd_constr(const char * db_name,const char * src_name,const char * cfg_args)175 _nss_winbind_passwd_constr (const char* db_name,
176 const char* src_name,
177 const char* cfg_args)
178 {
179 nss_backend_t *be;
180
181 if(!(be = SMB_MALLOC_P(nss_backend_t)) )
182 return NULL;
183
184 be->ops = passwd_ops;
185 be->n_ops = sizeof(passwd_ops) / sizeof(nss_backend_op_t);
186
187 NSS_DEBUG("Initialized nss_winbind passwd backend");
188 return be;
189 }
190
191 /*****************************************************************
192 GROUP database backend
193 *****************************************************************/
194
_nss_winbind_setgrent_solwrap(nss_backend_t * be,void * args)195 static NSS_STATUS _nss_winbind_setgrent_solwrap (nss_backend_t* be, void* args)
196 {
197 NSS_DEBUG("_nss_winbind_setgrent_solwrap");
198 return _nss_winbind_setgrent();
199 }
200
201 static NSS_STATUS
_nss_winbind_endgrent_solwrap(nss_backend_t * be,void * args)202 _nss_winbind_endgrent_solwrap (nss_backend_t * be, void *args)
203 {
204 NSS_DEBUG("_nss_winbind_endgrent_solwrap");
205 return _nss_winbind_endgrent();
206 }
207
208 static NSS_STATUS
_nss_winbind_getgrent_solwrap(nss_backend_t * be,void * args)209 _nss_winbind_getgrent_solwrap(nss_backend_t* be, void* args)
210 {
211 NSS_STATUS ret;
212 char* buffer = NSS_ARGS(args)->buf.buffer;
213 int buflen = NSS_ARGS(args)->buf.buflen;
214 struct group* result = (struct group*) NSS_ARGS(args)->buf.result;
215 int* errnop = &NSS_ARGS(args)->erange;
216 char logmsg[80];
217
218 ret = _nss_winbind_getgrent_r(result, buffer,
219 buflen, errnop);
220
221 if(ret == NSS_STATUS_SUCCESS)
222 {
223 snprintf(logmsg, 79, "_nss_winbind_getgrent_solwrap: Returning group: %s\n", result->gr_name);
224 NSS_DEBUG(logmsg);
225 NSS_ARGS(args)->returnval = (void*) result;
226 } else {
227 snprintf(logmsg, 79, "_nss_winbind_getgrent_solwrap: Returning error: %d.\n", ret);
228 NSS_DEBUG(logmsg);
229 }
230
231 return ret;
232
233 }
234
235 static NSS_STATUS
_nss_winbind_getgrnam_solwrap(nss_backend_t * be,void * args)236 _nss_winbind_getgrnam_solwrap(nss_backend_t* be, void* args)
237 {
238 NSS_STATUS ret;
239 struct group* result = (struct group*) NSS_ARGS(args)->buf.result;
240
241 NSS_DEBUG("_nss_winbind_getgrnam_solwrap");
242 ret = _nss_winbind_getgrnam_r(NSS_ARGS(args)->key.name,
243 result,
244 NSS_ARGS(args)->buf.buffer,
245 NSS_ARGS(args)->buf.buflen,
246 &NSS_ARGS(args)->erange);
247
248 if(ret == NSS_STATUS_SUCCESS)
249 NSS_ARGS(args)->returnval = (void*) result;
250
251 if (NSS_ARGS(args)->erange == ERANGE && ret == NSS_STATUS_TRYAGAIN)
252 return NSS_STATUS_UNAVAIL;
253
254 return ret;
255 }
256
257 static NSS_STATUS
_nss_winbind_getgrgid_solwrap(nss_backend_t * be,void * args)258 _nss_winbind_getgrgid_solwrap(nss_backend_t* be, void* args)
259 {
260 NSS_STATUS ret;
261 struct group* result = (struct group*) NSS_ARGS(args)->buf.result;
262
263 NSS_DEBUG("_nss_winbind_getgrgid_solwrap");
264 ret = _nss_winbind_getgrgid_r (NSS_ARGS(args)->key.gid,
265 result,
266 NSS_ARGS(args)->buf.buffer,
267 NSS_ARGS(args)->buf.buflen,
268 &NSS_ARGS(args)->erange);
269
270 if(ret == NSS_STATUS_SUCCESS)
271 NSS_ARGS(args)->returnval = (void*) result;
272
273 if (NSS_ARGS(args)->erange == ERANGE && ret == NSS_STATUS_TRYAGAIN)
274 return NSS_STATUS_UNAVAIL;
275
276 return ret;
277 }
278
279 static NSS_STATUS
_nss_winbind_getgroupsbymember_solwrap(nss_backend_t * be,void * args)280 _nss_winbind_getgroupsbymember_solwrap(nss_backend_t* be, void* args)
281 {
282 int errnop;
283 struct nss_groupsbymem *gmem = (struct nss_groupsbymem *)args;
284 long int numgids = gmem->numgids;
285 long int maxgids = gmem->maxgids;
286
287 NSS_DEBUG("_nss_winbind_getgroupsbymember");
288
289 _nss_winbind_initgroups_dyn(gmem->username,
290 gmem->gid_array[0], /* Primary Group */
291 &numgids,
292 &maxgids,
293 &gmem->gid_array,
294 gmem->maxgids,
295 &errnop);
296
297 gmem->numgids = numgids;
298 gmem->maxgids = maxgids;
299
300 /*
301 * If the maximum number of gids have been found, return
302 * SUCCESS so the switch engine will stop searching. Otherwise
303 * return NOTFOUND so nsswitch will continue to get groups
304 * from the remaining database backends specified in the
305 * nsswitch.conf file.
306 */
307 return (gmem->numgids == gmem->maxgids ? NSS_STATUS_SUCCESS : NSS_STATUS_NOTFOUND);
308 }
309
310 static NSS_STATUS
_nss_winbind_group_destr(nss_backend_t * be,void * args)311 _nss_winbind_group_destr (nss_backend_t* be, void* args)
312 {
313 SAFE_FREE(be);
314 NSS_DEBUG("_nss_winbind_group_destr");
315 return NSS_STATUS_SUCCESS;
316 }
317
318 static nss_backend_op_t group_ops[] =
319 {
320 _nss_winbind_group_destr,
321 _nss_winbind_endgrent_solwrap,
322 _nss_winbind_setgrent_solwrap,
323 _nss_winbind_getgrent_solwrap,
324 _nss_winbind_getgrnam_solwrap,
325 _nss_winbind_getgrgid_solwrap,
326 _nss_winbind_getgroupsbymember_solwrap
327 };
328
329 nss_backend_t*
_nss_winbind_group_constr(const char * db_name,const char * src_name,const char * cfg_args)330 _nss_winbind_group_constr (const char* db_name,
331 const char* src_name,
332 const char* cfg_args)
333 {
334 nss_backend_t* be;
335
336 if(!(be = SMB_MALLOC_P(nss_backend_t)) )
337 return NULL;
338
339 be->ops = group_ops;
340 be->n_ops = sizeof(group_ops) / sizeof(nss_backend_op_t);
341
342 NSS_DEBUG("Initialized nss_winbind group backend");
343 return be;
344 }
345
346 /*****************************************************************
347 hosts and ipnodes backend
348 *****************************************************************/
349 #if defined(SUNOS5) /* not compatible with HP-UX */
350
351 /* this parser is shared between get*byname and get*byaddr, as key type
352 in request is stored in different locations, I had to provide the
353 address family as an argument, caller must free the winbind response. */
354
355 static NSS_STATUS
parse_response(int af,nss_XbyY_args_t * argp,struct winbindd_response * response)356 parse_response(int af, nss_XbyY_args_t* argp, struct winbindd_response *response)
357 {
358 struct hostent *he = (struct hostent *)argp->buf.result;
359 char *buffer = argp->buf.buffer;
360 int buflen = argp->buf.buflen;
361 NSS_STATUS ret;
362
363 char *p, *data;
364 int addrcount = 0;
365 int len = 0;
366 struct in_addr *addrp;
367 #if defined(AF_INET6)
368 struct in6_addr *addrp6;
369 #endif
370 int i;
371
372 /* response is tab separated list of ip addresses with hostname
373 and newline at the end. so at first we will strip newline
374 then construct list of addresses for hostent.
375 */
376 p = strchr(response->data.winsresp, '\n');
377 if(p) *p = '\0';
378 else {/* it must be broken */
379 argp->h_errno = NO_DATA;
380 return NSS_STATUS_UNAVAIL;
381 }
382
383 for(; p != response->data.winsresp; p--) {
384 if(*p == '\t') addrcount++;
385 }
386
387 if(addrcount == 0) {/* it must be broken */
388 argp->h_errno = NO_DATA;
389 return NSS_STATUS_UNAVAIL;
390 }
391
392 /* allocate space for addresses and h_addr_list */
393 he->h_addrtype = af;
394 if( he->h_addrtype == AF_INET) {
395 he->h_length = sizeof(struct in_addr);
396 addrp = (struct in_addr *)ROUND_DOWN(buffer + buflen,
397 sizeof(struct in_addr));
398 addrp -= addrcount;
399 he->h_addr_list = (char **)ROUND_DOWN(addrp, sizeof (char*));
400 he->h_addr_list -= addrcount+1;
401 }
402 #if defined(AF_INET6)
403 else {
404 he->h_length = sizeof(struct in6_addr);
405 addrp6 = (struct in6_addr *)ROUND_DOWN(buffer + buflen,
406 sizeof(struct in6_addr));
407 addrp6 -= addrcount;
408 he->h_addr_list = (char **)ROUND_DOWN(addrp6, sizeof (char*));
409 he->h_addr_list -= addrcount+1;
410 }
411 #endif
412
413 /* buffer too small?! */
414 if((char *)he->h_addr_list < buffer ) {
415 argp->erange = 1;
416 return NSS_STR_PARSE_ERANGE;
417 }
418
419 data = response->data.winsresp;
420 for( i = 0; i < addrcount; i++) {
421 p = strchr(data, '\t');
422 if(p == NULL) break; /* just in case... */
423
424 *p = '\0'; /* terminate the string */
425 if(he->h_addrtype == AF_INET) {
426 he->h_addr_list[i] = (char *)&addrp[i];
427 if ((addrp[i].s_addr = inet_addr(data)) == -1) {
428 argp->erange = 1;
429 return NSS_STR_PARSE_ERANGE;
430 }
431 }
432 #if defined(AF_INET6)
433 else {
434 he->h_addr_list[i] = (char *)&addrp6[i];
435 if (strchr(data, ':') != 0) {
436 if (inet_pton(AF_INET6, data, &addrp6[i]) != 1) {
437 argp->erange = 1;
438 return NSS_STR_PARSE_ERANGE;
439 }
440 } else {
441 struct in_addr in4;
442 if ((in4.s_addr = inet_addr(data)) == -1) {
443 argp->erange = 1;
444 return NSS_STR_PARSE_ERANGE;
445 }
446 IN6_INADDR_TO_V4MAPPED(&in4, &addrp6[i]);
447 }
448 }
449 #endif
450 data = p+1;
451 }
452
453 he->h_addr_list[i] = (char *)NULL;
454
455 len = strlen(data);
456 if(len > he->h_addr_list - (char**)argp->buf.buffer) {
457 argp->erange = 1;
458 return NSS_STR_PARSE_ERANGE;
459 }
460
461 /* this is a bit overkill to use _nss_netdb_aliases here since
462 there seems to be no aliases but it will create all data for us */
463 he->h_aliases = _nss_netdb_aliases(data, len, buffer,
464 ((char*) he->h_addr_list) - buffer);
465 if(he->h_aliases == NULL) {
466 argp->erange = 1;
467 ret = NSS_STR_PARSE_ERANGE;
468 } else {
469 he->h_name = he->h_aliases[0];
470 he->h_aliases++;
471 ret = NSS_STR_PARSE_SUCCESS;
472 }
473
474 argp->returnval = (void*)he;
475 return ret;
476 }
477
478 static NSS_STATUS
_nss_winbind_ipnodes_getbyname(nss_backend_t * be,void * args)479 _nss_winbind_ipnodes_getbyname(nss_backend_t* be, void *args)
480 {
481 nss_XbyY_args_t *argp = (nss_XbyY_args_t*) args;
482 struct winbindd_request request = {
483 .wb_flags = WBFLAG_FROM_NSS,
484 };
485 struct winbindd_response response = {
486 .length = 0,
487 };
488 NSS_STATUS ret;
489 int af;
490
491 /* I assume there that AI_ADDRCONFIG cases are handled in nss
492 frontend code, at least it seems done so in solaris...
493
494 we will give NO_DATA for pure IPv6; IPv4 will be returned for
495 AF_INET or for AF_INET6 and AI_ALL|AI_V4MAPPED we have to map
496 IPv4 to IPv6.
497 */
498 #if defined(AF_INET6)
499 #ifdef HAVE_NSS_XBYY_KEY_IPNODE
500 af = argp->key.ipnode.af_family;
501 if(af == AF_INET6 && argp->key.ipnode.flags == 0) {
502 argp->h_errno = NO_DATA;
503 return NSS_STATUS_UNAVAIL;
504 }
505 #else
506 /* I'm not that sure if this is correct, but... */
507 af = AF_INET6;
508 #endif
509 #endif
510
511 strncpy(request.data.winsreq, argp->key.name, sizeof(request.data.winsreq) - 1);
512 request.data.winsreq[sizeof(request.data.winsreq) - 1] = '\0';
513
514 if( (ret = winbindd_request_response(NULL, WINBINDD_WINS_BYNAME,
515 &request, &response))
516 == NSS_STATUS_SUCCESS ) {
517 ret = parse_response(af, argp, &response);
518 }
519
520 winbindd_free_response(&response);
521 return ret;
522 }
523
524 static NSS_STATUS
_nss_winbind_hosts_getbyname(nss_backend_t * be,void * args)525 _nss_winbind_hosts_getbyname(nss_backend_t* be, void *args)
526 {
527 nss_XbyY_args_t *argp = (nss_XbyY_args_t*) args;
528 struct winbindd_request request = {
529 .wb_flags = WBFLAG_FROM_NSS,
530 };
531 struct winbindd_response response = {
532 .length = 0,
533 };
534 NSS_STATUS ret;
535
536 strncpy(request.data.winsreq, argp->key.name, sizeof(request.data.winsreq) - 1);
537 request.data.winsreq[sizeof(request.data.winsreq) - 1] = '\0';
538
539 if( (ret = winbindd_request_response(NULL, WINBINDD_WINS_BYNAME,
540 &request, &response))
541 == NSS_STATUS_SUCCESS ) {
542 ret = parse_response(AF_INET, argp, &response);
543 }
544
545 winbindd_free_response(&response);
546 return ret;
547 }
548
549 static NSS_STATUS
_nss_winbind_hosts_getbyaddr(nss_backend_t * be,void * args)550 _nss_winbind_hosts_getbyaddr(nss_backend_t* be, void *args)
551 {
552 NSS_STATUS ret;
553 struct winbindd_request request = {
554 .wb_flags = WBFLAG_FROM_NSS,
555 };
556 struct winbindd_response response = {
557 .length = 0,
558 };
559 nss_XbyY_args_t *argp = (nss_XbyY_args_t *)args;
560 const char *p;
561
562 #if defined(AF_INET6)
563 /* winbindd currently does not resolve IPv6 */
564 if(argp->key.hostaddr.type == AF_INET6) {
565 argp->h_errno = NO_DATA;
566 return NSS_STATUS_UNAVAIL;
567 }
568
569 p = inet_ntop(argp->key.hostaddr.type, argp->key.hostaddr.addr,
570 request.data.winsreq, sizeof request.data.winsreq);
571 #else
572 snprintf(request.data.winsreq, sizeof request.data.winsreq,
573 "%u.%u.%u.%u",
574 ((unsigned char *)argp->key.hostaddr.addr)[0],
575 ((unsigned char *)argp->key.hostaddr.addr)[1],
576 ((unsigned char *)argp->key.hostaddr.addr)[2],
577 ((unsigned char *)argp->key.hostaddr.addr)[3]);
578 #endif
579
580 ret = winbindd_request_response(NULL, WINBINDD_WINS_BYIP,
581 &request, &response);
582
583 if( ret == NSS_STATUS_SUCCESS) {
584 parse_response(argp->key.hostaddr.type, argp, &response);
585 }
586 winbindd_free_response(&response);
587 return ret;
588 }
589
590 /* winbind does not provide setent, getent, endent for wins */
591 static NSS_STATUS
_nss_winbind_common_endent(nss_backend_t * be,void * args)592 _nss_winbind_common_endent(nss_backend_t* be, void *args)
593 {
594 return (NSS_STATUS_UNAVAIL);
595 }
596
597 static NSS_STATUS
_nss_winbind_common_setent(nss_backend_t * be,void * args)598 _nss_winbind_common_setent(nss_backend_t* be, void *args)
599 {
600 return (NSS_STATUS_UNAVAIL);
601 }
602
603 static NSS_STATUS
_nss_winbind_common_getent(nss_backend_t * be,void * args)604 _nss_winbind_common_getent(nss_backend_t* be, void *args)
605 {
606 return (NSS_STATUS_UNAVAIL);
607 }
608
609 static nss_backend_t*
_nss_winbind_common_constr(nss_backend_op_t ops[],int n_ops)610 _nss_winbind_common_constr (nss_backend_op_t ops[], int n_ops)
611 {
612 nss_backend_t* be;
613
614 if(!(be = SMB_MALLOC_P(nss_backend_t)) )
615 return NULL;
616
617 be->ops = ops;
618 be->n_ops = n_ops;
619
620 return be;
621 }
622
623 static NSS_STATUS
_nss_winbind_common_destr(nss_backend_t * be,void * args)624 _nss_winbind_common_destr (nss_backend_t* be, void* args)
625 {
626 SAFE_FREE(be);
627 return NSS_STATUS_SUCCESS;
628 }
629
630 static nss_backend_op_t ipnodes_ops[] = {
631 _nss_winbind_common_destr,
632 _nss_winbind_common_endent,
633 _nss_winbind_common_setent,
634 _nss_winbind_common_getent,
635 _nss_winbind_ipnodes_getbyname,
636 _nss_winbind_hosts_getbyaddr,
637 };
638
639 nss_backend_t *
_nss_winbind_ipnodes_constr(dummy1,dummy2,dummy3)640 _nss_winbind_ipnodes_constr(dummy1, dummy2, dummy3)
641 const char *dummy1, *dummy2, *dummy3;
642 {
643 return (_nss_winbind_common_constr(ipnodes_ops,
644 sizeof (ipnodes_ops) / sizeof (ipnodes_ops[0])));
645 }
646
647 static nss_backend_op_t host_ops[] = {
648 _nss_winbind_common_destr,
649 _nss_winbind_common_endent,
650 _nss_winbind_common_setent,
651 _nss_winbind_common_getent,
652 _nss_winbind_hosts_getbyname,
653 _nss_winbind_hosts_getbyaddr,
654 };
655
656 nss_backend_t *
_nss_winbind_hosts_constr(dummy1,dummy2,dummy3)657 _nss_winbind_hosts_constr(dummy1, dummy2, dummy3)
658 const char *dummy1, *dummy2, *dummy3;
659 {
660 return (_nss_winbind_common_constr(host_ops,
661 sizeof (host_ops) / sizeof (host_ops[0])));
662 }
663
664 #endif /* defined(SUNOS5) */
665 #endif /* defined(HAVE_NSS_COMMON_H) || defined(HPUX) */
666