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", ¶m->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