rpcbind.c (9e293969c29a9c274758e70e5a7349223cef86c1) rpcbind.c (8f6d9dae92449b59bdafcb7777bc32f1b2726e48)
1/*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE

--- 8 unchanged lines hidden (view full) ---

17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21/*
22 * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 */
1/*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE

--- 8 unchanged lines hidden (view full) ---

17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21/*
22 * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 */
25/*
26 * Copyright 2014 Nexenta Systems, Inc. All rights reserved.
27 */
25/* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
26/* All Rights Reserved */
27/*
28 * University Copyright- Copyright (c) 1982, 1986, 1988
29 * The Regents of the University of California
30 * All Rights Reserved
31 *
32 * University Acknowledgment- Portions of this document are derived from
33 * software developed by the University of California, Berkeley, and its
34 * contributors.
35 */
36
37/*
28/* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
29/* All Rights Reserved */
30/*
31 * University Copyright- Copyright (c) 1982, 1986, 1988
32 * The Regents of the University of California
33 * All Rights Reserved
34 *
35 * University Acknowledgment- Portions of this document are derived from
36 * software developed by the University of California, Berkeley, and its
37 * contributors.
38 */
39
40/*
38 * rpcbind.c
39 * Implements the program, version to address mapping for rpc.
41 * This is an implementation of RCPBIND according the RFC 1833: Binding
42 * Protocols for ONC RPC Version 2. The RFC specifies three versions of the
43 * binding protocol:
40 *
44 *
45 * 1) RPCBIND Version 3 (Section 2.2.1 of the RFC)
46 * 2) RPCBIND, Version 4 (Section 2.2.2 of the RFC)
47 * 3) Port Mapper Program Protocol (Section 3 of the RFC)
48 *
49 * Where the "Port Mapper Program Protocol" is refered as Version 2 of the
50 * binding protocol. The implementation of the Version 2 of the binding
51 * protocol is compiled in only in a case the PORTMAP macro is defined (by
52 * default it is defined).
53 *
54 * The implementation is based on top of the networking services library -
55 * libnsl(3lib) and uses Automatic MT mode (see rcp_control(3nsl) and
56 * svc_run(3nsl) for more details).
57 *
58 * Usually, when a thread handles an RPCBIND procedure (one that arrived from a
59 * client), it obtains the data for the response internally, and immediately
60 * sends the response back to the client. The only exception to this rule are
61 * remote (aka indirect) RPC calls, for example RPCBPROC_INDIRECT. Such
62 * procedures are designed to forward the RPC request from the client to some
63 * other RPC service specified by the client, wait for the result, and forward
64 * the result back to the client. This is implemented in rpcbproc_callit_com().
65 *
66 * The response from the other (remote) RPC service is handled in
67 * handle_reply(), where the thread waiting in rpcbproc_callit_com() is woken
68 * up to finish the handling and to send (forward) the response back to the
69 * client.
70 *
71 * The thread implementing the indirect RPC call might be blocked in the
72 * rpcbproc_callit_com() waiting for the response from the other RPC service
73 * for very long time. During this time the thread is unable to handle other
74 * RPCBIND requests. To avoid a case when all threads are waiting in
75 * rpcbproc_callit_com() and there is no free thread able to handle other
76 * RPCBIND requests, the implementation has reserved eight threads to never be
77 * used for the remote RPC calls. The number of active remote RPC calls is in
78 * rpcb_rmtcalls, the upper limit of such calls is in rpcb_rmtcalls_max.
79 *
80 * In addition to the worker threads described above, there are two other
81 * threads. The logthread() thread is responsible for asynchronous logging to
82 * syslog. The terminate() thread is signal handler responsible for reload of
83 * the rpcbind configuration (on SIGHUP), or for gracefully shutting down
84 * rpcbind (otherwise).
85 *
86 * There are two global lists used for holding the information about the
87 * registered services: list_rbl is for Version 3 and 4 of the binding
88 * protocol, and list_pml is for Version 2. To protect these lists, two global
89 * readers/writer locks are defined and heavily used across the rpcbind
90 * implementation: list_rbl_lock protecting list_rbl, and list_pml_lock,
91 * protecting list_pml.
92 *
93 * The defined locking order is: list_rbl_lock first, list_pml_lock second.
41 */
42
43#include <dlfcn.h>
44#include <stdio.h>
45#include <stdio_ext.h>
46#include <sys/types.h>
47#include <unistd.h>
48#include <stdlib.h>

--- 20 unchanged lines hidden (view full) ---

69#include <syslog.h>
70#include <string.h>
71#include <sys/time.h>
72#include <sys/resource.h>
73#include <rpcsvc/daemon_utils.h>
74#include <priv_utils.h>
75#include <libscf.h>
76#include <sys/ccompile.h>
94 */
95
96#include <dlfcn.h>
97#include <stdio.h>
98#include <stdio_ext.h>
99#include <sys/types.h>
100#include <unistd.h>
101#include <stdlib.h>

--- 20 unchanged lines hidden (view full) ---

122#include <syslog.h>
123#include <string.h>
124#include <sys/time.h>
125#include <sys/resource.h>
126#include <rpcsvc/daemon_utils.h>
127#include <priv_utils.h>
128#include <libscf.h>
129#include <sys/ccompile.h>
130#include <zone.h>
131#include <ctype.h>
132#include <limits.h>
133#include <assert.h>
77
134
78#ifdef PORTMAP
79extern void pmap_service(struct svc_req *, SVCXPRT *xprt);
80#endif
81extern void rpcb_service_3(struct svc_req *, SVCXPRT *xprt);
82extern void rpcb_service_4(struct svc_req *, SVCXPRT *xprt);
83extern void read_warmstart(void);
84extern void write_warmstart(void);
85extern int Is_ipv6present(void);
135static sigset_t sigwaitset;
86
136
87#define MAX_FILEDESC_LIMIT 1023
88
89static void terminate(int);
90static void note_refresh(int);
137static void terminate(void);
91static void detachfromtty(void);
92static void parseargs(int, char *[]);
93static void rbllist_add(ulong_t, ulong_t, struct netconfig *, struct netbuf *);
94static int init_transport(struct netconfig *);
95static int check_netconfig(void);
96
97static boolean_t check_hostserv(struct netconfig *, const char *, const char *);
98static int setopt_reuseaddr(int);
99static int setopt_anon_mlp(int);
100static int setup_callit(int);
101
138static void detachfromtty(void);
139static void parseargs(int, char *[]);
140static void rbllist_add(ulong_t, ulong_t, struct netconfig *, struct netbuf *);
141static int init_transport(struct netconfig *);
142static int check_netconfig(void);
143
144static boolean_t check_hostserv(struct netconfig *, const char *, const char *);
145static int setopt_reuseaddr(int);
146static int setopt_anon_mlp(int);
147static int setup_callit(int);
148
149static void rpcb_check_init(void);
150
102/* Global variables */
151/* Global variables */
103#ifdef ND_DEBUG
104int debugging = 1; /* Tell me what's going on */
105#else
106int debugging = 0; /* Tell me what's going on */
152int debugging = 0; /* Tell me what's going on */
107#endif
108static int ipv6flag = 0;
109int doabort = 0; /* When debugging, do an abort on errors */
153static int ipv6flag = 0;
154int doabort = 0; /* When debugging, do an abort on errors */
110static int listen_backlog = 64;
155static int listen_backlog;
156static const int reserved_threads = 8;
157
158/*
159 * list_rbl_lock protects list_rbl
160 * lock order: list_rbl_lock, list_pml_lock
161 */
162rwlock_t list_rbl_lock = DEFAULTRWLOCK;
111rpcblist_ptr list_rbl; /* A list of version 3/4 rpcbind services */
163rpcblist_ptr list_rbl; /* A list of version 3/4 rpcbind services */
164
112char *loopback_dg; /* Datagram loopback transport, for set and unset */
113char *loopback_vc; /* COTS loopback transport, for set and unset */
114char *loopback_vc_ord; /* COTS_ORD loopback transport, for set and unset */
115
165char *loopback_dg; /* Datagram loopback transport, for set and unset */
166char *loopback_vc; /* COTS loopback transport, for set and unset */
167char *loopback_vc_ord; /* COTS_ORD loopback transport, for set and unset */
168
116boolean_t verboselog = B_FALSE;
117boolean_t wrap_enabled = B_FALSE;
118boolean_t allow_indirect = B_TRUE;
119boolean_t local_only = B_FALSE;
169volatile boolean_t verboselog = B_FALSE;
170volatile boolean_t wrap_enabled = B_FALSE;
171volatile boolean_t allow_indirect = B_TRUE;
172volatile boolean_t local_only = B_TRUE;
120
173
121volatile sig_atomic_t sigrefresh;
122
123/* Local Variable */
124static int warmstart = 0; /* Grab a old copy of registrations */
125
126#ifdef PORTMAP
174/* Local Variable */
175static int warmstart = 0; /* Grab a old copy of registrations */
176
177#ifdef PORTMAP
178/*
179 * list_pml_lock protects list_pml
180 * lock order: list_rbl_lock, list_pml_lock
181 */
182rwlock_t list_pml_lock = DEFAULTRWLOCK;
127PMAPLIST *list_pml; /* A list of version 2 rpcbind services */
183PMAPLIST *list_pml; /* A list of version 2 rpcbind services */
184
128char *udptrans; /* Name of UDP transport */
129char *tcptrans; /* Name of TCP transport */
130char *udp_uaddr; /* Universal UDP address */
131char *tcp_uaddr; /* Universal TCP address */
132#endif
133static char servname[] = "rpcbind";
134static char superuser[] = "superuser";
135
136static const char daemon_dir[] = DAEMON_DIR;
137
185char *udptrans; /* Name of UDP transport */
186char *tcptrans; /* Name of TCP transport */
187char *udp_uaddr; /* Universal UDP address */
188char *tcp_uaddr; /* Universal TCP address */
189#endif
190static char servname[] = "rpcbind";
191static char superuser[] = "superuser";
192
193static const char daemon_dir[] = DAEMON_DIR;
194
195static void
196block_signals(void)
197{
198 (void) sigemptyset(&sigwaitset);
199 (void) sigaddset(&sigwaitset, SIGINT);
200 (void) sigaddset(&sigwaitset, SIGTERM);
201 (void) sigaddset(&sigwaitset, SIGQUIT);
202 (void) sigaddset(&sigwaitset, SIGHUP);
203 (void) sigprocmask(SIG_BLOCK, &sigwaitset, NULL);
204
205 /* ignore other signals that could get sent */
206 (void) signal(SIGUSR1, SIG_IGN);
207 (void) signal(SIGUSR2, SIG_IGN);
208}
209
138int
139main(int argc, char *argv[])
140{
141 struct netconfig *nconf;
142 void *nc_handle; /* Net config handle */
143 struct rlimit rl;
210int
211main(int argc, char *argv[])
212{
213 struct netconfig *nconf;
214 void *nc_handle; /* Net config handle */
215 struct rlimit rl;
216 int rpc_svc_fdunlim = 1;
217 int rpc_svc_mode = RPC_SVC_MT_AUTO;
144 int maxrecsz = RPC_MAXDATASIZE;
145 boolean_t can_do_mlp;
146
218 int maxrecsz = RPC_MAXDATASIZE;
219 boolean_t can_do_mlp;
220
221 block_signals();
222
147 parseargs(argc, argv);
148
223 parseargs(argc, argv);
224
149 getrlimit(RLIMIT_NOFILE, &rl);
150
151 if (rl.rlim_cur < MAX_FILEDESC_LIMIT) {
152 if (rl.rlim_max <= MAX_FILEDESC_LIMIT)
153 rl.rlim_cur = rl.rlim_max;
154 else
155 rl.rlim_cur = MAX_FILEDESC_LIMIT;
156 setrlimit(RLIMIT_NOFILE, &rl);
225 if (getrlimit(RLIMIT_NOFILE, &rl) != 0) {
226 syslog(LOG_ERR, "getrlimit failed");
227 } else {
228 rl.rlim_cur = rl.rlim_max;
229 if (setrlimit(RLIMIT_NOFILE, &rl) != 0)
230 syslog(LOG_ERR, "setrlimit failed");
157 }
158 (void) enable_extended_FILE_stdio(-1, -1);
159
160 openlog("rpcbind", LOG_CONS, LOG_DAEMON);
161
162 /*
163 * Create the daemon directory in /var/run
164 */

--- 11 unchanged lines hidden (view full) ---

176 can_do_mlp = priv_ineffect(PRIV_NET_BINDMLP);
177 if (__init_daemon_priv(PU_RESETGROUPS|PU_CLEARLIMITSET, DAEMON_UID,
178 DAEMON_GID, PRIV_NET_PRIVADDR, PRIV_SYS_NFS,
179 can_do_mlp ? PRIV_NET_BINDMLP : NULL, NULL) == -1) {
180 fprintf(stderr, "Insufficient privileges\n");
181 exit(1);
182 }
183
231 }
232 (void) enable_extended_FILE_stdio(-1, -1);
233
234 openlog("rpcbind", LOG_CONS, LOG_DAEMON);
235
236 /*
237 * Create the daemon directory in /var/run
238 */

--- 11 unchanged lines hidden (view full) ---

250 can_do_mlp = priv_ineffect(PRIV_NET_BINDMLP);
251 if (__init_daemon_priv(PU_RESETGROUPS|PU_CLEARLIMITSET, DAEMON_UID,
252 DAEMON_GID, PRIV_NET_PRIVADDR, PRIV_SYS_NFS,
253 can_do_mlp ? PRIV_NET_BINDMLP : NULL, NULL) == -1) {
254 fprintf(stderr, "Insufficient privileges\n");
255 exit(1);
256 }
257
258 myzone = getzoneid();
259
184 /*
260 /*
261 * Set number of file descriptors to unlimited
262 */
263 if (!rpc_control(RPC_SVC_USE_POLLFD, &rpc_svc_fdunlim)) {
264 syslog(LOG_INFO, "unable to set number of FD to unlimited");
265 }
266
267 /*
268 * Tell RPC that we want automatic thread mode.
269 * A new thread will be spawned for each request.
270 */
271 if (!rpc_control(RPC_SVC_MTMODE_SET, &rpc_svc_mode)) {
272 syslog(LOG_ERR, "unable to set automatic MT mode");
273 exit(1);
274 }
275
276 /*
185 * Enable non-blocking mode and maximum record size checks for
186 * connection oriented transports.
187 */
188 if (!rpc_control(RPC_SVC_CONNMAXREC_SET, &maxrecsz)) {
189 syslog(LOG_INFO, "unable to set RPC max record size");
190 }
191
277 * Enable non-blocking mode and maximum record size checks for
278 * connection oriented transports.
279 */
280 if (!rpc_control(RPC_SVC_CONNMAXREC_SET, &maxrecsz)) {
281 syslog(LOG_INFO, "unable to set RPC max record size");
282 }
283
192 nc_handle = setnetconfig(); /* open netconfig file */
193 if (nc_handle == NULL) {
194 syslog(LOG_ERR, "could not read /etc/netconfig");
195 exit(1);
196 }
197 loopback_dg = "";
198 loopback_vc = "";
199 loopback_vc_ord = "";
200#ifdef PORTMAP
201 udptrans = "";
202 tcptrans = "";
203#endif
204
205 {
206 /*
207 * rpcbind is the first application to encounter the
208 * various netconfig files. check_netconfig() verifies
209 * that they are set up correctly and complains loudly
210 * if not.
211 */
212 int trouble;
213
214 trouble = check_netconfig();
215 if (trouble) {
284 {
285 /*
286 * rpcbind is the first application to encounter the
287 * various netconfig files. check_netconfig() verifies
288 * that they are set up correctly and complains loudly
289 * if not.
290 */
291 int trouble;
292
293 trouble = check_netconfig();
294 if (trouble) {
216 syslog(LOG_ERR,
217 "%s: found %d errors with network configuration files. Exiting.",
295 syslog(LOG_ERR, "%s: found %d errors with network "
296 "configuration files. Exiting.", argv[0], trouble);
297 fprintf(stderr, "%s: found %d errors with network "
298 "configuration files. Exiting.\n",
218 argv[0], trouble);
299 argv[0], trouble);
219 fprintf(stderr,
220 "%s: found %d errors with network configuration files. Exiting.\n",
221 argv[0], trouble);
222 exit(1);
223 }
224 }
300 exit(1);
301 }
302 }
303
304 loopback_dg = "";
305 loopback_vc = "";
306 loopback_vc_ord = "";
307#ifdef PORTMAP
308 udptrans = "";
309 tcptrans = "";
310#endif
311
225 ipv6flag = Is_ipv6present();
226 rpcb_check_init();
312 ipv6flag = Is_ipv6present();
313 rpcb_check_init();
227 while (nconf = getnetconfig(nc_handle)) {
314
315 nc_handle = setnetconfig(); /* open netconfig file */
316 if (nc_handle == NULL) {
317 syslog(LOG_ERR, "could not read /etc/netconfig");
318 exit(1);
319 }
320 while ((nconf = getnetconfig(nc_handle)) != NULL) {
228 if (nconf->nc_flag & NC_VISIBLE)
229 init_transport(nconf);
230 }
231 endnetconfig(nc_handle);
232
233 if ((loopback_dg[0] == NULL) && (loopback_vc[0] == NULL) &&
234 (loopback_vc_ord[0] == NULL)) {
235 syslog(LOG_ERR, "could not find loopback transports");
236 exit(1);
237 }
238
321 if (nconf->nc_flag & NC_VISIBLE)
322 init_transport(nconf);
323 }
324 endnetconfig(nc_handle);
325
326 if ((loopback_dg[0] == NULL) && (loopback_vc[0] == NULL) &&
327 (loopback_vc_ord[0] == NULL)) {
328 syslog(LOG_ERR, "could not find loopback transports");
329 exit(1);
330 }
331
239 /* catch the usual termination signals for graceful exit */
240 (void) signal(SIGINT, terminate);
241 (void) signal(SIGTERM, terminate);
242 (void) signal(SIGQUIT, terminate);
243 /* ignore others that could get sent */
244 (void) sigset(SIGHUP, note_refresh);
245 (void) signal(SIGUSR1, SIG_IGN);
246 (void) signal(SIGUSR2, SIG_IGN);
247 if (warmstart) {
248 read_warmstart();
249 }
332 if (warmstart) {
333 read_warmstart();
334 }
335
336 /* Create terminate signal handler for graceful exit */
337 if (thr_create(NULL, 0, (void *(*)(void *))terminate, NULL, 0, NULL)) {
338 syslog(LOG_ERR, "Failed to create terminate thread");
339 exit(1);
340 }
341
250 if (debugging) {
251 printf("rpcbind debugging enabled.");
252 if (doabort) {
253 printf(" Will abort on errors!\n");
254 } else {
255 printf("\n");
256 }
257 } else {
258 detachfromtty();
259 }
260
261 /* These are basic privileges we do not need */
262 __fini_daemon_priv(PRIV_PROC_EXEC, PRIV_PROC_SESSION,
263 PRIV_FILE_LINK_ANY, PRIV_PROC_INFO, (char *)NULL);
264
342 if (debugging) {
343 printf("rpcbind debugging enabled.");
344 if (doabort) {
345 printf(" Will abort on errors!\n");
346 } else {
347 printf("\n");
348 }
349 } else {
350 detachfromtty();
351 }
352
353 /* These are basic privileges we do not need */
354 __fini_daemon_priv(PRIV_PROC_EXEC, PRIV_PROC_SESSION,
355 PRIV_FILE_LINK_ANY, PRIV_PROC_INFO, (char *)NULL);
356
265 my_svc_run();
357 svc_run();
266 syslog(LOG_ERR, "svc_run returned unexpectedly");
267 rpcbind_abort();
268 /* NOTREACHED */
269}
270
271/*
272 * Increments a counter each time a problem is found with the network
273 * configuration information.

--- 12 unchanged lines hidden (view full) ---

286 nc = setnetconfig();
287 if (nc == NULL) {
288 if (debugging)
289 fprintf(stderr,
290 "setnetconfig() failed: %s\n", nc_sperror());
291 syslog(LOG_ALERT, "setnetconfig() failed: %s", nc_sperror());
292 return (1);
293 }
358 syslog(LOG_ERR, "svc_run returned unexpectedly");
359 rpcbind_abort();
360 /* NOTREACHED */
361}
362
363/*
364 * Increments a counter each time a problem is found with the network
365 * configuration information.

--- 12 unchanged lines hidden (view full) ---

378 nc = setnetconfig();
379 if (nc == NULL) {
380 if (debugging)
381 fprintf(stderr,
382 "setnetconfig() failed: %s\n", nc_sperror());
383 syslog(LOG_ALERT, "setnetconfig() failed: %s", nc_sperror());
384 return (1);
385 }
294 while (np = getnetconfig(nc)) {
386 while ((np = getnetconfig(nc)) != NULL) {
295 if ((np->nc_flag & NC_VISIBLE) == 0)
296 continue;
297 if (debugging)
298 fprintf(stderr, "checking netid \"%s\"\n",
299 np->nc_netid);
300 if (strcmp(np->nc_protofmly, NC_LOOPBACK) == 0)
301 switch (np->nc_semantics) {
302 case NC_TPI_CLTS:

--- 22 unchanged lines hidden (view full) ---

325 for (i = 0; i < np->nc_nlookups; i++) {
326 char *libname = np->nc_lookups[i];
327
328 if ((dlcookie = dlopen(libname, RTLD_LAZY)) == NULL) {
329 char *dlerrstr;
330
331 dlerrstr = dlerror();
332 if (debugging) {
387 if ((np->nc_flag & NC_VISIBLE) == 0)
388 continue;
389 if (debugging)
390 fprintf(stderr, "checking netid \"%s\"\n",
391 np->nc_netid);
392 if (strcmp(np->nc_protofmly, NC_LOOPBACK) == 0)
393 switch (np->nc_semantics) {
394 case NC_TPI_CLTS:

--- 22 unchanged lines hidden (view full) ---

417 for (i = 0; i < np->nc_nlookups; i++) {
418 char *libname = np->nc_lookups[i];
419
420 if ((dlcookie = dlopen(libname, RTLD_LAZY)) == NULL) {
421 char *dlerrstr;
422
423 dlerrstr = dlerror();
424 if (debugging) {
333 fprintf(stderr,
334 "\tnetid %s: dlopen of name-to-address library %s failed\ndlerror: %s",
425 fprintf(stderr, "\tnetid %s: dlopen of "
426 "name-to-address library %s "
427 "failed\ndlerror: %s",
335 np->nc_netid, libname,
336 dlerrstr ? dlerrstr : "");
337 }
428 np->nc_netid, libname,
429 dlerrstr ? dlerrstr : "");
430 }
338 syslog(LOG_ERR,
339 "netid %s: dlopen of name-to-address library %s failed",
431 syslog(LOG_ERR, "netid %s: dlopen of "
432 "name-to-address library %s failed",
340 np->nc_netid, libname);
341 if (dlerrstr)
342 syslog(LOG_ERR, "%s", dlerrstr);
343 busted++;
344 } else {
345 if (debugging)
433 np->nc_netid, libname);
434 if (dlerrstr)
435 syslog(LOG_ERR, "%s", dlerrstr);
436 busted++;
437 } else {
438 if (debugging)
346 fprintf(stderr,
347 "\tdlopen of name-to-address library %s succeeded\n", libname);
439 fprintf(stderr, "\tdlopen of "
440 "name-to-address library %s "
441 "succeeded\n", libname);
348 (void) dlclose(dlcookie);
349 }
350 }
351 nconf = getnetconfigent(np->nc_netid);
352
353 if (!check_hostserv(nconf, HOST_SELF, ""))
354 busted++;
355 if (!check_hostserv(nconf, HOST_SELF_CONNECT, ""))

--- 44 unchanged lines hidden (view full) ---

400static int
401init_transport(struct netconfig *nconf)
402{
403 int fd;
404 struct t_bind *taddr, *baddr;
405 SVCXPRT *my_xprt;
406 struct nd_addrlist *nas;
407 struct nd_hostserv hs;
442 (void) dlclose(dlcookie);
443 }
444 }
445 nconf = getnetconfigent(np->nc_netid);
446
447 if (!check_hostserv(nconf, HOST_SELF, ""))
448 busted++;
449 if (!check_hostserv(nconf, HOST_SELF_CONNECT, ""))

--- 44 unchanged lines hidden (view full) ---

494static int
495init_transport(struct netconfig *nconf)
496{
497 int fd;
498 struct t_bind *taddr, *baddr;
499 SVCXPRT *my_xprt;
500 struct nd_addrlist *nas;
501 struct nd_hostserv hs;
408 int status; /* bound checking ? */
409 static int msgprt = 0;
410
411 if ((nconf->nc_semantics != NC_TPI_CLTS) &&
412 (nconf->nc_semantics != NC_TPI_COTS) &&
413 (nconf->nc_semantics != NC_TPI_COTS_ORD))
414 return (1); /* not my type */
415
416 if ((strcmp(nconf->nc_protofmly, NC_INET6) == 0) && !ipv6flag) {
417 if (!msgprt)
502 static int msgprt = 0;
503
504 if ((nconf->nc_semantics != NC_TPI_CLTS) &&
505 (nconf->nc_semantics != NC_TPI_COTS) &&
506 (nconf->nc_semantics != NC_TPI_COTS_ORD))
507 return (1); /* not my type */
508
509 if ((strcmp(nconf->nc_protofmly, NC_INET6) == 0) && !ipv6flag) {
510 if (!msgprt)
418 syslog(LOG_DEBUG,
419"/etc/netconfig has IPv6 entries but IPv6 is not configured");
511 syslog(LOG_DEBUG, "/etc/netconfig has IPv6 entries but "
512 "IPv6 is not configured");
420 msgprt++;
421 return (1);
422 }
513 msgprt++;
514 return (1);
515 }
423#ifdef ND_DEBUG
424 {
425 int i;
426 char **s;
427
516
428 (void) fprintf(stderr, "%s: %d lookup routines :\n",
429 nconf->nc_netid, nconf->nc_nlookups);
430 for (i = 0, s = nconf->nc_lookups; i < nconf->nc_nlookups; i++, s++)
431 fprintf(stderr, "[%d] - %s\n", i, *s);
432 }
433#endif
434
435 if ((fd = t_open(nconf->nc_device, O_RDWR, NULL)) < 0) {
436 syslog(LOG_ERR, "%s: cannot open connection: %s",
437 nconf->nc_netid, t_errlist[t_errno]);
438 return (1);
439 }
440
441 if (is_system_labeled() &&
442 (strcmp(nconf->nc_protofmly, NC_INET) == 0 ||

--- 22 unchanged lines hidden (view full) ---

465 hs.h_host = HOST_SELF;
466 hs.h_serv = servname;
467 if (netdir_getbyname(nconf, &hs, &nas))
468 goto error;
469
470 /* Copy the address */
471 taddr->addr.len = nas->n_addrs->len;
472 memcpy(taddr->addr.buf, nas->n_addrs->buf, (int)nas->n_addrs->len);
517 if ((fd = t_open(nconf->nc_device, O_RDWR, NULL)) < 0) {
518 syslog(LOG_ERR, "%s: cannot open connection: %s",
519 nconf->nc_netid, t_errlist[t_errno]);
520 return (1);
521 }
522
523 if (is_system_labeled() &&
524 (strcmp(nconf->nc_protofmly, NC_INET) == 0 ||

--- 22 unchanged lines hidden (view full) ---

547 hs.h_host = HOST_SELF;
548 hs.h_serv = servname;
549 if (netdir_getbyname(nconf, &hs, &nas))
550 goto error;
551
552 /* Copy the address */
553 taddr->addr.len = nas->n_addrs->len;
554 memcpy(taddr->addr.buf, nas->n_addrs->buf, (int)nas->n_addrs->len);
473#ifdef ND_DEBUG
474 {
475 /* for debugging print out our universal address */
476 char *uaddr;
477
478 uaddr = taddr2uaddr(nconf, nas->n_addrs);
479 (void) fprintf(stderr, "rpcbind : my address is %s\n", uaddr);
480 (void) free(uaddr);
481 }
482#endif
483 netdir_free((char *)nas, ND_ADDRLIST);
484
485 if (nconf->nc_semantics == NC_TPI_CLTS)
486 taddr->qlen = 0;
487 else
488 taddr->qlen = listen_backlog;
489
490 if (strcmp(nconf->nc_proto, NC_TCP) == 0) {
491 /*
492 * Sm: If we are running then set SO_REUSEADDR option
493 * so that we can bind to our preferred address even if
494 * previous connections are in FIN_WAIT state
495 */
555 netdir_free((char *)nas, ND_ADDRLIST);
556
557 if (nconf->nc_semantics == NC_TPI_CLTS)
558 taddr->qlen = 0;
559 else
560 taddr->qlen = listen_backlog;
561
562 if (strcmp(nconf->nc_proto, NC_TCP) == 0) {
563 /*
564 * Sm: If we are running then set SO_REUSEADDR option
565 * so that we can bind to our preferred address even if
566 * previous connections are in FIN_WAIT state
567 */
496#ifdef ND_DEBUG
497 fprintf(stdout, "Setting SO_REUSEADDR.\n");
498#endif
499 if (setopt_reuseaddr(fd) == -1) {
500 syslog(LOG_ERR, "Couldn't set SO_REUSEADDR option");
501 }
502 }
503
504 if (t_bind(fd, taddr, baddr) != 0) {
505 syslog(LOG_ERR, "%s: cannot bind: %s",
506 nconf->nc_netid, t_errlist[t_errno]);
507 goto error;
508 }
509
568 if (setopt_reuseaddr(fd) == -1) {
569 syslog(LOG_ERR, "Couldn't set SO_REUSEADDR option");
570 }
571 }
572
573 if (t_bind(fd, taddr, baddr) != 0) {
574 syslog(LOG_ERR, "%s: cannot bind: %s",
575 nconf->nc_netid, t_errlist[t_errno]);
576 goto error;
577 }
578
579 if (nconf->nc_semantics != NC_TPI_CLTS && taddr->qlen != baddr->qlen)
580 syslog(LOG_NOTICE, "%s: unable to set listen backlog to %d "
581 "(negotiated: %d)", nconf->nc_netid, taddr->qlen,
582 baddr->qlen);
510
511 if (memcmp(taddr->addr.buf, baddr->addr.buf, (int)baddr->addr.len)) {
512 syslog(LOG_ERR, "%s: address in use", nconf->nc_netid);
513 goto error;
514 }
515
583
584 if (memcmp(taddr->addr.buf, baddr->addr.buf, (int)baddr->addr.len)) {
585 syslog(LOG_ERR, "%s: address in use", nconf->nc_netid);
586 goto error;
587 }
588
516 my_xprt = (SVCXPRT *)svc_tli_create(fd, nconf, baddr, 0, 0);
517 if (my_xprt == (SVCXPRT *)NULL) {
589 my_xprt = svc_tli_create(fd, nconf, baddr, 0, 0);
590 if (my_xprt == NULL) {
518 syslog(LOG_ERR, "%s: could not create service",
519 nconf->nc_netid);
520 goto error;
521 }
522
523 /* set up multicast address for RPC CALL_IT, IPv6 */
524
525 if ((strcmp(nconf->nc_protofmly, NC_INET6) == 0) &&
526 (strcmp(nconf->nc_proto, NC_UDP) == 0)) {
527 if (setup_callit(fd) < 0) {
591 syslog(LOG_ERR, "%s: could not create service",
592 nconf->nc_netid);
593 goto error;
594 }
595
596 /* set up multicast address for RPC CALL_IT, IPv6 */
597
598 if ((strcmp(nconf->nc_protofmly, NC_INET6) == 0) &&
599 (strcmp(nconf->nc_proto, NC_UDP) == 0)) {
600 if (setup_callit(fd) < 0) {
528 syslog(LOG_ERR, "Unable to join IPv6 multicast group \
529for rpc broadcast %s", RPCB_MULTICAST_ADDR);
601 syslog(LOG_ERR, "Unable to join IPv6 multicast group "
602 "for rpc broadcast %s", RPCB_MULTICAST_ADDR);
530 }
531 }
532
533 if (strcmp(nconf->nc_proto, NC_TCP) == 0) {
603 }
604 }
605
606 if (strcmp(nconf->nc_proto, NC_TCP) == 0) {
534 svc_control(my_xprt, SVCSET_KEEPALIVE, (void *) TRUE);
607 svc_control(my_xprt, SVCSET_KEEPALIVE, (void *) TRUE);
535 }
536
537#ifdef PORTMAP
538 /*
539 * Register both the versions for tcp/ip and udp/ip
540 */
541 if ((strcmp(nconf->nc_protofmly, NC_INET) == 0) &&
542 ((strcmp(nconf->nc_proto, NC_TCP) == 0) ||
543 (strcmp(nconf->nc_proto, NC_UDP) == 0))) {
544 PMAPLIST *pml;
545
546 if (!svc_register(my_xprt, PMAPPROG, PMAPVERS,
547 pmap_service, NULL)) {
548 syslog(LOG_ERR, "could not register on %s",
549 nconf->nc_netid);
550 goto error;
551 }
608 }
609
610#ifdef PORTMAP
611 /*
612 * Register both the versions for tcp/ip and udp/ip
613 */
614 if ((strcmp(nconf->nc_protofmly, NC_INET) == 0) &&
615 ((strcmp(nconf->nc_proto, NC_TCP) == 0) ||
616 (strcmp(nconf->nc_proto, NC_UDP) == 0))) {
617 PMAPLIST *pml;
618
619 if (!svc_register(my_xprt, PMAPPROG, PMAPVERS,
620 pmap_service, NULL)) {
621 syslog(LOG_ERR, "could not register on %s",
622 nconf->nc_netid);
623 goto error;
624 }
552 pml = (PMAPLIST *)malloc((uint_t)sizeof (PMAPLIST));
553 if (pml == (PMAPLIST *)NULL) {
625 pml = malloc(sizeof (PMAPLIST));
626 if (pml == NULL) {
554 syslog(LOG_ERR, "no memory!");
555 exit(1);
556 }
557 pml->pml_map.pm_prog = PMAPPROG;
558 pml->pml_map.pm_vers = PMAPVERS;
559 pml->pml_map.pm_port = PMAPPORT;
560 if (strcmp(nconf->nc_proto, NC_TCP) == 0) {
561 if (tcptrans[0]) {

--- 19 unchanged lines hidden (view full) ---

581 /* Let's snarf the universal address */
582 /* "h1.h2.h3.h4.p1.p2" */
583 udp_uaddr = taddr2uaddr(nconf, &baddr->addr);
584 }
585 pml->pml_next = list_pml;
586 list_pml = pml;
587
588 /* Add version 3 information */
627 syslog(LOG_ERR, "no memory!");
628 exit(1);
629 }
630 pml->pml_map.pm_prog = PMAPPROG;
631 pml->pml_map.pm_vers = PMAPVERS;
632 pml->pml_map.pm_port = PMAPPORT;
633 if (strcmp(nconf->nc_proto, NC_TCP) == 0) {
634 if (tcptrans[0]) {

--- 19 unchanged lines hidden (view full) ---

654 /* Let's snarf the universal address */
655 /* "h1.h2.h3.h4.p1.p2" */
656 udp_uaddr = taddr2uaddr(nconf, &baddr->addr);
657 }
658 pml->pml_next = list_pml;
659 list_pml = pml;
660
661 /* Add version 3 information */
589 pml = (PMAPLIST *)malloc((uint_t)sizeof (PMAPLIST));
590 if (pml == (PMAPLIST *)NULL) {
662 pml = malloc(sizeof (PMAPLIST));
663 if (pml == NULL) {
591 syslog(LOG_ERR, "no memory!");
592 exit(1);
593 }
594 pml->pml_map = list_pml->pml_map;
595 pml->pml_map.pm_vers = RPCBVERS;
596 pml->pml_next = list_pml;
597 list_pml = pml;
598
599 /* Add version 4 information */
664 syslog(LOG_ERR, "no memory!");
665 exit(1);
666 }
667 pml->pml_map = list_pml->pml_map;
668 pml->pml_map.pm_vers = RPCBVERS;
669 pml->pml_next = list_pml;
670 list_pml = pml;
671
672 /* Add version 4 information */
600 pml = (PMAPLIST *)malloc((uint_t)sizeof (PMAPLIST));
601 if (pml == (PMAPLIST *)NULL) {
673 pml = malloc(sizeof (PMAPLIST));
674 if (pml == NULL) {
602 syslog(LOG_ERR, "no memory!");
603 exit(1);
604 }
605 pml->pml_map = list_pml->pml_map;
606 pml->pml_map.pm_vers = RPCBVERS4;
607 pml->pml_next = list_pml;
608 list_pml = pml;
609

--- 23 unchanged lines hidden (view full) ---

633 loopback_dg = strdup(nconf->nc_netid);
634 else if (nconf->nc_semantics == NC_TPI_COTS)
635 loopback_vc = strdup(nconf->nc_netid);
636 else if (nconf->nc_semantics == NC_TPI_COTS_ORD)
637 loopback_vc_ord = strdup(nconf->nc_netid);
638 }
639
640 /* decide if bound checking works for this transport */
675 syslog(LOG_ERR, "no memory!");
676 exit(1);
677 }
678 pml->pml_map = list_pml->pml_map;
679 pml->pml_map.pm_vers = RPCBVERS4;
680 pml->pml_next = list_pml;
681 list_pml = pml;
682

--- 23 unchanged lines hidden (view full) ---

706 loopback_dg = strdup(nconf->nc_netid);
707 else if (nconf->nc_semantics == NC_TPI_COTS)
708 loopback_vc = strdup(nconf->nc_netid);
709 else if (nconf->nc_semantics == NC_TPI_COTS_ORD)
710 loopback_vc_ord = strdup(nconf->nc_netid);
711 }
712
713 /* decide if bound checking works for this transport */
641 status = add_bndlist(nconf, taddr, baddr);
642#ifdef BIND_DEBUG
643 if (status < 0) {
644 fprintf(stderr, "Error in finding bind status for %s\n",
645 nconf->nc_netid);
646 } else if (status == 0) {
647 fprintf(stderr, "check binding for %s\n",
648 nconf->nc_netid);
649 } else if (status > 0) {
650 fprintf(stderr, "No check binding for %s\n",
651 nconf->nc_netid);
652 }
653#endif
714 (void) add_bndlist(nconf, taddr, baddr);
715
654 /*
655 * rmtcall only supported on CLTS transports for now.
716 /*
717 * rmtcall only supported on CLTS transports for now.
656 * only needed when we are allowing indirect calls
657 */
718 */
658 if (allow_indirect && nconf->nc_semantics == NC_TPI_CLTS) {
659 status = create_rmtcall_fd(nconf);
719 if (nconf->nc_semantics == NC_TPI_CLTS)
720 (void) create_rmtcall_fd(nconf);
660
721
661#ifdef BIND_DEBUG
662 if (status < 0) {
663 fprintf(stderr, "Could not create rmtcall fd for %s\n",
664 nconf->nc_netid);
665 } else {
666 fprintf(stderr, "rmtcall fd for %s is %d\n",
667 nconf->nc_netid, status);
668 }
669#endif
670 }
671 (void) t_free((char *)taddr, T_BIND);
672 (void) t_free((char *)baddr, T_BIND);
673 return (0);
674error:
675 (void) t_free((char *)taddr, T_BIND);
676 (void) t_free((char *)baddr, T_BIND);
677 (void) t_close(fd);
678 return (1);
679}
680
681static void
682rbllist_add(ulong_t prog, ulong_t vers, struct netconfig *nconf,
722 (void) t_free((char *)taddr, T_BIND);
723 (void) t_free((char *)baddr, T_BIND);
724 return (0);
725error:
726 (void) t_free((char *)taddr, T_BIND);
727 (void) t_free((char *)baddr, T_BIND);
728 (void) t_close(fd);
729 return (1);
730}
731
732static void
733rbllist_add(ulong_t prog, ulong_t vers, struct netconfig *nconf,
683 struct netbuf *addr)
734 struct netbuf *addr)
684{
685 rpcblist_ptr rbl;
686
735{
736 rpcblist_ptr rbl;
737
687 rbl = (rpcblist_ptr)malloc((uint_t)sizeof (rpcblist));
688 if (rbl == (rpcblist_ptr)NULL) {
738 rbl = malloc(sizeof (rpcblist));
739 if (rbl == NULL) {
689 syslog(LOG_ERR, "no memory!");
690 exit(1);
691 }
692
693 rbl->rpcb_map.r_prog = prog;
694 rbl->rpcb_map.r_vers = vers;
695 rbl->rpcb_map.r_netid = strdup(nconf->nc_netid);
696 rbl->rpcb_map.r_addr = taddr2uaddr(nconf, addr);
740 syslog(LOG_ERR, "no memory!");
741 exit(1);
742 }
743
744 rbl->rpcb_map.r_prog = prog;
745 rbl->rpcb_map.r_vers = vers;
746 rbl->rpcb_map.r_netid = strdup(nconf->nc_netid);
747 rbl->rpcb_map.r_addr = taddr2uaddr(nconf, addr);
748 if (rbl->rpcb_map.r_addr == NULL)
749 rbl->rpcb_map.r_addr = strdup("");
697 rbl->rpcb_map.r_owner = strdup(superuser);
750 rbl->rpcb_map.r_owner = strdup(superuser);
751
752 if (rbl->rpcb_map.r_netid == NULL || rbl->rpcb_map.r_addr == NULL ||
753 rbl->rpcb_map.r_owner == NULL) {
754 syslog(LOG_ERR, "no memory!");
755 exit(1);
756 }
757
698 rbl->rpcb_next = list_rbl; /* Attach to global list */
699 list_rbl = rbl;
700}
701
702/*
758 rbl->rpcb_next = list_rbl; /* Attach to global list */
759 list_rbl = rbl;
760}
761
762/*
703 * Catch the signal and die
763 * Catch the signal and die, if not SIGHUP
704 */
764 */
705/* ARGSUSED */
706static void
765static void
707terminate(int sig)
766terminate(void)
708{
767{
709 syslog(LOG_ERR, "rpcbind terminating on signal.");
768 int sig;
769
770 for (;;) {
771 sig = sigwait(&sigwaitset);
772 if (sig == SIGHUP) {
773 rpcb_check_init();
774 continue;
775 }
776 if (sig != -1 || errno != EINTR)
777 break;
778 }
779
780 syslog(LOG_ERR, "rpcbind terminating on signal %d.", sig);
781
782 rw_wrlock(&list_rbl_lock);
783#ifdef PORTMAP
784 rw_wrlock(&list_pml_lock);
785#endif
710 write_warmstart(); /* Dump yourself */
786 write_warmstart(); /* Dump yourself */
787
711 exit(2);
712}
713
788 exit(2);
789}
790
714/* ARGSUSED */
715static void
716note_refresh(int sig)
717{
718 sigrefresh = 1;
719}
720
721void
722rpcbind_abort(void)
723{
791void
792rpcbind_abort(void)
793{
794 /*
795 * We need to hold write locks to make sure
796 * write_warmstart() is executed exactly once
797 */
798 rw_wrlock(&list_rbl_lock);
799#ifdef PORTMAP
800 rw_wrlock(&list_pml_lock);
801#endif
724 write_warmstart(); /* Dump yourself */
802 write_warmstart(); /* Dump yourself */
803
725 abort();
726}
727
728/*
729 * detach from tty
730 */
731static void
732detachfromtty(void)

--- 11 unchanged lines hidden (view full) ---

744 exit(0);
745 }
746 setsid();
747 (void) open("/dev/null", O_RDWR, 0);
748 dup(0);
749 dup(0);
750}
751
804 abort();
805}
806
807/*
808 * detach from tty
809 */
810static void
811detachfromtty(void)

--- 11 unchanged lines hidden (view full) ---

823 exit(0);
824 }
825 setsid();
826 (void) open("/dev/null", O_RDWR, 0);
827 dup(0);
828 dup(0);
829}
830
831static int
832convert_int(int *val, char *str)
833{
834 long lval;
835
836 if (str == NULL || !isdigit(*str))
837 return (-1);
838
839 lval = strtol(str, &str, 10);
840 if (*str != '\0' || lval > INT_MAX)
841 return (-2);
842
843 *val = (int)lval;
844 return (0);
845}
846
847static int get_smf_iprop(const char *, int, int, int);
848
752/* get command line options */
753static void
754parseargs(int argc, char *argv[])
755{
756 int c;
757 int tmp;
758
849/* get command line options */
850static void
851parseargs(int argc, char *argv[])
852{
853 int c;
854 int tmp;
855
856 listen_backlog = get_smf_iprop("listen_backlog", 64, 1, INT_MAX);
857
759 while ((c = getopt(argc, argv, "dwal:")) != EOF) {
760 switch (c) {
761 case 'd':
762 debugging = 1;
763 break;
764 case 'a':
765 doabort = 1; /* when debugging, do an abort on */
766 break; /* errors; for rpcbind developers */
767 /* only! */
768 case 'w':
769 warmstart = 1;
770 break;
771
772 case 'l':
858 while ((c = getopt(argc, argv, "dwal:")) != EOF) {
859 switch (c) {
860 case 'd':
861 debugging = 1;
862 break;
863 case 'a':
864 doabort = 1; /* when debugging, do an abort on */
865 break; /* errors; for rpcbind developers */
866 /* only! */
867 case 'w':
868 warmstart = 1;
869 break;
870
871 case 'l':
773 if (sscanf(optarg, "%d", &tmp)) {
774 if (tmp > listen_backlog) {
775 listen_backlog = tmp;
776 }
872 if (convert_int(&tmp, optarg) != 0 || tmp < 1) {
873 (void) fprintf(stderr, "%s: invalid "
874 "listen_backlog option, using defaults\n",
875 argv[0]);
876 break;
777 }
877 }
878 listen_backlog = tmp;
778 break;
779 default: /* error */
780 fprintf(stderr,
879 break;
880 default: /* error */
881 fprintf(stderr,
781 "usage: rpcbind [-d] [-w] [-l listen_backlog]\n");
882 "usage: rpcbind [-d] [-w] [-l listen_backlog]\n");
782 exit(1);
783 }
784 }
785 if (doabort && !debugging) {
786 fprintf(stderr,
787 "-a (abort) specified without -d "
788 "(debugging) -- ignored.\n");
789 doabort = 0;

--- 135 unchanged lines hidden (view full) ---

925} logmsg;
926
927static logmsg *loghead = NULL;
928static logmsg **logtailp = &loghead;
929static mutex_t logmutex = DEFAULTMUTEX;
930static cond_t logcond = DEFAULTCV;
931static int logcount = 0;
932
883 exit(1);
884 }
885 }
886 if (doabort && !debugging) {
887 fprintf(stderr,
888 "-a (abort) specified without -d "
889 "(debugging) -- ignored.\n");
890 doabort = 0;

--- 135 unchanged lines hidden (view full) ---

1026} logmsg;
1027
1028static logmsg *loghead = NULL;
1029static logmsg **logtailp = &loghead;
1030static mutex_t logmutex = DEFAULTMUTEX;
1031static cond_t logcond = DEFAULTCV;
1032static int logcount = 0;
1033
933/*ARGSUSED*/
1034/* ARGSUSED */
934static void * __NORETURN
935logthread(void *arg)
936{
1035static void * __NORETURN
1036logthread(void *arg)
1037{
937 while (1) {
1038 for (;;) {
938 logmsg *msg;
939 (void) mutex_lock(&logmutex);
940 while ((msg = loghead) == NULL)
941 (void) cond_wait(&logcond, &logmutex);
942
943 loghead = msg->log_next;
944 logcount--;
945 if (loghead == NULL) {

--- 10 unchanged lines hidden (view full) ---

956static boolean_t
957get_smf_prop(const char *var, boolean_t def_val)
958{
959 scf_simple_prop_t *prop;
960 uint8_t *val;
961 boolean_t res = def_val;
962
963 prop = scf_simple_prop_get(NULL, NULL, "config", var);
1039 logmsg *msg;
1040 (void) mutex_lock(&logmutex);
1041 while ((msg = loghead) == NULL)
1042 (void) cond_wait(&logcond, &logmutex);
1043
1044 loghead = msg->log_next;
1045 logcount--;
1046 if (loghead == NULL) {

--- 10 unchanged lines hidden (view full) ---

1057static boolean_t
1058get_smf_prop(const char *var, boolean_t def_val)
1059{
1060 scf_simple_prop_t *prop;
1061 uint8_t *val;
1062 boolean_t res = def_val;
1063
1064 prop = scf_simple_prop_get(NULL, NULL, "config", var);
964 if (prop) {
1065 if (prop != NULL) {
965 if ((val = scf_simple_prop_next_boolean(prop)) != NULL)
966 res = (*val == 0) ? B_FALSE : B_TRUE;
967 scf_simple_prop_free(prop);
968 }
969
970 if (prop == NULL || val == NULL) {
971 syslog(LOG_ALERT, "no value for config/%s (%s). "
972 "Using default \"%s\"", var, scf_strerror(scf_error()),
973 def_val ? "true" : "false");
974 }
975
976 return (res);
977}
978
1066 if ((val = scf_simple_prop_next_boolean(prop)) != NULL)
1067 res = (*val == 0) ? B_FALSE : B_TRUE;
1068 scf_simple_prop_free(prop);
1069 }
1070
1071 if (prop == NULL || val == NULL) {
1072 syslog(LOG_ALERT, "no value for config/%s (%s). "
1073 "Using default \"%s\"", var, scf_strerror(scf_error()),
1074 def_val ? "true" : "false");
1075 }
1076
1077 return (res);
1078}
1079
1080static int
1081get_smf_iprop(const char *var, int def_val, int min, int max)
1082{
1083 scf_simple_prop_t *prop;
1084 int64_t *val;
1085 int res = def_val;
1086
1087 prop = scf_simple_prop_get(NULL, NULL, "config", var);
1088 if (prop != NULL) {
1089 if ((val = scf_simple_prop_next_integer(prop)) != NULL) {
1090 if (*val < min || *val > max)
1091 syslog(LOG_ALERT, "value for config/%s out of "
1092 "range. Using default %d", var, def_val);
1093 else
1094 res = (int)*val;
1095 }
1096 scf_simple_prop_free(prop);
1097 }
1098
1099 if (prop == NULL || val == NULL) {
1100 syslog(LOG_ALERT, "no value for config/%s (%s). "
1101 "Using default %d", var, scf_strerror(scf_error()),
1102 def_val);
1103 }
1104
1105 return (res);
1106}
1107
979/*
980 * Initialize: read the configuration parameters from SMF.
981 * This function must be idempotent because it can be called from the
1108/*
1109 * Initialize: read the configuration parameters from SMF.
1110 * This function must be idempotent because it can be called from the
982 * main poll() loop in my_svc_run().
1111 * signal handler.
983 */
1112 */
984void
1113static void
985rpcb_check_init(void)
986{
987 thread_t tid;
1114rpcb_check_init(void)
1115{
1116 thread_t tid;
1117 int max_threads;
988 static int thr_running;
989
990 wrap_enabled = get_smf_prop("enable_tcpwrappers", B_FALSE);
991 verboselog = get_smf_prop("verbose_logging", B_FALSE);
992 allow_indirect = get_smf_prop("allow_indirect", B_TRUE);
1118 static int thr_running;
1119
1120 wrap_enabled = get_smf_prop("enable_tcpwrappers", B_FALSE);
1121 verboselog = get_smf_prop("verbose_logging", B_FALSE);
1122 allow_indirect = get_smf_prop("allow_indirect", B_TRUE);
993 local_only = get_smf_prop("local_only", B_FALSE);
1123 local_only = get_smf_prop("local_only", B_TRUE);
994
995 if (wrap_enabled && !thr_running) {
996 (void) thr_create(NULL, 0, logthread, NULL, THR_DETACHED, &tid);
997 thr_running = 1;
998 }
1124
1125 if (wrap_enabled && !thr_running) {
1126 (void) thr_create(NULL, 0, logthread, NULL, THR_DETACHED, &tid);
1127 thr_running = 1;
1128 }
1129
1130 /*
1131 * Set the maximum number of threads.
1132 */
1133 max_threads = get_smf_iprop("max_threads", 72, 1, INT_MAX);
1134 if (!rpc_control(RPC_SVC_THRMAX_SET, &max_threads)) {
1135 int tmp;
1136
1137 /*
1138 * The following rpc_control() call cannot fail
1139 */
1140 if (!rpc_control(RPC_SVC_THRMAX_GET, &tmp))
1141 assert(0);
1142
1143 if (tmp != max_threads) {
1144 syslog(LOG_ERR, "setting max_threads to %d failed, "
1145 "using %d worker threads", max_threads, tmp);
1146 max_threads = tmp;
1147 }
1148 }
1149
1150 /*
1151 * Set rpcb_rmtcalls_max.
1152 */
1153 if (max_threads < reserved_threads)
1154 set_rpcb_rmtcalls_max(0);
1155 else
1156 set_rpcb_rmtcalls_max(max_threads - reserved_threads);
999}
1000
1001/*
1002 * qsyslog() - queue a request for syslog(); if syslog blocks, the other
1003 * thread blocks; we make sure we don't run out of memory by allowing
1004 * only a limited number of outstandig syslog() requests.
1005 */
1006void
1007qsyslog(int pri, const char *fmt, ...)
1008{
1009 logmsg *msg = malloc(sizeof (*msg));
1157}
1158
1159/*
1160 * qsyslog() - queue a request for syslog(); if syslog blocks, the other
1161 * thread blocks; we make sure we don't run out of memory by allowing
1162 * only a limited number of outstandig syslog() requests.
1163 */
1164void
1165qsyslog(int pri, const char *fmt, ...)
1166{
1167 logmsg *msg = malloc(sizeof (*msg));
1010 int oldcount;
1011 va_list ap;
1012
1013 if (msg == NULL)
1014 return;
1015
1016 msg->log_pri = pri;
1017
1018 va_start(ap, fmt);
1019 (void) vsnprintf(msg->log_msg, sizeof (msg->log_msg), fmt, ap);
1020 va_end(ap);
1021
1022 msg->log_next = NULL;
1023
1024 (void) mutex_lock(&logmutex);
1168 va_list ap;
1169
1170 if (msg == NULL)
1171 return;
1172
1173 msg->log_pri = pri;
1174
1175 va_start(ap, fmt);
1176 (void) vsnprintf(msg->log_msg, sizeof (msg->log_msg), fmt, ap);
1177 va_end(ap);
1178
1179 msg->log_next = NULL;
1180
1181 (void) mutex_lock(&logmutex);
1025 oldcount = logcount;
1026 if (logcount < MAXLOG) {
1182 if (logcount < MAXLOG) {
1183 if (logcount == 0)
1184 (void) cond_signal(&logcond);
1027 logcount++;
1028 *logtailp = msg;
1029 logtailp = &msg->log_next;
1185 logcount++;
1186 *logtailp = msg;
1187 logtailp = &msg->log_next;
1188 (void) mutex_unlock(&logmutex);
1030 } else {
1189 } else {
1190 (void) mutex_unlock(&logmutex);
1031 free(msg);
1032 }
1191 free(msg);
1192 }
1033 (void) mutex_unlock(&logmutex);
1034 if (oldcount == 0)
1035 (void) cond_signal(&logcond);
1036}
1193}