xref: /illumos-gate/usr/src/uts/common/fs/smbsrv/smb_print.c (revision 148c5f43199ca0b43fc8e3b643aab11cd66ea327)
1da6c28aaSamw /*
2da6c28aaSamw  * CDDL HEADER START
3da6c28aaSamw  *
4da6c28aaSamw  * The contents of this file are subject to the terms of the
5da6c28aaSamw  * Common Development and Distribution License (the "License").
6da6c28aaSamw  * You may not use this file except in compliance with the License.
7da6c28aaSamw  *
8da6c28aaSamw  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9da6c28aaSamw  * or http://www.opensolaris.org/os/licensing.
10da6c28aaSamw  * See the License for the specific language governing permissions
11da6c28aaSamw  * and limitations under the License.
12da6c28aaSamw  *
13da6c28aaSamw  * When distributing Covered Code, include this CDDL HEADER in each
14da6c28aaSamw  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15da6c28aaSamw  * If applicable, add the following below this CDDL HEADER, with the
16da6c28aaSamw  * fields enclosed by brackets "[]" replaced with your own identifying
17da6c28aaSamw  * information: Portions Copyright [yyyy] [name of copyright owner]
18da6c28aaSamw  *
19da6c28aaSamw  * CDDL HEADER END
20da6c28aaSamw  */
21da6c28aaSamw /*
22*148c5f43SAlan Wright  * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
23da6c28aaSamw  */
24da6c28aaSamw 
25da6c28aaSamw /*
26da6c28aaSamw  * SMB print interface.
27da6c28aaSamw  */
28da6c28aaSamw 
29bbf6f00cSJordan Brown #include <smbsrv/smb_kproto.h>
30da6c28aaSamw 
31da6c28aaSamw /*
32f96bd5c8SAlan Wright  * Create a new printer file, which should be deleted automatically once
33f96bd5c8SAlan Wright  * it has been closed and printed.
34da6c28aaSamw  *
35da6c28aaSamw  * SetupLength is the number of bytes in the first part of the resulting
36da6c28aaSamw  * print spool file which contains printer-specific control strings.
37da6c28aaSamw  *
38da6c28aaSamw  * Mode can have the following values:
39da6c28aaSamw  *      0     Text mode.  The server may optionally
40da6c28aaSamw  *            expand tabs to a series of spaces.
41da6c28aaSamw  *      1     Graphics mode.  No conversion of data
42da6c28aaSamw  *            should be done by the server.
43da6c28aaSamw  *
44f96bd5c8SAlan Wright  * IdentifierString can be used by the server to provide some sort of
45f96bd5c8SAlan Wright  * per-client identifying component to the print file.
46da6c28aaSamw  *
47f96bd5c8SAlan Wright  * When the file is closed, it will be sent to the spooler and printed.
48da6c28aaSamw  */
49faa1795aSjb150015 smb_sdrc_t
50faa1795aSjb150015 smb_pre_open_print_file(smb_request_t *sr)
51da6c28aaSamw {
52f96bd5c8SAlan Wright 	static uint32_t		tmp_id = 10000;
53f96bd5c8SAlan Wright 	struct open_param	*op = &sr->arg.open;
54f96bd5c8SAlan Wright 	char			*path;
55f96bd5c8SAlan Wright 	char			*identifier;
56*148c5f43SAlan Wright 	uint32_t		new_id;
57f96bd5c8SAlan Wright 	uint16_t		setup;
58f96bd5c8SAlan Wright 	uint16_t		mode;
59f96bd5c8SAlan Wright 	int			rc;
60f96bd5c8SAlan Wright 
61f96bd5c8SAlan Wright 	bzero(op, sizeof (sr->arg.open));
62f96bd5c8SAlan Wright 
63f96bd5c8SAlan Wright 	rc = smbsr_decode_vwv(sr, "ww", &setup, &mode);
64f96bd5c8SAlan Wright 	if (rc == 0)
65f96bd5c8SAlan Wright 		rc = smbsr_decode_data(sr, "%S", sr, &identifier);
66f96bd5c8SAlan Wright 
67*148c5f43SAlan Wright 	if (rc == 0) {
689fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		path = smb_srm_zalloc(sr, MAXPATHLEN);
69f96bd5c8SAlan Wright 		op->fqi.fq_path.pn_path = path;
70*148c5f43SAlan Wright 		new_id = atomic_inc_32_nv(&tmp_id);
71*148c5f43SAlan Wright 		(void) snprintf(path, MAXPATHLEN, "%s%05u", identifier, new_id);
72*148c5f43SAlan Wright 	}
73f96bd5c8SAlan Wright 
74f96bd5c8SAlan Wright 	op->create_disposition = FILE_OVERWRITE_IF;
75f96bd5c8SAlan Wright 	op->create_options = FILE_NON_DIRECTORY_FILE;
76f96bd5c8SAlan Wright 
77f96bd5c8SAlan Wright 	DTRACE_SMB_2(op__OpenPrintFile__start, smb_request_t *, sr,
78f96bd5c8SAlan Wright 	    struct open_param *, op);
79f96bd5c8SAlan Wright 
80f96bd5c8SAlan Wright 	return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
81faa1795aSjb150015 }
82faa1795aSjb150015 
83faa1795aSjb150015 void
84faa1795aSjb150015 smb_post_open_print_file(smb_request_t *sr)
85faa1795aSjb150015 {
86faa1795aSjb150015 	DTRACE_SMB_1(op__OpenPrintFile__done, smb_request_t *, sr);
87faa1795aSjb150015 }
88faa1795aSjb150015 
89f96bd5c8SAlan Wright smb_sdrc_t
90faa1795aSjb150015 smb_com_open_print_file(smb_request_t *sr)
91faa1795aSjb150015 {
92f96bd5c8SAlan Wright 	int rc;
93f96bd5c8SAlan Wright 
94f96bd5c8SAlan Wright 	if (!STYPE_ISPRN(sr->tid_tree->t_res_type)) {
95f96bd5c8SAlan Wright 		smbsr_error(sr, NT_STATUS_BAD_DEVICE_TYPE,
96f96bd5c8SAlan Wright 		    ERRDOS, ERROR_BAD_DEV_TYPE);
97f96bd5c8SAlan Wright 		return (SDRC_ERROR);
98da6c28aaSamw 	}
99da6c28aaSamw 
100f96bd5c8SAlan Wright 	if (smb_common_create(sr) != NT_STATUS_SUCCESS)
101f96bd5c8SAlan Wright 		return (SDRC_ERROR);
102f96bd5c8SAlan Wright 
103f96bd5c8SAlan Wright 	rc = smbsr_encode_result(sr, 1, 0, "bww", 1, sr->smb_fid, 0);
104f96bd5c8SAlan Wright 	return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
105f96bd5c8SAlan Wright }
106da6c28aaSamw 
107da6c28aaSamw /*
108f96bd5c8SAlan Wright  * Close the specified file handle and queue the file for printing.
109f96bd5c8SAlan Wright  * The fid refers to a file previously created as a print spool file.
110da6c28aaSamw  * On successful completion of this request, the file is queued for
111da6c28aaSamw  * printing by the server.
112da6c28aaSamw  *
113f96bd5c8SAlan Wright  * Servers that negotiate LANMAN1.0 or later allow all the the fid
114f96bd5c8SAlan Wright  * to be closed and printed via any close request.
115da6c28aaSamw  */
116faa1795aSjb150015 smb_sdrc_t
117faa1795aSjb150015 smb_pre_close_print_file(smb_request_t *sr)
118da6c28aaSamw {
119f96bd5c8SAlan Wright 	int rc;
120f96bd5c8SAlan Wright 
121f96bd5c8SAlan Wright 	rc = smbsr_decode_vwv(sr, "w", &sr->smb_fid);
122f96bd5c8SAlan Wright 
123faa1795aSjb150015 	DTRACE_SMB_1(op__ClosePrintFile__start, smb_request_t *, sr);
124f96bd5c8SAlan Wright 	return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
125faa1795aSjb150015 }
126faa1795aSjb150015 
127faa1795aSjb150015 void
128faa1795aSjb150015 smb_post_close_print_file(smb_request_t *sr)
129faa1795aSjb150015 {
130faa1795aSjb150015 	DTRACE_SMB_1(op__ClosePrintFile__done, smb_request_t *, sr);
131faa1795aSjb150015 }
132faa1795aSjb150015 
133f96bd5c8SAlan Wright smb_sdrc_t
134faa1795aSjb150015 smb_com_close_print_file(smb_request_t *sr)
135faa1795aSjb150015 {
136f96bd5c8SAlan Wright 	if (!STYPE_ISPRN(sr->tid_tree->t_res_type)) {
137f96bd5c8SAlan Wright 		smbsr_error(sr, NT_STATUS_BAD_DEVICE_TYPE,
138f96bd5c8SAlan Wright 		    ERRDOS, ERROR_BAD_DEV_TYPE);
139f96bd5c8SAlan Wright 		return (SDRC_ERROR);
140da6c28aaSamw 	}
141da6c28aaSamw 
142f96bd5c8SAlan Wright 	return (smb_com_close(sr));
143f96bd5c8SAlan Wright }
144da6c28aaSamw 
145da6c28aaSamw /*
146f96bd5c8SAlan Wright  * Get a list of print queue entries on the server.  Support for
147f96bd5c8SAlan Wright  * this request is optional (not required for Windows clients).
148da6c28aaSamw  */
1497b59d02dSjb150015 smb_sdrc_t
150faa1795aSjb150015 smb_pre_get_print_queue(smb_request_t *sr)
151faa1795aSjb150015 {
152faa1795aSjb150015 	DTRACE_SMB_1(op__GetPrintQueue__start, smb_request_t *, sr);
153faa1795aSjb150015 	return (SDRC_SUCCESS);
154faa1795aSjb150015 }
155faa1795aSjb150015 
156faa1795aSjb150015 void
157faa1795aSjb150015 smb_post_get_print_queue(smb_request_t *sr)
158faa1795aSjb150015 {
159faa1795aSjb150015 	DTRACE_SMB_1(op__GetPrintQueue__done, smb_request_t *, sr);
160faa1795aSjb150015 }
161faa1795aSjb150015 
162faa1795aSjb150015 smb_sdrc_t
163faa1795aSjb150015 smb_com_get_print_queue(smb_request_t *sr)
164da6c28aaSamw {
165da6c28aaSamw 	unsigned short max_count, start_ix;
166da6c28aaSamw 
1677b59d02dSjb150015 	if (smbsr_decode_vwv(sr, "ww", &max_count, &start_ix) != 0)
168faa1795aSjb150015 		return (SDRC_ERROR);
169da6c28aaSamw 
1707b59d02dSjb150015 	if (smbsr_encode_result(sr, 2, 3, "bwwwbw", 2, 0, 0, 3, 1, 0))
171faa1795aSjb150015 		return (SDRC_ERROR);
1727b59d02dSjb150015 
173faa1795aSjb150015 	return (SDRC_SUCCESS);
174da6c28aaSamw }
175da6c28aaSamw 
176da6c28aaSamw /*
177f96bd5c8SAlan Wright  * Write (append) data to a print spool file.  The fid must refer to
178f96bd5c8SAlan Wright  * a print spool file.
179da6c28aaSamw  *
180f96bd5c8SAlan Wright  * The first SetupLength bytes (see SMB_COM_OPEN_PRINT_FILE) in the
181f96bd5c8SAlan Wright  * print spool file contain printer setup data.
182da6c28aaSamw  *
183f96bd5c8SAlan Wright  * Servers that negotiate LANMAN1.0 or later also support the use of
184f96bd5c8SAlan Wright  * normal write requests with print spool files.
185da6c28aaSamw  */
186faa1795aSjb150015 smb_sdrc_t
187faa1795aSjb150015 smb_pre_write_print_file(smb_request_t *sr)
188da6c28aaSamw {
189f96bd5c8SAlan Wright 	smb_rw_param_t	*param;
190f96bd5c8SAlan Wright 	int		rc;
191f96bd5c8SAlan Wright 
192f96bd5c8SAlan Wright 	param = kmem_zalloc(sizeof (smb_rw_param_t), KM_SLEEP);
193f96bd5c8SAlan Wright 	sr->arg.rw = param;
194f96bd5c8SAlan Wright 	param->rw_magic = SMB_RW_MAGIC;
195f96bd5c8SAlan Wright 
196f96bd5c8SAlan Wright 	rc = smbsr_decode_vwv(sr, "w", &sr->smb_fid);
197f96bd5c8SAlan Wright 
198faa1795aSjb150015 	DTRACE_SMB_1(op__WritePrintFile__start, smb_request_t *, sr);
199f96bd5c8SAlan Wright 	return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
200faa1795aSjb150015 }
201faa1795aSjb150015 
202faa1795aSjb150015 void
203faa1795aSjb150015 smb_post_write_print_file(smb_request_t *sr)
204faa1795aSjb150015 {
205faa1795aSjb150015 	DTRACE_SMB_1(op__WritePrintFile__done, smb_request_t *, sr);
206f96bd5c8SAlan Wright 
207f96bd5c8SAlan Wright 	kmem_free(sr->arg.rw, sizeof (smb_rw_param_t));
208faa1795aSjb150015 }
209faa1795aSjb150015 
210f96bd5c8SAlan Wright smb_sdrc_t
211faa1795aSjb150015 smb_com_write_print_file(smb_request_t *sr)
212faa1795aSjb150015 {
213f96bd5c8SAlan Wright 	smb_rw_param_t	*param = sr->arg.rw;
214f96bd5c8SAlan Wright 	smb_node_t	*node;
215f96bd5c8SAlan Wright 	smb_attr_t	attr;
216f96bd5c8SAlan Wright 	int		rc;
217f96bd5c8SAlan Wright 
218f96bd5c8SAlan Wright 	if (!STYPE_ISPRN(sr->tid_tree->t_res_type)) {
219f96bd5c8SAlan Wright 		smbsr_error(sr, NT_STATUS_BAD_DEVICE_TYPE,
220f96bd5c8SAlan Wright 		    ERRDOS, ERROR_BAD_DEV_TYPE);
221f96bd5c8SAlan Wright 		return (SDRC_ERROR);
222f96bd5c8SAlan Wright 	}
223f96bd5c8SAlan Wright 
224f96bd5c8SAlan Wright 	smbsr_lookup_file(sr);
225f96bd5c8SAlan Wright 	if (sr->fid_ofile == NULL) {
226f96bd5c8SAlan Wright 		smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRbadfid);
227f96bd5c8SAlan Wright 		return (SDRC_ERROR);
228f96bd5c8SAlan Wright 	}
229f96bd5c8SAlan Wright 
230f96bd5c8SAlan Wright 	node = sr->fid_ofile->f_node;
231f96bd5c8SAlan Wright 	sr->user_cr = smb_ofile_getcred(sr->fid_ofile);
232f96bd5c8SAlan Wright 
233f96bd5c8SAlan Wright 	if (smb_node_getattr(sr, node, &attr) != 0) {
234f96bd5c8SAlan Wright 		smbsr_error(sr, NT_STATUS_INTERNAL_ERROR,
235f96bd5c8SAlan Wright 		    ERRDOS, ERROR_INTERNAL_ERROR);
236f96bd5c8SAlan Wright 		return (SDRC_ERROR);
237f96bd5c8SAlan Wright 	}
238f96bd5c8SAlan Wright 
239f96bd5c8SAlan Wright 	if ((smbsr_decode_data(sr, "D", &param->rw_vdb)) != 0) {
240f96bd5c8SAlan Wright 		smbsr_error(sr, NT_STATUS_INVALID_PARAMETER,
241f96bd5c8SAlan Wright 		    ERRDOS, ERROR_INVALID_PARAMETER);
242f96bd5c8SAlan Wright 		return (SDRC_ERROR);
243f96bd5c8SAlan Wright 	}
244f96bd5c8SAlan Wright 
245f96bd5c8SAlan Wright 	param->rw_count = param->rw_vdb.vdb_len;
246f96bd5c8SAlan Wright 	param->rw_offset = attr.sa_vattr.va_size;
247f96bd5c8SAlan Wright 	param->rw_vdb.vdb_uio.uio_loffset = (offset_t)param->rw_offset;
248f96bd5c8SAlan Wright 
249f96bd5c8SAlan Wright 	if ((rc = smb_common_write(sr, param)) != 0) {
250f96bd5c8SAlan Wright 		if (sr->smb_error.status != NT_STATUS_FILE_LOCK_CONFLICT)
251f96bd5c8SAlan Wright 			smbsr_errno(sr, rc);
252f96bd5c8SAlan Wright 		return (SDRC_ERROR);
253f96bd5c8SAlan Wright 	}
254f96bd5c8SAlan Wright 
255f96bd5c8SAlan Wright 	rc = smbsr_encode_empty_result(sr);
256f96bd5c8SAlan Wright 	return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
257da6c28aaSamw }
258