Mercurial > illumos > illumos-gate
changeset 13094:81ec56bf6147
6972305 Preferred DC not selected after setting pdc via sharectl
6971047 smbd hang during FVT regression test
6711195 Sparc:Get error "Windows Explorer has stopped working" once click on Details fr Properties on Vista
PSARC/2009/464 Offline attribute
6972515 Offline attribute - PSARC 2009/464
PSARC/2010/037 Windows Sparse Attribute
6972519 Windows Sparse Attribute - PSARC 2010/037
6719444 [CLI] - idmap help's output is not consistent with man pages's
6975449 idmap test suite needs idmap_cache_get_data() from libidmap
6974351 OpenSSL still taking smbd down
line wrap: on
line diff
--- a/usr/src/cmd/idmap/idmap/idmap.c Wed Aug 11 17:59:10 2010 -0400 +++ b/usr/src/cmd/idmap/idmap/idmap.c Wed Aug 11 16:48:54 2010 -0700 @@ -455,11 +455,11 @@ "idmap remove -a\n" "idmap remove [-f|-t] name\n" "idmap remove [-d] name1 name2\n" - "idmap set-namemap [-a authenticationMethod] [-D bindDN] " - "[-j passwdfile] name1 name2\n" + "idmap set-namemap [-a authenticationMethod] [-D bindDN]\n" + " [-j passwdfile] name1 name2\n" "idmap show [-c] [-v] identity [targettype]\n" - "idmap unset-namemap [-a authenticationMethod] [-D bindDN]" - "[-j passwdfile] name\n"); + "idmap unset-namemap [-a authenticationMethod] [-D bindDN]\n" + " [-j passwdfile] name [targettype]\n"); } /* The handler for the "help" command. */
--- a/usr/src/cmd/smbsrv/dtrace/msrpc.d Wed Aug 11 17:59:10 2010 -0400 +++ b/usr/src/cmd/smbsrv/dtrace/msrpc.d Wed Aug 11 16:48:54 2010 -0700 @@ -327,6 +327,14 @@ } /* + * SPOOLSS + */ +pid$target::spoolss_*:entry, +pid$target::spoolss_*:return +{ +} + +/* * SVCCTL */ pid$target::svcctl_s_*:entry,
--- a/usr/src/cmd/smbsrv/smbd/Makefile Wed Aug 11 17:59:10 2010 -0400 +++ b/usr/src/cmd/smbsrv/smbd/Makefile Wed Aug 11 16:48:54 2010 -0700 @@ -32,6 +32,7 @@ smbd_nicmon.c \ smbd_opipe_doorsvc.c \ smbd_share_doorsvc.c \ + smbd_spool.c \ smbd_vss.c include ../../Makefile.cmd
--- a/usr/src/cmd/smbsrv/smbd/smbd.h Wed Aug 11 17:59:10 2010 -0400 +++ b/usr/src/cmd/smbsrv/smbd/smbd.h Wed Aug 11 16:48:54 2010 -0700 @@ -46,6 +46,7 @@ void smbd_nicmon_stop(void); int smbd_nicmon_refresh(void); int smbd_dc_monitor_init(void); +void smbd_dc_monitor_refresh(void); smb_token_t *smbd_user_auth_logon(smb_logon_t *); void smbd_user_nonauth_logon(uint32_t); void smbd_user_auth_logoff(uint32_t); @@ -54,6 +55,12 @@ boolean_t smbd_online(void); void smbd_online_wait(const char *); +void smbd_spool_init(void); +void smbd_spool_fini(void); +int smbd_cups_init(void); +void smbd_cups_fini(void); +void smbd_load_printers(void); + int smbd_vss_get_count(const char *, uint32_t *); void smbd_vss_get_snapshots(const char *, uint32_t, uint32_t *, uint32_t *, char **); @@ -75,6 +82,9 @@ int s_door_srv; int s_door_opipe; int s_secmode; /* Current security mode */ + char s_site[MAXHOSTNAMELEN]; + smb_inaddr_t s_pdc; + boolean_t s_pdc_changed; pthread_t s_refresh_tid; pthread_t s_localtime_tid; pthread_t s_spool_tid;
--- a/usr/src/cmd/smbsrv/smbd/smbd_join.c Wed Aug 11 17:59:10 2010 -0400 +++ b/usr/src/cmd/smbsrv/smbd/smbd_join.c Wed Aug 11 16:48:54 2010 -0700 @@ -43,6 +43,9 @@ extern smbd_t smbd; +static mutex_t smbd_dc_mutex; +static cond_t smbd_dc_cv; + static void *smbd_dc_monitor(void *); static void smbd_dc_update(void); static boolean_t smbd_set_netlogon_cred(void); @@ -59,6 +62,9 @@ pthread_attr_t attr; int rc; + (void) smb_config_getstr(SMB_CI_ADS_SITE, smbd.s_site, + MAXHOSTNAMELEN); + (void) smb_config_getip(SMB_CI_DOMAIN_SRV, &smbd.s_pdc); smb_ads_init(); if (smbd.s_secmode != SMB_SECMODE_DOMAIN) @@ -72,18 +78,55 @@ return (rc); } +void +smbd_dc_monitor_refresh(void) +{ + char site[MAXHOSTNAMELEN]; + smb_inaddr_t pdc; + + site[0] = '\0'; + bzero(&pdc, sizeof (smb_inaddr_t)); + (void) smb_config_getstr(SMB_CI_ADS_SITE, site, MAXHOSTNAMELEN); + (void) smb_config_getip(SMB_CI_DOMAIN_SRV, &pdc); + + (void) mutex_lock(&smbd_dc_mutex); + + if ((bcmp(&smbd.s_pdc, &pdc, sizeof (smb_inaddr_t)) != 0) || + (smb_strcasecmp(smbd.s_site, site, 0) != 0)) { + bcopy(&pdc, &smbd.s_pdc, sizeof (smb_inaddr_t)); + (void) strlcpy(smbd.s_site, site, MAXHOSTNAMELEN); + smbd.s_pdc_changed = B_TRUE; + (void) cond_signal(&smbd_dc_cv); + } + + (void) mutex_unlock(&smbd_dc_mutex); +} + /*ARGSUSED*/ static void * smbd_dc_monitor(void *arg) { boolean_t ds_not_responding = B_FALSE; + boolean_t ds_cfg_changed = B_FALSE; + timestruc_t delay; int i; smbd_dc_update(); smbd_online_wait("smbd_dc_monitor"); while (smbd_online()) { - (void) sleep(SMBD_DC_MONITOR_INTERVAL); + delay.tv_sec = SMBD_DC_MONITOR_INTERVAL; + delay.tv_nsec = 0; + + (void) mutex_lock(&smbd_dc_mutex); + (void) cond_reltimedwait(&smbd_dc_cv, &smbd_dc_mutex, &delay); + + if (smbd.s_pdc_changed) { + smbd.s_pdc_changed = B_FALSE; + ds_cfg_changed = B_TRUE; + } + + (void) mutex_unlock(&smbd_dc_mutex); for (i = 0; i < SMBD_DC_MONITOR_ATTEMPTS; ++i) { if (dssetup_check_service() == 0) { @@ -95,10 +138,12 @@ (void) sleep(SMBD_DC_MONITOR_RETRY_INTERVAL); } - if (ds_not_responding) { + if (ds_not_responding) smb_log(smbd.s_loghd, LOG_NOTICE, "smbd_dc_monitor: domain service not responding"); + if (ds_not_responding || ds_cfg_changed) { + ds_cfg_changed = B_FALSE; smb_ads_refresh(); smbd_dc_update(); }
--- a/usr/src/cmd/smbsrv/smbd/smbd_main.c Wed Aug 11 17:59:10 2010 -0400 +++ b/usr/src/cmd/smbsrv/smbd/smbd_main.c Wed Aug 11 16:48:54 2010 -0700 @@ -59,10 +59,9 @@ #include "smbd.h" #define SMBD_ONLINE_WAIT_INTERVAL 10 -#define SMB_CUPS_DOCNAME "generic_doc" +#define SMBD_REFRESH_INTERVAL 10 #define DRV_DEVICE_PATH "/devices/pseudo/smbsrv@0:smbsrv" #define SMB_DBDIR "/var/smb" -#define SMB_SPOOL_WAIT 2 static void *smbd_nbt_listener(void *); static void *smbd_tcp_listener(void *); @@ -87,25 +86,16 @@ static void smbd_sig_handler(int sig); static int32_t smbd_gmtoff(void); -static int smbd_localtime_init(void); +static void smbd_localtime_init(void); static void *smbd_localtime_monitor(void *arg); -static int smbd_spool_init(void); -static void *smbd_spool_monitor(void *arg); - -static int smbd_spool_init(void); -static void *smbd_spool_monitor(void *arg); +static void smbd_dyndns_init(void); +static void smbd_load_shares(void); static int smbd_refresh_init(void); static void smbd_refresh_fini(void); static void *smbd_refresh_monitor(void *); -static void *smbd_nbt_receiver(void *); -static void *smbd_nbt_listener(void *); - -static void *smbd_tcp_receiver(void *); -static void *smbd_tcp_listener(void *); - static int smbd_start_listeners(void); static void smbd_stop_listeners(void); static int smbd_kernel_start(void); @@ -494,10 +484,14 @@ smbd.s_loghd = smb_log_create(SMBD_LOGSIZE, SMBD_LOGNAME); smb_codepage_init(); + rc = smbd_cups_init(); + if (smb_config_getbool(SMB_CI_PRINT_ENABLE)) + smbd_report("print service %savailable", (rc == 0) ? "" : "un"); + if (smbd_nicmon_start(SMBD_DEFAULT_INSTANCE_FMRI) != 0) smbd_report("NIC monitor failed to start"); - (void) dyndns_start(); + smbd_dyndns_init(); smb_ipc_init(); if (smb_netbios_start() != 0) @@ -539,7 +533,7 @@ } dyndns_update_zones(); - (void) smbd_localtime_init(); + smbd_localtime_init(); (void) smb_lgrp_start(); smb_pwd_init(B_TRUE); @@ -558,19 +552,8 @@ return (-1); } - if (smb_shr_load() != 0) { - smbd_report("failed to start loading shares: %s", - strerror(errno)); - (void) mutex_unlock(&smbd_service_mutex); - return (-1); - } - - if (smbd_spool_init() != 0) { - smbd_report("failed to start print monitor: %s", - strerror(errno)); - (void) mutex_unlock(&smbd_service_mutex); - return (-1); - } + smbd_load_shares(); + smbd_load_printers(); smbd.s_initialized = B_TRUE; smbd_report("service initialized"); @@ -622,6 +605,7 @@ smb_domain_fini(); mlsvc_fini(); smb_netbios_stop(); + smbd_cups_fini(); smbd.s_initialized = B_FALSE; smbd_report("service terminated"); @@ -655,6 +639,9 @@ NULL); (void) pthread_attr_destroy(&tattr); + if (rc != 0) + smbd_report("unable to start refresh monitor: %s", + strerror(errno)); return (rc); } @@ -666,7 +653,8 @@ static void smbd_refresh_fini() { - if (pthread_self() != smbd.s_refresh_tid) { + if ((pthread_self() != smbd.s_refresh_tid) && + (smbd.s_refresh_tid != 0)) { (void) pthread_cancel(smbd.s_refresh_tid); (void) pthread_cond_destroy(&refresh_cond); (void) pthread_mutex_destroy(&refresh_mutex); @@ -674,20 +662,20 @@ } /* - * smbd_refresh_monitor() - * - * Wait for a refresh event. When this thread wakes up, update the - * smbd configuration from the SMF config information then go back to - * wait for the next refresh. + * Wait for refresh events. When woken up, update the smbd configuration + * from SMF and check for changes that require service reconfiguration. + * Throttling is applied to coallesce multiple refresh events when the + * service is being refreshed repeatedly. */ /*ARGSUSED*/ static void * smbd_refresh_monitor(void *arg) { - smb_kmod_cfg_t cfg; - int error; + smbd_online_wait("smbd_refresh_monitor"); while (!smbd.s_shutting_down) { + (void) sleep(SMBD_REFRESH_INTERVAL); + (void) pthread_mutex_lock(&refresh_mutex); while ((atomic_swap_uint(&smbd.s_refreshes, 0) == 0) && (!smbd.s_shutting_down)) @@ -701,45 +689,29 @@ (void) mutex_lock(&smbd_service_mutex); - /* - * We've been woken up by a refresh event so go do - * what is necessary. - */ - smb_ads_refresh(); + smbd_dc_monitor_refresh(); smb_ccache_remove(SMB_CCACHE_PATH); /* - * Start the dyndns thread, if required. * Clear the DNS zones for the existing interfaces * before updating the NIC interface list. */ - (void) dyndns_start(); dyndns_clear_zones(); if (smbd_nicmon_refresh() != 0) smbd_report("NIC monitor refresh failed"); + smb_netbios_name_reconfig(); smb_browser_reconfig(); dyndns_update_zones(); + (void) smbd_kernel_bind(); + smbd_load_shares(); + smbd_load_printers(); (void) mutex_unlock(&smbd_service_mutex); - - if (!smbd.s_kbound) { - if ((error = smbd_kernel_bind()) == 0) - (void) smb_shr_load(); - - continue; - } - - (void) smb_shr_load(); - - smb_load_kconfig(&cfg); - error = smb_kmod_setcfg(&cfg); - if (error < 0) - smbd_report("configuration update failed: %s", - strerror(error)); } + smbd.s_refresh_tid = 0; return (NULL); } @@ -778,16 +750,13 @@ void smbd_online_wait(const char *text) { - while (!smbd_online()) { - if (text != NULL) - smb_log(smbd.s_loghd, LOG_DEBUG, - "%s: waiting for online", text); + while (!smbd_online()) + (void) sleep(SMBD_ONLINE_WAIT_INTERVAL); - (void) sleep(SMBD_ONLINE_WAIT_INTERVAL); + if (text != NULL) { + smb_log(smbd.s_loghd, LOG_DEBUG, "%s: online", text); + (void) fprintf(stderr, "%s: online\n", text); } - - if (text != NULL) - smb_log(smbd.s_loghd, LOG_DEBUG, "%s: online", text); } /* @@ -821,14 +790,26 @@ /* * smbd_kernel_bind * - * This function open the smbsrv device and start the kernel service. + * If smbsrv is already bound, reload the configuration and update smbsrv. + * Otherwise, open the smbsrv device and start the kernel service. */ static int smbd_kernel_bind(void) { - int rc; + smb_kmod_cfg_t cfg; + int rc; - smbd_kernel_unbind(); + if (smbd.s_kbound) { + smb_load_kconfig(&cfg); + rc = smb_kmod_setcfg(&cfg); + if (rc < 0) + smbd_report("kernel configuration update failed: %s", + strerror(errno)); + return (rc); + } + + if (smb_kmod_isbound()) + smbd_kernel_unbind(); if ((rc = smb_kmod_bind()) == 0) { rc = smbd_kernel_start(); @@ -867,6 +848,7 @@ if (rc != 0) return (rc); + smbd_spool_init(); return (0); } @@ -876,69 +858,52 @@ static void smbd_kernel_unbind(void) { + smbd_spool_fini(); smbd_stop_listeners(); smb_kmod_unbind(); smbd.s_kbound = B_FALSE; } /* - * Initialization of the spool thread. - * Returns 0 on success, an error number if thread creation fails. + * Create the Dynamic DNS publisher thread. */ - -static int -smbd_spool_init(void) +static void +smbd_dyndns_init(void) { - pthread_attr_t tattr; - int rc; + pthread_t tid; + pthread_attr_t attr; + int rc; + + dyndns_start(); - (void) pthread_attr_init(&tattr); - (void) pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_DETACHED); - rc = pthread_create(&smbd.s_spool_tid, &tattr, smbd_spool_monitor, - NULL); - (void) pthread_attr_destroy(&tattr); + (void) pthread_attr_init(&attr); + (void) pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); + rc = pthread_create(&tid, &attr, dyndns_publisher, NULL); + (void) pthread_attr_destroy(&attr); - return (rc); + if (rc != 0) + smbd_report("unable to start dyndns publisher: %s", + strerror(errno)); } /* - * This user thread blocks waiting for close print file - * in the kernel. It then uses the data returned from the ioctl - * to copy the spool file into the cups spooler. - * This function is really only used by Vista and Win7 clients, - * other versions of windows create only a zero size file and this - * be removed by spoolss_copy_spool_file function. + * Launches a thread to populate the share cache by share information + * stored in sharemgr */ - -/*ARGSUSED*/ -static void * -smbd_spool_monitor(void *arg) +static void +smbd_load_shares(void) { - uint32_t spool_num; - char username[MAXNAMELEN]; - char path[MAXPATHLEN]; - smb_inaddr_t ipaddr; - int error_retry_cnt = 5; + pthread_t tid; + pthread_attr_t attr; + int rc; - smbd_online_wait("smbd_spool_monitor"); - - while (!smbd.s_shutting_down && (error_retry_cnt > 0)) { - errno = 0; + (void) pthread_attr_init(&attr); + (void) pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); + rc = pthread_create(&tid, &attr, smb_shr_load, NULL); + (void) pthread_attr_destroy(&attr); - if (smb_kmod_get_spool_doc(&spool_num, username, - path, &ipaddr) == 0) { - spoolss_copy_spool_file(&ipaddr, - username, path, SMB_CUPS_DOCNAME); - error_retry_cnt = 5; - } else { - if (errno == ECANCELED) - break; - - (void) sleep(SMB_SPOOL_WAIT); - error_retry_cnt--; - } - } - return (NULL); + if (rc != 0) + smbd_report("unable to load disk shares: %s", strerror(errno)); } /* @@ -946,29 +911,28 @@ * Returns 0 on success, an error number if thread creation fails. */ -int +static void smbd_localtime_init(void) { - pthread_attr_t tattr; - int rc; + pthread_attr_t attr; + int rc; - (void) pthread_attr_init(&tattr); - (void) pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_DETACHED); - rc = pthread_create(&smbd.s_localtime_tid, &tattr, + (void) pthread_attr_init(&attr); + (void) pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); + rc = pthread_create(&smbd.s_localtime_tid, &attr, smbd_localtime_monitor, NULL); - (void) pthread_attr_destroy(&tattr); - return (rc); + (void) pthread_attr_destroy(&attr); + + if (rc != 0) + smbd_report("unable to monitor localtime: %s", strerror(errno)); } /* - * Local time thread to kernel land. - * Send local gmtoff to kernel module one time at startup - * and each time it changes (up to twice a year). - * Local gmtoff is checked once every 15 minutes and - * since some timezones are aligned on half and qtr hour boundaries, - * once an hour would likely suffice. + * Send local gmtoff to the kernel module one time at startup and each + * time it changes (up to twice a year). + * Local gmtoff is checked once every 15 minutes since some timezones + * are aligned on half and quarter hour boundaries. */ - /*ARGSUSED*/ static void * smbd_localtime_monitor(void *arg)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/cmd/smbsrv/smbd/smbd_spool.c Wed Aug 11 16:48:54 2010 -0700 @@ -0,0 +1,510 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. + */ + +/* + * CUPS support for the SMB and SPOOLSS print services. + */ + +#include <sys/types.h> +#include <sys/stat.h> +#include <cups/cups.h> +#include <strings.h> +#include <syslog.h> +#include <signal.h> +#include <pthread.h> +#include <synch.h> +#include <dlfcn.h> +#include <errno.h> +#include <smbsrv/smb.h> +#include <smbsrv/smb_share.h> +#include "smbd.h" + +#define SMB_SPOOL_WAIT 2 +#define SMBD_PJOBLEN 256 +#define SMBD_PRINTER "Postscript" +#define SMBD_FN_PREFIX "cifsprintjob-" +#define SMBD_CUPS_SPOOL_DIR "//var//spool//cups" +#define SMBD_CUPS_DOCNAME "generic_doc" + +typedef struct smbd_printjob { + pid_t pj_pid; + int pj_sysjob; + int pj_fd; + time_t pj_start_time; + int pj_status; + size_t pj_size; + int pj_page_count; + boolean_t pj_isspooled; + boolean_t pj_jobnum; + char pj_filename[SMBD_PJOBLEN]; + char pj_jobname[SMBD_PJOBLEN]; + char pj_username[SMBD_PJOBLEN]; + char pj_queuename[SMBD_PJOBLEN]; +} smbd_printjob_t; + +typedef struct smb_cups_ops { + void *cups_hdl; + cups_lang_t *(*cupsLangDefault)(); + const char *(*cupsLangEncoding)(cups_lang_t *); + void (*cupsLangFree)(cups_lang_t *); + ipp_status_t (*cupsLastError)(); + int (*cupsGetDests)(cups_dest_t **); + void (*cupsFreeDests)(int, cups_dest_t *); + ipp_t *(*cupsDoFileRequest)(http_t *, ipp_t *, + const char *, const char *); + ipp_t *(*ippNew)(); + void (*ippDelete)(); + char *(*ippErrorString)(); + ipp_attribute_t *(*ippAddString)(); + void (*httpClose)(http_t *); + http_t *(*httpConnect)(const char *, int); +} smb_cups_ops_t; + +static uint32_t smbd_cups_jobnum = 1; +static smb_cups_ops_t smb_cups; +static mutex_t smbd_cups_mutex; + +static void *smbd_spool_monitor(void *); +static smb_cups_ops_t *smbd_cups_ops(void); +static void smbd_print_share_comment(smb_share_t *, cups_dest_t *); +static void *smbd_share_printers(void *); +static void smbd_spool_copyfile(smb_inaddr_t *, char *, char *, char *); + +extern smbd_t smbd; + +/* + * Initialize the spool thread. + * Returns 0 on success, an error number if thread creation fails. + */ +void +smbd_spool_init(void) +{ + pthread_attr_t attr; + int rc; + + (void) pthread_attr_init(&attr); + (void) pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); + rc = pthread_create(&smbd.s_spool_tid, &attr, smbd_spool_monitor, NULL); + (void) pthread_attr_destroy(&attr); + + if (rc != 0) + smb_log(smbd.s_loghd, LOG_NOTICE, + "failed to start print monitor: %s", strerror(errno)); +} + +/* + * A single pthread_kill should be sufficient but we include + * a couple of retries to avoid implementation idiosyncrasies + * around signal delivery. + */ +void +smbd_spool_fini(void) +{ + int i; + + if (pthread_self() == smbd.s_spool_tid) + return; + + for (i = 0; i < 3 && smbd.s_spool_tid != 0; ++i) { + if (pthread_kill(smbd.s_spool_tid, SIGTERM) == ESRCH) + break; + + (void) sleep(1); + } +} + +/* + * This thread blocks waiting for close print file in the kernel. + * It then uses the data returned from the ioctl to copy the spool file + * into the cups spooler. + * + * This mechanism is really only used by Windows Vista and Windows 7. + * Other versions of Windows create a zero size file, which is removed + * by smbd_spool_copyfile. + */ +/*ARGSUSED*/ +static void * +smbd_spool_monitor(void *arg) +{ + uint32_t spool_num; + char username[MAXNAMELEN]; + char path[MAXPATHLEN]; + smb_inaddr_t ipaddr; + int error_retry_cnt = 5; + + smbd_online_wait("smbd_spool_monitor"); + + spoolss_register_copyfile(smbd_spool_copyfile); + + while (!smbd.s_shutting_down && (error_retry_cnt > 0)) { + errno = 0; + + if (smb_kmod_get_spool_doc(&spool_num, username, + path, &ipaddr) == 0) { + smbd_spool_copyfile(&ipaddr, + username, path, SMBD_CUPS_DOCNAME); + error_retry_cnt = 5; + } else { + if (errno == ECANCELED) + break; + + (void) sleep(SMB_SPOOL_WAIT); + error_retry_cnt--; + } + } + + spoolss_register_copyfile(NULL); + smbd.s_spool_tid = 0; + return (NULL); +} + +/* + * All versions of windows use this function to spool files to a printer + * via the cups interface + */ +static void +smbd_spool_copyfile(smb_inaddr_t *ipaddr, char *username, char *path, + char *doc_name) +{ + smb_cups_ops_t *cups; + http_t *http = NULL; /* HTTP connection to server */ + ipp_t *request = NULL; /* IPP Request */ + ipp_t *response = NULL; /* IPP Response */ + cups_lang_t *language = NULL; /* Default language */ + char uri[HTTP_MAX_URI]; /* printer-uri attribute */ + char new_jobname[SMBD_PJOBLEN]; + smbd_printjob_t pjob; + char clientname[INET6_ADDRSTRLEN]; + struct stat sbuf; + int rc = 1; + + if (stat(path, &sbuf)) { + smb_log(smbd.s_loghd, LOG_INFO, "smbd_spool_copyfile: %s: %s", + path, strerror(errno)); + return; + } + + /* + * Remove zero size files and return; these were inadvertantly + * created by XP or 2000. + */ + if (sbuf.st_size == 0) { + if (remove(path) != 0) + smb_log(smbd.s_loghd, LOG_INFO, + "smbd_spool_copyfile: cannot remove %s: %s", + path, strerror(errno)); + return; + } + + if ((cups = smbd_cups_ops()) == NULL) + return; + + if ((http = cups->httpConnect("localhost", 631)) == NULL) { + smb_log(smbd.s_loghd, LOG_INFO, + "smbd_spool_copyfile: cupsd not running"); + return; + } + + if ((request = cups->ippNew()) == NULL) { + smb_log(smbd.s_loghd, LOG_INFO, + "smbd_spool_copyfile: ipp not running"); + return; + } + + request->request.op.operation_id = IPP_PRINT_JOB; + request->request.op.request_id = 1; + language = cups->cupsLangDefault(); + + cups->ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET, + "attributes-charset", NULL, cups->cupsLangEncoding(language)); + + cups->ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE, + "attributes-natural-language", NULL, language->language); + + (void) snprintf(uri, sizeof (uri), "ipp://localhost/printers/%s", + SMBD_PRINTER); + pjob.pj_pid = pthread_self(); + pjob.pj_sysjob = 10; + (void) strlcpy(pjob.pj_filename, path, SMBD_PJOBLEN); + pjob.pj_start_time = time(NULL); + pjob.pj_status = 2; + pjob.pj_size = sbuf.st_blocks * 512; + pjob.pj_page_count = 1; + pjob.pj_isspooled = B_TRUE; + pjob.pj_jobnum = smbd_cups_jobnum; + + (void) strlcpy(pjob.pj_jobname, doc_name, SMBD_PJOBLEN); + (void) strlcpy(pjob.pj_username, username, SMBD_PJOBLEN); + (void) strlcpy(pjob.pj_queuename, SMBD_CUPS_SPOOL_DIR, SMBD_PJOBLEN); + + cups->ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, + "printer-uri", NULL, uri); + + cups->ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, + "requesting-user-name", NULL, pjob.pj_username); + + if (smb_inet_ntop(ipaddr, clientname, + SMB_IPSTRLEN(ipaddr->a_family)) == NULL) { + smb_log(smbd.s_loghd, LOG_INFO, + "smbd_spool_copyfile: %s: unknown client", clientname); + goto out; + } + + cups->ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, + "job-originating-host-name", NULL, clientname); + + (void) snprintf(new_jobname, SMBD_PJOBLEN, "%s%d", + SMBD_FN_PREFIX, pjob.pj_jobnum); + cups->ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, + "job-name", NULL, new_jobname); + + (void) snprintf(uri, sizeof (uri) - 1, "/printers/%s", SMBD_PRINTER); + + response = cups->cupsDoFileRequest(http, request, uri, + pjob.pj_filename); + if (response != NULL) { + if (response->request.status.status_code >= IPP_OK_CONFLICT) { + smb_log(smbd.s_loghd, LOG_ERR, + "smbd_spool_copyfile: printer %s: %s", + SMBD_PRINTER, + cups->ippErrorString(cups->cupsLastError())); + } else { + atomic_inc_32(&smbd_cups_jobnum); + rc = 0; + } + } else { + smb_log(smbd.s_loghd, LOG_ERR, + "smbd_spool_copyfile: unable to print to %s", + cups->ippErrorString(cups->cupsLastError())); + } + + if (rc == 0) + (void) unlink(pjob.pj_filename); + +out: + if (response) + cups->ippDelete(response); + + if (language) + cups->cupsLangFree(language); + + if (http) + cups->httpClose(http); +} + +int +smbd_cups_init(void) +{ + (void) mutex_lock(&smbd_cups_mutex); + + if (smb_cups.cups_hdl != NULL) { + (void) mutex_unlock(&smbd_cups_mutex); + return (0); + } + + if ((smb_cups.cups_hdl = dlopen("libcups.so.2", RTLD_NOW)) == NULL) { + (void) mutex_unlock(&smbd_cups_mutex); + smb_log(smbd.s_loghd, LOG_DEBUG, + "smbd_cups_init: cannot open libcups"); + return (ENOENT); + } + + smb_cups.cupsLangDefault = + (cups_lang_t *(*)())dlsym(smb_cups.cups_hdl, "cupsLangDefault"); + smb_cups.cupsLangEncoding = (const char *(*)(cups_lang_t *)) + dlsym(smb_cups.cups_hdl, "cupsLangEncoding"); + smb_cups.cupsDoFileRequest = + (ipp_t *(*)(http_t *, ipp_t *, const char *, const char *)) + dlsym(smb_cups.cups_hdl, "cupsDoFileRequest"); + smb_cups.cupsLastError = (ipp_status_t (*)()) + dlsym(smb_cups.cups_hdl, "cupsLastError"); + smb_cups.cupsLangFree = (void (*)(cups_lang_t *)) + dlsym(smb_cups.cups_hdl, "cupsLangFree"); + smb_cups.cupsGetDests = (int (*)(cups_dest_t **)) + dlsym(smb_cups.cups_hdl, "cupsGetDests"); + smb_cups.cupsFreeDests = (void (*)(int, cups_dest_t *)) + dlsym(smb_cups.cups_hdl, "cupsFreeDests"); + + smb_cups.httpClose = (void (*)(http_t *)) + dlsym(smb_cups.cups_hdl, "httpClose"); + smb_cups.httpConnect = (http_t *(*)(const char *, int)) + dlsym(smb_cups.cups_hdl, "httpConnect"); + + smb_cups.ippNew = (ipp_t *(*)())dlsym(smb_cups.cups_hdl, "ippNew"); + smb_cups.ippDelete = (void (*)())dlsym(smb_cups.cups_hdl, "ippDelete"); + smb_cups.ippErrorString = (char *(*)()) + dlsym(smb_cups.cups_hdl, "ippErrorString"); + smb_cups.ippAddString = (ipp_attribute_t *(*)()) + dlsym(smb_cups.cups_hdl, "ippAddString"); + + if (smb_cups.cupsLangDefault == NULL || + smb_cups.cupsLangEncoding == NULL || + smb_cups.cupsDoFileRequest == NULL || + smb_cups.cupsLastError == NULL || + smb_cups.cupsLangFree == NULL || + smb_cups.cupsGetDests == NULL || + smb_cups.cupsFreeDests == NULL || + smb_cups.ippNew == NULL || + smb_cups.httpClose == NULL || + smb_cups.httpConnect == NULL || + smb_cups.ippDelete == NULL || + smb_cups.ippErrorString == NULL || + smb_cups.ippAddString == NULL) { + (void) dlclose(smb_cups.cups_hdl); + smb_cups.cups_hdl = NULL; + (void) mutex_unlock(&smbd_cups_mutex); + smb_log(smbd.s_loghd, LOG_DEBUG, + "smbd_cups_init: cannot load libcups"); + return (ENOENT); + } + + (void) mutex_unlock(&smbd_cups_mutex); + return (0); +} + +void +smbd_cups_fini(void) +{ + (void) mutex_lock(&smbd_cups_mutex); + + if (smb_cups.cups_hdl != NULL) { + (void) dlclose(smb_cups.cups_hdl); + smb_cups.cups_hdl = NULL; + } + + (void) mutex_unlock(&smbd_cups_mutex); +} + +static smb_cups_ops_t * +smbd_cups_ops(void) +{ + if (smb_cups.cups_hdl == NULL) + return (NULL); + + return (&smb_cups); +} + +void +smbd_load_printers(void) +{ + pthread_t tid; + pthread_attr_t attr; + int rc; + + if (!smb_config_getbool(SMB_CI_PRINT_ENABLE)) + return; + + (void) pthread_attr_init(&attr); + (void) pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); + rc = pthread_create(&tid, &attr, smbd_share_printers, &tid); + (void) pthread_attr_destroy(&attr); + + if (rc != 0) + smb_log(smbd.s_loghd, LOG_NOTICE, + "unable to load printer shares: %s", strerror(errno)); +} + +/* + * All print shares use the path from print$. + */ +/*ARGSUSED*/ +static void * +smbd_share_printers(void *arg) +{ + cups_dest_t *dests; + cups_dest_t *dest; + smb_cups_ops_t *cups; + smb_share_t si; + uint32_t nerr; + int num_dests; + int i; + + if (!smb_config_getbool(SMB_CI_PRINT_ENABLE)) + return (NULL); + + if ((cups = smbd_cups_ops()) == NULL) + return (NULL); + + if (smb_shr_get(SMB_SHARE_PRINT, &si) != NERR_Success) { + smb_log(smbd.s_loghd, LOG_DEBUG, + "smbd_share_printers unable to load %s", SMB_SHARE_PRINT); + return (NULL); + } + + num_dests = cups->cupsGetDests(&dests); + + for (i = num_dests, dest = dests; i > 0; i--, dest++) { + if (dest->instance != NULL) + continue; + + (void) strlcpy(si.shr_name, dest->name, MAXPATHLEN); + smbd_print_share_comment(&si, dest); + si.shr_type = STYPE_PRINTQ; + + nerr = smb_shr_add(&si); + if (nerr == NERR_Success || nerr == NERR_DuplicateShare) + smb_log(smbd.s_loghd, LOG_DEBUG, + "shared printer: %s", si.shr_name); + else + smb_log(smbd.s_loghd, LOG_DEBUG, + "smbd_share_printers: unable to add share %s: %u", + si.shr_name, nerr); + } + + cups->cupsFreeDests(num_dests, dests); + return (NULL); +} + +static void +smbd_print_share_comment(smb_share_t *si, cups_dest_t *dest) +{ + cups_option_t *options; + char *comment; + char *name; + char *value; + int i; + + comment = "Print Share"; + + if ((options = dest->options) == NULL) { + (void) strlcpy(si->shr_cmnt, comment, SMB_SHARE_CMNT_MAX); + return; + } + + for (i = 0; i < dest->num_options; ++i) { + name = options[i].name; + value = options[i].value; + + if (name == NULL || value == NULL || + *name == '\0' || *value == '\0') + continue; + + if (strcasecmp(name, "printer-info") == 0) { + comment = value; + break; + } + } + + (void) strlcpy(si->shr_cmnt, comment, SMB_SHARE_CMNT_MAX); +}
--- a/usr/src/common/xattr/xattr_common.c Wed Aug 11 17:59:10 2010 -0400 +++ b/usr/src/common/xattr/xattr_common.c Wed Aug 11 16:48:54 2010 -0700 @@ -63,6 +63,8 @@ { A_REPARSE_POINT, O_REPARSE_POINT, XATTR_VIEW_READONLY, DATA_TYPE_BOOLEAN_VALUE }, { A_GEN, O_NONE, XATTR_VIEW_READONLY, DATA_TYPE_UINT64 }, + { A_OFFLINE, O_OFFLINE, XATTR_VIEW_READWRITE, DATA_TYPE_BOOLEAN_VALUE }, + { A_SPARSE, O_SPARSE, XATTR_VIEW_READWRITE, DATA_TYPE_BOOLEAN_VALUE }, }; const char *
--- a/usr/src/lib/libidmap/common/mapfile-vers Wed Aug 11 17:59:10 2010 -0400 +++ b/usr/src/lib/libidmap/common/mapfile-vers Wed Aug 11 16:48:54 2010 -0700 @@ -60,6 +60,7 @@ directory_sid_from_group_name; directory_sid_from_name; directory_sid_from_user_name; + idmap_cache_get_data; # used by idmap test suite idmap_flush; idmap_free; idmap_get_create;
--- a/usr/src/lib/libzpool/common/sys/zfs_context.h Wed Aug 11 17:59:10 2010 -0400 +++ b/usr/src/lib/libzpool/common/sys/zfs_context.h Wed Aug 11 16:48:54 2010 -0700 @@ -401,6 +401,8 @@ uint8_t xoa_av_modified; uint8_t xoa_av_scanstamp[AV_SCANSTAMP_SZ]; uint8_t xoa_reparse; + uint8_t xoa_offline; + uint8_t xoa_sparse; } xoptattr_t; typedef struct vattr {
--- a/usr/src/lib/smbsrv/libmlrpc/common/ndr_server.c Wed Aug 11 17:59:10 2010 -0400 +++ b/usr/src/lib/smbsrv/libmlrpc/common/ndr_server.c Wed Aug 11 16:48:54 2010 -0700 @@ -407,7 +407,6 @@ np->np_iov.iov_base = np->np_buf + np->np_uio.uio_offset; np->np_uio.uio_resid += desired; np->np_iov.iov_len += desired; - smb_tracef("ndr_pipe_grow: %d bytes", required); return (0); }
--- a/usr/src/lib/smbsrv/libmlsvc/common/libmlsvc.h Wed Aug 11 17:59:10 2010 -0400 +++ b/usr/src/lib/smbsrv/libmlsvc/common/libmlsvc.h Wed Aug 11 16:48:54 2010 -0700 @@ -277,9 +277,11 @@ uint32_t dfs_get_referrals(const char *, dfs_reftype_t, dfs_info_t *); void dfs_info_free(dfs_info_t *); -/* spool functions */ -void spoolss_copy_spool_file(smb_inaddr_t *, char *, char *, char *); - +/* + * The spoolss installable copyfile API. + */ +typedef void (*spoolss_copyfile_t)(smb_inaddr_t *, char *, char *, char *); +void spoolss_register_copyfile(spoolss_copyfile_t); #ifdef __cplusplus }
--- a/usr/src/lib/smbsrv/libmlsvc/common/lsar_svc.c Wed Aug 11 17:59:10 2010 -0400 +++ b/usr/src/lib/smbsrv/libmlsvc/common/lsar_svc.c Wed Aug 11 16:48:54 2010 -0700 @@ -786,6 +786,7 @@ * * On success return 0. Otherwise return an RPC specific error code. */ + static int lsarpc_s_LookupSids(void *arg, ndr_xa_t *mxa) { @@ -797,20 +798,22 @@ smb_account_t account; smb_sid_t *sid; DWORD n_entry; + DWORD n_mapped; + char sidstr[SMB_SID_STRSZ]; int result; int i; + bzero(&account, sizeof (smb_account_t)); + n_mapped = 0; n_entry = param->lup_sid_table.n_entry; + names = NDR_NEWN(mxa, struct mslsa_name_entry, n_entry); domain_table = NDR_NEW(mxa, struct mslsa_domain_table); domain_entry = NDR_NEWN(mxa, struct mslsa_domain_entry, MLSVC_DOMAIN_MAX); - if (names == NULL || domain_table == NULL || domain_entry == NULL) { - bzero(param, sizeof (struct mslsa_LookupSids)); - param->status = NT_SC_ERROR(NT_STATUS_NO_MEMORY); - return (NDR_DRC_OK); - } + if (names == NULL || domain_table == NULL || domain_entry == NULL) + goto lookup_sid_failed; domain_table->entries = domain_entry; domain_table->n_entry = 0; @@ -818,29 +821,33 @@ name = names; for (i = 0; i < n_entry; ++i, name++) { - bzero(&names[i], sizeof (struct mslsa_name_entry)); + bzero(name, sizeof (struct mslsa_name_entry)); sid = (smb_sid_t *)param->lup_sid_table.entries[i].psid; result = lsa_lookup_sid(sid, &account); - if (result != NT_STATUS_SUCCESS) - goto lookup_sid_failed; + if ((result != NT_STATUS_SUCCESS) || + (account.a_name == NULL) || (*account.a_name == '\0')) { + account.a_type = SidTypeUnknown; + smb_sid_tostr(sid, sidstr); - if (*account.a_name != '\0') { + if (NDR_MSTRING(mxa, sidstr, + (ndr_mstring_t *)&name->name) == -1) + goto lookup_sid_failed; + + } else { if (NDR_MSTRING(mxa, account.a_name, - (ndr_mstring_t *)&name->name) == -1) { - result = NT_STATUS_NO_MEMORY; + (ndr_mstring_t *)&name->name) == -1) goto lookup_sid_failed; - } + + ++n_mapped; } + name->sid_name_use = account.a_type; result = lsarpc_s_UpdateDomainTable(mxa, &account, domain_table, &name->domain_ix); - - if (result == -1) { - result = NT_STATUS_INTERNAL_ERROR; + if (result == -1) goto lookup_sid_failed; - } smb_account_free(&account); } @@ -848,20 +855,21 @@ param->domain_table = domain_table; param->name_table.n_entry = n_entry; param->name_table.entries = names; - param->mapped_count = n_entry; - param->status = 0; + param->mapped_count = n_mapped; + + if (n_mapped == n_entry) + param->status = NT_STATUS_SUCCESS; + else if (n_mapped == 0) + param->status = NT_STATUS_NONE_MAPPED; + else + param->status = NT_STATUS_SOME_NOT_MAPPED; return (NDR_DRC_OK); lookup_sid_failed: - param->domain_table = 0; - param->name_table.n_entry = 0; - param->name_table.entries = 0; - param->mapped_count = 0; - param->status = NT_SC_ERROR(result); - smb_account_free(&account); - return (NDR_DRC_OK); + bzero(param, sizeof (struct mslsa_LookupSids)); + return (NDR_DRC_FAULT_OUT_OF_MEMORY); } /* @@ -942,20 +950,22 @@ smb_account_t account; smb_sid_t *sid; DWORD n_entry; + DWORD n_mapped; + char sidstr[SMB_SID_STRSZ]; int result; int i; + bzero(&account, sizeof (smb_account_t)); + n_mapped = 0; n_entry = param->lup_sid_table.n_entry; + names = NDR_NEWN(mxa, struct lsar_name_entry2, n_entry); domain_table = NDR_NEW(mxa, struct mslsa_domain_table); domain_entry = NDR_NEWN(mxa, struct mslsa_domain_entry, MLSVC_DOMAIN_MAX); - if (names == NULL || domain_table == NULL || domain_entry == NULL) { - bzero(param, sizeof (struct lsar_lookup_sids2)); - param->status = NT_SC_ERROR(NT_STATUS_NO_MEMORY); - return (NDR_DRC_OK); - } + if (names == NULL || domain_table == NULL || domain_entry == NULL) + goto lookup_sid_failed; domain_table->entries = domain_entry; domain_table->n_entry = 0; @@ -967,25 +977,29 @@ sid = (smb_sid_t *)param->lup_sid_table.entries[i].psid; result = lsa_lookup_sid(sid, &account); - if (result != NT_STATUS_SUCCESS) - goto lookup_sid_failed; + if ((result != NT_STATUS_SUCCESS) || + (account.a_name == NULL) || (*account.a_name == '\0')) { + account.a_type = SidTypeUnknown; + smb_sid_tostr(sid, sidstr); - if (*account.a_name != '\0') { + if (NDR_MSTRING(mxa, sidstr, + (ndr_mstring_t *)&name->name) == -1) + goto lookup_sid_failed; + + } else { if (NDR_MSTRING(mxa, account.a_name, - (ndr_mstring_t *)&name->name) == -1) { - result = NT_STATUS_NO_MEMORY; + (ndr_mstring_t *)&name->name) == -1) goto lookup_sid_failed; - } + + ++n_mapped; } + name->sid_name_use = account.a_type; result = lsarpc_s_UpdateDomainTable(mxa, &account, domain_table, &name->domain_ix); - - if (result == -1) { - result = NT_STATUS_INTERNAL_ERROR; + if (result == -1) goto lookup_sid_failed; - } smb_account_free(&account); } @@ -993,20 +1007,21 @@ param->domain_table = domain_table; param->name_table.n_entry = n_entry; param->name_table.entries = names; - param->mapped_count = n_entry; - param->status = 0; + param->mapped_count = n_mapped; + + if (n_mapped == n_entry) + param->status = NT_STATUS_SUCCESS; + else if (n_mapped == 0) + param->status = NT_STATUS_NONE_MAPPED; + else + param->status = NT_STATUS_SOME_NOT_MAPPED; return (NDR_DRC_OK); lookup_sid_failed: - param->domain_table = 0; - param->name_table.n_entry = 0; - param->name_table.entries = 0; - param->mapped_count = 0; - param->status = NT_SC_ERROR(result); - smb_account_free(&account); - return (NDR_DRC_OK); + bzero(param, sizeof (struct lsar_lookup_sids2)); + return (NDR_DRC_FAULT_OUT_OF_MEMORY); } /*
--- a/usr/src/lib/smbsrv/libmlsvc/common/mapfile-vers Wed Aug 11 17:59:10 2010 -0400 +++ b/usr/src/lib/smbsrv/libmlsvc/common/mapfile-vers Wed Aug 11 16:48:54 2010 -0700 @@ -76,7 +76,7 @@ smb_shr_stop; smb_token_destroy; smb_token_log; - spoolss_copy_spool_file; + spoolss_register_copyfile; local: *; };
--- a/usr/src/lib/smbsrv/libmlsvc/common/mlsvc.h Wed Aug 11 17:59:10 2010 -0400 +++ b/usr/src/lib/smbsrv/libmlsvc/common/mlsvc.h Wed Aug 11 16:48:54 2010 -0700 @@ -25,7 +25,6 @@ #ifndef _SMBSRV_MLSVC_H #define _SMBSRV_MLSVC_H -#include <cups/cups.h> #include <smbsrv/smb_share.h> #include <smbsrv/ndl/netlogon.ndl> @@ -80,26 +79,6 @@ void smb_quota_add_fs(const char *); void smb_quota_remove_fs(const char *); -typedef struct smb_cups_ops { - void *cups_hdl; - cups_lang_t *(*cupsLangDefault)(); - const char *(*cupsLangEncoding)(cups_lang_t *); - void (*cupsLangFree)(cups_lang_t *); - ipp_status_t (*cupsLastError)(); - int (*cupsGetDests)(cups_dest_t **); - void (*cupsFreeDests)(int, cups_dest_t *); - ipp_t *(*cupsDoFileRequest)(http_t *, ipp_t *, const char *, - const char *); - ipp_t *(*ippNew)(); - void (*ippDelete)(); - char *(*ippErrorString)(); - ipp_attribute_t *(*ippAddString)(); - void (*httpClose)(http_t *); - http_t *(*httpConnect)(const char *, int); -} smb_cups_ops_t; - -smb_cups_ops_t *spoolss_cups_ops(void); - #ifdef __cplusplus } #endif
--- a/usr/src/lib/smbsrv/libmlsvc/common/smb_share.c Wed Aug 11 17:59:10 2010 -0400 +++ b/usr/src/lib/smbsrv/libmlsvc/common/smb_share.c Wed Aug 11 16:48:54 2010 -0700 @@ -52,7 +52,6 @@ #include <smbsrv/smb.h> #include <mlsvc.h> #include <dfs.h> -#include <cups/cups.h> #define SMB_SHR_ERROR_THRESHOLD 3 #define SMB_SHR_CSC_BUFSZ 64 @@ -139,12 +138,10 @@ /* * sharemgr functions */ -static void *smb_shr_sa_loadall(void *); static void smb_shr_sa_loadgrp(sa_group_t); static uint32_t smb_shr_sa_load(sa_share_t, sa_resource_t); static uint32_t smb_shr_sa_loadbyname(char *); static uint32_t smb_shr_sa_get(sa_share_t, sa_resource_t, smb_share_t *); -static void smb_shr_load_cups_printers(); /* * .ZFS management functions @@ -312,30 +309,6 @@ } /* - * Launches a thread to populate the share cache by share information - * stored in sharemgr - */ -int -smb_shr_load(void) -{ - pthread_t load_thr; - pthread_attr_t tattr; - int rc; - - (void) pthread_attr_init(&tattr); - (void) pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_DETACHED); - rc = pthread_create(&load_thr, &tattr, smb_shr_sa_loadall, 0); - (void) pthread_attr_destroy(&tattr); - - (void) mutex_lock(&smb_shr_exec_mtx); - (void) smb_config_get_execinfo(smb_shr_exec_map, smb_shr_exec_unmap, - MAXPATHLEN); - (void) mutex_unlock(&smb_shr_exec_mtx); - - return (rc); -} - -/* * Return the total number of shares */ int @@ -1458,17 +1431,21 @@ * Load shares from sharemgr */ /*ARGSUSED*/ -static void * -smb_shr_sa_loadall(void *args) +void * +smb_shr_load(void *args) { sa_handle_t handle; sa_group_t group, subgroup; char *gstate; boolean_t gdisabled; - boolean_t printing_enabled; + + (void) mutex_lock(&smb_shr_exec_mtx); + (void) smb_config_get_execinfo(smb_shr_exec_map, smb_shr_exec_unmap, + MAXPATHLEN); + (void) mutex_unlock(&smb_shr_exec_mtx); if ((handle = smb_shr_sa_enter()) == NULL) { - syslog(LOG_ERR, "smb_shr_sa_loadall: ret NULL"); + syslog(LOG_ERR, "smb_shr_load: load failed"); return (NULL); } @@ -1493,53 +1470,10 @@ } smb_shr_sa_exit(); - printing_enabled = smb_config_getbool(SMB_CI_PRINT_ENABLE); - if (printing_enabled) - smb_shr_load_cups_printers(); return (NULL); } /* - * Load print shares from cups - */ -static void -smb_shr_load_cups_printers() -{ - uint32_t nerr; - int i; - cups_dest_t *dests; - int num_dests; - cups_dest_t *dest; - smb_share_t si; - smb_cups_ops_t *cups; - - if ((cups = spoolss_cups_ops()) == NULL) - return; - - if (smb_shr_get(SMB_SHARE_PRINT, &si) != NERR_Success) { - syslog(LOG_DEBUG, "error getting print$"); - return; - } - - num_dests = cups->cupsGetDests(&dests); - for (i = num_dests, dest = dests; i > 0; i--, dest++) { - if (dest->instance == NULL) { - /* - * Use the path from print$ - */ - (void) strlcpy(si.shr_name, dest->name, MAXPATHLEN); - (void) strlcpy(si.shr_cmnt, - SMB_SHARE_PRINT, SMB_SHARE_PRINT_LEN + 1); - si.shr_type = STYPE_PRINTQ; - nerr = smb_shr_add(&si); - if (nerr != NERR_Success) - break; - } - } - cups->cupsFreeDests(num_dests, dests); -} - -/* * Load the shares contained in the specified group. * * Don't process groups on which the smb protocol is disabled.
--- a/usr/src/lib/smbsrv/libmlsvc/common/spoolss_svc.c Wed Aug 11 17:59:10 2010 -0400 +++ b/usr/src/lib/smbsrv/libmlsvc/common/spoolss_svc.c Wed Aug 11 16:48:54 2010 -0700 @@ -25,62 +25,61 @@ /* * Printing and Spooling RPC service. */ +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/utsname.h> #include <unistd.h> #include <stdlib.h> #include <strings.h> -#include <pthread.h> -#include <synch.h> +#include <fcntl.h> +#include <errno.h> #include <smbsrv/libsmb.h> #include <smbsrv/libmlrpc.h> #include <smbsrv/libmlsvc.h> -#include <smbsrv/ndl/ndrtypes.ndl> +#include <smbsrv/smb.h> #include <smbsrv/ndl/spoolss.ndl> +#include <smbsrv/ndl/winreg.ndl> #include <smb/nterror.h> #include <smbsrv/smbinfo.h> #include <smbsrv/nmpipes.h> -#include <wchar.h> -#include <cups/cups.h> -#include <fcntl.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <errno.h> -#include <dlfcn.h> #include <mlsvc.h> +#define SPOOLSS_PRINTER "Postscript" + typedef struct smb_spool { - list_t sp_list; - int sp_cnt; - rwlock_t sp_rwl; - int sp_initialized; + list_t sp_list; + int sp_cnt; + rwlock_t sp_rwl; + int sp_initialized; } smb_spool_t; +typedef struct smb_spooldoc { + uint32_t sd_magic; + list_node_t sd_lnd; + smb_inaddr_t sd_ipaddr; + int sd_spool_num; + char sd_username[MAXNAMELEN]; + char sd_path[MAXPATHLEN]; + char sd_doc_name[MAXNAMELEN]; + char sd_printer_name[MAXPATHLEN]; + int32_t sd_fd; + ndr_hdid_t sd_handle; +} smb_spooldoc_t; + +typedef struct { + char *name; + uint32_t value; +} spoolss_winreg_t; + +typedef struct { + uint8_t *sd_buf; + uint32_t sd_size; +} spoolss_sd_t; + static uint32_t spoolss_cnt; -static uint32_t spoolss_jobnum = 1; static smb_spool_t spoolss_splist; -static smb_cups_ops_t smb_cups; -static mutex_t spoolss_cups_mutex; - -#define SPOOLSS_PJOBLEN 256 -#define SPOOLSS_JOB_NOT_ISSUED 3004 -#define SPOOLSS_PRINTER "Postscript" -#define SPOOLSS_FN_PREFIX "cifsprintjob-" -#define SPOOLSS_CUPS_SPOOL_DIR "//var//spool//cups" -struct spoolss_printjob { - pid_t pj_pid; - int pj_sysjob; - int pj_fd; - time_t pj_start_time; - int pj_status; - size_t pj_size; - int pj_page_count; - boolean_t pj_isspooled; - boolean_t pj_jobnum; - char pj_filename[SPOOLSS_PJOBLEN]; - char pj_jobname[SPOOLSS_PJOBLEN]; - char pj_username[SPOOLSS_PJOBLEN]; - char pj_queuename[SPOOLSS_PJOBLEN]; -}; +void (*spoolss_copyfile_callback)(smb_inaddr_t *, char *, char *, char *); DECL_FIXUP_STRUCT(spoolss_GetPrinter_result_u); DECL_FIXUP_STRUCT(spoolss_GetPrinter_result); @@ -92,13 +91,10 @@ DECL_FIXUP_STRUCT(spoolss_RFNPCNEX); uint32_t srvsvc_sd_set_relative(smb_sd_t *, uint8_t *); -static int spoolss_s_make_sd(uint8_t *); -static uint32_t spoolss_sd_format(smb_sd_t *); -static int spoolss_find_fd(ndr_hdid_t *); -static void spoolss_find_doc_and_print(ndr_hdid_t *); -static void spoolss_add_spool_doc(smb_spooldoc_t *); -static int spoolss_cups_init(void); -static void spoolss_cups_fini(void); +static int spoolss_getservername(char *, size_t); +static uint32_t spoolss_make_sd(ndr_xa_t *, spoolss_sd_t *); +static uint32_t spoolss_format_sd(smb_sd_t *); +static int spoolss_find_document(ndr_hdid_t *); static int spoolss_s_OpenPrinter(void *, ndr_xa_t *); static int spoolss_s_ClosePrinter(void *, ndr_xa_t *); @@ -116,7 +112,14 @@ static int spoolss_s_EndPagePrinter(void *, ndr_xa_t *); static int spoolss_s_rfnpcnex(void *, ndr_xa_t *); static int spoolss_s_WritePrinter(void *, ndr_xa_t *); +static int spoolss_s_AddForm(void *, ndr_xa_t *); +static int spoolss_s_DeleteForm(void *, ndr_xa_t *); static int spoolss_s_EnumForms(void *, ndr_xa_t *); +static int spoolss_s_AddMonitor(void *, ndr_xa_t *); +static int spoolss_s_DeleteMonitor(void *, ndr_xa_t *); +static int spoolss_s_DeletePort(void *, ndr_xa_t *); +static int spoolss_s_AddPortEx(void *, ndr_xa_t *); +static int spoolss_s_SetPort(void *, ndr_xa_t *); static int spoolss_s_stub(void *, ndr_xa_t *); static ndr_stub_table_t spoolss_stub_table[] = { @@ -138,7 +141,14 @@ { spoolss_s_ScheduleJob, SPOOLSS_OPNUM_ScheduleJob }, { spoolss_s_GetPrinterData, SPOOLSS_OPNUM_GetPrinterData }, { spoolss_s_ClosePrinter, SPOOLSS_OPNUM_ClosePrinter }, + { spoolss_s_AddForm, SPOOLSS_OPNUM_AddForm }, + { spoolss_s_DeleteForm, SPOOLSS_OPNUM_DeleteForm }, { spoolss_s_EnumForms, SPOOLSS_OPNUM_EnumForms }, + { spoolss_s_AddMonitor, SPOOLSS_OPNUM_AddMonitor }, + { spoolss_s_DeleteMonitor, SPOOLSS_OPNUM_DeleteMonitor }, + { spoolss_s_DeletePort, SPOOLSS_OPNUM_DeletePort }, + { spoolss_s_AddPortEx, SPOOLSS_OPNUM_AddPortEx }, + { spoolss_s_SetPort, SPOOLSS_OPNUM_SetPort }, { spoolss_s_stub, SPOOLSS_OPNUM_GetPrinterDriver2 }, { spoolss_s_stub, SPOOLSS_OPNUM_FCPN }, { spoolss_s_stub, SPOOLSS_OPNUM_ReplyOpenPrinter }, @@ -168,32 +178,66 @@ spoolss_stub_table /* stub_table */ }; -/* - * Defer calling spoolss_cups_init() until something actually - * needs access to CUPS due to the libcups dependency on OpenSSL. - * OpenSSL is not MT-safe and initializing CUPS here can crash - * OpenSSL if it collides with other threads that are in other - * libraries that are attempting to use OpenSSL. - */ void spoolss_initialize(void) { + if (!spoolss_splist.sp_initialized) { + list_create(&spoolss_splist.sp_list, + sizeof (smb_spooldoc_t), + offsetof(smb_spooldoc_t, sd_lnd)); + spoolss_splist.sp_initialized = 1; + } + + spoolss_copyfile_callback = NULL; + (void) ndr_svc_register(&spoolss_service); } void spoolss_finalize(void) { - spoolss_cups_fini(); + spoolss_copyfile_callback = NULL; +} + +/* + * Register a copyfile callback that the spoolss service can use to + * copy files to the spool directory. + * + * Set a null pointer to disable the copying of files to the spool + * directory. + */ +void +spoolss_register_copyfile(spoolss_copyfile_t copyfile) +{ + spoolss_copyfile_callback = copyfile; +} + +static void +spoolss_copyfile(smb_inaddr_t *ipaddr, char *username, char *path, + char *docname) +{ + if (spoolss_copyfile_callback != NULL) + (*spoolss_copyfile_callback)(ipaddr, username, path, docname); } static int spoolss_s_OpenPrinter(void *arg, ndr_xa_t *mxa) { struct spoolss_OpenPrinter *param = arg; - ndr_hdid_t *id; + char *name = (char *)param->printer_name; + ndr_hdid_t *id; - if ((id = ndr_hdalloc(mxa, 0)) == NULL) { + if (name != NULL && *name != '\0') { + if (strspn(name, "\\") > 2) { + bzero(¶m->handle, sizeof (spoolss_handle_t)); + param->status = ERROR_INVALID_PRINTER_NAME; + return (NDR_DRC_OK); + } + + smb_tracef("spoolss_s_OpenPrinter: %s", name); + } + + if ((id = ndr_hdalloc(mxa, NULL)) == NULL) { bzero(¶m->handle, sizeof (spoolss_handle_t)); param->status = ERROR_NOT_ENOUGH_MEMORY; return (NDR_DRC_OK); @@ -201,7 +245,6 @@ bcopy(id, ¶m->handle, sizeof (spoolss_handle_t)); param->status = 0; - return (NDR_DRC_OK); } @@ -228,99 +271,9 @@ } /* - * - * adds new spool doc to the tail. used by windows - * XP and 2000 only - * - * Return values - * smb_spooldoc_t - NULL if not found - */ - -static void -spoolss_add_spool_doc(smb_spooldoc_t *sp) -{ - (void) rw_wrlock(&spoolss_splist.sp_rwl); - if (!spoolss_splist.sp_initialized) { - list_create(&spoolss_splist.sp_list, - sizeof (smb_spooldoc_t), - offsetof(smb_spooldoc_t, sd_lnd)); - spoolss_splist.sp_initialized = 1; - } - list_insert_tail(&spoolss_splist.sp_list, sp); - spoolss_splist.sp_cnt++; - (void) rw_unlock(&spoolss_splist.sp_rwl); -} - -/* - * - * finds a completed spool doc using the RPC handle - * as the key, then prints the doc - * - * XP and 2000 only - * - */ - -static void -spoolss_find_doc_and_print(ndr_hdid_t *handle) -{ - smb_spooldoc_t *sp; - - if (!spoolss_splist.sp_initialized) { - syslog(LOG_ERR, "spoolss_find_doc_and_print: not initialized"); - return; - } - (void) rw_wrlock(&spoolss_splist.sp_rwl); - sp = list_head(&spoolss_splist.sp_list); - while (sp != NULL) { - /* - * search the spooldoc list for a matching RPC handle - * and use the info to pass to cups for printing - */ - if (!memcmp(handle, &(sp->sd_handle), sizeof (ndr_hdid_t))) { - spoolss_copy_spool_file(&sp->sd_ipaddr, - sp->sd_username, sp->sd_path, sp->sd_doc_name); - (void) close(sp->sd_fd); - list_remove(&spoolss_splist.sp_list, sp); - free(sp); - (void) rw_unlock(&spoolss_splist.sp_rwl); - return; - } - sp = list_next(&spoolss_splist.sp_list, sp); - } - syslog(LOG_ERR, "spoolss_find_doc_and_print: handle not found"); - (void) rw_unlock(&spoolss_splist.sp_rwl); -} - -static int -spoolss_find_fd(ndr_hdid_t *handle) -{ - smb_spooldoc_t *sp; - - if (!spoolss_splist.sp_initialized) { - syslog(LOG_ERR, "spoolss_find_fd: not initialized"); - return (-1); - } - (void) rw_rdlock(&spoolss_splist.sp_rwl); - sp = list_head(&spoolss_splist.sp_list); - while (sp != NULL) { - /* - * check for a matching rpc handle in the - * spooldoc list - */ - if (!memcmp(handle, &(sp->sd_handle), sizeof (ndr_hdid_t))) { - (void) rw_unlock(&spoolss_splist.sp_rwl); - return (sp->sd_fd); - } - sp = list_next(&spoolss_splist.sp_list, sp); - } - syslog(LOG_ERR, "spoolss_find_fd: handle not found"); - (void) rw_unlock(&spoolss_splist.sp_rwl); - return (-1); -} - -/* * Windows XP and 2000 use this mechanism to write spool files. - * Creates a spool file fd to be used by spoolss_s_WritePrinter. + * Create a spool file fd to be used by spoolss_s_WritePrinter + * and add it to the tail of the spool list. */ static int spoolss_s_StartDocPrinter(void *arg, ndr_xa_t *mxa) @@ -335,7 +288,7 @@ int fd; if (ndr_hdlookup(mxa, id) == NULL) { - syslog(LOG_ERR, "spoolss_s_StartDocPrinter: invalid handle"); + smb_tracef("spoolss_s_StartDocPrinter: invalid handle"); param->status = ERROR_INVALID_HANDLE; return (NDR_DRC_OK); } @@ -346,7 +299,7 @@ } if ((rc = smb_shr_get(SMB_SHARE_PRINT, &si)) != NERR_Success) { - syslog(LOG_INFO, "spoolss_s_StartDocPrinter: %s error=%d", + smb_tracef("spoolss_s_StartDocPrinter: %s error=%d", SMB_SHARE_PRINT, rc); param->status = rc; return (NDR_DRC_OK); @@ -372,8 +325,8 @@ spfile->sd_ipaddr = mxa->pipe->np_user.ui_ipaddr; (void) strlcpy((char *)spfile->sd_username, mxa->pipe->np_user.ui_account, MAXNAMELEN); - (void) memcpy(&spfile->sd_handle, ¶m->handle, - sizeof (rpc_handle_t)); + (void) memcpy(&spfile->sd_handle, ¶m->handle, sizeof (ndr_hdid_t)); + /* * write temporary spool file to print$ */ @@ -383,14 +336,22 @@ fd = open(g_path, O_CREAT | O_RDWR, 0600); if (fd == -1) { - syslog(LOG_INFO, "spoolss_s_StartDocPrinter: %s: %s", + smb_tracef("spoolss_s_StartDocPrinter: %s: %s", g_path, strerror(errno)); param->status = ERROR_OPEN_FAILED; free(spfile); } else { (void) strlcpy((char *)spfile->sd_path, g_path, MAXPATHLEN); spfile->sd_fd = (uint16_t)fd; - spoolss_add_spool_doc(spfile); + + /* + * Add the document to the spool list. + */ + (void) rw_wrlock(&spoolss_splist.sp_rwl); + list_insert_tail(&spoolss_splist.sp_list, spfile); + spoolss_splist.sp_cnt++; + (void) rw_unlock(&spoolss_splist.sp_rwl); + /* * JobId isn't used now, but if printQ management is added * this will have to be incremented per job submitted. @@ -403,16 +364,44 @@ /* * Windows XP and 2000 use this mechanism to write spool files + * Search the spooldoc list for a matching RPC handle and pass + * the spool the file for printing. */ - -/*ARGSUSED*/ static int spoolss_s_EndDocPrinter(void *arg, ndr_xa_t *mxa) { struct spoolss_EndDocPrinter *param = arg; + ndr_hdid_t *id = (ndr_hdid_t *)¶m->handle; + smb_spooldoc_t *sp; - spoolss_find_doc_and_print((ndr_hdid_t *)¶m->handle); - param->status = ERROR_SUCCESS; + if (ndr_hdlookup(mxa, id) == NULL) { + smb_tracef("spoolss_s_EndDocPrinter: invalid handle"); + param->status = ERROR_INVALID_HANDLE; + return (NDR_DRC_OK); + } + + param->status = ERROR_INVALID_HANDLE; + (void) rw_wrlock(&spoolss_splist.sp_rwl); + + sp = list_head(&spoolss_splist.sp_list); + while (sp != NULL) { + if (!memcmp(id, &(sp->sd_handle), sizeof (ndr_hdid_t))) { + spoolss_copyfile(&sp->sd_ipaddr, + sp->sd_username, sp->sd_path, sp->sd_doc_name); + (void) close(sp->sd_fd); + list_remove(&spoolss_splist.sp_list, sp); + free(sp); + param->status = ERROR_SUCCESS; + break; + } + + sp = list_next(&spoolss_splist.sp_list, sp); + } + + (void) rw_unlock(&spoolss_splist.sp_rwl); + + if (param->status != ERROR_SUCCESS) + smb_tracef("spoolss_s_EndDocPrinter: document not found"); return (NDR_DRC_OK); } @@ -440,8 +429,8 @@ spoolss_s_ClosePrinter(void *arg, ndr_xa_t *mxa) { struct spoolss_ClosePrinter *param = arg; - ndr_hdid_t *id = (ndr_hdid_t *)¶m->handle; - ndr_handle_t *hd; + ndr_hdid_t *id = (ndr_hdid_t *)¶m->handle; + ndr_handle_t *hd; if ((hd = ndr_hdlookup(mxa, id)) != NULL) { free(hd->nh_data); @@ -454,20 +443,110 @@ return (NDR_DRC_OK); } -/*ARGSUSED*/ -int +static int +spoolss_s_AddForm(void *arg, ndr_xa_t *mxa) +{ + struct spoolss_AddForm *param = arg; + ndr_hdid_t *id = (ndr_hdid_t *)¶m->handle; + + if (ndr_hdlookup(mxa, id) == NULL) { + bzero(param, sizeof (struct spoolss_AddForm)); + param->status = ERROR_INVALID_HANDLE; + return (NDR_DRC_OK); + } + + bzero(param, sizeof (struct spoolss_AddForm)); + param->status = ERROR_SUCCESS; + return (NDR_DRC_OK); +} + +static int +spoolss_s_DeleteForm(void *arg, ndr_xa_t *mxa) +{ + struct spoolss_DeleteForm *param = arg; + ndr_hdid_t *id = (ndr_hdid_t *)¶m->handle; + + if (ndr_hdlookup(mxa, id) == NULL) { + bzero(param, sizeof (struct spoolss_DeleteForm)); + param->status = ERROR_INVALID_HANDLE; + return (NDR_DRC_OK); + } + + bzero(param, sizeof (struct spoolss_DeleteForm)); + param->status = ERROR_SUCCESS; + return (NDR_DRC_OK); +} + +static int spoolss_s_EnumForms(void *arg, ndr_xa_t *mxa) { struct spoolss_EnumForms *param = arg; - DWORD status = ERROR_SUCCESS; + ndr_hdid_t *id = (ndr_hdid_t *)¶m->handle; - param->status = status; + if (ndr_hdlookup(mxa, id) == NULL) { + bzero(param, sizeof (struct spoolss_EnumForms)); + param->status = ERROR_INVALID_HANDLE; + return (NDR_DRC_OK); + } + + bzero(param, sizeof (struct spoolss_EnumForms)); + param->status = ERROR_SUCCESS; param->needed = 0; return (NDR_DRC_OK); } /*ARGSUSED*/ -int +static int +spoolss_s_AddMonitor(void *arg, ndr_xa_t *mxa) +{ + struct spoolss_AddMonitor *param = arg; + + param->status = ERROR_SUCCESS; + return (NDR_DRC_OK); +} + +/*ARGSUSED*/ +static int +spoolss_s_DeleteMonitor(void *arg, ndr_xa_t *mxa) +{ + struct spoolss_DeleteMonitor *param = arg; + + param->status = ERROR_SUCCESS; + return (NDR_DRC_OK); +} + +/*ARGSUSED*/ +static int +spoolss_s_DeletePort(void *arg, ndr_xa_t *mxa) +{ + struct spoolss_DeletePort *param = arg; + + param->status = ERROR_SUCCESS; + return (NDR_DRC_OK); +} + +/*ARGSUSED*/ +static int +spoolss_s_AddPortEx(void *arg, ndr_xa_t *mxa) +{ + struct spoolss_AddPortEx *param = arg; + + param->status = ERROR_SUCCESS; + return (NDR_DRC_OK); +} + +/*ARGSUSED*/ +static int +spoolss_s_SetPort(void *arg, ndr_xa_t *mxa) +{ + struct spoolss_SetPort *param = arg; + + param->status = ERROR_SUCCESS; + return (NDR_DRC_OK); +} + +/*ARGSUSED*/ +static int spoolss_s_EnumJobs(void *arg, ndr_xa_t *mxa) { struct spoolss_EnumJobs *param = arg; @@ -510,7 +589,7 @@ spoolss_s_ScheduleJob(void *arg, ndr_xa_t *mxa) { struct spoolss_ScheduleJob *param = arg; - DWORD status = SPOOLSS_JOB_NOT_ISSUED; + DWORD status = ERROR_SPL_NO_ADDJOB; param->status = status; return (NDR_DRC_OK); @@ -552,20 +631,20 @@ if (ndr_hdlookup(mxa, id) == NULL) { param->written = 0; param->status = ERROR_INVALID_HANDLE; - syslog(LOG_ERR, "spoolss_s_WritePrinter: invalid handle"); + smb_tracef("spoolss_s_WritePrinter: invalid handle"); return (NDR_DRC_OK); } - if ((spfd = spoolss_find_fd(id)) < 0) { + if ((spfd = spoolss_find_document(id)) < 0) { param->written = 0; param->status = ERROR_INVALID_HANDLE; - syslog(LOG_ERR, "spoolss_s_WritePrinter: cannot find fd"); + smb_tracef("spoolss_s_WritePrinter: document not found"); return (NDR_DRC_OK); } written = write(spfd, param->pBuf, param->BufCount); if (written < param->BufCount) { - syslog(LOG_ERR, "spoolss_s_WritePrinter: write failed"); + smb_tracef("spoolss_s_WritePrinter: write failed"); param->written = 0; param->status = ERROR_CANTWRITE; return (NDR_DRC_OK); @@ -577,274 +656,182 @@ } /* - * All versions of windows use this function to print - * spool files via the cups interface + * Find a document by RPC handle in the spool list and return the fd. */ - -void -spoolss_copy_spool_file(smb_inaddr_t *ipaddr, char *username, - char *path, char *doc_name) +static int +spoolss_find_document(ndr_hdid_t *handle) { - smb_cups_ops_t *cups; - int ret = 1; /* Return value */ - http_t *http = NULL; /* HTTP connection to server */ - ipp_t *request = NULL; /* IPP Request */ - ipp_t *response = NULL; /* IPP Response */ - cups_lang_t *language = NULL; /* Default language */ - char uri[HTTP_MAX_URI]; /* printer-uri attribute */ - char new_jobname[SPOOLSS_PJOBLEN]; - struct spoolss_printjob pjob; - char clientname[INET6_ADDRSTRLEN]; - struct stat sbuf; + smb_spooldoc_t *sp; - if (stat(path, &sbuf)) { - syslog(LOG_INFO, "spoolss_copy_spool_file: %s: %s", - path, strerror(errno)); - return; - } + (void) rw_rdlock(&spoolss_splist.sp_rwl); - /* - * Remove zero size files and return; these were inadvertantly - * created by XP or 2000. - */ - if (sbuf.st_blocks == 0) { - if (remove(path)) - syslog(LOG_INFO, - "spoolss_copy_spool_file: cannot remove %s", path); - return; - } - - if ((cups = spoolss_cups_ops()) == NULL) - return; - - if ((http = cups->httpConnect("localhost", 631)) == NULL) { - syslog(LOG_INFO, "spoolss_copy_spool_file: cupsd not running"); - return; + sp = list_head(&spoolss_splist.sp_list); + while (sp != NULL) { + if (!memcmp(handle, &(sp->sd_handle), sizeof (ndr_hdid_t))) { + (void) rw_unlock(&spoolss_splist.sp_rwl); + return (sp->sd_fd); + } + sp = list_next(&spoolss_splist.sp_list, sp); } - if ((request = cups->ippNew()) == NULL) { - syslog(LOG_INFO, "spoolss_copy_spool_file: ipp not running"); - return; - } - request->request.op.operation_id = IPP_PRINT_JOB; - request->request.op.request_id = 1; - language = cups->cupsLangDefault(); - - cups->ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET, - "attributes-charset", NULL, cups->cupsLangEncoding(language)); - - cups->ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE, - "attributes-natural-language", NULL, language->language); - - (void) snprintf(uri, sizeof (uri), "ipp://localhost/printers/%s", - SPOOLSS_PRINTER); - pjob.pj_pid = pthread_self(); - pjob.pj_sysjob = 10; - (void) strlcpy(pjob.pj_filename, path, SPOOLSS_PJOBLEN); - pjob.pj_start_time = time(NULL); - pjob.pj_status = 2; - pjob.pj_size = sbuf.st_blocks * 512; - pjob.pj_page_count = 1; - pjob.pj_isspooled = B_TRUE; - pjob.pj_jobnum = spoolss_jobnum; - - (void) strlcpy(pjob.pj_jobname, doc_name, SPOOLSS_PJOBLEN); - (void) strlcpy(pjob.pj_username, username, SPOOLSS_PJOBLEN); - (void) strlcpy(pjob.pj_queuename, SPOOLSS_CUPS_SPOOL_DIR, - SPOOLSS_PJOBLEN); - cups->ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, - "printer-uri", NULL, uri); - - cups->ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, - "requesting-user-name", NULL, pjob.pj_username); - - if (smb_inet_ntop(ipaddr, clientname, - SMB_IPSTRLEN(ipaddr->a_family)) == NULL) { - syslog(LOG_INFO, "spoolss_copy_spool_file: %s: unknown client", - clientname); - goto out; - } - cups->ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, - "job-originating-host-name", NULL, clientname); - - (void) snprintf(new_jobname, SPOOLSS_PJOBLEN, "%s%d", - SPOOLSS_FN_PREFIX, pjob.pj_jobnum); - cups->ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, - "job-name", NULL, new_jobname); - - (void) snprintf(uri, sizeof (uri) - 1, "/printers/%s", SPOOLSS_PRINTER); - - response = cups->cupsDoFileRequest(http, request, uri, - pjob.pj_filename); - if (response != NULL) { - if (response->request.status.status_code >= IPP_OK_CONFLICT) { - syslog(LOG_ERR, - "spoolss_copy_spool_file: file print %s: %s", - SPOOLSS_PRINTER, - cups->ippErrorString(cups->cupsLastError())); - } else { - atomic_inc_32(&spoolss_jobnum); - ret = 0; - } - } else { - syslog(LOG_ERR, - "spoolss_copy_spool_file: unable to print file to %s", - cups->ippErrorString(cups->cupsLastError())); - } - - if (ret == 0) - (void) unlink(pjob.pj_filename); - -out: - if (response) - cups->ippDelete(response); - - if (language) - cups->cupsLangFree(language); - - if (http) - cups->httpClose(http); + (void) rw_unlock(&spoolss_splist.sp_rwl); + return (-1); } +/* + * GetPrinterData is used t obtain values from the registry for a + * printer or a print server. See [MS-RPRN] for value descriptions. + * The registry returns ERROR_FILE_NOT_FOUND for unknown keys. + */ static int spoolss_s_GetPrinterData(void *arg, ndr_xa_t *mxa) { - struct spoolss_GetPrinterData *param = arg; - DWORD status = ERROR_SUCCESS; + static spoolss_winreg_t reg[] = { + { "ChangeId", 0x0050acf2 }, + { "W3SvcInstalled", 0x00000000 }, + { "BeepEnabled", 0x00000000 }, + { "EventLog", 0x0000001f }, + { "NetPopup", 0x00000000 }, + { "NetPopupToComputer", 0x00000000 }, + { "MajorVersion", 0x00000003 }, + { "MinorVersion", 0x00000000 }, + { "DsPresent", 0x00000000 } + }; - if (param->Size > 0) { - param->Buf = NDR_NEWN(mxa, char, param->Size); - bzero(param->Buf, param->Size); - } else { - param->Buf = NDR_NEWN(mxa, uint32_t, 1); - param->Buf[0] = 1; - param->Buf[1] = 1; - param->Buf[2] = 2; - param->Buf[3] = 2; + struct spoolss_GetPrinterData *param = arg; + char *name = (char *)param->pValueName; + char buf[MAXPATHLEN]; + static uint8_t reserved_buf[4]; + spoolss_winreg_t *rp; + smb_share_t si; + smb_version_t *osversion; + struct utsname sysname; + smb_wchar_t *wcs; + uint32_t value; + uint32_t status; + int wcslen; + int i; + + if (name == NULL || *name == '\0') { + status = ERROR_FILE_NOT_FOUND; + goto report_error; } - /* - * Increment pType if the Printer Data changes - * as specified by Microsoft documentation - */ - param->pType = 1; - if (strcasecmp((char *)param->pValueName, "ChangeId") == 0) { - param->pType = 4; - param->Buf[3] = 0x00; - param->Buf[2] = 0x50; - param->Buf[1] = 0xac; - param->Buf[0] = 0xf2; - } else if (strcasecmp((char *)param->pValueName, - "UISingleJobStatusString") == 0) { - status = ERROR_FILE_NOT_FOUND; - } else if (strcasecmp((char *)param->pValueName, - "W3SvcInstalled") == 0) { - status = ERROR_FILE_NOT_FOUND; - } else if (strcasecmp((char *)param->pValueName, - "PrintProcCaps_NT EMF 1.008") == 0) { - status = ERROR_FILE_NOT_FOUND; - } else if (strcasecmp((char *)param->pValueName, "OSVersion") == 0) { - param->Buf = NDR_NEWN(mxa, char, param->Size); - bzero(param->Buf, param->Size); - param->Buf[0] = 0x14; - param->Buf[1] = 0x01; - param->Buf[4] = 0x05; - param->Buf[12] = 0x93; - param->Buf[13] = 0x08; - } - param->status = status; - param->Needed = param->Size; - return (NDR_DRC_OK); -} + for (i = 0; i < sizeof (reg) / sizeof (reg[0]); ++i) { + param->pType = WINREG_DWORD; + param->Needed = sizeof (uint32_t); + rp = ®[i]; + + if (strcasecmp(name, rp->name) != 0) + continue; + + if (param->Size < sizeof (uint32_t)) { + param->Size = 0; + goto need_more_data; + } -smb_cups_ops_t * -spoolss_cups_ops(void) -{ - if (spoolss_cups_init() != 0) - return (NULL); + if ((param->Buf = NDR_NEW(mxa, uint32_t)) == NULL) { + status = ERROR_NOT_ENOUGH_MEMORY; + goto report_error; + } - return (&smb_cups); -} + value = rp->value; -static int -spoolss_cups_init(void) -{ - (void) mutex_lock(&spoolss_cups_mutex); + if ((strcasecmp(name, "DsPresent") == 0) && + (smb_config_get_secmode() == SMB_SECMODE_DOMAIN)) + value = 0x00000001; - if (smb_cups.cups_hdl != NULL) { - (void) mutex_unlock(&spoolss_cups_mutex); - return (0); + bcopy(&value, param->Buf, sizeof (uint32_t)); + param->Size = sizeof (uint32_t); + param->status = ERROR_SUCCESS; + return (NDR_DRC_OK); } - if ((smb_cups.cups_hdl = dlopen("libcups.so.2", RTLD_NOW)) == NULL) { - (void) mutex_unlock(&spoolss_cups_mutex); - syslog(LOG_DEBUG, "spoolss_cups_init: cannot open libcups"); - return (ENOENT); + if (strcasecmp(name, "OSVersion") == 0) { + param->pType = WINREG_BINARY; + param->Needed = sizeof (smb_version_t); + + if (param->Size < sizeof (smb_version_t)) { + param->Size = sizeof (smb_version_t); + goto need_more_data; + } + + if ((osversion = NDR_NEW(mxa, smb_version_t)) == NULL) { + status = ERROR_NOT_ENOUGH_MEMORY; + goto report_error; + } + + smb_config_get_version(osversion); + param->Buf = (uint8_t *)osversion; + param->status = ERROR_SUCCESS; + return (NDR_DRC_OK); + } + + if (strcasecmp(name, "DNSMachineName") == 0) { + param->pType = WINREG_SZ; + buf[0] = '\0'; + (void) smb_getfqhostname(buf, MAXHOSTNAMELEN); + goto encode_string; + } + + if (strcasecmp(name, "DefaultSpoolDirectory") == 0) { + param->pType = WINREG_SZ; + buf[0] = '\0'; + + if (smb_shr_get(SMB_SHARE_PRINT, &si) != NERR_Success) { + status = ERROR_FILE_NOT_FOUND; + goto report_error; + } + + (void) snprintf(buf, MAXPATHLEN, "C:/%s", si.shr_path); + (void) strcanon(buf, "/\\"); + (void) strsubst(buf, '/', '\\'); + goto encode_string; } - smb_cups.cupsLangDefault = - (cups_lang_t *(*)())dlsym(smb_cups.cups_hdl, "cupsLangDefault"); - smb_cups.cupsLangEncoding = (const char *(*)(cups_lang_t *)) - dlsym(smb_cups.cups_hdl, "cupsLangEncoding"); - smb_cups.cupsDoFileRequest = - (ipp_t *(*)(http_t *, ipp_t *, const char *, const char *)) - dlsym(smb_cups.cups_hdl, "cupsDoFileRequest"); - smb_cups.cupsLastError = (ipp_status_t (*)()) - dlsym(smb_cups.cups_hdl, "cupsLastError"); - smb_cups.cupsLangFree = (void (*)(cups_lang_t *)) - dlsym(smb_cups.cups_hdl, "cupsLangFree"); - smb_cups.cupsGetDests = (int (*)(cups_dest_t **)) - dlsym(smb_cups.cups_hdl, "cupsGetDests"); - smb_cups.cupsFreeDests = (void (*)(int, cups_dest_t *)) - dlsym(smb_cups.cups_hdl, "cupsFreeDests"); - - smb_cups.httpClose = (void (*)(http_t *)) - dlsym(smb_cups.cups_hdl, "httpClose"); - smb_cups.httpConnect = (http_t *(*)(const char *, int)) - dlsym(smb_cups.cups_hdl, "httpConnect"); + if (strcasecmp(name, "Architecture") == 0) { + param->pType = WINREG_SZ; - smb_cups.ippNew = (ipp_t *(*)())dlsym(smb_cups.cups_hdl, "ippNew"); - smb_cups.ippDelete = (void (*)())dlsym(smb_cups.cups_hdl, "ippDelete"); - smb_cups.ippErrorString = (char *(*)()) - dlsym(smb_cups.cups_hdl, "ippErrorString"); - smb_cups.ippAddString = (ipp_attribute_t *(*)()) - dlsym(smb_cups.cups_hdl, "ippAddString"); + if (uname(&sysname) < 0) + (void) strlcpy(buf, "Solaris", MAXPATHLEN); + else + (void) snprintf(buf, MAXPATHLEN, "%s %s", + sysname.sysname, sysname.machine); - if (smb_cups.cupsLangDefault == NULL || - smb_cups.cupsLangEncoding == NULL || - smb_cups.cupsDoFileRequest == NULL || - smb_cups.cupsLastError == NULL || - smb_cups.cupsLangFree == NULL || - smb_cups.cupsGetDests == NULL || - smb_cups.cupsFreeDests == NULL || - smb_cups.ippNew == NULL || - smb_cups.httpClose == NULL || - smb_cups.httpConnect == NULL || - smb_cups.ippDelete == NULL || - smb_cups.ippErrorString == NULL || - smb_cups.ippAddString == NULL) { - smb_dlclose(smb_cups.cups_hdl); - smb_cups.cups_hdl = NULL; - (void) mutex_unlock(&spoolss_cups_mutex); - syslog(LOG_DEBUG, "spoolss_cups_init: cannot load libcups"); - return (ENOENT); + goto encode_string; } - (void) mutex_unlock(&spoolss_cups_mutex); - return (0); -} + status = ERROR_FILE_NOT_FOUND; -static void -spoolss_cups_fini(void) -{ - (void) mutex_lock(&spoolss_cups_mutex); +report_error: + bzero(param, sizeof (struct spoolss_GetPrinterData)); + param->Buf = reserved_buf; + param->status = status; + return (NDR_DRC_OK); - if (smb_cups.cups_hdl != NULL) { - smb_dlclose(smb_cups.cups_hdl); - smb_cups.cups_hdl = NULL; +encode_string: + wcslen = smb_wcequiv_strlen(buf) + sizeof (smb_wchar_t); + if (param->Size < wcslen) { + param->Needed = wcslen; + goto need_more_data; } - (void) mutex_unlock(&spoolss_cups_mutex); + if ((wcs = NDR_MALLOC(mxa, wcslen)) == NULL) { + status = ERROR_NOT_ENOUGH_MEMORY; + goto report_error; + } + + (void) ndr_mbstowcs(NULL, wcs, buf, wcslen); + param->Buf = (uint8_t *)wcs; + param->Needed = wcslen; + param->status = ERROR_SUCCESS; + return (NDR_DRC_OK); + +need_more_data: + param->Size = 0; + param->Buf = reserved_buf; + param->status = ERROR_MORE_DATA; + return (NDR_DRC_OK); } void @@ -864,73 +851,68 @@ int spoolss_s_GetPrinter(void *arg, ndr_xa_t *mxa) { - struct spoolss_GetPrinter *param = arg; - struct spoolss_GetPrinter0 *pinfo0; - struct spoolss_GetPrinter1 *pinfo1; - struct spoolss_GetPrinter2 *pinfo2; - struct spoolss_DeviceMode *devmode2; - DWORD status = ERROR_SUCCESS; - char *wname; - uint32_t offset; - smb_inaddr_t ipaddr; - struct hostent *h; - char hname[MAXHOSTNAMELEN]; - char soutbuf[MAXNAMELEN]; - char poutbuf[MAXNAMELEN]; - char ipstr[INET6_ADDRSTRLEN]; - int error; - uint8_t *tmpbuf; + struct spoolss_GetPrinter *param = arg; + struct spoolss_GetPrinter0 *pinfo0; + struct spoolss_GetPrinter1 *pinfo1; + struct spoolss_GetPrinter2 *pinfo2; + struct spoolss_DeviceMode *devmode2; + ndr_hdid_t *id = (ndr_hdid_t *)¶m->handle; + spoolss_sd_t secdesc; + char server[MAXNAMELEN]; + char printer[MAXNAMELEN]; + DWORD status = ERROR_SUCCESS; + char *wname; + uint32_t offset; + uint8_t *tmpbuf; - if (param->BufCount == 0) { - status = ERROR_INSUFFICIENT_BUFFER; + if (ndr_hdlookup(mxa, id) == NULL) { + status = ERROR_INVALID_HANDLE; + goto error_out; + } + + if (spoolss_getservername(server, MAXNAMELEN) != 0) { + status = ERROR_INTERNAL_ERROR; goto error_out; } - param->Buf = NDR_NEWN(mxa, char, param->BufCount); + + (void) snprintf(printer, MAXNAMELEN, "%s\\%s", server, SPOOLSS_PRINTER); + + switch (param->switch_value) { + case 0: + case 1: + param->needed = 460; + break; + case 2: + param->needed = 712; + break; + default: + status = ERROR_INVALID_LEVEL; + goto error_out; + } + + if (param->BufCount < param->needed) { + param->BufCount = 0; + param->Buf = NULL; + param->status = ERROR_INSUFFICIENT_BUFFER; + return (NDR_DRC_OK); + } + + if ((param->Buf = NDR_MALLOC(mxa, param->BufCount)) == NULL) { + status = ERROR_NOT_ENOUGH_MEMORY; + goto error_out; + } + bzero(param->Buf, param->BufCount); + wname = (char *)param->Buf; + offset = param->needed; + switch (param->switch_value) { case 0: /*LINTED E_BAD_PTR_CAST_ALIGN*/ pinfo0 = (struct spoolss_GetPrinter0 *)param->Buf; - break; - case 1: - /*LINTED E_BAD_PTR_CAST_ALIGN*/ - pinfo1 = (struct spoolss_GetPrinter1 *)param->Buf; - break; - case 2: - /*LINTED E_BAD_PTR_CAST_ALIGN*/ - pinfo2 = (struct spoolss_GetPrinter2 *)param->Buf; - break; - } - wname = (char *)param->Buf; - status = ERROR_INVALID_PARAMETER; - if (smb_gethostname(hname, MAXHOSTNAMELEN, 0) != 0) { - syslog(LOG_NOTICE, "spoolss_s_GetPrinter: gethostname failed"); - goto error_out; - } - if ((h = smb_gethostbyname(hname, &error)) == NULL) { - syslog(LOG_NOTICE, - "spoolss_s_GetPrinter: gethostbyname failed"); - goto error_out; - } - bcopy(h->h_addr, &ipaddr, h->h_length); - ipaddr.a_family = h->h_addrtype; - freehostent(h); - if (smb_inet_ntop(&ipaddr, ipstr, SMB_IPSTRLEN(ipaddr.a_family)) - == NULL) { - syslog(LOG_NOTICE, "spoolss_s_GetPrinter: inet_ntop failed"); - goto error_out; - } - status = ERROR_SUCCESS; - (void) snprintf(poutbuf, MAXNAMELEN, "\\\\%s\\%s", - ipstr, SPOOLSS_PRINTER); - (void) snprintf(soutbuf, MAXNAMELEN, "\\\\%s", ipstr); - param->needed = 0; - switch (param->switch_value) { - case 0: - offset = 460; - smb_rpc_off(wname, "", &offset, &pinfo0->servername); - smb_rpc_off(wname, poutbuf, &offset, &pinfo0->printername); + smb_rpc_off(wname, server, &offset, &pinfo0->servername); + smb_rpc_off(wname, printer, &offset, &pinfo0->printername); pinfo0->cjobs = 0; pinfo0->total_jobs = 6; pinfo0->total_bytes = 1040771; @@ -948,16 +930,20 @@ pinfo0->c_setprinter = 0; break; case 1: + /*LINTED E_BAD_PTR_CAST_ALIGN*/ + pinfo1 = (struct spoolss_GetPrinter1 *)param->Buf; + pinfo1->flags = PRINTER_ENUM_ICON8; - offset = 460; - smb_rpc_off(wname, poutbuf, &offset, &pinfo1->flags); - smb_rpc_off(wname, poutbuf, &offset, &pinfo1->description); - smb_rpc_off(wname, poutbuf, &offset, &pinfo1->comment); + smb_rpc_off(wname, printer, &offset, &pinfo1->flags); + smb_rpc_off(wname, printer, &offset, &pinfo1->description); + smb_rpc_off(wname, printer, &offset, &pinfo1->comment); break; case 2: - offset = param->BufCount; - smb_rpc_off(wname, soutbuf, &offset, &pinfo2->servername); - smb_rpc_off(wname, poutbuf, &offset, &pinfo2->printername); + /*LINTED E_BAD_PTR_CAST_ALIGN*/ + pinfo2 = (struct spoolss_GetPrinter2 *)param->Buf; + + smb_rpc_off(wname, server, &offset, &pinfo2->servername); + smb_rpc_off(wname, printer, &offset, &pinfo2->printername); smb_rpc_off(wname, SPOOLSS_PRINTER, &offset, &pinfo2->sharename); smb_rpc_off(wname, "CIFS Printer Port", &offset, @@ -966,11 +952,26 @@ smb_rpc_off(wname, SPOOLSS_PRINTER, &offset, &pinfo2->comment); smb_rpc_off(wname, "farside", &offset, &pinfo2->location); + + offset -= sizeof (struct spoolss_DeviceMode); + pinfo2->devmode = offset; + /*LINTED E_BAD_PTR_CAST_ALIGN*/ + devmode2 = (struct spoolss_DeviceMode *)(param->Buf + offset); + smb_rpc_off(wname, "farside", &offset, &pinfo2->sepfile); smb_rpc_off(wname, "winprint", &offset, &pinfo2->printprocessor); smb_rpc_off(wname, "RAW", &offset, &pinfo2->datatype); - smb_rpc_off(wname, "", &offset, &pinfo2->datatype); + smb_rpc_off(wname, "", &offset, &pinfo2->parameters); + + status = spoolss_make_sd(mxa, &secdesc); + if (status == ERROR_SUCCESS) { + offset -= secdesc.sd_size; + pinfo2->secdesc = offset; + tmpbuf = (uint8_t *)(param->Buf + offset); + bcopy(secdesc.sd_buf, tmpbuf, secdesc.sd_size); + } + pinfo2->attributes = 0x00001048; pinfo2->status = 0x00000000; pinfo2->starttime = 0; @@ -978,13 +979,10 @@ pinfo2->cjobs = 0; pinfo2->averageppm = 0; pinfo2->defaultpriority = 0; - pinfo2->devmode = 568; // offset + /*LINTED E_BAD_PTR_CAST_ALIGN*/ - devmode2 = (struct spoolss_DeviceMode *)(param->Buf - + pinfo2->devmode); - /*LINTED E_BAD_PTR_CAST_ALIGN*/ - (void) smb_mbstowcs(((smb_wchar_t *) - (devmode2->devicename)), (const char *)poutbuf, 25); + (void) smb_mbstowcs((smb_wchar_t *)devmode2->devicename, + printer, 32); devmode2->specversion = 0x0401; devmode2->driverversion = 1024; devmode2->size = 220; @@ -1004,8 +1002,8 @@ devmode2->ttoption = 1; devmode2->collate = 0; /*LINTED E_BAD_PTR_CAST_ALIGN*/ - (void) smb_mbstowcs(((smb_wchar_t *) - (devmode2->formname)), (const char *)"Letter", 6); + (void) smb_mbstowcs((smb_wchar_t *)devmode2->formname, + "Letter", 32); devmode2->logpixels = 0; devmode2->bitsperpel = 0; devmode2->pelswidth = 0; @@ -1020,51 +1018,92 @@ devmode2->reserved2 = 0; devmode2->panningwidth = 0; devmode2->panningheight = 0; - - pinfo2->secdesc = 84; - tmpbuf = (uint8_t *)(pinfo2->secdesc + (uint8_t *)param->Buf); - error = spoolss_s_make_sd(tmpbuf); - param->needed = 712; break; default: - syslog(LOG_NOTICE, "spoolss_s_GetPrinter: INVALID_LEVEL"); - status = ERROR_INVALID_LEVEL; break; + } - } + param->status = status; + return (NDR_DRC_OK); + error_out: + smb_tracef("spoolss_s_GetPrinter: error %u", status); + bzero(param, sizeof (struct spoolss_GetPrinter)); param->status = status; return (NDR_DRC_OK); } -int -spoolss_s_make_sd(uint8_t *sd_buf) +static int +spoolss_getservername(char *name, size_t namelen) { - smb_sd_t sd; - uint32_t status; + char hostname[MAXHOSTNAMELEN]; + char ipstr[INET6_ADDRSTRLEN]; + smb_inaddr_t ipaddr; + struct hostent *h; + const char *p; + int error; + + if (smb_gethostname(hostname, MAXHOSTNAMELEN, 0) != 0) { + smb_tracef("spoolss_s_GetPrinter: gethostname failed"); + return (-1); + } + + if ((h = smb_gethostbyname(hostname, &error)) == NULL) { + smb_tracef("spoolss_s_GetPrinter: gethostbyname failed: %d", + error); + return (-1); + } + + bcopy(h->h_addr, &ipaddr, h->h_length); + ipaddr.a_family = h->h_addrtype; + freehostent(h); + + p = smb_inet_ntop(&ipaddr, ipstr, SMB_IPSTRLEN(ipaddr.a_family)); + if (p == NULL) { + smb_tracef("spoolss_s_GetPrinter: inet_ntop failed"); + return (-1); + } + + (void) snprintf(name, namelen, "\\\\%s", ipstr); + return (0); +} + +static uint32_t +spoolss_make_sd(ndr_xa_t *mxa, spoolss_sd_t *secdesc) +{ + smb_sd_t sd; + uint8_t *sd_buf; + uint32_t sd_len; + uint32_t status; bzero(&sd, sizeof (smb_sd_t)); - if ((status = spoolss_sd_format(&sd)) == ERROR_SUCCESS) { - status = srvsvc_sd_set_relative(&sd, sd_buf); - smb_sd_term(&sd); - return (NDR_DRC_OK); - } - syslog(LOG_NOTICE, "spoolss_s_make_sd: error status=%d", status); + if ((status = spoolss_format_sd(&sd)) != ERROR_SUCCESS) + return (status); + + sd_len = smb_sd_len(&sd, SMB_ALL_SECINFO); + + if ((sd_buf = NDR_MALLOC(mxa, sd_len)) == NULL) + return (ERROR_NOT_ENOUGH_MEMORY); + + secdesc->sd_buf = sd_buf; + secdesc->sd_size = sd_len; + + status = srvsvc_sd_set_relative(&sd, sd_buf); smb_sd_term(&sd); - return (NDR_DRC_OK); + return (status); } static uint32_t -spoolss_sd_format(smb_sd_t *sd) +spoolss_format_sd(smb_sd_t *sd) { smb_fssd_t fs_sd; acl_t *acl; uint32_t status = ERROR_SUCCESS; if (acl_fromtext("everyone@:full_set::allow", &acl) != 0) { - syslog(LOG_ERR, "spoolss_sd_format: NOT_ENOUGH_MEMORY"); + smb_tracef("spoolss_format_sd: NOT_ENOUGH_MEMORY"); return (ERROR_NOT_ENOUGH_MEMORY); } smb_fssd_init(&fs_sd, SMB_ALL_SECINFO, SMB_FSSD_FLAGS_DIR); @@ -1073,8 +1112,9 @@ fs_sd.sd_zdacl = acl; fs_sd.sd_zsacl = NULL; - if (smb_sd_fromfs(&fs_sd, sd) != NT_STATUS_SUCCESS) { - syslog(LOG_NOTICE, "spoolss_sd_format: ACCESS_DENIED"); + status = smb_sd_fromfs(&fs_sd, sd); + if (status != NT_STATUS_SUCCESS) { + smb_tracef("spoolss_format_sd: %u", status); status = ERROR_ACCESS_DENIED; } smb_fssd_term(&fs_sd); @@ -1088,7 +1128,6 @@ return (NDR_DRC_FAULT_PARAM_0_UNIMPLEMENTED); } -/*ARGSUSED*/ void fixup_spoolss_RFNPCNEX(struct spoolss_RFNPCNEX *val) {
--- a/usr/src/lib/smbsrv/libsmb/common/libsmb.h Wed Aug 11 17:59:10 2010 -0400 +++ b/usr/src/lib/smbsrv/libsmb/common/libsmb.h Wed Aug 11 16:48:54 2010 -0700 @@ -227,23 +227,6 @@ extern void smb_config_setdomaininfo(char *, char *, char *, char *, char *); extern uint32_t smb_get_dcinfo(char *, uint32_t, smb_inaddr_t *); -CONTEXT_HANDLE(rpc_handle) rpc_handle_t; - -typedef struct smb_spooldoc { - uint32_t sd_magic; - list_node_t sd_lnd; - smb_inaddr_t sd_ipaddr; - int sd_spool_num; - char sd_username[MAXNAMELEN]; - char sd_path[MAXPATHLEN]; - char sd_doc_name[MAXNAMELEN]; - char sd_printer_name[MAXPATHLEN]; - int32_t sd_fd; - rpc_handle_t sd_handle; -} smb_spooldoc_t; - -int smb_kmod_get_spool_doc(uint32_t *, char *, char *, smb_inaddr_t *); - /* * buffer context structure. This is used to keep track of the buffer * context. @@ -895,6 +878,7 @@ /* Kernel Module Interface */ int smb_kmod_bind(void); +boolean_t smb_kmod_isbound(void); int smb_kmod_setcfg(smb_kmod_cfg_t *); int smb_kmod_setgmtoff(int32_t); int smb_kmod_start(int, int, int); @@ -914,6 +898,7 @@ void smb_kmod_enum_fini(smb_netsvc_t *); int smb_kmod_session_close(const char *, const char *); int smb_kmod_file_close(uint32_t); +int smb_kmod_get_spool_doc(uint32_t *, char *, char *, smb_inaddr_t *); void smb_name_parse(char *, char **, char **); uint32_t smb_name_validate_share(const char *);
--- a/usr/src/lib/smbsrv/libsmb/common/mapfile-vers Wed Aug 11 17:59:10 2010 -0400 +++ b/usr/src/lib/smbsrv/libsmb/common/mapfile-vers Wed Aug 11 16:48:54 2010 -0700 @@ -221,6 +221,7 @@ smb_kmod_file_close; smb_kmod_get_open_num; smb_kmod_get_spool_doc; + smb_kmod_isbound; smb_kmod_nbtlisten; smb_kmod_nbtreceive; smb_kmod_session_close;
--- a/usr/src/lib/smbsrv/libsmb/common/smb_cfg.c Wed Aug 11 17:59:10 2010 -0400 +++ b/usr/src/lib/smbsrv/libsmb/common/smb_cfg.c Wed Aug 11 16:48:54 2010 -0700 @@ -877,16 +877,18 @@ char *p; int rc, i; static smb_version_t ver_table [] = { - { SMB_MAJOR_NT, SMB_MINOR_NT }, - { SMB_MAJOR_2000, SMB_MINOR_2000 }, - { SMB_MAJOR_XP, SMB_MINOR_XP }, - { SMB_MAJOR_2003, SMB_MINOR_2003 }, - { SMB_MAJOR_VISTA, SMB_MINOR_VISTA }, - { SMB_MAJOR_2008, SMB_MINOR_2008 }, - { SMB_MAJOR_2008R2, SMB_MINOR_2008R2} + { 0, SMB_MAJOR_NT, SMB_MINOR_NT, 1381, 0 }, + { 0, SMB_MAJOR_2000, SMB_MINOR_2000, 2195, 0 }, + { 0, SMB_MAJOR_XP, SMB_MINOR_XP, 2196, 0 }, + { 0, SMB_MAJOR_2003, SMB_MINOR_2003, 2196, 0 }, + { 0, SMB_MAJOR_VISTA, SMB_MINOR_VISTA, 6000, 0 }, + { 0, SMB_MAJOR_2008, SMB_MINOR_2008, 6000, 0 }, + { 0, SMB_MAJOR_2008R2, SMB_MINOR_2008R2, 7007, 0 }, + { 0, SMB_MAJOR_7, SMB_MINOR_7, 7007, 0 } }; *version = ver_table[1]; + version->sv_size = sizeof (smb_version_t); rc = smb_config_getstr(SMB_CI_VERSION, verstr, sizeof (verstr)); if (rc != SMBD_SMF_OK) @@ -903,6 +905,7 @@ if ((tmpver.sv_major == ver_table[i].sv_major) && (tmpver.sv_minor == ver_table[i].sv_minor)) { *version = ver_table[i]; + version->sv_size = sizeof (smb_version_t); break; } }
--- a/usr/src/lib/smbsrv/libsmb/common/smb_kmod.c Wed Aug 11 17:59:10 2010 -0400 +++ b/usr/src/lib/smbsrv/libsmb/common/smb_kmod.c Wed Aug 11 16:48:54 2010 -0700 @@ -63,6 +63,12 @@ return (0); } +boolean_t +smb_kmod_isbound(void) +{ + return ((smbdrv_fd == -1) ? B_FALSE : B_TRUE); +} + int smb_kmod_setcfg(smb_kmod_cfg_t *cfg) {
--- a/usr/src/lib/smbsrv/libsmbns/common/libsmbns.h Wed Aug 11 17:59:10 2010 -0400 +++ b/usr/src/lib/smbsrv/libsmbns/common/libsmbns.h Wed Aug 11 16:48:54 2010 -0700 @@ -19,8 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2010 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. */ #ifndef _LIBSMBNS_H @@ -96,7 +95,8 @@ extern smb_ads_host_info_t *smb_ads_find_host(char *, char *); /* DYNDNS functions */ -extern int dyndns_start(void); +extern void *dyndns_publisher(void *); +extern void dyndns_start(void); extern void dyndns_stop(void); extern int dyndns_update(char *); extern void dyndns_update_zones(void);
--- a/usr/src/lib/smbsrv/libsmbns/common/mapfile-vers Wed Aug 11 17:59:10 2010 -0400 +++ b/usr/src/lib/smbsrv/libsmbns/common/mapfile-vers Wed Aug 11 16:48:54 2010 -0700 @@ -41,6 +41,7 @@ SYMBOL_VERSION SUNWprivate { global: dyndns_clear_zones; + dyndns_publisher; dyndns_start; dyndns_stop; dyndns_update;
--- a/usr/src/lib/smbsrv/libsmbns/common/smbns_browser.c Wed Aug 11 17:59:10 2010 -0400 +++ b/usr/src/lib/smbsrv/libsmbns/common/smbns_browser.c Wed Aug 11 16:48:54 2010 -0700 @@ -19,8 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2010 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. */ #include <sys/tzfile.h> @@ -834,8 +833,8 @@ ++hinfo->hi_updatecnt, next_announcement * 60000, /* Periodicity in MilliSeconds */ hinfo->hi_nbname, - hinfo->hi_version.sv_major, - hinfo->hi_version.sv_minor, + (uint8_t)hinfo->hi_version.sv_major, + (uint8_t)hinfo->hi_version.sv_minor, type, SMB_SERVER_SIGNATURE, hinfo->hi_nic.nic_cmnt);
--- a/usr/src/lib/smbsrv/libsmbns/common/smbns_dyndns.c Wed Aug 11 17:59:10 2010 -0400 +++ b/usr/src/lib/smbsrv/libsmbns/common/smbns_dyndns.c Wed Aug 11 16:48:54 2010 -0700 @@ -104,7 +104,6 @@ static void dyndns_queue_request(int, const char *); static void dyndns_queue_flush(list_t *); -static void *dyndns_publisher(void *); static void dyndns_process(list_t *); static int dyndns_update_core(char *); static int dyndns_clear_rev_zone(char *); @@ -112,20 +111,14 @@ static int dyndns_get_msgid(void); static void dyndns_syslog(int, int, const char *); -int +void dyndns_start(void) { - pthread_t publisher; - pthread_attr_t tattr; - int rc; + (void) mutex_lock(&dyndns_queue.ddq_mtx); - if (!smb_config_getbool(SMB_CI_DYNDNS_ENABLE)) - return (0); - - (void) mutex_lock(&dyndns_queue.ddq_mtx); if (dyndns_queue.ddq_state != DYNDNS_STATE_INIT) { (void) mutex_unlock(&dyndns_queue.ddq_mtx); - return (0); + return; } dyndns_msgid_init(); @@ -133,13 +126,8 @@ list_create(&dyndns_queue.ddq_list, sizeof (dyndns_qentry_t), offsetof(dyndns_qentry_t, dqe_lnd)); dyndns_queue.ddq_state = DYNDNS_STATE_READY; + (void) mutex_unlock(&dyndns_queue.ddq_mtx); - - (void) pthread_attr_init(&tattr); - (void) pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_DETACHED); - rc = pthread_create(&publisher, &tattr, dyndns_publisher, 0); - (void) pthread_attr_destroy(&tattr); - return (rc); } void @@ -194,6 +182,9 @@ /* * Add a request to the queue. + * + * To comply with RFC 4120 section 6.2.1, entry->dqe_fqdn is converted + * to lower case. */ static void dyndns_queue_request(int op, const char *fqdn) @@ -203,33 +194,27 @@ if (!smb_config_getbool(SMB_CI_DYNDNS_ENABLE)) return; + if ((entry = malloc(sizeof (dyndns_qentry_t))) == NULL) + return; + + bzero(entry, sizeof (dyndns_qentry_t)); + entry->dqe_op = op; + (void) strlcpy(entry->dqe_fqdn, fqdn, MAXNAMELEN); + (void) smb_strlwr(entry->dqe_fqdn); + (void) mutex_lock(&dyndns_queue.ddq_mtx); switch (dyndns_queue.ddq_state) { case DYNDNS_STATE_READY: case DYNDNS_STATE_PUBLISHING: + list_insert_tail(&dyndns_queue.ddq_list, entry); + (void) cond_signal(&dyndns_queue.ddq_cv); break; default: - (void) mutex_unlock(&dyndns_queue.ddq_mtx); - return; - } - - if ((entry = malloc(sizeof (dyndns_qentry_t))) == NULL) { - (void) mutex_unlock(&dyndns_queue.ddq_mtx); - return; + free(entry); + break; } - bzero(entry, sizeof (dyndns_qentry_t)); - entry->dqe_op = op; - (void) strlcpy(entry->dqe_fqdn, fqdn, MAXNAMELEN); - /* - * To comply with RFC 4120 section 6.2.1, entry->dqe_fqdn is converted - * to lower case. - */ - (void) smb_strlwr(entry->dqe_fqdn); - - list_insert_tail(&dyndns_queue.ddq_list, entry); - (void) cond_signal(&dyndns_queue.ddq_cv); (void) mutex_unlock(&dyndns_queue.ddq_mtx); } @@ -255,7 +240,7 @@ * to retry. */ /*ARGSUSED*/ -static void * +void * dyndns_publisher(void *arg) { dyndns_qentry_t *entry;
--- a/usr/src/uts/common/fs/smbsrv/smb_common_transact.c Wed Aug 11 17:59:10 2010 -0400 +++ b/usr/src/uts/common/fs/smbsrv/smb_common_transact.c Wed Aug 11 16:48:54 2010 -0700 @@ -1007,7 +1007,8 @@ (void) smb_mbc_encodef(&xa->rep_data_mb, "l", MBC_LENGTH(&str_mb)); (void) smb_mbc_encodef(&str_mb, "s", domain); (void) smb_mbc_encodef(&xa->rep_data_mb, "bbl", - sr->sr_cfg->skc_version.sv_major, sr->sr_cfg->skc_version.sv_minor, + (uint8_t)sr->sr_cfg->skc_version.sv_major, + (uint8_t)sr->sr_cfg->skc_version.sv_minor, MBC_LENGTH(&str_mb)); (void) smb_mbc_encodef(&str_mb, "s", domain); (void) smb_mbc_encodef(&xa->rep_data_mb, "l", MBC_LENGTH(&str_mb)); @@ -1070,8 +1071,8 @@ (void) smb_mbc_encodef(&str_mb, "s", sr->sr_cfg->skc_system_comment); (void) smb_mbc_encodef(&xa->rep_data_mb, "16cbbll", server_name, - sr->sr_cfg->skc_version.sv_major, - sr->sr_cfg->skc_version.sv_minor, + (uint8_t)sr->sr_cfg->skc_version.sv_major, + (uint8_t)sr->sr_cfg->skc_version.sv_minor, MY_SERVER_TYPE, max_data - MBC_LENGTH(&str_mb)); break; @@ -1315,8 +1316,8 @@ (void) smb_mbc_encodef(&xa->rep_data_mb, "16c", hostname); if (level == 1) { (void) smb_mbc_encodef(&xa->rep_data_mb, "bbll", - sr->sr_cfg->skc_version.sv_major, - sr->sr_cfg->skc_version.sv_minor, + (uint8_t)sr->sr_cfg->skc_version.sv_major, + (uint8_t)sr->sr_cfg->skc_version.sv_minor, MY_SERVER_TYPE, MBC_LENGTH(&str_mb)); (void) smb_mbc_encodef(&str_mb, "s", si->skc_system_comment); }
--- a/usr/src/uts/common/fs/smbsrv/smb_fsinfo.c Wed Aug 11 17:59:10 2010 -0400 +++ b/usr/src/uts/common/fs/smbsrv/smb_fsinfo.c Wed Aug 11 16:48:54 2010 -0700 @@ -19,8 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2010 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. */ #include <smbsrv/smb_kproto.h> @@ -336,6 +335,9 @@ if (tree->t_flags & SMB_TREE_QUOTA) flags |= FILE_VOLUME_QUOTAS; + if (tree->t_flags & SMB_TREE_SPARSE) + flags |= FILE_SUPPORTS_SPARSE_FILES; + (void) smb_mbc_encodef(&xa->rep_data_mb, encode_str, sr, flags, MAXNAMELEN, /* max name */
--- a/usr/src/uts/common/fs/smbsrv/smb_nt_transact_ioctl.c Wed Aug 11 17:59:10 2010 -0400 +++ b/usr/src/uts/common/fs/smbsrv/smb_nt_transact_ioctl.c Wed Aug 11 16:48:54 2010 -0700 @@ -27,8 +27,11 @@ static uint32_t smb_nt_trans_ioctl_noop(smb_request_t *, smb_xa_t *); -static uint32_t smb_nt_trans_ioctl_invalid_parm(smb_request_t *, +static uint32_t smb_nt_trans_ioctl_invalid_parm(smb_request_t *, smb_xa_t *); +static uint32_t smb_nt_trans_ioctl_set_sparse(smb_request_t *, smb_xa_t *); +static uint32_t smb_nt_trans_ioctl_query_alloc_ranges(smb_request_t *, smb_xa_t *); +static uint32_t smb_nt_trans_ioctl_set_zero_data(smb_request_t *, smb_xa_t *); /* * This table defines the list of FSCTL values for which we'll @@ -43,9 +46,10 @@ uint32_t (*ioctl_func)(smb_request_t *sr, smb_xa_t *xa); } ioctl_ret_tbl[] = { { FSCTL_GET_OBJECT_ID, smb_nt_trans_ioctl_invalid_parm }, - { FSCTL_QUERY_ALLOCATED_RANGES, smb_nt_trans_ioctl_invalid_parm }, + { FSCTL_QUERY_ALLOCATED_RANGES, smb_nt_trans_ioctl_query_alloc_ranges }, + { FSCTL_SET_ZERO_DATA, smb_nt_trans_ioctl_set_zero_data }, { FSCTL_SRV_ENUMERATE_SNAPSHOTS, smb_vss_ioctl_enumerate_snaps }, - { FSCTL_SET_SPARSE, smb_nt_trans_ioctl_noop }, + { FSCTL_SET_SPARSE, smb_nt_trans_ioctl_set_sparse }, { FSCTL_FIND_FILES_BY_SID, smb_nt_trans_ioctl_noop } }; @@ -84,13 +88,12 @@ { uint32_t status = NT_STATUS_NOT_SUPPORTED; uint32_t fcode; - unsigned short fid; unsigned char is_fsctl; unsigned char is_flags; int i; if (smb_mbc_decodef(&xa->req_setup_mb, "lwbb", - &fcode, &fid, &is_fsctl, &is_flags) != 0) { + &fcode, &sr->smb_fid, &is_fsctl, &is_flags) != 0) { smbsr_error(sr, NT_STATUS_INVALID_PARAMETER, 0, 0); return (SDRC_ERROR); } @@ -129,3 +132,188 @@ { return (NT_STATUS_INVALID_PARAMETER); } + +/* + * smb_nt_trans_ioctl_set_sparse + * + * There may, or may not be a data block in this request. + * If there IS a data block, the first byte is a boolean + * specifying whether to set (non zero) or clear (zero) + * the sparse attribute of the file. + * If there is no data block, this indicates a request to + * set the sparse attribute. + */ +static uint32_t +smb_nt_trans_ioctl_set_sparse(smb_request_t *sr, smb_xa_t *xa) +{ + int rc = 0; + uint8_t set = 1; + smb_node_t *node; + smb_attr_t attr; + + if (SMB_TREE_IS_READONLY(sr)) + return (NT_STATUS_ACCESS_DENIED); + + if (STYPE_ISIPC(sr->tid_tree->t_res_type)) + return (NT_STATUS_INVALID_PARAMETER); + + smbsr_lookup_file(sr); + if (sr->fid_ofile == NULL) + return (NT_STATUS_INVALID_HANDLE); + + if (!SMB_FTYPE_IS_DISK(sr->fid_ofile->f_ftype)) { + smbsr_release_file(sr); + return (NT_STATUS_INVALID_PARAMETER); + } + + node = sr->fid_ofile->f_node; + if (smb_node_is_dir(node)) { + smbsr_release_file(sr); + return (NT_STATUS_INVALID_PARAMETER); + } + + if (smbsr_decode_data_avail(sr)) { + if (smb_mbc_decodef(&xa->req_data_mb, "b", &set) != 0) { + smbsr_release_file(sr); + return (sr->smb_error.status); + } + } + + bzero(&attr, sizeof (smb_attr_t)); + attr.sa_mask = SMB_AT_DOSATTR; + if ((rc = smb_node_getattr(sr, node, &attr)) != 0) { + smbsr_errno(sr, rc); + smbsr_release_file(sr); + return (sr->smb_error.status); + } + + attr.sa_mask = 0; + if ((set == 0) && + (attr.sa_dosattr & FILE_ATTRIBUTE_SPARSE_FILE)) { + attr.sa_dosattr &= ~FILE_ATTRIBUTE_SPARSE_FILE; + attr.sa_mask = SMB_AT_DOSATTR; + } else if ((set != 0) && + !(attr.sa_dosattr & FILE_ATTRIBUTE_SPARSE_FILE)) { + attr.sa_dosattr |= FILE_ATTRIBUTE_SPARSE_FILE; + attr.sa_mask = SMB_AT_DOSATTR; + } + + if (attr.sa_mask != 0) { + rc = smb_node_setattr(sr, node, sr->user_cr, NULL, &attr); + if (rc != 0) { + smbsr_errno(sr, rc); + smbsr_release_file(sr); + return (sr->smb_error.status); + } + } + + smbsr_release_file(sr); + return (NT_STATUS_SUCCESS); +} + +/* + * smb_nt_trans_ioctl_set_zero_data + * + * Check that the request is valid on the specified file. + * The implementation is a noop. + */ +/* ARGSUSED */ +static uint32_t +smb_nt_trans_ioctl_set_zero_data(smb_request_t *sr, smb_xa_t *xa) +{ + smb_node_t *node; + + if (SMB_TREE_IS_READONLY(sr)) + return (NT_STATUS_ACCESS_DENIED); + + if (STYPE_ISIPC(sr->tid_tree->t_res_type)) + return (NT_STATUS_INVALID_PARAMETER); + + smbsr_lookup_file(sr); + if (sr->fid_ofile == NULL) + return (NT_STATUS_INVALID_HANDLE); + + if (!SMB_FTYPE_IS_DISK(sr->fid_ofile->f_ftype)) { + smbsr_release_file(sr); + return (NT_STATUS_INVALID_PARAMETER); + } + + node = sr->fid_ofile->f_node; + if (smb_node_is_dir(node)) { + smbsr_release_file(sr); + return (NT_STATUS_INVALID_PARAMETER); + } + + smbsr_release_file(sr); + return (NT_STATUS_SUCCESS); +} + +/* + * smb_nt_trans_ioctl_query_alloc_ranges + * + * Responds with either: + * - no data if the file is zero size + * - a single range containing the starting point and length requested + */ +static uint32_t +smb_nt_trans_ioctl_query_alloc_ranges(smb_request_t *sr, smb_xa_t *xa) +{ + int rc; + uint64_t offset, len; + smb_node_t *node; + smb_attr_t attr; + + if (STYPE_ISIPC(sr->tid_tree->t_res_type)) + return (NT_STATUS_INVALID_PARAMETER); + + smbsr_lookup_file(sr); + if (sr->fid_ofile == NULL) + return (NT_STATUS_INVALID_HANDLE); + + if (!SMB_FTYPE_IS_DISK(sr->fid_ofile->f_ftype)) { + smbsr_release_file(sr); + return (NT_STATUS_INVALID_PARAMETER); + } + + node = sr->fid_ofile->f_node; + if (smb_node_is_dir(node)) { + smbsr_release_file(sr); + return (NT_STATUS_INVALID_PARAMETER); + } + + /* If zero size file don't return any data */ + bzero(&attr, sizeof (smb_attr_t)); + attr.sa_mask = SMB_AT_SIZE; + if ((rc = smb_node_getattr(sr, node, &attr)) != 0) { + smbsr_errno(sr, rc); + smbsr_release_file(sr); + return (sr->smb_error.status); + } + + if (attr.sa_vattr.va_size == 0) { + smbsr_release_file(sr); + return (NT_STATUS_SUCCESS); + } + + if (smb_mbc_decodef(&xa->req_data_mb, "qq", &offset, &len) != 0) { + smbsr_release_file(sr); + return (sr->smb_error.status); + } + + /* + * Return a single range regardless of whether the file + * is sparse or not. + */ + if (MBC_ROOM_FOR(&xa->rep_data_mb, 16) == 0) { + smbsr_release_file(sr); + return (NT_STATUS_BUFFER_TOO_SMALL); + } + + if (smb_mbc_encodef(&xa->rep_data_mb, "qq", offset, len) != 0) { + smbsr_release_file(sr); + return (sr->smb_error.status); + } + + smbsr_release_file(sr); + return (NT_STATUS_SUCCESS); +}
--- a/usr/src/uts/common/fs/smbsrv/smb_tree.c Wed Aug 11 17:59:10 2010 -0400 +++ b/usr/src/uts/common/fs/smbsrv/smb_tree.c Wed Aug 11 16:48:54 2010 -0700 @@ -1107,7 +1107,8 @@ } smb_mtype_t; static smb_mtype_t smb_mtype[] = { - { "zfs", 3, SMB_TREE_UNICODE_ON_DISK | SMB_TREE_QUOTA }, + { "zfs", 3, SMB_TREE_UNICODE_ON_DISK | + SMB_TREE_QUOTA | SMB_TREE_SPARSE}, { "ufs", 3, SMB_TREE_UNICODE_ON_DISK }, { "nfs", 3, SMB_TREE_NFS_MOUNTED }, { "tmpfs", 5, SMB_TREE_NO_EXPORT }
--- a/usr/src/uts/common/fs/smbsrv/smb_vops.c Wed Aug 11 17:59:10 2010 -0400 +++ b/usr/src/uts/common/fs/smbsrv/smb_vops.c Wed Aug 11 16:48:54 2010 -0700 @@ -19,8 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2010 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. */ #include <sys/types.h> @@ -328,6 +327,8 @@ XVA_SET_REQ(&tmp_xvattr, XAT_ARCHIVE); XVA_SET_REQ(&tmp_xvattr, XAT_CREATETIME); XVA_SET_REQ(&tmp_xvattr, XAT_REPARSE); + XVA_SET_REQ(&tmp_xvattr, XAT_OFFLINE); + XVA_SET_REQ(&tmp_xvattr, XAT_SPARSE); error = VOP_GETATTR(use_vp, &tmp_xvattr.xva_vattr, flags, cr, &smb_ct); @@ -367,6 +368,17 @@ FILE_ATTRIBUTE_REPARSE_POINT; } + if ((XVA_ISSET_RTN(&tmp_xvattr, XAT_OFFLINE)) && + (xoap->xoa_offline)) { + ret_attr->sa_dosattr |= FILE_ATTRIBUTE_OFFLINE; + } + + if ((XVA_ISSET_RTN(&tmp_xvattr, XAT_SPARSE)) && + (xoap->xoa_sparse)) { + ret_attr->sa_dosattr |= + FILE_ATTRIBUTE_SPARSE_FILE; + } + ret_attr->sa_crtime = xoap->xoa_createtime; } else { ret_attr->sa_crtime = ret_attr->sa_vattr.va_mtime; @@ -442,7 +454,8 @@ if (attr->sa_mask & SMB_AT_DOSATTR) { attr->sa_dosattr &= (FILE_ATTRIBUTE_ARCHIVE | FILE_ATTRIBUTE_READONLY | - FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM); + FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM | + FILE_ATTRIBUTE_OFFLINE | FILE_ATTRIBUTE_SPARSE_FILE); } if (unnamed_vp) { @@ -860,6 +873,8 @@ XVA_SET_REQ(xvattr, XAT_SYSTEM); XVA_SET_REQ(xvattr, XAT_READONLY); XVA_SET_REQ(xvattr, XAT_HIDDEN); + XVA_SET_REQ(xvattr, XAT_OFFLINE); + XVA_SET_REQ(xvattr, XAT_SPARSE); /* * smb_attr->sa_dosattr: If a given bit is not set, @@ -879,6 +894,12 @@ if (smb_attr->sa_dosattr & FILE_ATTRIBUTE_HIDDEN) xoap->xoa_hidden = 1; + + if (smb_attr->sa_dosattr & FILE_ATTRIBUTE_OFFLINE) + xoap->xoa_offline = 1; + + if (smb_attr->sa_dosattr & FILE_ATTRIBUTE_SPARSE_FILE) + xoap->xoa_sparse = 1; } if (smb_attr->sa_mask & SMB_AT_CRTIME) {
--- a/usr/src/uts/common/fs/xattr.c Wed Aug 11 17:59:10 2010 -0400 +++ b/usr/src/uts/common/fs/xattr.c Wed Aug 11 16:48:54 2010 -0700 @@ -228,6 +228,12 @@ case F_GEN: XVA_SET_REQ(&xvattr, XAT_GEN); break; + case F_OFFLINE: + XVA_SET_REQ(&xvattr, XAT_OFFLINE); + break; + case F_SPARSE: + XVA_SET_REQ(&xvattr, XAT_SPARSE); + break; default: break; } @@ -320,6 +326,16 @@ attr_to_name(F_GEN), xoap->xoa_generation) == 0); } + if (XVA_ISSET_RTN(&xvattr, XAT_OFFLINE)) { + VERIFY(nvlist_add_boolean_value(nvlp, + attr_to_name(F_OFFLINE), + xoap->xoa_offline) == 0); + } + if (XVA_ISSET_RTN(&xvattr, XAT_SPARSE)) { + VERIFY(nvlist_add_boolean_value(nvlp, + attr_to_name(F_SPARSE), + xoap->xoa_sparse) == 0); + } } /* * Check for optional ownersid/groupsid @@ -697,6 +713,14 @@ XVA_SET_REQ(&xvattr, XAT_REPARSE); xoap->xoa_reparse = value; break; + case F_OFFLINE: + XVA_SET_REQ(&xvattr, XAT_OFFLINE); + xoap->xoa_offline = value; + break; + case F_SPARSE: + XVA_SET_REQ(&xvattr, XAT_SPARSE); + xoap->xoa_sparse = value; + break; default: break; } @@ -838,6 +862,8 @@ XVA_SET_REQ(&xvattr, XAT_AV_QUARANTINED); XVA_SET_REQ(&xvattr, XAT_CREATETIME); XVA_SET_REQ(&xvattr, XAT_REPARSE); + XVA_SET_REQ(&xvattr, XAT_OFFLINE); + XVA_SET_REQ(&xvattr, XAT_SPARSE); pdvp = gfs_file_parent(sdvp); error = VOP_GETATTR(pdvp, &xvattr.xva_vattr, 0, cr, ct);
--- a/usr/src/uts/common/fs/zfs/sys/zfs_znode.h Wed Aug 11 17:59:10 2010 -0400 +++ b/usr/src/uts/common/fs/zfs/sys/zfs_znode.h Wed Aug 11 16:48:54 2010 -0700 @@ -60,6 +60,8 @@ #define ZFS_AV_QUARANTINED 0x0000020000000000 #define ZFS_AV_MODIFIED 0x0000040000000000 #define ZFS_REPARSE 0x0000080000000000 +#define ZFS_OFFLINE 0x0000100000000000 +#define ZFS_SPARSE 0x0000200000000000 #define ZFS_ATTR_SET(zp, attr, value, pflags, tx) \ { \
--- a/usr/src/uts/common/fs/zfs/zfs_log.c Wed Aug 11 17:59:10 2010 -0400 +++ b/usr/src/uts/common/fs/zfs/zfs_log.c Wed Aug 11 16:48:54 2010 -0700 @@ -169,6 +169,12 @@ if (XVA_ISSET_REQ(xvap, XAT_REPARSE)) *attrs |= (xoap->xoa_reparse == 0) ? 0 : XAT0_REPARSE; + if (XVA_ISSET_REQ(xvap, XAT_OFFLINE)) + *attrs |= (xoap->xoa_offline == 0) ? 0 : + XAT0_OFFLINE; + if (XVA_ISSET_REQ(xvap, XAT_SPARSE)) + *attrs |= (xoap->xoa_sparse == 0) ? 0 : + XAT0_SPARSE; } static void *
--- a/usr/src/uts/common/fs/zfs/zfs_replay.c Wed Aug 11 17:59:10 2010 -0400 +++ b/usr/src/uts/common/fs/zfs/zfs_replay.c Wed Aug 11 16:48:54 2010 -0700 @@ -128,6 +128,10 @@ bcopy(scanstamp, xoap->xoa_av_scanstamp, AV_SCANSTAMP_SZ); if (XVA_ISSET_REQ(xvap, XAT_REPARSE)) xoap->xoa_reparse = ((*attrs & XAT0_REPARSE) != 0); + if (XVA_ISSET_REQ(xvap, XAT_OFFLINE)) + xoap->xoa_offline = ((*attrs & XAT0_OFFLINE) != 0); + if (XVA_ISSET_REQ(xvap, XAT_SPARSE)) + xoap->xoa_sparse = ((*attrs & XAT0_SPARSE) != 0); } static int
--- a/usr/src/uts/common/fs/zfs/zfs_vnops.c Wed Aug 11 17:59:10 2010 -0400 +++ b/usr/src/uts/common/fs/zfs/zfs_vnops.c Wed Aug 11 16:48:54 2010 -0700 @@ -2543,6 +2543,18 @@ xoap->xoa_generation = zp->z_gen; XVA_SET_RTN(xvap, XAT_GEN); } + + if (XVA_ISSET_REQ(xvap, XAT_OFFLINE)) { + xoap->xoa_offline = + ((zp->z_pflags & ZFS_OFFLINE) != 0); + XVA_SET_RTN(xvap, XAT_OFFLINE); + } + + if (XVA_ISSET_REQ(xvap, XAT_SPARSE)) { + xoap->xoa_sparse = + ((zp->z_pflags & ZFS_SPARSE) != 0); + XVA_SET_RTN(xvap, XAT_SPARSE); + } } ZFS_TIME_DECODE(&vap->va_atime, zp->z_atime); @@ -2720,6 +2732,8 @@ ((mask & AT_XVATTR) && (XVA_ISSET_REQ(xvap, XAT_HIDDEN) || XVA_ISSET_REQ(xvap, XAT_READONLY) || XVA_ISSET_REQ(xvap, XAT_ARCHIVE) || + XVA_ISSET_REQ(xvap, XAT_OFFLINE) || + XVA_ISSET_REQ(xvap, XAT_SPARSE) || XVA_ISSET_REQ(xvap, XAT_CREATETIME) || XVA_ISSET_REQ(xvap, XAT_SYSTEM)))) { need_policy = zfs_zaccess(zp, ACE_WRITE_ATTRIBUTES, 0,
--- a/usr/src/uts/common/fs/zfs/zfs_znode.c Wed Aug 11 17:59:10 2010 -0400 +++ b/usr/src/uts/common/fs/zfs/zfs_znode.c Wed Aug 11 16:48:54 2010 -0700 @@ -1088,6 +1088,16 @@ zp->z_pflags, tx); XVA_SET_RTN(xvap, XAT_REPARSE); } + if (XVA_ISSET_REQ(xvap, XAT_OFFLINE)) { + ZFS_ATTR_SET(zp, ZFS_OFFLINE, xoap->xoa_offline, + zp->z_pflags, tx); + XVA_SET_RTN(xvap, XAT_OFFLINE); + } + if (XVA_ISSET_REQ(xvap, XAT_SPARSE)) { + ZFS_ATTR_SET(zp, ZFS_SPARSE, xoap->xoa_sparse, + zp->z_pflags, tx); + XVA_SET_RTN(xvap, XAT_SPARSE); + } } int @@ -1564,6 +1574,8 @@ dmu_tx_t *tx; rl_t *rl; int error; + sa_bulk_attr_t bulk[2]; + int count = 0; /* * We will change zp_size, lock the whole file. @@ -1600,9 +1612,15 @@ } zp->z_size = end; + SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_SIZE(zfsvfs), + NULL, &zp->z_size, sizeof (zp->z_size)); - VERIFY(0 == sa_update(zp->z_sa_hdl, SA_ZPL_SIZE(zp->z_zfsvfs), - &zp->z_size, sizeof (zp->z_size), tx)); + if (end == 0) { + zp->z_pflags &= ~ZFS_SPARSE; + SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_FLAGS(zfsvfs), + NULL, &zp->z_pflags, 8); + } + VERIFY(sa_bulk_update(zp->z_sa_hdl, bulk, count, tx) == 0); dmu_tx_commit(tx);
--- a/usr/src/uts/common/fs/zut/zut.c Wed Aug 11 17:59:10 2010 -0400 +++ b/usr/src/uts/common/fs/zut/zut.c Wed Aug 11 16:48:54 2010 -0700 @@ -19,8 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved. */ #include <sys/conf.h> @@ -218,6 +217,8 @@ XVA_SET_REQ(&xv, XAT_AV_QUARANTINED); XVA_SET_REQ(&xv, XAT_AV_MODIFIED); XVA_SET_REQ(&xv, XAT_REPARSE); + XVA_SET_REQ(&xv, XAT_OFFLINE); + XVA_SET_REQ(&xv, XAT_SPARSE); xv.xva_vattr.va_mask |= AT_STAT | AT_NBLOCKS | AT_BLKSIZE | AT_SIZE; if (error = VOP_GETATTR(vp, &xv.xva_vattr, flag, cr, NULL)) @@ -266,6 +267,10 @@ *xvs |= (1 << F_AV_MODIFIED); if (XVA_ISSET_RTN(&xv, XAT_REPARSE) && xoap->xoa_reparse) *xvs |= (1 << F_REPARSE); + if (XVA_ISSET_RTN(&xv, XAT_OFFLINE) && xoap->xoa_offline) + *xvs |= (1 << F_OFFLINE); + if (XVA_ISSET_RTN(&xv, XAT_SPARSE) && xoap->xoa_sparse) + *xvs |= (1 << F_SPARSE); return (0); }
--- a/usr/src/uts/common/os/policy.c Wed Aug 11 17:59:10 2010 -0400 +++ b/usr/src/uts/common/os/policy.c Wed Aug 11 16:48:54 2010 -0700 @@ -1296,7 +1296,9 @@ XVA_ISSET_REQ(xvap, XAT_HIDDEN) || XVA_ISSET_REQ(xvap, XAT_READONLY) || XVA_ISSET_REQ(xvap, XAT_SYSTEM) || - XVA_ISSET_REQ(xvap, XAT_CREATETIME)) { + XVA_ISSET_REQ(xvap, XAT_CREATETIME) || + XVA_ISSET_REQ(xvap, XAT_OFFLINE) || + XVA_ISSET_REQ(xvap, XAT_SPARSE)) { if ((error = secpolicy_vnode_owner(cr, owner)) != 0) return (error); }
--- a/usr/src/uts/common/smbsrv/ndl/lsarpc.ndl Wed Aug 11 17:59:10 2010 -0400 +++ b/usr/src/uts/common/smbsrv/ndl/lsarpc.ndl Wed Aug 11 16:48:54 2010 -0700 @@ -19,8 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. */ #ifndef _MLSVC_LSA_NDL_ @@ -519,7 +518,7 @@ OUT struct mslsa_domain_table *domain_table; INOUT struct mslsa_name_table name_table; - IN DWORD lookup_level; + IN WORD lookup_level; INOUT DWORD mapped_count; OUT DWORD status; }; @@ -577,15 +576,15 @@ OPERATION(LSARPC_OPNUM_LookupNames) struct mslsa_LookupNames { - IN mslsa_handle_t handle; + IN mslsa_handle_t handle; IN REFERENCE struct mslsa_lup_name_table *name_table; - OUT struct mslsa_domain_table *domain_table; + OUT struct mslsa_domain_table *domain_table; INOUT struct mslsa_rid_table translated_sids; - IN DWORD lookup_level; + IN WORD lookup_level; INOUT DWORD mapped_count; - OUT DWORD status; + OUT DWORD status; }; @@ -879,7 +878,7 @@ IN struct mslsa_lup_sid_table lup_sid_table; OUT struct mslsa_domain_table *domain_table; INOUT struct lsar_name_table2 name_table; - IN DWORD lookup_level; + IN WORD lookup_level; INOUT DWORD mapped_count; IN DWORD lookup_options; IN DWORD client_revision; @@ -891,7 +890,7 @@ IN struct mslsa_lup_sid_table lup_sid_table; OUT struct mslsa_domain_table *domain_table; INOUT lsar_translated_names_ex_t name_table; - IN DWORD lookup_level; + IN WORD lookup_level; INOUT DWORD mapped_count; IN DWORD lookup_options; IN DWORD client_revision; @@ -930,7 +929,7 @@ IN REFERENCE struct mslsa_lup_name_table *name_table; OUT struct mslsa_domain_table *domain_table; INOUT struct lsar_rid_table2 translated_sids; - IN DWORD lookup_level; + IN WORD lookup_level; INOUT DWORD mapped_count; IN DWORD lookup_options; IN DWORD client_revision; @@ -959,7 +958,7 @@ IN REFERENCE struct mslsa_lup_name_table *name_table; OUT struct mslsa_domain_table *domain_table; INOUT struct lsar_sid_ex2_table translated_sids; - IN DWORD lookup_level; + IN WORD lookup_level; INOUT DWORD mapped_count; IN DWORD lookup_options; IN DWORD client_revision; @@ -971,7 +970,7 @@ IN REFERENCE struct mslsa_lup_name_table *name_table; OUT struct mslsa_domain_table *domain_table; INOUT struct lsar_sid_ex2_table translated_sids; - IN DWORD lookup_level; + IN WORD lookup_level; INOUT DWORD mapped_count; IN DWORD lookup_options; IN DWORD client_revision;
--- a/usr/src/uts/common/smbsrv/ndl/spoolss.ndl Wed Aug 11 17:59:10 2010 -0400 +++ b/usr/src/uts/common/smbsrv/ndl/spoolss.ndl Wed Aug 11 16:48:54 2010 -0700 @@ -34,6 +34,7 @@ #define TABLE_DEVMODE 4 #define TABLE_SECURITY_DESCRIPTOR 5 +#define SPOOLSS_OPNUM_EnumPrinters 0x00 #define SPOOLSS_OPNUM_OpenPrinter 0x01 #define SPOOLSS_OPNUM_GetJob 0x03 #define SPOOLSS_OPNUM_EnumJobs 0x04 @@ -50,18 +51,27 @@ #define SPOOLSS_OPNUM_ScheduleJob 0x19 #define SPOOLSS_OPNUM_GetPrinterData 0x1a #define SPOOLSS_OPNUM_ClosePrinter 0x1d +#define SPOOLSS_OPNUM_AddForm 0x1e +#define SPOOLSS_OPNUM_DeleteForm 0x1f #define SPOOLSS_OPNUM_EndDocPrinter 0x17 #define SPOOLSS_OPNUM_EnumForms 0x22 +#define SPOOLSS_OPNUM_EnumPorts 0x23 +#define SPOOLSS_OPNUM_EnumMonitor 0x24 +#define SPOOLSS_OPNUM_DeletePort 0x27 #define SPOOLSS_OPNUM_CreatePrinterIC 0x28 +#define SPOOLSS_OPNUM_AddMonitor 0x2e +#define SPOOLSS_OPNUM_DeleteMonitor 0x2f #define SPOOLSS_OPNUM_ResetPrinter 0x34 #define SPOOLSS_OPNUM_GetPrinterDriver2 0x35 #define SPOOLSS_OPNUM_FCPN 0x38 #define SPOOLSS_OPNUM_ReplyOpenPrinter 0x3a #define SPOOLSS_OPNUM_ReplyClosePrinter 0x3c +#define SPOOLSS_OPNUM_AddPortEx 0x3d #define SPOOLSS_OPNUM_RFFPCNEX 0x41 #define SPOOLSS_OPNUM_RRPCN 0x42 #define SPOOLSS_OPNUM_RFNPCNEX 0x43 #define SPOOLSS_OPNUM_OpenPrinterEx 0x45 +#define SPOOLSS_OPNUM_SetPort 0x47 #define SPOOLSS_OPNUM_EnumPrinterData 0x48 #define SPOOLSS_OPNUM_EnumPrinterDataEx 0x4f #define SPOOLSS_OPNUM_EnumPrinterKey 0x50 @@ -126,8 +136,8 @@ IN LPTSTR printer_name; OUT spoolss_handle_t handle; IN LPTSTR data_type; - IN struct spoolssDevmodeContainer dmodeContainer; - IN DWORD AccessRequired; + /* IN struct spoolssDevmodeContainer dmodeContainer; */ + /* IN DWORD AccessRequired; */ OUT DWORD status; }; @@ -451,8 +461,8 @@ IN spoolss_handle_t handle; IN REFERENCE LPTSTR pValueName; OUT DWORD pType; - SIZE_IS(Size) - OUT LPBYTE Buf; + SIZE_IS(Size) + OUT REFERENCE LPBYTE Buf; IN DWORD Size; OUT DWORD Needed; OUT DWORD status; @@ -498,6 +508,54 @@ OUT DWORD status; }; +OPERATION(SPOOLSS_OPNUM_EnumPorts) +struct spoolss_EnumPorts { + IN LPTSTR name; + IN DWORD level; + OUT DWORD needed; + OUT DWORD returned; + OUT DWORD status; +}; + +OPERATION(SPOOLSS_OPNUM_DeletePort) +struct spoolss_DeletePort { + IN LPTSTR name; + OUT DWORD status; +}; + +OPERATION(SPOOLSS_OPNUM_AddPortEx) +struct spoolss_AddPortEx { + IN LPTSTR name; + OUT DWORD status; +}; + +OPERATION(SPOOLSS_OPNUM_SetPort) +struct spoolss_SetPort { + IN LPTSTR name; + OUT DWORD status; +}; + +OPERATION(SPOOLSS_OPNUM_EnumMonitor) +struct spoolss_EnumMonitor { + IN LPTSTR name; + IN DWORD level; + OUT DWORD needed; + OUT DWORD returned; + OUT DWORD status; +}; + +OPERATION(SPOOLSS_OPNUM_AddMonitor) +struct spoolss_AddMonitor { + IN LPTSTR name; + OUT DWORD status; +}; + +OPERATION(SPOOLSS_OPNUM_DeleteMonitor) +struct spoolss_DeleteMonitor { + IN LPTSTR name; + OUT DWORD status; +}; + OPERATION(SPOOLSS_OPNUM_ResetPrinter) struct spoolss_ResetPrinter { IN spoolss_handle_t handle; @@ -570,6 +628,20 @@ OUT DWORD status; }; +OPERATION(SPOOLSS_OPNUM_AddForm) +struct spoolss_AddForm { + IN spoolss_handle_t handle; + /* FORM_CONTAINER *form_container; */ + OUT DWORD status; +}; + +OPERATION(SPOOLSS_OPNUM_DeleteForm) +struct spoolss_DeleteForm { + IN spoolss_handle_t handle; + /* IN REFERENCE LPTSTR form_name; */ + OUT DWORD status; +}; + OPERATION(SPOOLSS_OPNUM_EnumForms) struct spoolss_EnumForms { IN spoolss_handle_t handle; @@ -637,6 +709,10 @@ struct spoolss_OpenPrinterEx { IN LPTSTR printer_name; OUT spoolss_handle_t handle; + IN LPTSTR data_type; + /* IN struct spoolssDevmodeContainer dmodeContainer; */ + /* IN DWORD AccessRequired; */ + /* IN CLIENT_CONTAINER client_info; */ OUT DWORD status; }; @@ -692,7 +768,16 @@ CASE(SPOOLSS_OPNUM_ResetPrinter) struct spoolss_ResetPrinter ResetPrinter; - + + CASE(SPOOLSS_OPNUM_EnumMonitor) + struct spoolss_EnumMonitor EnumMonitor; + + CASE(SPOOLSS_OPNUM_AddMonitor) + struct spoolss_AddMonitor AddMonitor; + + CASE(SPOOLSS_OPNUM_DeleteMonitor) + struct spoolss_DeleteMonitor DeleteMonitor; + CASE(SPOOLSS_OPNUM_WritePrinter) struct spoolss_WritePrinter WritePrinter; @@ -717,12 +802,27 @@ CASE(SPOOLSS_OPNUM_ScheduleJob) struct spoolss_ScheduleJob ScheduleJob; + CASE(SPOOLSS_OPNUM_AddForm) + struct spoolss_AddForm AddForm; + + CASE(SPOOLSS_OPNUM_DeleteForm) + struct spoolss_DeleteForm DeleteForm; + CASE(SPOOLSS_OPNUM_EnumForms) struct spoolss_EnumForms EnumForms; - CASE(SPOOLSS_OPNUM_EnumJobs) - struct spoolss_EnumJobs EnumJobs; - + CASE(SPOOLSS_OPNUM_EnumPorts) + struct spoolss_EnumPorts EnumPorts; + + CASE(SPOOLSS_OPNUM_DeletePort) + struct spoolss_DeletePort DeletePort; + + CASE(SPOOLSS_OPNUM_AddPortEx) + struct spoolss_AddPortEx AddPortEx; + + CASE(SPOOLSS_OPNUM_SetPort) + struct spoolss_SetPort SetPort; + CASE(SPOOLSS_OPNUM_RFNPCNEX) struct spoolss_RFNPCNEX RFNPCNEX;
--- a/usr/src/uts/common/smbsrv/smb_ktypes.h Wed Aug 11 17:59:10 2010 -0400 +++ b/usr/src/uts/common/smbsrv/smb_ktypes.h Wed Aug 11 16:48:54 2010 -0700 @@ -1050,6 +1050,7 @@ #define SMB_TREE_ABE 0x00008000 #define SMB_TREE_QUOTA 0x00010000 #define SMB_TREE_DFSROOT 0x00020000 +#define SMB_TREE_SPARSE 0x00040000 typedef enum { SMB_TREE_STATE_CONNECTED = 0,
--- a/usr/src/uts/common/smbsrv/smb_share.h Wed Aug 11 17:59:10 2010 -0400 +++ b/usr/src/uts/common/smbsrv/smb_share.h Wed Aug 11 16:48:54 2010 -0700 @@ -235,7 +235,7 @@ */ int smb_shr_start(void); void smb_shr_stop(void); -int smb_shr_load(void); +void *smb_shr_load(void *); void smb_shr_iterinit(smb_shriter_t *); smb_share_t *smb_shr_iterate(smb_shriter_t *); void smb_shr_list(int, smb_shrlist_t *);
--- a/usr/src/uts/common/smbsrv/smbinfo.h Wed Aug 11 17:59:10 2010 -0400 +++ b/usr/src/uts/common/smbsrv/smbinfo.h Wed Aug 11 16:48:54 2010 -0700 @@ -102,9 +102,16 @@ */ #define SMB_PI_MAX_WORKERS_MIN 64 +/* + * sv_size is used by the RPC services and should be set to + * sizeof (smb_version_t). + */ typedef struct smb_version { - uint8_t sv_major; - uint8_t sv_minor; + uint32_t sv_size; + uint32_t sv_major; + uint32_t sv_minor; + uint32_t sv_build_number; + uint32_t sv_platform_id; } smb_version_t; typedef struct smb_kmod_cfg { @@ -137,13 +144,14 @@ /* * Major version numbers */ -#define SMB_MAJOR_NT 4 +#define SMB_MAJOR_NT 4 /* Windows 95/98/Me, Windows NT4.0 */ #define SMB_MAJOR_2000 5 #define SMB_MAJOR_XP 5 #define SMB_MAJOR_2003 5 #define SMB_MAJOR_VISTA 6 #define SMB_MAJOR_2008 6 #define SMB_MAJOR_2008R2 6 +#define SMB_MAJOR_7 6 /* * Minor version numbers @@ -155,6 +163,7 @@ #define SMB_MINOR_VISTA 0 #define SMB_MINOR_2008 0 #define SMB_MINOR_2008R2 1 +#define SMB_MINOR_7 1 /* * Max version length in string format
--- a/usr/src/uts/common/sys/attr.h Wed Aug 11 17:59:10 2010 -0400 +++ b/usr/src/uts/common/sys/attr.h Wed Aug 11 16:48:54 2010 -0700 @@ -55,6 +55,8 @@ #define A_GROUPSID "groupsid" #define A_REPARSE_POINT "reparse" #define A_GEN "generation" +#define A_OFFLINE "offline" +#define A_SPARSE "sparse" /* Attribute option for utilities */ #define O_HIDDEN "H" @@ -68,6 +70,8 @@ #define O_AV_QUARANTINED "q" #define O_AV_MODIFIED "m" #define O_REPARSE_POINT "r" +#define O_OFFLINE "O" +#define O_SPARSE "s" #define O_NONE "" /* ownersid and groupsid are composed of two nvpairs */ @@ -94,6 +98,8 @@ F_FSID, F_REPARSE, F_GEN, + F_OFFLINE, + F_SPARSE, F_ATTR_ALL } f_attr_t;
--- a/usr/src/uts/common/sys/vnode.h Wed Aug 11 17:59:10 2010 -0400 +++ b/usr/src/uts/common/sys/vnode.h Wed Aug 11 16:48:54 2010 -0700 @@ -399,6 +399,8 @@ uint8_t xoa_av_scanstamp[AV_SCANSTAMP_SZ]; uint8_t xoa_reparse; uint64_t xoa_generation; + uint8_t xoa_offline; + uint8_t xoa_sparse; } xoptattr_t; /* @@ -579,11 +581,13 @@ #define XAT0_AV_SCANSTAMP 0x00001000 /* anti-virus scanstamp */ #define XAT0_REPARSE 0x00002000 /* FS reparse point */ #define XAT0_GEN 0x00004000 /* object generation number */ +#define XAT0_OFFLINE 0x00008000 /* offline */ +#define XAT0_SPARSE 0x00010000 /* sparse */ #define XAT0_ALL_ATTRS (XAT0_CREATETIME|XAT0_ARCHIVE|XAT0_SYSTEM| \ XAT0_READONLY|XAT0_HIDDEN|XAT0_NOUNLINK|XAT0_IMMUTABLE|XAT0_APPENDONLY| \ - XAT0_NODUMP|XAT0_OPAQUE|XAT0_AV_QUARANTINED| \ - XAT0_AV_MODIFIED|XAT0_AV_SCANSTAMP|XAT0_REPARSE|XAT0_GEN) + XAT0_NODUMP|XAT0_OPAQUE|XAT0_AV_QUARANTINED| XAT0_AV_MODIFIED| \ + XAT0_AV_SCANSTAMP|XAT0_REPARSE|XATO_GEN|XAT0_OFFLINE|XAT0_SPARSE) /* Support for XAT_* optional attributes */ #define XVA_MASK 0xffffffff /* Used to mask off 32 bits */ @@ -618,6 +622,8 @@ #define XAT_AV_SCANSTAMP ((XAT0_INDEX << XVA_SHFT) | XAT0_AV_SCANSTAMP) #define XAT_REPARSE ((XAT0_INDEX << XVA_SHFT) | XAT0_REPARSE) #define XAT_GEN ((XAT0_INDEX << XVA_SHFT) | XAT0_GEN) +#define XAT_OFFLINE ((XAT0_INDEX << XVA_SHFT) | XAT0_OFFLINE) +#define XAT_SPARSE ((XAT0_INDEX << XVA_SHFT) | XAT0_SPARSE) /* * The returned attribute map array (xva_rtnattrmap[]) is located past the