xref: /onnv-gate/usr/src/uts/common/fs/smbsrv/smb_print.c (revision 12890:16985853e3aa)
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 /*
2212508Samw@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>
30*12890SJoyce.McIntosh@Sun.COM #include <sys/unistd.h>
31*12890SJoyce.McIntosh@Sun.COM #include <sys/stat.h>
32*12890SJoyce.McIntosh@Sun.COM #include <sys/types.h>
33*12890SJoyce.McIntosh@Sun.COM #include <sys/fcntl.h>
34*12890SJoyce.McIntosh@Sun.COM #include <smbsrv/smb_share.h>
355331Samw 
365331Samw /*
37*12890SJoyce.McIntosh@Sun.COM  * Starts the creation of a new printer file, which will be deleted
38*12890SJoyce.McIntosh@Sun.COM  * automatically once it has been closed and printed.
395331Samw  *
405331Samw  * SetupLength is the number of bytes in the first part of the resulting
415331Samw  * print spool file which contains printer-specific control strings.
425331Samw  *
435331Samw  * Mode can have the following values:
445331Samw  *      0     Text mode.  The server may optionally
455331Samw  *            expand tabs to a series of spaces.
465331Samw  *      1     Graphics mode.  No conversion of data
475331Samw  *            should be done by the server.
485331Samw  *
4911447Samw@Sun.COM  * IdentifierString can be used by the server to provide some sort of
5011447Samw@Sun.COM  * per-client identifying component to the print file.
515331Samw  *
5211447Samw@Sun.COM  * When the file is closed, it will be sent to the spooler and printed.
535331Samw  */
546139Sjb150015 smb_sdrc_t
smb_pre_open_print_file(smb_request_t * sr)556139Sjb150015 smb_pre_open_print_file(smb_request_t *sr)
566139Sjb150015 {
5711447Samw@Sun.COM 	struct open_param	*op = &sr->arg.open;
5811447Samw@Sun.COM 	char			*path;
5911447Samw@Sun.COM 	char			*identifier;
6012508Samw@Sun.COM 	uint32_t		new_id;
6111447Samw@Sun.COM 	uint16_t		setup;
6211447Samw@Sun.COM 	uint16_t		mode;
6311447Samw@Sun.COM 	int			rc;
64*12890SJoyce.McIntosh@Sun.COM 	static uint32_t		tmp_id = 10000;
6511447Samw@Sun.COM 
6611447Samw@Sun.COM 	bzero(op, sizeof (sr->arg.open));
6711447Samw@Sun.COM 	rc = smbsr_decode_vwv(sr, "ww", &setup, &mode);
6811447Samw@Sun.COM 	if (rc == 0)
6911447Samw@Sun.COM 		rc = smbsr_decode_data(sr, "%S", sr, &identifier);
7011447Samw@Sun.COM 
7112508Samw@Sun.COM 	if (rc == 0) {
7212508Samw@Sun.COM 		path = smb_srm_zalloc(sr, MAXPATHLEN);
7312508Samw@Sun.COM 		op->fqi.fq_path.pn_path = path;
7412508Samw@Sun.COM 		new_id = atomic_inc_32_nv(&tmp_id);
7512508Samw@Sun.COM 		(void) snprintf(path, MAXPATHLEN, "%s%05u", identifier, new_id);
7612508Samw@Sun.COM 	}
7711447Samw@Sun.COM 
7811447Samw@Sun.COM 	op->create_disposition = FILE_OVERWRITE_IF;
7911447Samw@Sun.COM 	op->create_options = FILE_NON_DIRECTORY_FILE;
8011447Samw@Sun.COM 	DTRACE_SMB_2(op__OpenPrintFile__start, smb_request_t *, sr,
8111447Samw@Sun.COM 	    struct open_param *, op);
8211447Samw@Sun.COM 
8311447Samw@Sun.COM 	return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
846139Sjb150015 }
856139Sjb150015 
866139Sjb150015 void
smb_post_open_print_file(smb_request_t * sr)876139Sjb150015 smb_post_open_print_file(smb_request_t *sr)
886139Sjb150015 {
896139Sjb150015 	DTRACE_SMB_1(op__OpenPrintFile__done, smb_request_t *, sr);
906139Sjb150015 }
916139Sjb150015 
92*12890SJoyce.McIntosh@Sun.COM /*
93*12890SJoyce.McIntosh@Sun.COM  * Creates a new spool file which will be later copied and
94*12890SJoyce.McIntosh@Sun.COM  * deleted by cupsd.  After the file is created, information
95*12890SJoyce.McIntosh@Sun.COM  * related to the file will be placed in a spooldoc list
96*12890SJoyce.McIntosh@Sun.COM  * to be later used by cupsd
97*12890SJoyce.McIntosh@Sun.COM  *
98*12890SJoyce.McIntosh@Sun.COM  * Return values
99*12890SJoyce.McIntosh@Sun.COM  * 	rc 0 SDRC_SUCCESS
100*12890SJoyce.McIntosh@Sun.COM  *	rc non-zero SDRC_ERROR
101*12890SJoyce.McIntosh@Sun.COM  */
102*12890SJoyce.McIntosh@Sun.COM 
10311447Samw@Sun.COM smb_sdrc_t
smb_com_open_print_file(smb_request_t * sr)1046139Sjb150015 smb_com_open_print_file(smb_request_t *sr)
1055331Samw {
106*12890SJoyce.McIntosh@Sun.COM 	int 		rc;
107*12890SJoyce.McIntosh@Sun.COM 	smb_kspooldoc_t *sp;
108*12890SJoyce.McIntosh@Sun.COM 	smb_kshare_t 	*si;
109*12890SJoyce.McIntosh@Sun.COM 	struct open_param *op = &sr->arg.open;
11011447Samw@Sun.COM 
11111447Samw@Sun.COM 	if (!STYPE_ISPRN(sr->tid_tree->t_res_type)) {
112*12890SJoyce.McIntosh@Sun.COM 		cmn_err(CE_WARN, "smb_com_open_print_file: bad device");
11311447Samw@Sun.COM 		smbsr_error(sr, NT_STATUS_BAD_DEVICE_TYPE,
11411447Samw@Sun.COM 		    ERRDOS, ERROR_BAD_DEV_TYPE);
11511447Samw@Sun.COM 		return (SDRC_ERROR);
11611447Samw@Sun.COM 	}
117*12890SJoyce.McIntosh@Sun.COM 	if ((rc = smb_common_create(sr)) != NT_STATUS_SUCCESS) {
118*12890SJoyce.McIntosh@Sun.COM 		cmn_err(CE_WARN, "smb_com_open_print_file: error rc=%d", rc);
11911447Samw@Sun.COM 		return (SDRC_ERROR);
120*12890SJoyce.McIntosh@Sun.COM 	}
121*12890SJoyce.McIntosh@Sun.COM 	if ((rc = smbsr_encode_result(sr, 1, 0,
122*12890SJoyce.McIntosh@Sun.COM 	    "bww", 1, sr->smb_fid, 0)) == 0) {
123*12890SJoyce.McIntosh@Sun.COM 		if ((si = smb_kshare_lookup(SMB_SHARE_PRINT)) == NULL) {
124*12890SJoyce.McIntosh@Sun.COM 			cmn_err(CE_NOTE, "smb_com_open_print_file: SDRC_ERROR");
125*12890SJoyce.McIntosh@Sun.COM 			return (SDRC_ERROR);
126*12890SJoyce.McIntosh@Sun.COM 		}
127*12890SJoyce.McIntosh@Sun.COM 		sp = kmem_zalloc(sizeof (smb_kspooldoc_t), KM_SLEEP);
128*12890SJoyce.McIntosh@Sun.COM 		(void) snprintf(sp->sd_path, MAXPATHLEN, "%s/%s", si->shr_path,
129*12890SJoyce.McIntosh@Sun.COM 		    op->fqi.fq_path.pn_path);
130*12890SJoyce.McIntosh@Sun.COM 		sp->sd_spool_num = sr->sr_server->sp_info.sp_cnt;
131*12890SJoyce.McIntosh@Sun.COM 		sp->sd_ipaddr = sr->session->ipaddr;
132*12890SJoyce.McIntosh@Sun.COM 		(void) strlcpy(sp->sd_username, sr->uid_user->u_name,
133*12890SJoyce.McIntosh@Sun.COM 		    MAXNAMELEN);
134*12890SJoyce.McIntosh@Sun.COM 		sp->sd_fid = sr->smb_fid;
135*12890SJoyce.McIntosh@Sun.COM 		if (smb_spool_add_doc(sp))
136*12890SJoyce.McIntosh@Sun.COM 			kmem_free(sp, sizeof (smb_kspooldoc_t));
137*12890SJoyce.McIntosh@Sun.COM 		smb_kshare_release(si);
138*12890SJoyce.McIntosh@Sun.COM 	}
13911447Samw@Sun.COM 	return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
1405331Samw }
1415331Samw 
1425331Samw /*
14311447Samw@Sun.COM  * Close the specified file handle and queue the file for printing.
14411447Samw@Sun.COM  * The fid refers to a file previously created as a print spool file.
1455331Samw  * On successful completion of this request, the file is queued for
1465331Samw  * printing by the server.
1475331Samw  *
14811447Samw@Sun.COM  * Servers that negotiate LANMAN1.0 or later allow all the the fid
14911447Samw@Sun.COM  * to be closed and printed via any close request.
1505331Samw  */
1516139Sjb150015 smb_sdrc_t
smb_pre_close_print_file(smb_request_t * sr)1526139Sjb150015 smb_pre_close_print_file(smb_request_t *sr)
1536139Sjb150015 {
15411447Samw@Sun.COM 	int rc;
15511447Samw@Sun.COM 
15611447Samw@Sun.COM 	rc = smbsr_decode_vwv(sr, "w", &sr->smb_fid);
15711447Samw@Sun.COM 
1586139Sjb150015 	DTRACE_SMB_1(op__ClosePrintFile__start, smb_request_t *, sr);
15911447Samw@Sun.COM 	return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
1606139Sjb150015 }
1616139Sjb150015 
1626139Sjb150015 void
smb_post_close_print_file(smb_request_t * sr)1636139Sjb150015 smb_post_close_print_file(smb_request_t *sr)
1646139Sjb150015 {
1656139Sjb150015 	DTRACE_SMB_1(op__ClosePrintFile__done, smb_request_t *, sr);
1666139Sjb150015 }
1676139Sjb150015 
168*12890SJoyce.McIntosh@Sun.COM /*
169*12890SJoyce.McIntosh@Sun.COM  *
170*12890SJoyce.McIntosh@Sun.COM  * Adds the print file fid to a list to be used as a search
171*12890SJoyce.McIntosh@Sun.COM  * key in the spooldoc list.  It then wakes up the smbd
172*12890SJoyce.McIntosh@Sun.COM  * spool monitor thread to copy the spool file.
173*12890SJoyce.McIntosh@Sun.COM  *
174*12890SJoyce.McIntosh@Sun.COM  * Return values
175*12890SJoyce.McIntosh@Sun.COM  * rc - 0 success
176*12890SJoyce.McIntosh@Sun.COM  *
177*12890SJoyce.McIntosh@Sun.COM  */
178*12890SJoyce.McIntosh@Sun.COM 
17911447Samw@Sun.COM smb_sdrc_t
smb_com_close_print_file(smb_request_t * sr)1806139Sjb150015 smb_com_close_print_file(smb_request_t *sr)
1815331Samw {
182*12890SJoyce.McIntosh@Sun.COM 	smb_sdrc_t rc;
183*12890SJoyce.McIntosh@Sun.COM 
18411447Samw@Sun.COM 	if (!STYPE_ISPRN(sr->tid_tree->t_res_type)) {
18511447Samw@Sun.COM 		smbsr_error(sr, NT_STATUS_BAD_DEVICE_TYPE,
18611447Samw@Sun.COM 		    ERRDOS, ERROR_BAD_DEV_TYPE);
187*12890SJoyce.McIntosh@Sun.COM 		cmn_err(CE_WARN, "smb_com_close_print_file: SDRC_ERROR");
18811447Samw@Sun.COM 		return (SDRC_ERROR);
18911447Samw@Sun.COM 	}
190*12890SJoyce.McIntosh@Sun.COM 	rc = smb_com_close(sr);
19111447Samw@Sun.COM 
192*12890SJoyce.McIntosh@Sun.COM 	(void) smb_spool_add_fid(sr->smb_fid);
193*12890SJoyce.McIntosh@Sun.COM 	cv_broadcast(&sr->sr_server->sp_info.sp_cv);
194*12890SJoyce.McIntosh@Sun.COM 
195*12890SJoyce.McIntosh@Sun.COM 	return (rc);
1965331Samw }
1975331Samw 
1985331Samw /*
19911447Samw@Sun.COM  * Get a list of print queue entries on the server.  Support for
20011447Samw@Sun.COM  * this request is optional (not required for Windows clients).
2015331Samw  */
2026030Sjb150015 smb_sdrc_t
smb_pre_get_print_queue(smb_request_t * sr)2036139Sjb150015 smb_pre_get_print_queue(smb_request_t *sr)
2046139Sjb150015 {
2056139Sjb150015 	DTRACE_SMB_1(op__GetPrintQueue__start, smb_request_t *, sr);
2066139Sjb150015 	return (SDRC_SUCCESS);
2076139Sjb150015 }
2086139Sjb150015 
2096139Sjb150015 void
smb_post_get_print_queue(smb_request_t * sr)2106139Sjb150015 smb_post_get_print_queue(smb_request_t *sr)
2116139Sjb150015 {
2126139Sjb150015 	DTRACE_SMB_1(op__GetPrintQueue__done, smb_request_t *, sr);
2136139Sjb150015 }
2146139Sjb150015 
2156139Sjb150015 smb_sdrc_t
smb_com_get_print_queue(smb_request_t * sr)2166139Sjb150015 smb_com_get_print_queue(smb_request_t *sr)
2175331Samw {
2185331Samw 	unsigned short max_count, start_ix;
2195331Samw 
2206030Sjb150015 	if (smbsr_decode_vwv(sr, "ww", &max_count, &start_ix) != 0)
2216139Sjb150015 		return (SDRC_ERROR);
2225331Samw 
2236030Sjb150015 	if (smbsr_encode_result(sr, 2, 3, "bwwwbw", 2, 0, 0, 3, 1, 0))
2246139Sjb150015 		return (SDRC_ERROR);
2256030Sjb150015 
2266139Sjb150015 	return (SDRC_SUCCESS);
2275331Samw }
2285331Samw 
2295331Samw /*
23011447Samw@Sun.COM  * Write (append) data to a print spool file.  The fid must refer to
23111447Samw@Sun.COM  * a print spool file.
2325331Samw  *
23311447Samw@Sun.COM  * The first SetupLength bytes (see SMB_COM_OPEN_PRINT_FILE) in the
23411447Samw@Sun.COM  * print spool file contain printer setup data.
2355331Samw  *
23611447Samw@Sun.COM  * Servers that negotiate LANMAN1.0 or later also support the use of
23711447Samw@Sun.COM  * normal write requests with print spool files.
2385331Samw  */
2396139Sjb150015 smb_sdrc_t
smb_pre_write_print_file(smb_request_t * sr)2406139Sjb150015 smb_pre_write_print_file(smb_request_t *sr)
2415331Samw {
24211447Samw@Sun.COM 	smb_rw_param_t	*param;
24311447Samw@Sun.COM 	int		rc;
24411447Samw@Sun.COM 
24511447Samw@Sun.COM 	param = kmem_zalloc(sizeof (smb_rw_param_t), KM_SLEEP);
24611447Samw@Sun.COM 	sr->arg.rw = param;
24711447Samw@Sun.COM 	param->rw_magic = SMB_RW_MAGIC;
24811447Samw@Sun.COM 
24911447Samw@Sun.COM 	rc = smbsr_decode_vwv(sr, "w", &sr->smb_fid);
25011447Samw@Sun.COM 
2516139Sjb150015 	DTRACE_SMB_1(op__WritePrintFile__start, smb_request_t *, sr);
25211447Samw@Sun.COM 	return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
2535331Samw }
2546139Sjb150015 
2556139Sjb150015 void
smb_post_write_print_file(smb_request_t * sr)2566139Sjb150015 smb_post_write_print_file(smb_request_t *sr)
2576139Sjb150015 {
2586139Sjb150015 	DTRACE_SMB_1(op__WritePrintFile__done, smb_request_t *, sr);
25911447Samw@Sun.COM 
26011447Samw@Sun.COM 	kmem_free(sr->arg.rw, sizeof (smb_rw_param_t));
2616139Sjb150015 }
2626139Sjb150015 
26311447Samw@Sun.COM smb_sdrc_t
smb_com_write_print_file(smb_request_t * sr)2646139Sjb150015 smb_com_write_print_file(smb_request_t *sr)
2656139Sjb150015 {
26611447Samw@Sun.COM 	smb_rw_param_t	*param = sr->arg.rw;
26711447Samw@Sun.COM 	smb_node_t	*node;
26811447Samw@Sun.COM 	smb_attr_t	attr;
26911447Samw@Sun.COM 	int		rc;
27011447Samw@Sun.COM 
27111447Samw@Sun.COM 	if (!STYPE_ISPRN(sr->tid_tree->t_res_type)) {
27211447Samw@Sun.COM 		smbsr_error(sr, NT_STATUS_BAD_DEVICE_TYPE,
27311447Samw@Sun.COM 		    ERRDOS, ERROR_BAD_DEV_TYPE);
27411447Samw@Sun.COM 		return (SDRC_ERROR);
27511447Samw@Sun.COM 	}
27611447Samw@Sun.COM 
27711447Samw@Sun.COM 	smbsr_lookup_file(sr);
27811447Samw@Sun.COM 	if (sr->fid_ofile == NULL) {
27911447Samw@Sun.COM 		smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRbadfid);
28011447Samw@Sun.COM 		return (SDRC_ERROR);
28111447Samw@Sun.COM 	}
28211447Samw@Sun.COM 
28311447Samw@Sun.COM 	node = sr->fid_ofile->f_node;
28411447Samw@Sun.COM 	sr->user_cr = smb_ofile_getcred(sr->fid_ofile);
28511447Samw@Sun.COM 
28611447Samw@Sun.COM 	if (smb_node_getattr(sr, node, &attr) != 0) {
28711447Samw@Sun.COM 		smbsr_error(sr, NT_STATUS_INTERNAL_ERROR,
28811447Samw@Sun.COM 		    ERRDOS, ERROR_INTERNAL_ERROR);
28911447Samw@Sun.COM 		return (SDRC_ERROR);
29011447Samw@Sun.COM 	}
29111447Samw@Sun.COM 
29211447Samw@Sun.COM 	if ((smbsr_decode_data(sr, "D", &param->rw_vdb)) != 0) {
29311447Samw@Sun.COM 		smbsr_error(sr, NT_STATUS_INVALID_PARAMETER,
29411447Samw@Sun.COM 		    ERRDOS, ERROR_INVALID_PARAMETER);
29511447Samw@Sun.COM 		return (SDRC_ERROR);
29611447Samw@Sun.COM 	}
29711447Samw@Sun.COM 
29811447Samw@Sun.COM 	param->rw_count = param->rw_vdb.vdb_len;
29911447Samw@Sun.COM 	param->rw_offset = attr.sa_vattr.va_size;
30011447Samw@Sun.COM 	param->rw_vdb.vdb_uio.uio_loffset = (offset_t)param->rw_offset;
30111447Samw@Sun.COM 
30211447Samw@Sun.COM 	if ((rc = smb_common_write(sr, param)) != 0) {
30311447Samw@Sun.COM 		if (sr->smb_error.status != NT_STATUS_FILE_LOCK_CONFLICT)
30411447Samw@Sun.COM 			smbsr_errno(sr, rc);
30511447Samw@Sun.COM 		return (SDRC_ERROR);
30611447Samw@Sun.COM 	}
30711447Samw@Sun.COM 
30811447Samw@Sun.COM 	rc = smbsr_encode_empty_result(sr);
30911447Samw@Sun.COM 	return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
3106139Sjb150015 }
311