xref: /onnv-gate/usr/src/uts/common/fs/smbsrv/smb_print.c (revision 11447:b5b2a9bd508f)
15331Samw /*
25331Samw  * CDDL HEADER START
35331Samw  *
45331Samw  * The contents of this file are subject to the terms of the
55331Samw  * Common Development and Distribution License (the "License").
65331Samw  * You may not use this file except in compliance with the License.
75331Samw  *
85331Samw  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
95331Samw  * or http://www.opensolaris.org/os/licensing.
105331Samw  * See the License for the specific language governing permissions
115331Samw  * and limitations under the License.
125331Samw  *
135331Samw  * When distributing Covered Code, include this CDDL HEADER in each
145331Samw  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
155331Samw  * If applicable, add the following below this CDDL HEADER, with the
165331Samw  * fields enclosed by brackets "[]" replaced with your own identifying
175331Samw  * information: Portions Copyright [yyyy] [name of copyright owner]
185331Samw  *
195331Samw  * CDDL HEADER END
205331Samw  */
215331Samw /*
22*11447Samw@Sun.COM  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
235331Samw  * Use is subject to license terms.
245331Samw  */
255331Samw 
265331Samw /*
275331Samw  * SMB print interface.
285331Samw  */
295331Samw 
3010966SJordan.Brown@Sun.COM #include <smbsrv/smb_kproto.h>
315331Samw 
325331Samw /*
33*11447Samw@Sun.COM  * Create a new printer file, which should be deleted automatically once
34*11447Samw@Sun.COM  * it has been closed and printed.
355331Samw  *
365331Samw  * SetupLength is the number of bytes in the first part of the resulting
375331Samw  * print spool file which contains printer-specific control strings.
385331Samw  *
395331Samw  * Mode can have the following values:
405331Samw  *      0     Text mode.  The server may optionally
415331Samw  *            expand tabs to a series of spaces.
425331Samw  *      1     Graphics mode.  No conversion of data
435331Samw  *            should be done by the server.
445331Samw  *
45*11447Samw@Sun.COM  * IdentifierString can be used by the server to provide some sort of
46*11447Samw@Sun.COM  * per-client identifying component to the print file.
475331Samw  *
48*11447Samw@Sun.COM  * When the file is closed, it will be sent to the spooler and printed.
495331Samw  */
506139Sjb150015 smb_sdrc_t
516139Sjb150015 smb_pre_open_print_file(smb_request_t *sr)
526139Sjb150015 {
53*11447Samw@Sun.COM 	static uint32_t		tmp_id = 10000;
54*11447Samw@Sun.COM 	struct open_param	*op = &sr->arg.open;
55*11447Samw@Sun.COM 	char			*path;
56*11447Samw@Sun.COM 	char			*identifier;
57*11447Samw@Sun.COM 	uint16_t		setup;
58*11447Samw@Sun.COM 	uint16_t		mode;
59*11447Samw@Sun.COM 	int			rc;
60*11447Samw@Sun.COM 
61*11447Samw@Sun.COM 	bzero(op, sizeof (sr->arg.open));
62*11447Samw@Sun.COM 
63*11447Samw@Sun.COM 	rc = smbsr_decode_vwv(sr, "ww", &setup, &mode);
64*11447Samw@Sun.COM 	if (rc == 0)
65*11447Samw@Sun.COM 		rc = smbsr_decode_data(sr, "%S", sr, &identifier);
66*11447Samw@Sun.COM 
67*11447Samw@Sun.COM 	atomic_inc_32(&tmp_id);
68*11447Samw@Sun.COM 
69*11447Samw@Sun.COM 	path = smb_srm_alloc(sr, MAXPATHLEN);
70*11447Samw@Sun.COM 	(void) snprintf(path, MAXPATHLEN, "%s%05u", identifier, tmp_id);
71*11447Samw@Sun.COM 	op->fqi.fq_path.pn_path = path;
72*11447Samw@Sun.COM 
73*11447Samw@Sun.COM 	op->create_disposition = FILE_OVERWRITE_IF;
74*11447Samw@Sun.COM 	op->create_options = FILE_NON_DIRECTORY_FILE;
75*11447Samw@Sun.COM 
76*11447Samw@Sun.COM 	DTRACE_SMB_2(op__OpenPrintFile__start, smb_request_t *, sr,
77*11447Samw@Sun.COM 	    struct open_param *, op);
78*11447Samw@Sun.COM 
79*11447Samw@Sun.COM 	return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
806139Sjb150015 }
816139Sjb150015 
826139Sjb150015 void
836139Sjb150015 smb_post_open_print_file(smb_request_t *sr)
846139Sjb150015 {
856139Sjb150015 	DTRACE_SMB_1(op__OpenPrintFile__done, smb_request_t *, sr);
866139Sjb150015 }
876139Sjb150015 
88*11447Samw@Sun.COM smb_sdrc_t
896139Sjb150015 smb_com_open_print_file(smb_request_t *sr)
905331Samw {
91*11447Samw@Sun.COM 	int rc;
92*11447Samw@Sun.COM 
93*11447Samw@Sun.COM 	if (!STYPE_ISPRN(sr->tid_tree->t_res_type)) {
94*11447Samw@Sun.COM 		smbsr_error(sr, NT_STATUS_BAD_DEVICE_TYPE,
95*11447Samw@Sun.COM 		    ERRDOS, ERROR_BAD_DEV_TYPE);
96*11447Samw@Sun.COM 		return (SDRC_ERROR);
97*11447Samw@Sun.COM 	}
98*11447Samw@Sun.COM 
99*11447Samw@Sun.COM 	if (smb_common_create(sr) != NT_STATUS_SUCCESS)
100*11447Samw@Sun.COM 		return (SDRC_ERROR);
101*11447Samw@Sun.COM 
102*11447Samw@Sun.COM 	rc = smbsr_encode_result(sr, 1, 0, "bww", 1, sr->smb_fid, 0);
103*11447Samw@Sun.COM 	return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
1045331Samw }
1055331Samw 
1065331Samw /*
107*11447Samw@Sun.COM  * Close the specified file handle and queue the file for printing.
108*11447Samw@Sun.COM  * The fid refers to a file previously created as a print spool file.
1095331Samw  * On successful completion of this request, the file is queued for
1105331Samw  * printing by the server.
1115331Samw  *
112*11447Samw@Sun.COM  * Servers that negotiate LANMAN1.0 or later allow all the the fid
113*11447Samw@Sun.COM  * to be closed and printed via any close request.
1145331Samw  */
1156139Sjb150015 smb_sdrc_t
1166139Sjb150015 smb_pre_close_print_file(smb_request_t *sr)
1176139Sjb150015 {
118*11447Samw@Sun.COM 	int rc;
119*11447Samw@Sun.COM 
120*11447Samw@Sun.COM 	rc = smbsr_decode_vwv(sr, "w", &sr->smb_fid);
121*11447Samw@Sun.COM 
1226139Sjb150015 	DTRACE_SMB_1(op__ClosePrintFile__start, smb_request_t *, sr);
123*11447Samw@Sun.COM 	return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
1246139Sjb150015 }
1256139Sjb150015 
1266139Sjb150015 void
1276139Sjb150015 smb_post_close_print_file(smb_request_t *sr)
1286139Sjb150015 {
1296139Sjb150015 	DTRACE_SMB_1(op__ClosePrintFile__done, smb_request_t *, sr);
1306139Sjb150015 }
1316139Sjb150015 
132*11447Samw@Sun.COM smb_sdrc_t
1336139Sjb150015 smb_com_close_print_file(smb_request_t *sr)
1345331Samw {
135*11447Samw@Sun.COM 	if (!STYPE_ISPRN(sr->tid_tree->t_res_type)) {
136*11447Samw@Sun.COM 		smbsr_error(sr, NT_STATUS_BAD_DEVICE_TYPE,
137*11447Samw@Sun.COM 		    ERRDOS, ERROR_BAD_DEV_TYPE);
138*11447Samw@Sun.COM 		return (SDRC_ERROR);
139*11447Samw@Sun.COM 	}
140*11447Samw@Sun.COM 
141*11447Samw@Sun.COM 	return (smb_com_close(sr));
1425331Samw }
1435331Samw 
1445331Samw /*
145*11447Samw@Sun.COM  * Get a list of print queue entries on the server.  Support for
146*11447Samw@Sun.COM  * this request is optional (not required for Windows clients).
1475331Samw  */
1486030Sjb150015 smb_sdrc_t
1496139Sjb150015 smb_pre_get_print_queue(smb_request_t *sr)
1506139Sjb150015 {
1516139Sjb150015 	DTRACE_SMB_1(op__GetPrintQueue__start, smb_request_t *, sr);
1526139Sjb150015 	return (SDRC_SUCCESS);
1536139Sjb150015 }
1546139Sjb150015 
1556139Sjb150015 void
1566139Sjb150015 smb_post_get_print_queue(smb_request_t *sr)
1576139Sjb150015 {
1586139Sjb150015 	DTRACE_SMB_1(op__GetPrintQueue__done, smb_request_t *, sr);
1596139Sjb150015 }
1606139Sjb150015 
1616139Sjb150015 smb_sdrc_t
1626139Sjb150015 smb_com_get_print_queue(smb_request_t *sr)
1635331Samw {
1645331Samw 	unsigned short max_count, start_ix;
1655331Samw 
1666030Sjb150015 	if (smbsr_decode_vwv(sr, "ww", &max_count, &start_ix) != 0)
1676139Sjb150015 		return (SDRC_ERROR);
1685331Samw 
1696030Sjb150015 	if (smbsr_encode_result(sr, 2, 3, "bwwwbw", 2, 0, 0, 3, 1, 0))
1706139Sjb150015 		return (SDRC_ERROR);
1716030Sjb150015 
1726139Sjb150015 	return (SDRC_SUCCESS);
1735331Samw }
1745331Samw 
1755331Samw /*
176*11447Samw@Sun.COM  * Write (append) data to a print spool file.  The fid must refer to
177*11447Samw@Sun.COM  * a print spool file.
1785331Samw  *
179*11447Samw@Sun.COM  * The first SetupLength bytes (see SMB_COM_OPEN_PRINT_FILE) in the
180*11447Samw@Sun.COM  * print spool file contain printer setup data.
1815331Samw  *
182*11447Samw@Sun.COM  * Servers that negotiate LANMAN1.0 or later also support the use of
183*11447Samw@Sun.COM  * normal write requests with print spool files.
1845331Samw  */
1856139Sjb150015 smb_sdrc_t
1866139Sjb150015 smb_pre_write_print_file(smb_request_t *sr)
1875331Samw {
188*11447Samw@Sun.COM 	smb_rw_param_t	*param;
189*11447Samw@Sun.COM 	int		rc;
190*11447Samw@Sun.COM 
191*11447Samw@Sun.COM 	param = kmem_zalloc(sizeof (smb_rw_param_t), KM_SLEEP);
192*11447Samw@Sun.COM 	sr->arg.rw = param;
193*11447Samw@Sun.COM 	param->rw_magic = SMB_RW_MAGIC;
194*11447Samw@Sun.COM 
195*11447Samw@Sun.COM 	rc = smbsr_decode_vwv(sr, "w", &sr->smb_fid);
196*11447Samw@Sun.COM 
1976139Sjb150015 	DTRACE_SMB_1(op__WritePrintFile__start, smb_request_t *, sr);
198*11447Samw@Sun.COM 	return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
1995331Samw }
2006139Sjb150015 
2016139Sjb150015 void
2026139Sjb150015 smb_post_write_print_file(smb_request_t *sr)
2036139Sjb150015 {
2046139Sjb150015 	DTRACE_SMB_1(op__WritePrintFile__done, smb_request_t *, sr);
205*11447Samw@Sun.COM 
206*11447Samw@Sun.COM 	kmem_free(sr->arg.rw, sizeof (smb_rw_param_t));
2076139Sjb150015 }
2086139Sjb150015 
209*11447Samw@Sun.COM smb_sdrc_t
2106139Sjb150015 smb_com_write_print_file(smb_request_t *sr)
2116139Sjb150015 {
212*11447Samw@Sun.COM 	smb_rw_param_t	*param = sr->arg.rw;
213*11447Samw@Sun.COM 	smb_node_t	*node;
214*11447Samw@Sun.COM 	smb_attr_t	attr;
215*11447Samw@Sun.COM 	int		rc;
216*11447Samw@Sun.COM 
217*11447Samw@Sun.COM 	if (!STYPE_ISPRN(sr->tid_tree->t_res_type)) {
218*11447Samw@Sun.COM 		smbsr_error(sr, NT_STATUS_BAD_DEVICE_TYPE,
219*11447Samw@Sun.COM 		    ERRDOS, ERROR_BAD_DEV_TYPE);
220*11447Samw@Sun.COM 		return (SDRC_ERROR);
221*11447Samw@Sun.COM 	}
222*11447Samw@Sun.COM 
223*11447Samw@Sun.COM 	smbsr_lookup_file(sr);
224*11447Samw@Sun.COM 	if (sr->fid_ofile == NULL) {
225*11447Samw@Sun.COM 		smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRbadfid);
226*11447Samw@Sun.COM 		return (SDRC_ERROR);
227*11447Samw@Sun.COM 	}
228*11447Samw@Sun.COM 
229*11447Samw@Sun.COM 	node = sr->fid_ofile->f_node;
230*11447Samw@Sun.COM 	sr->user_cr = smb_ofile_getcred(sr->fid_ofile);
231*11447Samw@Sun.COM 
232*11447Samw@Sun.COM 	if (smb_node_getattr(sr, node, &attr) != 0) {
233*11447Samw@Sun.COM 		smbsr_error(sr, NT_STATUS_INTERNAL_ERROR,
234*11447Samw@Sun.COM 		    ERRDOS, ERROR_INTERNAL_ERROR);
235*11447Samw@Sun.COM 		return (SDRC_ERROR);
236*11447Samw@Sun.COM 	}
237*11447Samw@Sun.COM 
238*11447Samw@Sun.COM 	if ((smbsr_decode_data(sr, "D", &param->rw_vdb)) != 0) {
239*11447Samw@Sun.COM 		smbsr_error(sr, NT_STATUS_INVALID_PARAMETER,
240*11447Samw@Sun.COM 		    ERRDOS, ERROR_INVALID_PARAMETER);
241*11447Samw@Sun.COM 		return (SDRC_ERROR);
242*11447Samw@Sun.COM 	}
243*11447Samw@Sun.COM 
244*11447Samw@Sun.COM 	param->rw_count = param->rw_vdb.vdb_len;
245*11447Samw@Sun.COM 	param->rw_offset = attr.sa_vattr.va_size;
246*11447Samw@Sun.COM 	param->rw_vdb.vdb_uio.uio_loffset = (offset_t)param->rw_offset;
247*11447Samw@Sun.COM 
248*11447Samw@Sun.COM 	if ((rc = smb_common_write(sr, param)) != 0) {
249*11447Samw@Sun.COM 		if (sr->smb_error.status != NT_STATUS_FILE_LOCK_CONFLICT)
250*11447Samw@Sun.COM 			smbsr_errno(sr, rc);
251*11447Samw@Sun.COM 		return (SDRC_ERROR);
252*11447Samw@Sun.COM 	}
253*11447Samw@Sun.COM 
254*11447Samw@Sun.COM 	rc = smbsr_encode_empty_result(sr);
255*11447Samw@Sun.COM 	return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
2566139Sjb150015 }
257