Home | History | Annotate | Download | only in configd
      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