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.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
31 #include <stdio_ext.h>
35 #include <sys/types.h>
49 #include <sys/param.h>
50 #include <sys/systeminfo.h>
51 #include <sys/thread.h>
54 #include <sys/fs_reparse.h>
55 #include <priv_utils.h>
56 #include <rpcsvc/daemon_utils.h>
58 #define REPARSED_CMD_OPTS "v"
59 #define DOOR_RESULT_BUFSZ (MAXPATHLEN + sizeof (reparsed_door_res_t))
60 #define SAFETY_BUFFER 8*1024
63 static int verbose
= 0;
65 static int start_reparsed_svcs();
66 static void daemonize(void);
67 static void reparsed_door_call_error(int error
, int buflen
);
68 static void reparsed_doorfunc(void *cookie
, char *argp
, size_t arg_size
,
69 door_desc_t
*dp
, uint_t n_desc
);
74 syslog(LOG_ERR
, "Usage: %s", MyName
);
75 syslog(LOG_ERR
, "\t[-v]\t\tverbose error messages)");
82 syslog(LOG_ERR
, "SIGHUP received: ignored");
83 (void) signal(SIGHUP
, warn_hup
);
87 * Processing for daemonization
94 syslog(LOG_ERR
, "reparsed: can't fork - errno %d", errno
);
100 default: /* parent */
106 * Close stdin, stdout, and stderr.
107 * Open again to redirect input+output
112 (void) open("/dev/null", O_RDONLY
);
113 (void) open("/dev/null", O_WRONLY
);
119 main(int argc
, char *argv
[])
127 * There is no check for non-global zone and Trusted Extensions.
128 * Reparsed works in both of these environments as long as the
129 * services that use reparsed are supported.
133 if (geteuid() != 0) {
134 syslog(LOG_ERR
, "%s must be run as root", MyName
);
138 while ((c
= getopt(argc
, argv
, REPARSED_CMD_OPTS
)) != EOF
) {
149 openlog(MyName
, LOG_PID
| LOG_NDELAY
, LOG_DAEMON
);
151 (void) _create_daemon_lock(REPARSED
, DAEMON_UID
, DAEMON_GID
);
152 (void) enable_extended_FILE_stdio(-1, -1);
153 switch (_enter_daemon_lock(REPARSED
)) {
157 syslog(LOG_ERR
, "Error locking for %s", REPARSED
);
160 /* daemon was already running */
164 (void) signal(SIGHUP
, warn_hup
);
167 * Make the process a privilege aware daemon.
168 * Only "basic" privileges are required.
171 if (__init_daemon_priv(PU_RESETGROUPS
|PU_CLEARLIMITSET
, 0, 0,
172 (char *)NULL
) == -1) {
173 syslog(LOG_ERR
, "should be run with sufficient privileges");
178 * Clear basic privileges not required by reparsed.
180 __fini_daemon_priv(PRIV_PROC_FORK
, PRIV_PROC_EXEC
, PRIV_PROC_SESSION
,
181 PRIV_FILE_LINK_ANY
, PRIV_PROC_INFO
, (char *)NULL
);
183 return (start_reparsed_svcs());
187 reparsed_door_call_error(int error
, int buflen
)
189 reparsed_door_res_t rpd_res
;
191 memset(&rpd_res
, 0, sizeof (reparsed_door_res_t
));
192 rpd_res
.res_status
= error
;
193 rpd_res
.res_len
= buflen
;
194 door_return((char *)&rpd_res
, sizeof (reparsed_door_res_t
), NULL
, 0);
196 (void) door_return(NULL
, 0, NULL
, 0);
203 * argp: "service_type:service_data" string
204 * dp & n_desc: not used.
207 reparsed_doorfunc(void *cookie
, char *argp
, size_t arg_size
,
208 door_desc_t
*dp
, uint_t n_desc
)
212 char *svc_type
, *svc_data
;
213 char *cp
, *buf
, *sbuf
, res_buf
[DOOR_RESULT_BUFSZ
];
214 reparsed_door_res_t
*resp
;
216 if ((argp
== NULL
) || (arg_size
== 0)) {
217 reparsed_door_call_error(EINVAL
, 0);
222 syslog(LOG_NOTICE
, "reparsed_door: [%s, %d]", argp
, arg_size
);
224 if ((svc_type
= strdup(argp
)) == NULL
) {
225 reparsed_door_call_error(ENOMEM
, 0);
230 * Door argument string comes in "service_type:service_data" format.
231 * Need to break it into separate "service_type" and "service_data"
232 * string before passing them to reparse_deref() to process them.
234 if ((cp
= strchr(svc_type
, ':')) == NULL
) {
236 reparsed_door_call_error(EINVAL
, 0);
243 * Setup buffer for reparse_deref(). 'bufsz' is the actual
244 * buffer size to hold the result returned by reparse_deref().
246 resp
= (reparsed_door_res_t
*)res_buf
;
247 buf
= resp
->res_data
;
248 bufsz
= sizeof (res_buf
) - sizeof (reparsed_door_res_t
);
251 * reparse_deref() calls the service type plugin library to process
252 * the service data. The plugin library function should understand
253 * the context of the service data and should be the one to XDR the
254 * results before returning it to the caller.
256 err
= reparse_deref(svc_type
, svc_data
, buf
, &bufsz
);
260 "reparsed_deref(svc_type: %s, data: %s, size: %d) -> %d",
261 svc_type
, svc_data
, bufsz
, err
);
269 * bufsz was returned with size needed by reparse_deref().
271 * We cannot use malloc() here because door_return() never
272 * returns, and memory allocated by malloc() would get leaked.
274 sbuf
= alloca(bufsz
+ sizeof (reparsed_door_res_t
));
275 if (sbuf
== NULL
|| stack_inbounds(buf
) == 0 ||
276 stack_inbounds(buf
+ sizeof (reparsed_door_res_t
) +
277 SAFETY_BUFFER
- 1) == 0) {
279 reparsed_door_call_error(ENOMEM
, 0);
283 resp
= (reparsed_door_res_t
*)sbuf
;
284 if ((err
= reparse_deref(svc_type
, svc_data
, resp
->res_data
,
292 reparsed_door_call_error(err
, 0);
299 syslog(LOG_NOTICE
, "reparsed_door_return <buf=%s> size=%d",
302 resp
->res_status
= 0;
303 resp
->res_len
= bufsz
;
304 (void) door_return((char *)resp
, bufsz
+ sizeof (reparsed_door_res_t
),
307 (void) door_return(NULL
, 0, NULL
, 0);
312 start_reparsed_svcs()
317 if ((doorfd
= door_create(reparsed_doorfunc
, NULL
,
318 DOOR_REFUSE_DESC
|DOOR_NO_CANCEL
)) == -1) {
319 syslog(LOG_ERR
, "Unable to create door");
324 * Create a file system path for the door
326 if ((dfd
= open(REPARSED_DOOR
, O_RDWR
|O_CREAT
|O_TRUNC
,
327 S_IRUSR
|S_IWUSR
|S_IRGRP
|S_IROTH
)) == -1) {
328 syslog(LOG_ERR
, "unable to open %s", REPARSED_DOOR
);
329 (void) close(doorfd
);
334 * Clean up any stale associations
336 (void) fdetach(REPARSED_DOOR
);
339 * Register in the kernel namespace for door_ki_open().
341 if (fattach(doorfd
, REPARSED_DOOR
) == -1) {
342 syslog(LOG_ERR
, "Unable to fattach door %s", REPARSED_DOOR
);
343 (void) close(doorfd
);
350 * Wait for incoming calls
356 syslog(LOG_ERR
, "Door server exited");