xref: /onnv-gate/usr/src/uts/common/fs/smbsrv/smb_print.c (revision 12508:edb7861a1533)
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*12508Samw@Sun.COM  * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
235331Samw  */
245331Samw 
255331Samw /*
265331Samw  * SMB print interface.
275331Samw  */
285331Samw 
2910966SJordan.Brown@Sun.COM #include <smbsrv/smb_kproto.h>
305331Samw 
315331Samw /*
3211447Samw@Sun.COM  * Create a new printer file, which should be deleted automatically once
3311447Samw@Sun.COM  * it has been closed and printed.
345331Samw  *
355331Samw  * SetupLength is the number of bytes in the first part of the resulting
365331Samw  * print spool file which contains printer-specific control strings.
375331Samw  *
385331Samw  * Mode can have the following values:
395331Samw  *      0     Text mode.  The server may optionally
405331Samw  *            expand tabs to a series of spaces.
415331Samw  *      1     Graphics mode.  No conversion of data
425331Samw  *            should be done by the server.
435331Samw  *
4411447Samw@Sun.COM  * IdentifierString can be used by the server to provide some sort of
4511447Samw@Sun.COM  * per-client identifying component to the print file.
465331Samw  *
4711447Samw@Sun.COM  * When the file is closed, it will be sent to the spooler and printed.
485331Samw  */
496139Sjb150015 smb_sdrc_t
506139Sjb150015 smb_pre_open_print_file(smb_request_t *sr)
516139Sjb150015 {
5211447Samw@Sun.COM 	static uint32_t		tmp_id = 10000;
5311447Samw@Sun.COM 	struct open_param	*op = &sr->arg.open;
5411447Samw@Sun.COM 	char			*path;
5511447Samw@Sun.COM 	char			*identifier;
56*12508Samw@Sun.COM 	uint32_t		new_id;
5711447Samw@Sun.COM 	uint16_t		setup;
5811447Samw@Sun.COM 	uint16_t		mode;
5911447Samw@Sun.COM 	int			rc;
6011447Samw@Sun.COM 
6111447Samw@Sun.COM 	bzero(op, sizeof (sr->arg.open));
6211447Samw@Sun.COM 
6311447Samw@Sun.COM 	rc = smbsr_decode_vwv(sr, "ww", &setup, &mode);
6411447Samw@Sun.COM 	if (rc == 0)
6511447Samw@Sun.COM 		rc = smbsr_decode_data(sr, "%S", sr, &identifier);
6611447Samw@Sun.COM 
67*12508Samw@Sun.COM 	if (rc == 0) {
68*12508Samw@Sun.COM 		path = smb_srm_zalloc(sr, MAXPATHLEN);
69*12508Samw@Sun.COM 		op->fqi.fq_path.pn_path = path;
70*12508Samw@Sun.COM 		new_id = atomic_inc_32_nv(&tmp_id);
71*12508Samw@Sun.COM 		(void) snprintf(path, MAXPATHLEN, "%s%05u", identifier, new_id);
72*12508Samw@Sun.COM 	}
7311447Samw@Sun.COM 
7411447Samw@Sun.COM 	op->create_disposition = FILE_OVERWRITE_IF;
7511447Samw@Sun.COM 	op->create_options = FILE_NON_DIRECTORY_FILE;
7611447Samw@Sun.COM 
7711447Samw@Sun.COM 	DTRACE_SMB_2(op__OpenPrintFile__start, smb_request_t *, sr,
7811447Samw@Sun.COM 	    struct open_param *, op);
7911447Samw@Sun.COM 
8011447Samw@Sun.COM 	return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
816139Sjb150015 }
826139Sjb150015 
836139Sjb150015 void
846139Sjb150015 smb_post_open_print_file(smb_request_t *sr)
856139Sjb150015 {
866139Sjb150015 	DTRACE_SMB_1(op__OpenPrintFile__done, smb_request_t *, sr);
876139Sjb150015 }
886139Sjb150015 
8911447Samw@Sun.COM smb_sdrc_t
906139Sjb150015 smb_com_open_print_file(smb_request_t *sr)
915331Samw {
9211447Samw@Sun.COM 	int rc;
9311447Samw@Sun.COM 
9411447Samw@Sun.COM 	if (!STYPE_ISPRN(sr->tid_tree->t_res_type)) {
9511447Samw@Sun.COM 		smbsr_error(sr, NT_STATUS_BAD_DEVICE_TYPE,
9611447Samw@Sun.COM 		    ERRDOS, ERROR_BAD_DEV_TYPE);
9711447Samw@Sun.COM 		return (SDRC_ERROR);
9811447Samw@Sun.COM 	}
9911447Samw@Sun.COM 
10011447Samw@Sun.COM 	if (smb_common_create(sr) != NT_STATUS_SUCCESS)
10111447Samw@Sun.COM 		return (SDRC_ERROR);
10211447Samw@Sun.COM 
10311447Samw@Sun.COM 	rc = smbsr_encode_result(sr, 1, 0, "bww", 1, sr->smb_fid, 0);
10411447Samw@Sun.COM 	return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
1055331Samw }
1065331Samw 
1075331Samw /*
10811447Samw@Sun.COM  * Close the specified file handle and queue the file for printing.
10911447Samw@Sun.COM  * The fid refers to a file previously created as a print spool file.
1105331Samw  * On successful completion of this request, the file is queued for
1115331Samw  * printing by the server.
1125331Samw  *
11311447Samw@Sun.COM  * Servers that negotiate LANMAN1.0 or later allow all the the fid
11411447Samw@Sun.COM  * to be closed and printed via any close request.
1155331Samw  */
1166139Sjb150015 smb_sdrc_t
1176139Sjb150015 smb_pre_close_print_file(smb_request_t *sr)
1186139Sjb150015 {
11911447Samw@Sun.COM 	int rc;
12011447Samw@Sun.COM 
12111447Samw@Sun.COM 	rc = smbsr_decode_vwv(sr, "w", &sr->smb_fid);
12211447Samw@Sun.COM 
1236139Sjb150015 	DTRACE_SMB_1(op__ClosePrintFile__start, smb_request_t *, sr);
12411447Samw@Sun.COM 	return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
1256139Sjb150015 }
1266139Sjb150015 
1276139Sjb150015 void
1286139Sjb150015 smb_post_close_print_file(smb_request_t *sr)
1296139Sjb150015 {
1306139Sjb150015 	DTRACE_SMB_1(op__ClosePrintFile__done, smb_request_t *, sr);
1316139Sjb150015 }
1326139Sjb150015 
13311447Samw@Sun.COM smb_sdrc_t
1346139Sjb150015 smb_com_close_print_file(smb_request_t *sr)
1355331Samw {
13611447Samw@Sun.COM 	if (!STYPE_ISPRN(sr->tid_tree->t_res_type)) {
13711447Samw@Sun.COM 		smbsr_error(sr, NT_STATUS_BAD_DEVICE_TYPE,
13811447Samw@Sun.COM 		    ERRDOS, ERROR_BAD_DEV_TYPE);
13911447Samw@Sun.COM 		return (SDRC_ERROR);
14011447Samw@Sun.COM 	}
14111447Samw@Sun.COM 
14211447Samw@Sun.COM 	return (smb_com_close(sr));
1435331Samw }
1445331Samw 
1455331Samw /*
14611447Samw@Sun.COM  * Get a list of print queue entries on the server.  Support for
14711447Samw@Sun.COM  * this request is optional (not required for Windows clients).
1485331Samw  */
1496030Sjb150015 smb_sdrc_t
1506139Sjb150015 smb_pre_get_print_queue(smb_request_t *sr)
1516139Sjb150015 {
1526139Sjb150015 	DTRACE_SMB_1(op__GetPrintQueue__start, smb_request_t *, sr);
1536139Sjb150015 	return (SDRC_SUCCESS);
1546139Sjb150015 }
1556139Sjb150015 
1566139Sjb150015 void
1576139Sjb150015 smb_post_get_print_queue(smb_request_t *sr)
1586139Sjb150015 {
1596139Sjb150015 	DTRACE_SMB_1(op__GetPrintQueue__done, smb_request_t *, sr);
1606139Sjb150015 }
1616139Sjb150015 
1626139Sjb150015 smb_sdrc_t
1636139Sjb150015 smb_com_get_print_queue(smb_request_t *sr)
1645331Samw {
1655331Samw 	unsigned short max_count, start_ix;
1665331Samw 
1676030Sjb150015 	if (smbsr_decode_vwv(sr, "ww", &max_count, &start_ix) != 0)
1686139Sjb150015 		return (SDRC_ERROR);
1695331Samw 
1706030Sjb150015 	if (smbsr_encode_result(sr, 2, 3, "bwwwbw", 2, 0, 0, 3, 1, 0))
1716139Sjb150015 		return (SDRC_ERROR);
1726030Sjb150015 
1736139Sjb150015 	return (SDRC_SUCCESS);
1745331Samw }
1755331Samw 
1765331Samw /*
17711447Samw@Sun.COM  * Write (append) data to a print spool file.  The fid must refer to
17811447Samw@Sun.COM  * a print spool file.
1795331Samw  *
18011447Samw@Sun.COM  * The first SetupLength bytes (see SMB_COM_OPEN_PRINT_FILE) in the
18111447Samw@Sun.COM  * print spool file contain printer setup data.
1825331Samw  *
18311447Samw@Sun.COM  * Servers that negotiate LANMAN1.0 or later also support the use of
18411447Samw@Sun.COM  * normal write requests with print spool files.
1855331Samw  */
1866139Sjb150015 smb_sdrc_t
1876139Sjb150015 smb_pre_write_print_file(smb_request_t *sr)
1885331Samw {
18911447Samw@Sun.COM 	smb_rw_param_t	*param;
19011447Samw@Sun.COM 	int		rc;
19111447Samw@Sun.COM 
19211447Samw@Sun.COM 	param = kmem_zalloc(sizeof (smb_rw_param_t), KM_SLEEP);
19311447Samw@Sun.COM 	sr->arg.rw = param;
19411447Samw@Sun.COM 	param->rw_magic = SMB_RW_MAGIC;
19511447Samw@Sun.COM 
19611447Samw@Sun.COM 	rc = smbsr_decode_vwv(sr, "w", &sr->smb_fid);
19711447Samw@Sun.COM 
1986139Sjb150015 	DTRACE_SMB_1(op__WritePrintFile__start, smb_request_t *, sr);
19911447Samw@Sun.COM 	return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
2005331Samw }
2016139Sjb150015 
2026139Sjb150015 void
2036139Sjb150015 smb_post_write_print_file(smb_request_t *sr)
2046139Sjb150015 {
2056139Sjb150015 	DTRACE_SMB_1(op__WritePrintFile__done, smb_request_t *, sr);
20611447Samw@Sun.COM 
20711447Samw@Sun.COM 	kmem_free(sr->arg.rw, sizeof (smb_rw_param_t));
2086139Sjb150015 }
2096139Sjb150015 
21011447Samw@Sun.COM smb_sdrc_t
2116139Sjb150015 smb_com_write_print_file(smb_request_t *sr)
2126139Sjb150015 {
21311447Samw@Sun.COM 	smb_rw_param_t	*param = sr->arg.rw;
21411447Samw@Sun.COM 	smb_node_t	*node;
21511447Samw@Sun.COM 	smb_attr_t	attr;
21611447Samw@Sun.COM 	int		rc;
21711447Samw@Sun.COM 
21811447Samw@Sun.COM 	if (!STYPE_ISPRN(sr->tid_tree->t_res_type)) {
21911447Samw@Sun.COM 		smbsr_error(sr, NT_STATUS_BAD_DEVICE_TYPE,
22011447Samw@Sun.COM 		    ERRDOS, ERROR_BAD_DEV_TYPE);
22111447Samw@Sun.COM 		return (SDRC_ERROR);
22211447Samw@Sun.COM 	}
22311447Samw@Sun.COM 
22411447Samw@Sun.COM 	smbsr_lookup_file(sr);
22511447Samw@Sun.COM 	if (sr->fid_ofile == NULL) {
22611447Samw@Sun.COM 		smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRbadfid);
22711447Samw@Sun.COM 		return (SDRC_ERROR);
22811447Samw@Sun.COM 	}
22911447Samw@Sun.COM 
23011447Samw@Sun.COM 	node = sr->fid_ofile->f_node;
23111447Samw@Sun.COM 	sr->user_cr = smb_ofile_getcred(sr->fid_ofile);
23211447Samw@Sun.COM 
23311447Samw@Sun.COM 	if (smb_node_getattr(sr, node, &attr) != 0) {
23411447Samw@Sun.COM 		smbsr_error(sr, NT_STATUS_INTERNAL_ERROR,
23511447Samw@Sun.COM 		    ERRDOS, ERROR_INTERNAL_ERROR);
23611447Samw@Sun.COM 		return (SDRC_ERROR);
23711447Samw@Sun.COM 	}
23811447Samw@Sun.COM 
23911447Samw@Sun.COM 	if ((smbsr_decode_data(sr, "D", &param->rw_vdb)) != 0) {
24011447Samw@Sun.COM 		smbsr_error(sr, NT_STATUS_INVALID_PARAMETER,
24111447Samw@Sun.COM 		    ERRDOS, ERROR_INVALID_PARAMETER);
24211447Samw@Sun.COM 		return (SDRC_ERROR);
24311447Samw@Sun.COM 	}
24411447Samw@Sun.COM 
24511447Samw@Sun.COM 	param->rw_count = param->rw_vdb.vdb_len;
24611447Samw@Sun.COM 	param->rw_offset = attr.sa_vattr.va_size;
24711447Samw@Sun.COM 	param->rw_vdb.vdb_uio.uio_loffset = (offset_t)param->rw_offset;
24811447Samw@Sun.COM 
24911447Samw@Sun.COM 	if ((rc = smb_common_write(sr, param)) != 0) {
25011447Samw@Sun.COM 		if (sr->smb_error.status != NT_STATUS_FILE_LOCK_CONFLICT)
25111447Samw@Sun.COM 			smbsr_errno(sr, rc);
25211447Samw@Sun.COM 		return (SDRC_ERROR);
25311447Samw@Sun.COM 	}
25411447Samw@Sun.COM 
25511447Samw@Sun.COM 	rc = smbsr_encode_empty_result(sr);
25611447Samw@Sun.COM 	return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
2576139Sjb150015 }
258