xref: /illumos-gate/usr/src/cmd/svc/configd/maindoor.c (revision 4c87aefe8930bd07275b8dd2e96ea5f24d93a52e)
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, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #pragma ident	"%Z%%M%	%I%	%E% SMI"
28 
29 #include <assert.h>
30 #include <door.h>
31 #include <errno.h>
32 #include <fcntl.h>
33 #include <pthread.h>
34 #include <signal.h>
35 #include <stdio.h>
36 #include <stdlib.h>
37 #include <sys/stat.h>
38 #include <unistd.h>
39 #include <ucred.h>
40 
41 #include "repcache_protocol.h"
42 #include "configd.h"
43 
44 #define	INVALID_RESULT		((uint32_t)-1U)
45 
46 static int		main_door_fd = -1;
47 
48 /*ARGSUSED*/
49 static void
50 main_switcher(void *cookie, char *argp, size_t arg_size, door_desc_t *desc,
51     uint_t n_desc)
52 {
53 	repository_door_request_t *request;
54 	repository_door_response_t reply;
55 	door_desc_t reply_desc;
56 
57 	thread_info_t *ti = thread_self();
58 
59 	int send_desc = 0;
60 	int fd;
61 
62 	thread_newstate(ti, TI_MAIN_DOOR_CALL);
63 	ti->ti_main_door_request = (void *)argp;
64 
65 	assert(cookie == REPOSITORY_DOOR_COOKIE);
66 
67 	reply.rdr_status = INVALID_RESULT;
68 
69 	if (argp == DOOR_UNREF_DATA) {
70 		backend_fini();
71 
72 		exit(CONFIGD_EXIT_LOST_MAIN_DOOR);
73 	}
74 
75 	/*
76 	 * No file descriptors allowed
77 	 */
78 	assert(n_desc == 0);
79 
80 	/*
81 	 * first, we just check the version
82 	 */
83 	if (arg_size < offsetofend(repository_door_request_t, rdr_version)) {
84 		reply.rdr_status = REPOSITORY_DOOR_FAIL_BAD_REQUEST;
85 		goto fail;
86 	}
87 
88 	/* LINTED alignment */
89 	request = (repository_door_request_t *)argp;
90 	ti->ti_main_door_request = request;
91 
92 	if (request->rdr_version != REPOSITORY_DOOR_VERSION) {
93 		reply.rdr_status = REPOSITORY_DOOR_FAIL_VERSION_MISMATCH;
94 		goto fail;
95 	}
96 
97 	/*
98 	 * Now, check that the argument is of the minimum required size
99 	 */
100 	if (arg_size < offsetofend(repository_door_request_t, rdr_request)) {
101 		reply.rdr_status = REPOSITORY_DOOR_FAIL_BAD_REQUEST;
102 		goto fail;
103 	}
104 
105 	if (door_ucred(&ti->ti_ucred) != 0) {
106 		reply.rdr_status = REPOSITORY_DOOR_FAIL_PERMISSION_DENIED;
107 		goto fail;
108 	}
109 
110 	switch (request->rdr_request) {
111 	case REPOSITORY_DOOR_REQUEST_CONNECT:
112 		fd = -1;
113 		reply.rdr_status = create_connection(ti->ti_ucred, request,
114 		    arg_size, &fd);
115 		if (reply.rdr_status != REPOSITORY_DOOR_SUCCESS) {
116 			assert(fd == -1);
117 			goto fail;
118 		}
119 		assert(fd != -1);
120 		reply_desc.d_attributes = DOOR_DESCRIPTOR | DOOR_RELEASE;
121 		reply_desc.d_data.d_desc.d_descriptor = fd;
122 		send_desc = 1;
123 		break;
124 
125 	default:
126 		reply.rdr_status = REPOSITORY_DOOR_FAIL_BAD_REQUEST;
127 		goto fail;
128 	}
129 
130 fail:
131 	assert(reply.rdr_status != INVALID_RESULT);
132 
133 	thread_newstate(ti, TI_DOOR_RETURN);
134 	ti->ti_main_door_request = NULL;
135 
136 	(void) door_return((char *)&reply, sizeof (reply),
137 	    &reply_desc, (send_desc)? 1:0);
138 	(void) door_return(NULL, 0, NULL, 0);
139 }
140 
141 int
142 setup_main_door(const char *doorpath)
143 {
144 	mode_t oldmask;
145 	int fd;
146 
147 	int door_flags = DOOR_UNREF | DOOR_REFUSE_DESC;
148 #ifdef DOOR_NO_CANCEL
149 	door_flags |= DOOR_NO_CANCEL;
150 #endif
151 	if ((main_door_fd = door_create(main_switcher, REPOSITORY_DOOR_COOKIE,
152 	    door_flags)) < 0) {
153 		perror("door_create");
154 		return (0);
155 	}
156 
157 #ifdef DOOR_PARAM_DATA_MIN
158 	if (door_setparam(main_door_fd, DOOR_PARAM_DATA_MIN,
159 	    offsetofend(repository_door_request_t, rdr_request)) == -1 ||
160 	    door_setparam(main_door_fd, DOOR_PARAM_DATA_MAX,
161 	    sizeof (repository_door_request_t)) == -1) {
162 		perror("door_setparam");
163 		return (0);
164 	}
165 #endif /* DOOR_PARAM_DATA_MIN */
166 
167 	/*
168 	 * Create the file if it doesn't exist.  Ignore errors, since
169 	 * fattach(3C) will catch any real problems.
170 	 */
171 	oldmask = umask(000);		/* disable umask temporarily */
172 	fd = open(doorpath, O_RDWR | O_CREAT | O_EXCL, 0644);
173 	(void) umask(oldmask);
174 
175 	if (fd >= 0)
176 		(void) close(fd);
177 
178 	if (fattach(main_door_fd, doorpath) < 0) {
179 		if ((errno != EBUSY) ||
180 		    (fdetach(doorpath) < 0) ||
181 		    (fattach(main_door_fd, doorpath) < 0)) {
182 			perror("fattach");
183 			(void) door_revoke(main_door_fd);
184 			main_door_fd = -1;
185 			return (0);
186 		}
187 	}
188 
189 	return (1);
190 }
191