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 2007 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 #pragma ident	"%Z%%M%	%I%	%E% SMI"
27 
28 /*
29  * User-space door client routines for both SMB daemon and CLIs.
30  */
31 
32 #include <fcntl.h>
33 #include <syslog.h>
34 #include <door.h>
35 #include <string.h>
36 #include <strings.h>
37 #include <stdlib.h>
38 #include <errno.h>
39 #include <sys/mman.h>
40 #include <smbsrv/libsmb.h>
41 #include <smbsrv/wintypes.h>
42 #include <smbsrv/smb_door_svc.h>
43 #include <smbsrv/smb_common_door.h>
44 
45 /*
46  * Returns 0 on success. Otherwise, -1.
47  */
48 int
49 smb_dr_clnt_open(int *fd, char *path, char *op_desc)
50 {
51 	int rc = 0;
52 
53 	if (!op_desc)
54 		op_desc = "unknown operation";
55 
56 	if (!path || !fd)
57 		return (-1);
58 
59 	if ((*fd = open(path, O_RDONLY)) < 0) {
60 		syslog(LOG_ERR, "%s: open %s failed %s", op_desc,
61 		    path, strerror(errno));
62 		rc = -1;
63 	}
64 
65 	return (rc);
66 }
67 
68 /*
69  * smb_dr_clnt_call
70  *
71  * This function will make a door call to the server function
72  * associated with the door descriptor fd. The specified door
73  * request buffer (i.e. argp) will be passed as the argument to the
74  * door_call(). Upon success, the result buffer is returned. Otherwise,
75  * NULL pointer is returned. The size of the result buffer is returned
76  * via rbufsize.
77  */
78 char *
79 smb_dr_clnt_call(int fd, char *argp, size_t arg_size, size_t *rbufsize,
80     char *op_desc)
81 {
82 	door_arg_t arg;
83 
84 	if (!argp) {
85 		syslog(LOG_ERR, "smb_dr_clnt_call: invalid parameter");
86 		return (NULL);
87 	}
88 
89 	arg.data_ptr = argp;
90 	arg.data_size = arg_size;
91 	arg.desc_ptr = NULL;
92 	arg.desc_num = 0;
93 	arg.rbuf = argp;
94 	arg.rsize = arg_size;
95 
96 	if (!op_desc)
97 		op_desc = "unknown operation";
98 
99 	if (door_call(fd, &arg) < 0) {
100 		syslog(LOG_ERR, "%s: Door call failed %s", op_desc,
101 		    strerror(errno));
102 		free(argp);
103 		argp = NULL;
104 		return (NULL);
105 	}
106 
107 	if (smb_dr_get_res_stat(arg.data_ptr, arg.rsize)
108 	    != SMB_DR_OP_SUCCESS) {
109 		smb_dr_clnt_free(argp, arg_size, arg.rbuf, arg.rsize);
110 		*rbufsize = 0;
111 		return (NULL);
112 	}
113 	*rbufsize = arg.rsize;
114 	return (arg.data_ptr);
115 }
116 
117 /*
118  * smb_dr_clnt_free
119  *
120  * This function should be invoked to free both the argument/result door buffer
121  * regardless of the status of the door call.
122  *
123  * The doorfs allocates a new buffer if the result buffer passed by the client
124  * is too small. This function will munmap if that happens.
125  */
126 /*ARGSUSED*/
127 void
128 smb_dr_clnt_free(char *argp, size_t arg_size, char *rbufp, size_t rbuf_size)
129 {
130 	if (argp) {
131 		if (argp == rbufp) {
132 			free(argp);
133 			argp = NULL;
134 		} else if (rbufp) {
135 			free(argp);
136 			argp = NULL;
137 			if (munmap(rbufp, rbuf_size) != 0) {
138 				syslog(LOG_ERR, "munmap failed");
139 			}
140 		}
141 	} else {
142 		if (rbufp) {
143 			if (munmap(rbufp, rbuf_size) != 0) {
144 				syslog(LOG_ERR, "munmap failed");
145 			}
146 		}
147 	}
148 }
149