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