1 /* Copyright (C) 1997, 1998 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
3 Contributed by Thorsten Kukuk <kukuk@vt.uni-paderborn.de>, 1997.
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. */
25 #include <rpc/pmap_clnt.h>
29 #include <sys/socket.h>
30 #include <netinet/in.h>
31 #include <arpa/inet.h>
32 #include <rpc/key_prot.h>
33 #include <rpcsvc/nis.h>
34 #include <bits/libc-lock.h>
36 #include "nis_intern.h"
38 /* Sorry, we are not able to make this threadsafe. Stupid. But some
39 functions doesn't send us a nis_result obj, so we don't have a
40 cookie. Maybe we could use keys for threads ? Have to learn more
41 about pthreads -- kukuk@vt.uni-paderborn.de */
43 #define CB_PROG ((u_long)100302)
44 #define CB_VERS ((u_long)1)
45 #define CBPROC_RECEIVE ((u_long)1)
46 #define CBPROC_FINISH ((u_long)2)
47 #define CBPROC_ERROR ((u_long)3)
49 typedef nis_object
*obj_p
;
60 typedef struct cback_data cback_data
;
64 __libc_lock_define_initialized (static, callback
)
68 __nis_getpkey(const char *sname
)
70 char buf
[(strlen (sname
) + 1) * 2 + 40];
71 char pkey
[HEXKEYBYTES
+ 1];
76 domain
= strchr (sname
, '.');
80 /* Remove prefixing dot */
83 cp
= stpcpy (buf
, "[cname=");
84 cp
= stpcpy (cp
, sname
);
85 cp
= stpcpy (cp
, ",auth_type=DES],cred.org_dir.");
86 cp
= stpcpy (cp
, domain
);
88 res
= nis_list (buf
, USE_DGRAM
|NO_AUTHINFO
|FOLLOW_LINKS
|FOLLOW_PATH
,
94 if (res
->status
!= NIS_SUCCESS
)
100 len
= ENTRY_LEN(NIS_RES_OBJECT(res
), 3);
101 strncpy (pkey
, ENTRY_VAL(NIS_RES_OBJECT(res
), 3), len
);
103 cp
= strchr (pkey
, ':');
107 nis_freeresult (res
);
109 return strdup (pkey
);
113 static bool_t
xdr_cback_data (XDR
*, cback_data
*);
116 cb_prog_1 (struct svc_req
*rqstp
, SVCXPRT
*transp
)
120 cback_data cbproc_receive_1_arg
;
121 nis_error cbproc_error_1_arg
;
125 xdrproc_t xdr_argument
, xdr_result
;
128 switch (rqstp
->rq_proc
)
131 svc_sendreply (transp
, (xdrproc_t
) xdr_void
, (char *) NULL
);
138 xdr_argument
= (xdrproc_t
) xdr_cback_data
;
139 xdr_result
= (xdrproc_t
) xdr_bool
;
140 memset (&argument
, 0, sizeof (argument
));
141 if (!svc_getargs (transp
, xdr_argument
, (caddr_t
) & argument
))
143 svcerr_decode (transp
);
147 for (i
= 0; i
< argument
.cbproc_receive_1_arg
.entries
.entries_len
; ++i
)
149 #define cbproc_entry(a) argument.cbproc_receive_1_arg.entries.entries_val[a]
150 char name
[strlen (cbproc_entry(i
)->zo_name
) +
151 strlen (cbproc_entry(i
)->zo_domain
) + 3];
154 cp
= stpcpy (name
, cbproc_entry(i
)->zo_name
);
156 cp
= stpcpy (cp
, cbproc_entry(i
)->zo_domain
);
158 fprintf (stderr
, "name=%s\n", name
);
160 if ((data
->callback
) (name
, cbproc_entry(i
), data
->userdata
))
164 data
->result
= NIS_SUCCESS
;
168 result
= (char *) &bool_result
;
172 xdr_argument
= (xdrproc_t
) xdr_void
;
173 xdr_result
= (xdrproc_t
) xdr_void
;
174 memset (&argument
, 0, sizeof (argument
));
175 if (!svc_getargs (transp
, xdr_argument
, (caddr_t
) & argument
))
177 svcerr_decode (transp
);
181 data
->result
= NIS_SUCCESS
;
182 bool_result
= TRUE
; /* to make gcc happy, not necessary */
183 result
= (char *) &bool_result
;
186 xdr_argument
= (xdrproc_t
) xdr_nis_error
;
187 xdr_result
= (xdrproc_t
) xdr_void
;
188 memset (&argument
, 0, sizeof (argument
));
189 if (!svc_getargs (transp
, xdr_argument
, (caddr_t
) & argument
))
191 svcerr_decode (transp
);
195 data
->result
= argument
.cbproc_error_1_arg
;
196 bool_result
= TRUE
; /* to make gcc happy, not necessary */
197 result
= (char *) &bool_result
;
200 svcerr_noproc (transp
);
203 if (result
!= NULL
&& !svc_sendreply (transp
, xdr_result
, result
))
204 svcerr_systemerr (transp
);
205 if (!svc_freeargs (transp
, xdr_argument
, (caddr_t
) & argument
))
207 fputs (_ ("unable to free arguments"), stderr
);
214 xdr_obj_p (XDR
* xdrs
, obj_p
*objp
)
216 if (!xdr_pointer (xdrs
, (char **) objp
, sizeof (nis_object
),
217 (xdrproc_t
) xdr_nis_object
))
223 xdr_cback_data (XDR
*xdrs
, cback_data
*objp
)
225 if (!xdr_array (xdrs
, (char **) &objp
->entries
.entries_val
,
226 (u_int
*) & objp
->entries
.entries_len
, ~0, sizeof (obj_p
),
227 (xdrproc_t
) xdr_obj_p
))
233 internal_nis_do_callback (struct dir_binding
*bptr
, netobj
*cookie
,
236 /* Default timeout can be changed using clnt_control() */
237 static struct timeval TIMEOUT
= {25, 0};
242 #endif /* def FD_SETSIZE */
244 bool_t cb_is_running
= FALSE
;
254 #endif /* def FD_SETSIZE */
257 switch (select (_rpc_dtablesize (), &readfds
, NULL
, NULL
, &tv
))
264 /* See if callback 'thread' in the server is still alive. */
265 memset ((char *) &cb_is_running
, 0, sizeof (cb_is_running
));
266 if (clnt_call (bptr
->clnt
, NIS_CALLBACK
, (xdrproc_t
) xdr_netobj
,
267 (caddr_t
) cookie
, (xdrproc_t
) xdr_bool
,
268 (caddr_t
) & cb_is_running
, TIMEOUT
) != RPC_SUCCESS
)
269 cb_is_running
= FALSE
;
271 if (cb_is_running
== FALSE
)
273 syslog (LOG_ERR
, "NIS+: callback timed out");
278 svc_getreqset (&readfds
);
286 __nis_do_callback (struct dir_binding
*bptr
, netobj
*cookie
,
291 __libc_lock_lock (callback
);
293 result
= internal_nis_do_callback (bptr
, cookie
, cb
);
295 __libc_lock_unlock (callback
);
301 __nis_create_callback (int (*callback
) (const_nis_name
, const nis_object
*,
303 const void *userdata
, u_long flags
)
306 int sock
= RPC_ANYSOCK
;
307 struct sockaddr_in sin
;
308 int len
= sizeof (struct sockaddr_in
);
309 char addr
[NIS_MAXNAMELEN
+ 1];
312 cb
= (struct nis_cb
*) calloc (1, sizeof (struct nis_cb
));
315 syslog (LOG_ERR
, "NIS+: out of memory allocating callback");
319 cb
->serv
= (nis_server
*) calloc (1, sizeof (nis_server
));
320 if (cb
->serv
== NULL
)
323 syslog (LOG_ERR
, "NIS+: out of memory allocating callback");
326 cb
->serv
->name
= strdup (nis_local_principal ());
327 cb
->serv
->ep
.ep_val
= (endpoint
*) calloc (2, sizeof (endpoint
));
328 cb
->serv
->ep
.ep_len
= 1;
329 cb
->serv
->ep
.ep_val
[0].family
= strdup ("inet");
330 cb
->callback
= callback
;
331 cb
->userdata
= userdata
;
333 if ((flags
& NO_AUTHINFO
) && key_secretkey_is_set ())
335 cb
->serv
->key_type
= NIS_PK_NONE
;
336 cb
->serv
->pkey
.n_bytes
= NULL
;
337 cb
->serv
->pkey
.n_len
= 0;
341 if ((cb
->serv
->pkey
.n_bytes
= __nis_getpkey (cb
->serv
->name
)) == NULL
)
343 cb
->serv
->pkey
.n_len
= 0;
344 cb
->serv
->key_type
= NIS_PK_NONE
;
348 cb
->serv
->key_type
= NIS_PK_DH
;
349 cb
->serv
->pkey
.n_len
= strlen(cb
->serv
->pkey
.n_bytes
);
353 if (flags
& USE_DGRAM
)
355 cb
->serv
->ep
.ep_val
[0].proto
= strdup ("udp");
356 cb
->xprt
= svcudp_bufcreate (sock
, 100, 8192);
360 cb
->serv
->ep
.ep_val
[0].proto
= strdup ("tcp");
361 cb
->xprt
= svctcp_create (sock
, 100, 8192);
363 cb
->sock
= cb
->xprt
->xp_sock
;
364 if (!svc_register (cb
->xprt
, CB_PROG
, CB_VERS
, cb_prog_1
, 0))
366 xprt_unregister (cb
->xprt
);
367 svc_destroy (cb
->xprt
);
368 xdr_free ((xdrproc_t
) xdr_nis_server
, (char *) cb
->serv
);
371 syslog (LOG_ERR
, "NIS+: failed to register callback dispatcher");
375 if (getsockname (cb
->sock
, (struct sockaddr
*) &sin
, &len
) == -1)
377 xprt_unregister (cb
->xprt
);
378 svc_destroy (cb
->xprt
);
379 xdr_free ((xdrproc_t
) xdr_nis_server
, (char *) cb
->serv
);
382 syslog (LOG_ERR
, "NIS+: failed to read local socket info");
386 get_myaddress (&sin
);
387 snprintf (addr
, sizeof (addr
), "%s.%d.%d", inet_ntoa (sin
.sin_addr
),
388 port
& 0x00FF, (port
& 0xFF00) >> 8);
389 cb
->serv
->ep
.ep_val
[0].uaddr
= strdup (addr
);
395 __nis_destroy_callback (struct nis_cb
*cb
)
397 xprt_unregister (cb
->xprt
);
398 svc_destroy (cb
->xprt
);
400 xdr_free ((xdrproc_t
) xdr_nis_server
, (char *) cb
->serv
);