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} |