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
main_switcher(void * cookie,char * argp,size_t arg_size,door_desc_t * desc,uint_t n_desc)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
setup_main_door(const char * doorpath)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