xref: /illumos-gate/usr/src/cmd/svc/configd/maindoor.c (revision 012e6ce759c490003aed29439cc47d3d73a99ad3)
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 #include <assert.h>
28 #include <door.h>
29 #include <errno.h>
30 #include <fcntl.h>
31 #include <pthread.h>
32 #include <signal.h>
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <sys/stat.h>
36 #include <unistd.h>
37 #include <ucred.h>
38 
39 #include "repcache_protocol.h"
40 #include "configd.h"
41 
42 #define	INVALID_RESULT		((uint32_t)-1U)
43 
44 static int		main_door_fd = -1;
45 
46 /*ARGSUSED*/
47 static void
48 main_switcher(void *cookie, char *argp, size_t arg_size, door_desc_t *desc,
49     uint_t n_desc)
50 {
51 	repository_door_request_t *request;
52 	repository_door_response_t reply;
53 	door_desc_t reply_desc;
54 
55 	thread_info_t *ti = thread_self();
56 
57 	int send_desc = 0;
58 	int fd;
59 
60 	thread_newstate(ti, TI_MAIN_DOOR_CALL);
61 	ti->ti_main_door_request = (void *)argp;
62 
63 	assert(cookie == REPOSITORY_DOOR_COOKIE);
64 
65 	reply.rdr_status = INVALID_RESULT;
66 
67 	if (argp == DOOR_UNREF_DATA) {
68 		backend_fini();
69 
70 		exit(CONFIGD_EXIT_LOST_MAIN_DOOR);
71 	}
72 
73 	/*
74 	 * No file descriptors allowed
75 	 */
76 	assert(n_desc == 0);
77 
78 	/*
79 	 * first, we just check the version
80 	 */
81 	if (arg_size < offsetofend(repository_door_request_t, rdr_version)) {
82 		reply.rdr_status = REPOSITORY_DOOR_FAIL_BAD_REQUEST;
83 		goto fail;
84 	}
85 
86 	/* LINTED alignment */
87 	request = (repository_door_request_t *)argp;
88 	ti->ti_main_door_request = request;
89 
90 	if (request->rdr_version != REPOSITORY_DOOR_VERSION) {
91 		reply.rdr_status = REPOSITORY_DOOR_FAIL_VERSION_MISMATCH;
92 		goto fail;
93 	}
94 
95 	/*
96 	 * Now, check that the argument is of the minimum required size
97 	 */
98 	if (arg_size < offsetofend(repository_door_request_t, rdr_request)) {
99 		reply.rdr_status = REPOSITORY_DOOR_FAIL_BAD_REQUEST;
100 		goto fail;
101 	}
102 
103 	if (door_ucred(&ti->ti_ucred) != 0) {
104 		reply.rdr_status = REPOSITORY_DOOR_FAIL_PERMISSION_DENIED;
105 		goto fail;
106 	}
107 
108 	switch (request->rdr_request) {
109 	case REPOSITORY_DOOR_REQUEST_CONNECT:
110 		fd = -1;
111 		reply.rdr_status = create_connection(ti->ti_ucred, request,
112 		    arg_size, &fd);
113 		if (reply.rdr_status != REPOSITORY_DOOR_SUCCESS) {
114 			assert(fd == -1);
115 			goto fail;
116 		}
117 		assert(fd != -1);
118 		reply_desc.d_attributes = DOOR_DESCRIPTOR | DOOR_RELEASE;
119 		reply_desc.d_data.d_desc.d_descriptor = fd;
120 		send_desc = 1;
121 		break;
122 
123 	default:
124 		reply.rdr_status = REPOSITORY_DOOR_FAIL_BAD_REQUEST;
125 		goto fail;
126 	}
127 
128 fail:
129 	assert(reply.rdr_status != INVALID_RESULT);
130 
131 	thread_newstate(ti, TI_DOOR_RETURN);
132 	ti->ti_main_door_request = NULL;
133 
134 	(void) door_return((char *)&reply, sizeof (reply),
135 	    &reply_desc, (send_desc)? 1:0);
136 	(void) door_return(NULL, 0, NULL, 0);
137 }
138 
139 int
140 setup_main_door(const char *doorpath)
141 {
142 	mode_t oldmask;
143 	int fd;
144 
145 	int door_flags = DOOR_UNREF | DOOR_REFUSE_DESC;
146 #ifdef DOOR_NO_CANCEL
147 	door_flags |= DOOR_NO_CANCEL;
148 #endif
149 	if ((main_door_fd = door_create(main_switcher, REPOSITORY_DOOR_COOKIE,
150 	    door_flags)) < 0) {
151 		perror("door_create");
152 		return (0);
153 	}
154 
155 #ifdef DOOR_PARAM_DATA_MIN
156 	if (door_setparam(main_door_fd, DOOR_PARAM_DATA_MIN,
157 	    offsetofend(repository_door_request_t, rdr_request)) == -1 ||
158 	    door_setparam(main_door_fd, DOOR_PARAM_DATA_MAX,
159 	    sizeof (repository_door_request_t)) == -1) {
160 		perror("door_setparam");
161 		return (0);
162 	}
163 #endif /* DOOR_PARAM_DATA_MIN */
164 
165 	/*
166 	 * Create the file if it doesn't exist.  Ignore errors, since
167 	 * fattach(3C) will catch any real problems.
168 	 */
169 	oldmask = umask(000);		/* disable umask temporarily */
170 	fd = open(doorpath, O_RDWR | O_CREAT | O_EXCL, 0644);
171 	(void) umask(oldmask);
172 
173 	if (fd >= 0)
174 		(void) close(fd);
175 
176 	if (fattach(main_door_fd, doorpath) < 0) {
177 		if ((errno != EBUSY) ||
178 		    (fdetach(doorpath) < 0) ||
179 		    (fattach(main_door_fd, doorpath) < 0)) {
180 			perror("fattach");
181 			(void) door_revoke(main_door_fd);
182 			main_door_fd = -1;
183 			return (0);
184 		}
185 	}
186 
187 	return (1);
188 }
189