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 (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 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. 12 * 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] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 /* 27 * SMBd door server 28 */ 29 30 #include <alloca.h> 31 #include <door.h> 32 #include <errno.h> 33 #include <syslog.h> 34 #include <unistd.h> 35 #include <varargs.h> 36 #include <stdio.h> 37 #include <synch.h> 38 #include <string.h> 39 #include <stdlib.h> 40 #include <sys/stat.h> 41 #include <fcntl.h> 42 #include <pthread.h> 43 #include <strings.h> 44 #include <smbsrv/smb_door_svc.h> 45 #include <smbsrv/smb_common_door.h> 46 47 48 static int smb_doorsrv_fildes = -1; 49 static mutex_t smb_doorsrv_mutex; 50 51 static void smb_door_srv_func(void *cookie, char *ptr, size_t size, 52 door_desc_t *dp, uint_t n_odesc); 53 54 /* 55 * smb_door_srv_start 56 * 57 * Start the smbd door service. Create and bind to a door. 58 * Returns 0 on success. Otherwise, -1. 59 */ 60 int 61 smb_door_srv_start() 62 { 63 int newfd; 64 65 (void) mutex_lock(&smb_doorsrv_mutex); 66 67 if (smb_doorsrv_fildes != -1) { 68 (void) fprintf(stderr, "smb_doorsrv_start: already started"); 69 (void) mutex_unlock(&smb_doorsrv_mutex); 70 return (-1); 71 } 72 73 if ((smb_doorsrv_fildes = door_create(smb_door_srv_func, 74 SMB_DR_SVC_COOKIE, DOOR_UNREF)) < 0) { 75 (void) fprintf(stderr, "smb_doorsrv_start: door_create: %s", 76 strerror(errno)); 77 smb_doorsrv_fildes = -1; 78 (void) mutex_unlock(&smb_doorsrv_mutex); 79 return (-1); 80 } 81 82 (void) unlink(SMB_DR_SVC_NAME); 83 84 if ((newfd = creat(SMB_DR_SVC_NAME, 0644)) < 0) { 85 (void) fprintf(stderr, "smb_doorsrv_start: open: %s", 86 strerror(errno)); 87 (void) door_revoke(smb_doorsrv_fildes); 88 smb_doorsrv_fildes = -1; 89 (void) mutex_unlock(&smb_doorsrv_mutex); 90 return (-1); 91 } 92 93 (void) close(newfd); 94 (void) fdetach(SMB_DR_SVC_NAME); 95 96 if (fattach(smb_doorsrv_fildes, SMB_DR_SVC_NAME) < 0) { 97 (void) fprintf(stderr, "smb_doorsrv_start: fattach: %s", 98 strerror(errno)); 99 (void) door_revoke(smb_doorsrv_fildes); 100 smb_doorsrv_fildes = -1; 101 (void) mutex_unlock(&smb_doorsrv_mutex); 102 return (-1); 103 } 104 105 (void) mutex_unlock(&smb_doorsrv_mutex); 106 return (smb_doorsrv_fildes); 107 } 108 109 110 /* 111 * smb_door_srv_stop 112 * 113 * Stop the smbd door service. 114 */ 115 void 116 smb_door_srv_stop(void) 117 { 118 (void) mutex_lock(&smb_doorsrv_mutex); 119 120 if (smb_doorsrv_fildes != -1) { 121 (void) fdetach(SMB_DR_SVC_NAME); 122 (void) door_revoke(smb_doorsrv_fildes); 123 smb_doorsrv_fildes = -1; 124 } 125 126 (void) mutex_unlock(&smb_doorsrv_mutex); 127 } 128 129 /* 130 * smb_door_err_hdlr 131 * 132 * Encode the appropriate error code to the first 4-byte of the result 133 * buffer upon any door operation failure. 134 */ 135 static char * 136 smb_door_srv_err_hdlr(int stat, size_t *rbufsize) 137 { 138 char *rbuf; 139 140 if ((rbuf = smb_dr_set_res_stat(stat, rbufsize)) == NULL) { 141 *rbufsize = 0; 142 return (NULL); 143 } 144 145 return (rbuf); 146 } 147 148 /* 149 * smb_door_srv_func 150 * 151 * This function will determine the opcode by decoding the first 4-byte of 152 * the argument buffer passed by a door client. The corresponding door 153 * operation will be looked up from the optab and get invoked. 154 * Basically, any door operation will takes the argument buffer as its 155 * parameter, and generates the result buffer. 156 */ 157 /*ARGSUSED*/ 158 void 159 smb_door_srv_func(void *cookie, char *argp, size_t arg_size, door_desc_t *dp, 160 uint_t n_desc) 161 { 162 char *resbuf = NULL, *tmpbuf = NULL; 163 size_t rbufsize = 0; 164 int opcode; 165 int err; 166 smb_dr_op_t smbop; 167 168 if ((cookie != SMB_DR_SVC_COOKIE) || (argp == NULL) || 169 (arg_size < sizeof (uint32_t))) { 170 (void) door_return(NULL, 0, NULL, 0); 171 } 172 173 if ((opcode = smb_dr_get_opcode(argp, arg_size)) < 0) { 174 tmpbuf = smb_door_srv_err_hdlr(SMB_DR_OP_ERR_DECODE, 175 &rbufsize); 176 goto door_return; 177 } 178 179 if (smb_dr_is_valid_opcode(opcode) != 0) { 180 tmpbuf = smb_door_srv_err_hdlr(SMB_DR_OP_ERR_INVALID_OPCODE, 181 &rbufsize); 182 } else { 183 smbop = smb_doorsrv_optab[opcode]; 184 if ((tmpbuf = smbop(argp + sizeof (opcode), 185 arg_size - sizeof (opcode), dp, n_desc, 186 &rbufsize, &err)) == NULL) 187 tmpbuf = smb_door_srv_err_hdlr(err, &rbufsize); 188 } 189 190 door_return: 191 if (tmpbuf) { 192 if ((resbuf = (char *)alloca(rbufsize)) == NULL) 193 rbufsize = 0; 194 else 195 (void) memcpy(resbuf, tmpbuf, rbufsize); 196 free(tmpbuf); 197 } 198 199 (void) door_return(resbuf, rbufsize, NULL, 0); 200 /*NOTREACHED*/ 201 } 202