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